Files
old.admin.gaertan.art/src/components/sort/SortableImage.tsx
2025-07-12 22:08:55 +02:00

88 lines
2.6 KiB
TypeScript

'use client';
import { useSortable } from '@dnd-kit/sortable';
import { CSS } from '@dnd-kit/utilities';
import clsx from 'clsx';
import { CheckCircle, Circle, GripVertical } from 'lucide-react';
import NextImage from 'next/image';
import Link from 'next/link';
type SortableCardItemProps = {
id: string;
item: {
id: string;
name: string;
fileKey: string;
altText: string;
published?: boolean;
creationDate?: Date | string;
};
};
export function SortableImage({ id, item }: SortableCardItemProps) {
const { attributes, listeners, setNodeRef, transform, transition } = useSortable({ id });
const style = {
transform: CSS.Transform.toString(transform),
transition,
};
const href = `/portfolio/edit/${item.id}`;
let dateDisplay = null;
if (item.creationDate instanceof Date) {
dateDisplay = item.creationDate.toLocaleDateString('de-DE');
} else if (typeof item.creationDate === 'string') {
const parsed = new Date(item.creationDate);
if (!isNaN(parsed.getTime())) {
dateDisplay = parsed.toLocaleDateString('de-DE');
}
}
return (
<div
ref={setNodeRef}
style={style}
{...attributes}
className="relative cursor-grab active:cursor-grabbing"
>
<div
{...listeners}
className="absolute top-2 left-2 z-20 text-muted-foreground bg-white/70 rounded-full p-1"
title="Drag to reorder"
>
<GripVertical className="w-4 h-4" />
</div>
<Link href={href}>
<div className="group rounded-lg border overflow-hidden hover:shadow-md transition-shadow bg-background relative">
<div className="relative aspect-[4/3] w-full bg-muted items-center justify-center">
<NextImage
src={`/api/image/thumbnail/${item.fileKey}.webp`}
alt={item.altText ? item.altText : "Image"}
fill
className={clsx("object-cover transition duration-300")}
/>
</div>
{/* Content */}
<div className="p-4 text-center">
<h2 className="text-lg font-semibold truncate">{item.name}</h2>
{dateDisplay && (
<p className="text-xs text-muted-foreground mt-1">{dateDisplay}</p>
)}
</div>
{/* Status icon in bottom-left corner */}
<div className="absolute bottom-2 left-2 z-10 bg-white/80 rounded-full p-1">
{item.published ? (
<CheckCircle className="w-4 h-4 text-green-600" />
) : (
<Circle className="w-4 h-4 text-muted-foreground" />
)}
</div>
</div>
</Link>
</div>
);
}