@servicetitan/dte-pdf-editor 1.86.0 → 1.88.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 (96) hide show
  1. package/README.md +37 -30
  2. package/dist/components/display-conditions/condition-row.d.ts.map +1 -1
  3. package/dist/components/display-conditions/condition-row.js +51 -22
  4. package/dist/components/display-conditions/condition-row.js.map +1 -1
  5. package/dist/components/display-conditions/condition-value-control.d.ts.map +1 -1
  6. package/dist/components/display-conditions/condition-value-control.js +1 -2
  7. package/dist/components/display-conditions/condition-value-control.js.map +1 -1
  8. package/dist/components/display-conditions/display-condition-modal.d.ts.map +1 -1
  9. package/dist/components/display-conditions/display-condition-modal.js +6 -49
  10. package/dist/components/display-conditions/display-condition-modal.js.map +1 -1
  11. package/dist/components/field-config-panel/e-sign-date-rules-summary.d.ts +11 -0
  12. package/dist/components/field-config-panel/e-sign-date-rules-summary.d.ts.map +1 -0
  13. package/dist/components/field-config-panel/e-sign-date-rules-summary.js +36 -0
  14. package/dist/components/field-config-panel/e-sign-date-rules-summary.js.map +1 -0
  15. package/dist/components/field-config-panel/e-sign-date-signed-offset-modal.d.ts +16 -0
  16. package/dist/components/field-config-panel/e-sign-date-signed-offset-modal.d.ts.map +1 -0
  17. package/dist/components/field-config-panel/e-sign-date-signed-offset-modal.js +62 -0
  18. package/dist/components/field-config-panel/e-sign-date-signed-offset-modal.js.map +1 -0
  19. package/dist/components/field-config-panel/e-sign-offset-rule-row.d.ts +16 -0
  20. package/dist/components/field-config-panel/e-sign-offset-rule-row.d.ts.map +1 -0
  21. package/dist/components/field-config-panel/e-sign-offset-rule-row.js +25 -0
  22. package/dist/components/field-config-panel/e-sign-offset-rule-row.js.map +1 -0
  23. package/dist/components/field-config-panel/e-sign-options-modal.d.ts +15 -0
  24. package/dist/components/field-config-panel/e-sign-options-modal.d.ts.map +1 -0
  25. package/dist/components/field-config-panel/e-sign-options-modal.js +26 -0
  26. package/dist/components/field-config-panel/e-sign-options-modal.js.map +1 -0
  27. package/dist/components/field-config-panel/field-config-panel.d.ts.map +1 -1
  28. package/dist/components/field-config-panel/field-config-panel.js +30 -28
  29. package/dist/components/field-config-panel/field-config-panel.js.map +1 -1
  30. package/dist/components/field-sidebar/e-sign-field-type-list.d.ts.map +1 -1
  31. package/dist/components/field-sidebar/e-sign-field-type-list.js +1 -6
  32. package/dist/components/field-sidebar/e-sign-field-type-list.js.map +1 -1
  33. package/dist/components/pdf-fields-overlay/pdf-overlay-field-fillable.d.ts.map +1 -1
  34. package/dist/components/pdf-fields-overlay/pdf-overlay-field-fillable.js +22 -8
  35. package/dist/components/pdf-fields-overlay/pdf-overlay-field-fillable.js.map +1 -1
  36. package/dist/components/pdf-view/pdf-view-fillable.d.ts.map +1 -1
  37. package/dist/components/pdf-view/pdf-view-fillable.js +3 -3
  38. package/dist/components/pdf-view/pdf-view-fillable.js.map +1 -1
  39. package/dist/constants/field.constants.d.ts +1 -5
  40. package/dist/constants/field.constants.d.ts.map +1 -1
  41. package/dist/constants/field.constants.js +21 -7
  42. package/dist/constants/field.constants.js.map +1 -1
  43. package/dist/hooks/usePdfFieldDnD.d.ts.map +1 -1
  44. package/dist/hooks/usePdfFieldDnD.js +13 -5
  45. package/dist/hooks/usePdfFieldDnD.js.map +1 -1
  46. package/dist/interface/types.d.ts +26 -1
  47. package/dist/interface/types.d.ts.map +1 -1
  48. package/dist/interface/types.js +1 -0
  49. package/dist/interface/types.js.map +1 -1
  50. package/dist/styles/field-config-panel.css +11 -0
  51. package/dist/styles/field-type.css +12 -0
  52. package/dist/styles/index.css +1 -0
  53. package/dist/styles/variables.css +2 -0
  54. package/dist/utils/conditions/condition-match-type.utils.d.ts +14 -0
  55. package/dist/utils/conditions/condition-match-type.utils.d.ts.map +1 -0
  56. package/dist/utils/conditions/condition-match-type.utils.js +50 -0
  57. package/dist/utils/conditions/condition-match-type.utils.js.map +1 -0
  58. package/dist/utils/conditions/e-sign-offset-rules.utils.d.ts +12 -0
  59. package/dist/utils/conditions/e-sign-offset-rules.utils.d.ts.map +1 -0
  60. package/dist/utils/conditions/e-sign-offset-rules.utils.js +19 -0
  61. package/dist/utils/conditions/e-sign-offset-rules.utils.js.map +1 -0
  62. package/dist/utils/conditions/index.d.ts +2 -0
  63. package/dist/utils/conditions/index.d.ts.map +1 -1
  64. package/dist/utils/conditions/index.js +2 -0
  65. package/dist/utils/conditions/index.js.map +1 -1
  66. package/dist/utils/field/field-placeholder-text.utils.d.ts +1 -0
  67. package/dist/utils/field/field-placeholder-text.utils.d.ts.map +1 -1
  68. package/dist/utils/field/field-placeholder-text.utils.js +9 -4
  69. package/dist/utils/field/field-placeholder-text.utils.js.map +1 -1
  70. package/package.json +1 -1
  71. package/src/__tests__/field-types/custom-fields.test.ts +187 -0
  72. package/src/components/display-conditions/condition-row.tsx +114 -131
  73. package/src/components/display-conditions/condition-value-control.tsx +1 -2
  74. package/src/components/display-conditions/display-condition-modal.tsx +13 -63
  75. package/src/components/field-config-panel/e-sign-date-rules-summary.tsx +114 -0
  76. package/src/components/field-config-panel/e-sign-date-signed-offset-modal.tsx +197 -0
  77. package/src/components/field-config-panel/e-sign-offset-rule-row.tsx +91 -0
  78. package/src/components/field-config-panel/e-sign-options-modal.tsx +112 -0
  79. package/src/components/field-config-panel/field-config-panel.tsx +70 -91
  80. package/src/components/field-sidebar/e-sign-field-type-list.tsx +11 -14
  81. package/src/components/pdf-fields-overlay/pdf-overlay-field-fillable.tsx +46 -14
  82. package/src/components/pdf-view/pdf-view-fillable.tsx +3 -2
  83. package/src/constants/field.constants.ts +21 -8
  84. package/src/hooks/usePdfFieldDnD.ts +17 -2
  85. package/src/interface/types.ts +34 -1
  86. package/src/styles/field-config-panel.css +11 -0
  87. package/src/styles/field-type.css +12 -0
  88. package/src/styles/index.css +1 -0
  89. package/src/styles/variables.css +2 -0
  90. package/src/utils/conditions/__tests__/condition-match-type.utils.test.ts +104 -0
  91. package/src/utils/conditions/__tests__/e-sign-offset-rules.utils.test.ts +51 -0
  92. package/src/utils/conditions/condition-match-type.utils.ts +80 -0
  93. package/src/utils/conditions/e-sign-offset-rules.utils.ts +32 -0
  94. package/src/utils/conditions/index.ts +2 -0
  95. package/src/utils/field/__tests__/field-placeholder-text.utils.test.ts +17 -1
  96. package/src/utils/field/field-placeholder-text.utils.ts +10 -4
