make tv mode list work better

This commit is contained in:
2025-09-25 11:17:34 -05:00
parent db7bf75815
commit 467d452bb4
8 changed files with 157 additions and 315 deletions

View File

@@ -26,7 +26,7 @@
"@radix-ui/react-slot": "^1.2.3",
"@radix-ui/react-switch": "^1.2.6",
"@radix-ui/react-tabs": "^1.1.13",
"@sentry/nextjs": "^10.14.0",
"@sentry/nextjs": "^10.15.0",
"@t3-oss/env-nextjs": "^0.13.8",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",

View File

@@ -122,8 +122,7 @@ export const AvatarUpload = ({ preloadedUser }: AvatarUploadProps) => {
<BasedAvatar
src={currentImageUrl ?? undefined}
fullName={user?.name}
className='h-42 w-42'
fallbackProps={{ className: 'text-4xl font-semibold' }}
className='h-42 w-42 text-6xl font-semibold'
userIconProps={{ size: 100 }}
/>
<div

View File

@@ -124,9 +124,9 @@ export const StatusList = ({
const containerCn = ccn({
context: tvMode,
className: 'max-w-4xl mx-auto',
on: 'px-6',
off: 'px-4 sm:px-6',
className: 'mx-auto',
on: 'px-6 max-w-7xl',
off: 'max-w-4xl px-4 sm:px-6',
});
const tabsCn = ccn({
@@ -185,22 +185,26 @@ export const StatusList = ({
{/* Desktop header */}
<div className={headerCn}>
<div className='flex items-center gap-4 text-xs sm:text-base'>
<div className='flex items-center gap-2 text-muted-foreground'>
<Users className='sm:w-4 sm:h-4 w-3 h-3' />
<span>{statuses.length} members</span>
<div className='flex w-full justify-between px-4'>
<div className='flex items-center gap-4 text-xs sm:text-base'>
<div className='flex items-center gap-2 text-muted-foreground'>
<Users className='sm:w-4 sm:h-4 w-3 h-3' />
<span>{statuses.length} members</span>
</div>
</div>
<div className='flex items-center gap-2 text-xs'>
<Link href='/table' className='font-medium hover:underline'>
Miss the old table?
</Link>
<div className='flex items-center gap-4 text-xs sm:text-base'>
<div className='flex items-center gap-2 text-xs'>
<Link href='/table' className='font-medium hover:underline'>
Miss the old table?
</Link>
</div>
</div>
</div>
</div>
{/* Card list */}
<div className='space-y-2 sm:space-y-3 pb-24 sm:pb-0'>
{statuses.map((statusData) => {
{previousStatuses.map((statusData) => {
const { user: u, status: s } = statusData;
const isSelected = selectedUserIds.includes(u.id);
const isAnimating = animatingIds.has(u.id);
@@ -238,37 +242,35 @@ export const StatusList = ({
fullName={u.name ?? 'User'}
className={`
transition-all duration-300
${tvMode ? 'w-18 h-18' : 'w-10 h-10 sm:w-12 sm:h-12'}
${tvMode ? 'w-36 h-36 text-4xl' : 'w-10 h-10 sm:w-12 sm:h-12'}
${isAnimating ? 'ring-primary/30 ring-4' : ''}
`}
/>
</div>
{/* Content */}
<div className='flex-1 min-w-0'>
<div className='flex items-center gap-2 sm:gap-3 mb-1'>
<h3
className={`
font-semibold truncate
${tvMode ? 'text-3xl' : 'text-base sm:text-xl'}
${tvMode ? 'text-5xl' : 'text-base sm:text-xl'}
`}
title={u.name ?? u.email ?? 'User'}
>
{u.name ?? u.email ?? 'User'}
</h3>
{isUpdatedByOther && s?.updatedBy && (
<div
className='hidden sm:flex items-center gap-2
text-muted-foreground min-w-0'
>
<span className='text-sm'>via</span>
<span className={`${tvMode ? 'text-3xl': 'text-sm'}`}>via</span>
<BasedAvatar
src={s.updatedBy.imageUrl}
fullName={s.updatedBy.name ?? 'User'}
className='w-4 h-4'
className={`${tvMode ? 'w-14 h-14 text-xl' : 'w-6 h-6'}`}
/>
<span className='text-sm truncate'>
<span className={`${tvMode ? 'text-4xl': 'truncate'}`}>
{s.updatedBy.name ??
s.updatedBy.email ??
'another user'}
@@ -276,51 +278,71 @@ export const StatusList = ({
</div>
)}
</div>
<div
className={`
mb-2 sm:mb-3 leading-relaxed break-words
${tvMode ? 'text-2xl' : 'text-[0.95rem] sm:text-lg'}
${
s
? 'text-foreground'
: 'text-muted-foreground italic'
}
line-clamp-2
mb-2 sm:mb-3
${tvMode ? 'text-6xl' : 'text-[0.95rem] sm:text-lg'}
${s ? 'text-foreground' : 'text-muted-foreground italic'}
`}
title={s?.message ?? undefined}
>
{s?.message ?? 'No status yet.'}
</div>
{/* Meta */}
<div
className='flex items-center gap-3 sm:gap-4
text-muted-foreground'
>
{/* Meta - only show here when NOT in TV mode */}
{!tvMode && (
<div
className={`
flex items-center text-muted-foreground gap-3 sm:gap-4
`}
>
<div className='flex items-center gap-1.5'>
<Clock className='w-4 h-4 sm:w-4 sm:h-4' />
<span className='text-sm sm:text-lg'>
{s ? formatTime(s.updatedAt) : '--:--'}
</span>
</div>
<div className='flex items-center gap-1.5'>
<Calendar className='w-4 h-4 sm:w-4 sm:h-4' />
<span className='text-sm sm:text-lg'>
{s ? formatDate(s.updatedAt) : '--/--'}
</span>
</div>
{s && (
<div className='flex items-center gap-1.5'>
<Activity className='w-4 h-4 sm:w-4 sm:h-4' />
<span className='text-sm sm:text-lg'>
{getStatusAge(s.updatedAt)}
</span>
</div>
)}
</div>
)}
</div>
{/* Date/Time Column - only show when in TV mode */}
{tvMode && (
<div className='flex flex-col items-end gap-2 text-muted-foreground min-w-0'>
<div className='flex items-center gap-1.5'>
<Clock className='w-4 h-4 sm:w-4 sm:h-4' />
<span className='text-xs sm:text-sm'>
<Clock className='w-8 h-8' />
<span className='text-4xl'>
{s ? formatTime(s.updatedAt) : '--:--'}
</span>
</div>
<div className='hidden xs:flex items-center gap-1.5'>
<Calendar className='w-4 h-4' />
<span className='text-xs sm:text-sm'>
<div className='flex items-center gap-1.5'>
<Calendar className='w-8 h-8' />
<span className='text-4xl'>
{s ? formatDate(s.updatedAt) : '--/--'}
</span>
</div>
{s && (
<div className='flex items-center gap-1.5'>
<Activity className='w-4 h-4' />
<span className='text-xs sm:text-sm'>
<Activity className='w-8 h-8' />
<span className='text-4xl'>
{getStatusAge(s.updatedAt)}
</span>
</div>
)}
</div>
</div>
)}
{/* Actions */}
{!tvMode && (
<div className='flex flex-col items-end gap-2'>
@@ -341,7 +363,6 @@ export const StatusList = ({
</div>
)}
</div>
{/* Mobile "via user" line */}
{isUpdatedByOther && s?.updatedBy && (
<div

View File

@@ -173,7 +173,7 @@ export const StatusTable = ({
<BasedAvatar
src={u.imageUrl}
fullName={u.name}
className={tvMode ? 'w-16 h-16' : 'w-12 h-12'}
className={tvMode ? 'w-16 h-16 text-2xl' : 'w-12 h-12'}
/>
<div>
<p> {u.name ?? 'Technician #' + (i + 1)} </p>
@@ -182,7 +182,7 @@ export const StatusTable = ({
<BasedAvatar
src={s.updatedBy.imageUrl}
fullName={s.updatedBy.name}
className='w-5 h-5'
className='w-5 h-5 text-xs'
/>
<span className={tvMode ? 'text-xl' : 'text-base'}>
Updated by {s.updatedBy.name}