From dfcaa175ab3816adbe078023f36e16ef34359ce6 Mon Sep 17 00:00:00 2001 From: saridsa2 Date: Thu, 16 Apr 2026 21:31:30 +0530 Subject: [PATCH] feat: PageHeader component + refactor all 6 list pages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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) --- src/components/layout/page-header.tsx | 55 ++++++++++++++++ src/pages/all-leads.tsx | 62 +++++++++--------- src/pages/appointments-v2.tsx | 48 +++++++------- src/pages/call-history.tsx | 91 ++++++++++++++------------- src/pages/contacts.tsx | 22 +++---- src/pages/missed-calls.tsx | 86 ++++++++++++------------- src/pages/patients.tsx | 73 +++++++++++---------- 7 files changed, 246 insertions(+), 191 deletions(-) create mode 100644 src/components/layout/page-header.tsx diff --git a/src/components/layout/page-header.tsx b/src/components/layout/page-header.tsx new file mode 100644 index 0000000..8a312a1 --- /dev/null +++ b/src/components/layout/page-header.tsx @@ -0,0 +1,55 @@ +// PageHeader — consistent header layout for all list pages. +// +// Row 1: Title (+ optional badge + subtitle) on the left, +// controls (search, columns, export, etc.) on the right. +// Row 2: Optional tabs (underline style) — no extra borders. +// +// Usage: +// - - + color="secondary" + iconLeading={Download01} + onClick={handleExportCsv} + > + Export CSV + + + } + />
diff --git a/src/pages/appointments-v2.tsx b/src/pages/appointments-v2.tsx index ee5f984..9571ae6 100644 --- a/src/pages/appointments-v2.tsx +++ b/src/pages/appointments-v2.tsx @@ -20,6 +20,7 @@ import { Select } from '@/components/base/select/select'; import { DatePicker } from '@/components/application/date-picker/date-picker'; import { parseDate, today, getLocalTimeZone } from '@internationalized/date'; import { PhoneActionCell } from '@/components/call-desk/phone-action-cell'; +import { PageHeader } from '@/components/layout/page-header'; import { formatPhone, formatDateOnly, formatTimeOnly } from '@/lib/format'; import { apiClient } from '@/lib/api-client'; import { notify } from '@/lib/toast'; @@ -551,33 +552,32 @@ export const AppointmentsPageV2 = () => { return ( <> - {/* Header with search inline */} -
-
-

Appointments

-
-
- -
-
+ + +
+ } + tabs={ + setTab(key as StatusTab)}> + + {(item) => } + + + } + />
- {/* Tabs */} -
- setTab(key as StatusTab)}> - - {(item) => } - - -
{loading ? ( diff --git a/src/pages/call-history.tsx b/src/pages/call-history.tsx index e5bccd1..d2939f6 100644 --- a/src/pages/call-history.tsx +++ b/src/pages/call-history.tsx @@ -11,11 +11,12 @@ import { } from '@fortawesome/pro-duotone-svg-icons'; const SearchLg: FC<{ className?: string }> = ({ 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 (
-
- - -
- -
-
- setSearch(value)} - aria-label="Search calls" - /> -
+ +
+
- } - /> +
+ setSearch(value)} + aria-label="Search calls" + /> +
+ + } + /> +
{filteredCalls.length === 0 ? (

No calls found

@@ -314,15 +314,16 @@ export const CallHistoryPage = () => { )} -
- -
-
+ {totalPages > 1 && ( +
+ +
+ )}
); }; diff --git a/src/pages/contacts.tsx b/src/pages/contacts.tsx index 8a9fe33..ccc77bf 100644 --- a/src/pages/contacts.tsx +++ b/src/pages/contacts.tsx @@ -17,7 +17,7 @@ const SearchLg: FC<{ className?: string }> = ({ className }) => { return (
- - -
-
-

- People who reached out directly — phone, walk-in, referral. Not sourced from campaigns. -

-
+
{ -
-
+ + } + /> +
{ ]; return ( - <> - -
- {/* Tabs + toolbar */} -
+
+ + +
+ +
+ + } + tabs={ handleTab(key as StatusTab)}> {(item) => } -
- -
- -
-
-
+ } + /> - {/* Table */} -
- {loading ? ( -
-

Loading missed calls...

-
- ) : filtered.length === 0 ? ( -
-

{search ? 'No matching calls' : 'No missed calls'}

-
- ) : ( - visibleColumns.has(c.id))} - sortDescriptor={sortDescriptor} - onSortChange={setSortDescriptor} - /> - )} -
- - {/* Pagination */} - {totalPages > 1 && ( -
- + {/* Table */} +
+ {loading ? ( +
+

Loading missed calls...

+ ) : filtered.length === 0 ? ( +
+

{search ? 'No matching calls' : 'No missed calls'}

+
+ ) : ( + visibleColumns.has(c.id))} + sortDescriptor={sortDescriptor} + onSortChange={setSortDescriptor} + /> )}
- + + {/* Pagination */} + {totalPages > 1 && ( +
+ +
+ )} +
); }; diff --git a/src/pages/patients.tsx b/src/pages/patients.tsx index 07948ff..0fa18d2 100644 --- a/src/pages/patients.tsx +++ b/src/pages/patients.tsx @@ -7,7 +7,8 @@ import { faIcon } from '@/lib/icon-wrapper'; const SearchLg = faIcon(faMagnifyingGlass); import { Avatar } from '@/components/base/avatar/avatar'; import { Input } from '@/components/base/input/input'; -import { Table, TableCard } from '@/components/application/table/table'; +import { Table } from '@/components/application/table/table'; +import { PageHeader } from '@/components/layout/page-header'; import { PaginationPageDefault } from '@/components/application/pagination/pagination'; import { PhoneActionCell } from '@/components/call-desk/phone-action-cell'; @@ -127,37 +128,36 @@ export const PatientsPage = () => { return (
+ + + +
+ +
+ + } + /> +
-
- - - - -
- -
-
- } - /> - +
{loading ? (

Loading patients...

@@ -267,13 +267,12 @@ export const PatientsPage = () => { )} - - {totalPages > 1 && ( -
- -
- )} + {totalPages > 1 && ( +
+ +
+ )}
{/* Patient Profile Panel - collapsible with smooth transition */}