@burdenoff/microfe-crewfoundry 2026.1102.2 → 2026.1107.1

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.
@@ -1 +1 @@
1
- {"version":3,"file":"DispatchBoardCard.d.ts","sourceRoot":"","sources":["../../../../src/crewfoundry/components/field/DispatchBoardCard.tsx"],"names":[],"mappings":"AASA,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,cAAc,EAGpB,MAAM,oBAAoB,CAAC;AAS5B,UAAU,sBAAsB;IAC9B,UAAU,EAAE,YAAY,EAAE,CAAC;IAC3B,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,CAAC,QAAQ,EAAE,YAAY,KAAK,IAAI,CAAC;IAC3C,YAAY,EAAE,CAAC,QAAQ,EAAE,YAAY,EAAE,IAAI,EAAE,cAAc,KAAK,IAAI,CAAC;IACrE,QAAQ,EAAE,CAAC,QAAQ,EAAE,YAAY,KAAK,IAAI,CAAC;CAC5C;AAwDD,uFAAuF;AACvF,wBAAgB,iBAAiB,CAAC,EAAE,UAAU,EAAE,GAAG,OAAO,EAAE,EAAE,sBAAsB,+BAiDnF"}
1
+ {"version":3,"file":"DispatchBoardCard.d.ts","sourceRoot":"","sources":["../../../../src/crewfoundry/components/field/DispatchBoardCard.tsx"],"names":[],"mappings":"AASA,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,cAAc,EAGpB,MAAM,oBAAoB,CAAC;AAS5B,UAAU,sBAAsB;IAC9B,UAAU,EAAE,YAAY,EAAE,CAAC;IAC3B,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,CAAC,QAAQ,EAAE,YAAY,KAAK,IAAI,CAAC;IAC3C,YAAY,EAAE,CAAC,QAAQ,EAAE,YAAY,EAAE,IAAI,EAAE,cAAc,KAAK,IAAI,CAAC;IACrE,QAAQ,EAAE,CAAC,QAAQ,EAAE,YAAY,KAAK,IAAI,CAAC;CAC5C;AA0DD,uFAAuF;AACvF,wBAAgB,iBAAiB,CAAC,EAAE,UAAU,EAAE,GAAG,OAAO,EAAE,EAAE,sBAAsB,+BAiDnF"}
@@ -20,9 +20,12 @@ function v({ dispatch: e, canAssign: n, onAssign: d, onTransition: f, onRemove:
20
20
  /* @__PURE__ */ l("div", {
21
21
  className: "flex items-start justify-between gap-2",
22
22
  children: [/* @__PURE__ */ c("p", {
23
- className: "font-medium text-text-primary",
23
+ className: "min-w-0 break-words font-medium text-text-primary",
24
24
  children: e.title
25
- }), /* @__PURE__ */ c(t, { priority: e.priority })]
25
+ }), /* @__PURE__ */ c("span", {
26
+ className: "shrink-0",
27
+ children: /* @__PURE__ */ c(t, { priority: e.priority })
28
+ })]
26
29
  }),