@@ -1,4 +1,4 @@
1
- import { Button, Chip, Combobox, Flex, Text } from '@servicetitan/anvil2';
1
+ import { Button, Chip, Flex, SelectFieldSync, Text } from '@servicetitan/anvil2';
2
2
  import TrashIcon from '@servicetitan/anvil2/assets/icons/material/round/delete.svg';
3
3
  import { useEffect, useMemo, useState } from 'react';
4
4
  import {
@@ -220,6 +220,68 @@ export function ConditionRow({
220
220
  [operatorItems, condition.operator],
221
221
  );
222
222
 
223
+ const sourceKindSelectOptions = useMemo(
224
+ () => sourceKindOptions.map(option => ({ id: option.value, label: option.label })),
225
+ [sourceKindOptions],
226
+ );
227
+
228
+ const selectedSourceKindSelectOption = selectedSourceKindOption
229
+ ? { id: selectedSourceKindOption.value, label: selectedSourceKindOption.label }
230
+ : null;
231
+
232
+ const handleSourceKindSelect = (option: { id: string; label: string } | null) => {
233
+ handleSourceKindChange(sourceKindOptions.find(o => o.value === option?.id) ?? null);
234
+ };
235
+
236
+ const formSelectOptions = useMemo(
237
+ () => sortedForms.map(form => ({ id: form.id, label: form.name })),
238
+ [sortedForms],
239
+ );
240
+
241
+ const selectedFormSelectOption = pickerForm
242
+ ? { id: pickerForm.id, label: pickerForm.name }
243
+ : null;
244
+
245
+ const handleFormSelect = (option: { id: number; label: string }) => {
246
+ handlePickerFormChange(sortedForms.find(f => f.id === option?.id) ?? null);
247
+ };
248
+
249
+ const dataPointSelectOptions = useMemo(
250
+ () => dataPointItems.map(item => ({ id: item.fullKey, label: item.title })),
251
+ [dataPointItems],
252
+ );
253
+
254
+ const selectedDataPointSelectOption = selectedDataPoint
255
+ ? { id: selectedDataPoint.fullKey, label: selectedDataPoint.title }
256
+ : null;
257
+
258
+ const handleDataPointSelect = (option: { id: string; label: string }) => {
259
+ handleDataPointChange(dataPointItems.find(item => item.fullKey === option?.id) ?? null);
260
+ };
261
+
262
+ const operatorSelectOptions = useMemo(
263
+ () => operatorItems.map(op => ({ id: op.value, label: op.label })),
264
+ [operatorItems],
265
+ );
266
+
267
+ const selectedOperatorSelectOption = selectedOperator
268
+ ? { id: selectedOperator.value, label: selectedOperator.label }
269
+ : null;
270
+
271
+ const handleOperatorSelect = (option: { id: string; label: string } | null) => {
272
+ const nextOperator = (option?.id ?? 'is_equal_to') as DisplayConditionSingle['operator'];
273
+ onChange({
274
+ ...condition,
275
+ operator: nextOperator,
276
+ ...(isCheckbox
277
+ ? {
278
+ value: CHECKBOX_CONDITION_VALUE,
279
+ valueLabel: undefined,
280
+ }
281
+ : {}),
282
+ });
283
+ };
284
+
223
285
  const isValueLess =
224
286
  isCheckbox || VALUE_LESS_OPERATORS.includes(condition.operator as ConditionOperator);
225
287
 
@@ -336,51 +398,27 @@ export function ConditionRow({
336
398
  return (
337
399
  <Flex direction="column" gap="4" flex={1}>
338
400
  <Flex flex={1} gap="2">
339
- <Combobox
401
+ <SelectFieldSync
340
402
  flex={1}
341
- itemToKey={(item: SourceKindOption | null) => item?.value ?? ''}
342
- itemToString={(item: SourceKindOption | null) => item?.label ?? ''}
343
- items={sourceKindOptions}
344
- selectedItem={selectedSourceKindOption}
345
- onChange={handleSourceKindChange}
346
- filterOptions={{ keys: ['label'] }}
347
- >
348
- <Combobox.SelectTrigger label="Source" placeholder="Select source..." />
349
- <Combobox.Content>
350
- {({ items }: { items: SourceKindOption[] }) => (
351
- <Combobox.List>
352
- {items.map((item, i) => (
353
- <Combobox.Item index={i} item={item} key={item.value}>
354
- {item.label}
355
- </Combobox.Item>
356
- ))}
357
- </Combobox.List>
358
- )}
359
- </Combobox.Content>
360
- </Combobox>
403
+ disableSearch
404
+ disableClearButton
405
+ label="Source"
406
+ placeholder="Select source..."
407
+ options={sourceKindSelectOptions}
408
+ value={selectedSourceKindSelectOption}
409
+ onSelectedOptionChange={handleSourceKindSelect}
410
+ />
361
411
  {sourceKind === FieldTypeEnum.forms && (
362
- <Combobox
412
+ <SelectFieldSync
363
413
  flex={1}
364
- itemToKey={(item: FormInfo | null) => String(item?.id ?? '')}
365
- itemToString={(item: FormInfo | null) => item?.name ?? ''}
366
- items={sortedForms}
367
- selectedItem={pickerForm}
368
- onChange={handlePickerFormChange}
369
- filterOptions={{ keys: ['name'] }}
370
- >
371
- <Combobox.SelectTrigger label="Select Form" placeholder="Select form..." />
372
- <Combobox.Content>
373
- {({ items }: { items: FormInfo[] }) => (
374
- <Combobox.List>
375
- {items.map((item, i) => (
376
- <Combobox.Item index={i} item={item} key={item.id}>
377
- {item.name}
378
- </Combobox.Item>
379
- ))}
380
- </Combobox.List>
381
- )}
382
- </Combobox.Content>
383
- </Combobox>
414
+ disableSearch
415
+ disableClearButton
416
+ label="Select Form"
417
+ placeholder="Select form..."
418
+ options={formSelectOptions}
419
+ value={selectedFormSelectOption}
420
+ onSelectedOptionChange={handleFormSelect}
421
+ />
384
422
  )}
385
423
  </Flex>
386
424
 
@@ -401,113 +439,58 @@ export function ConditionRow({
401
439
  </Flex>
402
440
 
403
441
  <Flex flex={1} style={{ minWidth: 160 }}>
404
- <Combobox
442
+ <SelectFieldSync
405
443
  flex={1}
444
+ disableSearch
445
+ disableClearButton
406
446
  disabled={
407
447
  sourceKind === FieldTypeEnum.forms &&
408
448
  (!pickerForm || isLoadingFormFields)
409
449
  }
410
- itemToKey={(item: DataPointOption | null) => item?.fullKey ?? ''}
411
- itemToString={(item: DataPointOption | null) => item?.title ?? ''}
412
- items={dataPointItems}
413
- selectedItem={selectedDataPoint}
414
- onChange={handleDataPointChange}
415
- filterOptions={{ keys: ['title'] }}
416
- >
417
- <Combobox.SelectTrigger
418
- label="Data point"
419
- placeholder={
420
- sourceKind === FieldTypeEnum.forms && isLoadingFormFields
421
- ? 'Loading fields...'
422
- : sourceKind === FieldTypeEnum.forms && !pickerForm
423
- ? 'Select a form first...'
424
- : 'Select data point...'
425
- }
426
- />
427
- <Combobox.Content>
428
- {({ items }: { items: DataPointOption[] }) => (
429
- <Combobox.List>
430
- {items.map((item, i) => (
431
- <Combobox.Item index={i} item={item} key={item.fullKey}>
432
- {item.title}
433
- </Combobox.Item>
434
- ))}
435
- </Combobox.List>
436
- )}
437
- </Combobox.Content>
438
- </Combobox>
450
+ label="Data point"
451
+ placeholder={
452
+ sourceKind === FieldTypeEnum.forms && isLoadingFormFields
453
+ ? 'Loading fields...'
454
+ : sourceKind === FieldTypeEnum.forms && !pickerForm
455
+ ? 'Select a form first...'
456
+ : 'Select data point...'
457
+ }
458
+ options={dataPointSelectOptions}
459
+ value={selectedDataPointSelectOption}
460
+ onSelectedOptionChange={handleDataPointSelect}
461
+ />
439
462
  </Flex>
440
463
  <Flex flex={1} style={{ minWidth: 160 }}>
441
- <Combobox
464
+ <SelectFieldSync
442
465
  flex={1}
443
- itemToKey={(item: OperatorOption | null) => item?.value ?? ''}
444
- itemToString={(item: OperatorOption | null) => item?.label ?? ''}
445
- items={operatorItems}
446
- selectedItem={selectedOperator}
447
- onChange={(item: OperatorOption | null) => {
448
- const nextOperator = (item?.value ??
449
- 'is_equal_to') as DisplayConditionSingle['operator'];
450
- onChange({
451
- ...condition,
452
- operator: nextOperator,
453
- ...(isCheckbox
454
- ? {
455
- value: CHECKBOX_CONDITION_VALUE,
456
- valueLabel: undefined,
457
- }
458
- : {}),
459
- });
460
- }}
461
- filterOptions={{ keys: ['label'] }}
462
- >
463
- <Combobox.SelectTrigger label="Condition" placeholder="Select..." />
464
- <Combobox.Content>
465
- {({ items }: { items: OperatorOption[] }) => (
466
- <Combobox.List>
467
- {items.map((item, i) => (
468
- <Combobox.Item index={i} item={item} key={item.value}>
469
- {item.label}
470
- </Combobox.Item>
471
- ))}
472
- </Combobox.List>
473
- )}
474
- </Combobox.Content>
475
- </Combobox>
466
+ disableSearch
467
+ disableClearButton
468
+ label="Condition"
469
+ placeholder="Select..."
470
+ options={operatorSelectOptions}
471
+ value={selectedOperatorSelectOption}
472
+ onSelectedOptionChange={handleOperatorSelect}
473
+ />
476
474
  </Flex>
477
475
  {!isValueLess && (
478
476
  <Flex flex={1} style={{ minWidth: 160 }}>
479
477
  {isRadioGroup ? (
480
- <Combobox
478
+ <SelectFieldSync
481
479
  flex={1}
482
- itemToKey={item => item?.id ?? ''}
483
- itemToString={item => item?.label ?? ''}
484
- items={radioValueOptions}
485
- selectedItem={selectedRadioValue}
486
- onChange={(item: RadioGroupOption | null) =>
480
+ disableSearch
481
+ label="Value"
482
+ disableClearButton
483
+ placeholder="Select radio option..."
484
+ options={radioValueOptions}
485
+ value={selectedRadioValue}
486
+ onSelectedOptionChange={(item: RadioGroupOption | null) =>
487
487
  onChange({
488
488
  ...condition,
489
489
  value: item?.id ?? '',
490
490
  valueLabel: undefined,
491
491
  })
492
492
  }
493
- filterOptions={{ keys: ['label'] }}
494
- >
495
- <Combobox.SelectTrigger
496
- label="Value"
497
- placeholder="Select radio option..."
498
- />
499
- <Combobox.Content>
500
- {({ items }) => (
501
- <Combobox.List>
502
- {items.map((item, i) => (
503
- <Combobox.Item index={i} item={item} key={item.id}>
504
- {item.label}
505
- </Combobox.Item>
506
- ))}
507
- </Combobox.List>
508
- )}
509
- </Combobox.Content>
510
- </Combobox>
493
+ />
511
494
  ) : (
512
495
  <ConditionValueControl
513
496
  value={condition.value}
@@ -1,5 +1,4 @@
1
- import { TextField } from '@servicetitan/anvil2';
2
- import { SelectField, SelectFieldOption, SelectFieldSync } from '@servicetitan/anvil2/beta';
1
+ import { SelectField, SelectFieldOption, SelectFieldSync, TextField } from '@servicetitan/anvil2';
3
2
  import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
4
3
  import { useLookupOptions } from '../../hooks';
5
4
  import type { LookupOption } from '../../interface/host-events';
@@ -9,48 +9,15 @@ import type {
9
9
  SchemaObject,
10
10
  } from '../../interface/types';
11
11
  import {
12
- getDisplayConditionFieldTypeForKey,
12
+ applyConditionMatchType,
13
+ type ConditionMatchType,
14
+ deriveConditionMatchType,
13
15
  getDocumentFieldsDataPointOptions,
14
16
  getSchemaDataPointOptions,
15
- isValidNumber,
17
+ isValidConditionGroups,
16
18
  } from '../../utils';
17
19
  import { ConditionGroupsSection } from './condition-groups-section';
18
20
 
19
- type ConditionMatchType = 'and' | 'or';
20
-
21
- const deriveConditionMatchType = (conditionState: DisplayConditionState): ConditionMatchType => {
22
- for (let g = 0; g < conditionState.groups.length; g++) {
23
- const group = conditionState.groups[g];
24
- if (g > 0 && group.logicalOperator === 'or') {
25
- return 'or';
26
- }
27
- for (let i = 1; i < group.conditions.length; i++) {
28
- if (group.conditions[i]?.logicalOperator === 'or') {
29
- return 'or';
30
- }
31
- }
32
- }
33
- return 'and';
34
- };
35
-
36
- const applyConditionMatchType = (
37
- conditionState: DisplayConditionState,
38
- matchType: ConditionMatchType,
39
- ): DisplayConditionState => {
40
- return {
41
- ...conditionState,
42
- groups: conditionState.groups.map((group, groupIndex) => ({
43
- ...group,
44
- ...(groupIndex > 0 ? { logicalOperator: matchType } : {}),
45
- conditions: group.conditions.map((c, i) =>
46
- i === 0
47
- ? { ...c, logicalOperator: undefined }
48
- : { ...c, logicalOperator: matchType },
49
- ),
50
- })),
51
- };
52
- };
53
-
54
21
  const BEHAVIOR_OPTIONS = [
55
22
  { label: 'Show', value: 'show' },
56
23
  { label: 'Hide', value: 'hide' },
@@ -159,32 +126,15 @@ export function DisplayConditionModal({
159
126
  setState(prev => applyConditionMatchType(prev, value));
160
127
  }, []);
161
128
 
162
- const canSave = useMemo(() => {
163
- for (const group of state.groups) {
164
- for (const condition of group.conditions) {
165
- if (!condition.dataPointKey) {
166
- return false;
167
- }
168
- if (condition.operator === 'is_empty' || condition.operator === 'is_not_empty') {
169
- continue;
170
- }
171
- const trimmedValue = condition.value.trim();
172
- if (!trimmedValue) {
173
- return false;
174
- }
175
- const fieldType = getDisplayConditionFieldTypeForKey(
176
- condition.dataPointKey,
177
- mergeTagOptions,
178
- fillableOptions,
179
- formFieldsByFormId ?? {},
180
- );
181
- if (fieldType === 'number' && !isValidNumber(trimmedValue)) {
182
- return false;
183
- }
184
- }
185
- }
186
- return state.groups.length > 0;
187
- }, [fillableOptions, formFieldsByFormId, mergeTagOptions, state.groups]);
129
+ const canSave = useMemo(
130
+ () =>
131
+ isValidConditionGroups(state.groups, {
132
+ fillableOptions,
133
+ formFieldsByFormId,
134
+ mergeTagOptions,
135
+ }),
136
+ [fillableOptions, formFieldsByFormId, mergeTagOptions, state.groups],
137
+ );
188
138
 
189
139
  return (
190
140
  <Dialog open onClose={handleClose} size="xlarge">
@@ -0,0 +1,114 @@
1
+ import { Button, Flex, Text } from '@servicetitan/anvil2';
2
+ import EditIcon from '@servicetitan/anvil2/assets/icons/material/round/edit.svg';
3
+ import { FC, useMemo } from 'react';
4
+ import {
5
+ CHECKBOX_OPERATORS,
6
+ type ConditionOperator,
7
+ type DisplayConditionSingle,
8
+ type ESignDateSignedOffsetSettingsRule,
9
+ NUMBER_OPERATORS,
10
+ type PdfField,
11
+ RADIO_OPERATORS,
12
+ type SchemaObject,
13
+ STRING_OPERATORS,
14
+ VALUE_LESS_OPERATORS,
15
+ } from '../../interface/types';
16
+ import { getDataPointOptions } from '../../utils';
17
+
18
+ const ALL_OPERATORS = [
19
+ ...NUMBER_OPERATORS,
20
+ ...STRING_OPERATORS,
21
+ ...RADIO_OPERATORS,
22
+ ...CHECKBOX_OPERATORS,
23
+ ];
24
+
25
+ const getOperatorSymbol = (operator: string): string =>
26
+ ALL_OPERATORS.find(op => op.value === operator)?.label.split(' (')[0] ?? operator;
27
+
28
+ export interface ESignDateRulesSummaryProps {
29
+ elseDays: number;
30
+ rulesWithConditions: ESignDateSignedOffsetSettingsRule[];
31
+ schema?: SchemaObject;
32
+ documentFields?: PdfField[];
33
+ onEdit: () => void;
34
+ }
35
+
36
+ export const ESignDateRulesSummary: FC<ESignDateRulesSummaryProps> = ({
37
+ documentFields,
38
+ elseDays,
39
+ onEdit,
40
+ rulesWithConditions,
41
+ schema,
42
+ }) => {
43
+ const dataPointOptions = useMemo(
44
+ () => getDataPointOptions(schema, documentFields),
45
+ [schema, documentFields],
46
+ );
47
+
48
+ const getConditionText = (condition: DisplayConditionSingle) => {
49
+ const dataPoint = dataPointOptions.find(
50
+ option => option.fullKey === condition.dataPointKey,
51
+ );
52
+ const label = dataPoint?.title ?? condition.dataPointKey;
53
+ const symbol = getOperatorSymbol(condition.operator).replace('==', '=');
54
+ const isValueLess =
55
+ dataPoint?.isCheckbox === true ||
56
+ VALUE_LESS_OPERATORS.includes(condition.operator as ConditionOperator);
57
+ const value = condition.valueLabel ?? condition.value;
58
+
59
+ return `${label} ${symbol}${isValueLess ? '' : ` ${value}`}`;
60
+ };
61
+
62
+ return (
63
+ <Flex direction="column" gap="1">
64
+ <Flex justifyContent="space-between" alignItems="center">
65
+ <Text variant="body" size="medium" style={{ fontWeight: 500 }}>
66
+ Calculated date rules
67
+ </Text>
68
+ <Button
69
+ appearance="ghost"
70
+ size="small"
71
+ icon={{ before: EditIcon }}
72
+ onClick={onEdit}
73
+ >
74
+ Edit
75
+ </Button>
76
+ </Flex>
77
+ <Flex direction="column" gap="2" className="dte-rule-card --active">
78
+ {rulesWithConditions.map((rule, index) => {
79
+ const condition = rule.condition.groups[0]?.conditions[0];
80
+ return (
81
+ <Flex key={rule.condition.groups[0]?.id ?? index} direction="column">
82
+ <Text variant="body">{rule.days} After Signing When:</Text>
83
+ {condition && (
84
+ <Text
85
+ variant="body"
86
+ size="small"
87
+ style={{
88
+ color: '#422799',
89
+ }}
90
+ >
91
+ {getConditionText(condition)}
92
+ </Text>
93
+ )}
94
+ </Flex>
95
+ );
96
+ })}
97
+ <Flex direction="column">
98
+ <Text variant="body" size="medium">
99
+ {elseDays} After Signing When:
100
+ </Text>
101
+ <Text
102
+ variant="body"
103
+ size="small"
104
+ style={{
105
+ color: '#422799',
106
+ }}
107
+ >
108
+ ELSE
109
+ </Text>
110
+ </Flex>
111
+ </Flex>
112
+ </Flex>
113
+ );
114
+ };