1
0
Fork 0
polaris-task-force/src/components/frontend/account/AwardPickerDialog.tsx

120 lines
3.9 KiB
TypeScript

"use client";
import { useState } from "react";
import type { Award } from "@/payload-types";
import { Badge } from "@/components/ui/badge";
import {
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
} from "@/components/ui/dialog";
import { RibbonDesign } from "@/components/admin/awards/RibbonDesigner";
import { RibbonViewer } from "./RibbonViewer";
import { GrantAwardDialog } from "./GrantAwardDialog";
import { MedalIcon, RibbonIcon, ScrollTextIcon } from "lucide-react";
interface AwardPickerDialogProps {
awards: Award[];
recipientUserId: number;
recipientUsername: string;
open: boolean;
onOpenChange: (open: boolean) => void;
onGranted?: () => void;
}
/**
* Grid of grantable awards. Selecting a card closes this dialog and opens the
* GrantAwardDialog for that award with the recipient pre-filled.
*/
export function AwardPickerDialog({
awards,
recipientUserId,
recipientUsername,
open,
onOpenChange,
onGranted,
}: AwardPickerDialogProps) {
const [selectedAward, setSelectedAward] = useState<Award | null>(null);
function pick(award: Award) {
setSelectedAward(award);
onOpenChange(false);
}
return (
<>
<Dialog
open={open}
onOpenChange={(o) => {
if (!o) setSelectedAward(null);
onOpenChange(o);
}}
>
<DialogContent className="sm:max-w-2xl">
<DialogHeader>
<DialogTitle>Select an award</DialogTitle>
<DialogDescription>
Choose which award to grant to @{recipientUsername}.
</DialogDescription>
</DialogHeader>
{awards.length === 0 ? (
<p className="py-6 text-center text-sm text-muted-foreground">
No awards are available to grant.
</p>
) : (
<div className="grid max-h-[50vh] grid-cols-1 gap-3 overflow-y-auto sm:grid-cols-2 md:grid-cols-3">
{awards.map((award) => (
<button
key={award.id}
type="button"
onClick={() => pick(award)}
className="flex flex-col items-center gap-2 rounded-md border bg-card p-3 text-left transition-colors hover:border-primary/50 hover:bg-accent"
>
{award.type === "ribbon" && award.ribbonDesign ? (
<div className="flex h-16 w-full items-center justify-center">
<div className="w-32 max-w-full">
<RibbonViewer ribbonDesign={award.ribbonDesign as RibbonDesign} showRibbonOnly />
</div>
</div>
) : (
<span className="flex size-16 items-center justify-center rounded-md bg-muted">
{award.type === "medal" ? (
<MedalIcon className="size-6 text-muted-foreground" />
) : award.type === "commendation" ? (
<ScrollTextIcon className="size-6 text-muted-foreground" />
) : (
<RibbonIcon className="size-6 text-muted-foreground" />
)}
</span>
)}
<span className="line-clamp-2 text-center text-sm font-medium">
{award.name}
</span>
<Badge variant="secondary" className="w-fit capitalize">
{award.type ?? "award"}
</Badge>
</button>
))}
</div>
)}
</DialogContent>
</Dialog>
{selectedAward && (
<GrantAwardDialog
awardId={selectedAward.id}
awardName={selectedAward.name}
recipientUserId={recipientUserId}
recipientUsername={recipientUsername}
open
onOpenChange={(o) => {
if (!o) setSelectedAward(null);
}}
onGranted={onGranted}
/>
)}
</>
);
}