@burdenoff/microfe-technospam 2026.1102.1 → 2026.1102.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (133) hide show
  1. package/dist/generated/wspace-types.d.ts +7468 -141
  2. package/dist/generated/wspace-types.d.ts.map +1 -1
  3. package/dist/node_modules/@codemirror/autocomplete/dist/index.js +527 -0
  4. package/dist/node_modules/@codemirror/autocomplete/dist/index.js.map +1 -0
  5. package/dist/node_modules/@codemirror/commands/dist/index.js +1108 -0
  6. package/dist/node_modules/@codemirror/commands/dist/index.js.map +1 -0
  7. package/dist/node_modules/@codemirror/lang-go/dist/index.js +206 -0
  8. package/dist/node_modules/@codemirror/lang-go/dist/index.js.map +1 -0
  9. package/dist/node_modules/@codemirror/lang-javascript/dist/index.js +321 -0
  10. package/dist/node_modules/@codemirror/lang-javascript/dist/index.js.map +1 -0
  11. package/dist/node_modules/@codemirror/lang-python/dist/index.js +265 -0
  12. package/dist/node_modules/@codemirror/lang-python/dist/index.js.map +1 -0
  13. package/dist/node_modules/@codemirror/language/dist/index.js +957 -0
  14. package/dist/node_modules/@codemirror/language/dist/index.js.map +1 -0
  15. package/dist/node_modules/@codemirror/legacy-modes/mode/ruby.js +164 -0
  16. package/dist/node_modules/@codemirror/legacy-modes/mode/ruby.js.map +1 -0
  17. package/dist/node_modules/@codemirror/legacy-modes/mode/shell.js +109 -0
  18. package/dist/node_modules/@codemirror/legacy-modes/mode/shell.js.map +1 -0
  19. package/dist/node_modules/@codemirror/state/dist/index.js +1739 -0
  20. package/dist/node_modules/@codemirror/state/dist/index.js.map +1 -0
  21. package/dist/node_modules/@codemirror/streamparser/dist/index.js +70 -0
  22. package/dist/node_modules/@codemirror/streamparser/dist/index.js.map +1 -0
  23. package/dist/node_modules/@codemirror/view/dist/index.js +5427 -0
  24. package/dist/node_modules/@codemirror/view/dist/index.js.map +1 -0
  25. package/dist/node_modules/@lezer/common/dist/index.js +896 -0
  26. package/dist/node_modules/@lezer/common/dist/index.js.map +1 -0
  27. package/dist/node_modules/@lezer/go/dist/index.js +215 -0
  28. package/dist/node_modules/@lezer/go/dist/index.js.map +1 -0
  29. package/dist/node_modules/@lezer/highlight/dist/index.js +395 -0
  30. package/dist/node_modules/@lezer/highlight/dist/index.js.map +1 -0
  31. package/dist/node_modules/@lezer/javascript/dist/index.js +437 -0
  32. package/dist/node_modules/@lezer/javascript/dist/index.js.map +1 -0
  33. package/dist/node_modules/@lezer/lr/dist/index.js +842 -0
  34. package/dist/node_modules/@lezer/lr/dist/index.js.map +1 -0
  35. package/dist/node_modules/@lezer/python/dist/index.js +352 -0
  36. package/dist/node_modules/@lezer/python/dist/index.js.map +1 -0
  37. package/dist/node_modules/@marijn/find-cluster-break/src/index.js +66 -0
  38. package/dist/node_modules/@marijn/find-cluster-break/src/index.js.map +1 -0
  39. package/dist/node_modules/style-mod/src/style-mod.js +74 -0
  40. package/dist/node_modules/style-mod/src/style-mod.js.map +1 -0
  41. package/dist/node_modules/w3c-keyname/index.js +90 -0
  42. package/dist/node_modules/w3c-keyname/index.js.map +1 -0
  43. package/dist/stories/fixtures/technospamFixtures.d.ts.map +1 -1
  44. package/dist/stories/journeys/Problems.stories.d.ts.map +1 -1
  45. package/dist/technospam/TechnoSpamRoot.d.ts.map +1 -1
  46. package/dist/technospam/TechnoSpamRoot.js +187 -178
  47. package/dist/technospam/TechnoSpamRoot.js.map +1 -1
  48. package/dist/technospam/api/technospamApi.d.ts +39 -0
  49. package/dist/technospam/api/technospamApi.d.ts.map +1 -1
  50. package/dist/technospam/api/technospamApi.js +184 -150
  51. package/dist/technospam/api/technospamApi.js.map +1 -1
  52. package/dist/technospam/components/MediaCover.js +2 -2
  53. package/dist/technospam/components/MediaCover.js.map +1 -1
  54. package/dist/technospam/components/MobileSectionTabs.d.ts +9 -0
  55. package/dist/technospam/components/MobileSectionTabs.d.ts.map +1 -0
  56. package/dist/technospam/components/MobileSectionTabs.js +43 -0
  57. package/dist/technospam/components/MobileSectionTabs.js.map +1 -0
  58. package/dist/technospam/components/PageLayout.d.ts +7 -1
  59. package/dist/technospam/components/PageLayout.d.ts.map +1 -1
  60. package/dist/technospam/components/PageLayout.js +40 -28
  61. package/dist/technospam/components/PageLayout.js.map +1 -1
  62. package/dist/technospam/components/SubmissionViews.d.ts +6 -2
  63. package/dist/technospam/components/SubmissionViews.d.ts.map +1 -1
  64. package/dist/technospam/components/SubmissionViews.js +6 -5
  65. package/dist/technospam/components/SubmissionViews.js.map +1 -1
  66. package/dist/technospam/components/TechnoSpamErrorBoundary.d.ts +6 -0
  67. package/dist/technospam/components/TechnoSpamErrorBoundary.d.ts.map +1 -1
  68. package/dist/technospam/components/TechnoSpamErrorBoundary.js +2 -2
  69. package/dist/technospam/components/TechnoSpamErrorBoundary.js.map +1 -1
  70. package/dist/technospam/components/editor/CodeEditor.d.ts +26 -0
  71. package/dist/technospam/components/editor/CodeEditor.d.ts.map +1 -0
  72. package/dist/technospam/components/editor/CodeEditor.js +102 -0
  73. package/dist/technospam/components/editor/CodeEditor.js.map +1 -0
  74. package/dist/technospam/components/editor/RunOutputPanel.d.ts +14 -0
  75. package/dist/technospam/components/editor/RunOutputPanel.d.ts.map +1 -0
  76. package/dist/technospam/components/editor/RunOutputPanel.js +127 -0
  77. package/dist/technospam/components/editor/RunOutputPanel.js.map +1 -0
  78. package/dist/technospam/components/editor/editorLanguages.d.ts +11 -0
  79. package/dist/technospam/components/editor/editorLanguages.d.ts.map +1 -0
  80. package/dist/technospam/components/editor/editorLanguages.js +30 -0
  81. package/dist/technospam/components/editor/editorLanguages.js.map +1 -0
  82. package/dist/technospam/components/editor/editorTheme.d.ts +11 -0
  83. package/dist/technospam/components/editor/editorTheme.d.ts.map +1 -0
  84. package/dist/technospam/components/editor/editorTheme.js +120 -0
  85. package/dist/technospam/components/editor/editorTheme.js.map +1 -0
  86. package/dist/technospam/components/lesson/SaveCourseOffline.js +6 -6
  87. package/dist/technospam/hooks/usePhoneLayout.d.ts +18 -0
  88. package/dist/technospam/hooks/usePhoneLayout.d.ts.map +1 -0
  89. package/dist/technospam/hooks/usePhoneLayout.js +14 -0
  90. package/dist/technospam/hooks/usePhoneLayout.js.map +1 -0
  91. package/dist/technospam/hooks/useSolutionRunner.d.ts +35 -0
  92. package/dist/technospam/hooks/useSolutionRunner.d.ts.map +1 -0
  93. package/dist/technospam/hooks/useSolutionRunner.js +66 -0
  94. package/dist/technospam/hooks/useSolutionRunner.js.map +1 -0
  95. package/dist/technospam/hooks/useTechnoSpamAnalytics.d.ts +1 -1
  96. package/dist/technospam/hooks/useTechnoSpamAnalytics.d.ts.map +1 -1
  97. package/dist/technospam/hooks/useTechnoSpamAnalytics.js.map +1 -1
  98. package/dist/technospam/pages/AdminAdminDashboardPagePage.js +1 -1
  99. package/dist/technospam/pages/AdminAdminDashboardPagePage.js.map +1 -1
  100. package/dist/technospam/pages/ApplicationsProblemDetailsPagePage.d.ts.map +1 -1
  101. package/dist/technospam/pages/ApplicationsProblemDetailsPagePage.js +416 -263
  102. package/dist/technospam/pages/ApplicationsProblemDetailsPagePage.js.map +1 -1
  103. package/dist/technospam/pages/ApplicationsProblemsPagePage.d.ts.map +1 -1
  104. package/dist/technospam/pages/ApplicationsProblemsPagePage.js +89 -87
  105. package/dist/technospam/pages/ApplicationsProblemsPagePage.js.map +1 -1
  106. package/dist/technospam/pages/CoursesCourseDetailsPagePage.js +3 -3
  107. package/dist/technospam/pages/CoursesCourseDetailsPagePage.js.map +1 -1
  108. package/dist/technospam/pages/CoursesCoursesPagePage.d.ts.map +1 -1
  109. package/dist/technospam/pages/CoursesCoursesPagePage.js +117 -81
  110. package/dist/technospam/pages/CoursesCoursesPagePage.js.map +1 -1
  111. package/dist/technospam/pages/CoursesMyLearningPagePage.js +1 -1
  112. package/dist/technospam/pages/CoursesMyLearningPagePage.js.map +1 -1
  113. package/dist/technospam/pages/DashboardDashboardPagePage.d.ts.map +1 -1
  114. package/dist/technospam/pages/DashboardDashboardPagePage.js +21 -17
  115. package/dist/technospam/pages/DashboardDashboardPagePage.js.map +1 -1
  116. package/dist/technospam/pages/HackathonsHackathonDetailsPagePage.js +3 -3
  117. package/dist/technospam/pages/HackathonsHackathonDetailsPagePage.js.map +1 -1
  118. package/dist/technospam/pages/MentorshipMentorProfilePagePage.js +4 -4
  119. package/dist/technospam/pages/MentorshipMentorProfilePagePage.js.map +1 -1
  120. package/dist/technospam/pages/MentorshipMentorsPagePage.d.ts.map +1 -1
  121. package/dist/technospam/pages/MentorshipMentorsPagePage.js +6 -4
  122. package/dist/technospam/pages/MentorshipMentorsPagePage.js.map +1 -1
  123. package/dist/technospam/pages/MentorshipSessionsPagePage.js +1 -1
  124. package/dist/technospam/pages/MentorshipSessionsPagePage.js.map +1 -1
  125. package/dist/technospam/types/index.d.ts +7 -0
  126. package/dist/technospam/types/index.d.ts.map +1 -1
  127. package/dist/technospam/utils/mobileTabs.d.ts +45 -0
  128. package/dist/technospam/utils/mobileTabs.d.ts.map +1 -0
  129. package/dist/technospam/utils/mobileTabs.js +70 -0
  130. package/dist/technospam/utils/mobileTabs.js.map +1 -0
  131. package/dist/test/matchMedia.d.ts +6 -0
  132. package/dist/test/matchMedia.d.ts.map +1 -0
  133. package/package.json +16 -6
