From 02d1fcb73da4ab74a736c3e333ade595e4c9f7f9 Mon Sep 17 00:00:00 2001 From: lorentz Date: Fri, 10 Apr 2026 13:56:46 +0000 Subject: [PATCH] Design principles: Claims First (collapsed others) + Renewal Date (+1 day) everywhere --- ondeck/src/components/clients/client-card.tsx | 4 +- .../src/components/clients/client-table.tsx | 4 +- .../src/components/policies/policy-detail.tsx | 10 +-- .../components/renewal-groups/policy-chip.tsx | 2 +- .../src/components/ui/user-select-content.tsx | 83 ++++++++++++------- 5 files changed, 65 insertions(+), 38 deletions(-) diff --git a/ondeck/src/components/clients/client-card.tsx b/ondeck/src/components/clients/client-card.tsx index a6bade2..f08fa19 100644 --- a/ondeck/src/components/clients/client-card.tsx +++ b/ondeck/src/components/clients/client-card.tsx @@ -5,7 +5,7 @@ import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card' import { Badge } from '@/components/ui/badge' import { Building2, Calendar, FileText, CheckSquare, GitBranch, CornerLeftUp } from 'lucide-react' import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip' -import { formatDate, daysUntil } from '@/lib/utils' +import { formatRenewalDate, daysUntil } from '@/lib/utils' interface ClientCardProps { client: { @@ -117,7 +117,7 @@ export function ClientCard({ client }: ClientCardProps) { Renewal date: - {formatDate(nextPolicy.expirationDate)} + {formatRenewalDate(nextPolicy.expirationDate)} {daysToExpiration !== null && daysToExpiration <= 90 && ( {nextPolicy ? (
- {formatDate(nextPolicy.expirationDate)} + {formatRenewalDate(nextPolicy.expirationDate)} {daysToExpiration !== null && daysToExpiration <= 90 && ( - {isExpired ? 'Expired' : `Expires in ${daysUntilExpiration} days`} + {isExpired ? 'Expired' : `Renews in ${daysUntilExpiration} days`}

- {formatDate(policy.expirationDate)} + {formatRenewalDate(policy.expirationDate)}

@@ -117,10 +117,10 @@ export function PolicyDetail({ policy }: PolicyDetailProps) {

-

Expiration Date

+

Renewal Date

- {formatDate(policy.expirationDate)} + {formatRenewalDate(policy.expirationDate)}

diff --git a/ondeck/src/components/renewal-groups/policy-chip.tsx b/ondeck/src/components/renewal-groups/policy-chip.tsx index 9160612..7a65fee 100644 --- a/ondeck/src/components/renewal-groups/policy-chip.tsx +++ b/ondeck/src/components/renewal-groups/policy-chip.tsx @@ -61,7 +61,7 @@ export function PolicyChip({ policy, disabled }: PolicyChipProps) {
{policy.carrierName || 'Unknown carrier'} - {expDisplay && · Exp {expDisplay}} + {expDisplay && · Renews {expDisplay}}
{!policy.expirationDate && ( diff --git a/ondeck/src/components/ui/user-select-content.tsx b/ondeck/src/components/ui/user-select-content.tsx index fa0328d..84b18af 100644 --- a/ondeck/src/components/ui/user-select-content.tsx +++ b/ondeck/src/components/ui/user-select-content.tsx @@ -1,7 +1,8 @@ 'use client' -import { useMemo } from 'react' +import { useState, useMemo } from 'react' import { SelectContent, SelectGroup, SelectItem, SelectLabel } from '@/components/ui/select' +import { ChevronDown } from 'lucide-react' export interface SelectableUser { id: string @@ -24,53 +25,79 @@ function formatDepartment(dept: string): string { .join(' ') } -/** Departments shown first in this order; everything else follows alphabetically */ -const PRIORITY_DEPARTMENTS = ['claims'] - export function UserSelectContent({ users, excludeIds = [], prefixItem }: UserSelectContentProps) { - const grouped = useMemo(() => { - const eligible = users.filter((u) => !excludeIds.includes(u.id)) + const [showAll, setShowAll] = useState(false) + const { claimsUsers, otherGroups } = useMemo(() => { + const eligible = users.filter((u) => !excludeIds.includes(u.id)) + const sorter = (a: SelectableUser, b: SelectableUser) => + (a.displayName || a.email).localeCompare(b.displayName || b.email) + + const claims = eligible + .filter((u) => u.department?.toLowerCase() === 'claims') + .sort(sorter) + + // Group remaining users by department, sorted alphabetically const map = new Map() for (const u of eligible) { + if (u.department?.toLowerCase() === 'claims') continue const key = (u.department || 'other').toLowerCase() if (!map.has(key)) map.set(key, []) map.get(key)!.push(u) } + for (const list of map.values()) list.sort(sorter) - // Sort users within each group - for (const list of map.values()) { - list.sort((a, b) => - (a.displayName || a.email).localeCompare(b.displayName || b.email) - ) - } + const sortedKeys = [...map.keys()].sort((a, b) => a.localeCompare(b)) + const groups = sortedKeys.map((key) => ({ + key, + label: formatDepartment(key), + users: map.get(key)!, + })) - // Sort department keys: priority first, then alphabetical - const keys = [...map.keys()].sort((a, b) => { - const ai = PRIORITY_DEPARTMENTS.indexOf(a) - const bi = PRIORITY_DEPARTMENTS.indexOf(b) - if (ai !== -1 && bi !== -1) return ai - bi - if (ai !== -1) return -1 - if (bi !== -1) return 1 - return a.localeCompare(b) - }) - - return keys.map((key) => ({ key, label: formatDepartment(key), users: map.get(key)! })) + return { claimsUsers: claims, otherGroups: groups } }, [users, excludeIds]) return ( {prefixItem} - {grouped.map((group) => ( - - {group.label} - {group.users.map((u) => ( + {claimsUsers.length > 0 && ( + + Claims + {claimsUsers.map((u) => ( {u.displayName || u.email} ))} - ))} + )} + {otherGroups.length > 0 && ( + + { + e.preventDefault() + e.stopPropagation() + setShowAll((v) => !v) + }} + > + All Staff + + + {showAll && + otherGroups.map((group) => ( + + {group.label} + {group.users.map((u) => ( + + {u.displayName || u.email} + + ))} + + ))} + + )} ) }