- Add inline pickers on board cards for priority, assignee, and due date - Add custom trigger prop to PriorityPicker, AssigneePicker, DueDatePicker for styling control - Replace due date quick options with Calendar-based DueDatePicker in issue detail sidebar - Use PickerWrapper to stop event propagation from pickers to Link/drag handlers Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
70 lines
2.1 KiB
TypeScript
70 lines
2.1 KiB
TypeScript
"use client";
|
|
|
|
import { useState } from "react";
|
|
import { CalendarDays } from "lucide-react";
|
|
import type { UpdateIssueRequest } from "@/shared/types";
|
|
import { Calendar } from "@/components/ui/calendar";
|
|
import {
|
|
Popover,
|
|
PopoverTrigger,
|
|
PopoverContent,
|
|
} from "@/components/ui/popover";
|
|
import { Button } from "@/components/ui/button";
|
|
|
|
export function DueDatePicker({
|
|
dueDate,
|
|
onUpdate,
|
|
trigger: customTrigger,
|
|
}: {
|
|
dueDate: string | null;
|
|
onUpdate: (updates: Partial<UpdateIssueRequest>) => void;
|
|
trigger?: React.ReactNode;
|
|
}) {
|
|
const [open, setOpen] = useState(false);
|
|
const date = dueDate ? new Date(dueDate) : undefined;
|
|
const isOverdue = date ? date < new Date() : false;
|
|
|
|
return (
|
|
<Popover open={open} onOpenChange={setOpen}>
|
|
<PopoverTrigger className="flex items-center gap-1.5 cursor-pointer rounded px-1 -mx-1 hover:bg-accent/30 transition-colors">
|
|
{customTrigger ?? (
|
|
<>
|
|
<CalendarDays className="h-3.5 w-3.5 text-muted-foreground" />
|
|
{date ? (
|
|
<span className={isOverdue ? "text-destructive" : ""}>
|
|
{date.toLocaleDateString("en-US", { month: "short", day: "numeric" })}
|
|
</span>
|
|
) : (
|
|
<span className="text-muted-foreground">Due date</span>
|
|
)}
|
|
</>
|
|
)}
|
|
</PopoverTrigger>
|
|
<PopoverContent className="w-auto p-0" align="start">
|
|
<Calendar
|
|
mode="single"
|
|
selected={date}
|
|
onSelect={(d: Date | undefined) => {
|
|
onUpdate({ due_date: d ? d.toISOString() : null });
|
|
setOpen(false);
|
|
}}
|
|
/>
|
|
{date && (
|
|
<div className="border-t px-3 py-2">
|
|
<Button
|
|
variant="ghost"
|
|
size="xs"
|
|
onClick={() => {
|
|
onUpdate({ due_date: null });
|
|
setOpen(false);
|
|
}}
|
|
className="text-muted-foreground hover:text-foreground"
|
|
>
|
|
Clear date
|
|
</Button>
|
|
</div>
|
|
)}
|
|
</PopoverContent>
|
|
</Popover>
|
|
);
|
|
}
|