prjct-cli 0.18.1 → 0.19.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.
Files changed (245) hide show
  1. package/CHANGELOG.md +53 -0
  2. package/CLAUDE.md +74 -211
  3. package/core/agentic/prompt-builder.ts +3 -7
  4. package/core/command-registry/optional-commands.ts +0 -20
  5. package/core/infrastructure/command-installer/command-installer.ts +8 -1
  6. package/core/infrastructure/command-installer/global-config.ts +31 -1
  7. package/core/infrastructure/command-installer/index.ts +1 -1
  8. package/core/infrastructure/setup.ts +3 -0
  9. package/package.json +3 -17
  10. package/templates/agentic/subagent-generation.md +8 -6
  11. package/templates/commands/done.md +57 -258
  12. package/templates/commands/now.md +72 -277
  13. package/templates/commands/ship.md +55 -261
  14. package/templates/commands/sync.md +7 -7
  15. package/templates/commands/test.md +328 -21
  16. package/templates/global/CLAUDE.md +40 -205
  17. package/templates/global/docs/agents.md +88 -0
  18. package/templates/global/docs/architecture.md +103 -0
  19. package/templates/global/docs/commands.md +98 -0
  20. package/templates/global/docs/validation.md +95 -0
  21. package/templates/mcp-config.json +36 -0
  22. package/bin/dev.js +0 -216
  23. package/bin/serve.js +0 -361
  24. package/packages/web/README.md +0 -36
  25. package/packages/web/app/api/claude/sessions/route.ts +0 -44
  26. package/packages/web/app/api/claude/status/route.ts +0 -34
  27. package/packages/web/app/api/projects/[id]/icon/route.ts +0 -33
  28. package/packages/web/app/api/projects/[id]/momentum/route.ts +0 -257
  29. package/packages/web/app/api/projects/[id]/route.ts +0 -29
  30. package/packages/web/app/api/projects/[id]/stats/route.ts +0 -41
  31. package/packages/web/app/api/projects/[id]/status/route.ts +0 -21
  32. package/packages/web/app/api/projects/route.ts +0 -16
  33. package/packages/web/app/api/sessions/current/route.ts +0 -132
  34. package/packages/web/app/api/sessions/history/route.ts +0 -204
  35. package/packages/web/app/error.tsx +0 -34
  36. package/packages/web/app/favicon.ico +0 -0
  37. package/packages/web/app/globals.css +0 -198
  38. package/packages/web/app/layout.tsx +0 -53
  39. package/packages/web/app/loading.tsx +0 -7
  40. package/packages/web/app/not-found.tsx +0 -25
  41. package/packages/web/app/page.tsx +0 -12
  42. package/packages/web/app/project/[id]/code/layout.tsx +0 -18
  43. package/packages/web/app/project/[id]/code/page.tsx +0 -408
  44. package/packages/web/app/project/[id]/error.tsx +0 -41
  45. package/packages/web/app/project/[id]/loading.tsx +0 -9
  46. package/packages/web/app/project/[id]/not-found.tsx +0 -27
  47. package/packages/web/app/project/[id]/page.tsx +0 -384
  48. package/packages/web/app/project/[id]/reports/page.tsx +0 -59
  49. package/packages/web/app/project/[id]/reports/print/page.tsx +0 -58
  50. package/packages/web/app/sessions/page.tsx +0 -165
  51. package/packages/web/app/settings/page.tsx +0 -151
  52. package/packages/web/components/ActivityTimeline/ActivityTimeline.constants.ts +0 -2
  53. package/packages/web/components/ActivityTimeline/ActivityTimeline.tsx +0 -49
  54. package/packages/web/components/ActivityTimeline/ActivityTimeline.types.ts +0 -8
  55. package/packages/web/components/ActivityTimeline/hooks/index.ts +0 -2
  56. package/packages/web/components/ActivityTimeline/hooks/useExpandable.ts +0 -9
  57. package/packages/web/components/ActivityTimeline/hooks/useGroupedEvents.ts +0 -23
  58. package/packages/web/components/ActivityTimeline/index.ts +0 -2
  59. package/packages/web/components/AgentsCard/AgentsCard.tsx +0 -93
  60. package/packages/web/components/AgentsCard/AgentsCard.types.ts +0 -14
  61. package/packages/web/components/AgentsCard/index.ts +0 -2
  62. package/packages/web/components/AppSidebar/AppSidebar.tsx +0 -316
  63. package/packages/web/components/AppSidebar/index.ts +0 -1
  64. package/packages/web/components/BackLink/BackLink.tsx +0 -18
  65. package/packages/web/components/BackLink/BackLink.types.ts +0 -5
  66. package/packages/web/components/BackLink/index.ts +0 -2
  67. package/packages/web/components/BentoCard/BentoCard.constants.ts +0 -16
  68. package/packages/web/components/BentoCard/BentoCard.tsx +0 -48
  69. package/packages/web/components/BentoCard/BentoCard.types.ts +0 -15
  70. package/packages/web/components/BentoCard/index.ts +0 -2
  71. package/packages/web/components/BentoCardSkeleton/BentoCardSkeleton.constants.ts +0 -9
  72. package/packages/web/components/BentoCardSkeleton/BentoCardSkeleton.tsx +0 -18
  73. package/packages/web/components/BentoCardSkeleton/BentoCardSkeleton.types.ts +0 -5
  74. package/packages/web/components/BentoCardSkeleton/index.ts +0 -2
  75. package/packages/web/components/BentoGrid/BentoGrid.tsx +0 -18
  76. package/packages/web/components/BentoGrid/BentoGrid.types.ts +0 -4
  77. package/packages/web/components/BentoGrid/index.ts +0 -2
  78. package/packages/web/components/BlockersCard/BlockersCard.tsx +0 -75
  79. package/packages/web/components/BlockersCard/BlockersCard.types.ts +0 -12
  80. package/packages/web/components/BlockersCard/index.ts +0 -2
  81. package/packages/web/components/CommandBar/CommandBar.tsx +0 -67
  82. package/packages/web/components/CommandBar/index.ts +0 -1
  83. package/packages/web/components/CommandButton/CommandButton.tsx +0 -46
  84. package/packages/web/components/CommandButton/index.ts +0 -1
  85. package/packages/web/components/ConnectionStatus/ConnectionStatus.tsx +0 -29
  86. package/packages/web/components/ConnectionStatus/index.ts +0 -1
  87. package/packages/web/components/DashboardContent/DashboardContent.tsx +0 -284
  88. package/packages/web/components/DashboardContent/index.ts +0 -1
  89. package/packages/web/components/DateGroup/DateGroup.tsx +0 -18
  90. package/packages/web/components/DateGroup/DateGroup.types.ts +0 -6
  91. package/packages/web/components/DateGroup/DateGroup.utils.ts +0 -11
  92. package/packages/web/components/DateGroup/index.ts +0 -2
  93. package/packages/web/components/EmptyState/EmptyState.tsx +0 -76
  94. package/packages/web/components/EmptyState/EmptyState.types.ts +0 -11
  95. package/packages/web/components/EmptyState/index.ts +0 -2
  96. package/packages/web/components/EventRow/EventRow.constants.ts +0 -10
  97. package/packages/web/components/EventRow/EventRow.tsx +0 -49
  98. package/packages/web/components/EventRow/EventRow.types.ts +0 -7
  99. package/packages/web/components/EventRow/EventRow.utils.ts +0 -49
  100. package/packages/web/components/EventRow/index.ts +0 -2
  101. package/packages/web/components/ExpandButton/ExpandButton.tsx +0 -18
  102. package/packages/web/components/ExpandButton/ExpandButton.types.ts +0 -6
  103. package/packages/web/components/ExpandButton/index.ts +0 -2
  104. package/packages/web/components/HealthGradientBackground/HealthGradientBackground.tsx +0 -14
  105. package/packages/web/components/HealthGradientBackground/HealthGradientBackground.types.ts +0 -5
  106. package/packages/web/components/HealthGradientBackground/HealthGradientBackground.utils.ts +0 -13
  107. package/packages/web/components/HealthGradientBackground/index.ts +0 -2
  108. package/packages/web/components/HeroSection/HeroSection.tsx +0 -92
  109. package/packages/web/components/HeroSection/HeroSection.types.ts +0 -14
  110. package/packages/web/components/HeroSection/HeroSection.utils.ts +0 -11
  111. package/packages/web/components/HeroSection/hooks/index.ts +0 -2
  112. package/packages/web/components/HeroSection/hooks/useCountUp.ts +0 -45
  113. package/packages/web/components/HeroSection/hooks/useWeeklyActivity.ts +0 -18
  114. package/packages/web/components/HeroSection/index.ts +0 -2
  115. package/packages/web/components/IdeasCard/IdeasCard.tsx +0 -115
  116. package/packages/web/components/IdeasCard/IdeasCard.types.ts +0 -10
  117. package/packages/web/components/IdeasCard/index.ts +0 -2
  118. package/packages/web/components/InsightMessage/InsightMessage.tsx +0 -9
  119. package/packages/web/components/InsightMessage/InsightMessage.types.ts +0 -3
  120. package/packages/web/components/InsightMessage/index.ts +0 -2
  121. package/packages/web/components/Logo/Logo.tsx +0 -65
  122. package/packages/web/components/Logo/index.ts +0 -1
  123. package/packages/web/components/MarkdownContent/MarkdownContent.tsx +0 -123
  124. package/packages/web/components/MarkdownContent/index.ts +0 -1
  125. package/packages/web/components/MasonryGrid/MasonryGrid.tsx +0 -18
  126. package/packages/web/components/MasonryGrid/index.ts +0 -1
  127. package/packages/web/components/MomentumWidget/MomentumWidget.tsx +0 -119
  128. package/packages/web/components/MomentumWidget/MomentumWidget.types.ts +0 -16
  129. package/packages/web/components/MomentumWidget/index.ts +0 -2
  130. package/packages/web/components/NowCard/NowCard.tsx +0 -118
  131. package/packages/web/components/NowCard/NowCard.types.ts +0 -16
  132. package/packages/web/components/NowCard/index.ts +0 -2
  133. package/packages/web/components/PageHeader/PageHeader.tsx +0 -24
  134. package/packages/web/components/PageHeader/index.ts +0 -1
  135. package/packages/web/components/ProgressRing/ProgressRing.constants.ts +0 -20
  136. package/packages/web/components/ProgressRing/ProgressRing.tsx +0 -51
  137. package/packages/web/components/ProgressRing/ProgressRing.types.ts +0 -11
  138. package/packages/web/components/ProgressRing/index.ts +0 -2
  139. package/packages/web/components/ProjectAvatar/ProjectAvatar.tsx +0 -54
  140. package/packages/web/components/ProjectAvatar/index.ts +0 -1
  141. package/packages/web/components/ProjectColorDot/ProjectColorDot.tsx +0 -37
  142. package/packages/web/components/ProjectColorDot/index.ts +0 -1
  143. package/packages/web/components/ProjectSelectorModal/ProjectSelectorModal.tsx +0 -104
  144. package/packages/web/components/ProjectSelectorModal/index.ts +0 -1
  145. package/packages/web/components/Providers/Providers.tsx +0 -48
  146. package/packages/web/components/Providers/index.ts +0 -1
  147. package/packages/web/components/QueueCard/QueueCard.tsx +0 -125
  148. package/packages/web/components/QueueCard/QueueCard.types.ts +0 -12
  149. package/packages/web/components/QueueCard/QueueCard.utils.ts +0 -12
  150. package/packages/web/components/QueueCard/index.ts +0 -2
  151. package/packages/web/components/RecoverCard/RecoverCard.tsx +0 -72
  152. package/packages/web/components/RecoverCard/RecoverCard.types.ts +0 -16
  153. package/packages/web/components/RecoverCard/index.ts +0 -2
  154. package/packages/web/components/RoadmapCard/RoadmapCard.tsx +0 -145
  155. package/packages/web/components/RoadmapCard/RoadmapCard.types.ts +0 -16
  156. package/packages/web/components/RoadmapCard/index.ts +0 -2
  157. package/packages/web/components/ShipsCard/ShipsCard.tsx +0 -95
  158. package/packages/web/components/ShipsCard/ShipsCard.types.ts +0 -14
  159. package/packages/web/components/ShipsCard/ShipsCard.utils.ts +0 -4
  160. package/packages/web/components/ShipsCard/index.ts +0 -2
  161. package/packages/web/components/SparklineChart/SparklineChart.tsx +0 -40
  162. package/packages/web/components/SparklineChart/SparklineChart.types.ts +0 -6
  163. package/packages/web/components/SparklineChart/index.ts +0 -2
  164. package/packages/web/components/StatsMasonry/StatsMasonry.tsx +0 -95
  165. package/packages/web/components/StatsMasonry/index.ts +0 -1
  166. package/packages/web/components/StreakCard/StreakCard.constants.ts +0 -2
  167. package/packages/web/components/StreakCard/StreakCard.tsx +0 -55
  168. package/packages/web/components/StreakCard/StreakCard.types.ts +0 -4
  169. package/packages/web/components/StreakCard/index.ts +0 -2
  170. package/packages/web/components/TasksCounter/TasksCounter.tsx +0 -14
  171. package/packages/web/components/TasksCounter/TasksCounter.types.ts +0 -3
  172. package/packages/web/components/TasksCounter/index.ts +0 -2
  173. package/packages/web/components/TechStackBadges/TechStackBadges.tsx +0 -28
  174. package/packages/web/components/TechStackBadges/index.ts +0 -1
  175. package/packages/web/components/TerminalDock/DockToggleTab.tsx +0 -29
  176. package/packages/web/components/TerminalDock/TerminalDock.tsx +0 -386
  177. package/packages/web/components/TerminalDock/TerminalDockTab.tsx +0 -130
  178. package/packages/web/components/TerminalDock/TerminalTabBar.tsx +0 -142
  179. package/packages/web/components/TerminalDock/index.ts +0 -2
  180. package/packages/web/components/TerminalTabs/TerminalTab.tsx +0 -95
  181. package/packages/web/components/TerminalTabs/TerminalTabs.tsx +0 -211
  182. package/packages/web/components/TerminalTabs/index.ts +0 -1
  183. package/packages/web/components/VelocityBadge/VelocityBadge.tsx +0 -32
  184. package/packages/web/components/VelocityBadge/VelocityBadge.types.ts +0 -3
  185. package/packages/web/components/VelocityBadge/index.ts +0 -2
  186. package/packages/web/components/VelocityCard/VelocityCard.tsx +0 -73
  187. package/packages/web/components/VelocityCard/VelocityCard.types.ts +0 -7
  188. package/packages/web/components/VelocityCard/index.ts +0 -2
  189. package/packages/web/components/WeeklyReports/PrintableReport.tsx +0 -259
  190. package/packages/web/components/WeeklyReports/ReportPreviewCard.tsx +0 -187
  191. package/packages/web/components/WeeklyReports/WeekCalendar.tsx +0 -288
  192. package/packages/web/components/WeeklyReports/WeeklyReports.tsx +0 -149
  193. package/packages/web/components/WeeklyReports/index.ts +0 -4
  194. package/packages/web/components/WeeklySparkline/WeeklySparkline.tsx +0 -25
  195. package/packages/web/components/WeeklySparkline/WeeklySparkline.types.ts +0 -4
  196. package/packages/web/components/WeeklySparkline/index.ts +0 -2
  197. package/packages/web/components/charts/SessionsChart.tsx +0 -175
  198. package/packages/web/components/ui/alert-dialog.tsx +0 -157
  199. package/packages/web/components/ui/badge.tsx +0 -46
  200. package/packages/web/components/ui/button.tsx +0 -60
  201. package/packages/web/components/ui/card.tsx +0 -92
  202. package/packages/web/components/ui/chart.tsx +0 -385
  203. package/packages/web/components/ui/dialog.tsx +0 -143
  204. package/packages/web/components/ui/drawer.tsx +0 -135
  205. package/packages/web/components/ui/dropdown-menu.tsx +0 -257
  206. package/packages/web/components/ui/input.tsx +0 -21
  207. package/packages/web/components/ui/scroll-area.tsx +0 -58
  208. package/packages/web/components/ui/select.tsx +0 -187
  209. package/packages/web/components/ui/sheet.tsx +0 -139
  210. package/packages/web/components/ui/tabs.tsx +0 -66
  211. package/packages/web/components/ui/tooltip.tsx +0 -61
  212. package/packages/web/components.json +0 -22
  213. package/packages/web/context/GlobalTerminalContext.tsx +0 -538
  214. package/packages/web/context/TerminalContext.tsx +0 -45
  215. package/packages/web/context/TerminalTabsContext.tsx +0 -181
  216. package/packages/web/eslint.config.mjs +0 -18
  217. package/packages/web/hooks/useClaudeTerminal.ts +0 -425
  218. package/packages/web/hooks/useProjectStats.ts +0 -93
  219. package/packages/web/hooks/useProjects.ts +0 -73
  220. package/packages/web/lib/actions/projects.ts +0 -15
  221. package/packages/web/lib/commands.ts +0 -81
  222. package/packages/web/lib/format.ts +0 -23
  223. package/packages/web/lib/generate-week-report.ts +0 -285
  224. package/packages/web/lib/parse-prjct-files.ts +0 -1123
  225. package/packages/web/lib/project-colors.ts +0 -58
  226. package/packages/web/lib/projects.ts +0 -506
  227. package/packages/web/lib/pty.ts +0 -101
  228. package/packages/web/lib/query-config.ts +0 -44
  229. package/packages/web/lib/services/index.ts +0 -9
  230. package/packages/web/lib/services/projects.server.ts +0 -66
  231. package/packages/web/lib/services/stats.server.ts +0 -562
  232. package/packages/web/lib/unified-loader.ts +0 -396
  233. package/packages/web/lib/utils.ts +0 -6
  234. package/packages/web/next-env.d.ts +0 -6
  235. package/packages/web/next.config.ts +0 -7
  236. package/packages/web/package.json +0 -57
  237. package/packages/web/postcss.config.mjs +0 -7
  238. package/packages/web/public/file.svg +0 -1
  239. package/packages/web/public/globe.svg +0 -1
  240. package/packages/web/public/next.svg +0 -1
  241. package/packages/web/public/vercel.svg +0 -1
  242. package/packages/web/public/window.svg +0 -1
  243. package/packages/web/server.ts +0 -312
  244. package/packages/web/tsconfig.json +0 -34
  245. package/templates/commands/serve.md +0 -121
