@digihmis/esm-outpatient-app 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (116) hide show
  1. package/README.md +4 -0
  2. package/dist/117.js +1 -0
  3. package/dist/117.js.map +1 -0
  4. package/dist/132.js +1 -0
  5. package/dist/132.js.map +1 -0
  6. package/dist/152.js +1 -0
  7. package/dist/152.js.map +1 -0
  8. package/dist/209.js +1 -0
  9. package/dist/209.js.map +1 -0
  10. package/dist/317.js +1 -0
  11. package/dist/317.js.map +1 -0
  12. package/dist/349.js +1 -0
  13. package/dist/349.js.map +1 -0
  14. package/dist/371.js +1 -0
  15. package/dist/371.js.map +1 -0
  16. package/dist/378.js +1 -0
  17. package/dist/378.js.map +1 -0
  18. package/dist/395.js +12 -0
  19. package/dist/395.js.map +1 -0
  20. package/dist/442.js +1 -0
  21. package/dist/442.js.map +1 -0
  22. package/dist/45.js +1 -0
  23. package/dist/45.js.map +1 -0
  24. package/dist/466.js +1 -0
  25. package/dist/466.js.map +1 -0
  26. package/dist/508.js +1 -0
  27. package/dist/508.js.map +1 -0
  28. package/dist/564.js +1 -0
  29. package/dist/564.js.map +1 -0
  30. package/dist/61.js +1 -0
  31. package/dist/61.js.map +1 -0
  32. package/dist/640.js +1 -0
  33. package/dist/640.js.map +1 -0
  34. package/dist/689.js +1 -0
  35. package/dist/689.js.map +1 -0
  36. package/dist/709.js +1 -0
  37. package/dist/709.js.map +1 -0
  38. package/dist/712.js +1 -0
  39. package/dist/712.js.map +1 -0
  40. package/dist/720.js +1 -0
  41. package/dist/720.js.map +1 -0
  42. package/dist/742.js +1 -0
  43. package/dist/742.js.map +1 -0
  44. package/dist/759.js +15 -0
  45. package/dist/759.js.map +1 -0
  46. package/dist/771.js +1 -0
  47. package/dist/771.js.map +1 -0
  48. package/dist/797.js +1 -0
  49. package/dist/797.js.map +1 -0
  50. package/dist/806.js +1 -0
  51. package/dist/806.js.map +1 -0
  52. package/dist/912.js +1 -0
  53. package/dist/912.js.map +1 -0
  54. package/dist/913.js +1 -0
  55. package/dist/913.js.map +1 -0
  56. package/dist/940.js +1 -0
  57. package/dist/940.js.map +1 -0
  58. package/dist/974.js +1 -0
  59. package/dist/974.js.map +1 -0
  60. package/dist/digihmis-esm-outpatient-app.js +6 -0
  61. package/dist/digihmis-esm-outpatient-app.js.buildmanifest.json +827 -0
  62. package/dist/digihmis-esm-outpatient-app.js.map +1 -0
  63. package/dist/main.js +17 -0
  64. package/dist/main.js.map +1 -0
  65. package/dist/routes.json +1 -0
  66. package/jest.config.js +26 -0
  67. package/package.json +51 -0
  68. package/rspack.config.js +1 -0
  69. package/src/config-schema.ts +347 -0
  70. package/src/dashboard.meta.ts +16 -0
  71. package/src/declarations.d.ts +6 -0
  72. package/src/icon-wrapper/icon-wrapper.extension.tsx +17 -0
  73. package/src/index.ts +27 -0
  74. package/src/left-panel/left-panel.component.tsx +100 -0
  75. package/src/left-panel/left-panel.scss +13 -0
  76. package/src/main-dashboard/outpatient-dashboard.component.tsx +264 -0
  77. package/src/main-dashboard/outpatient-dashboard.resource.ts +71 -0
  78. package/src/main-dashboard/outpatient-dashboard.scss +166 -0
  79. package/src/main-dashboard/type/index.ts +162 -0
  80. package/src/page-header/page-header.component.tsx +35 -0
  81. package/src/page-header/page-header.scss +76 -0
  82. package/src/patient-management/components/auto-suggest/autosuggest.component.tsx +149 -0
  83. package/src/patient-management/components/auto-suggest/autosuggest.scss +61 -0
  84. package/src/patient-management/components/auto-suggest/diagnosis-autosuggest.component.tsx +131 -0
  85. package/src/patient-management/components/auto-suggest/diagnosis-autosuggest.scss +42 -0
  86. package/src/patient-management/patient-banner/patient-banner.component.tsx +60 -0
  87. package/src/patient-management/patient-banner/patient-banner.scss +72 -0
  88. package/src/patient-management/patient-management-workspace/billable-services-selector.component.tsx +150 -0
  89. package/src/patient-management/patient-management-workspace/patient-management-schema/index.ts +261 -0
  90. package/src/patient-management/patient-management-workspace/patient-management-workspace.scss +304 -0
  91. package/src/patient-management/patient-management-workspace/patient-management-workspace.tsx +1581 -0
  92. package/src/patient-management/patient-management-workspace/patient-management.resource.ts +182 -0
  93. package/src/patient-management/patient-management-workspace/type/index.ts +193 -0
  94. package/src/patient-management/patient-management-workspace/utils/index.ts +172 -0
  95. package/src/patient-management/patient-management.component.tsx +97 -0
  96. package/src/patient-management/patient-management.scss +30 -0
  97. package/src/patient-management/utils/index.ts +5 -0
  98. package/src/queue-room-table/queue-room-table.component.tsx +313 -0
  99. package/src/queue-room-table/queue-room-table.resource.ts +73 -0
  100. package/src/queue-room-table/queue-room-table.scss +193 -0
  101. package/src/queue-room-table/type/index.ts +34 -0
  102. package/src/queue-room-table/useQueueActions.ts +24 -0
  103. package/src/routes.json +55 -0
  104. package/src/setup-tests.ts +1 -0
  105. package/translations/am.json +57 -0
  106. package/translations/ar.json +57 -0
  107. package/translations/en.json +57 -0
  108. package/translations/es.json +57 -0
  109. package/translations/fr.json +57 -0
  110. package/translations/he.json +57 -0
  111. package/translations/km.json +57 -0
  112. package/translations/pt.json +57 -0
  113. package/translations/sw.json +57 -0
  114. package/translations/vi.json +57 -0
  115. package/translations/zh.json +57 -0
  116. package/tsconfig.json +5 -0