27
30
  /* @__PURE__ */ l("p", {
28
31
  className: "text-xs text-text-muted",
@@ -1 +1 @@
1
- {"version":3,"file":"DispatchBoardCard.js","names":[],"sources":["../../../../src/crewfoundry/components/field/DispatchBoardCard.tsx"],"sourcesContent":["import {\n Button,\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n} from '@burdenoff/fe-libs/ui';\nimport { Trash2, UserCheck } from 'lucide-react';\nimport {\n type CrewDispatch,\n type DispatchStatus,\n MANAGER_NEXT_STATUS,\n STATUS_ACTION_LABEL,\n} from '../../lib/fieldOps';\nimport { formatEnumLabel } from '../../utils/formatEnumLabel';\nimport { DispatchPriorityBadge, DispatchStatusBadge } from './FieldBadges';\nimport { formatWhen } from './fieldFormat';\n\nconst BOARD_COLUMNS: DispatchStatus[] = ['OPEN', 'ASSIGNED', 'EN_ROUTE', 'ON_SITE'];\nconst isClosed = (dispatch: CrewDispatch): boolean =>\n dispatch.status === 'COMPLETED' || dispatch.status === 'CANCELLED';\n\ninterface DispatchBoardCardProps {\n dispatches: CrewDispatch[];\n canAssign: boolean;\n onAssign: (dispatch: CrewDispatch) => void;\n onTransition: (dispatch: CrewDispatch, next: DispatchStatus) => void;\n onRemove: (dispatch: CrewDispatch) => void;\n}\n\nfunction DispatchTile({\n dispatch,\n canAssign,\n onAssign,\n onTransition,\n onRemove,\n}: Omit<DispatchBoardCardProps, 'dispatches'> & { dispatch: CrewDispatch }) {\n const assignable = dispatch.status === 'OPEN' || dispatch.status === 'ASSIGNED';\n return (\n <div className=\"space-y-2 rounded-[var(--radius-card)] border border-border-subtle bg-bg-surface p-3\">\n <div className=\"flex items-start justify-between gap-2\">\n <p className=\"font-medium text-text-primary\">{dispatch.title}</p>\n <DispatchPriorityBadge priority={dispatch.priority} />\n </div>\n <p className=\"text-xs text-text-muted\">\n {dispatch.employeeName ?? 'Unassigned'}\n {dispatch.siteName ? ` · ${dispatch.siteName}` : ''}\n {dispatch.dueAt ? ` · due ${formatWhen(dispatch.dueAt)}` : ''}\n </p>\n <div className=\"flex flex-wrap gap-1.5\">\n {assignable ? (\n <Button\n size=\"sm\"\n variant=\"outline\"\n disabled={!canAssign}\n onClick={() => onAssign(dispatch)}\n >\n <UserCheck className=\"mr-1 h-3.5 w-3.5\" />\n {dispatch.status === 'OPEN' ? 'Assign' : 'Reassign'}\n </Button>\n ) : null}\n {MANAGER_NEXT_STATUS[dispatch.status].map((next) => (\n <Button\n key={next}\n size=\"sm\"\n variant={next === 'CANCELLED' ? 'ghost' : 'outline'}\n onClick={() => onTransition(dispatch, next)}\n >\n {STATUS_ACTION_LABEL[next]}\n </Button>\n ))}\n <Button\n size=\"sm\"\n variant=\"ghost\"\n aria-label={`Remove ${dispatch.title}`}\n onClick={() => onRemove(dispatch)}\n >\n <Trash2 className=\"h-3.5 w-3.5 text-status-error-fg\" />\n </Button>\n </div>\n </div>\n );\n}\n\n/** Work-order board by status, plus the most recent closed work orders (BOFF-4205). */\nexport function DispatchBoardCard({ dispatches, ...actions }: DispatchBoardCardProps) {\n const closed = dispatches.filter(isClosed);\n return (\n <Card data-testid=\"field-dispatch-board\">\n <CardHeader>\n <CardTitle className=\"text-base\">Work orders</CardTitle>\n <CardDescription>\n {dispatches.filter((dispatch) => dispatch.status === 'COMPLETED').length} completed ·{' '}\n {dispatches.length - closed.length} in flight\n </CardDescription>\n </CardHeader>\n <CardContent>\n <div className=\"grid gap-3 md:grid-cols-2 xl:grid-cols-4\">\n {BOARD_COLUMNS.map((column) => {\n const items = dispatches.filter((dispatch) => dispatch.status === column);\n return (\n <section key={column} aria-label={formatEnumLabel(column)} className=\"space-y-2\">\n <h2 className=\"text-sm font-medium text-text-secondary\">\n {formatEnumLabel(column)} ({items.length})\n </h2>\n {items.map((dispatch) => (\n <DispatchTile key={dispatch.id} dispatch={dispatch} {...actions} />\n ))}\n </section>\n );\n })}\n </div>\n {closed.length > 0 ? (\n <div className=\"mt-4 space-y-1\">\n <h2 className=\"text-sm font-medium text-text-secondary\">Closed</h2>\n <ul className=\"space-y-1\">\n {closed.slice(0, 10).map((dispatch) => (\n <li\n key={dispatch.id}\n className=\"flex flex-wrap items-center gap-2 text-sm text-text-secondary\"\n >\n <DispatchStatusBadge status={dispatch.status} />\n <span className=\"text-text-primary\">{dispatch.title}</span>\n <span>{dispatch.employeeName ?? ''}</span>\n <span>{formatWhen(dispatch.completedAt ?? dispatch.createdAt)}</span>\n {dispatch.completionNotes ? <span>· {dispatch.completionNotes}</span> : null}\n </li>\n ))}\n </ul>\n </div>\n ) : null}\n </CardContent>\n </Card>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"DispatchBoardCard.js","names":[],"sources":["../../../../src/crewfoundry/components/field/DispatchBoardCard.tsx"],"sourcesContent":["import {\n Button,\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n} from '@burdenoff/fe-libs/ui';\nimport { Trash2, UserCheck } from 'lucide-react';\nimport {\n type CrewDispatch,\n type DispatchStatus,\n MANAGER_NEXT_STATUS,\n STATUS_ACTION_LABEL,\n} from '../../lib/fieldOps';\nimport { formatEnumLabel } from '../../utils/formatEnumLabel';\nimport { DispatchPriorityBadge, DispatchStatusBadge } from './FieldBadges';\nimport { formatWhen } from './fieldFormat';\n\nconst BOARD_COLUMNS: DispatchStatus[] = ['OPEN', 'ASSIGNED', 'EN_ROUTE', 'ON_SITE'];\nconst isClosed = (dispatch: CrewDispatch): boolean =>\n dispatch.status === 'COMPLETED' || dispatch.status === 'CANCELLED';\n\ninterface DispatchBoardCardProps {\n dispatches: CrewDispatch[];\n canAssign: boolean;\n onAssign: (dispatch: CrewDispatch) => void;\n onTransition: (dispatch: CrewDispatch, next: DispatchStatus) => void;\n onRemove: (dispatch: CrewDispatch) => void;\n}\n\nfunction DispatchTile({\n dispatch,\n canAssign,\n onAssign,\n onTransition,\n onRemove,\n}: Omit<DispatchBoardCardProps, 'dispatches'> & { dispatch: CrewDispatch }) {\n const assignable = dispatch.status === 'OPEN' || dispatch.status === 'ASSIGNED';\n return (\n <div className=\"space-y-2 rounded-[var(--radius-card)] border border-border-subtle bg-bg-surface p-3\">\n <div className=\"flex items-start justify-between gap-2\">\n <p className=\"min-w-0 break-words font-medium text-text-primary\">{dispatch.title}</p>\n <span className=\"shrink-0\">\n <DispatchPriorityBadge priority={dispatch.priority} />\n </span>\n </div>\n <p className=\"text-xs text-text-muted\">\n {dispatch.employeeName ?? 'Unassigned'}\n {dispatch.siteName ? ` · ${dispatch.siteName}` : ''}\n {dispatch.dueAt ? ` · due ${formatWhen(dispatch.dueAt)}` : ''}\n </p>\n <div className=\"flex flex-wrap gap-1.5\">\n {assignable ? (\n <Button\n size=\"sm\"\n variant=\"outline\"\n disabled={!canAssign}\n onClick={() => onAssign(dispatch)}\n >\n <UserCheck className=\"mr-1 h-3.5 w-3.5\" />\n {dispatch.status === 'OPEN' ? 'Assign' : 'Reassign'}\n </Button>\n ) : null}\n {MANAGER_NEXT_STATUS[dispatch.status].map((next) => (\n <Button\n key={next}\n size=\"sm\"\n variant={next === 'CANCELLED' ? 'ghost' : 'outline'}\n onClick={() => onTransition(dispatch, next)}\n >\n {STATUS_ACTION_LABEL[next]}\n </Button>\n ))}\n <Button\n size=\"sm\"\n variant=\"ghost\"\n aria-label={`Remove ${dispatch.title}`}\n onClick={() => onRemove(dispatch)}\n >\n <Trash2 className=\"h-3.5 w-3.5 text-status-error-fg\" />\n </Button>\n </div>\n </div>\n );\n}\n\n/** Work-order board by status, plus the most recent closed work orders (BOFF-4205). */\nexport function DispatchBoardCard({ dispatches, ...actions }: DispatchBoardCardProps) {\n const closed = dispatches.filter(isClosed);\n return (\n <Card data-testid=\"field-dispatch-board\">\n <CardHeader>\n <CardTitle className=\"text-base\">Work orders</CardTitle>\n <CardDescription>\n {dispatches.filter((dispatch) => dispatch.status === 'COMPLETED').length} completed ·{' '}\n {dispatches.length - closed.length} in flight\n </CardDescription>\n </CardHeader>\n <CardContent>\n <div className=\"grid gap-3 md:grid-cols-2 xl:grid-cols-4\">\n {BOARD_COLUMNS.map((column) => {\n const items = dispatches.filter((dispatch) => dispatch.status === column);\n return (\n <section key={column} aria-label={formatEnumLabel(column)} className=\"space-y-2\">\n <h2 className=\"text-sm font-medium text-text-secondary\">\n {formatEnumLabel(column)} ({items.length})\n </h2>\n {items.map((dispatch) => (\n <DispatchTile key={dispatch.id} dispatch={dispatch} {...actions} />\n ))}\n </section>\n );\n })}\n </div>\n {closed.length > 0 ? (\n <div className=\"mt-4 space-y-1\">\n <h2 className=\"text-sm font-medium text-text-secondary\">Closed</h2>\n <ul className=\"space-y-1\">\n {closed.slice(0, 10).map((dispatch) => (\n <li\n key={dispatch.id}\n className=\"flex flex-wrap items-center gap-2 text-sm text-text-secondary\"\n >\n <DispatchStatusBadge status={dispatch.status} />\n <span className=\"text-text-primary\">{dispatch.title}</span>\n <span>{dispatch.employeeName ?? ''}</span>\n <span>{formatWhen(dispatch.completedAt ?? dispatch.createdAt)}</span>\n {dispatch.completionNotes ? <span>· {dispatch.completionNotes}</span> : null}\n </li>\n ))}\n </ul>\n </div>\n ) : null}\n </CardContent>\n </Card>\n );\n}\n"],"mappings":"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"}
@@ -12,10 +12,10 @@ function c({ dispatch: c, focused: l, busy: u, onAdvance: d }) {
12
12
  /* @__PURE__ */ o("div", {
13
13
  className: "flex flex-wrap items-center justify-between gap-2",
14
14
  children: [/* @__PURE__ */ a("p", {
15
- className: "font-medium text-text-primary",
15
+ className: "min-w-0 break-words font-medium text-text-primary",
16
16
  children: c.title
17
17
  }), /* @__PURE__ */ o("div", {
18
- className: "flex gap-1.5",
18
+ className: "flex shrink-0 gap-1.5",
19
19
  children: [/* @__PURE__ */ a(e, { priority: c.priority }), /* @__PURE__ */ a(t, { status: c.status })]
20
20
  })]
21
21
  }),
@@ -1 +1 @@
1
- {"version":3,"file":"MyDispatchItem.js","names":[],"sources":["../../../../src/crewfoundry/components/field/MyDispatchItem.tsx"],"sourcesContent":["import { Button } from '@burdenoff/fe-libs/ui';\nimport {\n type CrewDispatch,\n type DispatchStatus,\n STATUS_ACTION_LABEL,\n WORKER_NEXT_STATUS,\n} from '../../lib/fieldOps';\nimport { DispatchPriorityBadge, DispatchStatusBadge } from './FieldBadges';\nimport { formatWhen } from './fieldFormat';\n\ninterface MyDispatchItemProps {\n dispatch: CrewDispatch;\n focused: boolean;\n busy: boolean;\n onAdvance: (dispatch: CrewDispatch, next: DispatchStatus) => void;\n}\n\n/** One of the worker's own work orders with the moves they may make (BOFF-4205). */\nexport function MyDispatchItem({ dispatch, focused, busy, onAdvance }: MyDispatchItemProps) {\n return (\n <li\n data-focused={focused ? 'true' : undefined}\n className={`space-y-2 rounded-[var(--radius-card)] border bg-bg-surface p-4 ${\n focused ? 'border-border-strong' : 'border-border-subtle'\n }`}\n >\n <div className=\"flex flex-wrap items-center justify-between gap-2\">\n <p className=\"font-medium text-text-primary\">{dispatch.title}</p>\n <div className=\"flex gap-1.5\">\n <DispatchPriorityBadge priority={dispatch.priority} />\n <DispatchStatusBadge status={dispatch.status} />\n </div>\n </div>\n {dispatch.description ? (\n <p className=\"text-sm text-text-secondary\">{dispatch.description}</p>\n ) : null}\n <p className=\"text-xs text-text-muted\">\n {[dispatch.siteName, dispatch.siteAddress].filter(Boolean).join(' · ') || 'No site given'}\n {dispatch.dueAt ? ` · due ${formatWhen(dispatch.dueAt)}` : ''}\n </p>\n <div className=\"flex flex-wrap gap-2\">\n {WORKER_NEXT_STATUS[dispatch.status].map((next) => (\n <Button\n key={next}\n size=\"sm\"\n variant={next === 'COMPLETED' ? 'default' : 'outline'}\n disabled={busy}\n onClick={() => onAdvance(dispatch, next)}\n >\n {STATUS_ACTION_LABEL[next]}\n </Button>\n ))}\n </div>\n </li>\n );\n}\n"],"mappings":";;;;;;AAkBA,SAAgB,EAAe,EAAE,aAAU,YAAS,SAAM,gBAAkC;AAC1F,QACE,kBAAC,MAAD;EACE,gBAAc,IAAU,SAAS,KAAA;EACjC,WAAW,mEACT,IAAU,yBAAyB;YAHvC;GAME,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,KAAD;KAAG,WAAU;eAAiC,EAAS;KAAU,CAAA,EACjE,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,GAAD,EAAuB,UAAU,EAAS,UAAY,CAAA,EACtD,kBAAC,GAAD,EAAqB,QAAQ,EAAS,QAAU,CAAA,CAC5C;OACF;;GACL,EAAS,cACR,kBAAC,KAAD;IAAG,WAAU;cAA+B,EAAS;IAAgB,CAAA,GACnE;GACJ,kBAAC,KAAD;IAAG,WAAU;cAAb,CACG,CAAC,EAAS,UAAU,EAAS,YAAY,CAAC,OAAO,QAAQ,CAAC,KAAK,MAAM,IAAI,iBACzE,EAAS,QAAQ,UAAU,EAAW,EAAS,MAAM,KAAK,GACzD;;GACJ,kBAAC,OAAD;IAAK,WAAU;cACZ,EAAmB,EAAS,QAAQ,KAAK,MACxC,kBAAC,GAAD;KAEE,MAAK;KACL,SAAS,MAAS,cAAc,YAAY;KAC5C,UAAU;KACV,eAAe,EAAU,GAAU,EAAK;eAEvC,EAAoB;KACd,EAPF,EAOE,CACT;IACE,CAAA;GACH"}
1
+ {"version":3,"file":"MyDispatchItem.js","names":[],"sources":["../../../../src/crewfoundry/components/field/MyDispatchItem.tsx"],"sourcesContent":["import { Button } from '@burdenoff/fe-libs/ui';\nimport {\n type CrewDispatch,\n type DispatchStatus,\n STATUS_ACTION_LABEL,\n WORKER_NEXT_STATUS,\n} from '../../lib/fieldOps';\nimport { DispatchPriorityBadge, DispatchStatusBadge } from './FieldBadges';\nimport { formatWhen } from './fieldFormat';\n\ninterface MyDispatchItemProps {\n dispatch: CrewDispatch;\n focused: boolean;\n busy: boolean;\n onAdvance: (dispatch: CrewDispatch, next: DispatchStatus) => void;\n}\n\n/** One of the worker's own work orders with the moves they may make (BOFF-4205). */\nexport function MyDispatchItem({ dispatch, focused, busy, onAdvance }: MyDispatchItemProps) {\n return (\n <li\n data-focused={focused ? 'true' : undefined}\n className={`space-y-2 rounded-[var(--radius-card)] border bg-bg-surface p-4 ${\n focused ? 'border-border-strong' : 'border-border-subtle'\n }`}\n >\n <div className=\"flex flex-wrap items-center justify-between gap-2\">\n <p className=\"min-w-0 break-words font-medium text-text-primary\">{dispatch.title}</p>\n <div className=\"flex shrink-0 gap-1.5\">\n <DispatchPriorityBadge priority={dispatch.priority} />\n <DispatchStatusBadge status={dispatch.status} />\n </div>\n </div>\n {dispatch.description ? (\n <p className=\"text-sm text-text-secondary\">{dispatch.description}</p>\n ) : null}\n <p className=\"text-xs text-text-muted\">\n {[dispatch.siteName, dispatch.siteAddress].filter(Boolean).join(' · ') || 'No site given'}\n {dispatch.dueAt ? ` · due ${formatWhen(dispatch.dueAt)}` : ''}\n </p>\n <div className=\"flex flex-wrap gap-2\">\n {WORKER_NEXT_STATUS[dispatch.status].map((next) => (\n <Button\n key={next}\n size=\"sm\"\n variant={next === 'COMPLETED' ? 'default' : 'outline'}\n disabled={busy}\n onClick={() => onAdvance(dispatch, next)}\n >\n {STATUS_ACTION_LABEL[next]}\n </Button>\n ))}\n </div>\n </li>\n );\n}\n"],"mappings":";;;;;;AAkBA,SAAgB,EAAe,EAAE,aAAU,YAAS,SAAM,gBAAkC;AAC1F,QACE,kBAAC,MAAD;EACE,gBAAc,IAAU,SAAS,KAAA;EACjC,WAAW,mEACT,IAAU,yBAAyB;YAHvC;GAME,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,KAAD;KAAG,WAAU;eAAqD,EAAS;KAAU,CAAA,EACrF,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,GAAD,EAAuB,UAAU,EAAS,UAAY,CAAA,EACtD,kBAAC,GAAD,EAAqB,QAAQ,EAAS,QAAU,CAAA,CAC5C;OACF;;GACL,EAAS,cACR,kBAAC,KAAD;IAAG,WAAU;cAA+B,EAAS;IAAgB,CAAA,GACnE;GACJ,kBAAC,KAAD;IAAG,WAAU;cAAb,CACG,CAAC,EAAS,UAAU,EAAS,YAAY,CAAC,OAAO,QAAQ,CAAC,KAAK,MAAM,IAAI,iBACzE,EAAS,QAAQ,UAAU,EAAW,EAAS,MAAM,KAAK,GACzD;;GACJ,kBAAC,OAAD;IAAK,WAAU;cACZ,EAAmB,EAAS,QAAQ,KAAK,MACxC,kBAAC,GAAD;KAEE,MAAK;KACL,SAAS,MAAS,cAAc,YAAY;KAC5C,UAAU;KACV,eAAe,EAAU,GAAU,EAAK;eAEvC,EAAoB;KACd,EAPF,EAOE,CACT;IACE,CAAA;GACH"}
@@ -1 +1 @@
1
- {"version":3,"file":"MyShiftItem.d.ts","sourceRoot":"","sources":["../../../../src/crewfoundry/components/field/MyShiftItem.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,SAAS,EAAuC,MAAM,oBAAoB,CAAC;AAIzF,UAAU,gBAAgB;IACxB,KAAK,EAAE,SAAS,CAAC;IACjB,GAAG,EAAE,IAAI,CAAC;IACV,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,OAAO,CAAC;IACd,SAAS,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC;IACtC,UAAU,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC;CACxC;AAED,uFAAuF;AACvF,wBAAgB,WAAW,CAAC,EAC1B,KAAK,EACL,GAAG,EACH,OAAO,EACP,IAAI,EACJ,SAAS,EACT,UAAU,GACX,EAAE,gBAAgB,+BA0ElB"}
1
+ {"version":3,"file":"MyShiftItem.d.ts","sourceRoot":"","sources":["../../../../src/crewfoundry/components/field/MyShiftItem.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,SAAS,EAAuC,MAAM,oBAAoB,CAAC;AAIzF,UAAU,gBAAgB;IACxB,KAAK,EAAE,SAAS,CAAC;IACjB,GAAG,EAAE,IAAI,CAAC;IACV,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,OAAO,CAAC;IACd,SAAS,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC;IACtC,UAAU,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC;CACxC;AAED,uFAAuF;AACvF,wBAAgB,WAAW,CAAC,EAC1B,KAAK,EACL,GAAG,EACH,OAAO,EACP,IAAI,EACJ,SAAS,EACT,UAAU,GACX,EAAE,gBAAgB,+BA4ElB"}
@@ -14,9 +14,12 @@ function h({ shift: h, now: g, focused: _, busy: v, onCheckIn: y, onCheckOut: b
14
14
  /* @__PURE__ */ p("div", {
15
15
  className: "flex flex-wrap items-center justify-between gap-2",
16
16
  children: [/* @__PURE__ */ f("p", {
17
- className: "font-medium text-text-primary",
17
+ className: "min-w-0 break-words font-medium text-text-primary",
18
18
  children: h.title
19
- }), /* @__PURE__ */ f(e, { status: h.status })]
19
+ }), /* @__PURE__ */ f("span", {
20
+ className: "shrink-0",
21
+ children: /* @__PURE__ */ f(e, { status: h.status })
22
+ })]
20
23
  }),
21
24
  /* @__PURE__ */ p("div", {
22
25
  className: "space-y-1 text-sm text-text-secondary",
@@ -1 +1 @@
1
- {"version":3,"file":"MyShiftItem.js","names":[],"sources":["../../../../src/crewfoundry/components/field/MyShiftItem.tsx"],"sourcesContent":["import { Button } from '@burdenoff/fe-libs/ui';\nimport { Clock, LocateFixed, LogIn, LogOut, MapPin, Navigation } from 'lucide-react';\nimport { type CrewShift, checkInAvailability, formatDistance } from '../../lib/fieldOps';\nimport { ShiftStatusBadge } from './FieldBadges';\nimport { formatTime, formatWhen, mapsLink } from './fieldFormat';\n\ninterface MyShiftItemProps {\n shift: CrewShift;\n now: Date;\n focused: boolean;\n busy: boolean;\n onCheckIn: (shift: CrewShift) => void;\n onCheckOut: (shift: CrewShift) => void;\n}\n\n/** One of the worker's own shifts with its check-in / check-out action (BOFF-4205). */\nexport function MyShiftItem({\n shift,\n now,\n focused,\n busy,\n onCheckIn,\n onCheckOut,\n}: MyShiftItemProps) {\n const availability = checkInAvailability(shift, now);\n const link = mapsLink(shift.siteLatitude, shift.siteLongitude, shift.siteAddress);\n return (\n <li\n data-focused={focused ? 'true' : undefined}\n className={`space-y-3 rounded-[var(--radius-card)] border bg-bg-surface p-4 ${\n focused ? 'border-border-strong' : 'border-border-subtle'\n }`}\n >\n <div className=\"flex flex-wrap items-center justify-between gap-2\">\n <p className=\"font-medium text-text-primary\">{shift.title}</p>\n <ShiftStatusBadge status={shift.status} />\n </div>\n <div className=\"space-y-1 text-sm text-text-secondary\">\n <p className=\"flex items-center gap-1.5\">\n <Clock className=\"h-4 w-4\" />\n {formatWhen(shift.startsAt)} – {formatTime(shift.endsAt)}\n </p>\n {shift.siteName || shift.siteAddress ? (\n <p className=\"flex flex-wrap items-center gap-1.5\">\n <MapPin className=\"h-4 w-4\" />\n {[shift.siteName, shift.siteAddress].filter(Boolean).join(' · ')}\n {link ? (\n <a\n href={link}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"inline-flex items-center gap-0.5 text-text-link underline\"\n >\n <Navigation className=\"h-3.5 w-3.5\" />\n Directions\n </a>\n ) : null}\n </p>\n ) : null}\n {shift.checkedInAt ? (\n <p className=\"text-xs text-text-muted\">\n Checked in at {formatTime(shift.checkedInAt)}\n {shift.checkInDistanceMeters !== null\n ? ` · ${formatDistance(shift.checkInDistanceMeters)} from the site`\n : ''}\n </p>\n ) : null}\n {shift.notes ? <p className=\"text-xs text-text-muted\">{shift.notes}</p> : null}\n </div>\n {availability.kind === 'check-in' ? (\n <Button className=\"w-full sm:w-auto\" disabled={busy} onClick={() => onCheckIn(shift)}>\n {busy ? (\n <LocateFixed className=\"mr-1 h-4 w-4 animate-pulse\" />\n ) : (\n <LogIn className=\"mr-1 h-4 w-4\" />\n )}\n Check in here\n </Button>\n ) : null}\n {availability.kind === 'check-out' ? (\n <Button\n className=\"w-full sm:w-auto\"\n variant=\"outline\"\n disabled={busy}\n onClick={() => onCheckOut(shift)}\n >\n <LogOut className=\"mr-1 h-4 w-4\" />\n Check out\n </Button>\n ) : null}\n {availability.kind === 'too-early' ? (\n <p className=\"text-xs text-text-muted\">\n Check-in opens at {formatTime(availability.opensAt)}\n </p>\n ) : null}\n </li>\n );\n}\n"],"mappings":";;;;;;;AAgBA,SAAgB,EAAY,EAC1B,UACA,QACA,YACA,SACA,cACA,iBACmB;CACnB,IAAM,IAAe,EAAoB,GAAO,EAAI,EAC9C,IAAO,EAAS,EAAM,cAAc,EAAM,eAAe,EAAM,YAAY;AACjF,QACE,kBAAC,MAAD;EACE,gBAAc,IAAU,SAAS,KAAA;EACjC,WAAW,mEACT,IAAU,yBAAyB;YAHvC;GAME,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,KAAD;KAAG,WAAU;eAAiC,EAAM;KAAU,CAAA,EAC9D,kBAAC,GAAD,EAAkB,QAAQ,EAAM,QAAU,CAAA,CACtC;;GACN,kBAAC,OAAD;IAAK,WAAU;cAAf;KACE,kBAAC,KAAD;MAAG,WAAU;gBAAb;OACE,kBAAC,GAAD,EAAO,WAAU,WAAY,CAAA;OAC5B,EAAW,EAAM,SAAS;OAAC;OAAI,EAAW,EAAM,OAAO;OACtD;;KACH,EAAM,YAAY,EAAM,cACvB,kBAAC,KAAD;MAAG,WAAU;gBAAb;OACE,kBAAC,GAAD,EAAQ,WAAU,WAAY,CAAA;OAC7B,CAAC,EAAM,UAAU,EAAM,YAAY,CAAC,OAAO,QAAQ,CAAC,KAAK,MAAM;OAC/D,IACC,kBAAC,KAAD;QACE,MAAM;QACN,QAAO;QACP,KAAI;QACJ,WAAU;kBAJZ,CAME,kBAAC,GAAD,EAAY,WAAU,eAAgB,CAAA,EAAA,aAEpC;YACF;OACF;UACF;KACH,EAAM,cACL,kBAAC,KAAD;MAAG,WAAU;gBAAb;OAAuC;OACtB,EAAW,EAAM,YAAY;OAC3C,EAAM,0BAA0B,OAE7B,KADA,MAAM,EAAe,EAAM,sBAAsB,CAAC;OAEpD;UACF;KACH,EAAM,QAAQ,kBAAC,KAAD;MAAG,WAAU;gBAA2B,EAAM;MAAU,CAAA,GAAG;KACtE;;GACL,EAAa,SAAS,aACrB,kBAAC,GAAD;IAAQ,WAAU;IAAmB,UAAU;IAAM,eAAe,EAAU,EAAM;cAApF,CACG,IACC,kBAAC,GAAD,EAAa,WAAU,8BAA+B,CAAA,GAEtD,kBAAC,GAAD,EAAO,WAAU,gBAAiB,CAAA,EAClC,gBAEK;QACP;GACH,EAAa,SAAS,cACrB,kBAAC,GAAD;IACE,WAAU;IACV,SAAQ;IACR,UAAU;IACV,eAAe,EAAW,EAAM;cAJlC,CAME,kBAAC,GAAD,EAAQ,WAAU,gBAAiB,CAAA,EAAA,YAE5B;QACP;GACH,EAAa,SAAS,cACrB,kBAAC,KAAD;IAAG,WAAU;cAAb,CAAuC,sBAClB,EAAW,EAAa,QAAQ,CACjD;QACF;GACD"}
1
+ {"version":3,"file":"MyShiftItem.js","names":[],"sources":["../../../../src/crewfoundry/components/field/MyShiftItem.tsx"],"sourcesContent":["import { Button } from '@burdenoff/fe-libs/ui';\nimport { Clock, LocateFixed, LogIn, LogOut, MapPin, Navigation } from 'lucide-react';\nimport { type CrewShift, checkInAvailability, formatDistance } from '../../lib/fieldOps';\nimport { ShiftStatusBadge } from './FieldBadges';\nimport { formatTime, formatWhen, mapsLink } from './fieldFormat';\n\ninterface MyShiftItemProps {\n shift: CrewShift;\n now: Date;\n focused: boolean;\n busy: boolean;\n onCheckIn: (shift: CrewShift) => void;\n onCheckOut: (shift: CrewShift) => void;\n}\n\n/** One of the worker's own shifts with its check-in / check-out action (BOFF-4205). */\nexport function MyShiftItem({\n shift,\n now,\n focused,\n busy,\n onCheckIn,\n onCheckOut,\n}: MyShiftItemProps) {\n const availability = checkInAvailability(shift, now);\n const link = mapsLink(shift.siteLatitude, shift.siteLongitude, shift.siteAddress);\n return (\n <li\n data-focused={focused ? 'true' : undefined}\n className={`space-y-3 rounded-[var(--radius-card)] border bg-bg-surface p-4 ${\n focused ? 'border-border-strong' : 'border-border-subtle'\n }`}\n >\n <div className=\"flex flex-wrap items-center justify-between gap-2\">\n <p className=\"min-w-0 break-words font-medium text-text-primary\">{shift.title}</p>\n <span className=\"shrink-0\">\n <ShiftStatusBadge status={shift.status} />\n </span>\n </div>\n <div className=\"space-y-1 text-sm text-text-secondary\">\n <p className=\"flex items-center gap-1.5\">\n <Clock className=\"h-4 w-4\" />\n {formatWhen(shift.startsAt)} – {formatTime(shift.endsAt)}\n </p>\n {shift.siteName || shift.siteAddress ? (\n <p className=\"flex flex-wrap items-center gap-1.5\">\n <MapPin className=\"h-4 w-4\" />\n {[shift.siteName, shift.siteAddress].filter(Boolean).join(' · ')}\n {link ? (\n <a\n href={link}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"inline-flex items-center gap-0.5 text-text-link underline\"\n >\n <Navigation className=\"h-3.5 w-3.5\" />\n Directions\n </a>\n ) : null}\n </p>\n ) : null}\n {shift.checkedInAt ? (\n <p className=\"text-xs text-text-muted\">\n Checked in at {formatTime(shift.checkedInAt)}\n {shift.checkInDistanceMeters !== null\n ? ` · ${formatDistance(shift.checkInDistanceMeters)} from the site`\n : ''}\n </p>\n ) : null}\n {shift.notes ? <p className=\"text-xs text-text-muted\">{shift.notes}</p> : null}\n </div>\n {availability.kind === 'check-in' ? (\n <Button className=\"w-full sm:w-auto\" disabled={busy} onClick={() => onCheckIn(shift)}>\n {busy ? (\n <LocateFixed className=\"mr-1 h-4 w-4 animate-pulse\" />\n ) : (\n <LogIn className=\"mr-1 h-4 w-4\" />\n )}\n Check in here\n </Button>\n ) : null}\n {availability.kind === 'check-out' ? (\n <Button\n className=\"w-full sm:w-auto\"\n variant=\"outline\"\n disabled={busy}\n onClick={() => onCheckOut(shift)}\n >\n <LogOut className=\"mr-1 h-4 w-4\" />\n Check out\n </Button>\n ) : null}\n {availability.kind === 'too-early' ? (\n <p className=\"text-xs text-text-muted\">\n Check-in opens at {formatTime(availability.opensAt)}\n </p>\n ) : null}\n </li>\n );\n}\n"],"mappings":";;;;;;;AAgBA,SAAgB,EAAY,EAC1B,UACA,QACA,YACA,SACA,cACA,iBACmB;CACnB,IAAM,IAAe,EAAoB,GAAO,EAAI,EAC9C,IAAO,EAAS,EAAM,cAAc,EAAM,eAAe,EAAM,YAAY;AACjF,QACE,kBAAC,MAAD;EACE,gBAAc,IAAU,SAAS,KAAA;EACjC,WAAW,mEACT,IAAU,yBAAyB;YAHvC;GAME,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,KAAD;KAAG,WAAU;eAAqD,EAAM;KAAU,CAAA,EAClF,kBAAC,QAAD;KAAM,WAAU;eACd,kBAAC,GAAD,EAAkB,QAAQ,EAAM,QAAU,CAAA;KACrC,CAAA,CACH;;GACN,kBAAC,OAAD;IAAK,WAAU;cAAf;KACE,kBAAC,KAAD;MAAG,WAAU;gBAAb;OACE,kBAAC,GAAD,EAAO,WAAU,WAAY,CAAA;OAC5B,EAAW,EAAM,SAAS;OAAC;OAAI,EAAW,EAAM,OAAO;OACtD;;KACH,EAAM,YAAY,EAAM,cACvB,kBAAC,KAAD;MAAG,WAAU;gBAAb;OACE,kBAAC,GAAD,EAAQ,WAAU,WAAY,CAAA;OAC7B,CAAC,EAAM,UAAU,EAAM,YAAY,CAAC,OAAO,QAAQ,CAAC,KAAK,MAAM;OAC/D,IACC,kBAAC,KAAD;QACE,MAAM;QACN,QAAO;QACP,KAAI;QACJ,WAAU;kBAJZ,CAME,kBAAC,GAAD,EAAY,WAAU,eAAgB,CAAA,EAAA,aAEpC;YACF;OACF;UACF;KACH,EAAM,cACL,kBAAC,KAAD;MAAG,WAAU;gBAAb;OAAuC;OACtB,EAAW,EAAM,YAAY;OAC3C,EAAM,0BAA0B,OAE7B,KADA,MAAM,EAAe,EAAM,sBAAsB,CAAC;OAEpD;UACF;KACH,EAAM,QAAQ,kBAAC,KAAD;MAAG,WAAU;gBAA2B,EAAM;MAAU,CAAA,GAAG;KACtE;;GACL,EAAa,SAAS,aACrB,kBAAC,GAAD;IAAQ,WAAU;IAAmB,UAAU;IAAM,eAAe,EAAU,EAAM;cAApF,CACG,IACC,kBAAC,GAAD,EAAa,WAAU,8BAA+B,CAAA,GAEtD,kBAAC,GAAD,EAAO,WAAU,gBAAiB,CAAA,EAClC,gBAEK;QACP;GACH,EAAa,SAAS,cACrB,kBAAC,GAAD;IACE,WAAU;IACV,SAAQ;IACR,UAAU;IACV,eAAe,EAAW,EAAM;cAJlC,CAME,kBAAC,GAAD,EAAQ,WAAU,gBAAiB,CAAA,EAAA,YAE5B;QACP;GACH,EAAa,SAAS,cACrB,kBAAC,KAAD;IAAG,WAAU;cAAb,CAAuC,sBAClB,EAAW,EAAa,QAAQ,CACjD;QACF;GACD"}
@@ -1 +1 @@
1
- {"version":3,"file":"ShiftsCard.d.ts","sourceRoot":"","sources":["../../../../src/crewfoundry/components/field/ShiftsCard.tsx"],"names":[],"mappings":"AAUA,OAAO,EAAE,KAAK,SAAS,EAAkB,MAAM,oBAAoB,CAAC;AAIpE,UAAU,eAAe;IACvB,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,QAAQ,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC;IACrC,QAAQ,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC;IACrC,QAAQ,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC;CACtC;AAiBD,qFAAqF;AACrF,wBAAgB,UAAU,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,eAAe,+BA+DnF"}
1
+ {"version":3,"file":"ShiftsCard.d.ts","sourceRoot":"","sources":["../../../../src/crewfoundry/components/field/ShiftsCard.tsx"],"names":[],"mappings":"AAUA,OAAO,EAAE,KAAK,SAAS,EAAkB,MAAM,oBAAoB,CAAC;AAIpE,UAAU,eAAe;IACvB,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,QAAQ,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC;IACrC,QAAQ,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC;IACrC,QAAQ,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC;CACtC;AAiBD,qFAAqF;AACrF,wBAAgB,UAAU,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,eAAe,+BAmEnF"}
@@ -26,9 +26,12 @@ function _({ shifts: t, onRemind: _, onCancel: v, onRemove: y }) {
26
26
  /* @__PURE__ */ c("div", {
27
27
  className: "flex flex-wrap items-center gap-2",
28
28
  children: [/* @__PURE__ */ s("p", {
29
- className: "font-medium text-text-primary",
29
+ className: "min-w-0 break-words font-medium text-text-primary",
30
30
  children: t.title
31
- }), /* @__PURE__ */ s(e, { status: t.status })]
31
+ }), /* @__PURE__ */ s("span", {
32
+ className: "shrink-0",
33
+ children: /* @__PURE__ */ s(e, { status: t.status })
34
+ })]
32
35
  }),
33
36
  /* @__PURE__ */ c("p", {
34
37
  className: "text-sm text-text-secondary",
@@ -1 +1 @@
1
- {"version":3,"file":"ShiftsCard.js","names":[],"sources":["../../../../src/crewfoundry/components/field/ShiftsCard.tsx"],"sourcesContent":["import {\n Button,\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n IllustratedEmptyState,\n} from '@burdenoff/fe-libs/ui';\nimport { BellRing, Trash2, XCircle } from 'lucide-react';\nimport { type CrewShift, formatDistance } from '../../lib/fieldOps';\nimport { ShiftStatusBadge } from './FieldBadges';\nimport { formatTime, formatWhen } from './fieldFormat';\n\ninterface ShiftsCardProps {\n shifts: CrewShift[];\n onRemind: (shift: CrewShift) => void;\n onCancel: (shift: CrewShift) => void;\n onRemove: (shift: CrewShift) => void;\n}\n\nfunction shiftDetail(shift: CrewShift): string {\n const parts = [shift.siteName ?? 'No site'];\n if (shift.siteLatitude !== null) parts.push(`${shift.geofenceRadiusMeters} m check-in radius`);\n if (shift.checkedInAt) {\n parts.push(\n `checked in ${formatTime(shift.checkedInAt)} (${formatDistance(shift.checkInDistanceMeters)} from site)`\n );\n }\n if (shift.checkedOutAt) parts.push(`out ${formatTime(shift.checkedOutAt)}`);\n if (shift.timeEntry && shift.status === 'COMPLETED')\n parts.push(`${shift.timeEntry.totalHours} h`);\n if (!shift.assigneeUserId) parts.push('no worker login linked');\n return parts.join(' · ');\n}\n\n/** Dispatcher list of shifts with reminder / cancel / remove actions (BOFF-4205). */\nexport function ShiftsCard({ shifts, onRemind, onCancel, onRemove }: ShiftsCardProps) {\n return (\n <Card data-testid=\"field-shifts\">\n <CardHeader>\n <CardTitle className=\"text-base\">Shifts</CardTitle>\n <CardDescription>The past week through the next four weeks.</CardDescription>\n </CardHeader>\n <CardContent>\n {shifts.length > 0 ? (\n <ul className=\"space-y-2\" aria-label=\"Shifts\">\n {shifts.map((shift) => (\n <li\n key={shift.id}\n className=\"flex flex-col gap-3 rounded-[var(--radius-card)] border border-border-subtle bg-bg-surface p-3 md:flex-row md:items-center md:justify-between\"\n >\n <div className=\"min-w-0 space-y-1\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <p className=\"font-medium text-text-primary\">{shift.title}</p>\n <ShiftStatusBadge status={shift.status} />\n </div>\n <p className=\"text-sm text-text-secondary\">\n {shift.employeeName} · {formatWhen(shift.startsAt)} – {formatTime(shift.endsAt)}\n </p>\n <p className=\"text-xs text-text-muted\">{shiftDetail(shift)}</p>\n </div>\n {shift.status === 'SCHEDULED' ? (\n <div className=\"flex flex-wrap gap-2\">\n <Button\n size=\"sm\"\n variant=\"outline\"\n disabled={!shift.assigneeUserId}\n onClick={() => onRemind(shift)}\n >\n <BellRing className=\"mr-1 h-3.5 w-3.5\" />\n Remind\n </Button>\n <Button size=\"sm\" variant=\"outline\" onClick={() => onCancel(shift)}>\n <XCircle className=\"mr-1 h-3.5 w-3.5\" />\n Cancel\n </Button>\n <Button\n size=\"sm\"\n variant=\"ghost\"\n aria-label={`Remove ${shift.title}`}\n onClick={() => onRemove(shift)}\n >\n <Trash2 className=\"h-3.5 w-3.5 text-status-error-fg\" />\n </Button>\n </div>\n ) : null}\n </li>\n ))}\n </ul>\n ) : (\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title=\"No shifts scheduled\"\n description=\"Schedule a shift to give a worker a site, a time window and a check-in geofence.\"\n />\n )}\n </CardContent>\n </Card>\n );\n}\n"],"mappings":";;;;;;;AAqBA,SAAS,EAAY,GAA0B;CAC7C,IAAM,IAAQ,CAAC,EAAM,YAAY,UAAU;AAW3C,QAVI,EAAM,iBAAiB,QAAM,EAAM,KAAK,GAAG,EAAM,qBAAqB,oBAAoB,EAC1F,EAAM,eACR,EAAM,KACJ,cAAc,EAAW,EAAM,YAAY,CAAC,IAAI,EAAe,EAAM,sBAAsB,CAAC,aAC7F,EAEC,EAAM,gBAAc,EAAM,KAAK,OAAO,EAAW,EAAM,aAAa,GAAG,EACvE,EAAM,aAAa,EAAM,WAAW,eACtC,EAAM,KAAK,GAAG,EAAM,UAAU,WAAW,IAAI,EAC1C,EAAM,kBAAgB,EAAM,KAAK,yBAAyB,EACxD,EAAM,KAAK,MAAM;;AAI1B,SAAgB,EAAW,EAAE,WAAQ,aAAU,aAAU,eAA6B;AACpF,QACE,kBAAC,GAAD;EAAM,eAAY;YAAlB,CACE,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD;GAAW,WAAU;aAAY;GAAkB,CAAA,EACnD,kBAAC,GAAD,EAAA,UAAiB,8CAA4D,CAAA,CAClE,EAAA,CAAA,EACb,kBAAC,GAAD,EAAA,UACG,EAAO,SAAS,IACf,kBAAC,MAAD;GAAI,WAAU;GAAY,cAAW;aAClC,EAAO,KAAK,MACX,kBAAC,MAAD;IAEE,WAAU;cAFZ,CAIE,kBAAC,OAAD;KAAK,WAAU;eAAf;MACE,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,KAAD;QAAG,WAAU;kBAAiC,EAAM;QAAU,CAAA,EAC9D,kBAAC,GAAD,EAAkB,QAAQ,EAAM,QAAU,CAAA,CACtC;;MACN,kBAAC,KAAD;OAAG,WAAU;iBAAb;QACG,EAAM;QAAa;QAAI,EAAW,EAAM,SAAS;QAAC;QAAI,EAAW,EAAM,OAAO;QAC7E;;MACJ,kBAAC,KAAD;OAAG,WAAU;iBAA2B,EAAY,EAAM;OAAK,CAAA;MAC3D;QACL,EAAM,WAAW,cAChB,kBAAC,OAAD;KAAK,WAAU;eAAf;MACE,kBAAC,GAAD;OACE,MAAK;OACL,SAAQ;OACR,UAAU,CAAC,EAAM;OACjB,eAAe,EAAS,EAAM;iBAJhC,CAME,kBAAC,GAAD,EAAU,WAAU,oBAAqB,CAAA,EAAA,SAElC;;MACT,kBAAC,GAAD;OAAQ,MAAK;OAAK,SAAQ;OAAU,eAAe,EAAS,EAAM;iBAAlE,CACE,kBAAC,GAAD,EAAS,WAAU,oBAAqB,CAAA,EAAA,SAEjC;;MACT,kBAAC,GAAD;OACE,MAAK;OACL,SAAQ;OACR,cAAY,UAAU,EAAM;OAC5B,eAAe,EAAS,EAAM;iBAE9B,kBAAC,GAAD,EAAQ,WAAU,oCAAqC,CAAA;OAChD,CAAA;MACL;SACJ,KACD;MAtCE,EAAM,GAsCR,CACL;GACC,CAAA,GAEL,kBAAC,GAAD;GACE,cAAa;GACb,OAAM;GACN,aAAY;GACZ,CAAA,EAEQ,CAAA,CACT"}
1
+ {"version":3,"file":"ShiftsCard.js","names":[],"sources":["../../../../src/crewfoundry/components/field/ShiftsCard.tsx"],"sourcesContent":["import {\n Button,\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n IllustratedEmptyState,\n} from '@burdenoff/fe-libs/ui';\nimport { BellRing, Trash2, XCircle } from 'lucide-react';\nimport { type CrewShift, formatDistance } from '../../lib/fieldOps';\nimport { ShiftStatusBadge } from './FieldBadges';\nimport { formatTime, formatWhen } from './fieldFormat';\n\ninterface ShiftsCardProps {\n shifts: CrewShift[];\n onRemind: (shift: CrewShift) => void;\n onCancel: (shift: CrewShift) => void;\n onRemove: (shift: CrewShift) => void;\n}\n\nfunction shiftDetail(shift: CrewShift): string {\n const parts = [shift.siteName ?? 'No site'];\n if (shift.siteLatitude !== null) parts.push(`${shift.geofenceRadiusMeters} m check-in radius`);\n if (shift.checkedInAt) {\n parts.push(\n `checked in ${formatTime(shift.checkedInAt)} (${formatDistance(shift.checkInDistanceMeters)} from site)`\n );\n }\n if (shift.checkedOutAt) parts.push(`out ${formatTime(shift.checkedOutAt)}`);\n if (shift.timeEntry && shift.status === 'COMPLETED')\n parts.push(`${shift.timeEntry.totalHours} h`);\n if (!shift.assigneeUserId) parts.push('no worker login linked');\n return parts.join(' · ');\n}\n\n/** Dispatcher list of shifts with reminder / cancel / remove actions (BOFF-4205). */\nexport function ShiftsCard({ shifts, onRemind, onCancel, onRemove }: ShiftsCardProps) {\n return (\n <Card data-testid=\"field-shifts\">\n <CardHeader>\n <CardTitle className=\"text-base\">Shifts</CardTitle>\n <CardDescription>The past week through the next four weeks.</CardDescription>\n </CardHeader>\n <CardContent>\n {shifts.length > 0 ? (\n <ul className=\"space-y-2\" aria-label=\"Shifts\">\n {shifts.map((shift) => (\n <li\n key={shift.id}\n className=\"flex flex-col gap-3 rounded-[var(--radius-card)] border border-border-subtle bg-bg-surface p-3 md:flex-row md:items-center md:justify-between\"\n >\n <div className=\"min-w-0 space-y-1\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <p className=\"min-w-0 break-words font-medium text-text-primary\">\n {shift.title}\n </p>\n <span className=\"shrink-0\">\n <ShiftStatusBadge status={shift.status} />\n </span>\n </div>\n <p className=\"text-sm text-text-secondary\">\n {shift.employeeName} · {formatWhen(shift.startsAt)} – {formatTime(shift.endsAt)}\n </p>\n <p className=\"text-xs text-text-muted\">{shiftDetail(shift)}</p>\n </div>\n {shift.status === 'SCHEDULED' ? (\n <div className=\"flex flex-wrap gap-2\">\n <Button\n size=\"sm\"\n variant=\"outline\"\n disabled={!shift.assigneeUserId}\n onClick={() => onRemind(shift)}\n >\n <BellRing className=\"mr-1 h-3.5 w-3.5\" />\n Remind\n </Button>\n <Button size=\"sm\" variant=\"outline\" onClick={() => onCancel(shift)}>\n <XCircle className=\"mr-1 h-3.5 w-3.5\" />\n Cancel\n </Button>\n <Button\n size=\"sm\"\n variant=\"ghost\"\n aria-label={`Remove ${shift.title}`}\n onClick={() => onRemove(shift)}\n >\n <Trash2 className=\"h-3.5 w-3.5 text-status-error-fg\" />\n </Button>\n </div>\n ) : null}\n </li>\n ))}\n </ul>\n ) : (\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title=\"No shifts scheduled\"\n description=\"Schedule a shift to give a worker a site, a time window and a check-in geofence.\"\n />\n )}\n </CardContent>\n </Card>\n );\n}\n"],"mappings":";;;;;;;AAqBA,SAAS,EAAY,GAA0B;CAC7C,IAAM,IAAQ,CAAC,EAAM,YAAY,UAAU;AAW3C,QAVI,EAAM,iBAAiB,QAAM,EAAM,KAAK,GAAG,EAAM,qBAAqB,oBAAoB,EAC1F,EAAM,eACR,EAAM,KACJ,cAAc,EAAW,EAAM,YAAY,CAAC,IAAI,EAAe,EAAM,sBAAsB,CAAC,aAC7F,EAEC,EAAM,gBAAc,EAAM,KAAK,OAAO,EAAW,EAAM,aAAa,GAAG,EACvE,EAAM,aAAa,EAAM,WAAW,eACtC,EAAM,KAAK,GAAG,EAAM,UAAU,WAAW,IAAI,EAC1C,EAAM,kBAAgB,EAAM,KAAK,yBAAyB,EACxD,EAAM,KAAK,MAAM;;AAI1B,SAAgB,EAAW,EAAE,WAAQ,aAAU,aAAU,eAA6B;AACpF,QACE,kBAAC,GAAD;EAAM,eAAY;YAAlB,CACE,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD;GAAW,WAAU;aAAY;GAAkB,CAAA,EACnD,kBAAC,GAAD,EAAA,UAAiB,8CAA4D,CAAA,CAClE,EAAA,CAAA,EACb,kBAAC,GAAD,EAAA,UACG,EAAO,SAAS,IACf,kBAAC,MAAD;GAAI,WAAU;GAAY,cAAW;aAClC,EAAO,KAAK,MACX,kBAAC,MAAD;IAEE,WAAU;cAFZ,CAIE,kBAAC,OAAD;KAAK,WAAU;eAAf;MACE,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,KAAD;QAAG,WAAU;kBACV,EAAM;QACL,CAAA,EACJ,kBAAC,QAAD;QAAM,WAAU;kBACd,kBAAC,GAAD,EAAkB,QAAQ,EAAM,QAAU,CAAA;QACrC,CAAA,CACH;;MACN,kBAAC,KAAD;OAAG,WAAU;iBAAb;QACG,EAAM;QAAa;QAAI,EAAW,EAAM,SAAS;QAAC;QAAI,EAAW,EAAM,OAAO;QAC7E;;MACJ,kBAAC,KAAD;OAAG,WAAU;iBAA2B,EAAY,EAAM;OAAK,CAAA;MAC3D;QACL,EAAM,WAAW,cAChB,kBAAC,OAAD;KAAK,WAAU;eAAf;MACE,kBAAC,GAAD;OACE,MAAK;OACL,SAAQ;OACR,UAAU,CAAC,EAAM;OACjB,eAAe,EAAS,EAAM;iBAJhC,CAME,kBAAC,GAAD,EAAU,WAAU,oBAAqB,CAAA,EAAA,SAElC;;MACT,kBAAC,GAAD;OAAQ,MAAK;OAAK,SAAQ;OAAU,eAAe,EAAS,EAAM;iBAAlE,CACE,kBAAC,GAAD,EAAS,WAAU,oBAAqB,CAAA,EAAA,SAEjC;;MACT,kBAAC,GAAD;OACE,MAAK;OACL,SAAQ;OACR,cAAY,UAAU,EAAM;OAC5B,eAAe,EAAS,EAAM;iBAE9B,kBAAC,GAAD,EAAQ,WAAU,oCAAqC,CAAA;OAChD,CAAA;MACL;SACJ,KACD;MA1CE,EAAM,GA0CR,CACL;GACC,CAAA,GAEL,kBAAC,GAAD;GACE,cAAa;GACb,OAAM;GACN,aAAY;GACZ,CAAA,EAEQ,CAAA,CACT"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@burdenoff/microfe-crewfoundry",
3
- "version": "2026.1102.2",
3
+ "version": "2026.1107.1",
4
4
  "description": "Burdenoff CrewFoundry Microfrontend",
5
5
  "type": "module",
6
6
  "files": [