29 KiB
HP CG Production Tracker — Roadmap
Single source of truth for project status and remaining work. Previous planning documents (IMPLEMENTATION_PLAN.md, UPGRADE_PLAN.md) are archived in
docs/archive/.
Last updated: 2026-03-14
Table of Contents
What's Built
Core Foundation (Phases 1–4)
| Feature | Status |
|---|---|
| Project scaffold (Next.js, TS, Tailwind, Prisma, Auth.js) | ✅ Complete |
| Design system (Oliver Agency palette, Montserrat + Inter, light/dark) | ✅ Complete |
| Auth — SSO (Google + Microsoft Entra ID) + dev bypass | ✅ Complete |
| Project CRUD + deliverable CRUD with auto-pipeline | ✅ Complete |
| User management + role assignment | ✅ Complete |
| Dependency engine + stage state machine | ✅ Complete |
| Artist assignments + My Work page | ✅ Complete |
| Table view (TanStack Table, filters, sort, column visibility) | ✅ Complete |
| Board view (Kanban drag-and-drop) | ✅ Complete |
| Timeline view (Gantt with dependencies) | ✅ Complete |
| Dashboard (KPIs, charts, overdue alerts) | ✅ Complete |
| Revision tracking (rounds, feedback notes, history) | ✅ Complete |
| Threaded comment system | ✅ Complete |
| Notification system (in-app bell + full page) | ✅ Complete |
| Excel import (bulk upload from Master CG Tracker) | ✅ Complete |
| Excel export | ✅ Complete |
| Deadline tracking (approaching/overdue + notifications) | ✅ Complete |
| Command palette (Cmd+K) | ✅ Complete |
| Bulk operations (multi-select → batch status/assignment/priority) | ✅ Complete |
| Loading skeletons, error boundaries, empty states | ✅ Complete |
| Responsive design + mobile sidebar | ✅ Complete |
| Accessibility (skip-to-content, ARIA, focus-visible) | ✅ Complete |
| Stage date override + scheduling features | ✅ Complete |
Beyond Phase 4 (implemented opportunistically)
| Feature | Notes |
|---|---|
| Workload capacity grid | Artist × Week grid with status bars, overallocation warnings, 4/8/12-week projections |
| Workload utilization heatmap | Color-coded heatmap on workload page (green → yellow → red by load). Added in c8f88c6. |
| Calendar view | Monthly calendar with event pills, filters, day detail. Not in original plan. |
| Calendar heatmap | Heatmap overlay on calendar grid with toggle and bar visualization. Added in bac6d4c. Not in original plan. |
| Automation rule engine | Full trigger/action engine with event bus, rule evaluator, action executor, execution log |
| Semantic search (pgvector + Ollama) | Embedding service, hybrid search, pgvector columns on Project + Deliverable |
| AI Chat panel | SSE streaming chat with tool calls (search_entities), entity cards, project/deliverable context. Not in original plan. |
| Weekly executive report | Full report page at /reports/weekly/[date] with KPI strip, completed, deadlines, at-risk, upcoming sections |
| Skill data model | Skill, UserSkill, StageSkillRequirement in schema with seed data — no assignment UI yet |
Remaining Work — Priority Order
A. Image Comparison & Visual Review
The highest-impact remaining feature area. CG production review is fundamentally visual — everything else supports this core workflow.
A1 — Reference Image Comparison (Lightweight, in Stage Detail)
What: A-B comparison tools embedded in the existing stage detail sheet. Producers and artists compare the reference/approved image against the current WIP render without leaving the deliverable page.
Why first: Lower complexity than the full review viewer (A2). Directly improves the daily review loop for existing users and unblocks meaningful visual feedback on revision rounds.
Implementation:
- New "Compare" tab in the stage detail sheet (alongside Revisions and Comments tabs)
- Upload zones for reference image + current render per revision round
- Three comparison modes:
- A-B Slider — draggable vertical divider (CSS clip-path + pointer events, no dependency)
- Toggle — click/Space to crossfade between images
- Side-by-side — synced zoom/pan on wide screens
- Scroll-to-zoom + click-drag pan, synced across both images in all modes
- Image gallery: thumbnails of all uploaded images across all revision rounds with round labels
- PNG alpha compositing on upload — flatten transparent PNGs onto white background server-side using
sharp, so CG renders with transparent drop shadows compare correctly - Extend
Revision.attachmentsJSON schema:{ referenceImage?: {...}, currentImage?: {...}, annotations?: [...] } - Lightweight markup overlay (optional): arrow, rectangle, freehand, text pin drawn on top of current image
New API endpoints:
POST /api/stages/[stageId]/revisions/[revisionId]/upload— multipart, reference or current imageDELETE /api/stages/[stageId]/revisions/[revisionId]/upload— remove image
Key files:
src/components/revisions/image-compare-slider.tsx— A-B slider with drag handlesrc/components/revisions/image-toggle.tsx— Toggle/crossfadesrc/components/revisions/image-side-by-side.tsx— Synced side-by-side with zoom/pansrc/components/revisions/image-upload-zone.tsx— Drag-and-drop uploadsrc/components/revisions/revision-image-gallery.tsx— Browse images across revision roundssrc/components/revisions/compare-tab.tsx— Orchestrator: mode selector + comparison viewsrc/components/revisions/markup-overlay.tsx— Lightweight annotation layer
New dependency: sharp (server-side PNG alpha compositing on upload)
A2 — Full-Screen Image Viewer
What: Dedicated full-screen viewer with high-fidelity zoom (up to 200%+) for pixel-level inspection of CG renders.
Implementation:
- Canvas-based viewer with WebGL acceleration for large images
- Zoom: scroll wheel, pinch, keyboard (+/-), toolbar buttons (fit, 50%, 100%, 150%, 200%, free)
- Pan via click-drag when zoomed; minimap overlay showing viewport position
- Pixel coordinate + color value readout (RGB/Hex) in status bar
- High-DPI display support (retina)
Key files:
src/components/review/image-viewer.tsxsrc/components/review/zoom-controls.tsxsrc/components/review/minimap.tsxsrc/hooks/use-image-viewer.ts
A3 — Pixel-Accurate Annotations
What: Draw annotations directly on images — circles, rectangles, arrows, freehand, text labels, pins. Anchored to image coordinates so they stay accurate at any zoom level.
New data model:
model Annotation {
id String @id @default(cuid())
commentId String
comment Comment @relation(fields: [commentId], references: [id], onDelete: Cascade)
revisionId String
revision Revision @relation(fields: [revisionId], references: [id], onDelete: Cascade)
type AnnotationType
data Json // { x, y, width, height, points[], text, color, strokeWidth }
imageX Float
imageY Float
createdById String
createdBy User @relation(fields: [createdById], references: [id])
createdAt DateTime @default(now())
}
enum AnnotationType { RECTANGLE ELLIPSE ARROW FREEHAND TEXT PIN }
Key files:
src/components/review/annotation-layer.tsxsrc/components/review/annotation-tools.tsxsrc/components/review/annotation-renderer.tsxsrc/lib/services/annotation-service.tssrc/lib/validators/annotation.tssrc/hooks/use-annotations.ts
Dependencies: Requires A2 (Image Viewer)
A4 — Side-by-Side Version Comparison (Full Viewer)
What: Compare two revisions in the full-screen viewer using side-by-side, overlay (opacity slider), wipe (draggable divider), or onion skin modes.
Key files:
src/components/review/comparison-viewer.tsxsrc/components/review/wipe-divider.tsxsrc/components/review/overlay-controls.tsxsrc/app/(app)/projects/[projectId]/deliverables/[deliverableId]/review/page.tsx
Dependencies: Requires A2
A5 — Revision History Timeline
What: Collapsible panel in the review viewer showing all revision rounds as a vertical timeline. Each node shows thumbnail, status badge, submitter, annotation count, comment summary, and decision record.
No new data model — aggregation over existing Revision, Comment, and Annotation records.
Key files:
src/components/review/revision-timeline.tsxsrc/components/review/revision-node.tsxsrc/components/review/revision-comments.tsxsrc/components/review/revision-annotations-summary.tsxsrc/hooks/use-revision-history.ts
Dependencies: Requires A2 + A3
A6 — Feedback Action Items (Artist Checklist)
What: Every annotation and actionable comment auto-creates a FeedbackItem on a structured checklist. Artists work through items (Critical / Major / Minor / Suggestion), check them off with resolution notes. Unresolved critical items block resubmission. Checklist appears in three places: review viewer panel, My Work page, and stage card badge.
New data model:
model FeedbackItem {
id String @id @default(cuid())
deliverableStageId String
deliverableStage DeliverableStage @relation(...)
revisionId String
revision Revision @relation(...)
annotationId String?
annotation Annotation? @relation(...)
commentId String?
comment Comment? @relation(...)
summary String
severity FeedbackSeverity @default(MAJOR)
status FeedbackStatus @default(OPEN)
sortOrder Int @default(0)
assignedToId String?
createdById String
resolvedById String?
resolvedAt DateTime?
resolutionNote String?
verifiedById String?
verifiedAt DateTime?
carriedFromId String? // carried forward from prior round
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@map("feedback_items")
}
enum FeedbackSeverity { CRITICAL MAJOR MINOR SUGGESTION }
enum FeedbackStatus { OPEN IN_PROGRESS RESOLVED VERIFIED REOPENED }
Key files:
src/components/review/feedback-checklist.tsxsrc/components/review/feedback-item.tsxsrc/components/review/feedback-progress-bar.tsxsrc/components/my-work/feedback-summary.tsxsrc/components/stages/feedback-indicator.tsxsrc/lib/services/feedback-service.tssrc/hooks/use-feedback-items.ts
Dependencies: Requires A3 + A5
A7 — Review Sessions & Playlists
What: Curate an ordered set of deliverables into a review session. Walk through them in presenter mode with per-item approve/request-changes/reject decisions. Shareable via link.
New data model:
model ReviewSession {
id String @id @default(cuid())
name String
status ReviewSessionStatus @default(DRAFT)
createdById String
organizationId String
shareToken String? @unique
expiresAt DateTime?
items ReviewSessionItem[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model ReviewSessionItem {
id String @id @default(cuid())
sessionId String
deliverableStageId String
revisionId String?
sortOrder Int
decision ReviewDecision?
decisionNote String?
decidedById String?
decidedAt DateTime?
}
enum ReviewSessionStatus { DRAFT IN_PROGRESS COMPLETED }
enum ReviewDecision { APPROVED CHANGES_REQUESTED REJECTED }
Key files:
src/app/(app)/reviews/page.tsxsrc/app/(app)/reviews/[sessionId]/page.tsxsrc/components/review/session-builder.tsxsrc/components/review/session-presenter.tsxsrc/components/review/session-summary.tsxsrc/lib/services/review-session-service.ts
Dependencies: Requires A2 + A3
B. Collaboration Enhancements
B1 — Rich @Mentions with Deep Linking
What: @ trigger in comment input opens user autocomplete. Mentioned users get a notification with a direct link to the comment.
Key files:
src/components/comments/mention-input.tsxsrc/components/comments/mention-renderer.tsx- Update
src/lib/services/comment-service.ts— extract mentions + create notifications
B2 — Project Activity Feed
What: Unified chronological stream of all activity on a project — status changes, comments, uploads, assignments, approvals.
New data model:
model ActivityEntry {
id String @id @default(cuid())
projectId String
deliverableId String?
stageId String?
userId String
type ActivityType
summary String
metadata Json?
createdAt DateTime @default(now())
}
enum ActivityType {
STATUS_CHANGE COMMENT_ADDED REVISION_SUBMITTED ASSIGNMENT_CHANGED
APPROVAL_DECISION FILE_UPLOADED DEADLINE_CHANGED PRIORITY_CHANGED
PROJECT_CREATED DELIVERABLE_CREATED
}
Key files:
src/components/activity/activity-feed.tsxsrc/components/activity/activity-entry.tsxsrc/lib/services/activity-service.tssrc/app/api/projects/[projectId]/activity/route.ts
B3 — External Review Links
What: Token-based URLs for external HP stakeholders to view specific deliverables without an account. Optional watermark (reviewer name, date, CONFIDENTIAL), configurable expiry, access logging, revoke capability.
Key files:
src/app/(external)/review/[token]/page.tsxsrc/components/review/watermark-overlay.tsxsrc/lib/services/external-link-service.ts
C. Reporting Completions
C1 — Velocity & Throughput Metrics
What: Deliverables completed per week, average time per stage, bottleneck detection. Trend charts over 4/8/12/26-week windows.
Key files:
src/components/dashboard/velocity-chart.tsxsrc/components/dashboard/cycle-time-chart.tsxsrc/components/dashboard/bottleneck-chart.tsxsrc/lib/services/analytics-service.ts
C2 — Burndown Charts
What: Per-project burndown with ideal line, actual line, and velocity-based projection with confidence interval. Warning when projection exceeds deadline.
Key files:
src/components/dashboard/burndown-chart.tsxsrc/components/dashboard/projection-engine.ts
C3 — Client-Facing Dashboard (Read-Only Portal)
What: Simplified read-only view for HP stakeholders via secure share link. No account required. Configurable visibility, optional password + expiry.
New data model:
model PortalLink {
id String @id @default(cuid())
token String @unique
organizationId String
projectIds String[]
createdById String
password String?
expiresAt DateTime?
lastAccessedAt DateTime?
accessCount Int @default(0)
isActive Boolean @default(true)
createdAt DateTime @default(now())
}
Key files:
src/app/(portal)/[token]/page.tsxsrc/app/(portal)/[token]/projects/[projectId]/page.tsxsrc/components/portal/portal-header.tsxsrc/lib/services/portal-service.ts
New dependency: bcryptjs (password hashing for portal links)
C4 — SLA Tracking
What: Target turnaround times per stage type. Real-time on-track / at-risk / breached status. Business-hours-aware calculation. Compliance dashboard widget.
New data model:
model SLATarget {
id String @id @default(cuid())
organizationId String
stageType String
targetHours Int
warningThreshold Float @default(0.75)
isActive Boolean @default(true)
createdAt DateTime @default(now())
}
Key files:
src/app/(app)/settings/sla/page.tsxsrc/components/dashboard/sla-compliance-chart.tsxsrc/components/stages/sla-indicator.tsxsrc/lib/services/sla-service.ts
D. Automation Completions
The automation rule engine (Phase 7.1) is fully built. These features extend it.
D1 — Automation Rules UI
What: Admin interface to create, edit, enable/disable automation rules. The engine exists — this is the management UI it's missing.
Key files:
src/app/(app)/settings/automations/page.tsxsrc/components/automations/rule-builder.tsxsrc/components/automations/execution-log.tsx
D2 — Multi-Level Approval Chains
What: Approval workflows requiring sign-off from multiple stakeholders in sequence. Each step: approver role/user, required/optional, auto-advance on approve. Visual progress indicator.
New data model:
model ApprovalChain {
id String @id @default(cuid())
name String
organizationId String
stageType String?
steps ApprovalStep[]
createdAt DateTime @default(now())
}
model ApprovalStep {
id String @id @default(cuid())
chainId String
stepOrder Int
approverRole Role?
approverUserId String?
isRequired Boolean @default(true)
autoAdvance Boolean @default(true)
approvalRecords ApprovalRecord[]
}
model ApprovalRecord {
id String @id @default(cuid())
deliverableStageId String
stepId String
decision ReviewDecision
note String?
decidedById String
decidedAt DateTime @default(now())
}
Key files:
src/app/(app)/settings/approvals/page.tsxsrc/components/approvals/chain-builder.tsxsrc/components/approvals/approval-progress.tsxsrc/lib/services/approval-service.ts
D3 — Project Templates
What: Save a full project configuration (deliverables, stage settings, default assignments) as a reusable template. One-click project creation for repeat HP SKU types.
New data model:
model ProjectTemplate {
id String @id @default(cuid())
name String
description String?
organizationId String
createdById String
isShared Boolean @default(true)
configuration Json
deliverables ProjectTemplateDeliverable[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model ProjectTemplateDeliverable {
id String @id @default(cuid())
templateId String
name String
type String?
priority Priority @default(MEDIUM)
defaultAssignments Json?
sortOrder Int
}
Key files:
src/app/(app)/templates/page.tsxsrc/components/templates/template-card.tsxsrc/components/templates/template-builder.tsxsrc/lib/services/template-service.ts
E. Asset Intelligence
E1 — File Validation on Upload
What: Automatically validate uploaded files against spec requirements (resolution, color space, format, file size, aspect ratio). Reject non-conforming files with clear error messages. Override option for producers.
New data model:
model AssetSpec {
id String @id @default(cuid())
organizationId String
stageType String
name String
rules Json // { minWidth, minHeight, maxFileSize, allowedFormats[], colorSpace, dpi }
isActive Boolean @default(true)
validationResults AssetValidationResult[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model AssetValidationResult {
id String @id @default(cuid())
revisionId String
specId String
passed Boolean
results Json // [{ check, expected, actual, passed }]
overrideById String?
overrideReason String?
validatedAt DateTime @default(now())
}
Key files:
src/app/(app)/settings/asset-specs/page.tsxsrc/components/upload/file-validator.tsxsrc/lib/services/asset-validation-service.ts
New dependency: sharp (already needed for A1 PNG compositing)
E2 — Thumbnail & Preview Generation
What: Auto-generate web-optimized thumbnails (200px), previews (1200px), and full copies from uploaded high-res assets. Background processing queue.
Key files:
src/lib/services/preview-service.tssrc/lib/jobs/generate-previews.tssrc/components/common/optimized-image.tsx
E3 — AI Review Engine Integration Point
What: Webhook endpoint for an external AI Review Engine to post structured quality analysis results. AI-flagged regions rendered as dashed-border annotations in the viewer. Configuration per stage type.
New data model:
model AIReviewResult {
id String @id @default(cuid())
revisionId String
overallScore Float
passed Boolean
checks Json
flaggedRegions Json
engineVersion String
processingTimeMs Int
createdAt DateTime @default(now())
}
Key files:
src/app/api/webhooks/ai-review/route.tssrc/components/review/ai-review-overlay.tsxsrc/components/review/ai-review-summary.tsxsrc/lib/services/ai-review-service.ts
F. Quality of Life
F1 — Saved Filters & Custom Views
What: Save current filter/sort/column config as a named view. Personal and shared views. URL-encodable for link sharing.
New data model:
model SavedView {
id String @id @default(cuid())
name String
userId String
organizationId String
projectId String?
viewType ViewType
configuration Json
isShared Boolean @default(false)
isPinned Boolean @default(false)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
enum ViewType { TABLE BOARD TIMELINE }
Key files:
src/components/views/saved-view-picker.tsxsrc/components/views/save-view-dialog.tsxsrc/lib/services/saved-view-service.ts
F2 — Skill-Based Assignment UI
What: The Skill / UserSkill / StageSkillRequirement data models already exist. This adds the UI: skill tags on user profiles, skill requirements on stage templates, and best-fit artist suggestions in the assignment dialog (sorted by skill match + lowest current load).
Key files:
src/app/(app)/settings/skills/page.tsxsrc/components/assignments/skill-match-suggestions.tsxsrc/lib/services/skill-service.ts— matching algorithm
F3 — Batch Upload with Auto-Matching
What: Drop multiple files onto a project; auto-match to deliverables by file naming convention (configurable regex). Preview table shows match confidence, manual override available.
Key files:
src/components/upload/batch-upload-zone.tsxsrc/components/upload/file-matcher.tsxsrc/lib/services/file-matching-service.ts
F4 — Extended Command Palette Actions
What: Add quick-action commands to the existing Cmd+K palette: "approve and advance," "assign to me," "mark blocked," "start review session." Context-aware based on current page.
Key files:
- Update
src/components/layout/command-palette.tsx src/lib/commands/action-registry.ts
G. Docker Deployment
G1 — Docker Compose Stack
What: docker-compose.yml with three services — Next.js app, PostgreSQL + pgvector, Ollama with pre-configured models. One docker compose up starts everything.
Note: Dockerfile and docker-compose.yml already exist in the repo root — review and complete as needed.
Services:
| Service | Image | Purpose |
|---|---|---|
app |
Custom Dockerfile | Next.js production build |
db |
pgvector/pgvector:pg17 |
PostgreSQL with pgvector |
ollama |
ollama/ollama:latest |
Local AI (nomic-embed-text + qwen3.5:9b) |
Key files:
Dockerfile— multi-stage Next.js build (review existing)docker-compose.yml— full stack (review existing)docker/ollama-entrypoint.sh— model bootstrap scriptdocker/db-init.sql—CREATE EXTENSION IF NOT EXISTS vector;.env.example— environment template
G2 — Health Checks & Startup Orchestration
What: pg_isready health check on db, Ollama API health check, prisma migrate deploy runs on app startup before next start. depends_on: condition: service_healthy ensures correct start order.
G3 — Dev Environment Override
What: docker-compose.dev.yml that mounts source code and runs next dev for hot reloading, while keeping database and Ollama in containers.
Key files:
docker-compose.dev.yml
Data Model Status
Models Currently in Schema
| Model | Status |
|---|---|
| Organization, User, Account, Session | ✅ |
| PipelineStageTemplate, PipelineStageDependency | ✅ |
| Project, Deliverable, DeliverableStage | ✅ (with pgvector embedding columns) |
| StageAssignment, Revision, Comment | ✅ |
| Notification | ✅ |
| AutomationRule, AutomationExecution | ✅ |
| Skill, UserSkill, StageSkillRequirement | ✅ |
| SearchLog | ✅ |
| ChatMessage | ✅ |
Models Needed (not yet in schema)
| Model | Feature |
|---|---|
| Annotation, FeedbackItem | A3, A6 |
| ReviewSession, ReviewSessionItem | A7 |
| ApprovalChain, ApprovalStep, ApprovalRecord | D2 |
| ProjectTemplate, ProjectTemplateDeliverable | D3 |
| AssetSpec, AssetValidationResult | E1 |
| AIReviewResult | E3 |
| PortalLink | C3 |
| SLATarget | C4 |
| ActivityEntry | B2 |
| SavedView | F1 |
Architecture Reference
src/
├── app/
│ ├── (auth)/login/ # SSO login
│ ├── (app)/ # Authenticated routes
│ │ ├── dashboard/
│ │ ├── projects/[projectId]/
│ │ │ ├── table/ board/ timeline/
│ │ │ └── deliverables/[deliverableId]/
│ │ ├── my-work/
│ │ ├── workload/ # ✅ Capacity grid + heatmap
│ │ ├── calendar/ # ✅ Calendar view
│ │ ├── reports/weekly/ # ✅ Weekly executive report
│ │ ├── reviews/ # A7 Review sessions
│ │ ├── templates/ # D3 Project templates
│ │ └── settings/
│ ├── (portal)/[token]/ # C3 Client portal (external)
│ ├── (external)/review/ # B3 External review links
│ └── api/
├── components/
│ ├── ui/ # shadcn/ui primitives
│ ├── layout/ # Sidebar, topbar, command palette
│ ├── views/ # Table, Board, Timeline, Dashboard
│ ├── workload/ # ✅ Capacity grid + heatmap components
│ ├── calendar/ # ✅ Calendar components
│ ├── reports/weekly/ # ✅ Weekly report components
│ ├── revisions/ # A1 Image comparison (to build)
│ ├── review/ # A2-A7 Full review viewer (to build)
│ ├── automations/ # D1 Automation UI (to build)
│ └── search/ # ✅ Smart search panel
├── lib/
│ ├── pipeline/ # ✅ Dependency engine + stage machine
│ ├── automation/ # ✅ Event bus + rule engine + executor
│ ├── services/ # Business logic per entity
│ └── validators/ # Zod schemas
├── hooks/ # TanStack Query hooks
└── stores/ # Zustand (UI state, filters)
Key Patterns
- Thin API routes → delegate to
lib/services/for all business logic - Service layer → Prisma queries + business rules (testable, reusable)
- URL-synced filters via
nuqs— views are shareable/bookmarkable - Server Components for initial fetch, TanStack Query for mutations/cache
npx prisma db pushfor schema changes (no migrations dir — use db push)
Local Dev
# Start DB
brew services start postgresql@17
# Start app (must source nvm)
export NVM_DIR="$HOME/.nvm" && [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" && npm run dev
Third-Party Libraries Needed for Remaining Work
| Library | Purpose | Feature |
|---|---|---|
sharp |
PNG alpha compositing + image validation + thumbnail generation | A1, E1, E2 |
bcryptjs |
Password hashing for portal links | C3 |
@react-pdf/renderer |
PDF export for weekly report download button | C — weekly report enhancement |
Document version: 1.0 — Created 2026-03-14 To be updated as features are built and priorities shift.