From 2a372fdec256b8be890e181c221c2a012ead9efa Mon Sep 17 00:00:00 2001 From: cashmere Date: Mon, 27 Jul 2026 01:21:02 +0200 Subject: refactor: strip landing page and upstream branding / redirects to /projects; marketing landing components, the feedback popover + API route, and all Discord links removed (editor header, footer, onboarding copy). --- .../src/feedback/components/feedback-popover.tsx | 242 --------------------- 1 file changed, 242 deletions(-) delete mode 100644 apps/web/src/feedback/components/feedback-popover.tsx (limited to 'apps/web/src/feedback/components/feedback-popover.tsx') diff --git a/apps/web/src/feedback/components/feedback-popover.tsx b/apps/web/src/feedback/components/feedback-popover.tsx deleted file mode 100644 index f94b7253..00000000 --- a/apps/web/src/feedback/components/feedback-popover.tsx +++ /dev/null @@ -1,242 +0,0 @@ -"use client"; - -import { useState } from "react"; -import { useForm } from "react-hook-form"; -import { toast } from "sonner"; -import { ClockIcon } from "lucide-react"; -import { - Popover, - PopoverContent, - PopoverTrigger, -} from "@/components/ui/popover"; -import { Button } from "@/components/ui/button"; -import { Textarea } from "@/components/ui/textarea"; -import { Spinner } from "@/components/ui/spinner"; -import { - Form, - FormField, - FormItem, - FormControl, - clearFormDraft, -} from "@/components/ui/form"; -import type { FeedbackEntry } from "../types"; - -const PERSIST_KEY = "feedback-draft"; -const HISTORY_KEY = "feedback-history"; -const MAX_HISTORY = 20; - -interface FeedbackFormValues { - message: string; -} - -function readHistory(): FeedbackEntry[] { - try { - const stored = localStorage.getItem(HISTORY_KEY); - return stored ? (JSON.parse(stored) as FeedbackEntry[]) : []; - } catch { - return []; - } -} - -function writeHistory({ entries }: { entries: FeedbackEntry[] }): void { - try { - localStorage.setItem(HISTORY_KEY, JSON.stringify(entries)); - } catch { - // localStorage may be full or unavailable - } -} - -function useFeedback() { - const [entries, setEntries] = useState(readHistory); - const [isSubmitting, setIsSubmitting] = useState(false); - - async function submit({ - values, - onSuccess, - }: { - values: FeedbackFormValues; - onSuccess: () => void; - }) { - if (isSubmitting) return; - setIsSubmitting(true); - - try { - const res = await fetch("/api/feedback", { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify(values), - }); - - if (!res.ok) { - const data = await res.json().catch(() => null); - throw new Error(data?.error ?? "Failed to submit"); - } - - const { entry } = await res.json(); - const next = [entry, ...entries].slice(0, MAX_HISTORY); - setEntries(next); - writeHistory({ entries: next }); - onSuccess(); - toast.success("Feedback sent"); - } catch (error) { - toast.error( - error instanceof Error ? error.message : "Failed to send feedback", - ); - } finally { - setIsSubmitting(false); - } - } - - return { entries, isSubmitting, submit }; -} - -export function FeedbackPopover() { - const [open, setOpen] = useState(false); - - return ( - - - - - - setOpen(false)} /> - - - ); -} - -type View = "compose" | "history"; - -function FeedbackPopoverContent({ onClose }: { onClose: () => void }) { - const { entries, isSubmitting, submit } = useFeedback(); - const [view, setView] = useState("compose"); - - const form = useForm({ - defaultValues: { message: "" }, - }); - - async function handleSubmit(values: FeedbackFormValues) { - await submit({ - values, - onSuccess: () => { - form.reset({ message: "" }); - clearFormDraft({ key: PERSIST_KEY }); - onClose(); - }, - }); - } - - if (view === "history") { - return ( -
-
- {entries.map((entry) => ( - - ))} -
-
- -
-
- ); - } - - return ( -
-
- - ( - - -