import { baseUrl } from "@/api/baseUrl"; import Chip from "@/components/indicators/Chip"; import { Form, FormControl, FormField, FormItem } from "@/components/ui/form"; import { Input } from "@/components/ui/input"; import { ScrollArea, ScrollBar } from "@/components/ui/scroll-area"; import { Toaster } from "@/components/ui/sonner"; import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"; import useOptimisticState from "@/hooks/use-optimistic-state"; import { zodResolver } from "@hookform/resolvers/zod"; import axios from "axios"; import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { isDesktop } from "react-device-detect"; import { useForm } from "react-hook-form"; import { LuTrash } from "react-icons/lu"; import { toast } from "sonner"; import useSWR from "swr"; import { z } from "zod"; export default function FaceLibrary() { const [page, setPage] = useState(); const [pageToggle, setPageToggle] = useOptimisticState(page, setPage, 100); const tabsRef = useRef(null); // face data const { data: faceData } = useSWR("faces"); const faces = useMemo( () => (faceData ? Object.keys(faceData) : []), [faceData], ); const faceImages = useMemo( () => (pageToggle && faceData ? faceData[pageToggle] : []), [pageToggle, faceData], ); useEffect(() => { if (!pageToggle && faces) { setPageToggle(faces[0]); } // we need to listen on the value of the faces list // eslint-disable-next-line react-hooks/exhaustive-deps }, [faces]); /** * */ const formSchema = z.object({ image: z .instanceof(File, { message: "Please select an image file." }) .refine((file) => file.size < 1000000, "Image size is too large."), }); const form = useForm>({ resolver: zodResolver(formSchema), mode: "onChange", }); return (
{ if (value) { setPageToggle(value); } }} > {Object.values(faces).map((item) => (
{item}
))}
( { // @ts-expect-error ignore } )} />
{pageToggle && (
{faceImages.map((image: string) => ( ))}
)}
); } type FaceImageProps = { name: string; image: string; }; function FaceImage({ name, image }: FaceImageProps) { const [hovered, setHovered] = useState(false); const onDelete = useCallback(() => { axios .post(`/faces/${name}/delete`, { ids: [image] }) .then((resp) => { if (resp.status == 200) { toast.error(`Successfully deleted face.`, { position: "top-center" }); } }) .catch((error) => { if (error.response?.data?.message) { toast.error(`Failed to delete: ${error.response.data.message}`, { position: "top-center", }); } else { toast.error(`Failed to delete: ${error.message}`, { position: "top-center", }); } }); }, [name, image]); return (
setHovered(true) : undefined} onMouseLeave={isDesktop ? () => setHovered(false) : undefined} onClick={isDesktop ? undefined : () => setHovered(!hovered)} > {hovered && (
onDelete()} >
)}
); }