chore: init

This commit is contained in:
Julien Froidefond
2025-11-27 12:49:33 +01:00
commit 5234428cc3
11 changed files with 977 additions and 0 deletions

BIN
.cursor/.DS_Store vendored Normal file

Binary file not shown.

View File

@@ -0,0 +1,32 @@
---
globs: app/api/**/*.ts
---
# API Routes Rules
1. Routes MUST only use services for data access
2. Routes MUST handle input validation
3. Routes MUST return typed responses
4. Routes MUST use proper error handling
Example of correct API route:
```typescript
import { MyService } from "@/services/my-service";
export async function GET(request: Request) {
try {
const service = new MyService(pool);
const data = await service.getData();
return Response.json(data);
} catch (error) {
return Response.error();
}
}
```
❌ FORBIDDEN:
- Direct database queries
- Business logic implementation
- Untyped responses

View File

@@ -0,0 +1,167 @@
---
alwaysApply: true
description: Enforce business logic separation between frontend and backend
---
# Business Logic Separation Rules
## Core Principle: NO Business Logic in Frontend
All business logic, data processing, and domain rules MUST be implemented in the backend services layer. The frontend is purely for presentation and user interaction.
## ✅ ALLOWED in Frontend ([src/components/](mdc:src/components/), [src/hooks/](mdc:src/hooks/), [src/clients/](mdc:src/clients/))
### Components
- UI rendering and presentation logic
- Form validation (UI-level only, not business rules)
- User interaction handling (clicks, inputs, navigation)
- Visual state management (loading, errors, UI states)
- Data formatting for display purposes only
### Hooks
- React state management
- API call orchestration (using clients)
- UI-specific logic (modals, forms, animations)
- Data fetching and caching coordination
### Clients
- HTTP requests to API routes
- Request/response transformation (serialization only)
- Error handling and retry logic
- Authentication token management
## ❌ FORBIDDEN in Frontend
### Business Rules
```typescript
// ❌ BAD: Business logic in component
const TaskCard = ({ task }) => {
const canEdit = task.status === 'open' && task.assignee === currentUser.id;
const priority = task.dueDate < new Date() ? 'high' : 'normal';
// This is business logic!
}
// ✅ GOOD: Get computed values from backend
const TaskCard = ({ task }) => {
const { canEdit, priority } = task; // Computed by backend service
}
```
### Data Processing
```typescript
// ❌ BAD: Data transformation in frontend
const processJiraTasks = (tasks) => {
return tasks.map(task => ({
...task,
normalizedStatus: mapJiraStatus(task.status),
estimatedHours: calculateEstimate(task.storyPoints)
}));
}
// ✅ GOOD: Data already processed by backend service
const { processedTasks } = await tasksClient.getTasks();
```
### Domain Logic
```typescript
// ❌ BAD: Domain calculations in frontend
const calculateTeamVelocity = (sprints) => {
// Complex business calculation
}
// ✅ GOOD: Domain logic in service
// This belongs in services/team-analytics.ts
```
## ✅ REQUIRED in Backend ([src/services/](mdc:src/services/), [src/app/api/](mdc:src/app/api/))
### Services Layer
- All business rules and domain logic
- Data validation and processing
- Integration with external APIs (Jira, macOS Reminders)
- Complex calculations and algorithms
- Data aggregation and analytics
- Permission and authorization logic
### API Routes
- Input validation and sanitization
- Service orchestration
- Response formatting
- Error handling and logging
- Authentication and authorization
## Implementation Pattern
### ✅ Correct Flow
```
User Action → Component → Client → API Route → Service → Database
↑ ↓
Pure UI Logic Business Logic
```
### ❌ Incorrect Flow
```
User Action → Component with Business Logic → Database
```
## Examples
### Task Status Management
```typescript
// ❌ BAD: In component
const updateTaskStatus = (taskId, newStatus) => {
if (newStatus === 'done' && !task.hasAllSubtasks) {
throw new Error('Cannot complete task with pending subtasks');
}
// Business rule in frontend!
}
// ✅ GOOD: In services/task-processor.ts
export const updateTaskStatus = async (taskId: string, newStatus: TaskStatus) => {
const task = await getTask(taskId);
// Business rules in service
if (newStatus === 'done' && !await hasAllSubtasksCompleted(taskId)) {
throw new BusinessError('Cannot complete task with pending subtasks');
}
return await updateTask(taskId, { status: newStatus });
}
```
### Team Analytics
```typescript
// ❌ BAD: In component
const TeamDashboard = () => {
const calculateBurndown = (tasks) => {
// Complex business calculation in component
}
}
// ✅ GOOD: In services/team-analytics.ts
export const getTeamBurndown = async (teamId: string, sprintId: string) => {
// All calculation logic in service
const tasks = await getSprintTasks(sprintId);
return calculateBurndownMetrics(tasks);
}
```
## Enforcement
When reviewing code:
1. **Components**: Should only contain JSX, event handlers, and UI state
2. **Hooks**: Should only orchestrate API calls and manage React state
3. **Clients**: Should only make HTTP requests and handle responses
4. **Services**: Should contain ALL business logic and data processing
5. **API Routes**: Should validate input and call appropriate services
## Red Flags
Watch for these patterns that indicate business logic in frontend:
- Complex calculations in components/hooks
- Business rule validation in forms
- Data transformation beyond display formatting
- Domain-specific constants and rules
- Integration logic with external systems
Remember: **The frontend is a thin presentation layer. All intelligence lives in the backend.**

