[+] Save user data

This commit is contained in:
2025-11-19 15:34:25 +08:00
parent a2e8538022
commit 3abad7ec31
5 changed files with 58 additions and 14 deletions
+11 -3
View File
@@ -1,5 +1,5 @@
import { db } from "./db"
import type { UserDocument } from "../../shared/types.ts";
import type { UserDocument, UserData } from "../../shared/types.ts";
const users = db.collection<UserDocument>("users")
@@ -42,5 +42,13 @@ export async function createSyncCode(session: string): Promise<string> {
return code
}
/**
* Update user data.
* @param session Session token
* @param data Data to update (partial)
*/
export async function updateUserData(session: string, data: Partial<UserData>): Promise<void> {
const user = await login(session)
const newData = { ...(user.data || {}), ...data }
await users.updateOne({ _id: user._id }, { $set: { data: newData } })
}
+15
View File
@@ -0,0 +1,15 @@
import type { UserData } from "../shared/types";
/**
* Save user data to the server.
* @param data Partial user data to update
*/
export async function saveUserData(data: Partial<UserData>) {
await fetch('/api/user', {
method: 'POST',
body: JSON.stringify(data),
headers: {
'Content-Type': 'application/json'
}
})
}
+19
View File
@@ -0,0 +1,19 @@
import { json } from '@sveltejs/kit'
import { updateUserData } from '$lib/server/user'
import type { RequestHandler } from './$types'
export const POST: RequestHandler = async ({ request, cookies }) => {
const session = cookies.get('session')
if (!session) {
return json({ error: 'Unauthorized' }, { status: 401 })
}
try {
const data = await request.json()
await updateUserData(session, data)
return json({ success: true })
} catch (e) {
console.error('Failed to update user data', e)
return json({ error: 'Internal Server Error' }, { status: 500 })
}
}
+5 -9
View File
@@ -3,12 +3,12 @@
import type { PageProps } from "./$types"
import { LinearProgress } from "m3-svelte";
import { onMount } from "svelte";
import type { LyricSegment } from "../../../shared/types.ts";
import { typingSettingsDefault, type LyricSegment } from "../../../shared/types.ts";
import { isKana, isKanji, toHiragana, toKatakana } from "wanakana";
import { composeList, fuzzyEquals } from "./IMEHelper.ts";
import MenuItem from "../../../components/material3/MenuItem.svelte";
import "../../../shared/ext.ts"
import { browser } from "$app/environment";
import { saveUserData } from "$lib/user";
let { data }: PageProps = $props()
@@ -19,13 +19,9 @@
let hiddenInput: HTMLInputElement
let inp = $state("")
// Settings stored in localStorage
let settingDefaults = {
isFuri: true,
allKata: false
}
let settings = $state(browser ? (localStorage.getItem('kashi-dash-settings')?.let((it) => JSON.parse(it)) ?? settingDefaults) : settingDefaults)
$effect(() => { if (browser) localStorage.setItem('kashi-dash-settings', JSON.stringify(settings)) })
// Settings stored in user data
let settings = $state(data.user.data?.typingSettings ?? typingSettingsDefault)
$effect(() => { saveUserData({ typingSettings: settings }) })
const preprocessKana = (kana: string) => settings.allKata ? toKatakana(kana) : kana
// Process each line into segments with swi (start word index) and kanji/kana
+8 -2
View File
@@ -56,7 +56,13 @@ export interface UserDocument {
data?: UserData
}
export const typingSettingsDefault = {
isFuri: true,
allKata: false
}
export interface UserData {
myPlaylists?: number[]
playHistory?: GameStats[]
myPlaylists?: number[]
playHistory?: GameStats[]
typingSettings?: typeof typingSettingsDefault
}