diff --git a/db.sqlite b/db.sqlite index cb7f1aa..7c42625 100644 Binary files a/db.sqlite and b/db.sqlite differ diff --git a/db.sqlite-shm b/db.sqlite-shm index cf5acf8..fe9ac28 100644 Binary files a/db.sqlite-shm and b/db.sqlite-shm differ diff --git a/db.sqlite-wal b/db.sqlite-wal index c392a4b..e69de29 100644 Binary files a/db.sqlite-wal and b/db.sqlite-wal differ diff --git a/server/api/character/[id]/notes.post.ts b/server/api/character/[id]/notes.post.ts new file mode 100644 index 0000000..3c081e1 --- /dev/null +++ b/server/api/character/[id]/notes.post.ts @@ -0,0 +1,45 @@ +import { eq } from 'drizzle-orm'; +import useDatabase from '~/composables/useDatabase'; +import { characterTable } from '~/db/schema'; +import { CharacterNotesValidation } from '#shared/character.util'; + +export default defineEventHandler(async (e) => { + const id = getRouterParam(e, "id"); + if(!id) + { + setResponseStatus(e, 400); + return; + } + + const body = await readValidatedBody(e, CharacterNotesValidation.safeParse); + if(!body.success) + { + console.error(body.error); + setResponseStatus(e, 400); + throw body.error; + } + + const db = useDatabase(); + const old = db.select({ id: characterTable.id, owner: characterTable.owner }).from(characterTable).where(eq(characterTable.id, parseInt(id, 10))).get(); + + if(!old) + { + setResponseStatus(e, 404); + return; + } + + const session = await getUserSession(e); + if(!session.user || old.owner !== session.user.id || session.user.state !== 1) + { + setResponseStatus(e, 401); + return; + } + + db.update(characterTable).set({ + public_notes: body.data.public, + private_notes: body.data.private, + }).where(eq(characterTable.id, parseInt(id, 10))).run(); + + setResponseStatus(e, 200); + return; +}); \ No newline at end of file diff --git a/shared/character.util.ts b/shared/character.util.ts index 42e93e7..1763587 100644 --- a/shared/character.util.ts +++ b/shared/character.util.ts @@ -237,6 +237,10 @@ export const weaponTypeTexts: Record = { "projectile": "Arme à projectile", }; +export const CharacterNotesValidation = z.object({ + public: z.string().optional(), + private: z.string().optional(), +}); export const CharacterVariablesValidation = z.object({ health: z.number(), mana: z.number(), @@ -259,10 +263,7 @@ export const CharacterValidation = z.object({ people: z.string().nullable(), level: z.number().min(1).max(20), aspect: z.number().nullable().optional(), - notes: z.object({ - public: z.string().optional(), - private: z.string().optional(), - }), + notes: CharacterNotesValidation, training: z.record(z.enum(MAIN_STATS), z.record(z.enum(TRAINING_LEVELS.map(String)), z.number().optional())), leveling: z.record(z.enum(LEVELS.map(String)), z.number().optional()), abilities: z.record(z.enum(ABILITIES), z.number().optional()), @@ -371,6 +372,15 @@ export class CharacterCompiler }) } } + saveNotes() + { + useRequestFetch()(`/api/character/${this.character.id}/notes`, { + method: 'POST', + body: this._character.notes, + }).then(() => {}).catch(() => { + Toaster.add({ type: 'error', content: 'Impossible de mettre à jour les données', duration: 5000, timer: true }); + }); + } protected add(feature?: string) { if(!feature) @@ -1261,6 +1271,14 @@ export class CharacterSheet const character = this.character.compiled; + const publicNotes = new MarkdownEditor(); + const privateNotes = new MarkdownEditor(); + + publicNotes.onChange = (v) => this.character!.character.notes!.public = v; + privateNotes.onChange = (v) => this.character!.character.notes!.private = v; + publicNotes.content = this.character!.character.notes!.public!; + privateNotes.content = this.character!.character.notes!.private!; + this.tabs = tabgroup([ { id: 'actions', title: [ text('Actions') ], content: () => this.actionsTab(character) }, @@ -1273,7 +1291,10 @@ export class CharacterSheet ] }, { id: 'notes', title: [ text('Notes') ], content: () => [ - + div('flex flex-col gap-2', [ + div('flex flex-col gap-2 border-b border-light-35 dark:border-dark-35 pb-4', [ div('flex flex-row w-full items-center justify-between', [ span('text-lg font-bold', 'Notes publics'), tooltip(button(icon('radix-icons:paper-plane', { width: 16, height: 16 }), () => this.character!.saveNotes(), 'p-1'), 'Enregistrer', 'right') ]), div('border border-light-35 dark:border-dark-35 p-1', [ publicNotes.dom ]) ]), + div('flex flex-col gap-2', [ span('text-lg font-bold', 'Notes privés'), div('border border-light-35 dark:border-dark-35 p-1', [ privateNotes.dom ]) ]), + ]) ] }, ], { focused: 'abilities', class: { container: 'flex-1 gap-4 px-4 w-[960px]' } }); this.container.replaceChildren(div('flex flex-col justify-center gap-1', [