@fuego-systems/react 0.1.12 → 0.1.14

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.
@@ -26,6 +26,12 @@ export interface HealthcareServiceCardProps {
26
26
  readonly specialty?: string;
27
27
  /** Optional custom badge rendered inline next to the service name. */
28
28
  readonly badge?: ReactNode;
29
+ /**
30
+ * Whether the study requires an appointment. When explicitly `false`, a
31
+ * "No requiere turno" (walk-in) badge is shown. `undefined`/`true` renders
32
+ * nothing. Mirrors `HealthcareService.appointmentRequired`.
33
+ */
34
+ readonly appointmentRequired?: boolean;
29
35
  /** Whether to render a close button in the top-right corner. Defaults to false. */
30
36
  readonly closable?: boolean;
31
37
  /** Callback invoked when the close button is clicked. Only relevant when `closable` is true. */
@@ -43,5 +49,5 @@ export interface HealthcareServiceProtocolSelection {
43
49
  /** The `action.id`s of toggled-on addon sub-actions within the selected action. */
44
50
  readonly addonIds?: readonly string[];
45
51
  }
46
- export declare function HealthcareServiceCard({ name, specialty, badge, closable, onClose, actions, protocolSelection, onProtocolSelectionChange }: HealthcareServiceCardProps): JSX.Element;
52
+ export declare function HealthcareServiceCard({ name, specialty, badge, appointmentRequired, closable, onClose, actions, protocolSelection, onProtocolSelectionChange }: HealthcareServiceCardProps): JSX.Element;
47
53
  //# sourceMappingURL=HealthcareServiceCard.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"HealthcareServiceCard.d.ts","sourceRoot":"","sources":["../../src/HealthcareServiceCard/HealthcareServiceCard.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAClD,OAAc,EAAE,KAAK,GAAG,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAIvD,6DAA6D;AAC7D,MAAM,WAAW,uBAAuB;IACtC,yCAAyC;IACzC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,wDAAwD;IACxD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,mDAAmD;IACnD,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;IAC1B,qCAAqC;IACrC,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAA;IAC5B;;;;OAIG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAA;IAC5B,0DAA0D;IAC1D,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,uBAAuB,EAAE,CAAA;CACrD;AAED,MAAM,WAAW,0BAA0B;IACzC,4BAA4B;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,iDAAiD;IACjD,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;IAC3B,sEAAsE;IACtE,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,CAAA;IAC1B,mFAAmF;IACnF,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAC3B,gGAAgG;IAChG,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;IAC7B,yDAAyD;IACzD,QAAQ,CAAC,OAAO,EAAE,SAAS,uBAAuB,EAAE,CAAA;IACpD,6EAA6E;IAC7E,QAAQ,CAAC,iBAAiB,CAAC,EAAE,kCAAkC,CAAA;IAC/D,iEAAiE;IACjE,QAAQ,CAAC,yBAAyB,CAAC,EAAE,CAAC,iBAAiB,EAAE,kCAAkC,KAAK,IAAI,CAAA;CACrG;AAED,MAAM,WAAW,kCAAkC;IACjD,sDAAsD;IACtD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,mFAAmF;IACnF,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CACtC;AAiCD,wBAAgB,qBAAqB,CAAE,EACrC,IAAI,EACJ,SAAS,EACT,KAAK,EACL,QAAgB,EAChB,OAAO,EACP,OAAO,EACP,iBAAiB,EACjB,yBAAyB,EAC1B,EAAE,0BAA0B,GAAG,GAAG,CAAC,OAAO,CA8K1C"}
1
+ {"version":3,"file":"HealthcareServiceCard.d.ts","sourceRoot":"","sources":["../../src/HealthcareServiceCard/HealthcareServiceCard.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAClD,OAAc,EAAE,KAAK,GAAG,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAIvD,6DAA6D;AAC7D,MAAM,WAAW,uBAAuB;IACtC,yCAAyC;IACzC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,wDAAwD;IACxD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,mDAAmD;IACnD,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;IAC1B,qCAAqC;IACrC,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAA;IAC5B;;;;OAIG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAA;IAC5B,0DAA0D;IAC1D,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,uBAAuB,EAAE,CAAA;CACrD;AAED,MAAM,WAAW,0BAA0B;IACzC,4BAA4B;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,iDAAiD;IACjD,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;IAC3B,sEAAsE;IACtE,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,CAAA;IAC1B;;;;OAIG;IACH,QAAQ,CAAC,mBAAmB,CAAC,EAAE,OAAO,CAAA;IACtC,mFAAmF;IACnF,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAC3B,gGAAgG;IAChG,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;IAC7B,yDAAyD;IACzD,QAAQ,CAAC,OAAO,EAAE,SAAS,uBAAuB,EAAE,CAAA;IACpD,6EAA6E;IAC7E,QAAQ,CAAC,iBAAiB,CAAC,EAAE,kCAAkC,CAAA;IAC/D,iEAAiE;IACjE,QAAQ,CAAC,yBAAyB,CAAC,EAAE,CAAC,iBAAiB,EAAE,kCAAkC,KAAK,IAAI,CAAA;CACrG;AAED,MAAM,WAAW,kCAAkC;IACjD,sDAAsD;IACtD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,mFAAmF;IACnF,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CACtC;AAyDD,wBAAgB,qBAAqB,CAAE,EACrC,IAAI,EACJ,SAAS,EACT,KAAK,EACL,mBAAmB,EACnB,QAAgB,EAChB,OAAO,EACP,OAAO,EACP,iBAAiB,EACjB,yBAAyB,EAC1B,EAAE,0BAA0B,GAAG,GAAG,CAAC,OAAO,CA0L1C"}
@@ -13,8 +13,13 @@ function CheckIcon(props) {
13
13
  const { size, style, ...rest } = props;
14
14
  return (_jsx("svg", { xmlns: "http://www.w3.org/2000/svg", width: size !== null && size !== void 0 ? size : 14, height: size !== null && size !== void 0 ? size : 14, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 3, strokeLinecap: "round", strokeLinejoin: "round", style: style, ...rest, children: _jsx("polyline", { points: "20 6 9 17 4 12" }) }));
15
15
  }
16
+ // "Walk-in / enter" glyph shown next to the no-appointment-required note.
17
+ function WalkInIcon(props) {
18
+ const { size, style, ...rest } = props;
19
+ return (_jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: size !== null && size !== void 0 ? size : 14, height: size !== null && size !== void 0 ? size : 14, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", style: style, ...rest, children: [_jsx("path", { d: "M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4" }), _jsx("polyline", { points: "10 17 15 12 10 7" }), _jsx("line", { x1: "15", y1: "12", x2: "3", y2: "12" })] }));
20
+ }
16
21
  // ─── Component ───────────────────────────────────────────────────────────────
17
- export function HealthcareServiceCard({ name, specialty, badge, closable = false, onClose, actions, protocolSelection, onProtocolSelectionChange }) {
22
+ export function HealthcareServiceCard({ name, specialty, badge, appointmentRequired, closable = false, onClose, actions, protocolSelection, onProtocolSelectionChange }) {
18
23
  var _a;
19
24
  const handleChange = (value) => {
20
25
  if (value !== (protocolSelection === null || protocolSelection === void 0 ? void 0 : protocolSelection.actionId)) {
@@ -29,7 +34,7 @@ export function HealthcareServiceCard({ name, specialty, badge, closable = false
29
34
  : current.filter((id) => id !== addonId);
30
35
  onProtocolSelectionChange === null || onProtocolSelectionChange === void 0 ? void 0 : onProtocolSelectionChange({ actionId, addonIds: next });
31
36
  };
32
- return (_jsx(Card, { withBorder: true, radius: "md", padding: "lg", children: _jsxs(Stack, { gap: "sm", children: [_jsxs(Stack, { gap: 4, children: [_jsxs(Group, { justify: "space-between", wrap: "nowrap", align: "flex-start", gap: "xs", children: [_jsx(Text, { fw: 700, size: "lg", style: { flex: 1, minWidth: 0, lineHeight: 1.2 }, children: name }), closable && (_jsx(CloseButton, { onClick: onClose, size: "sm", c: "red", "aria-label": "Quitar", style: { flexShrink: 0 } }))] }), (specialty || badge) && (_jsxs(Group, { gap: 6, wrap: "wrap", children: [specialty && (_jsx(Badge, { variant: "light", color: "blue", radius: "sm", size: "sm", children: specialty })), badge] }))] }), actions.length === 1 && (() => {
37
+ return (_jsx(Card, { withBorder: true, radius: "md", padding: "lg", children: _jsxs(Stack, { gap: "sm", children: [_jsxs(Stack, { gap: 4, children: [appointmentRequired === false && (_jsx(Badge, { variant: "light", color: "teal", radius: "sm", size: "sm", leftSection: _jsx(WalkInIcon, { size: 12, style: { display: 'block' } }), style: { alignSelf: 'flex-start' }, children: "No requiere turno" })), _jsxs(Group, { justify: "space-between", wrap: "nowrap", align: "flex-start", gap: "xs", children: [_jsx(Text, { fw: 700, size: "lg", style: { flex: 1, minWidth: 0, lineHeight: 1.2 }, children: name }), closable && (_jsx(CloseButton, { onClick: onClose, size: "sm", c: "red", "aria-label": "Quitar", style: { flexShrink: 0 } }))] }), (specialty || badge) && (_jsxs(Group, { gap: 6, wrap: "wrap", children: [specialty && (_jsx(Badge, { variant: "light", color: "blue", radius: "sm", size: "sm", children: specialty })), badge] }))] }), actions.length === 1 && (() => {
33
38
  var _a, _b;
34
39
  const action = actions[0];
35
40
  const duration = formatDuration(action.duration);
@@ -1 +1 @@
1
- {"version":3,"file":"HealthcareServiceCard.js","sourceRoot":"","sources":["../../src/HealthcareServiceCard/HealthcareServiceCard.tsx"],"names":[],"mappings":"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","sourcesContent":["import { Badge, Card, CloseButton, Group, Radio, Stack, Switch, Text } from '@mantine/core'\nimport type { Duration } from '@medplum/fhirtypes'\nimport React, { type JSX, type ReactNode } from 'react'\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\n/** A single protocol action entry to display in the card. */\nexport interface HealthcareServiceAction {\n /** Unique identifier for this action. */\n readonly id: string\n /** Display label for the action (e.g. \"Helicoidal\"). */\n readonly label: string\n /** User-facing question / hint for this action. */\n readonly question?: string\n /** FHIR Duration for this action. */\n readonly duration?: Duration\n /**\n * Only meaningful on addon entries. When `true`, the addon is always\n * included with its parent action and is hidden from the card UI — the\n * caller must still resolve and persist it server-side.\n */\n readonly mandatory?: boolean\n /** Optional addons (sub-actions with `any` selection). */\n readonly addons?: readonly HealthcareServiceAction[]\n}\n\nexport interface HealthcareServiceCardProps {\n /** Service display name. */\n readonly name: string\n /** Specialty display name (shown as a badge). */\n readonly specialty?: string\n /** Optional custom badge rendered inline next to the service name. */\n readonly badge?: ReactNode\n /** Whether to render a close button in the top-right corner. Defaults to false. */\n readonly closable?: boolean\n /** Callback invoked when the close button is clicked. Only relevant when `closable` is true. */\n readonly onClose?: () => void\n /** Protocol action variants the user can choose from. */\n readonly actions: readonly HealthcareServiceAction[]\n /** Current controlled selection for the chosen action and enabled addons. */\n readonly protocolSelection?: HealthcareServiceProtocolSelection\n /** Called whenever the controlled protocol selection changes. */\n readonly onProtocolSelectionChange?: (protocolSelection: HealthcareServiceProtocolSelection) => void\n}\n\nexport interface HealthcareServiceProtocolSelection {\n /** The `action.id` of the chosen top-level action. */\n readonly actionId: string\n /** The `action.id`s of toggled-on addon sub-actions within the selected action. */\n readonly addonIds?: readonly string[]\n}\n\n// ─── Helpers ─────────────────────────────────────────────────────────────────\n\nfunction formatDuration (d?: Duration): string | undefined {\n if (d?.value === undefined || d?.value === null) { return undefined }\n const unit = d.unit ?? d.code ?? ''\n return unit ? `${d.value} ${unit}` : String(d.value)\n}\n\nfunction CheckIcon (props: React.ComponentPropsWithoutRef<'svg'> & { size?: string | number }): JSX.Element {\n const { size, style, ...rest } = props\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width={size ?? 14}\n height={size ?? 14}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={3}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n style={style}\n {...rest}\n >\n <polyline points=\"20 6 9 17 4 12\" />\n </svg>\n )\n}\n\n// ─── Component ───────────────────────────────────────────────────────────────\n\nexport function HealthcareServiceCard ({\n name,\n specialty,\n badge,\n closable = false,\n onClose,\n actions,\n protocolSelection,\n onProtocolSelectionChange\n}: HealthcareServiceCardProps): JSX.Element {\n const handleChange = (value: string): void => {\n if (value !== protocolSelection?.actionId) {\n onProtocolSelectionChange?.({ actionId: value, addonIds: [] })\n }\n }\n\n const handleAddonToggle = (actionId: string, addonId: string, checked: boolean): void => {\n const current = protocolSelection?.addonIds ?? []\n const next = checked\n ? [...current, addonId]\n : current.filter((id) => id !== addonId)\n onProtocolSelectionChange?.({ actionId, addonIds: next })\n }\n\n return (\n <Card withBorder radius=\"md\" padding=\"lg\">\n <Stack gap=\"sm\">\n {/* Header: name + optional close; specialty + optional badge below */}\n <Stack gap={4}>\n <Group justify=\"space-between\" wrap=\"nowrap\" align=\"flex-start\" gap=\"xs\">\n <Text fw={700} size=\"lg\" style={{ flex: 1, minWidth: 0, lineHeight: 1.2 }}>{name}</Text>\n {closable && (\n <CloseButton\n onClick={onClose}\n size=\"sm\"\n c=\"red\"\n aria-label=\"Quitar\"\n style={{ flexShrink: 0 }}\n />\n )}\n </Group>\n {(specialty || badge) && (\n <Group gap={6} wrap=\"wrap\">\n {specialty && (\n <Badge variant=\"light\" color=\"blue\" radius=\"sm\" size=\"sm\">\n {specialty}\n </Badge>\n )}\n {badge}\n </Group>\n )}\n </Stack>\n\n {/* Action variants */}\n {actions.length === 1 && (() => {\n const action = actions[0]\n const duration = formatDuration(action.duration)\n const addons = (action.addons ?? []).filter((a) => !a.mandatory)\n const selectedAddons = protocolSelection?.actionId === action.id ? protocolSelection.addonIds ?? [] : []\n return (\n <Stack gap={4}>\n <Group gap=\"sm\" wrap=\"nowrap\" align=\"flex-start\">\n <Text component=\"span\" size=\"sm\" c=\"dark\" style={{ flex: 1, minWidth: 0, display: 'block' }}>{action.label}</Text>\n {duration && (\n <Text component=\"span\" size=\"xs\" c=\"dimmed\" style={{ flexShrink: 0 }}>{duration}</Text>\n )}\n </Group>\n {action.question && (\n <Text component=\"span\" size=\"xs\" c=\"dimmed\" style={{ display: 'block' }}>{action.question}</Text>\n )}\n {addons.length > 0 && (\n <Stack gap={2}>\n {addons.map((addon) => (\n <Switch\n key={addon.id}\n checked={selectedAddons.includes(addon.id)}\n onChange={(e) => handleAddonToggle(action.id, addon.id, e.currentTarget.checked)}\n size=\"xs\"\n label={\n <span>\n <Text component=\"span\" size=\"xs\" fw={500} style={{ display: 'block' }}>\n {addon.label}\n </Text>\n {addon.question && (\n <Text component=\"span\" size=\"xs\" c=\"dimmed\" style={{ display: 'block' }}>\n {addon.question}\n </Text>\n )}\n </span>\n }\n styles={{\n root: { cursor: 'pointer' },\n track: { cursor: 'pointer' },\n label: { cursor: 'pointer', paddingLeft: 6 },\n }}\n />\n ))}\n </Stack>\n )}\n </Stack>\n )\n })()}\n {actions.length > 1 && (\n <Radio.Group value={protocolSelection?.actionId ?? null} onChange={handleChange}>\n <Stack gap={6}>\n {actions.map((action) => {\n const duration = formatDuration(action.duration)\n const isSelected = action.id === protocolSelection?.actionId\n const addons = (action.addons ?? []).filter((a) => !a.mandatory)\n return (\n <Stack key={action.id} gap={0}>\n <Radio.Card\n value={action.id}\n radius=\"md\"\n p=\"xs\"\n withBorder\n style={{\n cursor: 'pointer',\n borderColor: isSelected\n ? 'var(--mantine-color-blue-4)'\n : 'var(--mantine-color-gray-2)',\n backgroundColor: isSelected\n ? 'var(--mantine-color-white)'\n : 'var(--mantine-color-gray-0)',\n }}\n >\n <Stack gap={2}>\n <Group gap=\"sm\" wrap=\"nowrap\" align=\"flex-start\">\n <Radio.Indicator\n icon={CheckIcon}\n size=\"xs\"\n style={{ flexShrink: 0 }}\n />\n <Text component=\"span\" size=\"sm\" c=\"dark\" style={{ flex: 1, minWidth: 0, display: 'block' }}>{action.label}</Text>\n {duration && (\n <Text component=\"span\" size=\"xs\" c=\"dimmed\" style={{ flexShrink: 0 }}>{duration}</Text>\n )}\n </Group>\n {action.question && (\n <Text component=\"span\" size=\"xs\" c=\"dimmed\" ml={28} style={{ display: 'block' }}>{action.question}</Text>\n )}\n </Stack>\n\n {/* Addons (toggles) — inside the selected card */}\n {isSelected && addons.length > 0 && (\n <Stack gap={2} mt={6} ml={28}>\n {addons.map((addon) => (\n <Switch\n key={addon.id}\n checked={protocolSelection.addonIds?.includes(addon.id)}\n onChange={(e) => handleAddonToggle(action.id, addon.id, e.currentTarget.checked)}\n size=\"xs\"\n label={\n <span>\n <Text component=\"span\" size=\"xs\" fw={500} style={{ display: 'block' }}>\n {addon.label}\n </Text>\n {addon.question && (\n <Text component=\"span\" size=\"xs\" c=\"dimmed\" style={{ display: 'block' }}>\n {addon.question}\n </Text>\n )}\n </span>\n }\n styles={{\n root: { cursor: 'pointer' },\n track: { cursor: 'pointer' },\n label: { cursor: 'pointer', paddingLeft: 6 },\n }}\n />\n ))}\n </Stack>\n )}\n </Radio.Card>\n </Stack>\n )\n })}\n </Stack>\n </Radio.Group>\n )}\n </Stack>\n </Card>\n )\n}\n"]}
1
+ {"version":3,"file":"HealthcareServiceCard.js","sourceRoot":"","sources":["../../src/HealthcareServiceCard/HealthcareServiceCard.tsx"],"names":[],"mappings":"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","sourcesContent":["import { Badge, Card, CloseButton, Group, Radio, Stack, Switch, Text } from '@mantine/core'\nimport type { Duration } from '@medplum/fhirtypes'\nimport React, { type JSX, type ReactNode } from 'react'\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\n/** A single protocol action entry to display in the card. */\nexport interface HealthcareServiceAction {\n /** Unique identifier for this action. */\n readonly id: string\n /** Display label for the action (e.g. \"Helicoidal\"). */\n readonly label: string\n /** User-facing question / hint for this action. */\n readonly question?: string\n /** FHIR Duration for this action. */\n readonly duration?: Duration\n /**\n * Only meaningful on addon entries. When `true`, the addon is always\n * included with its parent action and is hidden from the card UI — the\n * caller must still resolve and persist it server-side.\n */\n readonly mandatory?: boolean\n /** Optional addons (sub-actions with `any` selection). */\n readonly addons?: readonly HealthcareServiceAction[]\n}\n\nexport interface HealthcareServiceCardProps {\n /** Service display name. */\n readonly name: string\n /** Specialty display name (shown as a badge). */\n readonly specialty?: string\n /** Optional custom badge rendered inline next to the service name. */\n readonly badge?: ReactNode\n /**\n * Whether the study requires an appointment. When explicitly `false`, a\n * \"No requiere turno\" (walk-in) badge is shown. `undefined`/`true` renders\n * nothing. Mirrors `HealthcareService.appointmentRequired`.\n */\n readonly appointmentRequired?: boolean\n /** Whether to render a close button in the top-right corner. Defaults to false. */\n readonly closable?: boolean\n /** Callback invoked when the close button is clicked. Only relevant when `closable` is true. */\n readonly onClose?: () => void\n /** Protocol action variants the user can choose from. */\n readonly actions: readonly HealthcareServiceAction[]\n /** Current controlled selection for the chosen action and enabled addons. */\n readonly protocolSelection?: HealthcareServiceProtocolSelection\n /** Called whenever the controlled protocol selection changes. */\n readonly onProtocolSelectionChange?: (protocolSelection: HealthcareServiceProtocolSelection) => void\n}\n\nexport interface HealthcareServiceProtocolSelection {\n /** The `action.id` of the chosen top-level action. */\n readonly actionId: string\n /** The `action.id`s of toggled-on addon sub-actions within the selected action. */\n readonly addonIds?: readonly string[]\n}\n\n// ─── Helpers ─────────────────────────────────────────────────────────────────\n\nfunction formatDuration (d?: Duration): string | undefined {\n if (d?.value === undefined || d?.value === null) { return undefined }\n const unit = d.unit ?? d.code ?? ''\n return unit ? `${d.value} ${unit}` : String(d.value)\n}\n\nfunction CheckIcon (props: React.ComponentPropsWithoutRef<'svg'> & { size?: string | number }): JSX.Element {\n const { size, style, ...rest } = props\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width={size ?? 14}\n height={size ?? 14}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={3}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n style={style}\n {...rest}\n >\n <polyline points=\"20 6 9 17 4 12\" />\n </svg>\n )\n}\n\n// \"Walk-in / enter\" glyph shown next to the no-appointment-required note.\nfunction WalkInIcon (props: React.ComponentPropsWithoutRef<'svg'> & { size?: string | number }): JSX.Element {\n const { size, style, ...rest } = props\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width={size ?? 14}\n height={size ?? 14}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n style={style}\n {...rest}\n >\n <path d=\"M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4\" />\n <polyline points=\"10 17 15 12 10 7\" />\n <line x1=\"15\" y1=\"12\" x2=\"3\" y2=\"12\" />\n </svg>\n )\n}\n\n// ─── Component ───────────────────────────────────────────────────────────────\n\nexport function HealthcareServiceCard ({\n name,\n specialty,\n badge,\n appointmentRequired,\n closable = false,\n onClose,\n actions,\n protocolSelection,\n onProtocolSelectionChange\n}: HealthcareServiceCardProps): JSX.Element {\n const handleChange = (value: string): void => {\n if (value !== protocolSelection?.actionId) {\n onProtocolSelectionChange?.({ actionId: value, addonIds: [] })\n }\n }\n\n const handleAddonToggle = (actionId: string, addonId: string, checked: boolean): void => {\n const current = protocolSelection?.addonIds ?? []\n const next = checked\n ? [...current, addonId]\n : current.filter((id) => id !== addonId)\n onProtocolSelectionChange?.({ actionId, addonIds: next })\n }\n\n return (\n <Card withBorder radius=\"md\" padding=\"lg\">\n <Stack gap=\"sm\">\n {/* Header: name + optional close; specialty + optional badge below */}\n <Stack gap={4}>\n {appointmentRequired === false && (\n <Badge\n variant=\"light\"\n color=\"teal\"\n radius=\"sm\"\n size=\"sm\"\n leftSection={<WalkInIcon size={12} style={{ display: 'block' }} />}\n style={{ alignSelf: 'flex-start' }}\n >\n No requiere turno\n </Badge>\n )}\n <Group justify=\"space-between\" wrap=\"nowrap\" align=\"flex-start\" gap=\"xs\">\n <Text fw={700} size=\"lg\" style={{ flex: 1, minWidth: 0, lineHeight: 1.2 }}>{name}</Text>\n {closable && (\n <CloseButton\n onClick={onClose}\n size=\"sm\"\n c=\"red\"\n aria-label=\"Quitar\"\n style={{ flexShrink: 0 }}\n />\n )}\n </Group>\n {(specialty || badge) && (\n <Group gap={6} wrap=\"wrap\">\n {specialty && (\n <Badge variant=\"light\" color=\"blue\" radius=\"sm\" size=\"sm\">\n {specialty}\n </Badge>\n )}\n {badge}\n </Group>\n )}\n </Stack>\n\n {/* Action variants */}\n {actions.length === 1 && (() => {\n const action = actions[0]\n const duration = formatDuration(action.duration)\n const addons = (action.addons ?? []).filter((a) => !a.mandatory)\n const selectedAddons = protocolSelection?.actionId === action.id ? protocolSelection.addonIds ?? [] : []\n return (\n <Stack gap={4}>\n <Group gap=\"sm\" wrap=\"nowrap\" align=\"flex-start\">\n <Text component=\"span\" size=\"sm\" c=\"dark\" style={{ flex: 1, minWidth: 0, display: 'block' }}>{action.label}</Text>\n {duration && (\n <Text component=\"span\" size=\"xs\" c=\"dimmed\" style={{ flexShrink: 0 }}>{duration}</Text>\n )}\n </Group>\n {action.question && (\n <Text component=\"span\" size=\"xs\" c=\"dimmed\" style={{ display: 'block' }}>{action.question}</Text>\n )}\n {addons.length > 0 && (\n <Stack gap={2}>\n {addons.map((addon) => (\n <Switch\n key={addon.id}\n checked={selectedAddons.includes(addon.id)}\n onChange={(e) => handleAddonToggle(action.id, addon.id, e.currentTarget.checked)}\n size=\"xs\"\n label={\n <span>\n <Text component=\"span\" size=\"xs\" fw={500} style={{ display: 'block' }}>\n {addon.label}\n </Text>\n {addon.question && (\n <Text component=\"span\" size=\"xs\" c=\"dimmed\" style={{ display: 'block' }}>\n {addon.question}\n </Text>\n )}\n </span>\n }\n styles={{\n root: { cursor: 'pointer' },\n track: { cursor: 'pointer' },\n label: { cursor: 'pointer', paddingLeft: 6 },\n }}\n />\n ))}\n </Stack>\n )}\n </Stack>\n )\n })()}\n {actions.length > 1 && (\n <Radio.Group value={protocolSelection?.actionId ?? null} onChange={handleChange}>\n <Stack gap={6}>\n {actions.map((action) => {\n const duration = formatDuration(action.duration)\n const isSelected = action.id === protocolSelection?.actionId\n const addons = (action.addons ?? []).filter((a) => !a.mandatory)\n return (\n <Stack key={action.id} gap={0}>\n <Radio.Card\n value={action.id}\n radius=\"md\"\n p=\"xs\"\n withBorder\n style={{\n cursor: 'pointer',\n borderColor: isSelected\n ? 'var(--mantine-color-blue-4)'\n : 'var(--mantine-color-gray-2)',\n backgroundColor: isSelected\n ? 'var(--mantine-color-white)'\n : 'var(--mantine-color-gray-0)',\n }}\n >\n <Stack gap={2}>\n <Group gap=\"sm\" wrap=\"nowrap\" align=\"flex-start\">\n <Radio.Indicator\n icon={CheckIcon}\n size=\"xs\"\n style={{ flexShrink: 0 }}\n />\n <Text component=\"span\" size=\"sm\" c=\"dark\" style={{ flex: 1, minWidth: 0, display: 'block' }}>{action.label}</Text>\n {duration && (\n <Text component=\"span\" size=\"xs\" c=\"dimmed\" style={{ flexShrink: 0 }}>{duration}</Text>\n )}\n </Group>\n {action.question && (\n <Text component=\"span\" size=\"xs\" c=\"dimmed\" ml={28} style={{ display: 'block' }}>{action.question}</Text>\n )}\n </Stack>\n\n {/* Addons (toggles) — inside the selected card */}\n {isSelected && addons.length > 0 && (\n <Stack gap={2} mt={6} ml={28}>\n {addons.map((addon) => (\n <Switch\n key={addon.id}\n checked={protocolSelection.addonIds?.includes(addon.id)}\n onChange={(e) => handleAddonToggle(action.id, addon.id, e.currentTarget.checked)}\n size=\"xs\"\n label={\n <span>\n <Text component=\"span\" size=\"xs\" fw={500} style={{ display: 'block' }}>\n {addon.label}\n </Text>\n {addon.question && (\n <Text component=\"span\" size=\"xs\" c=\"dimmed\" style={{ display: 'block' }}>\n {addon.question}\n </Text>\n )}\n </span>\n }\n styles={{\n root: { cursor: 'pointer' },\n track: { cursor: 'pointer' },\n label: { cursor: 'pointer', paddingLeft: 6 },\n }}\n />\n ))}\n </Stack>\n )}\n </Radio.Card>\n </Stack>\n )\n })}\n </Stack>\n </Radio.Group>\n )}\n </Stack>\n </Card>\n )\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"HealthcareServiceDirectory.d.ts","sourceRoot":"","sources":["../../src/HealthcareServiceDirectory/HealthcareServiceDirectory.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AAC3D,OAAO,EAA6C,KAAK,GAAG,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAI3F,MAAM,WAAW,+BAA+B;IAC9C,oFAAoF;IACpF,QAAQ,CAAC,aAAa,EAAE,MAAM,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAAA;IAC1D,6CAA6C;IAC7C,QAAQ,CAAC,WAAW,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAA;IAC1C,6DAA6D;IAC7D,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,iBAAiB,KAAK,IAAI,CAAA;IACxD,sGAAsG;IACtG,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,iBAAiB,EAAE,QAAQ,EAAE,OAAO,KAAK,SAAS,CAAA;IACrF,iFAAiF;IACjF,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,CAAA;IAC/B,iFAAiF;IACjF,QAAQ,CAAC,YAAY,CAAC,EAAE,SAAS,CAAA;IACjC,mFAAmF;IACnF,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,CAAA;CAC5B;AA0ED,wBAAgB,0BAA0B,CAAC,EACzC,aAAa,EACb,WAAW,EACX,QAAQ,EACR,aAAa,EACb,UAAU,EACV,YAAY,EACZ,MAAM,GACP,EAAE,+BAA+B,GAAG,GAAG,CAAC,OAAO,CAyG/C"}
1
+ {"version":3,"file":"HealthcareServiceDirectory.d.ts","sourceRoot":"","sources":["../../src/HealthcareServiceDirectory/HealthcareServiceDirectory.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AAC3D,OAAO,EAA6C,KAAK,GAAG,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAI3F,MAAM,WAAW,+BAA+B;IAC9C,oFAAoF;IACpF,QAAQ,CAAC,aAAa,EAAE,MAAM,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAAA;IAC1D,6CAA6C;IAC7C,QAAQ,CAAC,WAAW,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAA;IAC1C,6DAA6D;IAC7D,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,iBAAiB,KAAK,IAAI,CAAA;IACxD,sGAAsG;IACtG,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,iBAAiB,EAAE,QAAQ,EAAE,OAAO,KAAK,SAAS,CAAA;IACrF,iFAAiF;IACjF,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,CAAA;IAC/B,iFAAiF;IACjF,QAAQ,CAAC,YAAY,CAAC,EAAE,SAAS,CAAA;IACjC,mFAAmF;IACnF,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,CAAA;CAC5B;AA0ED,wBAAgB,0BAA0B,CAAC,EACzC,aAAa,EACb,WAAW,EACX,QAAQ,EACR,aAAa,EACb,UAAU,EACV,YAAY,EACZ,MAAM,GACP,EAAE,+BAA+B,GAAG,GAAG,CAAC,OAAO,CAyG/C"}
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Accordion, ActionIcon, Alert, Group, Loader, Stack, Text, } from '@mantine/core';
2
+ import { Accordion, ActionIcon, Alert, Badge, Group, Loader, Stack, Text, } from '@mantine/core';
3
3
  import { useCallback, useEffect, useMemo, useState } from 'react';
4
4
  // ─── Helpers ─────────────────────────────────────────────────────────────────
5
5
  function getSpecialty(hs) {
@@ -92,7 +92,7 @@ function ServiceList({ services, selectedIds, onSelect, renderService, selectIco
92
92
  var _a, _b, _c, _d, _e, _f, _g;
93
93
  const id = (_a = hs.id) !== null && _a !== void 0 ? _a : '';
94
94
  const selected = (_b = selectedIds === null || selectedIds === void 0 ? void 0 : selectedIds.has(id)) !== null && _b !== void 0 ? _b : false;
95
- return (_jsxs(Group, { justify: "space-between", wrap: "nowrap", py: 4, children: [renderService ? (renderService(hs, selected)) : (_jsxs(Stack, { gap: 0, children: [_jsx(Text, { size: "sm", children: (_c = hs.name) !== null && _c !== void 0 ? _c : id }), ((_g = (_f = (_e = (_d = hs.category) === null || _d === void 0 ? void 0 : _d[0]) === null || _e === void 0 ? void 0 : _e.coding) === null || _f === void 0 ? void 0 : _f[0]) === null || _g === void 0 ? void 0 : _g.display) && (_jsx(Text, { size: "xs", c: "dimmed", children: hs.category[0].coding[0].display }))] })), _jsx(ActionIcon, { variant: selected ? 'filled' : 'light', color: selected ? 'green' : 'blue', onClick: () => onSelect(hs), disabled: selected, children: selected
95
+ return (_jsxs(Group, { justify: "space-between", wrap: "nowrap", py: 4, children: [renderService ? (renderService(hs, selected)) : (_jsxs(Stack, { gap: 2, children: [_jsx(Text, { size: "sm", children: (_c = hs.name) !== null && _c !== void 0 ? _c : id }), _jsxs(Group, { gap: 6, wrap: "wrap", children: [((_g = (_f = (_e = (_d = hs.category) === null || _d === void 0 ? void 0 : _d[0]) === null || _e === void 0 ? void 0 : _e.coding) === null || _f === void 0 ? void 0 : _f[0]) === null || _g === void 0 ? void 0 : _g.display) && (_jsx(Text, { size: "xs", c: "dimmed", children: hs.category[0].coding[0].display })), hs.appointmentRequired === false && (_jsx(Badge, { variant: "light", color: "teal", radius: "sm", size: "xs", children: "No requiere turno" }))] })] })), _jsx(ActionIcon, { variant: selected ? 'filled' : 'light', color: selected ? 'green' : 'blue', onClick: () => onSelect(hs), disabled: selected, children: selected
96
96
  ? (selectedIcon !== null && selectedIcon !== void 0 ? selectedIcon : _jsx(CheckIcon, {}))
97
97
  : (selectIcon !== null && selectIcon !== void 0 ? selectIcon : _jsx(PlusIcon, {})) })] }, id));
98
98
  }) }));
@@ -1 +1 @@
1
- {"version":3,"file":"HealthcareServiceDirectory.js","sourceRoot":"","sources":["../../src/HealthcareServiceDirectory/HealthcareServiceDirectory.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n Accordion,\n ActionIcon,\n Alert,\n Group,\n Loader,\n Stack,\n Text,\n} from '@mantine/core'\nimport type { HealthcareService } from '@medplum/fhirtypes'\nimport { useCallback, useEffect, useMemo, useState, type JSX, type ReactNode } from 'react'\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\nexport interface HealthcareServiceDirectoryProps {\n /** Function that fetches all HealthcareService resources to display in the tree. */\n readonly fetchServices: () => Promise<HealthcareService[]>\n /** Set of currently selected service IDs. */\n readonly selectedIds?: ReadonlySet<string>\n /** Called when the user clicks on a service to select it. */\n readonly onSelect?: (service: HealthcareService) => void\n /** Optional custom renderer for each service row. Receives the service and whether it is selected. */\n readonly renderService?: (service: HealthcareService, selected: boolean) => ReactNode\n /** Icon element for the select button when unselected. Defaults to a \"+\" SVG. */\n readonly selectIcon?: ReactNode\n /** Icon element for the select button when selected. Defaults to a check SVG. */\n readonly selectedIcon?: ReactNode\n /** Content to show at the bottom of the directory (e.g. fallback/contact info). */\n readonly footer?: ReactNode\n}\n\ninterface TreeCategory {\n name: string\n children: TreeSubcategory[]\n}\n\ninterface TreeSubcategory {\n name: string\n services: HealthcareService[]\n}\n\n// ─── Helpers ─────────────────────────────────────────────────────────────────\n\nfunction getSpecialty(hs: HealthcareService): string {\n return hs.specialty?.[0]?.coding?.[0]?.display ?? 'Otros'\n}\n\nfunction getCategory(hs: HealthcareService): string {\n return hs.category?.[0]?.coding?.[0]?.display ?? 'General'\n}\n\nfunction buildTree(services: HealthcareService[]): TreeCategory[] {\n const specialtyMap = new Map<string, Map<string, HealthcareService[]>>()\n\n for (const hs of services) {\n const specialty = getSpecialty(hs)\n const category = getCategory(hs)\n\n let catMap = specialtyMap.get(specialty)\n if (!catMap) {\n catMap = new Map()\n specialtyMap.set(specialty, catMap)\n }\n\n let list = catMap.get(category)\n if (!list) {\n list = []\n catMap.set(category, list)\n }\n list.push(hs)\n }\n\n const tree: TreeCategory[] = []\n for (const [specialty, catMap] of specialtyMap) {\n const children: TreeSubcategory[] = []\n for (const [category, svcs] of catMap) {\n children.push({ name: category, services: svcs })\n }\n tree.push({ name: specialty, children })\n }\n\n return tree\n}\n\nfunction PlusIcon(): JSX.Element {\n return (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={16} height={16} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\" />\n <line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\" />\n </svg>\n )\n}\n\nfunction CheckIcon(): JSX.Element {\n return (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={16} height={16} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <polyline points=\"20 6 9 17 4 12\" />\n </svg>\n )\n}\n\n// ─── Component ───────────────────────────────────────────────────────────────\n\nexport function HealthcareServiceDirectory({\n fetchServices,\n selectedIds,\n onSelect,\n renderService,\n selectIcon,\n selectedIcon,\n footer,\n}: HealthcareServiceDirectoryProps): JSX.Element {\n const [services, setServices] = useState<HealthcareService[]>([])\n const [loading, setLoading] = useState(true)\n const [error, setError] = useState<string>()\n\n useEffect(() => {\n let cancelled = false\n setLoading(true)\n setError(undefined)\n\n fetchServices()\n .then((result) => {\n if (!cancelled) {\n setServices(result)\n }\n })\n .catch((err) => {\n if (!cancelled) {\n setError(err instanceof Error ? err.message : String(err))\n }\n })\n .finally(() => {\n if (!cancelled) {\n setLoading(false)\n }\n })\n\n return () => { cancelled = true }\n }, [fetchServices])\n\n const tree = useMemo(() => buildTree(services), [services])\n\n const handleSelect = useCallback(\n (hs: HealthcareService) => {\n if (selectedIds?.has(hs.id ?? '')) {\n return\n }\n onSelect?.(hs)\n },\n [selectedIds, onSelect]\n )\n\n if (loading) {\n return (\n <Stack align=\"center\" py=\"xl\">\n <Loader size=\"md\" />\n </Stack>\n )\n }\n\n if (error) {\n return (\n <Alert color=\"red\" title=\"Error\">\n {error}\n </Alert>\n )\n }\n\n return (\n <Stack gap=\"md\">\n <Accordion variant=\"separated\">\n {tree.map((specialty) => (\n <Accordion.Item key={specialty.name} value={specialty.name}>\n <Accordion.Control>\n <Text fw={500}>{specialty.name}</Text>\n </Accordion.Control>\n <Accordion.Panel>\n {specialty.children.length === 1 ? (\n <ServiceList\n services={specialty.children[0].services}\n selectedIds={selectedIds}\n onSelect={handleSelect}\n renderService={renderService}\n selectIcon={selectIcon}\n selectedIcon={selectedIcon}\n />\n ) : (\n <Accordion variant=\"default\">\n {specialty.children.map((sub) => (\n <Accordion.Item key={sub.name} value={sub.name}>\n <Accordion.Control>\n <Text size=\"sm\">{sub.name}</Text>\n </Accordion.Control>\n <Accordion.Panel>\n <ServiceList\n services={sub.services}\n selectedIds={selectedIds}\n onSelect={handleSelect}\n renderService={renderService}\n selectIcon={selectIcon}\n selectedIcon={selectedIcon}\n />\n </Accordion.Panel>\n </Accordion.Item>\n ))}\n </Accordion>\n )}\n </Accordion.Panel>\n </Accordion.Item>\n ))}\n </Accordion>\n\n {footer}\n </Stack>\n )\n}\n\n// ─── ServiceList ─────────────────────────────────────────────────────────────\n\nfunction ServiceList({\n services,\n selectedIds,\n onSelect,\n renderService,\n selectIcon,\n selectedIcon,\n}: {\n services: HealthcareService[]\n selectedIds?: ReadonlySet<string>\n onSelect: (hs: HealthcareService) => void\n renderService?: (hs: HealthcareService, selected: boolean) => ReactNode\n selectIcon?: ReactNode\n selectedIcon?: ReactNode\n}): JSX.Element {\n return (\n <Stack gap=\"xs\">\n {services.map((hs) => {\n const id = hs.id ?? ''\n const selected = selectedIds?.has(id) ?? false\n return (\n <Group key={id} justify=\"space-between\" wrap=\"nowrap\" py={4}>\n {renderService ? (\n renderService(hs, selected)\n ) : (\n <Stack gap={0}>\n <Text size=\"sm\">{hs.name ?? id}</Text>\n {hs.category?.[0]?.coding?.[0]?.display && (\n <Text size=\"xs\" c=\"dimmed\">\n {hs.category[0].coding[0].display}\n </Text>\n )}\n </Stack>\n )}\n <ActionIcon\n variant={selected ? 'filled' : 'light'}\n color={selected ? 'green' : 'blue'}\n onClick={() => onSelect(hs)}\n disabled={selected}\n >\n {selected\n ? (selectedIcon ?? <CheckIcon />)\n : (selectIcon ?? <PlusIcon />)}\n </ActionIcon>\n </Group>\n )\n })}\n </Stack>\n )\n}\n"]}
1
+ {"version":3,"file":"HealthcareServiceDirectory.js","sourceRoot":"","sources":["../../src/HealthcareServiceDirectory/HealthcareServiceDirectory.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n Accordion,\n ActionIcon,\n Alert,\n Badge,\n Group,\n Loader,\n Stack,\n Text,\n} from '@mantine/core'\nimport type { HealthcareService } from '@medplum/fhirtypes'\nimport { useCallback, useEffect, useMemo, useState, type JSX, type ReactNode } from 'react'\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\nexport interface HealthcareServiceDirectoryProps {\n /** Function that fetches all HealthcareService resources to display in the tree. */\n readonly fetchServices: () => Promise<HealthcareService[]>\n /** Set of currently selected service IDs. */\n readonly selectedIds?: ReadonlySet<string>\n /** Called when the user clicks on a service to select it. */\n readonly onSelect?: (service: HealthcareService) => void\n /** Optional custom renderer for each service row. Receives the service and whether it is selected. */\n readonly renderService?: (service: HealthcareService, selected: boolean) => ReactNode\n /** Icon element for the select button when unselected. Defaults to a \"+\" SVG. */\n readonly selectIcon?: ReactNode\n /** Icon element for the select button when selected. Defaults to a check SVG. */\n readonly selectedIcon?: ReactNode\n /** Content to show at the bottom of the directory (e.g. fallback/contact info). */\n readonly footer?: ReactNode\n}\n\ninterface TreeCategory {\n name: string\n children: TreeSubcategory[]\n}\n\ninterface TreeSubcategory {\n name: string\n services: HealthcareService[]\n}\n\n// ─── Helpers ─────────────────────────────────────────────────────────────────\n\nfunction getSpecialty(hs: HealthcareService): string {\n return hs.specialty?.[0]?.coding?.[0]?.display ?? 'Otros'\n}\n\nfunction getCategory(hs: HealthcareService): string {\n return hs.category?.[0]?.coding?.[0]?.display ?? 'General'\n}\n\nfunction buildTree(services: HealthcareService[]): TreeCategory[] {\n const specialtyMap = new Map<string, Map<string, HealthcareService[]>>()\n\n for (const hs of services) {\n const specialty = getSpecialty(hs)\n const category = getCategory(hs)\n\n let catMap = specialtyMap.get(specialty)\n if (!catMap) {\n catMap = new Map()\n specialtyMap.set(specialty, catMap)\n }\n\n let list = catMap.get(category)\n if (!list) {\n list = []\n catMap.set(category, list)\n }\n list.push(hs)\n }\n\n const tree: TreeCategory[] = []\n for (const [specialty, catMap] of specialtyMap) {\n const children: TreeSubcategory[] = []\n for (const [category, svcs] of catMap) {\n children.push({ name: category, services: svcs })\n }\n tree.push({ name: specialty, children })\n }\n\n return tree\n}\n\nfunction PlusIcon(): JSX.Element {\n return (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={16} height={16} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\" />\n <line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\" />\n </svg>\n )\n}\n\nfunction CheckIcon(): JSX.Element {\n return (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={16} height={16} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <polyline points=\"20 6 9 17 4 12\" />\n </svg>\n )\n}\n\n// ─── Component ───────────────────────────────────────────────────────────────\n\nexport function HealthcareServiceDirectory({\n fetchServices,\n selectedIds,\n onSelect,\n renderService,\n selectIcon,\n selectedIcon,\n footer,\n}: HealthcareServiceDirectoryProps): JSX.Element {\n const [services, setServices] = useState<HealthcareService[]>([])\n const [loading, setLoading] = useState(true)\n const [error, setError] = useState<string>()\n\n useEffect(() => {\n let cancelled = false\n setLoading(true)\n setError(undefined)\n\n fetchServices()\n .then((result) => {\n if (!cancelled) {\n setServices(result)\n }\n })\n .catch((err) => {\n if (!cancelled) {\n setError(err instanceof Error ? err.message : String(err))\n }\n })\n .finally(() => {\n if (!cancelled) {\n setLoading(false)\n }\n })\n\n return () => { cancelled = true }\n }, [fetchServices])\n\n const tree = useMemo(() => buildTree(services), [services])\n\n const handleSelect = useCallback(\n (hs: HealthcareService) => {\n if (selectedIds?.has(hs.id ?? '')) {\n return\n }\n onSelect?.(hs)\n },\n [selectedIds, onSelect]\n )\n\n if (loading) {\n return (\n <Stack align=\"center\" py=\"xl\">\n <Loader size=\"md\" />\n </Stack>\n )\n }\n\n if (error) {\n return (\n <Alert color=\"red\" title=\"Error\">\n {error}\n </Alert>\n )\n }\n\n return (\n <Stack gap=\"md\">\n <Accordion variant=\"separated\">\n {tree.map((specialty) => (\n <Accordion.Item key={specialty.name} value={specialty.name}>\n <Accordion.Control>\n <Text fw={500}>{specialty.name}</Text>\n </Accordion.Control>\n <Accordion.Panel>\n {specialty.children.length === 1 ? (\n <ServiceList\n services={specialty.children[0].services}\n selectedIds={selectedIds}\n onSelect={handleSelect}\n renderService={renderService}\n selectIcon={selectIcon}\n selectedIcon={selectedIcon}\n />\n ) : (\n <Accordion variant=\"default\">\n {specialty.children.map((sub) => (\n <Accordion.Item key={sub.name} value={sub.name}>\n <Accordion.Control>\n <Text size=\"sm\">{sub.name}</Text>\n </Accordion.Control>\n <Accordion.Panel>\n <ServiceList\n services={sub.services}\n selectedIds={selectedIds}\n onSelect={handleSelect}\n renderService={renderService}\n selectIcon={selectIcon}\n selectedIcon={selectedIcon}\n />\n </Accordion.Panel>\n </Accordion.Item>\n ))}\n </Accordion>\n )}\n </Accordion.Panel>\n </Accordion.Item>\n ))}\n </Accordion>\n\n {footer}\n </Stack>\n )\n}\n\n// ─── ServiceList ─────────────────────────────────────────────────────────────\n\nfunction ServiceList({\n services,\n selectedIds,\n onSelect,\n renderService,\n selectIcon,\n selectedIcon,\n}: {\n services: HealthcareService[]\n selectedIds?: ReadonlySet<string>\n onSelect: (hs: HealthcareService) => void\n renderService?: (hs: HealthcareService, selected: boolean) => ReactNode\n selectIcon?: ReactNode\n selectedIcon?: ReactNode\n}): JSX.Element {\n return (\n <Stack gap=\"xs\">\n {services.map((hs) => {\n const id = hs.id ?? ''\n const selected = selectedIds?.has(id) ?? false\n return (\n <Group key={id} justify=\"space-between\" wrap=\"nowrap\" py={4}>\n {renderService ? (\n renderService(hs, selected)\n ) : (\n <Stack gap={2}>\n <Text size=\"sm\">{hs.name ?? id}</Text>\n <Group gap={6} wrap=\"wrap\">\n {hs.category?.[0]?.coding?.[0]?.display && (\n <Text size=\"xs\" c=\"dimmed\">\n {hs.category[0].coding[0].display}\n </Text>\n )}\n {hs.appointmentRequired === false && (\n <Badge variant=\"light\" color=\"teal\" radius=\"sm\" size=\"xs\">\n No requiere turno\n </Badge>\n )}\n </Group>\n </Stack>\n )}\n <ActionIcon\n variant={selected ? 'filled' : 'light'}\n color={selected ? 'green' : 'blue'}\n onClick={() => onSelect(hs)}\n disabled={selected}\n >\n {selected\n ? (selectedIcon ?? <CheckIcon />)\n : (selectIcon ?? <PlusIcon />)}\n </ActionIcon>\n </Group>\n )\n })}\n </Stack>\n )\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"HealthcareServiceAutocomplete.d.ts","sourceRoot":"","sources":["../../src/search/HealthcareServiceAutocomplete.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAA2B,MAAM,eAAe,CAAA;AAC1E,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AAGtD,OAAO,EAAE,GAAG,EAAe,MAAM,OAAO,CAAA;AAGxC,MAAM,WAAW,kCACf,SAAQ,IAAI,CAAC,iBAAiB,EAAE,MAAM,GAAG,OAAO,GAAG,cAAc,GAAG,UAAU,GAAG,gBAAgB,CAAC;IAClG,QAAQ,CAAC,KAAK,CAAC,EAAE,iBAAiB,CAAA;IAClC,QAAQ,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,iBAAiB,GAAG,SAAS,KAAK,IAAI,CAAA;IACnE,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;IAC7B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAA;CACjC;AAgBD,wBAAgB,6BAA6B,CAAE,KAAK,EAAE,kCAAkC,GAAG,GAAG,CAAC,OAAO,CA6DrG"}
1
+ {"version":3,"file":"HealthcareServiceAutocomplete.d.ts","sourceRoot":"","sources":["../../src/search/HealthcareServiceAutocomplete.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAA2B,MAAM,eAAe,CAAA;AAC1E,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AAGtD,OAAO,EAAE,GAAG,EAAe,MAAM,OAAO,CAAA;AAGxC,MAAM,WAAW,kCACf,SAAQ,IAAI,CAAC,iBAAiB,EAAE,MAAM,GAAG,OAAO,GAAG,cAAc,GAAG,UAAU,GAAG,gBAAgB,CAAC;IAClG,QAAQ,CAAC,KAAK,CAAC,EAAE,iBAAiB,CAAA;IAClC,QAAQ,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,iBAAiB,GAAG,SAAS,KAAK,IAAI,CAAA;IACnE,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;IAC7B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAA;CACjC;AAgBD,wBAAgB,6BAA6B,CAAE,KAAK,EAAE,kCAAkC,GAAG,GAAG,CAAC,OAAO,CAgErG"}
@@ -37,7 +37,7 @@ export function HealthcareServiceAutocomplete(props) {
37
37
  var _a, _b;
38
38
  const name = (_b = (_a = hs.name) !== null && _a !== void 0 ? _a : hs.id) !== null && _b !== void 0 ? _b : '';
39
39
  const code = getServiceCode(hs);
40
- return (_jsxs(Group, { gap: "xs", wrap: "nowrap", style: { width: '100%' }, children: [_jsxs(Box, { style: { flex: 1, minWidth: 0 }, children: [_jsx(Text, { size: "sm", fw: 500, truncate: true, children: name }), hs.active === false && (_jsx(Text, { size: "xs", c: "dimmed", children: "Inactivo" }))] }), code && (_jsx(Badge, { size: "xs", variant: "light", color: "blue", style: { flexShrink: 0 }, children: code }))] }));
40
+ return (_jsxs(Group, { gap: "xs", wrap: "nowrap", style: { width: '100%' }, children: [_jsxs(Box, { style: { flex: 1, minWidth: 0 }, children: [_jsx(Text, { size: "sm", fw: 500, truncate: true, children: name }), hs.active === false && (_jsx(Text, { size: "xs", c: "dimmed", children: "Inactivo" })), hs.appointmentRequired === false && (_jsx(Text, { size: "xs", c: "teal", children: "No requiere turno" }))] }), code && (_jsx(Badge, { size: "xs", variant: "light", color: "blue", style: { flexShrink: 0 }, children: code }))] }));
41
41
  } }));
42
42
  }
43
43
  //# sourceMappingURL=HealthcareServiceAutocomplete.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"HealthcareServiceAutocomplete.js","sourceRoot":"","sources":["../../src/search/HealthcareServiceAutocomplete.tsx"],"names":[],"mappings":"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","sourcesContent":["import { AutocompleteProps, Badge, Box, Group, Text } from '@mantine/core'\nimport { HealthcareService } from '@medplum/fhirtypes'\nimport { ContentType } from '@medplum/core'\nimport { useMedplum } from '@medplum/react'\nimport { JSX, useCallback } from 'react'\nimport { ServiceAutocomplete } from './ServiceAutocomplete'\n\nexport interface HealthcareServiceAutocompleteProps\n extends Omit<AutocompleteProps, 'data' | 'value' | 'defaultValue' | 'onChange' | 'onOptionSubmit'> {\n readonly value?: HealthcareService\n readonly onChange: (service: HealthcareService | undefined) => void\n readonly placeholder?: string\n readonly count?: number\n readonly minQueryLength?: number\n}\n\nconst SERVICE_CODES_SYSTEM = 'http://fuego.health/fhir/service-codes'\n\nfunction getServiceCode (hs: HealthcareService | undefined): string {\n return hs?.identifier?.find((id) => id.system === SERVICE_CODES_SYSTEM)?.value ?? ''\n}\n\nfunction getServiceId (hs: HealthcareService): string {\n return hs.id ?? ''\n}\n\nfunction getServiceLabel (hs: HealthcareService): string {\n return hs.name ?? hs.id ?? ''\n}\n\nexport function HealthcareServiceAutocomplete (props: HealthcareServiceAutocompleteProps): JSX.Element {\n const {\n value,\n onChange,\n placeholder = 'Buscar servicio...',\n count = 20,\n minQueryLength = 2,\n ...inputProps\n } = props\n\n const medplum = useMedplum()\n\n const searchFn = useCallback(async (query: string): Promise<HealthcareService[]> => {\n const bundle = await medplum.post(\n medplum.fhirUrl('HealthcareService', '$lookup'),\n {\n resourceType: 'Parameters',\n parameter: [\n { name: 'q', valueString: query },\n { name: 'count', valueInteger: count }\n ]\n },\n ContentType.FHIR_JSON\n )\n return (bundle?.entry ?? [])\n .map((entry: any) => entry.resource as HealthcareService)\n .filter((r: HealthcareService | undefined): r is HealthcareService => !!r)\n }, [medplum, count])\n\n return (\n <ServiceAutocomplete<HealthcareService>\n {...inputProps}\n searchFn={searchFn}\n getId={getServiceId}\n getLabel={getServiceLabel}\n getCode={getServiceCode}\n value={value}\n onChange={onChange}\n placeholder={placeholder}\n minQueryLength={minQueryLength}\n renderOption={(hs) => {\n const name = hs.name ?? hs.id ?? ''\n const code = getServiceCode(hs)\n return (\n <Group gap=\"xs\" wrap=\"nowrap\" style={{ width: '100%' }}>\n <Box style={{ flex: 1, minWidth: 0 }}>\n <Text size=\"sm\" fw={500} truncate>{name}</Text>\n {hs.active === false && (\n <Text size=\"xs\" c=\"dimmed\">Inactivo</Text>\n )}\n </Box>\n {code && (\n <Badge size=\"xs\" variant=\"light\" color=\"blue\" style={{ flexShrink: 0 }}>\n {code}\n </Badge>\n )}\n </Group>\n )\n }}\n />\n )\n}\n"]}
1
+ {"version":3,"file":"HealthcareServiceAutocomplete.js","sourceRoot":"","sources":["../../src/search/HealthcareServiceAutocomplete.tsx"],"names":[],"mappings":"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","sourcesContent":["import { AutocompleteProps, Badge, Box, Group, Text } from '@mantine/core'\nimport { HealthcareService } from '@medplum/fhirtypes'\nimport { ContentType } from '@medplum/core'\nimport { useMedplum } from '@medplum/react'\nimport { JSX, useCallback } from 'react'\nimport { ServiceAutocomplete } from './ServiceAutocomplete'\n\nexport interface HealthcareServiceAutocompleteProps\n extends Omit<AutocompleteProps, 'data' | 'value' | 'defaultValue' | 'onChange' | 'onOptionSubmit'> {\n readonly value?: HealthcareService\n readonly onChange: (service: HealthcareService | undefined) => void\n readonly placeholder?: string\n readonly count?: number\n readonly minQueryLength?: number\n}\n\nconst SERVICE_CODES_SYSTEM = 'http://fuego.health/fhir/service-codes'\n\nfunction getServiceCode (hs: HealthcareService | undefined): string {\n return hs?.identifier?.find((id) => id.system === SERVICE_CODES_SYSTEM)?.value ?? ''\n}\n\nfunction getServiceId (hs: HealthcareService): string {\n return hs.id ?? ''\n}\n\nfunction getServiceLabel (hs: HealthcareService): string {\n return hs.name ?? hs.id ?? ''\n}\n\nexport function HealthcareServiceAutocomplete (props: HealthcareServiceAutocompleteProps): JSX.Element {\n const {\n value,\n onChange,\n placeholder = 'Buscar servicio...',\n count = 20,\n minQueryLength = 2,\n ...inputProps\n } = props\n\n const medplum = useMedplum()\n\n const searchFn = useCallback(async (query: string): Promise<HealthcareService[]> => {\n const bundle = await medplum.post(\n medplum.fhirUrl('HealthcareService', '$lookup'),\n {\n resourceType: 'Parameters',\n parameter: [\n { name: 'q', valueString: query },\n { name: 'count', valueInteger: count }\n ]\n },\n ContentType.FHIR_JSON\n )\n return (bundle?.entry ?? [])\n .map((entry: any) => entry.resource as HealthcareService)\n .filter((r: HealthcareService | undefined): r is HealthcareService => !!r)\n }, [medplum, count])\n\n return (\n <ServiceAutocomplete<HealthcareService>\n {...inputProps}\n searchFn={searchFn}\n getId={getServiceId}\n getLabel={getServiceLabel}\n getCode={getServiceCode}\n value={value}\n onChange={onChange}\n placeholder={placeholder}\n minQueryLength={minQueryLength}\n renderOption={(hs) => {\n const name = hs.name ?? hs.id ?? ''\n const code = getServiceCode(hs)\n return (\n <Group gap=\"xs\" wrap=\"nowrap\" style={{ width: '100%' }}>\n <Box style={{ flex: 1, minWidth: 0 }}>\n <Text size=\"sm\" fw={500} truncate>{name}</Text>\n {hs.active === false && (\n <Text size=\"xs\" c=\"dimmed\">Inactivo</Text>\n )}\n {hs.appointmentRequired === false && (\n <Text size=\"xs\" c=\"teal\">No requiere turno</Text>\n )}\n </Box>\n {code && (\n <Badge size=\"xs\" variant=\"light\" color=\"blue\" style={{ flexShrink: 0 }}>\n {code}\n </Badge>\n )}\n </Group>\n )\n }}\n />\n )\n}\n"]}