31
.cursor/rules/clients.mdc Normal file
View File

@@ -0,0 +1,31 @@
---
globs: clients/**/*.ts
---
# HTTP Clients Rules
1. All HTTP calls MUST be in clients/domains/
2. Each domain MUST have its own client
3. Clients MUST use the base HTTP client
4. Clients MUST type their responses
Example of correct client:
```typescript
import { HttpClient } from "@/clients/base/http-client";
import { MyData } from "@/lib/types";
export class MyClient {
constructor(private httpClient: HttpClient) {}
async getData(): Promise<MyData[]> {
return this.httpClient.get("/api/data");
}
}
```
❌ FORBIDDEN:
- Direct fetch calls
- Business logic in clients
- Untyped responses

View File

@@ -0,0 +1,28 @@
---
globs: src/components/**/*.tsx
---
# Components Rules
1. UI components MUST be in src/components/ui/
2. Feature components MUST be in their feature folder
3. Components MUST use clients for data fetching
4. Components MUST be properly typed
Example of correct component:
```typescript
import { useMyClient } from '@/hooks/use-my-client';
export const MyComponent = () => {
const { data } = useMyClient();
return <div>{data.map(item => <Item key={item.id} {...item} />)}</div>;
};
```
❌ FORBIDDEN:
- Direct service usage
- Direct database queries
- Direct fetch calls
- Untyped props

View File

