2026-02-08 18:32:13 +00:00

172 lines
6.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { useEffect, useState } from "react";
import Navigation from "@/components/landing/Navigation";
import Footer from "@/components/landing/Footer";
import FAQSection from "@/components/landing/FAQSection";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Textarea } from "@/components/ui/textarea";
import { apiRequest, getQueryFn } from "@/lib/queryClient";
import { toast } from "@/hooks/use-toast";
import { useQuery } from "@tanstack/react-query";
type SessionUser = {
id: string;
username: string;
};
export default function SupportPage() {
const [form, setForm] = useState({
name: "",
email: "",
subject: "",
message: "",
});
const [ticketId, setTicketId] = useState("");
const [statusEmail, setStatusEmail] = useState("");
const [statusResult, setStatusResult] = useState<null | {
ticket_id: string;
status: string;
created_at?: string;
updated_at?: string;
}>(null);
const [submitting, setSubmitting] = useState(false);
const [checking, setChecking] = useState(false);
const { data: sessionUser } = useQuery<SessionUser | null>({
queryKey: ["/me"],
queryFn: getQueryFn<SessionUser | null>({ on401: "returnNull" }),
});
const sessionEmail = sessionUser?.username?.trim() || "";
useEffect(() => {
if (sessionEmail) {
setForm((prev) => ({ ...prev, email: sessionEmail }));
setStatusEmail(sessionEmail);
}
}, [sessionEmail]);
const submitTicket = async () => {
const effectiveEmail = sessionEmail || form.email.trim();
if (!form.name.trim() || !effectiveEmail || !form.subject.trim() || !form.message.trim()) {
toast({ title: "Please fill all fields." });
return;
}
setSubmitting(true);
try {
const res = await apiRequest("POST", "/support/ticket", {
...form,
email: effectiveEmail,
});
const data = await res.json();
setTicketId(data.ticket_id || "");
toast({ title: "Ticket created", description: `Ticket ID: ${data.ticket_id}` });
setForm({ name: "", email: "", subject: "", message: "" });
} catch (err: any) {
toast({ title: "Failed to create ticket", description: err?.message || "Try again." });
} finally {
setSubmitting(false);
}
};
const checkStatus = async () => {
const effectiveEmail = sessionEmail || statusEmail.trim();
if (!ticketId.trim() || !effectiveEmail) {
toast({ title: "Enter ticket ID and email." });
return;
}
setChecking(true);
try {
const res = await apiRequest("POST", `/support/ticket/status/${ticketId.trim()}`, {
email: effectiveEmail,
});
const data = await res.json();
setStatusResult(data);
} catch (err: any) {
setStatusResult(null);
toast({ title: "Ticket not found", description: "Check ticket ID and email." });
} finally {
setChecking(false);
}
};
return (
<div className="min-h-screen text-foreground">
<Navigation />
<main className="pt-24">
<section className="py-24 px-6 bg-card/10">
<div className="max-w-5xl mx-auto grid gap-10 lg:grid-cols-2">
<div className="space-y-6">
<h1 className="text-4xl md:text-5xl font-bold">Support Center</h1>
<p className="text-muted-foreground text-lg">
Need help? Create a support ticket and well get back to you.
</p>
<div className="rounded-2xl border border-card-border bg-card/60 p-6 space-y-4">
<h2 className="text-xl font-semibold">Contact support</h2>
<div className="grid gap-4">
<Input
placeholder="Full name"
value={form.name}
onChange={(e) => setForm((p) => ({ ...p, name: e.target.value }))}
/>
<Input
placeholder="Email"
value={form.email}
onChange={(e) => setForm((p) => ({ ...p, email: e.target.value }))}
disabled={Boolean(sessionEmail)}
/>
<Input
placeholder="Subject"
value={form.subject}
onChange={(e) => setForm((p) => ({ ...p, subject: e.target.value }))}
/>
<Textarea
placeholder="Describe your issue"
value={form.message}
onChange={(e) => setForm((p) => ({ ...p, message: e.target.value }))}
rows={5}
/>
<Button onClick={submitTicket} disabled={submitting}>
{submitting ? "Submitting..." : "Submit ticket"}
</Button>
</div>
</div>
</div>
<div className="space-y-6">
<div className="rounded-2xl border border-card-border bg-card/60 p-6 space-y-4">
<h2 className="text-xl font-semibold">Check ticket status</h2>
<Input
placeholder="Ticket ID"
value={ticketId}
onChange={(e) => setTicketId(e.target.value)}
/>
<Input
placeholder="Email used for ticket"
value={statusEmail}
onChange={(e) => setStatusEmail(e.target.value)}
disabled={Boolean(sessionEmail)}
/>
<Button onClick={checkStatus} disabled={checking}>
{checking ? "Checking..." : "Check status"}
</Button>
{statusResult && (
<div className="rounded-xl border border-card-border bg-black/30 p-4 text-sm">
<div><strong>Status:</strong> {statusResult.status}</div>
{statusResult.created_at && (
<div><strong>Created:</strong> {statusResult.created_at}</div>
)}
{statusResult.updated_at && (
<div><strong>Updated:</strong> {statusResult.updated_at}</div>
)}
</div>
)}
</div>
<FAQSection />
</div>
</div>
</section>
</main>
<Footer />
</div>
);
}