diff --git a/client/src/composables/srs.scoring.ts b/client/src/composables/srs.scoring.ts index 01a130b..f3c20f2 100644 --- a/client/src/composables/srs.scoring.ts +++ b/client/src/composables/srs.scoring.ts @@ -74,7 +74,6 @@ const nextSubject = async (subjectOptions: SubjectOptions): Promise r.accepted_answer).map(r => r.reading) || [] + if (answers.length === 0) + answers = [item.characters] } else if (mode === 'en_jp_writing') { subjectText = item.meanings?.filter(m => m.primary).map(m => m.meaning).join(', ') || '' if (subjectOptions.writingMode === 'kanji') { answers = [item.characters] } else if (subjectOptions.writingMode === 'kana') { answers = item.readings?.filter(r => r.accepted_answer).map(r => r.reading) || [] - } + } else if (answers.length === 0) + answers = [item.characters] } - console.log({ - type: item.type, - subject: subjectText, - answers, - pronunciation_audios, - mode, - }) - return { type: item.type, subject: subjectText, @@ -122,7 +116,6 @@ const nextSubject = async (subjectOptions: SubjectOptions): Promise { const res = await axios.get('/api/v1/review/stats', { headers: { diff --git a/client/src/composables/subject.ts b/client/src/composables/subject.ts deleted file mode 100644 index 95299a9..0000000 --- a/client/src/composables/subject.ts +++ /dev/null @@ -1,143 +0,0 @@ -type ReviewQueueItem = { - type: 'kanji' | 'vocab', - subject: any, - mode: 'meaning' | 'writing', -} - -export class Reviews { - private static instance: Reviews - - public data: { - kanji: any[], - vocab: any[], - } - - private queue: { type: 'kanji' | 'vocab', subject: any, mode: 'meaning' | 'writing' }[] = [] - - private options: { - type: 'kanji' | 'vocab' | 'both', - mode: 'meaning' | 'writing' | 'both', - } - - private constructor(options: { type?: 'kanji' | 'vocab' | 'both', mode?: 'meaning' | 'writing' | 'both' }) { - this.data = { - kanji: [], - vocab: [], - } - this.options = { - type: options.type ?? 'both', - mode: options.mode ?? 'both', - } - } - - public static async getInstance(options: { type?: 'kanji' | 'vocab' | 'both', mode?: 'meaning' | 'writing' | 'both' } = {}): Promise { - if (!Reviews.instance) { - const instance = new Reviews(options) - await instance.loadSubjects() - instance.buildQueue() - Reviews.instance = instance - } - return Reviews.instance - } - - public async setOptions(newOptions: { type?: 'kanji' | 'vocab' | 'both', mode?: 'meaning' | 'writing' | 'both' }) { - let needsReload = false - - if (newOptions.type && newOptions.type !== this.options.type) { - this.options.type = newOptions.type - needsReload = true - } - - if (newOptions.mode && newOptions.mode !== this.options.mode) { - this.options.mode = newOptions.mode - } - - if (needsReload) { - await this.loadSubjects() - } - - this.buildQueue() - } - - private async loadSubjects() { - const typesToLoad: ('kanji' | 'vocab')[] = - this.options.type === 'both' - ? ['kanji', 'vocab'] - : [this.options.type] - - for (const type of typesToLoad) { - await this.getSubjects(type) - } - } - - private buildQueue() { - this.queue = [] - - const types: ('kanji' | 'vocab')[] = - this.options.type === 'both' - ? ['kanji', 'vocab'] - : [this.options.type] - - for (const type of types) { - for (const subject of this.data[type]) { - switch (this.options.mode) { - case 'meaning': - this.queue.push({ type, subject, mode: 'meaning' }) - break - case 'writing': - this.queue.push({ type, subject, mode: 'writing' }) - break - case 'both': - this.queue.push({ type, subject, mode: 'meaning' }) - this.queue.push({ type, subject, mode: 'writing' }) - break - } - } - } - - this.shuffleQueue() - } - - private shuffleQueue() { - for (let i = this.queue.length - 1; i > 0; i--) { - const j = Math.floor(Math.random() * (i + 1)) - const tmp = this.queue[i]! - this.queue[i] = this.queue[j]! - this.queue[j] = tmp - } - } - - private async getSubjects(type: 'kanji' | 'vocab') { - try { - const res = await fetch(`/api/v1/subject/${type}`) - if (!res.ok) throw new Error(res.statusText) - this.data[type] = await res.json() - } catch (error) { - console.error(error) - } - } - - public nextSubject(): ReviewQueueItem | null { - return (this.queue.shift() as ReviewQueueItem | undefined) ?? null - } - - public getStats() { - const stats: { - mode: 'meaning' | 'writing' | 'both', - type: 'kanji' | 'vocab' | 'both', - kanjiCount: number, - vocabCount: number, - total: number, - queueRemaining: number, - } = { - mode: this.options.mode, - type: this.options.type, - kanjiCount: this.data.kanji.length, - vocabCount: this.data.vocab.length, - queueRemaining: this.queue.length, - total: this.queue.length, - } - - return stats - } -} diff --git a/client/src/pages/all.vue b/client/src/pages/all.vue index 859b024..dbf9dd8 100644 --- a/client/src/pages/all.vue +++ b/client/src/pages/all.vue @@ -1,7 +1,7 @@ diff --git a/client/src/pages/kanji.vue b/client/src/pages/kanji.vue deleted file mode 100644 index 9be3c1b..0000000 --- a/client/src/pages/kanji.vue +++ /dev/null @@ -1,288 +0,0 @@ - - - - - diff --git a/client/src/pages/login.vue b/client/src/pages/login.vue index e0ad21e..79c2a08 100644 --- a/client/src/pages/login.vue +++ b/client/src/pages/login.vue @@ -24,6 +24,7 @@ v-checkbox( label="Remember me" class="my-4" + v-model="rememberMe" ) v-btn( color="primary" @@ -47,10 +48,15 @@ const auth = useAuthStore() const username = ref('') const password = ref('') +const rememberMe = ref(false) async function loginHandler() { - const success = await auth.login(username.value, password.value) + const success = await auth.login(username.value, password.value, rememberMe.value) if (success) router.push('/') else console.error(auth.error) } + +onMounted(() => { + auth.fetchUser() +}) diff --git a/client/src/pages/trainer.vue b/client/src/pages/trainer.vue new file mode 100644 index 0000000..a85a7fa --- /dev/null +++ b/client/src/pages/trainer.vue @@ -0,0 +1,312 @@ + + + + + diff --git a/client/src/pages/vocab.vue b/client/src/pages/vocab.vue deleted file mode 100644 index 61b15a4..0000000 --- a/client/src/pages/vocab.vue +++ /dev/null @@ -1,296 +0,0 @@ - - - - - diff --git a/client/src/pages/writing.vue b/client/src/pages/writing.vue index 2136462..2f6914d 100644 --- a/client/src/pages/writing.vue +++ b/client/src/pages/writing.vue @@ -1,80 +1,106 @@