@@ -0,0 +1,167 @@
---
alwaysApply: true
description: CSS Variables theme system best practices
---
# CSS Variables Theme System
## Core Principle: Pure CSS Variables for Theming
This project uses **CSS Variables exclusively** for theming. No Tailwind `dark:` classes or conditional CSS classes.
## ✅ Architecture Pattern
### CSS Structure
```css
:root {
/* Light theme (default values) */
--background: #f1f5f9;
--foreground: #0f172a;
--primary: #0891b2;
--success: #059669;
--destructive: #dc2626;
--accent: #d97706;
--purple: #8b5cf6;
--yellow: #eab308;
--green: #059669;
--blue: #2563eb;
--gray: #6b7280;
--gray-light: #e5e7eb;
}
.dark {
/* Dark theme (override values) */
--background: #1e293b;
--foreground: #f1f5f9;
--primary: #06b6d4;
--success: #10b981;
--destructive: #ef4444;
--accent: #f59e0b;
--purple: #8b5cf6;
--yellow: #eab308;
--green: #10b981;
--blue: #3b82f6;
--gray: #9ca3af;
--gray-light: #374151;
}
```
### Theme Application
- **Single source of truth**: [ThemeContext.tsx](mdc:src/contexts/ThemeContext.tsx) applies theme class to `document.documentElement`
- **No duplication**: Theme is applied only once, not in multiple places
- **SSR safe**: Initial theme from server-side preferences
## ✅ Component Usage Patterns
### Correct: Using CSS Variables
```tsx
// ✅ GOOD: CSS Variables in className
<div className="bg-[var(--card)] text-[var(--foreground)] border-[var(--border)]">
// ✅ GOOD: CSS Variables in style prop
<div style={{ color: 'var(--primary)', backgroundColor: 'var(--card)' }}>
// ✅ GOOD: CSS Variables with color-mix for transparency
<div style={{
backgroundColor: 'color-mix(in srgb, var(--primary) 10%, transparent)',
borderColor: 'color-mix(in srgb, var(--primary) 20%, var(--border))'
}}>
```
### ❌ Forbidden: Tailwind Dark Mode Classes
```tsx
// ❌ BAD: Tailwind dark: classes
<div className="bg-white dark:bg-gray-800 text-black dark:text-white">
// ❌ BAD: Conditional classes
<div className={theme === 'dark' ? 'bg-gray-800' : 'bg-white'}>
// ❌ BAD: Hardcoded colors
<div className="bg-red-500 text-blue-600">
```
## ✅ Color System
### Semantic Color Tokens
- `--background`: Main background color
- `--foreground`: Main text color
- `--card`: Card/panel background
- `--card-hover`: Card hover state
- `--card-column`: Column background (darker than cards)
- `--border`: Border color
- `--input`: Input field background
- `--primary`: Primary brand color
- `--primary-foreground`: Text on primary background
- `--muted`: Muted text color
- `--muted-foreground`: Secondary text color
- `--accent`: Accent color (orange/amber)
- `--destructive`: Error/danger color (red)
- `--success`: Success color (green)
- `--purple`: Purple accent
- `--yellow`: Yellow accent
- `--green`: Green accent
- `--blue`: Blue accent
- `--gray`: Gray color
- `--gray-light`: Light gray background
### Color Mixing Patterns
```css
/* Background with transparency */
background-color: color-mix(in srgb, var(--primary) 10%, transparent);
/* Border with transparency */
border-color: color-mix(in srgb, var(--primary) 20%, var(--border));
/* Text with opacity */
color: color-mix(in srgb, var(--destructive) 80%, transparent);
```
## ✅ Theme Context Usage
### ThemeProvider Setup
```tsx
// In layout.tsx
<ThemeProvider initialTheme={initialPreferences.viewPreferences.theme}>
{children}
</ThemeProvider>
```
### Component Usage
```tsx
import { useTheme } from '@/contexts/ThemeContext';
function MyComponent() {
const { theme, toggleTheme, setTheme } = useTheme();
return (
<button onClick={toggleTheme}>
Switch to {theme === 'dark' ? 'light' : 'dark'} theme
</button>
);
}
```
## ✅ Future Extensibility
This system is designed to support:
- **Custom color themes**: Easy to add new color variables
- **User preferences**: Colors can be dynamically changed
- **Theme presets**: Multiple predefined themes
- **Accessibility**: High contrast modes
## 🚨 Anti-patterns to Avoid
1. **Don't mix approaches**: Never use both CSS variables and Tailwind dark: classes
2. **Don't duplicate theme application**: Theme should be applied only in ThemeContext
3. **Don't hardcode colors**: Always use semantic color tokens
4. **Don't use conditional classes**: Use CSS variables instead
5. **Don't forget transparency**: Use `color-mix()` for semi-transparent colors
## 📁 Key Files
- [globals.css](mdc:src/app/globals.css) - CSS Variables definitions
- [ThemeContext.tsx](mdc:src/contexts/ThemeContext.tsx) - Theme management
- [UserPreferencesContext.tsx](mdc:src/contexts/UserPreferencesContext.tsx) - Preferences sync
- [layout.tsx](mdc:src/app/layout.tsx) - Theme provider setup
Remember: **CSS Variables are the single source of truth for theming. Keep it pure and consistent.**