@@ -1 +1 @@
1
- {"version":3,"file":"ApplicationsProblemDetailsPagePage.js","names":[],"sources":["../../../src/technospam/pages/ApplicationsProblemDetailsPagePage.tsx"],"sourcesContent":["import { useEffect, useMemo, useRef, useState } from 'react';\nimport { useSearchParams } from 'react-router';\nimport {\n Clock,\n Code2,\n FileText,\n FlaskConical,\n Layers,\n RefreshCw,\n Send,\n Sparkles,\n Tag,\n Trophy,\n} from 'lucide-react';\nimport {\n Badge,\n Button,\n GlassCard,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n Skeleton,\n Textarea,\n} from '@burdenoff/fe-libs/ui';\nimport {\n CodePanel,\n EmptyView,\n ErrorView,\n IoBlock,\n LoadingRows,\n PageLayout,\n PremiumBadge,\n StatCard,\n StatusBadge,\n SubmissionReviewPanel,\n TagStrip,\n TestResultsPanel,\n UpgradeGate,\n} from '../components';\nimport { useTechnoSpam, useTechnoSpamNavigate } from '../providers/TechnoSpamProvider';\nimport {\n useProblemQuery,\n useRegradeSubmission,\n useSubmissionsQuery,\n useSubmitSolution,\n type TecSubmission,\n} from '../api/technospamApi';\nimport { formatDateTime, humanizeEnum } from '../utils/format';\nimport { notify } from '../lib/toast';\nimport { useTechnoSpamAnalytics } from '../hooks/useTechnoSpamAnalytics';\nimport {\n FOCUSED_CARD_CLASS,\n focusableCardProps,\n useFocusedRecordParam,\n} from '../hooks/useFocusedRecordParam';\nimport { FOCUS_PARAMS } from '../utils/pageContext';\nimport { cn } from '../utils/cn';\n\nconst FALLBACK_LANGUAGES = ['javascript', 'python', 'typescript'];\n\n/**\n * A submission made while the grading sandbox is cold comes back PENDING and is\n * graded in the background (BOFF-4414). Poll the submissions list until the\n * verdict lands, giving up after a few minutes so a genuinely failed grade\n * falls back to the manual re-run button.\n */\nconst PENDING_POLL_INTERVAL_MS = 3_000;\nconst PENDING_POLL_MAX_MS = 3 * 60_000;\n\nfunction SubmissionRow({\n s,\n focused,\n onToggle,\n}: {\n s: TecSubmission;\n /** The focused submission (`?submissionId=`) is the one the assistant acts on. */\n focused: boolean;\n onToggle: () => void;\n}) {\n return (\n <div\n className={cn(\n 'cursor-pointer rounded-lg border border-transparent px-2 py-3 transition-colors hover:border-border-seam hover:bg-bg-sunken',\n focused && FOCUSED_CARD_CLASS\n )}\n {...focusableCardProps(focused, onToggle)}\n >\n <div className=\"flex flex-wrap items-center gap-x-4 gap-y-1\">\n <button\n type=\"button\"\n aria-pressed={focused}\n aria-label={`Focus submission from ${formatDateTime(s.createdAt)}`}\n onClick={onToggle}\n className=\"rounded-full\"\n >\n <StatusBadge status={s.verdict} />\n </button>\n <span className=\"inline-flex items-center gap-1 text-sm font-medium text-text-primary\">\n <Code2 size={13} /> {humanizeEnum(s.language)}\n </span>\n <span className=\"inline-flex items-center gap-1 text-xs text-text-muted\">\n <Clock size={12} /> {s.runtimeMs} ms\n </span>\n <span className=\"inline-flex items-center gap-1 text-xs text-text-muted\">\n <Trophy size={12} /> {s.pointsAwarded} pts\n </span>\n <span className=\"ml-auto text-xs text-text-muted\">{formatDateTime(s.createdAt)}</span>\n </div>\n {s.totalCount > 0 ? (\n <p className=\"mt-1 px-0.5 text-xs text-text-muted\">\n Passed {s.passedCount} of {s.totalCount} test cases\n </p>\n ) : null}\n </div>\n );\n}\n\nexport function ApplicationsProblemDetailsPagePage() {\n const [params] = useSearchParams();\n const id = params.get('id') ?? '';\n // The focused submission lives in `?submissionId=` so the assistant's page\n // context names it (\"explain this submission\").\n const [focusedSubmissionId, setFocusedSubmissionId] = useFocusedRecordParam(\n FOCUS_PARAMS.submission\n );\n const { currentUser, workspaceId } = useTechnoSpam();\n const navigate = useTechnoSpamNavigate();\n const learnerId = currentUser?.id;\n const { emit } = useTechnoSpamAnalytics();\n\n const { data, loading, error, refetch } = useProblemQuery(id);\n\n useEffect(() => {\n if (id) {\n emit('technospam.problem.viewed', {\n workspaceId,\n entityId: id,\n entityType: 'TEC_PROBLEM',\n });\n }\n }, [id, workspaceId, emit]);\n const {\n data: subsData,\n loading: subsLoading,\n error: subsError,\n refetch: refetchSubs,\n } = useSubmissionsQuery({ ...(learnerId ? { learnerId } : {}), problemId: id });\n const [submit, { loading: submitting }] = useSubmitSolution();\n const [regrade, { loading: regrading }] = useRegradeSubmission();\n\n const problem = data?.tecProblem ?? null;\n\n const languages = useMemo(\n () => (problem?.languages?.length ? problem.languages : FALLBACK_LANGUAGES),\n [problem]\n );\n\n const [language, setLanguage] = useState('');\n const [code, setCode] = useState('');\n const initedRef = useRef(false);\n\n useEffect(() => {\n if (problem && !initedRef.current) {\n setLanguage(problem.languages[0] ?? FALLBACK_LANGUAGES[0]!);\n setCode(problem.starterCode ?? '');\n initedRef.current = true;\n }\n }, [problem]);\n\n const submissions = useMemo(\n () =>\n [...(subsData?.tecListSubmissions?.items ?? [])].sort(\n (a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()\n ),\n [subsData]\n );\n\n const handleSubmit = async () => {\n if (!id) return;\n if (!language) {\n notify.error('Pick a language', 'Choose a language before submitting.');\n return;\n }\n if (!code.trim()) {\n notify.error('Add your solution', 'Write some code before submitting.');\n return;\n }\n emit('technospam.problem.submit_clicked', {\n workspaceId,\n entityId: id,\n entityType: 'TEC_PROBLEM',\n language,\n });\n const res = await submit({ variables: { input: { problemId: id, language, code } } });\n if (res.data?.tecSubmitSolution) {\n emit('technospam.problem.submitted', {\n workspaceId,\n entityId: id,\n entityType: 'TEC_PROBLEM',\n submissionId: res.data.tecSubmitSolution.id,\n });\n const graded = res.data.tecSubmitSolution;\n if (graded.verdict === 'PENDING') {\n notify.info(\n 'Solution submitted',\n 'Grading has started — your verdict will appear here in a moment.'\n );\n } else if (graded.verdict === 'ACCEPTED') {\n notify.success('Accepted', `Passed all ${graded.totalCount} test cases.`);\n } else {\n notify.error(\n humanizeEnum(graded.verdict),\n `Passed ${graded.passedCount} of ${graded.totalCount} test cases.`\n );\n }\n await Promise.all([refetch(), refetchSubs()]);\n }\n };\n\n const handleRegrade = async (submissionId: string) => {\n const res = await regrade({ variables: { id: submissionId } });\n const graded = res.data?.tecRegradeSubmission;\n if (!graded) return;\n if (graded.verdict === 'PENDING') {\n notify.error('Still pending', 'The grader is not available yet. Please try again shortly.');\n } else {\n notify.success('Grading complete', `Verdict: ${humanizeEnum(graded.verdict)}.`);\n }\n await Promise.all([refetch(), refetchSubs()]);\n };\n\n /** Most recent submission that actually carries grading detail. */\n const latestGraded = submissions.find((s) => (s.testResults?.length ?? 0) > 0) ?? null;\n const latestSubmission = submissions[0] ?? null;\n const pendingId = latestSubmission?.verdict === 'PENDING' ? latestSubmission.id : null;\n\n // Poll while the newest submission is still being graded in the background.\n const [pollExpiredFor, setPollExpiredFor] = useState<string | null>(null);\n const polling = pendingId !== null && pollExpiredFor !== pendingId;\n useEffect(() => {\n if (!pendingId || pollExpiredFor === pendingId) return undefined;\n const startedAt = Date.now();\n const timer = window.setInterval(() => {\n if (Date.now() - startedAt > PENDING_POLL_MAX_MS) {\n window.clearInterval(timer);\n setPollExpiredFor(pendingId);\n return;\n }\n void refetchSubs();\n }, PENDING_POLL_INTERVAL_MS);\n return () => window.clearInterval(timer);\n }, [pendingId, pollExpiredFor, refetchSubs]);\n\n // Announce the verdict once a background-graded submission settles.\n const awaitedIdRef = useRef<string | null>(null);\n useEffect(() => {\n if (pendingId) {\n awaitedIdRef.current = pendingId;\n return;\n }\n const awaitedId = awaitedIdRef.current;\n if (!awaitedId) return;\n const settled = submissions.find((s) => s.id === awaitedId);\n if (!settled || settled.verdict === 'PENDING') return;\n awaitedIdRef.current = null;\n if (settled.verdict === 'ACCEPTED') {\n notify.success('Accepted', `Passed all ${settled.totalCount} test cases.`);\n } else {\n notify.error(\n humanizeEnum(settled.verdict),\n `Passed ${settled.passedCount} of ${settled.totalCount} test cases.`\n );\n }\n void refetch();\n }, [pendingId, submissions, refetch]);\n\n if (loading && !problem) {\n return (\n <PageLayout title=\"Problem\" backPath=\"/applications/problems-page\">\n <Skeleton className=\"mb-4 h-28 w-full rounded-xl\" />\n <Skeleton className=\"h-72 w-full rounded-xl\" />\n </PageLayout>\n );\n }\n\n if (error || !problem) {\n return (\n <PageLayout title=\"Problem\" backPath=\"/applications/problems-page\">\n {error ? (\n <ErrorView title=\"Couldn't load problem\" error={error} />\n ) : (\n <EmptyView\n title=\"Problem not found\"\n description=\"This problem may have been unpublished.\"\n />\n )}\n </PageLayout>\n );\n }\n\n return (\n <PageLayout\n hero\n backPath=\"/applications/problems-page\"\n title={problem.title}\n description={problem.topic ?? undefined}\n >\n <div className=\"mb-5 flex flex-wrap items-center gap-2\">\n <StatusBadge status={problem.difficulty} kind=\"level\" />\n <StatusBadge status={problem.status} />\n {problem.topic ? (\n <Badge variant=\"outline\" className=\"gap-1\">\n <Layers size={12} /> {problem.topic}\n </Badge>\n ) : null}\n {problem.isPremiumOnly ? <PremiumBadge locked={problem.isLocked} /> : null}\n <TagStrip tags={problem.tags} />\n </div>\n\n <div className=\"mb-6 grid grid-cols-2 gap-3 sm:grid-cols-4\">\n <StatCard label=\"Points\" value={problem.points} icon={Trophy} tone=\"amber\" />\n <StatCard label=\"Languages\" value={languages.length} icon={Code2} tone=\"blue\" />\n <StatCard\n label=\"Difficulty\"\n value={humanizeEnum(problem.difficulty)}\n icon={Layers}\n tone=\"purple\"\n />\n <StatCard label=\"My submissions\" value={submissions.length} icon={FileText} tone=\"teal\" />\n </div>\n\n <div className=\"grid grid-cols-1 gap-5 lg:grid-cols-3\">\n <div className=\"space-y-5 lg:col-span-2\">\n <GlassCard className=\"p-5\">\n <h2 className=\"mb-2 text-base font-semibold text-text-primary\">Problem statement</h2>\n {problem.isLocked ? (\n // BOFF-4416: the API already nulled `statement` for a locked\n // premium problem — this explains why, rather than showing the\n // generic \"being prepared\" message used for a real content gap.\n <UpgradeGate description=\"This problem's statement is part of a paid TechnoSpam plan. Ask a workspace admin to upgrade to unlock it.\" />\n ) : problem.statement ? (\n <p className=\"whitespace-pre-wrap text-sm leading-relaxed text-text-secondary\">\n {problem.statement}\n </p>\n ) : (\n <p className=\"py-4 text-center text-sm text-text-muted\">\n The statement for this problem is being prepared.\n </p>\n )}\n </GlassCard>\n\n {problem.isLocked ? (\n <UpgradeGate\n compact\n description=\"Starter code and sample test cases unlock with a paid TechnoSpam plan.\"\n />\n ) : problem.starterCode ? (\n <GlassCard className=\"p-5\">\n <h2 className=\"mb-3 text-base font-semibold text-text-primary\">Starter code</h2>\n <CodePanel label={humanizeEnum(languages[0] ?? 'code')} bodyClassName=\"max-h-72\">\n {problem.starterCode}\n </CodePanel>\n </GlassCard>\n ) : null}\n\n <GlassCard className=\"p-5\">\n <div className=\"mb-3 flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between\">\n <h2 className=\"text-base font-semibold text-text-primary\">Submit a solution</h2>\n <div className=\"flex items-center gap-2\">\n <span className=\"text-sm text-text-secondary\">Language</span>\n <Select value={language} onValueChange={setLanguage}>\n <SelectTrigger className=\"w-full sm:w-48\" aria-label=\"Language\">\n <SelectValue placeholder=\"Choose a language\" />\n </SelectTrigger>\n <SelectContent>\n {languages.map((l) => (\n <SelectItem key={l} value={l}>\n {humanizeEnum(l)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n </div>\n\n <div className=\"overflow-hidden rounded-xl border border-border-strong bg-bg-sunken shadow-sm\">\n <div className=\"flex items-center justify-between gap-2 border-b border-border-seam bg-bg-canvas/40 px-4 py-2\">\n <div className=\"flex items-center gap-1.5\">\n <span className=\"h-2.5 w-2.5 rounded-full bg-status-error-border\" />\n <span className=\"h-2.5 w-2.5 rounded-full bg-status-warning-border\" />\n <span className=\"h-2.5 w-2.5 rounded-full bg-status-success-border\" />\n </div>\n <span className=\"inline-flex items-center gap-1.5 font-mono text-xs text-text-secondary\">\n <Code2 size={13} /> {language ? humanizeEnum(language) : 'solution'}\n </span>\n </div>\n <Textarea\n value={code}\n onChange={(e) => setCode(e.target.value)}\n placeholder=\"Write your solution…\"\n className=\"min-h-[280px] resize-y rounded-none border-0 bg-transparent font-mono text-xs leading-relaxed focus-visible:ring-0 focus-visible:ring-offset-0\"\n spellCheck={false}\n />\n </div>\n\n <Button\n className=\"mt-4 w-full\"\n onClick={handleSubmit}\n disabled={submitting || !code.trim()}\n >\n <Send size={16} /> {submitting ? 'Running test cases…' : 'Run & submit'}\n </Button>\n <p className=\"mt-2 text-center text-xs text-text-muted\">\n Your code runs against this problem&apos;s test cases in an isolated sandbox.\n </p>\n </GlassCard>\n\n {problem.publicTestCases?.length ? (\n <GlassCard className=\"p-5\">\n <h2 className=\"mb-1 flex items-center gap-2 text-base font-semibold text-text-primary\">\n <FlaskConical size={16} /> Sample test cases\n </h2>\n <p className=\"mb-3 text-sm text-text-secondary\">\n Your solution reads each input from stdin and must print the expected output. Hidden\n test cases are also run when you submit.\n </p>\n <div className=\"space-y-3\">\n {problem.publicTestCases.map((testCase) => (\n <div key={testCase.id} className=\"rounded-xl border border-border-seam p-3\">\n <div className=\"mb-2 flex flex-wrap items-center gap-x-3 gap-y-1\">\n <span className=\"text-sm font-medium text-text-primary\">{testCase.name}</span>\n <span className=\"inline-flex items-center gap-1 text-xs text-text-muted\">\n <Clock size={12} /> {testCase.timeLimitMs} ms limit\n </span>\n </div>\n <div className=\"grid grid-cols-1 gap-2 sm:grid-cols-2\">\n <IoBlock label=\"Input\" value={testCase.input} />\n <IoBlock label=\"Expected output\" value={testCase.expectedOutput} />\n </div>\n </div>\n ))}\n </div>\n </GlassCard>\n ) : null}\n\n {pendingId ? (\n <GlassCard className=\"p-5\">\n <h2 className=\"mb-2 text-base font-semibold text-text-primary\">Latest run</h2>\n {polling ? (\n <p className=\"mb-3 inline-flex items-center gap-2 text-sm text-text-secondary\">\n <RefreshCw size={14} className=\"animate-spin\" />\n Grading your submission — the grader is starting up. Your verdict will appear here\n automatically.\n </p>\n ) : (\n <p className=\"mb-3 text-sm text-text-secondary\">\n Your most recent submission has not been graded yet — the grader was unavailable.\n You can re-run it without resubmitting your code.\n </p>\n )}\n <Button\n variant=\"outline\"\n onClick={() => void handleRegrade(pendingId)}\n disabled={regrading}\n >\n <RefreshCw size={16} /> {regrading ? 'Re-running…' : 'Re-run grader'}\n </Button>\n </GlassCard>\n ) : latestGraded ? (\n <>\n <GlassCard className=\"p-5\">\n <h2 className=\"mb-3 text-base font-semibold text-text-primary\">Latest run</h2>\n <TestResultsPanel submission={latestGraded} />\n </GlassCard>\n <GlassCard className=\"p-5\">\n <h2 className=\"mb-3 flex items-center gap-2 text-base font-semibold text-text-primary\">\n <Sparkles size={16} /> TechnoSage review\n </h2>\n <SubmissionReviewPanel\n submission={latestGraded}\n onOpenProblem={(problemId) =>\n navigate(`/applications/problem-details-page?id=${problemId}`)\n }\n />\n </GlassCard>\n </>\n ) : null}\n </div>\n\n <div className=\"lg:col-span-1\">\n <GlassCard className=\"p-5\">\n <h2 className=\"mb-3 text-base font-semibold text-text-primary\">My submissions</h2>\n {subsLoading && !submissions.length ? (\n <LoadingRows count={3} height=\"h-12\" />\n ) : subsError ? (\n <ErrorView title=\"Couldn't load submissions\" error={subsError} />\n ) : submissions.length === 0 ? (\n <EmptyView\n icon={<FileText size={24} />}\n title=\"No submissions yet\"\n description=\"Submit a solution above to see your verdicts and points here.\"\n />\n ) : (\n <div className=\"space-y-1\">\n {submissions.map((s) => (\n <SubmissionRow\n key={s.id}\n s={s}\n focused={focusedSubmissionId === s.id}\n onToggle={() =>\n setFocusedSubmissionId(focusedSubmissionId === s.id ? null : s.id)\n }\n />\n ))}\n </div>\n )}\n </GlassCard>\n </div>\n </div>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"ApplicationsProblemDetailsPagePage.js","names":[],"sources":["../../../src/technospam/pages/ApplicationsProblemDetailsPagePage.tsx"],"sourcesContent":["import { Suspense, lazy, useEffect, useMemo, useRef, useState } from 'react';\nimport { useSearchParams } from 'react-router';\nimport {\n Clock,\n Code2,\n FileText,\n FlaskConical,\n BookOpen,\n Layers,\n Play,\n RefreshCw,\n RotateCcw,\n Send,\n Terminal,\n Sparkles,\n Trophy,\n} from 'lucide-react';\nimport {\n Badge,\n Button,\n GlassCard,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n Skeleton,\n Textarea,\n} from '@burdenoff/fe-libs/ui';\nimport {\n CodePanel,\n EmptyView,\n ErrorView,\n IoBlock,\n LoadingRows,\n PageLayout,\n PremiumBadge,\n StatCard,\n StatusBadge,\n SubmissionReviewPanel,\n TagStrip,\n TestResultsPanel,\n TechnoSpamErrorBoundary,\n UpgradeGate,\n} from '../components';\nimport { useTechnoSpam, useTechnoSpamNavigate } from '../providers/TechnoSpamProvider';\nimport {\n useProblemQuery,\n useRegradeSubmission,\n useSubmissionsQuery,\n useSubmitSolution,\n type TecSubmission,\n} from '../api/technospamApi';\nimport { formatDateTime, humanizeEnum } from '../utils/format';\nimport { notify } from '../lib/toast';\nimport { useTechnoSpamAnalytics } from '../hooks/useTechnoSpamAnalytics';\nimport { useSolutionRunner } from '../hooks/useSolutionRunner';\nimport { RunOutputPanel } from '../components/editor/RunOutputPanel';\nimport {\n FOCUSED_CARD_CLASS,\n focusableCardProps,\n useFocusedRecordParam,\n} from '../hooks/useFocusedRecordParam';\nimport { FOCUS_PARAMS } from '../utils/pageContext';\nimport { cn } from '../utils/cn';\n\nconst FALLBACK_LANGUAGES = ['javascript', 'python', 'typescript'];\n\n/**\n * The CodeMirror editor is the heaviest part of this page, so it loads as its\n * own chunk; the textarea-sized skeleton holds its place meanwhile.\n */\nconst CodeEditor = lazy(() => import('../components/editor/CodeEditor'));\n\n/** Which half of the page is visible below the `lg` breakpoint (mock 22). */\ntype MobilePane = 'description' | 'solution';\n\n/**\n * A submission made while the grading sandbox is cold comes back PENDING and is\n * graded in the background (BOFF-4414). Poll the submissions list until the\n * verdict lands, giving up after a few minutes so a genuinely failed grade\n * falls back to the manual re-run button.\n */\nconst PENDING_POLL_INTERVAL_MS = 3_000;\nconst PENDING_POLL_MAX_MS = 3 * 60_000;\n\nfunction SubmissionRow({\n s,\n focused,\n onToggle,\n}: {\n s: TecSubmission;\n /** The focused submission (`?submissionId=`) is the one the assistant acts on. */\n focused: boolean;\n onToggle: () => void;\n}) {\n return (\n <div\n className={cn(\n 'cursor-pointer rounded-lg border border-transparent px-2 py-3 transition-colors hover:border-border-seam hover:bg-bg-sunken',\n focused && FOCUSED_CARD_CLASS\n )}\n {...focusableCardProps(focused, onToggle)}\n >\n <div className=\"flex flex-wrap items-center gap-x-4 gap-y-1\">\n <button\n type=\"button\"\n aria-pressed={focused}\n aria-label={`Focus submission from ${formatDateTime(s.createdAt)}`}\n onClick={onToggle}\n className=\"rounded-full\"\n >\n <StatusBadge status={s.verdict} />\n </button>\n <span className=\"inline-flex items-center gap-1 text-sm font-medium text-text-primary\">\n <Code2 size={13} /> {humanizeEnum(s.language)}\n </span>\n <span className=\"inline-flex items-center gap-1 text-xs text-text-muted\">\n <Clock size={12} /> {s.runtimeMs} ms\n </span>\n <span className=\"inline-flex items-center gap-1 text-xs text-text-muted\">\n <Trophy size={12} /> {s.pointsAwarded} pts\n </span>\n <span className=\"ml-auto text-xs text-text-muted\">{formatDateTime(s.createdAt)}</span>\n </div>\n {s.totalCount > 0 ? (\n <p className=\"mt-1 px-0.5 text-xs text-text-muted\">\n Passed {s.passedCount} of {s.totalCount} test cases\n </p>\n ) : null}\n </div>\n );\n}\n\nexport function ApplicationsProblemDetailsPagePage() {\n const [params] = useSearchParams();\n const id = params.get('id') ?? '';\n // The focused submission lives in `?submissionId=` so the assistant's page\n // context names it (\"explain this submission\").\n const [focusedSubmissionId, setFocusedSubmissionId] = useFocusedRecordParam(\n FOCUS_PARAMS.submission\n );\n const { currentUser, workspaceId } = useTechnoSpam();\n const navigate = useTechnoSpamNavigate();\n const learnerId = currentUser?.id;\n const { emit } = useTechnoSpamAnalytics();\n\n const { data, loading, error, refetch } = useProblemQuery(id);\n\n useEffect(() => {\n if (id) {\n emit('technospam.problem.viewed', {\n workspaceId,\n entityId: id,\n entityType: 'TEC_PROBLEM',\n });\n }\n }, [id, workspaceId, emit]);\n const {\n data: subsData,\n loading: subsLoading,\n error: subsError,\n refetch: refetchSubs,\n } = useSubmissionsQuery({ ...(learnerId ? { learnerId } : {}), problemId: id });\n const [submit, { loading: submitting }] = useSubmitSolution();\n const [regrade, { loading: regrading }] = useRegradeSubmission();\n\n const problem = data?.tecProblem ?? null;\n\n const languages = useMemo(\n () => (problem?.languages?.length ? problem.languages : FALLBACK_LANGUAGES),\n [problem]\n );\n\n const [language, setLanguage] = useState('');\n const [code, setCode] = useState('');\n const [useCustomInput, setUseCustomInput] = useState(false);\n const [customInput, setCustomInput] = useState('');\n const [mobilePane, setMobilePane] = useState<MobilePane>('description');\n const runner = useSolutionRunner();\n // The id of the problem the editor state was initialised for. Navigating to\n // another problem (?id= changes without unmounting) must re-seed the language,\n // starter code and custom input, and drop the previous problem's run output.\n const initedForRef = useRef<string | null>(null);\n const resetRunner = runner.reset;\n\n useEffect(() => {\n if (problem && initedForRef.current !== problem.id) {\n setLanguage(problem.languages[0] ?? FALLBACK_LANGUAGES[0]!);\n setCode(problem.starterCode ?? '');\n setCustomInput(problem.publicTestCases?.[0]?.input ?? '');\n setUseCustomInput(false);\n resetRunner();\n initedForRef.current = problem.id;\n }\n }, [problem, resetRunner]);\n\n const handleLanguageChange = (next: string) => {\n setLanguage(next);\n // Run output belongs to the language it was produced with.\n runner.reset();\n };\n\n const submissions = useMemo(\n () =>\n [...(subsData?.tecListSubmissions?.items ?? [])].sort(\n (a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()\n ),\n [subsData]\n );\n\n const handleRun = () => {\n if (!id || runner.running || runner.warming || problem?.isLocked) return;\n if (!language) {\n notify.error('Pick a language', 'Choose a language before running your code.');\n return;\n }\n if (!code.trim()) {\n notify.error('Add your solution', 'Write some code before running it.');\n return;\n }\n emit('technospam.problem.run_clicked', {\n workspaceId,\n entityId: id,\n entityType: 'TEC_PROBLEM',\n language,\n customInput: useCustomInput,\n });\n runner.execute({\n problemId: id,\n language,\n code,\n stdin: useCustomInput ? customInput : null,\n });\n };\n\n const handleResetCode = () => {\n setCode(problem?.starterCode ?? '');\n runner.reset();\n };\n\n const handleSubmit = async () => {\n if (!id || submitting || problem?.isLocked) return;\n if (!language) {\n notify.error('Pick a language', 'Choose a language before submitting.');\n return;\n }\n if (!code.trim()) {\n notify.error('Add your solution', 'Write some code before submitting.');\n return;\n }\n emit('technospam.problem.submit_clicked', {\n workspaceId,\n entityId: id,\n entityType: 'TEC_PROBLEM',\n language,\n });\n const res = await submit({ variables: { input: { problemId: id, language, code } } });\n if (res.data?.tecSubmitSolution) {\n emit('technospam.problem.submitted', {\n workspaceId,\n entityId: id,\n entityType: 'TEC_PROBLEM',\n submissionId: res.data.tecSubmitSolution.id,\n });\n const graded = res.data.tecSubmitSolution;\n if (graded.verdict === 'PENDING') {\n notify.info(\n 'Solution submitted',\n 'Grading has started — your verdict will appear here in a moment.'\n );\n } else if (graded.verdict === 'ACCEPTED') {\n notify.success('Accepted', `Passed all ${graded.totalCount} test cases.`);\n } else {\n notify.error(\n humanizeEnum(graded.verdict),\n `Passed ${graded.passedCount} of ${graded.totalCount} test cases.`\n );\n }\n await Promise.all([refetch(), refetchSubs()]);\n }\n };\n\n const handleRegrade = async (submissionId: string) => {\n const res = await regrade({ variables: { id: submissionId } });\n const graded = res.data?.tecRegradeSubmission;\n if (!graded) return;\n if (graded.verdict === 'PENDING') {\n notify.error('Still pending', 'The grader is not available yet. Please try again shortly.');\n } else {\n notify.success('Grading complete', `Verdict: ${humanizeEnum(graded.verdict)}.`);\n }\n await Promise.all([refetch(), refetchSubs()]);\n };\n\n /** Most recent submission that actually carries grading detail. */\n const latestGraded = submissions.find((s) => (s.testResults?.length ?? 0) > 0) ?? null;\n const latestSubmission = submissions[0] ?? null;\n const pendingId = latestSubmission?.verdict === 'PENDING' ? latestSubmission.id : null;\n\n // Poll while the newest submission is still being graded in the background.\n const [pollExpiredFor, setPollExpiredFor] = useState<string | null>(null);\n const polling = pendingId !== null && pollExpiredFor !== pendingId;\n useEffect(() => {\n if (!pendingId || pollExpiredFor === pendingId) return undefined;\n const startedAt = Date.now();\n const timer = window.setInterval(() => {\n if (Date.now() - startedAt > PENDING_POLL_MAX_MS) {\n window.clearInterval(timer);\n setPollExpiredFor(pendingId);\n return;\n }\n void refetchSubs();\n }, PENDING_POLL_INTERVAL_MS);\n return () => window.clearInterval(timer);\n }, [pendingId, pollExpiredFor, refetchSubs]);\n\n // Announce the verdict once a background-graded submission settles.\n const awaitedIdRef = useRef<string | null>(null);\n useEffect(() => {\n if (pendingId) {\n awaitedIdRef.current = pendingId;\n return;\n }\n const awaitedId = awaitedIdRef.current;\n if (!awaitedId) return;\n const settled = submissions.find((s) => s.id === awaitedId);\n if (!settled || settled.verdict === 'PENDING') return;\n awaitedIdRef.current = null;\n if (settled.verdict === 'ACCEPTED') {\n notify.success('Accepted', `Passed all ${settled.totalCount} test cases.`);\n } else {\n notify.error(\n humanizeEnum(settled.verdict),\n `Passed ${settled.passedCount} of ${settled.totalCount} test cases.`\n );\n }\n void refetch();\n }, [pendingId, submissions, refetch]);\n\n if (loading && !problem) {\n return (\n <PageLayout title=\"Problem\" backPath=\"/applications/problems-page\">\n <Skeleton className=\"mb-4 h-28 w-full rounded-xl\" />\n <Skeleton className=\"h-72 w-full rounded-xl\" />\n </PageLayout>\n );\n }\n\n if (error || !problem) {\n return (\n <PageLayout title=\"Problem\" backPath=\"/applications/problems-page\">\n {error ? (\n <ErrorView title=\"Couldn't load problem\" error={error} />\n ) : (\n <EmptyView\n title=\"Problem not found\"\n description=\"This problem may have been unpublished.\"\n />\n )}\n </PageLayout>\n );\n }\n\n return (\n <PageLayout\n hero\n backPath=\"/applications/problems-page\"\n title={problem.title}\n description={problem.topic ?? undefined}\n >\n <div className=\"mb-5 flex flex-wrap items-center gap-2\">\n <StatusBadge status={problem.difficulty} kind=\"level\" />\n <StatusBadge status={problem.status} />\n {problem.topic ? (\n <Badge variant=\"outline\" className=\"gap-1\">\n <Layers size={12} /> {problem.topic}\n </Badge>\n ) : null}\n {problem.isPremiumOnly ? <PremiumBadge locked={problem.isLocked} /> : null}\n <TagStrip tags={problem.tags} />\n </div>\n\n <div className=\"mb-6 grid grid-cols-2 gap-3 sm:grid-cols-4\">\n <StatCard label=\"Points\" value={problem.points} icon={Trophy} tone=\"amber\" />\n <StatCard label=\"Languages\" value={languages.length} icon={Code2} tone=\"blue\" />\n <StatCard\n label=\"Difficulty\"\n value={humanizeEnum(problem.difficulty)}\n icon={Layers}\n tone=\"purple\"\n />\n <StatCard label=\"My submissions\" value={submissions.length} icon={FileText} tone=\"teal\" />\n </div>\n\n {/* Below lg the page is two tabs (mock 22); at lg both panes sit side by side. */}\n <div\n role=\"tablist\"\n aria-label=\"Problem sections\"\n className=\"mb-4 grid grid-cols-2 gap-1 rounded-xl border border-border-seam bg-bg-sunken p-1 lg:hidden\"\n >\n {(\n [\n { pane: 'description', label: 'Description', icon: BookOpen },\n { pane: 'solution', label: 'Solution', icon: Code2 },\n ] as const\n ).map(({ pane, label, icon: Icon }) => (\n <button\n key={pane}\n type=\"button\"\n role=\"tab\"\n id={`problem-tab-${pane}`}\n aria-selected={mobilePane === pane}\n aria-controls={`problem-pane-${pane}`}\n onClick={() => setMobilePane(pane)}\n className={cn(\n 'inline-flex items-center justify-center gap-1.5 rounded-lg px-3 py-2 text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus',\n mobilePane === pane\n ? 'bg-bg-surface text-text-primary shadow-sm'\n : 'text-text-secondary hover:text-text-primary'\n )}\n >\n <Icon size={14} /> {label}\n </button>\n ))}\n </div>\n\n <div className=\"grid grid-cols-1 gap-5 lg:grid-cols-2\">\n <div\n id=\"problem-pane-description\"\n role=\"tabpanel\"\n aria-labelledby=\"problem-tab-description\"\n className={cn('min-w-0 space-y-5', mobilePane !== 'description' && 'hidden lg:block')}\n >\n <GlassCard className=\"p-5\">\n <h2 className=\"mb-2 text-base font-semibold text-text-primary\">Problem statement</h2>\n {problem.isLocked ? (\n // BOFF-4416: the API already nulled `statement` for a locked\n // premium problem — this explains why, rather than showing the\n // generic \"being prepared\" message used for a real content gap.\n <UpgradeGate description=\"This problem's statement is part of a paid TechnoSpam plan. Ask a workspace admin to upgrade to unlock it.\" />\n ) : problem.statement ? (\n <p className=\"whitespace-pre-wrap text-sm leading-relaxed text-text-secondary\">\n {problem.statement}\n </p>\n ) : (\n <p className=\"py-4 text-center text-sm text-text-muted\">\n The statement for this problem is being prepared.\n </p>\n )}\n </GlassCard>\n\n {problem.isLocked ? (\n <UpgradeGate\n compact\n description=\"Starter code and sample test cases unlock with a paid TechnoSpam plan.\"\n />\n ) : null}\n\n {problem.publicTestCases?.length ? (\n <GlassCard className=\"p-5\">\n <h2 className=\"mb-1 flex items-center gap-2 text-base font-semibold text-text-primary\">\n <FlaskConical size={16} /> Sample test cases\n </h2>\n <p className=\"mb-3 text-sm text-text-secondary\">\n Your solution reads each input from stdin and must print the expected output.\n <strong className=\"font-medium text-text-primary\"> Run</strong> checks these\n samples; <strong className=\"font-medium text-text-primary\">Submit</strong> also runs\n the hidden test cases.\n </p>\n <div className=\"space-y-3\">\n {problem.publicTestCases.map((testCase) => (\n <div key={testCase.id} className=\"rounded-xl border border-border-seam p-3\">\n <div className=\"mb-2 flex flex-wrap items-center gap-x-3 gap-y-1\">\n <span className=\"text-sm font-medium text-text-primary\">{testCase.name}</span>\n <span className=\"inline-flex items-center gap-1 text-xs text-text-muted\">\n <Clock size={12} /> {testCase.timeLimitMs} ms limit\n </span>\n </div>\n <div className=\"grid grid-cols-1 gap-2 sm:grid-cols-2\">\n <IoBlock label=\"Input\" value={testCase.input} />\n <IoBlock label=\"Expected output\" value={testCase.expectedOutput} />\n </div>\n </div>\n ))}\n </div>\n </GlassCard>\n ) : null}\n\n {!problem.isLocked && problem.starterCode ? (\n <GlassCard className=\"p-5\">\n <h2 className=\"mb-3 text-base font-semibold text-text-primary\">Starter code</h2>\n <CodePanel label={humanizeEnum(languages[0] ?? 'code')} bodyClassName=\"max-h-72\">\n {problem.starterCode}\n </CodePanel>\n </GlassCard>\n ) : null}\n </div>\n\n <div\n id=\"problem-pane-solution\"\n role=\"tabpanel\"\n aria-labelledby=\"problem-tab-solution\"\n className={cn('min-w-0 space-y-5', mobilePane !== 'solution' && 'hidden lg:block')}\n >\n <GlassCard className=\"p-5\">\n <div className=\"mb-3 flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between\">\n <h2 className=\"inline-flex items-center gap-2 text-base font-semibold text-text-primary\">\n <Code2 size={16} /> Solve\n </h2>\n <div className=\"flex items-center gap-2\">\n <span className=\"text-sm text-text-secondary\">Language</span>\n <Select value={language} onValueChange={handleLanguageChange}>\n <SelectTrigger className=\"w-full sm:w-44\" aria-label=\"Language\">\n <SelectValue placeholder=\"Choose a language\" />\n </SelectTrigger>\n <SelectContent>\n {languages.map((l) => (\n <SelectItem key={l} value={l}>\n {humanizeEnum(l)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n onClick={handleResetCode}\n aria-label=\"Reset to starter code\"\n title=\"Reset to starter code\"\n >\n <RotateCcw size={16} />\n </Button>\n </div>\n </div>\n\n <div className=\"overflow-hidden rounded-xl border border-border-strong bg-bg-sunken shadow-sm focus-within:ring-2 focus-within:ring-border-focus\">\n <div className=\"flex items-center justify-between gap-2 border-b border-border-seam bg-bg-canvas/40 px-4 py-2\">\n <div className=\"flex items-center gap-1.5\" aria-hidden=\"true\">\n <span className=\"h-2.5 w-2.5 rounded-full bg-status-error-border\" />\n <span className=\"h-2.5 w-2.5 rounded-full bg-status-warning-border\" />\n <span className=\"h-2.5 w-2.5 rounded-full bg-status-success-border\" />\n </div>\n <span className=\"inline-flex items-center gap-1.5 font-mono text-xs text-text-secondary\">\n <Code2 size={13} /> {language ? humanizeEnum(language) : 'solution'}\n </span>\n </div>\n <TechnoSpamErrorBoundary\n fallback={\n // The editor chunk failed to load (flaky network, or a deploy\n // replaced it). A plain textarea keeps the learner working.\n <Textarea\n value={code}\n onChange={(e) => setCode(e.target.value)}\n aria-label={`Solution code${language ? ` (${humanizeEnum(language)})` : ''}`}\n placeholder=\"Write your solution…\"\n spellCheck={false}\n className=\"h-[360px] resize-none rounded-none border-0 font-mono text-xs lg:h-[440px]\"\n />\n }\n >\n <Suspense\n fallback={<Skeleton className=\"h-[360px] w-full rounded-none lg:h-[440px]\" />}\n >\n <CodeEditor\n value={code}\n onChange={setCode}\n language={language}\n ariaLabel={`Solution code${language ? ` (${humanizeEnum(language)})` : ''}`}\n placeholder=\"Write your solution…\"\n onRun={handleRun}\n onSubmit={() => void handleSubmit()}\n className=\"h-[360px] text-xs lg:h-[440px]\"\n />\n </Suspense>\n </TechnoSpamErrorBoundary>\n </div>\n\n <div className=\"mt-3\">\n <label className=\"inline-flex cursor-pointer items-center gap-2 text-sm text-text-secondary\">\n <input\n type=\"checkbox\"\n checked={useCustomInput}\n onChange={(e) => setUseCustomInput(e.target.checked)}\n className=\"h-4 w-4 rounded border-border-strong accent-current\"\n />\n <Terminal size={14} /> Run with custom input\n </label>\n {useCustomInput ? (\n <Textarea\n value={customInput}\n onChange={(e) => setCustomInput(e.target.value)}\n aria-label=\"Custom input (stdin)\"\n placeholder=\"Input passed to your program on stdin\"\n className=\"mt-2 min-h-[88px] font-mono text-xs\"\n spellCheck={false}\n />\n ) : null}\n </div>\n\n <div className=\"mt-4 grid grid-cols-2 gap-2\">\n <Button\n variant=\"outline\"\n onClick={handleRun}\n disabled={\n runner.running || runner.warming || !code.trim() || Boolean(problem.isLocked)\n }\n >\n <Play size={16} />{' '}\n {runner.warming ? 'Starting…' : runner.running ? 'Running…' : 'Run'}\n </Button>\n <Button\n onClick={() => void handleSubmit()}\n disabled={submitting || !code.trim() || Boolean(problem.isLocked)}\n >\n <Send size={16} /> {submitting ? 'Submitting…' : 'Submit'}\n </Button>\n </div>\n <p className=\"mt-2 text-center text-xs text-text-muted\">\n Code runs in an isolated sandbox. Ctrl/⌘+Enter runs, Ctrl/⌘+Shift+Enter submits; press\n Esc then Tab to leave the editor.\n </p>\n </GlassCard>\n\n <GlassCard className=\"p-5\" aria-live=\"polite\">\n <h2 className=\"mb-3 flex items-center gap-2 text-base font-semibold text-text-primary\">\n <Terminal size={16} /> Run output\n </h2>\n <RunOutputPanel\n run={runner.run}\n running={runner.running}\n warming={runner.warming}\n error={runner.error}\n />\n </GlassCard>\n\n {pendingId ? (\n <GlassCard className=\"p-5\">\n <h2 className=\"mb-2 text-base font-semibold text-text-primary\">Latest submission</h2>\n {polling ? (\n <p className=\"mb-3 inline-flex items-center gap-2 text-sm text-text-secondary\">\n <RefreshCw size={14} className=\"animate-spin\" />\n Grading your submission — the grader is starting up. Your verdict will appear here\n automatically.\n </p>\n ) : (\n <p className=\"mb-3 text-sm text-text-secondary\">\n Your most recent submission has not been graded yet — the grader was unavailable.\n You can re-run it without resubmitting your code.\n </p>\n )}\n <Button\n variant=\"outline\"\n onClick={() => void handleRegrade(pendingId)}\n disabled={regrading}\n >\n <RefreshCw size={16} /> {regrading ? 'Re-running…' : 'Re-run grader'}\n </Button>\n </GlassCard>\n ) : latestGraded ? (\n <>\n <GlassCard className=\"p-5\">\n <h2 className=\"mb-3 text-base font-semibold text-text-primary\">\n Latest submission\n </h2>\n <TestResultsPanel submission={latestGraded} />\n </GlassCard>\n <GlassCard className=\"p-5\">\n <h2 className=\"mb-3 flex items-center gap-2 text-base font-semibold text-text-primary\">\n <Sparkles size={16} /> TechnoSage review\n </h2>\n <SubmissionReviewPanel\n submission={latestGraded}\n onOpenProblem={(problemId) =>\n navigate(`/applications/problem-details-page?id=${problemId}`)\n }\n />\n </GlassCard>\n </>\n ) : null}\n\n <GlassCard className=\"p-5\">\n <h2 className=\"mb-3 text-base font-semibold text-text-primary\">My submissions</h2>\n {subsLoading && !submissions.length ? (\n <LoadingRows count={3} height=\"h-12\" />\n ) : subsError ? (\n <ErrorView title=\"Couldn't load submissions\" error={subsError} />\n ) : submissions.length === 0 ? (\n <EmptyView\n icon={<FileText size={24} />}\n title=\"No submissions yet\"\n description=\"Submit a solution to see your verdicts and points here.\"\n />\n ) : (\n <div className=\"space-y-1\">\n {submissions.map((s) => (\n <SubmissionRow\n key={s.id}\n s={s}\n focused={focusedSubmissionId === s.id}\n onToggle={() =>\n setFocusedSubmissionId(focusedSubmissionId === s.id ? null : s.id)\n }\n />\n ))}\n </div>\n )}\n </GlassCard>\n </div>\n </div>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"ApplicationsProblemsPagePage.d.ts","sourceRoot":"","sources":["../../../src/technospam/pages/ApplicationsProblemsPagePage.tsx"],"names":[],"mappings":"AAyJA,wBAAgB,4BAA4B,gCAuT3C"}
1
+ {"version":3,"file":"ApplicationsProblemsPagePage.d.ts","sourceRoot":"","sources":["../../../src/technospam/pages/ApplicationsProblemsPagePage.tsx"],"names":[],"mappings":"AA0JA,wBAAgB,4BAA4B,gCA8T3C"}
@@ -1,26 +1,27 @@
1
1
  import { useTechnoSpam as e, useTechnoSpamNavigate as t } from "../providers/TechnoSpamProvider.js";
2
2
  import { useTechnoSpamAnalytics as n } from "../hooks/useTechnoSpamAnalytics.js";
3
- import { useTr as r } from "../hooks/useTr.js";
4
- import { PageLayout as i } from "../components/PageLayout.js";
3
+ import { usePhoneLayout as r } from "../hooks/usePhoneLayout.js";
4
+ import { useTr as i } from "../hooks/useTr.js";
5
+ import { PageLayout as ee } from "../components/PageLayout.js";
5
6
  import { StatCard as a } from "../components/StatCard.js";
6
7
  import { MediaCover as o, topicIcon as s } from "../components/MediaCover.js";
7
8
  import { StatusBadge as c } from "../components/StatusBadge.js";
8
- import { readProblemCatalogView as l, safeLocalStorage as u, writeProblemCatalogView as d } from "../utils/problemCatalog.js";
9
- import { PremiumBadge as f } from "../components/UpgradeGate.js";
10
- import { ProblemsTable as ee } from "../components/ProblemsTable.js";
11
- import { LoadMore as te } from "../components/LoadMore.js";
12
- import { EmptyView as ne, ErrorView as re, LoadingGrid as p } from "../components/StateViews.js";
13
- import { pageArg as ie, usePageLimit as ae, useProblemsQuery as oe, useSolvedProblemIds as se } from "../api/technospamApi.js";
14
- import { CardOpenButton as m } from "../components/CardOpenButton.js";
9
+ import { readProblemCatalogView as l, safeLocalStorage as u, writeProblemCatalogView as te } from "../utils/problemCatalog.js";
10
+ import { PremiumBadge as d } from "../components/UpgradeGate.js";
11
+ import { ProblemsTable as ne } from "../components/ProblemsTable.js";
12
+ import { LoadMore as re } from "../components/LoadMore.js";
13
+ import { EmptyView as f, ErrorView as ie, LoadingGrid as ae } from "../components/StateViews.js";
14
+ import { pageArg as oe, usePageLimit as se, useProblemsQuery as p, useSolvedProblemIds as m } from "../api/technospamApi.js";
15
+ import { CardOpenButton as h } from "../components/CardOpenButton.js";
15
16
  import "../components/index.js";
16
17
  import { TAB_PANEL_FOCUS_CLASS as ce } from "../lib/a11y.js";
17
- import { useCallback as h, useMemo as g, useState as _ } from "react";
18
- import { Building2 as v, CheckCircle2 as y, Code2 as b, Flame as x, Gauge as S, Layers as C, LayoutGrid as le, List as ue, Search as w, Tag as T, Trophy as E } from "lucide-react";
18
+ import { useCallback as g, useMemo as _, useState as v } from "react";
19
+ import { Building2 as y, CheckCircle2 as b, Code2 as x, Flame as S, Gauge as C, Layers as w, LayoutGrid as le, List as ue, Search as de, Tag as T, Trophy as E } from "lucide-react";
19
20
  import { jsx as D, jsxs as O } from "react/jsx-runtime";
20
- import { Badge as k, Button as A, GlassCard as j, Input as de, Select as M, SelectContent as N, SelectItem as P, SelectTrigger as F, SelectValue as I, Tabs as L, TabsContent as R, TabsList as z, TabsTrigger as B } from "@burdenoff/fe-libs/ui";
21
+ import { Badge as k, Button as A, GlassCard as j, Input as fe, Select as M, SelectContent as N, SelectItem as P, SelectTrigger as F, SelectValue as I, Tabs as L, TabsContent as R, TabsList as z, TabsTrigger as B } from "@burdenoff/fe-libs/ui";
21
22
  //#region src/technospam/pages/ApplicationsProblemsPagePage.tsx
22
23
  function V({ problem: e, solved: t, onOpen: n }) {
23
- let i = r();
24
+ let r = i();
24
25
  return /* @__PURE__ */ O(j, {
25
26
  className: "group flex cursor-pointer flex-col overflow-hidden transition-all duration-200 hover:-translate-y-1 hover:shadow-lg",
26
27
  children: [/* @__PURE__ */ O(o, {
@@ -29,16 +30,16 @@ function V({ problem: e, solved: t, onOpen: n }) {
29
30
  children: [t ? /* @__PURE__ */ O("span", {
30
31
  className: "inline-flex items-center gap-1 rounded-full bg-status-success-bg-subtle px-2 py-0.5 text-[11px] font-medium text-status-success-text ring-1 ring-status-success-border/30",
31
32
  children: [
32
- /* @__PURE__ */ D(y, { size: 12 }),
33
+ /* @__PURE__ */ D(b, { size: 12 }),
33
34
  " ",
34
- i("technospam.problems.solved", "Solved")
35
+ r("technospam.problems.solved", "Solved")
35
36
  ]
36
37
  }) : /* @__PURE__ */ D("span", {}), /* @__PURE__ */ O("div", {
37
38
  className: "flex flex-wrap items-center gap-1.5",
38
39
  children: [/* @__PURE__ */ D(c, {
39
40
  status: e.difficulty,
40
41
  kind: "level"
41
- }), e.isPremiumOnly ? /* @__PURE__ */ D(f, { locked: e.isLocked }) : null]
42
+ }), e.isPremiumOnly ? /* @__PURE__ */ D(d, { locked: e.isLocked }) : null]
42
43
  })]
43
44
  }), /* @__PURE__ */ O("div", {
44
45
  className: "flex flex-1 flex-col gap-3 p-4",
@@ -47,7 +48,7 @@ function V({ problem: e, solved: t, onOpen: n }) {
47
48
  className: "min-w-0",
48
49
  children: [/* @__PURE__ */ D("h3", {
49
50
  className: "truncate text-base font-semibold text-text-primary group-hover:text-accent-primary",
50
- children: /* @__PURE__ */ D(m, {
51
+ children: /* @__PURE__ */ D(h, {
51
52
  onOpen: n,
52
53
  children: e.title
53
54
  })
@@ -62,7 +63,7 @@ function V({ problem: e, solved: t, onOpen: n }) {
62
63
  e.topic ? /* @__PURE__ */ O("span", {
63
64
  className: "inline-flex items-center gap-1",
64
65
  children: [
65
- /* @__PURE__ */ D(C, { size: 13 }),
66
+ /* @__PURE__ */ D(w, { size: 13 }),
66
67
  " ",
67
68
  e.topic
68
69
  ]
@@ -72,15 +73,15 @@ function V({ problem: e, solved: t, onOpen: n }) {
72
73
  children: [
73
74
  /* @__PURE__ */ D(E, { size: 13 }),
74
75
  " ",
75
- i("technospam.problems.points", "{{count}} pts", { count: e.points })
76
+ r("technospam.problems.points", "{{count}} pts", { count: e.points })
76
77
  ]
77
78
  }),
78
79
  e.languages.length ? /* @__PURE__ */ O("span", {
79
80
  className: "inline-flex items-center gap-1",
80
81
  children: [
81
- /* @__PURE__ */ D(b, { size: 13 }),
82
+ /* @__PURE__ */ D(x, { size: 13 }),
82
83
  " ",
83
- e.languages.length === 1 ? i("technospam.problems.languages", "{{count}} lang", { count: e.languages.length }) : i("technospam.problems.languagesPlural", "{{count}} langs", { count: e.languages.length })
84
+ e.languages.length === 1 ? r("technospam.problems.languages", "{{count}} lang", { count: e.languages.length }) : r("technospam.problems.languagesPlural", "{{count}} langs", { count: e.languages.length })
84
85
  ]
85
86
  }) : null
86
87
  ]
@@ -90,17 +91,17 @@ function V({ problem: e, solved: t, onOpen: n }) {
90
91
  children: [e.companies.slice(0, 3).map((e) => /* @__PURE__ */ O(k, {
91
92
  variant: "outline",
92
93
  className: "text-[11px] capitalize",
93
- children: [/* @__PURE__ */ D(v, {
94
+ children: [/* @__PURE__ */ D(y, {
94
95
  size: 10,
95
96
  className: "mr-1"
96
97
  }), e.replace(/-/g, " ")]
97
98
  }, e)), e.interviewFrequency === "HIGH" ? /* @__PURE__ */ O(k, {
98
99
  variant: "secondary",
99
100
  className: "text-[11px] text-status-warning-text",
100
- children: [/* @__PURE__ */ D(x, {
101
+ children: [/* @__PURE__ */ D(S, {
101
102
  size: 10,
102
103
  className: "mr-1"
103
- }), i("technospam.problems.frequentlyAsked", "Frequently asked")]
104
+ }), r("technospam.problems.frequentlyAsked", "Frequently asked")]
104
105
  }) : null]
105
106
  }) : null,
106
107
  e.tags.length ? /* @__PURE__ */ D("div", {
@@ -119,26 +120,26 @@ function V({ problem: e, solved: t, onOpen: n }) {
119
120
  });
120
121
  }
121
122
  function H() {
122
- let o = t(), { currentUser: s, workspaceId: c } = e(), { emit: f } = n(), m = r(), v = s?.id, [C, T] = _("ALL"), [E, k] = _("ALL"), [j, H] = _("ALL"), [U, fe] = _(""), [W, pe] = _(() => l(u())), G = h((e) => {
123
- pe(e), d(u(), e);
124
- }, []), me = g(() => [
123
+ let o = t(), { currentUser: s, workspaceId: c } = e(), { emit: d } = n(), h = i(), y = s?.id, [w, T] = v("ALL"), [E, k] = v("ALL"), [j, H] = v("ALL"), [U, pe] = v(""), [W, me] = v(() => l(u())), { isPhone: he } = r(), ge = he ? "cards" : W, G = g((e) => {
124
+ me(e), te(u(), e);
125
+ }, []), _e = _(() => [
125
126
  {
126
127
  value: "ALL",
127
- label: m("technospam.problems.filterAll", "All")
128
+ label: h("technospam.problems.filterAll", "All")
128
129
  },
129
130
  {
130
131
  value: "EASY",
131
- label: m("technospam.problems.filterEasy", "Easy")
132
+ label: h("technospam.problems.filterEasy", "Easy")
132
133
  },
133
134
  {
134
135
  value: "MEDIUM",
135
- label: m("technospam.problems.filterMedium", "Medium")
136
+ label: h("technospam.problems.filterMedium", "Medium")
136
137
  },
137
138
  {
138
139
  value: "HARD",
139
- label: m("technospam.problems.filterHard", "Hard")
140
+ label: h("technospam.problems.filterHard", "Hard")
140
141
  }
141
- ], [m]), he = g(() => [
142
+ ], [h]), ve = _(() => [
142
143
  {
143
144
  value: "google",
144
145
  label: "Google"
@@ -163,7 +164,7 @@ function H() {
163
164
  value: "netflix",
164
165
  label: "Netflix"
165
166
  }
166
- ], []), ge = g(() => [
167
+ ], []), ye = _(() => [
167
168
  {
168
169
  value: "frontend",
169
170
  label: "Frontend"
@@ -188,82 +189,83 @@ function H() {
188
189
  value: "sre",
189
190
  label: "SRE / Infra"
190
191
  }
191
- ], []), { limit: _e, more: ve } = ae(), { data: K, loading: q, error: J } = oe({
192
+ ], []), { limit: be, more: xe } = se(), { data: K, loading: q, error: J } = p({
192
193
  status: "PUBLISHED",
193
- pagination: ie(_e),
194
- ...C === "ALL" ? {} : { difficulty: C },
194
+ pagination: oe(be),
195
+ ...w === "ALL" ? {} : { difficulty: w },
195
196
  ...E === "ALL" ? {} : { company: E },
196
197
  ...j === "ALL" ? {} : { role: j }
197
- }), Y = se(v), X = g(() => K?.tecListProblems?.items ?? [], [K]), Z = K?.tecListProblems?.pageInfo?.hasMore ?? !1, ye = X.filter((e) => Y.has(e.id)).length, be = X.filter((e) => e.difficulty === "EASY").length, xe = X.filter((e) => e.difficulty === "HARD").length, Q = g(() => {
198
+ }), Y = m(y), X = _(() => K?.tecListProblems?.items ?? [], [K]), Z = K?.tecListProblems?.pageInfo?.hasMore ?? !1, Se = X.filter((e) => Y.has(e.id)).length, Ce = X.filter((e) => e.difficulty === "EASY").length, we = X.filter((e) => e.difficulty === "HARD").length, Q = _(() => {
198
199
  let e = U.trim().toLowerCase();
199
200
  return e ? X.filter((t) => t.title.toLowerCase().includes(e) || (t.topic ?? "").toLowerCase().includes(e) || t.tags.some((t) => t.toLowerCase().includes(e))) : X;
200
- }, [X, U]), $ = h((e) => {
201
- f("technospam.problem.viewed", {
201
+ }, [X, U]), $ = g((e) => {
202
+ d("technospam.problem.viewed", {
202
203
  workspaceId: c,
203
204
  entityId: e.id,
204
205
  entityType: "TEC_PROBLEM"
205
206
  }), o(`/applications/problem-details-page?id=${e.id}`);
206
207
  }, [
207
- f,
208
+ d,
208
209
  o,
209
210
  c
210
211
  ]);
211
- return /* @__PURE__ */ O(i, {
212
+ return /* @__PURE__ */ O(ee, {
212
213
  hero: !0,
213
- title: m("technospam.problems.title", "Coding Problems"),
214
- description: m("technospam.problems.description", "Sharpen your problem-solving with hands-on, mentor-judged challenges across topics and difficulty."),
214
+ mobileSection: !0,
215
+ title: h("technospam.problems.title", "Coding Problems"),
216
+ description: h("technospam.problems.description", "Sharpen your problem-solving with hands-on, mentor-judged challenges across topics and difficulty."),
215
217
  children: [/* @__PURE__ */ O("div", {
216
- className: "mb-5 grid grid-cols-2 gap-3 sm:grid-cols-4",
218
+ className: "mb-5 hidden grid-cols-2 gap-3 sm:grid sm:grid-cols-4",
217
219
  children: [
218
220
  /* @__PURE__ */ D(a, {
219
- label: m("technospam.problems.statProblems", "Problems"),
221
+ label: h("technospam.problems.statProblems", "Problems"),
220
222
  value: X.length,
221
- icon: b,
223
+ icon: x,
222
224
  tone: "blue"
223
225
  }),
224
226
  /* @__PURE__ */ D(a, {
225
- label: m("technospam.problems.statSolved", "Solved"),
226
- value: ye,
227
- icon: y,
227
+ label: h("technospam.problems.statSolved", "Solved"),
228
+ value: Se,
229
+ icon: b,
228
230
  tone: "green"
229
231
  }),
230
232
  /* @__PURE__ */ D(a, {
231
- label: m("technospam.problems.statEasy", "Easy"),
232
- value: be,
233
- icon: S,
233
+ label: h("technospam.problems.statEasy", "Easy"),
234
+ value: Ce,
235
+ icon: C,
234
236
  tone: "teal"
235
237
  }),
236
238
  /* @__PURE__ */ D(a, {
237
- label: m("technospam.problems.statHard", "Hard"),
238
- value: xe,
239
- icon: x,
239
+ label: h("technospam.problems.statHard", "Hard"),
240
+ value: we,
241
+ icon: S,
240
242
  tone: "amber"
241
243
  })
242
244
  ]
243
245
  }), /* @__PURE__ */ O(L, {
244
246
  className: "gap-0",
245
- value: C,
247
+ value: w,
246
248
  onValueChange: (e) => T(e),
247
249
  children: [
248
250
  /* @__PURE__ */ O("div", {
249
251
  className: "mb-4 flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between",
250
- children: [/* @__PURE__ */ D(z, { children: me.map((e) => /* @__PURE__ */ D(B, {
252
+ children: [/* @__PURE__ */ D(z, { children: _e.map((e) => /* @__PURE__ */ D(B, {
251
253
  value: e.value,
252
254
  children: e.label
253
255
  }, e.value)) }), /* @__PURE__ */ O("div", {
254
256
  className: "relative w-full sm:w-72",
255
- children: [/* @__PURE__ */ D(w, {
257
+ children: [/* @__PURE__ */ D(de, {
256
258
  className: "pointer-events-none absolute left-3 top-1/2 -translate-y-1/2 text-text-muted",
257
259
  size: 16
258
- }), /* @__PURE__ */ D(de, {
260
+ }), /* @__PURE__ */ D(fe, {
259
261
  className: "pl-9",
260
- "aria-label": m("technospam.problems.searchLabel", "Search problems"),
261
- placeholder: m("technospam.problems.searchPlaceholder", "Search problems…"),
262
+ "aria-label": h("technospam.problems.searchLabel", "Search problems"),
263
+ placeholder: h("technospam.problems.searchPlaceholder", "Search problems…"),
262
264
  value: U,
263
- onChange: (e) => fe(e.target.value),
265
+ onChange: (e) => pe(e.target.value),
264
266
  onBlur: () => {
265
267
  let e = U.trim();
266
- e && f("technospam.search.performed", {
268
+ e && d("technospam.search.performed", {
267
269
  workspaceId: c,
268
270
  entityType: "problem",
269
271
  queryLength: e.length
@@ -280,12 +282,12 @@ function H() {
280
282
  onValueChange: k,
281
283
  children: [/* @__PURE__ */ D(F, {
282
284
  className: "w-full sm:w-48",
283
- "aria-label": m("technospam.problems.companyFilterLabel", "Filter by company"),
284
- children: /* @__PURE__ */ D(I, { placeholder: m("technospam.problems.companyPlaceholder", "Company") })
285
+ "aria-label": h("technospam.problems.companyFilterLabel", "Filter by company"),
286
+ children: /* @__PURE__ */ D(I, { placeholder: h("technospam.problems.companyPlaceholder", "Company") })
285
287
  }), /* @__PURE__ */ O(N, { children: [/* @__PURE__ */ D(P, {
286
288
  value: "ALL",
287
- children: m("technospam.problems.companyAll", "All companies")
288
- }), he.map((e) => /* @__PURE__ */ D(P, {
289
+ children: h("technospam.problems.companyAll", "All companies")
290
+ }), ve.map((e) => /* @__PURE__ */ D(P, {
289
291
  value: e.value,
290
292
  children: e.label
291
293
  }, e.value))] })]
@@ -295,20 +297,20 @@ function H() {
295
297
  onValueChange: H,
296
298
  children: [/* @__PURE__ */ D(F, {
297
299
  className: "w-full sm:w-48",
298
- "aria-label": m("technospam.problems.roleFilterLabel", "Filter by role"),
299
- children: /* @__PURE__ */ D(I, { placeholder: m("technospam.problems.rolePlaceholder", "Role") })
300
+ "aria-label": h("technospam.problems.roleFilterLabel", "Filter by role"),
301
+ children: /* @__PURE__ */ D(I, { placeholder: h("technospam.problems.rolePlaceholder", "Role") })
300
302
  }), /* @__PURE__ */ O(N, { children: [/* @__PURE__ */ D(P, {
301
303
  value: "ALL",
302
- children: m("technospam.problems.roleAll", "All roles")
303
- }), ge.map((e) => /* @__PURE__ */ D(P, {
304
+ children: h("technospam.problems.roleAll", "All roles")
305
+ }), ye.map((e) => /* @__PURE__ */ D(P, {
304
306
  value: e.value,
305
307
  children: e.label
306
308
  }, e.value))] })]
307
309
  }),
308
310
  /* @__PURE__ */ O("div", {
309
311
  role: "group",
310
- "aria-label": m("technospam.problems.viewLabel", "Catalog layout"),
311
- className: "inline-flex items-center gap-1 self-start rounded-md border border-border-subtle bg-bg-surface p-1 sm:ml-auto sm:self-auto",
312
+ "aria-label": h("technospam.problems.viewLabel", "Catalog layout"),
313
+ className: "hidden items-center gap-1 self-start rounded-md border border-border-subtle bg-bg-surface p-1 sm:ml-auto sm:inline-flex sm:self-auto",
312
314
  children: [/* @__PURE__ */ O(A, {
313
315
  type: "button",
314
316
  size: "sm",
@@ -319,7 +321,7 @@ function H() {
319
321
  size: 14,
320
322
  className: "mr-1.5",
321
323
  "aria-hidden": "true"
322
- }), m("technospam.problems.viewTable", "Table")]
324
+ }), h("technospam.problems.viewTable", "Table")]
323
325
  }), /* @__PURE__ */ O(A, {
324
326
  type: "button",
325
327
  size: "sm",
@@ -330,23 +332,23 @@ function H() {
330
332
  size: 14,
331
333
  className: "mr-1.5",
332
334
  "aria-hidden": "true"
333
- }), m("technospam.problems.viewCards", "Cards")]
335
+ }), h("technospam.problems.viewCards", "Cards")]
334
336
  })]
335
337
  })
336
338
  ]
337
339
  }),
338
340
  /* @__PURE__ */ O(R, {
339
- value: C,
341
+ value: w,
340
342
  className: ce,
341
343
  children: [
342
- q && !X.length ? /* @__PURE__ */ D(p, {}) : J ? /* @__PURE__ */ D(re, {
343
- title: m("technospam.common.errorLoadProblems", "Couldn't load problems"),
344
+ q && !X.length ? /* @__PURE__ */ D(ae, {}) : J ? /* @__PURE__ */ D(ie, {
345
+ title: h("technospam.common.errorLoadProblems", "Couldn't load problems"),
344
346
  error: J
345
- }) : Q.length === 0 ? /* @__PURE__ */ D(ne, {
346
- icon: /* @__PURE__ */ D(b, { size: 26 }),
347
- title: U || C !== "ALL" || E !== "ALL" || j !== "ALL" ? m("technospam.problems.emptySearchTitle", "No matching problems") : m("technospam.problems.emptyDefaultTitle", "No problems published yet"),
348
- description: U || C !== "ALL" || E !== "ALL" || j !== "ALL" ? m("technospam.problems.emptySearchDesc", "Try a different search, difficulty, company, or role filter.") : m("technospam.problems.emptyDefaultDesc", "Published problems will appear here. Check back soon — TechnoSpam is pre-launch.")
349
- }) : W === "table" ? /* @__PURE__ */ D(ee, {
347
+ }) : Q.length === 0 ? /* @__PURE__ */ D(f, {
348
+ icon: /* @__PURE__ */ D(x, { size: 26 }),
349
+ title: U || w !== "ALL" || E !== "ALL" || j !== "ALL" ? h("technospam.problems.emptySearchTitle", "No matching problems") : h("technospam.problems.emptyDefaultTitle", "No problems published yet"),
350
+ description: U || w !== "ALL" || E !== "ALL" || j !== "ALL" ? h("technospam.problems.emptySearchDesc", "Try a different search, difficulty, company, or role filter.") : h("technospam.problems.emptyDefaultDesc", "Published problems will appear here. Check back soon — TechnoSpam is pre-launch.")
351
+ }) : ge === "table" ? /* @__PURE__ */ D(ne, {
350
352
  problems: Q,
351
353
  solvedIds: Y,
352
354
  onOpen: $
@@ -360,15 +362,15 @@ function H() {
360
362
  }),
361
363
  Q.length > 0 && !J ? /* @__PURE__ */ D("p", {
362
364
  className: "mt-4 text-sm text-text-muted",
363
- children: Q.length < X.length ? m("technospam.problems.showingFiltered", "Showing {{shown}} of {{total}} loaded problems", {
365
+ children: Q.length < X.length ? h("technospam.problems.showingFiltered", "Showing {{shown}} of {{total}} loaded problems", {
364
366
  shown: Q.length,
365
367
  total: X.length
366
- }) : Z ? m("technospam.problems.showingMore", "Showing 1 to {{count}} problems — load more to see the rest", { count: Q.length }) : m("technospam.problems.showingAll", "Showing all {{count}} problems", { count: Q.length })
368
+ }) : Z ? h("technospam.problems.showingMore", "Showing 1 to {{count}} problems — load more to see the rest", { count: Q.length }) : h("technospam.problems.showingAll", "Showing all {{count}} problems", { count: Q.length })
367
369
  }) : null,
368
- /* @__PURE__ */ D(te, {
370
+ /* @__PURE__ */ D(re, {
369
371
  hasMore: Z,
370
372
  loading: q,
371
- onClick: ve
373
+ onClick: xe
372
374
  })
373
375
  ]
374
376
  })