Project: doctolib-doctolib · Branch: .invalid · Mode: ` · **Model:**claude-haiku-4-5-20251001`
Stats: 1 user messages, 52 tool calls, tools used: Bash, Read.
Conversation
Turn 1 — User
Explore the NHR document list UI components in /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/. I need a thorough understanding of:
- All component files and their structure (list them all with full paths)
- The NhrEntryPoint component - what props it accepts, what it renders
- The document list table/grid component - columns, how status/visibility are rendered
- The filter panel/sidebar component - what filters exist, how they're structured
- Any header/toolbar area with the filter button and results count
- How document categories (icons) are rendered
- How the "Shared by" column is rendered
- How Status column (Active/Archived/Obsolete) is rendered
- How Visibility column is rendered
- The pagination component
- What i18n keys exist in src/locales/ or i18n.json
Also look at /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records/src/ for shared types and business logic.
Be thorough - read actual file contents for all key components, not just list them.
Turn 1 — Assistant
I'll conduct a thorough exploration of the NHR document list UI components. Let me start by mapping out the directory structure and then examining the key files.
Tools used:
Bash:find /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src -type f -name "*.tsx" -o -name "*.ts" -o -name "*.json" | head -50
Tool results:
→ result (ok): /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/locales/loadNamespace.ts /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/locales/fr/tpf_national_health_records_ui.json /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/locales/en/tpf_national_health_records_ui.json /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/i18n.ts /Users/USER/w …(truncated, 6923 more chars)
Let me continue exploring the component structure:
Tools used:
Bash:find /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src -type f \( -name "*.tsx" -o -name "*.ts" \) | sort
Tool results:
→ result (ok): /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/tests/index.test.ts /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/business/factories/actions/createMoreActionsAction.test.ts /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/business/factories/actions/createMoreActionsAction.ts /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/bus …(truncated, 18203 more chars)
Now let me read the key component files. I'll start with the NhrEntryPoint and main components:
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 { 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, 1179 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 { SpinnerLoader } from '@doctolib/design-system-b2b/SpinnerLoader'
2 import type { NhrDocument } from '@doctolib/tpf-national-health-records'
3 import { useState } from 'react'
4
5 import type { ActionConfig, ColumnConfig, FilterConfig, NhrPatientInfo } from '../../types'
6 import { NhrDocumentListFilterPanel } from '../NhrDocumentListFilterPanel/NhrDocumentListFilterPanel'
7 import { NhrDocumentListHeader } from '../NhrDocumentListModal/NhrDocumentListHeader/NhrDocumentListHeader'
8 i
…(truncated, 2308 more chars)
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 { useDocuments } from '#data/documents'
2 import { wrapActions } from '#helpers/actions'
3 import { Modal } from '@doctolib/design-system/Modal'
4 import { ModalBody } from '@doctolib/design-system/ModalBody'
5 import { useMemo, useState } from 'react'
6
7 import type { ActionConfig, ColumnConfig, FilterConfig, NhrPatientInfo, SearchDocumentsFn } from '../../types'
8 import { NhrDocumentList } from '../NhrDocumentList/NhrDocumentList'
9
10 export type NhrDocumentListModalProps = {
11
…(truncated, 1354 more chars)
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 { Paragraph } from '@doctolib/design-system/Paragraph'
4
5 import { formatAge, formatGender } from '../../../business/formatters/patientFormatter'
6 import type { NhrPatientInfo } from '../../../types'
7
8 export type NhrDocumentListHeaderProps = {
9 patient: NhrPatientInfo
10 filterCount: number
11 onOpenFilters: () => void
12 }
13
…(truncated, 909 more chars)
Now let me read the table and cell components:
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 { Pagination } from '@doctolib/design-system/Pagination'
2 import { Table } from '@doctolib/design-system/Table'
3 import type { NhrDocument } from '@doctolib/tpf-national-health-records'
4
5 import type { ActionConfig, ColumnConfig } from '../../../types'
6 import { NhrDocumentListTableBody } from './NhrDocumentListTableBody/NhrDocumentListTableBody'
7 import { NhrDocumentListTableHead } from './NhrDocumentListTableHead/NhrDocumentListTableHead'
8
9 export type NhrDocumentListTablePr
…(truncated, 593 more chars)
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, 338 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 { IconButton } from '@doctolib/design-system/IconButton/v2'
2 import { TableBody } from '@doctolib/design-system/TableBody'
3 import { TableCell } from '@doctolib/design-system/TableCell'
4 import { TableRow } from '@doctolib/design-system/TableRow'
5 import { TableSelectCell } from '@doctolib/design-system/TableSelectCell'
6 import type { NhrDocument } from '@doctolib/tpf-national-health-records'
7
8 import type { ActionConfig, ColumnConfig } from '../../../../types'
9
10 export type
…(truncated, 1453 more chars)
Now let me read the filter panel and status/visibility cell components:
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 { IconButton } from '@doctolib/design-system/IconButton/v2'
4 import { Paragraph } from '@doctolib/design-system/Paragraph'
5 import { useEffect, useState } from 'react'
6
7 import type { FilterConfig } from '../../types'
8
9 export type NhrDocumentListFilterPanelProps = {
10 isOpen: boolean
11 onClose: () => void
12
…(truncated, 3877 more chars)
Tools used:
Read:/Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/components/NhrDocumentList/NhrStatusCell/NhrStatusCell.tsx
Tool results:
→ result (ok): 1 import { Badge } from '@doctolib/design-system/Badge'
2
3 type StatusConfig = {
4 label: string
5 variant?: string
6 }
7
8 type Props = {
9 rawStatus: string | undefined
10 splitStatus: ((status: string) => string[]) | undefined
11 statusMap: Record<string, StatusConfig>
12 defaultStatus: StatusConfig
13 }
14
15 const resolveStatuses = (
16 rawStatus: string | undefined,
17 splitStatus: ((status: string) => string[]) | undefined,
18 statusMap: Record<string, StatusConfig>,
…(truncated, 831 more chars)
Tools used:
Read:/Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/components/NhrDocumentList/NhrVisibilityCell/NhrVisibilityCell.tsx
Tool results:
→ result (ok): 1 type Props = {
2 label: string | undefined
3 }
4
5 export const NhrVisibilityCell = ({ label }: Props) => {
6 if (label === undefined) return null
7 return <span>{label}</span>
8 }
9
Tools used:
Read:/Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/components/NhrDocumentList/NhrSharedByCell/NhrSharedByCell.tsx
Tool results:
→ result (ok): 1 import { Badge } from '@doctolib/design-system/Badge'
2
3 type Props = {
4 isPatientAuthored: boolean
5 patientLabel: string
6 authorName: string | undefined
7 }
8
9 export const NhrSharedByCell = ({ isPatientAuthored, patientLabel, authorName }: Props) =>
10 isPatientAuthored ? <Badge uiStyle='neutral'>{patientLabel}</Badge> : <span>{authorName ?? ''}</span>
11
[result-id: r12]
Now let me read the filter components and document category cell:
Tools used:
Read:/Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/components/NhrDocumentList/NhrDocumentCategoryCell/NhrDocumentCategoryCell.tsx
Tool results:
→ result (ok): 1 import type { DesignSystemIconComponent } from '@doctolib/design-system-icons'
2
3 export type IconMap = Record<string, DesignSystemIconComponent | undefined>
4
5 type NhrDocumentCategoryCellProps = {
6 label: string | undefined
7 iconMap?: IconMap
8 }
9
10 export const NhrDocumentCategoryCell = ({ label, iconMap }: NhrDocumentCategoryCellProps) => {
11 if (label === undefined) return null
12 const Icon = iconMap?.[label] ?? iconMap?.['*']
13 return (
14 <span className='flex
…(truncated, 113 more chars)
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, 324 more chars)
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 value: string
6 options: Option[]
7 onSelectionChange: (option: Option) => void
8 onSearchChange: (search: string) => void
9 }
10
11 export const NhrDocumentCategoryFilter = ({
12 value,
13 options,
14 onSelectionChange,
15 onSearchChange,
16 }: NhrDocumentCategoryFilterProps) => (
17 <BetaComboBox
1
…(truncated, 210 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, 645 more chars)
Now let me read the types file and factory functions for columns and filters:
Tools used:
Read:/Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/types.ts
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, 2025 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, 912 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 { NhrDocument } from '@doctolib/tpf-national-health-records'
2
3 import { NhrStatusCell } from '../../../components/NhrDocumentList/NhrStatusCell'
4 import type { ColumnConfig } from '../../../types'
5
6 /*
7 * Aliases Oxygen BadgeStyle for consumer type-safety.
8 * Only includes values that are semantically meaningful for document status display.
9 /
10 export type NhrStatusBadgeVariant =
11 | 'info'
12 | 'error'
13 | 'success'
14 | 'warning'
15 | 'dark-info'
16
…(truncated, 2092 more chars)
Let me read more factory functions:
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'
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 / Extracts the human-readable do
…(truncated, 782 more chars)
Tools used:
Read:/Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/business/factories/columns/createNhrSharedByColumn.tsx
Tool results:
→ result (ok): 1 import type { NhrDocument } from '@doctolib/tpf-national-health-records'
2
3 import { NhrSharedByCell } from '../../../components/NhrDocumentList/NhrSharedByCell'
4 import type { ColumnConfig } from '../../../types'
5
6 export type NhrSharedByColumnOptions = {
7 / Translated column header */
8 header: string
9 /
10 * Returns true when the document was authored by the patient.
11 * EX_3.1-1040: classCode=90 triggers the Patient badge.
12 */
13 isPatientAuthored: (doc: Nhr
…(truncated, 943 more chars)
Tools used:
Read:/Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/business/factories/columns/createNhrVisibilityColumn.tsx
Tool results:
→ result (ok): 1 import type { NhrDocument } from '@doctolib/tpf-national-health-records'
2
3 import { NhrVisibilityCell } from '../../../components/NhrDocumentList/NhrVisibilityCell'
4 import type { ColumnConfig } from '../../../types'
5
6 export type NhrVisibilityColumnOptions = {
7 / Translated column header */
8 header: string
9 / Extracts the human-readable visibility label from the document /
10 getVisibility: (doc: NhrDocument) => string | undefined
11 }
12
13 /*
14 * Feature-based fac
…(truncated, 470 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, 176 more chars)
Now let me read the filter factories and i18n files:
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 = (options: Option[] = [], defaultValue = ''): FilterConfig => ({
7 key: 'typeCodes',
8 render: (filters, onChange) => {
9 const currentValue = (filters.typeCodes as string[] | undefi
…(truncated, 412 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, 355 more chars)
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 type { Option } from '@doctolib/design-system/Option'
2
3 import {
4 type DateMode,
5 NhrDateSelectionFilter,
6 } from '../../../components/NhrDateSelectionFilter/NhrDateSelectionFilter'
7 import type { FilterConfig } from '../../../types'
8
9 export const createNhrDateSelectionFilterConfig = ({
10 label,
11 dateTypeOptions = [],
12 dateTypeLabel,
13 defaultDateType = '',
14 lastAccessDate,
15 fromLabel,
16 toLabel,
17 }: {
18 label: string
19 dateTypeOptions?: O
…(truncated, 1346 more chars)
Tools used:
Read:/Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/locales/en/tpf_national_health_records_ui.json
Tool results:
→ result (ok): 1 {
2 "entry_point.open": "Open NHR",
3 "filters.date_selection.custom_range.label": "Custom date range",
4 "filters.date_selection.last_access.label": "Since I last accessed this DMP",
5 "filters.date_selection.last_access.message": "Last accessed on:",
6 "translation": "Translation"
7 }
8
[result-id: r27]
Now let me check the date-related filter components and the shared types from the business logic package:
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, 2253 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, 91 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, 553 more chars)
Now let me check the tpf-national-health-records package for shared types:
Tools used:
Bash:find /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records/src -type f \( -name "*.ts" -o -name "*.tsx" \) | head -20
Tool results:
→ result (ok): /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records/src/business/nhr-service-factory.ts /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records/src/business/types/document.ts /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records/src/business/types/participant.ts /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records/src/business/types/index.ts /Users/USER/workspace/doctolib/treatmen …(truncated, 568 more chars)
Tools used:
Read:/Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records/src/business/types/document.ts
Tool results:
→ result (ok): 1 import type { NhrDocumentAuthor, NhrPatientInformation } from '#business/types/participant'
2
3 // General types ---
4 /* The services/procedures this document is associated with /
5 export type NhrServiceInformation = {
6 startDate?: string
7 endDate?: string
8 }
9
10 export type NhrDocumentClassification = {
11 codes: Code[]
12 }
13
14 export type Code = {
15 system: string
16 code: string
17 }
18
19 export type DateRange = {
20 upperLimit?: string
21 lowerLimit?: string
…(truncated, 1005 more chars)
Tools used:
Read:/Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records/src/index.ts
Tool results:
→ result (ok): 1 // bump 2 export { createNhrService } from '#business/nhr-service-factory' 3 export type { NhrAdapter, NhrService, CountryCode } from '#business/types/service' 4 export type { 5 NhrDocumentSearchProps, 6 NhrDocumentSearchResult, 7 NhrDocument, 8 NhrServiceInformation, 9 NhrDocumentSearchParams, 10 NhrDocumentClassification, 11 DateRange, 12 Code, 13 } from '#business/types/document' 14 export type { 15 NhrDocumentAuthor, 16 NhrAddress, 17 NhrContact, 18 NhrInstitution,
…(truncated, 290 more chars)
Let me check the other column factories and actions:
Tools used:
Read:/Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/business/factories/columns/createNhrDocumentNameColumn.tsx
Tool results:
→ result (ok): 1 import type { NhrDocument } from '@doctolib/tpf-national-health-records'
2
3 import { NhrDocumentNameCell } from '../../../components/NhrDocumentList/NhrDocumentNameCell'
4 import type { ColumnConfig } from '../../../types'
5
6 export type NhrDocumentNameColumnOptions = {
7 / Translated column header */
8 header: string
9 }
10
11 /
12 * Feature-based factory: produces a ColumnConfig for the document name column.
13 * Always reads from doc.title.
14 *
15 * the key is always 'docu
…(truncated, 331 more chars)
Tools used:
Read:/Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/business/factories/columns/createNhrProcedureDateColumn.tsx
Tool results:
→ result (ok): 1 import type { NhrDocument } from '@doctolib/tpf-national-health-records'
2
3 import { NhrProcedureDateCell } from '../../../components/NhrDocumentList/NhrProcedureDateCell'
4 import type { ColumnConfig } from '../../../types'
5
6 export type NhrProcedureDateColumnOptions = {
7 / Translated column header */
8 header: string
9 /
10 * Extracts the ISO date string for the procedure date from the document.
11 * Returns undefined when the procedure date is absent.
12 */
13 get
…(truncated, 701 more chars)
Tools used:
Read:/Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/business/factories/columns/createNhrShareDateColumn.tsx
Tool results:
→ result (ok): 1 import type { NhrDocument } from '@doctolib/tpf-national-health-records'
2
3 import { NhrShareDateCell } from '../../../components/NhrDocumentList/NhrShareDateCell'
4 import type { ColumnConfig } from '../../../types'
5
6 export type NhrShareDateColumnOptions = {
7 / Translated column header */
8 header: string
9 /
10 * Extracts the ISO date string for the share date from the document.
11 * Returns undefined when the share date is absent.
12 */
13 getDate: (doc: NhrDocum
…(truncated, 653 more chars)
Tools used:
Read:/Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/business/factories/actions/createViewDocumentAction.ts
Tool results:
→ result (ok): 1 import { EyeRegularIcon } from '@doctolib/design-system-icons/EyeRegularIcon'
2 import type { NhrDocument } from '@doctolib/tpf-national-health-records'
3
4 import type { ActionConfig } from '../../../types'
5
6 export const createViewDocumentAction = (onClick: (doc: NhrDocument) => Promise<void>): ActionConfig => ({
7 key: 'view',
8 tooltip: 'View document',
9 iconComponent: EyeRegularIcon,
10 variant: 'transparent',
11 onClick,
12 })
13
[result-id: r37]
Tools used:
Read:/Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/business/factories/actions/createMoreActionsAction.ts
Tool results:
→ result (ok): 1 import { EllipsisVerticalRegularIcon } from '@doctolib/design-system-icons/EllipsisVerticalRegularIcon'
2 import type { NhrDocument } from '@doctolib/tpf-national-health-records'
3
4 import type { ActionConfig } from '../../../types'
5
6 export const createMoreActionsAction = (onClick: (doc: NhrDocument) => Promise<void>): ActionConfig => ({
7 key: 'more',
8 tooltip: 'More actions',
9 iconComponent: EllipsisVerticalRegularIcon,
10 variant: 'transparent',
11 onClick,
12 })
13
[resu
…(truncated, 11 more chars)
Tools used:
Read:/Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/components/NhrDocumentList/NhrDocumentNameCell/NhrDocumentNameCell.tsx
Tool results:
→ result (ok): 1 type Props = {
2 title: string | undefined
3 }
4
5 export const NhrDocumentNameCell = ({ title }: Props) => (title === undefined ? null : <span>{title}</span>)
6
Tools used:
Read:/Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/components/NhrDocumentList/NhrProcedureDateCell/NhrProcedureDateCell.tsx
Tool results:
→ result (ok): 1 type Props = {
2 isoDate: string | undefined
3 }
4
5 export const NhrProcedureDateCell = ({ isoDate }: Props) => {
6 if (!isoDate) return null
7 return <span>{new Date(isoDate).toLocaleDateString()}</span>
8 }
9
Tools used:
Read:/Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/components/NhrDocumentList/NhrShareDateCell/NhrShareDateCell.tsx
Tool results:
→ result (ok): 1 type Props = {
2 isoDate: string | undefined
3 }
4
5 export const NhrShareDateCell = ({ isoDate }: Props) => {
6 if (!isoDate) return null
7 return <span>{new Date(isoDate).toLocaleDateString()}</span>
8 }
9
Let me check the helpers and data layer:
Tools used:
Read:/Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/data/documents.ts
Tool results:
→ result (ok): 1 import type { NhrDocument } from '@doctolib/tpf-national-health-records'
2 import { useQuery } from '@tanstack/react-query-v5'
3
4 import type { SearchDocumentsFn } from '../types'
5
6 export type DocumentsQueryParam = {
7 searchDocuments: SearchDocumentsFn
8 appliedFilters: Record<string, unknown>
9 }
10
11 export const buildQueryKeyDocuments = (appliedFilters: Record<string, unknown>) => [
12 'nhr',
13 'documents',
14 { appliedFilters },
15 ]
16
17 const DEFAULT_OPTIONS: { enab
…(truncated, 480 more chars)
Tools used:
Read:/Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/helpers/actions.ts
Tool results:
→ result (ok): 1 import type { NhrDocument } from '@doctolib/tpf-national-health-records'
2
3 import type { ActionConfig } from '../types'
4
5 export const wrapActions = (
6 actions: ActionConfig[] | undefined,
7 setIsLoading: (loading: boolean) => void
8 ): ActionConfig[] | undefined =>
9 actions?.map((action) => ({
10 ...action,
11 onClick: async (doc: NhrDocument) => {
12 setIsLoading(true)
13
14 try {
15 await action.onClick(doc)
16 } finally {
17 setIsLoa
…(truncated, 62 more chars)
Tools used:
Read:/Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/i18n.ts
Tool results:
→ result (ok): 1 import { i18n } from '@doctolib/tpf-commons/i18n'
2
3 import { loadNamespace } from './locales/loadNamespace'
4
5 i18n.registerNamespace('tpf_national_health_records_ui', loadNamespace)
6
7 export const t = i18n.t
8 export const changeLanguage = i18n.changeLanguage
9 // To be used only for storybook
10 export const getInstance = i18n.getInstance
11
[result-id: r41]
Let me check the entry point file and NhrEntryPointButton:
Tools used:
Read:/Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/entry.ts
Tool results:
→ result (ok): 1 // For module federation 2 export const NhrEntryPoint = import('./components/NhrEntryPoint/NhrEntryPoint') 3
Tools used:
Read:/Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/components/NhrEntryPointButton/NhrEntryPointButton.tsx
Tool results:
→ result (ok): 1 import { Badge } from '@doctolib/design-system/Badge'
2 import { IconButton } from '@doctolib/design-system/IconButton/v2'
3
4 import { t } from '../../i18n'
5
6 const NEW_DOCUMENTS_COUNT_LIMIT = 99
7
8 const formatNewDocumentsCount = (newDocumentsCount: number) =>
9 newDocumentsCount > NEW_DOCUMENTS_COUNT_LIMIT ? '99+' : newDocumentsCount
10
11 export type NhrEntryPointButtonProps = {
12 newDocumentsCount?: number
13 onClick: () => void
14 }
15
16 export const NhrEntryPointButton =
…(truncated, 550 more chars)
Tools used:
Read:/Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/locales/loadNamespace.ts
Tool results:
→ result (ok): 1 import type { Language } from '@doctolib/upfront-core/i18n'
2
3 import NationalHealthRecordsUiEn from './en/tpf_national_health_records_ui.json'
4 import NationalHealthRecordsUiFr from './fr/tpf_national_health_records_ui.json'
5
6 export const loadNamespace = (lang: Language, namespace: string) => {
7 console.log(Loading namespace: ${namespace} for language: ${lang})
8
9 if (namespace !== 'tpf_national_health_records_ui') {
10 throw new Error(Unsupported namespace: ${namespace}
…(truncated, 302 more chars)
Let me check the French locales and the test fixture data:
Tools used:
Read:/Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/locales/fr/tpf_national_health_records_ui.json
Tool results:
→ result (ok): 1 {
2 "entry_point.open": "Ouvrir NHR",
3 "filters.date_selection.custom_range.label": "Plage de dates personnalisée",
4 "filters.date_selection.last_access.label": "Depuis ma dernière connexion au DMP",
5 "filters.date_selection.last_access.message": "Dernière consultation le :"
6 }
7
[result-id: r44]
Tools used:
Read:/Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/test-helpers/fixtures/mockData.ts
Tool results:
→ result (ok): 1 import { nhrDocumentFixtureBuilder } from './nhrDocumentFixtureBuilder'
2 import { nhrPatientInfoFixtureBuilder } from './nhrPatientInfoFixtureBuilder'
3
4 export { nhrDocumentListColumns as mockColumns } from '../../components/NhrEntryPoint/nhrDocumentListColumns'
5
6 export const mockPatientInfo = nhrPatientInfoFixtureBuilder()
7
8 export const mockRows = [
9 nhrDocumentFixtureBuilder(),
10 nhrDocumentFixtureBuilder({
11 id: '2',
12 title: 'MRI Brain scan',
13 creationDate
…(truncated, 670 more chars)
Tools used:
Read:/Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/test-helpers/fixtures/nhrDocumentFixtureBuilder.ts
Tool results:
→ result (ok): 1 import type { NhrDocument } from '@doctolib/tpf-national-health-records'
2
3 import { createFixtureBuilder } from './createFixtureBuilder'
4
5 export const nhrDocumentFixtureBuilder = createFixtureBuilder<NhrDocument>({
6 id: '1',
7 title: 'SOPK test results',
8 creationDate: '2025-01-13',
9 submissionDate: '2025-01-18',
10 status: 'Current',
11 visibility: 'Visible to all',
12 format: 'application/pdf',
13 authors: [{ id: 'doc1', firstName: 'Mario', lastName: 'Casas', role:
…(truncated, 138 more chars)
Perfect! Now let me create a comprehensive summary document. Let me check a few more supporting files to complete the picture:
Tools used:
Bash:ls -la /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/components/
Tool results:
→ result (ok): drwxr-xr-x clertonra staff 352 B Wed Apr 1 10:05:06 2026 . drwxr-xr-x clertonra staff 448 B Wed Apr 8 10:20:35 2026 .. drwxr-xr-x clertonra staff 160 B Wed Apr 1 10:05:06 2026 NhrDateRangeFilter drwxr-xr-x clertonra staff 160 B Wed Apr 1 10:05:06 2026 NhrDateSelectionFilter drwxr-xr-x clertonra staff 160 B Wed Apr 1 10:05:06 2026 NhrDateTypeFilter drwxr-xr-x clertonra staff 448 B Wed Apr 8 10:20:35 2026 NhrDocumentList drwxr-xr-x clertonra staff 160 B Wed Apr 1 10:05:06 2026 NhrDocumentLi …(truncated, 345 more chars)
Excellent! I now have a comprehensive understanding of the codebase. Let me compile the complete report:
Complete NHR Document List UI Components Analysis
1. ALL COMPONENT FILES - Complete List with Full Paths
Main Entry Points:
- /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/components/NhrEntryPoint/NhrEntryPoint.tsx
- /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/components/NhrEntryPoint/nhrDocumentListColumns.tsx
- /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/components/NhrEntryPointButton/NhrEntryPointButton.tsx
Modal & List Container:
- /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/components/NhrDocumentListModal/NhrDocumentListModal.tsx
- /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/components/NhrDocumentList/NhrDocumentList.tsx
Table Components:
- /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/components/NhrDocumentListModal/NhrDocumentListTable/NhrDocumentListTable.tsx
- /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/components/NhrDocumentListModal/NhrDocumentListTable/NhrDocumentListTableHead/NhrDocumentListTableHead.tsx
- /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/components/NhrDocumentListModal/NhrDocumentListTable/NhrDocumentListTableBody/NhrDocumentListTableBody.tsx
Header Component:
- /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/components/NhrDocumentListModal/NhrDocumentListHeader/NhrDocumentListHeader.tsx
Filter Panel & Components:
- /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/components/NhrDocumentListFilterPanel/NhrDocumentListFilterPanel.tsx
- /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/components/NhrDocumentList/NhrDocumentStatusFilter/NhrDocumentStatusFilter.tsx
- /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/components/NhrDocumentList/NhrDocumentCategoryFilter/NhrDocumentCategoryFilter.tsx
- /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/components/NhrDocumentVisibilityFilter/NhrDocumentVisibilityFilter.tsx
- /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/components/NhrDateSelectionFilter/NhrDateSelectionFilter.tsx
- /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/components/NhrDateTypeFilter/NhrDateTypeFilter.tsx
- /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/components/NhrDateRangeFilter/NhrDateRangeFilter.tsx
Table Cell Components:
- /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/components/NhrDocumentList/NhrDocumentNameCell/NhrDocumentNameCell.tsx
- /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/components/NhrDocumentList/NhrDocumentCategoryCell/NhrDocumentCategoryCell.tsx
- /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/components/NhrDocumentList/NhrProcedureDateCell/NhrProcedureDateCell.tsx
- /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/components/NhrDocumentList/NhrShareDateCell/NhrShareDateCell.tsx
- /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/components/NhrDocumentList/NhrSharedByCell/NhrSharedByCell.tsx
- /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/components/NhrDocumentList/NhrStatusCell/NhrStatusCell.tsx
- /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/components/NhrDocumentList/NhrVisibilityCell/NhrVisibilityCell.tsx
Factory Functions:
- Columns: /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/business/factories/columns/createNhr*.tsx (8 files)
- Filters: /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/business/factories/filters/createNhr*.tsx (4 files)
- Actions: /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/business/factories/actions/createNhr*.ts (2 files)
2. NhrEntryPoint Component - Props & Rendering
NhrEntryPoint.tsx:
export type NhrEntryPointProps = {
patient: {
show_ins_features?: boolean
}
patientInfo: NhrPatientInfo
title: string
columns: ColumnConfig[]
filters: FilterConfig[]
searchDocuments: SearchDocumentsFn
actions?: ActionConfig[]
newDocumentsCount?: number
status: 'enabled' | 'disabled' | 'missing_requirements'
}
Rendering Logic:
- Checks patient eligibility: requires patient.show_ins_features === true AND status === 'enabled'
- Returns null if not eligible (patient feature gating for active DMP)
- Renders <NhrEntryPointButton> with optional badge showing count of new documents (capped at "99+")
- Renders <NhrDocumentListModal> in fullscreen size
- Modal opens/closes with internal state
NhrEntryPointButton:
- Small icon button with folder-open icon
- Shows Info badge overlay if newDocumentsCount > 0 (positioned top-right)
- Badge formatting caps at 99+ for accessibility
- i18n tooltip: 'tpf_national_health_records_ui.entry_point.open'
3. Document List Table/Grid Component - Columns & Status/Visibility Rendering
NhrDocumentListTable.tsx:
- Wraps <Table> from design-system with head and body
- Includes <Pagination> component (currently stubbed: currentPage={1}, total={rows.length}, nbRowsPerPage={20})
Table Columns Structure (ColumnConfig):
type ColumnConfig = {
key: string
header: string
sortable: boolean
sortAccessor?: (doc: NhrDocument) => string
render: (doc: NhrDocument) => ReactNode
}
NhrDocumentListTableHead:
- Renders <TableHeadSelectAllCell> checkbox
- Maps columns to <TableHeadCell> with header text
- Adds empty header cell for row actions column
NhrDocumentListTableBody:
- Shows skeleton loader with 8 rows while isLoading === true
- Maps each row with <TableSelectCell> checkbox
- Renders column cells via col.render(row)
- Renders row actions (IconButtons) in final cell
Status Column Rendering (NhrStatusCell.tsx):
- Accepts rawStatus string from document
- Optionally splits via splitStatus() function (e.g., "MASKED|ACTIVE" → ["MASKED", "ACTIVE"])
- Maps tokens via statusMap: Record<string, StatusConfig> to get labels + badge variants
- Renders stacked <Badge> components (one per token)
- Falls back to defaultStatus if no tokens match or status is undefined
- Supports variants: 'info' | 'error' | 'success' | 'warning' | 'dark-info' | 'mute' | 'no-background' | 'neutral' | 'disabled'
Visibility Column Rendering (NhrVisibilityCell.tsx):
- Simple cell: renders label string or null if undefined
- Label extracted via getVisibility(doc) factory option
4. Filter Panel/Sidebar Component - Filters & Structure
NhrDocumentListFilterPanel.tsx: - Overlay panel positioned on right side (w-400px, h-full) - Three sub-sections: - Header: "Filters" title + close (xmark) button - Body: scrollable flex-col with filter configs, gap-16 spacing - Footer: Reset button (left), Cancel & Apply buttons (right)
Filter Application Flow:
- Maintains pendingFilters state (unsaved user selections)
- appliedFilters prop drives the actual query
- onChange patches pending filters with new values
- On Apply: calls onApply(pendingFilters) then closes panel
- On Reset: clears all pending fi
…(truncated, 10683 more chars)