claude-code-workflow 7.2.19 → 7.2.21
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.
- package/.claude/commands/workflow/analyze-with-file.md +58 -20
- package/.codex/skills/analyze-with-file/SKILL.md +55 -8
- package/.codex/skills/team-arch-opt/SKILL.md +24 -0
- package/.codex/skills/team-arch-opt/roles/coordinator/role.md +22 -0
- package/.codex/skills/team-brainstorm/SKILL.md +24 -0
- package/.codex/skills/team-brainstorm/roles/coordinator/role.md +20 -0
- package/.codex/skills/team-coordinate/SKILL.md +24 -0
- package/.codex/skills/team-coordinate/roles/coordinator/role.md +40 -12
- package/.codex/skills/team-frontend/SKILL.md +24 -0
- package/.codex/skills/team-frontend/roles/coordinator/role.md +20 -0
- package/.codex/skills/team-frontend-debug/SKILL.md +24 -0
- package/.codex/skills/team-frontend-debug/roles/coordinator/role.md +21 -0
- package/.codex/skills/team-issue/SKILL.md +24 -0
- package/.codex/skills/team-issue/roles/coordinator/role.md +19 -0
- package/.codex/skills/team-iterdev/SKILL.md +24 -0
- package/.codex/skills/team-iterdev/roles/coordinator/role.md +20 -0
- package/.codex/skills/team-lifecycle-v4/SKILL.md +24 -0
- package/.codex/skills/team-lifecycle-v4/roles/coordinator/role.md +28 -2
- package/.codex/skills/team-perf-opt/SKILL.md +24 -0
- package/.codex/skills/team-perf-opt/roles/coordinator/role.md +20 -0
- package/.codex/skills/team-planex/SKILL.md +24 -0
- package/.codex/skills/team-planex/roles/coordinator/role.md +19 -0
- package/.codex/skills/team-quality-assurance/SKILL.md +24 -0
- package/.codex/skills/team-quality-assurance/roles/coordinator/role.md +21 -0
- package/.codex/skills/team-review/SKILL.md +24 -0
- package/.codex/skills/team-review/roles/coordinator/role.md +21 -0
- package/.codex/skills/team-roadmap-dev/SKILL.md +24 -0
- package/.codex/skills/team-roadmap-dev/roles/coordinator/role.md +19 -0
- package/.codex/skills/team-tech-debt/SKILL.md +24 -0
- package/.codex/skills/team-tech-debt/roles/coordinator/role.md +19 -0
- package/.codex/skills/team-testing/SKILL.md +24 -0
- package/.codex/skills/team-testing/roles/coordinator/role.md +21 -0
- package/.codex/skills/team-uidesign/SKILL.md +24 -0
- package/.codex/skills/team-uidesign/roles/coordinator/role.md +20 -0
- package/.codex/skills/team-ultra-analyze/SKILL.md +24 -0
- package/.codex/skills/team-ultra-analyze/roles/coordinator/role.md +20 -0
- package/.codex/skills/team-ux-improve/SKILL.md +24 -0
- package/.codex/skills/team-ux-improve/roles/coordinator/role.md +20 -0
- package/ccw/frontend/dist/assets/{AlertDialog-zDuLRyN3.js → AlertDialog-Cukb0xv2.js} +2 -2
- package/ccw/frontend/dist/assets/{AlertDialog-zDuLRyN3.js.map → AlertDialog-Cukb0xv2.js.map} +1 -1
- package/ccw/frontend/dist/assets/{AnalysisPage-DGCGwIZY.js → AnalysisPage-Ddmv0J4x.js} +2 -2
- package/ccw/frontend/dist/assets/{AnalysisPage-DGCGwIZY.js.map → AnalysisPage-Ddmv0J4x.js.map} +1 -1
- package/ccw/frontend/dist/assets/{ApiSettingsPage-CgclCqmv.js → ApiSettingsPage-DMkrTZDX.js} +2 -2
- package/ccw/frontend/dist/assets/{ApiSettingsPage-CgclCqmv.js.map → ApiSettingsPage-DMkrTZDX.js.map} +1 -1
- package/ccw/frontend/dist/assets/{CliModeToggle-CbGH7qO4.js → CliModeToggle-DXenjpbe.js} +2 -2
- package/ccw/frontend/dist/assets/{CliModeToggle-CbGH7qO4.js.map → CliModeToggle-DXenjpbe.js.map} +1 -1
- package/ccw/frontend/dist/assets/{CliSessionSharePage-CJGlwyDw.js → CliSessionSharePage-B-ZIMqmX.js} +2 -2
- package/ccw/frontend/dist/assets/{CliSessionSharePage-CJGlwyDw.js.map → CliSessionSharePage-B-ZIMqmX.js.map} +1 -1
- package/ccw/frontend/dist/assets/{CliViewerPage-D-MHYyDt.js → CliViewerPage-9YxGyLxh.js} +2 -2
- package/ccw/frontend/dist/assets/{CliViewerPage-D-MHYyDt.js.map → CliViewerPage-9YxGyLxh.js.map} +1 -1
- package/ccw/frontend/dist/assets/{CodexLensPage-z6miX68P.js → CodexLensPage-B_uv5wdn.js} +2 -2
- package/ccw/frontend/dist/assets/{CodexLensPage-z6miX68P.js.map → CodexLensPage-B_uv5wdn.js.map} +1 -1
- package/ccw/frontend/dist/assets/{Collapsible-D5zS2wef.js → Collapsible-C2qk3yV0.js} +2 -2
- package/ccw/frontend/dist/assets/{Collapsible-D5zS2wef.js.map → Collapsible-C2qk3yV0.js.map} +1 -1
- package/ccw/frontend/dist/assets/{CommandsManagerPage-ChcTwmAn.js → CommandsManagerPage-DBtaWxLB.js} +2 -2
- package/ccw/frontend/dist/assets/{CommandsManagerPage-ChcTwmAn.js.map → CommandsManagerPage-DBtaWxLB.js.map} +1 -1
- package/ccw/frontend/dist/assets/{DeepWikiPage-Cv5LifSi.js → DeepWikiPage-d9K4_TgG.js} +2 -2
- package/ccw/frontend/dist/assets/{DeepWikiPage-Cv5LifSi.js.map → DeepWikiPage-d9K4_TgG.js.map} +1 -1
- package/ccw/frontend/dist/assets/{EndpointsPage-BcyNmqIa.js → EndpointsPage-DhW6hYrI.js} +2 -2
- package/ccw/frontend/dist/assets/{EndpointsPage-BcyNmqIa.js.map → EndpointsPage-DhW6hYrI.js.map} +1 -1
- package/ccw/frontend/dist/assets/{ExplorerPage-DfHtqeQM.js → ExplorerPage-DYYpCvtB.js} +2 -2
- package/ccw/frontend/dist/assets/{ExplorerPage-DfHtqeQM.js.map → ExplorerPage-DYYpCvtB.js.map} +1 -1
- package/ccw/frontend/dist/assets/{FixSessionPage-CbvZApeF.js → FixSessionPage-CSmiT5SE.js} +2 -2
- package/ccw/frontend/dist/assets/{FixSessionPage-CbvZApeF.js.map → FixSessionPage-CSmiT5SE.js.map} +1 -1
- package/ccw/frontend/dist/assets/{FloatingFileBrowser-DLz85cw9.js → FloatingFileBrowser-DvMsXLdP.js} +2 -2
- package/ccw/frontend/dist/assets/{FloatingFileBrowser-DLz85cw9.js.map → FloatingFileBrowser-DvMsXLdP.js.map} +1 -1
- package/ccw/frontend/dist/assets/{FloatingPanel-DrUTmgtV.js → FloatingPanel-sqezhSI8.js} +2 -2
- package/ccw/frontend/dist/assets/{FloatingPanel-DrUTmgtV.js.map → FloatingPanel-sqezhSI8.js.map} +1 -1
- package/ccw/frontend/dist/assets/{GraphExplorerPage-C439yLvH.js → GraphExplorerPage-DS8ghMFM.js} +2 -2
- package/ccw/frontend/dist/assets/{GraphExplorerPage-C439yLvH.js.map → GraphExplorerPage-DS8ghMFM.js.map} +1 -1
- package/ccw/frontend/dist/assets/{HistoryPage-BClJJMEy.js → HistoryPage-B-x1RyHu.js} +2 -2
- package/ccw/frontend/dist/assets/{HistoryPage-BClJJMEy.js.map → HistoryPage-B-x1RyHu.js.map} +1 -1
- package/ccw/frontend/dist/assets/{HookManagerPage-DI-2QDLJ.js → HookManagerPage-BbxpDb68.js} +2 -2
- package/ccw/frontend/dist/assets/{HookManagerPage-DI-2QDLJ.js.map → HookManagerPage-BbxpDb68.js.map} +1 -1
- package/ccw/frontend/dist/assets/{InstallationsPage-DKlz1ypL.js → InstallationsPage-3bShz_Ai.js} +2 -2
- package/ccw/frontend/dist/assets/{InstallationsPage-DKlz1ypL.js.map → InstallationsPage-3bShz_Ai.js.map} +1 -1
- package/ccw/frontend/dist/assets/{IssueHubPage--6DduN4j.js → IssueHubPage-BQY_Hh3e.js} +2 -2
- package/ccw/frontend/dist/assets/{IssueHubPage--6DduN4j.js.map → IssueHubPage-BQY_Hh3e.js.map} +1 -1
- package/ccw/frontend/dist/assets/{LiteTasksPage-39j6xEeL.js → LiteTasksPage-vD_8fQcR.js} +2 -2
- package/ccw/frontend/dist/assets/{LiteTasksPage-39j6xEeL.js.map → LiteTasksPage-vD_8fQcR.js.map} +1 -1
- package/ccw/frontend/dist/assets/{McpManagerPage-D00C9RVN.js → McpManagerPage-CI5ZzB8A.js} +2 -2
- package/ccw/frontend/dist/assets/{McpManagerPage-D00C9RVN.js.map → McpManagerPage-CI5ZzB8A.js.map} +1 -1
- package/ccw/frontend/dist/assets/{MemoryPage-BXWKdTyM.js → MemoryPage-CNuj2eNg.js} +2 -2
- package/ccw/frontend/dist/assets/{MemoryPage-BXWKdTyM.js.map → MemoryPage-CNuj2eNg.js.map} +1 -1
- package/ccw/frontend/dist/assets/{NotFoundPage-h5o3I7cF.js → NotFoundPage-BrnAXkb1.js} +2 -2
- package/ccw/frontend/dist/assets/{NotFoundPage-h5o3I7cF.js.map → NotFoundPage-BrnAXkb1.js.map} +1 -1
- package/ccw/frontend/dist/assets/{OrchestratorPage-jkyjmiI1.js → OrchestratorPage-CH81PGt4.js} +2 -2
- package/ccw/frontend/dist/assets/{OrchestratorPage-jkyjmiI1.js.map → OrchestratorPage-CH81PGt4.js.map} +1 -1
- package/ccw/frontend/dist/assets/{ProjectOverviewPage-C2bE5eb2.js → ProjectOverviewPage-dwiEXl2O.js} +2 -2
- package/ccw/frontend/dist/assets/{ProjectOverviewPage-C2bE5eb2.js.map → ProjectOverviewPage-dwiEXl2O.js.map} +1 -1
- package/ccw/frontend/dist/assets/{PromptHistoryPage-DzmPK4GZ.js → PromptHistoryPage-CabgLjJU.js} +2 -2
- package/ccw/frontend/dist/assets/{PromptHistoryPage-DzmPK4GZ.js.map → PromptHistoryPage-CabgLjJU.js.map} +1 -1
- package/ccw/frontend/dist/assets/{ReviewSessionPage-CVMH1K6G.js → ReviewSessionPage-DAMrNFn8.js} +2 -2
- package/ccw/frontend/dist/assets/{ReviewSessionPage-CVMH1K6G.js.map → ReviewSessionPage-DAMrNFn8.js.map} +1 -1
- package/ccw/frontend/dist/assets/{RulesManagerPage-BDZco-r2.js → RulesManagerPage-4jzmxPn0.js} +2 -2
- package/ccw/frontend/dist/assets/{RulesManagerPage-BDZco-r2.js.map → RulesManagerPage-4jzmxPn0.js.map} +1 -1
- package/ccw/frontend/dist/assets/{SessionDetailPage-D5cM-8Kk.js → SessionDetailPage-C5Btktmp.js} +2 -2
- package/ccw/frontend/dist/assets/{SessionDetailPage-D5cM-8Kk.js.map → SessionDetailPage-C5Btktmp.js.map} +1 -1
- package/ccw/frontend/dist/assets/{SessionsPage-BFy74ye3.js → SessionsPage-CQIB4E8m.js} +2 -2
- package/ccw/frontend/dist/assets/{SessionsPage-BFy74ye3.js.map → SessionsPage-CQIB4E8m.js.map} +1 -1
- package/ccw/frontend/dist/assets/SettingsPage-Yi9UAfm7.js +150 -0
- package/ccw/frontend/dist/assets/SettingsPage-Yi9UAfm7.js.map +1 -0
- package/ccw/frontend/dist/assets/{SkillsManagerPage-8Dsq4AUD.js → SkillsManagerPage-BqfvYSkT.js} +2 -2
- package/ccw/frontend/dist/assets/{SkillsManagerPage-8Dsq4AUD.js.map → SkillsManagerPage-BqfvYSkT.js.map} +1 -1
- package/ccw/frontend/dist/assets/{SpecsSettingsPage-CG77iAYQ.js → SpecsSettingsPage-BdVPM5R6.js} +2 -2
- package/ccw/frontend/dist/assets/{SpecsSettingsPage-CG77iAYQ.js.map → SpecsSettingsPage-BdVPM5R6.js.map} +1 -1
- package/ccw/frontend/dist/assets/{Switch-BbuvVsX-.js → Switch-BG929kV0.js} +2 -2
- package/ccw/frontend/dist/assets/{Switch-BbuvVsX-.js.map → Switch-BG929kV0.js.map} +1 -1
- package/ccw/frontend/dist/assets/{TabsNavigation-SGJhC8-P.js → TabsNavigation-Bol1y09b.js} +2 -2
- package/ccw/frontend/dist/assets/{TabsNavigation-SGJhC8-P.js.map → TabsNavigation-Bol1y09b.js.map} +1 -1
- package/ccw/frontend/dist/assets/{TaskDrawer-p51jeScU.js → TaskDrawer-Dwutrn8_.js} +2 -2
- package/ccw/frontend/dist/assets/{TaskDrawer-p51jeScU.js.map → TaskDrawer-Dwutrn8_.js.map} +1 -1
- package/ccw/frontend/dist/assets/{TeamPage-CvZBThbr.js → TeamPage-CpCSwpxD.js} +2 -2
- package/ccw/frontend/dist/assets/{TeamPage-CvZBThbr.js.map → TeamPage-CpCSwpxD.js.map} +1 -1
- package/ccw/frontend/dist/assets/{TerminalDashboardPage-uhM7kGKI.js → TerminalDashboardPage-DODKjOeK.js} +2 -2
- package/ccw/frontend/dist/assets/{TerminalDashboardPage-uhM7kGKI.js.map → TerminalDashboardPage-DODKjOeK.js.map} +1 -1
- package/ccw/frontend/dist/assets/{archive-D6ySrtHC.js → archive-CQw634kD.js} +2 -2
- package/ccw/frontend/dist/assets/{archive-D6ySrtHC.js.map → archive-CQw634kD.js.map} +1 -1
- package/ccw/frontend/dist/assets/{archive-restore-C1uI-5TY.js → archive-restore-B-_EG6wE.js} +2 -2
- package/ccw/frontend/dist/assets/{archive-restore-C1uI-5TY.js.map → archive-restore-B-_EG6wE.js.map} +1 -1
- package/ccw/frontend/dist/assets/{arrow-right-qE5-FMG8.js → arrow-right-CcQtxBrU.js} +2 -2
- package/ccw/frontend/dist/assets/{arrow-right-qE5-FMG8.js.map → arrow-right-CcQtxBrU.js.map} +1 -1
- package/ccw/frontend/dist/assets/{bookmark-plus-DL4iL38T.js → bookmark-plus-Cl-BbcpR.js} +2 -2
- package/ccw/frontend/dist/assets/{bookmark-plus-DL4iL38T.js.map → bookmark-plus-Cl-BbcpR.js.map} +1 -1
- package/ccw/frontend/dist/assets/{bot-CZzIeEkg.js → bot-CLSNSkW_.js} +2 -2
- package/ccw/frontend/dist/assets/{bot-CZzIeEkg.js.map → bot-CLSNSkW_.js.map} +1 -1
- package/ccw/frontend/dist/assets/{braces-MEPRT2LN.js → braces-DWwkaDS6.js} +2 -2
- package/ccw/frontend/dist/assets/{braces-MEPRT2LN.js.map → braces-DWwkaDS6.js.map} +1 -1
- package/ccw/frontend/dist/assets/{circle-stop-GQcecSUg.js → circle-stop-DiS7e6ma.js} +2 -2
- package/ccw/frontend/dist/assets/{circle-stop-GQcecSUg.js.map → circle-stop-DiS7e6ma.js.map} +1 -1
- package/ccw/frontend/dist/assets/{cpu-CzxYMs1Y.js → cpu-CuvHUVXO.js} +2 -2
- package/ccw/frontend/dist/assets/{cpu-CzxYMs1Y.js.map → cpu-CuvHUVXO.js.map} +1 -1
- package/ccw/frontend/dist/assets/{ellipsis-vertical-DZMfiFKo.js → ellipsis-vertical-BoVlINSw.js} +2 -2
- package/ccw/frontend/dist/assets/{ellipsis-vertical-DZMfiFKo.js.map → ellipsis-vertical-BoVlINSw.js.map} +1 -1
- package/ccw/frontend/dist/assets/{eye-BXfPoClW.js → eye-BEMOdcAN.js} +2 -2
- package/ccw/frontend/dist/assets/{eye-BXfPoClW.js.map → eye-BEMOdcAN.js.map} +1 -1
- package/ccw/frontend/dist/assets/{eye-off-CyaKXmAk.js → eye-off-C5HS4Ytm.js} +2 -2
- package/ccw/frontend/dist/assets/{eye-off-CyaKXmAk.js.map → eye-off-C5HS4Ytm.js.map} +1 -1
- package/ccw/frontend/dist/assets/{file-json-B4LbFfTU.js → file-json-DQ9XLq0B.js} +2 -2
- package/ccw/frontend/dist/assets/{file-json-B4LbFfTU.js.map → file-json-DQ9XLq0B.js.map} +1 -1
- package/ccw/frontend/dist/assets/{file-text-CIWG7Xgj.js → file-text-TGs_qCbw.js} +2 -2
- package/ccw/frontend/dist/assets/{file-text-CIWG7Xgj.js.map → file-text-TGs_qCbw.js.map} +1 -1
- package/ccw/frontend/dist/assets/{filter-CNBjjvBX.js → filter-CIuCqnDB.js} +2 -2
- package/ccw/frontend/dist/assets/{filter-CNBjjvBX.js.map → filter-CIuCqnDB.js.map} +1 -1
- package/ccw/frontend/dist/assets/{folder-DT_XOYw9.js → folder-BkivHBwn.js} +2 -2
- package/ccw/frontend/dist/assets/{folder-DT_XOYw9.js.map → folder-BkivHBwn.js.map} +1 -1
- package/ccw/frontend/dist/assets/{gauge-mvQWOG3S.js → gauge-CtM68fVY.js} +2 -2
- package/ccw/frontend/dist/assets/{gauge-mvQWOG3S.js.map → gauge-CtM68fVY.js.map} +1 -1
- package/ccw/frontend/dist/assets/{globe-B25jraBz.js → globe-DpnrINqP.js} +2 -2
- package/ccw/frontend/dist/assets/{globe-B25jraBz.js.map → globe-DpnrINqP.js.map} +1 -1
- package/ccw/frontend/dist/assets/{grid-3x3-CptugI_Z.js → grid-3x3-SjX0a5JH.js} +2 -2
- package/ccw/frontend/dist/assets/{grid-3x3-CptugI_Z.js.map → grid-3x3-SjX0a5JH.js.map} +1 -1
- package/ccw/frontend/dist/assets/{hard-drive-BUK9Wcoz.js → hard-drive-ByAmnoEg.js} +2 -2
- package/ccw/frontend/dist/assets/{hard-drive-BUK9Wcoz.js.map → hard-drive-ByAmnoEg.js.map} +1 -1
- package/ccw/frontend/dist/assets/{hash-dddMDYK7.js → hash-DbLc3VOZ.js} +2 -2
- package/ccw/frontend/dist/assets/{hash-dddMDYK7.js.map → hash-DbLc3VOZ.js.map} +1 -1
- package/ccw/frontend/dist/assets/{history-BdDj8MtC.js → history-Botz5Z5d.js} +2 -2
- package/ccw/frontend/dist/assets/{history-BdDj8MtC.js.map → history-Botz5Z5d.js.map} +1 -1
- package/ccw/frontend/dist/assets/{index-CcxBnbbQ.js → index-BGvyf4-9.js} +2 -2
- package/ccw/frontend/dist/assets/{index-CcxBnbbQ.js.map → index-BGvyf4-9.js.map} +1 -1
- package/ccw/frontend/dist/assets/index-BoqylFO4.css +39 -0
- package/ccw/frontend/dist/assets/{index-DZGHdspr.js → index-DP_mTJI8.js} +3 -3
- package/ccw/frontend/dist/assets/{index-DZGHdspr.js.map → index-DP_mTJI8.js.map} +1 -1
- package/ccw/frontend/dist/assets/{index-B6UfIzhR.js → index-MkgdhX7a.js} +2 -2
- package/ccw/frontend/dist/assets/{index-B6UfIzhR.js.map → index-MkgdhX7a.js.map} +1 -1
- package/ccw/frontend/dist/assets/{index-EFcT7h67.js → index-ni-tG9rm.js} +2 -2
- package/ccw/frontend/dist/assets/{index-EFcT7h67.js.map → index-ni-tG9rm.js.map} +1 -1
- package/ccw/frontend/dist/assets/{layout-grid-BVlT1oI7.js → layout-grid-11E4bGJz.js} +2 -2
- package/ccw/frontend/dist/assets/{layout-grid-BVlT1oI7.js.map → layout-grid-11E4bGJz.js.map} +1 -1
- package/ccw/frontend/dist/assets/{lightbulb-Mt3Tlwh4.js → lightbulb-8KrKY82b.js} +2 -2
- package/ccw/frontend/dist/assets/{lightbulb-Mt3Tlwh4.js.map → lightbulb-8KrKY82b.js.map} +1 -1
- package/ccw/frontend/dist/assets/{link-2-DXqT64qo.js → link-2-BUn6RILb.js} +2 -2
- package/ccw/frontend/dist/assets/{link-2-DXqT64qo.js.map → link-2-BUn6RILb.js.map} +1 -1
- package/ccw/frontend/dist/assets/{link-CBMtrpcI.js → link-CmP254Ai.js} +2 -2
- package/ccw/frontend/dist/assets/{link-CBMtrpcI.js.map → link-CmP254Ai.js.map} +1 -1
- package/ccw/frontend/dist/assets/{list-DDyEM4AO.js → list-BAwzl4a2.js} +2 -2
- package/ccw/frontend/dist/assets/{list-DDyEM4AO.js.map → list-BAwzl4a2.js.map} +1 -1
- package/ccw/frontend/dist/assets/{map-pin-B2FxBKfk.js → map-pin-gi342rqk.js} +2 -2
- package/ccw/frontend/dist/assets/{map-pin-B2FxBKfk.js.map → map-pin-gi342rqk.js.map} +1 -1
- package/ccw/frontend/dist/assets/{messages-square-zJfTY9pq.js → messages-square-C1Lh8q8b.js} +2 -2
- package/ccw/frontend/dist/assets/{messages-square-zJfTY9pq.js.map → messages-square-C1Lh8q8b.js.map} +1 -1
- package/ccw/frontend/dist/assets/{minimize-2-DnhGZj79.js → minimize-2-OgWNLKdq.js} +2 -2
- package/ccw/frontend/dist/assets/{minimize-2-DnhGZj79.js.map → minimize-2-OgWNLKdq.js.map} +1 -1
- package/ccw/frontend/dist/assets/{package-DYzAybhU.js → package-Djsvs5qp.js} +2 -2
- package/ccw/frontend/dist/assets/{package-DYzAybhU.js.map → package-Djsvs5qp.js.map} +1 -1
- package/ccw/frontend/dist/assets/{plug-B3kKHsu1.js → plug-DvSZP2cp.js} +2 -2
- package/ccw/frontend/dist/assets/{plug-B3kKHsu1.js.map → plug-DvSZP2cp.js.map} +1 -1
- package/ccw/frontend/dist/assets/{power-BPNNZgLy.js → power-BY7vTLmU.js} +2 -2
- package/ccw/frontend/dist/assets/{power-BPNNZgLy.js.map → power-BY7vTLmU.js.map} +1 -1
- package/ccw/frontend/dist/assets/{save-Cwry93p-.js → save-DXfqv84T.js} +2 -2
- package/ccw/frontend/dist/assets/{save-Cwry93p-.js.map → save-DXfqv84T.js.map} +1 -1
- package/ccw/frontend/dist/assets/{send-DuWWy2J8.js → send-E2o2LZSX.js} +2 -2
- package/ccw/frontend/dist/assets/{send-DuWWy2J8.js.map → send-E2o2LZSX.js.map} +1 -1
- package/ccw/frontend/dist/assets/{settings-2-C3U1eSK6.js → settings-2-ChD1LFHH.js} +2 -2
- package/ccw/frontend/dist/assets/{settings-2-C3U1eSK6.js.map → settings-2-ChD1LFHH.js.map} +1 -1
- package/ccw/frontend/dist/assets/{square-check-big-CrG1ejFB.js → square-check-big-CBymuqmD.js} +2 -2
- package/ccw/frontend/dist/assets/{square-check-big-CrG1ejFB.js.map → square-check-big-CBymuqmD.js.map} +1 -1
- package/ccw/frontend/dist/assets/{square-pen-eLWlCgZ5.js → square-pen-BfaiJgOX.js} +2 -2
- package/ccw/frontend/dist/assets/{square-pen-eLWlCgZ5.js.map → square-pen-BfaiJgOX.js.map} +1 -1
- package/ccw/frontend/dist/assets/{star-sveo4KRn.js → star-DHMWqZ09.js} +2 -2
- package/ccw/frontend/dist/assets/{star-sveo4KRn.js.map → star-DHMWqZ09.js.map} +1 -1
- package/ccw/frontend/dist/assets/{style-CRdAX7Cu.js → style-wvcOEAiM.js} +2 -2
- package/ccw/frontend/dist/assets/{style-CRdAX7Cu.js.map → style-wvcOEAiM.js.map} +1 -1
- package/ccw/frontend/dist/assets/{target-Oz1-z8Zu.js → target-B8AMmf_N.js} +2 -2
- package/ccw/frontend/dist/assets/{target-Oz1-z8Zu.js.map → target-B8AMmf_N.js.map} +1 -1
- package/ccw/frontend/dist/assets/{test-tube-BozkZKD6.js → test-tube-BpDeTJi1.js} +2 -2
- package/ccw/frontend/dist/assets/{test-tube-BozkZKD6.js.map → test-tube-BpDeTJi1.js.map} +1 -1
- package/ccw/frontend/dist/assets/{upload-CTlUsxyh.js → upload-pflkdIDG.js} +2 -2
- package/ccw/frontend/dist/assets/{upload-CTlUsxyh.js.map → upload-pflkdIDG.js.map} +1 -1
- package/ccw/frontend/dist/assets/{useApiSettings-D6WfgFYj.js → useApiSettings-BPx4DyKT.js} +2 -2
- package/ccw/frontend/dist/assets/{useApiSettings-D6WfgFYj.js.map → useApiSettings-BPx4DyKT.js.map} +1 -1
- package/ccw/frontend/dist/assets/{useCli-CgGVNN5I.js → useCli-D1jfH3XA.js} +2 -2
- package/ccw/frontend/dist/assets/{useCli-CgGVNN5I.js.map → useCli-D1jfH3XA.js.map} +1 -1
- package/ccw/frontend/dist/assets/{useCommands-o5CKv-10.js → useCommands-DhR71vpa.js} +2 -2
- package/ccw/frontend/dist/assets/{useCommands-o5CKv-10.js.map → useCommands-DhR71vpa.js.map} +1 -1
- package/ccw/frontend/dist/assets/{useDebounce-rKo_bCBK.js → useDebounce-a6Yyer3m.js} +2 -2
- package/ccw/frontend/dist/assets/{useDebounce-rKo_bCBK.js.map → useDebounce-a6Yyer3m.js.map} +1 -1
- package/ccw/frontend/dist/assets/{useFileExplorer-WeE4t9Hg.js → useFileExplorer-B8W2JTj2.js} +2 -2
- package/ccw/frontend/dist/assets/{useFileExplorer-WeE4t9Hg.js.map → useFileExplorer-B8W2JTj2.js.map} +1 -1
- package/ccw/frontend/dist/assets/{useLocale-BS0tTC-_.js → useLocale-aMHdQIL_.js} +2 -2
- package/ccw/frontend/dist/assets/{useLocale-BS0tTC-_.js.map → useLocale-aMHdQIL_.js.map} +1 -1
- package/ccw/frontend/dist/assets/{useSkills-BUgAhw6r.js → useSkills-BHpc2LtN.js} +3 -3
- package/ccw/frontend/dist/assets/{useSkills-BUgAhw6r.js.map → useSkills-BHpc2LtN.js.map} +1 -1
- package/ccw/frontend/dist/assets/{useSystemSettings-CLhmINg1.js → useSystemSettings-BFD0SvEF.js} +2 -2
- package/ccw/frontend/dist/assets/{useSystemSettings-CLhmINg1.js.map → useSystemSettings-BFD0SvEF.js.map} +1 -1
- package/ccw/frontend/dist/assets/{wand-sparkles-BUHKJH1X.js → wand-sparkles-dYtI2IKM.js} +2 -2
- package/ccw/frontend/dist/assets/{wand-sparkles-BUHKJH1X.js.map → wand-sparkles-dYtI2IKM.js.map} +1 -1
- package/ccw/frontend/dist/index.html +2 -2
- package/package.json +1 -1
- package/ccw/frontend/dist/assets/SettingsPage-Qj0fFDjX.js +0 -150
- package/ccw/frontend/dist/assets/SettingsPage-Qj0fFDjX.js.map +0 -1
- package/ccw/frontend/dist/assets/index-nU0QYi1y.css +0 -39
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{j as e,C as U,a as X,c as b,u as J,Z as le,S as re,F as ce,b as A,B as x,D as W,d as Y,e as f,f as ee,g as F,h as E,T as de,i as oe,L as me,k as H,l as xe,R as se,m as T,n as he,r as y,o as Q,s as pe,p as ue,q as ge,t as fe,I as je,X as K,v as ve,w as Ne,x as we,y as ye,z as be,A as Ce,E as ke,G as Se}from"./index-DZGHdspr.js";import{F as I}from"./file-text-CIWG7Xgj.js";import{T as Fe}from"./test-tube-BozkZKD6.js";import{E as De}from"./ellipsis-vertical-DZMfiFKo.js";import{E as Me}from"./eye-BXfPoClW.js";import{A as _e}from"./archive-D6ySrtHC.js";import{T as Le}from"./TabsNavigation-SGJhC8-P.js";import{M as Pe,a as Te}from"./minimize-2-DnhGZj79.js";import{F as Ae}from"./filter-CNBjjvBX.js";const Ee={planning:{variant:"info"},in_progress:{variant:"warning"},completed:{variant:"success"},archived:{variant:"secondary"},paused:{variant:"default"}},V={planning:"sessions.status.planning",in_progress:"sessions.status.inProgress",completed:"sessions.status.completed",archived:"sessions.status.archived",paused:"sessions.status.paused"},Ie={review:{variant:"review",icon:A},tdd:{variant:"success",icon:Fe},test:{variant:"info",icon:I},docs:{variant:"warning",icon:ce},workflow:{variant:"default",icon:re},"lite-plan":{variant:"secondary",icon:I},"lite-fix":{variant:"destructive",icon:le}},Z={review:"sessions.type.review",tdd:"sessions.type.tdd",test:"sessions.type.test",docs:"sessions.type.docs",workflow:"sessions.type.workflow","lite-plan":"sessions.type.lite-plan","lite-fix":"sessions.type.lite-fix"};function q(s){if(!s)return"Unknown";try{return new Date(s).toLocaleDateString(void 0,{year:"numeric",month:"short",day:"numeric"})}catch{return"Invalid date"}}function ze(s){if(!s||s.length===0)return{total:0,completed:0,failed:0,pending:0,inProgress:0,percentage:0};const d=s.length,o=s.filter(r=>r.status==="completed").length,h=s.filter(r=>r.status==="blocked"||r.status==="skipped").length,n=s.filter(r=>r.status==="in_progress").length,g=s.filter(r=>r.status==="pending").length,l=Math.round(o/d*100);return{total:d,completed:o,failed:h,pending:g,inProgress:n,percentage:l}}function Be(s){if(!(s!=null&&s.dimensions)||s.dimensions.length===0)return{total:0,critical:0,high:0,medium:0,low:0};let d=0,o=0,h=0,n=0;return s.dimensions.forEach(l=>{l.findings&&l.findings.forEach(r=>{var u;const t=(u=r.severity)==null?void 0:u.toLowerCase();t==="critical"?d++:t==="high"?o++:t==="medium"?h++:t==="low"&&n++})}),{total:d+o+h+n,critical:d,high:o,medium:h,low:n}}function Ke({session:s,onView:d,onArchive:o,onDelete:h,onClick:n,className:g,showActions:l=!0,actionsDisabled:r=!1}){var k,_,L;const{formatMessage:t}=J(),{variant:u}=Ee[s.status]||{variant:"default"},D=V[s.status]?t({id:V[s.status]}):t({id:"common.status.unknown"}),j=s.type?Ie[s.type]:null,v=s.type&&Z[s.type]?t({id:Z[s.type]}):null,i=ze(s.tasks),p=Be(s.review),C=s.status==="planning",z=s.status==="archived"||s.location==="archived",M=c=>{c.target.closest("[data-radix-popper-content-wrapper]")||n==null||n(s.session_id)},w=(c,N)=>{switch(c.stopPropagation(),N){case"view":d==null||d(s.session_id);break;case"archive":o==null||o(s.session_id);break;case"delete":h==null||h(s.session_id);break}};return e.jsx(U,{className:b("group cursor-pointer transition-all duration-200 hover:shadow-md hover:border-primary/30",C&&"border-info/30 bg-info/5",g),onClick:M,children:e.jsxs(X,{className:"p-4",children:[e.jsxs("div",{className:"flex items-start justify-between gap-2 mb-2",children:[e.jsx("div",{className:"flex-1 min-w-0",children:e.jsxs("div",{className:"flex items-center gap-2 mb-1",children:[j&&v&&e.jsxs(x,{variant:j.variant,className:"gap-1 flex-shrink-0",children:[e.jsx(j.icon,{className:"h-3 w-3"}),v]}),e.jsx("h3",{className:"font-bold text-card-foreground text-sm tracking-wide uppercase truncate",children:s.session_id})]})}),e.jsxs("div",{className:"flex items-center gap-2 flex-shrink-0",children:[e.jsx(x,{variant:u,children:D}),l&&e.jsxs(W,{children:[e.jsx(Y,{asChild:!0,children:e.jsxs(f,{variant:"ghost",size:"icon",className:"h-8 w-8 opacity-0 group-hover:opacity-100 transition-opacity",onClick:c=>c.stopPropagation(),disabled:r,children:[e.jsx(De,{className:"h-4 w-4"}),e.jsx("span",{className:"sr-only",children:t({id:"common.aria.actions"})})]})}),e.jsxs(ee,{align:"end",children:[e.jsxs(F,{onClick:c=>w(c,"view"),children:[e.jsx(Me,{className:"mr-2 h-4 w-4"}),t({id:"sessions.actions.viewDetails"})]}),!z&&e.jsxs(e.Fragment,{children:[e.jsx(E,{}),e.jsxs(F,{onClick:c=>w(c,"archive"),children:[e.jsx(_e,{className:"mr-2 h-4 w-4"}),t({id:"sessions.actions.archive"})]})]}),e.jsx(E,{}),e.jsxs(F,{onClick:c=>w(c,"delete"),className:"text-destructive focus:text-destructive",children:[e.jsx(de,{className:"mr-2 h-4 w-4"}),t({id:"sessions.actions.delete"})]})]})]})]})]}),s.title&&e.jsx("p",{className:"text-sm text-foreground line-clamp-2 mb-3",children:s.title}),e.jsxs("div",{className:"flex flex-wrap items-center gap-x-4 gap-y-2 text-xs text-muted-foreground",children:[e.jsxs("span",{className:"flex items-center gap-1",children:[e.jsx(oe,{className:"h-3.5 w-3.5"}),q(s.created_at)]}),s.type==="review"?e.jsxs(e.Fragment,{children:[((k=s.review)==null?void 0:k.dimensions)&&s.review.dimensions.length>0&&e.jsxs("span",{className:"flex items-center gap-1",children:[e.jsx(A,{className:"h-3.5 w-3.5"}),s.review.dimensions.length," ",t({id:"sessions.card.dimensions"})]}),((_=s.review)==null?void 0:_.findings)!==void 0&&e.jsxs("span",{className:"flex items-center gap-1",children:[e.jsx(I,{className:"h-3.5 w-3.5"}),typeof s.review.findings=="number"?s.review.findings:((L=s.review.dimensions)==null?void 0:L.reduce((c,N)=>{var P;return c+(((P=N.findings)==null?void 0:P.length)||0)},0))||0," ",t({id:"sessions.card.findings"})]})]}):e.jsxs(e.Fragment,{children:[e.jsxs("span",{className:"flex items-center gap-1",children:[e.jsx(me,{className:"h-3.5 w-3.5"}),i.total," ",t({id:"sessions.card.tasks"})]}),i.total>0&&e.jsxs("span",{className:"flex items-center gap-1",children:[e.jsx(H,{className:"h-3.5 w-3.5 text-success"}),i.completed," ",t({id:"sessions.card.completed"})]})]}),s.updated_at&&s.updated_at!==s.created_at&&e.jsxs("span",{className:"flex items-center gap-1",children:[e.jsx(xe,{className:"h-3.5 w-3.5"}),t({id:"sessions.card.updated"}),": ",q(s.updated_at)]})]}),s.type!=="review"&&i.total>0&&e.jsxs("div",{className:"flex flex-wrap items-center gap-1.5 mt-2",children:[i.inProgress>0&&e.jsxs(x,{variant:"info",className:"gap-1 px-1.5 py-0 text-[10px]",children:[e.jsx(se,{className:"h-3 w-3"}),i.inProgress," ",t({id:"sessions.taskStatus.inProgress"})]}),i.completed>0&&e.jsxs(x,{variant:"success",className:"gap-1 px-1.5 py-0 text-[10px]",children:[e.jsx(H,{className:"h-3 w-3"}),i.completed," ",t({id:"sessions.taskStatus.completed"})]}),i.failed>0&&e.jsxs(x,{variant:"destructive",className:"gap-1 px-1.5 py-0 text-[10px]",children:[e.jsx(T,{className:"h-3 w-3"}),i.failed," ",t({id:"sessions.taskStatus.failed"})]})]}),s.type==="review"&&p.total>0&&e.jsxs("div",{className:"flex flex-wrap items-center gap-1.5 mt-2",children:[p.critical>0&&e.jsxs(x,{variant:"destructive",className:"gap-1 px-1.5 py-0 text-[10px]",children:[e.jsx(T,{className:"h-3 w-3"}),p.critical," Critical"]}),p.high>0&&e.jsxs(x,{variant:"warning",className:"gap-1 px-1.5 py-0 text-[10px]",children:[e.jsx(T,{className:"h-3 w-3"}),p.high," High"]}),p.medium>0&&e.jsxs(x,{variant:"info",className:"gap-1 px-1.5 py-0 text-[10px]",children:[e.jsx(A,{className:"h-3 w-3"}),p.medium," Medium"]}),p.low>0&&e.jsxs(x,{variant:"secondary",className:"gap-1 px-1.5 py-0 text-[10px]",children:[e.jsx(I,{className:"h-3 w-3"}),p.low," Low"]})]}),s.type!=="review"&&i.total>0&&!C&&e.jsxs("div",{className:"mt-3",children:[e.jsxs("div",{className:"flex items-center justify-between text-xs mb-1",children:[e.jsx("span",{className:"text-muted-foreground",children:t({id:"sessions.card.progress"})}),e.jsxs("span",{className:"text-card-foreground font-medium",children:[i.completed,"/",i.total," (",i.percentage,"%)"]})]}),e.jsx("div",{className:"h-1.5 w-full rounded-full bg-muted overflow-hidden",children:e.jsx("div",{className:b("h-full transition-all duration-300",i.percentage===100?"bg-success":"bg-primary"),style:{width:`${i.percentage}%`}})})]}),s.description&&s.description!==s.title&&e.jsx("p",{className:"mt-2 text-xs text-muted-foreground line-clamp-2 italic",children:s.description})]})})}function $e({className:s}){return e.jsx(U,{className:b("animate-pulse",s),children:e.jsxs(X,{className:"p-4",children:[e.jsxs("div",{className:"flex items-start justify-between",children:[e.jsxs("div",{className:"flex-1",children:[e.jsx("div",{className:"h-5 w-32 rounded bg-muted"}),e.jsx("div",{className:"mt-1 h-3 w-24 rounded bg-muted"})]}),e.jsx("div",{className:"h-5 w-16 rounded-full bg-muted"})]}),e.jsxs("div",{className:"mt-3 flex gap-4",children:[e.jsx("div",{className:"h-4 w-20 rounded bg-muted"}),e.jsx("div",{className:"h-4 w-16 rounded bg-muted"})]}),e.jsxs("div",{className:"mt-2 flex gap-1.5",children:[e.jsx("div",{className:"h-5 w-16 rounded-full bg-muted"}),e.jsx("div",{className:"h-5 w-20 rounded-full bg-muted"}),e.jsx("div",{className:"h-5 w-18 rounded-full bg-muted"})]}),e.jsx("div",{className:"mt-3",children:e.jsx("div",{className:"h-1.5 w-full rounded-full bg-muted"})})]})})}const G={planning:"sessions.status.planning",in_progress:"sessions.status.inProgress",completed:"sessions.status.completed",archived:"sessions.status.archived",paused:"sessions.status.paused"};function Xe(){const{formatMessage:s}=J(),d=he(),[o,h]=y.useState("active"),[n,g]=y.useState(""),[l,r]=y.useState([]),[t,u]=y.useState(!1),[D,j]=y.useState(null),v=Q(pe),i=Q(a=>a.toggleImmersiveMode),p=y.useMemo(()=>({location:o,search:n,status:l.length>0?l:void 0}),[o,n,l]),{filteredSessions:C,isLoading:z,isFetching:M,error:w,refetch:k}=ue({filter:p}),{archiveSession:_,isArchiving:L}=ge(),{deleteSession:c,isDeleting:N}=fe(),P=L||N,$=(a,m)=>{d(m==="review"?`/sessions/${a}/review`:`/sessions/${a}`)},ae=async a=>{try{await _(a)}catch(m){console.error("Failed to archive session:",m)}},te=a=>{j(a),u(!0)},ie=async()=>{if(D)try{await c(D),u(!1),j(null)}catch(a){console.error("Failed to delete session:",a)}},O=()=>{g("")},R=a=>{r(m=>m.includes(a)?m.filter(ne=>ne!==a):[...m,a])},B=()=>{r([]),g("")},S=l.length>0||n.length>0;return e.jsxs("div",{className:b("space-y-6",v&&"h-screen overflow-hidden"),children:[e.jsxs("div",{className:"flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"text-2xl font-semibold text-foreground",children:s({id:"sessions.title"})}),e.jsx("p",{className:"text-sm text-muted-foreground mt-1",children:s({id:"sessions.description"})})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs(f,{variant:"outline",size:"sm",onClick:()=>k(),disabled:M,children:[e.jsx(se,{className:b("h-4 w-4 mr-2",M&&"animate-spin")}),s({id:"common.actions.refresh"})]}),e.jsx("button",{onClick:i,className:b("p-2 rounded-md transition-colors",v?"bg-primary/10 text-primary":"text-muted-foreground hover:text-foreground hover:bg-muted"),title:s(v?{id:"common.exitFullscreen",defaultMessage:"Exit Fullscreen"}:{id:"common.fullscreen",defaultMessage:"Fullscreen"}),children:v?e.jsx(Pe,{className:"w-4 h-4"}):e.jsx(Te,{className:"w-4 h-4"})})]})]}),w&&e.jsxs("div",{className:"flex items-center gap-2 p-4 rounded-lg bg-destructive/10 border border-destructive/30 text-destructive",children:[e.jsx(T,{className:"h-5 w-5 flex-shrink-0"}),e.jsxs("div",{className:"flex-1",children:[e.jsx("p",{className:"text-sm font-medium",children:s({id:"common.errors.loadFailed"})}),e.jsx("p",{className:"text-xs mt-0.5",children:w.message})]}),e.jsx(f,{variant:"outline",size:"sm",onClick:()=>k(),children:s({id:"home.errors.retry"})})]}),e.jsxs("div",{className:"flex flex-col gap-4 sm:flex-row sm:items-center",children:[e.jsx(Le,{value:o,onValueChange:a=>h(a),tabs:[{value:"active",label:s({id:"sessions.filters.active"})},{value:"archived",label:s({id:"sessions.filters.archived"})},{value:"all",label:s({id:"sessions.filters.all"})}]}),e.jsxs("div",{className:"flex-1 max-w-sm relative",children:[e.jsx(A,{className:"absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground"}),e.jsx(je,{placeholder:s({id:"sessions.searchPlaceholder"}),value:n,onChange:a=>g(a.target.value),className:"pl-9 pr-9"}),n&&e.jsx("button",{onClick:O,className:"absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground",children:e.jsx(K,{className:"h-4 w-4"})})]}),e.jsxs(W,{children:[e.jsx(Y,{asChild:!0,children:e.jsxs(f,{variant:"outline",size:"sm",className:"gap-2",children:[e.jsx(Ae,{className:"h-4 w-4"}),s({id:"common.actions.filter"}),l.length>0&&e.jsx(x,{variant:"secondary",className:"ml-1 h-5 min-w-5 px-1",children:l.length})]})}),e.jsxs(ee,{align:"end",className:"w-48",children:[e.jsx(ve,{children:s({id:"common.status.label"})}),e.jsx(E,{}),["planning","in_progress","completed","paused"].map(a=>e.jsxs(F,{onClick:()=>R(a),className:"justify-between",children:[e.jsx("span",{children:s({id:G[a]})}),l.includes(a)&&e.jsx("span",{className:"text-primary",children:"✓"})]},a)),S&&e.jsxs(e.Fragment,{children:[e.jsx(E,{}),e.jsx(F,{onClick:B,className:"text-destructive",children:s({id:"common.actions.clearFilters"})})]})]})]})]}),S&&e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsxs("span",{className:"text-sm text-muted-foreground",children:[s({id:"common.actions.filters"}),":"]}),l.map(a=>e.jsxs(x,{variant:"secondary",className:"cursor-pointer",onClick:()=>R(a),children:[s({id:G[a]}),e.jsx(K,{className:"ml-1 h-3 w-3"})]},a)),n&&e.jsxs(x,{variant:"secondary",className:"cursor-pointer",onClick:O,children:[s({id:"common.actions.search"}),": ",n,e.jsx(K,{className:"ml-1 h-3 w-3"})]}),e.jsx(f,{variant:"ghost",size:"sm",onClick:B,className:"h-6 text-xs",children:s({id:"common.actions.clearAll"})})]}),z?e.jsx("div",{className:"grid gap-4 grid-cols-1 md:grid-cols-2 lg:grid-cols-3",children:Array.from({length:9}).map((a,m)=>e.jsx($e,{},m))}):C.length===0?e.jsxs("div",{className:"flex flex-col items-center justify-center py-16 px-4 border border-dashed border-border rounded-lg",children:[e.jsx(Ne,{className:"h-12 w-12 text-muted-foreground mb-4"}),e.jsx("h3",{className:"text-lg font-medium text-foreground mb-1",children:s(S?{id:"sessions.emptyState.title"}:{id:"sessions.emptyState.title"})}),e.jsx("p",{className:"text-sm text-muted-foreground text-center max-w-sm mb-4",children:s(S?{id:"sessions.emptyState.message"}:{id:"sessions.emptyState.createFirst"})}),S&&e.jsx(f,{variant:"outline",onClick:B,children:s({id:"common.actions.clearFilters"})})]}):e.jsx("div",{className:"grid gap-4 grid-cols-1 md:grid-cols-2 lg:grid-cols-3",children:C.map(a=>e.jsx(Ke,{session:a,onClick:m=>$(m,a.type),onView:m=>$(m,a.type),onArchive:ae,onDelete:te,actionsDisabled:P},a.session_id))}),e.jsx(we,{open:t,onOpenChange:u,children:e.jsxs(ye,{children:[e.jsxs(be,{children:[e.jsx(Ce,{children:s({id:"common.dialog.deleteSession"})}),e.jsx(ke,{children:s({id:"common.dialog.deleteConfirm"})})]}),e.jsxs(Se,{children:[e.jsx(f,{variant:"outline",onClick:()=>{u(!1),j(null)},children:s({id:"common.actions.cancel"})}),e.jsx(f,{variant:"destructive",onClick:ie,disabled:N,children:s(N?{id:"common.status.deleting"}:{id:"common.actions.delete"})})]})]})})]})}export{Xe as SessionsPage,Xe as default};
|
|
2
|
-
//# sourceMappingURL=SessionsPage-
|
|
1
|
+
import{j as e,C as U,a as X,c as b,u as J,Z as le,S as re,F as ce,b as A,B as x,D as W,d as Y,e as f,f as ee,g as F,h as E,T as de,i as oe,L as me,k as H,l as xe,R as se,m as T,n as he,r as y,o as Q,s as pe,p as ue,q as ge,t as fe,I as je,X as K,v as ve,w as Ne,x as we,y as ye,z as be,A as Ce,E as ke,G as Se}from"./index-DP_mTJI8.js";import{F as I}from"./file-text-TGs_qCbw.js";import{T as Fe}from"./test-tube-BpDeTJi1.js";import{E as De}from"./ellipsis-vertical-BoVlINSw.js";import{E as Me}from"./eye-BEMOdcAN.js";import{A as _e}from"./archive-CQw634kD.js";import{T as Le}from"./TabsNavigation-Bol1y09b.js";import{M as Pe,a as Te}from"./minimize-2-OgWNLKdq.js";import{F as Ae}from"./filter-CIuCqnDB.js";const Ee={planning:{variant:"info"},in_progress:{variant:"warning"},completed:{variant:"success"},archived:{variant:"secondary"},paused:{variant:"default"}},V={planning:"sessions.status.planning",in_progress:"sessions.status.inProgress",completed:"sessions.status.completed",archived:"sessions.status.archived",paused:"sessions.status.paused"},Ie={review:{variant:"review",icon:A},tdd:{variant:"success",icon:Fe},test:{variant:"info",icon:I},docs:{variant:"warning",icon:ce},workflow:{variant:"default",icon:re},"lite-plan":{variant:"secondary",icon:I},"lite-fix":{variant:"destructive",icon:le}},Z={review:"sessions.type.review",tdd:"sessions.type.tdd",test:"sessions.type.test",docs:"sessions.type.docs",workflow:"sessions.type.workflow","lite-plan":"sessions.type.lite-plan","lite-fix":"sessions.type.lite-fix"};function q(s){if(!s)return"Unknown";try{return new Date(s).toLocaleDateString(void 0,{year:"numeric",month:"short",day:"numeric"})}catch{return"Invalid date"}}function ze(s){if(!s||s.length===0)return{total:0,completed:0,failed:0,pending:0,inProgress:0,percentage:0};const d=s.length,o=s.filter(r=>r.status==="completed").length,h=s.filter(r=>r.status==="blocked"||r.status==="skipped").length,n=s.filter(r=>r.status==="in_progress").length,g=s.filter(r=>r.status==="pending").length,l=Math.round(o/d*100);return{total:d,completed:o,failed:h,pending:g,inProgress:n,percentage:l}}function Be(s){if(!(s!=null&&s.dimensions)||s.dimensions.length===0)return{total:0,critical:0,high:0,medium:0,low:0};let d=0,o=0,h=0,n=0;return s.dimensions.forEach(l=>{l.findings&&l.findings.forEach(r=>{var u;const t=(u=r.severity)==null?void 0:u.toLowerCase();t==="critical"?d++:t==="high"?o++:t==="medium"?h++:t==="low"&&n++})}),{total:d+o+h+n,critical:d,high:o,medium:h,low:n}}function Ke({session:s,onView:d,onArchive:o,onDelete:h,onClick:n,className:g,showActions:l=!0,actionsDisabled:r=!1}){var k,_,L;const{formatMessage:t}=J(),{variant:u}=Ee[s.status]||{variant:"default"},D=V[s.status]?t({id:V[s.status]}):t({id:"common.status.unknown"}),j=s.type?Ie[s.type]:null,v=s.type&&Z[s.type]?t({id:Z[s.type]}):null,i=ze(s.tasks),p=Be(s.review),C=s.status==="planning",z=s.status==="archived"||s.location==="archived",M=c=>{c.target.closest("[data-radix-popper-content-wrapper]")||n==null||n(s.session_id)},w=(c,N)=>{switch(c.stopPropagation(),N){case"view":d==null||d(s.session_id);break;case"archive":o==null||o(s.session_id);break;case"delete":h==null||h(s.session_id);break}};return e.jsx(U,{className:b("group cursor-pointer transition-all duration-200 hover:shadow-md hover:border-primary/30",C&&"border-info/30 bg-info/5",g),onClick:M,children:e.jsxs(X,{className:"p-4",children:[e.jsxs("div",{className:"flex items-start justify-between gap-2 mb-2",children:[e.jsx("div",{className:"flex-1 min-w-0",children:e.jsxs("div",{className:"flex items-center gap-2 mb-1",children:[j&&v&&e.jsxs(x,{variant:j.variant,className:"gap-1 flex-shrink-0",children:[e.jsx(j.icon,{className:"h-3 w-3"}),v]}),e.jsx("h3",{className:"font-bold text-card-foreground text-sm tracking-wide uppercase truncate",children:s.session_id})]})}),e.jsxs("div",{className:"flex items-center gap-2 flex-shrink-0",children:[e.jsx(x,{variant:u,children:D}),l&&e.jsxs(W,{children:[e.jsx(Y,{asChild:!0,children:e.jsxs(f,{variant:"ghost",size:"icon",className:"h-8 w-8 opacity-0 group-hover:opacity-100 transition-opacity",onClick:c=>c.stopPropagation(),disabled:r,children:[e.jsx(De,{className:"h-4 w-4"}),e.jsx("span",{className:"sr-only",children:t({id:"common.aria.actions"})})]})}),e.jsxs(ee,{align:"end",children:[e.jsxs(F,{onClick:c=>w(c,"view"),children:[e.jsx(Me,{className:"mr-2 h-4 w-4"}),t({id:"sessions.actions.viewDetails"})]}),!z&&e.jsxs(e.Fragment,{children:[e.jsx(E,{}),e.jsxs(F,{onClick:c=>w(c,"archive"),children:[e.jsx(_e,{className:"mr-2 h-4 w-4"}),t({id:"sessions.actions.archive"})]})]}),e.jsx(E,{}),e.jsxs(F,{onClick:c=>w(c,"delete"),className:"text-destructive focus:text-destructive",children:[e.jsx(de,{className:"mr-2 h-4 w-4"}),t({id:"sessions.actions.delete"})]})]})]})]})]}),s.title&&e.jsx("p",{className:"text-sm text-foreground line-clamp-2 mb-3",children:s.title}),e.jsxs("div",{className:"flex flex-wrap items-center gap-x-4 gap-y-2 text-xs text-muted-foreground",children:[e.jsxs("span",{className:"flex items-center gap-1",children:[e.jsx(oe,{className:"h-3.5 w-3.5"}),q(s.created_at)]}),s.type==="review"?e.jsxs(e.Fragment,{children:[((k=s.review)==null?void 0:k.dimensions)&&s.review.dimensions.length>0&&e.jsxs("span",{className:"flex items-center gap-1",children:[e.jsx(A,{className:"h-3.5 w-3.5"}),s.review.dimensions.length," ",t({id:"sessions.card.dimensions"})]}),((_=s.review)==null?void 0:_.findings)!==void 0&&e.jsxs("span",{className:"flex items-center gap-1",children:[e.jsx(I,{className:"h-3.5 w-3.5"}),typeof s.review.findings=="number"?s.review.findings:((L=s.review.dimensions)==null?void 0:L.reduce((c,N)=>{var P;return c+(((P=N.findings)==null?void 0:P.length)||0)},0))||0," ",t({id:"sessions.card.findings"})]})]}):e.jsxs(e.Fragment,{children:[e.jsxs("span",{className:"flex items-center gap-1",children:[e.jsx(me,{className:"h-3.5 w-3.5"}),i.total," ",t({id:"sessions.card.tasks"})]}),i.total>0&&e.jsxs("span",{className:"flex items-center gap-1",children:[e.jsx(H,{className:"h-3.5 w-3.5 text-success"}),i.completed," ",t({id:"sessions.card.completed"})]})]}),s.updated_at&&s.updated_at!==s.created_at&&e.jsxs("span",{className:"flex items-center gap-1",children:[e.jsx(xe,{className:"h-3.5 w-3.5"}),t({id:"sessions.card.updated"}),": ",q(s.updated_at)]})]}),s.type!=="review"&&i.total>0&&e.jsxs("div",{className:"flex flex-wrap items-center gap-1.5 mt-2",children:[i.inProgress>0&&e.jsxs(x,{variant:"info",className:"gap-1 px-1.5 py-0 text-[10px]",children:[e.jsx(se,{className:"h-3 w-3"}),i.inProgress," ",t({id:"sessions.taskStatus.inProgress"})]}),i.completed>0&&e.jsxs(x,{variant:"success",className:"gap-1 px-1.5 py-0 text-[10px]",children:[e.jsx(H,{className:"h-3 w-3"}),i.completed," ",t({id:"sessions.taskStatus.completed"})]}),i.failed>0&&e.jsxs(x,{variant:"destructive",className:"gap-1 px-1.5 py-0 text-[10px]",children:[e.jsx(T,{className:"h-3 w-3"}),i.failed," ",t({id:"sessions.taskStatus.failed"})]})]}),s.type==="review"&&p.total>0&&e.jsxs("div",{className:"flex flex-wrap items-center gap-1.5 mt-2",children:[p.critical>0&&e.jsxs(x,{variant:"destructive",className:"gap-1 px-1.5 py-0 text-[10px]",children:[e.jsx(T,{className:"h-3 w-3"}),p.critical," Critical"]}),p.high>0&&e.jsxs(x,{variant:"warning",className:"gap-1 px-1.5 py-0 text-[10px]",children:[e.jsx(T,{className:"h-3 w-3"}),p.high," High"]}),p.medium>0&&e.jsxs(x,{variant:"info",className:"gap-1 px-1.5 py-0 text-[10px]",children:[e.jsx(A,{className:"h-3 w-3"}),p.medium," Medium"]}),p.low>0&&e.jsxs(x,{variant:"secondary",className:"gap-1 px-1.5 py-0 text-[10px]",children:[e.jsx(I,{className:"h-3 w-3"}),p.low," Low"]})]}),s.type!=="review"&&i.total>0&&!C&&e.jsxs("div",{className:"mt-3",children:[e.jsxs("div",{className:"flex items-center justify-between text-xs mb-1",children:[e.jsx("span",{className:"text-muted-foreground",children:t({id:"sessions.card.progress"})}),e.jsxs("span",{className:"text-card-foreground font-medium",children:[i.completed,"/",i.total," (",i.percentage,"%)"]})]}),e.jsx("div",{className:"h-1.5 w-full rounded-full bg-muted overflow-hidden",children:e.jsx("div",{className:b("h-full transition-all duration-300",i.percentage===100?"bg-success":"bg-primary"),style:{width:`${i.percentage}%`}})})]}),s.description&&s.description!==s.title&&e.jsx("p",{className:"mt-2 text-xs text-muted-foreground line-clamp-2 italic",children:s.description})]})})}function $e({className:s}){return e.jsx(U,{className:b("animate-pulse",s),children:e.jsxs(X,{className:"p-4",children:[e.jsxs("div",{className:"flex items-start justify-between",children:[e.jsxs("div",{className:"flex-1",children:[e.jsx("div",{className:"h-5 w-32 rounded bg-muted"}),e.jsx("div",{className:"mt-1 h-3 w-24 rounded bg-muted"})]}),e.jsx("div",{className:"h-5 w-16 rounded-full bg-muted"})]}),e.jsxs("div",{className:"mt-3 flex gap-4",children:[e.jsx("div",{className:"h-4 w-20 rounded bg-muted"}),e.jsx("div",{className:"h-4 w-16 rounded bg-muted"})]}),e.jsxs("div",{className:"mt-2 flex gap-1.5",children:[e.jsx("div",{className:"h-5 w-16 rounded-full bg-muted"}),e.jsx("div",{className:"h-5 w-20 rounded-full bg-muted"}),e.jsx("div",{className:"h-5 w-18 rounded-full bg-muted"})]}),e.jsx("div",{className:"mt-3",children:e.jsx("div",{className:"h-1.5 w-full rounded-full bg-muted"})})]})})}const G={planning:"sessions.status.planning",in_progress:"sessions.status.inProgress",completed:"sessions.status.completed",archived:"sessions.status.archived",paused:"sessions.status.paused"};function Xe(){const{formatMessage:s}=J(),d=he(),[o,h]=y.useState("active"),[n,g]=y.useState(""),[l,r]=y.useState([]),[t,u]=y.useState(!1),[D,j]=y.useState(null),v=Q(pe),i=Q(a=>a.toggleImmersiveMode),p=y.useMemo(()=>({location:o,search:n,status:l.length>0?l:void 0}),[o,n,l]),{filteredSessions:C,isLoading:z,isFetching:M,error:w,refetch:k}=ue({filter:p}),{archiveSession:_,isArchiving:L}=ge(),{deleteSession:c,isDeleting:N}=fe(),P=L||N,$=(a,m)=>{d(m==="review"?`/sessions/${a}/review`:`/sessions/${a}`)},ae=async a=>{try{await _(a)}catch(m){console.error("Failed to archive session:",m)}},te=a=>{j(a),u(!0)},ie=async()=>{if(D)try{await c(D),u(!1),j(null)}catch(a){console.error("Failed to delete session:",a)}},O=()=>{g("")},R=a=>{r(m=>m.includes(a)?m.filter(ne=>ne!==a):[...m,a])},B=()=>{r([]),g("")},S=l.length>0||n.length>0;return e.jsxs("div",{className:b("space-y-6",v&&"h-screen overflow-hidden"),children:[e.jsxs("div",{className:"flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"text-2xl font-semibold text-foreground",children:s({id:"sessions.title"})}),e.jsx("p",{className:"text-sm text-muted-foreground mt-1",children:s({id:"sessions.description"})})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs(f,{variant:"outline",size:"sm",onClick:()=>k(),disabled:M,children:[e.jsx(se,{className:b("h-4 w-4 mr-2",M&&"animate-spin")}),s({id:"common.actions.refresh"})]}),e.jsx("button",{onClick:i,className:b("p-2 rounded-md transition-colors",v?"bg-primary/10 text-primary":"text-muted-foreground hover:text-foreground hover:bg-muted"),title:s(v?{id:"common.exitFullscreen",defaultMessage:"Exit Fullscreen"}:{id:"common.fullscreen",defaultMessage:"Fullscreen"}),children:v?e.jsx(Pe,{className:"w-4 h-4"}):e.jsx(Te,{className:"w-4 h-4"})})]})]}),w&&e.jsxs("div",{className:"flex items-center gap-2 p-4 rounded-lg bg-destructive/10 border border-destructive/30 text-destructive",children:[e.jsx(T,{className:"h-5 w-5 flex-shrink-0"}),e.jsxs("div",{className:"flex-1",children:[e.jsx("p",{className:"text-sm font-medium",children:s({id:"common.errors.loadFailed"})}),e.jsx("p",{className:"text-xs mt-0.5",children:w.message})]}),e.jsx(f,{variant:"outline",size:"sm",onClick:()=>k(),children:s({id:"home.errors.retry"})})]}),e.jsxs("div",{className:"flex flex-col gap-4 sm:flex-row sm:items-center",children:[e.jsx(Le,{value:o,onValueChange:a=>h(a),tabs:[{value:"active",label:s({id:"sessions.filters.active"})},{value:"archived",label:s({id:"sessions.filters.archived"})},{value:"all",label:s({id:"sessions.filters.all"})}]}),e.jsxs("div",{className:"flex-1 max-w-sm relative",children:[e.jsx(A,{className:"absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground"}),e.jsx(je,{placeholder:s({id:"sessions.searchPlaceholder"}),value:n,onChange:a=>g(a.target.value),className:"pl-9 pr-9"}),n&&e.jsx("button",{onClick:O,className:"absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground",children:e.jsx(K,{className:"h-4 w-4"})})]}),e.jsxs(W,{children:[e.jsx(Y,{asChild:!0,children:e.jsxs(f,{variant:"outline",size:"sm",className:"gap-2",children:[e.jsx(Ae,{className:"h-4 w-4"}),s({id:"common.actions.filter"}),l.length>0&&e.jsx(x,{variant:"secondary",className:"ml-1 h-5 min-w-5 px-1",children:l.length})]})}),e.jsxs(ee,{align:"end",className:"w-48",children:[e.jsx(ve,{children:s({id:"common.status.label"})}),e.jsx(E,{}),["planning","in_progress","completed","paused"].map(a=>e.jsxs(F,{onClick:()=>R(a),className:"justify-between",children:[e.jsx("span",{children:s({id:G[a]})}),l.includes(a)&&e.jsx("span",{className:"text-primary",children:"✓"})]},a)),S&&e.jsxs(e.Fragment,{children:[e.jsx(E,{}),e.jsx(F,{onClick:B,className:"text-destructive",children:s({id:"common.actions.clearFilters"})})]})]})]})]}),S&&e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsxs("span",{className:"text-sm text-muted-foreground",children:[s({id:"common.actions.filters"}),":"]}),l.map(a=>e.jsxs(x,{variant:"secondary",className:"cursor-pointer",onClick:()=>R(a),children:[s({id:G[a]}),e.jsx(K,{className:"ml-1 h-3 w-3"})]},a)),n&&e.jsxs(x,{variant:"secondary",className:"cursor-pointer",onClick:O,children:[s({id:"common.actions.search"}),": ",n,e.jsx(K,{className:"ml-1 h-3 w-3"})]}),e.jsx(f,{variant:"ghost",size:"sm",onClick:B,className:"h-6 text-xs",children:s({id:"common.actions.clearAll"})})]}),z?e.jsx("div",{className:"grid gap-4 grid-cols-1 md:grid-cols-2 lg:grid-cols-3",children:Array.from({length:9}).map((a,m)=>e.jsx($e,{},m))}):C.length===0?e.jsxs("div",{className:"flex flex-col items-center justify-center py-16 px-4 border border-dashed border-border rounded-lg",children:[e.jsx(Ne,{className:"h-12 w-12 text-muted-foreground mb-4"}),e.jsx("h3",{className:"text-lg font-medium text-foreground mb-1",children:s(S?{id:"sessions.emptyState.title"}:{id:"sessions.emptyState.title"})}),e.jsx("p",{className:"text-sm text-muted-foreground text-center max-w-sm mb-4",children:s(S?{id:"sessions.emptyState.message"}:{id:"sessions.emptyState.createFirst"})}),S&&e.jsx(f,{variant:"outline",onClick:B,children:s({id:"common.actions.clearFilters"})})]}):e.jsx("div",{className:"grid gap-4 grid-cols-1 md:grid-cols-2 lg:grid-cols-3",children:C.map(a=>e.jsx(Ke,{session:a,onClick:m=>$(m,a.type),onView:m=>$(m,a.type),onArchive:ae,onDelete:te,actionsDisabled:P},a.session_id))}),e.jsx(we,{open:t,onOpenChange:u,children:e.jsxs(ye,{children:[e.jsxs(be,{children:[e.jsx(Ce,{children:s({id:"common.dialog.deleteSession"})}),e.jsx(ke,{children:s({id:"common.dialog.deleteConfirm"})})]}),e.jsxs(Se,{children:[e.jsx(f,{variant:"outline",onClick:()=>{u(!1),j(null)},children:s({id:"common.actions.cancel"})}),e.jsx(f,{variant:"destructive",onClick:ie,disabled:N,children:s(N?{id:"common.status.deleting"}:{id:"common.actions.delete"})})]})]})})]})}export{Xe as SessionsPage,Xe as default};
|
|
2
|
+
//# sourceMappingURL=SessionsPage-CQIB4E8m.js.map
|
package/ccw/frontend/dist/assets/{SessionsPage-BFy74ye3.js.map → SessionsPage-CQIB4E8m.js.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SessionsPage-BFy74ye3.js","sources":["../../src/components/shared/SessionCard.tsx","../../src/pages/SessionsPage.tsx"],"sourcesContent":["// ========================================\r\n// SessionCard Component\r\n// ========================================\r\n// Session card with status badge and action menu\r\n\r\nimport * as React from 'react';\r\nimport { useIntl } from 'react-intl';\r\nimport { cn } from '@/lib/utils';\r\nimport { Card, CardContent } from '@/components/ui/Card';\r\nimport { Badge } from '@/components/ui/Badge';\r\nimport { Button } from '@/components/ui/Button';\r\nimport {\r\n DropdownMenu,\r\n DropdownMenuTrigger,\r\n DropdownMenuContent,\r\n DropdownMenuItem,\r\n DropdownMenuSeparator,\r\n} from '@/components/ui/Dropdown';\r\nimport {\r\n Calendar,\r\n ListChecks,\r\n MoreVertical,\r\n Eye,\r\n Archive,\r\n Trash2,\r\n Clock,\r\n CheckCircle2,\r\n AlertCircle,\r\n RefreshCw,\r\n FileText,\r\n Search,\r\n TestTube,\r\n File,\r\n Settings,\r\n Zap,\r\n} from 'lucide-react';\r\nimport type { SessionMetadata } from '@/types/store';\r\n\r\nexport interface SessionCardProps {\r\n /** Session data */\r\n session: SessionMetadata;\r\n /** Called when view action is triggered */\r\n onView?: (sessionId: string) => void;\r\n /** Called when archive action is triggered */\r\n onArchive?: (sessionId: string) => void;\r\n /** Called when delete action is triggered */\r\n onDelete?: (sessionId: string) => void;\r\n /** Called when card is clicked */\r\n onClick?: (sessionId: string) => void;\r\n /** Optional className */\r\n className?: string;\r\n /** Show actions dropdown */\r\n showActions?: boolean;\r\n /** Disabled state for actions */\r\n actionsDisabled?: boolean;\r\n}\r\n\r\n// Status variant configuration (without labels for i18n)\r\nconst statusVariantConfig: Record<\r\n SessionMetadata['status'],\r\n { variant: 'default' | 'secondary' | 'destructive' | 'success' | 'warning' | 'info' }\r\n> = {\r\n planning: { variant: 'info' },\r\n in_progress: { variant: 'warning' },\r\n completed: { variant: 'success' },\r\n archived: { variant: 'secondary' },\r\n paused: { variant: 'default' },\r\n};\r\n\r\n// Status label keys for i18n\r\nconst statusLabelKeys: Record<SessionMetadata['status'], string> = {\r\n planning: 'sessions.status.planning',\r\n in_progress: 'sessions.status.inProgress',\r\n completed: 'sessions.status.completed',\r\n archived: 'sessions.status.archived',\r\n paused: 'sessions.status.paused',\r\n};\r\n\r\n// Type variant configuration for session type badges (unique colors for each type)\r\nconst typeVariantConfig: Record<\r\n NonNullable<SessionMetadata['type']>,\r\n { variant: 'default' | 'secondary' | 'destructive' | 'success' | 'warning' | 'info' | 'review'; icon: React.ElementType }\r\n> = {\r\n review: { variant: 'review', icon: Search }, // Purple\r\n 'tdd': { variant: 'success', icon: TestTube }, // Green\r\n test: { variant: 'info', icon: FileText }, // Blue\r\n docs: { variant: 'warning', icon: File }, // Orange/Yellow\r\n workflow: { variant: 'default', icon: Settings }, // Primary (blue-violet)\r\n 'lite-plan': { variant: 'secondary', icon: FileText }, // Gray/Neutral\r\n 'lite-fix': { variant: 'destructive', icon: Zap }, // Red\r\n};\r\n\r\n// Type label keys for i18n\r\nconst typeLabelKeys: Record<NonNullable<SessionMetadata['type']>, string> = {\r\n review: 'sessions.type.review',\r\n tdd: 'sessions.type.tdd',\r\n test: 'sessions.type.test',\r\n docs: 'sessions.type.docs',\r\n workflow: 'sessions.type.workflow',\r\n 'lite-plan': 'sessions.type.lite-plan',\r\n 'lite-fix': 'sessions.type.lite-fix',\r\n};\r\n\r\n/**\r\n * Format date to localized string\r\n */\r\nfunction formatDate(dateString: string | undefined): string {\r\n if (!dateString) return 'Unknown';\r\n\r\n try {\r\n const date = new Date(dateString);\r\n return date.toLocaleDateString(undefined, {\r\n year: 'numeric',\r\n month: 'short',\r\n day: 'numeric',\r\n });\r\n } catch {\r\n return 'Invalid date';\r\n }\r\n}\r\n\r\n/**\r\n * Task status breakdown returned by calculateProgress\r\n */\r\ninterface TaskStatusBreakdown {\r\n total: number;\r\n completed: number;\r\n failed: number;\r\n pending: number;\r\n inProgress: number;\r\n percentage: number;\r\n}\r\n\r\n/**\r\n * Calculate progress and status breakdown from tasks\r\n */\r\nfunction calculateProgress(tasks: SessionMetadata['tasks']): TaskStatusBreakdown {\r\n if (!tasks || tasks.length === 0) {\r\n return { total: 0, completed: 0, failed: 0, pending: 0, inProgress: 0, percentage: 0 };\r\n }\r\n\r\n const total = tasks.length;\r\n const completed = tasks.filter((t) => t.status === 'completed').length;\r\n const failed = tasks.filter((t) => t.status === 'blocked' || t.status === 'skipped').length;\r\n const inProgress = tasks.filter((t) => t.status === 'in_progress').length;\r\n const pending = tasks.filter((t) => t.status === 'pending').length;\r\n const percentage = Math.round((completed / total) * 100);\r\n\r\n return { total, completed, failed, pending, inProgress, percentage };\r\n}\r\n\r\n/**\r\n * Severity breakdown for review sessions\r\n */\r\ninterface SeverityBreakdown {\r\n total: number;\r\n critical: number;\r\n high: number;\r\n medium: number;\r\n low: number;\r\n}\r\n\r\n/**\r\n * Calculate severity breakdown from review dimensions\r\n */\r\nfunction calculateSeverityBreakdown(review: SessionMetadata['review']): SeverityBreakdown {\r\n if (!review?.dimensions || review.dimensions.length === 0) {\r\n return { total: 0, critical: 0, high: 0, medium: 0, low: 0 };\r\n }\r\n\r\n let critical = 0, high = 0, medium = 0, low = 0;\r\n\r\n review.dimensions.forEach(dim => {\r\n if (dim.findings) {\r\n dim.findings.forEach(finding => {\r\n const severity = finding.severity?.toLowerCase();\r\n if (severity === 'critical') critical++;\r\n else if (severity === 'high') high++;\r\n else if (severity === 'medium') medium++;\r\n else if (severity === 'low') low++;\r\n });\r\n }\r\n });\r\n\r\n const total = critical + high + medium + low;\r\n return { total, critical, high, medium, low };\r\n}\r\n\r\n/**\r\n * SessionCard component for displaying session information\r\n *\r\n * @example\r\n * ```tsx\r\n * <SessionCard\r\n * session={session}\r\n * onView={(id) => navigate(`/sessions/${id}`)}\r\n * onArchive={(id) => archiveSession(id)}\r\n * onDelete={(id) => deleteSession(id)}\r\n * />\r\n * ```\r\n */\r\nexport function SessionCard({\r\n session,\r\n onView,\r\n onArchive,\r\n onDelete,\r\n onClick,\r\n className,\r\n showActions = true,\r\n actionsDisabled = false,\r\n}: SessionCardProps) {\r\n const { formatMessage } = useIntl();\r\n\r\n const { variant: statusVariant } = statusVariantConfig[session.status] || {\r\n variant: 'default' as const,\r\n };\r\n const statusLabel = statusLabelKeys[session.status]\r\n ? formatMessage({ id: statusLabelKeys[session.status] })\r\n : formatMessage({ id: 'common.status.unknown' });\r\n\r\n // Type badge configuration (graceful degradation when type is undefined)\r\n const typeConfig = session.type ? typeVariantConfig[session.type] : null;\r\n const typeLabel = session.type && typeLabelKeys[session.type]\r\n ? formatMessage({ id: typeLabelKeys[session.type] })\r\n : null;\r\n\r\n const progress = calculateProgress(session.tasks);\r\n const severity = calculateSeverityBreakdown(session.review);\r\n const isPlanning = session.status === 'planning';\r\n const isArchived = session.status === 'archived' || session.location === 'archived';\r\n\r\n const handleCardClick = (e: React.MouseEvent) => {\r\n // Don't trigger if clicking on dropdown\r\n if ((e.target as HTMLElement).closest('[data-radix-popper-content-wrapper]')) {\r\n return;\r\n }\r\n onClick?.(session.session_id);\r\n };\r\n\r\n const handleAction = (\r\n e: React.MouseEvent,\r\n action: 'view' | 'archive' | 'delete'\r\n ) => {\r\n e.stopPropagation();\r\n switch (action) {\r\n case 'view':\r\n onView?.(session.session_id);\r\n break;\r\n case 'archive':\r\n onArchive?.(session.session_id);\r\n break;\r\n case 'delete':\r\n onDelete?.(session.session_id);\r\n break;\r\n }\r\n };\r\n\r\n return (\r\n <Card\r\n className={cn(\r\n 'group cursor-pointer transition-all duration-200 hover:shadow-md hover:border-primary/30',\r\n isPlanning && 'border-info/30 bg-info/5',\r\n className\r\n )}\r\n onClick={handleCardClick}\r\n >\r\n <CardContent className=\"p-4\">\r\n {/* Header - Type badge + Session ID as title */}\r\n <div className=\"flex items-start justify-between gap-2 mb-2\">\r\n <div className=\"flex-1 min-w-0\">\r\n <div className=\"flex items-center gap-2 mb-1\">\r\n {/* Type badge BEFORE title */}\r\n {typeConfig && typeLabel && (\r\n <Badge variant={typeConfig.variant} className=\"gap-1 flex-shrink-0\">\r\n <typeConfig.icon className=\"h-3 w-3\" />\r\n {typeLabel}\r\n </Badge>\r\n )}\r\n <h3 className=\"font-bold text-card-foreground text-sm tracking-wide uppercase truncate\">\r\n {session.session_id}\r\n </h3>\r\n </div>\r\n </div>\r\n <div className=\"flex items-center gap-2 flex-shrink-0\">\r\n <Badge variant={statusVariant}>{statusLabel}</Badge>\r\n {showActions && (\r\n <DropdownMenu>\r\n <DropdownMenuTrigger asChild>\r\n <Button\r\n variant=\"ghost\"\r\n size=\"icon\"\r\n className=\"h-8 w-8 opacity-0 group-hover:opacity-100 transition-opacity\"\r\n onClick={(e) => e.stopPropagation()}\r\n disabled={actionsDisabled}\r\n >\r\n <MoreVertical className=\"h-4 w-4\" />\r\n <span className=\"sr-only\">{formatMessage({ id: 'common.aria.actions' })}</span>\r\n </Button>\r\n </DropdownMenuTrigger>\r\n <DropdownMenuContent align=\"end\">\r\n <DropdownMenuItem onClick={(e) => handleAction(e, 'view')}>\r\n <Eye className=\"mr-2 h-4 w-4\" />\r\n {formatMessage({ id: 'sessions.actions.viewDetails' })}\r\n </DropdownMenuItem>\r\n {!isArchived && (\r\n <>\r\n <DropdownMenuSeparator />\r\n <DropdownMenuItem onClick={(e) => handleAction(e, 'archive')}>\r\n <Archive className=\"mr-2 h-4 w-4\" />\r\n {formatMessage({ id: 'sessions.actions.archive' })}\r\n </DropdownMenuItem>\r\n </>\r\n )}\r\n <DropdownMenuSeparator />\r\n <DropdownMenuItem\r\n onClick={(e) => handleAction(e, 'delete')}\r\n className=\"text-destructive focus:text-destructive\"\r\n >\r\n <Trash2 className=\"mr-2 h-4 w-4\" />\r\n {formatMessage({ id: 'sessions.actions.delete' })}\r\n </DropdownMenuItem>\r\n </DropdownMenuContent>\r\n </DropdownMenu>\r\n )}\r\n </div>\r\n </div>\r\n\r\n {/* Title as description */}\r\n {session.title && (\r\n <p className=\"text-sm text-foreground line-clamp-2 mb-3\">\r\n {session.title}\r\n </p>\r\n )}\r\n\r\n {/* Meta info - different based on session type */}\r\n <div className=\"flex flex-wrap items-center gap-x-4 gap-y-2 text-xs text-muted-foreground\">\r\n <span className=\"flex items-center gap-1\">\r\n <Calendar className=\"h-3.5 w-3.5\" />\r\n {formatDate(session.created_at)}\r\n </span>\r\n\r\n {/* Review sessions: Show findings and dimensions */}\r\n {session.type === 'review' ? (\r\n <>\r\n {session.review?.dimensions && session.review.dimensions.length > 0 && (\r\n <span className=\"flex items-center gap-1\">\r\n <Search className=\"h-3.5 w-3.5\" />\r\n {session.review.dimensions.length} {formatMessage({ id: 'sessions.card.dimensions' })}\r\n </span>\r\n )}\r\n {session.review?.findings !== undefined && (\r\n <span className=\"flex items-center gap-1\">\r\n <FileText className=\"h-3.5 w-3.5\" />\r\n {typeof session.review.findings === 'number'\r\n ? session.review.findings\r\n : session.review.dimensions?.reduce((sum, dim) => sum + (dim.findings?.length || 0), 0) || 0\r\n } {formatMessage({ id: 'sessions.card.findings' })}\r\n </span>\r\n )}\r\n </>\r\n ) : (\r\n <>\r\n {/* Workflow/other sessions: Show tasks */}\r\n <span className=\"flex items-center gap-1\">\r\n <ListChecks className=\"h-3.5 w-3.5\" />\r\n {progress.total} {formatMessage({ id: 'sessions.card.tasks' })}\r\n </span>\r\n {progress.total > 0 && (\r\n <span className=\"flex items-center gap-1\">\r\n <CheckCircle2 className=\"h-3.5 w-3.5 text-success\" />\r\n {progress.completed} {formatMessage({ id: 'sessions.card.completed' })}\r\n </span>\r\n )}\r\n </>\r\n )}\r\n {session.updated_at && session.updated_at !== session.created_at && (\r\n <span className=\"flex items-center gap-1\">\r\n <Clock className=\"h-3.5 w-3.5\" />\r\n {formatMessage({ id: 'sessions.card.updated' })}: {formatDate(session.updated_at)}\r\n </span>\r\n )}\r\n </div>\r\n\r\n {/* Task status badges - only for non-review sessions */}\r\n {session.type !== 'review' && progress.total > 0 && (\r\n <div className=\"flex flex-wrap items-center gap-1.5 mt-2\">\r\n {progress.inProgress > 0 && (\r\n <Badge variant=\"info\" className=\"gap-1 px-1.5 py-0 text-[10px]\">\r\n <RefreshCw className=\"h-3 w-3\" />\r\n {progress.inProgress} {formatMessage({ id: 'sessions.taskStatus.inProgress' })}\r\n </Badge>\r\n )}\r\n {progress.completed > 0 && (\r\n <Badge variant=\"success\" className=\"gap-1 px-1.5 py-0 text-[10px]\">\r\n <CheckCircle2 className=\"h-3 w-3\" />\r\n {progress.completed} {formatMessage({ id: 'sessions.taskStatus.completed' })}\r\n </Badge>\r\n )}\r\n {progress.failed > 0 && (\r\n <Badge variant=\"destructive\" className=\"gap-1 px-1.5 py-0 text-[10px]\">\r\n <AlertCircle className=\"h-3 w-3\" />\r\n {progress.failed} {formatMessage({ id: 'sessions.taskStatus.failed' })}\r\n </Badge>\r\n )}\r\n </div>\r\n )}\r\n\r\n {/* Severity badges - only for review sessions */}\r\n {session.type === 'review' && severity.total > 0 && (\r\n <div className=\"flex flex-wrap items-center gap-1.5 mt-2\">\r\n {severity.critical > 0 && (\r\n <Badge variant=\"destructive\" className=\"gap-1 px-1.5 py-0 text-[10px]\">\r\n <AlertCircle className=\"h-3 w-3\" />\r\n {severity.critical} Critical\r\n </Badge>\r\n )}\r\n {severity.high > 0 && (\r\n <Badge variant=\"warning\" className=\"gap-1 px-1.5 py-0 text-[10px]\">\r\n <AlertCircle className=\"h-3 w-3\" />\r\n {severity.high} High\r\n </Badge>\r\n )}\r\n {severity.medium > 0 && (\r\n <Badge variant=\"info\" className=\"gap-1 px-1.5 py-0 text-[10px]\">\r\n <Search className=\"h-3 w-3\" />\r\n {severity.medium} Medium\r\n </Badge>\r\n )}\r\n {severity.low > 0 && (\r\n <Badge variant=\"secondary\" className=\"gap-1 px-1.5 py-0 text-[10px]\">\r\n <FileText className=\"h-3 w-3\" />\r\n {severity.low} Low\r\n </Badge>\r\n )}\r\n </div>\r\n )}\r\n\r\n {/* Progress bar (only show for non-review sessions with tasks) */}\r\n {session.type !== 'review' && progress.total > 0 && !isPlanning && (\r\n <div className=\"mt-3\">\r\n <div className=\"flex items-center justify-between text-xs mb-1\">\r\n <span className=\"text-muted-foreground\">{formatMessage({ id: 'sessions.card.progress' })}</span>\r\n <span className=\"text-card-foreground font-medium\">\r\n {progress.completed}/{progress.total} ({progress.percentage}%)\r\n </span>\r\n </div>\r\n <div className=\"h-1.5 w-full rounded-full bg-muted overflow-hidden\">\r\n <div\r\n className={cn(\r\n \"h-full transition-all duration-300\",\r\n progress.percentage === 100 ? \"bg-success\" : \"bg-primary\"\r\n )}\r\n style={{ width: `${progress.percentage}%` }}\r\n />\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Description (if exists and different from title) */}\r\n {session.description && session.description !== session.title && (\r\n <p className=\"mt-2 text-xs text-muted-foreground line-clamp-2 italic\">\r\n {session.description}\r\n </p>\r\n )}\r\n </CardContent>\r\n </Card>\r\n );\r\n}\r\n\r\n/**\r\n * Skeleton loader for SessionCard\r\n */\r\nexport function SessionCardSkeleton({ className }: { className?: string }) {\r\n return (\r\n <Card className={cn('animate-pulse', className)}>\r\n <CardContent className=\"p-4\">\r\n <div className=\"flex items-start justify-between\">\r\n <div className=\"flex-1\">\r\n <div className=\"h-5 w-32 rounded bg-muted\" />\r\n <div className=\"mt-1 h-3 w-24 rounded bg-muted\" />\r\n </div>\r\n <div className=\"h-5 w-16 rounded-full bg-muted\" />\r\n </div>\r\n <div className=\"mt-3 flex gap-4\">\r\n <div className=\"h-4 w-20 rounded bg-muted\" />\r\n <div className=\"h-4 w-16 rounded bg-muted\" />\r\n </div>\r\n {/* Status badge skeletons */}\r\n <div className=\"mt-2 flex gap-1.5\">\r\n <div className=\"h-5 w-16 rounded-full bg-muted\" />\r\n <div className=\"h-5 w-20 rounded-full bg-muted\" />\r\n <div className=\"h-5 w-18 rounded-full bg-muted\" />\r\n </div>\r\n <div className=\"mt-3\">\r\n <div className=\"h-1.5 w-full rounded-full bg-muted\" />\r\n </div>\r\n </CardContent>\r\n </Card>\r\n );\r\n}\r\n","// ========================================\n// SessionsPage Component\n// ========================================\n// Sessions list page with CRUD operations\n\nimport * as React from 'react';\nimport { useNavigate } from 'react-router-dom';\nimport { useIntl } from 'react-intl';\nimport {\n RefreshCw,\n Search,\n Filter,\n AlertCircle,\n FolderKanban,\n X,\n Maximize2,\n Minimize2,\n} from 'lucide-react';\nimport {\n useSessions,\n useArchiveSession,\n useDeleteSession,\n type SessionsFilter,\n} from '@/hooks/useSessions';\nimport { SessionCard, SessionCardSkeleton } from '@/components/shared/SessionCard';\nimport { Button } from '@/components/ui/Button';\nimport { Input } from '@/components/ui/Input';\nimport { Badge } from '@/components/ui/Badge';\nimport {\n Dialog,\n DialogContent,\n DialogHeader,\n DialogTitle,\n DialogDescription,\n DialogFooter,\n} from '@/components/ui/Dialog';\nimport {\n DropdownMenu,\n DropdownMenuTrigger,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuSeparator,\n DropdownMenuLabel,\n} from '@/components/ui/Dropdown';\nimport { TabsNavigation } from '@/components/ui/TabsNavigation';\nimport { cn } from '@/lib/utils';\nimport type { SessionMetadata } from '@/types/store';\nimport { useAppStore, selectIsImmersiveMode } from '@/stores/appStore';\n\ntype LocationFilter = 'all' | 'active' | 'archived';\n\n// Status label keys for i18n (maps snake_case status to camelCase translation keys)\nconst statusLabelKeys: Record<SessionMetadata['status'], string> = {\n planning: 'sessions.status.planning',\n in_progress: 'sessions.status.inProgress',\n completed: 'sessions.status.completed',\n archived: 'sessions.status.archived',\n paused: 'sessions.status.paused',\n};\n\n/**\n * SessionsPage component - Sessions list with CRUD operations\n */\nexport function SessionsPage() {\n const { formatMessage } = useIntl();\n const navigate = useNavigate();\n\n // Filter state\n const [locationFilter, setLocationFilter] = React.useState<LocationFilter>('active');\n const [searchQuery, setSearchQuery] = React.useState('');\n const [statusFilter, setStatusFilter] = React.useState<SessionMetadata['status'][]>([]);\n\n // Dialog state\n const [deleteDialogOpen, setDeleteDialogOpen] = React.useState(false);\n const [sessionToDelete, setSessionToDelete] = React.useState<string | null>(null);\n\n // Immersive mode (fullscreen)\n const isImmersiveMode = useAppStore(selectIsImmersiveMode);\n const toggleImmersiveMode = useAppStore((s) => s.toggleImmersiveMode);\n\n // Build filter object\n const filter: SessionsFilter = React.useMemo(\n () => ({\n location: locationFilter,\n search: searchQuery,\n status: statusFilter.length > 0 ? statusFilter : undefined,\n }),\n [locationFilter, searchQuery, statusFilter]\n );\n\n // Fetch sessions with filter\n const {\n filteredSessions,\n isLoading,\n isFetching,\n error,\n refetch,\n } = useSessions({ filter });\n\n // Mutations\n const { archiveSession, isArchiving } = useArchiveSession();\n const { deleteSession, isDeleting } = useDeleteSession();\n\n const isMutating = isArchiving || isDeleting;\n\n // Handlers\n const handleSessionClick = (sessionId: string, sessionType?: SessionMetadata['type']) => {\n // Route review sessions to the dedicated review page\n if (sessionType === 'review') {\n navigate(`/sessions/${sessionId}/review`);\n } else {\n navigate(`/sessions/${sessionId}`);\n }\n };\n\n const handleArchive = async (sessionId: string) => {\n try {\n await archiveSession(sessionId);\n } catch (err) {\n console.error('Failed to archive session:', err);\n }\n };\n\n const handleDeleteClick = (sessionId: string) => {\n setSessionToDelete(sessionId);\n setDeleteDialogOpen(true);\n };\n\n const handleConfirmDelete = async () => {\n if (!sessionToDelete) return;\n\n try {\n await deleteSession(sessionToDelete);\n setDeleteDialogOpen(false);\n setSessionToDelete(null);\n } catch (err) {\n console.error('Failed to delete session:', err);\n }\n };\n\n const handleClearSearch = () => {\n setSearchQuery('');\n };\n\n const toggleStatusFilter = (status: SessionMetadata['status']) => {\n setStatusFilter((prev) =>\n prev.includes(status) ? prev.filter((s) => s !== status) : [...prev, status]\n );\n };\n\n const clearFilters = () => {\n setStatusFilter([]);\n setSearchQuery('');\n };\n\n const hasActiveFilters = statusFilter.length > 0 || searchQuery.length > 0;\n\n return (\n <div className={cn(\"space-y-6\", isImmersiveMode && \"h-screen overflow-hidden\")}>\n {/* Header */}\n <div className=\"flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between\">\n <div>\n <h1 className=\"text-2xl font-semibold text-foreground\">{formatMessage({ id: 'sessions.title' })}</h1>\n <p className=\"text-sm text-muted-foreground mt-1\">\n {formatMessage({ id: 'sessions.description' })}\n </p>\n </div>\n <div className=\"flex items-center gap-2\">\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => refetch()}\n disabled={isFetching}\n >\n <RefreshCw className={cn('h-4 w-4 mr-2', isFetching && 'animate-spin')} />\n {formatMessage({ id: 'common.actions.refresh' })}\n </Button>\n <button\n onClick={toggleImmersiveMode}\n className={cn(\n 'p-2 rounded-md transition-colors',\n isImmersiveMode\n ? 'bg-primary/10 text-primary'\n : 'text-muted-foreground hover:text-foreground hover:bg-muted'\n )}\n title={isImmersiveMode ? formatMessage({ id: 'common.exitFullscreen', defaultMessage: 'Exit Fullscreen' }) : formatMessage({ id: 'common.fullscreen', defaultMessage: 'Fullscreen' })}\n >\n {isImmersiveMode ? <Minimize2 className=\"w-4 h-4\" /> : <Maximize2 className=\"w-4 h-4\" />}\n </button>\n </div>\n </div>\n\n {/* Error alert */}\n {error && (\n <div className=\"flex items-center gap-2 p-4 rounded-lg bg-destructive/10 border border-destructive/30 text-destructive\">\n <AlertCircle className=\"h-5 w-5 flex-shrink-0\" />\n <div className=\"flex-1\">\n <p className=\"text-sm font-medium\">{formatMessage({ id: 'common.errors.loadFailed' })}</p>\n <p className=\"text-xs mt-0.5\">{error.message}</p>\n </div>\n <Button variant=\"outline\" size=\"sm\" onClick={() => refetch()}>\n {formatMessage({ id: 'home.errors.retry' })}\n </Button>\n </div>\n )}\n\n {/* Filters */}\n <div className=\"flex flex-col gap-4 sm:flex-row sm:items-center\">\n {/* Location tabs */}\n <TabsNavigation\n value={locationFilter}\n onValueChange={(v) => setLocationFilter(v as LocationFilter)}\n tabs={[\n { value: 'active', label: formatMessage({ id: 'sessions.filters.active' }) },\n { value: 'archived', label: formatMessage({ id: 'sessions.filters.archived' }) },\n { value: 'all', label: formatMessage({ id: 'sessions.filters.all' }) },\n ]}\n />\n\n {/* Search input */}\n <div className=\"flex-1 max-w-sm relative\">\n <Search className=\"absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground\" />\n <Input\n placeholder={formatMessage({ id: 'sessions.searchPlaceholder' })}\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n className=\"pl-9 pr-9\"\n />\n {searchQuery && (\n <button\n onClick={handleClearSearch}\n className=\"absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground\"\n >\n <X className=\"h-4 w-4\" />\n </button>\n )}\n </div>\n\n {/* Status filter dropdown */}\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button variant=\"outline\" size=\"sm\" className=\"gap-2\">\n <Filter className=\"h-4 w-4\" />\n {formatMessage({ id: 'common.actions.filter' })}\n {statusFilter.length > 0 && (\n <Badge variant=\"secondary\" className=\"ml-1 h-5 min-w-5 px-1\">\n {statusFilter.length}\n </Badge>\n )}\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\" className=\"w-48\">\n <DropdownMenuLabel>{formatMessage({ id: 'common.status.label' })}</DropdownMenuLabel>\n <DropdownMenuSeparator />\n {(['planning', 'in_progress', 'completed', 'paused'] as const).map((status) => (\n <DropdownMenuItem\n key={status}\n onClick={() => toggleStatusFilter(status)}\n className=\"justify-between\"\n >\n <span>{formatMessage({ id: statusLabelKeys[status] })}</span>\n {statusFilter.includes(status) && (\n <span className=\"text-primary\">✓</span>\n )}\n </DropdownMenuItem>\n ))}\n {hasActiveFilters && (\n <>\n <DropdownMenuSeparator />\n <DropdownMenuItem onClick={clearFilters} className=\"text-destructive\">\n {formatMessage({ id: 'common.actions.clearFilters' })}\n </DropdownMenuItem>\n </>\n )}\n </DropdownMenuContent>\n </DropdownMenu>\n </div>\n\n {/* Active filters display */}\n {hasActiveFilters && (\n <div className=\"flex flex-wrap items-center gap-2\">\n <span className=\"text-sm text-muted-foreground\">{formatMessage({ id: 'common.actions.filters' })}:</span>\n {statusFilter.map((status) => (\n <Badge\n key={status}\n variant=\"secondary\"\n className=\"cursor-pointer\"\n onClick={() => toggleStatusFilter(status)}\n >\n {formatMessage({ id: statusLabelKeys[status] })}\n <X className=\"ml-1 h-3 w-3\" />\n </Badge>\n ))}\n {searchQuery && (\n <Badge\n variant=\"secondary\"\n className=\"cursor-pointer\"\n onClick={handleClearSearch}\n >\n {formatMessage({ id: 'common.actions.search' })}: {searchQuery}\n <X className=\"ml-1 h-3 w-3\" />\n </Badge>\n )}\n <Button variant=\"ghost\" size=\"sm\" onClick={clearFilters} className=\"h-6 text-xs\">\n {formatMessage({ id: 'common.actions.clearAll' })}\n </Button>\n </div>\n )}\n\n {/* Sessions grid */}\n {isLoading ? (\n <div className=\"grid gap-4 grid-cols-1 md:grid-cols-2 lg:grid-cols-3\">\n {Array.from({ length: 9 }).map((_, i) => (\n <SessionCardSkeleton key={i} />\n ))}\n </div>\n ) : filteredSessions.length === 0 ? (\n <div className=\"flex flex-col items-center justify-center py-16 px-4 border border-dashed border-border rounded-lg\">\n <FolderKanban className=\"h-12 w-12 text-muted-foreground mb-4\" />\n <h3 className=\"text-lg font-medium text-foreground mb-1\">\n {hasActiveFilters ? formatMessage({ id: 'sessions.emptyState.title' }) : formatMessage({ id: 'sessions.emptyState.title' })}\n </h3>\n <p className=\"text-sm text-muted-foreground text-center max-w-sm mb-4\">\n {hasActiveFilters\n ? formatMessage({ id: 'sessions.emptyState.message' })\n : formatMessage({ id: 'sessions.emptyState.createFirst' })}\n </p>\n {hasActiveFilters && (\n <Button variant=\"outline\" onClick={clearFilters}>\n {formatMessage({ id: 'common.actions.clearFilters' })}\n </Button>\n )}\n </div>\n ) : (\n <div className=\"grid gap-4 grid-cols-1 md:grid-cols-2 lg:grid-cols-3\">\n {filteredSessions.map((session) => (\n <SessionCard\n key={session.session_id}\n session={session}\n onClick={(sessionId) => handleSessionClick(sessionId, session.type)}\n onView={(sessionId) => handleSessionClick(sessionId, session.type)}\n onArchive={handleArchive}\n onDelete={handleDeleteClick}\n actionsDisabled={isMutating}\n />\n ))}\n </div>\n )}\n\n {/* Delete Confirmation Dialog */}\n <Dialog open={deleteDialogOpen} onOpenChange={setDeleteDialogOpen}>\n <DialogContent>\n <DialogHeader>\n <DialogTitle>{formatMessage({ id: 'common.dialog.deleteSession' })}</DialogTitle>\n <DialogDescription>\n {formatMessage({ id: 'common.dialog.deleteConfirm' })}\n </DialogDescription>\n </DialogHeader>\n <DialogFooter>\n <Button\n variant=\"outline\"\n onClick={() => {\n setDeleteDialogOpen(false);\n setSessionToDelete(null);\n }}\n >\n {formatMessage({ id: 'common.actions.cancel' })}\n </Button>\n <Button\n variant=\"destructive\"\n onClick={handleConfirmDelete}\n disabled={isDeleting}\n >\n {isDeleting ? formatMessage({ id: 'common.status.deleting' }) : formatMessage({ id: 'common.actions.delete' })}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n </div>\n );\n}\n\nexport default SessionsPage;\n"],"names":["statusVariantConfig","statusLabelKeys","typeVariantConfig","Search","TestTube","FileText","File","Settings","Zap","typeLabelKeys","formatDate","dateString","calculateProgress","tasks","total","completed","t","failed","inProgress","pending","percentage","calculateSeverityBreakdown","review","critical","high","medium","low","dim","finding","severity","_a","SessionCard","session","onView","onArchive","onDelete","onClick","className","showActions","actionsDisabled","formatMessage","useIntl","statusVariant","statusLabel","typeConfig","typeLabel","progress","isPlanning","isArchived","handleCardClick","e","handleAction","action","jsx","Card","cn","jsxs","CardContent","Badge","DropdownMenu","DropdownMenuTrigger","Button","MoreVertical","DropdownMenuContent","DropdownMenuItem","Eye","Fragment","DropdownMenuSeparator","Archive","Trash2","Calendar","_b","_c","sum","ListChecks","CheckCircle2","Clock","RefreshCw","AlertCircle","SessionCardSkeleton","SessionsPage","navigate","useNavigate","locationFilter","setLocationFilter","React.useState","searchQuery","setSearchQuery","statusFilter","setStatusFilter","deleteDialogOpen","setDeleteDialogOpen","sessionToDelete","setSessionToDelete","isImmersiveMode","useAppStore","selectIsImmersiveMode","toggleImmersiveMode","s","filter","React.useMemo","filteredSessions","isLoading","isFetching","error","refetch","useSessions","archiveSession","isArchiving","useArchiveSession","deleteSession","isDeleting","useDeleteSession","isMutating","handleSessionClick","sessionId","sessionType","handleArchive","err","handleDeleteClick","handleConfirmDelete","handleClearSearch","toggleStatusFilter","status","prev","clearFilters","hasActiveFilters","Minimize2","Maximize2","TabsNavigation","v","Input","X","Filter","DropdownMenuLabel","_","i","FolderKanban","Dialog","DialogContent","DialogHeader","DialogTitle","DialogDescription","DialogFooter"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SessionsPage-CQIB4E8m.js","sources":["../../src/components/shared/SessionCard.tsx","../../src/pages/SessionsPage.tsx"],"sourcesContent":["// ========================================\r\n// SessionCard Component\r\n// ========================================\r\n// Session card with status badge and action menu\r\n\r\nimport * as React from 'react';\r\nimport { useIntl } from 'react-intl';\r\nimport { cn } from '@/lib/utils';\r\nimport { Card, CardContent } from '@/components/ui/Card';\r\nimport { Badge } from '@/components/ui/Badge';\r\nimport { Button } from '@/components/ui/Button';\r\nimport {\r\n DropdownMenu,\r\n DropdownMenuTrigger,\r\n DropdownMenuContent,\r\n DropdownMenuItem,\r\n DropdownMenuSeparator,\r\n} from '@/components/ui/Dropdown';\r\nimport {\r\n Calendar,\r\n ListChecks,\r\n MoreVertical,\r\n Eye,\r\n Archive,\r\n Trash2,\r\n Clock,\r\n CheckCircle2,\r\n AlertCircle,\r\n RefreshCw,\r\n FileText,\r\n Search,\r\n TestTube,\r\n File,\r\n Settings,\r\n Zap,\r\n} from 'lucide-react';\r\nimport type { SessionMetadata } from '@/types/store';\r\n\r\nexport interface SessionCardProps {\r\n /** Session data */\r\n session: SessionMetadata;\r\n /** Called when view action is triggered */\r\n onView?: (sessionId: string) => void;\r\n /** Called when archive action is triggered */\r\n onArchive?: (sessionId: string) => void;\r\n /** Called when delete action is triggered */\r\n onDelete?: (sessionId: string) => void;\r\n /** Called when card is clicked */\r\n onClick?: (sessionId: string) => void;\r\n /** Optional className */\r\n className?: string;\r\n /** Show actions dropdown */\r\n showActions?: boolean;\r\n /** Disabled state for actions */\r\n actionsDisabled?: boolean;\r\n}\r\n\r\n// Status variant configuration (without labels for i18n)\r\nconst statusVariantConfig: Record<\r\n SessionMetadata['status'],\r\n { variant: 'default' | 'secondary' | 'destructive' | 'success' | 'warning' | 'info' }\r\n> = {\r\n planning: { variant: 'info' },\r\n in_progress: { variant: 'warning' },\r\n completed: { variant: 'success' },\r\n archived: { variant: 'secondary' },\r\n paused: { variant: 'default' },\r\n};\r\n\r\n// Status label keys for i18n\r\nconst statusLabelKeys: Record<SessionMetadata['status'], string> = {\r\n planning: 'sessions.status.planning',\r\n in_progress: 'sessions.status.inProgress',\r\n completed: 'sessions.status.completed',\r\n archived: 'sessions.status.archived',\r\n paused: 'sessions.status.paused',\r\n};\r\n\r\n// Type variant configuration for session type badges (unique colors for each type)\r\nconst typeVariantConfig: Record<\r\n NonNullable<SessionMetadata['type']>,\r\n { variant: 'default' | 'secondary' | 'destructive' | 'success' | 'warning' | 'info' | 'review'; icon: React.ElementType }\r\n> = {\r\n review: { variant: 'review', icon: Search }, // Purple\r\n 'tdd': { variant: 'success', icon: TestTube }, // Green\r\n test: { variant: 'info', icon: FileText }, // Blue\r\n docs: { variant: 'warning', icon: File }, // Orange/Yellow\r\n workflow: { variant: 'default', icon: Settings }, // Primary (blue-violet)\r\n 'lite-plan': { variant: 'secondary', icon: FileText }, // Gray/Neutral\r\n 'lite-fix': { variant: 'destructive', icon: Zap }, // Red\r\n};\r\n\r\n// Type label keys for i18n\r\nconst typeLabelKeys: Record<NonNullable<SessionMetadata['type']>, string> = {\r\n review: 'sessions.type.review',\r\n tdd: 'sessions.type.tdd',\r\n test: 'sessions.type.test',\r\n docs: 'sessions.type.docs',\r\n workflow: 'sessions.type.workflow',\r\n 'lite-plan': 'sessions.type.lite-plan',\r\n 'lite-fix': 'sessions.type.lite-fix',\r\n};\r\n\r\n/**\r\n * Format date to localized string\r\n */\r\nfunction formatDate(dateString: string | undefined): string {\r\n if (!dateString) return 'Unknown';\r\n\r\n try {\r\n const date = new Date(dateString);\r\n return date.toLocaleDateString(undefined, {\r\n year: 'numeric',\r\n month: 'short',\r\n day: 'numeric',\r\n });\r\n } catch {\r\n return 'Invalid date';\r\n }\r\n}\r\n\r\n/**\r\n * Task status breakdown returned by calculateProgress\r\n */\r\ninterface TaskStatusBreakdown {\r\n total: number;\r\n completed: number;\r\n failed: number;\r\n pending: number;\r\n inProgress: number;\r\n percentage: number;\r\n}\r\n\r\n/**\r\n * Calculate progress and status breakdown from tasks\r\n */\r\nfunction calculateProgress(tasks: SessionMetadata['tasks']): TaskStatusBreakdown {\r\n if (!tasks || tasks.length === 0) {\r\n return { total: 0, completed: 0, failed: 0, pending: 0, inProgress: 0, percentage: 0 };\r\n }\r\n\r\n const total = tasks.length;\r\n const completed = tasks.filter((t) => t.status === 'completed').length;\r\n const failed = tasks.filter((t) => t.status === 'blocked' || t.status === 'skipped').length;\r\n const inProgress = tasks.filter((t) => t.status === 'in_progress').length;\r\n const pending = tasks.filter((t) => t.status === 'pending').length;\r\n const percentage = Math.round((completed / total) * 100);\r\n\r\n return { total, completed, failed, pending, inProgress, percentage };\r\n}\r\n\r\n/**\r\n * Severity breakdown for review sessions\r\n */\r\ninterface SeverityBreakdown {\r\n total: number;\r\n critical: number;\r\n high: number;\r\n medium: number;\r\n low: number;\r\n}\r\n\r\n/**\r\n * Calculate severity breakdown from review dimensions\r\n */\r\nfunction calculateSeverityBreakdown(review: SessionMetadata['review']): SeverityBreakdown {\r\n if (!review?.dimensions || review.dimensions.length === 0) {\r\n return { total: 0, critical: 0, high: 0, medium: 0, low: 0 };\r\n }\r\n\r\n let critical = 0, high = 0, medium = 0, low = 0;\r\n\r\n review.dimensions.forEach(dim => {\r\n if (dim.findings) {\r\n dim.findings.forEach(finding => {\r\n const severity = finding.severity?.toLowerCase();\r\n if (severity === 'critical') critical++;\r\n else if (severity === 'high') high++;\r\n else if (severity === 'medium') medium++;\r\n else if (severity === 'low') low++;\r\n });\r\n }\r\n });\r\n\r\n const total = critical + high + medium + low;\r\n return { total, critical, high, medium, low };\r\n}\r\n\r\n/**\r\n * SessionCard component for displaying session information\r\n *\r\n * @example\r\n * ```tsx\r\n * <SessionCard\r\n * session={session}\r\n * onView={(id) => navigate(`/sessions/${id}`)}\r\n * onArchive={(id) => archiveSession(id)}\r\n * onDelete={(id) => deleteSession(id)}\r\n * />\r\n * ```\r\n */\r\nexport function SessionCard({\r\n session,\r\n onView,\r\n onArchive,\r\n onDelete,\r\n onClick,\r\n className,\r\n showActions = true,\r\n actionsDisabled = false,\r\n}: SessionCardProps) {\r\n const { formatMessage } = useIntl();\r\n\r\n const { variant: statusVariant } = statusVariantConfig[session.status] || {\r\n variant: 'default' as const,\r\n };\r\n const statusLabel = statusLabelKeys[session.status]\r\n ? formatMessage({ id: statusLabelKeys[session.status] })\r\n : formatMessage({ id: 'common.status.unknown' });\r\n\r\n // Type badge configuration (graceful degradation when type is undefined)\r\n const typeConfig = session.type ? typeVariantConfig[session.type] : null;\r\n const typeLabel = session.type && typeLabelKeys[session.type]\r\n ? formatMessage({ id: typeLabelKeys[session.type] })\r\n : null;\r\n\r\n const progress = calculateProgress(session.tasks);\r\n const severity = calculateSeverityBreakdown(session.review);\r\n const isPlanning = session.status === 'planning';\r\n const isArchived = session.status === 'archived' || session.location === 'archived';\r\n\r\n const handleCardClick = (e: React.MouseEvent) => {\r\n // Don't trigger if clicking on dropdown\r\n if ((e.target as HTMLElement).closest('[data-radix-popper-content-wrapper]')) {\r\n return;\r\n }\r\n onClick?.(session.session_id);\r\n };\r\n\r\n const handleAction = (\r\n e: React.MouseEvent,\r\n action: 'view' | 'archive' | 'delete'\r\n ) => {\r\n e.stopPropagation();\r\n switch (action) {\r\n case 'view':\r\n onView?.(session.session_id);\r\n break;\r\n case 'archive':\r\n onArchive?.(session.session_id);\r\n break;\r\n case 'delete':\r\n onDelete?.(session.session_id);\r\n break;\r\n }\r\n };\r\n\r\n return (\r\n <Card\r\n className={cn(\r\n 'group cursor-pointer transition-all duration-200 hover:shadow-md hover:border-primary/30',\r\n isPlanning && 'border-info/30 bg-info/5',\r\n className\r\n )}\r\n onClick={handleCardClick}\r\n >\r\n <CardContent className=\"p-4\">\r\n {/* Header - Type badge + Session ID as title */}\r\n <div className=\"flex items-start justify-between gap-2 mb-2\">\r\n <div className=\"flex-1 min-w-0\">\r\n <div className=\"flex items-center gap-2 mb-1\">\r\n {/* Type badge BEFORE title */}\r\n {typeConfig && typeLabel && (\r\n <Badge variant={typeConfig.variant} className=\"gap-1 flex-shrink-0\">\r\n <typeConfig.icon className=\"h-3 w-3\" />\r\n {typeLabel}\r\n </Badge>\r\n )}\r\n <h3 className=\"font-bold text-card-foreground text-sm tracking-wide uppercase truncate\">\r\n {session.session_id}\r\n </h3>\r\n </div>\r\n </div>\r\n <div className=\"flex items-center gap-2 flex-shrink-0\">\r\n <Badge variant={statusVariant}>{statusLabel}</Badge>\r\n {showActions && (\r\n <DropdownMenu>\r\n <DropdownMenuTrigger asChild>\r\n <Button\r\n variant=\"ghost\"\r\n size=\"icon\"\r\n className=\"h-8 w-8 opacity-0 group-hover:opacity-100 transition-opacity\"\r\n onClick={(e) => e.stopPropagation()}\r\n disabled={actionsDisabled}\r\n >\r\n <MoreVertical className=\"h-4 w-4\" />\r\n <span className=\"sr-only\">{formatMessage({ id: 'common.aria.actions' })}</span>\r\n </Button>\r\n </DropdownMenuTrigger>\r\n <DropdownMenuContent align=\"end\">\r\n <DropdownMenuItem onClick={(e) => handleAction(e, 'view')}>\r\n <Eye className=\"mr-2 h-4 w-4\" />\r\n {formatMessage({ id: 'sessions.actions.viewDetails' })}\r\n </DropdownMenuItem>\r\n {!isArchived && (\r\n <>\r\n <DropdownMenuSeparator />\r\n <DropdownMenuItem onClick={(e) => handleAction(e, 'archive')}>\r\n <Archive className=\"mr-2 h-4 w-4\" />\r\n {formatMessage({ id: 'sessions.actions.archive' })}\r\n </DropdownMenuItem>\r\n </>\r\n )}\r\n <DropdownMenuSeparator />\r\n <DropdownMenuItem\r\n onClick={(e) => handleAction(e, 'delete')}\r\n className=\"text-destructive focus:text-destructive\"\r\n >\r\n <Trash2 className=\"mr-2 h-4 w-4\" />\r\n {formatMessage({ id: 'sessions.actions.delete' })}\r\n </DropdownMenuItem>\r\n </DropdownMenuContent>\r\n </DropdownMenu>\r\n )}\r\n </div>\r\n </div>\r\n\r\n {/* Title as description */}\r\n {session.title && (\r\n <p className=\"text-sm text-foreground line-clamp-2 mb-3\">\r\n {session.title}\r\n </p>\r\n )}\r\n\r\n {/* Meta info - different based on session type */}\r\n <div className=\"flex flex-wrap items-center gap-x-4 gap-y-2 text-xs text-muted-foreground\">\r\n <span className=\"flex items-center gap-1\">\r\n <Calendar className=\"h-3.5 w-3.5\" />\r\n {formatDate(session.created_at)}\r\n </span>\r\n\r\n {/* Review sessions: Show findings and dimensions */}\r\n {session.type === 'review' ? (\r\n <>\r\n {session.review?.dimensions && session.review.dimensions.length > 0 && (\r\n <span className=\"flex items-center gap-1\">\r\n <Search className=\"h-3.5 w-3.5\" />\r\n {session.review.dimensions.length} {formatMessage({ id: 'sessions.card.dimensions' })}\r\n </span>\r\n )}\r\n {session.review?.findings !== undefined && (\r\n <span className=\"flex items-center gap-1\">\r\n <FileText className=\"h-3.5 w-3.5\" />\r\n {typeof session.review.findings === 'number'\r\n ? session.review.findings\r\n : session.review.dimensions?.reduce((sum, dim) => sum + (dim.findings?.length || 0), 0) || 0\r\n } {formatMessage({ id: 'sessions.card.findings' })}\r\n </span>\r\n )}\r\n </>\r\n ) : (\r\n <>\r\n {/* Workflow/other sessions: Show tasks */}\r\n <span className=\"flex items-center gap-1\">\r\n <ListChecks className=\"h-3.5 w-3.5\" />\r\n {progress.total} {formatMessage({ id: 'sessions.card.tasks' })}\r\n </span>\r\n {progress.total > 0 && (\r\n <span className=\"flex items-center gap-1\">\r\n <CheckCircle2 className=\"h-3.5 w-3.5 text-success\" />\r\n {progress.completed} {formatMessage({ id: 'sessions.card.completed' })}\r\n </span>\r\n )}\r\n </>\r\n )}\r\n {session.updated_at && session.updated_at !== session.created_at && (\r\n <span className=\"flex items-center gap-1\">\r\n <Clock className=\"h-3.5 w-3.5\" />\r\n {formatMessage({ id: 'sessions.card.updated' })}: {formatDate(session.updated_at)}\r\n </span>\r\n )}\r\n </div>\r\n\r\n {/* Task status badges - only for non-review sessions */}\r\n {session.type !== 'review' && progress.total > 0 && (\r\n <div className=\"flex flex-wrap items-center gap-1.5 mt-2\">\r\n {progress.inProgress > 0 && (\r\n <Badge variant=\"info\" className=\"gap-1 px-1.5 py-0 text-[10px]\">\r\n <RefreshCw className=\"h-3 w-3\" />\r\n {progress.inProgress} {formatMessage({ id: 'sessions.taskStatus.inProgress' })}\r\n </Badge>\r\n )}\r\n {progress.completed > 0 && (\r\n <Badge variant=\"success\" className=\"gap-1 px-1.5 py-0 text-[10px]\">\r\n <CheckCircle2 className=\"h-3 w-3\" />\r\n {progress.completed} {formatMessage({ id: 'sessions.taskStatus.completed' })}\r\n </Badge>\r\n )}\r\n {progress.failed > 0 && (\r\n <Badge variant=\"destructive\" className=\"gap-1 px-1.5 py-0 text-[10px]\">\r\n <AlertCircle className=\"h-3 w-3\" />\r\n {progress.failed} {formatMessage({ id: 'sessions.taskStatus.failed' })}\r\n </Badge>\r\n )}\r\n </div>\r\n )}\r\n\r\n {/* Severity badges - only for review sessions */}\r\n {session.type === 'review' && severity.total > 0 && (\r\n <div className=\"flex flex-wrap items-center gap-1.5 mt-2\">\r\n {severity.critical > 0 && (\r\n <Badge variant=\"destructive\" className=\"gap-1 px-1.5 py-0 text-[10px]\">\r\n <AlertCircle className=\"h-3 w-3\" />\r\n {severity.critical} Critical\r\n </Badge>\r\n )}\r\n {severity.high > 0 && (\r\n <Badge variant=\"warning\" className=\"gap-1 px-1.5 py-0 text-[10px]\">\r\n <AlertCircle className=\"h-3 w-3\" />\r\n {severity.high} High\r\n </Badge>\r\n )}\r\n {severity.medium > 0 && (\r\n <Badge variant=\"info\" className=\"gap-1 px-1.5 py-0 text-[10px]\">\r\n <Search className=\"h-3 w-3\" />\r\n {severity.medium} Medium\r\n </Badge>\r\n )}\r\n {severity.low > 0 && (\r\n <Badge variant=\"secondary\" className=\"gap-1 px-1.5 py-0 text-[10px]\">\r\n <FileText className=\"h-3 w-3\" />\r\n {severity.low} Low\r\n </Badge>\r\n )}\r\n </div>\r\n )}\r\n\r\n {/* Progress bar (only show for non-review sessions with tasks) */}\r\n {session.type !== 'review' && progress.total > 0 && !isPlanning && (\r\n <div className=\"mt-3\">\r\n <div className=\"flex items-center justify-between text-xs mb-1\">\r\n <span className=\"text-muted-foreground\">{formatMessage({ id: 'sessions.card.progress' })}</span>\r\n <span className=\"text-card-foreground font-medium\">\r\n {progress.completed}/{progress.total} ({progress.percentage}%)\r\n </span>\r\n </div>\r\n <div className=\"h-1.5 w-full rounded-full bg-muted overflow-hidden\">\r\n <div\r\n className={cn(\r\n \"h-full transition-all duration-300\",\r\n progress.percentage === 100 ? \"bg-success\" : \"bg-primary\"\r\n )}\r\n style={{ width: `${progress.percentage}%` }}\r\n />\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Description (if exists and different from title) */}\r\n {session.description && session.description !== session.title && (\r\n <p className=\"mt-2 text-xs text-muted-foreground line-clamp-2 italic\">\r\n {session.description}\r\n </p>\r\n )}\r\n </CardContent>\r\n </Card>\r\n );\r\n}\r\n\r\n/**\r\n * Skeleton loader for SessionCard\r\n */\r\nexport function SessionCardSkeleton({ className }: { className?: string }) {\r\n return (\r\n <Card className={cn('animate-pulse', className)}>\r\n <CardContent className=\"p-4\">\r\n <div className=\"flex items-start justify-between\">\r\n <div className=\"flex-1\">\r\n <div className=\"h-5 w-32 rounded bg-muted\" />\r\n <div className=\"mt-1 h-3 w-24 rounded bg-muted\" />\r\n </div>\r\n <div className=\"h-5 w-16 rounded-full bg-muted\" />\r\n </div>\r\n <div className=\"mt-3 flex gap-4\">\r\n <div className=\"h-4 w-20 rounded bg-muted\" />\r\n <div className=\"h-4 w-16 rounded bg-muted\" />\r\n </div>\r\n {/* Status badge skeletons */}\r\n <div className=\"mt-2 flex gap-1.5\">\r\n <div className=\"h-5 w-16 rounded-full bg-muted\" />\r\n <div className=\"h-5 w-20 rounded-full bg-muted\" />\r\n <div className=\"h-5 w-18 rounded-full bg-muted\" />\r\n </div>\r\n <div className=\"mt-3\">\r\n <div className=\"h-1.5 w-full rounded-full bg-muted\" />\r\n </div>\r\n </CardContent>\r\n </Card>\r\n );\r\n}\r\n","// ========================================\n// SessionsPage Component\n// ========================================\n// Sessions list page with CRUD operations\n\nimport * as React from 'react';\nimport { useNavigate } from 'react-router-dom';\nimport { useIntl } from 'react-intl';\nimport {\n RefreshCw,\n Search,\n Filter,\n AlertCircle,\n FolderKanban,\n X,\n Maximize2,\n Minimize2,\n} from 'lucide-react';\nimport {\n useSessions,\n useArchiveSession,\n useDeleteSession,\n type SessionsFilter,\n} from '@/hooks/useSessions';\nimport { SessionCard, SessionCardSkeleton } from '@/components/shared/SessionCard';\nimport { Button } from '@/components/ui/Button';\nimport { Input } from '@/components/ui/Input';\nimport { Badge } from '@/components/ui/Badge';\nimport {\n Dialog,\n DialogContent,\n DialogHeader,\n DialogTitle,\n DialogDescription,\n DialogFooter,\n} from '@/components/ui/Dialog';\nimport {\n DropdownMenu,\n DropdownMenuTrigger,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuSeparator,\n DropdownMenuLabel,\n} from '@/components/ui/Dropdown';\nimport { TabsNavigation } from '@/components/ui/TabsNavigation';\nimport { cn } from '@/lib/utils';\nimport type { SessionMetadata } from '@/types/store';\nimport { useAppStore, selectIsImmersiveMode } from '@/stores/appStore';\n\ntype LocationFilter = 'all' | 'active' | 'archived';\n\n// Status label keys for i18n (maps snake_case status to camelCase translation keys)\nconst statusLabelKeys: Record<SessionMetadata['status'], string> = {\n planning: 'sessions.status.planning',\n in_progress: 'sessions.status.inProgress',\n completed: 'sessions.status.completed',\n archived: 'sessions.status.archived',\n paused: 'sessions.status.paused',\n};\n\n/**\n * SessionsPage component - Sessions list with CRUD operations\n */\nexport function SessionsPage() {\n const { formatMessage } = useIntl();\n const navigate = useNavigate();\n\n // Filter state\n const [locationFilter, setLocationFilter] = React.useState<LocationFilter>('active');\n const [searchQuery, setSearchQuery] = React.useState('');\n const [statusFilter, setStatusFilter] = React.useState<SessionMetadata['status'][]>([]);\n\n // Dialog state\n const [deleteDialogOpen, setDeleteDialogOpen] = React.useState(false);\n const [sessionToDelete, setSessionToDelete] = React.useState<string | null>(null);\n\n // Immersive mode (fullscreen)\n const isImmersiveMode = useAppStore(selectIsImmersiveMode);\n const toggleImmersiveMode = useAppStore((s) => s.toggleImmersiveMode);\n\n // Build filter object\n const filter: SessionsFilter = React.useMemo(\n () => ({\n location: locationFilter,\n search: searchQuery,\n status: statusFilter.length > 0 ? statusFilter : undefined,\n }),\n [locationFilter, searchQuery, statusFilter]\n );\n\n // Fetch sessions with filter\n const {\n filteredSessions,\n isLoading,\n isFetching,\n error,\n refetch,\n } = useSessions({ filter });\n\n // Mutations\n const { archiveSession, isArchiving } = useArchiveSession();\n const { deleteSession, isDeleting } = useDeleteSession();\n\n const isMutating = isArchiving || isDeleting;\n\n // Handlers\n const handleSessionClick = (sessionId: string, sessionType?: SessionMetadata['type']) => {\n // Route review sessions to the dedicated review page\n if (sessionType === 'review') {\n navigate(`/sessions/${sessionId}/review`);\n } else {\n navigate(`/sessions/${sessionId}`);\n }\n };\n\n const handleArchive = async (sessionId: string) => {\n try {\n await archiveSession(sessionId);\n } catch (err) {\n console.error('Failed to archive session:', err);\n }\n };\n\n const handleDeleteClick = (sessionId: string) => {\n setSessionToDelete(sessionId);\n setDeleteDialogOpen(true);\n };\n\n const handleConfirmDelete = async () => {\n if (!sessionToDelete) return;\n\n try {\n await deleteSession(sessionToDelete);\n setDeleteDialogOpen(false);\n setSessionToDelete(null);\n } catch (err) {\n console.error('Failed to delete session:', err);\n }\n };\n\n const handleClearSearch = () => {\n setSearchQuery('');\n };\n\n const toggleStatusFilter = (status: SessionMetadata['status']) => {\n setStatusFilter((prev) =>\n prev.includes(status) ? prev.filter((s) => s !== status) : [...prev, status]\n );\n };\n\n const clearFilters = () => {\n setStatusFilter([]);\n setSearchQuery('');\n };\n\n const hasActiveFilters = statusFilter.length > 0 || searchQuery.length > 0;\n\n return (\n <div className={cn(\"space-y-6\", isImmersiveMode && \"h-screen overflow-hidden\")}>\n {/* Header */}\n <div className=\"flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between\">\n <div>\n <h1 className=\"text-2xl font-semibold text-foreground\">{formatMessage({ id: 'sessions.title' })}</h1>\n <p className=\"text-sm text-muted-foreground mt-1\">\n {formatMessage({ id: 'sessions.description' })}\n </p>\n </div>\n <div className=\"flex items-center gap-2\">\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => refetch()}\n disabled={isFetching}\n >\n <RefreshCw className={cn('h-4 w-4 mr-2', isFetching && 'animate-spin')} />\n {formatMessage({ id: 'common.actions.refresh' })}\n </Button>\n <button\n onClick={toggleImmersiveMode}\n className={cn(\n 'p-2 rounded-md transition-colors',\n isImmersiveMode\n ? 'bg-primary/10 text-primary'\n : 'text-muted-foreground hover:text-foreground hover:bg-muted'\n )}\n title={isImmersiveMode ? formatMessage({ id: 'common.exitFullscreen', defaultMessage: 'Exit Fullscreen' }) : formatMessage({ id: 'common.fullscreen', defaultMessage: 'Fullscreen' })}\n >\n {isImmersiveMode ? <Minimize2 className=\"w-4 h-4\" /> : <Maximize2 className=\"w-4 h-4\" />}\n </button>\n </div>\n </div>\n\n {/* Error alert */}\n {error && (\n <div className=\"flex items-center gap-2 p-4 rounded-lg bg-destructive/10 border border-destructive/30 text-destructive\">\n <AlertCircle className=\"h-5 w-5 flex-shrink-0\" />\n <div className=\"flex-1\">\n <p className=\"text-sm font-medium\">{formatMessage({ id: 'common.errors.loadFailed' })}</p>\n <p className=\"text-xs mt-0.5\">{error.message}</p>\n </div>\n <Button variant=\"outline\" size=\"sm\" onClick={() => refetch()}>\n {formatMessage({ id: 'home.errors.retry' })}\n </Button>\n </div>\n )}\n\n {/* Filters */}\n <div className=\"flex flex-col gap-4 sm:flex-row sm:items-center\">\n {/* Location tabs */}\n <TabsNavigation\n value={locationFilter}\n onValueChange={(v) => setLocationFilter(v as LocationFilter)}\n tabs={[\n { value: 'active', label: formatMessage({ id: 'sessions.filters.active' }) },\n { value: 'archived', label: formatMessage({ id: 'sessions.filters.archived' }) },\n { value: 'all', label: formatMessage({ id: 'sessions.filters.all' }) },\n ]}\n />\n\n {/* Search input */}\n <div className=\"flex-1 max-w-sm relative\">\n <Search className=\"absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground\" />\n <Input\n placeholder={formatMessage({ id: 'sessions.searchPlaceholder' })}\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n className=\"pl-9 pr-9\"\n />\n {searchQuery && (\n <button\n onClick={handleClearSearch}\n className=\"absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground\"\n >\n <X className=\"h-4 w-4\" />\n </button>\n )}\n </div>\n\n {/* Status filter dropdown */}\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button variant=\"outline\" size=\"sm\" className=\"gap-2\">\n <Filter className=\"h-4 w-4\" />\n {formatMessage({ id: 'common.actions.filter' })}\n {statusFilter.length > 0 && (\n <Badge variant=\"secondary\" className=\"ml-1 h-5 min-w-5 px-1\">\n {statusFilter.length}\n </Badge>\n )}\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\" className=\"w-48\">\n <DropdownMenuLabel>{formatMessage({ id: 'common.status.label' })}</DropdownMenuLabel>\n <DropdownMenuSeparator />\n {(['planning', 'in_progress', 'completed', 'paused'] as const).map((status) => (\n <DropdownMenuItem\n key={status}\n onClick={() => toggleStatusFilter(status)}\n className=\"justify-between\"\n >\n <span>{formatMessage({ id: statusLabelKeys[status] })}</span>\n {statusFilter.includes(status) && (\n <span className=\"text-primary\">✓</span>\n )}\n </DropdownMenuItem>\n ))}\n {hasActiveFilters && (\n <>\n <DropdownMenuSeparator />\n <DropdownMenuItem onClick={clearFilters} className=\"text-destructive\">\n {formatMessage({ id: 'common.actions.clearFilters' })}\n </DropdownMenuItem>\n </>\n )}\n </DropdownMenuContent>\n </DropdownMenu>\n </div>\n\n {/* Active filters display */}\n {hasActiveFilters && (\n <div className=\"flex flex-wrap items-center gap-2\">\n <span className=\"text-sm text-muted-foreground\">{formatMessage({ id: 'common.actions.filters' })}:</span>\n {statusFilter.map((status) => (\n <Badge\n key={status}\n variant=\"secondary\"\n className=\"cursor-pointer\"\n onClick={() => toggleStatusFilter(status)}\n >\n {formatMessage({ id: statusLabelKeys[status] })}\n <X className=\"ml-1 h-3 w-3\" />\n </Badge>\n ))}\n {searchQuery && (\n <Badge\n variant=\"secondary\"\n className=\"cursor-pointer\"\n onClick={handleClearSearch}\n >\n {formatMessage({ id: 'common.actions.search' })}: {searchQuery}\n <X className=\"ml-1 h-3 w-3\" />\n </Badge>\n )}\n <Button variant=\"ghost\" size=\"sm\" onClick={clearFilters} className=\"h-6 text-xs\">\n {formatMessage({ id: 'common.actions.clearAll' })}\n </Button>\n </div>\n )}\n\n {/* Sessions grid */}\n {isLoading ? (\n <div className=\"grid gap-4 grid-cols-1 md:grid-cols-2 lg:grid-cols-3\">\n {Array.from({ length: 9 }).map((_, i) => (\n <SessionCardSkeleton key={i} />\n ))}\n </div>\n ) : filteredSessions.length === 0 ? (\n <div className=\"flex flex-col items-center justify-center py-16 px-4 border border-dashed border-border rounded-lg\">\n <FolderKanban className=\"h-12 w-12 text-muted-foreground mb-4\" />\n <h3 className=\"text-lg font-medium text-foreground mb-1\">\n {hasActiveFilters ? formatMessage({ id: 'sessions.emptyState.title' }) : formatMessage({ id: 'sessions.emptyState.title' })}\n </h3>\n <p className=\"text-sm text-muted-foreground text-center max-w-sm mb-4\">\n {hasActiveFilters\n ? formatMessage({ id: 'sessions.emptyState.message' })\n : formatMessage({ id: 'sessions.emptyState.createFirst' })}\n </p>\n {hasActiveFilters && (\n <Button variant=\"outline\" onClick={clearFilters}>\n {formatMessage({ id: 'common.actions.clearFilters' })}\n </Button>\n )}\n </div>\n ) : (\n <div className=\"grid gap-4 grid-cols-1 md:grid-cols-2 lg:grid-cols-3\">\n {filteredSessions.map((session) => (\n <SessionCard\n key={session.session_id}\n session={session}\n onClick={(sessionId) => handleSessionClick(sessionId, session.type)}\n onView={(sessionId) => handleSessionClick(sessionId, session.type)}\n onArchive={handleArchive}\n onDelete={handleDeleteClick}\n actionsDisabled={isMutating}\n />\n ))}\n </div>\n )}\n\n {/* Delete Confirmation Dialog */}\n <Dialog open={deleteDialogOpen} onOpenChange={setDeleteDialogOpen}>\n <DialogContent>\n <DialogHeader>\n <DialogTitle>{formatMessage({ id: 'common.dialog.deleteSession' })}</DialogTitle>\n <DialogDescription>\n {formatMessage({ id: 'common.dialog.deleteConfirm' })}\n </DialogDescription>\n </DialogHeader>\n <DialogFooter>\n <Button\n variant=\"outline\"\n onClick={() => {\n setDeleteDialogOpen(false);\n setSessionToDelete(null);\n }}\n >\n {formatMessage({ id: 'common.actions.cancel' })}\n </Button>\n <Button\n variant=\"destructive\"\n onClick={handleConfirmDelete}\n disabled={isDeleting}\n >\n {isDeleting ? formatMessage({ id: 'common.status.deleting' }) : formatMessage({ id: 'common.actions.delete' })}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n </div>\n );\n}\n\nexport default SessionsPage;\n"],"names":["statusVariantConfig","statusLabelKeys","typeVariantConfig","Search","TestTube","FileText","File","Settings","Zap","typeLabelKeys","formatDate","dateString","calculateProgress","tasks","total","completed","t","failed","inProgress","pending","percentage","calculateSeverityBreakdown","review","critical","high","medium","low","dim","finding","severity","_a","SessionCard","session","onView","onArchive","onDelete","onClick","className","showActions","actionsDisabled","formatMessage","useIntl","statusVariant","statusLabel","typeConfig","typeLabel","progress","isPlanning","isArchived","handleCardClick","e","handleAction","action","jsx","Card","cn","jsxs","CardContent","Badge","DropdownMenu","DropdownMenuTrigger","Button","MoreVertical","DropdownMenuContent","DropdownMenuItem","Eye","Fragment","DropdownMenuSeparator","Archive","Trash2","Calendar","_b","_c","sum","ListChecks","CheckCircle2","Clock","RefreshCw","AlertCircle","SessionCardSkeleton","SessionsPage","navigate","useNavigate","locationFilter","setLocationFilter","React.useState","searchQuery","setSearchQuery","statusFilter","setStatusFilter","deleteDialogOpen","setDeleteDialogOpen","sessionToDelete","setSessionToDelete","isImmersiveMode","useAppStore","selectIsImmersiveMode","toggleImmersiveMode","s","filter","React.useMemo","filteredSessions","isLoading","isFetching","error","refetch","useSessions","archiveSession","isArchiving","useArchiveSession","deleteSession","isDeleting","useDeleteSession","isMutating","handleSessionClick","sessionId","sessionType","handleArchive","err","handleDeleteClick","handleConfirmDelete","handleClearSearch","toggleStatusFilter","status","prev","clearFilters","hasActiveFilters","Minimize2","Maximize2","TabsNavigation","v","Input","X","Filter","DropdownMenuLabel","_","i","FolderKanban","Dialog","DialogContent","DialogHeader","DialogTitle","DialogDescription","DialogFooter"],"mappings":"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"}
|