import { useForm, usePage } from '@inertiajs/react'; import { Flag } from 'lucide-react'; import type { ReactNode } from 'react'; import { useId, useState } from 'react'; import { store } from '@/actions/App/Http/Controllers/CommitReportController'; import { ImageDropOverlay, ImagePickerButton, ImagePickerPreviews, imageErrorFrom, useImagePreviewCleanup, } from '@/components/commit-image-picker'; import InputError from '@/components/input-error'; import { Button } from '@/components/ui/button'; import { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger, } from '@/components/ui/dialog'; import { Tooltip, TooltipContent, TooltipTrigger, } from '@/components/ui/tooltip'; import { useCommitNotFound } from '@/hooks/use-deleted-resources'; import { useImageAttachments } from '@/hooks/use-image-attachments'; import type { Commit } from '@/types'; const reasons = [ ['spam', 'Spam or misleading links'], ['harassment', 'Harassment or hate'], ['unsafe', 'Harmful or private information'], ['other', 'Something else'], ]; export function useCanReport(commit: Commit): boolean { const { auth } = usePage().props; return ( auth.user !== null && commit.status === 'approved' && commit.user_id !== auth.user.id ); } export function CommitReportButton({ commit }: { commit: Commit }) { const [open, setOpen] = useState(false); if (!useCanReport(commit)) { return null; } return ( Report commit ); } export function CommitReportDialog({ commit, open, onOpenChange, children, }: { commit: Commit; open: boolean; onOpenChange: (open: boolean) => void; children?: ReactNode; }) { const [isSending, setIsSending] = useState(false); return ( { if (!isSending) { onOpenChange(next); } }} > {children} onOpenChange(false)} /> ); } /** * The report itself, mounted only while its dialog shows: every card has a report dialog, and most never open. It * starts blank each time the dialog opens. */ function ReportForm({ commit, onSendingChange, onDone, }: { commit: Commit; onSendingChange: (isSending: boolean) => void; onDone: () => void; }) { const [failure, setFailure] = useState(''); const commitNotFound = useCommitNotFound(); const id = useId(); const form = useForm({ reason: '', details: '', images: [] as File[], image_descriptions: [] as string[], }); useImagePreviewCleanup(form.data.images); const attachments = useImageAttachments( form.data.images, form.data.image_descriptions, (images, descriptions) => { form.setData((data) => ({ ...data, images, image_descriptions: descriptions, })); }, `report:${commit.id}:${id}`, ); return ( <> Report commit Your report is private. Attachments are visible only to you and moderators. Reporting does not hide this commit.

{commit.body}

{ event.preventDefault(); if (form.processing || attachments.isReading()) return; setFailure(''); form.submit(store(commit), { preserveScroll: true, onStart: () => onSendingChange(true), onFinish: () => onSendingChange(false), onSuccess: () => { onDone(); attachments.clear(); form.reset(); }, onHttpException: (response) => { if (commitNotFound(commit.id, response)) { onDone(); return false; } setFailure( response.status === 429 ? 'Too many reports. Please wait a minute and try again.' : 'This commit is no longer available to report.', ); return false; }, onNetworkError: () => { setFailure( 'Could not send your report. Check your connection and try again.', ); return false; }, }); }} >
Why are you reporting this commit? {reasons.map(([value, label]) => ( ))}