Project: workspace-doctolib · Branch: HEAD · Mode: ` · **Model:**claude-haiku-4-5-20251001`
Stats: 1 user messages, 37 tool calls, tools used: Bash, Read.
Conversation
Turn 1 — User
I need a comprehensive exploration of the National Health Records (NHR) document list filter implementation across two repositories. Please read ALL the following files and provide their full content:
/Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/- list all files recursively- Find and read the main component file:
NhrDocumentListModal.tsx(likely in/Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/) - Find and read
NhrEntryPoint.tsxin the same package - Find and read
useNhrDocumentListVariant(any hook file with this name in treatment-plan) - Read
/Users/USER/workspace/doctolib/doctolib/packages/@doctolib/national-health-records/src/hooks/useSearchDocuments.ts - Read the full
/Users/USER/workspace/doctolib/doctolib/packages/@doctolib/national-health-records/src/directory (list all files) - Find and read
PatientCard.tsxat/Users/USER/workspace/doctolib/doctolib/packages/@doctolib/shared_patient_file_and_appointment_page_components/src/desktop/PatientCard/PatientCard.tsx(around line 117) - Look for any mocked data files related to NHR documents in the national-health-records package
- Look for the
nhr_document_list_search_mockedfeature switch usage - Find and read any test files related to
searchDocumentsorNhrDocumentListModal
For each file, provide the FULL content. Be thorough - this is for planning purposes.
Turn 1 — Assistant
I'll help you explore the NHR document list filter implementation. Let me start by systematically gathering all the files you've requested.
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" 2>/dev/null | 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, 6815 more chars)
Let me continue gathering the files and get a complete list of the src directory:
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" \) 2>/dev/null
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, 18376 more chars)
Now let me look for the key files you mentioned and the doctolib package files. Let me read them in parallel:
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, 2194 more chars)
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, 1162 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 { 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, 1416 more chars)
Tools used:
Bash:find /Users/USER/workspace/doctolib/treatment-plan -name "*useNhrDocumentListVariant*" 2>/dev/null
Tool results:
→ result (ok): (Bash completed with no output)
Now let me search for the hook and doctolib files:
Tools used:
Bash:find /Users/USER/workspace/doctolib -path "*/national-health-records/src" -type d 2>/dev/null
Tool results:
→ result (ok): Command running in background with ID: bi6d8f4ji. Output is being written to: /private/tmp/claude-501/-Users-clertonra-workspace-doctolib/4e907511-941c-4735-b688-9b631a659fb5/tasks/bi6d8f4ji.output
Let me wait for that result and find the files more directly:
Tools used:
Bash:ls -la /Users/USER/workspace/doctolib/doctolib/packages/@doctolib/national-health-records/src/ 2>/dev/null | head -30
Tool results:
→ result (ok): drwxr-xr-x clertonra staff 256 B Wed Apr 8 16:08:29 2026 . drwxr-xr-x clertonra staff 352 B Mon Apr 13 15:34:16 2026 .. drwxr-xr-x clertonra staff 160 B Wed Apr 8 16:08:29 2026 business drwxr-xr-x clertonra staff 256 B Tue Apr 14 08:54:10 2026 hooks .rw-r--r-- clertonra staff 404 B Wed Apr 8 16:08:29 2026 index.ts drwxr-xr-x clertonra staff 128 B Thu Feb 26 14:08:52 2026 locales drwxr-xr-x clertonra staff 192 B Tue Apr 14 08:54:10 2026 mocks drwxr-xr-x clertonra staff 160 B Tue Apr 14 08:54:1 …(truncated, 15 more chars)
Good! Now let me get all the files from this directory and related ones:
Tools used:
Bash:find /Users/USER/workspace/doctolib/doctolib/packages/@doctolib/national-health-records/src -type f \( -name "*.ts" -o -name "*.tsx" -o -name "*.json" \) 2>/dev/null
Tools used:
Bash:find /Users/USER/workspace/doctolib/doctolib/packages/@doctolib/shared_patient_file_and_appointment_page_components/src -name "*PatientCard*" 2>/dev/null
Tool results:
→ result (ok): /Users/USER/workspace/doctolib/doctolib/packages/@doctolib/national-health-records/src/mocks/generateNhrDocuments.ts /Users/USER/workspace/doctolib/doctolib/packages/@doctolib/national-health-records/src/mocks/nhrMockedColumns.ts /Users/USER/workspace/doctolib/doctolib/packages/@doctolib/national-health-records/src/mocks/nhrMockedDocuments.ts /Users/USER/workspace/doctolib/doctolib/packages/@doctolib/national-health-records/src/mocks/generateNhrDocuments.test.ts /Users/USER/workspace/doctolib/do …(truncated, 2933 more chars)
Tool results:
→ result (ok): /Users/USER/workspace/doctolib/doctolib/packages/@doctolib/shared_patient_file_and_appointment_page_components/src/desktop/PatientCard /Users/USER/workspace/doctolib/doctolib/packages/@doctolib/shared_patient_file_and_appointment_page_components/src/desktop/PatientCard/PatientCard.test.tsx /Users/USER/workspace/doctolib/doctolib/packages/@doctolib/shared_patient_file_and_appointment_page_components/src/desktop/PatientCard/PatientCardIcons /Users/USER/workspace/doctolib/doctolib/packages/@doctoli …(truncated, 883 more chars)
Now let me read all the critical files. Let me start with multiple files in parallel:
Tools used:
Read:/Users/USER/workspace/doctolib/doctolib/packages/@doctolib/national-health-records/src/hooks/useSearchDocuments.ts
Tool results:
→ result (ok): 1 import { useQueryClient } from '@tanstack/react-query-v5' 2 import type { Patient } from 'monolith_DEPRECATED/types/doctor/api/Patient' 3 import { isFeatureEnabled } from '@doctolib/variation_management' 4 import type { NhrDocumentListVariant, MapFiltersToSearchDocumentsParams, ServerFilters } from '../variants/types' 5 import { useNationalHealthRecords } from './useNationalHealthRecords' 6 import { generateNhrDocuments } from '../mocks/generateNhrDocuments' 7 import { toNhrPatientInformation …(truncated, 2248 more chars)
Tools used:
Read:/Users/USER/workspace/doctolib/doctolib/packages/@doctolib/national-health-records/src/variants/useNhrDocumentListVariant.ts
Tool results:
→ result (ok): 1 import { useProductLineVariation, ProductLineKey } from '@doctolib/variation_management'
2 import type { DocumentSearchOptions, NhrDocumentListVariant } from './types'
3 import { useDmpDocumentListVariant } from './dmp'
4
5 export const useNhrDocumentListVariant = (patient: DocumentSearchOptions['patient']): NhrDocumentListVariant | null => {
6 const dmpVariant = useDmpDocumentListVariant(patient)
7
8 return useProductLineVariation<NhrDocumentListVariant>({
9 variants: {
10 [Pr
…(truncated, 389 more chars)
Tools used:
Read:/Users/USER/workspace/doctolib/doctolib/packages/@doctolib/national-health-records/src/variants/dmp/useDmpDocumentListVariant.ts
Tool results:
→ result (ok): 1 import { columnsFactory } from './factories/columnsFactory'
2 import { filtersFactory } from './factories/filtersFactory'
3 import type { NhrDocumentListVariant, DocumentSearchOptions } from '../types'
4 import useDmpSearchDocuments from '../../hooks/useSearchDocuments'
5 import { mapFiltersToSearchDocumentsParams } from './mappers/mapFiltersToSearchDocumentsParams'
6
7 export const useDmpDocumentListVariant = (patient: DocumentSearchOptions['patient']): NhrDocumentListVariant => {
8 const
…(truncated, 207 more chars)
Tools used:
Read:/Users/USER/workspace/doctolib/doctolib/packages/@doctolib/national-health-records/src/hooks/useSearchDocuments.test.ts
Tool results:
→ result (ok): 1 import React from 'react' 2 import { renderHook } from '@testing-library/react' 3 import { QueryClient, QueryClientProvider } from '@tanstack/react-query-v5' 4 import * as variationManagement from '@doctolib/variation_management' 5 import type { Patient } from 'monolith_DEPRECATED/types/doctor/api/Patient' 6 import type { NhrDocument, NhrDocumentSearchParams } from '@doctolib/tpf-national-health-records' 7 import { useNationalHealthRecords } from './useNationalHealthRecords' 8 import { generat …(truncated, 12586 more chars)
Now let me continue reading more files:
Tools used:
Read:/Users/USER/workspace/doctolib/doctolib/packages/@doctolib/national-health-records/src/variants/dmp/mappers/mapFiltersToSearchDocumentsParams.ts
Tool results:
→ result (ok): 1 import type { NhrDocumentSearchParams } from '@doctolib/tpf-national-health-records'
2 import { DOCUMENT_STATUS, DOCUMENT_VISIBILITY } from '@doctolib/dmp'
3 import type { ServerFilters } from '../../types'
4 import { toNhrPatientInformation } from '../../../business/mappers/toNhrPatientInformation'
5
6 // Maps UI-level ServerFilters to the NhrDocumentSearchParams format expected by the NHR API.
7 // Each ServerFilters field needs an explicit mapping — field names do not match NhrDocumentSear
…(truncated, 2415 more chars)
Tools used:
Read:/Users/USER/workspace/doctolib/doctolib/packages/@doctolib/national-health-records/src/mocks/generateNhrDocuments.ts
Tool results:
→ result (ok): 1 import type { NhrDocument } from '@doctolib/tpf-national-health-records'
2
3 import { nhrMockedDocuments } from './nhrMockedDocuments'
4
5 export type GenerateNhrDocumentsOptions = {
6 count?: number
7 randomize?: boolean
8 }
9
10 const DEFAULT_COUNT = 20
11 const RANDOM_COUNT_MAX = 40
12
13 const STATUSES = ['1', '2', '4', undefined] as const
14 const VISIBILITIES = ['1', '2', '4', '8', '10', '12', undefined] as const
15 const FORMATS = ['application/pdf', 'text/xml', 'application/dic
…(truncated, 3242 more chars)
Tools used:
Read:/Users/USER/workspace/doctolib/doctolib/packages/@doctolib/national-health-records/src/mocks/nhrMockedDocuments.ts
Tool results:
→ result (ERROR): File content (11228 tokens) exceeds maximum allowed tokens (10000). Use offset and limit parameters to read specific portions of the file, or search for specific content instead of reading the whole file.
Tools used:
Read:/Users/USER/workspace/doctolib/doctolib/packages/@doctolib/shared_patient_file_and_appointment_page_components/src/desktop/PatientCard/PatientCard.tsx
Tool results:
→ result (ok): 1 import PatientFileIcon from 'images/icons/patient-file-icon.svg?as-react-component' 2 import PatientAppointmentIcon from 'images/icons/patient-appointment-icon.svg?as-react-component' 3 import { type ComponentType, lazy, useContext, useMemo, Suspense } from 'react' 4 import classNames from 'classnames' 5 import AccountContext from 'monolith_DEPRECATED/contexts/doctor/AccountContext' 6 import INSiAutomaticCallContext from '@doctolib/financial_os_api/public/contexts/INSiAutomaticCallContext' 7 i …(truncated, 7405 more chars)
Let me read the mocked documents file with offset/limit:
Tools used:
Read:/Users/USER/workspace/doctolib/doctolib/packages/@doctolib/national-health-records/src/mocks/nhrMockedDocuments.ts(0–300)
Tool results:
→ result (ok): 0 import type { NhrDocument } from '@doctolib/tpf-national-health-records'
1
2 export const nhrMockedDocuments: NhrDocument[] = [
3 // ── Batch 1: Laboratory reports (6 docs) ──────────────────────────────────
4 {
5 id: 'mock-001',
6 title: 'SOPK hormone panel',
7 creationDate: '2025-01-13',
8 submissionDate: '2025-01-18',
9 status: '1',
10 visibility: '1',
11 format: 'application/pdf',
12 serviceInformation: { startDate: '2025-01-10' },
13 authors: [{ id
…(truncated, 11344 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, 3084 more chars)
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, 2157 more chars)
Tools used:
Read:/Users/USER/workspace/doctolib/doctolib/packages/@doctolib/national-health-records/src/variants/types.ts
Tool results:
→ result (ok): 1 import type { ColumnConfig, FilterConfig } from '@doctolib/tpf-national-health-records-ui'
2 import type { Patient } from 'monolith_DEPRECATED/types/doctor/api/Patient'
3 import type { NhrDocument, NhrDocumentSearchParams } from '@doctolib/tpf-national-health-records'
4
5 interface SearchDocumentsResult {
6 data: NhrDocument[]
7 total: number
8 }
9
10 export type NhrDocumentListVariant = {
11 columns: ColumnConfig[]
12 filters: FilterConfig[]
13 searchDocuments: (appliedFilters?: R
…(truncated, 791 more chars)
Now let me read more critical filter and factory files:
Tools used:
Read:/Users/USER/workspace/doctolib/doctolib/packages/@doctolib/national-health-records/src/variants/dmp/factories/filtersFactory.ts
Tool results:
→ result (ok): 1 import {
2 type FilterConfig,
3 createNhrDateSelectionFilterConfig,
4 createNhrDocumentCategoryFilterConfig,
5 createNhrDocumentStatusFilterConfig,
6 createNhrDocumentVisibilityFilterConfig,
7 } from '@doctolib/tpf-national-health-records-ui'
8
9 type FiltersOptions = {
10 lastAccessDate?: string
11 }
12
13 export function filtersFactory({ lastAccessDate = '' }: FiltersOptions = {}): FilterConfig[] {
14 return [
15 createNhrDocumentCategoryFilterConfig(),
16 createNhrDa
…(truncated, 1029 more chars)
Tools used:
Read:/Users/USER/workspace/doctolib/doctolib/packages/@doctolib/national-health-records/src/variants/dmp/factories/columnsFactory.ts
Tool results:
→ result (ok): 1 import type { ColumnConfig } from '@doctolib/tpf-national-health-records-ui' 2 import { 3 createNhrDocumentCategoryColumn, 4 createNhrDocumentNameColumn, 5 createNhrProcedureDateColumn, 6 createNhrShareDateColumn, 7 createNhrSharedByColumn, 8 createNhrStatusColumn, 9 createNhrVisibilityColumn, 10 } from '@doctolib/tpf-national-health-records-ui' 11 import { DOCUMENT_STATUS } from '@doctolib/dmp' 12 import { FileRegularIcon } from '@doctolib/design-system-icons/FileRegularIcon' 13 …(truncated, 1466 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, 192 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, 306 more chars)
Let me read more filter factory configurations:
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, 394 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, 158 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, 1328 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 { 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, 3859 more chars)
Let me read the visibility filter config and DMP helpers:
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, 337 more chars)
Tools used:
Read:/Users/USER/workspace/doctolib/doctolib/packages/@doctolib/national-health-records/src/variants/dmp/mappers/dmpDocumentHelpers.ts
Tool results:
→ result (ok): 1 import type { NhrDocument } from '@doctolib/tpf-national-health-records'
2 import type { NhrVisibilityEntry } from '@doctolib/tpf-national-health-records-ui'
3 import { DOCUMENT_STATUS, DOCUMENT_VISIBILITY } from '@doctolib/dmp'
4
5 const DMP_SYSTEM = 'dmp:classCode'
6 const PATIENT_CODE = '90' // EX_3.1-1040: class code for patient-authored documents
7
8 export const getTypeCode = (doc: NhrDocument): string | undefined =>
9 doc.classification?.codes.find((c) => c.system === DMP_SYSTEM)?.c
…(truncated, 1357 more chars)
Tools used:
Read:/Users/USER/workspace/doctolib/doctolib/packages/@doctolib/national-health-records/src/variants/dmp/factories/filtersFactory.test.ts
Tool results:
→ result (ok): 1 import { filtersFactory } from './filtersFactory'
2
3 describe('filtersFactory', () => {
4 it('should return exactly 4 FilterConfig objects', () => {
5 expect(filtersFactory()).toHaveLength(4)
6 })
7
8 it('should return filters with correct keys in order', () => {
9 expect(filtersFactory().map((f) => f.key)).toEqual(['typeCodes', 'dateMode', 'documentStatus', 'visibilityGroup'])
10 })
11 })
12
Tools used:
Read:/Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/components/NhrDocumentListModal/NhrDocumentListModal.test.tsx
Tool results:
→ result (ok): 1 import type { DesignSystemIconComponent } from '@doctolib/design-system-icons'
2 import { setup } from '@doctolib/test-helpers'
3 import { screen } from '@testing-library/react'
4 import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
5
6 import { mockColumns, mockPatientInfo } from '../../test-helpers'
7 import { nhrDocumentFixtureBuilder } from '../../test-helpers/fixtures/nhrDocumentFixtureBuilder'
8 import type { ActionConfig, FilterConfig } from '../../types'
9 import {
…(truncated, 6926 more chars)
Perfect! Now let me read a few more key mapper/factory files:
Tools used:
Read:/Users/USER/workspace/doctolib/doctolib/packages/@doctolib/national-health-records/src/variants/dmp/mappers/mapFiltersToSearchDocumentsParams.test.ts
Tool results:
→ result (ok): 1 import { mapFiltersToSearchDocumentsParams } from './mapFiltersToSearchDocumentsParams'
2
3 jest.mock('@doctolib/dmp', () => ({
4 DOCUMENT_STATUS: { validated: 1, obsolete: 2, archived: 4 },
5 DOCUMENT_VISIBILITY: {
6 sharedWithAll: 1,
7 notSharedWithPatient: 2,
8 notSharedWithPractitioner: 4,
9 notSharedWithLegalRepresentative: 8,
10 },
11 }))
12
13 jest.mock('../../../business/mappers/toNhrPatientInformation', () => ({
14 toNhrPatientInformation: (ins: string) => ({
…(truncated, 6530 more chars)
Tools used:
Read:/Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/components/NhrDocumentList/NhrDocumentList.test.tsx(0–200)
Tool results:
→ result (ok): 0 import type { NhrDocument } from '@doctolib/tpf-national-health-records'
1 import { render, screen } from '@testing-library/react'
2 // eslint-disable-next-line import/no-extraneous-dependencies, @doctolib-tpf/no-undeclared-dependencies
3 import { userEvent } from '@testing-library/user-event'
4 import { describe, expect, it, vi } from 'vitest'
5
6 import type { ColumnConfig, FilterConfig, NhrPatientInfo } from '../../types'
7 import { NhrDocumentList } from './NhrDocumentList'
8
9 // Mock c
…(truncated, 6219 more chars)
Tools used:
Read:/Users/USER/workspace/doctolib/doctolib/packages/@doctolib/national-health-records/src/hooks/useNationalHealthRecords.ts
Tool results:
→ result (ok): 1 import type { NhrDocumentSearchProps, NhrDocumentSearchResult } from '@doctolib/tpf-national-health-records'
2 import { useProductLineVariation, ProductLineKey } from '@doctolib/variation_management'
3 import type { Patient } from 'monolith_DEPRECATED/types/doctor/api/Patient'
4 import { useDmpNhr } from './useDmpNhr'
5
6 export type UseNhrOperations = {
7 searchDocuments: (props: NhrDocumentSearchProps) => Promise<NhrDocumentSearchResult>
8 }
9
10 export const useNationalHealthRecords = (
…(truncated, 597 more chars)
Excellent! Now I have a comprehensive understanding. Let me compile a summary document with all the key findings:
Comprehensive Exploration Report: NHR Document List Filter Implementation
I have completed a thorough exploration of the National Health Records (NHR) document list filter implementation across both repositories. Here is the full breakdown:
REPOSITORY STRUCTURE
Treatment Plan Repository (tpf-national-health-records-ui):
- Location: /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/
- Focus: UI components, filter factories, and shared business logic
- Key entry points: NhrDocumentListModal.tsx, NhrEntryPoint.tsx
Doctolib Monolith Repository (national-health-records):
- Location: /Users/USER/workspace/doctolib/doctolib/packages/@doctolib/national-health-records/src/
- Focus: Data hooks, variant factories, and DMP-specific mappers
- Key entry points: useSearchDocuments.ts, useNhrDocumentListVariant.ts, useDmpDocumentListVariant.ts
CORE ARCHITECTURE
Filter Data Flow (Complete Chain)
PatientCard (monolith)
↓
NhrEntryPoint (UI package)
↓
NhrDocumentListModal (opens with empty filters)
↓
NhrDocumentList (internal state or controlled by Modal)
↓
NhrDocumentListFilterPanel (renders filter config UI)
↓
Filter Factories (create individual filter controls)
↓
mapFiltersToSearchDocumentsParams (converts UI filters → server params)
↓
useSearchDocuments (executes query with mapped params)
↓
nhrOperations.searchDocuments (calls DMP API via useDmpNhr)
Key Data Structures
Server-side Filter Object (ServerFilters) - From /doctolib/packages/@doctolib/national-health-records/src/variants/types.ts:
type ServerFilters = {
typeCodes?: string[] // Document categories (LOINC codes)
dateType?: 'shareDate' | 'procedureDate' // Date filter type selector
submissionDateFrom?: string // Start date for range
submissionDateTo?: string // End date for range
includeArchived?: boolean // Status filter
includeObsolete?: boolean // Status filter
includeMaskedToProfessionals?: boolean // Visibility filter
includeInvisibleToPatient?: boolean // Visibility filter
includeInvisibleToLegalReps?: boolean // Visibility filter
}
CRITICAL FILE LOCATIONS & CONTENT SUMMARY
1. Modal & Entry Points (Treatment Plan)
NhrDocumentListModal.tsx (89 lines)
- Opens with useEffect that fetches documents on mount with empty filters
- State: { rows, total, isLoading } and appliedFilters
- Calls searchDocuments(appliedFilters) when filters change via onApplyFilters
- Wraps action handlers with loading state
NhrEntryPoint.tsx (56 lines)
- Checks eligibility: patient.show_ins_features and status === 'enabled'
- Manages modal open/close state
- Passes through all props (columns, filters, searchDocuments, actions)
2. Filter Panel & Components (Treatment Plan)
NhrDocumentListFilterPanel.tsx (125 lines)
- Renders filter UI in a side panel (400px wide)
- Local pending state that syncs with appliedFilters on open
- Three sections: Header (Filters title), Body (filter controls), Footer (Reset/Cancel/Apply)
- Filters rendered via config.render(pendingFilters, onChange, context)
- Footer buttons: Reset → clears, Cancel → closes, Apply → submits
Filter Factory Functions:
- createNhrDocumentCategoryFilterConfig() → BetaComboBox (single category select)
- createNhrDocumentStatusFilterConfig() → Checkbox group (Archived, Obsolete)
- createNhrDateSelectionFilterConfig() → Date range picker with type selector
- createNhrDocumentVisibilityFilterConfig() → Checkbox group (visibility modes)
3. Data Layer - Hooks (Doctolib)
useSearchDocuments.ts (61 lines)
- Feature flag check: isFeatureEnabled('nhr_document_list_search_mocked')
- If enabled: returns mocked documents from generateNhrDocuments()
- If disabled: checks patient has INS, maps filters, calls nhrOperations.searchDocuments()
- Caching: React Query with key ['dmp-documents', ins, appliedFilters]
- Retry logic: Max 3 retries, except for DMPAccessDeniedByExcededThreshold (fail immediately)
- Stale time: 5 minutes (close + reopen within 5 min = cache hit)
useNhrDocumentListVariant.ts (21 lines)
- Top-level hook for product line variation
- Returns dmpVariant for France, null for all other product lines
useDmpDocumentListVariant.ts (15 lines)
- Creates NhrDocumentListVariant object with:
- columns: columnsFactory()
- filters: filtersFactory()
- searchDocuments: useDmpSearchDocuments(...)
4. Filter Mapping - DMP Variant (Doctolib)
mapFiltersToSearchDocumentsParams.ts (65 lines)
- Maps UI ServerFilters → NhrDocumentSearchParams
- Category mapping: typeCodes → categories (direct pass-through)
- Date mapping:
- Default (no dateType or shareDate): → submissionDate object with { lowerLimit, upperLimit }
- procedureDate: → serviceStartDate object
- Status mapping: Bitwise OR composition of DOCUMENT_STATUS flags (1=validated, 2=obsolete, 4=archived)
- Visibility mapping: Bitwise OR composition of DOCUMENT_VISIBILITY flags
Comprehensive test file (157 lines) covers all mapping scenarios including: - Partial date ranges - Bitwise flag combinations - All filter types combined
5. Mocked Data
generateNhrDocuments.ts (101 lines)
- Returns 20 documents by default (from static nhrMockedDocuments array)
- Supports randomization with count and randomize options
- Options: { count?: number, randomize?: boolean }
nhrMockedDocuments.ts (300+ lines)
- 23 hand-crafted documents in 5 batches:
- Laboratory reports (6 docs)
- Imaging (6 docs)
- Consultation reports (6 docs)
- Prescriptions (5 docs)
- Discharge summaries (5 docs)
- Each document has full schema: id, title, dates, status, visibility, format, authors, classification
6. Column Factories (Doctolib)
columnsFactory.ts (62 lines)
- Creates 7 columns: Category, Name, Procedure Date, Share Date, Shared By, Status, Visibility
- Uses helper functions like getTypeCode(), getProcedureDate(), getVisibilityEntries()
columnsFactory.test.ts (11 lines)
- Verifies 4 filters are returned in correct order: ['typeCodes', 'dateMode', 'documentStatus', 'visibilityGroup']
7. Filter Factories (Doctolib)
filtersFactory.ts (45 lines)
- Returns 4 filters in order:
1. Category (combo box)
2. Date (date range + type selector)
3. Status (checkboxes: Archived, Obsolete)
4. Visibility (checkboxes: 3 modes)
INTEGRATION POINTS
PatientCard.tsx (monolith, line 114+):
- Checks: isFeatureEnabled('nhr_document_list') AND nhrVariant !== null
- Lazy-loads NhrEntryPointModule from treatment-plan package
- Builds actions via actionsBuilder.createViewDocumentAction() and .createMoreActionsAction()
- Passes: columns, filters, searchDocuments from nhrVariant
Key Filter Count (in header):
- Calculated as: Object.values(appliedFilters).filter(Boolean).length
- Counts truthy values (not undefined, null, false, 0, etc.)
TEST FILES
-
useSearchDocuments.test.ts(319 lines) - Cache behavior tests (cache hits on repeated calls) - Retry logic (no retry on DMPAccessDeniedByExcededThreshold) - Mocking feature flag enabled/disabled - Patient INS validation -
mapFiltersToSearchDocumentsParams.test.ts(157 lines) - All mapping scenarios (categories, dates, status, visibility) - Partial date ranges - Bitwise flag compositions -
filtersFactory.test.ts(11 lines) - Verifies 4 filters returned with correct keys -
NhrDocumentListModal.test.tsx(191 lines) …(truncated, 2488 more chars)