'use client'; import Link from 'next/link'; import { useState } from 'react'; import { type Preloaded, usePreloadedQuery, useMutation } from 'convex/react'; import { api } from '~/convex/_generated/api'; import { type Id } from '~/convex/_generated/dataModel'; import { useTVMode } from '@/components/providers'; import { BasedAvatar, Button, Card, CardContent, Drawer, DrawerTrigger, Input, SubmitButton, } from '@/components/ui'; import { toast } from 'sonner'; import { ccn, formatTime, formatDate } from '@/lib/utils'; import { Clock, Calendar, CheckCircle2 } from 'lucide-react'; import { StatusHistory } from '@/components/layout/status'; type StatusListProps = { preloadedUser: Preloaded; preloadedStatuses: Preloaded; }; export const StatusList = ({ preloadedUser, preloadedStatuses, }: StatusListProps) => { const user = usePreloadedQuery(preloadedUser); const statuses = usePreloadedQuery(preloadedStatuses); const { tvMode } = useTVMode(); const [selectedUserIds, setSelectedUserIds] = useState[]>([]); const [selectAll, setSelectAll] = useState(false); const [statusInput, setStatusInput] = useState(''); const [updatingStatus, setUpdatingStatus] = useState(false); const bulkCreate = useMutation(api.statuses.bulkCreate); const handleSelectUser = (id: Id<'users'>, e: React.MouseEvent) => { setSelectedUserIds((prev) => prev.some((i) => i === id) ? prev.filter((prevId) => prevId !== id) : [...prev, id], ); }; const handleSelectAll = () => { if (selectAll) setSelectedUserIds([]); else setSelectedUserIds(statuses.map((s) => s.user.id)); setSelectAll(!selectAll); }; const handleUpdateStatus = async () => { const message = statusInput.trim(); setUpdatingStatus(true); try { if (message.length < 3 || message.length > 80) throw new Error('Status must be between 3 & 80 characters'); if (selectedUserIds.length === 0 && user?.id) await bulkCreate({ message, userIds: [user.id] }); await bulkCreate({ message, userIds: selectedUserIds }); toast.success('Status updated.'); setSelectedUserIds([]); setSelectAll(false); setStatusInput(''); } catch (error) { toast.error(`Update failed. ${error as Error}`); } finally { setUpdatingStatus(false); } }; const containerCn = ccn({ context: tvMode, className: 'flex flex-col mx-auto items-center\ sm:w-5/6 md:w-3/4 lg:w-2/3 xl:w-1/2 min-w-[450px]', on: 'mt-8', off: 'px-10', }); const headerCn = ccn({ context: tvMode, className: 'w-full', on: 'hidden', off: 'flex mb-3 justify-between items-center', }); const selectAllIconCn = ccn({ context: selectAll, className: 'w-4 h-4', on: 'text-green-500', off: '', }); const cardContainerCn = ccn({ context: tvMode, className: 'w-full space-y-2', on: 'text-primary', off: '', }); return (
{!tvMode && (
Miss the old table? Find it here!
)}
{statuses.map((status) => { const { user: u, status: s } = status; const isSelected = selectedUserIds.includes(u.id); const isUpdatedByOther = !!s?.updatedBy; return ( handleSelectUser(u.id, e)} >

{u.name ?? 'Technician'}

{s?.message ?? 'No status yet.'}

{s ? formatTime(s.updatedAt) : '--:--'}
{s ? formatDate(s.updatedAt) : '--/--'}
{isUpdatedByOther && s.updatedBy && (

Updated by

{s.updatedBy.name ?? 'User'}
)}
); })}
{statuses.length === 0 && (

No status updates have been made in the past day.

)} {!tvMode && (

Update Status

setStatusInput(e.target.value)} onKeyDown={(e) => { if (e.key === 'Enter' && !e.shiftKey && !updatingStatus) { e.preventDefault(); void handleUpdateStatus(); } }} /> {selectedUserIds.length > 0 ? `Update ${selectedUserIds.length} ${selectedUserIds.length > 1 ? 'users' : 'user' }` : 'Update Status'}
)}
); };