diff --git a/app/lang/de.json b/app/lang/de.json index 77b8b65..dadf2d5 100644 --- a/app/lang/de.json +++ b/app/lang/de.json @@ -36,11 +36,11 @@ }, "enums": { "text_type": { + "CHAR": "Ein Zeichen", "INTEGER": "Ganzzahl", "NUMBER": "Zahl", "TEXT": "Freitext", - "WORD": "Ein Wort", - "CHAR": "Ein Zeichen" + "WORD": "Ein Wort" }, "user_role": { "ADMIN": "Admin", @@ -80,6 +80,28 @@ "refresh": "Aktualisieren", "update_btn": "Updaten" }, + "create_hunt": { + "allow_join": "Beitreten erlauben", + "create_btn": "Hunt erstellen", + "de": "Deutsch", + "description_de": "Beschreibung (Deutsch)", + "description_en": "Beschreibung (Englisch)", + "en": "Englisch", + "end": "Ende", + "has_end": "Hat ein Enddatum?", + "has_start": "Hat ein Startdatum?", + "name_de": "Name (Deutsch)", + "name_en": "Name (Englisch)", + "not_allowed": "Du benötigst die Creator- oder Admin-Rolle, um Hunts zu erstellen.", + "public": "Öffentlich (auf der Startseite sichtbar)", + "reveal_answers": "Antworten aufdecken", + "reveal_quests": "Quests aufdecken", + "sidebar": "Hunt erstellen", + "start": "Start", + "success": "Hunt erfolgreich erstellt!", + "title": "Neuen Hunt erstellen", + "virtual": "Virtueller Hunt" + }, "diashow": { "head": "Diashow" }, @@ -129,11 +151,11 @@ "title": "Impressum" }, "pictures": { - "head": "Bilderwand", - "select_team": "Wähle ein Team", + "filter_quest": "Filtere Bilder nach Quests", "filter_team": "Filtere Bilder nach Teams", + "head": "Bilderwand", "select_quest": "Wähle eine Quest", - "filter_quest": "Filtere Bilder nach Quests" + "select_team": "Wähle ein Team" }, "profile": { "admins_and_creators": "Admins & Ersteller", @@ -144,8 +166,8 @@ "promote": "Befördern", "promote_user": "Benutzer befördern", "role": "Rolle", - "role_changed": "Rolle aktualisiert!", "role_change_error": "Rolle konnte nicht geändert werden!", + "role_changed": "Rolle aktualisiert!", "role_confirm": "Möchtest du die Rolle von {name} zu {role} ändern?", "search_user": "Benutzer per E-Mail suchen...", "uploaded_pictures": "Hochgeladene Bilder", @@ -273,4 +295,4 @@ "uploadFile": "Datei hochladen", "voteRating": "vote rating {value} of {max}" } -} +} \ No newline at end of file diff --git a/app/lang/en.json b/app/lang/en.json index 2d3a933..3889b28 100644 --- a/app/lang/en.json +++ b/app/lang/en.json @@ -36,11 +36,11 @@ }, "enums": { "text_type": { + "CHAR": "One character", "INTEGER": "Whole number", "NUMBER": "Number", "TEXT": "Free text", - "WORD": "One word", - "CHAR": "One character" + "WORD": "One word" }, "user_role": { "ADMIN": "Admin", @@ -80,6 +80,28 @@ "refresh": "Refresh", "update_btn": "Update" }, + "create_hunt": { + "allow_join": "Allow joining", + "create_btn": "Create Hunt", + "de": "German", + "description_de": "Description (German)", + "description_en": "Description (English)", + "en": "English", + "end": "End", + "has_end": "Has end date?", + "has_start": "Has start date?", + "name_de": "Name (German)", + "name_en": "Name (English)", + "not_allowed": "You need the Creator or Admin role to create hunts.", + "public": "Public (visible on home page)", + "reveal_answers": "Reveal answers", + "reveal_quests": "Reveal quests", + "sidebar": "Create Hunt", + "start": "Start", + "success": "Hunt created successfully!", + "title": "Create a new Hunt", + "virtual": "Virtual hunt" + }, "diashow": { "head": "Diashow" }, @@ -129,11 +151,11 @@ "title": "Imprint" }, "pictures": { - "head": "Picture wall", - "select_team": "Select a team", + "filter_quest": "Filter pictures by quests", "filter_team": "Filter pictures by teams", + "head": "Picture wall", "select_quest": "Select a quest", - "filter_quest": "Filter pictures by quests" + "select_team": "Select a team" }, "profile": { "admins_and_creators": "Admins & Creators", @@ -144,8 +166,8 @@ "promote": "Promote", "promote_user": "Promote a user", "role": "Role", - "role_changed": "Role updated!", "role_change_error": "Could not change role!", + "role_changed": "Role updated!", "role_confirm": "Do you want to change the role of {name} to {role}?", "search_user": "Search user by email...", "uploaded_pictures": "Uploaded pictures", @@ -273,4 +295,4 @@ "uploadFile": "Upload file", "voteRating": "vote rating {value} of {max}" } -} +} \ No newline at end of file diff --git a/app/layouts/default.vue b/app/layouts/default.vue index 8b9263c..ddf63f6 100644 --- a/app/layouts/default.vue +++ b/app/layouts/default.vue @@ -60,6 +60,18 @@ const isHuntAdmin = computed( Home + + + + {{ + t('page.create_hunt.sidebar') + }} + + +import { sluggy } from '#imports'; + +definePageMeta({ + middleware: ['auth'] +}); + +const { t } = useI18n(); +const { user } = useUserSession(); +const localePath = useLocalePath(); +const router = useRouter(); +const { init } = useToast(); +const validation = useValidation(); + +const canCreate = computed( + () => user.value?.role === 'CREATOR' || user.value?.role === 'ADMIN' +); + +const form = reactive({ + name_de: '', + name_en: '', + description_de: '', + description_en: '', + virtual: false, + start: null as Date | null, + end: null as Date | null, + allowJoin: false, + revealQuests: false, + revealAnswers: false, + public: true +}); + +const loading = ref(false); +const formError = ref(''); + +async function submit() { + loading.value = true; + formError.value = ''; + + try { + const hunt = await $fetch('/api/admin/hunt', { + method: 'POST', + body: { + ...form, + start: form.start?.toISOString() ?? null, + end: form.end?.toISOString() ?? null + } + }); + + init({ + message: t('page.create_hunt.success'), + color: 'success' + }); + + await router.push( + localePath(`/hunt/${sluggy({ id: hunt.id, name: hunt.name_de })}/admin`) + ); + } catch (e) { + formError.value = parseError(e); + } + + loading.value = false; +} + + + diff --git a/app/pages/hunt/[huntSlug]/admin.vue b/app/pages/hunt/[huntSlug]/admin.vue index c7829c8..be93904 100644 --- a/app/pages/hunt/[huntSlug]/admin.vue +++ b/app/pages/hunt/[huntSlug]/admin.vue @@ -253,6 +253,7 @@ async function deleteImage() { clearable-icon="replay" /> + { description_de: true, description_en: true, virtual: true, + public: true, start: true, end: true, allowJoin: true, diff --git a/server/api/admin/hunt/[huntId]/index.post.ts b/server/api/admin/hunt/[huntId]/index.post.ts index 44a6bb7..8efc8cc 100644 --- a/server/api/admin/hunt/[huntId]/index.post.ts +++ b/server/api/admin/hunt/[huntId]/index.post.ts @@ -21,8 +21,9 @@ export default defineEventHandler(async (event) => { description_de: z.string().min(1).max(1000).trim(), description_en: z.string().min(1).max(1000).trim(), virtual: z.boolean(), - start: z.iso.datetime(), - end: z.iso.datetime(), + public: z.boolean(), + start: z.iso.datetime().nullable(), + end: z.iso.datetime().nullable(), allowJoin: z.boolean(), revealQuests: z.boolean(), revealAnswers: z.boolean() diff --git a/server/api/admin/hunt/index.post.ts b/server/api/admin/hunt/index.post.ts new file mode 100644 index 0000000..c4ffce0 --- /dev/null +++ b/server/api/admin/hunt/index.post.ts @@ -0,0 +1,47 @@ +import { useValidatedBody, z } from 'h3-zod'; +import prisma from '~~/lib/prisma'; + +export default defineEventHandler(async (event) => { + const user = await requireUserSession(event); + + if (user.user.role !== 'CREATOR' && user.user.role !== 'ADMIN') { + throw createError({ + statusCode: 403, + statusMessage: 'Not allowed!' + }); + } + + const body = await useValidatedBody( + event, + z.object({ + name_de: z.string().min(1).max(256).trim(), + name_en: z.string().min(1).max(256).trim(), + description_de: z.string().max(1000).trim().default(''), + description_en: z.string().max(1000).trim().default(''), + virtual: z.boolean().default(false), + start: z.iso.datetime().nullish(), + end: z.iso.datetime().nullish(), + allowJoin: z.boolean().default(false), + revealQuests: z.boolean().default(false), + revealAnswers: z.boolean().default(false), + public: z.boolean().default(true) + }) + ); + + return await prisma.hunt.create({ + data: { + ...body, + creatorId: user.user.id, + members: { + create: { + memberId: user.user.id + } + } + }, + select: { + id: true, + name_de: true, + name_en: true + } + }); +}); diff --git a/server/api/home.get.ts b/server/api/home.get.ts index ef422ce..a91b224 100644 --- a/server/api/home.get.ts +++ b/server/api/home.get.ts @@ -103,6 +103,7 @@ export default defineEventHandler(async (event) => { }, where: { deletedAt: null, + public: true, OR: [ { start: {