Report Abuse

Previous

Vercel Platform report abuse block.

Docs
vercel-platformblock

Preview

Loading preview…
registry/default/blocks/report-abuse.tsx
"use client";

import { Button } from "@/components/ui/button";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import { AlertTriangle, Shield } from "lucide-react";
import { useState } from "react";

export type ReportAbuseProps = {
  types: {
    value: string;
    label: string;
  }[];
};

export function ReportAbuse({ types }: ReportAbuseProps) {
  const [open, setOpen] = useState(false);
  const [category, setCategory] = useState("");
  const [contentUrl, setContentUrl] = useState("");
  const [description, setDescription] = useState("");
  const [email, setEmail] = useState("");

  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    setOpen(false);
    // Reset form
    setCategory("");
    setContentUrl("");
    setDescription("");
    setEmail("");
  };

  const handleCancel = () => {
    setOpen(false);
    // Reset form
    setCategory("");
    setContentUrl("");
    setDescription("");
    setEmail("");
  };

  return (
    <Dialog onOpenChange={setOpen} open={open}>
      <DialogTrigger asChild>
        <Button variant="destructive">Report Abuse</Button>
      </DialogTrigger>
      <DialogContent>
        <DialogHeader>
          <div className="mb-2 flex items-center gap-3">
            <div className="flex size-10 items-center justify-center rounded-full bg-red-50">
              <AlertTriangle className="size-4 text-red-600" />
            </div>
            <div className="space-y-1">
              <DialogTitle>Report Abuse</DialogTitle>
              <DialogDescription>
                Help us keep our platform safe
              </DialogDescription>
            </div>
          </div>
        </DialogHeader>
        <form className="space-y-4" onSubmit={handleSubmit}>
          <div className="space-y-2">
            <Label>What type of issue are you reporting?</Label>
            <Select onValueChange={setCategory} required value={category}>
              <SelectTrigger className="w-full" id="category">
                <SelectValue placeholder="Select a category" />
              </SelectTrigger>
              <SelectContent>
                {types.map((type) => (
                  <SelectItem key={type.value} value={type.value}>
                    {type.label}
                  </SelectItem>
                ))}
              </SelectContent>
            </Select>
          </div>

          <div className="space-y-2">
            <Label htmlFor="url">
              Content URL{" "}
              <span className="text-muted-foreground">(optional)</span>
            </Label>
            <Input
              id="url"
              onChange={(e) => setContentUrl(e.target.value)}
              placeholder="https://example.com/content"
              type="url"
              value={contentUrl}
            />
          </div>

          <div className="space-y-2">
            <Label htmlFor="description">Description</Label>
            <textarea
              className="flex min-h-[120px] w-full resize-none rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-xs transition-[color,box-shadow] placeholder:text-muted-foreground focus-visible:border-ring focus-visible:outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50"
              id="description"
              onChange={(e) => setDescription(e.target.value)}
              placeholder="Please describe the issue in detail. Include any relevant context that will help us understand the problem."
              required
              value={description}
            />
          </div>

          <div className="space-y-2">
            <Label htmlFor="email">Your email</Label>
            <Input
              id="email"
              onChange={(e) => setEmail(e.target.value)}
              placeholder="your.email@example.com"
              required
              type="email"
              value={email}
            />
            <p className="text-muted-foreground text-xs">
              We may contact you for additional information about this report.
            </p>
          </div>

          <div className="rounded-lg border bg-muted/30 p-4">
            <div className="flex gap-3">
              <Shield className="mt-0.5 size-4 flex-shrink-0 text-muted-foreground" />
              <div className="space-y-1">
                <p className="font-medium text-sm">Privacy Notice</p>
                <p className="text-muted-foreground text-sm">
                  Your report will be reviewed by our moderation team. We take
                  all reports seriously and will investigate accordingly. False
                  reports may result in account restrictions.
                </p>
              </div>
            </div>
          </div>

          <div className="flex gap-3 pt-2">
            <Button onClick={handleCancel} type="button" variant="outline">
              Cancel
            </Button>
            <Button type="submit">Submit Report</Button>
          </div>
        </form>
      </DialogContent>
    </Dialog>
  );
}

Installation

npx shadcn@latest add @vercel-platform/report-abuse

Usage

import { ReportAbuse } from "@/components/report-abuse"
<ReportAbuse />