diff --git a/.prettierrc.json b/.prettierrc.json
new file mode 100644
index 0000000..8d35929
--- /dev/null
+++ b/.prettierrc.json
@@ -0,0 +1,9 @@
+{
+ "semi": true,
+ "trailingComma": "es5",
+ "singleQuote": true,
+ "printWidth": 100,
+ "tabWidth": 2,
+ "useTabs": false,
+ "plugins": ["prettier-plugin-tailwindcss"]
+}
diff --git a/README.md b/README.md
index e215bc4..07bb6be 100644
--- a/README.md
+++ b/README.md
@@ -1,36 +1,157 @@
-This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app).
+# ColaFlow Web
+
+AI-Powered Project Management System - Frontend
+
+## Tech Stack
+
+- **Framework**: Next.js 15 (App Router)
+- **Language**: TypeScript 5.x
+- **UI Components**: shadcn/ui + Radix UI
+- **Styling**: Tailwind CSS 4
+- **State Management**:
+ - TanStack Query v5 (server state)
+ - Zustand (client state)
+- **Form Handling**: React Hook Form + Zod
+- **Icons**: Lucide React
+
+## Project Structure
+
+```
+colaflow-web/
+├── app/ # Next.js App Router
+│ ├── (auth)/ # Authentication routes
+│ ├── (dashboard)/ # Main application routes
+│ │ ├── dashboard/ # Dashboard page
+│ │ ├── projects/ # Projects management
+│ │ └── kanban/ # Kanban board
+│ ├── layout.tsx # Root layout
+│ └── page.tsx # Home page (redirects to dashboard)
+├── components/
+│ ├── ui/ # shadcn/ui components
+│ ├── features/ # Feature-specific components
+│ │ ├── projects/ # Project components
+│ │ └── kanban/ # Kanban components
+│ └── layout/ # Layout components (Header, Sidebar)
+├── lib/
+│ ├── api/ # API client and endpoints
+│ ├── hooks/ # Custom React hooks
+│ ├── providers/ # Context providers
+│ └── utils.ts # Utility functions
+├── stores/ # Zustand stores
+├── types/ # TypeScript type definitions
+└── public/ # Static assets
+```
## Getting Started
-First, run the development server:
+### Prerequisites
+
+- Node.js 20 LTS or higher
+- npm or yarn
+
+### Installation
+
+1. Install dependencies:
+```bash
+npm install
+```
+
+2. Create `.env.local` file:
+```env
+NEXT_PUBLIC_API_URL=http://localhost:5000/api/v1
+```
+
+### Development
+
+Start the development server:
```bash
npm run dev
-# or
-yarn dev
-# or
-pnpm dev
-# or
-bun dev
```
-Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
+Open [http://localhost:3000](http://localhost:3000) in your browser.
-You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
+### Build
-This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel.
+Build the production application:
-## Learn More
+```bash
+npm run build
+```
-To learn more about Next.js, take a look at the following resources:
+### Linting & Formatting
-- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
-- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
+```bash
+# Run ESLint
+npm run lint
-You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!
+# Format code with Prettier
+npm run format
+```
-## Deploy on Vercel
+## Features Implemented (Sprint 1)
-The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
+### Core Pages
+- Dashboard with project overview
+- Projects list page with search and filtering
+- Project detail page
+- Kanban board (static, drag-and-drop in Sprint 2)
-Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.
+### Components
+- Responsive layout with sidebar navigation
+- Project creation dialog with form validation
+- Kanban board with column and task cards
+- shadcn/ui integration (Button, Card, Dialog, Form, Input, Table)
+
+### State Management
+- TanStack Query for server state
+- Zustand for UI state (sidebar, theme, modals, notifications)
+- Custom hooks for projects and kanban
+
+### API Integration
+- Type-safe API client with error handling
+- Projects API endpoints
+- Kanban board API integration
+
+## TypeScript Types
+
+All API responses and data models are fully typed:
+
+- `types/project.ts` - Project, Epic, Story, Task types
+- `types/kanban.ts` - Kanban board types
+- `types/user.ts` - User and authentication types
+
+## API Endpoints
+
+The frontend expects the following API endpoints:
+
+- `GET /api/v1/projects` - List all projects
+- `POST /api/v1/projects` - Create project
+- `GET /api/v1/projects/{id}` - Get project details
+- `PUT /api/v1/projects/{id}` - Update project
+- `DELETE /api/v1/projects/{id}` - Delete project
+- `GET /api/v1/projects/{id}/kanban` - Get kanban board
+
+## Environment Variables
+
+| Variable | Description | Default |
+|----------|-------------|---------|
+| `NEXT_PUBLIC_API_URL` | Backend API URL | `http://localhost:5000/api/v1` |
+
+## Next Steps (Sprint 2)
+
+- Implement drag-and-drop for Kanban board
+- Add task creation and editing
+- Implement authentication (login/register)
+- Add user profile management
+- Implement real-time updates with SignalR
+- Add workflow customization
+- Implement audit logs viewer
+
+## Architecture Reference
+
+For complete architecture details, see: `docs/M1-Architecture-Design.md`
+
+## License
+
+Proprietary - ColaFlow Project
diff --git a/app/(dashboard)/dashboard/page.tsx b/app/(dashboard)/dashboard/page.tsx
new file mode 100644
index 0000000..c523578
--- /dev/null
+++ b/app/(dashboard)/dashboard/page.tsx
@@ -0,0 +1,108 @@
+'use client';
+
+import Link from 'next/link';
+import { FolderKanban, Plus } from 'lucide-react';
+import { Button } from '@/components/ui/button';
+import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
+import { useProjects } from '@/lib/hooks/use-projects';
+
+export default function DashboardPage() {
+ const { data: projects } = useProjects();
+
+ return (
+
+
+
Dashboard
+
+ Welcome to ColaFlow - Your AI-powered project management system
+
+
+
+
+
+
+ Total Projects
+
+
+
+ {projects?.length || 0}
+
+ Active projects in your workspace
+
+
+
+
+
+
+ Active Projects
+
+
+
+
+ {projects?.filter((p) => p.status === 'Active').length || 0}
+
+
+ Currently in progress
+
+
+
+
+
+
+ Quick Actions
+
+
+
+
+
+
+
+
+
+
+
+
+ Recent Projects
+
+ Your most recently updated projects
+
+
+
+ {projects && projects.length > 0 ? (
+
+ {projects.slice(0, 5).map((project) => (
+
+
+
+
{project.name}
+
{project.key}
+
+
+ {project.status}
+
+
+
+ ))}
+
+ ) : (
+
+ No projects yet. Create your first project to get started.
+
+ )}
+
+
+
+ );
+}
diff --git a/app/(dashboard)/kanban/[projectId]/page.tsx b/app/(dashboard)/kanban/[projectId]/page.tsx
new file mode 100644
index 0000000..8682dd9
--- /dev/null
+++ b/app/(dashboard)/kanban/[projectId]/page.tsx
@@ -0,0 +1,57 @@
+'use client';
+
+import { use } from 'react';
+import Link from 'next/link';
+import { ArrowLeft, Loader2 } from 'lucide-react';
+import { Button } from '@/components/ui/button';
+import { KanbanBoard } from '@/components/features/kanban/KanbanBoard';
+import { useKanbanBoard } from '@/lib/hooks/use-kanban';
+
+interface KanbanPageProps {
+ params: Promise<{ projectId: string }>;
+}
+
+export default function KanbanPage({ params }: KanbanPageProps) {
+ const { projectId } = use(params);
+ const { data: board, isLoading, error } = useKanbanBoard(projectId);
+
+ if (isLoading) {
+ return (
+
+
+
+ );
+ }
+
+ if (error || !board) {
+ return (
+
+
+
+
+
+
+ Failed to load kanban board. Please try again later.
+
+
+
+ );
+ }
+
+ return (
+
+
+
+
+
+
Kanban Board
+
+
+
+
+ );
+}
diff --git a/app/(dashboard)/layout.tsx b/app/(dashboard)/layout.tsx
new file mode 100644
index 0000000..84dc138
--- /dev/null
+++ b/app/(dashboard)/layout.tsx
@@ -0,0 +1,29 @@
+'use client';
+
+import { Header } from '@/components/layout/Header';
+import { Sidebar } from '@/components/layout/Sidebar';
+import { useUIStore } from '@/stores/ui-store';
+
+export default function DashboardLayout({
+ children,
+}: {
+ children: React.ReactNode;
+}) {
+ const sidebarOpen = useUIStore((state) => state.sidebarOpen);
+
+ return (
+
+ );
+}
diff --git a/app/(dashboard)/projects/[id]/page.tsx b/app/(dashboard)/projects/[id]/page.tsx
new file mode 100644
index 0000000..beb7ab9
--- /dev/null
+++ b/app/(dashboard)/projects/[id]/page.tsx
@@ -0,0 +1,91 @@
+'use client';
+
+import { use } from 'react';
+import Link from 'next/link';
+import { ArrowLeft, Loader2, KanbanSquare } from 'lucide-react';
+import { Button } from '@/components/ui/button';
+import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
+import { useProject } from '@/lib/hooks/use-projects';
+
+interface ProjectDetailPageProps {
+ params: Promise<{ id: string }>;
+}
+
+export default function ProjectDetailPage({ params }: ProjectDetailPageProps) {
+ const { id } = use(params);
+ const { data: project, isLoading, error } = useProject(id);
+
+ if (isLoading) {
+ return (
+
+
+
+ );
+ }
+
+ if (error || !project) {
+ return (
+
+
+ Project not found or failed to load.
+
+
+ );
+ }
+
+ return (
+
+
+
+
+
+
+
+
{project.name}
+
+ {project.status}
+
+
+
Key: {project.key}
+
+
+
+
+
+
+
+
+ Project Details
+ Information about this project
+
+
+
+
Description
+
{project.description || 'No description provided'}
+
+
+
Created
+
{new Date(project.createdAt).toLocaleDateString()}
+
+ {project.updatedAt && (
+
+
Last Updated
+
{new Date(project.updatedAt).toLocaleDateString()}
+
+ )}
+
+
+
+ );
+}
diff --git a/app/(dashboard)/projects/page.tsx b/app/(dashboard)/projects/page.tsx
new file mode 100644
index 0000000..2c1d4cd
--- /dev/null
+++ b/app/(dashboard)/projects/page.tsx
@@ -0,0 +1,95 @@
+'use client';
+
+import { useState } from 'react';
+import Link from 'next/link';
+import { Plus, Loader2 } from 'lucide-react';
+import { Button } from '@/components/ui/button';
+import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
+import { useProjects } from '@/lib/hooks/use-projects';
+import { CreateProjectDialog } from '@/components/features/projects/CreateProjectDialog';
+
+export default function ProjectsPage() {
+ const [isCreateDialogOpen, setIsCreateDialogOpen] = useState(false);
+ const { data: projects, isLoading, error } = useProjects();
+
+ if (isLoading) {
+ return (
+
+
+
+ );
+ }
+
+ if (error) {
+ return (
+
+
+ Failed to load projects. Please try again later.
+
+
+ );
+ }
+
+ return (
+
+
+
+
Projects
+
+ Manage your projects and track progress
+
+
+
+
+
+
+ {projects?.map((project) => (
+
+
+
+
+
+ {project.name}
+ {project.key}
+
+
+ {project.status}
+
+
+
+
+
+ {project.description}
+
+
+
+
+ ))}
+
+ {!projects || projects.length === 0 ? (
+
+
+
+ No projects yet. Create your first project to get started.
+
+
+
+ ) : null}
+
+
+
+
+ );
+}
diff --git a/app/globals.css b/app/globals.css
index a2dc41e..dc98be7 100644
--- a/app/globals.css
+++ b/app/globals.css
@@ -1,26 +1,122 @@
@import "tailwindcss";
+@import "tw-animate-css";
-:root {
- --background: #ffffff;
- --foreground: #171717;
-}
+@custom-variant dark (&:is(.dark *));
@theme inline {
--color-background: var(--background);
--color-foreground: var(--foreground);
--font-sans: var(--font-geist-sans);
--font-mono: var(--font-geist-mono);
+ --color-sidebar-ring: var(--sidebar-ring);
+ --color-sidebar-border: var(--sidebar-border);
+ --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
+ --color-sidebar-accent: var(--sidebar-accent);
+ --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
+ --color-sidebar-primary: var(--sidebar-primary);
+ --color-sidebar-foreground: var(--sidebar-foreground);
+ --color-sidebar: var(--sidebar);
+ --color-chart-5: var(--chart-5);
+ --color-chart-4: var(--chart-4);
+ --color-chart-3: var(--chart-3);
+ --color-chart-2: var(--chart-2);
+ --color-chart-1: var(--chart-1);
+ --color-ring: var(--ring);
+ --color-input: var(--input);
+ --color-border: var(--border);
+ --color-destructive: var(--destructive);
+ --color-accent-foreground: var(--accent-foreground);
+ --color-accent: var(--accent);
+ --color-muted-foreground: var(--muted-foreground);
+ --color-muted: var(--muted);
+ --color-secondary-foreground: var(--secondary-foreground);
+ --color-secondary: var(--secondary);
+ --color-primary-foreground: var(--primary-foreground);
+ --color-primary: var(--primary);
+ --color-popover-foreground: var(--popover-foreground);
+ --color-popover: var(--popover);
+ --color-card-foreground: var(--card-foreground);
+ --color-card: var(--card);
+ --radius-sm: calc(var(--radius) - 4px);
+ --radius-md: calc(var(--radius) - 2px);
+ --radius-lg: var(--radius);
+ --radius-xl: calc(var(--radius) + 4px);
}
-@media (prefers-color-scheme: dark) {
- :root {
- --background: #0a0a0a;
- --foreground: #ededed;
+:root {
+ --radius: 0.625rem;
+ --background: oklch(1 0 0);
+ --foreground: oklch(0.145 0 0);
+ --card: oklch(1 0 0);
+ --card-foreground: oklch(0.145 0 0);
+ --popover: oklch(1 0 0);
+ --popover-foreground: oklch(0.145 0 0);
+ --primary: oklch(0.205 0 0);
+ --primary-foreground: oklch(0.985 0 0);
+ --secondary: oklch(0.97 0 0);
+ --secondary-foreground: oklch(0.205 0 0);
+ --muted: oklch(0.97 0 0);
+ --muted-foreground: oklch(0.556 0 0);
+ --accent: oklch(0.97 0 0);
+ --accent-foreground: oklch(0.205 0 0);
+ --destructive: oklch(0.577 0.245 27.325);
+ --border: oklch(0.922 0 0);
+ --input: oklch(0.922 0 0);
+ --ring: oklch(0.708 0 0);
+ --chart-1: oklch(0.646 0.222 41.116);
+ --chart-2: oklch(0.6 0.118 184.704);
+ --chart-3: oklch(0.398 0.07 227.392);
+ --chart-4: oklch(0.828 0.189 84.429);
+ --chart-5: oklch(0.769 0.188 70.08);
+ --sidebar: oklch(0.985 0 0);
+ --sidebar-foreground: oklch(0.145 0 0);
+ --sidebar-primary: oklch(0.205 0 0);
+ --sidebar-primary-foreground: oklch(0.985 0 0);
+ --sidebar-accent: oklch(0.97 0 0);
+ --sidebar-accent-foreground: oklch(0.205 0 0);
+ --sidebar-border: oklch(0.922 0 0);
+ --sidebar-ring: oklch(0.708 0 0);
+}
+
+.dark {
+ --background: oklch(0.145 0 0);
+ --foreground: oklch(0.985 0 0);
+ --card: oklch(0.205 0 0);
+ --card-foreground: oklch(0.985 0 0);
+ --popover: oklch(0.205 0 0);
+ --popover-foreground: oklch(0.985 0 0);
+ --primary: oklch(0.922 0 0);
+ --primary-foreground: oklch(0.205 0 0);
+ --secondary: oklch(0.269 0 0);
+ --secondary-foreground: oklch(0.985 0 0);
+ --muted: oklch(0.269 0 0);
+ --muted-foreground: oklch(0.708 0 0);
+ --accent: oklch(0.269 0 0);
+ --accent-foreground: oklch(0.985 0 0);
+ --destructive: oklch(0.704 0.191 22.216);
+ --border: oklch(1 0 0 / 10%);
+ --input: oklch(1 0 0 / 15%);
+ --ring: oklch(0.556 0 0);
+ --chart-1: oklch(0.488 0.243 264.376);
+ --chart-2: oklch(0.696 0.17 162.48);
+ --chart-3: oklch(0.769 0.188 70.08);
+ --chart-4: oklch(0.627 0.265 303.9);
+ --chart-5: oklch(0.645 0.246 16.439);
+ --sidebar: oklch(0.205 0 0);
+ --sidebar-foreground: oklch(0.985 0 0);
+ --sidebar-primary: oklch(0.488 0.243 264.376);
+ --sidebar-primary-foreground: oklch(0.985 0 0);
+ --sidebar-accent: oklch(0.269 0 0);
+ --sidebar-accent-foreground: oklch(0.985 0 0);
+ --sidebar-border: oklch(1 0 0 / 10%);
+ --sidebar-ring: oklch(0.556 0 0);
+}
+
+@layer base {
+ * {
+ @apply border-border outline-ring/50;
+ }
+ body {
+ @apply bg-background text-foreground;
}
}
-
-body {
- background: var(--background);
- color: var(--foreground);
- font-family: Arial, Helvetica, sans-serif;
-}
diff --git a/app/layout.tsx b/app/layout.tsx
index f7fa87e..fa7df7d 100644
--- a/app/layout.tsx
+++ b/app/layout.tsx
@@ -1,6 +1,7 @@
import type { Metadata } from "next";
import { Geist, Geist_Mono } from "next/font/google";
import "./globals.css";
+import { QueryProvider } from "@/lib/providers/query-provider";
const geistSans = Geist({
variable: "--font-geist-sans",
@@ -13,8 +14,8 @@ const geistMono = Geist_Mono({
});
export const metadata: Metadata = {
- title: "Create Next App",
- description: "Generated by create next app",
+ title: "ColaFlow - AI-Powered Project Management",
+ description: "Modern project management system with AI and MCP protocol",
};
export default function RootLayout({
@@ -27,7 +28,7 @@ export default function RootLayout({
- {children}
+ {children}