View File

@@ -0,0 +1,30 @@
---
alwaysApply: true
---
# Project Structure Rules
1. Backend:
- [src/services/](mdc:src/services/) - ALL database access
- [src/app/api/](mdc:src/app/api/) - API routes using services
2. Frontend:
- [src/clients/](mdc:src/clients/) - HTTP clients
- [src/components/](mdc:src/components/) - React components (organized by domain)
- [src/hooks/](mdc:src/hooks/) - React hooks
3. Shared:
- [src/lib/](mdc:src/lib/) - Types and utilities
- [scripts/](mdc:scripts/) - Utility scripts
Key Files:
- [src/services/database.ts](mdc:src/services/database.ts) - Database pool
- [src/clients/base/http-client.ts](mdc:src/clients/base/http-client.ts) - Base HTTP client
- [src/lib/types.ts](mdc:src/lib/types.ts) - Shared types
❌ FORBIDDEN:
- Database access outside src/services/
- HTTP calls outside src/clients/
- Business logic in src/components/

View File

@@ -0,0 +1,113 @@
---
alwaysApply: true
description: Guide for when to use Server Actions vs API Routes in Next.js App Router
---
# Server Actions vs API Routes - Decision Guide
## ✅ USE SERVER ACTIONS for:
### Quick Actions & Mutations
- **TaskCard actions**: `updateTaskStatus()`, `updateTaskTitle()`, `deleteTask()`
- **Daily checkboxes**: `toggleCheckbox()`, `addCheckbox()`, `updateCheckbox()`
- **User preferences**: `updateTheme()`, `updateViewPreferences()`, `updateFilters()`
- **Simple CRUD**: `createTag()`, `updateTag()`, `deleteTag()`
### Characteristics of Server Action candidates:
- Simple, frequent mutations
- No complex business logic
- Used in interactive components (forms, buttons, toggles)
- Need immediate UI feedback with `useTransition`
- Benefit from automatic cache revalidation
## ❌ KEEP API ROUTES for:
### Complex Endpoints
- **Initial data fetching**: `GET /api/tasks` with complex filters
- **External integrations**: `POST /api/jira/sync` with complex logic
- **Analytics & reports**: Complex data aggregation
- **Public API**: Endpoints that might be called from mobile/external
### Characteristics that require API Routes:
- Complex business logic or data processing
- Multiple service orchestration
- Need for HTTP monitoring/logging
- External consumption (mobile apps, webhooks)
- Real-time features (WebSockets, SSE)
- File uploads or special content types
## 🔄 Implementation Pattern
### Server Actions Structure
```typescript
// actions/tasks.ts
'use server'
import { tasksService } from '@/services/tasks';
import { revalidatePath } from 'next/cache';
export async function updateTaskStatus(taskId: string, status: TaskStatus) {
try {
const task = await tasksService.updateTask(taskId, { status });
revalidatePath('/'); // Auto cache invalidation
return { success: true, data: task };
} catch (error) {
return { success: false, error: error.message };
}
}
```
### Component Usage with useTransition
```typescript
// components/TaskCard.tsx
'use client';
import { updateTaskStatus } from '@/actions/tasks';
import { useTransition } from 'react';
export function TaskCard({ task }) {
const [isPending, startTransition] = useTransition();
const handleStatusChange = (status) => {
startTransition(async () => {
const result = await updateTaskStatus(task.id, status);
if (!result.success) {
// Handle error
}
});
};
return (
<div className={isPending ? 'opacity-50' : ''}>
{/* UI with loading state */}
</div>
);
}
```
## 🏗️ Migration Strategy
When migrating from API Routes to Server Actions:
1. **Create server action** in `actions/` directory
2. **Update component** to use server action directly
3. **Remove API route** (PATCH, POST, DELETE for mutations)
4. **Simplify client** (remove mutation methods, keep GET only)
5. **Update hooks** to use server actions instead of HTTP calls
## 🎯 Benefits of Server Actions
- **🚀 Performance**: No HTTP serialization overhead
- **🔄 Cache intelligence**: Automatic revalidation with `revalidatePath()`
- **📦 Bundle reduction**: Less client-side HTTP code
- **⚡ UX**: Native loading states with `useTransition`
- **🎯 Simplicity**: Direct service calls, less boilerplate
## 🚨 Anti-patterns to Avoid
- Don't use server actions for complex data fetching
- Don't use server actions for endpoints that need HTTP monitoring
- Don't use server actions for public API endpoints
- Don't mix server actions with client-side state management for the same data
Remember: Server Actions are for **direct mutations**, API Routes are for **complex operations** and **public interfaces**.

