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.
Files changed (246) hide show
  1. package/CHANGELOG.md +82 -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/agents/uxui.md +210 -0
  11. package/templates/commands/bug.md +219 -41
  12. package/templates/commands/done.md +57 -258
  13. package/templates/commands/feature.md +368 -80
  14. package/templates/commands/now.md +72 -277
  15. package/templates/commands/ship.md +167 -246
  16. package/templates/commands/sync.md +62 -3
  17. package/templates/commands/test.md +160 -20
  18. package/templates/global/CLAUDE.md +40 -205
  19. package/templates/global/docs/agents.md +88 -0
  20. package/templates/global/docs/architecture.md +103 -0
  21. package/templates/global/docs/commands.md +98 -0
  22. package/templates/global/docs/validation.md +95 -0
  23. package/bin/dev.js +0 -216
  24. package/bin/serve.js +0 -361
  25. package/packages/web/README.md +0 -36
  26. package/packages/web/app/api/claude/sessions/route.ts +0 -44
  27. package/packages/web/app/api/claude/status/route.ts +0 -34
  28. package/packages/web/app/api/projects/[id]/icon/route.ts +0 -33
  29. package/packages/web/app/api/projects/[id]/momentum/route.ts +0 -257
  30. package/packages/web/app/api/projects/[id]/route.ts +0 -29
  31. package/packages/web/app/api/projects/[id]/stats/route.ts +0 -41
  32. package/packages/web/app/api/projects/[id]/status/route.ts +0 -21
  33. package/packages/web/app/api/projects/route.ts +0 -16
  34. package/packages/web/app/api/sessions/current/route.ts +0 -132
  35. package/packages/web/app/api/sessions/history/route.ts +0 -204
  36. package/packages/web/app/error.tsx +0 -34
  37. package/packages/web/app/favicon.ico +0 -0
  38. package/packages/web/app/globals.css +0 -198
  39. package/packages/web/app/layout.tsx +0 -53
  40. package/packages/web/app/loading.tsx +0 -7
  41. package/packages/web/app/not-found.tsx +0 -25
  42. package/packages/web/app/page.tsx +0 -12
  43. package/packages/web/app/project/[id]/code/layout.tsx +0 -18
  44. package/packages/web/app/project/[id]/code/page.tsx +0 -408
  45. package/packages/web/app/project/[id]/error.tsx +0 -41
  46. package/packages/web/app/project/[id]/loading.tsx +0 -9
  47. package/packages/web/app/project/[id]/not-found.tsx +0 -27
  48. package/packages/web/app/project/[id]/page.tsx +0 -384
  49. package/packages/web/app/project/[id]/reports/page.tsx +0 -59
  50. package/packages/web/app/project/[id]/reports/print/page.tsx +0 -58
  51. package/packages/web/app/sessions/page.tsx +0 -165
  52. package/packages/web/app/settings/page.tsx +0 -151
  53. package/packages/web/components/ActivityTimeline/ActivityTimeline.constants.ts +0 -2
  54. package/packages/web/components/ActivityTimeline/ActivityTimeline.tsx +0 -49
  55. package/packages/web/components/ActivityTimeline/ActivityTimeline.types.ts +0 -8
  56. package/packages/web/components/ActivityTimeline/hooks/index.ts +0 -2
  57. package/packages/web/components/ActivityTimeline/hooks/useExpandable.ts +0 -9
  58. package/packages/web/components/ActivityTimeline/hooks/useGroupedEvents.ts +0 -23
  59. package/packages/web/components/ActivityTimeline/index.ts +0 -2
  60. package/packages/web/components/AgentsCard/AgentsCard.tsx +0 -93
  61. package/packages/web/components/AgentsCard/AgentsCard.types.ts +0 -14
  62. package/packages/web/components/AgentsCard/index.ts +0 -2
  63. package/packages/web/components/AppSidebar/AppSidebar.tsx +0 -316
  64. package/packages/web/components/AppSidebar/index.ts +0 -1
  65. package/packages/web/components/BackLink/BackLink.tsx +0 -18
  66. package/packages/web/components/BackLink/BackLink.types.ts +0 -5
  67. package/packages/web/components/BackLink/index.ts +0 -2
  68. package/packages/web/components/BentoCard/BentoCard.constants.ts +0 -16
  69. package/packages/web/components/BentoCard/BentoCard.tsx +0 -48
  70. package/packages/web/components/BentoCard/BentoCard.types.ts +0 -15
  71. package/packages/web/components/BentoCard/index.ts +0 -2
  72. package/packages/web/components/BentoCardSkeleton/BentoCardSkeleton.constants.ts +0 -9
  73. package/packages/web/components/BentoCardSkeleton/BentoCardSkeleton.tsx +0 -18
  74. package/packages/web/components/BentoCardSkeleton/BentoCardSkeleton.types.ts +0 -5
  75. package/packages/web/components/BentoCardSkeleton/index.ts +0 -2
  76. package/packages/web/components/BentoGrid/BentoGrid.tsx +0 -18
  77. package/packages/web/components/BentoGrid/BentoGrid.types.ts +0 -4
  78. package/packages/web/components/BentoGrid/index.ts +0 -2
  79. package/packages/web/components/BlockersCard/BlockersCard.tsx +0 -75
  80. package/packages/web/components/BlockersCard/BlockersCard.types.ts +0 -12
  81. package/packages/web/components/BlockersCard/index.ts +0 -2
  82. package/packages/web/components/CommandBar/CommandBar.tsx +0 -67
  83. package/packages/web/components/CommandBar/index.ts +0 -1
  84. package/packages/web/components/CommandButton/CommandButton.tsx +0 -46
  85. package/packages/web/components/CommandButton/index.ts +0 -1
  86. package/packages/web/components/ConnectionStatus/ConnectionStatus.tsx +0 -29
  87. package/packages/web/components/ConnectionStatus/index.ts +0 -1
  88. package/packages/web/components/DashboardContent/DashboardContent.tsx +0 -284
  89. package/packages/web/components/DashboardContent/index.ts +0 -1
  90. package/packages/web/components/DateGroup/DateGroup.tsx +0 -18
  91. package/packages/web/components/DateGroup/DateGroup.types.ts +0 -6
  92. package/packages/web/components/DateGroup/DateGroup.utils.ts +0 -11
  93. package/packages/web/components/DateGroup/index.ts +0 -2
  94. package/packages/web/components/EmptyState/EmptyState.tsx +0 -76
  95. package/packages/web/components/EmptyState/EmptyState.types.ts +0 -11
  96. package/packages/web/components/EmptyState/index.ts +0 -2
  97. package/packages/web/components/EventRow/EventRow.constants.ts +0 -10
  98. package/packages/web/components/EventRow/EventRow.tsx +0 -49
  99. package/packages/web/components/EventRow/EventRow.types.ts +0 -7
  100. package/packages/web/components/EventRow/EventRow.utils.ts +0 -49
  101. package/packages/web/components/EventRow/index.ts +0 -2
  102. package/packages/web/components/ExpandButton/ExpandButton.tsx +0 -18
  103. package/packages/web/components/ExpandButton/ExpandButton.types.ts +0 -6
  104. package/packages/web/components/ExpandButton/index.ts +0 -2
  105. package/packages/web/components/HealthGradientBackground/HealthGradientBackground.tsx +0 -14
  106. package/packages/web/components/HealthGradientBackground/HealthGradientBackground.types.ts +0 -5
  107. package/packages/web/components/HealthGradientBackground/HealthGradientBackground.utils.ts +0 -13
  108. package/packages/web/components/HealthGradientBackground/index.ts +0 -2
  109. package/packages/web/components/HeroSection/HeroSection.tsx +0 -92
  110. package/packages/web/components/HeroSection/HeroSection.types.ts +0 -14
  111. package/packages/web/components/HeroSection/HeroSection.utils.ts +0 -11
  112. package/packages/web/components/HeroSection/hooks/index.ts +0 -2
  113. package/packages/web/components/HeroSection/hooks/useCountUp.ts +0 -45
  114. package/packages/web/components/HeroSection/hooks/useWeeklyActivity.ts +0 -18
  115. package/packages/web/components/HeroSection/index.ts +0 -2
  116. package/packages/web/components/IdeasCard/IdeasCard.tsx +0 -115
  117. package/packages/web/components/IdeasCard/IdeasCard.types.ts +0 -10
  118. package/packages/web/components/IdeasCard/index.ts +0 -2
  119. package/packages/web/components/InsightMessage/InsightMessage.tsx +0 -9
  120. package/packages/web/components/InsightMessage/InsightMessage.types.ts +0 -3
  121. package/packages/web/components/InsightMessage/index.ts +0 -2
  122. package/packages/web/components/Logo/Logo.tsx +0 -65
  123. package/packages/web/components/Logo/index.ts +0 -1
  124. package/packages/web/components/MarkdownContent/MarkdownContent.tsx +0 -123
  125. package/packages/web/components/MarkdownContent/index.ts +0 -1
  126. package/packages/web/components/MasonryGrid/MasonryGrid.tsx +0 -18
  127. package/packages/web/components/MasonryGrid/index.ts +0 -1
  128. package/packages/web/components/MomentumWidget/MomentumWidget.tsx +0 -119
  129. package/packages/web/components/MomentumWidget/MomentumWidget.types.ts +0 -16
  130. package/packages/web/components/MomentumWidget/index.ts +0 -2
  131. package/packages/web/components/NowCard/NowCard.tsx +0 -118
  132. package/packages/web/components/NowCard/NowCard.types.ts +0 -16
  133. package/packages/web/components/NowCard/index.ts +0 -2
  134. package/packages/web/components/PageHeader/PageHeader.tsx +0 -24
  135. package/packages/web/components/PageHeader/index.ts +0 -1
  136. package/packages/web/components/ProgressRing/ProgressRing.constants.ts +0 -20
  137. package/packages/web/components/ProgressRing/ProgressRing.tsx +0 -51
  138. package/packages/web/components/ProgressRing/ProgressRing.types.ts +0 -11
  139. package/packages/web/components/ProgressRing/index.ts +0 -2
  140. package/packages/web/components/ProjectAvatar/ProjectAvatar.tsx +0 -54
  141. package/packages/web/components/ProjectAvatar/index.ts +0 -1
  142. package/packages/web/components/ProjectColorDot/ProjectColorDot.tsx +0 -37
  143. package/packages/web/components/ProjectColorDot/index.ts +0 -1
  144. package/packages/web/components/ProjectSelectorModal/ProjectSelectorModal.tsx +0 -104
  145. package/packages/web/components/ProjectSelectorModal/index.ts +0 -1
  146. package/packages/web/components/Providers/Providers.tsx +0 -48
  147. package/packages/web/components/Providers/index.ts +0 -1
  148. package/packages/web/components/QueueCard/QueueCard.tsx +0 -125
  149. package/packages/web/components/QueueCard/QueueCard.types.ts +0 -12
  150. package/packages/web/components/QueueCard/QueueCard.utils.ts +0 -12
  151. package/packages/web/components/QueueCard/index.ts +0 -2
  152. package/packages/web/components/RecoverCard/RecoverCard.tsx +0 -72
  153. package/packages/web/components/RecoverCard/RecoverCard.types.ts +0 -16
  154. package/packages/web/components/RecoverCard/index.ts +0 -2
  155. package/packages/web/components/RoadmapCard/RoadmapCard.tsx +0 -145
  156. package/packages/web/components/RoadmapCard/RoadmapCard.types.ts +0 -16
  157. package/packages/web/components/RoadmapCard/index.ts +0 -2
  158. package/packages/web/components/ShipsCard/ShipsCard.tsx +0 -95
  159. package/packages/web/components/ShipsCard/ShipsCard.types.ts +0 -14
  160. package/packages/web/components/ShipsCard/ShipsCard.utils.ts +0 -4
  161. package/packages/web/components/ShipsCard/index.ts +0 -2
  162. package/packages/web/components/SparklineChart/SparklineChart.tsx +0 -40
  163. package/packages/web/components/SparklineChart/SparklineChart.types.ts +0 -6
  164. package/packages/web/components/SparklineChart/index.ts +0 -2
  165. package/packages/web/components/StatsMasonry/StatsMasonry.tsx +0 -95
  166. package/packages/web/components/StatsMasonry/index.ts +0 -1
  167. package/packages/web/components/StreakCard/StreakCard.constants.ts +0 -2
  168. package/packages/web/components/StreakCard/StreakCard.tsx +0 -55
  169. package/packages/web/components/StreakCard/StreakCard.types.ts +0 -4
  170. package/packages/web/components/StreakCard/index.ts +0 -2
  171. package/packages/web/components/TasksCounter/TasksCounter.tsx +0 -14
  172. package/packages/web/components/TasksCounter/TasksCounter.types.ts +0 -3
  173. package/packages/web/components/TasksCounter/index.ts +0 -2
  174. package/packages/web/components/TechStackBadges/TechStackBadges.tsx +0 -28
  175. package/packages/web/components/TechStackBadges/index.ts +0 -1
  176. package/packages/web/components/TerminalDock/DockToggleTab.tsx +0 -29
  177. package/packages/web/components/TerminalDock/TerminalDock.tsx +0 -386
  178. package/packages/web/components/TerminalDock/TerminalDockTab.tsx +0 -130
  179. package/packages/web/components/TerminalDock/TerminalTabBar.tsx +0 -142
  180. package/packages/web/components/TerminalDock/index.ts +0 -2
  181. package/packages/web/components/TerminalTabs/TerminalTab.tsx +0 -95
  182. package/packages/web/components/TerminalTabs/TerminalTabs.tsx +0 -211
  183. package/packages/web/components/TerminalTabs/index.ts +0 -1
  184. package/packages/web/components/VelocityBadge/VelocityBadge.tsx +0 -32
  185. package/packages/web/components/VelocityBadge/VelocityBadge.types.ts +0 -3
  186. package/packages/web/components/VelocityBadge/index.ts +0 -2
  187. package/packages/web/components/VelocityCard/VelocityCard.tsx +0 -73
  188. package/packages/web/components/VelocityCard/VelocityCard.types.ts +0 -7
  189. package/packages/web/components/VelocityCard/index.ts +0 -2
  190. package/packages/web/components/WeeklyReports/PrintableReport.tsx +0 -259
  191. package/packages/web/components/WeeklyReports/ReportPreviewCard.tsx +0 -187
  192. package/packages/web/components/WeeklyReports/WeekCalendar.tsx +0 -288
  193. package/packages/web/components/WeeklyReports/WeeklyReports.tsx +0 -149
  194. package/packages/web/components/WeeklyReports/index.ts +0 -4
  195. package/packages/web/components/WeeklySparkline/WeeklySparkline.tsx +0 -25
  196. package/packages/web/components/WeeklySparkline/WeeklySparkline.types.ts +0 -4
  197. package/packages/web/components/WeeklySparkline/index.ts +0 -2
  198. package/packages/web/components/charts/SessionsChart.tsx +0 -175
  199. package/packages/web/components/ui/alert-dialog.tsx +0 -157
  200. package/packages/web/components/ui/badge.tsx +0 -46
  201. package/packages/web/components/ui/button.tsx +0 -60
  202. package/packages/web/components/ui/card.tsx +0 -92
  203. package/packages/web/components/ui/chart.tsx +0 -385
  204. package/packages/web/components/ui/dialog.tsx +0 -143
  205. package/packages/web/components/ui/drawer.tsx +0 -135
  206. package/packages/web/components/ui/dropdown-menu.tsx +0 -257
  207. package/packages/web/components/ui/input.tsx +0 -21
  208. package/packages/web/components/ui/scroll-area.tsx +0 -58
  209. package/packages/web/components/ui/select.tsx +0 -187
  210. package/packages/web/components/ui/sheet.tsx +0 -139
  211. package/packages/web/components/ui/tabs.tsx +0 -66
  212. package/packages/web/components/ui/tooltip.tsx +0 -61
  213. package/packages/web/components.json +0 -22
  214. package/packages/web/context/GlobalTerminalContext.tsx +0 -538
  215. package/packages/web/context/TerminalContext.tsx +0 -45
  216. package/packages/web/context/TerminalTabsContext.tsx +0 -181
  217. package/packages/web/eslint.config.mjs +0 -18
  218. package/packages/web/hooks/useClaudeTerminal.ts +0 -425
  219. package/packages/web/hooks/useProjectStats.ts +0 -93
  220. package/packages/web/hooks/useProjects.ts +0 -73
  221. package/packages/web/lib/actions/projects.ts +0 -15
  222. package/packages/web/lib/commands.ts +0 -81
  223. package/packages/web/lib/format.ts +0 -23
  224. package/packages/web/lib/generate-week-report.ts +0 -285
  225. package/packages/web/lib/parse-prjct-files.ts +0 -1123
  226. package/packages/web/lib/project-colors.ts +0 -58
  227. package/packages/web/lib/projects.ts +0 -506
  228. package/packages/web/lib/pty.ts +0 -101
  229. package/packages/web/lib/query-config.ts +0 -44
  230. package/packages/web/lib/services/index.ts +0 -9
  231. package/packages/web/lib/services/projects.server.ts +0 -66
  232. package/packages/web/lib/services/stats.server.ts +0 -562
  233. package/packages/web/lib/unified-loader.ts +0 -396
  234. package/packages/web/lib/utils.ts +0 -6
  235. package/packages/web/next-env.d.ts +0 -6
  236. package/packages/web/next.config.ts +0 -7
  237. package/packages/web/package.json +0 -57
  238. package/packages/web/postcss.config.mjs +0 -7
  239. package/packages/web/public/file.svg +0 -1
  240. package/packages/web/public/globe.svg +0 -1
  241. package/packages/web/public/next.svg +0 -1
  242. package/packages/web/public/vercel.svg +0 -1
  243. package/packages/web/public/window.svg +0 -1
  244. package/packages/web/server.ts +0 -312
  245. package/packages/web/tsconfig.json +0 -34
  246. package/templates/commands/serve.md +0 -121
