### Start Production Server with pnpm Source: https://github.com/jason-uxui/project-dashboard/blob/main/README.md Starts the production server after building the project. This command is used to run the optimized production build. ```bash pnpm start ``` -------------------------------- ### Install Dependencies with pnpm Source: https://github.com/jason-uxui/project-dashboard/blob/main/README.md Use this command to install project dependencies. pnpm is recommended for this project. ```bash pnpm install ``` -------------------------------- ### Development Setup and Commands Source: https://context7.com/jason-uxui/project-dashboard/llms.txt Provides essential commands for setting up the project, running the development server, building for production, and linting the codebase. Node.js 18+ is required. ```bash # Install dependencies (Node.js 18+ required) pnpm install # Start development server pnpm dev # → http://localhost:3000 # Production build pnpm build pnpm start # Lint pnpm lint ``` -------------------------------- ### Run Development Server with pnpm Source: https://github.com/jason-uxui/project-dashboard/blob/main/README.md Starts the development server for local testing and development. The application will be available at http://localhost:3000. ```bash pnpm dev ``` -------------------------------- ### ProjectWizard Component (TSX) Source: https://context7.com/jason-uxui/project-dashboard/llms.txt An animated multi-step modal for creating projects, supporting both quick and guided flows. Tracks steps and emits onCreate event. ```tsx import { ProjectWizard } from "@/components/project-wizard/ProjectWizard" // Mount when isOpen=true; unmount on close {isWizardOpen && ( setIsWizardOpen(false)} onCreate={() => { // persist project data here — currently fires toast only setIsWizardOpen(false) }} /> )} // Internal step flow: // step 0 : StepMode → user picks "quick" or "guided" // step 100: StepQuickCreate (quick path only) // step 1 : StepIntent → project intent category // step 2 : StepOutcome → deliverables, metrics, description, deadline // step 3 : StepOwnership → owner (required to advance), contributors, stakeholders // step 4 : StepStructure → addStarterTasks toggle // step 5 : StepReview → summary with edit-step shortcuts + "Create project" CTA // ProjectData shape collected across steps: type ProjectData = { mode?: "quick" | "guided" intent?: string successType: string deliverables: string[] metrics: string[] description: string deadlineType: "none" | string ownerId?: string contributorIds: string[] stakeholderIds: string[] addStarterTasks: boolean } ``` -------------------------------- ### Build for Production with pnpm Source: https://github.com/jason-uxui/project-dashboard/blob/main/README.md Builds the project for production deployment. This command generates optimized production assets. ```bash pnpm build ``` -------------------------------- ### Main Page Structure with Sidebar Source: https://context7.com/jason-uxui/project-dashboard/llms.txt This component sets up the main page layout, wrapping the sidebar and content area with SidebarProvider. It uses Suspense for asynchronous loading of project content. ```tsx // app/page.tsx import { Suspense } from "react" import { AppSidebar } from "@/components/app-sidebar" import { ProjectsContent } from "@/components/projects-content" import { SidebarProvider, SidebarInset } from "@/components/ui/sidebar" export default function Page() { return ( {/* URL-synced, filter-aware, view-switching */} ) } ``` -------------------------------- ### Update View Options Source: https://context7.com/jason-uxui/project-dashboard/llms.txt Shows how to create a new `ViewOptions` object by overriding properties from `DEFAULT_VIEW_OPTIONS`. This is useful for applying specific view configurations, such as switching to a timeline view sorted alphabetically. ```typescript // Switching to timeline view sorted alphabetically const nextOpts: ViewOptions = { ...DEFAULT_VIEW_OPTIONS, viewType: "timeline", ordering: "alphabetical", } ``` -------------------------------- ### Root Layout Configuration (TSX) Source: https://context7.com/jason-uxui/project-dashboard/llms.txt Sets global metadata, fonts, theme provider, toaster, and analytics for the application. This is the main entry point for the app. ```tsx // app/layout.tsx export const metadata: Metadata = { title: "PM Tools - Project Management", description: "Modern project and task management tool with timeline view", } export const viewport: Viewport = { themeColor: "#3b82f6", } export default function RootLayout({ children }) { return ( {children} ) } ``` -------------------------------- ### Kanban Project Board View Source: https://context7.com/jason-uxui/project-dashboard/llms.txt Kanban board component displaying projects in four status columns. Supports drag-and-drop between columns and status changes via a popover menu. Renders skeleton and empty states. ```tsx import { ProjectBoardView } from "@/components/project-board-view" import { projects } from "@/lib/data/projects" // Full usage openWizard()} /> // Drag-and-drop is handled internally: // onDragStart → stores project.id in dataTransfer // onDrop → updates local state: project.status = targetColumn // Popover "Move to …" → same status update without drag // Column order is fixed: const COLUMN_ORDER = ["backlog", "planned", "active", "completed"] ``` -------------------------------- ### Apply Filters using Next.js Navigation Source: https://context7.com/jason-uxui/project-dashboard/llms.txt Demonstrates a typical usage pattern within a Next.js component to apply filters by updating the URL using `router.replace`. It converts current search params to chips, then back to a query string for the new URL. ```typescript // Typical usage inside a Next.js component import { useSearchParams, useRouter, usePathname } from "next/navigation" function MyPage() { const searchParams = useSearchParams() const router = useRouter() const pathname = usePathname() const chips = paramsToChips(new URLSearchParams(searchParams.toString())) const applyFilters = (next: FilterChip[]) => { const qs = chipsToParams(next).toString() const url = qs ? `${pathname}?${qs}` : pathname router.replace(url, { scroll: false }) } return null } ``` -------------------------------- ### Project Cards Grid View Source: https://context7.com/jason-uxui/project-dashboard/llms.txt Responsive grid view for project cards, adapting column count based on screen size. Includes loading, empty, and add card states. ```tsx import { ProjectCardsView } from "@/components/project-cards-view" import { projects } from "@/lib/data/projects" // With data setIsWizardOpen(true)} /> // Loading state — renders 8 skeleton cards // Empty state — renders illustration + CTA button setIsWizardOpen(true)} /> ``` -------------------------------- ### ProjectsContent State Management Source: https://context7.com/jason-uxui/project-dashboard/llms.txt Manages URL-synced filter state, view options, and the project wizard lifecycle. Use this component to orchestrate the main content of the projects page. ```tsx "use client" // Simplified version showing state management pattern import { useEffect, useState, useRef, useMemo } from "react" import { useSearchParams, useRouter, usePathname } from "next/navigation" import { ProjectTimeline } from "@/components/project-timeline" import { ProjectCardsView } from "@/components/project-cards-view" import { ProjectBoardView } from "@/components/project-board-view" import { ProjectWizard } from "@/components/project-wizard/ProjectWizard" import { computeFilterCounts, projects } from "@/lib/data/projects" import { DEFAULT_VIEW_OPTIONS, type FilterChip, type ViewOptions } from "@/lib/view-options" import { chipsToParams, paramsToChips } from "@/lib/url/filters" export function ProjectsContent() { const [viewOptions, setViewOptions] = useState(DEFAULT_VIEW_OPTIONS) const [filters, setFilters] = useState([]) const [isWizardOpen, setIsWizardOpen] = useState(false) // filteredProjects applies status toggle + chip filters + ordering const filteredProjects = useMemo(() => { let list = projects.slice() if (!viewOptions.showClosedProjects) { list = list.filter(p => p.status !== "completed" && p.status !== "cancelled") } // … chip filtering by status, priority, tags, members … if (viewOptions.ordering === "alphabetical") list.sort((a, b) => a.name.localeCompare(b.name)) if (viewOptions.ordering === "date") list.sort((a, b) => a.endDate.getTime() - b.endDate.getTime()) return list }, [filters, viewOptions]) return (
{/* ProjectHeader with filter chips and view options */} {viewOptions.viewType === "timeline" && } {viewOptions.viewType === "list" && setIsWizardOpen(true)} />} {viewOptions.viewType === "board" && setIsWizardOpen(true)} />} {isWizardOpen && setIsWizardOpen(false)} onCreate={() => setIsWizardOpen(false)} />}
) } ``` -------------------------------- ### Define Default View Options Source: https://context7.com/jason-uxui/project-dashboard/llms.txt Defines the default state for view controls, including view type, task display, ordering, grouping, and visible properties. This constant is used to initialize the view state. ```typescript import { DEFAULT_VIEW_OPTIONS, type ViewOptions } from "@/lib/view-options" const opts: ViewOptions = { viewType: "list", // "list" | "board" | "timeline" tasks: "indented", // "indented" | "collapsed" | "flat" ordering: "manual", // "manual" | "alphabetical" | "date" showAbsentParent: false, showClosedProjects: true, groupBy: "none", // "none" | "status" | "assignee" | "tags" properties: ["title", "status", "assignee", "dueDate"], } ``` -------------------------------- ### ProjectTimeline Drop-in Usage Source: https://context7.com/jason-uxui/project-dashboard/llms.txt A drop-in component that reads from internal data and maintains its own local state for drag mutations. Use this for displaying an interactive Gantt-style timeline. ```tsx import { ProjectTimeline } from "@/components/project-timeline" // Drop-in: reads from lib/data/projects internally, // maintains its own local state copy for drag mutations. export default function TimelinePage() { return (
) } ``` ```typescript // Internal interaction API (callbacks used by DraggableBar): // onUpdateStart(projectId, newStart: Date) — move project bar // onUpdateDuration(projectId, newStart, newEnd) — resize project bar // onUpdateTask(projectId, taskId, newStart) — move task bar // onUpdateTaskDuration(projectId, taskId, ns, ne) — resize task bar // toggleProject(projectId) — expand/collapse row // goToToday() — scroll viewport to today // navigateTime("prev" | "next") — advance by view-period ``` -------------------------------- ### Sidebar Navigation and Data Seeds Source: https://context7.com/jason-uxui/project-dashboard/llms.txt Provides typed seed data for the `AppSidebar` component, controlling navigation items, active projects, and footer menus. Modifying these arrays reshapes the sidebar. ```typescript import { navItems, activeProjects, footerItems, type NavItem, type ActiveProjectSummary, type SidebarFooterItem, } from "@/lib/data/sidebar" // navItems drives the primary navigation list navItems.forEach((item: NavItem) => { console.log(item.id, item.label, item.badge) }) // "inbox" "Inbox" 24 // "my-tasks" "My task" undefined // "projects" "Projects" undefined (isActive: true) // "clients" "Clients" undefined // "performance" "Performance" undefined // activeProjects drives the "Active Projects" sidebar section activeProjects.forEach((p: ActiveProjectSummary) => { console.log(p.name, p.progress, p.color) }) // "AI Learning Platform" 25 "var(--chart-5)" // "Fintech Mobile App" 80 "var(--chart-3)" ``` -------------------------------- ### Project Detail Page Routing Source: https://context7.com/jason-uxui/project-dashboard/llms.txt Defines the dynamic route for individual project detail views. This page is accessed when a user clicks on a ProjectCard, navigating to a specific project's URL. ```tsx // app/projects/[id]/page.tsx // Accessed via router.push(`/projects/${project.id}`) in ProjectCard // Companion routes: // app/projects/[id]/backlog/page.tsx — backlog sub-view // app/inbox/page.tsx — notifications / inbox // app/tasks/page.tsx — personal task list // app/clients/[id]/page.tsx — client detail // app/performance/page.tsx — performance metrics ``` -------------------------------- ### App Sidebar Canonical Usage in Next.js Source: https://context7.com/jason-uxui/project-dashboard/llms.txt Shows the canonical usage of the `AppSidebar` component within a Next.js page (`app/page.tsx`). It highlights the integration with `SidebarProvider` and `Suspense` for lazy loading content. ```tsx // app/page.tsx — canonical usage import { Suspense } from "react" import { AppSidebar } from "@/components/app-sidebar" import { ProjectsContent } from "@/components/projects-content" import { SidebarProvider, SidebarInset } from "@/components/ui/sidebar" export default function Page() { return ( {/* Sidebar is self-contained */} ) } ``` -------------------------------- ### Convert Filter Chips to URL Parameters Source: https://context7.com/jason-uxui/project-dashboard/llms.txt Converts an array of filter chips into a URLSearchParams string. Useful for sharing filter states or persisting them across sessions. Ensure the input `FilterChip` array is correctly formatted. ```typescript import { chipsToParams, paramsToChips } from "@/lib/url/filters" import type { FilterChip } from "@/lib/view-options" // Convert active filter chips → URL query string const chips: FilterChip[] = [ { key: "Status", value: "Active" }, { key: "Priority", value: "High" }, { key: "Tag", value: "frontend" }, ] const params = chipsToParams(chips) console.log(params.toString()) // "status=Active&priority=High&tags=frontend" ``` -------------------------------- ### Project Type Definition and Access Source: https://context7.com/jason-uxui/project-dashboard/llms.txt Defines the `Project` type, the central data model for all dashboard features. Shows how to access the typed project shape and the seed array. ```typescript import { projects, type Project } from "@/lib/data/projects" // Fully-typed project shape const example: Project = { id: "1", name: "Fintech Mobile App Redesign", taskCount: 4, progress: 35, // 0–100 startDate: new Date(2024, 0, 19), endDate: new Date(2024, 1, 13), status: "active", // "backlog" | "planned" | "active" | "cancelled" | "completed" priority: "high", // "urgent" | "high" | "medium" | "low" tags: ["frontend", "feature"], members: ["jason duong"], client: "Acme Corp", typeLabel: "MVP", durationLabel: "2 weeks", tasks: [ { id: "1-1", name: "Discovery & IA", type: "task", // "bug" | "improvement" | "task" assignee: "JD", status: "done", // "todo" | "in-progress" | "done" startDate: new Date(2024, 0, 19), endDate: new Date(2024, 0, 26), }, ], } // Access the seed array directly console.log(projects.length) // 12 console.log(projects[0].name) // "Fintech Mobile App Redesign" ``` -------------------------------- ### Progress Circle Component Source: https://context7.com/jason-uxui/project-dashboard/llms.txt An SVG component for visualizing completion percentage with a background ring and an animated progress arc. Used in sidebar lists. ```tsx import { ProgressCircle } from "@/components/progress-circle" // Default: 18px, 2px stroke // Custom size & stroke // Renders: // // // // ``` -------------------------------- ### Component Usage of `cn` Utility Source: https://context7.com/jason-uxui/project-dashboard/llms.txt Illustrates the typical usage of the `cn` utility within a React component's `className` prop to conditionally apply styles based on component state, such as `isActive`. ```typescript // Typical component usage function MyComponent({ isActive }: { isActive: boolean }) { return (
) } ``` -------------------------------- ### App Sidebar Navigation Routing Table Source: https://context7.com/jason-uxui/project-dashboard/llms.txt Internal routing table for the `AppSidebar` component, mapping internal IDs to their corresponding URL paths. This defines the navigation structure within the application. ```typescript // AppSidebar navigation routing table (internal): // id: "inbox" → /inbox // id: "my-tasks" → /tasks // id: "projects" → / // id: "clients" → /clients // id: "performance" → /performance ``` -------------------------------- ### Priority Display Components (TSX) Source: https://context7.com/jason-uxui/project-dashboard/llms.txt Use PriorityGlyphIcon for icon-only display and PriorityBadge for pill or inline text badges. Configure appearance and size as needed. ```tsx import { PriorityBadge, PriorityGlyphIcon } from "@/components/priority-badge" // Icon only (used in timeline task rows) // 3-bar SVG glyph // WarningOctagon icon // Pill badge (used in card list view) // → rounded border pill: "⟨bars⟩ Medium" // Inline text with icon (used in board card header) // → "⟨bars⟩ High" (no border/background) // Badge without icon // → "Low" (xs text, pill border) ``` -------------------------------- ### Individual Project Card Component Source: https://context7.com/jason-uxui/project-dashboard/llms.txt Component to display a single project card in list or board variants. Includes navigation, drag guards, and status/priority badges. ```tsx import { ProjectCard } from "@/components/project-card" import { projects } from "@/lib/data/projects" // List variant (default) — used in ProjectCardsView // Board variant — used in ProjectBoardView, adds drag-guard logic …move-to options… } /> // Keyboard: Enter / Space → navigate to project detail // Board drag guard: if pointer moved > 5px, navigation is suppressed on mouseup ``` -------------------------------- ### Resolve Tailwind Class Conflicts Source: https://context7.com/jason-uxui/project-dashboard/llms.txt Demonstrates how `cn` resolves conflicting Tailwind classes, prioritizing the last specified class. This ensures consistent styling by preventing duplicate or contradictory utility classes. ```typescript // Resolving Tailwind conflicts (tailwind-merge keeps last) cn("text-sm text-muted-foreground", "text-base") // → "text-muted-foreground text-base" ``` -------------------------------- ### Draggable Timeline Bar Component Source: https://context7.com/jason-uxui/project-dashboard/llms.txt A low-level component for creating draggable and resizable timeline bars. Use for tasks or projects within a timeline view. State is managed locally and propagated via callbacks. ```tsx import { DraggableBar, type TimelineBarItem } from "@/components/project-timeline-draggable-bar" const item: TimelineBarItem = { id: "task-1", name: "Wireframe layout", startDate: new Date(2024, 0, 25), endDate: new Date(2024, 0, 30), status: "in-progress", // controls color: "done" → teal, else blue } console.log("moved to", newStart)} onUpdateDuration={(id, ns, ne) => console.log("resized", ns, "→", ne)} onDoubleClick={() => openEditDialog("task", item.id)} /> // Drag within 8px of left/right edge → resize; drag elsewhere → move // Fires onUpdateStart / onUpdateDuration only when daysMoved !== 0 ``` -------------------------------- ### Compute Filter Counts Utility Source: https://context7.com/jason-uxui/project-dashboard/llms.txt Calculates counts for filterable project dimensions from a `Project[]` list. Useful for displaying the number of projects matching each filter option. ```typescript import { computeFilterCounts, projects } from "@/lib/data/projects" const all = computeFilterCounts(projects) // { // status: { active: 4, completed: 4, planned: 3, backlog: 1 }, // priority: { high: 3, medium: 4, urgent: 1, low: 4 }, // tags: { frontend: 5, backend: 3, feature: 4, bug: 2, … }, // members: { current: 11, jason: 11, "no-member": 1 } // } // Counts after a runtime filter const active = projects.filter(p => p.status === "active") const activeCounts = computeFilterCounts(active) console.log(activeCounts.priority) // { high: 1, medium: 2, urgent: 1 } ``` -------------------------------- ### Reconstruct Filter Chips from URL Parameters Source: https://context7.com/jason-uxui/project-dashboard/llms.txt Reconstructs an array of `FilterChip` objects from a `URLSearchParams` object. This is useful for restoring filter states after navigation or page reloads. Handles multiple values for the same key. ```typescript // Reconstruct chips from a URL (e.g. after navigation) const incoming = new URLSearchParams("status=Active,Completed&priority=High") const restored = paramsToChips(incoming) // [ // { key: "Status", value: "Active" }, // { key: "Status", value: "Completed" }, // { key: "Priority", value: "High" }, // ] ``` -------------------------------- ### Merge Conditional Tailwind Classes Source: https://context7.com/jason-uxui/project-dashboard/llms.txt A utility function that merges Tailwind CSS class strings, handling conditional classes and resolving conflicts using `clsx` and `tailwind-merge`. It's used universally for dynamic styling. ```typescript import { cn } from "@/lib/utils" // Basic conditional class merging cn("px-4 py-2", true && "bg-blue-500", false && "bg-red-500") // → "px-4 py-2 bg-blue-500" ``` -------------------------------- ### FilterPopover Component (TSX) Source: https://context7.com/jason-uxui/project-dashboard/llms.txt A two-panel filter sheet for selecting categories and options. Emits FilterChip array on apply and provides an onClear callback. ```tsx import { FilterPopover } from "@/components/filter-popover" import type { FilterChip } from "@/lib/view-options" import { computeFilterCounts, projects } from "@/lib/data/projects" const [chips, setChips] = useState([]) setChips(next)} onClear={() => setChips([])} /> // After clicking "Apply" with Status=Active, Priority=High selected: // onApply([ // { key: "Status", value: "Active" }, // { key: "Priority", value: "High" }, // ]) ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.