diff --git a/app/pages/feedback.vue b/app/pages/feedback.vue index 9dce572..15f3ae9 100644 --- a/app/pages/feedback.vue +++ b/app/pages/feedback.vue @@ -69,6 +69,17 @@ class="w-full rounded-2xl border border-white/10 bg-black/40 px-4 py-3 text-sm text-white placeholder:text-white/30 focus:border-cyan-400 focus:outline-none" /> +
+ + +
@@ -229,7 +240,7 @@

Prefer to talk it through?

-

We are more than happy to jump on Discord or TeamSpeak for a quick debrief about your ideas.

+

Drop your Discord handle above or ping us for a quick Discord or TeamSpeak debrief about your ideas.

import {reactive, ref} from 'vue' -import {useHead, useNuxtApp} from '#imports' +import {useHead} from '#imports' useHead({title: 'Feedback & ideas • OpenSquawk'}) @@ -283,6 +294,7 @@ const frictionOptions = [ const form = reactive({ name: '', email: '', + discordHandle: '', excitement: 4, highlightSelections: [] as string[], highlightNotes: '', @@ -297,23 +309,47 @@ const form = reactive({ const submissionState = ref<'idle' | 'submitting' | 'success' | 'error'>('idle') const submissionError = ref(null) -const {$fetch} = useNuxtApp() - async function handleSubmit() { submissionError.value = null submissionState.value = 'submitting' try { - await $fetch('/api/service/feedback', { + const response = await fetch('/api/service/feedback', { method: 'POST', - body: { + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ ...form, excitement: form.excitement, highlightSelections: [...form.highlightSelections], frictionSelections: [...form.frictionSelections], - }, + }), }) + if (!response.ok) { + let errorMessage: string | null = null + + try { + const errorBody = await response.json() + if (errorBody && typeof errorBody === 'object') { + if (typeof errorBody.statusMessage === 'string') { + errorMessage = errorBody.statusMessage + } else if (typeof errorBody.message === 'string') { + errorMessage = errorBody.message + } + } + } catch (parseError) { + // ignore JSON parse errors and fall back to status text + } + + if (!errorMessage || errorMessage.length === 0) { + errorMessage = response.statusText || 'Failed to send feedback.' + } + + throw new Error(errorMessage) + } + submissionState.value = 'success' form.highlightSelections = [] @@ -323,19 +359,13 @@ async function handleSubmit() { form.classroomNotes = '' form.hostingInterest = '' form.otherIdeas = '' + form.discordHandle = '' } catch (error: unknown) { submissionState.value = 'error' - if (error && typeof error === 'object') { - const statusMessage = - (error as any).statusMessage || - ((error as any).data && typeof (error as any).data?.statusMessage === 'string' ? (error as any).data.statusMessage : null) - if (typeof statusMessage === 'string' && statusMessage.length > 0) { - submissionError.value = statusMessage - return - } - } if (error instanceof Error) { submissionError.value = error.message + } else if (error && typeof error === 'object' && 'message' in error && typeof (error as any).message === 'string') { + submissionError.value = (error as any).message } else { submissionError.value = 'Unknown error occurred.' } diff --git a/server/api/service/feedback/index.post.ts b/server/api/service/feedback/index.post.ts index dcb3d4d..4c74524 100644 --- a/server/api/service/feedback/index.post.ts +++ b/server/api/service/feedback/index.post.ts @@ -4,6 +4,7 @@ import { sendAdminNotification } from '../../../utils/notifications' interface FeedbackRequestBody { name?: string email?: string + discordHandle?: string excitement?: number highlightSelections?: string[] highlightNotes?: string @@ -52,6 +53,7 @@ export default defineEventHandler(async (event) => { const name = normaliseText(body.name) const email = normaliseText(body.email) + const discordHandle = normaliseText(body.discordHandle) const highlightNotes = normaliseText(body.highlightNotes) const frictionNotes = normaliseText(body.frictionNotes) const classroomNotes = normaliseText(body.classroomNotes) @@ -64,6 +66,10 @@ export default defineEventHandler(async (event) => { const details: string[] = [] details.push(`Overall excitement: ${excitement}/5`) details.push(`Highlights: ${highlightSelections.length ? highlightSelections.join(', ') : '—'}`) + if (discordHandle) { + details.push('') + details.push(`Discord: ${discordHandle}`) + } if (highlightNotes) { details.push('') details.push('Highlight notes:') @@ -98,6 +104,7 @@ export default defineEventHandler(async (event) => { data: [ ['Name', name || '—'], ['Email', email || '—'], + ['Discord', discordHandle || '—'], ['Okay to contact', allowContact ? 'Yes' : 'No'], ], from: email || undefined,