infoalloggi-monorepo/apps/infoalloggi/src/components/etichette.tsx

184 lines
4.3 KiB
TypeScript

import { Plus } from "lucide-react";
import { useState } from "react";
import { Button } from "~/components/ui/button";
import {
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
} from "~/components/ui/dialog";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "~/components/ui/select";
import { Separator } from "~/components/ui/separator";
import { colorIsDarkSimple } from "~/lib/color";
import { cn } from "~/lib/utils";
import type { ChatsChatid } from "~/schemas/public/Chats";
import type { EtichetteIdEtichetta } from "~/schemas/public/Etichette";
import { api } from "~/utils/api";
export const EtichetteDisplayer = ({
chatId,
className,
}: {
chatId: ChatsChatid;
className?: string;
}) => {
const { data, isLoading } = api.chat.getChatEtichette.useQuery({
chatId,
});
const [openEdit, setOpenEdit] = useState(false);
const handleOpen = (status: boolean) => {
setOpenEdit(status);
};
if ((!isLoading && !data) || !data) return null;
return (
<div className={cn("flex flex-wrap gap-2", className)}>
{data.map((etichetta) => (
<Etichetta
className="text-xs"
color_hex={etichetta.color_hex}
key={etichetta.id_etichetta}
title={etichetta.title}
/>
))}
<button
className="flex items-center justify-center rounded-lg border p-1"
onClick={() => setOpenEdit(true)}
type="button"
>
<Plus className="size-4" />
</button>
<EtichetteModal
chatId={chatId}
onOpenChange={handleOpen}
open={openEdit}
/>
</div>
);
};
export const EtichetteModal = ({
chatId,
open,
onOpenChange,
}: {
chatId: ChatsChatid;
open: boolean;
onOpenChange: (status: boolean) => void;
}) => {
const [selected, setSelected] = useState<EtichetteIdEtichetta | null>(null);
const utils = api.useUtils();
const { data } = api.chat.getChatEtichette.useQuery({ chatId });
const { data: etichette } = api.etichette.getAllEtichette.useQuery();
const { mutate: remove } = api.chat.removeEtichettaFromChat.useMutation({
onSuccess: async () => {
await utils.chat.getChatEtichette.invalidate({ chatId });
await utils.chat.getActiveChats.invalidate();
},
});
const { mutate: add } = api.chat.addEtichettaToChat.useMutation({
onSuccess: async () => {
await utils.chat.getChatEtichette.invalidate({ chatId });
await utils.chat.getActiveChats.invalidate();
},
});
if (!data) return null;
return (
<Dialog onOpenChange={onOpenChange} open={open}>
<DialogContent>
<DialogHeader>
<DialogTitle>Etichette Attive</DialogTitle>
<DialogDescription className="sr-only">Attive</DialogDescription>
</DialogHeader>
<div className="space-y-5">
<div className="flex flex-col gap-2">
{data.map((etichetta) => (
<div
className="flex gap-2"
key={`${etichetta.id_etichetta}${chatId}`}
>
<Etichetta
color_hex={etichetta.color_hex}
title={etichetta.title}
/>
<Button
onClick={() => {
remove({ chatId, etichettaId: etichetta.id_etichetta });
}}
>
Rimuovi
</Button>
</div>
))}
</div>
<Separator />
<div className="flex gap-2">
<Select
onValueChange={(value) =>
setSelected(parseInt(value) as EtichetteIdEtichetta)
}
>
<SelectTrigger className="w-45">
<SelectValue placeholder="Seleziona" />
</SelectTrigger>
<SelectContent>
{etichette?.map((etichetta) => (
<SelectItem
key={etichetta.id_etichetta}
value={String(etichetta.id_etichetta)}
>
{etichetta.title}
</SelectItem>
))}
</SelectContent>
</Select>
<Button
onClick={() => {
if (selected) {
add({ chatId, etichettaId: selected });
}
}}
>
Aggiungi
</Button>
</div>
</div>
</DialogContent>
</Dialog>
);
};
export const Etichetta = ({
title,
color_hex,
className,
}: {
title: string;
color_hex: string;
className?: string;
}) => {
return (
<span
className={cn(
"flex w-fit select-none items-center justify-center whitespace-nowrap rounded-md px-1.5 text-sm",
className,
)}
style={{
backgroundColor: color_hex,
color: colorIsDarkSimple(color_hex) ? "#FFFFFF" : "#000000",
}}
>
{title}
</span>
);
};