"use client"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from "@/components/ui/card"; import { toast } from "@/components/ui/sonner"; import { useTranslation } from "@/lib/i18n/client"; import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import { Check, Loader2, Mail, X } from "lucide-react"; import { useTRPC } from "@karakeep/shared-react/trpc"; interface Invitation { id: string; role: string; list: { name: string; icon?: string; description?: string | null; owner?: { name?: string; } | null; }; } function InvitationRow({ invitation }: { invitation: Invitation }) { const api = useTRPC(); const { t } = useTranslation(); const queryClient = useQueryClient(); const acceptInvitation = useMutation( api.lists.acceptInvitation.mutationOptions({ onSuccess: async () => { toast({ description: t("lists.invitations.accepted"), }); await Promise.all([ queryClient.invalidateQueries( api.lists.getPendingInvitations.pathFilter(), ), queryClient.invalidateQueries(api.lists.list.pathFilter()), ]); }, onError: (error) => { toast({ variant: "destructive", description: error.message || t("lists.invitations.failed_to_accept"), }); }, }), ); const declineInvitation = useMutation( api.lists.declineInvitation.mutationOptions({ onSuccess: async () => { toast({ description: t("lists.invitations.declined"), }); await queryClient.invalidateQueries( api.lists.getPendingInvitations.pathFilter(), ); }, onError: (error) => { toast({ variant: "destructive", description: error.message || t("lists.invitations.failed_to_decline"), }); }, }), ); return (
{invitation.list.name} {invitation.list.icon}
{invitation.list.description && (
{invitation.list.description}
)}
{t("lists.invitations.invited_by")}{" "} {invitation.list.owner?.name || "Unknown"} {" • "} {invitation.role}
); } export function PendingInvitationsCard() { const api = useTRPC(); const { t } = useTranslation(); const { data: invitations, isLoading } = useQuery( api.lists.getPendingInvitations.queryOptions(), ); if (isLoading) { return null; } if (!invitations || invitations.length === 0) { return null; } return ( {t("lists.invitations.pending")} {invitations.length} {t("lists.invitations.description")} {invitations.map((invitation) => ( ))} ); }