From 92efc5a6c24428bb9d32dc6dbf7b4b58567d4a17 Mon Sep 17 00:00:00 2001
From: Remi <73385395+itsrubberduck@users.noreply.github.com>
Date: Sun, 5 Oct 2025 14:23:10 +0200
Subject: [PATCH] Wire feedback form to backend endpoint
---
app/pages/api-docs.vue | 88 ++++++++-
app/pages/feedback.vue | 217 +++++++++------------
server/api/service/feedback/index.post.ts | 107 ++++++++++
server/api/service/feedback/issues.post.ts | 70 +++++++
4 files changed, 361 insertions(+), 121 deletions(-)
create mode 100644 server/api/service/feedback/index.post.ts
create mode 100644 server/api/service/feedback/issues.post.ts
diff --git a/app/pages/api-docs.vue b/app/pages/api-docs.vue
index 6169677..3543ffa 100644
--- a/app/pages/api-docs.vue
+++ b/app/pages/api-docs.vue
@@ -406,13 +406,14 @@ interface NavigationSectionItem {
const BASE_URL = 'https://opensquawk.de'
const sectionCategoryOrder: Record = {
- 'Public endpoints': ['Waitlist & marketing', 'Authentication & onboarding', 'Tools & diagnostics'],
+ 'Public endpoints': ['Waitlist & marketing', 'Feedback & insights', 'Authentication & onboarding', 'Tools & diagnostics'],
'Protected endpoints': ['Session controls', 'Invitation management', 'ATC synthesis', 'Decision engine'],
}
const sectionCategoryDescriptions: Record> = {
'Public endpoints': {
'Waitlist & marketing': 'Capture interest, collect consent, and gauge roadmap sentiment.',
+ 'Feedback & insights': 'Share structured bug reports and qualitative feedback with the team.',
'Authentication & onboarding': 'Account creation, recovery, and invitation flows during the alpha programme.',
'Tools & diagnostics': 'Helper utilities for simulator integrations and latency checks.',
},
@@ -578,6 +579,91 @@ const endpointSections: EndpointSection[] = [
"suggestionId": "6625c9f0e1f8f5d4068a1234"
}`,
},
+ {
+ method: 'POST',
+ path: '/api/service/feedback',
+ summary: 'Send qualitative feedback directly to the OpenSquawk crew.',
+ category: 'Feedback & insights',
+ auth: 'public',
+ body: [
+ { name: 'name', type: 'string', description: 'Optional display name.' },
+ { name: 'email', type: 'string', description: 'Optional contact email to receive a reply.' },
+ { name: 'excitement', type: 'number (1..5)', required: true, description: 'Overall excitement rating.' },
+ {
+ name: 'highlightSelections',
+ type: 'string[]',
+ description: 'Checkbox selections describing what already works well.',
+ },
+ { name: 'highlightNotes', type: 'string', description: 'Long-form notes about the highlights.' },
+ {
+ name: 'frictionSelections',
+ type: 'string[]',
+ description: 'Checkbox selections describing friction points.',
+ },
+ { name: 'frictionNotes', type: 'string', description: 'Detailed explanation of friction areas.' },
+ { name: 'classroomNotes', type: 'string', description: 'Stories about the classroom missions.' },
+ { name: 'hostingInterest', type: 'string', description: 'Thoughts on self-hosting or managed hosting.' },
+ { name: 'otherIdeas', type: 'string', description: 'Wildcard space for big ideas and requests.' },
+ {
+ name: 'contactConsent',
+ type: 'boolean',
+ description: 'Set true if it is okay for the team to follow up via email.',
+ },
+ ],
+ sampleRequest: `curl -X POST https://opensquawk.de/api/service/feedback \
+ -H 'Content-Type: application/json' \
+ -d '{
+ "name": "Jane Pilot",
+ "email": "jane.pilot@example.com",
+ "excitement": 5,
+ "highlightSelections": ["Lesson console", "UI design"],
+ "highlightNotes": "The console feels crisp and fast.",
+ "frictionSelections": ["Latency or responsiveness"],
+ "frictionNotes": "Audio hiccups during busy moments.",
+ "classroomNotes": "Loved the clearance training mission.",
+ "hostingInterest": "Curious about a managed EU cluster.",
+ "otherIdeas": "It would be great to add printable kneeboards.",
+ "contactConsent": true
+ }'`,
+ sampleResponse: `{
+ "success": true
+}`,
+ },
+ {
+ method: 'POST',
+ path: '/api/service/feedback/issues',
+ summary: 'File a public feedback report with categories, title, and description.',
+ category: 'Feedback & insights',
+ auth: 'public',
+ body: [
+ { name: 'title', type: 'string', required: true, description: 'At least 4 characters.' },
+ { name: 'description', type: 'string', required: true, description: 'At least 20 characters explaining the report.' },
+ {
+ name: 'categories',
+ type: 'string[]',
+ required: true,
+ description: 'One or more tags such as "audio", "ui", or "content".',
+ },
+ {
+ name: 'contactEmail',
+ type: 'string',
+ description: 'Optional email address if you want a follow-up message.',
+ },
+ ],
+ sampleRequest: `curl -X POST https://opensquawk.de/api/service/feedback/issues \
+ -H 'Content-Type: application/json' \
+ -d '{
+ "title": "Audio drops in busy towers",
+ "description": "While working EDDF Approach the audio fell silent twice during high traffic. It recovers after ~5 seconds but the gap is scary.",
+ "categories": ["audio", "stability"],
+ "contactEmail": "pilot@example.com"
+ }'`,
+ sampleResponse: `{
+ "success": true,
+ "reportId": "5f0b4a16-7b52-4b63-8894-0f3a28e2d6a4"
+}`,
+ notes: 'Reports are delivered to the operations team and may be triaged publicly in future releases.',
+ },
{
method: 'POST',
path: '/api/service/auth/login',
diff --git a/app/pages/feedback.vue b/app/pages/feedback.vue
index 9b1c132..a1df35f 100644
--- a/app/pages/feedback.vue
+++ b/app/pages/feedback.vue
@@ -23,24 +23,14 @@
We are currently a German development team, but all public docs and tools start in English so we can reach as many people as possible.
-
-
-
-
Quick heads-up
-
All notes are sent by email. When you submit below we prepare an email to info@opensquawk.de with your answers, just like the rest of our forms.
-
-
-
- Request a call
-
+
+
+
-