prjct-cli 0.18.2 → 0.20.0
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/CHANGELOG.md +82 -0
- package/CLAUDE.md +74 -211
- package/core/agentic/prompt-builder.ts +3 -7
- package/core/command-registry/optional-commands.ts +0 -20
- package/core/infrastructure/command-installer/command-installer.ts +8 -1
- package/core/infrastructure/command-installer/global-config.ts +31 -1
- package/core/infrastructure/command-installer/index.ts +1 -1
- package/core/infrastructure/setup.ts +3 -0
- package/package.json +3 -17
- package/templates/agentic/agents/uxui.md +210 -0
- package/templates/commands/bug.md +219 -41
- package/templates/commands/done.md +57 -258
- package/templates/commands/feature.md +368 -80
- package/templates/commands/now.md +72 -277
- package/templates/commands/ship.md +167 -246
- package/templates/commands/sync.md +62 -3
- package/templates/commands/test.md +160 -20
- package/templates/global/CLAUDE.md +40 -205
- package/templates/global/docs/agents.md +88 -0
- package/templates/global/docs/architecture.md +103 -0
- package/templates/global/docs/commands.md +98 -0
- package/templates/global/docs/validation.md +95 -0
- package/bin/dev.js +0 -216
- package/bin/serve.js +0 -361
- package/packages/web/README.md +0 -36
- package/packages/web/app/api/claude/sessions/route.ts +0 -44
- package/packages/web/app/api/claude/status/route.ts +0 -34
- package/packages/web/app/api/projects/[id]/icon/route.ts +0 -33
- package/packages/web/app/api/projects/[id]/momentum/route.ts +0 -257
- package/packages/web/app/api/projects/[id]/route.ts +0 -29
- package/packages/web/app/api/projects/[id]/stats/route.ts +0 -41
- package/packages/web/app/api/projects/[id]/status/route.ts +0 -21
- package/packages/web/app/api/projects/route.ts +0 -16
- package/packages/web/app/api/sessions/current/route.ts +0 -132
- package/packages/web/app/api/sessions/history/route.ts +0 -204
- package/packages/web/app/error.tsx +0 -34
- package/packages/web/app/favicon.ico +0 -0
- package/packages/web/app/globals.css +0 -198
- package/packages/web/app/layout.tsx +0 -53
- package/packages/web/app/loading.tsx +0 -7
- package/packages/web/app/not-found.tsx +0 -25
- package/packages/web/app/page.tsx +0 -12
- package/packages/web/app/project/[id]/code/layout.tsx +0 -18
- package/packages/web/app/project/[id]/code/page.tsx +0 -408
- package/packages/web/app/project/[id]/error.tsx +0 -41
- package/packages/web/app/project/[id]/loading.tsx +0 -9
- package/packages/web/app/project/[id]/not-found.tsx +0 -27
- package/packages/web/app/project/[id]/page.tsx +0 -384
- package/packages/web/app/project/[id]/reports/page.tsx +0 -59
- package/packages/web/app/project/[id]/reports/print/page.tsx +0 -58
- package/packages/web/app/sessions/page.tsx +0 -165
- package/packages/web/app/settings/page.tsx +0 -151
- package/packages/web/components/ActivityTimeline/ActivityTimeline.constants.ts +0 -2
- package/packages/web/components/ActivityTimeline/ActivityTimeline.tsx +0 -49
- package/packages/web/components/ActivityTimeline/ActivityTimeline.types.ts +0 -8
- package/packages/web/components/ActivityTimeline/hooks/index.ts +0 -2
- package/packages/web/components/ActivityTimeline/hooks/useExpandable.ts +0 -9
- package/packages/web/components/ActivityTimeline/hooks/useGroupedEvents.ts +0 -23
- package/packages/web/components/ActivityTimeline/index.ts +0 -2
- package/packages/web/components/AgentsCard/AgentsCard.tsx +0 -93
- package/packages/web/components/AgentsCard/AgentsCard.types.ts +0 -14
- package/packages/web/components/AgentsCard/index.ts +0 -2
- package/packages/web/components/AppSidebar/AppSidebar.tsx +0 -316
- package/packages/web/components/AppSidebar/index.ts +0 -1
- package/packages/web/components/BackLink/BackLink.tsx +0 -18
- package/packages/web/components/BackLink/BackLink.types.ts +0 -5
- package/packages/web/components/BackLink/index.ts +0 -2
- package/packages/web/components/BentoCard/BentoCard.constants.ts +0 -16
- package/packages/web/components/BentoCard/BentoCard.tsx +0 -48
- package/packages/web/components/BentoCard/BentoCard.types.ts +0 -15
- package/packages/web/components/BentoCard/index.ts +0 -2
- package/packages/web/components/BentoCardSkeleton/BentoCardSkeleton.constants.ts +0 -9
- package/packages/web/components/BentoCardSkeleton/BentoCardSkeleton.tsx +0 -18
- package/packages/web/components/BentoCardSkeleton/BentoCardSkeleton.types.ts +0 -5
- package/packages/web/components/BentoCardSkeleton/index.ts +0 -2
- package/packages/web/components/BentoGrid/BentoGrid.tsx +0 -18
- package/packages/web/components/BentoGrid/BentoGrid.types.ts +0 -4
- package/packages/web/components/BentoGrid/index.ts +0 -2
- package/packages/web/components/BlockersCard/BlockersCard.tsx +0 -75
- package/packages/web/components/BlockersCard/BlockersCard.types.ts +0 -12
- package/packages/web/components/BlockersCard/index.ts +0 -2
- package/packages/web/components/CommandBar/CommandBar.tsx +0 -67
- package/packages/web/components/CommandBar/index.ts +0 -1
- package/packages/web/components/CommandButton/CommandButton.tsx +0 -46
- package/packages/web/components/CommandButton/index.ts +0 -1
- package/packages/web/components/ConnectionStatus/ConnectionStatus.tsx +0 -29
- package/packages/web/components/ConnectionStatus/index.ts +0 -1
- package/packages/web/components/DashboardContent/DashboardContent.tsx +0 -284
- package/packages/web/components/DashboardContent/index.ts +0 -1
- package/packages/web/components/DateGroup/DateGroup.tsx +0 -18
- package/packages/web/components/DateGroup/DateGroup.types.ts +0 -6
- package/packages/web/components/DateGroup/DateGroup.utils.ts +0 -11
- package/packages/web/components/DateGroup/index.ts +0 -2
- package/packages/web/components/EmptyState/EmptyState.tsx +0 -76
- package/packages/web/components/EmptyState/EmptyState.types.ts +0 -11
- package/packages/web/components/EmptyState/index.ts +0 -2
- package/packages/web/components/EventRow/EventRow.constants.ts +0 -10
- package/packages/web/components/EventRow/EventRow.tsx +0 -49
- package/packages/web/components/EventRow/EventRow.types.ts +0 -7
- package/packages/web/components/EventRow/EventRow.utils.ts +0 -49
- package/packages/web/components/EventRow/index.ts +0 -2
- package/packages/web/components/ExpandButton/ExpandButton.tsx +0 -18
- package/packages/web/components/ExpandButton/ExpandButton.types.ts +0 -6
- package/packages/web/components/ExpandButton/index.ts +0 -2
- package/packages/web/components/HealthGradientBackground/HealthGradientBackground.tsx +0 -14
- package/packages/web/components/HealthGradientBackground/HealthGradientBackground.types.ts +0 -5
- package/packages/web/components/HealthGradientBackground/HealthGradientBackground.utils.ts +0 -13
- package/packages/web/components/HealthGradientBackground/index.ts +0 -2
- package/packages/web/components/HeroSection/HeroSection.tsx +0 -92
- package/packages/web/components/HeroSection/HeroSection.types.ts +0 -14
- package/packages/web/components/HeroSection/HeroSection.utils.ts +0 -11
- package/packages/web/components/HeroSection/hooks/index.ts +0 -2
- package/packages/web/components/HeroSection/hooks/useCountUp.ts +0 -45
- package/packages/web/components/HeroSection/hooks/useWeeklyActivity.ts +0 -18
- package/packages/web/components/HeroSection/index.ts +0 -2
- package/packages/web/components/IdeasCard/IdeasCard.tsx +0 -115
- package/packages/web/components/IdeasCard/IdeasCard.types.ts +0 -10
- package/packages/web/components/IdeasCard/index.ts +0 -2
- package/packages/web/components/InsightMessage/InsightMessage.tsx +0 -9
- package/packages/web/components/InsightMessage/InsightMessage.types.ts +0 -3
- package/packages/web/components/InsightMessage/index.ts +0 -2
- package/packages/web/components/Logo/Logo.tsx +0 -65
- package/packages/web/components/Logo/index.ts +0 -1
- package/packages/web/components/MarkdownContent/MarkdownContent.tsx +0 -123
- package/packages/web/components/MarkdownContent/index.ts +0 -1
- package/packages/web/components/MasonryGrid/MasonryGrid.tsx +0 -18
- package/packages/web/components/MasonryGrid/index.ts +0 -1
- package/packages/web/components/MomentumWidget/MomentumWidget.tsx +0 -119
- package/packages/web/components/MomentumWidget/MomentumWidget.types.ts +0 -16
- package/packages/web/components/MomentumWidget/index.ts +0 -2
- package/packages/web/components/NowCard/NowCard.tsx +0 -118
- package/packages/web/components/NowCard/NowCard.types.ts +0 -16
- package/packages/web/components/NowCard/index.ts +0 -2
- package/packages/web/components/PageHeader/PageHeader.tsx +0 -24
- package/packages/web/components/PageHeader/index.ts +0 -1
- package/packages/web/components/ProgressRing/ProgressRing.constants.ts +0 -20
- package/packages/web/components/ProgressRing/ProgressRing.tsx +0 -51
- package/packages/web/components/ProgressRing/ProgressRing.types.ts +0 -11
- package/packages/web/components/ProgressRing/index.ts +0 -2
- package/packages/web/components/ProjectAvatar/ProjectAvatar.tsx +0 -54
- package/packages/web/components/ProjectAvatar/index.ts +0 -1
- package/packages/web/components/ProjectColorDot/ProjectColorDot.tsx +0 -37
- package/packages/web/components/ProjectColorDot/index.ts +0 -1
- package/packages/web/components/ProjectSelectorModal/ProjectSelectorModal.tsx +0 -104
- package/packages/web/components/ProjectSelectorModal/index.ts +0 -1
- package/packages/web/components/Providers/Providers.tsx +0 -48
- package/packages/web/components/Providers/index.ts +0 -1
- package/packages/web/components/QueueCard/QueueCard.tsx +0 -125
- package/packages/web/components/QueueCard/QueueCard.types.ts +0 -12
- package/packages/web/components/QueueCard/QueueCard.utils.ts +0 -12
- package/packages/web/components/QueueCard/index.ts +0 -2
- package/packages/web/components/RecoverCard/RecoverCard.tsx +0 -72
- package/packages/web/components/RecoverCard/RecoverCard.types.ts +0 -16
- package/packages/web/components/RecoverCard/index.ts +0 -2
- package/packages/web/components/RoadmapCard/RoadmapCard.tsx +0 -145
- package/packages/web/components/RoadmapCard/RoadmapCard.types.ts +0 -16
- package/packages/web/components/RoadmapCard/index.ts +0 -2
- package/packages/web/components/ShipsCard/ShipsCard.tsx +0 -95
- package/packages/web/components/ShipsCard/ShipsCard.types.ts +0 -14
- package/packages/web/components/ShipsCard/ShipsCard.utils.ts +0 -4
- package/packages/web/components/ShipsCard/index.ts +0 -2
- package/packages/web/components/SparklineChart/SparklineChart.tsx +0 -40
- package/packages/web/components/SparklineChart/SparklineChart.types.ts +0 -6
- package/packages/web/components/SparklineChart/index.ts +0 -2
- package/packages/web/components/StatsMasonry/StatsMasonry.tsx +0 -95
- package/packages/web/components/StatsMasonry/index.ts +0 -1
- package/packages/web/components/StreakCard/StreakCard.constants.ts +0 -2
- package/packages/web/components/StreakCard/StreakCard.tsx +0 -55
- package/packages/web/components/StreakCard/StreakCard.types.ts +0 -4
- package/packages/web/components/StreakCard/index.ts +0 -2
- package/packages/web/components/TasksCounter/TasksCounter.tsx +0 -14
- package/packages/web/components/TasksCounter/TasksCounter.types.ts +0 -3
- package/packages/web/components/TasksCounter/index.ts +0 -2
- package/packages/web/components/TechStackBadges/TechStackBadges.tsx +0 -28
- package/packages/web/components/TechStackBadges/index.ts +0 -1
- package/packages/web/components/TerminalDock/DockToggleTab.tsx +0 -29
- package/packages/web/components/TerminalDock/TerminalDock.tsx +0 -386
- package/packages/web/components/TerminalDock/TerminalDockTab.tsx +0 -130
- package/packages/web/components/TerminalDock/TerminalTabBar.tsx +0 -142
- package/packages/web/components/TerminalDock/index.ts +0 -2
- package/packages/web/components/TerminalTabs/TerminalTab.tsx +0 -95
- package/packages/web/components/TerminalTabs/TerminalTabs.tsx +0 -211
- package/packages/web/components/TerminalTabs/index.ts +0 -1
- package/packages/web/components/VelocityBadge/VelocityBadge.tsx +0 -32
- package/packages/web/components/VelocityBadge/VelocityBadge.types.ts +0 -3
- package/packages/web/components/VelocityBadge/index.ts +0 -2
- package/packages/web/components/VelocityCard/VelocityCard.tsx +0 -73
- package/packages/web/components/VelocityCard/VelocityCard.types.ts +0 -7
- package/packages/web/components/VelocityCard/index.ts +0 -2
- package/packages/web/components/WeeklyReports/PrintableReport.tsx +0 -259
- package/packages/web/components/WeeklyReports/ReportPreviewCard.tsx +0 -187
- package/packages/web/components/WeeklyReports/WeekCalendar.tsx +0 -288
- package/packages/web/components/WeeklyReports/WeeklyReports.tsx +0 -149
- package/packages/web/components/WeeklyReports/index.ts +0 -4
- package/packages/web/components/WeeklySparkline/WeeklySparkline.tsx +0 -25
- package/packages/web/components/WeeklySparkline/WeeklySparkline.types.ts +0 -4
- package/packages/web/components/WeeklySparkline/index.ts +0 -2
- package/packages/web/components/charts/SessionsChart.tsx +0 -175
- package/packages/web/components/ui/alert-dialog.tsx +0 -157
- package/packages/web/components/ui/badge.tsx +0 -46
- package/packages/web/components/ui/button.tsx +0 -60
- package/packages/web/components/ui/card.tsx +0 -92
- package/packages/web/components/ui/chart.tsx +0 -385
- package/packages/web/components/ui/dialog.tsx +0 -143
- package/packages/web/components/ui/drawer.tsx +0 -135
- package/packages/web/components/ui/dropdown-menu.tsx +0 -257
- package/packages/web/components/ui/input.tsx +0 -21
- package/packages/web/components/ui/scroll-area.tsx +0 -58
- package/packages/web/components/ui/select.tsx +0 -187
- package/packages/web/components/ui/sheet.tsx +0 -139
- package/packages/web/components/ui/tabs.tsx +0 -66
- package/packages/web/components/ui/tooltip.tsx +0 -61
- package/packages/web/components.json +0 -22
- package/packages/web/context/GlobalTerminalContext.tsx +0 -538
- package/packages/web/context/TerminalContext.tsx +0 -45
- package/packages/web/context/TerminalTabsContext.tsx +0 -181
- package/packages/web/eslint.config.mjs +0 -18
- package/packages/web/hooks/useClaudeTerminal.ts +0 -425
- package/packages/web/hooks/useProjectStats.ts +0 -93
- package/packages/web/hooks/useProjects.ts +0 -73
- package/packages/web/lib/actions/projects.ts +0 -15
- package/packages/web/lib/commands.ts +0 -81
- package/packages/web/lib/format.ts +0 -23
- package/packages/web/lib/generate-week-report.ts +0 -285
- package/packages/web/lib/parse-prjct-files.ts +0 -1123
- package/packages/web/lib/project-colors.ts +0 -58
- package/packages/web/lib/projects.ts +0 -506
- package/packages/web/lib/pty.ts +0 -101
- package/packages/web/lib/query-config.ts +0 -44
- package/packages/web/lib/services/index.ts +0 -9
- package/packages/web/lib/services/projects.server.ts +0 -66
- package/packages/web/lib/services/stats.server.ts +0 -562
- package/packages/web/lib/unified-loader.ts +0 -396
- package/packages/web/lib/utils.ts +0 -6
- package/packages/web/next-env.d.ts +0 -6
- package/packages/web/next.config.ts +0 -7
- package/packages/web/package.json +0 -57
- package/packages/web/postcss.config.mjs +0 -7
- package/packages/web/public/file.svg +0 -1
- package/packages/web/public/globe.svg +0 -1
- package/packages/web/public/next.svg +0 -1
- package/packages/web/public/vercel.svg +0 -1
- package/packages/web/public/window.svg +0 -1
- package/packages/web/server.ts +0 -312
- package/packages/web/tsconfig.json +0 -34
- package/templates/commands/serve.md +0 -121
|
@@ -1,408 +0,0 @@
|
|
|
1
|
-
'use client'
|
|
2
|
-
|
|
3
|
-
import { useState, use, useEffect, useRef, useCallback } from 'react'
|
|
4
|
-
import { useRouter, useSearchParams } from 'next/navigation'
|
|
5
|
-
import { useProject, useDeleteProject } from '@/hooks/useProjects'
|
|
6
|
-
import { useGlobalTerminal } from '@/context/GlobalTerminalContext'
|
|
7
|
-
import { TerminalDockTab } from '@/components/TerminalDock/TerminalDockTab'
|
|
8
|
-
import { TerminalTabBar } from '@/components/TerminalDock/TerminalTabBar'
|
|
9
|
-
import { CommandBar } from '@/components/CommandBar'
|
|
10
|
-
import { Button } from '@/components/ui/button'
|
|
11
|
-
import { Badge } from '@/components/ui/badge'
|
|
12
|
-
import { TooltipProvider, Tooltip, TooltipTrigger, TooltipContent } from '@/components/ui/tooltip'
|
|
13
|
-
import {
|
|
14
|
-
AlertDialog,
|
|
15
|
-
AlertDialogAction,
|
|
16
|
-
AlertDialogCancel,
|
|
17
|
-
AlertDialogContent,
|
|
18
|
-
AlertDialogDescription,
|
|
19
|
-
AlertDialogFooter,
|
|
20
|
-
AlertDialogHeader,
|
|
21
|
-
AlertDialogTitle,
|
|
22
|
-
} from '@/components/ui/alert-dialog'
|
|
23
|
-
import { ProjectAvatar } from '@/components/ProjectAvatar'
|
|
24
|
-
import { TechStackBadges } from '@/components/TechStackBadges'
|
|
25
|
-
import { MomentumWidget } from '@/components/MomentumWidget'
|
|
26
|
-
import { formatPath } from '@/lib/format'
|
|
27
|
-
import {
|
|
28
|
-
Panel,
|
|
29
|
-
PanelGroup,
|
|
30
|
-
PanelResizeHandle,
|
|
31
|
-
} from 'react-resizable-panels'
|
|
32
|
-
import {
|
|
33
|
-
Loader2,
|
|
34
|
-
AlertTriangle,
|
|
35
|
-
Trash2,
|
|
36
|
-
ArrowLeft,
|
|
37
|
-
FolderGit2,
|
|
38
|
-
Plus,
|
|
39
|
-
Terminal,
|
|
40
|
-
SplitSquareHorizontal,
|
|
41
|
-
Minus,
|
|
42
|
-
} from 'lucide-react'
|
|
43
|
-
import { cn } from '@/lib/utils'
|
|
44
|
-
|
|
45
|
-
// Inner component that uses the terminal context
|
|
46
|
-
function ProjectPageContent({ projectId, project }: { projectId: string; project: NonNullable<ReturnType<typeof useProject>['data']> }) {
|
|
47
|
-
const router = useRouter()
|
|
48
|
-
const searchParams = useSearchParams()
|
|
49
|
-
const commandExecutedRef = useRef(false)
|
|
50
|
-
|
|
51
|
-
// Global terminal context
|
|
52
|
-
const {
|
|
53
|
-
activeSessionId,
|
|
54
|
-
secondActiveSessionId,
|
|
55
|
-
isSplitEnabled,
|
|
56
|
-
setSplitEnabled,
|
|
57
|
-
createSessionForProject,
|
|
58
|
-
getProjectSessions,
|
|
59
|
-
switchSession,
|
|
60
|
-
closeSession,
|
|
61
|
-
sendCommandToActive,
|
|
62
|
-
getActiveSession,
|
|
63
|
-
setFullScreen,
|
|
64
|
-
getAllSessions,
|
|
65
|
-
getLeftPanelSessions,
|
|
66
|
-
getRightPanelSessions,
|
|
67
|
-
updateSession,
|
|
68
|
-
} = useGlobalTerminal()
|
|
69
|
-
|
|
70
|
-
const sessions = getProjectSessions(projectId)
|
|
71
|
-
const allSessions = getAllSessions()
|
|
72
|
-
const activeSession = getActiveSession()
|
|
73
|
-
const hasActiveSessions = sessions.length > 0
|
|
74
|
-
const isActiveConnected = activeSession?.isConnected ?? false
|
|
75
|
-
|
|
76
|
-
const projectPath = project.repoPath || project.path || '/tmp'
|
|
77
|
-
const projectName = project.name || projectId
|
|
78
|
-
|
|
79
|
-
// Set full-screen mode when entering code page
|
|
80
|
-
useEffect(() => {
|
|
81
|
-
setFullScreen(true)
|
|
82
|
-
return () => setFullScreen(false)
|
|
83
|
-
}, [setFullScreen])
|
|
84
|
-
|
|
85
|
-
// Handle new terminal - creates session directly in the specified panel
|
|
86
|
-
const handleNewTerminal = useCallback((panel: 'left' | 'right' = 'left') => {
|
|
87
|
-
createSessionForProject(projectId, projectName, projectPath, panel)
|
|
88
|
-
}, [projectId, projectName, projectPath, createSessionForProject])
|
|
89
|
-
|
|
90
|
-
// Handle close session
|
|
91
|
-
const handleCloseSession = useCallback((sessionId: string) => {
|
|
92
|
-
const disconnectKey = `terminal_disconnect_${sessionId}`
|
|
93
|
-
const disconnectFn = (window as unknown as Record<string, () => void>)[disconnectKey]
|
|
94
|
-
if (disconnectFn) {
|
|
95
|
-
disconnectFn()
|
|
96
|
-
}
|
|
97
|
-
closeSession(sessionId)
|
|
98
|
-
}, [closeSession])
|
|
99
|
-
|
|
100
|
-
// Handle rename session
|
|
101
|
-
const handleRenameSession = useCallback((sessionId: string, newLabel: string) => {
|
|
102
|
-
updateSession(sessionId, { label: newLabel })
|
|
103
|
-
}, [updateSession])
|
|
104
|
-
|
|
105
|
-
// Auto-execute command from URL param (e.g., ?cmd=p.%20done)
|
|
106
|
-
useEffect(() => {
|
|
107
|
-
const cmd = searchParams.get('cmd')
|
|
108
|
-
if (cmd && isActiveConnected && !commandExecutedRef.current) {
|
|
109
|
-
commandExecutedRef.current = true
|
|
110
|
-
const decoded = decodeURIComponent(cmd)
|
|
111
|
-
setTimeout(() => {
|
|
112
|
-
sendCommandToActive(decoded)
|
|
113
|
-
router.replace(`/project/${projectId}/code`)
|
|
114
|
-
}, 500)
|
|
115
|
-
}
|
|
116
|
-
}, [searchParams, isActiveConnected, sendCommandToActive, router, projectId])
|
|
117
|
-
|
|
118
|
-
// Terminal content with split support
|
|
119
|
-
const TerminalContent = (
|
|
120
|
-
<div className="flex-1 relative overflow-hidden">
|
|
121
|
-
{allSessions.length === 0 ? (
|
|
122
|
-
<div className="flex flex-col items-center justify-center h-full text-muted-foreground gap-4">
|
|
123
|
-
<Terminal className="w-12 h-12 opacity-50" />
|
|
124
|
-
<div className="text-center">
|
|
125
|
-
<p className="text-lg font-medium">No terminal sessions</p>
|
|
126
|
-
<p className="text-sm">Open a terminal to get started</p>
|
|
127
|
-
</div>
|
|
128
|
-
<button
|
|
129
|
-
onClick={() => handleNewTerminal('left')}
|
|
130
|
-
className="flex items-center gap-2 px-4 py-2 rounded-lg bg-orange-500 hover:bg-orange-600 text-white transition-colors"
|
|
131
|
-
>
|
|
132
|
-
<Plus className="w-4 h-4" />
|
|
133
|
-
Open Terminal
|
|
134
|
-
</button>
|
|
135
|
-
</div>
|
|
136
|
-
) : isSplitEnabled ? (
|
|
137
|
-
<PanelGroup direction="horizontal">
|
|
138
|
-
<Panel defaultSize={50} minSize={20}>
|
|
139
|
-
<div className="h-full flex flex-col">
|
|
140
|
-
<div className="border-b border-border bg-muted/30">
|
|
141
|
-
<TerminalTabBar
|
|
142
|
-
sessions={getLeftPanelSessions()}
|
|
143
|
-
activeSessionId={activeSessionId}
|
|
144
|
-
onSwitchSession={(id) => switchSession(id, 'left')}
|
|
145
|
-
onCloseSession={handleCloseSession}
|
|
146
|
-
onNewTerminal={() => handleNewTerminal('left')}
|
|
147
|
-
onRenameSession={handleRenameSession}
|
|
148
|
-
/>
|
|
149
|
-
</div>
|
|
150
|
-
<div className="flex-1 relative">
|
|
151
|
-
{getLeftPanelSessions().length > 0 ? (
|
|
152
|
-
getLeftPanelSessions().map((session) => (
|
|
153
|
-
<TerminalDockTab
|
|
154
|
-
key={session.id}
|
|
155
|
-
session={session}
|
|
156
|
-
isActive={session.id === activeSessionId}
|
|
157
|
-
/>
|
|
158
|
-
))
|
|
159
|
-
) : (
|
|
160
|
-
<div className="absolute inset-0 flex items-center justify-center bg-card/95 text-muted-foreground text-sm">
|
|
161
|
-
<button
|
|
162
|
-
onClick={() => handleNewTerminal('left')}
|
|
163
|
-
className="text-orange-500 hover:text-orange-400 underline"
|
|
164
|
-
>
|
|
165
|
-
Open terminal in left panel
|
|
166
|
-
</button>
|
|
167
|
-
</div>
|
|
168
|
-
)}
|
|
169
|
-
</div>
|
|
170
|
-
</div>
|
|
171
|
-
</Panel>
|
|
172
|
-
|
|
173
|
-
<PanelResizeHandle className="w-1 bg-border hover:bg-orange-500/50 transition-colors" />
|
|
174
|
-
|
|
175
|
-
<Panel defaultSize={50} minSize={20}>
|
|
176
|
-
<div className="h-full flex flex-col">
|
|
177
|
-
<div className="border-b border-border bg-muted/30">
|
|
178
|
-
<TerminalTabBar
|
|
179
|
-
sessions={getRightPanelSessions()}
|
|
180
|
-
activeSessionId={secondActiveSessionId}
|
|
181
|
-
onSwitchSession={(id) => switchSession(id, 'right')}
|
|
182
|
-
onCloseSession={handleCloseSession}
|
|
183
|
-
onNewTerminal={() => handleNewTerminal('right')}
|
|
184
|
-
onRenameSession={handleRenameSession}
|
|
185
|
-
/>
|
|
186
|
-
</div>
|
|
187
|
-
<div className="flex-1 relative">
|
|
188
|
-
{getRightPanelSessions().length > 0 ? (
|
|
189
|
-
getRightPanelSessions().map((session) => (
|
|
190
|
-
<TerminalDockTab
|
|
191
|
-
key={`right-${session.id}`}
|
|
192
|
-
session={session}
|
|
193
|
-
isActive={session.id === secondActiveSessionId}
|
|
194
|
-
/>
|
|
195
|
-
))
|
|
196
|
-
) : (
|
|
197
|
-
<div className="absolute inset-0 flex items-center justify-center bg-card/95 text-muted-foreground text-sm">
|
|
198
|
-
<button
|
|
199
|
-
onClick={() => handleNewTerminal('right')}
|
|
200
|
-
className="text-orange-500 hover:text-orange-400 underline"
|
|
201
|
-
>
|
|
202
|
-
Open terminal in right panel
|
|
203
|
-
</button>
|
|
204
|
-
</div>
|
|
205
|
-
)}
|
|
206
|
-
</div>
|
|
207
|
-
</div>
|
|
208
|
-
</Panel>
|
|
209
|
-
</PanelGroup>
|
|
210
|
-
) : (
|
|
211
|
-
<div className="h-full flex flex-col">
|
|
212
|
-
<div className="border-b border-border bg-muted/30">
|
|
213
|
-
<TerminalTabBar
|
|
214
|
-
sessions={allSessions}
|
|
215
|
-
activeSessionId={activeSessionId}
|
|
216
|
-
onSwitchSession={(id) => switchSession(id)}
|
|
217
|
-
onCloseSession={handleCloseSession}
|
|
218
|
-
onNewTerminal={() => handleNewTerminal('left')}
|
|
219
|
-
onRenameSession={handleRenameSession}
|
|
220
|
-
/>
|
|
221
|
-
</div>
|
|
222
|
-
<div className="flex-1 relative">
|
|
223
|
-
{allSessions.map((session) => (
|
|
224
|
-
<TerminalDockTab
|
|
225
|
-
key={session.id}
|
|
226
|
-
session={session}
|
|
227
|
-
isActive={session.id === activeSessionId}
|
|
228
|
-
/>
|
|
229
|
-
))}
|
|
230
|
-
</div>
|
|
231
|
-
</div>
|
|
232
|
-
)}
|
|
233
|
-
</div>
|
|
234
|
-
)
|
|
235
|
-
|
|
236
|
-
return (
|
|
237
|
-
<div className="h-full">
|
|
238
|
-
<TooltipProvider>
|
|
239
|
-
<div className="flex flex-col h-full">
|
|
240
|
-
{/* Header - Responsive */}
|
|
241
|
-
<header className="h-auto md:h-14 flex flex-col md:flex-row md:items-center justify-between px-3 md:px-4 py-2 md:py-0 border-b border-border bg-card gap-2">
|
|
242
|
-
{/* Left: Project info */}
|
|
243
|
-
<div className="flex items-center gap-3">
|
|
244
|
-
<ProjectAvatar
|
|
245
|
-
projectId={projectId}
|
|
246
|
-
name={project.name || projectId}
|
|
247
|
-
iconPath={project.iconPath}
|
|
248
|
-
size="sm"
|
|
249
|
-
/>
|
|
250
|
-
<div className="flex flex-col min-w-0">
|
|
251
|
-
<div className="flex items-center gap-2">
|
|
252
|
-
<span className="font-bold leading-tight truncate">{project.name || projectId}</span>
|
|
253
|
-
{project.version && (
|
|
254
|
-
<Badge variant="outline" className="text-[10px] px-1.5 py-0 font-mono shrink-0">
|
|
255
|
-
v{project.version}
|
|
256
|
-
</Badge>
|
|
257
|
-
)}
|
|
258
|
-
</div>
|
|
259
|
-
{project.repoPath && (
|
|
260
|
-
<span className="text-xs text-muted-foreground leading-tight flex items-center gap-1 truncate">
|
|
261
|
-
<FolderGit2 className="w-3 h-3 shrink-0" />
|
|
262
|
-
<span className="truncate">{formatPath(project.repoPath)}</span>
|
|
263
|
-
</span>
|
|
264
|
-
)}
|
|
265
|
-
</div>
|
|
266
|
-
{hasActiveSessions && (
|
|
267
|
-
<Badge variant="outline" className="text-green-500 border-green-500/50 shrink-0">
|
|
268
|
-
{sessions.filter(s => s.isConnected).length} active
|
|
269
|
-
</Badge>
|
|
270
|
-
)}
|
|
271
|
-
</div>
|
|
272
|
-
|
|
273
|
-
{/* Center: Momentum widget - desktop only */}
|
|
274
|
-
<div className="hidden md:flex items-center justify-center flex-1">
|
|
275
|
-
<MomentumWidget projectId={projectId} />
|
|
276
|
-
</div>
|
|
277
|
-
|
|
278
|
-
{/* Right: metadata and tech stack - desktop only */}
|
|
279
|
-
<div className="hidden md:flex items-center gap-4">
|
|
280
|
-
<div className="flex items-center gap-3 text-xs text-muted-foreground">
|
|
281
|
-
{project.filesCount && (
|
|
282
|
-
<span><span className="font-medium text-foreground">{project.filesCount}</span> files</span>
|
|
283
|
-
)}
|
|
284
|
-
{project.commitsCount && (
|
|
285
|
-
<span><span className="font-medium text-foreground">{project.commitsCount}</span> commits</span>
|
|
286
|
-
)}
|
|
287
|
-
</div>
|
|
288
|
-
<TechStackBadges techStack={project.techStack || []} />
|
|
289
|
-
</div>
|
|
290
|
-
</header>
|
|
291
|
-
|
|
292
|
-
{/* Command bar + actions - SAME AS DOCK */}
|
|
293
|
-
<div className="flex items-center justify-between border-b border-border bg-card/95 shrink-0">
|
|
294
|
-
<CommandBar isConnected={isActiveConnected} onCommand={sendCommandToActive} />
|
|
295
|
-
|
|
296
|
-
{/* Header actions: split toggle, back button */}
|
|
297
|
-
<div className="flex items-center gap-1 px-2">
|
|
298
|
-
<Tooltip>
|
|
299
|
-
<TooltipTrigger asChild>
|
|
300
|
-
<button
|
|
301
|
-
onClick={() => setSplitEnabled(!isSplitEnabled)}
|
|
302
|
-
className={cn(
|
|
303
|
-
'p-1.5 rounded transition-colors',
|
|
304
|
-
isSplitEnabled
|
|
305
|
-
? 'bg-accent text-accent-foreground'
|
|
306
|
-
: 'text-muted-foreground hover:bg-accent hover:text-accent-foreground'
|
|
307
|
-
)}
|
|
308
|
-
>
|
|
309
|
-
<SplitSquareHorizontal className="w-4 h-4" />
|
|
310
|
-
</button>
|
|
311
|
-
</TooltipTrigger>
|
|
312
|
-
<TooltipContent>{isSplitEnabled ? 'Single view' : 'Split view'}</TooltipContent>
|
|
313
|
-
</Tooltip>
|
|
314
|
-
|
|
315
|
-
<Tooltip>
|
|
316
|
-
<TooltipTrigger asChild>
|
|
317
|
-
<button
|
|
318
|
-
onClick={() => router.push(`/project/${projectId}`)}
|
|
319
|
-
className="p-1.5 rounded text-muted-foreground hover:bg-accent hover:text-accent-foreground transition-colors"
|
|
320
|
-
>
|
|
321
|
-
<Minus className="w-4 h-4" />
|
|
322
|
-
</button>
|
|
323
|
-
</TooltipTrigger>
|
|
324
|
-
<TooltipContent>Back to project</TooltipContent>
|
|
325
|
-
</Tooltip>
|
|
326
|
-
</div>
|
|
327
|
-
</div>
|
|
328
|
-
|
|
329
|
-
{/* Terminal content area */}
|
|
330
|
-
{TerminalContent}
|
|
331
|
-
</div>
|
|
332
|
-
</TooltipProvider>
|
|
333
|
-
</div>
|
|
334
|
-
)
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
export default function ProjectPage({ params }: { params: Promise<{ id: string }> }) {
|
|
338
|
-
const { id: projectId } = use(params)
|
|
339
|
-
const router = useRouter()
|
|
340
|
-
const [showDeleteConfirm, setShowDeleteConfirm] = useState(false)
|
|
341
|
-
|
|
342
|
-
const { data: project, isLoading: projectLoading } = useProject(projectId)
|
|
343
|
-
const deleteMutation = useDeleteProject()
|
|
344
|
-
|
|
345
|
-
if (projectLoading) {
|
|
346
|
-
return (
|
|
347
|
-
<div className="flex items-center justify-center h-full">
|
|
348
|
-
<Loader2 className="w-8 h-8 animate-spin text-muted-foreground" />
|
|
349
|
-
</div>
|
|
350
|
-
)
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
if (!project) {
|
|
354
|
-
return (
|
|
355
|
-
<div className="flex items-center justify-center h-full p-4">
|
|
356
|
-
<div className="text-center space-y-4 max-w-sm">
|
|
357
|
-
<div className="w-16 h-16 rounded-full bg-muted flex items-center justify-center mx-auto">
|
|
358
|
-
<AlertTriangle className="w-8 h-8 text-muted-foreground" />
|
|
359
|
-
</div>
|
|
360
|
-
<div>
|
|
361
|
-
<h2 className="text-lg font-medium">Project not found</h2>
|
|
362
|
-
<p className="text-sm text-muted-foreground mt-1 break-all">ID: {projectId}</p>
|
|
363
|
-
</div>
|
|
364
|
-
<div className="flex flex-col sm:flex-row gap-2 justify-center">
|
|
365
|
-
<Button variant="outline" onClick={() => router.push('/')}>
|
|
366
|
-
<ArrowLeft className="w-4 h-4 mr-2" />
|
|
367
|
-
Back to Dashboard
|
|
368
|
-
</Button>
|
|
369
|
-
<Button variant="destructive" onClick={() => setShowDeleteConfirm(true)}>
|
|
370
|
-
<Trash2 className="w-4 h-4 mr-2" />
|
|
371
|
-
Delete from Storage
|
|
372
|
-
</Button>
|
|
373
|
-
</div>
|
|
374
|
-
|
|
375
|
-
<AlertDialog open={showDeleteConfirm} onOpenChange={setShowDeleteConfirm}>
|
|
376
|
-
<AlertDialogContent className="max-w-[calc(100vw-2rem)] sm:max-w-lg">
|
|
377
|
-
<AlertDialogHeader>
|
|
378
|
-
<AlertDialogTitle className="flex items-center gap-2">
|
|
379
|
-
<AlertTriangle className="w-5 h-5 text-destructive" />
|
|
380
|
-
Delete Project Data?
|
|
381
|
-
</AlertDialogTitle>
|
|
382
|
-
<AlertDialogDescription>
|
|
383
|
-
This will move the project storage to trash.
|
|
384
|
-
<br />
|
|
385
|
-
<span className="text-muted-foreground text-sm break-all">ID: {projectId}</span>
|
|
386
|
-
</AlertDialogDescription>
|
|
387
|
-
</AlertDialogHeader>
|
|
388
|
-
<AlertDialogFooter className="flex-col sm:flex-row gap-2">
|
|
389
|
-
<AlertDialogCancel disabled={deleteMutation.isPending} className="w-full sm:w-auto">
|
|
390
|
-
Cancel
|
|
391
|
-
</AlertDialogCancel>
|
|
392
|
-
<AlertDialogAction
|
|
393
|
-
onClick={() => deleteMutation.mutate(projectId, { onSuccess: () => router.push('/') })}
|
|
394
|
-
disabled={deleteMutation.isPending}
|
|
395
|
-
className="bg-destructive text-destructive-foreground hover:bg-destructive/90 w-full sm:w-auto"
|
|
396
|
-
>
|
|
397
|
-
{deleteMutation.isPending ? 'Deleting...' : 'Delete'}
|
|
398
|
-
</AlertDialogAction>
|
|
399
|
-
</AlertDialogFooter>
|
|
400
|
-
</AlertDialogContent>
|
|
401
|
-
</AlertDialog>
|
|
402
|
-
</div>
|
|
403
|
-
</div>
|
|
404
|
-
)
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
return <ProjectPageContent projectId={projectId} project={project} />
|
|
408
|
-
}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
'use client'
|
|
2
|
-
|
|
3
|
-
import { useEffect } from 'react'
|
|
4
|
-
import { useRouter } from 'next/navigation'
|
|
5
|
-
import { Button } from '@/components/ui/button'
|
|
6
|
-
import { AlertTriangle, ArrowLeft } from 'lucide-react'
|
|
7
|
-
|
|
8
|
-
export default function ProjectError({
|
|
9
|
-
error,
|
|
10
|
-
reset,
|
|
11
|
-
}: {
|
|
12
|
-
error: Error & { digest?: string }
|
|
13
|
-
reset: () => void
|
|
14
|
-
}) {
|
|
15
|
-
const router = useRouter()
|
|
16
|
-
|
|
17
|
-
useEffect(() => {
|
|
18
|
-
console.error(error)
|
|
19
|
-
}, [error])
|
|
20
|
-
|
|
21
|
-
return (
|
|
22
|
-
<div className="flex items-center justify-center h-full">
|
|
23
|
-
<div className="text-center space-y-4">
|
|
24
|
-
<div className="w-16 h-16 rounded-full bg-destructive/10 flex items-center justify-center mx-auto">
|
|
25
|
-
<AlertTriangle className="w-8 h-8 text-destructive" />
|
|
26
|
-
</div>
|
|
27
|
-
<div>
|
|
28
|
-
<h2 className="text-lg font-medium">Failed to load project</h2>
|
|
29
|
-
<p className="text-sm text-muted-foreground mt-1">{error.message}</p>
|
|
30
|
-
</div>
|
|
31
|
-
<div className="flex gap-2 justify-center">
|
|
32
|
-
<Button onClick={() => router.push('/')} variant="outline">
|
|
33
|
-
<ArrowLeft className="w-4 h-4 mr-2" />
|
|
34
|
-
Dashboard
|
|
35
|
-
</Button>
|
|
36
|
-
<Button onClick={reset}>Try again</Button>
|
|
37
|
-
</div>
|
|
38
|
-
</div>
|
|
39
|
-
</div>
|
|
40
|
-
)
|
|
41
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import Link from 'next/link'
|
|
2
|
-
import { Button } from '@/components/ui/button'
|
|
3
|
-
import { FolderX, ArrowLeft } from 'lucide-react'
|
|
4
|
-
|
|
5
|
-
export default function ProjectNotFound() {
|
|
6
|
-
return (
|
|
7
|
-
<div className="flex items-center justify-center h-full">
|
|
8
|
-
<div className="text-center space-y-4">
|
|
9
|
-
<div className="w-16 h-16 rounded-full bg-muted flex items-center justify-center mx-auto">
|
|
10
|
-
<FolderX className="w-8 h-8 text-muted-foreground" />
|
|
11
|
-
</div>
|
|
12
|
-
<div>
|
|
13
|
-
<h2 className="text-lg font-medium">Project not found</h2>
|
|
14
|
-
<p className="text-sm text-muted-foreground mt-1">
|
|
15
|
-
This project may have been deleted or moved.
|
|
16
|
-
</p>
|
|
17
|
-
</div>
|
|
18
|
-
<Button asChild variant="outline">
|
|
19
|
-
<Link href="/">
|
|
20
|
-
<ArrowLeft className="w-4 h-4 mr-2" />
|
|
21
|
-
Back to Dashboard
|
|
22
|
-
</Link>
|
|
23
|
-
</Button>
|
|
24
|
-
</div>
|
|
25
|
-
</div>
|
|
26
|
-
)
|
|
27
|
-
}
|