chore: code refactor

This commit is contained in:
gosangam
2026-06-13 02:24:42 +05:30
parent cc5633c37a
commit 439664a97d
151 changed files with 1387 additions and 1138 deletions
@@ -0,0 +1,135 @@
"use client";
/**
* ReportCommentModal — compact category + reason form for reporting a comment.
* Controlled by the parent via `comment` (null = closed). Submits through the
* comments API and toasts the outcome.
*/
import { useEffect, useState } from "react";
import { toast } from "sonner";
import { cn } from "@/lib/utils";
import {
comments as commentsApi,
SocialError,
type Comment,
type PostReportCategory,
} from "@/lib/social";
const REPORT_CATEGORIES: { value: PostReportCategory; label: string }[] = [
{ value: "spam", label: "Spam or misleading" },
{ value: "harassment", label: "Harassment or bullying" },
{ value: "misinformation", label: "Misinformation" },
{ value: "inappropriate", label: "Inappropriate content" },
{ value: "other", label: "Something else" },
];
export function ReportCommentModal({
comment,
onClose,
}: {
comment: Comment | null;
onClose: () => void;
}) {
const [category, setCategory] = useState<PostReportCategory>("spam");
const [reason, setReason] = useState("");
const [working, setWorking] = useState(false);
useEffect(() => {
if (comment) {
setCategory("spam");
setReason("");
setWorking(false);
}
}, [comment]);
if (!comment) return null;
async function submit() {
if (!comment) return;
setWorking(true);
try {
await commentsApi.report(comment.id, category, reason.trim());
toast("Thanks — your report was submitted", { duration: 2500 });
onClose();
} catch (err) {
toast.error(
err instanceof SocialError ? err.message : "Could not submit report",
{ duration: 3000 },
);
} finally {
setWorking(false);
}
}
return (
<div className="fixed inset-0 z-[110] flex items-center justify-center px-4">
<div
className="absolute inset-0 bg-foreground/40 backdrop-blur-sm"
onClick={() => !working && onClose()}
aria-hidden
/>
<div
role="dialog"
aria-modal="true"
className="relative w-full max-w-md rounded-2xl border border-border bg-card shadow-xl p-5"
>
<h2 className="font-[family-name:var(--font-title)] font-semibold text-lg text-foreground">
Report comment
</h2>
<p className="mt-1 text-sm text-muted-foreground">
Reports are private and reviewed by our team.
</p>
<div className="mt-4 space-y-1.5">
{REPORT_CATEGORIES.map((c) => (
<label
key={c.value}
className={cn(
"flex items-center gap-3 rounded-md border px-3 py-2 cursor-pointer transition-colors",
category === c.value
? "border-primary bg-primary/5"
: "border-border hover:bg-muted",
)}
>
<input
type="radio"
name="comment-report-category"
value={c.value}
checked={category === c.value}
onChange={() => setCategory(c.value)}
className="accent-primary"
/>
<span className="text-sm text-foreground">{c.label}</span>
</label>
))}
</div>
<textarea
value={reason}
onChange={(e) => setReason(e.target.value)}
rows={2}
maxLength={2000}
placeholder="Add details (optional)"
className="mt-3 w-full resize-none rounded-md border border-border bg-background px-3 py-2 text-base sm:text-sm text-foreground outline-none focus-visible:ring-2 focus-visible:ring-primary/40"
/>
<div className="mt-4 flex items-center justify-end gap-2">
<button
type="button"
onClick={onClose}
disabled={working}
className="h-10 px-4 rounded-md text-sm font-medium text-foreground hover:bg-muted transition-colors disabled:opacity-50"
>
Cancel
</button>
<button
type="button"
onClick={submit}
disabled={working}
className="h-10 px-4 rounded-md text-sm font-medium bg-destructive text-white hover:bg-destructive/90 transition-colors disabled:opacity-60"
>
{working ? "Submitting…" : "Submit report"}
</button>
</div>
</div>
</div>
);
}