@@ -1,259 +0,0 @@
1
- 'use client'
2
-
3
- import { useMemo } from 'react'
4
- import { useParams } from 'next/navigation'
5
- import Link from 'next/link'
6
- import { Rocket, CheckCircle2, Bug, Calendar, Printer, ArrowLeft } from 'lucide-react'
7
- import {
8
- filterDataByWeek,
9
- formatDateRange,
10
- type WeekData,
11
- } from '@/lib/generate-week-report'
12
- import type { StatsResult } from '@/lib/services/stats.server'
13
-
14
- interface PrintableReportProps {
15
- stats: StatsResult
16
- projectName: string
17
- selectedWeeks: number[]
18
- year: number
19
- }
20
-
21
- export function PrintableReport({
22
- stats,
23
- projectName,
24
- selectedWeeks,
25
- year,
26
- }: PrintableReportProps) {
27
- const params = useParams()
28
- const projectId = params.id as string
29
-
30
- const weekDataList = useMemo(() => {
31
- return selectedWeeks.map(w => filterDataByWeek(stats, year, w))
32
- }, [stats, year, selectedWeeks])
33
-
34
- // Aggregate data
35
- const allShipped = weekDataList.flatMap(w => w.shipped)
36
- const uniqueShipsMap = new Map<string, typeof allShipped[0]>()
37
- for (const ship of allShipped) {
38
- if (!uniqueShipsMap.has(ship.name)) {
39
- uniqueShipsMap.set(ship.name, ship)
40
- }
41
- }
42
- // Sort by date descending (most recent first)
43
- const uniqueShips = Array.from(uniqueShipsMap.values())
44
- .sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime())
45
-
46
- // Group ships by date for display
47
- const shipsByDate = new Map<string, typeof uniqueShips>()
48
- for (const ship of uniqueShips) {
49
- const dateKey = ship.date
50
- if (!shipsByDate.has(dateKey)) {
51
- shipsByDate.set(dateKey, [])
52
- }
53
- shipsByDate.get(dateKey)!.push(ship)
54
- }
55
-
56
- const totalTasks = weekDataList.reduce((sum, w) => sum + w.tasksCompleted, 0)
57
- const totalBugs = weekDataList.reduce((sum, w) => sum + w.bugsFixed, 0)
58
- const totalDays = weekDataList.reduce((sum, w) => sum + w.activeDays, 0)
59
-
60
- // Date range
61
- const firstWeek = weekDataList[0]
62
- const lastWeek = weekDataList[weekDataList.length - 1]
63
- const dateRangeStr = weekDataList.length === 1
64
- ? formatDateRange(firstWeek.startDate, firstWeek.endDate)
65
- : formatDateRange(firstWeek.startDate, lastWeek.endDate)
66
-
67
- const weekLabel = weekDataList.length === 1
68
- ? `Semana ${firstWeek.week}`
69
- : `Semanas ${firstWeek.week}-${lastWeek.week}`
70
-
71
- const handlePrint = () => {
72
- window.print()
73
- }
74
-
75
- return (
76
- <div className="min-h-screen bg-white">
77
- {/* Action buttons - hidden when printing */}
78
- <div className="print:hidden fixed top-4 right-4 z-50 flex items-center gap-2">
79
- <Link
80
- href={`/project/${projectId}/reports`}
81
- className="flex items-center gap-2 px-4 py-2 bg-white text-gray-700 border border-gray-300 rounded-lg hover:bg-gray-50 transition-colors shadow-lg"
82
- >
83
- <ArrowLeft className="h-4 w-4" />
84
- Regresar
85
- </Link>
86
- <button
87
- onClick={handlePrint}
88
- className="flex items-center gap-2 px-4 py-2 bg-gray-900 text-white rounded-lg hover:bg-gray-800 transition-colors shadow-lg"
89
- >
90
- <Printer className="h-4 w-4" />
91
- Imprimir / PDF
92
- </button>
93
- </div>
94
-
95
- {/* Printable content */}
96
- <div className="max-w-2xl mx-auto p-8 print:p-0 print:max-w-none">
97
- {/* Header */}
98
- <header className="mb-8 pb-6 border-b-2 border-gray-200">
99
- <h1 className="text-3xl font-bold text-gray-900 mb-2">{projectName}</h1>
100
- <p className="text-lg text-gray-600">
101
- Reporte de Progreso - {weekLabel}
102
- </p>
103
- <p className="text-gray-500">{dateRangeStr}, {year}</p>
104
- </header>
105
-
106
- {/* Stats Summary */}
107
- <section className="mb-8">
108
- <div className="grid grid-cols-4 gap-4">
109
- <StatBox
110
- icon={<Rocket className="h-6 w-6" />}
111
- value={uniqueShips.length}
112
- label="Entregados"
113
- color="text-emerald-600"
114
- />
115
- <StatBox
116
- icon={<CheckCircle2 className="h-6 w-6" />}
117
- value={totalTasks}
118
- label="Tareas"
119
- color="text-blue-600"
120
- />
121
- <StatBox
122
- icon={<Bug className="h-6 w-6" />}
123
- value={totalBugs}
124
- label="Bugs"
125
- color="text-orange-600"
126
- />
127
- <StatBox
128
- icon={<Calendar className="h-6 w-6" />}
129
- value={totalDays}
130
- label="Dias Activos"
131
- color="text-purple-600"
132
- />
133
- </div>
134
- </section>
135
-
136
- {/* Shipped Features grouped by date */}
137
- {uniqueShips.length > 0 && (
138
- <section className="mb-8">
139
- <h2 className="text-xl font-semibold text-gray-900 mb-4 flex items-center gap-2">
140
- <Rocket className="h-5 w-5 text-emerald-600" />
141
- Entregado
142
- </h2>
143
- <div className="space-y-5">
144
- {Array.from(shipsByDate.entries()).map(([date, ships]) => (
145
- <div key={date}>
146
- <p className="text-sm font-medium text-gray-500 mb-2">
147
- {new Date(date).toLocaleDateString('es-MX', {
148
- weekday: 'long',
149
- month: 'long',
150
- day: 'numeric'
151
- })}
152
- </p>
153
- <ul className="space-y-2 pl-4 border-l-2 border-emerald-200">
154
- {ships.map((ship, i) => (
155
- <li key={i} className="pl-3 text-gray-700">
156
- <span className="font-medium">{ship.name}</span>
157
- {ship.version && (
158
- <span className="ml-2 text-sm text-gray-500 bg-gray-100 px-2 py-0.5 rounded">
159
- {ship.version}
160
- </span>
161
- )}
162
- </li>
163
- ))}
164
- </ul>
165
- </div>
166
- ))}
167
- </div>
168
- </section>
169
- )}
170
-
171
- {/* Activity Details */}
172
- {(totalTasks > 0 || totalBugs > 0) && (
173
- <section className="mb-8">
174
- <h2 className="text-xl font-semibold text-gray-900 mb-4 flex items-center gap-2">
175
- <CheckCircle2 className="h-5 w-5 text-blue-600" />
176
- Actividad
177
- </h2>
178
- <ul className="space-y-2 text-gray-700">
179
- {totalTasks > 0 && (
180
- <li className="flex items-center gap-2">
181
- <CheckCircle2 className="h-4 w-4 text-blue-500" />
182
- {totalTasks} tarea{totalTasks !== 1 ? 's' : ''} completada{totalTasks !== 1 ? 's' : ''}
183
- </li>
184
- )}
185
- {totalBugs > 0 && (
186
- <li className="flex items-center gap-2">
187
- <Bug className="h-4 w-4 text-orange-500" />
188
- {totalBugs} bug{totalBugs !== 1 ? 's' : ''} corregido{totalBugs !== 1 ? 's' : ''}
189
- </li>
190
- )}
191
- {totalDays > 0 && (
192
- <li className="flex items-center gap-2">
193
- <Calendar className="h-4 w-4 text-purple-500" />
194
- {totalDays} dia{totalDays !== 1 ? 's' : ''} activo{totalDays !== 1 ? 's' : ''}
195
- </li>
196
- )}
197
- </ul>
198
- </section>
199
- )}
200
-
201
- {/* No activity message */}
202
- {uniqueShips.length === 0 && totalTasks === 0 && totalBugs === 0 && (
203
- <section className="mb-8 p-6 bg-gray-50 rounded-lg text-center text-gray-500">
204
- Sin actividad registrada para este periodo
205
- </section>
206
- )}
207
-
208
- {/* Next Steps placeholder */}
209
- <section className="mb-8">
210
- <h2 className="text-xl font-semibold text-gray-900 mb-4">
211
- Siguiente
212
- </h2>
213
- <ul className="space-y-2 text-gray-600">
214
- <li className="flex items-center gap-2">
215
- <span className="text-gray-400">&#x2022;</span>
216
- <span className="italic text-gray-400">[Pendiente por definir]</span>
217
- </li>
218
- </ul>
219
- </section>
220
-
221
- {/* Footer */}
222
- <footer className="mt-12 pt-6 border-t border-gray-200 text-sm text-gray-400 text-center print:mt-8">
223
- <p>Generado con prjct - {new Date().toLocaleDateString('es-MX')}</p>
224
- </footer>
225
- </div>
226
-
227
- {/* Print styles */}
228
- <style jsx global>{`
229
- @media print {
230
- @page {
231
- size: letter;
232
- margin: 1in;
233
- }
234
- body {
235
- -webkit-print-color-adjust: exact;
236
- print-color-adjust: exact;
237
- }
238
- }
239
- `}</style>
240
- </div>
241
- )
242
- }
243
-
244
- interface StatBoxProps {
245
- icon: React.ReactNode
246
- value: number
247
- label: string
248
- color: string
249
- }
250
-
251
- function StatBox({ icon, value, label, color }: StatBoxProps) {
252
- return (
253
- <div className="text-center p-4 border border-gray-200 rounded-lg">
254
- <div className={`${color} flex justify-center mb-2`}>{icon}</div>
255
- <div className="text-2xl font-bold text-gray-900">{value}</div>
256
- <div className="text-sm text-gray-500">{label}</div>
257
- </div>
258
- )
259
- }
@@ -1,187 +0,0 @@
1
- 'use client'
2
-
3
- import { Rocket, CheckCircle2, Bug, Activity } from 'lucide-react'
4
- import { cn } from '@/lib/utils'
5
- import { formatDateRange } from '@/lib/generate-week-report'
6
- import type { WeekData } from '@/lib/generate-week-report'
7
-
8
- interface ReportPreviewCardProps {
9
- weekData: WeekData[]
10
- className?: string
11
- }
12
-
13
- export function ReportPreviewCard({ weekData, className }: ReportPreviewCardProps) {
14
- if (weekData.length === 0) {
15
- return (
16
- <div className={cn('rounded-xl border bg-card p-6', className)}>
17
- <p className="text-muted-foreground text-center">Select a week to preview</p>
18
- </div>
19
- )
20
- }
21
-
22
- // Aggregate data from all selected weeks
23
- const allShipped = weekData.flatMap(w => w.shipped)
24
- const uniqueShipsMap = new Map<string, typeof allShipped[0]>()
25
- for (const ship of allShipped) {
26
- if (!uniqueShipsMap.has(ship.name)) {
27
- uniqueShipsMap.set(ship.name, ship)
28
- }
29
- }
30
- // Sort by date descending (most recent first)
31
- const uniqueShips = Array.from(uniqueShipsMap.values())
32
- .sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime())
33
-
34
- // Group ships by date for display
35
- const shipsByDate = new Map<string, typeof uniqueShips>()
36
- for (const ship of uniqueShips) {
37
- const dateKey = ship.date
38
- if (!shipsByDate.has(dateKey)) {
39
- shipsByDate.set(dateKey, [])
40
- }
41
- shipsByDate.get(dateKey)!.push(ship)
42
- }
43
-
44
- const totalTasks = weekData.reduce((sum, w) => sum + w.tasksCompleted, 0)
45
- const totalBugs = weekData.reduce((sum, w) => sum + w.bugsFixed, 0)
46
- const totalSyncs = weekData.reduce((sum, w) => sum + w.syncs, 0)
47
- const totalDays = weekData.reduce((sum, w) => sum + w.activeDays, 0)
48
-
49
- // Date range header
50
- const firstWeek = weekData[0]
51
- const lastWeek = weekData[weekData.length - 1]
52
- const dateRangeStr = weekData.length === 1
53
- ? `Week ${firstWeek.week} · ${formatDateRange(firstWeek.startDate, firstWeek.endDate)}`
54
- : `Weeks ${firstWeek.week}-${lastWeek.week} · ${formatDateRange(firstWeek.startDate, lastWeek.endDate)}`
55
-
56
- const hasNoData = uniqueShips.length === 0 && totalTasks === 0 && totalBugs === 0 && totalDays === 0
57
-
58
- return (
59
- <div className={cn('rounded-xl border bg-card overflow-hidden', className)}>
60
- {/* Header */}
61
- <div className="px-6 py-4 border-b bg-muted/30">
62
- <h3 className="font-semibold text-lg">{dateRangeStr}</h3>
63
- </div>
64
-
65
- {hasNoData ? (
66
- <div className="p-6">
67
- <p className="text-muted-foreground text-center">No activity this week</p>
68
- </div>
69
- ) : (
70
- <div className="p-6 space-y-6">
71
- {/* Stats row */}
72
- <div className="grid grid-cols-4 gap-4">
73
- <StatCard
74
- icon={Rocket}
75
- value={uniqueShips.length}
76
- label="shipped"
77
- color="text-foreground"
78
- bgColor="bg-muted"
79
- />
80
- <StatCard
81
- icon={CheckCircle2}
82
- value={totalTasks}
83
- label="tasks"
84
- color="text-foreground"
85
- bgColor="bg-muted"
86
- />
87
- <StatCard
88
- icon={Bug}
89
- value={totalBugs}
90
- label="bugs"
91
- color="text-foreground"
92
- bgColor="bg-muted"
93
- />
94
- <StatCard
95
- icon={Activity}
96
- value={totalDays}
97
- label="days"
98
- color="text-foreground"
99
- bgColor="bg-muted"
100
- />
101
- </div>
102
-
103
- {/* Shipped list grouped by date */}
104
- {uniqueShips.length > 0 && (
105
- <div>
106
- <h4 className="text-xs font-medium text-muted-foreground uppercase tracking-wider mb-3">
107
- Shipped
108
- </h4>
109
- <div className="space-y-4">
110
- {Array.from(shipsByDate.entries()).map(([date, ships]) => (
111
- <div key={date}>
112
- <p className="text-xs text-muted-foreground mb-2">
113
- {new Date(date).toLocaleDateString('es-MX', {
114
- weekday: 'short',
115
- month: 'short',
116
- day: 'numeric'
117
- })}
118
- </p>
119
- <ul className="space-y-1.5 pl-2 border-l-2 border-muted-foreground/30">
120
- {ships.map((ship, i) => (
121
- <li key={i} className="flex items-start gap-2 pl-2">
122
- <span className="flex-1">
123
- {ship.name}
124
- {ship.version && (
125
- <span className="text-muted-foreground ml-1 text-sm">({ship.version})</span>
126
- )}
127
- </span>
128
- </li>
129
- ))}
130
- </ul>
131
- </div>
132
- ))}
133
- </div>
134
- </div>
135
- )}
136
-
137
- {/* Activity summary */}
138
- {(totalTasks > 0 || totalBugs > 0 || totalSyncs > 0) && (
139
- <div>
140
- <h4 className="text-xs font-medium text-muted-foreground uppercase tracking-wider mb-3">
141
- Activity
142
- </h4>
143
- <ul className="space-y-1 text-sm text-muted-foreground">
144
- {totalTasks > 0 && (
145
- <li className="flex items-center gap-2">
146
- <CheckCircle2 className="h-3.5 w-3.5 text-muted-foreground" />
147
- {totalTasks} task{totalTasks !== 1 ? 's' : ''} completed
148
- </li>
149
- )}
150
- {totalBugs > 0 && (
151
- <li className="flex items-center gap-2">
152
- <Bug className="h-3.5 w-3.5 text-muted-foreground" />
153
- {totalBugs} bug{totalBugs !== 1 ? 's' : ''} fixed
154
- </li>
155
- )}
156
- {totalSyncs > 0 && (
157
- <li className="flex items-center gap-2">
158
- <Activity className="h-3.5 w-3.5 text-muted-foreground" />
159
- {totalSyncs} sync{totalSyncs !== 1 ? 's' : ''}
160
- </li>
161
- )}
162
- </ul>
163
- </div>
164
- )}
165
- </div>
166
- )}
167
- </div>
168
- )
169
- }
170
-
171
- interface StatCardProps {
172
- icon: React.ElementType
173
- value: number
174
- label: string
175
- color: string
176
- bgColor: string
177
- }
178
-
179
- function StatCard({ icon: Icon, value, label, color, bgColor }: StatCardProps) {
180
- return (
181
- <div className={cn('rounded-xl p-4 text-center', bgColor)}>
182
- <Icon className={cn('h-5 w-5 mx-auto mb-1', color)} />
183
- <div className="text-2xl font-bold tabular-nums">{value}</div>
184
- <div className="text-xs text-muted-foreground">{label}</div>
185
- </div>
186
- )
187
- }