A modern, scalable Project Management Dashboard built with React 19, React Router v7 (App Router), Redux Toolkit, and TailwindCSS v4.
A modern, scalable Project Management Dashboard built with React 19, React Router v7 (App Router), TailwindCSS v4, and Clerk Authentication.
The project follows real-world production architecture, focusing on:
- UI-first development
- Feature-based folder organization
- Skeleton loaders for async UX
- Clean separation of concerns
- Accessibility and performance best practices
This project is built in React Router v7 framework mode (file-based routing). Routes must be defined inside app/routes.
- Fully configured React Router v7 App Directory (file-based routing)
- Modular & scalable component architecture
- Global Layout system (Navbar + Sidebar)
- Intelligent layout hiding for routes like
/loginand404 - Organized folder structure following industry-level best practices
- Integrated ClerkProvider at the app root
- Authentication handled fully by Clerk
- Supports:
- OAuth providers (Google-ready)
- Session-based auth
- Secure route protection
The dashboard is composed of multiple independent widgets:
- Stats Grid (animated with Framer Motion)
- Project overview
- Recent activities
- Task summary
Each widget: - Is built as an isolated component
- Uses mock data for UI validation
- Is ready for backend integration
- Avoids premature global state coupling
Added highly polished skeleton loaders for:
StatsGridSkeletonProjectOverviewSkeletonRecentActivitySkeletonTaskSummarySkeleton
- Smooth entrance animations for dashboard widgets using Framer Motion
- Staggered card animations in the StatsGrid
- Skeleton → content transitions for improved perceived performance
- Subtle hover micro-interactions for stat cards
Skeletons:
- Match final layout structure
- Use TailwindCSS animate-pulse
- Prevent layout shift
- Are easily replaceable with real loading states later
Performance Optimizations
- Dashboard sections are:
- Lazy-loaded with React.lazy
- Wrapped with Suspense
- Memoized using memo()
- Optimized re-renders and layout stability
- Search bar
- Light/Dark theme toggle
- User avatar
- Fully keyboard accessible
- Desktop fixed version
- Mobile slide-in version
- Touch-friendly overlay
- Click outside to close
- Escape key support
- ARIA role-based navigation
Standardized form behavior across the entire application by customizing base shadcn/ui components.
Improvements include:
- Consistent labeled form layout for all dialogs
- Structured 2-column grid alignment for related fields
- Full-width selects for primary inputs (Lead, Members)
- Centralized Select dropdown styling with:
- Blue hover state
- Blue keyboard focus state
- Accessible interactions
- Customized Input & Textarea focus styles:
- Thin black border on focus
- Removed default ring glow
- Cleaner modern SaaS look
- Updated styles directly inside
/components/ui/*to avoid repetition
Implemented a reusable CreateProjectDialog component for creating new projects.
Features:
- Lazy-loaded using React.lazy
- Conditionally mounted (renders only when opened)
- Memoized with React.memo to prevent unnecessary re-renders
- Structured labeled form layout
- 2-column responsive grid alignment
- Status & Priority selectors
- Start/End date inputs
- Project Lead and Team Members dropdowns
- Global Select hover/focus styling
- Consistent Input & Textarea focus behavior
- Fully accessible (focus trap, keyboard support, ARIA compliant)
Performance:
- Dialog mounts only when opened
- Reduces initial bundle size
- Improves first paint
- Ensures smooth open/close animations
Implemented a fully responsive Projects module following feature-based architecture.
- Added /projects route using React Router v7 file-based routing
- Integrated with global Layout (Navbar + Sidebar)
- Protected under Clerk authentication
- Responsive layout
- Header with contextual page description
- Gradient “New Project” action button
- Search input field (UI-ready)
- Status filter dropdown (shadcn Select)
- Priority filter dropdown (shadcn Select)
- Grid-based project layou
- Accessible semantic structure (, ,
) - Reusable and memoized
- Fully typed with strict TypeScript interfaces
- Status badge with dynamic color mapping
- Priority display
- Progress bar with ARIA attributes
- Accessible navigation via Link
- Responsive design and hover interactions
- Added NotFound (404) Page
- Automatically served for unknown routes
- Sidebar + Navbar are hidden on 404 page
Implemented a scalable nested routing structure for project-level navigation.
The application now supports dynamic routes using: /projects/:projectId
Each project contains nested sections:
/projects/:projectId/tasks /projects/:projectId/analytics /projects/:projectId/calendar /projects/:projectId/settings
- Uses useParams() to extract projectId
- Renders shared project header
- Provides tab-based navigation
- Uses for nested rendering
- Avoids re-rendering full layout on tab switch
- Nested Routing Configuration
- Routes are structured using React Router v7 framework mode:
- Index route defaults to tasks
- Child routes render inside ProjectLayout
- Clean separation between layout and content
- Built a dynamic ProjectSidebar component:
- Displays workspace projects
- Uses shadcn/ui Collapsible for expandable navigation
- Links to dynamic project routes
- Auto-expands active project based on URL
- Fully accessible and keyboard-friendly
Implemented a scalable and extensible task management system inside each project.
Tasks are rendered via nested routing under:
- /projects/:projectId The default index route renders the Tasks module.
- Built using @tanstack/react-table v8
- Integrated with shadcn/ui Table components
- Fully typed using strict TypeScript generics
- Column sorting
- Custom cell rendering
- Status badges
- Priority formatting
- Empty state handling
- Responsive container with horizontal scroll
- Accessible semantic table structure
Implemented a responsive and accessible Project Settings module under:
- Replaced tab-based layout with responsive 2-column grid
- Left: General project configuration
- Right: Project members management
- Consistent bordered sections aligned with Tasks module UI
- Mobile-first responsive design
- Fully typed form using React Hook Form + Zod
- Editable fields:
- Project Name
- Description
- Start & End Dates
- Status
- Priority
- Accessible labels and ARIA attributes
- Clean focus states aligned with global UI system
- Responsive member list
- Role display (Team Lead / Member)
- Change Role action
- Remove member action
- Improved mobile layout:
- Stacked action buttons
- Equal button width
- Proper alignment
- Semantic structure using
, - , and
UI Improvements:
- Refined button alignment for better UX
- Improved spacing consistency
- Reduced visual imbalance in action buttons
- Fully responsive and accessible design
Implemented a fully interactive and responsive Calendar module under:
/projects/:projectId/calendar
The Calendar module provides a visual task scheduling interface within each project.
It is built using FullCalendar and follows performance, scalability, and accessibility best practices.- Monthly grid view (DayGridMonth)
- Custom day cell rendering
- Full-cell highlighting for task dates
- Dynamic task badge injection
- Date click → opens Task Modal
- Drag-and-drop support (UI-ready for backend integration)
- Responsive layout with sidebar integration
- Derived Upcoming & Overdue task panels
- Optimized event lookup using Map for constant-time access (O(1))
The Calendar page uses a responsive grid system:
- Desktop → 2/3 Calendar | 1/3 Sidebar (Upcoming & Overdue)
- Tablet → Stacked layout
- Mobile → Fully stacked vertical layout
Sidebar includes:
- Upcoming Tasks
- Overdue Tasks
Both sections:
- Use semantic
<section>and<ul>structures - Implement accessible
<time>elements - Follow consistent UI system styling
- Support keyboard navigation and focus states
- Events transformed using a custom
useCalendarEventshook - Precomputed
Mapfor constant-time date lookups - Memoized derived state (upcoming & overdue tasks)
- Avoided repeated
.find()operations inside calendar cells - Local modal state (no unnecessary global state usage)
- ARIA-labelled sections
- Semantic HTML structure
- Focus-visible styling
- Screen-reader friendly time elements
- Keyboard-accessible interactions
Implemented a fully responsive and data-driven Analytics module under:
/projects/:projectId/analytics
The Analytics module provides real-time project insights using visual KPIs and interactive charts.
It transforms raw task data into meaningful performance metrics using memoized calculations and responsive visualizations.Built with:
- Recharts (Bar & Pie charts)
- Lucide React (icons)
- TailwindCSS design system
- Semantic & accessible chart structures
- React.memo for render optimization
Displayed at the top of the page:
- Completion Rate (%)
- Active Tasks (IN_PROGRESS)
- Overdue Tasks
- Team Size
Each KPI:
- Uses a reusable
MetricCardcomponent - Is memoized with React.memo
- Supports semantic structure using
<article> - Uses accessible ARIA labels
- Includes smooth hover micro-interactions
- Displays TODO, IN_PROGRESS, DONE counts
- Dynamic semantic color mapping
- No deprecated
<Cell>usage - Uses data-driven
fillproperty - Custom tooltip component
- Responsive via
ResponsiveContainer - Accessible via
<section>+<figure>+<figcaption>
- Displays distribution of task types (Feature, Bug, Improvement, etc.)
- Custom tooltip styling
- Animated transitions
- Legend support
- Fully responsive container
- Screen-reader friendly structure
- Calculates LOW / MEDIUM / HIGH distribution
- Displays percentage relative to total tasks
- Derived from memoized analytics logic
- Fully typed using strict TypeScript interfaces
All analytics calculations are wrapped inside
useMemo()to prevent unnecessary recalculations.Derived values include:
- Total tasks
- Completed tasks
- In-progress tasks
- Overdue tasks
- Status distribution
- Type distribution
- Priority percentage breakdown
Benefits:
- Prevents redundant loops
- Ensures stable chart data
- Optimizes re-renders
- Keeps analytics computation isolated from UI
- Semantic
<main>,<section>,<header>,<article>structure - ARIA-labelled chart sections
- Screen-reader descriptions using
<figcaption class="sr-only"> - Accessible tooltip contrast
- Keyboard-friendly UI structure
- Clear color contrast in charts
- Responsive KPI grid (1 → 2 → 4 columns)
- Two-column chart layout on large screens
- Stacked layout on mobile
- Consistent bordered container system (aligned with Tasks & Settings modules)
- Dark mode fully supported
- Reusable
MetricCard,StatusBarChart, andTypePieChartcomponents - Strict TypeScript typing for analytics data models
- Clean separation between data processing and visualization
- Future-ready for backend integration
Implemented a fully scalable and production-ready Team Management module.
Route:
/team
The Team module allows workspace-level team management with a consistent UI system aligned with the Projects module.
Built with:
- TanStack React Table v8
- shadcn/ui components
- Controlled dialog pattern
- Strict TypeScript typing
- Reusable StatsGrid integration
The Team page includes:
- Header with primary CTA (Invite Member)
- Stats overview grid
- Search input for member filtering
- Sortable team data table
All sections follow semantic HTML structure using:
<main><header><section>
Reused the existing
StatsGridcomponent from Dashboard.Displays:
- Total Members
- Active Projects
- Total Tasks
Ensures:
- Component reuse
- Design consistency
- Avoided duplicate UI logic
Implemented using:
@tanstack/react-table v8createColumnHelpergetCoreRowModelgetSortedRowModel
Features:
- Sortable Name column
- Custom cell rendering
- Role-based badge color mapping
- Dynamic avatar color generation
- Empty state handling
- Fully typed column definitions
- Semantic and accessible table structure
- Deterministic avatar background colors
- Generated using character-based hashing
- Improves visual differentiation between users
- Role-based color mapping using a scalable object pattern
- Avoided nested ternary conditions
- Easily extensible for additional roles
Refactored to follow the same architecture pattern as CreateProjectDialog.
Improvements:
- Controlled dialog pattern (
open+onOpenChange) - Parent-managed state
- Memoized component using
React.memo - useCallback for submit handler
- Accessible form structure
- Role selector using shadcn Select
- Loading state handling
- DialogFooter consistency
Performance:
- Prevents unnecessary re-renders
- Keeps modal logic isolated
- Enables permission-based rendering in future
Standardized CTA button styling across:
- New Project
- Invite Member
Ensures:
- Consistent primary button design
- Shared visual identity
- Reduced styling duplication
- Scalable design-system alignment
Implemented client-side filtering:
- Filters members by name
- Case-insensitive matching
- Ready for debounce integration
- Feature-based modular design
- Clean separation of UI and logic
- Reusable data table pattern
- Type-safe role management
- Future-ready for backend integration
The application integrates with a backend service using a structured API layer and centralized state management.
A reusable Axios client is configured to handle all API requests.
- Centralized base URL configuration
- Automatic JSON headers
- Request interceptor for authentication token injection
- Scalable structure for all API modules
apiClient.interceptors.request.use(async (config) => { const token = await getToken();
if (token) { config.headers.Authorization =
Bearer ${token}; }return config; });
Authentication is managed using Clerk.
- Clerk provides
getToken()viauseAuth() - Token is stored globally using a setter function
- Axios interceptor attaches token to every request
AuthProviderauthToken.ts
This ensures all API requests are automatically authenticated.
A dedicated API module handles all workspace-related backend communication.
export const workspaceApi = { getAll: async () => { const res = await apiClient.get("/api/workspace"); return res.data.data; } };
Redux Toolkit is used for global state management.
- Stores all user workspaces
- Maintains current workspace selection
- Persists workspace ID in localStorage
- Handles API loading and error states
fetchWorkspaces→ fetches workspace data from backendsetWorkspaceWithPersistence→ syncs Redux + localStoragedeleteWorkspaceWithCleanup→ removes workspace safely
The selected workspace is persisted using localStorage:
- Automatically restored on app reload
- Falls back to first available workspace if invalid
- Ensures consistent user experience across sessions
A dedicated task slice is implemented for managing task data.
- Add, update, delete tasks
- Store project-specific tasks
- Designed for future backend integration
All API responses and state are strictly typed using TypeScript.
export interface Workspace { id: string; name: string; slug: string; image_url?: string; }
This ensures:
- Safer API integration
- Better developer experience
- Fewer runtime errors
Clerk Auth → Token → Axios Interceptor ↓ API Layer (workspaceApi) ↓ Redux Thunks ↓ Redux Store (workspaceSlice) ↓ UI Components
This layered architecture ensures:
- Clean separation of concerns
- Scalability
- Maintainability
Implemented a multi-tenant workspace system using Clerk Organizations integrated with Redux state.
- Displays all available workspaces (organizations)
- Highlights the currently active workspace
- Allows seamless switching between workspaces
- Updates:
- Clerk active organization (auth context)
- Redux workspace state (UI context)
- Application route (
/workspace/:workspaceId)
Workspace selection follows a synchronized flow:
- Clerk
setActive()updates the organization context - Redux updates the current workspace state
- Application navigates to workspace-specific route
This ensures:
- Consistent auth context
- Correct API scoping
- UI state synchronization
- Uses Clerk's
openCreateOrganization()API - Opens a fully managed modal (centered, responsive)
- Handles:
- Organization creation
- Validation
- Closing interactions (ESC, outside click)
No custom modal implementation is required.
- Redux stores
currentWorkspaceId useEffectensures Clerk stays in sync with Redux- Prevents mismatch between UI and auth context
- Workspace ID is persisted in localStorage
- Automatically restored on reload
- Falls back to a valid workspace if needed
Clerk handles:
- Authentication
- Organization context
Redux handles:
- UI state
- Workspace selection
This separation ensures scalability and maintainability in a multi-tenant SaaS architecture.
Area Technology Language TypeScript Framework React 19 Router React Router v7 (App Router) State Management Redux Toolkit Styles TailwindCSS v4 UI Components shadcn/ui Icons Lucide React Bundler Vite Auth Clerk Database (Upcoming) Neon PostgreSQL