View File

@@ -0,0 +1,42 @@
---
globs: src/services/*.ts
---
# Services Rules
1. Services MUST contain ALL PostgreSQL queries
2. Services are the ONLY layer allowed to communicate with the database
3. Each service MUST:
- Use the pool from [src/services/database.ts](mdc:src/services/database.ts)
- Implement proper transaction management
- Handle errors and logging
- Validate data before insertion
- Have a clear interface
Example of correct service implementation:
```typescript
export class MyService {
constructor(private pool: Pool) {}
async myMethod(): Promise<Result> {
const client = await this.pool.connect();
try {
await client.query("BEGIN");
// ... queries
await client.query("COMMIT");
} catch (error) {
await client.query("ROLLBACK");
throw error;
} finally {
client.release();
}
}
}
```
❌ FORBIDDEN:
- Direct database queries outside src/services
- Raw SQL in API routes
- Database logic in components

View File

@@ -0,0 +1,54 @@
---
alwaysApply: true
description: Automatic TODO tracking and task completion management
---
# TODO Task Tracking Rules
## Automatic Task Completion
Whenever you complete a task or implement a feature mentioned in [TODO.md](mdc:TODO.md), you MUST:
1. **Immediately update the TODO.md** by changing `- [ ]` to `- [x]` for the completed task
2. **Use the exact task description** from the TODO - don't modify the text
3. **Update related sub-tasks** if completing a parent task affects them
4. **Add completion timestamp** in a comment if the task was significant
## Task Completion Examples
### ✅ Correct completion marking:
```markdown
- [x] Initialiser Next.js avec TypeScript
- [x] Configurer ESLint, Prettier
- [x] Setup structure de dossiers selon les règles du workspace
```
### ✅ With timestamp for major milestones:
```markdown
- [x] Créer `services/database.ts` - Pool de connexion DB <!-- Completed 2025-01-15 -->
```
## When to Update TODO.md
Update the TODO immediately after:
- Creating/modifying files mentioned in tasks
- Implementing features described in tasks
- Completing configuration steps
- Finishing any work item listed in the TODO
## Task Dependencies
When completing tasks, consider:
- **Parent tasks**: Mark parent complete only when ALL sub-tasks are done
- **Blocking tasks**: Some tasks may unblock others - mention this in updates
- **Phase completion**: Note when entire phases are completed
## Progress Tracking
Always maintain visibility of:
- Current phase progress
- Next logical task to tackle
- Any blockers or issues encountered
- Completed vs remaining work ratio
This ensures the TODO.md remains an accurate reflection of project progress and helps maintain momentum.

313
devbook.md Normal file
View File

@@ -0,0 +1,313 @@
# SWOT Manager - Development Book
Application de gestion d'ateliers SWOT pour entretiens managériaux.
## Stack Technique
- **Framework**: Next.js 15 (App Router)
- **Styling**: Tailwind CSS + CSS Variables theming
- **Auth**: NextAuth.js v5
- **Database**: PostgreSQL + Prisma
- **Drag & Drop**: @hello-pangea/dnd (fork maintenu de react-beautiful-dnd)
- **State**: React Context + Server Actions
---
## Phase 1 : Setup Initial
- [ ] Initialiser Next.js 15 avec TypeScript
- [ ] Configurer Tailwind CSS avec le système de CSS Variables
- [ ] Setup ESLint + Prettier
- [ ] Créer la structure de dossiers
```
src/
├── app/
│ ├── api/
│ ├── (auth)/
│ │ ├── login/
│ │ └── register/
│ ├── sessions/
│ │ ├── [id]/
│ │ └── new/
│ └── layout.tsx
├── components/
│ ├── ui/ # Composants réutilisables
│ ├── swot/ # Composants SWOT
│ └── layout/ # Header, Sidebar, etc.
├── services/ # Logique métier + DB
├── lib/ # Types, utils
├── contexts/ # React Contexts
└── actions/ # Server Actions
```
- [ ] Configurer les CSS Variables pour le theming (light/dark)
---
## Phase 2 : Base de Données
- [ ] Installer et configurer Prisma
- [ ] Créer le schéma de base de données :
```prisma
model User {
id String @id @default(cuid())
email String @unique
name String?
password String
sessions Session[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model Session {
id String @id @default(cuid())
title String
collaborator String # Nom du collaborateur évalué
date DateTime @default(now())
userId String
user User @relation(fields: [userId], references: [id])
items SwotItem[]
actions Action[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
enum SwotCategory {
STRENGTH
WEAKNESS
OPPORTUNITY
THREAT
}
model SwotItem {
id String @id @default(cuid())
content String
category SwotCategory
order Int @default(0)
sessionId String
session Session @relation(fields: [sessionId], references: [id], onDelete: Cascade)
actionLinks ActionLink[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model Action {
id String @id @default(cuid())
title String
description String?
priority Int @default(0) # 0=low, 1=medium, 2=high
status String @default("todo") # todo, in_progress, done
dueDate DateTime?
sessionId String
session Session @relation(fields: [sessionId], references: [id], onDelete: Cascade)
links ActionLink[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model ActionLink {
id String @id @default(cuid())
actionId String
action Action @relation(fields: [actionId], references: [id], onDelete: Cascade)
swotItemId String
swotItem SwotItem @relation(fields: [swotItemId], references: [id], onDelete: Cascade)
@@unique([actionId, swotItemId])
}
```
- [ ] Générer le client Prisma
- [ ] Créer les migrations initiales
- [ ] Créer le service database.ts (pool de connexion)
---
## Phase 3 : Authentification
- [ ] Installer NextAuth.js v5
- [ ] Configurer le provider Credentials (email/password)
- [ ] Créer les pages :
- [ ] `/login` - Page de connexion
- [ ] `/register` - Page d'inscription
- [ ] Créer le service auth.ts
- [ ] Protéger les routes avec middleware
- [ ] Créer le composant AuthProvider
---
## Phase 4 : Layout & Navigation
- [ ] Créer le layout principal avec :
- [ ] Header avec navigation et user menu
- [ ] Theme toggle (dark/light)
- [ ] Créer les composants UI de base :
- [ ] Button
- [ ] Card
- [ ] Input
- [ ] Modal
- [ ] Badge
- [ ] Créer la page d'accueil `/` - Dashboard avec liste des sessions
---
## Phase 5 : Gestion des Sessions SWOT
- [ ] Créer le service `sessions.ts`
- [ ] Créer les Server Actions pour les sessions :
- [ ] `createSession`
- [ ] `updateSession`
- [ ] `deleteSession`
- [ ] `getSession`
- [ ] `getUserSessions`
- [ ] Créer les pages :
- [ ] `/sessions` - Liste des sessions
- [ ] `/sessions/new` - Création de session
- [ ] `/sessions/[id]` - Vue détaillée de la session SWOT
- [ ] Créer les composants :
- [ ] `SessionCard` - Carte de session dans la liste
- [ ] `SessionForm` - Formulaire création/édition
---
## Phase 6 : Matrice SWOT Interactive
- [ ] Installer @hello-pangea/dnd
- [ ] Créer les composants SWOT :
- [ ] `SwotBoard` - Container principal de la matrice
- [ ] `SwotQuadrant` - Un quadrant (S, W, O, T)
- [ ] `SwotCard` - Une carte dans un quadrant
- [ ] `SwotCardForm` - Formulaire ajout/édition de carte
- [ ] Implémenter le drag & drop :
- [ ] Réorganisation dans un même quadrant
- [ ] Déplacement entre quadrants
- [ ] Créer les Server Actions pour les items :
- [ ] `createSwotItem`
- [ ] `updateSwotItem`
- [ ] `deleteSwotItem`
- [ ] `reorderSwotItems`
- [ ] Édition inline des cartes
---
## Phase 7 : Système de Liaison & Actions
- [ ] Créer le mode "liaison" :
- [ ] Bouton pour activer le mode liaison
- [ ] Sélection multiple d'items SWOT
- [ ] Visualisation des items sélectionnés (highlight)
- [ ] Créer les composants Actions :
- [ ] `ActionPanel` - Panneau des actions croisées
- [ ] `ActionCard` - Une action avec ses liens
- [ ] `ActionForm` - Formulaire création/édition d'action
- [ ] `LinkedItemsBadges` - Badges des items liés
- [ ] Créer les Server Actions pour les actions :
- [ ] `createAction`
- [ ] `updateAction`
- [ ] `deleteAction`
- [ ] `linkItemToAction`
- [ ] `unlinkItemFromAction`
- [ ] Visualisation des liens sur la matrice (highlight on hover)
---
## Phase 8 : Roadmap & Priorisation
- [ ] Créer la vue Roadmap :
- [ ] `RoadmapView` - Vue timeline des actions
- [ ] Filtres par statut, priorité
- [ ] Tri par date d'échéance
- [ ] Drag & drop pour réordonner les priorités
- [ ] Mise à jour du statut des actions (todo → in_progress → done)
- [ ] Vue Kanban alternative des actions
---
## Phase 9 : Export & Partage
- [ ] Export PDF de la matrice SWOT
- [ ] Export PDF de la roadmap
- [ ] Génération de lien de partage en lecture seule
- [ ] Copie au format texte pour coller dans un email
---
## Phase 10 : Polish & UX
- [ ] Animations et transitions fluides
- [ ] États de chargement (skeletons)
- [ ] Messages de confirmation et toasts
- [ ] Raccourcis clavier :
- [ ] `N` - Nouvelle carte
- [ ] `Escape` - Annuler
- [ ] `Enter` - Valider
- [ ] Responsive design (tablette minimum)
- [ ] Mode présentation (masquer les contrôles)
---
## Phase 11 : Bonus (Optionnel)
- [ ] Templates de sessions SWOT prédéfinis
- [ ] Collaboration temps réel (plusieurs personnes sur la même session)
- [ ] Historique des modifications
- [ ] Import depuis Miro/Trello
- [ ] Intégration calendrier pour les échéances
- [ ] Notifications par email pour les deadlines
---
## Notes Techniques
### Structure des Server Actions
```typescript
// actions/swot-items.ts
'use server'
import { swotService } from '@/services/swot';
import { revalidatePath } from 'next/cache';
export async function createSwotItem(sessionId: string, data: CreateSwotItemInput) {
const item = await swotService.createItem(sessionId, data);
revalidatePath(`/sessions/${sessionId}`);
return { success: true, data: item };
}
```
### Pattern de Liaison
```typescript
// Mode liaison : state dans le composant parent
const [linkMode, setLinkMode] = useState(false);
const [selectedItems, setSelectedItems] = useState<string[]>([]);
// Quand 2+ items sélectionnés, proposer création d'action
if (selectedItems.length >= 2) {
// Ouvrir modal de création d'action avec items pré-sélectionnés
}
```
### Visualisation des Liens
- Au hover d'une action : highlight des items liés
- Au hover d'un item : highlight des actions liées
- Couleurs par type de croisement (SO, ST, WO, WT)
---
## Commandes Utiles
```bash
# Lancer le dev server
npm run dev
# Prisma
npx prisma migrate dev --name <name>
npx prisma generate
npx prisma studio
# Build
npm run build
# Lint
npm run lint
```