mirror of
https://dev.azure.com/globalhealthx/EMR/_git/helix-engage
synced 2026-05-18 20:08:19 +00:00
feat: PageHeader component + refactor all 6 list pages
New reusable PageHeader component (src/components/layout/page-header.tsx) with consistent layout: title + badge + subtitle on left, controls on right, optional tabs below with no extra borders. Refactored pages: - All Leads: inline header → PageHeader - Contacts: inline header → PageHeader - Appointments v2: inline header → PageHeader with tabs - Call History: removed p-7 wrapper + TableCard.Root → flat table - Patients: removed p-7 wrapper + TableCard.Root → flat table - Missed Calls: removed TopBar → PageHeader with tabs All pages now share identical header spacing, font sizing, and control alignment. No more double borders from tab + container. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -11,11 +11,12 @@ import {
|
||||
} from '@fortawesome/pro-duotone-svg-icons';
|
||||
|
||||
const SearchLg: FC<{ className?: string }> = ({ className }) => <FontAwesomeIcon icon={faMagnifyingGlass} className={className} />;
|
||||
import { Table, TableCard } from '@/components/application/table/table';
|
||||
import { Table } from '@/components/application/table/table';
|
||||
import { Badge } from '@/components/base/badges/badges';
|
||||
import { Button } from '@/components/base/buttons/button';
|
||||
import { Input } from '@/components/base/input/input';
|
||||
import { Select } from '@/components/base/select/select';
|
||||
import { PageHeader } from '@/components/layout/page-header';
|
||||
import { PhoneActionCell } from '@/components/call-desk/phone-action-cell';
|
||||
import { formatShortDate, formatPhone } from '@/lib/format';
|
||||
// cx removed — no longer used after SLA column removal
|
||||
@@ -189,44 +190,43 @@ export const CallHistoryPage = () => {
|
||||
|
||||
return (
|
||||
<div className="flex flex-1 flex-col overflow-hidden">
|
||||
<div className="flex flex-1 flex-col overflow-hidden p-7">
|
||||
<TableCard.Root size="md" className="flex-1 min-h-0">
|
||||
<TableCard.Header
|
||||
title={isAdmin ? 'Call History' : 'My Call History'}
|
||||
badge={String(filteredCalls.length)}
|
||||
description={isAdmin ? `${completedCount} completed \u00B7 ${missedCount} missed` : `${completedCount} completed`}
|
||||
contentTrailing={
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="w-44">
|
||||
<Select
|
||||
size="sm"
|
||||
placeholder="All Calls"
|
||||
selectedKey={filter}
|
||||
onSelectionChange={(key) => setFilter(key as FilterKey)}
|
||||
items={isAdmin ? allFilterItems : agentFilterItems}
|
||||
aria-label="Filter calls"
|
||||
>
|
||||
{(item) => (
|
||||
<Select.Item id={item.id} label={item.label}>
|
||||
{item.label}
|
||||
</Select.Item>
|
||||
)}
|
||||
</Select>
|
||||
</div>
|
||||
<div className="w-56">
|
||||
<Input
|
||||
placeholder="Search calls..."
|
||||
icon={SearchLg}
|
||||
size="sm"
|
||||
value={search}
|
||||
onChange={(value) => setSearch(value)}
|
||||
aria-label="Search calls"
|
||||
/>
|
||||
</div>
|
||||
<PageHeader
|
||||
title={isAdmin ? 'Call History' : 'My Call History'}
|
||||
badge={filteredCalls.length}
|
||||
subtitle={isAdmin ? `${completedCount} completed \u00B7 ${missedCount} missed` : `${completedCount} completed`}
|
||||
controls={
|
||||
<>
|
||||
<div className="w-44">
|
||||
<Select
|
||||
size="sm"
|
||||
placeholder="All Calls"
|
||||
selectedKey={filter}
|
||||
onSelectionChange={(key) => setFilter(key as FilterKey)}
|
||||
items={isAdmin ? allFilterItems : agentFilterItems}
|
||||
aria-label="Filter calls"
|
||||
>
|
||||
{(item) => (
|
||||
<Select.Item id={item.id} label={item.label}>
|
||||
{item.label}
|
||||
</Select.Item>
|
||||
)}
|
||||
</Select>
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
<div className="w-56">
|
||||
<Input
|
||||
placeholder="Search calls..."
|
||||
icon={SearchLg}
|
||||
size="sm"
|
||||
value={search}
|
||||
onChange={(value) => setSearch(value)}
|
||||
aria-label="Search calls"
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
|
||||
<div className="flex flex-1 flex-col min-h-0 overflow-hidden px-4 pt-3">
|
||||
{filteredCalls.length === 0 ? (
|
||||
<div className="flex flex-col items-center justify-center py-16">
|
||||
<h3 className="text-sm font-semibold text-primary">No calls found</h3>
|
||||
@@ -314,15 +314,16 @@ export const CallHistoryPage = () => {
|
||||
</Table.Body>
|
||||
</Table>
|
||||
)}
|
||||
<div className="shrink-0">
|
||||
<PaginationCardDefault
|
||||
page={page}
|
||||
total={totalPages}
|
||||
onPageChange={setPage}
|
||||
/>
|
||||
</div>
|
||||
</TableCard.Root>
|
||||
</div>
|
||||
{totalPages > 1 && (
|
||||
<div className="shrink-0 border-t border-secondary px-6 py-3">
|
||||
<PaginationCardDefault
|
||||
page={page}
|
||||
total={totalPages}
|
||||
onPageChange={setPage}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user