feat: Implement person management features
- 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.
This commit is contained in:
102
libertas-frontend/src/components/people/person-card.tsx
Normal file
102
libertas-frontend/src/components/people/person-card.tsx
Normal file
@@ -0,0 +1,102 @@
|
||||
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>
|
||||
</>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user