From fe035da7c343151486cfd84c366399750c023784 Mon Sep 17 00:00:00 2001
From: Alexis <35.alexis.pele@gmail.com>
Date: Fri, 28 Feb 2025 19:24:53 +0100
Subject: [PATCH] Added edit world functions
---
components/world/dialog/Edit.vue | 53 +++++++++++++++
components/world/form/Edit.vue | 113 +++++++++++++++++++++++++++++++
i18n.config.ts | 14 ++++
models/World.ts | 4 ++
pages/my/index.vue | 30 ++++++--
server/api/worlds/[id].patch.ts | 77 +++++++++++++++++++++
6 files changed, 285 insertions(+), 6 deletions(-)
create mode 100644 components/world/dialog/Edit.vue
create mode 100644 components/world/form/Edit.vue
create mode 100644 server/api/worlds/[id].patch.ts
diff --git a/components/world/dialog/Edit.vue b/components/world/dialog/Edit.vue
new file mode 100644
index 0000000..1487278
--- /dev/null
+++ b/components/world/dialog/Edit.vue
@@ -0,0 +1,53 @@
+
+
+
+
+
+
+
+
+
+ {{ $t('entity.world.editDialog.title') }} — {{ worldSkeletonName }}
+
+
+ {{ $t('entity.world.editDialog.title') }}
+
+
+
+
+
+ {{ $t('entity.world.editDialog.subtitle') }}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/world/form/Edit.vue b/components/world/form/Edit.vue
new file mode 100644
index 0000000..fe8d1ba
--- /dev/null
+++ b/components/world/form/Edit.vue
@@ -0,0 +1,113 @@
+
+
+
+
+
+
+
diff --git a/i18n.config.ts b/i18n.config.ts
index 111535b..b7d716e 100644
--- a/i18n.config.ts
+++ b/i18n.config.ts
@@ -88,10 +88,17 @@ export default defineI18nConfig(() => ({
title: "Create a world",
subtitle: "Worlds are the building blocks which hold all your characters, your calendars…"
},
+ editDialog: {
+ title: "Edit world",
+ subtitle: "Update world data",
+ },
deleteDialog: {
title: "Delete this world ?",
subtitle: "This world will be deleted permanently, and all of its associated data will be lost !",
},
+ updatedToast: {
+ title: "The world \"{world}\" has been successfuly updated.",
+ },
deletedToast: {
title: "The world \"{world}\" has been successfuly deleted.",
},
@@ -331,10 +338,17 @@ export default defineI18nConfig(() => ({
title: "Créer un monde",
subtitle: "Un monde est la brique de base qui contient vos personnages, vos calendriers…"
},
+ editDialog: {
+ title: "Modifier le monde",
+ subtitle: "Mettre à jour les données du monde",
+ },
deleteDialog: {
title: "Supprimer ce monde ?",
subtitle: "Le monde sera supprimé définitivement, vous perdrez toutes les données associées !",
},
+ updatedToast: {
+ title: "Le monde \"{world}\" a été modifié avec succès.",
+ },
deletedToast: {
title: "Le monde \"{world}\" a été supprimé avec succès.",
},
diff --git a/models/World.ts b/models/World.ts
index 165ecc1..8a98fa3 100644
--- a/models/World.ts
+++ b/models/World.ts
@@ -2,6 +2,8 @@ import { z } from "zod"
import type { Calendar } from "./CalendarConfig"
import { rpgColorSchema, type RPGColor } from "./Color"
+export type WorldState = "published" | "draft" | "archived"
+
export interface World {
id?: number
name: string
@@ -9,6 +11,7 @@ export interface World {
color?: RPGColor,
calendars?: Calendar[],
gmId?: string
+ state?: WorldState
}
export const postWorldSchema = z.object({
@@ -16,4 +19,5 @@ export const postWorldSchema = z.object({
description: z.string().optional().nullable(),
color: rpgColorSchema,
gmId: z.string().optional().nullable(),
+ state: z.string().optional().nullable().default("draft"),
})
diff --git a/pages/my/index.vue b/pages/my/index.vue
index 1471b8a..6b619fb 100644
--- a/pages/my/index.vue
+++ b/pages/my/index.vue
@@ -1,5 +1,5 @@
@@ -169,9 +180,15 @@ function hideDeleteModal() {
{{ world.description }}
-
-
-
+
@@ -180,6 +197,7 @@ function hideDeleteModal() {
+
diff --git a/server/api/worlds/[id].patch.ts b/server/api/worlds/[id].patch.ts
new file mode 100644
index 0000000..8aa1fb7
--- /dev/null
+++ b/server/api/worlds/[id].patch.ts
@@ -0,0 +1,77 @@
+import { z } from "zod"
+import { serverSupabaseClient } from "#supabase/server"
+import { postWorldSchema, type World } from "~/models/World"
+
+const paramsSchema = z.object({
+ id: z.number({ coerce: true }).positive().int()
+})
+
+export default defineEventHandler(async (event) => {
+ const client = await serverSupabaseClient(event)
+
+ const { data: params, error: paramsError} = await getValidatedRouterParams(event, paramsSchema.safeParse)
+ const { data: bodyData, error: bodyError } = await readValidatedBody(event, body => postWorldSchema.safeParse(body))
+
+ if (paramsError) {
+ throw createError({
+ cause: "Utilisateur",
+ fatal: false,
+ message: "L'identifiant du monde est manquant ou mal renseigné.",
+ status: 401,
+ })
+ }
+
+ if (bodyError) {
+ const error = createError({
+ cause: "Utilisateur",
+ fatal: false,
+ statusCode: 401,
+ statusMessage: "Validation Error",
+ message: "Erreur de validation du schéma, probablement dûe à une erreur utilisateur.",
+ data: {
+ errors: bodyError.issues.map(issue => ({
+ path: issue.path,
+ message: issue.message,
+ code: issue.code
+ }))
+ }
+ })
+
+ throw error
+ }
+
+ try {
+ const { data, error } = await client
+ .from("worlds")
+ .update(
+ {
+ name: bodyData.name,
+ description: bodyData.description,
+ state: bodyData.state,
+ gm_id: bodyData.gmId,
+ color: bodyData.color
+ } as never
+ )
+ .eq("id", params.id)
+ .select(`
+ id,
+ name,
+ description,
+ color,
+ gm_id,
+ state
+ `)
+ .single()
+
+ if (error) throw error
+
+ return data
+ } catch (err) {
+ throw createError({
+ cause: "Serveur",
+ status: 500,
+ fatal: false,
+ message: "Une erreur inconnue est survenue."
+ })
+ }
+})