feat: Add optional date picker to photos

This commit is contained in:
gpt-engineer-app[bot]
2025-09-29 18:36:33 +00:00
parent 0801f6fd1d
commit 3499c4891f
2 changed files with 61 additions and 1 deletions

View File

@@ -4,14 +4,18 @@ import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Button } from '@/components/ui/button';
import { Badge } from '@/components/ui/badge';
import { X, Eye, GripVertical, Edit3 } from 'lucide-react';
import { Calendar } from '@/components/ui/calendar';
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';
import { X, Eye, GripVertical, Edit3, CalendarIcon } from 'lucide-react';
import { cn } from '@/lib/utils';
import { format } from 'date-fns';
export interface PhotoWithCaption {
url: string; // Object URL for preview, Cloudflare URL after upload
file?: File; // The actual file to upload later
caption: string;
title?: string;
date?: Date; // Optional date for the photo
order: number;
uploadStatus?: 'pending' | 'uploading' | 'uploaded' | 'failed';
}
@@ -47,6 +51,13 @@ export function PhotoCaptionEditor({
onPhotosChange(updatedPhotos);
};
const updatePhotoDate = (index: number, date: Date | undefined) => {
const updatedPhotos = photos.map((photo, i) =>
i === index ? { ...photo, date } : photo
);
onPhotosChange(updatedPhotos);
};
const movePhoto = (fromIndex: number, toIndex: number) => {
const updatedPhotos = [...photos];
const [movedPhoto] = updatedPhotos.splice(fromIndex, 1);
@@ -143,6 +154,48 @@ export function PhotoCaptionEditor({
className="h-8 text-sm"
/>
</div>
<div>
<Label htmlFor={`date-${index}`} className="text-xs">
Date (optional)
</Label>
<Popover>
<PopoverTrigger asChild>
<Button
id={`date-${index}`}
variant="outline"
className={cn(
"w-full h-8 justify-start text-left font-normal text-sm",
!photo.date && "text-muted-foreground"
)}
>
<CalendarIcon className="mr-2 h-3 w-3" />
{photo.date ? format(photo.date, "PPP") : <span>Pick a date</span>}
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto p-0" align="start">
<Calendar
mode="single"
selected={photo.date}
onSelect={(date) => updatePhotoDate(index, date)}
disabled={(date) => date > new Date()}
initialFocus
className={cn("p-3 pointer-events-auto")}
/>
{photo.date && (
<div className="p-2 border-t">
<Button
variant="ghost"
size="sm"
className="w-full h-7 text-xs"
onClick={() => updatePhotoDate(index, undefined)}
>
Clear date
</Button>
</div>
)}
</PopoverContent>
</Popover>
</div>
<div>
<Label htmlFor={`caption-${index}`} className="text-xs">
Caption
@@ -165,6 +218,12 @@ export function PhotoCaptionEditor({
{photo.title && (
<p className="text-sm font-medium">{photo.title}</p>
)}
{photo.date && (
<p className="text-xs text-muted-foreground flex items-center gap-1">
<CalendarIcon className="w-3 h-3" />
{format(photo.date, "PPP")}
</p>
)}
<p className="text-sm text-muted-foreground">
{photo.caption || (
<span className="italic">Click edit to add caption</span>

View File

@@ -198,6 +198,7 @@ export function UppyPhotoSubmissionUpload({
url: photo.uploadStatus === 'uploaded' ? photo.url : uploadedPhotos.find(p => p.order === photo.order)?.url || photo.url,
caption: photo.caption.trim(),
title: photo.title?.trim(),
date: photo.date?.toISOString(),
order: index,
})),
// NEW STRUCTURE: context as string, IDs at top level