- Added hooks for listing, creating, updating, deleting, sharing, and merging people. - Introduced a new route for person details and media. - Implemented clustering faces functionality. - Created services for person-related API interactions. feat: Introduce tag management functionality - Added hooks for listing, adding, and removing tags from media. - Created services for tag-related API interactions. feat: Enhance user authentication handling - Added a hook to fetch current user details. - Updated auth storage to manage user state more effectively. feat: Update album management features - Enhanced album service to return created album details. - Updated API handlers to return album responses upon creation. - Modified album repository to return created album. feat: Implement media management improvements - Added media details fetching and processing of media URLs. - Enhanced media upload functionality to return processed media. feat: Introduce face management features - Added services for listing faces for media and assigning faces to persons. fix: Update API client to clear authentication state on 401 errors.
103 lines
3.3 KiB
TypeScript
103 lines
3.3 KiB
TypeScript
import { useState } from "react";
|
|
import { type Person } from "@/domain/types";
|
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
|
import { useNavigate } from "@tanstack/react-router";
|
|
import { Trash2, UserSquare } from "lucide-react";
|
|
import {
|
|
ContextMenu,
|
|
ContextMenuContent,
|
|
ContextMenuItem,
|
|
ContextMenuTrigger,
|
|
} from "@/components/ui/context-menu";
|
|
import {
|
|
AlertDialog,
|
|
AlertDialogAction,
|
|
AlertDialogCancel,
|
|
AlertDialogContent,
|
|
AlertDialogDescription,
|
|
AlertDialogFooter,
|
|
AlertDialogHeader,
|
|
AlertDialogTitle,
|
|
} from "@/components/ui/alert-dialog";
|
|
import { useDeletePerson } from "@/features/people/use-people";
|
|
import { buttonVariants } from "@/components/ui/button";
|
|
|
|
type PersonCardProps = {
|
|
person: Person;
|
|
};
|
|
|
|
export function PersonCard({ person }: PersonCardProps) {
|
|
const navigate = useNavigate();
|
|
const [showDeleteDialog, setShowDeleteDialog] = useState(false);
|
|
const { mutate: deletePerson, isPending: isDeleting } = useDeletePerson(
|
|
person.id
|
|
);
|
|
|
|
const handleDelete = () => {
|
|
deletePerson();
|
|
};
|
|
|
|
return (
|
|
<>
|
|
<ContextMenu>
|
|
<ContextMenuTrigger>
|
|
<Card
|
|
className="overflow-hidden hover:shadow-lg transition-shadow cursor-pointer"
|
|
onClick={() => {
|
|
// Navigate on left click
|
|
navigate({
|
|
to: "/people/$personId",
|
|
params: { personId: person.id },
|
|
});
|
|
}}
|
|
>
|
|
<CardHeader className="p-0">
|
|
<div className="aspect-square bg-gray-200 flex items-center justify-center">
|
|
{/* TODO: Add person thumbnail */}
|
|
<UserSquare className="w-1/2 h-1/2 text-gray-400" />
|
|
</div>
|
|
</CardHeader>
|
|
<CardContent className="p-4">
|
|
<CardTitle className="text-lg truncate text-center">
|
|
{person.name}
|
|
</CardTitle>
|
|
</CardContent>
|
|
</Card>
|
|
</ContextMenuTrigger>
|
|
<ContextMenuContent>
|
|
<ContextMenuItem
|
|
className="text-destructive focus:text-destructive"
|
|
onSelect={() => setShowDeleteDialog(true)}
|
|
disabled={isDeleting}
|
|
>
|
|
<Trash2 className="mr-2 h-4 w-4" />
|
|
Delete Person
|
|
</ContextMenuItem>
|
|
</ContextMenuContent>
|
|
</ContextMenu>
|
|
|
|
<AlertDialog open={showDeleteDialog} onOpenChange={setShowDeleteDialog}>
|
|
<AlertDialogContent>
|
|
<AlertDialogHeader>
|
|
<AlertDialogTitle>Are you sure?</AlertDialogTitle>
|
|
<AlertDialogDescription>
|
|
This action cannot be undone. This will permanently delete{" "}
|
|
<strong>{person.name}</strong> and unassign all associated faces.
|
|
</AlertDialogDescription>
|
|
</AlertDialogHeader>
|
|
<AlertDialogFooter>
|
|
<AlertDialogCancel>Cancel</AlertDialogCancel>
|
|
<AlertDialogAction
|
|
className={buttonVariants({ variant: "destructive" })}
|
|
onClick={handleDelete}
|
|
disabled={isDeleting}
|
|
>
|
|
{isDeleting ? "Deleting..." : "Delete"}
|
|
</AlertDialogAction>
|
|
</AlertDialogFooter>
|
|
</AlertDialogContent>
|
|
</AlertDialog>
|
|
</>
|
|
);
|
|
}
|