Project: workspace-doctolib · Branch: HEAD · Mode: ` · **Model:**claude-haiku-4-5-20251001`
Stats: 1 user messages, 26 tool calls, tools used: Bash, Read.
Conversation
Turn 1 — User
Explore the package at /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src to understand the filter panel and document list components.
I need to understand: 1. The structure of the filter panel - what components exist, file paths 2. The DocumentCategory filter component - how it currently handles selection (single vs multi) 3. The DateFilter / "Filter by date" component - how "Since I last accessed this DMP" option works 4. The Visibility filter component - what checkboxes it has 5. The table/document list component - how columns are sized
Please provide: - File paths and key code snippets for each of the above - Props/interfaces used by the NhrEntryPoint component - How the filter state is managed (what types/interfaces are used)
Be thorough - look at all filter-related components, types, and the main table component.
Turn 1 — Assistant
I'll explore this package thoroughly to understand the filter panel and document list components. Let me start by examining the structure and then dive into each component.
Tools used:
Bash:find /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src -type f -name "*.tsx" -o -name "*.ts" | head -50
Tool results:
→ result (ok): /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/i18n.ts /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/entry.ts /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/types.ts /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/index.ts /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/i18n.test.ts /U …(truncated, 6554 more chars)
Let me continue exploring the structure and examine the key components:
Tools used:
Bash:find /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src -type f \( -name "*.tsx" -o -name "*.ts" \) | grep -i "filter\|entry\|document" | sort
Tool results:
→ result (ok): /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/business/factories/actions/createViewDocumentAction.test.ts /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/business/factories/actions/createViewDocumentAction.ts /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/business/factories/columns/createNhrDocumentCategoryColumn.test.tsx /Users/USER/workspace/doctolib/treatment-plan/p …(truncated, 15329 more chars)
Now let me read the key files to understand the structure. Let me start with the entry point and then examine the filter components:
Tools used:
Read:/Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/types.ts
Tools used:
Read:/Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/components/NhrEntryPoint/NhrEntryPoint.tsx
Tool results:
→ result (ok): 1 import type { DesignSystemIconComponent } from '@doctolib/design-system-icons'
2 import type { NhrDocument } from '@doctolib/tpf-national-health-records'
3 import type { ReactNode } from 'react'
4
5 export type NhrPatientInfo = {
6 fullName: string
7 gender: 'male' | 'female' | 'other'
8 birthDate: string
9 age: number
10 }
11
12 export type ColumnConfig = {
13 key: string
14 header: string
15 sortable: boolean
16 /** Only required when sortable: true. Returns a string for lo
…(truncated, 3733 more chars)
Tool results:
→ result (ok): 1 import { useState } from 'react'
2
3 import type { ActionConfig, ColumnConfig, FilterConfig, NhrPatientInfo, SearchDocumentsFn } from '../../types'
4 import { NhrDocumentListModal } from '../NhrDocumentListModal/NhrDocumentListModal'
5 import { NhrEntryPointButton } from '../NhrEntryPointButton/NhrEntryPointButton'
6
7 export type NhrEntryPointProps = {
8 patient: {
9 show_ins_features?: boolean
10 }
11 patientInfo: NhrPatientInfo
12 title: string
13 columns: ColumnConfig[]
14
…(truncated, 1502 more chars)
Tools used:
Read:/Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/components/NhrDocumentListFilterPanel/NhrDocumentListFilterPanel.tsx
Tool results:
→ result (ok): 1 import { ArrowRotateLeftRegularIcon } from '@doctolib/design-system-icons/ArrowRotateLeftRegularIcon'
2 import { Button } from '@doctolib/design-system/Button/v2'
3 import { Divider } from '@doctolib/design-system/Divider'
4 import { IconButton } from '@doctolib/design-system/IconButton/v2'
5 import { Paragraph } from '@doctolib/design-system/Paragraph'
6 import { useEffect, useState } from 'react'
7
8 import type { FilterConfig } from '../../types'
9
10 export type NhrDocumentListFilterPane
…(truncated, 4534 more chars)
Now let me examine the specific filter components and the document list table:
Tools used:
Read:/Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/components/NhrDocumentList/NhrDocumentCategoryFilter/NhrDocumentCategoryFilter.tsx
Tool results:
→ result (ok): 1 import { BetaComboBox } from '@doctolib/design-system/BetaComboBox'
2 import type { Option } from '@doctolib/design-system/Option'
3
4 type NhrDocumentCategoryFilterProps = {
5 label: string
6 value: string
7 options: Option[]
8 placeholder?: string
9 onSelectionChange: (option: Option) => void
10 onSearchChange: (search: string) => void
11 }
12
13 export const NhrDocumentCategoryFilter = ({
14 label,
15 value,
16 options,
17 placeholder,
18 onSelectionChange,
19 onSe
…(truncated, 669 more chars)
Tools used:
Read:/Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/business/factories/filters/createNhrDocumentCategoryFilterConfig.tsx
Tool results:
→ result (ok): 1 import type { Option } from '@doctolib/design-system/Option'
2
3 import { NhrDocumentCategoryFilter } from '../../../components/NhrDocumentList/NhrDocumentCategoryFilter/NhrDocumentCategoryFilter'
4 import type { FilterConfig } from '../../../types'
5
6 export const createNhrDocumentCategoryFilterConfig = ({
7 options = [],
8 defaultValue = '',
9 label = 'Document Category',
10 placeholder,
11 }: {
12 options?: Option[]
13 defaultValue?: string
14 label?: string
15 placeholde
…(truncated, 966 more chars)
Tools used:
Read:/Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/components/NhrDateSelectionFilter/NhrDateSelectionFilter.tsx
Tool results:
→ result (ok): 1 import { t } from '#i18n'
2 import type { Option } from '@doctolib/design-system/Option'
3 import { Paragraph } from '@doctolib/design-system/Paragraph'
4 import { RadioGroup } from '@doctolib/design-system/RadioGroup'
5
6 import { NhrDateRangeFilter } from '../NhrDateRangeFilter/NhrDateRangeFilter'
7 import { NhrDateTypeFilter } from '../NhrDateTypeFilter/NhrDateTypeFilter'
8
9 export type DateMode = 'customDateRange' | 'lastAccess'
10
11 type NhrDateSelectionFilterProps = {
12 label: st
…(truncated, 2582 more chars)
Let me continue reading the date filter factory and visibility filter:
Tools used:
Read:/Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/business/factories/filters/createNhrDateSelectionFilterConfig.tsx
Tool results:
→ result (ok): 1 import { formatNhrDateTime } from '#utils/nhrDateHelpers'
2 import type { Option } from '@doctolib/design-system/Option'
3
4 import {
5 type DateMode,
6 NhrDateSelectionFilter,
7 } from '../../../components/NhrDateSelectionFilter/NhrDateSelectionFilter'
8 import type { FilterConfig } from '../../../types'
9
10 export const createNhrDateSelectionFilterConfig = ({
11 label,
12 dateTypeOptions = [],
13 dateTypeLabel,
14 defaultDateType = '',
15 lastAccessDate,
16 fromLabel,
17
…(truncated, 1748 more chars)
Tools used:
Read:/Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/components/NhrDocumentVisibilityFilter/NhrDocumentVisibilityFilter.tsx
Tool results:
→ result (ok): 1 import { Checkbox } from '@doctolib/design-system/Checkbox/v2'
2 import { Heading } from '@doctolib/design-system/Heading'
3
4 import type { VisibilityOption } from '../../types'
5
6 export type NhrDocumentVisibilityFilterProps = {
7 groupLabel: string
8 visibilityModes: VisibilityOption[]
9 filters: Record<string, boolean>
10 onChange: (filterKey: string, checked: boolean) => void
11 }
12
13 export const NhrDocumentVisibilityFilter = ({
14 groupLabel,
15 visibilityModes,
16 f
…(truncated, 940 more chars)
Tools used:
Read:/Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/business/factories/filters/createNhrDocumentVisibilityFilterConfig.tsx
Tool results:
→ result (ok): 1 import { NhrDocumentVisibilityFilter } from '../../../components/NhrDocumentVisibilityFilter/NhrDocumentVisibilityFilter'
2 import type { FilterConfig, VisibilityOption } from '../../../types'
3
4 type CreateNhrDocumentVisibilityFilterConfigOptions = {
5 groupLabel: string
6 visibilityModes: VisibilityOption[]
7 }
8
9 export const createNhrDocumentVisibilityFilterConfig = ({
10 groupLabel,
11 visibilityModes,
12 }: CreateNhrDocumentVisibilityFilterConfigOptions): FilterConfig => ({
1
…(truncated, 677 more chars)
Now let me check the status filter and the main document list table:
Tools used:
Read:/Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/components/NhrDocumentList/NhrDocumentStatusFilter/NhrDocumentStatusFilter.tsx
Tool results:
→ result (ok): 1 import { Checkbox } from '@doctolib/design-system/Checkbox/v2'
2 import { Heading } from '@doctolib/design-system/Heading'
3
4 import type { NhrDocumentStatusFilterProps } from '../../../types'
5
6 export const NhrDocumentStatusFilter = ({ label, statuses, value, onChange }: NhrDocumentStatusFilterProps) => (
7 <>
8 <Heading level='h5'>{label}</Heading>
9 <div className='flex flex-col'>
10 {statuses.map((status) => (
11 <Checkbox
12 key={status.filterKey}
13
…(truncated, 667 more chars)
Tools used:
Read:/Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/business/factories/filters/createNhrDocumentStatusFilterConfig.tsx
Tool results:
→ result (ok): 1 import { NhrDocumentStatusFilter } from '../../../components/NhrDocumentList/NhrDocumentStatusFilter/NhrDocumentStatusFilter'
2 import type { FilterConfig, StatusOption } from '../../../types'
3
4 export const createNhrDocumentStatusFilterConfig = (statuses: StatusOption[], label: string): FilterConfig => ({
5 key: 'documentStatus',
6 render: (filters, onChange) => (
7 <NhrDocumentStatusFilter
8 label={label}
9 statuses={statuses}
10 value={statuses.filter((s) => fil
…(truncated, 498 more chars)
Tools used:
Read:/Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/components/NhrDocumentListModal/NhrDocumentListTable/NhrDocumentListTable.tsx
Tool results:
→ result (ok): 1 import { PAGE_SIZE } from '#utils/nhrPaginationHelpers'
2 import { Pagination } from '@doctolib/design-system/Pagination'
3 import { Table } from '@doctolib/design-system/Table'
4 import type { NhrDocument } from '@doctolib/tpf-national-health-records'
5
6 import type { ActionConfig, ColumnConfig } from '../../../types'
7 import { NhrDocumentListTableBody } from './NhrDocumentListTableBody/NhrDocumentListTableBody'
8 import { NhrDocumentListTableHead } from './NhrDocumentListTableHead/NhrDocu
…(truncated, 1314 more chars)
Let me check the table head and body to understand column sizing:
Tools used:
Read:/Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/components/NhrDocumentListModal/NhrDocumentListTable/NhrDocumentListTableHead/NhrDocumentListTableHead.tsx
Tool results:
→ result (ok): 1 import { TableHead } from '@doctolib/design-system/TableHead'
2 import { TableHeadCell } from '@doctolib/design-system/TableHeadCell'
3 import { TableHeadSelectAllCell } from '@doctolib/design-system/TableHeadSelectAllCell'
4 import { TableRow } from '@doctolib/design-system/TableRow'
5
6 import type { ColumnConfig } from '../../../../types'
7
8 export type NhrDocumentListTableHeadProps = {
9 columns: ColumnConfig[]
10 }
11
12 export const NhrDocumentListTableHead = ({ columns }: NhrDocum
…(truncated, 661 more chars)
Tools used:
Read:/Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/components/NhrDocumentListModal/NhrDocumentListTable/NhrDocumentListTableBody/NhrDocumentListTableBody.tsx
Tool results:
→ result (ok): 1 import { TableBody } from '@doctolib/design-system/TableBody'
2 import { TableCell } from '@doctolib/design-system/TableCell'
3 import { TableRow } from '@doctolib/design-system/TableRow'
4 import { TableSelectCell } from '@doctolib/design-system/TableSelectCell'
5 import type { NhrDocument } from '@doctolib/tpf-national-health-records'
6
7 import type { ActionConfig, ColumnConfig } from '../../../../types'
8 import { ActionButton } from './ActionButton'
9
10 export type NhrDocumentListTable
…(truncated, 1445 more chars)
Tools used:
Read:/Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/components/NhrEntryPoint/nhrDocumentListColumns.tsx
Tool results:
→ result (ok): 1 import type { ColumnConfig } from '../../types'
2
3 export const nhrDocumentListColumns: ColumnConfig[] = [
4 {
5 key: 'category',
6 header: 'Document category',
7 sortable: false,
8 render: (doc) => doc.classification?.codes[0]?.code ?? '-',
9 },
10 {
11 key: 'title',
12 header: 'Document name',
13 sortable: true,
14 sortAccessor: (doc) => doc.title,
15 render: (doc) => doc.title,
16 },
17 {
18 key: 'procedureDate',
19 header: 'Procedure
…(truncated, 1234 more chars)
Now let me check the modal and document list components to understand the overall structure:
Tools used:
Read:/Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/components/NhrDocumentListModal/NhrDocumentListModal.tsx
Tool results:
→ result (ok): 1 import { Modal } from '@doctolib/design-system/Modal'
2 import { ModalBody } from '@doctolib/design-system/ModalBody'
3 import type { NhrDocument } from '@doctolib/tpf-national-health-records'
4 import { useEffect, useMemo, useState } from 'react'
5
6 import type { ActionConfig, ColumnConfig, FilterConfig, NhrPatientInfo, SearchDocumentsFn } from '../../types'
7 import { NhrDocumentList } from '../NhrDocumentList/NhrDocumentList'
8
9 export type NhrDocumentListModalProps = {
10 isOpen: boo
…(truncated, 3149 more chars)
Tools used:
Read:/Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/components/NhrDocumentList/NhrDocumentList.tsx
Tool results:
→ result (ok): 1 import { getPagedData } from '#utils/nhrPaginationHelpers'
2 import { SpinnerLoader } from '@doctolib/design-system/SpinnerLoader'
3 import type { NhrDocument } from '@doctolib/tpf-national-health-records'
4 import { useMemo, useState } from 'react'
5
6 import type { ActionConfig, ColumnConfig, FilterConfig, NhrPatientInfo } from '../../types'
7 import { NhrDocumentListFilterPanel } from '../NhrDocumentListFilterPanel/NhrDocumentListFilterPanel'
8 import { NhrDocumentListHeader } from '../Nhr
…(truncated, 3453 more chars)
Perfect! Now let me check the header component and look at the NhrDateRangeFilter and NhrDateTypeFilter to get a complete picture:
Tools used:
Read:/Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/components/NhrDocumentListModal/NhrDocumentListHeader/NhrDocumentListHeader.tsx
Tool results:
→ result (ok): 1 import { SlidersRegularIcon } from '@doctolib/design-system-icons/SlidersRegularIcon'
2 import { Button } from '@doctolib/design-system/Button/v2'
3 import { Divider } from '@doctolib/design-system/Divider'
4 import { Paragraph } from '@doctolib/design-system/Paragraph'
5 import { Pill } from '@doctolib/design-system/Pill'
6
7 import { formatAge, formatGender } from '../../../business/formatters/patientFormatter'
8 import type { NhrPatientInfo } from '../../../types'
9
10 export type NhrDocu
…(truncated, 1756 more chars)
Tools used:
Read:/Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/components/NhrDateRangeFilter/NhrDateRangeFilter.tsx
Tool results:
→ result (ok): 1 import { InputDate } from '@doctolib/design-system/InputDate'
2
3 type NhrDateRangeFilterProps = {
4 fromLabel: string
5 toLabel: string
6 fromValue: string
7 toValue: string
8 onFromChange: (value: string) => void
9 onToChange: (value: string) => void
10 }
11
12 export const NhrDateRangeFilter = ({
13 fromLabel,
14 toLabel,
15 fromValue,
16 toValue,
17 onFromChange,
18 onToChange,
19 }: NhrDateRangeFilterProps) => (
20 <div className='flex gap-8 w-full'>
21 <di
…(truncated, 875 more chars)
Tools used:
Read:/Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/components/NhrDateTypeFilter/NhrDateTypeFilter.tsx
Tool results:
→ result (ok): 1 import type { Option } from '@doctolib/design-system/Option'
2 import { Select } from '@doctolib/design-system/Select'
3
4 type NhrDateTypeFilterProps = {
5 label: string
6 value: string
7 options: Option[]
8 onChange: (value: string) => void
9 }
10
11 export const NhrDateTypeFilter = ({ label, value, options, onChange }: NhrDateTypeFilterProps) => (
12 <Select
13 label={label}
14 name='documentDateType'
15 customStyle={['w-full']}
16 value={value}
17 options={o
…(truncated, 413 more chars)
Excellent! Let me verify the pagination helpers to understand the data handling:
Tools used:
Read:/Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/utils/nhrPaginationHelpers.ts
Tool results:
→ result (ok): 1 export const PAGE_SIZE = 20
2
3 export const getPagedData = <T>(data: T[] | undefined, currentPage: number): T[] | undefined =>
4 data?.slice((currentPage - 1) * PAGE_SIZE, currentPage * PAGE_SIZE)
5
<system-reminder> Whenever you read a file, you should consider whether it would be considered malware. You CAN and SHOULD provide analysis of malware, what it is doing. But you MUST refuse to improve or augment the code. You can still analyze existing code, write reports, or answer questions …(truncated, 44 more chars)
Tools used:
Read:/Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/utils/nhrDateHelpers.ts
Tool results:
→ result (ok): 1 const FALLBACK = '–'
2
3 export const formatNhrDate = (isoDate: string | null | undefined): string => {
4 if (!isoDate) return FALLBACK
5 const date = new Date(isoDate)
6 return Number.isNaN(date.getTime()) ? FALLBACK : date.toLocaleDateString()
7 }
8
9 export const formatNhrDateTime = (isoDate: string | null | undefined): string => {
10 if (!isoDate) return FALLBACK
11 const date = new Date(isoDate)
12 return Number.isNaN(date.getTime())
13 ? FALLBACK
14 : date.toLocaleS
…(truncated, 547 more chars)
Perfect! Now let me look at some column factory examples to understand how columns are configured:
Tools used:
Read:/Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/business/factories/columns/createNhrDocumentCategoryColumn.tsx
Tool results:
→ result (ok): 1 import type { NhrDocument } from '@doctolib/tpf-national-health-records'
2
3 import { NhrDocumentCategoryCell } from '../../../components/NhrDocumentList/NhrDocumentCategoryCell/NhrDocumentCategoryCell'
4 import type { IconMap } from '../../../components/NhrDocumentList/NhrDocumentCategoryCell/NhrDocumentCategoryCell'
5 import type { ColumnConfig } from '../../../types'
6
7 export type NhrDocumentCategoryColumnOptions = {
8 / Translated column header */
9 header: string
10 / Extrac
…(truncated, 1411 more chars)
Tools used:
Read:/Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/business/factories/columns/createNhrStatusColumn.tsx
Tool results:
→ result (ok): 1 import type { PillColor } from '@doctolib/design-system/Pill'
2 import type { NhrDocument } from '@doctolib/tpf-national-health-records'
3
4 import { NhrStatusCell } from '../../../components/NhrDocumentList/NhrStatusCell'
5 import type { ColumnConfig } from '../../../types'
6
7 / Pill config for a single recognized status token */
8 export type NhrDocumentStatusConfig = {
9 label: string
10 color?: PillColor
11 }
12
13 export type NhrStatusColumnOptions = {
14 / Translated column
…(truncated, 2104 more chars)
Perfect! I have all the information I need. Let me create a comprehensive summary of my findings:
Comprehensive Exploration Report: TPF National Health Records UI Package
I've thoroughly explored the package structure and understand all major components. Here's the complete breakdown:
1. FILTER PANEL STRUCTURE
Main Filter Panel Component:
- File Path: /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/components/NhrDocumentListFilterPanel/NhrDocumentListFilterPanel.tsx
- Key Props:
```typescript
type NhrDocumentListFilterPanelProps = {
isOpen: boolean
onClose: () => void
filters: FilterConfig[] // Feature-based filter factories
appliedFilters: Record<string, unknown>
onApply: (pendingFilters: Record<string, unknown>) => void
}
- **Structure:**
- Header (title + close button)
- Body (renders each FilterConfig dynamically)
- Footer (Reset, Cancel, Apply filters buttons)
- Panel width: 528px
- Uses Tailwind for layout with flex/overflow
---
## 2. DOCUMENTCATEGORY FILTER - SINGLE SELECTION
**Component:** `/Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/components/NhrDocumentList/NhrDocumentCategoryFilter/NhrDocumentCategoryFilter.tsx`
**Key Details:**
- Uses `BetaComboBox` from design system (single selection)
- Props structure:
```typescript
type NhrDocumentCategoryFilterProps = {
label: string
value: string // Single string value (SINGLE selection)
options: Option[]
placeholder?: string
onSelectionChange: (option: Option) => void
onSearchChange: (search: string) => void
}
Factory: /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/business/factories/filters/createNhrDocumentCategoryFilterConfig.tsx
Filter State Management:
key: 'typeCodes' // Note: internally stored as array
render: (filters, onChange) => {
const currentValue = (filters.typeCodes as string[] | undefined)?.[0] ?? defaultValue
// Only passes first element [option.value] to onChange
onSelectionChange={(option) => onChange({ typeCodes: [option.value] })}
}
- Stores in filters as array:
typeCodes: [selectedValue] - Extracts only first element for display (single selection pattern)
3. DATEFILTER / "FILTER BY DATE" - LAST ACCESS OPTION
Component: /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/components/NhrDateSelectionFilter/NhrDateSelectionFilter.tsx
Date Mode Type:
type DateMode = 'customDateRange' | 'lastAccess'
Props:
type NhrDateSelectionFilterProps = {
label: string
dateMode: DateMode // Radio selection between two modes
onDateModeChange: (mode: DateMode) => void
dateTypeLabel: string
dateTypeValue: string
dateTypeOptions: Option[] // e.g., "Submission date", "Procedure date"
onDateTypeChange: (value: string) => void
lastAccessDate: string // Pre-formatted datetime string
fromLabel: string
toLabel: string
fromValue: string
toValue: string
onFromChange: (value: string) => void
onToChange: (value: string) => void
}
"Since I last accessed this DMP" Implementation:
{dateMode === 'lastAccess' && (
<Paragraph>
{t('tpf_national_health_records_ui.filters.date_selection.last_access.message')}
{lastAccessDate} // e.g., "Jan 5, 2024 at 10:45"
</Paragraph>
)}
- Uses RadioGroup with two options: 'customDateRange' | 'lastAccess'
- When
lastAccessselected, displays only the formatted lastAccessDate - When
customDateRangeselected, shows date type dropdown + from/to date inputs
Factory: /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/business/factories/filters/createNhrDateSelectionFilterConfig.tsx
Filter State Keys:
- dateMode: DateMode - which mode is selected
- dateType: string[] - array of date type values (submission vs procedure date)
- submissionDateFrom: string - from date ISO string
- submissionDateTo: string - to date ISO string
- lastAccessDate: string - passed as prop, formatted via formatNhrDateTime()
Date Input Components:
- NhrDateRangeFilter - Two InputDate fields side-by-side (full width split)
- NhrDateTypeFilter - Select dropdown for choosing date type
4. VISIBILITY FILTER - CHECKBOXES
Component: /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/components/NhrDocumentVisibilityFilter/NhrDocumentVisibilityFilter.tsx
Props:
type NhrDocumentVisibilityFilterProps = {
groupLabel: string
visibilityModes: VisibilityOption[]
filters: Record<string, boolean>
onChange: (filterKey: string, checked: boolean) => void
}
// VisibilityOption from types.ts:
type VisibilityOption = {
filterKey: string
label: string
isDisabled?: boolean
}
Structure:
<Heading>{groupLabel}</Heading>
<div className='flex flex-col'>
{visibilityModes.map(mode => (
<Checkbox
name={mode.filterKey}
label={mode.label}
value={Boolean(filters[mode.filterKey])}
isDisabled={mode.isDisabled}
onChange={(checked) => onChange(mode.filterKey, checked)}
/>
))}
</div>
- Multiple checkboxes - supports any number of visibility options
- Filter State: Each checkbox key maps to a boolean:
{ [filterKey]: true/false } - Commonly used for: public/private visibility, shared states, etc.
Factory: /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/business/factories/filters/createNhrDocumentVisibilityFilterConfig.tsx
5. DOCUMENT LIST TABLE - COLUMN SIZING
Table Component: /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/components/NhrDocumentListModal/NhrDocumentListTable/NhrDocumentListTable.tsx
Props:
type NhrDocumentListTableProps = {
columns: ColumnConfig[]
isLoading?: boolean
rows?: NhrDocument[]
actions?: ActionConfig[]
currentPage: number
onPageChange: (page: number) => void
total: number
}
Layout Structure:
<div className='flex h-full flex-col'>
<div className='min-h-0 flex-1 overflow-auto'>
<Table>
<NhrDocumentListTableHead columns={columns} />
<NhrDocumentListTableBody columns={columns} rows={rows} actions={actions} />
</Table>
</div>
<div className='shrink-0 pt-16'>
<Pagination />
</div>
</div>
Column Sizing:
- No explicit column width definitions in the table itself
- Uses design system's Table component (auto-sizing)
- Column structure:
[Checkbox] [Column1] [Column2] ... [ColumnN] [Actions]
- The design system
TableHeadCellandTableCellhandle sizing - Responsive: Uses Tailwind's flex model with
min-h-0 flex-1 overflow-autofor scrolling
Table Head: /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/components/NhrDocumentListModal/NhrDocumentListTable/NhrDocumentListTableHead/NhrDocumentListTableHead.tsx
<TableHeadSelectAllCell />
{columns.map(col => <TableHeadCell>{col.header}</TableHeadCell>)}
<TableHeadCell /> // Empty for actions
Table Body: /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/components/NhrDocumentListModal/NhrDocumentListTable/NhrDocumentListTableBody/NhrDocumentListTableBody.tsx
<TableSelectCell /> // Checkbox
{columns.map(col => <TableCell>{col.render(row)}</TableCell>)}
<TableCell>
{actions?.map(action => <ActionButton action={action} row={row} />)}
</TableCell>
6. DEFAULT COLUMNS CONFIGURATION
File: /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/components/NhrEntryPoint/nhrDocumentListColumns.tsx
type ColumnConfig = {
key: stri
…(truncated, 5418 more chars)