@pablo2410/shared-ui 0.26.0 → 0.27.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,"sources":["../../src/reporting/ReportingToolbar.tsx","../../src/reporting/index.ts"],"sourcesContent":["/**\n * ReportingToolbar — the header \"User Actions\" dropdown for all Oplytics\n * subdomains.\n *\n * ⚙ User Actions ▾ → Report\n * Safety Incident (OSHA 1904 · ISO 45001)\n * Environmental (ISO 14001)\n * Stop Work (ISO 45001)\n * ── (separator) ──\n * Feedback\n * Report a Problem\n * Suggestion\n *\n * Feedback opens a self-contained dialog: pick the service, say whether it's\n * blocking you, a short summary, the detail, and optionally attach a\n * screenshot. On submit `onFeedbackSubmit(feedback: FeedbackReport)` is called\n * — the host POSTs it to Portal's /api/service/feedback.\n *\n * Report opens one of three bespoke dialogs (Safety / Environmental / Stop\n * Work), each built against the external standard named in its header and\n * `REPORT_STANDARD_REFERENCES` (see reporting/index.ts) — shown to the user\n * via an `Alert` at the top of the form, not just documented in code. On\n * submit `onReportSubmit(report: IncidentReport)` is called with the\n * discriminated union — the host POSTs it to Portal's /api/service/reports.\n *\n * Oplytics dark theme: #0A0E1A bg, #8C34E9 accent.\n */\nimport { useRef, useState } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport {\n Button,\n Badge,\n Textarea,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n Input,\n Label,\n Switch,\n Checkbox,\n Alert,\n AlertTitle,\n AlertDescription,\n Dialog,\n DialogContent,\n DialogDescription,\n DialogHeader,\n DialogTitle,\n DialogFooter,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from \"../primitives\";\nimport {\n ShieldAlert,\n Leaf,\n OctagonX,\n Bug,\n Lightbulb,\n ChevronDown,\n Send,\n ImagePlus,\n X,\n UserCog,\n BookMarked,\n} from \"lucide-react\";\nimport { toast } from \"sonner\";\nimport {\n OPLYTICS_SERVICES,\n REPORT_STANDARD_REFERENCES,\n isAcceptableScreenshot,\n readFileAsScreenshot,\n type ReportCategory,\n type FeedbackCategory,\n type IncidentReport,\n type SafetyIncidentReport,\n type EnvironmentalIncidentReport,\n type StopWorkIncidentReport,\n type IncidentSeverity,\n type OshaInjuryClassification,\n type EnvironmentalAspect,\n type HazardCategory,\n type FeedbackReport,\n type ReportScreenshot,\n type ReportSubmitter,\n type ReportHierarchyContext,\n type OplyticsService,\n type ReportingToolbarConfig,\n} from \"./index\";\n\n/* ── Option catalogues ── */\n\ninterface ReportOption {\n category: ReportCategory;\n label: string;\n description: string;\n icon: React.ElementType;\n color: string;\n}\n\nconst ALL_REPORT_OPTIONS: ReportOption[] = [\n {\n category: \"safety\",\n label: \"Safety Incident\",\n description: \"Report a safety hazard, near miss, or injury\",\n icon: ShieldAlert,\n color: \"#EF4444\",\n },\n {\n category: \"environmental\",\n label: \"Environmental\",\n description: \"Report an environmental concern or spill\",\n icon: Leaf,\n color: \"#22C55E\",\n },\n {\n category: \"stop-work\",\n label: \"Stop Work\",\n description: \"Raise a stop work authority — immediate halt\",\n icon: OctagonX,\n color: \"#F59E0B\",\n },\n];\n\ninterface FeedbackOption {\n category: FeedbackCategory;\n label: string;\n description: string;\n icon: React.ElementType;\n color: string;\n}\n\nconst ALL_FEEDBACK_OPTIONS: FeedbackOption[] = [\n {\n category: \"problem\",\n label: \"Report a Problem\",\n description: \"Something isn't working\",\n icon: Bug,\n color: \"#EF4444\",\n },\n {\n category: \"suggestion\",\n label: \"Suggestion\",\n description: \"An idea for improvement\",\n icon: Lightbulb,\n color: \"#8C34E9\",\n },\n];\n\n/* ── Props ── */\n\nexport interface ReportingToolbarProps extends Omit<\n ReportingToolbarConfig,\n \"moduleName\"\n> {\n /** Service/module name (e.g. \"Connect\"). Defaults to \"Oplytics\". */\n moduleName?: string;\n /** The current org-hierarchy selection, forwarded on every submission. */\n hierarchyContext?: ReportHierarchyContext;\n /** The authenticated user — openId is authoritative, name/email are hints. */\n currentUser?: ReportSubmitter;\n /** Service list for the feedback picker. Defaults to OPLYTICS_SERVICES. */\n services?: OplyticsService[];\n /** Pre-selected service slug in the feedback picker. */\n defaultServiceSlug?: string;\n /** Show the \"attach screenshot\" control (default: true). */\n enableScreenshot?: boolean;\n /**\n * While true, the Report items are disabled with a \"Coming soon\" badge and\n * `onReportSubmit` is never called. Defaults to `false` — pass `true` only\n * if this host's `onReportSubmit` doesn't actually persist the report yet.\n */\n reportsComingSoon?: boolean;\n /**\n * @deprecated the toolbar handles responsive collapse itself.\n */\n compact?: boolean;\n /** CSS class for the container. */\n className?: string;\n}\n\n/* ── Component ── */\n\n/** Fields shared by all three Report forms' local state. */\ninterface ReportDraft {\n description: string;\n location: string;\n severity: IncidentSeverity;\n immediateAction: string;\n}\n\nconst EMPTY_DRAFT: ReportDraft = {\n description: \"\",\n location: \"\",\n severity: \"medium\",\n immediateAction: \"\",\n};\n\nexport function ReportingToolbar({\n moduleName = \"Oplytics\",\n showIncidentReporting = true,\n showFeedback = true,\n reportCategories = [\"safety\", \"environmental\", \"stop-work\"],\n feedbackCategories = [\"problem\", \"suggestion\"],\n onReportSubmit,\n onFeedbackSubmit,\n hierarchyContext,\n currentUser,\n services = OPLYTICS_SERVICES,\n defaultServiceSlug,\n enableScreenshot = true,\n reportsComingSoon = false,\n className,\n}: ReportingToolbarProps) {\n const reportOptions = ALL_REPORT_OPTIONS.filter(opt =>\n reportCategories.includes(opt.category)\n );\n const feedbackOptions = ALL_FEEDBACK_OPTIONS.filter(opt =>\n feedbackCategories.includes(opt.category)\n );\n\n const firstServiceSlug = defaultServiceSlug ?? services[0]?.slug ?? \"portal\";\n\n /* ── Feedback dialog state ── */\n const [feedbackOpen, setFeedbackOpen] = useState(false);\n const [category, setCategory] = useState<FeedbackCategory>(\"problem\");\n const [serviceSlug, setServiceSlug] = useState(firstServiceSlug);\n const [isBlocking, setIsBlocking] = useState(false);\n const [summary, setSummary] = useState(\"\");\n const [details, setDetails] = useState(\"\");\n const [screenshot, setScreenshot] = useState<ReportScreenshot | null>(null);\n const [screenshotName, setScreenshotName] = useState<string | null>(null);\n const [submitting, setSubmitting] = useState(false);\n const fileInputRef = useRef<HTMLInputElement | null>(null);\n\n const openFeedback = (c: FeedbackCategory) => {\n setCategory(c);\n setServiceSlug(firstServiceSlug);\n setIsBlocking(false);\n setSummary(\"\");\n setDetails(\"\");\n setScreenshot(null);\n setScreenshotName(null);\n setFeedbackOpen(true);\n };\n\n /* ── Report dialog state (Safety / Environmental / Stop Work) ── */\n const [reportOpen, setReportOpen] = useState(false);\n const [reportCategory, setReportCategory] =\n useState<ReportCategory>(\"safety\");\n const [reportDraft, setReportDraft] = useState<ReportDraft>(EMPTY_DRAFT);\n const [reportSubmitting, setReportSubmitting] = useState(false);\n\n // Safety-specific\n const [injuryOccurred, setInjuryOccurred] = useState(false);\n const [injuryClassification, setInjuryClassification] = useState<\n OshaInjuryClassification | undefined\n >(undefined);\n const [daysAwayFromWork, setDaysAwayFromWork] = useState(\"\");\n const [daysRestrictedOrTransferred, setDaysRestrictedOrTransferred] =\n useState(\"\");\n const [firstAiderAttended, setFirstAiderAttended] = useState(false);\n const [witnessName, setWitnessName] = useState(\"\");\n const [bodyPart, setBodyPart] = useState(\"\");\n const [treatmentType, setTreatmentType] = useState(\"\");\n\n // Environmental-specific\n const [environmentalAspect, setEnvironmentalAspect] = useState<\n EnvironmentalAspect | undefined\n >(undefined);\n const [regulatoryReportable, setRegulatoryReportable] = useState(false);\n const [substance, setSubstance] = useState(\"\");\n const [estimatedQuantity, setEstimatedQuantity] = useState(\"\");\n const [contained, setContained] = useState(false);\n const [reachedWatercourse, setReachedWatercourse] = useState(false);\n\n // Stop Work-specific\n const [hazardCategory, setHazardCategory] = useState<\n HazardCategory | undefined\n >(undefined);\n const [hazardDescription, setHazardDescription] = useState(\"\");\n const [areaMadeSafe, setAreaMadeSafe] = useState(false);\n const [workResumed, setWorkResumed] = useState(false);\n\n const openReport = (c: ReportCategory) => {\n setReportCategory(c);\n setReportDraft({\n ...EMPTY_DRAFT,\n severity: c === \"stop-work\" ? \"critical\" : \"medium\",\n });\n setInjuryOccurred(false);\n setInjuryClassification(undefined);\n setDaysAwayFromWork(\"\");\n setDaysRestrictedOrTransferred(\"\");\n setFirstAiderAttended(false);\n setWitnessName(\"\");\n setBodyPart(\"\");\n setTreatmentType(\"\");\n setEnvironmentalAspect(undefined);\n setRegulatoryReportable(false);\n setSubstance(\"\");\n setEstimatedQuantity(\"\");\n setContained(false);\n setReachedWatercourse(false);\n setHazardCategory(undefined);\n setHazardDescription(\"\");\n setAreaMadeSafe(false);\n setWorkResumed(false);\n setReportOpen(true);\n };\n\n const submitReport = async () => {\n if (!reportDraft.description.trim()) {\n toast.error(\"Please describe what happened.\");\n return;\n }\n setReportSubmitting(true);\n try {\n const base = {\n description: reportDraft.description.trim(),\n location: reportDraft.location.trim() || undefined,\n severity: reportDraft.severity,\n immediateAction: reportDraft.immediateAction.trim() || undefined,\n moduleName,\n timestamp: new Date().toISOString(),\n submittedBy: currentUser,\n hierarchyContext,\n };\n\n let report: IncidentReport;\n if (reportCategory === \"safety\") {\n const safety: SafetyIncidentReport = {\n ...base,\n category: \"safety\",\n injuryOccurred,\n injuryClassification,\n daysAwayFromWork: daysAwayFromWork\n ? Number(daysAwayFromWork)\n : undefined,\n daysRestrictedOrTransferred: daysRestrictedOrTransferred\n ? Number(daysRestrictedOrTransferred)\n : undefined,\n firstAiderAttended,\n witnessName: witnessName.trim() || undefined,\n bodyPart: bodyPart.trim() || undefined,\n treatmentType: treatmentType.trim() || undefined,\n };\n report = safety;\n } else if (reportCategory === \"environmental\") {\n const environmental: EnvironmentalIncidentReport = {\n ...base,\n category: \"environmental\",\n environmentalAspect,\n regulatoryReportable,\n substance: substance.trim() || undefined,\n estimatedQuantity: estimatedQuantity.trim() || undefined,\n contained,\n reachedWatercourse,\n };\n report = environmental;\n } else {\n const stopWork: StopWorkIncidentReport = {\n ...base,\n category: \"stop-work\",\n hazardCategory,\n hazardDescription: hazardDescription.trim() || undefined,\n areaMadeSafe,\n workResumed,\n };\n report = stopWork;\n }\n\n await onReportSubmit(report);\n toast.success(\"Report logged. Thanks for raising it.\");\n setReportOpen(false);\n } catch (err) {\n console.error(\"[ReportingToolbar] report submit failed:\", err);\n toast.error(\"Couldn't submit that. Please try again.\");\n } finally {\n setReportSubmitting(false);\n }\n };\n\n const handlePickFile = async (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n e.target.value = \"\"; // allow re-picking the same file\n if (!file) return;\n const check = isAcceptableScreenshot(file);\n if (!check.ok) {\n toast.error(check.reason);\n return;\n }\n try {\n const shot = await readFileAsScreenshot(file);\n setScreenshot(shot);\n setScreenshotName(file.name);\n } catch (err) {\n console.error(\"[ReportingToolbar] screenshot read failed:\", err);\n toast.error(\"Could not read that image.\");\n }\n };\n\n const submitFeedback = async () => {\n if (!details.trim()) {\n toast.error(\"Please describe the problem or idea.\");\n return;\n }\n setSubmitting(true);\n try {\n const feedback: FeedbackReport = {\n category,\n serviceSlug,\n summary: summary.trim() || undefined,\n details: details.trim(),\n isBlocking,\n moduleName,\n timestamp: new Date().toISOString(),\n pageContext:\n typeof window !== \"undefined\" ? window.location.pathname : undefined,\n submittedBy: currentUser,\n screenshot: screenshot ?? undefined,\n };\n await onFeedbackSubmit(feedback);\n toast.success(\n category === \"problem\"\n ? \"Thanks — we've logged it. You'll get a confirmation email.\"\n : \"Thanks for the suggestion — you'll get a confirmation email.\"\n );\n setFeedbackOpen(false);\n } catch (err) {\n console.error(\"[ReportingToolbar] feedback submit failed:\", err);\n toast.error(\"Couldn't submit that. Please try again.\");\n } finally {\n setSubmitting(false);\n }\n };\n\n const showReportGroup = showIncidentReporting && reportOptions.length > 0;\n const showFeedbackGroup = showFeedback && feedbackOptions.length > 0;\n if (!showReportGroup && !showFeedbackGroup) return null;\n\n return (\n <>\n <div className={cn(\"flex items-center gap-2\", className)}>\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"h-9 gap-1.5 text-xs font-medium text-[#8890A0] hover:bg-[#1E2738] hover:text-[#E2E8F0] border border-[#1E2738]\"\n >\n <UserCog className=\"h-3.5 w-3.5\" />\n <span className=\"shell-hidden shell-sm:inline\">User Actions</span>\n <ChevronDown className=\"h-3 w-3\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\" className=\"w-60\">\n {showReportGroup && (\n <>\n <DropdownMenuLabel className=\"flex items-center gap-2 text-[10px] uppercase tracking-wide text-muted-foreground\">\n Report\n {reportsComingSoon && (\n <Badge\n variant=\"outline\"\n className=\"border-[#8C34E9]/40 text-[9px] font-normal text-[#C084FC]\"\n >\n Coming soon\n </Badge>\n )}\n </DropdownMenuLabel>\n {reportOptions.map(opt => (\n <DropdownMenuItem\n key={opt.category}\n disabled={reportsComingSoon}\n onClick={() => {\n if (!reportsComingSoon) openReport(opt.category);\n }}\n className=\"gap-3 py-2.5\"\n >\n <opt.icon\n className=\"h-4 w-4\"\n style={{ color: opt.color }}\n />\n <div>\n <p className=\"text-sm font-medium\">{opt.label}</p>\n <p className=\"text-[10px] text-muted-foreground\">\n {REPORT_STANDARD_REFERENCES[opt.category].label}\n </p>\n </div>\n </DropdownMenuItem>\n ))}\n </>\n )}\n\n {showReportGroup && showFeedbackGroup && <DropdownMenuSeparator />}\n\n {showFeedbackGroup && (\n <>\n <DropdownMenuLabel className=\"text-[10px] uppercase tracking-wide text-muted-foreground\">\n Feedback\n </DropdownMenuLabel>\n {feedbackOptions.map(opt => (\n <DropdownMenuItem\n key={opt.category}\n onClick={() => openFeedback(opt.category)}\n className=\"gap-3 py-2.5\"\n >\n <opt.icon\n className=\"h-4 w-4\"\n style={{ color: opt.color }}\n />\n <div>\n <p className=\"text-sm font-medium\">{opt.label}</p>\n <p className=\"text-[10px] text-muted-foreground\">\n {opt.description}\n </p>\n </div>\n </DropdownMenuItem>\n ))}\n </>\n )}\n </DropdownMenuContent>\n </DropdownMenu>\n </div>\n\n {/* Feedback dialog */}\n <Dialog open={feedbackOpen} onOpenChange={setFeedbackOpen}>\n <DialogContent className=\"sm:max-w-[520px]\">\n <DialogHeader>\n <DialogTitle className=\"flex items-center gap-2\">\n {category === \"problem\" ? (\n <Bug className=\"h-5 w-5 text-[#EF4444]\" />\n ) : (\n <Lightbulb className=\"h-5 w-5 text-[#8C34E9]\" />\n )}\n {category === \"problem\"\n ? \"Report a Problem\"\n : \"Share a Suggestion\"}\n </DialogTitle>\n <DialogDescription>\n {category === \"problem\"\n ? \"Tell us what went wrong. We triage within 24 hours.\"\n : \"We review every suggestion and schedule improvements against the roadmap.\"}\n </DialogDescription>\n </DialogHeader>\n\n <div className=\"space-y-4 py-2\">\n <div className=\"space-y-2\">\n <Label className=\"text-xs font-medium\">Which service?</Label>\n <Select value={serviceSlug} onValueChange={setServiceSlug}>\n <SelectTrigger className=\"h-9\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {services.map(s => (\n <SelectItem key={s.slug} value={s.slug}>\n {s.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n {category === \"problem\" && (\n <div className=\"flex items-center justify-between rounded-md border border-[#1E2738] px-3 py-2\">\n <div>\n <p className=\"text-sm font-medium\">Is this blocking you?</p>\n <p className=\"text-[10px] text-muted-foreground\">\n Blocking issues are treated as high priority.\n </p>\n </div>\n <Switch checked={isBlocking} onCheckedChange={setIsBlocking} />\n </div>\n )}\n\n <div className=\"space-y-2\">\n <Label className=\"text-xs font-medium\">Summary</Label>\n <Input\n value={summary}\n onChange={e => setSummary(e.target.value)}\n placeholder={\n category === \"problem\"\n ? \"Brief summary of the issue\"\n : \"Brief summary of your idea\"\n }\n className=\"h-9\"\n />\n </div>\n\n <div className=\"space-y-2\">\n <Label className=\"text-xs font-medium\">Details *</Label>\n <Textarea\n value={details}\n onChange={e => setDetails(e.target.value)}\n placeholder={\n category === \"problem\"\n ? \"What were you trying to do? What happened instead?\"\n : \"Describe your suggestion and how it would help…\"\n }\n rows={5}\n />\n </div>\n\n {enableScreenshot && (\n <div className=\"space-y-2\">\n <Label className=\"text-xs font-medium\">\n Screenshot (optional)\n </Label>\n <input\n ref={fileInputRef}\n type=\"file\"\n accept=\"image/*\"\n className=\"hidden\"\n onChange={handlePickFile}\n />\n {screenshot ? (\n <div className=\"flex items-center gap-2 rounded-md border border-[#1E2738] px-3 py-2\">\n <ImagePlus className=\"h-4 w-4 text-[#8C34E9]\" />\n <span className=\"flex-1 truncate text-xs text-[#E2E8F0]\">\n {screenshotName ?? \"screenshot\"}\n </span>\n <button\n type=\"button\"\n onClick={() => {\n setScreenshot(null);\n setScreenshotName(null);\n }}\n className=\"text-muted-foreground hover:text-[#E2E8F0]\"\n aria-label=\"Remove screenshot\"\n >\n <X className=\"h-3.5 w-3.5\" />\n </button>\n </div>\n ) : (\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n className=\"h-9 gap-1.5\"\n onClick={() => fileInputRef.current?.click()}\n >\n <ImagePlus className=\"h-3.5 w-3.5\" />\n Attach an image\n </Button>\n )}\n </div>\n )}\n\n <p className=\"text-[10px] text-muted-foreground\">\n {moduleName} · you'll get a confirmation email once this is\n logged.\n </p>\n </div>\n\n <DialogFooter>\n <Button variant=\"outline\" onClick={() => setFeedbackOpen(false)}>\n Cancel\n </Button>\n <Button\n onClick={submitFeedback}\n disabled={submitting || !details.trim()}\n className=\"gap-2\"\n style={{\n backgroundColor: category === \"problem\" ? \"#EF4444\" : \"#8C34E9\",\n color: \"white\",\n }}\n >\n <Send className=\"h-3.5 w-3.5\" />\n {submitting ? \"Submitting…\" : \"Submit\"}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n\n {/* Report dialog — Safety / Environmental / Stop Work */}\n <Dialog open={reportOpen} onOpenChange={setReportOpen}>\n <DialogContent className=\"sm:max-w-[560px] max-h-[90vh] overflow-y-auto\">\n <DialogHeader>\n <DialogTitle className=\"flex items-center gap-2\">\n {reportCategory === \"safety\" && (\n <ShieldAlert className=\"h-5 w-5 text-[#EF4444]\" />\n )}\n {reportCategory === \"environmental\" && (\n <Leaf className=\"h-5 w-5 text-[#22C55E]\" />\n )}\n {reportCategory === \"stop-work\" && (\n <OctagonX className=\"h-5 w-5 text-[#F59E0B]\" />\n )}\n {ALL_REPORT_OPTIONS.find(o => o.category === reportCategory)\n ?.label ?? \"Report\"}\n </DialogTitle>\n <DialogDescription>\n {\n ALL_REPORT_OPTIONS.find(o => o.category === reportCategory)\n ?.description\n }\n </DialogDescription>\n </DialogHeader>\n\n <div className=\"space-y-4 py-2\">\n <Alert className=\"border-[#8C34E9]/30 bg-[#8C34E9]/5\">\n <BookMarked className=\"h-4 w-4 text-[#8C34E9]\" />\n <AlertTitle className=\"text-xs font-semibold text-[#C084FC]\">\n {REPORT_STANDARD_REFERENCES[reportCategory].label}\n </AlertTitle>\n <AlertDescription className=\"text-[11px]\">\n {REPORT_STANDARD_REFERENCES[reportCategory].description}\n </AlertDescription>\n </Alert>\n\n <div className=\"space-y-2\">\n <Label className=\"text-xs font-medium\">Severity</Label>\n <Select\n value={reportDraft.severity}\n onValueChange={(v: IncidentSeverity) =>\n setReportDraft(d => ({ ...d, severity: v }))\n }\n >\n <SelectTrigger className=\"h-9\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"low\">Low</SelectItem>\n <SelectItem value=\"medium\">Medium</SelectItem>\n <SelectItem value=\"high\">High</SelectItem>\n <SelectItem value=\"critical\">Critical</SelectItem>\n </SelectContent>\n </Select>\n </div>\n\n <div className=\"space-y-2\">\n <Label className=\"text-xs font-medium\">Location (optional)</Label>\n <Input\n value={reportDraft.location}\n onChange={e =>\n setReportDraft(d => ({ ...d, location: e.target.value }))\n }\n placeholder=\"Where did this happen?\"\n className=\"h-9\"\n />\n </div>\n\n <div className=\"space-y-2\">\n <Label className=\"text-xs font-medium\">What happened? *</Label>\n <Textarea\n value={reportDraft.description}\n onChange={e =>\n setReportDraft(d => ({\n ...d,\n description: e.target.value,\n }))\n }\n placeholder=\"Describe what happened…\"\n rows={4}\n />\n </div>\n\n {reportCategory === \"safety\" && (\n <>\n <div className=\"flex items-center justify-between rounded-md border border-[#1E2738] px-3 py-2\">\n <p className=\"text-sm font-medium\">Was anyone injured?</p>\n <Switch\n checked={injuryOccurred}\n onCheckedChange={setInjuryOccurred}\n />\n </div>\n\n {injuryOccurred && (\n <>\n <div className=\"space-y-2\">\n <Label className=\"text-xs font-medium\">\n Injury classification (OSHA 1904)\n </Label>\n <Select\n value={injuryClassification}\n onValueChange={(v: OshaInjuryClassification) =>\n setInjuryClassification(v)\n }\n >\n <SelectTrigger className=\"h-9\">\n <SelectValue placeholder=\"Select a classification\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"first_aid_only\">\n First aid only\n </SelectItem>\n <SelectItem value=\"recordable\">Recordable</SelectItem>\n <SelectItem value=\"days_away_restricted_transfer\">\n Days away, restricted, or transferred (DART)\n </SelectItem>\n <SelectItem value=\"fatality\">Fatality</SelectItem>\n </SelectContent>\n </Select>\n </div>\n\n {injuryClassification ===\n \"days_away_restricted_transfer\" && (\n <div className=\"grid grid-cols-2 gap-3\">\n <div className=\"space-y-2\">\n <Label className=\"text-xs font-medium\">\n Days away from work\n </Label>\n <Input\n type=\"number\"\n min={0}\n value={daysAwayFromWork}\n onChange={e => setDaysAwayFromWork(e.target.value)}\n className=\"h-9\"\n />\n </div>\n <div className=\"space-y-2\">\n <Label className=\"text-xs font-medium\">\n Days restricted/transferred\n </Label>\n <Input\n type=\"number\"\n min={0}\n value={daysRestrictedOrTransferred}\n onChange={e =>\n setDaysRestrictedOrTransferred(e.target.value)\n }\n className=\"h-9\"\n />\n </div>\n </div>\n )}\n\n <div className=\"flex items-center gap-2\">\n <Checkbox\n id=\"firstAiderAttended\"\n checked={firstAiderAttended}\n onCheckedChange={c => setFirstAiderAttended(!!c)}\n />\n <Label\n htmlFor=\"firstAiderAttended\"\n className=\"text-xs font-normal\"\n >\n A first aider attended\n </Label>\n </div>\n\n <div className=\"grid grid-cols-2 gap-3\">\n <div className=\"space-y-2\">\n <Label className=\"text-xs font-medium\">\n Body part affected\n </Label>\n <Input\n value={bodyPart}\n onChange={e => setBodyPart(e.target.value)}\n className=\"h-9\"\n />\n </div>\n <div className=\"space-y-2\">\n <Label className=\"text-xs font-medium\">\n Treatment given\n </Label>\n <Input\n value={treatmentType}\n onChange={e => setTreatmentType(e.target.value)}\n className=\"h-9\"\n />\n </div>\n </div>\n\n <div className=\"space-y-2\">\n <Label className=\"text-xs font-medium\">\n Witness name (optional)\n </Label>\n <Input\n value={witnessName}\n onChange={e => setWitnessName(e.target.value)}\n className=\"h-9\"\n />\n </div>\n </>\n )}\n </>\n )}\n\n {reportCategory === \"environmental\" && (\n <>\n <div className=\"space-y-2\">\n <Label className=\"text-xs font-medium\">\n Environmental aspect (ISO 14001)\n </Label>\n <Select\n value={environmentalAspect}\n onValueChange={(v: EnvironmentalAspect) =>\n setEnvironmentalAspect(v)\n }\n >\n <SelectTrigger className=\"h-9\">\n <SelectValue placeholder=\"What element of the environment is affected?\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"air_emission\">Air emission</SelectItem>\n <SelectItem value=\"water_discharge\">\n Water discharge\n </SelectItem>\n <SelectItem value=\"soil_contamination\">\n Soil contamination\n </SelectItem>\n <SelectItem value=\"waste\">Waste</SelectItem>\n <SelectItem value=\"spill\">Spill</SelectItem>\n <SelectItem value=\"noise\">Noise</SelectItem>\n <SelectItem value=\"other\">Other</SelectItem>\n </SelectContent>\n </Select>\n </div>\n\n <div className=\"grid grid-cols-2 gap-3\">\n <div className=\"space-y-2\">\n <Label className=\"text-xs font-medium\">\n Substance (optional)\n </Label>\n <Input\n value={substance}\n onChange={e => setSubstance(e.target.value)}\n className=\"h-9\"\n />\n </div>\n <div className=\"space-y-2\">\n <Label className=\"text-xs font-medium\">\n Estimated quantity\n </Label>\n <Input\n value={estimatedQuantity}\n onChange={e => setEstimatedQuantity(e.target.value)}\n className=\"h-9\"\n />\n </div>\n </div>\n\n <div className=\"flex items-center gap-2\">\n <Checkbox\n id=\"contained\"\n checked={contained}\n onCheckedChange={c => setContained(!!c)}\n />\n <Label htmlFor=\"contained\" className=\"text-xs font-normal\">\n Contained on site\n </Label>\n </div>\n\n <div className=\"flex items-center gap-2\">\n <Checkbox\n id=\"reachedWatercourse\"\n checked={reachedWatercourse}\n onCheckedChange={c => setReachedWatercourse(!!c)}\n />\n <Label\n htmlFor=\"reachedWatercourse\"\n className=\"text-xs font-normal\"\n >\n Reached a watercourse\n </Label>\n </div>\n\n <div className=\"flex items-center gap-2\">\n <Checkbox\n id=\"regulatoryReportable\"\n checked={regulatoryReportable}\n onCheckedChange={c => setRegulatoryReportable(!!c)}\n />\n <Label\n htmlFor=\"regulatoryReportable\"\n className=\"text-xs font-normal\"\n >\n This may need reporting to a regulator\n </Label>\n </div>\n </>\n )}\n\n {reportCategory === \"stop-work\" && (\n <>\n <div className=\"space-y-2\">\n <Label className=\"text-xs font-medium\">\n Hazard category (ISO 45001)\n </Label>\n <Select\n value={hazardCategory}\n onValueChange={(v: HazardCategory) => setHazardCategory(v)}\n >\n <SelectTrigger className=\"h-9\">\n <SelectValue placeholder=\"What kind of hazard?\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"mechanical\">Mechanical</SelectItem>\n <SelectItem value=\"electrical\">Electrical</SelectItem>\n <SelectItem value=\"chemical\">Chemical</SelectItem>\n <SelectItem value=\"working_at_height\">\n Working at height\n </SelectItem>\n <SelectItem value=\"confined_space\">\n Confined space\n </SelectItem>\n <SelectItem value=\"vehicle_traffic\">\n Vehicle / traffic\n </SelectItem>\n <SelectItem value=\"other\">Other</SelectItem>\n </SelectContent>\n </Select>\n </div>\n\n <div className=\"space-y-2\">\n <Label className=\"text-xs font-medium\">\n Hazard description\n </Label>\n <Textarea\n value={hazardDescription}\n onChange={e => setHazardDescription(e.target.value)}\n rows={3}\n />\n </div>\n\n <div className=\"flex items-center gap-2\">\n <Checkbox\n id=\"areaMadeSafe\"\n checked={areaMadeSafe}\n onCheckedChange={c => setAreaMadeSafe(!!c)}\n />\n <Label htmlFor=\"areaMadeSafe\" className=\"text-xs font-normal\">\n Area has been made safe\n </Label>\n </div>\n\n <div className=\"flex items-center gap-2\">\n <Checkbox\n id=\"workResumed\"\n checked={workResumed}\n onCheckedChange={c => setWorkResumed(!!c)}\n />\n <Label htmlFor=\"workResumed\" className=\"text-xs font-normal\">\n Work has resumed\n </Label>\n </div>\n </>\n )}\n\n <div className=\"space-y-2\">\n <Label className=\"text-xs font-medium\">\n Immediate action taken (optional)\n </Label>\n <Textarea\n value={reportDraft.immediateAction}\n onChange={e =>\n setReportDraft(d => ({\n ...d,\n immediateAction: e.target.value,\n }))\n }\n rows={2}\n />\n </div>\n\n <p className=\"text-[10px] text-muted-foreground\">\n {moduleName} · this is logged centrally and escalated\n automatically.\n </p>\n </div>\n\n <DialogFooter>\n <Button variant=\"outline\" onClick={() => setReportOpen(false)}>\n Cancel\n </Button>\n <Button\n onClick={submitReport}\n disabled={reportSubmitting || !reportDraft.description.trim()}\n className=\"gap-2\"\n style={{\n backgroundColor: ALL_REPORT_OPTIONS.find(\n o => o.category === reportCategory\n )?.color,\n color: \"white\",\n }}\n >\n <Send className=\"h-3.5 w-3.5\" />\n {reportSubmitting ? \"Submitting…\" : \"Submit\"}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n </>\n );\n}\n","/**\n * @oplytics/shared-ui/reporting\n *\n * Reporting and feedback toolbar types + configuration for all Oplytics\n * subdomains — the header \"User Actions\" dropdown (ReportingToolbar).\n *\n * Both groups are fully wired. Feedback collects a service, an \"is this\n * blocking you?\" signal, a short summary, the detail, and an optional\n * screenshot, then calls `onFeedbackSubmit` with the canonical\n * `FeedbackReport` shape. Report (Safety / Environmental / Stop Work) is\n * three bespoke forms, one per category, each collecting the fields needed\n * to conform to the external standard it's built against (see each\n * category's comment below), then calls `onReportSubmit` with the\n * discriminated `IncidentReport` union. Either way the host owns the\n * transport (Feedback POSTs to Portal's `/api/service/feedback`; Report\n * POSTs to Portal's `/api/service/reports`).\n *\n * `reportsComingSoon` defaults to `false` as of this version — pass `true`\n * per-host only if that host's `onReportSubmit` doesn't actually persist yet.\n */\n\n// ─── Report types ───────────────────────────────────────────────────────────\n\nexport type ReportCategory = \"safety\" | \"environmental\" | \"stop-work\";\nexport type FeedbackCategory = \"problem\" | \"suggestion\";\n\n/** Where in the org hierarchy the submission was made. */\nexport interface ReportHierarchyContext {\n enterpriseId?: number;\n businessUnitId?: number;\n siteId?: number;\n areaId?: number;\n assetId?: number;\n}\n\n/** The authenticated user, as much as the host can supply. */\nexport interface ReportSubmitter {\n /** JWT `openId` claim — the host must NOT trust name/email over this. */\n openId?: string;\n name?: string;\n email?: string;\n}\n\n/** An attached screenshot: base64 WITHOUT the `data:...;base64,` prefix. */\nexport interface ReportScreenshot {\n dataBase64: string;\n mime: string;\n}\n\nexport type IncidentSeverity = \"low\" | \"medium\" | \"high\" | \"critical\";\n\n/**\n * OSHA 29 CFR 1904's own injury-and-illness recordkeeping classification —\n * the standard the Safety form's injury fields conform to, alongside\n * ISO 45001 (the international OH&S management-system standard it sits\n * under). Shown to the user on the form, not just used internally.\n */\nexport type OshaInjuryClassification =\n | \"none\"\n | \"first_aid_only\"\n | \"recordable\"\n | \"days_away_restricted_transfer\"\n | \"fatality\";\n\n/** ISO 14001's \"environmental aspect\" concept — which element of the\n * environment an incident affects. The standard the Environmental form's\n * classification field conforms to. */\nexport type EnvironmentalAspect =\n | \"air_emission\"\n | \"water_discharge\"\n | \"soil_contamination\"\n | \"waste\"\n | \"spill\"\n | \"noise\"\n | \"other\";\n\n/** ISO 45001's hierarchy-of-controls hazard classification. Stop Work\n * authority isn't itself a numbered standard — it's a control mechanism\n * exercised under an ISO 45001 OH&S management system, which this\n * classification maps to. */\nexport type HazardCategory =\n | \"mechanical\"\n | \"electrical\"\n | \"chemical\"\n | \"working_at_height\"\n | \"confined_space\"\n | \"vehicle_traffic\"\n | \"other\";\n\ninterface IncidentReportBase {\n description: string;\n location?: string;\n severity?: IncidentSeverity;\n /** Optional — what was done at the scene to make the area safe. */\n immediateAction?: string;\n moduleName: string;\n /** ISO timestamp */\n timestamp: string;\n submittedBy?: ReportSubmitter;\n hierarchyContext?: ReportHierarchyContext;\n}\n\nexport interface SafetyIncidentReport extends IncidentReportBase {\n category: \"safety\";\n injuryOccurred: boolean;\n /** OSHA 1904 classification — see `OshaInjuryClassification`. */\n injuryClassification?: OshaInjuryClassification;\n /** OSHA DART-rate inputs — only meaningful when injuryClassification is\n * \"days_away_restricted_transfer\". */\n daysAwayFromWork?: number;\n daysRestrictedOrTransferred?: number;\n firstAiderAttended?: boolean;\n witnessName?: string;\n bodyPart?: string;\n treatmentType?: string;\n}\n\nexport interface EnvironmentalIncidentReport extends IncidentReportBase {\n category: \"environmental\";\n /** ISO 14001 environmental aspect — see `EnvironmentalAspect`. */\n environmentalAspect?: EnvironmentalAspect;\n /** Does this trigger a duty to notify an external regulator? */\n regulatoryReportable?: boolean;\n substance?: string;\n estimatedQuantity?: string;\n contained?: boolean;\n reachedWatercourse?: boolean;\n}\n\nexport interface StopWorkIncidentReport extends IncidentReportBase {\n category: \"stop-work\";\n /** ISO 45001 hazard classification — see `HazardCategory`. */\n hazardCategory?: HazardCategory;\n hazardDescription?: string;\n areaMadeSafe?: boolean;\n workResumed?: boolean;\n}\n\n/** Discriminated on `category` — narrow on it to get the right per-type\n * fields (`report.category === \"safety\"` narrows to `SafetyIncidentReport`,\n * etc.). Each variant maps 1:1 onto its own bespoke form; see\n * ReportingToolbar.tsx's SafetyForm/EnvironmentalForm/StopWorkForm. */\nexport type IncidentReport =\n SafetyIncidentReport | EnvironmentalIncidentReport | StopWorkIncidentReport;\n\nexport interface FeedbackReport {\n category: FeedbackCategory;\n /** Canonical service slug the feedback is about (from the picker). */\n serviceSlug: string;\n /** Optional short one-liner shown above the detail. */\n summary?: string;\n /** Required detail body. */\n details: string;\n /** \"Is this blocking you?\" — drives priority server-side. */\n isBlocking: boolean;\n /** Human-readable originating module (\"OEE Manager\", \"SQDCP\", …). */\n moduleName: string;\n /** ISO timestamp */\n timestamp: string;\n /** Route the submitter was on. */\n pageContext?: string;\n submittedBy?: ReportSubmitter;\n screenshot?: ReportScreenshot;\n}\n\n// ─── Service catalogue ──────────────────────────────────────────────────────\n\nexport interface OplyticsService {\n slug: string;\n label: string;\n}\n\n/**\n * The services a user can attribute feedback to. Kept here so every subdomain's\n * picker shows the same list; a host can narrow or override it via the\n * `services` prop. Slugs match Portal's `platform_feedback.serviceSlug`.\n */\nexport const OPLYTICS_SERVICES: OplyticsService[] = [\n { slug: \"sqdcp\", label: \"SQDCP\" },\n { slug: \"oee-manager\", label: \"OEE Manager\" },\n { slug: \"action-manager\", label: \"Action Manager\" },\n { slug: \"policy-deployment\", label: \"Policy Deployment\" },\n { slug: \"connect\", label: \"Connect\" },\n { slug: \"portal\", label: \"Portal\" },\n];\n\n// ─── Toolbar configuration ──────────────────────────────────────────────────\n\nexport interface ReportingToolbarConfig {\n /** Service/module name (e.g. \"SQDCP\", \"OEE Manager\"). */\n moduleName: string;\n /** Whether to show the Report group at all (default: true). */\n showIncidentReporting?: boolean;\n /** Whether to show the Feedback group at all (default: true). */\n showFeedback?: boolean;\n /** Report categories to show (default: all three). */\n reportCategories?: ReportCategory[];\n /** Feedback categories to show (default: both). */\n feedbackCategories?: FeedbackCategory[];\n /** Called when an incident report is submitted. The host is responsible\n * for actually persisting it — see `reportsComingSoon` above. */\n onReportSubmit: (report: IncidentReport) => Promise<void> | void;\n /** Called when feedback is submitted — the host POSTs it to Portal. */\n onFeedbackSubmit: (feedback: FeedbackReport) => Promise<void> | void;\n}\n\n// ─── Button definitions (kept for backwards compatibility / config helpers) ──\n\nexport interface ReportButtonDef {\n category: ReportCategory;\n label: string;\n iconName: string;\n color: string;\n description: string;\n}\n\nexport interface FeedbackButtonDef {\n category: FeedbackCategory;\n label: string;\n iconName: string;\n color: string;\n description: string;\n}\n\nexport const REPORT_BUTTONS: ReportButtonDef[] = [\n {\n category: \"safety\",\n label: \"Safety\",\n iconName: \"ShieldAlert\",\n color: \"#ef4444\",\n description: \"Report a safety incident, near-miss, or hazard\",\n },\n {\n category: \"environmental\",\n label: \"Environmental\",\n iconName: \"Leaf\",\n color: \"#22c55e\",\n description: \"Report an environmental incident or concern\",\n },\n {\n category: \"stop-work\",\n label: \"Stop Work\",\n iconName: \"OctagonX\",\n color: \"#f59e0b\",\n description: \"Raise a stop work authority — immediate safety concern\",\n },\n];\n\nexport const FEEDBACK_BUTTONS: FeedbackButtonDef[] = [\n {\n category: \"problem\",\n label: \"Problem\",\n iconName: \"AlertTriangle\",\n color: \"#ef4444\",\n description: \"Report a problem with the platform\",\n },\n {\n category: \"suggestion\",\n label: \"Suggestion\",\n iconName: \"Lightbulb\",\n color: \"#8C34E9\",\n description: \"Suggest an improvement or new feature\",\n },\n];\n\n// ─── Standards references ──────────────────────────────────────────────────\n//\n// Each Report form is built against a named external standard, shown to the\n// user on the form itself (not just documented in code) so it's clear the\n// classification fields aren't arbitrary. Locked with Paul, 2026-09-19:\n// Safety → OSHA 1904 + ISO 45001; Environmental → ISO 14001; Stop Work →\n// ISO 45001 (as the parent OH&S management-system framework stop-work\n// authority sits under — it isn't itself a numbered standard).\n\nexport interface ReportStandardReference {\n category: ReportCategory;\n /** Short label shown on the form, e.g. \"OSHA 1904 · ISO 45001\". */\n label: string;\n /** One sentence explaining what the standard governs here. */\n description: string;\n}\n\nexport const REPORT_STANDARD_REFERENCES: Record<\n ReportCategory,\n ReportStandardReference\n> = {\n safety: {\n category: \"safety\",\n label: \"OSHA 29 CFR 1904 · ISO 45001\",\n description:\n \"Injury classification follows OSHA's recordkeeping taxonomy (first aid only / recordable / days away, restricted, or transferred / fatality), within an ISO 45001 occupational health & safety management system.\",\n },\n environmental: {\n category: \"environmental\",\n label: \"ISO 14001\",\n description:\n \"Environmental aspect and regulatory-reportable classification follow ISO 14001's environmental management system requirements.\",\n },\n \"stop-work\": {\n category: \"stop-work\",\n label: \"ISO 45001\",\n description:\n \"Stop Work authority is a hazard-control mechanism exercised under an ISO 45001 occupational health & safety management system.\",\n },\n};\n\n// ─── Helpers ────────────────────────────────────────────────────────────────\n\n/** Create a default ReportingToolbarConfig with sensible defaults. */\nexport function createReportingConfig(\n moduleName: string,\n handlers: {\n onReportSubmit: (report: IncidentReport) => Promise<void> | void;\n onFeedbackSubmit: (feedback: FeedbackReport) => Promise<void> | void;\n }\n): ReportingToolbarConfig {\n return {\n moduleName,\n showIncidentReporting: true,\n showFeedback: true,\n reportCategories: [\"safety\", \"environmental\", \"stop-work\"],\n feedbackCategories: [\"problem\", \"suggestion\"],\n ...handlers,\n };\n}\n\n/**\n * Read a picked File into `{ dataBase64, mime }` (no data: prefix), rejecting\n * non-images and anything over `maxBytes` decoded. Pure-ish (needs FileReader);\n * exported so the size rule can be unit-tested and reused.\n */\nexport const FEEDBACK_SCREENSHOT_MAX_BYTES = 300 * 1024;\n\nexport function isAcceptableScreenshot(\n file: { type: string; size: number },\n maxBytes: number = FEEDBACK_SCREENSHOT_MAX_BYTES\n): { ok: true } | { ok: false; reason: string } {\n if (!file.type.startsWith(\"image/\")) {\n return { ok: false, reason: \"Please choose an image file.\" };\n }\n if (file.size > maxBytes) {\n return {\n ok: false,\n reason: `Image is too large (max ${Math.round(maxBytes / 1024)} KB).`,\n };\n }\n return { ok: true };\n}\n\nexport function readFileAsScreenshot(file: File): Promise<ReportScreenshot> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onerror = () => reject(new Error(\"Could not read the file.\"));\n reader.onload = () => {\n const result = String(reader.result || \"\");\n const comma = result.indexOf(\",\");\n const dataBase64 = comma >= 0 ? result.slice(comma + 1) : result;\n resolve({ dataBase64, mime: file.type || \"image/png\" });\n };\n reader.readAsDataURL(file);\n });\n}\n\n// ─── ReportingToolbar component ─────────────────────────────────────────────\n\nexport {\n ReportingToolbar,\n type ReportingToolbarProps,\n} from \"./ReportingToolbar\";\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/reporting/ReportingToolbar.tsx","../../src/reporting/index.ts"],"sourcesContent":["/**\n * ReportingToolbar — the header \"User Actions\" dropdown for all Oplytics\n * subdomains.\n *\n * ⚙ User Actions ▾ → Report\n * Safety Incident (OSHA 1904 · ISO 45001)\n * Environmental (ISO 14001)\n * Stop Work (ISO 45001)\n * ── (separator) ──\n * Feedback\n * Report a Problem\n * Suggestion\n *\n * Feedback opens a self-contained dialog: pick the service, say whether it's\n * blocking you, a short summary, the detail, and optionally attach a\n * screenshot. On submit `onFeedbackSubmit(feedback: FeedbackReport)` is called\n * — the host POSTs it to Portal's /api/service/feedback.\n *\n * Report opens one of three bespoke dialogs (Safety / Environmental / Stop\n * Work), each built against the external standard named in its header and\n * `REPORT_STANDARD_REFERENCES` (see reporting/index.ts) — shown to the user\n * via an `Alert` at the top of the form, not just documented in code. On\n * submit `onReportSubmit(report: IncidentReport)` is called with the\n * discriminated union — the host POSTs it to Portal's /api/service/reports.\n *\n * Oplytics dark theme: #0A0E1A bg, #8C34E9 accent.\n */\nimport { useRef, useState } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport {\n Button,\n Badge,\n Textarea,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n Input,\n Label,\n Switch,\n Checkbox,\n Alert,\n AlertTitle,\n AlertDescription,\n Dialog,\n DialogContent,\n DialogDescription,\n DialogHeader,\n DialogTitle,\n DialogFooter,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from \"../primitives\";\nimport {\n ShieldAlert,\n Leaf,\n OctagonX,\n Bug,\n Lightbulb,\n ChevronDown,\n Send,\n ImagePlus,\n X,\n UserCog,\n BookMarked,\n} from \"lucide-react\";\nimport { toast } from \"sonner\";\nimport {\n OPLYTICS_SERVICES,\n REPORT_STANDARD_REFERENCES,\n isAcceptableScreenshot,\n readFileAsScreenshot,\n type ReportCategory,\n type FeedbackCategory,\n type IncidentReport,\n type SafetyIncidentReport,\n type EnvironmentalIncidentReport,\n type StopWorkIncidentReport,\n type IncidentSeverity,\n type OshaInjuryClassification,\n type EnvironmentalAspect,\n type HazardCategory,\n type FeedbackReport,\n type ReportScreenshot,\n type ReportSubmitter,\n type ReportHierarchyContext,\n type OplyticsService,\n type ReportingToolbarConfig,\n} from \"./index\";\n\n/* ── Option catalogues ── */\n\ninterface ReportOption {\n category: ReportCategory;\n label: string;\n description: string;\n icon: React.ElementType;\n color: string;\n}\n\nconst ALL_REPORT_OPTIONS: ReportOption[] = [\n {\n category: \"safety\",\n label: \"Safety Incident\",\n description: \"Report a safety hazard, near miss, or injury\",\n icon: ShieldAlert,\n color: \"#EF4444\",\n },\n {\n category: \"environmental\",\n label: \"Environmental\",\n description: \"Report an environmental concern or spill\",\n icon: Leaf,\n color: \"#22C55E\",\n },\n {\n category: \"stop-work\",\n label: \"Stop Work\",\n description: \"Raise a stop work authority — immediate halt\",\n icon: OctagonX,\n color: \"#F59E0B\",\n },\n];\n\ninterface FeedbackOption {\n category: FeedbackCategory;\n label: string;\n description: string;\n icon: React.ElementType;\n color: string;\n}\n\nconst ALL_FEEDBACK_OPTIONS: FeedbackOption[] = [\n {\n category: \"problem\",\n label: \"Report a Problem\",\n description: \"Something isn't working\",\n icon: Bug,\n color: \"#EF4444\",\n },\n {\n category: \"suggestion\",\n label: \"Suggestion\",\n description: \"An idea for improvement\",\n icon: Lightbulb,\n color: \"#8C34E9\",\n },\n];\n\n/* ── Props ── */\n\nexport interface ReportingToolbarProps extends Omit<\n ReportingToolbarConfig,\n \"moduleName\"\n> {\n /** Service/module name (e.g. \"Connect\"). Defaults to \"Oplytics\". */\n moduleName?: string;\n /** The current org-hierarchy selection, forwarded on every submission. */\n hierarchyContext?: ReportHierarchyContext;\n /** The authenticated user — openId is authoritative, name/email are hints. */\n currentUser?: ReportSubmitter;\n /** Service list for the feedback picker. Defaults to OPLYTICS_SERVICES. */\n services?: OplyticsService[];\n /** Pre-selected service slug in the feedback picker. */\n defaultServiceSlug?: string;\n /** Show the \"attach screenshot\" control (default: true). */\n enableScreenshot?: boolean;\n /**\n * While true, the Report items are disabled with a \"Coming soon\" badge and\n * `onReportSubmit` is never called. Defaults to `false` — pass `true` only\n * if this host's `onReportSubmit` doesn't actually persist the report yet.\n */\n reportsComingSoon?: boolean;\n /**\n * @deprecated the toolbar handles responsive collapse itself.\n */\n compact?: boolean;\n /** CSS class for the container. */\n className?: string;\n}\n\n/* ── Component ── */\n\n/** Fields shared by all three Report forms' local state. */\ninterface ReportDraft {\n description: string;\n location: string;\n severity: IncidentSeverity;\n immediateAction: string;\n}\n\nconst EMPTY_DRAFT: ReportDraft = {\n description: \"\",\n location: \"\",\n severity: \"medium\",\n immediateAction: \"\",\n};\n\nexport function ReportingToolbar({\n moduleName = \"Oplytics\",\n showIncidentReporting = true,\n showFeedback = true,\n reportCategories = [\"safety\", \"environmental\", \"stop-work\"],\n feedbackCategories = [\"problem\", \"suggestion\"],\n onReportSubmit,\n onFeedbackSubmit,\n hierarchyContext,\n currentUser,\n services = OPLYTICS_SERVICES,\n defaultServiceSlug,\n enableScreenshot = true,\n reportsComingSoon = false,\n className,\n}: ReportingToolbarProps) {\n const reportOptions = ALL_REPORT_OPTIONS.filter(opt =>\n reportCategories.includes(opt.category)\n );\n const feedbackOptions = ALL_FEEDBACK_OPTIONS.filter(opt =>\n feedbackCategories.includes(opt.category)\n );\n\n const firstServiceSlug = defaultServiceSlug ?? services[0]?.slug ?? \"portal\";\n\n /* ── Feedback dialog state ── */\n const [feedbackOpen, setFeedbackOpen] = useState(false);\n const [category, setCategory] = useState<FeedbackCategory>(\"problem\");\n const [serviceSlug, setServiceSlug] = useState(firstServiceSlug);\n const [isBlocking, setIsBlocking] = useState(false);\n const [summary, setSummary] = useState(\"\");\n const [details, setDetails] = useState(\"\");\n const [screenshot, setScreenshot] = useState<ReportScreenshot | null>(null);\n const [screenshotName, setScreenshotName] = useState<string | null>(null);\n const [submitting, setSubmitting] = useState(false);\n const fileInputRef = useRef<HTMLInputElement | null>(null);\n\n const openFeedback = (c: FeedbackCategory) => {\n setCategory(c);\n setServiceSlug(firstServiceSlug);\n setIsBlocking(false);\n setSummary(\"\");\n setDetails(\"\");\n setScreenshot(null);\n setScreenshotName(null);\n setFeedbackOpen(true);\n };\n\n /* ── Report dialog state (Safety / Environmental / Stop Work) ── */\n const [reportOpen, setReportOpen] = useState(false);\n const [reportCategory, setReportCategory] =\n useState<ReportCategory>(\"safety\");\n const [reportDraft, setReportDraft] = useState<ReportDraft>(EMPTY_DRAFT);\n const [reportSubmitting, setReportSubmitting] = useState(false);\n\n // Safety-specific\n const [injuryOccurred, setInjuryOccurred] = useState(false);\n const [injuryClassification, setInjuryClassification] = useState<\n OshaInjuryClassification | undefined\n >(undefined);\n const [daysAwayFromWork, setDaysAwayFromWork] = useState(\"\");\n const [daysRestrictedOrTransferred, setDaysRestrictedOrTransferred] =\n useState(\"\");\n const [firstAiderAttended, setFirstAiderAttended] = useState(false);\n const [witnessName, setWitnessName] = useState(\"\");\n const [bodyPart, setBodyPart] = useState(\"\");\n const [treatmentType, setTreatmentType] = useState(\"\");\n\n // Environmental-specific\n const [environmentalAspect, setEnvironmentalAspect] = useState<\n EnvironmentalAspect | undefined\n >(undefined);\n const [regulatoryReportable, setRegulatoryReportable] = useState(false);\n const [substance, setSubstance] = useState(\"\");\n const [estimatedQuantity, setEstimatedQuantity] = useState(\"\");\n const [contained, setContained] = useState(false);\n const [reachedWatercourse, setReachedWatercourse] = useState(false);\n\n // Stop Work-specific\n const [hazardCategory, setHazardCategory] = useState<\n HazardCategory | undefined\n >(undefined);\n const [hazardDescription, setHazardDescription] = useState(\"\");\n const [areaMadeSafe, setAreaMadeSafe] = useState(false);\n const [workResumed, setWorkResumed] = useState(false);\n\n const openReport = (c: ReportCategory) => {\n setReportCategory(c);\n setReportDraft({\n ...EMPTY_DRAFT,\n severity: c === \"stop-work\" ? \"critical\" : \"medium\",\n });\n setInjuryOccurred(false);\n setInjuryClassification(undefined);\n setDaysAwayFromWork(\"\");\n setDaysRestrictedOrTransferred(\"\");\n setFirstAiderAttended(false);\n setWitnessName(\"\");\n setBodyPart(\"\");\n setTreatmentType(\"\");\n setEnvironmentalAspect(undefined);\n setRegulatoryReportable(false);\n setSubstance(\"\");\n setEstimatedQuantity(\"\");\n setContained(false);\n setReachedWatercourse(false);\n setHazardCategory(undefined);\n setHazardDescription(\"\");\n setAreaMadeSafe(false);\n setWorkResumed(false);\n setReportOpen(true);\n };\n\n const submitReport = async () => {\n if (!reportDraft.description.trim()) {\n toast.error(\"Please describe what happened.\");\n return;\n }\n setReportSubmitting(true);\n try {\n const base = {\n description: reportDraft.description.trim(),\n location: reportDraft.location.trim() || undefined,\n severity: reportDraft.severity,\n immediateAction: reportDraft.immediateAction.trim() || undefined,\n moduleName,\n timestamp: new Date().toISOString(),\n submittedBy: currentUser,\n hierarchyContext,\n };\n\n let report: IncidentReport;\n if (reportCategory === \"safety\") {\n const safety: SafetyIncidentReport = {\n ...base,\n category: \"safety\",\n injuryOccurred,\n injuryClassification,\n daysAwayFromWork: daysAwayFromWork\n ? Number(daysAwayFromWork)\n : undefined,\n daysRestrictedOrTransferred: daysRestrictedOrTransferred\n ? Number(daysRestrictedOrTransferred)\n : undefined,\n firstAiderAttended,\n witnessName: witnessName.trim() || undefined,\n bodyPart: bodyPart.trim() || undefined,\n treatmentType: treatmentType.trim() || undefined,\n };\n report = safety;\n } else if (reportCategory === \"environmental\") {\n const environmental: EnvironmentalIncidentReport = {\n ...base,\n category: \"environmental\",\n environmentalAspect,\n regulatoryReportable,\n substance: substance.trim() || undefined,\n estimatedQuantity: estimatedQuantity.trim() || undefined,\n contained,\n reachedWatercourse,\n };\n report = environmental;\n } else {\n const stopWork: StopWorkIncidentReport = {\n ...base,\n category: \"stop-work\",\n hazardCategory,\n hazardDescription: hazardDescription.trim() || undefined,\n areaMadeSafe,\n workResumed,\n };\n report = stopWork;\n }\n\n await onReportSubmit(report);\n toast.success(\"Report logged. Thanks for raising it.\");\n setReportOpen(false);\n } catch (err) {\n console.error(\"[ReportingToolbar] report submit failed:\", err);\n toast.error(\"Couldn't submit that. Please try again.\");\n } finally {\n setReportSubmitting(false);\n }\n };\n\n const handlePickFile = async (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n e.target.value = \"\"; // allow re-picking the same file\n if (!file) return;\n const check = isAcceptableScreenshot(file);\n if (!check.ok) {\n toast.error(check.reason);\n return;\n }\n try {\n const shot = await readFileAsScreenshot(file);\n setScreenshot(shot);\n setScreenshotName(file.name);\n } catch (err) {\n console.error(\"[ReportingToolbar] screenshot read failed:\", err);\n toast.error(\"Could not read that image.\");\n }\n };\n\n const submitFeedback = async () => {\n if (!details.trim()) {\n toast.error(\"Please describe the problem or idea.\");\n return;\n }\n setSubmitting(true);\n try {\n const feedback: FeedbackReport = {\n category,\n serviceSlug,\n summary: summary.trim() || undefined,\n details: details.trim(),\n isBlocking,\n moduleName,\n timestamp: new Date().toISOString(),\n pageContext:\n typeof window !== \"undefined\" ? window.location.pathname : undefined,\n submittedBy: currentUser,\n screenshot: screenshot ?? undefined,\n };\n await onFeedbackSubmit(feedback);\n toast.success(\n category === \"problem\"\n ? \"Thanks — we've logged it. You'll get a confirmation email.\"\n : \"Thanks for the suggestion — you'll get a confirmation email.\"\n );\n setFeedbackOpen(false);\n } catch (err) {\n console.error(\"[ReportingToolbar] feedback submit failed:\", err);\n toast.error(\"Couldn't submit that. Please try again.\");\n } finally {\n setSubmitting(false);\n }\n };\n\n const showReportGroup = showIncidentReporting && reportOptions.length > 0;\n const showFeedbackGroup = showFeedback && feedbackOptions.length > 0;\n if (!showReportGroup && !showFeedbackGroup) return null;\n\n return (\n <>\n <div className={cn(\"flex items-center gap-2\", className)}>\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"h-9 gap-1.5 text-xs font-medium text-[#8890A0] hover:bg-[#1E2738] hover:text-[#E2E8F0] border border-[#1E2738]\"\n >\n <UserCog className=\"h-3.5 w-3.5\" />\n <span className=\"shell-hidden shell-sm:inline\">User Actions</span>\n <ChevronDown className=\"h-3 w-3\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\" className=\"w-60\">\n {showReportGroup && (\n <>\n <DropdownMenuLabel className=\"flex items-center gap-2 text-[10px] uppercase tracking-wide text-muted-foreground\">\n Report\n {reportsComingSoon && (\n <Badge\n variant=\"outline\"\n className=\"border-[#8C34E9]/40 text-[9px] font-normal text-[#C084FC]\"\n >\n Coming soon\n </Badge>\n )}\n </DropdownMenuLabel>\n {reportOptions.map(opt => (\n <DropdownMenuItem\n key={opt.category}\n disabled={reportsComingSoon}\n onClick={() => {\n if (!reportsComingSoon) openReport(opt.category);\n }}\n className=\"gap-3 py-2.5\"\n >\n <opt.icon\n className=\"h-4 w-4\"\n style={{ color: opt.color }}\n />\n <div>\n <p className=\"text-sm font-medium\">{opt.label}</p>\n <p className=\"text-[10px] text-muted-foreground\">\n {REPORT_STANDARD_REFERENCES[opt.category].label}\n </p>\n </div>\n </DropdownMenuItem>\n ))}\n </>\n )}\n\n {showReportGroup && showFeedbackGroup && <DropdownMenuSeparator />}\n\n {showFeedbackGroup && (\n <>\n <DropdownMenuLabel className=\"text-[10px] uppercase tracking-wide text-muted-foreground\">\n Feedback\n </DropdownMenuLabel>\n {feedbackOptions.map(opt => (\n <DropdownMenuItem\n key={opt.category}\n onClick={() => openFeedback(opt.category)}\n className=\"gap-3 py-2.5\"\n >\n <opt.icon\n className=\"h-4 w-4\"\n style={{ color: opt.color }}\n />\n <div>\n <p className=\"text-sm font-medium\">{opt.label}</p>\n <p className=\"text-[10px] text-muted-foreground\">\n {opt.description}\n </p>\n </div>\n </DropdownMenuItem>\n ))}\n </>\n )}\n </DropdownMenuContent>\n </DropdownMenu>\n </div>\n\n {/* Feedback dialog */}\n <Dialog open={feedbackOpen} onOpenChange={setFeedbackOpen}>\n <DialogContent className=\"sm:max-w-[520px]\">\n <DialogHeader>\n <DialogTitle className=\"flex items-center gap-2\">\n {category === \"problem\" ? (\n <Bug className=\"h-5 w-5 text-[#EF4444]\" />\n ) : (\n <Lightbulb className=\"h-5 w-5 text-[#8C34E9]\" />\n )}\n {category === \"problem\"\n ? \"Report a Problem\"\n : \"Share a Suggestion\"}\n </DialogTitle>\n <DialogDescription>\n {category === \"problem\"\n ? \"Tell us what went wrong. We triage within 24 hours.\"\n : \"We review every suggestion and schedule improvements against the roadmap.\"}\n </DialogDescription>\n </DialogHeader>\n\n <div className=\"space-y-4 py-2\">\n <div className=\"space-y-2\">\n <Label className=\"text-xs font-medium\">Which service?</Label>\n <Select value={serviceSlug} onValueChange={setServiceSlug}>\n <SelectTrigger className=\"h-9\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {services.map(s => (\n <SelectItem key={s.slug} value={s.slug}>\n {s.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n {category === \"problem\" && (\n <div className=\"flex items-center justify-between rounded-md border border-[#1E2738] px-3 py-2\">\n <div>\n <p className=\"text-sm font-medium\">Is this blocking you?</p>\n <p className=\"text-[10px] text-muted-foreground\">\n Blocking issues are treated as high priority.\n </p>\n </div>\n <Switch checked={isBlocking} onCheckedChange={setIsBlocking} />\n </div>\n )}\n\n <div className=\"space-y-2\">\n <Label className=\"text-xs font-medium\">Summary</Label>\n <Input\n value={summary}\n onChange={e => setSummary(e.target.value)}\n placeholder={\n category === \"problem\"\n ? \"Brief summary of the issue\"\n : \"Brief summary of your idea\"\n }\n className=\"h-9\"\n />\n </div>\n\n <div className=\"space-y-2\">\n <Label className=\"text-xs font-medium\">Details *</Label>\n <Textarea\n value={details}\n onChange={e => setDetails(e.target.value)}\n placeholder={\n category === \"problem\"\n ? \"What were you trying to do? What happened instead?\"\n : \"Describe your suggestion and how it would help…\"\n }\n rows={5}\n />\n </div>\n\n {enableScreenshot && (\n <div className=\"space-y-2\">\n <Label className=\"text-xs font-medium\">\n Screenshot (optional)\n </Label>\n <input\n ref={fileInputRef}\n type=\"file\"\n accept=\"image/*\"\n className=\"hidden\"\n onChange={handlePickFile}\n />\n {screenshot ? (\n <div className=\"flex items-center gap-2 rounded-md border border-[#1E2738] px-3 py-2\">\n <ImagePlus className=\"h-4 w-4 text-[#8C34E9]\" />\n <span className=\"flex-1 truncate text-xs text-[#E2E8F0]\">\n {screenshotName ?? \"screenshot\"}\n </span>\n <button\n type=\"button\"\n onClick={() => {\n setScreenshot(null);\n setScreenshotName(null);\n }}\n className=\"text-muted-foreground hover:text-[#E2E8F0]\"\n aria-label=\"Remove screenshot\"\n >\n <X className=\"h-3.5 w-3.5\" />\n </button>\n </div>\n ) : (\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n className=\"h-9 gap-1.5\"\n onClick={() => fileInputRef.current?.click()}\n >\n <ImagePlus className=\"h-3.5 w-3.5\" />\n Attach an image\n </Button>\n )}\n </div>\n )}\n\n <p className=\"text-[10px] text-muted-foreground\">\n {moduleName} · you'll get a confirmation email once this is\n logged.\n </p>\n </div>\n\n <DialogFooter>\n <Button variant=\"outline\" onClick={() => setFeedbackOpen(false)}>\n Cancel\n </Button>\n <Button\n onClick={submitFeedback}\n disabled={submitting || !details.trim()}\n className=\"gap-2\"\n style={{\n backgroundColor: category === \"problem\" ? \"#EF4444\" : \"#8C34E9\",\n color: \"white\",\n }}\n >\n <Send className=\"h-3.5 w-3.5\" />\n {submitting ? \"Submitting…\" : \"Submit\"}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n\n {/* Report dialog — Safety / Environmental / Stop Work */}\n <Dialog open={reportOpen} onOpenChange={setReportOpen}>\n <DialogContent className=\"sm:max-w-[560px] max-h-[90vh] overflow-y-auto\">\n <DialogHeader>\n <DialogTitle className=\"flex items-center gap-2\">\n {reportCategory === \"safety\" && (\n <ShieldAlert className=\"h-5 w-5 text-[#EF4444]\" />\n )}\n {reportCategory === \"environmental\" && (\n <Leaf className=\"h-5 w-5 text-[#22C55E]\" />\n )}\n {reportCategory === \"stop-work\" && (\n <OctagonX className=\"h-5 w-5 text-[#F59E0B]\" />\n )}\n {ALL_REPORT_OPTIONS.find(o => o.category === reportCategory)\n ?.label ?? \"Report\"}\n </DialogTitle>\n <DialogDescription>\n {\n ALL_REPORT_OPTIONS.find(o => o.category === reportCategory)\n ?.description\n }\n </DialogDescription>\n </DialogHeader>\n\n <div className=\"space-y-4 py-2\">\n <Alert className=\"border-[#8C34E9]/30 bg-[#8C34E9]/5\">\n <BookMarked className=\"h-4 w-4 text-[#8C34E9]\" />\n <AlertTitle className=\"text-xs font-semibold text-[#C084FC]\">\n {REPORT_STANDARD_REFERENCES[reportCategory].label}\n </AlertTitle>\n <AlertDescription className=\"text-[11px]\">\n {REPORT_STANDARD_REFERENCES[reportCategory].description}\n </AlertDescription>\n </Alert>\n\n <div className=\"space-y-2\">\n <Label className=\"text-xs font-medium\">Severity</Label>\n <Select\n value={reportDraft.severity}\n onValueChange={(v: IncidentSeverity) =>\n setReportDraft(d => ({ ...d, severity: v }))\n }\n >\n <SelectTrigger className=\"h-9\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"low\">Low</SelectItem>\n <SelectItem value=\"medium\">Medium</SelectItem>\n <SelectItem value=\"high\">High</SelectItem>\n <SelectItem value=\"critical\">Critical</SelectItem>\n </SelectContent>\n </Select>\n </div>\n\n <div className=\"space-y-2\">\n <Label className=\"text-xs font-medium\">Location (optional)</Label>\n <Input\n value={reportDraft.location}\n onChange={e =>\n setReportDraft(d => ({ ...d, location: e.target.value }))\n }\n placeholder=\"Where did this happen?\"\n className=\"h-9\"\n />\n </div>\n\n <div className=\"space-y-2\">\n <Label className=\"text-xs font-medium\">What happened? *</Label>\n <Textarea\n value={reportDraft.description}\n onChange={e =>\n setReportDraft(d => ({\n ...d,\n description: e.target.value,\n }))\n }\n placeholder=\"Describe what happened…\"\n rows={4}\n />\n </div>\n\n {reportCategory === \"safety\" && (\n <>\n <div className=\"flex items-center justify-between rounded-md border border-[#1E2738] px-3 py-2\">\n <p className=\"text-sm font-medium\">Was anyone injured?</p>\n <Switch\n checked={injuryOccurred}\n onCheckedChange={setInjuryOccurred}\n />\n </div>\n\n {injuryOccurred && (\n <>\n <div className=\"space-y-2\">\n <Label className=\"text-xs font-medium\">\n Injury classification (OSHA 1904)\n </Label>\n <Select\n value={injuryClassification}\n onValueChange={(v: OshaInjuryClassification) =>\n setInjuryClassification(v)\n }\n >\n <SelectTrigger className=\"h-9\">\n <SelectValue placeholder=\"Select a classification\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"first_aid_only\">\n First aid only\n </SelectItem>\n <SelectItem value=\"recordable\">Recordable</SelectItem>\n <SelectItem value=\"days_away_restricted_transfer\">\n Days away, restricted, or transferred (DART)\n </SelectItem>\n <SelectItem value=\"fatality\">Fatality</SelectItem>\n </SelectContent>\n </Select>\n </div>\n\n {injuryClassification ===\n \"days_away_restricted_transfer\" && (\n <div className=\"grid grid-cols-2 gap-3\">\n <div className=\"space-y-2\">\n <Label className=\"text-xs font-medium\">\n Days away from work\n </Label>\n <Input\n type=\"number\"\n min={0}\n value={daysAwayFromWork}\n onChange={e => setDaysAwayFromWork(e.target.value)}\n className=\"h-9\"\n />\n </div>\n <div className=\"space-y-2\">\n <Label className=\"text-xs font-medium\">\n Days restricted/transferred\n </Label>\n <Input\n type=\"number\"\n min={0}\n value={daysRestrictedOrTransferred}\n onChange={e =>\n setDaysRestrictedOrTransferred(e.target.value)\n }\n className=\"h-9\"\n />\n </div>\n </div>\n )}\n\n <div className=\"flex items-center gap-2\">\n <Checkbox\n id=\"firstAiderAttended\"\n checked={firstAiderAttended}\n onCheckedChange={c => setFirstAiderAttended(!!c)}\n />\n <Label\n htmlFor=\"firstAiderAttended\"\n className=\"text-xs font-normal\"\n >\n A first aider attended\n </Label>\n </div>\n\n <div className=\"grid grid-cols-2 gap-3\">\n <div className=\"space-y-2\">\n <Label className=\"text-xs font-medium\">\n Body part affected\n </Label>\n <Input\n value={bodyPart}\n onChange={e => setBodyPart(e.target.value)}\n className=\"h-9\"\n />\n </div>\n <div className=\"space-y-2\">\n <Label className=\"text-xs font-medium\">\n Treatment given\n </Label>\n <Input\n value={treatmentType}\n onChange={e => setTreatmentType(e.target.value)}\n className=\"h-9\"\n />\n </div>\n </div>\n\n <div className=\"space-y-2\">\n <Label className=\"text-xs font-medium\">\n Witness name (optional)\n </Label>\n <Input\n value={witnessName}\n onChange={e => setWitnessName(e.target.value)}\n className=\"h-9\"\n />\n </div>\n </>\n )}\n </>\n )}\n\n {reportCategory === \"environmental\" && (\n <>\n <div className=\"space-y-2\">\n <Label className=\"text-xs font-medium\">\n Environmental aspect (ISO 14001)\n </Label>\n <Select\n value={environmentalAspect}\n onValueChange={(v: EnvironmentalAspect) =>\n setEnvironmentalAspect(v)\n }\n >\n <SelectTrigger className=\"h-9\">\n <SelectValue placeholder=\"What element of the environment is affected?\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"air_emission\">Air emission</SelectItem>\n <SelectItem value=\"water_discharge\">\n Water discharge\n </SelectItem>\n <SelectItem value=\"soil_contamination\">\n Soil contamination\n </SelectItem>\n <SelectItem value=\"waste\">Waste</SelectItem>\n <SelectItem value=\"spill\">Spill</SelectItem>\n <SelectItem value=\"noise\">Noise</SelectItem>\n <SelectItem value=\"other\">Other</SelectItem>\n </SelectContent>\n </Select>\n </div>\n\n <div className=\"grid grid-cols-2 gap-3\">\n <div className=\"space-y-2\">\n <Label className=\"text-xs font-medium\">\n Substance (optional)\n </Label>\n <Input\n value={substance}\n onChange={e => setSubstance(e.target.value)}\n className=\"h-9\"\n />\n </div>\n <div className=\"space-y-2\">\n <Label className=\"text-xs font-medium\">\n Estimated quantity\n </Label>\n <Input\n value={estimatedQuantity}\n onChange={e => setEstimatedQuantity(e.target.value)}\n className=\"h-9\"\n />\n </div>\n </div>\n\n <div className=\"flex items-center gap-2\">\n <Checkbox\n id=\"contained\"\n checked={contained}\n onCheckedChange={c => setContained(!!c)}\n />\n <Label htmlFor=\"contained\" className=\"text-xs font-normal\">\n Contained on site\n </Label>\n </div>\n\n <div className=\"flex items-center gap-2\">\n <Checkbox\n id=\"reachedWatercourse\"\n checked={reachedWatercourse}\n onCheckedChange={c => setReachedWatercourse(!!c)}\n />\n <Label\n htmlFor=\"reachedWatercourse\"\n className=\"text-xs font-normal\"\n >\n Reached a watercourse\n </Label>\n </div>\n\n <div className=\"flex items-center gap-2\">\n <Checkbox\n id=\"regulatoryReportable\"\n checked={regulatoryReportable}\n onCheckedChange={c => setRegulatoryReportable(!!c)}\n />\n <Label\n htmlFor=\"regulatoryReportable\"\n className=\"text-xs font-normal\"\n >\n This may need reporting to a regulator\n </Label>\n </div>\n </>\n )}\n\n {reportCategory === \"stop-work\" && (\n <>\n <div className=\"space-y-2\">\n <Label className=\"text-xs font-medium\">\n Hazard category (ISO 45001)\n </Label>\n <Select\n value={hazardCategory}\n onValueChange={(v: HazardCategory) => setHazardCategory(v)}\n >\n <SelectTrigger className=\"h-9\">\n <SelectValue placeholder=\"What kind of hazard?\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"mechanical\">Mechanical</SelectItem>\n <SelectItem value=\"electrical\">Electrical</SelectItem>\n <SelectItem value=\"chemical\">Chemical</SelectItem>\n <SelectItem value=\"working_at_height\">\n Working at height\n </SelectItem>\n <SelectItem value=\"confined_space\">\n Confined space\n </SelectItem>\n <SelectItem value=\"vehicle_traffic\">\n Vehicle / traffic\n </SelectItem>\n <SelectItem value=\"other\">Other</SelectItem>\n </SelectContent>\n </Select>\n </div>\n\n <div className=\"space-y-2\">\n <Label className=\"text-xs font-medium\">\n Hazard description\n </Label>\n <Textarea\n value={hazardDescription}\n onChange={e => setHazardDescription(e.target.value)}\n rows={3}\n />\n </div>\n\n <div className=\"flex items-center gap-2\">\n <Checkbox\n id=\"areaMadeSafe\"\n checked={areaMadeSafe}\n onCheckedChange={c => setAreaMadeSafe(!!c)}\n />\n <Label htmlFor=\"areaMadeSafe\" className=\"text-xs font-normal\">\n Area has been made safe\n </Label>\n </div>\n\n <div className=\"flex items-center gap-2\">\n <Checkbox\n id=\"workResumed\"\n checked={workResumed}\n onCheckedChange={c => setWorkResumed(!!c)}\n />\n <Label htmlFor=\"workResumed\" className=\"text-xs font-normal\">\n Work has resumed\n </Label>\n </div>\n </>\n )}\n\n <div className=\"space-y-2\">\n <Label className=\"text-xs font-medium\">\n Immediate action taken (optional)\n </Label>\n <Textarea\n value={reportDraft.immediateAction}\n onChange={e =>\n setReportDraft(d => ({\n ...d,\n immediateAction: e.target.value,\n }))\n }\n rows={2}\n />\n </div>\n\n <p className=\"text-[10px] text-muted-foreground\">\n {moduleName} · this is logged centrally and escalated\n automatically.\n </p>\n </div>\n\n <DialogFooter>\n <Button variant=\"outline\" onClick={() => setReportOpen(false)}>\n Cancel\n </Button>\n <Button\n onClick={submitReport}\n disabled={reportSubmitting || !reportDraft.description.trim()}\n className=\"gap-2\"\n style={{\n backgroundColor: ALL_REPORT_OPTIONS.find(\n o => o.category === reportCategory\n )?.color,\n color: \"white\",\n }}\n >\n <Send className=\"h-3.5 w-3.5\" />\n {reportSubmitting ? \"Submitting…\" : \"Submit\"}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n </>\n );\n}\n","/**\n * @oplytics/shared-ui/reporting\n *\n * Reporting and feedback toolbar types + configuration for all Oplytics\n * subdomains — the header \"User Actions\" dropdown (ReportingToolbar).\n *\n * Both groups are fully wired. Feedback collects a service, an \"is this\n * blocking you?\" signal, a short summary, the detail, and an optional\n * screenshot, then calls `onFeedbackSubmit` with the canonical\n * `FeedbackReport` shape. Report (Safety / Environmental / Stop Work) is\n * three bespoke forms, one per category, each collecting the fields needed\n * to conform to the external standard it's built against (see each\n * category's comment below), then calls `onReportSubmit` with the\n * discriminated `IncidentReport` union. Either way the host owns the\n * transport (Feedback POSTs to Portal's `/api/service/feedback`; Report\n * POSTs to Portal's `/api/service/reports`).\n *\n * `reportsComingSoon` defaults to `false` as of this version — pass `true`\n * per-host only if that host's `onReportSubmit` doesn't actually persist yet.\n */\n\n// ─── Report types ───────────────────────────────────────────────────────────\n\nexport type ReportCategory = \"safety\" | \"environmental\" | \"stop-work\";\nexport type FeedbackCategory = \"problem\" | \"suggestion\";\n\n/** Where in the org hierarchy the submission was made. */\nexport interface ReportHierarchyContext {\n enterpriseId?: number;\n businessUnitId?: number;\n siteId?: number;\n areaId?: number;\n assetId?: number;\n}\n\n/** The authenticated user, as much as the host can supply. */\nexport interface ReportSubmitter {\n /** JWT `openId` claim — the host must NOT trust name/email over this. */\n openId?: string;\n name?: string;\n email?: string;\n}\n\n/** An attached screenshot: base64 WITHOUT the `data:...;base64,` prefix. */\nexport interface ReportScreenshot {\n dataBase64: string;\n mime: string;\n}\n\nexport type IncidentSeverity = \"low\" | \"medium\" | \"high\" | \"critical\";\n\n/**\n * OSHA 29 CFR 1904's own injury-and-illness recordkeeping classification —\n * the standard the Safety form's injury fields conform to, alongside\n * ISO 45001 (the international OH&S management-system standard it sits\n * under). Shown to the user on the form, not just used internally.\n */\nexport type OshaInjuryClassification =\n | \"none\"\n | \"first_aid_only\"\n | \"recordable\"\n | \"days_away_restricted_transfer\"\n | \"fatality\";\n\n/** ISO 14001's \"environmental aspect\" concept — which element of the\n * environment an incident affects. The standard the Environmental form's\n * classification field conforms to. */\nexport type EnvironmentalAspect =\n | \"air_emission\"\n | \"water_discharge\"\n | \"soil_contamination\"\n | \"waste\"\n | \"spill\"\n | \"noise\"\n | \"other\";\n\n/** ISO 45001's hierarchy-of-controls hazard classification. Stop Work\n * authority isn't itself a numbered standard — it's a control mechanism\n * exercised under an ISO 45001 OH&S management system, which this\n * classification maps to. */\nexport type HazardCategory =\n | \"mechanical\"\n | \"electrical\"\n | \"chemical\"\n | \"working_at_height\"\n | \"confined_space\"\n | \"vehicle_traffic\"\n | \"other\";\n\ninterface IncidentReportBase {\n description: string;\n location?: string;\n severity?: IncidentSeverity;\n /** Optional — what was done at the scene to make the area safe. */\n immediateAction?: string;\n moduleName: string;\n /** ISO timestamp */\n timestamp: string;\n submittedBy?: ReportSubmitter;\n hierarchyContext?: ReportHierarchyContext;\n}\n\nexport interface SafetyIncidentReport extends IncidentReportBase {\n category: \"safety\";\n injuryOccurred: boolean;\n /** OSHA 1904 classification — see `OshaInjuryClassification`. */\n injuryClassification?: OshaInjuryClassification;\n /** OSHA DART-rate inputs — only meaningful when injuryClassification is\n * \"days_away_restricted_transfer\". */\n daysAwayFromWork?: number;\n daysRestrictedOrTransferred?: number;\n firstAiderAttended?: boolean;\n witnessName?: string;\n bodyPart?: string;\n treatmentType?: string;\n}\n\nexport interface EnvironmentalIncidentReport extends IncidentReportBase {\n category: \"environmental\";\n /** ISO 14001 environmental aspect — see `EnvironmentalAspect`. */\n environmentalAspect?: EnvironmentalAspect;\n /** Does this trigger a duty to notify an external regulator? */\n regulatoryReportable?: boolean;\n substance?: string;\n estimatedQuantity?: string;\n contained?: boolean;\n reachedWatercourse?: boolean;\n}\n\nexport interface StopWorkIncidentReport extends IncidentReportBase {\n category: \"stop-work\";\n /** ISO 45001 hazard classification — see `HazardCategory`. */\n hazardCategory?: HazardCategory;\n hazardDescription?: string;\n areaMadeSafe?: boolean;\n workResumed?: boolean;\n}\n\n/** Discriminated on `category` — narrow on it to get the right per-type\n * fields (`report.category === \"safety\"` narrows to `SafetyIncidentReport`,\n * etc.). Each variant maps 1:1 onto its own bespoke form; see\n * ReportingToolbar.tsx's SafetyForm/EnvironmentalForm/StopWorkForm. */\nexport type IncidentReport =\n SafetyIncidentReport | EnvironmentalIncidentReport | StopWorkIncidentReport;\n\nexport interface FeedbackReport {\n category: FeedbackCategory;\n /** Canonical service slug the feedback is about (from the picker). */\n serviceSlug: string;\n /** Optional short one-liner shown above the detail. */\n summary?: string;\n /** Required detail body. */\n details: string;\n /** \"Is this blocking you?\" — drives priority server-side. */\n isBlocking: boolean;\n /** Human-readable originating module (\"OEE Manager\", \"SQDCP\", …). */\n moduleName: string;\n /** ISO timestamp */\n timestamp: string;\n /** Route the submitter was on. */\n pageContext?: string;\n submittedBy?: ReportSubmitter;\n screenshot?: ReportScreenshot;\n}\n\n// ─── Service catalogue ──────────────────────────────────────────────────────\n\nexport interface OplyticsService {\n slug: string;\n label: string;\n}\n\n/**\n * The services a user can attribute feedback to. Kept here so every subdomain's\n * picker shows the same list; a host can narrow or override it via the\n * `services` prop. Slugs match Portal's `platform_feedback.serviceSlug`.\n */\nexport const OPLYTICS_SERVICES: OplyticsService[] = [\n { slug: \"sqdcp\", label: \"SQDCP\" },\n { slug: \"oee-manager\", label: \"OEE Manager\" },\n { slug: \"action-manager\", label: \"Action Manager\" },\n { slug: \"policy-deployment\", label: \"Policy Deployment\" },\n { slug: \"portal\", label: \"Portal\" },\n];\n\n// ─── Toolbar configuration ──────────────────────────────────────────────────\n\nexport interface ReportingToolbarConfig {\n /** Service/module name (e.g. \"SQDCP\", \"OEE Manager\"). */\n moduleName: string;\n /** Whether to show the Report group at all (default: true). */\n showIncidentReporting?: boolean;\n /** Whether to show the Feedback group at all (default: true). */\n showFeedback?: boolean;\n /** Report categories to show (default: all three). */\n reportCategories?: ReportCategory[];\n /** Feedback categories to show (default: both). */\n feedbackCategories?: FeedbackCategory[];\n /** Called when an incident report is submitted. The host is responsible\n * for actually persisting it — see `reportsComingSoon` above. */\n onReportSubmit: (report: IncidentReport) => Promise<void> | void;\n /** Called when feedback is submitted — the host POSTs it to Portal. */\n onFeedbackSubmit: (feedback: FeedbackReport) => Promise<void> | void;\n}\n\n// ─── Button definitions (kept for backwards compatibility / config helpers) ──\n\nexport interface ReportButtonDef {\n category: ReportCategory;\n label: string;\n iconName: string;\n color: string;\n description: string;\n}\n\nexport interface FeedbackButtonDef {\n category: FeedbackCategory;\n label: string;\n iconName: string;\n color: string;\n description: string;\n}\n\nexport const REPORT_BUTTONS: ReportButtonDef[] = [\n {\n category: \"safety\",\n label: \"Safety\",\n iconName: \"ShieldAlert\",\n color: \"#ef4444\",\n description: \"Report a safety incident, near-miss, or hazard\",\n },\n {\n category: \"environmental\",\n label: \"Environmental\",\n iconName: \"Leaf\",\n color: \"#22c55e\",\n description: \"Report an environmental incident or concern\",\n },\n {\n category: \"stop-work\",\n label: \"Stop Work\",\n iconName: \"OctagonX\",\n color: \"#f59e0b\",\n description: \"Raise a stop work authority — immediate safety concern\",\n },\n];\n\nexport const FEEDBACK_BUTTONS: FeedbackButtonDef[] = [\n {\n category: \"problem\",\n label: \"Problem\",\n iconName: \"AlertTriangle\",\n color: \"#ef4444\",\n description: \"Report a problem with the platform\",\n },\n {\n category: \"suggestion\",\n label: \"Suggestion\",\n iconName: \"Lightbulb\",\n color: \"#8C34E9\",\n description: \"Suggest an improvement or new feature\",\n },\n];\n\n// ─── Standards references ──────────────────────────────────────────────────\n//\n// Each Report form is built against a named external standard, shown to the\n// user on the form itself (not just documented in code) so it's clear the\n// classification fields aren't arbitrary. Locked with Paul, 2026-09-19:\n// Safety → OSHA 1904 + ISO 45001; Environmental → ISO 14001; Stop Work →\n// ISO 45001 (as the parent OH&S management-system framework stop-work\n// authority sits under — it isn't itself a numbered standard).\n\nexport interface ReportStandardReference {\n category: ReportCategory;\n /** Short label shown on the form, e.g. \"OSHA 1904 · ISO 45001\". */\n label: string;\n /** One sentence explaining what the standard governs here. */\n description: string;\n}\n\nexport const REPORT_STANDARD_REFERENCES: Record<\n ReportCategory,\n ReportStandardReference\n> = {\n safety: {\n category: \"safety\",\n label: \"OSHA 29 CFR 1904 · ISO 45001\",\n description:\n \"Injury classification follows OSHA's recordkeeping taxonomy (first aid only / recordable / days away, restricted, or transferred / fatality), within an ISO 45001 occupational health & safety management system.\",\n },\n environmental: {\n category: \"environmental\",\n label: \"ISO 14001\",\n description:\n \"Environmental aspect and regulatory-reportable classification follow ISO 14001's environmental management system requirements.\",\n },\n \"stop-work\": {\n category: \"stop-work\",\n label: \"ISO 45001\",\n description:\n \"Stop Work authority is a hazard-control mechanism exercised under an ISO 45001 occupational health & safety management system.\",\n },\n};\n\n// ─── Helpers ────────────────────────────────────────────────────────────────\n\n/** Create a default ReportingToolbarConfig with sensible defaults. */\nexport function createReportingConfig(\n moduleName: string,\n handlers: {\n onReportSubmit: (report: IncidentReport) => Promise<void> | void;\n onFeedbackSubmit: (feedback: FeedbackReport) => Promise<void> | void;\n }\n): ReportingToolbarConfig {\n return {\n moduleName,\n showIncidentReporting: true,\n showFeedback: true,\n reportCategories: [\"safety\", \"environmental\", \"stop-work\"],\n feedbackCategories: [\"problem\", \"suggestion\"],\n ...handlers,\n };\n}\n\n/**\n * Read a picked File into `{ dataBase64, mime }` (no data: prefix), rejecting\n * non-images and anything over `maxBytes` decoded. Pure-ish (needs FileReader);\n * exported so the size rule can be unit-tested and reused.\n */\nexport const FEEDBACK_SCREENSHOT_MAX_BYTES = 300 * 1024;\n\nexport function isAcceptableScreenshot(\n file: { type: string; size: number },\n maxBytes: number = FEEDBACK_SCREENSHOT_MAX_BYTES\n): { ok: true } | { ok: false; reason: string } {\n if (!file.type.startsWith(\"image/\")) {\n return { ok: false, reason: \"Please choose an image file.\" };\n }\n if (file.size > maxBytes) {\n return {\n ok: false,\n reason: `Image is too large (max ${Math.round(maxBytes / 1024)} KB).`,\n };\n }\n return { ok: true };\n}\n\nexport function readFileAsScreenshot(file: File): Promise<ReportScreenshot> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onerror = () => reject(new Error(\"Could not read the file.\"));\n reader.onload = () => {\n const result = String(reader.result || \"\");\n const comma = result.indexOf(\",\");\n const dataBase64 = comma >= 0 ? result.slice(comma + 1) : result;\n resolve({ dataBase64, mime: file.type || \"image/png\" });\n };\n reader.readAsDataURL(file);\n });\n}\n\n// ─── ReportingToolbar component ─────────────────────────────────────────────\n\nexport {\n ReportingToolbar,\n type ReportingToolbarProps,\n} from \"./ReportingToolbar\";\n"],"mappings":"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","names":[]}
@@ -1,4 +1,4 @@
1
- export { A as ADMIN_SEE_ALL_ROLES, B as BuildCrossServiceLinksOptions, C as CrossServiceLink, S as SLUG_ALIASES, b as buildCrossServiceLinks, n as normalizeServiceSlug } from '../crossNav-Bz0RXU_F.js';
1
+ export { A as ADMIN_SEE_ALL_ROLES, B as BuildCrossServiceLinksOptions, C as CrossServiceLink, S as SLUG_ALIASES, b as buildCrossServiceLinks, n as normalizeServiceSlug } from '../crossNav-DBX4Eyx7.js';
2
2
  import '../orgHierarchy-Buky69YP.js';
3
3
 
4
4
  /**
@@ -53,7 +53,6 @@ declare function portalUrl(path?: string): string;
53
53
  * - Platform adds: route, external URL, React icon component
54
54
  * - Marketing adds: heroImage, demoImage, problem, howItWorks, results, aiFeatures
55
55
  */
56
- type ServiceStatus = "live" | "in-development" | "coming-soon";
57
56
  type ServiceCategory = "core" | "hub";
58
57
  interface ServiceDefinition {
59
58
  /** Unique identifier used for DB lookups, URL slugs, and cross-referencing */
@@ -68,8 +67,6 @@ interface ServiceDefinition {
68
67
  icon: string;
69
68
  /** Hex accent color for cards, badges, and theming */
70
69
  accentColor: string;
71
- /** Current availability status */
72
- status: ServiceStatus;
73
70
  /** Core = standalone product, Hub = extension/add-on module */
74
71
  category: ServiceCategory;
75
72
  /**
@@ -121,12 +118,11 @@ interface ServiceOnboardingFeature {
121
118
  declare const SERVICE_CATALOG: ServiceDefinition[];
122
119
  declare const coreServices: ServiceDefinition[];
123
120
  declare const hubServices: ServiceDefinition[];
121
+ /** Every service in the catalog is live: an entry is only added once it ships. */
124
122
  declare const liveServices: ServiceDefinition[];
125
- declare const inDevServices: ServiceDefinition[];
126
- declare const comingSoonServices: ServiceDefinition[];
127
123
  /** Services with a scripted onboarding tour step, in catalog order. */
128
124
  declare const onboardingTourServices: ServiceDefinition[];
129
125
  declare function getServiceBySlug(slug: string): ServiceDefinition | undefined;
130
126
  declare function getServiceUrl(service: ServiceDefinition): string | null;
131
127
 
132
- export { DEFAULT_PLATFORM_DOMAIN, SERVICE_CATALOG, type ServiceCategory, type ServiceDefinition, type ServiceOnboardingContent, type ServiceOnboardingFeature, type ServiceStatus, comingSoonServices, coreServices, getPlatformDomain, getServiceBySlug, getServiceUrl, hubServices, inDevServices, liveServices, onboardingTourServices, platformUrl, portalUrl };
128
+ export { DEFAULT_PLATFORM_DOMAIN, SERVICE_CATALOG, type ServiceCategory, type ServiceDefinition, type ServiceOnboardingContent, type ServiceOnboardingFeature, coreServices, getPlatformDomain, getServiceBySlug, getServiceUrl, hubServices, liveServices, onboardingTourServices, platformUrl, portalUrl };
@@ -3,16 +3,14 @@ import {
3
3
  SERVICE_CATALOG,
4
4
  SLUG_ALIASES,
5
5
  buildCrossServiceLinks,
6
- comingSoonServices,
7
6
  coreServices,
8
7
  getServiceBySlug,
9
8
  getServiceUrl,
10
9
  hubServices,
11
- inDevServices,
12
10
  liveServices,
13
11
  normalizeServiceSlug,
14
12
  onboardingTourServices
15
- } from "../chunk-MGTOQY6O.js";
13
+ } from "../chunk-45ZQDLPA.js";
16
14
  import {
17
15
  DEFAULT_PLATFORM_DOMAIN,
18
16
  getPlatformDomain,
@@ -27,13 +25,11 @@ export {
27
25
  SERVICE_CATALOG,
28
26
  SLUG_ALIASES,
29
27
  buildCrossServiceLinks,
30
- comingSoonServices,
31
28
  coreServices,
32
29
  getPlatformDomain,
33
30
  getServiceBySlug,
34
31
  getServiceUrl,
35
32
  hubServices,
36
- inDevServices,
37
33
  liveServices,
38
34
  normalizeServiceSlug,
39
35
  onboardingTourServices,
@@ -1,6 +1,6 @@
1
- import { D as DashboardLayout, a as DashboardLayoutEnterprise, b as DashboardLayoutProps, c as DashboardLayoutUser } from '../HealthFooter-BpByxJkc.js';
2
- export { C as CrossServiceNav, d as CrossServiceNavProps, H as HealthFooter, e as HealthFooterEnterprise, f as HealthFooterProps, g as HealthFooterUser, M as MenuItem, h as MenuSection } from '../HealthFooter-BpByxJkc.js';
3
- export { C as CrossServiceLink, b as buildCrossServiceLinks } from '../crossNav-Bz0RXU_F.js';
1
+ import { D as DashboardLayout, a as DashboardLayoutEnterprise, b as DashboardLayoutProps, c as DashboardLayoutUser } from '../HealthFooter-Cepg3mRC.js';
2
+ export { C as CrossServiceNav, d as CrossServiceNavProps, H as HealthFooter, e as HealthFooterEnterprise, f as HealthFooterProps, g as HealthFooterUser, M as MenuItem, h as MenuSection } from '../HealthFooter-Cepg3mRC.js';
3
+ export { C as CrossServiceLink, b as buildCrossServiceLinks } from '../crossNav-DBX4Eyx7.js';
4
4
  import 'react';
5
5
  import '../orgHierarchy-Buky69YP.js';
6
6
 
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  buildCrossServiceLinks
3
- } from "../chunk-MGTOQY6O.js";
3
+ } from "../chunk-45ZQDLPA.js";
4
4
  import {
5
5
  CrossServiceNav,
6
6
  DashboardLayout,
7
7
  HealthFooter
8
- } from "../chunk-CIGJSBWS.js";
9
- import "../chunk-LUQAR6NB.js";
8
+ } from "../chunk-HWPEU5YY.js";
9
+ import "../chunk-BG4DVZAY.js";
10
10
  import "../chunk-7LI4Y6WT.js";
11
11
  import "../chunk-RSFGV7CG.js";
12
12
  import "../chunk-DMUQ5WNO.js";
@@ -27,7 +27,7 @@ import {
27
27
  useTourProgress,
28
28
  useTourState,
29
29
  validateTourDefinition
30
- } from "../chunk-LUQAR6NB.js";
30
+ } from "../chunk-BG4DVZAY.js";
31
31
  import "../chunk-7LI4Y6WT.js";
32
32
  import "../chunk-JT3XLKKD.js";
33
33
  export {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pablo2410/shared-ui",
3
- "version": "0.26.0",
3
+ "version": "0.27.1",
4
4
  "description": "Shared UI component library for all Oplytics.digital subdomains",
5
5
  "type": "module",
6
6
  "exports": {
@@ -94,36 +94,36 @@
94
94
  "tailwindcss": "^4.3.3",
95
95
  "tsup": "^8.5.1",
96
96
  "typescript": "^5.9.3",
97
- "vite": "^8.3.2",
97
+ "vite": "^8.3.3",
98
98
  "vitest": "^5.0.3"
99
99
  },
100
100
  "dependencies": {
101
- "@radix-ui/react-accordion": "^1.2.20",
102
- "@radix-ui/react-alert-dialog": "^1.1.23",
103
- "@radix-ui/react-aspect-ratio": "^1.1.15",
104
- "@radix-ui/react-avatar": "^1.2.6",
105
- "@radix-ui/react-checkbox": "^1.3.11",
106
- "@radix-ui/react-collapsible": "^1.1.20",
107
- "@radix-ui/react-context-menu": "^2.3.7",
108
- "@radix-ui/react-dialog": "^1.1.23",
109
- "@radix-ui/react-dropdown-menu": "^2.1.24",
110
- "@radix-ui/react-hover-card": "^1.1.23",
111
- "@radix-ui/react-label": "^2.1.15",
112
- "@radix-ui/react-menubar": "^1.1.24",
113
- "@radix-ui/react-navigation-menu": "^1.2.22",
114
- "@radix-ui/react-popover": "^1.1.23",
115
- "@radix-ui/react-progress": "^1.1.16",
116
- "@radix-ui/react-radio-group": "^1.4.7",
117
- "@radix-ui/react-scroll-area": "^1.2.18",
118
- "@radix-ui/react-select": "^2.3.7",
119
- "@radix-ui/react-separator": "^1.1.15",
120
- "@radix-ui/react-slider": "^1.4.7",
121
- "@radix-ui/react-slot": "^1.3.3",
122
- "@radix-ui/react-switch": "^1.3.7",
123
- "@radix-ui/react-tabs": "^1.1.21",
124
- "@radix-ui/react-toggle": "^1.1.18",
125
- "@radix-ui/react-toggle-group": "^1.1.19",
126
- "@radix-ui/react-tooltip": "^1.2.16",
101
+ "@radix-ui/react-accordion": "^1.2.21",
102
+ "@radix-ui/react-alert-dialog": "^1.1.24",
103
+ "@radix-ui/react-aspect-ratio": "^1.1.16",
104
+ "@radix-ui/react-avatar": "^1.2.7",
105
+ "@radix-ui/react-checkbox": "^1.3.12",
106
+ "@radix-ui/react-collapsible": "^1.1.21",
107
+ "@radix-ui/react-context-menu": "^2.3.8",
108
+ "@radix-ui/react-dialog": "^1.2.0",
109
+ "@radix-ui/react-dropdown-menu": "^2.1.25",
110
+ "@radix-ui/react-hover-card": "^1.1.24",
111
+ "@radix-ui/react-label": "^2.1.16",
112
+ "@radix-ui/react-menubar": "^1.1.25",
113
+ "@radix-ui/react-navigation-menu": "^1.3.0",
114
+ "@radix-ui/react-popover": "^1.2.0",
115
+ "@radix-ui/react-progress": "^1.1.17",
116
+ "@radix-ui/react-radio-group": "^1.4.8",
117
+ "@radix-ui/react-scroll-area": "^1.3.0",
118
+ "@radix-ui/react-select": "^2.3.8",
119
+ "@radix-ui/react-separator": "^1.1.16",
120
+ "@radix-ui/react-slider": "^1.5.0",
121
+ "@radix-ui/react-slot": "^1.4.0",
122
+ "@radix-ui/react-switch": "^1.3.8",
123
+ "@radix-ui/react-tabs": "^1.1.22",
124
+ "@radix-ui/react-toggle": "^1.1.19",
125
+ "@radix-ui/react-toggle-group": "^1.1.20",
126
+ "@radix-ui/react-tooltip": "^1.3.0",
127
127
  "class-variance-authority": "^0.7.1",
128
128
  "clsx": "^2.1.1",
129
129
  "cmdk": "^1.1.1",