Skip to content

Commit

Permalink
Added create deck and get decks anki API hooks
Browse files Browse the repository at this point in the history
  • Loading branch information
TomPlum committed Oct 1, 2023
1 parent fd3a538 commit cefe20f
Show file tree
Hide file tree
Showing 12 changed files with 112 additions and 23 deletions.
12 changes: 6 additions & 6 deletions src/api/clients/useAnkiConnect/types.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
export interface AnkiConnectResponse {
result: string
export interface AnkiConnectResponse<Result> {
result: Result
error: string | null
}

export interface AnkiConnectRequest<Params> {
action: string
version: number
params: Params
params?: Params
}

export type AnkiConnectAction = 'addNote'
export type AnkiConnectAction = 'addNote' | 'deckNames' | 'createDeck'

export interface AnkiConnectClient<Params> {
call: (action: AnkiConnectAction, params: Params) => Promise<AnkiConnectResponse>
export interface AnkiConnectClient<Params, Result> {
call: (action: AnkiConnectAction, params?: Params) => Promise<AnkiConnectResponse<Result>>
}
10 changes: 7 additions & 3 deletions src/api/clients/useAnkiConnect/useAnkiConnect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,18 @@ import {
import { useCallback } from "react"
import { AxiosResponse } from "axios"

const useAnkiConnect = <Params>(): AnkiConnectClient<Params> => {
const useAnkiConnect = <Params, Result>(): AnkiConnectClient<Params, Result> => {
const client = useClient({
host: hosts[import.meta.env.MODE].anki,
contextRoot: ''
})

const call = useCallback(async (action: AnkiConnectAction, params: unknown) => {
const { data } = await client.post<object, AxiosResponse<AnkiConnectResponse>, AnkiConnectRequest<unknown>>('', {
const call = useCallback(async (action: AnkiConnectAction, params?: unknown) => {
const { data } = await client.post<
object,
AxiosResponse<AnkiConnectResponse<Result>>,
AnkiConnectRequest<unknown>
>('', {
action,
version: 6,
params: params
Expand Down
1 change: 1 addition & 0 deletions src/api/hooks/useCreateAnkiDeck/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './useCreateAnkiDeck.ts'
3 changes: 3 additions & 0 deletions src/api/hooks/useCreateAnkiDeck/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export interface CreateAnkiDeckParams {
deck: string
}
24 changes: 24 additions & 0 deletions src/api/hooks/useCreateAnkiDeck/useCreateAnkiDeck.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import useAnkiConnect from "api/clients/useAnkiConnect"
import { useCallback } from "react"
import { CreateAnkiDeckParams } from "api/hooks/useCreateAnkiDeck/types.ts"
import { queryKeys } from "api/queryKeys.ts"
import { useMutation } from "@tanstack/react-query"

export const useCreateAnkiDeckMutationKey = () => {
return [queryKeys.createAnkiDeck]
}

const useCreateAnkiDeck = () => {
const client = useAnkiConnect<CreateAnkiDeckParams, string>()

const createDeck = useCallback(async (params: CreateAnkiDeckParams) => {
const { result } = await client.call('createDeck', params)
return result
}, [client])

const mutationKey = useCreateAnkiDeckMutationKey()

return useMutation(mutationKey, createDeck)
}

export default useCreateAnkiDeck
1 change: 1 addition & 0 deletions src/api/hooks/useGetAnkiDecks/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './useGetAnkiDecks.ts'
3 changes: 3 additions & 0 deletions src/api/hooks/useGetAnkiDecks/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export interface AnkiDecksResponse {
decks: string[]
}
23 changes: 23 additions & 0 deletions src/api/hooks/useGetAnkiDecks/useGetAnkiDecks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import useAnkiConnect from "api/clients/useAnkiConnect"
import { useCallback } from "react"
import { useQuery } from "@tanstack/react-query"
import { queryKeys } from "api/queryKeys.ts"

export const useGetAnkiDecksQueryKey = () => {
return [queryKeys.getAnkiDecks]
}

const useGetAnkiDecks = () => {
const client = useAnkiConnect<undefined, string[]>()

const getDeckNames = useCallback(async () => {
const { result } = await client.call('deckNames')
return result
}, [client])

const queryKey = useGetAnkiDecksQueryKey()

return useQuery(queryKey, getDeckNames)
}

export default useGetAnkiDecks
4 changes: 3 additions & 1 deletion src/api/queryKeys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,7 @@ export const queryKeys = {
getNewsCatcherHeadlines: 'getNewsCatcherHeadlines',
getMainichiFlash: 'getMainichiFlashRss',
getAsahiHeadlines: 'getAsahiHeadlines',
createAnkiCard: 'createAnkiCard'
createAnkiCard: 'createAnkiCard',
getAnkiDecks: 'getAnkiDecks',
createAnkiDeck: 'createAnkiDeck'
}
1 change: 0 additions & 1 deletion src/hooks/useAnki/types.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { CreateAnkiCardParams } from "api/hooks/useCreateAnkiCard/types.ts"

export interface AnkiResponse {
loading: boolean
createCard: (params: CreateAnkiCardParams) => Promise<void>
}
32 changes: 26 additions & 6 deletions src/hooks/useAnki/useAnki.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,41 @@
import { AnkiResponse } from "hooks/useAnki/types.ts"
import useCreateAnkiCard from "api/hooks/useCreateAnkiCard"
import { useCallback, useState } from "react"
import { useCallback } from "react"
import { useToastContext } from "modules/Toast/useToastContext.ts"
import { useTranslation } from "react-i18next"
import { CreateAnkiCardParams } from "api/hooks/useCreateAnkiCard/types.ts"
import useGetAnkiDecks from "api/hooks/useGetAnkiDecks"
import useCreateAnkiDeck from "api/hooks/useCreateAnkiDeck"

const useAnki = (): AnkiResponse => {
const { fireToast } = useToastContext()
const [loading, setLoading] = useState(false)
const { data: decks } = useGetAnkiDecks()
const { mutateAsync: createDeck } = useCreateAnkiDeck()
const { mutateAsync: createCardApi } = useCreateAnkiCard()
const { t } = useTranslation('translation', { keyPrefix: 'anki' })

const createAnkiDeck = useCallback(async () => {
try {
await createDeck({ deck: 'Japanese::Nyusu' })

fireToast({
type: 'success',
message: t('create-deck.toast.success')
})
} catch (e) {
fireToast({
type: 'error',
message: t('create-deck.toast.error')
})
}
}, [createDeck, fireToast, t])

const createCard = useCallback(async (args: CreateAnkiCardParams) => {
if (decks && !decks.includes('Japanese::Nyusu')) {
await createAnkiDeck()
}

try {
setLoading(true)
await createCardApi(args)

fireToast({
Expand All @@ -27,11 +49,9 @@ const useAnki = (): AnkiResponse => {
})
}

setLoading(false)
}, [fireToast, createCardApi, t])
}, [decks, createAnkiDeck, createCardApi, fireToast, t])

return {
loading,
createCard
}
}
Expand Down
21 changes: 15 additions & 6 deletions src/modules/Newspaper/components/AnkiArticle/AnkiArticle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,17 @@ import styles from './AnkiArticle.module.scss'
import useAnki from "hooks/useAnki"
import { Button, CircularProgress } from "@mui/material"
import { AnkiArticleProps } from "modules/Newspaper/components/AnkiArticle/types.ts"
import { useCallback } from "react"
import { useCallback, useState } from "react"

export const AnkiArticle = ({ article }: AnkiArticleProps) => {
const { loading, createCard } = useAnki()
const { createCard } = useAnki()
const [loading, setLoading] = useState(false)

const handleCreateCard = useCallback(async () => {
await createCard({
const handleCreateCard = useCallback(() => {
setLoading(true)
createCard({
note: {
deckName: 'Nyusu',
deckName: 'Japanese::Nyusu',
modelName: 'Basic',
fields: {
Back: {
Expand All @@ -24,13 +26,20 @@ export const AnkiArticle = ({ article }: AnkiArticleProps) => {
},
tags: ['nyusu']
}
}).then(() => {
setLoading(false)
}).catch(e => {
console.debug(e)
})
}, [article.link, article.title, createCard])

return (
<div className={styles.article}>
{loading && <CircularProgress />}
<Button onClick={handleCreateCard}>Add Card</Button>

<Button onClick={handleCreateCard}>
Add Card
</Button>
</div>
)
}
Expand Down

0 comments on commit cefe20f

Please sign in to comment.