import { useEffect, useMemo, useRef, useState } from "react"; import type React from "react"; import { Activity, BarChart3, Download, FileClock, FileJson, Github, HelpCircle, Heart, Search, Plus, RotateCcw, Save, Send, ShieldAlert, Trash2, Upload, X, UserRound } from "lucide-react"; import { accommodationLabels, categoryTooltipTexts, delayedSymptomLabels, limitationLabels, negativeScale, positiveScale, recoveryLabels, statusLabels, taskCompletionLabels, taskTypeLabels, tooltipTexts, worseLabels } from "./labels"; import { deleteEvaluatorNote, deleteEvaluatorProfile, exportEvaluatorBackup, importEvaluatorBackup, importExportPayload, listEvaluatorProfiles, renameEvaluatorProfile, upsertEvaluatorNote } from "./evaluatorStorage"; import { calculatePeriodWorkAbilityAssessment, calculateReportScore, getEntryTime, getReportScore, getScoreBand, normalizeReportMetric, scoreBandDisclaimer } from "./scoring"; import { verificationLabel, verificationTooltip } from "./integrity"; import { I18nProvider, translateScoreBand, translateScoreBandDescription, translateVerificationStatus, useI18n } from "./i18n"; import { createFollowup, createReport, deleteAllReports, deleteReport, exportReports, getLastWorkReport, importReportsFromJson, listReports, previewImportReports } from "./storage"; import type { Accommodation, DelayedFollowup, DelayedSymptom, EvaluatorProfile, FollowupDraft, ImportSummary, Limitation, RecoveryStatus, Report, ReportDraft, ReportStatus, ScaleValue, StoredEntry, TaskCompletion, TaskType, WorseThanBefore } from "./types"; type View = "registrer" | "oppfolging" | "oversikt" | "personvern"; type PresetRange = "7d" | "1m" | "3m" | "6m" | "1y" | "3y" | "5y" | "all" | "custom"; type LineVisibility = "normal" | "dim" | "hidden"; type TrendMetric = { key: keyof Report | "total_score_percent"; label: string; short: string; color: string }; const PERIOD_KEY = "arbeidsevne-egenvurdering:trend-period"; const APP_VERSION = "1.0"; const taskTypeOptions = Object.keys(taskTypeLabels) as TaskType[]; const limitationOptions = Object.keys(limitationLabels) as Limitation[]; const accommodationOptions = Object.keys(accommodationLabels) as Accommodation[]; const delayedSymptomOptions = Object.keys(delayedSymptomLabels) as DelayedSymptom[]; const visibleStatusOptions: ReportStatus[] = ["kan_fortsette", "trenger_pause", "trenger_enklere_oppgave", "b酶r_stoppe"]; const trendMetrics: TrendMetric[] = [ { key: "total_score_percent", label: "Totalscore", short: "T", color: "#235b5e" }, { key: "work_ability", label: "Arbeidsevne", short: "A", color: "#307f78" }, { key: "energy_level", label: "Energi", short: "E", color: "#b2642a" }, { key: "mental_clarity", label: "Klarhet", short: "K", color: "#4f5c9c" }, { key: "symptom_burden", label: "Symptomer", short: "S", color: "#b23b4a" }, { key: "effort_strain", label: "Belastning", short: "B", color: "#6b5a3a" } ]; function App() { return ( ); } function AppRoutes() { const { t } = useI18n(); if (window.location.pathname.startsWith("/evaluator") || window.location.pathname.startsWith("/veileder")) { return ; } const [view, setView] = useState("registrer"); const [entries, setEntries] = useState(() => listReports()); const [selectedEntryId, setSelectedEntryId] = useState(null); const [deleteRequest, setDeleteRequest] = useState<{ id: string; name: string } | null>(null); const refresh = () => setEntries(listReports()); const selectedEntry = selectedEntryId ? entries.find((entry) => entry.id === selectedEntryId) : undefined; return (

{t("app.eyebrow")}

{t("app.title")}

{t("app.evaluator")}
{view === "registrer" && } {view === "oppfolging" && } {view === "oversikt" && ( setSelectedEntryId(null)} onRequestDelete={(entry) => setDeleteRequest({ id: entry.id, name: entry.type === "work_report" ? entry.workplace || t("danger.reportName") : t("danger.followupName") })} /> )} {view === "personvern" && }
setDeleteRequest(null)} onConfirm={() => { if (!deleteRequest) return; deleteReport(deleteRequest.id); if (selectedEntryId === deleteRequest.id) setSelectedEntryId(null); setDeleteRequest(null); refresh(); }} />
); } function NavButton({ icon, label, active, onClick }: { icon: React.ReactNode; label: string; active: boolean; onClick: () => void; }) { return ( ); } function AppFooter() { const { language, setLanguage, t } = useI18n(); const baseYear = 2026; const currentYear = new Date().getFullYear(); const yearLabel = currentYear > baseYear ? `${baseYear}-${currentYear}` : `${baseYear}`; return ( ); } function ConfirmDeleteModal({ open, itemName, onCancel, onConfirm }: { open: boolean; itemName: string; onCancel: () => void; onConfirm: () => void; }) { const { t } = useI18n(); const [secondsLeft, setSecondsLeft] = useState(1); useEffect(() => { if (!open) return; setSecondsLeft(1); const timer = window.setTimeout(() => setSecondsLeft(0), 1000); return () => window.clearTimeout(timer); }, [open, itemName]); useEffect(() => { if (!open) return; const onKeyDown = (event: KeyboardEvent) => { if (event.key === "Escape") onCancel(); if (event.key === "Enter" && secondsLeft > 0) event.preventDefault(); }; window.addEventListener("keydown", onKeyDown); return () => window.removeEventListener("keydown", onKeyDown); }, [onCancel, open, secondsLeft]); if (!open) return null; return (
event.stopPropagation()}>

{t("deleteModal.title")}

{t("deleteModal.body", { itemName })}

); } function createInitialReportDraft(): ReportDraft { const last = getLastWorkReport(); return { workplace: last?.workplace ?? "", work_start_time: last?.work_start_time ?? "", work_end_time: last?.work_end_time ?? "", task_types: [], main_limitations: [], helpful_accommodations: [], note: "" }; } function ReportForm({ onSaved }: { onSaved: () => void }) { const { labels, t } = useI18n(); const [draft, setDraft] = useState(() => createInitialReportDraft()); const [attempted, setAttempted] = useState(false); const [savedText, setSavedText] = useState(""); const reportFields = requiredReportFields.map((field) => ({ ...field, label: reportFieldLabel(field.key, t) })); const missing = reportFields.filter((field) => !draft[field.key]); const canSubmit = missing.length === 0; const setScale = (key: keyof ReportDraft, value: ScaleValue) => { setDraft((current) => ({ ...current, [key]: value })); }; const toggle = (key: keyof ReportDraft, value: T) => { setDraft((current) => { const values = current[key] as T[]; return { ...current, [key]: values.includes(value) ? values.filter((item) => item !== value) : [...values, value] }; }); }; const submit = () => { setAttempted(true); if (!canSubmit) return; createReport(draft); setDraft(createInitialReportDraft()); setAttempted(false); setSavedText(t("register.saved")); onSaved(); window.setTimeout(() => setSavedText(""), 2400); }; return (

{t("register.workSession")}

{reportFields.map((field) => ( setScale(field.key, value)} /> ))}

{t("register.continueQuestion")}

{t("register.chooseBestNow")}

{visibleStatusOptions.map((status) => ( ))}
{t("register.optionalDetails")}
setScale("physical_energy_detail", value)} /> setScale("mental_energy_detail", value)} /> setScale("perceived_productivity", value)} /> setDraft((current) => ({ ...current, task_completion: value }))} /> toggle("task_types", value)} /> toggle("main_limitations", value)} /> toggle("helpful_accommodations", value)} />