@@ -0,0 +1,150 @@
1
+ import React from 'react';
2
+ import { useTranslation } from 'react-i18next';
3
+ import { Control, Controller } from 'react-hook-form';
4
+ import { Stack, Tag, Layer, FilterableMultiSelect, InlineNotification, InlineLoading } from '@carbon/react';
5
+ import { useCurrencyFormatting } from './utils';
6
+ import type { TransformedBillableItem, PaymentInfo } from './type';
7
+ import type { ClinicalEncounterFormData } from './patient-management-schema';
8
+ import styles from './patient-management-workspace.scss';
9
+
10
+ interface BillableServicesSelectorProps {
11
+ control: Control<ClinicalEncounterFormData>;
12
+ fieldName: 'procedures' | 'labTests' | 'imagingTests';
13
+ lineItems: Array<TransformedBillableItem>;
14
+ isLoading: boolean;
15
+ paymentInfo: PaymentInfo;
16
+ title: string;
17
+ searchPlaceholder: string;
18
+ errors?: {
19
+ message?: string;
20
+ };
21
+ }
22
+
23
+ export const BillableServicesSelector: React.FC<BillableServicesSelectorProps> = ({
24
+ control,
25
+ fieldName,
26
+ lineItems,
27
+ isLoading,
28
+ paymentInfo,
29
+ title,
30
+ searchPlaceholder,
31
+ errors,
32
+ }) => {
33
+ const { t } = useTranslation();
34
+ const { formatSimple } = useCurrencyFormatting();
35
+
36
+ return (
37
+ <Stack gap={5}>
38
+ <Controller
39
+ name={fieldName}
40
+ control={control}
41
+ render={({ field }) => {
42
+ const selectedServices = field.value || [];
43
+
44
+ return (
45
+ <>
46
+ {/* Show selected services as tags with prices */}
47
+ {selectedServices.length > 0 && (
48
+ <div className={styles.selectedProceduresContainer}>
49
+ <div className={styles.selectedProceduresTags}>
50
+ {selectedServices.map((item: TransformedBillableItem, index: number) => {
51
+ const price =
52
+ typeof item.price === 'number'
53
+ ? item.price
54
+ : typeof item.price === 'string'
55
+ ? parseFloat(item.price)
56
+ : 0;
57
+ const displayText = `${item.name || item.text} - ${formatSimple(price, {
58
+ minimumFractionDigits: 2,
59
+ maximumFractionDigits: 2,
60
+ })}`;
61
+
62
+ return (
63
+ <Tag
64
+ key={`${item.id}-${index}`}
65
+ type="cyan"
66
+ filter
67
+ onClose={() => {
68
+ const updated = selectedServices.filter(
69
+ (_: TransformedBillableItem, i: number) => i !== index,
70
+ );
71
+ field.onChange(updated);
72
+ }}
73
+ className={styles.selectedProcedureTag}>
74
+ {displayText}
75
+ </Tag>
76
+ );
77
+ })}
78
+ </div>
79
+ </div>
80
+ )}
81
+
82
+ {/* FilterableMultiSelect */}
83
+ {isLoading ? (
84
+ <InlineLoading description={t('loadingServices', 'Loading services...')} />
85
+ ) : lineItems && lineItems.length > 0 ? (
86
+ <Layer>
87
+ <div>
88
+ {(() => {
89
+ const selectedIds = new Set(
90
+ selectedServices.map((svc: TransformedBillableItem) => svc.id || svc.conceptUuid),
91
+ );
92
+
93
+ const selectedDropdownItems = lineItems.filter((option) => {
94
+ const isSelected = selectedIds.has(option.id);
95
+ return isSelected;
96
+ });
97
+
98
+ return (
99
+ <FilterableMultiSelect
100
+ key={`${fieldName}-multiselect`}
101
+ id={`${fieldName}-select`}
102
+ className={styles.symptomsMultiSelect}
103
+ titleText={title}
104
+ placeholder={searchPlaceholder}
105
+ items={lineItems}
106
+ itemToString={(item: TransformedBillableItem | null | undefined) =>
107
+ item ? item.name || item.text : ''
108
+ }
109
+ compareItems={(item1: TransformedBillableItem, item2: TransformedBillableItem) => {
110
+ const result = item1?.id === item2?.id;
111
+ return result;
112
+ }}
113
+ selectedItems={selectedDropdownItems}
114
+ onChange={({ selectedItems }: { selectedItems: TransformedBillableItem[] }) => {
115
+ const servicesWithDetails: TransformedBillableItem[] = selectedItems.map((item) => ({
116
+ id: item.id,
117
+ text: item.name,
118
+ name: item.name,
119
+ price: item.price,
120
+ paymentModeUuid: item.paymentModeUuid,
121
+ paymentModeName: item.paymentModeName,
122
+ billableServiceUuid: item.billableServiceUuid,
123
+ conceptUuid: item.conceptUuid,
124
+ priceUuid: item.priceUuid,
125
+ }));
126
+ field.onChange(servicesWithDetails);
127
+ }}
128
+ invalid={!!errors}
129
+ invalidText={errors?.message}
130
+ />
131
+ );
132
+ })()}
133
+ </div>
134
+ </Layer>
135
+ ) : (
136
+ <InlineNotification
137
+ kind="warning"
138
+ lowContrast
139
+ hideCloseButton
140
+ title={t('noBillableServices', 'No billable services')}
141
+ subtitle={t('noBillableServicesDescription', 'Please configure billable services to continue.')}
142
+ />
143
+ )}
144
+ </>
145
+ );
146
+ }}
147
+ />
148
+ </Stack>
149
+ );
150
+ };
@@ -0,0 +1,261 @@
1
+ // patient-management-schema.ts
2
+
3
+ import { z } from 'zod';
4
+
5
+ export const OTHER_SYMPTOM_UUID = '5622AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
6
+ export const YES_ANSWER_UUID = '1065AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
7
+ export const SURGICAL_HISTORY_UUID = '1651AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
8
+ export const ADMISSION_HISTORY_UUID = '165644AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
9
+ export const OTHER_PAST_ILLNESS_UUID = '5622AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
10
+
11
+ // General Examination UUIDs
12
+ export const ABNORMAL_GAIT_UUID = '5108AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
13
+ export const JAUNDICE_UUID = '136443AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
14
+ export const CYANOSIS_UUID = '143050AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
15
+ export const DEHYDRATION_UUID = '142630AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
16
+ export const FINGER_CLUBBING_UUID = '140125AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
17
+ export const OEDEMA_UUID = '460AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
18
+ export const PALLOR_UUID = '5245AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
19
+ export const LYMPHADENOPATHY_UUID = '135488AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
20
+
21
+ // Generic item schema (for symptoms, past illness, etc.)
22
+ const genericItemSchema = z.object({
23
+ id: z.string(),
24
+ text: z.string(),
25
+ });
26
+
27
+ // Schema for billable services with full billing details
28
+ const genericItemWithBillingSchema = z.object({
29
+ id: z.string(),
30
+ text: z.string(),
31
+ name: z.string(),
32
+ price: z.number(),
33
+ paymentModeUuid: z.string(),
34
+ paymentModeName: z.string(),
35
+ billableServiceUuid: z.string(),
36
+ conceptUuid: z.string(),
37
+ priceUuid: z.string(),
38
+ });
39
+
40
+ export const BaseClinicalEncounterSchema = z.object({
41
+ // Section 0: Symptoms
42
+ symptoms: z.array(genericItemSchema).min(1, 'Please select at least one symptom'),
43
+ onsetStatus: z.string().optional(),
44
+ tbContact: z.string().optional(),
45
+ otherSymptomText: z.string().optional(),
46
+
47
+ // Section 1: History of present illness
48
+ pastIllness: z.array(genericItemSchema).optional().default([]),
49
+ surgeryDetails: z.string().optional(),
50
+ admissionReason: z.string().optional(),
51
+ otherPastIllnessText: z.string().optional(),
52
+ medicationsTaken: z.string().optional(),
53
+ medicationDetails: z.string().optional(),
54
+
55
+ // Section 2: Physical Examination - General Examination
56
+ generalExamination: z.array(genericItemSchema).optional().default([]),
57
+ generalExaminationNotes: z.string().optional(),
58
+
59
+ // Gait (when Abnormal Gait is selected)
60
+ gaitFinding: z.string().optional(),
61
+
62
+ // Jaundice (when Jaundice is selected)
63
+ jaundiceGrading: z.string().optional(),
64
+
65
+ // Cyanosis (when Cyanosis is selected)
66
+ cyanosisType: z.string().optional(),
67
+
68
+ // Dehydration (when Dehydration is selected)
69
+ dehydrationType: z.array(genericItemSchema).optional().default([]),
70
+
71
+ // Finger Clubbing (when Finger Clubbing is selected)
72
+ fingerclubGrading: z.string().optional(),
73
+
74
+ // Oedema (when Oedema is selected)
75
+ oedemaLocation: z.array(genericItemSchema).optional().default([]),
76
+ oedemaType: z.string().optional(),
77
+ oedemaGrading: z.string().optional(),
78
+
79
+ // Pallor (when Pallor is selected)
80
+ pallorLocation: z.array(genericItemSchema).optional().default([]),
81
+ pallorGrading: z.string().optional(),
82
+
83
+ // Lymphadenopathy (when Lymphadenopathy is selected)
84
+ siteLymphadenopathy: z.array(genericItemSchema).optional().default([]),
85
+
86
+ // Section 3: Diagnosis
87
+ primaryDiagnosis: z.array(genericItemSchema).optional().default([]),
88
+ secondaryDiagnosis: z.array(genericItemSchema).optional().default([]),
89
+ diagnosisNotes: z.string().optional(),
90
+
91
+ // Section 4: Procedures with billing details
92
+ procedures: z.array(genericItemWithBillingSchema).optional().default([]),
93
+
94
+ // Section 5: Laboratory tests with billing details
95
+ labTests: z.array(genericItemWithBillingSchema).optional().default([]),
96
+
97
+ // Section 6: Imaging tests with billing details
98
+ imagingTests: z.array(genericItemWithBillingSchema).optional().default([]),
99
+
100
+ // Section 7: Notes/Instructions
101
+ notes: z.string().optional(),
102
+
103
+ // Section 8: Outcome
104
+ patientOutcome: z.string().optional(),
105
+ });
106
+
107
+ export const ClinicalEncounterSchema = BaseClinicalEncounterSchema.superRefine((data, ctx) => {
108
+ // Section 0 validations
109
+ const hasOtherSymptom = data.symptoms.some((s) => s.id === OTHER_SYMPTOM_UUID);
110
+ if (hasOtherSymptom && (!data.otherSymptomText || data.otherSymptomText.trim().length === 0)) {
111
+ ctx.addIssue({
112
+ code: z.ZodIssueCode.custom,
113
+ message: 'This field is required when "Other" symptom is selected',
114
+ path: ['otherSymptomText'],
115
+ });
116
+ }
117
+
118
+ // Section 1 validations
119
+ const hasSurgicalHistory = data.pastIllness?.some((p) => p.id === SURGICAL_HISTORY_UUID);
120
+ if (hasSurgicalHistory && (!data.surgeryDetails || data.surgeryDetails.trim().length === 0)) {
121
+ ctx.addIssue({
122
+ code: z.ZodIssueCode.custom,
123
+ message: 'Surgery details are required when Surgical History is selected',
124
+ path: ['surgeryDetails'],
125
+ });
126
+ }
127
+
128
+ const hasAdmissionHistory = data.pastIllness?.some((p) => p.id === ADMISSION_HISTORY_UUID);
129
+ if (hasAdmissionHistory && (!data.admissionReason || data.admissionReason.trim().length === 0)) {
130
+ ctx.addIssue({
131
+ code: z.ZodIssueCode.custom,
132
+ message: 'Reason for admission is required when Admission History is selected',
133
+ path: ['admissionReason'],
134
+ });
135
+ }
136
+
137
+ const hasOtherPastIllness = data.pastIllness?.some((p) => p.id === OTHER_PAST_ILLNESS_UUID);
138
+ if (hasOtherPastIllness && (!data.otherPastIllnessText || data.otherPastIllnessText.trim().length === 0)) {
139
+ ctx.addIssue({
140
+ code: z.ZodIssueCode.custom,
141
+ message: 'Please specify the other illness',
142
+ path: ['otherPastIllnessText'],
143
+ });
144
+ }
145
+
146
+ if (
147
+ data.medicationsTaken === YES_ANSWER_UUID &&
148
+ (!data.medicationDetails || data.medicationDetails.trim().length === 0)
149
+ ) {
150
+ ctx.addIssue({
151
+ code: z.ZodIssueCode.custom,
152
+ message: 'Please provide details of medications taken',
153
+ path: ['medicationDetails'],
154
+ });
155
+ }
156
+
157
+ // Section 2: Physical Examination validations
158
+ const hasAbnormalGait = data.generalExamination?.some((e) => e.id === ABNORMAL_GAIT_UUID);
159
+ if (hasAbnormalGait && !data.gaitFinding) {
160
+ ctx.addIssue({
161
+ code: z.ZodIssueCode.custom,
162
+ message: 'Please specify the gait finding',
163
+ path: ['gaitFinding'],
164
+ });
165
+ }
166
+
167
+ const hasJaundice = data.generalExamination?.some((e) => e.id === JAUNDICE_UUID);
168
+ if (hasJaundice && !data.jaundiceGrading) {
169
+ ctx.addIssue({
170
+ code: z.ZodIssueCode.custom,
171
+ message: 'Please specify the jaundice grading',
172
+ path: ['jaundiceGrading'],
173
+ });
174
+ }
175
+
176
+ const hasCyanosis = data.generalExamination?.some((e) => e.id === CYANOSIS_UUID);
177
+ if (hasCyanosis && !data.cyanosisType) {
178
+ ctx.addIssue({
179
+ code: z.ZodIssueCode.custom,
180
+ message: 'Please specify the cyanosis type',
181
+ path: ['cyanosisType'],
182
+ });
183
+ }
184
+
185
+ const hasDehydration = data.generalExamination?.some((e) => e.id === DEHYDRATION_UUID);
186
+ if (hasDehydration && (!data.dehydrationType || data.dehydrationType.length === 0)) {
187
+ ctx.addIssue({
188
+ code: z.ZodIssueCode.custom,
189
+ message: 'Please specify the dehydration type',
190
+ path: ['dehydrationType'],
191
+ });
192
+ }
193
+
194
+ const hasFingerClubbing = data.generalExamination?.some((e) => e.id === FINGER_CLUBBING_UUID);
195
+ if (hasFingerClubbing && !data.fingerclubGrading) {
196
+ ctx.addIssue({
197
+ code: z.ZodIssueCode.custom,
198
+ message: 'Please specify the finger clubbing grading',
199
+ path: ['fingerclubGrading'],
200
+ });
201
+ }
202
+
203
+ const hasOedema = data.generalExamination?.some((e) => e.id === OEDEMA_UUID);
204
+ if (hasOedema) {
205
+ if (!data.oedemaLocation || data.oedemaLocation.length === 0) {
206
+ ctx.addIssue({
207
+ code: z.ZodIssueCode.custom,
208
+ message: 'Please specify the oedema location',
209
+ path: ['oedemaLocation'],
210
+ });
211
+ }
212
+ if (!data.oedemaType) {
213
+ ctx.addIssue({
214
+ code: z.ZodIssueCode.custom,
215
+ message: 'Please specify the oedema type',
216
+ path: ['oedemaType'],
217
+ });
218
+ }
219
+ if (!data.oedemaGrading) {
220
+ ctx.addIssue({
221
+ code: z.ZodIssueCode.custom,
222
+ message: 'Please specify the oedema grading',
223
+ path: ['oedemaGrading'],
224
+ });
225
+ }
226
+ }
227
+
228
+ const hasPallor = data.generalExamination?.some((e) => e.id === PALLOR_UUID);
229
+ if (hasPallor) {
230
+ if (!data.pallorLocation || data.pallorLocation.length === 0) {
231
+ ctx.addIssue({
232
+ code: z.ZodIssueCode.custom,
233
+ message: 'Please specify the pallor location',
234
+ path: ['pallorLocation'],
235
+ });
236
+ }
237
+ if (!data.pallorGrading) {
238
+ ctx.addIssue({
239
+ code: z.ZodIssueCode.custom,
240
+ message: 'Please specify the pallor grading',
241
+ path: ['pallorGrading'],
242
+ });
243
+ }
244
+ }
245
+
246
+ const hasLymphadenopathy = data.generalExamination?.some((e) => e.id === LYMPHADENOPATHY_UUID);
247
+ if (hasLymphadenopathy && (!data.siteLymphadenopathy || data.siteLymphadenopathy.length === 0)) {
248
+ ctx.addIssue({
249
+ code: z.ZodIssueCode.custom,
250
+ message: 'Please specify the lymphadenopathy site',
251
+ path: ['siteLymphadenopathy'],
252
+ });
253
+ }
254
+ });
255
+
256
+ // Export types
257
+ export type ClinicalEncounterFormData = z.infer<typeof BaseClinicalEncounterSchema>;
258
+ export type GenericItem = z.infer<typeof genericItemSchema>;
259
+ export type ProcedureWithBilling = z.infer<typeof genericItemWithBillingSchema>;
260
+
261
+ export type TransformedBillableItem = ProcedureWithBilling;
@@ -0,0 +1,304 @@
1
+ @use '@carbon/colors';
2
+ @use '@carbon/layout';
3
+ @use '@carbon/type';
4
+ @use '@openmrs/esm-styleguide/src/vars' as *;
5
+
6
+ .container {
7
+ margin: layout.$spacing-05;
8
+
9
+ & section {
10
+ margin: layout.$spacing-05 0 layout.$spacing-03;
11
+
12
+ &:first-of-type {
13
+ margin-top: 0;
14
+ }
15
+
16
+ &:last-of-type {
17
+ margin-bottom: 0;
18
+ }
19
+ }
20
+ }
21
+
22
+ .heading {
23
+ @include type.type-style('heading-03');
24
+ margin: layout.$spacing-05;
25
+ }
26
+
27
+ .sectionTitle {
28
+ @include type.type-style('heading-compact-02');
29
+ color: colors.$gray-70;
30
+ margin: 0 0 layout.$spacing-03 0;
31
+
32
+ &:after {
33
+ content: '';
34
+ display: block;
35
+ width: layout.$spacing-07;
36
+ padding-top: 3px;
37
+ border-bottom: 0.375rem solid;
38
+ @include brand-03(border-bottom-color);
39
+ }
40
+ }
41
+
42
+ .dateTimeSection {
43
+ display: flex;
44
+ margin: layout.$spacing-05 0;
45
+ align-items: center;
46
+ }
47
+
48
+ .radioButton {
49
+ margin: layout.$spacing-05 0;
50
+ }
51
+
52
+ .headerGridRow {
53
+ border-bottom: 0.0625rem solid colors.$gray-20;
54
+ margin: 0;
55
+ }
56
+
57
+ .dataGridRow {
58
+ display: grid;
59
+ grid-template-columns: 50% 10% 1fr;
60
+ margin: layout.$spacing-03 layout.$spacing-05;
61
+ }
62
+
63
+ .form {
64
+ display: flex;
65
+ flex-direction: column;
66
+ justify-content: start;
67
+ height: 100%;
68
+ }
69
+
70
+ .patientHeader {
71
+ padding: layout.$spacing-05;
72
+ border-bottom: 1px solid colors.$gray-20;
73
+ background-color: colors.$gray-10;
74
+ flex-shrink: 0;
75
+
76
+ .patientName {
77
+ @include type.type-style('heading-compact-01');
78
+ font-weight: 600;
79
+ margin-right: layout.$spacing-03;
80
+ }
81
+
82
+ .patientId {
83
+ @include type.type-style('body-compact-01');
84
+ font-weight: 600;
85
+ margin-right: layout.$spacing-02;
86
+ }
87
+
88
+ .patientDetails {
89
+ @include type.type-style('body-compact-01');
90
+ color: colors.$gray-70;
91
+ }
92
+ }
93
+
94
+ .buttonSet {
95
+ width: 100%;
96
+ display: flex;
97
+
98
+ button {
99
+ max-width: none;
100
+ width: 100%;
101
+ }
102
+ }
103
+
104
+ .button {
105
+ min-width: 50%;
106
+ }
107
+
108
+ .tablet {
109
+ padding: layout.$spacing-06 layout.$spacing-05;
110
+ background-color: white;
111
+ }
112
+
113
+ .desktop {
114
+ padding: 0;
115
+ }
116
+
117
+ .inputRow {
118
+ display: grid;
119
+ grid-template-columns: 1fr 1fr;
120
+ gap: layout.$spacing-05;
121
+
122
+ :global(.omrs-breakpoint-lt-tablet) & {
123
+ grid-template-columns: 1fr;
124
+ }
125
+ }
126
+
127
+ .dateTimeSection {
128
+ :global(.omrs-breakpoint-lt-tablet) & {
129
+ flex-direction: column;
130
+ }
131
+ }
132
+
133
+ .inlineNotification {
134
+ width: 100%;
135
+ max-width: unset;
136
+ padding: '0';
137
+ }
138
+
139
+ .label {
140
+ @include type.type-style('label-01');
141
+ color: colors.$gray-70;
142
+ }
143
+
144
+ .workspaceWrapper {
145
+ display: flex;
146
+ flex-direction: column;
147
+ height: 100%;
148
+ }
149
+
150
+ .workspaceContainer {
151
+ display: flex;
152
+ flex: 1;
153
+ min-height: 0;
154
+ }
155
+
156
+ .sidebar {
157
+ width: 220px;
158
+ min-width: 220px;
159
+ background-color: #f4f4f4;
160
+ border-right: 1px solid #e0e0e0;
161
+ overflow-y: auto;
162
+ }
163
+
164
+ .sidebarContent {
165
+ display: flex;
166
+ flex-direction: column;
167
+ flex: 1;
168
+ overflow-y: auto;
169
+ }
170
+
171
+ :global(.cds--tree-node__label) {
172
+ padding-inline-start: 0.5rem !important;
173
+ }
174
+
175
+ :global(.cds--tree-node--active > .cds--tree-node__label:before) {
176
+ background-color: var(--cds-interactive, #4a90b8);
177
+ }
178
+
179
+ .sectionButton {
180
+ padding: 0.75rem 1rem;
181
+ text-align: left;
182
+ background: transparent;
183
+ border: none;
184
+ border-left: 3px solid transparent;
185
+ cursor: pointer;
186
+ font-size: 0.875rem;
187
+ color: #525252;
188
+ transition: all 0.2s ease;
189
+ margin-bottom: 0.25rem;
190
+
191
+ &:hover {
192
+ background-color: #e0e0e0;
193
+ }
194
+
195
+ &.active {
196
+ border-left-color: #0f62fe;
197
+ background-color: #ffffff;
198
+ font-weight: 600;
199
+ color: #161616;
200
+ }
201
+ }
202
+
203
+ .mainContent {
204
+ flex: 1;
205
+ display: flex;
206
+ flex-direction: column;
207
+ background-color: #ffffff;
208
+ min-height: 0;
209
+ }
210
+
211
+ .formWrapper {
212
+ display: flex;
213
+ flex-direction: column;
214
+ height: 100%;
215
+ }
216
+
217
+ .formContent {
218
+ flex: 1;
219
+ padding: 1.5rem;
220
+ overflow-y: auto;
221
+ min-height: 0;
222
+ }
223
+
224
+ .navigationButtons {
225
+ border-top: 1px solid colors.$gray-20;
226
+ padding: layout.$spacing-05;
227
+ background-color: colors.$white;
228
+ flex-shrink: 0;
229
+ }
230
+
231
+ @media (max-width: 768px) {
232
+ .workspaceContainer {
233
+ flex-direction: column;
234
+ }
235
+
236
+ .sidebar {
237
+ width: 100%;
238
+ border-right: none;
239
+ border-bottom: 1px solid #e0e0e0;
240
+ }
241
+
242
+ .sidebarContent {
243
+ flex-direction: row;
244
+ overflow-x: auto;
245
+ }
246
+
247
+ .sectionButton {
248
+ white-space: nowrap;
249
+ }
250
+
251
+ .navigationButtons {
252
+ padding: layout.$spacing-04;
253
+ }
254
+
255
+ .buttonSet {
256
+ button {
257
+ flex: 1;
258
+ }
259
+ }
260
+ }
261
+
262
+ .symptomsMultiSelect {
263
+ padding-top: 0.5rem;
264
+ }
265
+
266
+ .selectedSymptomTag {
267
+ margin-right: 0.5rem;
268
+ }
269
+
270
+ .selectedSymptomsContainer {
271
+ width: 100%;
272
+ }
273
+
274
+ .selectedSymptomsTags {
275
+ display: flex;
276
+ flex-wrap: wrap;
277
+ gap: 0.5rem;
278
+ margin-bottom: 1rem;
279
+ }
280
+ .radioButtonGroup {
281
+ padding-top: 1rem;
282
+ }
283
+ .textAreaInput {
284
+ padding-top: 1rem;
285
+ }
286
+ .radioButtonOption {
287
+ padding-top: 0.7rem;
288
+ }
289
+
290
+ .selectedProceduresTags {
291
+ display: flex;
292
+ flex-wrap: wrap;
293
+ gap: layout.$spacing-03;
294
+ }
295
+
296
+ .selectedProcedureTag {
297
+ max-width: 100%;
298
+ font-weight: 500;
299
+
300
+ :global(.cds--tag__label) {
301
+ white-space: normal;
302
+ word-break: break-word;
303
+ }
304
+ }