@@ -1,92 +0,0 @@
1
- 'use client'
2
-
3
- import Link from 'next/link'
4
- import { Play, FileText, Flame } from 'lucide-react'
5
- import { ProgressRing } from '@/components/ProgressRing'
6
- import { TasksCounter } from '@/components/TasksCounter'
7
- import { InsightMessage } from '@/components/InsightMessage'
8
- import { WeeklySparkline } from '@/components/WeeklySparkline'
9
- import { HealthGradientBackground } from '@/components/HealthGradientBackground'
10
- import { useCountUp, useWeeklyActivity } from './hooks'
11
- import { getCompletionColor } from './HeroSection.utils'
12
- import type { HeroProps } from './HeroSection.types'
13
-
14
- export function HeroSection({
15
- projectId,
16
- projectName,
17
- projectVersion,
18
- totalShips,
19
- completionRate,
20
- streak,
21
- insightMessage,
22
- timeline = [],
23
- }: HeroProps) {
24
- const animatedCount = useCountUp(totalShips)
25
- const weeklyData = useWeeklyActivity(timeline)
26
- const completionColor = getCompletionColor(completionRate)
27
-
28
- return (
29
- <div className="relative mb-6 md:mb-8">
30
- <HealthGradientBackground score={completionRate} />
31
-
32
- <div className="relative z-10 flex items-center justify-between my-16">
33
- <div className="flex items-baseline gap-3">
34
- <h1 className="text-5xl md:text-6xl font-bold tracking-tight">{projectName}</h1>
35
- {projectVersion && (
36
- <span className="text-lg md:text-xl font-mono text-muted-foreground">v{projectVersion}</span>
37
- )}
38
- </div>
39
-
40
- <div className="flex items-center gap-3">
41
- {/* Reports Link */}
42
- <Link
43
- href={`/project/${projectId}/reports`}
44
- className="inline-flex items-center gap-2 px-4 py-3 bg-muted hover:bg-muted/80 text-foreground font-medium rounded-xl transition-all duration-200 hover:scale-105"
45
- >
46
- <FileText className="h-5 w-5" />
47
- <span>Reports</span>
48
- </Link>
49
-
50
- {/* Start Working CTA */}
51
- <Link
52
- href={`/project/${projectId}/code`}
53
- className="group relative inline-flex items-center gap-2 px-6 py-3 bg-emerald-500 hover:bg-emerald-600 text-white font-semibold rounded-xl shadow-lg shadow-emerald-500/25 hover:shadow-emerald-500/40 transition-all duration-200 hover:scale-105"
54
- >
55
- <Play className="h-5 w-5 fill-current" />
56
- <span>Start Working</span>
57
- <div className="absolute inset-0 rounded-xl bg-gradient-to-r from-emerald-400 to-emerald-600 opacity-0 group-hover:opacity-100 transition-opacity -z-10" />
58
- </Link>
59
- </div>
60
- </div>
61
-
62
- <div className="relative flex flex-col md:flex-row md:items-start md:justify-between gap-4 md:gap-0">
63
- <div className="flex items-center md:items-start gap-4 md:gap-6">
64
- <ProgressRing
65
- value={completionRate}
66
- size="xl"
67
- accentColor={completionColor}
68
- className="shrink-0"
69
- />
70
-
71
- <div className="flex-1 min-w-0">
72
- <TasksCounter count={animatedCount} />
73
- {/* Streak badge */}
74
- {streak > 0 && (
75
- <div className="flex items-center gap-1.5 mt-1">
76
- <Flame className="h-4 w-4 text-muted-foreground" />
77
- <span className="text-sm font-medium text-muted-foreground">
78
- {streak} day streak
79
- </span>
80
- </div>
81
- )}
82
- <InsightMessage message={insightMessage} />
83
- </div>
84
- </div>
85
-
86
- <div className="flex flex-col items-start md:items-end gap-3 md:gap-4">
87
- <WeeklySparkline data={weeklyData} size="lg" />
88
- </div>
89
- </div>
90
- </div>
91
- )
92
- }
@@ -1,14 +0,0 @@
1
- import type { TimelineEvent } from '@/lib/parse-prjct-files'
2
-
3
- export type { TimelineEvent }
4
-
5
- export interface HeroProps {
6
- projectId: string
7
- projectName: string
8
- projectVersion?: string | null
9
- totalShips: number
10
- completionRate: number
11
- streak: number
12
- insightMessage: string
13
- timeline?: TimelineEvent[]
14
- }
@@ -1,11 +0,0 @@
1
- export type AccentColor = 'default' | 'success' | 'warning' | 'destructive'
2
-
3
- // Completion rate color: traffic light based on project progress
4
- // Green >= 75% (almost done!)
5
- // Yellow 25-74% (good progress)
6
- // Red < 25% (just getting started)
7
- export function getCompletionColor(rate: number): AccentColor {
8
- if (rate >= 75) return 'success'
9
- if (rate >= 25) return 'warning'
10
- return 'destructive'
11
- }
@@ -1,2 +0,0 @@
1
- export { useCountUp } from './useCountUp'
2
- export { useWeeklyActivity } from './useWeeklyActivity'
@@ -1,45 +0,0 @@
1
- 'use client'
2
-
3
- import { useEffect, useRef, useState } from 'react'
4
-
5
- export function useCountUp(target: number, duration: number = 800): number {
6
- const [count, setCount] = useState(0)
7
- const prevTargetRef = useRef(target)
8
-
9
- useEffect(() => {
10
- if (target === 0) {
11
- // Only reset if target changed to 0 (not if it was already 0)
12
- if (prevTargetRef.current !== 0) {
13
- // Defer state update to avoid synchronous setState in effect
14
- const timeoutId = setTimeout(() => setCount(0), 0)
15
- prevTargetRef.current = target
16
- return () => clearTimeout(timeoutId)
17
- }
18
- prevTargetRef.current = target
19
- return
20
- }
21
-
22
- prevTargetRef.current = target
23
-
24
- const startTime = performance.now()
25
-
26
- const animate = (currentTime: number) => {
27
- const elapsed = currentTime - startTime
28
- const progress = Math.min(elapsed / duration, 1)
29
- const easeOut = 1 - Math.pow(1 - progress, 3)
30
- const current = Math.floor(easeOut * target)
31
-
32
- setCount(current)
33
-
34
- if (progress < 1) {
35
- requestAnimationFrame(animate)
36
- } else {
37
- setCount(target)
38
- }
39
- }
40
-
41
- requestAnimationFrame(animate)
42
- }, [target, duration])
43
-
44
- return count
45
- }
@@ -1,18 +0,0 @@
1
- 'use client'
2
-
3
- import { useMemo } from 'react'
4
- import type { TimelineEvent } from '../HeroSection.types'
5
-
6
- export function useWeeklyActivity(timeline: TimelineEvent[]): number[] {
7
- return useMemo(() => {
8
- const today = new Date()
9
-
10
- return Array.from({ length: 7 }, (_, i) => {
11
- const date = new Date(today)
12
- date.setDate(date.getDate() - (6 - i))
13
- const dateStr = date.toISOString().split('T')[0]
14
-
15
- return timeline.filter(e => e.ts?.startsWith(dateStr)).length
16
- })
17
- }, [timeline])
18
- }
@@ -1,2 +0,0 @@
1
- export { HeroSection } from './HeroSection'
2
- export type { HeroProps } from './HeroSection.types'
@@ -1,115 +0,0 @@
1
- 'use client'
2
-
3
- import { useState } from 'react'
4
- import Link from 'next/link'
5
- import { EmptyState } from '@/components/EmptyState'
6
- import { ExpandButton } from '@/components/ExpandButton'
7
- import { Lightbulb, Sparkles, Rocket, X } from 'lucide-react'
8
- import { cn } from '@/lib/utils'
9
- import type { IdeasCardProps } from './IdeasCard.types'
10
-
11
- const COLLAPSED_LIMIT = 8
12
- const EXPANDED_LIMIT = 30
13
-
14
- export function IdeasCard({ ideas, codeHref, className }: IdeasCardProps) {
15
- const [expanded, setExpanded] = useState(false)
16
- const limit = expanded ? EXPANDED_LIMIT : COLLAPSED_LIMIT
17
- const displayIdeas = ideas.slice(0, limit)
18
- const highImpactCount = ideas.filter(i => i.impact === 'HIGH').length
19
- const hasMore = ideas.length > limit
20
-
21
- return (
22
- <div className={cn(
23
- 'relative overflow-hidden rounded-xl border bg-card p-4',
24
- className
25
- )}>
26
- <div className="flex items-center justify-between mb-3">
27
- <div className="flex items-center gap-2">
28
- <Lightbulb className="h-4 w-4 text-muted-foreground" />
29
- <span className="text-xs font-bold uppercase tracking-[0.15em] text-muted-foreground">
30
- Ideas
31
- </span>
32
- </div>
33
- <div className="flex items-center gap-2">
34
- {highImpactCount > 0 && (
35
- <span className="text-xs font-medium text-muted-foreground bg-muted px-1.5 py-0.5 rounded">
36
- {highImpactCount} high impact
37
- </span>
38
- )}
39
- <span className="text-xs font-medium text-muted-foreground tabular-nums">
40
- {ideas.length}
41
- </span>
42
- </div>
43
- </div>
44
-
45
- {ideas.length === 0 ? (
46
- <EmptyState
47
- icon={Lightbulb}
48
- title="No ideas yet"
49
- command="/p:idea"
50
- href={codeHref}
51
- compact
52
- />
53
- ) : (
54
- <div className="space-y-1">
55
- {displayIdeas.map((idea, i) => {
56
- const featureHref = codeHref
57
- ? `${codeHref}?cmd=${encodeURIComponent(`p. feature "${idea.title}"`)}`
58
- : undefined
59
- const deleteHref = codeHref
60
- ? `${codeHref}?cmd=${encodeURIComponent(`p. idea remove ${i + 1}`)}`
61
- : undefined
62
-
63
- return (
64
- <div
65
- key={i}
66
- className="flex items-start gap-2 py-1.5 group hover:bg-muted/50 rounded px-1 -mx-1"
67
- >
68
- {idea.impact === 'HIGH' ? (
69
- <Sparkles className="h-3 w-3 mt-0.5 shrink-0 text-foreground" />
70
- ) : (
71
- <Lightbulb className="h-3 w-3 mt-0.5 shrink-0 text-muted-foreground" />
72
- )}
73
- <p className={cn(
74
- 'text-sm flex-1 min-w-0',
75
- idea.impact === 'HIGH' && 'font-medium'
76
- )}>
77
- {idea.title}
78
- </p>
79
- {/* Always visible action buttons */}
80
- <div className="flex items-center gap-1 shrink-0">
81
- {featureHref && (
82
- <Link
83
- href={featureHref}
84
- className="p-1 rounded hover:bg-muted text-muted-foreground hover:text-foreground transition-colors"
85
- title="Convert to feature"
86
- >
87
- <Rocket className="h-3.5 w-3.5" />
88
- </Link>
89
- )}
90
- {deleteHref && (
91
- <Link
92
- href={deleteHref}
93
- className="p-1 rounded hover:bg-muted text-muted-foreground hover:text-foreground transition-colors"
94
- title="Delete idea"
95
- >
96
- <X className="h-3.5 w-3.5" />
97
- </Link>
98
- )}
99
- </div>
100
- </div>
101
- )
102
- })}
103
- {(hasMore || expanded) && ideas.length > COLLAPSED_LIMIT && (
104
- <ExpandButton
105
- expanded={expanded}
106
- totalCount={ideas.length}
107
- collapsedLimit={COLLAPSED_LIMIT}
108
- onToggle={() => setExpanded(!expanded)}
109
- />
110
- )}
111
- </div>
112
- )}
113
- </div>
114
- )
115
- }
@@ -1,10 +0,0 @@
1
- export interface Idea {
2
- title: string
3
- impact?: string
4
- }
5
-
6
- export interface IdeasCardProps {
7
- ideas: Idea[]
8
- codeHref?: string
9
- className?: string
10
- }
@@ -1,2 +0,0 @@
1
- export { IdeasCard } from './IdeasCard'
2
- export type { IdeasCardProps } from './IdeasCard.types'
@@ -1,9 +0,0 @@
1
- import type { InsightMessageProps } from './InsightMessage.types'
2
-
3
- export function InsightMessage({ message }: InsightMessageProps) {
4
- return (
5
- <p className="text-sm md:text-base text-muted-foreground mt-2 md:mt-3 max-w-md">
6
- {message}
7
- </p>
8
- )
9
- }
@@ -1,3 +0,0 @@
1
- export interface InsightMessageProps {
2
- message: string
3
- }
@@ -1,2 +0,0 @@
1
- export { InsightMessage } from './InsightMessage'
2
- export type { InsightMessageProps } from './InsightMessage.types'
@@ -1,65 +0,0 @@
1
- import { cn } from '@/lib/utils'
2
-
3
- interface LogoProps {
4
- showText?: boolean
5
- size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl'
6
- rounded?: boolean
7
- }
8
-
9
- export function Logo({ showText = true, size = 'md', rounded = false }: LogoProps) {
10
- const logoSize = {
11
- xs: 'size-7',
12
- sm: 'size-10',
13
- md: 'size-12',
14
- lg: 'size-14',
15
- xl: 'size-16',
16
- }
17
-
18
- const textSize = {
19
- xs: 'text-sm',
20
- sm: 'text-lg',
21
- md: 'text-lg',
22
- lg: 'text-2xl',
23
- xl: 'text-3xl',
24
- }
25
-
26
- const containerTextSize = {
27
- xs: 'text-sm',
28
- sm: 'text-base',
29
- md: 'text-xl',
30
- lg: 'text-2xl',
31
- xl: 'text-3xl',
32
- }
33
-
34
- const brandTextSize = {
35
- xs: 'text-xs',
36
- sm: 'text-sm',
37
- md: 'text-lg',
38
- lg: 'text-xl',
39
- xl: 'text-2xl',
40
- }
41
-
42
- return (
43
- <div
44
- className={cn('flex items-center gap-2', containerTextSize[size])}
45
- data-testid="prjct-logo"
46
- >
47
- <div className="relative isolate overflow-visible">
48
- <div className={cn("fancy-border pointer-events-none", rounded && "rounded-full")}></div>
49
- <div
50
- className={cn(
51
- 'relative z-10 flex items-center justify-center border border-border bg-foreground text-background shadow-sm',
52
- rounded ? 'rounded-full' : 'rounded-lg',
53
- logoSize[size]
54
- )}
55
- data-testid="prjct-logo-icon"
56
- >
57
- <p className={cn('mb-0.5 inline-block font-bold leading-none', textSize[size])}>p/</p>
58
- </div>
59
- </div>
60
- {showText && (
61
- <span className={cn(brandTextSize[size], 'font-bold text-foreground')}>prjct</span>
62
- )}
63
- </div>
64
- )
65
- }
@@ -1 +0,0 @@
1
- export { Logo } from './Logo'
@@ -1,123 +0,0 @@
1
- 'use client'
2
-
3
- import ReactMarkdown from 'react-markdown'
4
- import remarkGfm from 'remark-gfm'
5
- import { cn } from '@/lib/utils'
6
-
7
- interface MarkdownContentProps {
8
- content: string
9
- className?: string
10
- }
11
-
12
- export function MarkdownContent({ content, className }: MarkdownContentProps) {
13
- if (!content || !content.trim()) {
14
- return (
15
- <p className="text-sm text-muted-foreground italic">No content</p>
16
- )
17
- }
18
-
19
- return (
20
- <div className={cn('prose prose-sm dark:prose-invert max-w-none', className)}>
21
- <ReactMarkdown
22
- remarkPlugins={[remarkGfm]}
23
- components={{
24
- // Headers
25
- h1: ({ children }) => (
26
- <h1 className="text-xl font-bold mt-4 mb-2 first:mt-0">{children}</h1>
27
- ),
28
- h2: ({ children }) => (
29
- <h2 className="text-lg font-semibold mt-4 mb-2 border-b pb-1">{children}</h2>
30
- ),
31
- h3: ({ children }) => (
32
- <h3 className="text-base font-medium mt-3 mb-1">{children}</h3>
33
- ),
34
- // Lists
35
- ul: ({ children }) => (
36
- <ul className="list-disc list-inside space-y-1 my-2">{children}</ul>
37
- ),
38
- ol: ({ children }) => (
39
- <ol className="list-decimal list-inside space-y-1 my-2">{children}</ol>
40
- ),
41
- li: ({ children }) => (
42
- <li className="text-sm">{children}</li>
43
- ),
44
- // Checkbox lists (GFM)
45
- input: ({ checked, ...props }) => (
46
- <input
47
- type="checkbox"
48
- checked={checked}
49
- readOnly
50
- className="mr-2 rounded"
51
- {...props}
52
- />
53
- ),
54
- // Paragraphs
55
- p: ({ children }) => (
56
- <p className="text-sm my-1.5 leading-relaxed">{children}</p>
57
- ),
58
- // Code
59
- code: ({ className, children, ...props }) => {
60
- const isInline = !className
61
- if (isInline) {
62
- return (
63
- <code className="bg-muted px-1 py-0.5 rounded text-xs font-mono" {...props}>
64
- {children}
65
- </code>
66
- )
67
- }
68
- return (
69
- <code className={cn('block bg-muted p-2 rounded text-xs font-mono overflow-x-auto', className)} {...props}>
70
- {children}
71
- </code>
72
- )
73
- },
74
- pre: ({ children }) => (
75
- <pre className="bg-muted p-3 rounded-md overflow-x-auto my-2 text-xs">
76
- {children}
77
- </pre>
78
- ),
79
- // Tables
80
- table: ({ children }) => (
81
- <div className="overflow-x-auto my-2">
82
- <table className="min-w-full text-xs border-collapse">{children}</table>
83
- </div>
84
- ),
85
- thead: ({ children }) => (
86
- <thead className="bg-muted">{children}</thead>
87
- ),
88
- th: ({ children }) => (
89
- <th className="px-2 py-1 text-left font-medium border-b">{children}</th>
90
- ),
91
- td: ({ children }) => (
92
- <td className="px-2 py-1 border-b">{children}</td>
93
- ),
94
- // Blockquotes
95
- blockquote: ({ children }) => (
96
- <blockquote className="border-l-2 border-muted-foreground/30 pl-3 italic text-muted-foreground my-2">
97
- {children}
98
- </blockquote>
99
- ),
100
- // Horizontal rules
101
- hr: () => (
102
- <hr className="my-4 border-border" />
103
- ),
104
- // Strong/em
105
- strong: ({ children }) => (
106
- <strong className="font-semibold">{children}</strong>
107
- ),
108
- em: ({ children }) => (
109
- <em className="italic">{children}</em>
110
- ),
111
- // Links
112
- a: ({ href, children }) => (
113
- <a href={href} className="text-primary hover:underline" target="_blank" rel="noopener noreferrer">
114
- {children}
115
- </a>
116
- ),
117
- }}
118
- >
119
- {content}
120
- </ReactMarkdown>
121
- </div>
122
- )
123
- }
@@ -1 +0,0 @@
1
- export { MarkdownContent } from './MarkdownContent'
@@ -1,18 +0,0 @@
1
- import { cn } from '@/lib/utils'
2
-
3
- interface MasonryGridProps {
4
- children: React.ReactNode
5
- className?: string
6
- }
7
-
8
- export function MasonryGrid({ children, className }: MasonryGridProps) {
9
- return (
10
- <div className={cn(
11
- 'columns-1 sm:columns-2 xl:columns-3 gap-4 max-w-full overflow-x-hidden',
12
- '[&>*]:mb-4 [&>*]:break-inside-avoid',
13
- className
14
- )}>
15
- {children}
16
- </div>
17
- )
18
- }
@@ -1 +0,0 @@
1
- export { MasonryGrid } from './MasonryGrid'
@@ -1,119 +0,0 @@
1
- 'use client'
2
-
3
- import { useEffect, useState } from 'react'
4
- import { SparklineChart } from '@/components/SparklineChart'
5
- import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip'
6
- import { Flame, TrendingUp, Activity, Heart } from 'lucide-react'
7
- import { cn } from '@/lib/utils'
8
- import type { MomentumWidgetProps, MomentumData, MomentumStatus } from './MomentumWidget.types'
9
-
10
- const statusConfig: Record<MomentumStatus, {
11
- color: string
12
- bgColor: string
13
- textColor: string
14
- icon: typeof Flame
15
- }> = {
16
- // Growing - you're killing it!
17
- hot: {
18
- color: '#22c55e',
19
- bgColor: 'bg-green-500/10',
20
- textColor: 'text-green-500',
21
- icon: Flame
22
- },
23
- // Normal activity - neutral tones
24
- active: {
25
- color: '#a1a1aa',
26
- bgColor: 'bg-muted',
27
- textColor: 'text-muted-foreground',
28
- icon: Activity
29
- },
30
- // Slight slowdown - still neutral
31
- cooling: {
32
- color: '#a1a1aa',
33
- bgColor: 'bg-muted',
34
- textColor: 'text-muted-foreground',
35
- icon: TrendingUp
36
- },
37
- // Abandoned (7+ days) - red alert
38
- cold: {
39
- color: '#ef4444',
40
- bgColor: 'bg-red-500/10',
41
- textColor: 'text-red-500',
42
- icon: Heart
43
- }
44
- }
45
-
46
- export function MomentumWidget({ projectId }: MomentumWidgetProps) {
47
- const [data, setData] = useState<MomentumData | null>(null)
48
- const [loading, setLoading] = useState(true)
49
-
50
- useEffect(() => {
51
- async function fetchMomentum() {
52
- try {
53
- const res = await fetch(`/api/projects/${projectId}/momentum`)
54
- const json = await res.json()
55
- if (json.success) {
56
- setData(json.data)
57
- }
58
- } catch (error) {
59
- console.error('Failed to fetch momentum:', error)
60
- } finally {
61
- setLoading(false)
62
- }
63
- }
64
-
65
- fetchMomentum()
66
- }, [projectId])
67
-
68
- if (loading) {
69
- return (
70
- <div className="flex items-center gap-2 h-10 animate-pulse">
71
- <div className="h-10 w-32 bg-muted rounded" />
72
- <div className="h-4 w-16 bg-muted rounded" />
73
- </div>
74
- )
75
- }
76
-
77
- if (!data) return null
78
-
79
- const config = statusConfig[data.status]
80
- const Icon = config.icon
81
-
82
- return (
83
- <Tooltip>
84
- <TooltipTrigger asChild>
85
- <div className={cn(
86
- 'flex items-center gap-2 px-2 py-1 rounded-md cursor-default transition-colors',
87
- config.bgColor
88
- )}>
89
- {/* Mini sparkline - matching button width for visual weight */}
90
- <div className="w-32 h-10">
91
- <SparklineChart
92
- data={data.dailyTasks}
93
- color={config.color}
94
- height={40}
95
- showArea={true}
96
- />
97
- </div>
98
-
99
- {/* Status badge */}
100
- <div className={cn('flex items-center gap-1.5', config.textColor)}>
101
- <Icon className="w-4 h-4" />
102
- <span className="text-sm font-medium whitespace-nowrap">
103
- {data.message}
104
- </span>
105
- </div>
106
- </div>
107
- </TooltipTrigger>
108
- <TooltipContent side="bottom" className="text-xs">
109
- <div className="space-y-1">
110
- <p className="font-medium">7-day activity</p>
111
- <p>{data.totalTasks} tasks, {data.totalShips} ships</p>
112
- {data.streak > 0 && (
113
- <p className="text-foreground font-medium">{data.streak} day streak!</p>
114
- )}
115
- </div>
116
- </TooltipContent>
117
- </Tooltip>
118
- )
119
- }