"use client"; import type { ChangeEvent, ComponentType } from "react"; import Image from "next/image"; import { Bug, Check, CheckCircle2, CreditCard, ImagePlus, Lightbulb, MessageCircleMore, Send, Trash2, } from "lucide-react"; import { BackButton } from "@/app/_components"; import { MobileShell } from "@/app/_components/core"; import type { FeedbackCategory } from "@/data/schemas/feedback"; import { resolveGlobalRouteContext, type GlobalReturnToValue, } from "@/router/global-route-context"; import { useGlobalAppNavigator } from "@/router/use-global-app-navigator"; import { FEEDBACK_IMAGE_ACCEPT, FEEDBACK_IMAGE_LIMIT, } from "./feedback-image"; import { FEEDBACK_CONTENT_MIN_LENGTH, FEEDBACK_CONTENT_MAX_LENGTH, useFeedbackSubmission, } from "./use-feedback-submission"; import styles from "./feedback-screen.module.css"; interface CategoryOption { value: FeedbackCategory; label: string; icon: ComponentType<{ size?: number; strokeWidth?: number }>; } const CATEGORY_OPTIONS: readonly CategoryOption[] = [ { value: "problem", label: "Problem", icon: Bug }, { value: "suggestion", label: "Suggestion", icon: Lightbulb }, { value: "payment", label: "Payment", icon: CreditCard }, { value: "other", label: "Other", icon: MessageCircleMore }, ]; export interface FeedbackScreenProps { returnTo?: GlobalReturnToValue; } export function FeedbackScreen({ returnTo }: FeedbackScreenProps) { const navigator = useGlobalAppNavigator(); const navigation = resolveGlobalRouteContext(returnTo); const form = useFeedbackSubmission(); if (form.feedbackId) { return ( Feedback received Thank you for helping us. Your report is safely on its way to the CozSweet team. Feedback ID {form.feedbackId} navigator.replace(navigation.sidebarUrl)} > Back to Sidebar ); } const handleImageChange = (event: ChangeEvent) => { if (event.target.files) void form.addImages(event.target.files); event.target.value = ""; }; return ( Help us improve CozSweet Tell us what happened. Screenshots help us understand it faster. What is this about? {CATEGORY_OPTIONS.map((option) => { const Icon = option.icon; const selected = form.category === option.value; return ( form.setCategory(option.value)} /> {option.label} {selected ? ( ) : null} ); })} Describe your feedback Minimum {FEEDBACK_CONTENT_MIN_LENGTH} characters required. form.setContent(event.target.value)} /> {form.content.length}/{FEEDBACK_CONTENT_MAX_LENGTH} Add screenshots Optional JPEG, PNG or WebP ยท up to 5 MB each {form.images.length}/{FEEDBACK_IMAGE_LIMIT} {form.images.map((image, index) => ( form.removeImage(image.id)} > ))} {form.images.length < FEEDBACK_IMAGE_LIMIT ? ( {form.isPreparingImages ? "Preparing..." : "Add image"} ) : null} {form.errorMessage ? ( {form.errorMessage} ) : null} {form.isSubmitting ? "Sending feedback..." : "Send feedback"} ); }
Feedback received
Your report is safely on its way to the CozSweet team.
Tell us what happened. Screenshots help us understand it faster.
Minimum {FEEDBACK_CONTENT_MIN_LENGTH} characters required.
JPEG, PNG or WebP ยท up to 5 MB each
{form.errorMessage}