'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, Drawer, DrawerTrigger, Input, SubmitButton, } from '@/components/ui'; import { toast } from 'sonner'; import { ccn, formatTime, formatDate } from '@/lib/utils'; import { Clock, Calendar } from 'lucide-react'; import { StatusHistory } from '@/components/layout/status'; type StatusTableProps = { preloadedUser: Preloaded; preloadedStatuses: Preloaded; }; export const StatusTable = ({ preloadedUser, preloadedStatuses, }: StatusTableProps) => { 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'>) => { 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: 'mx-auto', on: 'lg:w-11/12 w-full', off: 'w-5/6', }); const headerCn = ccn({ context: tvMode, className: 'w-full mb-2 flex justify-between', on: '', off: 'mb-2', }); const thCn = ccn({ context: tvMode, className: 'py-4 px-4 border font-semibold ', on: 'lg:text-6xl xl:min-w-[420px]', off: 'lg:text-5xl xl:min-w-[320px]', }); const tdCn = ccn({ context: tvMode, className: 'py-2 px-2 border', on: 'lg:text-5xl', off: 'lg:text-4xl', }); const tCheckboxCn = `py-3 px-4 border`; const checkBoxCn = `lg:scale-200 cursor-pointer`; return (
{!tvMode && (

Tired of the old table?

Try the new status list!
)}
{!tvMode && ( )} {statuses.map((status, i) => { const { user: u, status: s } = status; const isSelected = selectedUserIds.includes(u.id); return ( {!tvMode && ( )} ); })}
Technician Status Updated At
handleSelectUser(u.id)} />

{u.name ?? 'Technician #' + (i + 1)}

{s?.updatedBy && s.updatedBy.id !== u.id && (
Updated by {s.updatedBy.name}
)}
{s?.message}

{s ? formatTime(s.updatedAt) : '--:--'}

{s ? formatDate(s.updatedAt) : '--:--'}

{statuses.length === 0 && (

No status updates yet

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