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,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">•</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
|
-
}
|