'use client'; import { signIn } from '@/app/actions/user'; import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger, } from "@/components/ui/alert-dialog"; import { toast } from '@/hooks/use-toast'; import { usersAtom } from '@/lib/atoms'; import { useHelpers } from '@/lib/client-helpers'; import { SafeUser, User } from '@/lib/types'; import { cn } from '@/lib/utils'; import { Description } from '@radix-ui/react-dialog'; import { useAtom } from 'jotai'; import { Crown, Plus, Trash2, User as UserIcon, UserRoundPen } from 'lucide-react'; import { useTranslations } from 'next-intl'; import { useState } from 'react'; import PasswordEntryForm from './PasswordEntryForm'; import UserForm from './UserForm'; import { Avatar, AvatarFallback, AvatarImage } from './ui/avatar'; import { Dialog, DialogContent, DialogHeader, DialogTitle } from './ui/dialog'; function UserCard({ user, onSelect, onEdit, showEdit, isCurrentUser, currentLoggedInUserId, // For "don't delete self" check onUserDeleted // Callback to update usersAtom }: { user: User, onSelect: () => void, onEdit: () => void, showEdit: boolean, isCurrentUser: boolean, currentLoggedInUserId?: string, onUserDeleted: (userId: string) => void, }) { const t = useTranslations('UserSelectModal'); const tWarning = useTranslations('Warning'); const [showDeleteConfirm, setShowDeleteConfirm] = useState(false); const [isDeleting, setIsDeleting] = useState(false); const handleDeleteUser = async () => { setIsDeleting(true); try { const response = await fetch('/api/user/delete', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ userId: user.id }), }); if (response.ok) { toast({ title: t('deleteUserSuccessTitle'), description: t('deleteUserSuccessDescription', { username: user.username }), }); onUserDeleted(user.id); } else { const errorData = await response.json(); toast({ title: t('deleteUserErrorTitle'), description: errorData.error || t('genericError'), variant: 'destructive', }); } } catch (error) { toast({ title: t('deleteUserErrorTitle'), description: t('networkError'), variant: 'destructive', }); } finally { setIsDeleting(false); setShowDeleteConfirm(false); } }; return (
{showEdit && (
{showEdit && ( )} {showEdit && user.id !== currentLoggedInUserId && ( {tWarning('areYouSure')} {t('deleteUserConfirmation', { username: user.username })} { e.stopPropagation(); setShowDeleteConfirm(false);}} disabled={isDeleting}>{tWarning('cancel')} { e.stopPropagation(); handleDeleteUser();}} disabled={isDeleting} className="bg-destructive text-destructive-foreground hover:bg-destructive/90" > {isDeleting ? t('deletingButtonText') : t('confirmDeleteButtonText')} )}
)}
); } function AddUserButton({ onClick }: { onClick: () => void }) { const t = useTranslations('UserSelectModal'); return ( ); } function UserSelectionView({ users, currentUserFromHook, // Renamed to avoid confusion with map variable onUserSelect, onEditUser, onCreateUser, onUserDeleted, // Pass through the delete handler }: { users: User[], currentUserFromHook?: SafeUser, onUserSelect: (userId: string) => void, onEditUser: (userId: string) => void, onCreateUser: () => void, onUserDeleted: (userId: string) => void, }) { return (
{users .filter(user => user.id !== currentUserFromHook?.id) // Show other users .map((user) => ( onUserSelect(user.id)} onEdit={() => onEditUser(user.id)} showEdit={!!currentUserFromHook?.isAdmin} isCurrentUser={false} // This card isn't the currently logged-in user for switching TO currentLoggedInUserId={currentUserFromHook?.id} // For the "don't delete self" check onUserDeleted={onUserDeleted} /> ))} {currentUserFromHook?.isAdmin && }
); } export default function UserSelectModal({ onClose }: { onClose: () => void }) { const t = useTranslations('UserSelectModal'); const [selectedUser, setSelectedUser] = useState(); const [isCreating, setIsCreating] = useState(false); const [isEditing, setIsEditing] = useState(false); const [error, setError] = useState(''); const [usersData, setUsersData] = useAtom(usersAtom); const users = usersData.users; const { currentUser } = useHelpers(); const handleUserDeleted = (userIdToDelete: string) => { setUsersData(prevData => ({ ...prevData, users: prevData.users.filter(u => u.id !== userIdToDelete) })); }; const handleUserSelect = (userId: string) => { setSelectedUser(userId); setError(''); }; const handleEditUser = (userId: string) => { setSelectedUser(userId); setIsEditing(true); }; const handleCreateUser = () => { setIsCreating(true); }; const handleFormSuccess = () => { setSelectedUser(undefined); setIsCreating(false); setIsEditing(false); onClose(); }; const handleFormCancel = () => { setSelectedUser(undefined); setIsCreating(false); setIsEditing(false); setError(''); }; return ( {isCreating ? t('createNewUserTitle') : t('selectUserTitle')}
{!selectedUser && !isCreating && !isEditing ? ( ) : isCreating || isEditing ? ( ) : ( u.id === selectedUser)!} onCancel={() => setSelectedUser(undefined)} onSubmit={async (password) => { try { setError(''); const user = users.find(u => u.id === selectedUser); if (!user) throw new Error("User not found"); await signIn(user.username, password); setError(''); onClose(); toast({ title: t('signInSuccessTitle'), description: t('signInSuccessDescription', { username: user.username }), variant: "default" }); setTimeout(() => window.location.reload(), 300); } catch (err) { setError(t('errorInvalidPassword')); throw err; } }} error={error} /> )}
); }