initial commit
This commit is contained in:
2572
docs/architecture.md
Normal file
2572
docs/architecture.md
Normal file
File diff suppressed because it is too large
Load Diff
35
docs/architecture/1-introduction.md
Normal file
35
docs/architecture/1-introduction.md
Normal file
@@ -0,0 +1,35 @@
|
||||
# 1. Introduction
|
||||
|
||||
## Project Overview
|
||||
|
||||
**Dofus Manager** est une application web personnelle conçue pour gérer efficacement plus de 60 personnages du MMORPG Dofus, répartis sur plusieurs comptes. L'application centralise le suivi des progressions (quêtes, donjons, succès) et permet une gestion optimisée via des équipes.
|
||||
|
||||
## Goals
|
||||
|
||||
- **Centralisation** : Un point unique pour gérer tous les personnages et comptes
|
||||
- **Suivi des progressions** : Tracker l'avancement des quêtes, donjons et succès
|
||||
- **Gestion par équipes** : Organiser les personnages en équipes pour faciliter le suivi
|
||||
- **Efficacité** : Interface rapide avec opérations bulk et filtres avancés
|
||||
|
||||
## Scope
|
||||
|
||||
| In Scope | Out of Scope |
|
||||
|----------|--------------|
|
||||
| Gestion des personnages (CRUD) | Intégration directe avec le jeu |
|
||||
| Gestion des comptes | Multi-utilisateurs |
|
||||
| Suivi des progressions | Application mobile native |
|
||||
| Gestion des équipes | Synchronisation automatique |
|
||||
| Import données DofusDB | Fonctionnalités sociales |
|
||||
| Interface responsive | Mode hors-ligne |
|
||||
|
||||
## Non-Functional Requirements
|
||||
|
||||
| Requirement | Target |
|
||||
|-------------|--------|
|
||||
| Performance | < 200ms pour les opérations courantes |
|
||||
| Disponibilité | 99% uptime (usage personnel) |
|
||||
| Sécurité | Authentification requise, données protégées |
|
||||
| Scalabilité | Support de 100+ personnages |
|
||||
| Maintenabilité | Code typé, tests automatisés |
|
||||
|
||||
---
|
||||
187
docs/architecture/10-frontend-architecture.md
Normal file
187
docs/architecture/10-frontend-architecture.md
Normal file
@@ -0,0 +1,187 @@
|
||||
# 10. Frontend Architecture
|
||||
|
||||
## State Management Strategy
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ STATE MANAGEMENT │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────────────────────┐ │
|
||||
│ │ TanStack Query │ │
|
||||
│ │ (Server State / Cache) │ │
|
||||
│ │ │ │
|
||||
│ │ • Characters list │ │
|
||||
│ │ • Accounts data │ │
|
||||
│ │ • Teams & members │ │
|
||||
│ │ • Progressions │ │
|
||||
│ │ • DofusDB reference data │ │
|
||||
│ └─────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────────────────────┐ │
|
||||
│ │ Zustand │ │
|
||||
│ │ (Client/UI State) │ │
|
||||
│ │ │ │
|
||||
│ │ • Selected items (multi-select) │ │
|
||||
│ │ • UI preferences (sidebar collapsed, etc.) │ │
|
||||
│ │ • Filter states │ │
|
||||
│ │ • Modal open/close states │ │
|
||||
│ │ • Theme preference │ │
|
||||
│ └─────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────────────────────┐ │
|
||||
│ │ React State │ │
|
||||
│ │ (Component-local State) │ │
|
||||
│ │ │ │
|
||||
│ │ • Form inputs │ │
|
||||
│ │ • Hover/focus states │ │
|
||||
│ │ • Animation states │ │
|
||||
│ │ • Temporary UI states │ │
|
||||
│ └─────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## TanStack Query Setup
|
||||
|
||||
```typescript
|
||||
// src/lib/client/query-client.ts
|
||||
import { QueryClient } from '@tanstack/react-query';
|
||||
|
||||
export const queryClient = new QueryClient({
|
||||
defaultOptions: {
|
||||
queries: {
|
||||
staleTime: 1000 * 60 * 5, // 5 minutes
|
||||
gcTime: 1000 * 60 * 30, // 30 minutes
|
||||
retry: 1,
|
||||
refetchOnWindowFocus: false,
|
||||
},
|
||||
mutations: {
|
||||
onError: (error) => {
|
||||
console.error('Mutation error:', error);
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// Query keys factory
|
||||
export const queryKeys = {
|
||||
characters: {
|
||||
all: ['characters'] as const,
|
||||
list: (filters: CharacterFilters) => [...queryKeys.characters.all, 'list', filters] as const,
|
||||
detail: (id: string) => [...queryKeys.characters.all, 'detail', id] as const,
|
||||
},
|
||||
accounts: {
|
||||
all: ['accounts'] as const,
|
||||
list: () => [...queryKeys.accounts.all, 'list'] as const,
|
||||
detail: (id: string) => [...queryKeys.accounts.all, 'detail', id] as const,
|
||||
},
|
||||
teams: {
|
||||
all: ['teams'] as const,
|
||||
list: () => [...queryKeys.teams.all, 'list'] as const,
|
||||
detail: (id: string) => [...queryKeys.teams.all, 'detail', id] as const,
|
||||
},
|
||||
progressions: {
|
||||
all: ['progressions'] as const,
|
||||
list: (type?: ProgressionType) => [...queryKeys.progressions.all, 'list', type] as const,
|
||||
byCharacter: (characterId: string) => [...queryKeys.progressions.all, 'character', characterId] as const,
|
||||
},
|
||||
} as const;
|
||||
```
|
||||
|
||||
## Zustand Store
|
||||
|
||||
```typescript
|
||||
// src/lib/client/stores/ui-store.ts
|
||||
import { create } from 'zustand';
|
||||
import { persist } from 'zustand/middleware';
|
||||
|
||||
interface UIState {
|
||||
// Sidebar
|
||||
sidebarCollapsed: boolean;
|
||||
toggleSidebar: () => void;
|
||||
|
||||
// Theme
|
||||
theme: 'light' | 'dark';
|
||||
setTheme: (theme: 'light' | 'dark') => void;
|
||||
|
||||
// Selection (for bulk actions)
|
||||
selectedCharacterIds: string[];
|
||||
selectCharacter: (id: string) => void;
|
||||
deselectCharacter: (id: string) => void;
|
||||
selectAllCharacters: (ids: string[]) => void;
|
||||
clearSelection: () => void;
|
||||
}
|
||||
|
||||
export const useUIStore = create<UIState>()(
|
||||
persist(
|
||||
(set) => ({
|
||||
// Sidebar
|
||||
sidebarCollapsed: false,
|
||||
toggleSidebar: () => set((state) => ({ sidebarCollapsed: !state.sidebarCollapsed })),
|
||||
|
||||
// Theme
|
||||
theme: 'dark',
|
||||
setTheme: (theme) => set({ theme }),
|
||||
|
||||
// Selection
|
||||
selectedCharacterIds: [],
|
||||
selectCharacter: (id) =>
|
||||
set((state) => ({
|
||||
selectedCharacterIds: [...state.selectedCharacterIds, id]
|
||||
})),
|
||||
deselectCharacter: (id) =>
|
||||
set((state) => ({
|
||||
selectedCharacterIds: state.selectedCharacterIds.filter((i) => i !== id)
|
||||
})),
|
||||
selectAllCharacters: (ids) => set({ selectedCharacterIds: ids }),
|
||||
clearSelection: () => set({ selectedCharacterIds: [] }),
|
||||
}),
|
||||
{
|
||||
name: 'dofus-manager-ui',
|
||||
partialize: (state) => ({
|
||||
sidebarCollapsed: state.sidebarCollapsed,
|
||||
theme: state.theme,
|
||||
}),
|
||||
}
|
||||
)
|
||||
);
|
||||
```
|
||||
|
||||
## Routing Structure
|
||||
|
||||
```typescript
|
||||
// src/routes/__root.tsx
|
||||
import { createRootRoute, Outlet } from '@tanstack/react-router';
|
||||
import { AppShell } from '@/components/layout/app-shell';
|
||||
|
||||
export const Route = createRootRoute({
|
||||
component: () => (
|
||||
<AppShell>
|
||||
<Outlet />
|
||||
</AppShell>
|
||||
),
|
||||
});
|
||||
|
||||
// Route tree
|
||||
/*
|
||||
src/routes/
|
||||
├── __root.tsx # Root layout with AppShell
|
||||
├── index.tsx # / → Dashboard
|
||||
├── characters/
|
||||
│ ├── index.tsx # /characters → List
|
||||
│ └── $id.tsx # /characters/:id → Detail
|
||||
├── accounts/
|
||||
│ ├── index.tsx # /accounts → List
|
||||
│ └── $id.tsx # /accounts/:id → Detail
|
||||
├── teams/
|
||||
│ ├── index.tsx # /teams → List
|
||||
│ └── $id.tsx # /teams/:id → Detail
|
||||
├── progressions/
|
||||
│ └── index.tsx # /progressions → Tracker
|
||||
└── settings/
|
||||
└── index.tsx # /settings → Settings
|
||||
*/
|
||||
```
|
||||
|
||||
---
|
||||
205
docs/architecture/11-backend-architecture.md
Normal file
205
docs/architecture/11-backend-architecture.md
Normal file
@@ -0,0 +1,205 @@
|
||||
# 11. Backend Architecture
|
||||
|
||||
## Server Functions Organization
|
||||
|
||||
```
|
||||
src/server/
|
||||
├── functions/
|
||||
│ ├── auth.ts # Authentication functions
|
||||
│ ├── characters.ts # Character CRUD
|
||||
│ ├── accounts.ts # Account CRUD
|
||||
│ ├── teams.ts # Team management
|
||||
│ ├── progressions.ts # Progression tracking
|
||||
│ └── dofusdb.ts # DofusDB sync
|
||||
│
|
||||
├── middleware/
|
||||
│ └── auth.ts # Authentication middleware
|
||||
│
|
||||
└── index.ts # Export all functions
|
||||
```
|
||||
|
||||
## Server Function Example
|
||||
|
||||
```typescript
|
||||
// src/server/functions/characters.ts
|
||||
import { createServerFn } from '@tanstack/react-start/server';
|
||||
import { z } from 'zod';
|
||||
import { db } from '@/lib/server/db';
|
||||
import { requireAuth } from '@/server/middleware/auth';
|
||||
|
||||
// Schemas
|
||||
const createCharacterSchema = z.object({
|
||||
name: z.string().min(2).max(50),
|
||||
level: z.number().int().min(1).max(200),
|
||||
classId: z.number().int().positive(),
|
||||
className: z.string(),
|
||||
serverId: z.number().int().positive(),
|
||||
serverName: z.string(),
|
||||
accountId: z.string().cuid(),
|
||||
});
|
||||
|
||||
const characterFiltersSchema = z.object({
|
||||
search: z.string().optional(),
|
||||
classIds: z.array(z.number()).optional(),
|
||||
serverIds: z.array(z.number()).optional(),
|
||||
accountIds: z.array(z.string()).optional(),
|
||||
page: z.number().int().positive().default(1),
|
||||
limit: z.number().int().min(1).max(100).default(20),
|
||||
});
|
||||
|
||||
// Functions
|
||||
export const getCharacters = createServerFn({ method: 'GET' })
|
||||
.validator((data: unknown) => characterFiltersSchema.parse(data))
|
||||
.handler(async ({ data }) => {
|
||||
const session = await requireAuth();
|
||||
const { search, classIds, serverIds, accountIds, page, limit } = data;
|
||||
|
||||
const where = {
|
||||
account: { userId: session.userId },
|
||||
...(search && {
|
||||
name: { contains: search, mode: 'insensitive' as const },
|
||||
}),
|
||||
...(classIds?.length && { classId: { in: classIds } }),
|
||||
...(serverIds?.length && { serverId: { in: serverIds } }),
|
||||
...(accountIds?.length && { accountId: { in: accountIds } }),
|
||||
};
|
||||
|
||||
const [characters, total] = await Promise.all([
|
||||
db.character.findMany({
|
||||
where,
|
||||
include: { account: { select: { id: true, name: true } } },
|
||||
skip: (page - 1) * limit,
|
||||
take: limit,
|
||||
orderBy: { name: 'asc' },
|
||||
}),
|
||||
db.character.count({ where }),
|
||||
]);
|
||||
|
||||
return {
|
||||
characters,
|
||||
pagination: {
|
||||
page,
|
||||
limit,
|
||||
total,
|
||||
totalPages: Math.ceil(total / limit),
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
export const createCharacter = createServerFn({ method: 'POST' })
|
||||
.validator((data: unknown) => createCharacterSchema.parse(data))
|
||||
.handler(async ({ data }) => {
|
||||
const session = await requireAuth();
|
||||
|
||||
// Verify account belongs to user
|
||||
const account = await db.account.findFirst({
|
||||
where: { id: data.accountId, userId: session.userId },
|
||||
});
|
||||
|
||||
if (!account) {
|
||||
throw new Error('Account not found');
|
||||
}
|
||||
|
||||
return db.character.create({ data });
|
||||
});
|
||||
|
||||
export const bulkDeleteCharacters = createServerFn({ method: 'POST' })
|
||||
.validator((data: unknown) => z.object({ ids: z.array(z.string().cuid()) }).parse(data))
|
||||
.handler(async ({ data }) => {
|
||||
const session = await requireAuth();
|
||||
|
||||
const result = await db.character.deleteMany({
|
||||
where: {
|
||||
id: { in: data.ids },
|
||||
account: { userId: session.userId },
|
||||
},
|
||||
});
|
||||
|
||||
return { deleted: result.count };
|
||||
});
|
||||
```
|
||||
|
||||
## Authentication Middleware
|
||||
|
||||
```typescript
|
||||
// src/server/middleware/auth.ts
|
||||
import { getWebRequest } from '@tanstack/react-start/server';
|
||||
import { db } from '@/lib/server/db';
|
||||
|
||||
interface Session {
|
||||
userId: string;
|
||||
sessionId: string;
|
||||
}
|
||||
|
||||
export async function requireAuth(): Promise<Session> {
|
||||
const request = getWebRequest();
|
||||
const sessionId = request.headers.get('cookie')
|
||||
?.split(';')
|
||||
.find(c => c.trim().startsWith('session='))
|
||||
?.split('=')[1];
|
||||
|
||||
if (!sessionId) {
|
||||
throw new Error('Unauthorized');
|
||||
}
|
||||
|
||||
const session = await db.session.findUnique({
|
||||
where: { id: sessionId },
|
||||
include: { user: true },
|
||||
});
|
||||
|
||||
if (!session || session.expiresAt < new Date()) {
|
||||
throw new Error('Session expired');
|
||||
}
|
||||
|
||||
return {
|
||||
userId: session.userId,
|
||||
sessionId: session.id,
|
||||
};
|
||||
}
|
||||
|
||||
export async function getOptionalAuth(): Promise<Session | null> {
|
||||
try {
|
||||
return await requireAuth();
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Caching Strategy
|
||||
|
||||
```typescript
|
||||
// src/lib/server/cache.ts
|
||||
import NodeCache from 'node-cache';
|
||||
|
||||
// Different TTLs for different data types
|
||||
const caches = {
|
||||
// Reference data (rarely changes)
|
||||
reference: new NodeCache({ stdTTL: 3600, checkperiod: 600 }), // 1 hour
|
||||
|
||||
// User data (changes more frequently)
|
||||
user: new NodeCache({ stdTTL: 300, checkperiod: 60 }), // 5 minutes
|
||||
};
|
||||
|
||||
export const referenceCache = {
|
||||
get: <T>(key: string): T | undefined => caches.reference.get(key),
|
||||
set: <T>(key: string, value: T): boolean => caches.reference.set(key, value),
|
||||
del: (key: string): number => caches.reference.del(key),
|
||||
flush: (): void => caches.reference.flushAll(),
|
||||
};
|
||||
|
||||
export const userCache = {
|
||||
get: <T>(key: string): T | undefined => caches.user.get(key),
|
||||
set: <T>(key: string, value: T): boolean => caches.user.set(key, value),
|
||||
del: (key: string | string[]): number => caches.user.del(key),
|
||||
flush: (): void => caches.user.flushAll(),
|
||||
|
||||
// Helper to invalidate all cache for a user
|
||||
invalidateUser: (userId: string): void => {
|
||||
const keys = caches.user.keys().filter(k => k.startsWith(`user:${userId}:`));
|
||||
caches.user.del(keys);
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
93
docs/architecture/12-project-structure.md
Normal file
93
docs/architecture/12-project-structure.md
Normal file
@@ -0,0 +1,93 @@
|
||||
# 12. Project Structure
|
||||
|
||||
```
|
||||
dofus-manager/
|
||||
├── .github/
|
||||
│ └── workflows/
|
||||
│ └── ci.yml
|
||||
│
|
||||
├── docker/
|
||||
│ ├── Dockerfile
|
||||
│ └── docker-compose.yml
|
||||
│
|
||||
├── docs/
|
||||
│ ├── prd.md
|
||||
│ ├── front-end-spec.md
|
||||
│ └── architecture.md
|
||||
│
|
||||
├── prisma/
|
||||
│ ├── schema.prisma
|
||||
│ └── migrations/
|
||||
│
|
||||
├── public/
|
||||
│ └── favicon.ico
|
||||
│
|
||||
├── src/
|
||||
│ ├── components/
|
||||
│ │ ├── ui/ # shadcn/ui components
|
||||
│ │ ├── layout/ # Layout components
|
||||
│ │ ├── characters/ # Character feature
|
||||
│ │ ├── accounts/ # Account feature
|
||||
│ │ ├── teams/ # Team feature
|
||||
│ │ ├── progressions/ # Progression feature
|
||||
│ │ └── shared/ # Shared components
|
||||
│ │
|
||||
│ ├── lib/
|
||||
│ │ ├── utils.ts # Utility functions (cn, etc.)
|
||||
│ │ ├── errors.ts # Error types
|
||||
│ │ ├── schemas/ # Zod schemas
|
||||
│ │ │ ├── character.ts
|
||||
│ │ │ ├── account.ts
|
||||
│ │ │ ├── team.ts
|
||||
│ │ │ └── progression.ts
|
||||
│ │ ├── client/ # Client-only code
|
||||
│ │ │ ├── query-client.ts
|
||||
│ │ │ └── stores/
|
||||
│ │ │ └── ui-store.ts
|
||||
│ │ └── server/ # Server-only code
|
||||
│ │ ├── db.ts
|
||||
│ │ ├── cache.ts
|
||||
│ │ ├── logger.ts
|
||||
│ │ └── dofusdb.ts
|
||||
│ │
|
||||
│ ├── routes/
|
||||
│ │ ├── __root.tsx
|
||||
│ │ ├── index.tsx
|
||||
│ │ ├── characters/
|
||||
│ │ ├── accounts/
|
||||
│ │ ├── teams/
|
||||
│ │ ├── progressions/
|
||||
│ │ └── settings/
|
||||
│ │
|
||||
│ ├── server/
|
||||
│ │ ├── functions/
|
||||
│ │ │ ├── auth.ts
|
||||
│ │ │ ├── characters.ts
|
||||
│ │ │ ├── accounts.ts
|
||||
│ │ │ ├── teams.ts
|
||||
│ │ │ ├── progressions.ts
|
||||
│ │ │ └── dofusdb.ts
|
||||
│ │ ├── middleware/
|
||||
│ │ │ └── auth.ts
|
||||
│ │ └── index.ts
|
||||
│ │
|
||||
│ ├── styles/
|
||||
│ │ └── globals.css
|
||||
│ │
|
||||
│ └── app.tsx # App entry point
|
||||
│
|
||||
├── tests/
|
||||
│ ├── unit/
|
||||
│ ├── integration/
|
||||
│ └── e2e/
|
||||
│
|
||||
├── .env.example
|
||||
├── .gitignore
|
||||
├── biome.json
|
||||
├── package.json
|
||||
├── tsconfig.json
|
||||
├── app.config.ts # TanStack Start config
|
||||
└── README.md
|
||||
```
|
||||
|
||||
---
|
||||
83
docs/architecture/13-development-workflow.md
Normal file
83
docs/architecture/13-development-workflow.md
Normal file
@@ -0,0 +1,83 @@
|
||||
# 13. Development Workflow
|
||||
|
||||
## Local Development Setup
|
||||
|
||||
```bash
|
||||
# 1. Clone repository
|
||||
git clone <repo-url>
|
||||
cd dofus-manager
|
||||
|
||||
# 2. Install dependencies
|
||||
pnpm install
|
||||
|
||||
# 3. Setup environment
|
||||
cp .env.example .env
|
||||
# Edit .env with your values
|
||||
|
||||
# 4. Start database
|
||||
docker compose up -d postgres
|
||||
|
||||
# 5. Run migrations
|
||||
pnpm prisma migrate dev
|
||||
|
||||
# 6. Seed database (optional)
|
||||
pnpm prisma db seed
|
||||
|
||||
# 7. Start development server
|
||||
pnpm dev
|
||||
```
|
||||
|
||||
## Environment Variables
|
||||
|
||||
```bash
|
||||
# .env.example
|
||||
|
||||
# Database
|
||||
DATABASE_URL="postgresql://postgres:postgres@localhost:5432/dofus_manager?schema=public"
|
||||
|
||||
# App
|
||||
APP_URL="http://localhost:3000"
|
||||
NODE_ENV="development"
|
||||
|
||||
# Session
|
||||
SESSION_SECRET="your-secret-key-min-32-chars"
|
||||
|
||||
# Optional: DofusDB
|
||||
DOFUSDB_CACHE_TTL="3600"
|
||||
```
|
||||
|
||||
## Git Workflow
|
||||
|
||||
```
|
||||
main (production)
|
||||
│
|
||||
└── develop (staging)
|
||||
│
|
||||
├── feature/add-character-filters
|
||||
├── feature/team-management
|
||||
└── fix/progression-update-bug
|
||||
```
|
||||
|
||||
## Branch Naming
|
||||
|
||||
- `feature/*` - New features
|
||||
- `fix/*` - Bug fixes
|
||||
- `refactor/*` - Code refactoring
|
||||
- `docs/*` - Documentation updates
|
||||
- `chore/*` - Maintenance tasks
|
||||
|
||||
## Commit Convention
|
||||
|
||||
```
|
||||
<type>(<scope>): <description>
|
||||
|
||||
Types: feat, fix, docs, style, refactor, test, chore
|
||||
Scope: characters, accounts, teams, progressions, auth, ui
|
||||
|
||||
Examples:
|
||||
feat(characters): add bulk delete functionality
|
||||
fix(progressions): correct date formatting
|
||||
docs(readme): update setup instructions
|
||||
```
|
||||
|
||||
---
|
||||
215
docs/architecture/14-deployment-architecture.md
Normal file
215
docs/architecture/14-deployment-architecture.md
Normal file
@@ -0,0 +1,215 @@
|
||||
# 14. Deployment Architecture
|
||||
|
||||
## Docker Configuration
|
||||
|
||||
```dockerfile
|
||||
# docker/Dockerfile
|
||||
|
||||
# Build stage
|
||||
FROM node:20-alpine AS builder
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Install pnpm
|
||||
RUN corepack enable && corepack prepare pnpm@latest --activate
|
||||
|
||||
# Copy package files
|
||||
COPY package.json pnpm-lock.yaml ./
|
||||
RUN pnpm install --frozen-lockfile
|
||||
|
||||
# Copy source and build
|
||||
COPY . .
|
||||
RUN pnpm prisma generate
|
||||
RUN pnpm build
|
||||
|
||||
# Production stage
|
||||
FROM node:20-alpine AS runner
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Install pnpm
|
||||
RUN corepack enable && corepack prepare pnpm@latest --activate
|
||||
|
||||
# Create non-root user
|
||||
RUN addgroup --system --gid 1001 nodejs
|
||||
RUN adduser --system --uid 1001 app
|
||||
|
||||
# Copy built application
|
||||
COPY --from=builder --chown=app:nodejs /app/.output ./.output
|
||||
COPY --from=builder --chown=app:nodejs /app/node_modules ./node_modules
|
||||
COPY --from=builder --chown=app:nodejs /app/package.json ./package.json
|
||||
COPY --from=builder --chown=app:nodejs /app/prisma ./prisma
|
||||
|
||||
USER app
|
||||
|
||||
EXPOSE 3000
|
||||
|
||||
ENV NODE_ENV=production
|
||||
ENV PORT=3000
|
||||
|
||||
CMD ["node", ".output/server/index.mjs"]
|
||||
```
|
||||
|
||||
## Docker Compose (Production)
|
||||
|
||||
```yaml
|
||||
# docker/docker-compose.yml
|
||||
|
||||
services:
|
||||
app:
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: docker/Dockerfile
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- DATABASE_URL=postgresql://postgres:${DB_PASSWORD}@postgres:5432/dofus_manager
|
||||
- SESSION_SECRET=${SESSION_SECRET}
|
||||
- NODE_ENV=production
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
networks:
|
||||
- internal
|
||||
- traefik
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.dofus.rule=Host(`dofus.example.com`)"
|
||||
- "traefik.http.routers.dofus.entrypoints=websecure"
|
||||
- "traefik.http.routers.dofus.tls.certresolver=letsencrypt"
|
||||
- "traefik.http.services.dofus.loadbalancer.server.port=3000"
|
||||
|
||||
postgres:
|
||||
image: postgres:16-alpine
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- POSTGRES_USER=postgres
|
||||
- POSTGRES_PASSWORD=${DB_PASSWORD}
|
||||
- POSTGRES_DB=dofus_manager
|
||||
volumes:
|
||||
- postgres_data:/var/lib/postgresql/data
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U postgres"]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
networks:
|
||||
- internal
|
||||
|
||||
traefik:
|
||||
image: traefik:v3.0
|
||||
restart: unless-stopped
|
||||
command:
|
||||
- "--api.dashboard=true"
|
||||
- "--providers.docker=true"
|
||||
- "--providers.docker.exposedbydefault=false"
|
||||
- "--entrypoints.web.address=:80"
|
||||
- "--entrypoints.websecure.address=:443"
|
||||
- "--entrypoints.web.http.redirections.entrypoint.to=websecure"
|
||||
- "--certificatesresolvers.letsencrypt.acme.httpchallenge=true"
|
||||
- "--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web"
|
||||
- "--certificatesresolvers.letsencrypt.acme.email=${ACME_EMAIL}"
|
||||
- "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
- letsencrypt:/letsencrypt
|
||||
networks:
|
||||
- traefik
|
||||
|
||||
volumes:
|
||||
postgres_data:
|
||||
letsencrypt:
|
||||
|
||||
networks:
|
||||
internal:
|
||||
traefik:
|
||||
external: true
|
||||
```
|
||||
|
||||
## GitLab CI/CD Pipeline
|
||||
|
||||
```yaml
|
||||
# .gitlab-ci.yml
|
||||
|
||||
stages:
|
||||
- test
|
||||
- build
|
||||
- deploy
|
||||
|
||||
variables:
|
||||
DOCKER_IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
|
||||
|
||||
# Test stage
|
||||
test:
|
||||
stage: test
|
||||
image: node:20-alpine
|
||||
before_script:
|
||||
- corepack enable
|
||||
- pnpm install --frozen-lockfile
|
||||
script:
|
||||
- pnpm lint
|
||||
- pnpm typecheck
|
||||
- pnpm test
|
||||
cache:
|
||||
key: ${CI_COMMIT_REF_SLUG}
|
||||
paths:
|
||||
- node_modules/
|
||||
|
||||
# Build stage
|
||||
build:
|
||||
stage: build
|
||||
image: docker:24
|
||||
services:
|
||||
- docker:24-dind
|
||||
before_script:
|
||||
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
|
||||
script:
|
||||
- docker build -t $DOCKER_IMAGE -f docker/Dockerfile .
|
||||
- docker push $DOCKER_IMAGE
|
||||
- docker tag $DOCKER_IMAGE $CI_REGISTRY_IMAGE:latest
|
||||
- docker push $CI_REGISTRY_IMAGE:latest
|
||||
only:
|
||||
- main
|
||||
- develop
|
||||
|
||||
# Deploy staging
|
||||
deploy_staging:
|
||||
stage: deploy
|
||||
image: alpine:latest
|
||||
before_script:
|
||||
- apk add --no-cache openssh-client
|
||||
- eval $(ssh-agent -s)
|
||||
- echo "$SSH_PRIVATE_KEY" | ssh-add -
|
||||
- mkdir -p ~/.ssh
|
||||
- echo "$SSH_KNOWN_HOSTS" >> ~/.ssh/known_hosts
|
||||
script:
|
||||
- ssh $STAGING_USER@$STAGING_HOST "cd /opt/dofus-manager && docker compose pull && docker compose up -d"
|
||||
environment:
|
||||
name: staging
|
||||
url: https://staging.dofus.example.com
|
||||
only:
|
||||
- develop
|
||||
|
||||
# Deploy production
|
||||
deploy_production:
|
||||
stage: deploy
|
||||
image: alpine:latest
|
||||
before_script:
|
||||
- apk add --no-cache openssh-client
|
||||
- eval $(ssh-agent -s)
|
||||
- echo "$SSH_PRIVATE_KEY" | ssh-add -
|
||||
- mkdir -p ~/.ssh
|
||||
- echo "$SSH_KNOWN_HOSTS" >> ~/.ssh/known_hosts
|
||||
script:
|
||||
- ssh $PROD_USER@$PROD_HOST "cd /opt/dofus-manager && docker compose pull && docker compose up -d && docker compose exec app pnpm prisma migrate deploy"
|
||||
environment:
|
||||
name: production
|
||||
url: https://dofus.example.com
|
||||
only:
|
||||
- main
|
||||
when: manual
|
||||
```
|
||||
|
||||
---
|
||||
68
docs/architecture/15-security-performance.md
Normal file
68
docs/architecture/15-security-performance.md
Normal file
@@ -0,0 +1,68 @@
|
||||
# 15. Security & Performance
|
||||
|
||||
## Security Measures
|
||||
|
||||
### Authentication
|
||||
- Session-based authentication with secure cookies
|
||||
- Password hashing with bcrypt (cost factor 12)
|
||||
- Session expiration and rotation
|
||||
|
||||
### Input Validation
|
||||
- All inputs validated with Zod schemas
|
||||
- Server-side validation mandatory
|
||||
- Prisma parameterized queries (SQL injection prevention)
|
||||
|
||||
### Headers (via Traefik)
|
||||
```yaml
|
||||
# Security headers middleware
|
||||
http:
|
||||
middlewares:
|
||||
security-headers:
|
||||
headers:
|
||||
stsSeconds: 31536000
|
||||
stsIncludeSubdomains: true
|
||||
contentTypeNosniff: true
|
||||
frameDeny: true
|
||||
browserXssFilter: true
|
||||
referrerPolicy: "strict-origin-when-cross-origin"
|
||||
contentSecurityPolicy: "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'"
|
||||
```
|
||||
|
||||
## Performance Optimizations
|
||||
|
||||
### Database
|
||||
- Indexes on foreign keys and search fields
|
||||
- Pagination for all list queries
|
||||
- Connection pooling via Prisma
|
||||
|
||||
### Caching
|
||||
- node-cache for server-side caching
|
||||
- TanStack Query for client-side caching
|
||||
- DofusDB data cached for 1 hour
|
||||
|
||||
### Frontend
|
||||
- Code splitting via TanStack Router
|
||||
- Lazy loading for routes
|
||||
- Optimistic updates for better UX
|
||||
|
||||
### Bundle Optimization
|
||||
```typescript
|
||||
// app.config.ts
|
||||
export default defineConfig({
|
||||
vite: {
|
||||
build: {
|
||||
rollupOptions: {
|
||||
output: {
|
||||
manualChunks: {
|
||||
'vendor-react': ['react', 'react-dom'],
|
||||
'vendor-tanstack': ['@tanstack/react-router', '@tanstack/react-query'],
|
||||
'vendor-ui': ['@radix-ui/react-dialog', '@radix-ui/react-select'],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
146
docs/architecture/16-testing-strategy.md
Normal file
146
docs/architecture/16-testing-strategy.md
Normal file
@@ -0,0 +1,146 @@
|
||||
# 16. Testing Strategy
|
||||
|
||||
## Testing Pyramid
|
||||
|
||||
```
|
||||
┌───────┐
|
||||
│ E2E │ ← Few, critical paths
|
||||
│ Tests │
|
||||
┌┴───────┴┐
|
||||
│Integration│ ← API & DB tests
|
||||
│ Tests │
|
||||
┌┴─────────┴┐
|
||||
│ Unit │ ← Many, fast
|
||||
│ Tests │
|
||||
└───────────┘
|
||||
```
|
||||
|
||||
## Unit Tests (Vitest)
|
||||
|
||||
```typescript
|
||||
// tests/unit/schemas/character.test.ts
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { createCharacterSchema } from '@/lib/schemas/character';
|
||||
|
||||
describe('createCharacterSchema', () => {
|
||||
it('validates correct input', () => {
|
||||
const input = {
|
||||
name: 'TestChar',
|
||||
level: 200,
|
||||
classId: 1,
|
||||
className: 'Cra',
|
||||
serverId: 1,
|
||||
serverName: 'Imagiro',
|
||||
accountId: 'clx123abc',
|
||||
};
|
||||
|
||||
expect(() => createCharacterSchema.parse(input)).not.toThrow();
|
||||
});
|
||||
|
||||
it('rejects invalid level', () => {
|
||||
const input = {
|
||||
name: 'TestChar',
|
||||
level: 250, // Invalid: max is 200
|
||||
classId: 1,
|
||||
className: 'Cra',
|
||||
serverId: 1,
|
||||
serverName: 'Imagiro',
|
||||
accountId: 'clx123abc',
|
||||
};
|
||||
|
||||
expect(() => createCharacterSchema.parse(input)).toThrow();
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
## Integration Tests
|
||||
|
||||
```typescript
|
||||
// tests/integration/characters.test.ts
|
||||
import { describe, it, expect, beforeAll, afterAll } from 'vitest';
|
||||
import { db } from '@/lib/server/db';
|
||||
|
||||
describe('Character API', () => {
|
||||
let testUserId: string;
|
||||
let testAccountId: string;
|
||||
|
||||
beforeAll(async () => {
|
||||
// Setup test data
|
||||
const user = await db.user.create({
|
||||
data: {
|
||||
email: 'test@test.com',
|
||||
passwordHash: 'hash',
|
||||
},
|
||||
});
|
||||
testUserId = user.id;
|
||||
|
||||
const account = await db.account.create({
|
||||
data: {
|
||||
name: 'TestAccount',
|
||||
userId: testUserId,
|
||||
},
|
||||
});
|
||||
testAccountId = account.id;
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
// Cleanup
|
||||
await db.user.delete({ where: { id: testUserId } });
|
||||
});
|
||||
|
||||
it('creates a character', async () => {
|
||||
const character = await db.character.create({
|
||||
data: {
|
||||
name: 'TestChar',
|
||||
level: 200,
|
||||
classId: 1,
|
||||
className: 'Cra',
|
||||
serverId: 1,
|
||||
serverName: 'Imagiro',
|
||||
accountId: testAccountId,
|
||||
},
|
||||
});
|
||||
|
||||
expect(character.name).toBe('TestChar');
|
||||
expect(character.level).toBe(200);
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
## E2E Tests (Playwright)
|
||||
|
||||
```typescript
|
||||
// tests/e2e/characters.spec.ts
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
test.describe('Characters Page', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
// Login
|
||||
await page.goto('/login');
|
||||
await page.fill('[name="email"]', 'test@test.com');
|
||||
await page.fill('[name="password"]', 'password');
|
||||
await page.click('button[type="submit"]');
|
||||
await page.waitForURL('/');
|
||||
});
|
||||
|
||||
test('displays character list', async ({ page }) => {
|
||||
await page.goto('/characters');
|
||||
|
||||
await expect(page.locator('h1')).toContainText('Personnages');
|
||||
await expect(page.locator('table')).toBeVisible();
|
||||
});
|
||||
|
||||
test('can create a new character', async ({ page }) => {
|
||||
await page.goto('/characters');
|
||||
|
||||
await page.click('button:has-text("Ajouter")');
|
||||
await page.fill('[name="name"]', 'NewChar');
|
||||
await page.fill('[name="level"]', '100');
|
||||
await page.click('button:has-text("Créer")');
|
||||
|
||||
await expect(page.locator('text=NewChar')).toBeVisible();
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
343
docs/architecture/17-coding-standards.md
Normal file
343
docs/architecture/17-coding-standards.md
Normal file
@@ -0,0 +1,343 @@
|
||||
# 17. Coding Standards
|
||||
|
||||
Cette section définit les standards de code minimaux mais critiques pour le développement. Ces règles sont conçues pour les agents IA et les développeurs.
|
||||
|
||||
## Critical Fullstack Rules
|
||||
|
||||
| Rule | Description |
|
||||
|------|-------------|
|
||||
| **Type Sharing** | Toujours définir les types partagés dans `src/types/` et les importer dans les composants et server functions. Ne jamais dupliquer les interfaces. |
|
||||
| **Server Functions Only** | Ne jamais faire d'appels HTTP directs (fetch, axios). Toujours utiliser les server functions importées depuis `@/server/*`. |
|
||||
| **Zod Validation** | Toute entrée utilisateur doit être validée avec un schéma Zod. Le schéma doit être colocalisé avec la server function. |
|
||||
| **Prisma Transactions** | Les opérations multi-tables doivent utiliser `prisma.$transaction()` pour garantir l'atomicité. |
|
||||
| **Cache Invalidation** | Après chaque mutation, invalider les caches affectés via `cacheService.invalidate()` et `queryClient.invalidateQueries()`. |
|
||||
| **Error Boundaries** | Chaque page doit être wrappée dans un ErrorBoundary. Les erreurs serveur doivent utiliser les classes de `@/lib/errors.ts`. |
|
||||
| **No Direct State Mutation** | Ne jamais muter l'état directement. Utiliser les setters de useState ou les mutations TanStack Query. |
|
||||
| **URL State for Filters** | Les filtres et la pagination doivent être stockés dans l'URL via TanStack Router, pas dans le state local. |
|
||||
| **Optimistic Updates Pattern** | Pour les actions fréquentes (toggle, update), utiliser les optimistic updates de TanStack Query. |
|
||||
| **Component Colocation** | Les hooks, types et helpers spécifiques à un composant doivent être dans le même dossier. |
|
||||
|
||||
## Naming Conventions
|
||||
|
||||
| Element | Frontend | Backend | Example |
|
||||
|---------|----------|---------|---------|
|
||||
| Components | PascalCase | — | `CharacterCard.tsx` |
|
||||
| Component files | kebab-case ou PascalCase | — | `character-card.tsx` |
|
||||
| Hooks | camelCase + use prefix | — | `useCharacters.ts` |
|
||||
| Server Functions | camelCase | camelCase | `getCharacters`, `createTeam` |
|
||||
| Server Function files | kebab-case | kebab-case | `characters.ts` |
|
||||
| Types/Interfaces | PascalCase | PascalCase | `Character`, `CreateCharacterInput` |
|
||||
| Enums | PascalCase | PascalCase | `CharacterClass`, `TeamType` |
|
||||
| Constants | SCREAMING_SNAKE | SCREAMING_SNAKE | `MAX_TEAM_SIZE` |
|
||||
| Database tables | — | snake_case | `character_progressions` |
|
||||
| Database columns | — | snake_case | `created_at`, `account_id` |
|
||||
| URL routes | kebab-case | kebab-case | `/characters`, `/bulk-progressions` |
|
||||
| Query keys | camelCase arrays | — | `['characters', 'list', filters]` |
|
||||
| CSS classes | Tailwind utilities | — | `bg-card text-foreground` |
|
||||
|
||||
## File Structure Conventions
|
||||
|
||||
### Component File Structure
|
||||
|
||||
```typescript
|
||||
// 1. Imports (grouped)
|
||||
import { useState } from 'react'; // React
|
||||
import { useQuery } from '@tanstack/react-query'; // External libs
|
||||
import { Button } from '@/components/ui/button'; // Internal UI
|
||||
import { getCharacters } from '@/server/characters'; // Server functions
|
||||
import type { Character } from '@/types'; // Types (last)
|
||||
|
||||
// 2. Types (if not in separate file)
|
||||
interface CharacterListProps {
|
||||
serverId?: string;
|
||||
}
|
||||
|
||||
// 3. Constants (if any)
|
||||
const PAGE_SIZE = 20;
|
||||
|
||||
// 4. Component
|
||||
export function CharacterList({ serverId }: CharacterListProps) {
|
||||
// 4a. Hooks (in order: router, query, state, effects, callbacks)
|
||||
const navigate = useNavigate();
|
||||
const { data, isLoading } = useQuery({ ... });
|
||||
const [selected, setSelected] = useState<string[]>([]);
|
||||
|
||||
// 4b. Early returns
|
||||
if (isLoading) return <Loading />;
|
||||
if (!data) return <EmptyState />;
|
||||
|
||||
// 4c. Render
|
||||
return (
|
||||
<div>
|
||||
{/* JSX */}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// 5. Sub-components (if small and only used here)
|
||||
function CharacterRow({ character }: { character: Character }) {
|
||||
return <tr>...</tr>;
|
||||
}
|
||||
```
|
||||
|
||||
### Server Function File Structure
|
||||
|
||||
```typescript
|
||||
// 1. Imports
|
||||
import { createServerFn } from '@tanstack/start';
|
||||
import { z } from 'zod';
|
||||
import { prisma } from '@/lib/prisma';
|
||||
import { cacheService } from '@/lib/cache';
|
||||
import { NotFoundError, ValidationError } from '@/lib/errors';
|
||||
|
||||
// 2. Schemas (colocated with functions)
|
||||
const createCharacterSchema = z.object({
|
||||
name: z.string().min(1).max(50),
|
||||
class: z.nativeEnum(CharacterClass),
|
||||
level: z.number().int().min(1).max(200),
|
||||
serverId: z.string().uuid(),
|
||||
accountId: z.string().uuid(),
|
||||
});
|
||||
|
||||
// 3. Server Functions (exported)
|
||||
export const getCharacters = createServerFn('GET', async (filters) => {
|
||||
// Implementation
|
||||
});
|
||||
|
||||
export const createCharacter = createServerFn('POST', async (input) => {
|
||||
const data = createCharacterSchema.parse(input);
|
||||
// Implementation
|
||||
});
|
||||
|
||||
// 4. Helper functions (private, at bottom)
|
||||
function buildWhereClause(filters: Filters): Prisma.CharacterWhereInput {
|
||||
// Implementation
|
||||
}
|
||||
```
|
||||
|
||||
## Code Quality Rules
|
||||
|
||||
### TypeScript
|
||||
|
||||
```typescript
|
||||
// ✅ DO: Explicit return types for exported functions
|
||||
export function calculateTotal(items: Item[]): number {
|
||||
return items.reduce((sum, item) => sum + item.amount, 0);
|
||||
}
|
||||
|
||||
// ❌ DON'T: Implicit any
|
||||
function processData(data) { ... }
|
||||
|
||||
// ✅ DO: Use type imports
|
||||
import type { Character } from '@/types';
|
||||
|
||||
// ❌ DON'T: Import types as values
|
||||
import { Character } from '@/types';
|
||||
|
||||
// ✅ DO: Discriminated unions for state
|
||||
type State =
|
||||
| { status: 'loading' }
|
||||
| { status: 'error'; error: Error }
|
||||
| { status: 'success'; data: Character[] };
|
||||
|
||||
// ❌ DON'T: Optional properties for state
|
||||
type State = {
|
||||
loading?: boolean;
|
||||
error?: Error;
|
||||
data?: Character[];
|
||||
};
|
||||
```
|
||||
|
||||
### React
|
||||
|
||||
```typescript
|
||||
// ✅ DO: Named exports for components
|
||||
export function CharacterCard({ character }: Props) { ... }
|
||||
|
||||
// ❌ DON'T: Default exports (except for routes)
|
||||
export default function CharacterCard() { ... }
|
||||
|
||||
// ✅ DO: Destructure props
|
||||
function CharacterCard({ character, onSelect }: Props) { ... }
|
||||
|
||||
// ❌ DON'T: Props object
|
||||
function CharacterCard(props: Props) {
|
||||
const character = props.character;
|
||||
}
|
||||
|
||||
// ✅ DO: useCallback for handlers passed to children
|
||||
const handleSelect = useCallback((id: string) => {
|
||||
setSelected(prev => [...prev, id]);
|
||||
}, []);
|
||||
|
||||
// ✅ DO: useMemo for expensive computations
|
||||
const filteredCharacters = useMemo(
|
||||
() => characters.filter(c => c.level >= 180),
|
||||
[characters]
|
||||
);
|
||||
|
||||
// ❌ DON'T: Inline objects/arrays in props (causes re-renders)
|
||||
<Table columns={[col1, col2]} /> // Creates new array each render
|
||||
```
|
||||
|
||||
### Prisma
|
||||
|
||||
```typescript
|
||||
// ✅ DO: Select only needed fields
|
||||
const characters = await prisma.character.findMany({
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
level: true,
|
||||
server: { select: { name: true } },
|
||||
},
|
||||
});
|
||||
|
||||
// ❌ DON'T: Fetch everything
|
||||
const characters = await prisma.character.findMany({
|
||||
include: {
|
||||
server: true,
|
||||
account: true,
|
||||
progressions: true,
|
||||
currencies: true,
|
||||
teamMemberships: true,
|
||||
},
|
||||
});
|
||||
|
||||
// ✅ DO: Use transactions for related operations
|
||||
await prisma.$transaction([
|
||||
prisma.teamMember.deleteMany({ where: { teamId } }),
|
||||
prisma.team.delete({ where: { id: teamId } }),
|
||||
]);
|
||||
|
||||
// ✅ DO: Count separately from data
|
||||
const [data, total] = await Promise.all([
|
||||
prisma.character.findMany({ take: 20 }),
|
||||
prisma.character.count(),
|
||||
]);
|
||||
```
|
||||
|
||||
## Import Order
|
||||
|
||||
ESLint avec `eslint-plugin-import` applique cet ordre :
|
||||
|
||||
```typescript
|
||||
// 1. React
|
||||
import { useState, useCallback } from 'react';
|
||||
|
||||
// 2. External packages (alphabetical)
|
||||
import { useQuery, useMutation } from '@tanstack/react-query';
|
||||
import { useNavigate } from '@tanstack/react-router';
|
||||
import { z } from 'zod';
|
||||
|
||||
// 3. Internal absolute imports (alphabetical by path)
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { DataTable } from '@/components/data-table/data-table';
|
||||
import { useCharacters } from '@/hooks/use-characters';
|
||||
import { prisma } from '@/lib/prisma';
|
||||
import { getCharacters } from '@/server/characters';
|
||||
|
||||
// 4. Relative imports
|
||||
import { CharacterRow } from './character-row';
|
||||
|
||||
// 5. Type imports (at the end)
|
||||
import type { Character, CharacterFilters } from '@/types';
|
||||
```
|
||||
|
||||
## ESLint & Prettier Config
|
||||
|
||||
### .eslintrc.cjs
|
||||
|
||||
```javascript
|
||||
module.exports = {
|
||||
root: true,
|
||||
env: { browser: true, es2022: true, node: true },
|
||||
extends: [
|
||||
'eslint:recommended',
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
'plugin:react-hooks/recommended',
|
||||
'prettier',
|
||||
],
|
||||
parser: '@typescript-eslint/parser',
|
||||
parserOptions: {
|
||||
ecmaVersion: 'latest',
|
||||
sourceType: 'module',
|
||||
project: './tsconfig.json',
|
||||
},
|
||||
plugins: ['@typescript-eslint', 'import'],
|
||||
rules: {
|
||||
// TypeScript
|
||||
'@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
|
||||
'@typescript-eslint/consistent-type-imports': 'error',
|
||||
'@typescript-eslint/no-explicit-any': 'warn',
|
||||
|
||||
// Import order
|
||||
'import/order': [
|
||||
'error',
|
||||
{
|
||||
groups: [
|
||||
'builtin',
|
||||
'external',
|
||||
'internal',
|
||||
'parent',
|
||||
'sibling',
|
||||
'index',
|
||||
'type',
|
||||
],
|
||||
'newlines-between': 'always',
|
||||
alphabetize: { order: 'asc' },
|
||||
},
|
||||
],
|
||||
|
||||
// React
|
||||
'react-hooks/rules-of-hooks': 'error',
|
||||
'react-hooks/exhaustive-deps': 'warn',
|
||||
|
||||
// General
|
||||
'no-console': ['warn', { allow: ['warn', 'error'] }],
|
||||
},
|
||||
ignorePatterns: ['node_modules', '.output', 'dist'],
|
||||
};
|
||||
```
|
||||
|
||||
### .prettierrc
|
||||
|
||||
```json
|
||||
{
|
||||
"semi": true,
|
||||
"singleQuote": true,
|
||||
"tabWidth": 2,
|
||||
"trailingComma": "es5",
|
||||
"printWidth": 100,
|
||||
"plugins": ["prettier-plugin-tailwindcss"]
|
||||
}
|
||||
```
|
||||
|
||||
## Git Commit Standards
|
||||
|
||||
```bash
|
||||
# Format
|
||||
<type>(<scope>): <subject>
|
||||
|
||||
# Types
|
||||
feat # New feature
|
||||
fix # Bug fix
|
||||
docs # Documentation
|
||||
style # Formatting (no code change)
|
||||
refactor # Refactoring
|
||||
test # Adding tests
|
||||
chore # Build, deps, tooling
|
||||
|
||||
# Scopes (optional)
|
||||
characters, teams, accounts, progressions, currencies
|
||||
ui, api, db, auth, dofusdb
|
||||
|
||||
# Examples
|
||||
feat(characters): add bulk progression update
|
||||
fix(teams): validate account constraint on member add
|
||||
refactor(api): extract prisma helpers
|
||||
test(teams): add integration tests for constraints
|
||||
chore(deps): upgrade TanStack Query to v5.17
|
||||
```
|
||||
|
||||
---
|
||||
167
docs/architecture/18-error-handling.md
Normal file
167
docs/architecture/18-error-handling.md
Normal file
@@ -0,0 +1,167 @@
|
||||
# 18. Error Handling
|
||||
|
||||
## Unified Error Types
|
||||
|
||||
```typescript
|
||||
// src/lib/errors.ts
|
||||
|
||||
export enum ErrorCode {
|
||||
// Validation (400)
|
||||
VALIDATION_ERROR = 'VALIDATION_ERROR',
|
||||
INVALID_INPUT = 'INVALID_INPUT',
|
||||
|
||||
// Authentication (401)
|
||||
UNAUTHORIZED = 'UNAUTHORIZED',
|
||||
SESSION_EXPIRED = 'SESSION_EXPIRED',
|
||||
|
||||
// Authorization (403)
|
||||
FORBIDDEN = 'FORBIDDEN',
|
||||
INSUFFICIENT_PERMISSIONS = 'INSUFFICIENT_PERMISSIONS',
|
||||
|
||||
// Not Found (404)
|
||||
NOT_FOUND = 'NOT_FOUND',
|
||||
RESOURCE_NOT_FOUND = 'RESOURCE_NOT_FOUND',
|
||||
|
||||
// Conflict (409)
|
||||
CONFLICT = 'CONFLICT',
|
||||
DUPLICATE_ENTRY = 'DUPLICATE_ENTRY',
|
||||
|
||||
// External Service (502)
|
||||
EXTERNAL_API_ERROR = 'EXTERNAL_API_ERROR',
|
||||
DOFUSDB_ERROR = 'DOFUSDB_ERROR',
|
||||
|
||||
// Server (500)
|
||||
INTERNAL_ERROR = 'INTERNAL_ERROR',
|
||||
DATABASE_ERROR = 'DATABASE_ERROR',
|
||||
}
|
||||
|
||||
export interface AppErrorData {
|
||||
code: ErrorCode;
|
||||
message: string;
|
||||
details?: Record<string, unknown>;
|
||||
field?: string;
|
||||
}
|
||||
|
||||
export class AppError extends Error {
|
||||
public readonly code: ErrorCode;
|
||||
public readonly statusCode: number;
|
||||
public readonly details?: Record<string, unknown>;
|
||||
public readonly field?: string;
|
||||
public readonly isOperational: boolean;
|
||||
|
||||
constructor(data: AppErrorData & { statusCode?: number }) {
|
||||
super(data.message);
|
||||
this.name = 'AppError';
|
||||
this.code = data.code;
|
||||
this.statusCode = data.statusCode ?? this.getDefaultStatusCode(data.code);
|
||||
this.details = data.details;
|
||||
this.field = data.field;
|
||||
this.isOperational = true;
|
||||
|
||||
Error.captureStackTrace(this, this.constructor);
|
||||
}
|
||||
|
||||
private getDefaultStatusCode(code: ErrorCode): number {
|
||||
const statusMap: Record<ErrorCode, number> = {
|
||||
[ErrorCode.VALIDATION_ERROR]: 400,
|
||||
[ErrorCode.INVALID_INPUT]: 400,
|
||||
[ErrorCode.UNAUTHORIZED]: 401,
|
||||
[ErrorCode.SESSION_EXPIRED]: 401,
|
||||
[ErrorCode.FORBIDDEN]: 403,
|
||||
[ErrorCode.INSUFFICIENT_PERMISSIONS]: 403,
|
||||
[ErrorCode.NOT_FOUND]: 404,
|
||||
[ErrorCode.RESOURCE_NOT_FOUND]: 404,
|
||||
[ErrorCode.CONFLICT]: 409,
|
||||
[ErrorCode.DUPLICATE_ENTRY]: 409,
|
||||
[ErrorCode.EXTERNAL_API_ERROR]: 502,
|
||||
[ErrorCode.DOFUSDB_ERROR]: 502,
|
||||
[ErrorCode.INTERNAL_ERROR]: 500,
|
||||
[ErrorCode.DATABASE_ERROR]: 500,
|
||||
};
|
||||
return statusMap[code] ?? 500;
|
||||
}
|
||||
|
||||
toJSON(): AppErrorData & { statusCode: number } {
|
||||
return {
|
||||
code: this.code,
|
||||
message: this.message,
|
||||
statusCode: this.statusCode,
|
||||
details: this.details,
|
||||
field: this.field,
|
||||
};
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Backend Error Handler
|
||||
|
||||
```typescript
|
||||
// src/lib/server/error-handler.ts
|
||||
|
||||
import { Prisma } from '@prisma/client';
|
||||
import { AppError, ErrorCode } from '@/lib/errors';
|
||||
|
||||
export function handlePrismaError(error: unknown): AppError {
|
||||
if (error instanceof Prisma.PrismaClientKnownRequestError) {
|
||||
switch (error.code) {
|
||||
case 'P2002':
|
||||
return new AppError({
|
||||
code: ErrorCode.DUPLICATE_ENTRY,
|
||||
message: 'Cette entrée existe déjà',
|
||||
details: { fields: error.meta?.target },
|
||||
});
|
||||
case 'P2025':
|
||||
return new AppError({
|
||||
code: ErrorCode.NOT_FOUND,
|
||||
message: 'Ressource non trouvée',
|
||||
});
|
||||
default:
|
||||
return new AppError({
|
||||
code: ErrorCode.DATABASE_ERROR,
|
||||
message: 'Erreur de base de données',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return new AppError({
|
||||
code: ErrorCode.INTERNAL_ERROR,
|
||||
message: 'Une erreur inattendue est survenue',
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
## Frontend Error Handler
|
||||
|
||||
```typescript
|
||||
// src/lib/client/error-handler.ts
|
||||
|
||||
import { toast } from 'sonner';
|
||||
import { AppError, ErrorCode } from '@/lib/errors';
|
||||
|
||||
const errorMessages: Record<ErrorCode, string> = {
|
||||
[ErrorCode.VALIDATION_ERROR]: 'Données invalides',
|
||||
[ErrorCode.UNAUTHORIZED]: 'Veuillez vous connecter',
|
||||
[ErrorCode.NOT_FOUND]: 'Ressource non trouvée',
|
||||
[ErrorCode.DUPLICATE_ENTRY]: 'Cette entrée existe déjà',
|
||||
[ErrorCode.INTERNAL_ERROR]: 'Erreur serveur',
|
||||
// ... other codes
|
||||
};
|
||||
|
||||
export function handleError(error: unknown): void {
|
||||
if (error instanceof AppError) {
|
||||
const message = error.message || errorMessages[error.code];
|
||||
|
||||
if (error.statusCode >= 500) {
|
||||
toast.error('Erreur serveur', { description: message });
|
||||
} else {
|
||||
toast.warning(message);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
console.error('Unexpected error:', error);
|
||||
toast.error('Une erreur inattendue est survenue');
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
131
docs/architecture/19-monitoring-observability.md
Normal file
131
docs/architecture/19-monitoring-observability.md
Normal file
@@ -0,0 +1,131 @@
|
||||
# 19. Monitoring & Observability
|
||||
|
||||
## Structured Logging (Pino)
|
||||
|
||||
```typescript
|
||||
// src/lib/server/logger.ts
|
||||
|
||||
import pino from 'pino';
|
||||
|
||||
const isDev = process.env.NODE_ENV === 'development';
|
||||
|
||||
export const logger = pino({
|
||||
level: process.env.LOG_LEVEL ?? (isDev ? 'debug' : 'info'),
|
||||
|
||||
transport: isDev
|
||||
? {
|
||||
target: 'pino-pretty',
|
||||
options: {
|
||||
colorize: true,
|
||||
translateTime: 'HH:MM:ss',
|
||||
ignore: 'pid,hostname',
|
||||
},
|
||||
}
|
||||
: undefined,
|
||||
|
||||
formatters: {
|
||||
level: (label) => ({ level: label }),
|
||||
},
|
||||
|
||||
base: {
|
||||
env: process.env.NODE_ENV,
|
||||
version: process.env.APP_VERSION ?? '0.0.0',
|
||||
},
|
||||
|
||||
redact: {
|
||||
paths: ['password', 'token', 'authorization'],
|
||||
censor: '[REDACTED]',
|
||||
},
|
||||
});
|
||||
|
||||
export const dbLogger = logger.child({ module: 'database' });
|
||||
export const apiLogger = logger.child({ module: 'api' });
|
||||
```
|
||||
|
||||
## Health Check Endpoint
|
||||
|
||||
```typescript
|
||||
// src/server/functions/health.ts
|
||||
|
||||
import { createServerFn } from '@tanstack/react-start/server';
|
||||
import { db } from '@/lib/server/db';
|
||||
|
||||
interface HealthStatus {
|
||||
status: 'healthy' | 'degraded' | 'unhealthy';
|
||||
timestamp: string;
|
||||
version: string;
|
||||
checks: {
|
||||
database: boolean;
|
||||
cache: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
export const getHealth = createServerFn({ method: 'GET' }).handler(
|
||||
async (): Promise<HealthStatus> => {
|
||||
const checks = {
|
||||
database: false,
|
||||
cache: true,
|
||||
};
|
||||
|
||||
try {
|
||||
await db.$queryRaw`SELECT 1`;
|
||||
checks.database = true;
|
||||
} catch {
|
||||
// Database check failed
|
||||
}
|
||||
|
||||
const allHealthy = Object.values(checks).every(Boolean);
|
||||
|
||||
return {
|
||||
status: allHealthy ? 'healthy' : 'degraded',
|
||||
timestamp: new Date().toISOString(),
|
||||
version: process.env.APP_VERSION ?? '0.0.0',
|
||||
checks,
|
||||
};
|
||||
}
|
||||
);
|
||||
```
|
||||
|
||||
## Application Metrics
|
||||
|
||||
```typescript
|
||||
// src/lib/server/metrics.ts
|
||||
|
||||
class MetricsCollector {
|
||||
private startTime = Date.now();
|
||||
private data = {
|
||||
requests: { total: 0, errors: 0 },
|
||||
database: { queries: 0, slowQueries: 0 },
|
||||
cache: { hits: 0, misses: 0 },
|
||||
};
|
||||
|
||||
incrementRequest(isError = false): void {
|
||||
this.data.requests.total++;
|
||||
if (isError) this.data.requests.errors++;
|
||||
}
|
||||
|
||||
incrementDbQuery(isSlow = false): void {
|
||||
this.data.database.queries++;
|
||||
if (isSlow) this.data.database.slowQueries++;
|
||||
}
|
||||
|
||||
incrementCacheHit(): void {
|
||||
this.data.cache.hits++;
|
||||
}
|
||||
|
||||
incrementCacheMiss(): void {
|
||||
this.data.cache.misses++;
|
||||
}
|
||||
|
||||
getMetrics() {
|
||||
return {
|
||||
...this.data,
|
||||
uptime: Math.floor((Date.now() - this.startTime) / 1000),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export const metrics = new MetricsCollector();
|
||||
```
|
||||
|
||||
---
|
||||
66
docs/architecture/2-high-level-architecture.md
Normal file
66
docs/architecture/2-high-level-architecture.md
Normal file
@@ -0,0 +1,66 @@
|
||||
# 2. High-Level Architecture
|
||||
|
||||
## System Architecture Diagram
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────────┐
|
||||
│ DOFUS MANAGER │
|
||||
├─────────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ CLIENT (Browser) │ │
|
||||
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌────────────┐ │ │
|
||||
│ │ │ React │ │ TanStack │ │ TanStack │ │ Zustand │ │ │
|
||||
│ │ │ Components│ │ Router │ │ Query │ │ (UI State)│ │ │
|
||||
│ │ └─────────────┘ └─────────────┘ └─────────────┘ └────────────┘ │ │
|
||||
│ └─────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │ │
|
||||
│ │ Server Functions (RPC) │
|
||||
│ ▼ │
|
||||
│ ┌─────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ SERVER (TanStack Start) │ │
|
||||
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌────────────┐ │ │
|
||||
│ │ │ Server │ │ Zod │ │ Prisma │ │ node-cache│ │ │
|
||||
│ │ │ Functions │ │ Validation │ │ ORM │ │ (Cache) │ │ │
|
||||
│ │ └─────────────┘ └─────────────┘ └─────────────┘ └────────────┘ │ │
|
||||
│ └─────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ ┌─────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ DATABASE (PostgreSQL) │ │
|
||||
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌────────────┐ │ │
|
||||
│ │ │ Characters │ │ Accounts │ │ Teams │ │Progressions│ │ │
|
||||
│ │ └─────────────┘ └─────────────┘ └─────────────┘ └────────────┘ │ │
|
||||
│ └─────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ EXTERNAL SERVICES │ │
|
||||
│ │ ┌─────────────────────────────────────────────────────────────┐ │ │
|
||||
│ │ │ DofusDB API │ │ │
|
||||
│ │ │ (Classes, Quêtes, Donjons, Succès) │ │ │
|
||||
│ │ └─────────────────────────────────────────────────────────────┘ │ │
|
||||
│ └─────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Data Flow
|
||||
|
||||
```
|
||||
User Action → React Component → TanStack Query → Server Function → Prisma → PostgreSQL
|
||||
↑ │
|
||||
└───────────────────────── Response ────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Key Architectural Decisions
|
||||
|
||||
| Decision | Choice | Rationale |
|
||||
|----------|--------|-----------|
|
||||
| Full-stack Framework | TanStack Start | Type-safe, modern React, server functions |
|
||||
| Database | PostgreSQL | Robust, JSON support, full-text search |
|
||||
| ORM | Prisma | Type-safe queries, excellent DX |
|
||||
| State Management | TanStack Query + Zustand | Server state vs UI state separation |
|
||||
| Styling | Tailwind + shadcn/ui | Rapid development, consistent design |
|
||||
| Deployment | Docker + Traefik | Easy SSL, reverse proxy, scalable |
|
||||
|
||||
---
|
||||
46
docs/architecture/20-architecture-checklist.md
Normal file
46
docs/architecture/20-architecture-checklist.md
Normal file
@@ -0,0 +1,46 @@
|
||||
# 20. Architecture Checklist
|
||||
|
||||
| Category | Item | Status |
|
||||
|----------|------|--------|
|
||||
| **Core Architecture** | | |
|
||||
| | High-level architecture diagram | ✅ |
|
||||
| | Technology stack justified | ✅ |
|
||||
| | Data flow documented | ✅ |
|
||||
| | Scalability considered | ✅ |
|
||||
| **Data Layer** | | |
|
||||
| | Database schema defined | ✅ |
|
||||
| | Relationships documented | ✅ |
|
||||
| | Indexes identified | ✅ |
|
||||
| | Migration strategy | ✅ |
|
||||
| **API Design** | | |
|
||||
| | API contracts defined | ✅ |
|
||||
| | Input validation | ✅ |
|
||||
| | Error responses standardized | ✅ |
|
||||
| | Authentication/Authorization | ✅ |
|
||||
| **Frontend** | | |
|
||||
| | Component architecture | ✅ |
|
||||
| | State management | ✅ |
|
||||
| | Routing strategy | ✅ |
|
||||
| | Error boundaries | ✅ |
|
||||
| **Security** | | |
|
||||
| | Authentication flow | ✅ |
|
||||
| | Input sanitization | ✅ |
|
||||
| | CORS/CSP headers | ✅ |
|
||||
| | Secrets management | ✅ |
|
||||
| **Performance** | | |
|
||||
| | Caching strategy | ✅ |
|
||||
| | Database optimization | ✅ |
|
||||
| | Bundle optimization | ✅ |
|
||||
| | Loading states | ✅ |
|
||||
| **DevOps** | | |
|
||||
| | CI/CD pipeline | ✅ |
|
||||
| | Docker configuration | ✅ |
|
||||
| | Environment separation | ✅ |
|
||||
| | Deployment strategy | ✅ |
|
||||
| **Observability** | | |
|
||||
| | Logging strategy | ✅ |
|
||||
| | Health checks | ✅ |
|
||||
| | Metrics collection | ✅ |
|
||||
| | Error tracking | ✅ |
|
||||
|
||||
---
|
||||
52
docs/architecture/3-technology-stack.md
Normal file
52
docs/architecture/3-technology-stack.md
Normal file
@@ -0,0 +1,52 @@
|
||||
# 3. Technology Stack
|
||||
|
||||
## Frontend
|
||||
|
||||
| Technology | Version | Purpose |
|
||||
|------------|---------|---------|
|
||||
| React | 19.x | UI library |
|
||||
| TanStack Router | 1.x | Type-safe routing |
|
||||
| TanStack Query | 5.x | Server state management |
|
||||
| Zustand | 5.x | Client state management |
|
||||
| Tailwind CSS | 4.x | Utility-first styling |
|
||||
| shadcn/ui | latest | Component library |
|
||||
| Lucide React | latest | Icons |
|
||||
| React Hook Form | 7.x | Form management |
|
||||
| Zod | 3.x | Schema validation |
|
||||
|
||||
## Backend
|
||||
|
||||
| Technology | Version | Purpose |
|
||||
|------------|---------|---------|
|
||||
| TanStack Start | 1.x | Full-stack framework |
|
||||
| Prisma | 6.x | Database ORM |
|
||||
| Zod | 3.x | Input validation |
|
||||
| node-cache | 5.x | In-memory caching |
|
||||
| Pino | 9.x | Structured logging |
|
||||
| bcryptjs | 2.x | Password hashing |
|
||||
|
||||
## Database
|
||||
|
||||
| Technology | Version | Purpose |
|
||||
|------------|---------|---------|
|
||||
| PostgreSQL | 16.x | Primary database |
|
||||
|
||||
## DevOps
|
||||
|
||||
| Technology | Purpose |
|
||||
|------------|---------|
|
||||
| Docker | Containerization |
|
||||
| Docker Compose | Local development & deployment |
|
||||
| Traefik | Reverse proxy, SSL termination |
|
||||
| GitLab CI | CI/CD pipeline |
|
||||
|
||||
## Development Tools
|
||||
|
||||
| Tool | Purpose |
|
||||
|------|---------|
|
||||
| TypeScript | Type safety |
|
||||
| Biome | Linting & formatting |
|
||||
| Vitest | Unit testing |
|
||||
| Playwright | E2E testing |
|
||||
|
||||
---
|
||||
119
docs/architecture/4-data-models.md
Normal file
119
docs/architecture/4-data-models.md
Normal file
@@ -0,0 +1,119 @@
|
||||
# 4. Data Models
|
||||
|
||||
## Entity Relationship Diagram
|
||||
|
||||
```
|
||||
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
|
||||
│ User │ │ Account │ │ Character │
|
||||
├─────────────┤ ├─────────────┤ ├─────────────┤
|
||||
│ id │ │ id │ │ id │
|
||||
│ email │──┐ │ name │──┐ │ name │
|
||||
│ password │ │ │ userId ◄─┘ │ │ level │
|
||||
│ createdAt │ └───►│ createdAt │ └───►│ classId │
|
||||
│ updatedAt │ │ updatedAt │ │ serverId │
|
||||
└─────────────┘ └─────────────┘ │ accountId ◄─┘
|
||||
│ createdAt │
|
||||
│ updatedAt │
|
||||
└──────┬──────┘
|
||||
│
|
||||
┌────────────────────────────┼────────────────────────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
|
||||
│ Team │ │TeamMember │ │ CharProgress│
|
||||
├─────────────┤ ├─────────────┤ ├─────────────┤
|
||||
│ id │◄─────────────│ teamId │ │ id │
|
||||
│ name │ │ characterId │◄─────────────│ characterId │
|
||||
│ type │ │ joinedAt │ │ progressId │
|
||||
│ userId │ └─────────────┘ │ completed │
|
||||
│ createdAt │ │ completedAt │
|
||||
│ updatedAt │ └─────────────┘
|
||||
└─────────────┘ │
|
||||
│
|
||||
▼
|
||||
┌─────────────┐
|
||||
│ Progression │
|
||||
├─────────────┤
|
||||
│ id │
|
||||
│ name │
|
||||
│ type │
|
||||
│ category │
|
||||
│ dofusDbId │
|
||||
└─────────────┘
|
||||
```
|
||||
|
||||
## Core Entities
|
||||
|
||||
### User
|
||||
```typescript
|
||||
interface User {
|
||||
id: string;
|
||||
email: string;
|
||||
passwordHash: string;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
}
|
||||
```
|
||||
|
||||
### Account
|
||||
```typescript
|
||||
interface Account {
|
||||
id: string;
|
||||
name: string;
|
||||
userId: string;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
}
|
||||
```
|
||||
|
||||
### Character
|
||||
```typescript
|
||||
interface Character {
|
||||
id: string;
|
||||
name: string;
|
||||
level: number;
|
||||
classId: number;
|
||||
className: string;
|
||||
serverId: number;
|
||||
serverName: string;
|
||||
accountId: string;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
}
|
||||
```
|
||||
|
||||
### Team
|
||||
```typescript
|
||||
interface Team {
|
||||
id: string;
|
||||
name: string;
|
||||
type: 'MAIN' | 'SECONDARY' | 'CUSTOM';
|
||||
userId: string;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
}
|
||||
```
|
||||
|
||||
### Progression
|
||||
```typescript
|
||||
interface Progression {
|
||||
id: string;
|
||||
name: string;
|
||||
type: 'QUEST' | 'DUNGEON' | 'ACHIEVEMENT' | 'DOFUS';
|
||||
category: string;
|
||||
dofusDbId: number | null;
|
||||
}
|
||||
```
|
||||
|
||||
### CharacterProgression
|
||||
```typescript
|
||||
interface CharacterProgression {
|
||||
id: string;
|
||||
characterId: string;
|
||||
progressionId: string;
|
||||
completed: boolean;
|
||||
completedAt: Date | null;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
111
docs/architecture/5-api-specification.md
Normal file
111
docs/architecture/5-api-specification.md
Normal file
@@ -0,0 +1,111 @@
|
||||
# 5. API Specification
|
||||
|
||||
## Server Functions Pattern
|
||||
|
||||
TanStack Start utilise des "Server Functions" - des fonctions RPC type-safe qui s'exécutent côté serveur.
|
||||
|
||||
```typescript
|
||||
// Définition
|
||||
import { createServerFn } from '@tanstack/react-start/server';
|
||||
import { z } from 'zod';
|
||||
|
||||
const inputSchema = z.object({
|
||||
name: z.string().min(1),
|
||||
});
|
||||
|
||||
export const createCharacter = createServerFn({ method: 'POST' })
|
||||
.validator((data: unknown) => inputSchema.parse(data))
|
||||
.handler(async ({ data }) => {
|
||||
// Logique serveur avec accès DB
|
||||
return await db.character.create({ data });
|
||||
});
|
||||
|
||||
// Utilisation côté client
|
||||
const result = await createCharacter({ data: { name: 'MyChar' } });
|
||||
```
|
||||
|
||||
## API Endpoints (Server Functions)
|
||||
|
||||
### Characters
|
||||
|
||||
| Function | Method | Description |
|
||||
|----------|--------|-------------|
|
||||
| `getCharacters` | GET | Liste tous les personnages avec filtres |
|
||||
| `getCharacter` | GET | Récupère un personnage par ID |
|
||||
| `createCharacter` | POST | Crée un nouveau personnage |
|
||||
| `updateCharacter` | POST | Met à jour un personnage |
|
||||
| `deleteCharacter` | POST | Supprime un personnage |
|
||||
| `bulkUpdateCharacters` | POST | Met à jour plusieurs personnages |
|
||||
| `bulkDeleteCharacters` | POST | Supprime plusieurs personnages |
|
||||
|
||||
### Accounts
|
||||
|
||||
| Function | Method | Description |
|
||||
|----------|--------|-------------|
|
||||
| `getAccounts` | GET | Liste tous les comptes |
|
||||
| `getAccount` | GET | Récupère un compte par ID |
|
||||
| `createAccount` | POST | Crée un nouveau compte |
|
||||
| `updateAccount` | POST | Met à jour un compte |
|
||||
| `deleteAccount` | POST | Supprime un compte |
|
||||
|
||||
### Teams
|
||||
|
||||
| Function | Method | Description |
|
||||
|----------|--------|-------------|
|
||||
| `getTeams` | GET | Liste toutes les équipes |
|
||||
| `getTeam` | GET | Récupère une équipe avec ses membres |
|
||||
| `createTeam` | POST | Crée une nouvelle équipe |
|
||||
| `updateTeam` | POST | Met à jour une équipe |
|
||||
| `deleteTeam` | POST | Supprime une équipe |
|
||||
| `addTeamMembers` | POST | Ajoute des personnages à une équipe |
|
||||
| `removeTeamMembers` | POST | Retire des personnages d'une équipe |
|
||||
|
||||
### Progressions
|
||||
|
||||
| Function | Method | Description |
|
||||
|----------|--------|-------------|
|
||||
| `getProgressions` | GET | Liste toutes les progressions |
|
||||
| `getCharacterProgressions` | GET | Progressions d'un personnage |
|
||||
| `updateCharacterProgression` | POST | Met à jour une progression |
|
||||
| `bulkUpdateProgressions` | POST | Met à jour plusieurs progressions |
|
||||
| `syncFromDofusDb` | POST | Synchronise depuis DofusDB |
|
||||
|
||||
### Auth
|
||||
|
||||
| Function | Method | Description |
|
||||
|----------|--------|-------------|
|
||||
| `login` | POST | Authentification |
|
||||
| `logout` | POST | Déconnexion |
|
||||
| `getSession` | GET | Récupère la session courante |
|
||||
|
||||
## Validation Schemas
|
||||
|
||||
```typescript
|
||||
// src/lib/schemas/character.ts
|
||||
import { z } from 'zod';
|
||||
|
||||
export const createCharacterSchema = z.object({
|
||||
name: z.string().min(2).max(50),
|
||||
level: z.number().int().min(1).max(200),
|
||||
classId: z.number().int().positive(),
|
||||
serverId: z.number().int().positive(),
|
||||
accountId: z.string().uuid(),
|
||||
});
|
||||
|
||||
export const updateCharacterSchema = createCharacterSchema.partial();
|
||||
|
||||
export const characterFiltersSchema = z.object({
|
||||
search: z.string().optional(),
|
||||
classIds: z.array(z.number()).optional(),
|
||||
serverIds: z.array(z.number()).optional(),
|
||||
accountIds: z.array(z.string()).optional(),
|
||||
minLevel: z.number().optional(),
|
||||
maxLevel: z.number().optional(),
|
||||
page: z.number().int().positive().default(1),
|
||||
limit: z.number().int().min(1).max(100).default(20),
|
||||
sortBy: z.enum(['name', 'level', 'class', 'server']).default('name'),
|
||||
sortOrder: z.enum(['asc', 'desc']).default('asc'),
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
65
docs/architecture/6-components-architecture.md
Normal file
65
docs/architecture/6-components-architecture.md
Normal file
@@ -0,0 +1,65 @@
|
||||
# 6. Components Architecture
|
||||
|
||||
## Component Hierarchy
|
||||
|
||||
```
|
||||
src/components/
|
||||
├── ui/ # shadcn/ui primitives
|
||||
│ ├── button.tsx
|
||||
│ ├── input.tsx
|
||||
│ ├── dialog.tsx
|
||||
│ ├── table.tsx
|
||||
│ ├── select.tsx
|
||||
│ ├── checkbox.tsx
|
||||
│ ├── tabs.tsx
|
||||
│ ├── card.tsx
|
||||
│ ├── badge.tsx
|
||||
│ ├── progress.tsx
|
||||
│ └── ...
|
||||
│
|
||||
├── layout/ # Layout components
|
||||
│ ├── app-shell.tsx # Main layout wrapper
|
||||
│ ├── app-sidebar.tsx # Navigation sidebar
|
||||
│ └── app-header.tsx # Top header with breadcrumbs
|
||||
│
|
||||
├── characters/ # Character feature components
|
||||
│ ├── character-list.tsx
|
||||
│ ├── character-card.tsx
|
||||
│ ├── character-form.tsx
|
||||
│ ├── character-filters.tsx
|
||||
│ └── character-bulk-actions.tsx
|
||||
│
|
||||
├── accounts/ # Account feature components
|
||||
│ ├── account-list.tsx
|
||||
│ ├── account-card.tsx
|
||||
│ └── account-form.tsx
|
||||
│
|
||||
├── teams/ # Team feature components
|
||||
│ ├── team-list.tsx
|
||||
│ ├── team-detail.tsx
|
||||
│ ├── team-form.tsx
|
||||
│ └── team-member-selector.tsx
|
||||
│
|
||||
├── progressions/ # Progression feature components
|
||||
│ ├── progression-section.tsx
|
||||
│ ├── progression-tracker.tsx
|
||||
│ └── progression-filters.tsx
|
||||
│
|
||||
└── shared/ # Shared components
|
||||
├── data-table.tsx
|
||||
├── search-input.tsx
|
||||
├── pagination.tsx
|
||||
├── confirmation-modal.tsx
|
||||
├── loading-spinner.tsx
|
||||
└── error-boundary.tsx
|
||||
```
|
||||
|
||||
## Component Design Principles
|
||||
|
||||
1. **Composition over inheritance** - Prefer composing smaller components
|
||||
2. **Props interface first** - Define TypeScript interfaces for all props
|
||||
3. **Controlled components** - Parent manages state when needed
|
||||
4. **Accessible by default** - Use semantic HTML, ARIA attributes
|
||||
5. **Responsive design** - Mobile-first approach with Tailwind
|
||||
|
||||
---
|
||||
68
docs/architecture/7-external-apis.md
Normal file
68
docs/architecture/7-external-apis.md
Normal file
@@ -0,0 +1,68 @@
|
||||
# 7. External APIs
|
||||
|
||||
## DofusDB API Integration
|
||||
|
||||
**Base URL**: `https://api.dofusdb.fr`
|
||||
|
||||
### Endpoints Used
|
||||
|
||||
| Endpoint | Purpose |
|
||||
|----------|---------|
|
||||
| `GET /classes` | Liste des classes de personnages |
|
||||
| `GET /servers` | Liste des serveurs |
|
||||
| `GET /quests` | Liste des quêtes |
|
||||
| `GET /dungeons` | Liste des donjons |
|
||||
| `GET /achievements` | Liste des succès |
|
||||
|
||||
### Integration Service
|
||||
|
||||
```typescript
|
||||
// src/lib/server/dofusdb.ts
|
||||
import NodeCache from 'node-cache';
|
||||
|
||||
const cache = new NodeCache({ stdTTL: 3600 }); // 1 hour cache
|
||||
const BASE_URL = 'https://api.dofusdb.fr';
|
||||
|
||||
interface DofusDbOptions {
|
||||
lang?: 'fr' | 'en';
|
||||
limit?: number;
|
||||
}
|
||||
|
||||
export async function fetchFromDofusDb<T>(
|
||||
endpoint: string,
|
||||
options: DofusDbOptions = {}
|
||||
): Promise<T> {
|
||||
const { lang = 'fr', limit = 100 } = options;
|
||||
const cacheKey = `dofusdb:${endpoint}:${lang}:${limit}`;
|
||||
|
||||
// Check cache
|
||||
const cached = cache.get<T>(cacheKey);
|
||||
if (cached) return cached;
|
||||
|
||||
// Fetch from API
|
||||
const url = new URL(endpoint, BASE_URL);
|
||||
url.searchParams.set('$lang', lang);
|
||||
url.searchParams.set('$limit', limit.toString());
|
||||
|
||||
const response = await fetch(url.toString(), {
|
||||
headers: { 'Accept': 'application/json' },
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`DofusDB API error: ${response.status}`);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
cache.set(cacheKey, data);
|
||||
|
||||
return data as T;
|
||||
}
|
||||
|
||||
// Specific fetchers
|
||||
export const getClasses = () => fetchFromDofusDb<DofusClass[]>('/classes');
|
||||
export const getServers = () => fetchFromDofusDb<DofusServer[]>('/servers');
|
||||
export const getQuests = () => fetchFromDofusDb<DofusQuest[]>('/quests');
|
||||
export const getDungeons = () => fetchFromDofusDb<DofusDungeon[]>('/dungeons');
|
||||
```
|
||||
|
||||
---
|
||||
114
docs/architecture/8-core-workflows.md
Normal file
114
docs/architecture/8-core-workflows.md
Normal file
@@ -0,0 +1,114 @@
|
||||
# 8. Core Workflows
|
||||
|
||||
## Character Creation Flow
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ CHARACTER CREATION FLOW │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
|
||||
│ │ Click │───▶│ Open │───▶│ Fill │───▶│ Validate │ │
|
||||
│ │ "Add" │ │ Modal │ │ Form │ │ (Zod) │ │
|
||||
│ └──────────┘ └──────────┘ └──────────┘ └────┬─────┘ │
|
||||
│ │ │
|
||||
│ ┌──────────────┴───┐ │
|
||||
│ ▼ ▼ │
|
||||
│ ┌──────────┐ ┌──────────┐ │
|
||||
│ │ Valid │ │ Invalid │ │
|
||||
│ └────┬─────┘ └────┬─────┘ │
|
||||
│ │ │ │
|
||||
│ ▼ ▼ │
|
||||
│ ┌────────────┐ ┌────────────┐ │
|
||||
│ │ Server │ │ Show │ │
|
||||
│ │ Function │ │ Errors │ │
|
||||
│ └─────┬──────┘ └────────────┘ │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ ┌────────────┐ │
|
||||
│ │ Prisma │ │
|
||||
│ │ Create │ │
|
||||
│ └─────┬──────┘ │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ ┌────────────┐ │
|
||||
│ │ Invalidate │ │
|
||||
│ │ Query │ │
|
||||
│ └─────┬──────┘ │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ ┌────────────┐ │
|
||||
│ │ Toast │ │
|
||||
│ │ Success │ │
|
||||
│ └────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Progression Update Flow
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ PROGRESSION UPDATE FLOW │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌──────────────┐ │
|
||||
│ │ Toggle Check │ │
|
||||
│ └──────┬───────┘ │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
|
||||
│ │ Optimistic │────▶│ Server │────▶│ Database │ │
|
||||
│ │ Update │ │ Function │ │ Update │ │
|
||||
│ └──────────────┘ └──────────────┘ └──────┬───────┘ │
|
||||
│ │ │ │
|
||||
│ │ ┌──────────┴─────┐ │
|
||||
│ │ ▼ ▼ │
|
||||
│ │ ┌──────────┐ ┌──────────┐ │
|
||||
│ │ │ Success │ │ Error │ │
|
||||
│ │ └────┬─────┘ └────┬─────┘ │
|
||||
│ │ │ │ │
|
||||
│ │ ▼ ▼ │
|
||||
│ │ ┌──────────┐ ┌──────────┐ │
|
||||
│ └────────────────────▶│ Confirm │ │ Rollback │ │
|
||||
│ │ State │ │ + Toast │ │
|
||||
│ └──────────┘ └──────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Bulk Operations Flow
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ BULK OPERATIONS FLOW │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
|
||||
│ │ Select │───▶│ Choose │───▶│ Confirm │───▶│ Process │ │
|
||||
│ │ Items │ │ Action │ │ Modal │ │ Batch │ │
|
||||
│ └──────────┘ └──────────┘ └──────────┘ └────┬─────┘ │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ ┌────────────┐ │
|
||||
│ │ Loading │ │
|
||||
│ │ State │ │
|
||||
│ └─────┬──────┘ │
|
||||
│ │ │
|
||||
│ ┌─────────────┴────────┐ │
|
||||
│ ▼ ▼ │
|
||||
│ ┌────────────┐ ┌────────┐│
|
||||
│ │ Success │ │ Partial││
|
||||
│ │ Toast │ │ Failure││
|
||||
│ └─────┬──────┘ └───┬────┘│
|
||||
│ │ │ │
|
||||
│ ▼ ▼ │
|
||||
│ ┌────────────┐ ┌──────────┐ │
|
||||
│ │ Invalidate │ │ Show │ │
|
||||
│ │ Queries │ │ Errors │ │
|
||||
│ └────────────┘ └──────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
175
docs/architecture/9-database-schema.md
Normal file
175
docs/architecture/9-database-schema.md
Normal file
@@ -0,0 +1,175 @@
|
||||
# 9. Database Schema
|
||||
|
||||
## Prisma Schema
|
||||
|
||||
```prisma
|
||||
// prisma/schema.prisma
|
||||
|
||||
generator client {
|
||||
provider = "prisma-client-js"
|
||||
}
|
||||
|
||||
datasource db {
|
||||
provider = "postgresql"
|
||||
url = env("DATABASE_URL")
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// USER & AUTHENTICATION
|
||||
// ============================================
|
||||
|
||||
model User {
|
||||
id String @id @default(cuid())
|
||||
email String @unique
|
||||
passwordHash String @map("password_hash")
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
updatedAt DateTime @updatedAt @map("updated_at")
|
||||
|
||||
accounts Account[]
|
||||
teams Team[]
|
||||
sessions Session[]
|
||||
|
||||
@@map("users")
|
||||
}
|
||||
|
||||
model Session {
|
||||
id String @id @default(cuid())
|
||||
userId String @map("user_id")
|
||||
expiresAt DateTime @map("expires_at")
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@index([userId])
|
||||
@@index([expiresAt])
|
||||
@@map("sessions")
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// CORE ENTITIES
|
||||
// ============================================
|
||||
|
||||
model Account {
|
||||
id String @id @default(cuid())
|
||||
name String
|
||||
userId String @map("user_id")
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
updatedAt DateTime @updatedAt @map("updated_at")
|
||||
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
characters Character[]
|
||||
|
||||
@@unique([userId, name])
|
||||
@@index([userId])
|
||||
@@map("accounts")
|
||||
}
|
||||
|
||||
model Character {
|
||||
id String @id @default(cuid())
|
||||
name String
|
||||
level Int @default(1)
|
||||
classId Int @map("class_id")
|
||||
className String @map("class_name")
|
||||
serverId Int @map("server_id")
|
||||
serverName String @map("server_name")
|
||||
accountId String @map("account_id")
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
updatedAt DateTime @updatedAt @map("updated_at")
|
||||
|
||||
account Account @relation(fields: [accountId], references: [id], onDelete: Cascade)
|
||||
teamMembers TeamMember[]
|
||||
progressions CharacterProgression[]
|
||||
|
||||
@@unique([accountId, name])
|
||||
@@index([accountId])
|
||||
@@index([classId])
|
||||
@@index([serverId])
|
||||
@@index([level])
|
||||
@@map("characters")
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// TEAMS
|
||||
// ============================================
|
||||
|
||||
enum TeamType {
|
||||
MAIN
|
||||
SECONDARY
|
||||
CUSTOM
|
||||
}
|
||||
|
||||
model Team {
|
||||
id String @id @default(cuid())
|
||||
name String
|
||||
type TeamType @default(CUSTOM)
|
||||
userId String @map("user_id")
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
updatedAt DateTime @updatedAt @map("updated_at")
|
||||
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
members TeamMember[]
|
||||
|
||||
@@unique([userId, name])
|
||||
@@index([userId])
|
||||
@@map("teams")
|
||||
}
|
||||
|
||||
model TeamMember {
|
||||
id String @id @default(cuid())
|
||||
teamId String @map("team_id")
|
||||
characterId String @map("character_id")
|
||||
joinedAt DateTime @default(now()) @map("joined_at")
|
||||
|
||||
team Team @relation(fields: [teamId], references: [id], onDelete: Cascade)
|
||||
character Character @relation(fields: [characterId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@unique([teamId, characterId])
|
||||
@@index([teamId])
|
||||
@@index([characterId])
|
||||
@@map("team_members")
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// PROGRESSIONS
|
||||
// ============================================
|
||||
|
||||
enum ProgressionType {
|
||||
QUEST
|
||||
DUNGEON
|
||||
ACHIEVEMENT
|
||||
DOFUS
|
||||
}
|
||||
|
||||
model Progression {
|
||||
id String @id @default(cuid())
|
||||
name String
|
||||
type ProgressionType
|
||||
category String
|
||||
dofusDbId Int? @unique @map("dofusdb_id")
|
||||
|
||||
characterProgressions CharacterProgression[]
|
||||
|
||||
@@index([type])
|
||||
@@index([category])
|
||||
@@map("progressions")
|
||||
}
|
||||
|
||||
model CharacterProgression {
|
||||
id String @id @default(cuid())
|
||||
characterId String @map("character_id")
|
||||
progressionId String @map("progression_id")
|
||||
completed Boolean @default(false)
|
||||
completedAt DateTime? @map("completed_at")
|
||||
|
||||
character Character @relation(fields: [characterId], references: [id], onDelete: Cascade)
|
||||
progression Progression @relation(fields: [progressionId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@unique([characterId, progressionId])
|
||||
@@index([characterId])
|
||||
@@index([progressionId])
|
||||
@@index([completed])
|
||||
@@map("character_progressions")
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
36
docs/architecture/architecture-summary.md
Normal file
36
docs/architecture/architecture-summary.md
Normal file
@@ -0,0 +1,36 @@
|
||||
# Architecture Summary
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────┐
|
||||
│ DOFUS MANAGER - FINAL ARCHITECTURE │
|
||||
├─────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Frontend (React + TanStack) Backend (TanStack Start) │
|
||||
│ ┌─────────────────────────┐ ┌─────────────────────────┐ │
|
||||
│ │ • TanStack Router │ │ • Server Functions │ │
|
||||
│ │ • TanStack Query │◀────────▶│ • Prisma ORM │ │
|
||||
│ │ • Zustand (UI state) │ RPC │ • Zod Validation │ │
|
||||
│ │ • shadcn/ui + Tailwind │ │ • node-cache │ │
|
||||
│ └─────────────────────────┘ └───────────┬─────────────┘ │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ ┌─────────────────────────┐ │
|
||||
│ │ PostgreSQL 16 │ │
|
||||
│ │ • 7 tables │ │
|
||||
│ │ • Full-text search │ │
|
||||
│ └─────────────────────────┘ │
|
||||
│ │
|
||||
│ Infrastructure │
|
||||
│ ┌─────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ Docker Compose + Traefik (reverse proxy + SSL) │ │
|
||||
│ │ GitLab CI/CD → VPS Deployment │ │
|
||||
│ └─────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
*Document généré avec BMAD Framework*
|
||||
*Version: 1.0.0*
|
||||
*Date: 2026-01-18*
|
||||
113
docs/architecture/index.md
Normal file
113
docs/architecture/index.md
Normal file
@@ -0,0 +1,113 @@
|
||||
# Dofus Manager - Architecture Document
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [Dofus Manager - Architecture Document](#table-of-contents)
|
||||
- [Table of Contents](./table-of-contents.md)
|
||||
- [1. Introduction](./1-introduction.md)
|
||||
- [Project Overview](./1-introduction.md#project-overview)
|
||||
- [Goals](./1-introduction.md#goals)
|
||||
- [Scope](./1-introduction.md#scope)
|
||||
- [Non-Functional Requirements](./1-introduction.md#non-functional-requirements)
|
||||
- [2. High-Level Architecture](./2-high-level-architecture.md)
|
||||
- [System Architecture Diagram](./2-high-level-architecture.md#system-architecture-diagram)
|
||||
- [Data Flow](./2-high-level-architecture.md#data-flow)
|
||||
- [Key Architectural Decisions](./2-high-level-architecture.md#key-architectural-decisions)
|
||||
- [3. Technology Stack](./3-technology-stack.md)
|
||||
- [Frontend](./3-technology-stack.md#frontend)
|
||||
- [Backend](./3-technology-stack.md#backend)
|
||||
- [Database](./3-technology-stack.md#database)
|
||||
- [DevOps](./3-technology-stack.md#devops)
|
||||
- [Development Tools](./3-technology-stack.md#development-tools)
|
||||
- [4. Data Models](./4-data-models.md)
|
||||
- [Entity Relationship Diagram](./4-data-models.md#entity-relationship-diagram)
|
||||
- [Core Entities](./4-data-models.md#core-entities)
|
||||
- [User](./4-data-models.md#user)
|
||||
- [Account](./4-data-models.md#account)
|
||||
- [Character](./4-data-models.md#character)
|
||||
- [Team](./4-data-models.md#team)
|
||||
- [Progression](./4-data-models.md#progression)
|
||||
- [CharacterProgression](./4-data-models.md#characterprogression)
|
||||
- [5. API Specification](./5-api-specification.md)
|
||||
- [Server Functions Pattern](./5-api-specification.md#server-functions-pattern)
|
||||
- [API Endpoints (Server Functions)](./5-api-specification.md#api-endpoints-server-functions)
|
||||
- [Characters](./5-api-specification.md#characters)
|
||||
- [Accounts](./5-api-specification.md#accounts)
|
||||
- [Teams](./5-api-specification.md#teams)
|
||||
- [Progressions](./5-api-specification.md#progressions)
|
||||
- [Auth](./5-api-specification.md#auth)
|
||||
- [Validation Schemas](./5-api-specification.md#validation-schemas)
|
||||
- [6. Components Architecture](./6-components-architecture.md)
|
||||
- [Component Hierarchy](./6-components-architecture.md#component-hierarchy)
|
||||
- [Component Design Principles](./6-components-architecture.md#component-design-principles)
|
||||
- [7. External APIs](./7-external-apis.md)
|
||||
- [DofusDB API Integration](./7-external-apis.md#dofusdb-api-integration)
|
||||
- [Endpoints Used](./7-external-apis.md#endpoints-used)
|
||||
- [Integration Service](./7-external-apis.md#integration-service)
|
||||
- [8. Core Workflows](./8-core-workflows.md)
|
||||
- [Character Creation Flow](./8-core-workflows.md#character-creation-flow)
|
||||
- [Progression Update Flow](./8-core-workflows.md#progression-update-flow)
|
||||
- [Bulk Operations Flow](./8-core-workflows.md#bulk-operations-flow)
|
||||
- [9. Database Schema](./9-database-schema.md)
|
||||
- [Prisma Schema](./9-database-schema.md#prisma-schema)
|
||||
- [10. Frontend Architecture](./10-frontend-architecture.md)
|
||||
- [State Management Strategy](./10-frontend-architecture.md#state-management-strategy)
|
||||
- [TanStack Query Setup](./10-frontend-architecture.md#tanstack-query-setup)
|
||||
- [Zustand Store](./10-frontend-architecture.md#zustand-store)
|
||||
- [Routing Structure](./10-frontend-architecture.md#routing-structure)
|
||||
- [11. Backend Architecture](./11-backend-architecture.md)
|
||||
- [Server Functions Organization](./11-backend-architecture.md#server-functions-organization)
|
||||
- [Server Function Example](./11-backend-architecture.md#server-function-example)
|
||||
- [Authentication Middleware](./11-backend-architecture.md#authentication-middleware)
|
||||
- [Caching Strategy](./11-backend-architecture.md#caching-strategy)
|
||||
- [12. Project Structure](./12-project-structure.md)
|
||||
- [13. Development Workflow](./13-development-workflow.md)
|
||||
- [Local Development Setup](./13-development-workflow.md#local-development-setup)
|
||||
- [Environment Variables](./13-development-workflow.md#environment-variables)
|
||||
- [Git Workflow](./13-development-workflow.md#git-workflow)
|
||||
- [Branch Naming](./13-development-workflow.md#branch-naming)
|
||||
- [Commit Convention](./13-development-workflow.md#commit-convention)
|
||||
- [14. Deployment Architecture](./14-deployment-architecture.md)
|
||||
- [Docker Configuration](./14-deployment-architecture.md#docker-configuration)
|
||||
- [Docker Compose (Production)](./14-deployment-architecture.md#docker-compose-production)
|
||||
- [GitLab CI/CD Pipeline](./14-deployment-architecture.md#gitlab-cicd-pipeline)
|
||||
- [15. Security & Performance](./15-security-performance.md)
|
||||
- [Security Measures](./15-security-performance.md#security-measures)
|
||||
- [Authentication](./15-security-performance.md#authentication)
|
||||
- [Input Validation](./15-security-performance.md#input-validation)
|
||||
- [Headers (via Traefik)](./15-security-performance.md#headers-via-traefik)
|
||||
- [Performance Optimizations](./15-security-performance.md#performance-optimizations)
|
||||
- [Database](./15-security-performance.md#database)
|
||||
- [Caching](./15-security-performance.md#caching)
|
||||
- [Frontend](./15-security-performance.md#frontend)
|
||||
- [Bundle Optimization](./15-security-performance.md#bundle-optimization)
|
||||
- [16. Testing Strategy](./16-testing-strategy.md)
|
||||
- [Testing Pyramid](./16-testing-strategy.md#testing-pyramid)
|
||||
- [Unit Tests (Vitest)](./16-testing-strategy.md#unit-tests-vitest)
|
||||
- [Integration Tests](./16-testing-strategy.md#integration-tests)
|
||||
- [E2E Tests (Playwright)](./16-testing-strategy.md#e2e-tests-playwright)
|
||||
- [17. Coding Standards](./17-coding-standards.md)
|
||||
- [Critical Fullstack Rules](./17-coding-standards.md#critical-fullstack-rules)
|
||||
- [Naming Conventions](./17-coding-standards.md#naming-conventions)
|
||||
- [File Structure Conventions](./17-coding-standards.md#file-structure-conventions)
|
||||
- [Component File Structure](./17-coding-standards.md#component-file-structure)
|
||||
- [Server Function File Structure](./17-coding-standards.md#server-function-file-structure)
|
||||
- [Code Quality Rules](./17-coding-standards.md#code-quality-rules)
|
||||
- [TypeScript](./17-coding-standards.md#typescript)
|
||||
- [React](./17-coding-standards.md#react)
|
||||
- [Prisma](./17-coding-standards.md#prisma)
|
||||
- [Import Order](./17-coding-standards.md#import-order)
|
||||
- [ESLint & Prettier Config](./17-coding-standards.md#eslint-prettier-config)
|
||||
- [.eslintrc.cjs](./17-coding-standards.md#eslintrccjs)
|
||||
- [.prettierrc](./17-coding-standards.md#prettierrc)
|
||||
- [Git Commit Standards](./17-coding-standards.md#git-commit-standards)
|
||||
- [18. Error Handling](./18-error-handling.md)
|
||||
- [Unified Error Types](./18-error-handling.md#unified-error-types)
|
||||
- [Backend Error Handler](./18-error-handling.md#backend-error-handler)
|
||||
- [Frontend Error Handler](./18-error-handling.md#frontend-error-handler)
|
||||
- [19. Monitoring & Observability](./19-monitoring-observability.md)
|
||||
- [Structured Logging (Pino)](./19-monitoring-observability.md#structured-logging-pino)
|
||||
- [Health Check Endpoint](./19-monitoring-observability.md#health-check-endpoint)
|
||||
- [Application Metrics](./19-monitoring-observability.md#application-metrics)
|
||||
- [20. Architecture Checklist](./20-architecture-checklist.md)
|
||||
- [Architecture Summary](./architecture-summary.md)
|
||||
24
docs/architecture/table-of-contents.md
Normal file
24
docs/architecture/table-of-contents.md
Normal file
@@ -0,0 +1,24 @@
|
||||
# Table of Contents
|
||||
|
||||
1. [Introduction](#1-introduction)
|
||||
2. [High-Level Architecture](#2-high-level-architecture)
|
||||
3. [Technology Stack](#3-technology-stack)
|
||||
4. [Data Models](#4-data-models)
|
||||
5. [API Specification](#5-api-specification)
|
||||
6. [Components Architecture](#6-components-architecture)
|
||||
7. [External APIs](#7-external-apis)
|
||||
8. [Core Workflows](#8-core-workflows)
|
||||
9. [Database Schema](#9-database-schema)
|
||||
10. [Frontend Architecture](#10-frontend-architecture)
|
||||
11. [Backend Architecture](#11-backend-architecture)
|
||||
12. [Project Structure](#12-project-structure)
|
||||
13. [Development Workflow](#13-development-workflow)
|
||||
14. [Deployment Architecture](#14-deployment-architecture)
|
||||
15. [Security & Performance](#15-security--performance)
|
||||
16. [Testing Strategy](#16-testing-strategy)
|
||||
17. [Coding Standards](#17-coding-standards)
|
||||
18. [Error Handling](#18-error-handling)
|
||||
19. [Monitoring & Observability](#19-monitoring--observability)
|
||||
20. [Architecture Checklist](#20-architecture-checklist)
|
||||
|
||||
---
|
||||
367
docs/brainstorming-session-results.md
Normal file
367
docs/brainstorming-session-results.md
Normal file
@@ -0,0 +1,367 @@
|
||||
# Brainstorming Session Results
|
||||
|
||||
**Session Date:** 2026-01-17
|
||||
**Facilitator:** Business Analyst Mary
|
||||
**Participant:** Theo
|
||||
|
||||
---
|
||||
|
||||
## Executive Summary
|
||||
|
||||
**Topic:** Création d'un site web de gestion de comptes et personnages pour le MMORPG Dofus
|
||||
|
||||
**Session Goals:** Idéation ciblée sur le développement produit — remplacer un tableur complexe (60+ personnages, dizaines de comptes) par une application web moderne et fonctionnelle.
|
||||
|
||||
**Techniques Used:**
|
||||
- First Principles Thinking
|
||||
- Mind Mapping
|
||||
- SCAMPER (Substitute, Combine, Adapt, Modify, Put to other uses, Eliminate)
|
||||
|
||||
**Total Ideas Generated:** 25+
|
||||
|
||||
### Key Themes Identified:
|
||||
- La gestion multi-comptes avec contrainte de non-simultanéité est un besoin fondamental
|
||||
- Le filtrage et la recherche multicritères sont essentiels pour 60+ personnages
|
||||
- Les actions groupées (bulk update) réduiront drastiquement le temps de maintenance
|
||||
- L'intégration avec DofusDB éliminera la saisie manuelle des données de référence
|
||||
- L'outil doit évoluer d'un simple tracker vers un assistant de jeu complet
|
||||
|
||||
---
|
||||
|
||||
## Technique Sessions
|
||||
|
||||
### First Principles Thinking
|
||||
|
||||
**Description:** Identification des problèmes fondamentaux que le tableur actuel résout mal, en partant des besoins réels de l'utilisateur.
|
||||
|
||||
#### Problèmes identifiés:
|
||||
|
||||
1. **Vue d'ensemble impossible** — 60+ personnages en colonnes horizontales ne tiennent pas à l'écran
|
||||
2. **Modifications fragiles** — Risque de tout casser, heures perdues à réparer le formatage
|
||||
3. **Contraintes non gérées** — La règle "pas 2 persos du même compte simultanément" est gérée mentalement
|
||||
4. **Pas de filtrage** — Parcours visuel fastidieux pour trouver "qui n'a pas fait X"
|
||||
5. **Manque de dynamisme** — Données statiques, pas de synchronisation, pas de totaux automatiques
|
||||
|
||||
#### Cas d'usage principaux:
|
||||
|
||||
1. Voir quels personnages sont sur quels comptes
|
||||
2. Ajouter un nouveau personnage monté
|
||||
3. Voir sur quels persos/teams un Dofus n'est pas fait
|
||||
4. Mettre à jour les recherchés faits
|
||||
5. Voir et gérer les monnaies (Doplons, Orichor, Kamas de glace...)
|
||||
6. Composer des teams valides (contrainte compte)
|
||||
7. Planifier les "run kamas brut" (multi-persos même compte pour maximiser kamas)
|
||||
|
||||
#### Insights Discovered:
|
||||
- Les teams sont généralement fixes (team principale de 8, teams succès Panda/Enu/Elio/Iop)
|
||||
- Mais parfois composition dynamique nécessaire (ex: 3 Cra + 5 mules pour PL)
|
||||
- L'outil sert à planifier les sessions de jeu ET à vérifier en temps réel pendant le jeu
|
||||
|
||||
#### Notable Connections:
|
||||
- Le système de récompenses Dofus est complexe : ressources/Dofus = 1x par compte, mais kamas = par perso
|
||||
- Les métiers sont maintenant liés au compte+serveur, pas au personnage
|
||||
- Le bonus XP par compte favorise la stratégie "run kamas brut"
|
||||
|
||||
---
|
||||
|
||||
### Mind Mapping
|
||||
|
||||
**Description:** Cartographie des entités, relations et fonctionnalités de l'application.
|
||||
|
||||
#### Modèle de données identifié:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────┐
|
||||
│ COMPTE │
|
||||
│ - Nom │
|
||||
│ - Ogrines (par compte) │
|
||||
│ - Récompenses succès débloquées (Dofus, ressources = 1x/compte) │
|
||||
└─────────────────────┬───────────────────────────────────────────────┘
|
||||
│
|
||||
┌─────────────┴─────────────┐
|
||||
│ │
|
||||
▼ ▼
|
||||
┌───────────────────┐ ┌─────────────────────────┐
|
||||
│ COMPTE + SERVEUR │ │ PERSONNAGE │
|
||||
│ - Métiers (niv.) │ │ - Pseudo │
|
||||
│ - Bonus XP perso │ │ - Classe │
|
||||
│ le plus haut │ │ - Niveau │
|
||||
└───────────────────┘ │ - Serveur │
|
||||
│ - Monnaies │
|
||||
│ - Progression quêtes │
|
||||
│ - Recherchés faits │
|
||||
│ - Donjons (tous succès) │
|
||||
└───────────┬─────────────┘
|
||||
│ N:M
|
||||
┌──────▼──────┐
|
||||
│ TEAM │
|
||||
│ - Nom │
|
||||
│ - Type │
|
||||
│ - Membres[] │
|
||||
└─────────────┘
|
||||
```
|
||||
|
||||
#### Modules fonctionnels:
|
||||
|
||||
1. **Comptes** — Liste, CRUD, ogrines, récompenses succès
|
||||
2. **Personnages** — Liste, filtres, CRUD, monnaies, progression
|
||||
3. **Teams** — Créer, valider contraintes comptes, statut global
|
||||
4. **Objectifs** — Définir, arborescence quêtes, % progression
|
||||
5. **Progression** — Quêtes Dofus, donjons (tous types succès), recherchés
|
||||
6. **Recherche & Filtres** — Multicritères, par team, par compte, "qui n'a pas fait"
|
||||
7. **Données API** — DofusDB pour import quêtes/succès/donjons
|
||||
8. **Analytics** — Kamas brut potentiel, stats par compte, tendances
|
||||
|
||||
---
|
||||
|
||||
### SCAMPER Analysis
|
||||
|
||||
#### S — Substitute (Substituer)
|
||||
|
||||
| Avant (Tableur) | Après (App) |
|
||||
|-----------------|-------------|
|
||||
| Colonnes par personnage | Fiches individuelles avec vue détaillée |
|
||||
| "x" manuels | Checkboxes avec date auto + bulk update |
|
||||
| Navigation horizontale infinie | Filtres + recherche + pagination |
|
||||
| Copier-coller pour nouveau perso | Formulaire de création guidé |
|
||||
|
||||
**Retenu:** Checkboxes intelligentes avec bulk update — le plus impactant pour réduire le temps de maintenance.
|
||||
|
||||
#### C — Combine (Combiner)
|
||||
|
||||
1. ✅ **Team + Progression** → Vue "Statut de ma team" avec % completion
|
||||
2. ✅ **Recherche + Action** → Résultats filtrés directement actionnables
|
||||
3. ✅ **Objectif + Notification** → Alertes "Il te reste X pour finir ton objectif"
|
||||
4. ✅ **Import API + Validation** → DofusDB comme source de vérité
|
||||
|
||||
#### A — Adapt (Adapter)
|
||||
|
||||
1. ❌ Kanban (non retenu)
|
||||
2. ✅ **Filtres façon e-commerce** → Sidebar avec facettes cliquables
|
||||
3. ✅ **Dashboards analytics** → Widgets personnalisables
|
||||
4. ✅ **Multi-select façon Gmail** → Sélection + actions groupées
|
||||
|
||||
#### M — Modify (Modifier/Amplifier)
|
||||
|
||||
1. ❌ Highlighting des manques (non retenu)
|
||||
2. ✅ **Réduire les clics** → Raccourcis clavier, actions au survol
|
||||
3. ✅ **Amplifier vue compte** → Page dédiée avec tous persos + stats
|
||||
4. ✅ **Simplifier monnaies** → Total agrégé avec drill-down
|
||||
|
||||
#### P — Put to other uses (Autres usages)
|
||||
|
||||
1. ✅ **Planificateur de session** → "J'ai 2h, que faire ?" avec suggestions
|
||||
2. ✅ **Partage guilde/amis** → Export/lien pour coordination
|
||||
3. ✅ **Journal d'activité** → Timeline, stats hebdo/mensuelles
|
||||
4. ✅ **Calculateur rentabilité** → ROI kamas brut par perso
|
||||
|
||||
#### E — Eliminate (Éliminer)
|
||||
|
||||
1. ✅ **Saisie manuelle quêtes/donjons** → Tout depuis DofusDB
|
||||
2. ✅ **Doublons de données** → 1 perso = 1 entité unique
|
||||
3. ✅ **Navigation profonde** → 2 clics max depuis dashboard
|
||||
4. ✅ **Exhaustivité obligatoire** → Tracking opt-in par catégorie
|
||||
|
||||
#### R — Reverse (Inverser)
|
||||
|
||||
- Non retenu — le modèle mental actuel (perso → compte → team) reste pertinent
|
||||
|
||||
---
|
||||
|
||||
## Idea Categorization
|
||||
|
||||
### Immediate Opportunities
|
||||
*Ideas ready to implement now (MVP)*
|
||||
|
||||
1. **Gestion CRUD Comptes/Personnages/Teams**
|
||||
- Description: Créer, lire, modifier, supprimer les entités principales
|
||||
- Why immediate: Fondation de l'application
|
||||
- Resources needed: PostgreSQL schema, API routes, formulaires React
|
||||
|
||||
2. **Filtres multicritères**
|
||||
- Description: Filtrer par classe, team, compte, niveau, statut progression
|
||||
- Why immediate: Résout le problème principal de "vue d'ensemble impossible"
|
||||
- Resources needed: UI filtres sidebar, logique de requêtes
|
||||
|
||||
3. **Checkboxes + Bulk Update**
|
||||
- Description: Cocher fait/pas fait avec date auto, actions groupées par team
|
||||
- Why immediate: Résout le problème de "modifications fragiles"
|
||||
- Resources needed: UI checkboxes, bulk actions API
|
||||
|
||||
4. **Vue statut team avec % completion**
|
||||
- Description: Tableau croisé team × succès avec pourcentage d'avancement
|
||||
- Why immediate: Cas d'usage fréquent "quelle team a pas fait X"
|
||||
- Resources needed: Calculs agrégés, composant tableau
|
||||
|
||||
5. **Validation contrainte compte**
|
||||
- Description: Empêcher 2 persos du même compte dans une team active
|
||||
- Why immediate: Règle métier fondamentale du jeu
|
||||
- Resources needed: Logique de validation, feedback UI
|
||||
|
||||
6. **Monnaies par perso + total**
|
||||
- Description: Tracker les monnaies, afficher total agrégé
|
||||
- Why immediate: Besoin exprimé, données déjà dans le tableur
|
||||
- Resources needed: Champs monnaies, widget total
|
||||
|
||||
7. **Intégration DofusDB**
|
||||
- Description: Import des données de référence (quêtes, donjons, succès)
|
||||
- Why immediate: Élimine la saisie manuelle, réduit les erreurs
|
||||
- Resources needed: Client API DofusDB, sync initiale
|
||||
|
||||
### Future Innovations
|
||||
*Ideas requiring development/research*
|
||||
|
||||
1. **Dashboard avec widgets**
|
||||
- Description: Vue d'accueil personnalisable avec KPIs
|
||||
- Development needed: Système de widgets drag & drop
|
||||
- Timeline estimate: V2
|
||||
|
||||
2. **Objectifs + alertes progression**
|
||||
- Description: Définir des objectifs, recevoir notifications
|
||||
- Development needed: Système de notifications, tracking objectifs
|
||||
- Timeline estimate: V2
|
||||
|
||||
3. **Raccourcis clavier**
|
||||
- Description: Navigation et actions rapides au clavier
|
||||
- Development needed: Hook keyboard, documentation raccourcis
|
||||
- Timeline estimate: V2
|
||||
|
||||
4. **Arborescence quêtes Dofus**
|
||||
- Description: Visualisation des dépendances de quêtes (style n1ark.com)
|
||||
- Development needed: Parser DofusDB pour dépendances, UI graphe
|
||||
- Timeline estimate: V3
|
||||
|
||||
5. **Planificateur de session**
|
||||
- Description: "J'ai 2h" → suggestions basées sur objectifs/rentabilité
|
||||
- Development needed: Algorithme de priorisation, UI planning
|
||||
- Timeline estimate: V3
|
||||
|
||||
### Moonshots
|
||||
*Ambitious, transformative concepts*
|
||||
|
||||
1. **Partage guilde/amis**
|
||||
- Description: Liens publics ou export pour coordination multi-joueurs
|
||||
- Transformative potential: Transformer l'outil solo en outil communautaire
|
||||
- Challenges to overcome: Authentification, permissions, vie privée
|
||||
|
||||
2. **Journal d'activité**
|
||||
- Description: Timeline des actions, statistiques temporelles
|
||||
- Transformative potential: Visualiser sa progression sur le long terme
|
||||
- Challenges to overcome: Volume de données, performance, rétention
|
||||
|
||||
3. **Calculateur rentabilité kamas brut**
|
||||
- Description: ROI par perso (XP investi vs kamas potentiels)
|
||||
- Transformative potential: Optimisation stratégique du temps de jeu
|
||||
- Challenges to overcome: Données de kamas par quête, formules complexes
|
||||
|
||||
### Insights & Learnings
|
||||
*Key realizations from the session*
|
||||
|
||||
- **Contrainte compte = règle métier centrale**: Toute l'application doit être consciente qu'on ne peut pas jouer 2 persos du même compte simultanément
|
||||
- **Récompenses 1x/compte vs N/perso**: Le système de récompenses Dofus a une dualité importante à modéliser
|
||||
- **Run kamas brut = méta actuelle**: L'application doit supporter cette stratégie de jeu populaire
|
||||
- **Métiers = compte+serveur maintenant**: Changement récent du jeu à prendre en compte dans le modèle
|
||||
- **Teams fixes + composition dynamique**: Les deux modes coexistent
|
||||
|
||||
---
|
||||
|
||||
## Action Planning
|
||||
|
||||
### Top 3 Priority Ideas
|
||||
|
||||
#### #1 Priority: CRUD + Modèle de données robuste
|
||||
|
||||
- **Rationale:** Fondation de toute l'application, impossible d'avancer sans
|
||||
- **Next steps:**
|
||||
1. Définir le schéma PostgreSQL complet
|
||||
2. Créer les migrations
|
||||
3. Implémenter les API routes CRUD
|
||||
4. Créer les formulaires React
|
||||
- **Resources needed:** PostgreSQL, Drizzle/Prisma, TanStack Start
|
||||
- **Timeline:** Premier sprint
|
||||
|
||||
#### #2 Priority: Filtres multicritères + Vue liste
|
||||
|
||||
- **Rationale:** Résout le problème #1 (vue d'ensemble impossible)
|
||||
- **Next steps:**
|
||||
1. Concevoir l'UI des filtres (sidebar facettes)
|
||||
2. Implémenter la logique de filtrage côté serveur
|
||||
3. Créer le composant liste avec pagination
|
||||
4. Ajouter les filtres rapides (classe, team, compte)
|
||||
- **Resources needed:** TanStack Table, composants UI
|
||||
- **Timeline:** Deuxième sprint
|
||||
|
||||
#### #3 Priority: Intégration DofusDB
|
||||
|
||||
- **Rationale:** Élimine la saisie manuelle, source de vérité pour les données de jeu
|
||||
- **Next steps:**
|
||||
1. Explorer l'API DofusDB, documenter les endpoints utiles
|
||||
2. Créer un client API TypeScript
|
||||
3. Script d'import initial (quêtes, donjons, succès, recherchés)
|
||||
4. Synchronisation périodique
|
||||
- **Resources needed:** Documentation API DofusDB, cron jobs
|
||||
- **Timeline:** En parallèle des sprints 1-2
|
||||
|
||||
---
|
||||
|
||||
## Reflection & Follow-up
|
||||
|
||||
### What Worked Well
|
||||
- First Principles pour identifier les vrais problèmes vs les symptômes
|
||||
- SCAMPER pour générer des améliorations concrètes vs le tableur
|
||||
- Analyse du fichier existant pour comprendre la structure de données réelle
|
||||
- Focus sur l'idéation produit plutôt qu'exploration technique
|
||||
|
||||
### Areas for Further Exploration
|
||||
- **API DofusDB**: Explorer les endpoints disponibles, limites, authentification
|
||||
- **Arborescence quêtes**: Étudier comment n1ark.com structure les dépendances
|
||||
- **UX mobile/tablette**: L'outil sera-t-il utilisé sur second écran pendant le jeu ?
|
||||
- **Import données existantes**: Comment migrer le tableur actuel vers l'app ?
|
||||
|
||||
### Recommended Follow-up Techniques
|
||||
- **User Story Mapping**: Pour détailler les parcours utilisateur du MVP
|
||||
- **Event Storming**: Pour modéliser les événements métier (perso créé, succès validé, etc.)
|
||||
- **Wireframing**: Pour valider l'UX avant développement
|
||||
|
||||
### Questions That Emerged
|
||||
- Faut-il un système d'authentification ou l'app reste-t-elle mono-utilisateur ?
|
||||
- Comment gérer les mises à jour du jeu (nouveaux donjons, quêtes) ?
|
||||
- Faut-il supporter plusieurs serveurs Dofus ou juste Agride ?
|
||||
- Comment importer les données du tableur existant ?
|
||||
|
||||
### Next Session Planning
|
||||
- **Suggested topics:** Architecture technique détaillée, schéma de base de données, wireframes UI
|
||||
- **Recommended timeframe:** Avant de commencer le développement
|
||||
- **Preparation needed:** Explorer l'API DofusDB, lister toutes les entités à tracker
|
||||
|
||||
---
|
||||
|
||||
## Technical Stack
|
||||
|
||||
| Composant | Technologie |
|
||||
|-----------|-------------|
|
||||
| Frontend | React + TanStack Start |
|
||||
| Backend | TanStack Start (full-stack) |
|
||||
| Base de données | PostgreSQL |
|
||||
| Conteneurisation | Docker |
|
||||
| Hébergement | Serveur dédié personnel |
|
||||
| API externe | DofusDB |
|
||||
|
||||
---
|
||||
|
||||
## Appendix: Données du tableur analysé
|
||||
|
||||
Le tableur source contient:
|
||||
- **60+ personnages** sur plusieurs dizaines de comptes
|
||||
- **Serveur principal**: Agride
|
||||
- **Classes représentées**: Cra, Enutrof, Eliotrope, Iop, Pandawa, Sadida, Eniripsa, Huppermage, Steamer, Zobal, Feca, Roublard, Ouginak, Sacrieur, Sram, Xelor, Osamodas
|
||||
- **Niveaux**: Tous niveau 200
|
||||
- **Quêtes Dofus trackées**: Turquoise, Pourpre, Émeraude, Des Glaces, Abyssal, Nébuleux, Domakuro, Dorigami, Tacheté, Vulbis
|
||||
- **Donjons trackés**: Par paliers (1-50, 51-100, 101-150, 151-190, 191-200) avec succès variés
|
||||
- **Monnaies**: Doplons, Almatons, Pages calendrier, Orichor, Kamas de glace, Perles des profondeurs, Alitons, Trukdivins
|
||||
- **Recherchés**: Par région (Astrub, Château d'Amakna, Saharach, Frigost I/II/III, Enutrosor, Srambad, Xélorium, etc.)
|
||||
- **Teams identifiées**: Main Team (8 persos), Songe, PL, Team succès, Team succes vierge
|
||||
|
||||
---
|
||||
|
||||
*Session facilitated using the BMAD-METHOD brainstorming framework*
|
||||
596
docs/front-end-spec.md
Normal file
596
docs/front-end-spec.md
Normal file
@@ -0,0 +1,596 @@
|
||||
# Dofus Manager UI/UX Specification
|
||||
|
||||
## Introduction
|
||||
|
||||
Ce document définit les objectifs d'expérience utilisateur, l'architecture de l'information, les flux utilisateur et les spécifications de design visuel pour l'interface de **Dofus Manager**. Il sert de fondation pour le design visuel et le développement frontend, assurant une expérience cohérente et centrée sur l'utilisateur.
|
||||
|
||||
---
|
||||
|
||||
## Overall UX Goals & Principles
|
||||
|
||||
### Target User Persona
|
||||
|
||||
**Theo - Le Multi-Compteur Organisé**
|
||||
|
||||
| Attribut | Description |
|
||||
|----------|-------------|
|
||||
| **Profil** | Joueur passionné de Dofus gérant 60+ personnages niveau 200 |
|
||||
| **Contexte d'usage** | Joue sur PC avec souvent un second écran pour consulter ses données |
|
||||
| **Frustrations actuelles** | Tableur Excel illisible, modifications fragiles, contraintes de compte gérées mentalement |
|
||||
| **Objectifs** | Trouver rapidement qui n'a pas fait quoi, composer des teams valides, mettre à jour efficacement |
|
||||
| **Expertise technique** | À l'aise avec les outils complexes, préfère la densité d'info à la simplicité |
|
||||
| **Fréquence d'usage** | Quotidien pendant les sessions de jeu + planification hebdomadaire |
|
||||
|
||||
### Usability Goals
|
||||
|
||||
1. **Efficacité de navigation** — Trouver n'importe quelle information en moins de 3 clics depuis le dashboard
|
||||
2. **Mises à jour rapides** — Pouvoir mettre à jour la progression d'une team entière en moins de 30 secondes
|
||||
3. **Prévention d'erreurs** — Impossible d'ajouter 2 personnages du même compte dans une team active
|
||||
4. **Vue d'ensemble immédiate** — Voir l'état global (teams, progressions, monnaies) en un coup d'œil
|
||||
5. **Mémorabilité** — Interface cohérente permettant de retrouver ses repères après plusieurs jours d'absence
|
||||
|
||||
### Design Principles
|
||||
|
||||
1. **Densité maîtrisée** — Maximiser l'information visible sans surcharger visuellement. Utiliser la hiérarchie typographique et les espaces blancs stratégiquement.
|
||||
|
||||
2. **Consistance des patterns** — Tous les tableaux se comportent de la même façon (tri, filtres, pagination). Toutes les actions CRUD suivent le même flow.
|
||||
|
||||
3. **Feedback immédiat** — Chaque action utilisateur génère une réponse visuelle instantanée (loading states, toasts, transitions).
|
||||
|
||||
4. **Raccourcis pour experts** — Permettre les bulk actions, raccourcis clavier (V2), et filtres combinés pour les utilisateurs avancés.
|
||||
|
||||
5. **Fail-safe par design** — Les actions destructives demandent confirmation. Les contraintes métier sont validées avant même que l'utilisateur ne puisse les violer.
|
||||
|
||||
### Change Log
|
||||
|
||||
| Date | Version | Description | Author |
|
||||
|------|---------|-------------|--------|
|
||||
| 2026-01-17 | 0.1 | Création initiale | Sally (UX Expert) |
|
||||
|
||||
---
|
||||
|
||||
## Information Architecture (IA)
|
||||
|
||||
### Site Map / Screen Inventory
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A[🏠 Dashboard<br/>Vue d'ensemble principale] --> B[👥 Personnages]
|
||||
A --> C[📁 Comptes]
|
||||
A --> D[⚔️ Teams]
|
||||
A --> E[⚙️ Paramètres]
|
||||
|
||||
A --> A1[Widget Comptes]
|
||||
A --> A2[Widget Personnages]
|
||||
A --> A3[Widget Teams]
|
||||
A --> A4[Widget Monnaies]
|
||||
A --> A5[Actions rapides]
|
||||
|
||||
B --> B1[Liste Personnages]
|
||||
B1 --> B2[Fiche Personnage]
|
||||
B2 --> B2a[Progressions]
|
||||
B2 --> B2b[Monnaies]
|
||||
B2 --> B2c[Teams]
|
||||
|
||||
C --> C1[Liste Comptes]
|
||||
C1 --> C2[Fiche Compte]
|
||||
C2 --> C2a[Personnages du compte]
|
||||
C2 --> C2b[Métiers]
|
||||
C2 --> C2c[Récompenses]
|
||||
|
||||
D --> D1[Liste Teams]
|
||||
D1 --> D2[Fiche Team]
|
||||
D2 --> D2a[Membres]
|
||||
D2 --> D2b[Statut Progressions]
|
||||
|
||||
E --> E1[Serveurs]
|
||||
E --> E2[Monnaies]
|
||||
E --> E3[Données DofusDB]
|
||||
|
||||
B1 --> F[🔄 Bulk Actions]
|
||||
F --> F1[Bulk Progressions]
|
||||
F --> F2[Bulk Monnaies]
|
||||
```
|
||||
|
||||
### Navigation Structure
|
||||
|
||||
**Primary Navigation (Sidebar)**
|
||||
|
||||
| Icône | Label | Route | Description |
|
||||
|-------|-------|-------|-------------|
|
||||
| 🏠 | Dashboard | `/` | Vue d'ensemble, KPIs, accès rapide |
|
||||
| 👥 | Personnages | `/characters` | Liste principale avec filtres |
|
||||
| 📁 | Comptes | `/accounts` | Gestion des comptes Dofus |
|
||||
| ⚔️ | Teams | `/teams` | Composition et statut des teams |
|
||||
| ⚙️ | Paramètres | `/settings` | Configuration (serveurs, monnaies, sync) |
|
||||
|
||||
**Secondary Navigation (Contextuelle)**
|
||||
|
||||
- **Onglets sur fiches détail** : Personnage → [Infos | Progressions | Monnaies | Teams]
|
||||
- **Sous-menu Paramètres** : [Serveurs | Monnaies | Données DofusDB]
|
||||
- **Actions groupées** : Accessible depuis la toolbar des listes (quand sélection active)
|
||||
|
||||
**Breadcrumb Strategy**
|
||||
|
||||
Format : `Section > Sous-section > Élément`
|
||||
|
||||
Exemples :
|
||||
- `Personnages > Krosmaster-Cra`
|
||||
- `Teams > Main Team > Statut Progressions`
|
||||
- `Paramètres > Données DofusDB`
|
||||
|
||||
**Dashboard Content**
|
||||
|
||||
| Widget | Contenu | Action au clic |
|
||||
|--------|---------|----------------|
|
||||
| **Comptes** | Liste des comptes avec nb persos, ogrines | → Fiche compte |
|
||||
| **Personnages** | Total, répartition par classe/niveau | → Liste filtrée |
|
||||
| **Teams** | Teams actives avec % complétion | → Fiche team |
|
||||
| **Monnaies** | Totaux globaux par type | → Détail par compte |
|
||||
| **Progressions** | Résumé global (X% Dofus faits, Y donjons) | → Bulk actions |
|
||||
| **Actions rapides** | Boutons : Nouveau perso, Bulk update, Sync DofusDB | → Action directe |
|
||||
|
||||
---
|
||||
|
||||
## User Flows
|
||||
|
||||
### Flow 1: Trouver les personnages qui n'ont pas fait X
|
||||
|
||||
**User Goal:** Identifier rapidement quels personnages n'ont pas complété une progression spécifique
|
||||
|
||||
**Entry Points:** Dashboard → Widget Progressions, Sidebar → Personnages, Fiche Team
|
||||
|
||||
**Success Criteria:** Liste filtrée affichée en < 3 clics, < 5 secondes
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A[Dashboard] --> B[Clic Personnages]
|
||||
B --> C[Liste avec Filtres]
|
||||
C --> D[Ouvrir filtre Progression]
|
||||
D --> E[Sélectionner type]
|
||||
E --> F[Sélectionner N'a pas fait]
|
||||
F --> G[✅ Liste filtrée affichée]
|
||||
|
||||
G --> H{Action suivante?}
|
||||
H --> I[Voir fiche perso]
|
||||
H --> J[Sélectionner plusieurs]
|
||||
J --> K[Bulk Update]
|
||||
```
|
||||
|
||||
**Edge Cases:**
|
||||
- Aucun résultat → Message "Tous les personnages ont complété X" avec bouton reset
|
||||
- Filtres combinés complexes → Indicateur des filtres actifs + "Clear all"
|
||||
|
||||
### Flow 2: Composer une team valide
|
||||
|
||||
**User Goal:** Créer ou modifier une team en respectant la contrainte compte
|
||||
|
||||
**Success Criteria:** Team créée avec membres valides, erreur claire si conflit
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A[Liste Teams] --> B[Nouvelle Team]
|
||||
B --> C[Modal création]
|
||||
C --> D[Saisir nom + type]
|
||||
D --> E[Enregistrer]
|
||||
E --> F[Fiche Team vide]
|
||||
|
||||
F --> G[Ajouter membre]
|
||||
G --> H[Sélecteur personnages]
|
||||
H --> I[Sélectionner perso]
|
||||
|
||||
I --> K{Même compte dans team?}
|
||||
K -->|Non| L[✅ Membre ajouté]
|
||||
K -->|Oui| M[❌ Erreur conflit]
|
||||
M --> H
|
||||
|
||||
L --> O{Continuer?}
|
||||
O -->|Oui| G
|
||||
O -->|Non| P[✅ Team complète]
|
||||
```
|
||||
|
||||
### Flow 3: Bulk update progressions pour une team
|
||||
|
||||
**User Goal:** Marquer une progression faite pour tous les membres d'une team
|
||||
|
||||
**Success Criteria:** Mise à jour de N personnages en < 30 secondes
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A[Fiche Team] --> B[Section Statut Progressions]
|
||||
B --> C[Sélectionner progression]
|
||||
C --> D[Voir statut par membre]
|
||||
D --> E{Tous faits?}
|
||||
E -->|Non| G[Bouton Marquer fait pour tous]
|
||||
|
||||
G --> H[Modal confirmation]
|
||||
H --> I[Récap: X persos à mettre à jour]
|
||||
I --> J{Confirmer?}
|
||||
J -->|Oui| K[Processing...]
|
||||
K --> L[✅ Toast: X persos mis à jour]
|
||||
L --> M[Refresh → 100%]
|
||||
```
|
||||
|
||||
### Flow 4: Ajouter un nouveau personnage
|
||||
|
||||
**User Goal:** Créer un personnage avec toutes ses informations
|
||||
|
||||
**Success Criteria:** Personnage créé et visible en < 1 minute
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A[Liste Personnages] --> B[Clic Ajouter]
|
||||
B --> C[Modal création]
|
||||
C --> D[Saisir pseudo]
|
||||
D --> E[Sélectionner classe]
|
||||
E --> F[Saisir niveau]
|
||||
F --> G[Sélectionner serveur]
|
||||
G --> H[Sélectionner compte]
|
||||
H --> I{Validation}
|
||||
I -->|OK| J[Enregistrer]
|
||||
J --> K[✅ Toast confirmation]
|
||||
K --> L[Liste rafraîchie]
|
||||
```
|
||||
|
||||
### Flow 5: Consulter le Dashboard
|
||||
|
||||
**User Goal:** Vue d'ensemble instantanée de tous les comptes et personnages
|
||||
|
||||
**Success Criteria:** Toutes les informations clés visibles sans scroll sur desktop
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A[Accès Dashboard] --> B[Chargement widgets]
|
||||
B --> C[Affichage simultané]
|
||||
|
||||
C --> D[Widget Comptes]
|
||||
C --> E[Widget Personnages]
|
||||
C --> F[Widget Teams]
|
||||
C --> G[Widget Monnaies]
|
||||
C --> H[Widget Progressions]
|
||||
|
||||
D --> I[Clic → Liste comptes]
|
||||
E --> J[Clic → Liste personnages]
|
||||
F --> K[Clic → Liste teams]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Wireframes & Mockups
|
||||
|
||||
### Screen 1: Dashboard
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────────┐
|
||||
│ ☰ DOFUS MANAGER [🌙 Dark Mode] │
|
||||
├────────────┬────────────────────────────────────────────────────────────────┤
|
||||
│ │ │
|
||||
│ 🏠 Dashboard│ DASHBOARD [+ Nouveau ▾] │
|
||||
│ │ ───────────────────────────────────────────────────────────── │
|
||||
│ 👥 Persos │ │
|
||||
│ │ ┌─────────────────┐ ┌─────────────────┐ ┌────────────────┐ │
|
||||
│ 📁 Comptes│ │ 📁 COMPTES │ │ 👥 PERSONNAGES │ │ ⚔️ TEAMS │ │
|
||||
│ │ │ 12 comptes │ │ 64 personnages │ │ 3 actives │ │
|
||||
│ ⚔️ Teams │ │ 45,230 ogrines │ │ Niv. moy: 198 │ │ 87% complete │ │
|
||||
│ │ │ [Voir tout →] │ │ [Voir tout →] │ │ [Voir tout →] │ │
|
||||
│ ─────────│ └─────────────────┘ └─────────────────┘ └────────────────┘ │
|
||||
│ ⚙️ Settings│ │
|
||||
│ │ ┌─────────────────────────────────┐ ┌──────────────────────┐ │
|
||||
│ │ │ 💰 MONNAIES │ │ 📊 PROGRESSIONS │ │
|
||||
│ │ │ Doplons 12,450 │ │ Dofus ████░ 72% │ │
|
||||
│ │ │ Orichor 3,200 │ │ Donjons ██░░░ 45% │ │
|
||||
│ │ │ Kamas glace 8,100 │ │ Recherchés███░░ 61% │ │
|
||||
│ │ │ [Détail par compte →] │ │ [Bulk Update →] │ │
|
||||
│ │ └─────────────────────────────────┘ └──────────────────────┘ │
|
||||
│ │ │
|
||||
│ │ ┌─────────────────────────────────────────────────────────┐ │
|
||||
│ │ │ ⚡ ACTIONS RAPIDES │ │
|
||||
│ │ │ [+ Personnage] [+ Team] [Bulk Progressions] [Sync] │ │
|
||||
│ │ └─────────────────────────────────────────────────────────┘ │
|
||||
└────────────┴────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Screen 2: Liste Personnages
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────────┐
|
||||
│ ☰ DOFUS MANAGER [🌙] │
|
||||
├────────────┬────────────────────────────────────────────────────────────────┤
|
||||
│ │ PERSONNAGES 🔍 [Rechercher... ] │
|
||||
│ 🏠 Dashboard│ ───────────────────────────────────────────────────────────── │
|
||||
│ ►👥 Persos │ │
|
||||
│ │ ┌──────────────┐ ┌──────────────────────────────────────────┐│
|
||||
│ 📁 Comptes│ │ FILTRES │ │ ☑ Sélection: 3 [Bulk Actions ▾] ││
|
||||
│ │ │ │ │ ─────────────────────────────────────── ││
|
||||
│ ⚔️ Teams │ │ ▼ Classe │ │ ☐ │ Nom │Classe│Niv│Serveur│Cpt││
|
||||
│ │ │ ☑ Cra 12 │ │ ──┼──────────────┼──────┼───┼───────┼───││
|
||||
│ ─────────│ │ ☑ Iop 8 │ │ ☑ │ Krosmaster │ Cra │200│Imagiro│C1 ││
|
||||
│ ⚙️ Settings│ │ ☐ Enu 6 │ │ ☐ │ TankMaster │ Iop │200│Imagiro│C1 ││
|
||||
│ │ │ │ │ ☑ │ MoneyMaker │ Enu │200│Imagiro│C2 ││
|
||||
│ │ │ ▼ Serveur │ │ ☐ │ HealBot │ Eni │200│Imagiro│C2 ││
|
||||
│ │ │ ☑ Imagiro │ │ ☑ │ PortalGuy │ Elio │200│Imagiro│C3 ││
|
||||
│ │ │ │ │ ─────────────────────────────────────── ││
|
||||
│ │ │ ▼ Progression│ │ Showing 1-20 of 64 [< 1 2 3 4 >] ││
|
||||
│ │ │ Type: [──▾] │ └──────────────────────────────────────────┘│
|
||||
│ │ │ ○ A fait │ │
|
||||
│ │ │ ○ N'a pas │ [+ Ajouter Personnage] │
|
||||
│ │ │ [Réinitialiser]│ │
|
||||
│ │ └──────────────┘ │
|
||||
└────────────┴────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Screen 3: Fiche Personnage
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────────┐
|
||||
│ ☰ DOFUS MANAGER [🌙] │
|
||||
├────────────┬────────────────────────────────────────────────────────────────┤
|
||||
│ │ ← Personnages / Krosmaster [✏️] [🗑️] │
|
||||
│ 🏠 Dashboard│ ───────────────────────────────────────────────────────────── │
|
||||
│ 👥 Persos │ │
|
||||
│ │ ┌─────────────────────────────────────────────────────────┐ │
|
||||
│ 📁 Comptes│ │ [Avatar] KROSMASTER │ │
|
||||
│ │ │ Classe: Cra Niveau: 200 │ │
|
||||
│ ⚔️ Teams │ │ Serveur: Imagiro Compte: Compte1 │ │
|
||||
│ │ │ Teams: Main Team, Team Succès │ │
|
||||
│ ─────────│ └─────────────────────────────────────────────────────────┘ │
|
||||
│ ⚙️ Settings│ │
|
||||
│ │ ┌─────────────────────────────────────────────────────────┐ │
|
||||
│ │ │ [Infos] [Progressions] [Monnaies] [Teams] │ │
|
||||
│ │ ├─────────────────────────────────────────────────────────┤ │
|
||||
│ │ │ PROGRESSIONS Filtre: [Tous ▾] │ │
|
||||
│ │ │ │ │
|
||||
│ │ │ ▼ Quêtes Dofus (7/10) │ │
|
||||
│ │ │ ☑ Dofus Turquoise ✓ 2026-01-10 │ │
|
||||
│ │ │ ☑ Dofus Pourpre ✓ 2026-01-08 │ │
|
||||
│ │ │ ☐ Dofus des Glaces │ │
|
||||
│ │ │ │ │
|
||||
│ │ │ ▼ Donjons 191-200 (12/18) │ │
|
||||
│ │ │ ☑ Bethel ✓ 2026-01-15 │ │
|
||||
│ │ │ ☐ Tal Kasha │ │
|
||||
│ │ └─────────────────────────────────────────────────────────┘ │
|
||||
└────────────┴────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Screen 4: Fiche Team
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────────┐
|
||||
│ ☰ DOFUS MANAGER [🌙] │
|
||||
├────────────┬────────────────────────────────────────────────────────────────┤
|
||||
│ │ ← Teams / Main Team [✏️] [🗑️] │
|
||||
│ 🏠 Dashboard│ │
|
||||
│ 👥 Persos │ ┌────────────────────────────────────────────────────────┐ │
|
||||
│ │ │ MAIN TEAM Type: Main │ │
|
||||
│ 📁 Comptes│ │ 8 membres • ✅ Active • 8 comptes différents │ │
|
||||
│ │ └────────────────────────────────────────────────────────┘ │
|
||||
│ ⚔️ Teams │ │
|
||||
│ │ ┌────────────────────────────────────────────────────────┐ │
|
||||
│ ─────────│ │ [Membres] [Statut Progressions] │ │
|
||||
│ ⚙️ Settings│ ├────────────────────────────────────────────────────────┤ │
|
||||
│ │ │ STATUT PROGRESSIONS │ │
|
||||
│ │ │ │ │
|
||||
│ │ │ Progression: [Dofus Turquoise ▾] │ │
|
||||
│ │ │ │ │
|
||||
│ │ │ ████████████████████░░░░ 75% (6/8) [Marquer tous] │ │
|
||||
│ │ │ │ │
|
||||
│ │ │ │ Perso │ Statut │ Date │ │ │
|
||||
│ │ │ │ Krosmaster │ ✅ │ 2026-01-10 │ │ │
|
||||
│ │ │ │ TankMaster │ ✅ │ 2026-01-10 │ │ │
|
||||
│ │ │ │ HealBot │ ❌ │ — │ │ │
|
||||
│ │ │ │ SramKiller │ ❌ │ — │ │ │
|
||||
│ │ └────────────────────────────────────────────────────────┘ │
|
||||
└────────────┴────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Component Library / Design System
|
||||
|
||||
**Design System:** shadcn/ui (composants copiés, personnalisables)
|
||||
|
||||
### Core Components
|
||||
|
||||
| Component | Purpose | Variants | States |
|
||||
|-----------|---------|----------|--------|
|
||||
| **DataTable** | Listes avec tri, filtres, pagination | default, selectable, compact | loading, empty, error, filtered |
|
||||
| **FilterSidebar** | Panel de filtres multicritères | default, collapsible, modal | default, active, loading |
|
||||
| **StatCard** | Widget Dashboard KPI | default, progress, compact | loading, default, hover |
|
||||
| **EntityCard** | Header fiches détail | character, account, team | default, editing |
|
||||
| **ProgressionCheckbox** | Toggle fait/pas fait | default, with-date, bulk | unchecked, checked, loading, disabled |
|
||||
| **BulkActionBar** | Actions sur sélection multiple | floating, inline | hidden, visible, processing |
|
||||
| **Modal** | Dialogues création/édition/confirmation | form, confirm, selector | default, loading, error |
|
||||
| **Toast** | Notifications feedback | success, error, warning, info | entering, visible, exiting |
|
||||
| **Tabs** | Navigation sous-sections | default, pills, underline | default, active, disabled |
|
||||
| **EmptyState** | Affichage liste vide | no-data, no-results, error | — |
|
||||
|
||||
---
|
||||
|
||||
## Branding & Style Guide
|
||||
|
||||
### Color Palette
|
||||
|
||||
#### Dark Mode (Principal)
|
||||
|
||||
| Color Type | Hex Code | Usage |
|
||||
|------------|----------|-------|
|
||||
| **Background** | `#0F172A` | Fond principal (slate-900) |
|
||||
| **Foreground** | `#F8FAFC` | Texte principal |
|
||||
| **Card** | `#1E293B` | Fond cartes (slate-800) |
|
||||
| **Primary** | `#60A5FA` | Actions principales (blue-400) |
|
||||
| **Secondary** | `#94A3B8` | Texte secondaire (slate-400) |
|
||||
| **Accent** | `#A78BFA` | Highlights (violet-400) |
|
||||
| **Border** | `#475569` | Bordures (slate-600) |
|
||||
|
||||
#### Semantic Colors
|
||||
|
||||
| Color Type | Hex | Usage |
|
||||
|------------|-----|-------|
|
||||
| **Success** | `#4ADE80` | Confirmations, complété |
|
||||
| **Warning** | `#FBBF24` | Alertes |
|
||||
| **Error** | `#F87171` | Erreurs |
|
||||
| **Info** | `#60A5FA` | Informations |
|
||||
|
||||
### Typography
|
||||
|
||||
| Element | Size | Weight | Line Height |
|
||||
|---------|------|--------|-------------|
|
||||
| **H1** | 32px | 700 | 1.2 |
|
||||
| **H2** | 24px | 600 | 1.3 |
|
||||
| **H3** | 20px | 600 | 1.4 |
|
||||
| **Body** | 14px | 400 | 1.5 |
|
||||
| **Small** | 12px | 400 | 1.4 |
|
||||
|
||||
**Font:** Inter (system-ui fallback)
|
||||
|
||||
### Iconography
|
||||
|
||||
**Library:** Lucide Icons
|
||||
|
||||
| Context | Size |
|
||||
|---------|------|
|
||||
| Navigation | 20px |
|
||||
| Buttons | 16px |
|
||||
| Inline | 14px |
|
||||
|
||||
### Spacing Scale (base 4px)
|
||||
|
||||
| Token | Value |
|
||||
|-------|-------|
|
||||
| `space-1` | 4px |
|
||||
| `space-2` | 8px |
|
||||
| `space-3` | 12px |
|
||||
| `space-4` | 16px |
|
||||
| `space-6` | 24px |
|
||||
| `space-8` | 32px |
|
||||
|
||||
### Layout Constants
|
||||
|
||||
| Element | Value |
|
||||
|---------|-------|
|
||||
| Sidebar width | 240px (collapsed: 64px) |
|
||||
| Max content width | 1280px |
|
||||
| Border radius | 8px (cards), 6px (buttons) |
|
||||
|
||||
---
|
||||
|
||||
## Accessibility Requirements
|
||||
|
||||
**Standard:** Pas de conformité WCAG formelle (app personnelle)
|
||||
|
||||
**Approche pragmatique :** Bonnes pratiques "gratuites" via shadcn/ui
|
||||
|
||||
### Key Requirements
|
||||
|
||||
| Category | Requirement |
|
||||
|----------|-------------|
|
||||
| **Visual** | Contraste 4.5:1, focus visible, états sans couleur seule |
|
||||
| **Interaction** | Navigation clavier, focus trap modals, touch targets 44px |
|
||||
| **Content** | Labels formulaires, messages d'erreur associés, structure headings |
|
||||
|
||||
---
|
||||
|
||||
## Responsiveness Strategy
|
||||
|
||||
### Breakpoints
|
||||
|
||||
| Breakpoint | Min Width | Target |
|
||||
|------------|-----------|--------|
|
||||
| **sm** (Mobile) | 0 | Smartphones |
|
||||
| **md** (Tablet) | 640px | Tablettes |
|
||||
| **lg** (Desktop) | 1024px | Laptops |
|
||||
| **xl** (Wide) | 1280px | Grands moniteurs |
|
||||
|
||||
### Adaptation Patterns
|
||||
|
||||
| Element | Desktop | Tablet | Mobile |
|
||||
|---------|---------|--------|--------|
|
||||
| **Sidebar** | Expanded | Collapsed (icons) | Burger menu |
|
||||
| **Dashboard** | 3 colonnes | 2 colonnes | 1 colonne |
|
||||
| **DataTable** | Full | Colonnes prioritaires | Cards |
|
||||
| **Modals** | Centré 500px | 90vw | Plein écran |
|
||||
| **Filtres** | Sidebar | Sidebar mini | Modal |
|
||||
|
||||
---
|
||||
|
||||
## Animation & Micro-interactions
|
||||
|
||||
### Motion Principles
|
||||
|
||||
1. **Fonctionnel avant décoratif**
|
||||
2. **Rapide et non-bloquant** (150-300ms)
|
||||
3. **Subtil et cohérent**
|
||||
4. **Respect prefers-reduced-motion**
|
||||
|
||||
### Key Animations
|
||||
|
||||
| Animation | Durée | Usage |
|
||||
|-----------|-------|-------|
|
||||
| Hover | 150ms | Buttons, rows |
|
||||
| Fade in | 200ms | Contenu chargé |
|
||||
| Slide in | 250ms | Modals, drawers |
|
||||
| Toast | 300ms in / 200ms out | Notifications |
|
||||
| Checkbox | 150ms | Toggle état |
|
||||
|
||||
### Performance Goals
|
||||
|
||||
| Metric | Target |
|
||||
|--------|--------|
|
||||
| First Contentful Paint | < 1.5s |
|
||||
| Time to Interactive | < 3s |
|
||||
| Interaction Response | < 100ms |
|
||||
| Animation FPS | 60fps |
|
||||
|
||||
---
|
||||
|
||||
## Next Steps
|
||||
|
||||
### Immediate Actions
|
||||
|
||||
1. Générer les maquettes haute-fidélité (v0, Lovable, ou Figma)
|
||||
2. Setup le projet avec shadcn/ui et configurer le thème
|
||||
3. Implémenter le Layout principal (sidebar + header)
|
||||
4. Développer le Dashboard avec widgets mockés
|
||||
|
||||
### Design Handoff Checklist
|
||||
|
||||
- [x] All user flows documented
|
||||
- [x] Component inventory complete
|
||||
- [x] Accessibility requirements defined
|
||||
- [x] Responsive strategy clear
|
||||
- [x] Brand guidelines incorporated
|
||||
- [x] Performance goals established
|
||||
|
||||
### Prompt v0.dev (Dashboard)
|
||||
|
||||
```
|
||||
Create a dark mode dashboard for a Dofus MMORPG character management app called "Dofus Manager".
|
||||
|
||||
Layout:
|
||||
- Left sidebar (240px) with navigation: Dashboard (active), Characters, Accounts, Teams, Settings
|
||||
- Main content area with widgets grid
|
||||
|
||||
Widgets (3 columns on desktop):
|
||||
1. "Comptes" card: showing "12 comptes" and "45,230 ogrines" with folder icon
|
||||
2. "Personnages" card: showing "64 personnages" and "Niv. moy: 198" with users icon
|
||||
3. "Teams" card: showing "3 actives" and "87% complete" with swords icon
|
||||
4. "Monnaies" card (spans 2 cols): list of currencies with amounts
|
||||
5. "Progressions" card: progress bars for Dofus, Donjons, Recherchés
|
||||
6. "Actions rapides" section: buttons for + Personnage, + Team, Bulk Progressions, Sync
|
||||
|
||||
Style: shadcn/ui, dark slate background (#0F172A), blue primary (#60A5FA), Inter font 14px
|
||||
```
|
||||
|
||||
### Prompt v0.dev (Liste Personnages)
|
||||
|
||||
```
|
||||
Create a character list page for "Dofus Manager" with filters sidebar.
|
||||
|
||||
Layout:
|
||||
- Left filter sidebar (250px): Classe checkboxes, Serveur checkboxes, Progression filter
|
||||
- Main data table: checkbox, Nom, Classe, Niveau, Serveur, Compte columns
|
||||
- Top bar: search input, bulk actions when selected, + Ajouter button
|
||||
- Pagination at bottom
|
||||
|
||||
Style: Dark mode, shadcn/ui, dense table rows (48px height), hover shows edit/delete icons
|
||||
```
|
||||
15
docs/front-end-spec/accessibility-requirements.md
Normal file
15
docs/front-end-spec/accessibility-requirements.md
Normal file
@@ -0,0 +1,15 @@
|
||||
# Accessibility Requirements
|
||||
|
||||
**Standard:** Pas de conformité WCAG formelle (app personnelle)
|
||||
|
||||
**Approche pragmatique :** Bonnes pratiques "gratuites" via shadcn/ui
|
||||
|
||||
## Key Requirements
|
||||
|
||||
| Category | Requirement |
|
||||
|----------|-------------|
|
||||
| **Visual** | Contraste 4.5:1, focus visible, états sans couleur seule |
|
||||
| **Interaction** | Navigation clavier, focus trap modals, touch targets 44px |
|
||||
| **Content** | Labels formulaires, messages d'erreur associés, structure headings |
|
||||
|
||||
---
|
||||
29
docs/front-end-spec/animation-micro-interactions.md
Normal file
29
docs/front-end-spec/animation-micro-interactions.md
Normal file
@@ -0,0 +1,29 @@
|
||||
# Animation & Micro-interactions
|
||||
|
||||
## Motion Principles
|
||||
|
||||
1. **Fonctionnel avant décoratif**
|
||||
2. **Rapide et non-bloquant** (150-300ms)
|
||||
3. **Subtil et cohérent**
|
||||
4. **Respect prefers-reduced-motion**
|
||||
|
||||
## Key Animations
|
||||
|
||||
| Animation | Durée | Usage |
|
||||
|-----------|-------|-------|
|
||||
| Hover | 150ms | Buttons, rows |
|
||||
| Fade in | 200ms | Contenu chargé |
|
||||
| Slide in | 250ms | Modals, drawers |
|
||||
| Toast | 300ms in / 200ms out | Notifications |
|
||||
| Checkbox | 150ms | Toggle état |
|
||||
|
||||
## Performance Goals
|
||||
|
||||
| Metric | Target |
|
||||
|--------|--------|
|
||||
| First Contentful Paint | < 1.5s |
|
||||
| Time to Interactive | < 3s |
|
||||
| Interaction Response | < 100ms |
|
||||
| Animation FPS | 60fps |
|
||||
|
||||
---
|
||||
67
docs/front-end-spec/branding-style-guide.md
Normal file
67
docs/front-end-spec/branding-style-guide.md
Normal file
@@ -0,0 +1,67 @@
|
||||
# Branding & Style Guide
|
||||
|
||||
## Color Palette
|
||||
|
||||
### Dark Mode (Principal)
|
||||
|
||||
| Color Type | Hex Code | Usage |
|
||||
|------------|----------|-------|
|
||||
| **Background** | `#0F172A` | Fond principal (slate-900) |
|
||||
| **Foreground** | `#F8FAFC` | Texte principal |
|
||||
| **Card** | `#1E293B` | Fond cartes (slate-800) |
|
||||
| **Primary** | `#60A5FA` | Actions principales (blue-400) |
|
||||
| **Secondary** | `#94A3B8` | Texte secondaire (slate-400) |
|
||||
| **Accent** | `#A78BFA` | Highlights (violet-400) |
|
||||
| **Border** | `#475569` | Bordures (slate-600) |
|
||||
|
||||
### Semantic Colors
|
||||
|
||||
| Color Type | Hex | Usage |
|
||||
|------------|-----|-------|
|
||||
| **Success** | `#4ADE80` | Confirmations, complété |
|
||||
| **Warning** | `#FBBF24` | Alertes |
|
||||
| **Error** | `#F87171` | Erreurs |
|
||||
| **Info** | `#60A5FA` | Informations |
|
||||
|
||||
## Typography
|
||||
|
||||
| Element | Size | Weight | Line Height |
|
||||
|---------|------|--------|-------------|
|
||||
| **H1** | 32px | 700 | 1.2 |
|
||||
| **H2** | 24px | 600 | 1.3 |
|
||||
| **H3** | 20px | 600 | 1.4 |
|
||||
| **Body** | 14px | 400 | 1.5 |
|
||||
| **Small** | 12px | 400 | 1.4 |
|
||||
|
||||
**Font:** Inter (system-ui fallback)
|
||||
|
||||
## Iconography
|
||||
|
||||
**Library:** Lucide Icons
|
||||
|
||||
| Context | Size |
|
||||
|---------|------|
|
||||
| Navigation | 20px |
|
||||
| Buttons | 16px |
|
||||
| Inline | 14px |
|
||||
|
||||
## Spacing Scale (base 4px)
|
||||
|
||||
| Token | Value |
|
||||
|-------|-------|
|
||||
| `space-1` | 4px |
|
||||
| `space-2` | 8px |
|
||||
| `space-3` | 12px |
|
||||
| `space-4` | 16px |
|
||||
| `space-6` | 24px |
|
||||
| `space-8` | 32px |
|
||||
|
||||
## Layout Constants
|
||||
|
||||
| Element | Value |
|
||||
|---------|-------|
|
||||
| Sidebar width | 240px (collapsed: 64px) |
|
||||
| Max content width | 1280px |
|
||||
| Border radius | 8px (cards), 6px (buttons) |
|
||||
|
||||
---
|
||||
20
docs/front-end-spec/component-library-design-system.md
Normal file
20
docs/front-end-spec/component-library-design-system.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# Component Library / Design System
|
||||
|
||||
**Design System:** shadcn/ui (composants copiés, personnalisables)
|
||||
|
||||
## Core Components
|
||||
|
||||
| Component | Purpose | Variants | States |
|
||||
|-----------|---------|----------|--------|
|
||||
| **DataTable** | Listes avec tri, filtres, pagination | default, selectable, compact | loading, empty, error, filtered |
|
||||
| **FilterSidebar** | Panel de filtres multicritères | default, collapsible, modal | default, active, loading |
|
||||
| **StatCard** | Widget Dashboard KPI | default, progress, compact | loading, default, hover |
|
||||
| **EntityCard** | Header fiches détail | character, account, team | default, editing |
|
||||
| **ProgressionCheckbox** | Toggle fait/pas fait | default, with-date, bulk | unchecked, checked, loading, disabled |
|
||||
| **BulkActionBar** | Actions sur sélection multiple | floating, inline | hidden, visible, processing |
|
||||
| **Modal** | Dialogues création/édition/confirmation | form, confirm, selector | default, loading, error |
|
||||
| **Toast** | Notifications feedback | success, error, warning, info | entering, visible, exiting |
|
||||
| **Tabs** | Navigation sous-sections | default, pills, underline | default, active, disabled |
|
||||
| **EmptyState** | Affichage liste vide | no-data, no-results, error | — |
|
||||
|
||||
---
|
||||
49
docs/front-end-spec/index.md
Normal file
49
docs/front-end-spec/index.md
Normal file
@@ -0,0 +1,49 @@
|
||||
# Dofus Manager UI/UX Specification
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [Dofus Manager UI/UX Specification](#table-of-contents)
|
||||
- [Introduction](./introduction.md)
|
||||
- [Overall UX Goals & Principles](./overall-ux-goals-principles.md)
|
||||
- [Target User Persona](./overall-ux-goals-principles.md#target-user-persona)
|
||||
- [Usability Goals](./overall-ux-goals-principles.md#usability-goals)
|
||||
- [Design Principles](./overall-ux-goals-principles.md#design-principles)
|
||||
- [Change Log](./overall-ux-goals-principles.md#change-log)
|
||||
- [Information Architecture (IA)](./information-architecture-ia.md)
|
||||
- [Site Map / Screen Inventory](./information-architecture-ia.md#site-map-screen-inventory)
|
||||
- [Navigation Structure](./information-architecture-ia.md#navigation-structure)
|
||||
- [User Flows](./user-flows.md)
|
||||
- [Flow 1: Trouver les personnages qui n'ont pas fait X](./user-flows.md#flow-1-trouver-les-personnages-qui-nont-pas-fait-x)
|
||||
- [Flow 2: Composer une team valide](./user-flows.md#flow-2-composer-une-team-valide)
|
||||
- [Flow 3: Bulk update progressions pour une team](./user-flows.md#flow-3-bulk-update-progressions-pour-une-team)
|
||||
- [Flow 4: Ajouter un nouveau personnage](./user-flows.md#flow-4-ajouter-un-nouveau-personnage)
|
||||
- [Flow 5: Consulter le Dashboard](./user-flows.md#flow-5-consulter-le-dashboard)
|
||||
- [Wireframes & Mockups](./wireframes-mockups.md)
|
||||
- [Screen 1: Dashboard](./wireframes-mockups.md#screen-1-dashboard)
|
||||
- [Screen 2: Liste Personnages](./wireframes-mockups.md#screen-2-liste-personnages)
|
||||
- [Screen 3: Fiche Personnage](./wireframes-mockups.md#screen-3-fiche-personnage)
|
||||
- [Screen 4: Fiche Team](./wireframes-mockups.md#screen-4-fiche-team)
|
||||
- [Component Library / Design System](./component-library-design-system.md)
|
||||
- [Core Components](./component-library-design-system.md#core-components)
|
||||
- [Branding & Style Guide](./branding-style-guide.md)
|
||||
- [Color Palette](./branding-style-guide.md#color-palette)
|
||||
- [Dark Mode (Principal)](./branding-style-guide.md#dark-mode-principal)
|
||||
- [Semantic Colors](./branding-style-guide.md#semantic-colors)
|
||||
- [Typography](./branding-style-guide.md#typography)
|
||||
- [Iconography](./branding-style-guide.md#iconography)
|
||||
- [Spacing Scale (base 4px)](./branding-style-guide.md#spacing-scale-base-4px)
|
||||
- [Layout Constants](./branding-style-guide.md#layout-constants)
|
||||
- [Accessibility Requirements](./accessibility-requirements.md)
|
||||
- [Key Requirements](./accessibility-requirements.md#key-requirements)
|
||||
- [Responsiveness Strategy](./responsiveness-strategy.md)
|
||||
- [Breakpoints](./responsiveness-strategy.md#breakpoints)
|
||||
- [Adaptation Patterns](./responsiveness-strategy.md#adaptation-patterns)
|
||||
- [Animation & Micro-interactions](./animation-micro-interactions.md)
|
||||
- [Motion Principles](./animation-micro-interactions.md#motion-principles)
|
||||
- [Key Animations](./animation-micro-interactions.md#key-animations)
|
||||
- [Performance Goals](./animation-micro-interactions.md#performance-goals)
|
||||
- [Next Steps](./next-steps.md)
|
||||
- [Immediate Actions](./next-steps.md#immediate-actions)
|
||||
- [Design Handoff Checklist](./next-steps.md#design-handoff-checklist)
|
||||
- [Prompt v0.dev (Dashboard)](./next-steps.md#prompt-v0dev-dashboard)
|
||||
- [Prompt v0.dev (Liste Personnages)](./next-steps.md#prompt-v0dev-liste-personnages)
|
||||
82
docs/front-end-spec/information-architecture-ia.md
Normal file
82
docs/front-end-spec/information-architecture-ia.md
Normal file
@@ -0,0 +1,82 @@
|
||||
# Information Architecture (IA)
|
||||
|
||||
## Site Map / Screen Inventory
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A[🏠 Dashboard<br/>Vue d'ensemble principale] --> B[👥 Personnages]
|
||||
A --> C[📁 Comptes]
|
||||
A --> D[⚔️ Teams]
|
||||
A --> E[⚙️ Paramètres]
|
||||
|
||||
A --> A1[Widget Comptes]
|
||||
A --> A2[Widget Personnages]
|
||||
A --> A3[Widget Teams]
|
||||
A --> A4[Widget Monnaies]
|
||||
A --> A5[Actions rapides]
|
||||
|
||||
B --> B1[Liste Personnages]
|
||||
B1 --> B2[Fiche Personnage]
|
||||
B2 --> B2a[Progressions]
|
||||
B2 --> B2b[Monnaies]
|
||||
B2 --> B2c[Teams]
|
||||
|
||||
C --> C1[Liste Comptes]
|
||||
C1 --> C2[Fiche Compte]
|
||||
C2 --> C2a[Personnages du compte]
|
||||
C2 --> C2b[Métiers]
|
||||
C2 --> C2c[Récompenses]
|
||||
|
||||
D --> D1[Liste Teams]
|
||||
D1 --> D2[Fiche Team]
|
||||
D2 --> D2a[Membres]
|
||||
D2 --> D2b[Statut Progressions]
|
||||
|
||||
E --> E1[Serveurs]
|
||||
E --> E2[Monnaies]
|
||||
E --> E3[Données DofusDB]
|
||||
|
||||
B1 --> F[🔄 Bulk Actions]
|
||||
F --> F1[Bulk Progressions]
|
||||
F --> F2[Bulk Monnaies]
|
||||
```
|
||||
|
||||
## Navigation Structure
|
||||
|
||||
**Primary Navigation (Sidebar)**
|
||||
|
||||
| Icône | Label | Route | Description |
|
||||
|-------|-------|-------|-------------|
|
||||
| 🏠 | Dashboard | `/` | Vue d'ensemble, KPIs, accès rapide |
|
||||
| 👥 | Personnages | `/characters` | Liste principale avec filtres |
|
||||
| 📁 | Comptes | `/accounts` | Gestion des comptes Dofus |
|
||||
| ⚔️ | Teams | `/teams` | Composition et statut des teams |
|
||||
| ⚙️ | Paramètres | `/settings` | Configuration (serveurs, monnaies, sync) |
|
||||
|
||||
**Secondary Navigation (Contextuelle)**
|
||||
|
||||
- **Onglets sur fiches détail** : Personnage → [Infos | Progressions | Monnaies | Teams]
|
||||
- **Sous-menu Paramètres** : [Serveurs | Monnaies | Données DofusDB]
|
||||
- **Actions groupées** : Accessible depuis la toolbar des listes (quand sélection active)
|
||||
|
||||
**Breadcrumb Strategy**
|
||||
|
||||
Format : `Section > Sous-section > Élément`
|
||||
|
||||
Exemples :
|
||||
- `Personnages > Krosmaster-Cra`
|
||||
- `Teams > Main Team > Statut Progressions`
|
||||
- `Paramètres > Données DofusDB`
|
||||
|
||||
**Dashboard Content**
|
||||
|
||||
| Widget | Contenu | Action au clic |
|
||||
|--------|---------|----------------|
|
||||
| **Comptes** | Liste des comptes avec nb persos, ogrines | → Fiche compte |
|
||||
| **Personnages** | Total, répartition par classe/niveau | → Liste filtrée |
|
||||
| **Teams** | Teams actives avec % complétion | → Fiche team |
|
||||
| **Monnaies** | Totaux globaux par type | → Détail par compte |
|
||||
| **Progressions** | Résumé global (X% Dofus faits, Y donjons) | → Bulk actions |
|
||||
| **Actions rapides** | Boutons : Nouveau perso, Bulk update, Sync DofusDB | → Action directe |
|
||||
|
||||
---
|
||||
5
docs/front-end-spec/introduction.md
Normal file
5
docs/front-end-spec/introduction.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# Introduction
|
||||
|
||||
Ce document définit les objectifs d'expérience utilisateur, l'architecture de l'information, les flux utilisateur et les spécifications de design visuel pour l'interface de **Dofus Manager**. Il sert de fondation pour le design visuel et le développement frontend, assurant une expérience cohérente et centrée sur l'utilisateur.
|
||||
|
||||
---
|
||||
51
docs/front-end-spec/next-steps.md
Normal file
51
docs/front-end-spec/next-steps.md
Normal file
@@ -0,0 +1,51 @@
|
||||
# Next Steps
|
||||
|
||||
## Immediate Actions
|
||||
|
||||
1. Générer les maquettes haute-fidélité (v0, Lovable, ou Figma)
|
||||
2. Setup le projet avec shadcn/ui et configurer le thème
|
||||
3. Implémenter le Layout principal (sidebar + header)
|
||||
4. Développer le Dashboard avec widgets mockés
|
||||
|
||||
## Design Handoff Checklist
|
||||
|
||||
- [x] All user flows documented
|
||||
- [x] Component inventory complete
|
||||
- [x] Accessibility requirements defined
|
||||
- [x] Responsive strategy clear
|
||||
- [x] Brand guidelines incorporated
|
||||
- [x] Performance goals established
|
||||
|
||||
## Prompt v0.dev (Dashboard)
|
||||
|
||||
```
|
||||
Create a dark mode dashboard for a Dofus MMORPG character management app called "Dofus Manager".
|
||||
|
||||
Layout:
|
||||
- Left sidebar (240px) with navigation: Dashboard (active), Characters, Accounts, Teams, Settings
|
||||
- Main content area with widgets grid
|
||||
|
||||
Widgets (3 columns on desktop):
|
||||
1. "Comptes" card: showing "12 comptes" and "45,230 ogrines" with folder icon
|
||||
2. "Personnages" card: showing "64 personnages" and "Niv. moy: 198" with users icon
|
||||
3. "Teams" card: showing "3 actives" and "87% complete" with swords icon
|
||||
4. "Monnaies" card (spans 2 cols): list of currencies with amounts
|
||||
5. "Progressions" card: progress bars for Dofus, Donjons, Recherchés
|
||||
6. "Actions rapides" section: buttons for + Personnage, + Team, Bulk Progressions, Sync
|
||||
|
||||
Style: shadcn/ui, dark slate background (#0F172A), blue primary (#60A5FA), Inter font 14px
|
||||
```
|
||||
|
||||
## Prompt v0.dev (Liste Personnages)
|
||||
|
||||
```
|
||||
Create a character list page for "Dofus Manager" with filters sidebar.
|
||||
|
||||
Layout:
|
||||
- Left filter sidebar (250px): Classe checkboxes, Serveur checkboxes, Progression filter
|
||||
- Main data table: checkbox, Nom, Classe, Niveau, Serveur, Compte columns
|
||||
- Top bar: search input, bulk actions when selected, + Ajouter button
|
||||
- Pagination at bottom
|
||||
|
||||
Style: Dark mode, shadcn/ui, dense table rows (48px height), hover shows edit/delete icons
|
||||
```
|
||||
42
docs/front-end-spec/overall-ux-goals-principles.md
Normal file
42
docs/front-end-spec/overall-ux-goals-principles.md
Normal file
@@ -0,0 +1,42 @@
|
||||
# Overall UX Goals & Principles
|
||||
|
||||
## Target User Persona
|
||||
|
||||
**Theo - Le Multi-Compteur Organisé**
|
||||
|
||||
| Attribut | Description |
|
||||
|----------|-------------|
|
||||
| **Profil** | Joueur passionné de Dofus gérant 60+ personnages niveau 200 |
|
||||
| **Contexte d'usage** | Joue sur PC avec souvent un second écran pour consulter ses données |
|
||||
| **Frustrations actuelles** | Tableur Excel illisible, modifications fragiles, contraintes de compte gérées mentalement |
|
||||
| **Objectifs** | Trouver rapidement qui n'a pas fait quoi, composer des teams valides, mettre à jour efficacement |
|
||||
| **Expertise technique** | À l'aise avec les outils complexes, préfère la densité d'info à la simplicité |
|
||||
| **Fréquence d'usage** | Quotidien pendant les sessions de jeu + planification hebdomadaire |
|
||||
|
||||
## Usability Goals
|
||||
|
||||
1. **Efficacité de navigation** — Trouver n'importe quelle information en moins de 3 clics depuis le dashboard
|
||||
2. **Mises à jour rapides** — Pouvoir mettre à jour la progression d'une team entière en moins de 30 secondes
|
||||
3. **Prévention d'erreurs** — Impossible d'ajouter 2 personnages du même compte dans une team active
|
||||
4. **Vue d'ensemble immédiate** — Voir l'état global (teams, progressions, monnaies) en un coup d'œil
|
||||
5. **Mémorabilité** — Interface cohérente permettant de retrouver ses repères après plusieurs jours d'absence
|
||||
|
||||
## Design Principles
|
||||
|
||||
1. **Densité maîtrisée** — Maximiser l'information visible sans surcharger visuellement. Utiliser la hiérarchie typographique et les espaces blancs stratégiquement.
|
||||
|
||||
2. **Consistance des patterns** — Tous les tableaux se comportent de la même façon (tri, filtres, pagination). Toutes les actions CRUD suivent le même flow.
|
||||
|
||||
3. **Feedback immédiat** — Chaque action utilisateur génère une réponse visuelle instantanée (loading states, toasts, transitions).
|
||||
|
||||
4. **Raccourcis pour experts** — Permettre les bulk actions, raccourcis clavier (V2), et filtres combinés pour les utilisateurs avancés.
|
||||
|
||||
5. **Fail-safe par design** — Les actions destructives demandent confirmation. Les contraintes métier sont validées avant même que l'utilisateur ne puisse les violer.
|
||||
|
||||
## Change Log
|
||||
|
||||
| Date | Version | Description | Author |
|
||||
|------|---------|-------------|--------|
|
||||
| 2026-01-17 | 0.1 | Création initiale | Sally (UX Expert) |
|
||||
|
||||
---
|
||||
22
docs/front-end-spec/responsiveness-strategy.md
Normal file
22
docs/front-end-spec/responsiveness-strategy.md
Normal file
@@ -0,0 +1,22 @@
|
||||
# Responsiveness Strategy
|
||||
|
||||
## Breakpoints
|
||||
|
||||
| Breakpoint | Min Width | Target |
|
||||
|------------|-----------|--------|
|
||||
| **sm** (Mobile) | 0 | Smartphones |
|
||||
| **md** (Tablet) | 640px | Tablettes |
|
||||
| **lg** (Desktop) | 1024px | Laptops |
|
||||
| **xl** (Wide) | 1280px | Grands moniteurs |
|
||||
|
||||
## Adaptation Patterns
|
||||
|
||||
| Element | Desktop | Tablet | Mobile |
|
||||
|---------|---------|--------|--------|
|
||||
| **Sidebar** | Expanded | Collapsed (icons) | Burger menu |
|
||||
| **Dashboard** | 3 colonnes | 2 colonnes | 1 colonne |
|
||||
| **DataTable** | Full | Colonnes prioritaires | Cards |
|
||||
| **Modals** | Centré 500px | 90vw | Plein écran |
|
||||
| **Filtres** | Sidebar | Sidebar mini | Modal |
|
||||
|
||||
---
|
||||
123
docs/front-end-spec/user-flows.md
Normal file
123
docs/front-end-spec/user-flows.md
Normal file
@@ -0,0 +1,123 @@
|
||||
# User Flows
|
||||
|
||||
## Flow 1: Trouver les personnages qui n'ont pas fait X
|
||||
|
||||
**User Goal:** Identifier rapidement quels personnages n'ont pas complété une progression spécifique
|
||||
|
||||
**Entry Points:** Dashboard → Widget Progressions, Sidebar → Personnages, Fiche Team
|
||||
|
||||
**Success Criteria:** Liste filtrée affichée en < 3 clics, < 5 secondes
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A[Dashboard] --> B[Clic Personnages]
|
||||
B --> C[Liste avec Filtres]
|
||||
C --> D[Ouvrir filtre Progression]
|
||||
D --> E[Sélectionner type]
|
||||
E --> F[Sélectionner N'a pas fait]
|
||||
F --> G[✅ Liste filtrée affichée]
|
||||
|
||||
G --> H{Action suivante?}
|
||||
H --> I[Voir fiche perso]
|
||||
H --> J[Sélectionner plusieurs]
|
||||
J --> K[Bulk Update]
|
||||
```
|
||||
|
||||
**Edge Cases:**
|
||||
- Aucun résultat → Message "Tous les personnages ont complété X" avec bouton reset
|
||||
- Filtres combinés complexes → Indicateur des filtres actifs + "Clear all"
|
||||
|
||||
## Flow 2: Composer une team valide
|
||||
|
||||
**User Goal:** Créer ou modifier une team en respectant la contrainte compte
|
||||
|
||||
**Success Criteria:** Team créée avec membres valides, erreur claire si conflit
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A[Liste Teams] --> B[Nouvelle Team]
|
||||
B --> C[Modal création]
|
||||
C --> D[Saisir nom + type]
|
||||
D --> E[Enregistrer]
|
||||
E --> F[Fiche Team vide]
|
||||
|
||||
F --> G[Ajouter membre]
|
||||
G --> H[Sélecteur personnages]
|
||||
H --> I[Sélectionner perso]
|
||||
|
||||
I --> K{Même compte dans team?}
|
||||
K -->|Non| L[✅ Membre ajouté]
|
||||
K -->|Oui| M[❌ Erreur conflit]
|
||||
M --> H
|
||||
|
||||
L --> O{Continuer?}
|
||||
O -->|Oui| G
|
||||
O -->|Non| P[✅ Team complète]
|
||||
```
|
||||
|
||||
## Flow 3: Bulk update progressions pour une team
|
||||
|
||||
**User Goal:** Marquer une progression faite pour tous les membres d'une team
|
||||
|
||||
**Success Criteria:** Mise à jour de N personnages en < 30 secondes
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A[Fiche Team] --> B[Section Statut Progressions]
|
||||
B --> C[Sélectionner progression]
|
||||
C --> D[Voir statut par membre]
|
||||
D --> E{Tous faits?}
|
||||
E -->|Non| G[Bouton Marquer fait pour tous]
|
||||
|
||||
G --> H[Modal confirmation]
|
||||
H --> I[Récap: X persos à mettre à jour]
|
||||
I --> J{Confirmer?}
|
||||
J -->|Oui| K[Processing...]
|
||||
K --> L[✅ Toast: X persos mis à jour]
|
||||
L --> M[Refresh → 100%]
|
||||
```
|
||||
|
||||
## Flow 4: Ajouter un nouveau personnage
|
||||
|
||||
**User Goal:** Créer un personnage avec toutes ses informations
|
||||
|
||||
**Success Criteria:** Personnage créé et visible en < 1 minute
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A[Liste Personnages] --> B[Clic Ajouter]
|
||||
B --> C[Modal création]
|
||||
C --> D[Saisir pseudo]
|
||||
D --> E[Sélectionner classe]
|
||||
E --> F[Saisir niveau]
|
||||
F --> G[Sélectionner serveur]
|
||||
G --> H[Sélectionner compte]
|
||||
H --> I{Validation}
|
||||
I -->|OK| J[Enregistrer]
|
||||
J --> K[✅ Toast confirmation]
|
||||
K --> L[Liste rafraîchie]
|
||||
```
|
||||
|
||||
## Flow 5: Consulter le Dashboard
|
||||
|
||||
**User Goal:** Vue d'ensemble instantanée de tous les comptes et personnages
|
||||
|
||||
**Success Criteria:** Toutes les informations clés visibles sans scroll sur desktop
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A[Accès Dashboard] --> B[Chargement widgets]
|
||||
B --> C[Affichage simultané]
|
||||
|
||||
C --> D[Widget Comptes]
|
||||
C --> E[Widget Personnages]
|
||||
C --> F[Widget Teams]
|
||||
C --> G[Widget Monnaies]
|
||||
C --> H[Widget Progressions]
|
||||
|
||||
D --> I[Clic → Liste comptes]
|
||||
E --> J[Clic → Liste personnages]
|
||||
F --> K[Clic → Liste teams]
|
||||
```
|
||||
|
||||
---
|
||||
128
docs/front-end-spec/wireframes-mockups.md
Normal file
128
docs/front-end-spec/wireframes-mockups.md
Normal file
@@ -0,0 +1,128 @@
|
||||
# Wireframes & Mockups
|
||||
|
||||
## Screen 1: Dashboard
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────────┐
|
||||
│ ☰ DOFUS MANAGER [🌙 Dark Mode] │
|
||||
├────────────┬────────────────────────────────────────────────────────────────┤
|
||||
│ │ │
|
||||
│ 🏠 Dashboard│ DASHBOARD [+ Nouveau ▾] │
|
||||
│ │ ───────────────────────────────────────────────────────────── │
|
||||
│ 👥 Persos │ │
|
||||
│ │ ┌─────────────────┐ ┌─────────────────┐ ┌────────────────┐ │
|
||||
│ 📁 Comptes│ │ 📁 COMPTES │ │ 👥 PERSONNAGES │ │ ⚔️ TEAMS │ │
|
||||
│ │ │ 12 comptes │ │ 64 personnages │ │ 3 actives │ │
|
||||
│ ⚔️ Teams │ │ 45,230 ogrines │ │ Niv. moy: 198 │ │ 87% complete │ │
|
||||
│ │ │ [Voir tout →] │ │ [Voir tout →] │ │ [Voir tout →] │ │
|
||||
│ ─────────│ └─────────────────┘ └─────────────────┘ └────────────────┘ │
|
||||
│ ⚙️ Settings│ │
|
||||
│ │ ┌─────────────────────────────────┐ ┌──────────────────────┐ │
|
||||
│ │ │ 💰 MONNAIES │ │ 📊 PROGRESSIONS │ │
|
||||
│ │ │ Doplons 12,450 │ │ Dofus ████░ 72% │ │
|
||||
│ │ │ Orichor 3,200 │ │ Donjons ██░░░ 45% │ │
|
||||
│ │ │ Kamas glace 8,100 │ │ Recherchés███░░ 61% │ │
|
||||
│ │ │ [Détail par compte →] │ │ [Bulk Update →] │ │
|
||||
│ │ └─────────────────────────────────┘ └──────────────────────┘ │
|
||||
│ │ │
|
||||
│ │ ┌─────────────────────────────────────────────────────────┐ │
|
||||
│ │ │ ⚡ ACTIONS RAPIDES │ │
|
||||
│ │ │ [+ Personnage] [+ Team] [Bulk Progressions] [Sync] │ │
|
||||
│ │ └─────────────────────────────────────────────────────────┘ │
|
||||
└────────────┴────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Screen 2: Liste Personnages
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────────┐
|
||||
│ ☰ DOFUS MANAGER [🌙] │
|
||||
├────────────┬────────────────────────────────────────────────────────────────┤
|
||||
│ │ PERSONNAGES 🔍 [Rechercher... ] │
|
||||
│ 🏠 Dashboard│ ───────────────────────────────────────────────────────────── │
|
||||
│ ►👥 Persos │ │
|
||||
│ │ ┌──────────────┐ ┌──────────────────────────────────────────┐│
|
||||
│ 📁 Comptes│ │ FILTRES │ │ ☑ Sélection: 3 [Bulk Actions ▾] ││
|
||||
│ │ │ │ │ ─────────────────────────────────────── ││
|
||||
│ ⚔️ Teams │ │ ▼ Classe │ │ ☐ │ Nom │Classe│Niv│Serveur│Cpt││
|
||||
│ │ │ ☑ Cra 12 │ │ ──┼──────────────┼──────┼───┼───────┼───││
|
||||
│ ─────────│ │ ☑ Iop 8 │ │ ☑ │ Krosmaster │ Cra │200│Imagiro│C1 ││
|
||||
│ ⚙️ Settings│ │ ☐ Enu 6 │ │ ☐ │ TankMaster │ Iop │200│Imagiro│C1 ││
|
||||
│ │ │ │ │ ☑ │ MoneyMaker │ Enu │200│Imagiro│C2 ││
|
||||
│ │ │ ▼ Serveur │ │ ☐ │ HealBot │ Eni │200│Imagiro│C2 ││
|
||||
│ │ │ ☑ Imagiro │ │ ☑ │ PortalGuy │ Elio │200│Imagiro│C3 ││
|
||||
│ │ │ │ │ ─────────────────────────────────────── ││
|
||||
│ │ │ ▼ Progression│ │ Showing 1-20 of 64 [< 1 2 3 4 >] ││
|
||||
│ │ │ Type: [──▾] │ └──────────────────────────────────────────┘│
|
||||
│ │ │ ○ A fait │ │
|
||||
│ │ │ ○ N'a pas │ [+ Ajouter Personnage] │
|
||||
│ │ │ [Réinitialiser]│ │
|
||||
│ │ └──────────────┘ │
|
||||
└────────────┴────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Screen 3: Fiche Personnage
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────────┐
|
||||
│ ☰ DOFUS MANAGER [🌙] │
|
||||
├────────────┬────────────────────────────────────────────────────────────────┤
|
||||
│ │ ← Personnages / Krosmaster [✏️] [🗑️] │
|
||||
│ 🏠 Dashboard│ ───────────────────────────────────────────────────────────── │
|
||||
│ 👥 Persos │ │
|
||||
│ │ ┌─────────────────────────────────────────────────────────┐ │
|
||||
│ 📁 Comptes│ │ [Avatar] KROSMASTER │ │
|
||||
│ │ │ Classe: Cra Niveau: 200 │ │
|
||||
│ ⚔️ Teams │ │ Serveur: Imagiro Compte: Compte1 │ │
|
||||
│ │ │ Teams: Main Team, Team Succès │ │
|
||||
│ ─────────│ └─────────────────────────────────────────────────────────┘ │
|
||||
│ ⚙️ Settings│ │
|
||||
│ │ ┌─────────────────────────────────────────────────────────┐ │
|
||||
│ │ │ [Infos] [Progressions] [Monnaies] [Teams] │ │
|
||||
│ │ ├─────────────────────────────────────────────────────────┤ │
|
||||
│ │ │ PROGRESSIONS Filtre: [Tous ▾] │ │
|
||||
│ │ │ │ │
|
||||
│ │ │ ▼ Quêtes Dofus (7/10) │ │
|
||||
│ │ │ ☑ Dofus Turquoise ✓ 2026-01-10 │ │
|
||||
│ │ │ ☑ Dofus Pourpre ✓ 2026-01-08 │ │
|
||||
│ │ │ ☐ Dofus des Glaces │ │
|
||||
│ │ │ │ │
|
||||
│ │ │ ▼ Donjons 191-200 (12/18) │ │
|
||||
│ │ │ ☑ Bethel ✓ 2026-01-15 │ │
|
||||
│ │ │ ☐ Tal Kasha │ │
|
||||
│ │ └─────────────────────────────────────────────────────────┘ │
|
||||
└────────────┴────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Screen 4: Fiche Team
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────────┐
|
||||
│ ☰ DOFUS MANAGER [🌙] │
|
||||
├────────────┬────────────────────────────────────────────────────────────────┤
|
||||
│ │ ← Teams / Main Team [✏️] [🗑️] │
|
||||
│ 🏠 Dashboard│ │
|
||||
│ 👥 Persos │ ┌────────────────────────────────────────────────────────┐ │
|
||||
│ │ │ MAIN TEAM Type: Main │ │
|
||||
│ 📁 Comptes│ │ 8 membres • ✅ Active • 8 comptes différents │ │
|
||||
│ │ └────────────────────────────────────────────────────────┘ │
|
||||
│ ⚔️ Teams │ │
|
||||
│ │ ┌────────────────────────────────────────────────────────┐ │
|
||||
│ ─────────│ │ [Membres] [Statut Progressions] │ │
|
||||
│ ⚙️ Settings│ ├────────────────────────────────────────────────────────┤ │
|
||||
│ │ │ STATUT PROGRESSIONS │ │
|
||||
│ │ │ │ │
|
||||
│ │ │ Progression: [Dofus Turquoise ▾] │ │
|
||||
│ │ │ │ │
|
||||
│ │ │ ████████████████████░░░░ 75% (6/8) [Marquer tous] │ │
|
||||
│ │ │ │ │
|
||||
│ │ │ │ Perso │ Statut │ Date │ │ │
|
||||
│ │ │ │ Krosmaster │ ✅ │ 2026-01-10 │ │ │
|
||||
│ │ │ │ TankMaster │ ✅ │ 2026-01-10 │ │ │
|
||||
│ │ │ │ HealBot │ ❌ │ — │ │ │
|
||||
│ │ │ │ SramKiller │ ❌ │ — │ │ │
|
||||
│ │ └────────────────────────────────────────────────────────┘ │
|
||||
└────────────┴────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
922
docs/prd.md
Normal file
922
docs/prd.md
Normal file
@@ -0,0 +1,922 @@
|
||||
# Dofus Manager - Product Requirements Document (PRD)
|
||||
|
||||
## Goals and Background Context
|
||||
|
||||
### Goals
|
||||
|
||||
- **Remplacer le tableur Excel** de gestion de 60+ personnages Dofus par une application web moderne et maintenable
|
||||
- **Offrir une vue d'ensemble claire** de tous les personnages avec filtrage multicritères et recherche instantanée
|
||||
- **Automatiser la gestion des données** via intégration avec l'API DofusDB (quêtes, donjons, succès)
|
||||
- **Faciliter les mises à jour groupées** (bulk update) pour réduire drastiquement le temps de maintenance
|
||||
- **Valider automatiquement les contraintes de compte** (pas 2 personnages du même compte simultanément dans une team)
|
||||
- **Tracker les progressions** (quêtes Dofus, donjons, recherchés, monnaies) par personnage et par team
|
||||
|
||||
### Background Context
|
||||
|
||||
Theo est un joueur de Dofus gérant **60+ personnages niveau 200** répartis sur plusieurs dizaines de comptes sur plusieurs serveurs (principalement Imagiro). Actuellement, cette gestion est faite via un tableur Excel avec les personnages en colonnes horizontales, ce qui rend la visualisation impossible sans scroll excessif, les modifications fragiles (risque de casser le formatage), et la règle métier fondamentale du jeu ("pas 2 persos du même compte simultanément") gérée uniquement mentalement.
|
||||
|
||||
L'application remplacera ce tableur par un système web permettant la gestion CRUD des comptes, personnages, serveurs et teams, avec des filtres avancés façon e-commerce, des actions groupées, et une intégration avec DofusDB pour éliminer la saisie manuelle des données de référence (quêtes, donjons, succès).
|
||||
|
||||
### Change Log
|
||||
|
||||
| Date | Version | Description | Author |
|
||||
|------|---------|-------------|--------|
|
||||
| 2026-01-17 | 0.1 | Création initiale du PRD | John (PM) |
|
||||
| 2026-01-17 | 0.2 | Ajout documentation API DofusDB (endpoints validés) | John (PM) |
|
||||
|
||||
---
|
||||
|
||||
## Requirements
|
||||
|
||||
### Functional Requirements
|
||||
|
||||
- **FR1:** Le système doit permettre la création, lecture, modification et suppression (CRUD) des **comptes** avec les attributs : nom, ogrines, récompenses succès débloquées (Dofus, ressources).
|
||||
|
||||
- **FR2:** Le système doit permettre la gestion CRUD des **personnages** avec les attributs : pseudo, classe (17 classes Dofus), niveau, serveur associé, compte associé.
|
||||
|
||||
- **FR3:** Le système doit permettre la gestion CRUD des **teams** avec validation automatique de la contrainte "pas 2 personnages du même compte dans une team active".
|
||||
|
||||
- **FR4:** Le système doit offrir un **filtrage multicritères** des personnages par : classe, niveau, compte, team, serveur, statut de progression (quêtes, donjons, recherchés).
|
||||
|
||||
- **FR5:** Le système doit permettre la **recherche textuelle** sur les noms de personnages, comptes et teams.
|
||||
|
||||
- **FR6:** Le système doit permettre les **mises à jour groupées (bulk update)** : cocher/décocher plusieurs progressions pour une sélection de personnages ou une team entière.
|
||||
|
||||
- **FR7:** Le système doit tracker les **progressions par personnage** : quêtes Dofus (Turquoise, Pourpre, Émeraude, etc.), donjons par paliers avec types de succès, recherchés par région.
|
||||
|
||||
- **FR8:** Le système doit tracker les **monnaies par personnage** : Doplons, Almatons, Orichor, Kamas de glace, Perles des profondeurs, Alitons, Trukdivins, Pages calendrier.
|
||||
|
||||
- **FR9:** Le système doit afficher les **totaux agrégés des monnaies** au niveau compte et global.
|
||||
|
||||
- **FR10:** Le système doit s'intégrer avec **l'API DofusDB** pour importer les données de référence (liste des quêtes, donjons, succès, recherchés).
|
||||
|
||||
- **FR11:** Le système doit afficher une **vue statut team** avec pourcentage de complétion par objectif (ex: "Dofus Turquoise: 6/8 persos = 75%").
|
||||
|
||||
- **FR12:** Le système doit gérer les **métiers par couple compte+serveur** (et non par personnage) avec niveau de maîtrise.
|
||||
|
||||
- **FR13:** Le système doit permettre la gestion CRUD des **serveurs** (ex: Imagiro, Jahash, Draconiros) avec possibilité d'en ajouter de nouveaux.
|
||||
|
||||
### Non-Functional Requirements
|
||||
|
||||
- **NFR1:** L'application doit être **responsive** et utilisable sur desktop et tablette (usage sur second écran pendant le jeu).
|
||||
|
||||
- **NFR2:** L'application doit offrir une **latence de réponse < 500ms** pour les opérations courantes (filtrage, CRUD).
|
||||
|
||||
- **NFR3:** L'application doit supporter **100+ personnages** sans dégradation notable des performances.
|
||||
|
||||
- **NFR4:** L'application doit être **auto-hébergeable** sur un serveur dédié personnel via Docker.
|
||||
|
||||
- **NFR5:** L'application doit utiliser **PostgreSQL** comme base de données pour la persistance.
|
||||
|
||||
- **NFR6:** L'application doit être développée avec **React + TanStack Start** (full-stack TypeScript).
|
||||
|
||||
- **NFR7:** Les données doivent être **sauvegardables et restaurables** facilement (backup PostgreSQL).
|
||||
|
||||
- **NFR8:** L'application doit fonctionner en **mode mono-utilisateur** (pas d'authentification multi-users dans le MVP).
|
||||
|
||||
---
|
||||
|
||||
## User Interface Design Goals
|
||||
|
||||
### Overall UX Vision
|
||||
|
||||
L'application doit offrir une expérience **efficace et dense en informations**, inspirée des outils de gestion de données professionnels. L'objectif est de permettre à l'utilisateur de :
|
||||
- Trouver rapidement l'information cherchée (quel perso n'a pas fait X ?)
|
||||
- Effectuer des modifications en masse sans friction
|
||||
- Avoir une vue d'ensemble claire malgré le volume de données (60+ personnages)
|
||||
|
||||
Le design privilégie la **fonctionnalité sur l'esthétique** : interface sobre, contrastes clairs, densité d'information élevée, navigation rapide.
|
||||
|
||||
### Key Interaction Paradigms
|
||||
|
||||
- **Filtres sidebar façon e-commerce** — Panel latéral avec facettes cliquables (classe, serveur, team, compte, statut)
|
||||
- **Multi-select façon Gmail** — Checkboxes pour sélection multiple + barre d'actions groupées
|
||||
- **Tables interactives** — Tri, resize colonnes, pagination, colonnes masquables
|
||||
- **Actions au survol** — Boutons edit/delete apparaissent au hover pour réduire le bruit visuel
|
||||
- **Drill-down progressif** — Liste → Fiche détaillée → Sous-sections (progressions, monnaies)
|
||||
- **Feedback immédiat** — Toasts pour confirmations, indicateurs de chargement, états vides informatifs
|
||||
|
||||
### Core Screens and Views
|
||||
|
||||
1. **Dashboard** — Vue d'accueil avec KPIs (total persos, teams, progression globale)
|
||||
2. **Liste Personnages** — Vue principale avec filtres, recherche, tableau paginé
|
||||
3. **Fiche Personnage** — Détails complets : infos, progressions, monnaies, teams
|
||||
4. **Liste Comptes** — Gestion des comptes avec leurs personnages associés
|
||||
5. **Fiche Compte** — Détails compte : ogrines, métiers (par serveur), récompenses
|
||||
6. **Liste Teams** — Toutes les teams avec statut de complétion
|
||||
7. **Fiche Team** — Membres, validation contraintes, % progression par objectif
|
||||
8. **Gestion Serveurs** — CRUD des serveurs disponibles
|
||||
9. **Données de référence** — Gestion des quêtes/donjons/recherchés (sync DofusDB)
|
||||
|
||||
### Accessibility
|
||||
|
||||
**Niveau cible : Aucun (pas de conformité WCAG requise)**
|
||||
|
||||
Application à usage personnel. Bonnes pratiques de base respectées : contrastes suffisants, navigation clavier, labels sur formulaires.
|
||||
|
||||
### Branding
|
||||
|
||||
**Aucun branding spécifique.** Design system sobre et moderne (shadcn/ui ou similaire), palette neutre, pas de thématique Dofus (éviter copyright), focus sur lisibilité.
|
||||
|
||||
### Target Device and Platforms
|
||||
|
||||
**Web Responsive (Desktop-first)**
|
||||
|
||||
- **Priorité 1 : Desktop** — Usage principal sur grand écran pendant les sessions de jeu
|
||||
- **Priorité 2 : Tablette** — Consultation occasionnelle
|
||||
- **Priorité 3 : Mobile** — Consultation basique acceptable
|
||||
|
||||
---
|
||||
|
||||
## Technical Assumptions
|
||||
|
||||
### Repository Structure: Monorepo
|
||||
|
||||
Projet organisé en **monorepo** :
|
||||
```
|
||||
/
|
||||
├── src/
|
||||
│ ├── routes/ # Pages et API routes (TanStack Start)
|
||||
│ ├── components/ # Composants React réutilisables
|
||||
│ ├── lib/ # Utilitaires, clients API, helpers
|
||||
│ └── server/ # Server functions, services
|
||||
├── prisma/ # Schéma et migrations Prisma
|
||||
├── docker/ # Configuration Docker
|
||||
└── docs/ # Documentation projet
|
||||
```
|
||||
|
||||
### Service Architecture: Monolith Full-Stack
|
||||
|
||||
**Architecture monolithique** avec TanStack Start :
|
||||
- **Frontend** : React avec TanStack Router (file-based routing)
|
||||
- **Backend** : Server functions intégrées à TanStack Start
|
||||
- **Base de données** : PostgreSQL avec Prisma ORM
|
||||
|
||||
### Testing Requirements: Unit + Integration
|
||||
|
||||
| Type | Scope | Outils |
|
||||
|------|-------|--------|
|
||||
| **Unit** | Logique métier, validations, helpers | Vitest |
|
||||
| **Integration** | API routes, queries DB | Vitest + testcontainers |
|
||||
| **E2E** | Non prioritaire MVP | (Playwright en V2) |
|
||||
|
||||
### Additional Technical Assumptions and Requests
|
||||
|
||||
**Stack technique :**
|
||||
- **Framework** : TanStack Start (React full-stack)
|
||||
- **ORM** : Prisma (type-safe, migrations robustes, écosystème mature)
|
||||
- **UI Components** : shadcn/ui (composants copiés, personnalisables)
|
||||
- **Tables** : TanStack Table (tri, filtres, pagination)
|
||||
- **Database** : PostgreSQL 16+
|
||||
- **Container** : Docker + Docker Compose
|
||||
|
||||
**Infrastructure :**
|
||||
- **Reverse proxy** : Traefik (existant sur le serveur)
|
||||
- **CI/CD** : GitLab personnel (pipelines de build et déploiement)
|
||||
- **Hébergement** : Serveur dédié personnel
|
||||
|
||||
**Intégration externe :**
|
||||
- **DofusDB API** : Client HTTP pour récupérer les données de référence
|
||||
- Sync manuelle ou cron pour mise à jour des données de jeu
|
||||
|
||||
**Conventions de code :**
|
||||
- TypeScript strict mode
|
||||
- ESLint + Prettier
|
||||
- Conventional commits (feat:, fix:, chore:, etc.)
|
||||
|
||||
**Déploiement :**
|
||||
- Docker Compose (app + postgres)
|
||||
- Pipeline GitLab CI pour build et push des images
|
||||
- Labels Traefik pour routing automatique
|
||||
|
||||
---
|
||||
|
||||
## DofusDB API Reference
|
||||
|
||||
Documentation de l'API externe utilisée pour l'Epic 6.
|
||||
|
||||
### Base URL
|
||||
|
||||
`https://api.dofusdb.fr/`
|
||||
|
||||
### Caractéristiques techniques
|
||||
|
||||
- **Framework:** FeathersJS (REST API)
|
||||
- **Pagination:** `$limit`, `$skip` (défaut: limit=10)
|
||||
- **Filtrage:** Style MongoDB (`$regex`, `$in`, `$gt`, etc.)
|
||||
- **Multilingue:** `name.fr`, `name.en`, `name.de`, `name.es`, `name.pt`
|
||||
- **Authentification:** Aucune (API publique)
|
||||
|
||||
### Endpoints disponibles
|
||||
|
||||
| Endpoint | Total | Champs clés |
|
||||
|----------|-------|-------------|
|
||||
| `/dungeons` | 187 | id, name, optimalPlayerLevel, monsters[], subarea |
|
||||
| `/quests` | 1978 | id, name, categoryId, levelMin, levelMax, steps[], rewards[] |
|
||||
| `/achievements` | 2788 | id, name, description, level, points, categoryId, rewards[] |
|
||||
| `/monsters` | 5093 | id, name, level, isBoss, stats, drops[], subareas[] |
|
||||
| `/items` | — | id, name, typeId (23 = Dofus trophées) |
|
||||
| `/quest-categories` | 43+ | id, name (régions, types de quêtes) |
|
||||
| `/achievement-categories` | 129 | id, name, parentId |
|
||||
|
||||
### Mapping pour le PRD
|
||||
|
||||
| Besoin PRD | Endpoint DofusDB | Query |
|
||||
|------------|------------------|-------|
|
||||
| **Donjons** | `/dungeons` | `?$limit=200` |
|
||||
| **Recherchés** | `/quests` | `?categoryId=6` |
|
||||
| **Items Dofus** | `/items` | `?typeId=23&name.fr[$regex]=Dofus` |
|
||||
| **Succès donjons** | `/achievements` | `?categoryId=3` |
|
||||
|
||||
### Dofus identifiés
|
||||
|
||||
| ID Item | Nom |
|
||||
|---------|-----|
|
||||
| 739 | Dofus Turquoise |
|
||||
| 694 | Dofus Pourpre |
|
||||
| 737 | Dofus Émeraude |
|
||||
| 7043 | Dofus des Glaces |
|
||||
| 18043 | Dofus Abyssal |
|
||||
| 8698 | Dofus Nébuleux |
|
||||
| 7112 | Dofus Tacheté |
|
||||
| 6980 | Dofus Vulbis |
|
||||
| 7754 | Dofus Ocre |
|
||||
| 7114 | Dofus Ébène |
|
||||
| 7115 | Dofus Ivoire |
|
||||
|
||||
### Exemples de requêtes
|
||||
|
||||
```bash
|
||||
# Tous les donjons
|
||||
curl "https://api.dofusdb.fr/dungeons?$limit=200"
|
||||
|
||||
# Quêtes de recherchés (Avis de recherche)
|
||||
curl "https://api.dofusdb.fr/quests?categoryId=6"
|
||||
|
||||
# Items Dofus
|
||||
curl "https://api.dofusdb.fr/items?typeId=23&name.fr[\$regex]=Dofus"
|
||||
|
||||
# Monstres boss
|
||||
curl "https://api.dofusdb.fr/monsters?isBoss=true&$limit=50"
|
||||
```
|
||||
|
||||
### Notes d'implémentation
|
||||
|
||||
- Les quêtes Dofus ne sont pas directement liées aux items Dofus dans l'API → nécessite un mapping manuel
|
||||
- Les recherchés sont sous `categoryId=6` dans `/quests`
|
||||
- Les noms sont multilingues : utiliser `name.fr` pour le français
|
||||
- Pagination recommandée pour les gros volumes (achievements, monsters)
|
||||
|
||||
---
|
||||
|
||||
## Epic List
|
||||
|
||||
| # | Epic | Objectif |
|
||||
|---|------|----------|
|
||||
| **1** | **Foundation & Core Entities** | Établir le projet, le schéma DB, et le CRUD de base pour Serveurs, Comptes et Personnages |
|
||||
| **2** | **Teams & Constraints** | Implémenter la gestion des Teams avec validation de la contrainte compte |
|
||||
| **3** | **Filtering & Search** | Ajouter les filtres multicritères et la recherche textuelle sur la liste des personnages |
|
||||
| **4** | **Progression Tracking** | Tracker les progressions (quêtes Dofus, donjons, recherchés) par personnage |
|
||||
| **5** | **Currencies & Aggregations** | Gérer les monnaies par personnage et afficher les totaux agrégés |
|
||||
| **6** | **DofusDB Integration** | Intégrer l'API DofusDB pour les données de référence |
|
||||
|
||||
---
|
||||
|
||||
## Epic 1: Foundation & Core Entities
|
||||
|
||||
**Goal:** Établir les fondations du projet (setup, Docker, Prisma, CI/CD) et implémenter le CRUD complet pour les entités de base : Serveurs, Comptes et Personnages. À la fin de cet epic, l'utilisateur peut créer, consulter, modifier et supprimer des serveurs, comptes et personnages.
|
||||
|
||||
### Story 1.1: Project Setup & Infrastructure
|
||||
|
||||
**As a** developer,
|
||||
**I want** a fully configured TanStack Start project with Docker and GitLab CI,
|
||||
**so that** I can start development with a working local environment and deployment pipeline.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
1. TanStack Start project initialized with TypeScript strict mode
|
||||
2. Docker Compose configuration with app service and PostgreSQL 16
|
||||
3. Prisma configured and connected to PostgreSQL
|
||||
4. shadcn/ui installed with base components (Button, Input, Card, Table)
|
||||
5. ESLint + Prettier configured with recommended rules
|
||||
6. GitLab CI pipeline: build, lint, test stages
|
||||
7. Dockerfile multi-stage pour production build
|
||||
8. README avec instructions de setup local
|
||||
9. Application démarre et affiche une page d'accueil "Dofus Manager"
|
||||
|
||||
### Story 1.2: Database Schema - Core Entities
|
||||
|
||||
**As a** developer,
|
||||
**I want** a Prisma schema with Server, Account, and Character models,
|
||||
**so that** the data structure is defined and migrations are ready.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
1. Model `Server`: id, name, createdAt, updatedAt
|
||||
2. Model `Account`: id, name, ogrines (integer), createdAt, updatedAt
|
||||
3. Model `Character`: id, name, class (enum 17 classes), level (1-200), serverId (FK), accountId (FK), createdAt, updatedAt
|
||||
4. Enum `CharacterClass` avec les 17 classes Dofus
|
||||
5. Relations définies : Character → Server (N:1), Character → Account (N:1)
|
||||
6. Migration initiale générée et appliquée
|
||||
7. Seed script avec données de test (2 serveurs, 3 comptes, 10 personnages)
|
||||
|
||||
### Story 1.3: Server CRUD
|
||||
|
||||
**As a** user,
|
||||
**I want** to manage servers (create, view, edit, delete),
|
||||
**so that** I can add the Dofus servers I play on.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
1. Page `/servers` affiche la liste des serveurs en tableau
|
||||
2. Bouton "Ajouter" ouvre un formulaire modal de création
|
||||
3. Formulaire avec champ nom (requis, unique)
|
||||
4. Actions Edit/Delete sur chaque ligne (icônes au hover)
|
||||
5. Confirmation avant suppression
|
||||
6. Toast de confirmation après chaque action
|
||||
7. Validation : nom non vide, unicité vérifiée côté serveur
|
||||
8. Serveurs triés par nom alphabétique
|
||||
|
||||
### Story 1.4: Account CRUD
|
||||
|
||||
**As a** user,
|
||||
**I want** to manage my Dofus accounts (create, view, edit, delete),
|
||||
**so that** I can organize my characters by account.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
1. Page `/accounts` affiche la liste des comptes en tableau (nom, ogrines, nb personnages)
|
||||
2. Bouton "Ajouter" ouvre un formulaire modal de création
|
||||
3. Formulaire avec champs : nom (requis), ogrines (optionnel, défaut 0)
|
||||
4. Actions Edit/Delete sur chaque ligne
|
||||
5. Clic sur un compte navigue vers `/accounts/:id` (fiche détail)
|
||||
6. Page détail affiche infos compte + liste des personnages associés
|
||||
7. Suppression compte impossible si personnages associés (message d'erreur)
|
||||
8. Toast de confirmation après chaque action
|
||||
|
||||
### Story 1.5: Character CRUD
|
||||
|
||||
**As a** user,
|
||||
**I want** to manage my characters (create, view, edit, delete),
|
||||
**so that** I can track all my Dofus characters.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
1. Page `/characters` affiche la liste des personnages en tableau (nom, classe, niveau, serveur, compte)
|
||||
2. Bouton "Ajouter" ouvre un formulaire modal de création
|
||||
3. Formulaire avec champs : nom (requis), classe (select), niveau (1-200), serveur (select), compte (select)
|
||||
4. Actions Edit/Delete sur chaque ligne
|
||||
5. Clic sur un personnage navigue vers `/characters/:id` (fiche détail)
|
||||
6. Page détail affiche toutes les infos du personnage
|
||||
7. Icônes de classe affichées (optionnel: images ou emojis)
|
||||
8. Tableau paginé (20 items par page)
|
||||
9. Toast de confirmation après chaque action
|
||||
|
||||
### Story 1.6: Navigation & Layout
|
||||
|
||||
**As a** user,
|
||||
**I want** a consistent navigation layout,
|
||||
**so that** I can easily move between sections of the app.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
1. Sidebar de navigation avec liens : Dashboard, Personnages, Comptes, Serveurs
|
||||
2. Layout responsive : sidebar collapse sur mobile
|
||||
3. Breadcrumb sur les pages de détail
|
||||
4. Page active mise en évidence dans la sidebar
|
||||
5. Header avec titre de l'application
|
||||
6. Dark mode toggle (état persisté en localStorage)
|
||||
|
||||
---
|
||||
|
||||
## Epic 2: Teams & Constraints
|
||||
|
||||
**Goal:** Implémenter la gestion complète des Teams avec la règle métier fondamentale : impossible d'avoir 2 personnages du même compte dans une team active. L'utilisateur peut créer des teams, y ajouter des personnages, et voir le statut de complétion.
|
||||
|
||||
### Story 2.1: Team Database Schema
|
||||
|
||||
**As a** developer,
|
||||
**I want** a Prisma schema for Teams with many-to-many relation to Characters,
|
||||
**so that** teams can be created and managed.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
1. Model `Team`: id, name, type (enum: MAIN, SUCCESS, PL, CUSTOM), isActive (boolean), createdAt, updatedAt
|
||||
2. Relation many-to-many Team ↔ Character via table de jonction `TeamMember`
|
||||
3. Model `TeamMember`: teamId, characterId, joinedAt
|
||||
4. Enum `TeamType` avec les types identifiés (Main, Succès, PL, Custom)
|
||||
5. Migration générée et appliquée
|
||||
6. Seed script mis à jour avec 2-3 teams de test
|
||||
|
||||
### Story 2.2: Team CRUD - Basic
|
||||
|
||||
**As a** user,
|
||||
**I want** to create, view, edit and delete teams,
|
||||
**so that** I can organize my characters into groups.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
1. Page `/teams` affiche la liste des teams en tableau (nom, type, nb membres, statut actif)
|
||||
2. Bouton "Ajouter" ouvre un formulaire modal de création
|
||||
3. Formulaire avec champs : nom (requis), type (select), isActive (checkbox)
|
||||
4. Actions Edit/Delete sur chaque ligne
|
||||
5. Clic sur une team navigue vers `/teams/:id` (fiche détail)
|
||||
6. Suppression team supprime aussi les TeamMember associés
|
||||
7. Badge visuel pour teams actives vs inactives
|
||||
8. Toast de confirmation après chaque action
|
||||
|
||||
### Story 2.3: Team Member Management
|
||||
|
||||
**As a** user,
|
||||
**I want** to add and remove characters from a team,
|
||||
**so that** I can compose my teams.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
1. Page `/teams/:id` affiche la liste des membres actuels
|
||||
2. Bouton "Ajouter membre" ouvre un sélecteur de personnages
|
||||
3. Sélecteur filtrable par nom, classe, compte, serveur
|
||||
4. Multi-select possible pour ajouter plusieurs personnages à la fois
|
||||
5. Bouton "Retirer" sur chaque membre pour le supprimer de la team
|
||||
6. Affichage du compte de chaque personnage dans la liste des membres
|
||||
7. Ordre des membres modifiable (drag & drop optionnel, sinon ordre d'ajout)
|
||||
|
||||
### Story 2.4: Account Constraint Validation
|
||||
|
||||
**As a** user,
|
||||
**I want** the system to prevent adding two characters from the same account to an active team,
|
||||
**so that** I respect the game's simultaneous play restriction.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
1. Lors de l'ajout d'un membre, vérification que son compte n'est pas déjà dans la team
|
||||
2. Si conflit détecté : message d'erreur clair indiquant le personnage en conflit
|
||||
3. Validation côté serveur (impossible de contourner)
|
||||
4. Validation côté client pour feedback immédiat
|
||||
5. La contrainte ne s'applique qu'aux teams **actives** (isActive = true)
|
||||
6. Teams inactives peuvent avoir plusieurs persos du même compte (pour planification)
|
||||
7. Lors du passage d'une team inactive → active : vérification des conflits
|
||||
|
||||
### Story 2.5: Team Status Overview
|
||||
|
||||
**As a** user,
|
||||
**I want** to see a summary of each team's composition,
|
||||
**so that** I can quickly assess my teams.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
1. Sur `/teams`, colonnes : nom, type, membres (count), statut, classes représentées
|
||||
2. Sur `/teams/:id`, section récapitulative : nb membres, comptes utilisés, classes
|
||||
3. Indicateur visuel si team incomplète (< 8 membres pour type MAIN)
|
||||
4. Liste des comptes utilisés dans la team (pour éviter conflits lors de multi-boxing)
|
||||
5. Affichage des classes sous forme d'icônes compactes
|
||||
|
||||
---
|
||||
|
||||
## Epic 3: Filtering & Search
|
||||
|
||||
**Goal:** Ajouter un système de filtrage multicritères et de recherche textuelle sur la liste des personnages. L'utilisateur peut rapidement trouver les personnages qui correspondent à ses critères (classe, serveur, compte, team, etc.).
|
||||
|
||||
### Story 3.1: Filter Sidebar Component
|
||||
|
||||
**As a** user,
|
||||
**I want** a sidebar with filter options on the characters list,
|
||||
**so that** I can narrow down the displayed characters.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
1. Sidebar à gauche de la liste des personnages
|
||||
2. Section "Classe" : checkboxes pour chaque classe (17 classes)
|
||||
3. Section "Serveur" : checkboxes pour chaque serveur existant
|
||||
4. Section "Compte" : checkboxes pour chaque compte existant
|
||||
5. Section "Team" : checkboxes pour chaque team existante
|
||||
6. Section "Niveau" : slider ou inputs min/max (1-200)
|
||||
7. Bouton "Réinitialiser les filtres"
|
||||
8. Sidebar collapsible sur mobile (bouton toggle)
|
||||
9. Compteur de résultats mis à jour en temps réel
|
||||
|
||||
### Story 3.2: Filter Logic Implementation
|
||||
|
||||
**As a** developer,
|
||||
**I want** server-side filtering with URL state,
|
||||
**so that** filters are shareable and persist on refresh.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
1. Filtres stockés dans les query params de l'URL (ex: `?class=CRA,IOP&server=1`)
|
||||
2. API endpoint accepte les paramètres de filtre
|
||||
3. Requête Prisma optimisée avec WHERE dynamique
|
||||
4. Filtres combinés en AND (classe ET serveur ET compte...)
|
||||
5. Au sein d'un même filtre, valeurs combinées en OR (Cra OU Iop)
|
||||
6. État des filtres synchronisé avec l'URL au changement
|
||||
7. Chargement initial lit les filtres depuis l'URL
|
||||
8. Debounce sur les changements pour éviter trop de requêtes
|
||||
|
||||
### Story 3.3: Text Search
|
||||
|
||||
**As a** user,
|
||||
**I want** to search characters by name,
|
||||
**so that** I can quickly find a specific character.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
1. Champ de recherche au-dessus du tableau
|
||||
2. Recherche sur le nom du personnage (insensible à la casse)
|
||||
3. Recherche également sur le nom du compte
|
||||
4. Résultats filtrés en temps réel (debounce 300ms)
|
||||
5. Recherche combinable avec les filtres sidebar
|
||||
6. Icône "clear" pour vider la recherche
|
||||
7. Placeholder : "Rechercher un personnage..."
|
||||
8. Recherche stockée dans l'URL (`?q=...`)
|
||||
|
||||
### Story 3.4: Column Sorting
|
||||
|
||||
**As a** user,
|
||||
**I want** to sort the characters table by clicking column headers,
|
||||
**so that** I can organize the data as needed.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
1. Colonnes triables : nom, classe, niveau, serveur, compte
|
||||
2. Clic sur header = tri ascendant, second clic = descendant, troisième = reset
|
||||
3. Indicateur visuel de la colonne triée (flèche up/down)
|
||||
4. Tri côté serveur pour performance
|
||||
5. Tri par défaut : niveau descendant (200 en premier)
|
||||
6. Tri stocké dans l'URL (`?sort=level&order=desc`)
|
||||
7. Un seul tri actif à la fois
|
||||
|
||||
### Story 3.5: Saved Filter Presets
|
||||
|
||||
**As a** user,
|
||||
**I want** to save and reuse filter combinations,
|
||||
**so that** I don't have to reconfigure common filters.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
1. Bouton "Sauvegarder ce filtre" quand filtres actifs
|
||||
2. Modal pour nommer le preset
|
||||
3. Liste des presets sauvegardés dans la sidebar (section "Mes filtres")
|
||||
4. Clic sur preset applique tous ses filtres
|
||||
5. Bouton supprimer sur chaque preset
|
||||
6. Presets stockés en base de données (model `FilterPreset`)
|
||||
7. Limite de 10 presets maximum
|
||||
8. Presets spécifiques à l'utilisateur (pour futur multi-user)
|
||||
|
||||
---
|
||||
|
||||
## Epic 4: Progression Tracking
|
||||
|
||||
**Goal:** Implémenter le tracking des progressions par personnage : quêtes Dofus, donjons par paliers, et recherchés par région. L'utilisateur peut marquer les progressions comme complétées et voir les statistiques par team.
|
||||
|
||||
### Story 4.1: Progression Database Schema
|
||||
|
||||
**As a** developer,
|
||||
**I want** a flexible schema for tracking character progressions,
|
||||
**so that** different types of progressions can be managed uniformly.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
1. Model `ProgressionType`: id, category (enum: DOFUS_QUEST, DUNGEON, WANTED), name, region (nullable), levelRange (nullable), createdAt
|
||||
2. Model `CharacterProgression`: characterId, progressionTypeId, completed (boolean), completedAt (nullable)
|
||||
3. Enum `ProgressionCategory`: DOFUS_QUEST, DUNGEON, WANTED
|
||||
4. Index composite sur (characterId, progressionTypeId) pour performance
|
||||
5. Migration générée et appliquée
|
||||
6. Seed script avec données de progression types :
|
||||
- 10 quêtes Dofus (Turquoise, Pourpre, Émeraude, Glaces, Abyssal, Nébuleux, Domakuro, Dorigami, Tacheté, Vulbis)
|
||||
- Donjons par paliers (1-50, 51-100, 101-150, 151-190, 191-200)
|
||||
- Recherchés par région (Astrub, Amakna, Frigost I/II/III, etc.)
|
||||
|
||||
### Story 4.2: Character Progression View
|
||||
|
||||
**As a** user,
|
||||
**I want** to see and edit a character's progressions on their detail page,
|
||||
**so that** I can track what each character has completed.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
1. Section "Progressions" sur la page `/characters/:id`
|
||||
2. Onglets par catégorie : Quêtes Dofus | Donjons | Recherchés
|
||||
3. Liste des items avec checkbox pour marquer fait/pas fait
|
||||
4. Date de complétion affichée si complété
|
||||
5. Clic sur checkbox toggle l'état et sauvegarde immédiatement
|
||||
6. Compteur de progression par catégorie (ex: "7/10 Dofus")
|
||||
7. Filtres : Tous | Faits | Non faits
|
||||
8. Items triés par nom ou par ordre logique (niveau pour donjons)
|
||||
|
||||
### Story 4.3: Bulk Progression Update
|
||||
|
||||
**As a** user,
|
||||
**I want** to update progressions for multiple characters at once,
|
||||
**so that** I can quickly mark a dungeon done for my whole team.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
1. Page `/progressions/bulk` accessible depuis le menu
|
||||
2. Sélecteur de personnages (multi-select avec filtres)
|
||||
3. Sélection possible par team entière (bouton "Sélectionner team X")
|
||||
4. Sélecteur de progression type à mettre à jour
|
||||
5. Action : "Marquer comme fait" ou "Marquer comme non fait"
|
||||
6. Confirmation avant exécution avec récapitulatif (X personnages, progression Y)
|
||||
7. Toast de succès avec nombre de mises à jour effectuées
|
||||
8. Retour à la page précédente après action
|
||||
|
||||
### Story 4.4: Team Progression Status
|
||||
|
||||
**As a** user,
|
||||
**I want** to see the progression status of my team for a specific objective,
|
||||
**so that** I can see who still needs to complete it.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
1. Sur `/teams/:id`, nouvelle section "Statut des progressions"
|
||||
2. Sélecteur de progression type (ex: "Dofus Turquoise")
|
||||
3. Tableau : membres de la team avec statut (fait/pas fait) pour cette progression
|
||||
4. Pourcentage global affiché (ex: "6/8 = 75%")
|
||||
5. Indicateur visuel clair (vert = fait, rouge = pas fait)
|
||||
6. Bouton "Marquer fait pour tous" pour bulk update depuis cette vue
|
||||
7. Filtrable par catégorie de progression
|
||||
|
||||
### Story 4.5: Progression Filters in Character List
|
||||
|
||||
**As a** user,
|
||||
**I want** to filter characters by progression status,
|
||||
**so that** I can find who hasn't completed a specific objective.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
1. Nouvelle section dans la sidebar des filtres : "Progression"
|
||||
2. Sélecteur de progression type
|
||||
3. Options : "A fait" / "N'a pas fait"
|
||||
4. Combinable avec les autres filtres existants
|
||||
5. Exemple d'usage : "Montrer tous les Cra qui n'ont pas fait le Dofus Turquoise"
|
||||
6. Compteur de résultats mis à jour
|
||||
7. Filtre stocké dans l'URL
|
||||
|
||||
---
|
||||
|
||||
## Epic 5: Currencies & Aggregations
|
||||
|
||||
**Goal:** Implémenter le tracking des monnaies par personnage (Doplons, Orichor, etc.) et afficher les totaux agrégés au niveau compte et global. L'utilisateur peut rapidement voir combien de chaque monnaie il possède au total.
|
||||
|
||||
### Story 5.1: Currency Database Schema
|
||||
|
||||
**As a** developer,
|
||||
**I want** a schema for tracking currencies per character,
|
||||
**so that** currency amounts can be stored and aggregated.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
1. Model `CurrencyType`: id, name, icon (nullable), createdAt
|
||||
2. Model `CharacterCurrency`: characterId, currencyTypeId, amount (integer), updatedAt
|
||||
3. Contrainte unique sur (characterId, currencyTypeId)
|
||||
4. Migration générée et appliquée
|
||||
5. Seed script avec les 8 monnaies identifiées :
|
||||
- Doplons, Almatons, Orichor, Kamas de glace
|
||||
- Perles des profondeurs, Alitons, Trukdivins, Pages calendrier
|
||||
6. Index sur characterId pour requêtes d'agrégation
|
||||
|
||||
### Story 5.2: Character Currency View
|
||||
|
||||
**As a** user,
|
||||
**I want** to see and edit a character's currencies on their detail page,
|
||||
**so that** I can track each character's wealth.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
1. Section "Monnaies" sur la page `/characters/:id`
|
||||
2. Liste des monnaies avec champ input numérique pour chaque
|
||||
3. Modification inline avec sauvegarde au blur ou sur Enter
|
||||
4. Indicateur de sauvegarde (loading spinner pendant save)
|
||||
5. Validation : montant >= 0, entier uniquement
|
||||
6. Affichage de l'icône/nom de chaque monnaie
|
||||
7. Dernière mise à jour affichée par monnaie
|
||||
|
||||
### Story 5.3: Bulk Currency Update
|
||||
|
||||
**As a** user,
|
||||
**I want** to update a currency for multiple characters at once,
|
||||
**so that** I can quickly update after a group activity.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
1. Page `/currencies/bulk` accessible depuis le menu
|
||||
2. Sélecteur de personnages (multi-select avec filtres, sélection par team)
|
||||
3. Sélecteur de monnaie à mettre à jour
|
||||
4. Mode d'opération : "Définir à" (valeur absolue) ou "Ajouter/Soustraire" (delta)
|
||||
5. Champ pour la valeur
|
||||
6. Confirmation avant exécution
|
||||
7. Toast de succès avec récapitulatif
|
||||
8. Historique des bulk updates (optionnel, pour audit)
|
||||
|
||||
### Story 5.4: Account Currency Totals
|
||||
|
||||
**As a** user,
|
||||
**I want** to see the total currencies for each account,
|
||||
**so that** I can see my wealth per account.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
1. Sur `/accounts/:id`, section "Total des monnaies"
|
||||
2. Tableau avec chaque monnaie et le total pour ce compte
|
||||
3. Total = somme des monnaies de tous les personnages du compte
|
||||
4. Mise à jour automatique quand les données changent
|
||||
5. Affichage compact (icône + montant)
|
||||
6. Zéro affiché si aucun personnage n'a cette monnaie
|
||||
|
||||
### Story 5.5: Global Currency Dashboard
|
||||
|
||||
**As a** user,
|
||||
**I want** to see my total currencies across all characters,
|
||||
**so that** I have a global view of my in-game wealth.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
1. Widget sur le Dashboard (page d'accueil) : "Mes monnaies"
|
||||
2. Liste de toutes les monnaies avec total global
|
||||
3. Total global = somme sur tous les personnages
|
||||
4. Possibilité de cliquer pour voir le détail par compte
|
||||
5. Drill-down : compte → personnages avec leurs montants
|
||||
6. Données mises en cache pour performance (invalidation au changement)
|
||||
|
||||
### Story 5.6: Currency Management (Admin)
|
||||
|
||||
**As a** user,
|
||||
**I want** to add or remove currency types,
|
||||
**so that** I can adapt to game updates adding new currencies.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
1. Page `/settings/currencies` pour gérer les types de monnaies
|
||||
2. Liste des monnaies existantes
|
||||
3. Formulaire d'ajout : nom, icône (optionnel)
|
||||
4. Suppression possible si aucun personnage n'a cette monnaie
|
||||
5. Avertissement si suppression avec données existantes
|
||||
6. Ordre d'affichage modifiable (drag & drop ou champ order)
|
||||
|
||||
---
|
||||
|
||||
## Epic 6: DofusDB Integration
|
||||
|
||||
**Goal:** Intégrer l'API DofusDB pour importer automatiquement les données de référence du jeu (quêtes, donjons, succès, recherchés). L'utilisateur n'a plus besoin de saisir manuellement ces informations.
|
||||
|
||||
### Story 6.1: DofusDB API Client
|
||||
|
||||
**As a** developer,
|
||||
**I want** a typed HTTP client for the DofusDB API,
|
||||
**so that** I can fetch game reference data reliably.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
1. Module `lib/dofusdb.ts` avec client HTTP typé
|
||||
2. Types TypeScript pour les réponses API (quêtes, donjons, succès, etc.)
|
||||
3. Gestion des erreurs API (timeout, rate limit, 404)
|
||||
4. Configuration via variables d'environnement (API URL, éventuels tokens)
|
||||
5. Retry automatique en cas d'échec temporaire (max 3 retries)
|
||||
6. Logging des appels API pour debug
|
||||
7. Tests unitaires avec mocks des réponses API
|
||||
|
||||
### Story 6.2: Dungeon Data Import
|
||||
|
||||
**As a** user,
|
||||
**I want** to import the list of dungeons from DofusDB,
|
||||
**so that** I don't have to add them manually.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
1. Endpoint ou script pour importer les donjons depuis DofusDB
|
||||
2. Mapping des données DofusDB vers le model `ProgressionType` (category: DUNGEON)
|
||||
3. Import des métadonnées : nom, niveau requis, zone/région
|
||||
4. Gestion des doublons : mise à jour si existant, création sinon
|
||||
5. Rapport d'import : X créés, Y mis à jour, Z erreurs
|
||||
6. Bouton "Importer donjons" dans `/settings/data`
|
||||
7. Indicateur de dernière synchronisation
|
||||
|
||||
### Story 6.3: Quest Data Import
|
||||
|
||||
**As a** user,
|
||||
**I want** to import Dofus quest chains from DofusDB,
|
||||
**so that** I can track my progress on main quests.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
1. Import des quêtes Dofus (les 10 quêtes principales identifiées)
|
||||
2. Mapping vers `ProgressionType` (category: DOFUS_QUEST)
|
||||
3. Import des métadonnées : nom, Dofus associé
|
||||
4. Option de filtrer quelles quêtes importer (sélection manuelle ou toutes)
|
||||
5. Gestion des doublons
|
||||
6. Bouton "Importer quêtes" dans `/settings/data`
|
||||
7. Rapport d'import
|
||||
|
||||
### Story 6.4: Wanted Posters Import
|
||||
|
||||
**As a** user,
|
||||
**I want** to import wanted poster data from DofusDB,
|
||||
**so that** I can track bounties by region.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
1. Import des recherchés par région depuis DofusDB
|
||||
2. Mapping vers `ProgressionType` (category: WANTED)
|
||||
3. Métadonnées : nom, région associée
|
||||
4. Regroupement par région (Astrub, Amakna, Frigost I/II/III, etc.)
|
||||
5. Gestion des doublons
|
||||
6. Bouton "Importer recherchés" dans `/settings/data`
|
||||
7. Rapport d'import
|
||||
|
||||
### Story 6.5: Sync Settings & Automation
|
||||
|
||||
**As a** user,
|
||||
**I want** to configure automatic synchronization with DofusDB,
|
||||
**so that** my reference data stays up to date.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
1. Page `/settings/data` avec configuration de sync
|
||||
2. Option sync manuelle (boutons par type de données)
|
||||
3. Option sync automatique périodique (daily, weekly, disabled)
|
||||
4. Cron job ou scheduled task pour sync auto
|
||||
5. Notification (toast ou log) après sync automatique
|
||||
6. Historique des syncs (date, type, résultat)
|
||||
7. Option de réinitialiser toutes les données de référence
|
||||
|
||||
### Story 6.6: Data Conflict Resolution
|
||||
|
||||
**As a** developer,
|
||||
**I want** a strategy for handling conflicts between local and API data,
|
||||
**so that** user modifications aren't lost during sync.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
1. Les `ProgressionType` importés ont un flag `source: API | MANUAL`
|
||||
2. Sync API ne modifie que les entrées `source: API`
|
||||
3. Entrées `source: MANUAL` préservées lors du sync
|
||||
4. Option de forcer l'écrasement (avec confirmation)
|
||||
5. Détection des entrées supprimées de l'API (soft delete ou warning)
|
||||
6. Log des conflits détectés pour review
|
||||
|
||||
---
|
||||
|
||||
## Checklist Results Report
|
||||
|
||||
### Executive Summary
|
||||
|
||||
| Metric | Value |
|
||||
|--------|-------|
|
||||
| **Overall PRD Completeness** | 95% |
|
||||
| **MVP Scope Appropriateness** | Just Right |
|
||||
| **Readiness for Architecture** | Ready |
|
||||
| **DofusDB API** | ✅ Validée et documentée |
|
||||
|
||||
### Category Analysis
|
||||
|
||||
| Category | Status | Notes |
|
||||
|----------|--------|-------|
|
||||
| 1. Problem Definition & Context | PASS | Problème clairement articulé, utilisateur cible défini |
|
||||
| 2. MVP Scope Definition | PASS | 6 epics bien délimités, scope MVP réaliste |
|
||||
| 3. User Experience Requirements | PASS | Flows documentés, paradigmes d'interaction définis |
|
||||
| 4. Functional Requirements | PASS | 13 FR + 8 NFR, tous testables |
|
||||
| 5. Non-Functional Requirements | PARTIAL | Performance OK, sécurité minimale (mono-user) |
|
||||
| 6. Epic & Story Structure | PASS | 6 epics séquentiels, 27 stories avec AC détaillés |
|
||||
| 7. Technical Guidance | PASS | Stack définie, architecture monolith documentée |
|
||||
| 8. Cross-Functional Requirements | PASS | Intégration DofusDB, schéma DB complet |
|
||||
| 9. Clarity & Communication | PASS | Document structuré, terminologie cohérente |
|
||||
|
||||
### Issues Identified
|
||||
|
||||
| Priority | Issue | Status |
|
||||
|----------|-------|--------|
|
||||
| ~~HIGH~~ | ~~API DofusDB non validée~~ | ✅ Résolu — Documentation ajoutée |
|
||||
| MEDIUM | Métriques de succès non formalisées | À définir post-MVP |
|
||||
| MEDIUM | Stratégie backup non détaillée | À documenter dans architecture |
|
||||
| LOW | Seed data à compléter | À préciser lors de l'implémentation |
|
||||
|
||||
### Final Decision
|
||||
|
||||
**✅ READY FOR ARCHITECT** — Le PRD est complet et prêt pour la phase d'architecture.
|
||||
|
||||
---
|
||||
|
||||
## Next Steps
|
||||
|
||||
### UX Expert Prompt
|
||||
|
||||
```
|
||||
Je travaille sur Dofus Manager, une application web de gestion de personnages pour le MMORPG Dofus.
|
||||
|
||||
Contexte : L'application remplace un tableur Excel pour gérer 60+ personnages sur plusieurs comptes. Les fonctionnalités clés sont :
|
||||
- CRUD pour Serveurs, Comptes, Personnages, Teams
|
||||
- Filtrage multicritères et recherche
|
||||
- Tracking des progressions (quêtes, donjons, recherchés)
|
||||
- Gestion des monnaies avec agrégations
|
||||
- Validation de contrainte : pas 2 persos du même compte dans une team active
|
||||
|
||||
Design goals :
|
||||
- Desktop-first, responsive tablette
|
||||
- Dense en informations, inspiré outils pro
|
||||
- Filtres sidebar façon e-commerce
|
||||
- Multi-select et bulk actions façon Gmail
|
||||
- shadcn/ui comme design system
|
||||
|
||||
Peux-tu créer les wireframes ou maquettes pour les écrans principaux :
|
||||
1. Liste des personnages avec filtres
|
||||
2. Fiche personnage (infos + progressions + monnaies)
|
||||
3. Gestion des teams avec validation contrainte
|
||||
|
||||
Le PRD complet est disponible dans docs/prd.md
|
||||
```
|
||||
|
||||
### Architect Prompt
|
||||
|
||||
```
|
||||
Je travaille sur Dofus Manager, une application web full-stack pour gérer des personnages de MMORPG.
|
||||
|
||||
Stack technique validée :
|
||||
- Framework : TanStack Start (React full-stack, TypeScript)
|
||||
- ORM : Prisma avec PostgreSQL 16
|
||||
- UI : shadcn/ui + TanStack Table
|
||||
- Infra : Docker, Traefik, GitLab CI
|
||||
|
||||
Contexte métier :
|
||||
- 60+ personnages, dizaines de comptes, plusieurs serveurs
|
||||
- Teams avec contrainte : pas 2 persos du même compte simultanément
|
||||
- Progressions (quêtes, donjons, recherchés) et monnaies à tracker
|
||||
- Intégration API DofusDB pour données de référence
|
||||
|
||||
Besoins architecture :
|
||||
1. Schéma Prisma complet pour les entités (Server, Account, Character, Team, ProgressionType, CurrencyType, etc.)
|
||||
2. Structure du projet TanStack Start
|
||||
3. Patterns pour server functions et data fetching
|
||||
4. Stratégie de cache pour agrégations
|
||||
5. Configuration Docker + GitLab CI
|
||||
|
||||
Le PRD complet avec les 6 epics et 27 stories est disponible dans docs/prd.md.
|
||||
Peux-tu initier le mode architecture et proposer une conception technique ?
|
||||
```
|
||||
|
||||
39
docs/prd/checklist-results-report.md
Normal file
39
docs/prd/checklist-results-report.md
Normal file
@@ -0,0 +1,39 @@
|
||||
# Checklist Results Report
|
||||
|
||||
## Executive Summary
|
||||
|
||||
| Metric | Value |
|
||||
|--------|-------|
|
||||
| **Overall PRD Completeness** | 95% |
|
||||
| **MVP Scope Appropriateness** | Just Right |
|
||||
| **Readiness for Architecture** | Ready |
|
||||
| **DofusDB API** | ✅ Validée et documentée |
|
||||
|
||||
## Category Analysis
|
||||
|
||||
| Category | Status | Notes |
|
||||
|----------|--------|-------|
|
||||
| 1. Problem Definition & Context | PASS | Problème clairement articulé, utilisateur cible défini |
|
||||
| 2. MVP Scope Definition | PASS | 6 epics bien délimités, scope MVP réaliste |
|
||||
| 3. User Experience Requirements | PASS | Flows documentés, paradigmes d'interaction définis |
|
||||
| 4. Functional Requirements | PASS | 13 FR + 8 NFR, tous testables |
|
||||
| 5. Non-Functional Requirements | PARTIAL | Performance OK, sécurité minimale (mono-user) |
|
||||
| 6. Epic & Story Structure | PASS | 6 epics séquentiels, 27 stories avec AC détaillés |
|
||||
| 7. Technical Guidance | PASS | Stack définie, architecture monolith documentée |
|
||||
| 8. Cross-Functional Requirements | PASS | Intégration DofusDB, schéma DB complet |
|
||||
| 9. Clarity & Communication | PASS | Document structuré, terminologie cohérente |
|
||||
|
||||
## Issues Identified
|
||||
|
||||
| Priority | Issue | Status |
|
||||
|----------|-------|--------|
|
||||
| ~~HIGH~~ | ~~API DofusDB non validée~~ | ✅ Résolu — Documentation ajoutée |
|
||||
| MEDIUM | Métriques de succès non formalisées | À définir post-MVP |
|
||||
| MEDIUM | Stratégie backup non détaillée | À documenter dans architecture |
|
||||
| LOW | Seed data à compléter | À préciser lors de l'implémentation |
|
||||
|
||||
## Final Decision
|
||||
|
||||
**✅ READY FOR ARCHITECT** — Le PRD est complet et prêt pour la phase d'architecture.
|
||||
|
||||
---
|
||||
77
docs/prd/dofusdb-api-reference.md
Normal file
77
docs/prd/dofusdb-api-reference.md
Normal file
@@ -0,0 +1,77 @@
|
||||
# DofusDB API Reference
|
||||
|
||||
Documentation de l'API externe utilisée pour l'Epic 6.
|
||||
|
||||
## Base URL
|
||||
|
||||
`https://api.dofusdb.fr/`
|
||||
|
||||
## Caractéristiques techniques
|
||||
|
||||
- **Framework:** FeathersJS (REST API)
|
||||
- **Pagination:** `$limit`, `$skip` (défaut: limit=10)
|
||||
- **Filtrage:** Style MongoDB (`$regex`, `$in`, `$gt`, etc.)
|
||||
- **Multilingue:** `name.fr`, `name.en`, `name.de`, `name.es`, `name.pt`
|
||||
- **Authentification:** Aucune (API publique)
|
||||
|
||||
## Endpoints disponibles
|
||||
|
||||
| Endpoint | Total | Champs clés |
|
||||
|----------|-------|-------------|
|
||||
| `/dungeons` | 187 | id, name, optimalPlayerLevel, monsters[], subarea |
|
||||
| `/quests` | 1978 | id, name, categoryId, levelMin, levelMax, steps[], rewards[] |
|
||||
| `/achievements` | 2788 | id, name, description, level, points, categoryId, rewards[] |
|
||||
| `/monsters` | 5093 | id, name, level, isBoss, stats, drops[], subareas[] |
|
||||
| `/items` | — | id, name, typeId (23 = Dofus trophées) |
|
||||
| `/quest-categories` | 43+ | id, name (régions, types de quêtes) |
|
||||
| `/achievement-categories` | 129 | id, name, parentId |
|
||||
|
||||
## Mapping pour le PRD
|
||||
|
||||
| Besoin PRD | Endpoint DofusDB | Query |
|
||||
|------------|------------------|-------|
|
||||
| **Donjons** | `/dungeons` | `?$limit=200` |
|
||||
| **Recherchés** | `/quests` | `?categoryId=6` |
|
||||
| **Items Dofus** | `/items` | `?typeId=23&name.fr[$regex]=Dofus` |
|
||||
| **Succès donjons** | `/achievements` | `?categoryId=3` |
|
||||
|
||||
## Dofus identifiés
|
||||
|
||||
| ID Item | Nom |
|
||||
|---------|-----|
|
||||
| 739 | Dofus Turquoise |
|
||||
| 694 | Dofus Pourpre |
|
||||
| 737 | Dofus Émeraude |
|
||||
| 7043 | Dofus des Glaces |
|
||||
| 18043 | Dofus Abyssal |
|
||||
| 8698 | Dofus Nébuleux |
|
||||
| 7112 | Dofus Tacheté |
|
||||
| 6980 | Dofus Vulbis |
|
||||
| 7754 | Dofus Ocre |
|
||||
| 7114 | Dofus Ébène |
|
||||
| 7115 | Dofus Ivoire |
|
||||
|
||||
## Exemples de requêtes
|
||||
|
||||
```bash
|
||||
# Tous les donjons
|
||||
curl "https://api.dofusdb.fr/dungeons?$limit=200"
|
||||
|
||||
# Quêtes de recherchés (Avis de recherche)
|
||||
curl "https://api.dofusdb.fr/quests?categoryId=6"
|
||||
|
||||
# Items Dofus
|
||||
curl "https://api.dofusdb.fr/items?typeId=23&name.fr[\$regex]=Dofus"
|
||||
|
||||
# Monstres boss
|
||||
curl "https://api.dofusdb.fr/monsters?isBoss=true&$limit=50"
|
||||
```
|
||||
|
||||
## Notes d'implémentation
|
||||
|
||||
- Les quêtes Dofus ne sont pas directement liées aux items Dofus dans l'API → nécessite un mapping manuel
|
||||
- Les recherchés sont sous `categoryId=6` dans `/quests`
|
||||
- Les noms sont multilingues : utiliser `name.fr` pour le français
|
||||
- Pagination recommandée pour les gros volumes (achievements, monsters)
|
||||
|
||||
---
|
||||
100
docs/prd/epic-1-foundation-core-entities.md
Normal file
100
docs/prd/epic-1-foundation-core-entities.md
Normal file
@@ -0,0 +1,100 @@
|
||||
# Epic 1: Foundation & Core Entities
|
||||
|
||||
**Goal:** Établir les fondations du projet (setup, Docker, Prisma, CI/CD) et implémenter le CRUD complet pour les entités de base : Serveurs, Comptes et Personnages. À la fin de cet epic, l'utilisateur peut créer, consulter, modifier et supprimer des serveurs, comptes et personnages.
|
||||
|
||||
## Story 1.1: Project Setup & Infrastructure
|
||||
|
||||
**As a** developer,
|
||||
**I want** a fully configured TanStack Start project with Docker and GitLab CI,
|
||||
**so that** I can start development with a working local environment and deployment pipeline.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
1. TanStack Start project initialized with TypeScript strict mode
|
||||
2. Docker Compose configuration with app service and PostgreSQL 16
|
||||
3. Prisma configured and connected to PostgreSQL
|
||||
4. shadcn/ui installed with base components (Button, Input, Card, Table)
|
||||
5. ESLint + Prettier configured with recommended rules
|
||||
6. GitLab CI pipeline: build, lint, test stages
|
||||
7. Dockerfile multi-stage pour production build
|
||||
8. README avec instructions de setup local
|
||||
9. Application démarre et affiche une page d'accueil "Dofus Manager"
|
||||
|
||||
## Story 1.2: Database Schema - Core Entities
|
||||
|
||||
**As a** developer,
|
||||
**I want** a Prisma schema with Server, Account, and Character models,
|
||||
**so that** the data structure is defined and migrations are ready.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
1. Model `Server`: id, name, createdAt, updatedAt
|
||||
2. Model `Account`: id, name, ogrines (integer), createdAt, updatedAt
|
||||
3. Model `Character`: id, name, class (enum 17 classes), level (1-200), serverId (FK), accountId (FK), createdAt, updatedAt
|
||||
4. Enum `CharacterClass` avec les 17 classes Dofus
|
||||
5. Relations définies : Character → Server (N:1), Character → Account (N:1)
|
||||
6. Migration initiale générée et appliquée
|
||||
7. Seed script avec données de test (2 serveurs, 3 comptes, 10 personnages)
|
||||
|
||||
## Story 1.3: Server CRUD
|
||||
|
||||
**As a** user,
|
||||
**I want** to manage servers (create, view, edit, delete),
|
||||
**so that** I can add the Dofus servers I play on.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
1. Page `/servers` affiche la liste des serveurs en tableau
|
||||
2. Bouton "Ajouter" ouvre un formulaire modal de création
|
||||
3. Formulaire avec champ nom (requis, unique)
|
||||
4. Actions Edit/Delete sur chaque ligne (icônes au hover)
|
||||
5. Confirmation avant suppression
|
||||
6. Toast de confirmation après chaque action
|
||||
7. Validation : nom non vide, unicité vérifiée côté serveur
|
||||
8. Serveurs triés par nom alphabétique
|
||||
|
||||
## Story 1.4: Account CRUD
|
||||
|
||||
**As a** user,
|
||||
**I want** to manage my Dofus accounts (create, view, edit, delete),
|
||||
**so that** I can organize my characters by account.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
1. Page `/accounts` affiche la liste des comptes en tableau (nom, ogrines, nb personnages)
|
||||
2. Bouton "Ajouter" ouvre un formulaire modal de création
|
||||
3. Formulaire avec champs : nom (requis), ogrines (optionnel, défaut 0)
|
||||
4. Actions Edit/Delete sur chaque ligne
|
||||
5. Clic sur un compte navigue vers `/accounts/:id` (fiche détail)
|
||||
6. Page détail affiche infos compte + liste des personnages associés
|
||||
7. Suppression compte impossible si personnages associés (message d'erreur)
|
||||
8. Toast de confirmation après chaque action
|
||||
|
||||
## Story 1.5: Character CRUD
|
||||
|
||||
**As a** user,
|
||||
**I want** to manage my characters (create, view, edit, delete),
|
||||
**so that** I can track all my Dofus characters.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
1. Page `/characters` affiche la liste des personnages en tableau (nom, classe, niveau, serveur, compte)
|
||||
2. Bouton "Ajouter" ouvre un formulaire modal de création
|
||||
3. Formulaire avec champs : nom (requis), classe (select), niveau (1-200), serveur (select), compte (select)
|
||||
4. Actions Edit/Delete sur chaque ligne
|
||||
5. Clic sur un personnage navigue vers `/characters/:id` (fiche détail)
|
||||
6. Page détail affiche toutes les infos du personnage
|
||||
7. Icônes de classe affichées (optionnel: images ou emojis)
|
||||
8. Tableau paginé (20 items par page)
|
||||
9. Toast de confirmation après chaque action
|
||||
|
||||
## Story 1.6: Navigation & Layout
|
||||
|
||||
**As a** user,
|
||||
**I want** a consistent navigation layout,
|
||||
**so that** I can easily move between sections of the app.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
1. Sidebar de navigation avec liens : Dashboard, Personnages, Comptes, Serveurs
|
||||
2. Layout responsive : sidebar collapse sur mobile
|
||||
3. Breadcrumb sur les pages de détail
|
||||
4. Page active mise en évidence dans la sidebar
|
||||
5. Header avec titre de l'application
|
||||
6. Dark mode toggle (état persisté en localStorage)
|
||||
|
||||
---
|
||||
78
docs/prd/epic-2-teams-constraints.md
Normal file
78
docs/prd/epic-2-teams-constraints.md
Normal file
@@ -0,0 +1,78 @@
|
||||
# Epic 2: Teams & Constraints
|
||||
|
||||
**Goal:** Implémenter la gestion complète des Teams avec la règle métier fondamentale : impossible d'avoir 2 personnages du même compte dans une team active. L'utilisateur peut créer des teams, y ajouter des personnages, et voir le statut de complétion.
|
||||
|
||||
## Story 2.1: Team Database Schema
|
||||
|
||||
**As a** developer,
|
||||
**I want** a Prisma schema for Teams with many-to-many relation to Characters,
|
||||
**so that** teams can be created and managed.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
1. Model `Team`: id, name, type (enum: MAIN, SUCCESS, PL, CUSTOM), isActive (boolean), createdAt, updatedAt
|
||||
2. Relation many-to-many Team ↔ Character via table de jonction `TeamMember`
|
||||
3. Model `TeamMember`: teamId, characterId, joinedAt
|
||||
4. Enum `TeamType` avec les types identifiés (Main, Succès, PL, Custom)
|
||||
5. Migration générée et appliquée
|
||||
6. Seed script mis à jour avec 2-3 teams de test
|
||||
|
||||
## Story 2.2: Team CRUD - Basic
|
||||
|
||||
**As a** user,
|
||||
**I want** to create, view, edit and delete teams,
|
||||
**so that** I can organize my characters into groups.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
1. Page `/teams` affiche la liste des teams en tableau (nom, type, nb membres, statut actif)
|
||||
2. Bouton "Ajouter" ouvre un formulaire modal de création
|
||||
3. Formulaire avec champs : nom (requis), type (select), isActive (checkbox)
|
||||
4. Actions Edit/Delete sur chaque ligne
|
||||
5. Clic sur une team navigue vers `/teams/:id` (fiche détail)
|
||||
6. Suppression team supprime aussi les TeamMember associés
|
||||
7. Badge visuel pour teams actives vs inactives
|
||||
8. Toast de confirmation après chaque action
|
||||
|
||||
## Story 2.3: Team Member Management
|
||||
|
||||
**As a** user,
|
||||
**I want** to add and remove characters from a team,
|
||||
**so that** I can compose my teams.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
1. Page `/teams/:id` affiche la liste des membres actuels
|
||||
2. Bouton "Ajouter membre" ouvre un sélecteur de personnages
|
||||
3. Sélecteur filtrable par nom, classe, compte, serveur
|
||||
4. Multi-select possible pour ajouter plusieurs personnages à la fois
|
||||
5. Bouton "Retirer" sur chaque membre pour le supprimer de la team
|
||||
6. Affichage du compte de chaque personnage dans la liste des membres
|
||||
7. Ordre des membres modifiable (drag & drop optionnel, sinon ordre d'ajout)
|
||||
|
||||
## Story 2.4: Account Constraint Validation
|
||||
|
||||
**As a** user,
|
||||
**I want** the system to prevent adding two characters from the same account to an active team,
|
||||
**so that** I respect the game's simultaneous play restriction.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
1. Lors de l'ajout d'un membre, vérification que son compte n'est pas déjà dans la team
|
||||
2. Si conflit détecté : message d'erreur clair indiquant le personnage en conflit
|
||||
3. Validation côté serveur (impossible de contourner)
|
||||
4. Validation côté client pour feedback immédiat
|
||||
5. La contrainte ne s'applique qu'aux teams **actives** (isActive = true)
|
||||
6. Teams inactives peuvent avoir plusieurs persos du même compte (pour planification)
|
||||
7. Lors du passage d'une team inactive → active : vérification des conflits
|
||||
|
||||
## Story 2.5: Team Status Overview
|
||||
|
||||
**As a** user,
|
||||
**I want** to see a summary of each team's composition,
|
||||
**so that** I can quickly assess my teams.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
1. Sur `/teams`, colonnes : nom, type, membres (count), statut, classes représentées
|
||||
2. Sur `/teams/:id`, section récapitulative : nb membres, comptes utilisés, classes
|
||||
3. Indicateur visuel si team incomplète (< 8 membres pour type MAIN)
|
||||
4. Liste des comptes utilisés dans la team (pour éviter conflits lors de multi-boxing)
|
||||
5. Affichage des classes sous forme d'icônes compactes
|
||||
|
||||
---
|
||||
85
docs/prd/epic-3-filtering-search.md
Normal file
85
docs/prd/epic-3-filtering-search.md
Normal file
@@ -0,0 +1,85 @@
|
||||
# Epic 3: Filtering & Search
|
||||
|
||||
**Goal:** Ajouter un système de filtrage multicritères et de recherche textuelle sur la liste des personnages. L'utilisateur peut rapidement trouver les personnages qui correspondent à ses critères (classe, serveur, compte, team, etc.).
|
||||
|
||||
## Story 3.1: Filter Sidebar Component
|
||||
|
||||
**As a** user,
|
||||
**I want** a sidebar with filter options on the characters list,
|
||||
**so that** I can narrow down the displayed characters.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
1. Sidebar à gauche de la liste des personnages
|
||||
2. Section "Classe" : checkboxes pour chaque classe (17 classes)
|
||||
3. Section "Serveur" : checkboxes pour chaque serveur existant
|
||||
4. Section "Compte" : checkboxes pour chaque compte existant
|
||||
5. Section "Team" : checkboxes pour chaque team existante
|
||||
6. Section "Niveau" : slider ou inputs min/max (1-200)
|
||||
7. Bouton "Réinitialiser les filtres"
|
||||
8. Sidebar collapsible sur mobile (bouton toggle)
|
||||
9. Compteur de résultats mis à jour en temps réel
|
||||
|
||||
## Story 3.2: Filter Logic Implementation
|
||||
|
||||
**As a** developer,
|
||||
**I want** server-side filtering with URL state,
|
||||
**so that** filters are shareable and persist on refresh.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
1. Filtres stockés dans les query params de l'URL (ex: `?class=CRA,IOP&server=1`)
|
||||
2. API endpoint accepte les paramètres de filtre
|
||||
3. Requête Prisma optimisée avec WHERE dynamique
|
||||
4. Filtres combinés en AND (classe ET serveur ET compte...)
|
||||
5. Au sein d'un même filtre, valeurs combinées en OR (Cra OU Iop)
|
||||
6. État des filtres synchronisé avec l'URL au changement
|
||||
7. Chargement initial lit les filtres depuis l'URL
|
||||
8. Debounce sur les changements pour éviter trop de requêtes
|
||||
|
||||
## Story 3.3: Text Search
|
||||
|
||||
**As a** user,
|
||||
**I want** to search characters by name,
|
||||
**so that** I can quickly find a specific character.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
1. Champ de recherche au-dessus du tableau
|
||||
2. Recherche sur le nom du personnage (insensible à la casse)
|
||||
3. Recherche également sur le nom du compte
|
||||
4. Résultats filtrés en temps réel (debounce 300ms)
|
||||
5. Recherche combinable avec les filtres sidebar
|
||||
6. Icône "clear" pour vider la recherche
|
||||
7. Placeholder : "Rechercher un personnage..."
|
||||
8. Recherche stockée dans l'URL (`?q=...`)
|
||||
|
||||
## Story 3.4: Column Sorting
|
||||
|
||||
**As a** user,
|
||||
**I want** to sort the characters table by clicking column headers,
|
||||
**so that** I can organize the data as needed.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
1. Colonnes triables : nom, classe, niveau, serveur, compte
|
||||
2. Clic sur header = tri ascendant, second clic = descendant, troisième = reset
|
||||
3. Indicateur visuel de la colonne triée (flèche up/down)
|
||||
4. Tri côté serveur pour performance
|
||||
5. Tri par défaut : niveau descendant (200 en premier)
|
||||
6. Tri stocké dans l'URL (`?sort=level&order=desc`)
|
||||
7. Un seul tri actif à la fois
|
||||
|
||||
## Story 3.5: Saved Filter Presets
|
||||
|
||||
**As a** user,
|
||||
**I want** to save and reuse filter combinations,
|
||||
**so that** I don't have to reconfigure common filters.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
1. Bouton "Sauvegarder ce filtre" quand filtres actifs
|
||||
2. Modal pour nommer le preset
|
||||
3. Liste des presets sauvegardés dans la sidebar (section "Mes filtres")
|
||||
4. Clic sur preset applique tous ses filtres
|
||||
5. Bouton supprimer sur chaque preset
|
||||
6. Presets stockés en base de données (model `FilterPreset`)
|
||||
7. Limite de 10 presets maximum
|
||||
8. Presets spécifiques à l'utilisateur (pour futur multi-user)
|
||||
|
||||
---
|
||||
84
docs/prd/epic-4-progression-tracking.md
Normal file
84
docs/prd/epic-4-progression-tracking.md
Normal file
@@ -0,0 +1,84 @@
|
||||
# Epic 4: Progression Tracking
|
||||
|
||||
**Goal:** Implémenter le tracking des progressions par personnage : quêtes Dofus, donjons par paliers, et recherchés par région. L'utilisateur peut marquer les progressions comme complétées et voir les statistiques par team.
|
||||
|
||||
## Story 4.1: Progression Database Schema
|
||||
|
||||
**As a** developer,
|
||||
**I want** a flexible schema for tracking character progressions,
|
||||
**so that** different types of progressions can be managed uniformly.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
1. Model `ProgressionType`: id, category (enum: DOFUS_QUEST, DUNGEON, WANTED), name, region (nullable), levelRange (nullable), createdAt
|
||||
2. Model `CharacterProgression`: characterId, progressionTypeId, completed (boolean), completedAt (nullable)
|
||||
3. Enum `ProgressionCategory`: DOFUS_QUEST, DUNGEON, WANTED
|
||||
4. Index composite sur (characterId, progressionTypeId) pour performance
|
||||
5. Migration générée et appliquée
|
||||
6. Seed script avec données de progression types :
|
||||
- 10 quêtes Dofus (Turquoise, Pourpre, Émeraude, Glaces, Abyssal, Nébuleux, Domakuro, Dorigami, Tacheté, Vulbis)
|
||||
- Donjons par paliers (1-50, 51-100, 101-150, 151-190, 191-200)
|
||||
- Recherchés par région (Astrub, Amakna, Frigost I/II/III, etc.)
|
||||
|
||||
## Story 4.2: Character Progression View
|
||||
|
||||
**As a** user,
|
||||
**I want** to see and edit a character's progressions on their detail page,
|
||||
**so that** I can track what each character has completed.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
1. Section "Progressions" sur la page `/characters/:id`
|
||||
2. Onglets par catégorie : Quêtes Dofus | Donjons | Recherchés
|
||||
3. Liste des items avec checkbox pour marquer fait/pas fait
|
||||
4. Date de complétion affichée si complété
|
||||
5. Clic sur checkbox toggle l'état et sauvegarde immédiatement
|
||||
6. Compteur de progression par catégorie (ex: "7/10 Dofus")
|
||||
7. Filtres : Tous | Faits | Non faits
|
||||
8. Items triés par nom ou par ordre logique (niveau pour donjons)
|
||||
|
||||
## Story 4.3: Bulk Progression Update
|
||||
|
||||
**As a** user,
|
||||
**I want** to update progressions for multiple characters at once,
|
||||
**so that** I can quickly mark a dungeon done for my whole team.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
1. Page `/progressions/bulk` accessible depuis le menu
|
||||
2. Sélecteur de personnages (multi-select avec filtres)
|
||||
3. Sélection possible par team entière (bouton "Sélectionner team X")
|
||||
4. Sélecteur de progression type à mettre à jour
|
||||
5. Action : "Marquer comme fait" ou "Marquer comme non fait"
|
||||
6. Confirmation avant exécution avec récapitulatif (X personnages, progression Y)
|
||||
7. Toast de succès avec nombre de mises à jour effectuées
|
||||
8. Retour à la page précédente après action
|
||||
|
||||
## Story 4.4: Team Progression Status
|
||||
|
||||
**As a** user,
|
||||
**I want** to see the progression status of my team for a specific objective,
|
||||
**so that** I can see who still needs to complete it.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
1. Sur `/teams/:id`, nouvelle section "Statut des progressions"
|
||||
2. Sélecteur de progression type (ex: "Dofus Turquoise")
|
||||
3. Tableau : membres de la team avec statut (fait/pas fait) pour cette progression
|
||||
4. Pourcentage global affiché (ex: "6/8 = 75%")
|
||||
5. Indicateur visuel clair (vert = fait, rouge = pas fait)
|
||||
6. Bouton "Marquer fait pour tous" pour bulk update depuis cette vue
|
||||
7. Filtrable par catégorie de progression
|
||||
|
||||
## Story 4.5: Progression Filters in Character List
|
||||
|
||||
**As a** user,
|
||||
**I want** to filter characters by progression status,
|
||||
**so that** I can find who hasn't completed a specific objective.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
1. Nouvelle section dans la sidebar des filtres : "Progression"
|
||||
2. Sélecteur de progression type
|
||||
3. Options : "A fait" / "N'a pas fait"
|
||||
4. Combinable avec les autres filtres existants
|
||||
5. Exemple d'usage : "Montrer tous les Cra qui n'ont pas fait le Dofus Turquoise"
|
||||
6. Compteur de résultats mis à jour
|
||||
7. Filtre stocké dans l'URL
|
||||
|
||||
---
|
||||
94
docs/prd/epic-5-currencies-aggregations.md
Normal file
94
docs/prd/epic-5-currencies-aggregations.md
Normal file
@@ -0,0 +1,94 @@
|
||||
# Epic 5: Currencies & Aggregations
|
||||
|
||||
**Goal:** Implémenter le tracking des monnaies par personnage (Doplons, Orichor, etc.) et afficher les totaux agrégés au niveau compte et global. L'utilisateur peut rapidement voir combien de chaque monnaie il possède au total.
|
||||
|
||||
## Story 5.1: Currency Database Schema
|
||||
|
||||
**As a** developer,
|
||||
**I want** a schema for tracking currencies per character,
|
||||
**so that** currency amounts can be stored and aggregated.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
1. Model `CurrencyType`: id, name, icon (nullable), createdAt
|
||||
2. Model `CharacterCurrency`: characterId, currencyTypeId, amount (integer), updatedAt
|
||||
3. Contrainte unique sur (characterId, currencyTypeId)
|
||||
4. Migration générée et appliquée
|
||||
5. Seed script avec les 8 monnaies identifiées :
|
||||
- Doplons, Almatons, Orichor, Kamas de glace
|
||||
- Perles des profondeurs, Alitons, Trukdivins, Pages calendrier
|
||||
6. Index sur characterId pour requêtes d'agrégation
|
||||
|
||||
## Story 5.2: Character Currency View
|
||||
|
||||
**As a** user,
|
||||
**I want** to see and edit a character's currencies on their detail page,
|
||||
**so that** I can track each character's wealth.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
1. Section "Monnaies" sur la page `/characters/:id`
|
||||
2. Liste des monnaies avec champ input numérique pour chaque
|
||||
3. Modification inline avec sauvegarde au blur ou sur Enter
|
||||
4. Indicateur de sauvegarde (loading spinner pendant save)
|
||||
5. Validation : montant >= 0, entier uniquement
|
||||
6. Affichage de l'icône/nom de chaque monnaie
|
||||
7. Dernière mise à jour affichée par monnaie
|
||||
|
||||
## Story 5.3: Bulk Currency Update
|
||||
|
||||
**As a** user,
|
||||
**I want** to update a currency for multiple characters at once,
|
||||
**so that** I can quickly update after a group activity.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
1. Page `/currencies/bulk` accessible depuis le menu
|
||||
2. Sélecteur de personnages (multi-select avec filtres, sélection par team)
|
||||
3. Sélecteur de monnaie à mettre à jour
|
||||
4. Mode d'opération : "Définir à" (valeur absolue) ou "Ajouter/Soustraire" (delta)
|
||||
5. Champ pour la valeur
|
||||
6. Confirmation avant exécution
|
||||
7. Toast de succès avec récapitulatif
|
||||
8. Historique des bulk updates (optionnel, pour audit)
|
||||
|
||||
## Story 5.4: Account Currency Totals
|
||||
|
||||
**As a** user,
|
||||
**I want** to see the total currencies for each account,
|
||||
**so that** I can see my wealth per account.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
1. Sur `/accounts/:id`, section "Total des monnaies"
|
||||
2. Tableau avec chaque monnaie et le total pour ce compte
|
||||
3. Total = somme des monnaies de tous les personnages du compte
|
||||
4. Mise à jour automatique quand les données changent
|
||||
5. Affichage compact (icône + montant)
|
||||
6. Zéro affiché si aucun personnage n'a cette monnaie
|
||||
|
||||
## Story 5.5: Global Currency Dashboard
|
||||
|
||||
**As a** user,
|
||||
**I want** to see my total currencies across all characters,
|
||||
**so that** I have a global view of my in-game wealth.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
1. Widget sur le Dashboard (page d'accueil) : "Mes monnaies"
|
||||
2. Liste de toutes les monnaies avec total global
|
||||
3. Total global = somme sur tous les personnages
|
||||
4. Possibilité de cliquer pour voir le détail par compte
|
||||
5. Drill-down : compte → personnages avec leurs montants
|
||||
6. Données mises en cache pour performance (invalidation au changement)
|
||||
|
||||
## Story 5.6: Currency Management (Admin)
|
||||
|
||||
**As a** user,
|
||||
**I want** to add or remove currency types,
|
||||
**so that** I can adapt to game updates adding new currencies.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
1. Page `/settings/currencies` pour gérer les types de monnaies
|
||||
2. Liste des monnaies existantes
|
||||
3. Formulaire d'ajout : nom, icône (optionnel)
|
||||
4. Suppression possible si aucun personnage n'a cette monnaie
|
||||
5. Avertissement si suppression avec données existantes
|
||||
6. Ordre d'affichage modifiable (drag & drop ou champ order)
|
||||
|
||||
---
|
||||
94
docs/prd/epic-6-dofusdb-integration.md
Normal file
94
docs/prd/epic-6-dofusdb-integration.md
Normal file
@@ -0,0 +1,94 @@
|
||||
# Epic 6: DofusDB Integration
|
||||
|
||||
**Goal:** Intégrer l'API DofusDB pour importer automatiquement les données de référence du jeu (quêtes, donjons, succès, recherchés). L'utilisateur n'a plus besoin de saisir manuellement ces informations.
|
||||
|
||||
## Story 6.1: DofusDB API Client
|
||||
|
||||
**As a** developer,
|
||||
**I want** a typed HTTP client for the DofusDB API,
|
||||
**so that** I can fetch game reference data reliably.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
1. Module `lib/dofusdb.ts` avec client HTTP typé
|
||||
2. Types TypeScript pour les réponses API (quêtes, donjons, succès, etc.)
|
||||
3. Gestion des erreurs API (timeout, rate limit, 404)
|
||||
4. Configuration via variables d'environnement (API URL, éventuels tokens)
|
||||
5. Retry automatique en cas d'échec temporaire (max 3 retries)
|
||||
6. Logging des appels API pour debug
|
||||
7. Tests unitaires avec mocks des réponses API
|
||||
|
||||
## Story 6.2: Dungeon Data Import
|
||||
|
||||
**As a** user,
|
||||
**I want** to import the list of dungeons from DofusDB,
|
||||
**so that** I don't have to add them manually.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
1. Endpoint ou script pour importer les donjons depuis DofusDB
|
||||
2. Mapping des données DofusDB vers le model `ProgressionType` (category: DUNGEON)
|
||||
3. Import des métadonnées : nom, niveau requis, zone/région
|
||||
4. Gestion des doublons : mise à jour si existant, création sinon
|
||||
5. Rapport d'import : X créés, Y mis à jour, Z erreurs
|
||||
6. Bouton "Importer donjons" dans `/settings/data`
|
||||
7. Indicateur de dernière synchronisation
|
||||
|
||||
## Story 6.3: Quest Data Import
|
||||
|
||||
**As a** user,
|
||||
**I want** to import Dofus quest chains from DofusDB,
|
||||
**so that** I can track my progress on main quests.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
1. Import des quêtes Dofus (les 10 quêtes principales identifiées)
|
||||
2. Mapping vers `ProgressionType` (category: DOFUS_QUEST)
|
||||
3. Import des métadonnées : nom, Dofus associé
|
||||
4. Option de filtrer quelles quêtes importer (sélection manuelle ou toutes)
|
||||
5. Gestion des doublons
|
||||
6. Bouton "Importer quêtes" dans `/settings/data`
|
||||
7. Rapport d'import
|
||||
|
||||
## Story 6.4: Wanted Posters Import
|
||||
|
||||
**As a** user,
|
||||
**I want** to import wanted poster data from DofusDB,
|
||||
**so that** I can track bounties by region.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
1. Import des recherchés par région depuis DofusDB
|
||||
2. Mapping vers `ProgressionType` (category: WANTED)
|
||||
3. Métadonnées : nom, région associée
|
||||
4. Regroupement par région (Astrub, Amakna, Frigost I/II/III, etc.)
|
||||
5. Gestion des doublons
|
||||
6. Bouton "Importer recherchés" dans `/settings/data`
|
||||
7. Rapport d'import
|
||||
|
||||
## Story 6.5: Sync Settings & Automation
|
||||
|
||||
**As a** user,
|
||||
**I want** to configure automatic synchronization with DofusDB,
|
||||
**so that** my reference data stays up to date.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
1. Page `/settings/data` avec configuration de sync
|
||||
2. Option sync manuelle (boutons par type de données)
|
||||
3. Option sync automatique périodique (daily, weekly, disabled)
|
||||
4. Cron job ou scheduled task pour sync auto
|
||||
5. Notification (toast ou log) après sync automatique
|
||||
6. Historique des syncs (date, type, résultat)
|
||||
7. Option de réinitialiser toutes les données de référence
|
||||
|
||||
## Story 6.6: Data Conflict Resolution
|
||||
|
||||
**As a** developer,
|
||||
**I want** a strategy for handling conflicts between local and API data,
|
||||
**so that** user modifications aren't lost during sync.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
1. Les `ProgressionType` importés ont un flag `source: API | MANUAL`
|
||||
2. Sync API ne modifie que les entrées `source: API`
|
||||
3. Entrées `source: MANUAL` préservées lors du sync
|
||||
4. Option de forcer l'écrasement (avec confirmation)
|
||||
5. Détection des entrées supprimées de l'API (soft delete ou warning)
|
||||
6. Log des conflits détectés pour review
|
||||
|
||||
---
|
||||
12
docs/prd/epic-list.md
Normal file
12
docs/prd/epic-list.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# Epic List
|
||||
|
||||
| # | Epic | Objectif |
|
||||
|---|------|----------|
|
||||
| **1** | **Foundation & Core Entities** | Établir le projet, le schéma DB, et le CRUD de base pour Serveurs, Comptes et Personnages |
|
||||
| **2** | **Teams & Constraints** | Implémenter la gestion des Teams avec validation de la contrainte compte |
|
||||
| **3** | **Filtering & Search** | Ajouter les filtres multicritères et la recherche textuelle sur la liste des personnages |
|
||||
| **4** | **Progression Tracking** | Tracker les progressions (quêtes Dofus, donjons, recherchés) par personnage |
|
||||
| **5** | **Currencies & Aggregations** | Gérer les monnaies par personnage et afficher les totaux agrégés |
|
||||
| **6** | **DofusDB Integration** | Intégrer l'API DofusDB pour les données de référence |
|
||||
|
||||
---
|
||||
25
docs/prd/goals-and-background-context.md
Normal file
25
docs/prd/goals-and-background-context.md
Normal file
@@ -0,0 +1,25 @@
|
||||
# Goals and Background Context
|
||||
|
||||
## Goals
|
||||
|
||||
- **Remplacer le tableur Excel** de gestion de 60+ personnages Dofus par une application web moderne et maintenable
|
||||
- **Offrir une vue d'ensemble claire** de tous les personnages avec filtrage multicritères et recherche instantanée
|
||||
- **Automatiser la gestion des données** via intégration avec l'API DofusDB (quêtes, donjons, succès)
|
||||
- **Faciliter les mises à jour groupées** (bulk update) pour réduire drastiquement le temps de maintenance
|
||||
- **Valider automatiquement les contraintes de compte** (pas 2 personnages du même compte simultanément dans une team)
|
||||
- **Tracker les progressions** (quêtes Dofus, donjons, recherchés, monnaies) par personnage et par team
|
||||
|
||||
## Background Context
|
||||
|
||||
Theo est un joueur de Dofus gérant **60+ personnages niveau 200** répartis sur plusieurs dizaines de comptes sur plusieurs serveurs (principalement Imagiro). Actuellement, cette gestion est faite via un tableur Excel avec les personnages en colonnes horizontales, ce qui rend la visualisation impossible sans scroll excessif, les modifications fragiles (risque de casser le formatage), et la règle métier fondamentale du jeu ("pas 2 persos du même compte simultanément") gérée uniquement mentalement.
|
||||
|
||||
L'application remplacera ce tableur par un système web permettant la gestion CRUD des comptes, personnages, serveurs et teams, avec des filtres avancés façon e-commerce, des actions groupées, et une intégration avec DofusDB pour éliminer la saisie manuelle des données de référence (quêtes, donjons, succès).
|
||||
|
||||
## Change Log
|
||||
|
||||
| Date | Version | Description | Author |
|
||||
|------|---------|-------------|--------|
|
||||
| 2026-01-17 | 0.1 | Création initiale du PRD | John (PM) |
|
||||
| 2026-01-17 | 0.2 | Ajout documentation API DofusDB (endpoints validés) | John (PM) |
|
||||
|
||||
---
|
||||
80
docs/prd/index.md
Normal file
80
docs/prd/index.md
Normal file
@@ -0,0 +1,80 @@
|
||||
# Dofus Manager - Product Requirements Document (PRD)
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [Dofus Manager - Product Requirements Document (PRD)](#table-of-contents)
|
||||
- [Goals and Background Context](./goals-and-background-context.md)
|
||||
- [Goals](./goals-and-background-context.md#goals)
|
||||
- [Background Context](./goals-and-background-context.md#background-context)
|
||||
- [Change Log](./goals-and-background-context.md#change-log)
|
||||
- [Requirements](./requirements.md)
|
||||
- [Functional Requirements](./requirements.md#functional-requirements)
|
||||
- [Non-Functional Requirements](./requirements.md#non-functional-requirements)
|
||||
- [User Interface Design Goals](./user-interface-design-goals.md)
|
||||
- [Overall UX Vision](./user-interface-design-goals.md#overall-ux-vision)
|
||||
- [Key Interaction Paradigms](./user-interface-design-goals.md#key-interaction-paradigms)
|
||||
- [Core Screens and Views](./user-interface-design-goals.md#core-screens-and-views)
|
||||
- [Accessibility](./user-interface-design-goals.md#accessibility)
|
||||
- [Branding](./user-interface-design-goals.md#branding)
|
||||
- [Target Device and Platforms](./user-interface-design-goals.md#target-device-and-platforms)
|
||||
- [Technical Assumptions](./technical-assumptions.md)
|
||||
- [Repository Structure: Monorepo](./technical-assumptions.md#repository-structure-monorepo)
|
||||
- [Service Architecture: Monolith Full-Stack](./technical-assumptions.md#service-architecture-monolith-full-stack)
|
||||
- [Testing Requirements: Unit + Integration](./technical-assumptions.md#testing-requirements-unit-integration)
|
||||
- [Additional Technical Assumptions and Requests](./technical-assumptions.md#additional-technical-assumptions-and-requests)
|
||||
- [DofusDB API Reference](./dofusdb-api-reference.md)
|
||||
- [Base URL](./dofusdb-api-reference.md#base-url)
|
||||
- [Caractéristiques techniques](./dofusdb-api-reference.md#caractristiques-techniques)
|
||||
- [Endpoints disponibles](./dofusdb-api-reference.md#endpoints-disponibles)
|
||||
- [Mapping pour le PRD](./dofusdb-api-reference.md#mapping-pour-le-prd)
|
||||
- [Dofus identifiés](./dofusdb-api-reference.md#dofus-identifis)
|
||||
- [Exemples de requêtes](./dofusdb-api-reference.md#exemples-de-requtes)
|
||||
- [Notes d'implémentation](./dofusdb-api-reference.md#notes-dimplmentation)
|
||||
- [Epic List](./epic-list.md)
|
||||
- [Epic 1: Foundation & Core Entities](./epic-1-foundation-core-entities.md)
|
||||
- [Story 1.1: Project Setup & Infrastructure](./epic-1-foundation-core-entities.md#story-11-project-setup-infrastructure)
|
||||
- [Story 1.2: Database Schema - Core Entities](./epic-1-foundation-core-entities.md#story-12-database-schema-core-entities)
|
||||
- [Story 1.3: Server CRUD](./epic-1-foundation-core-entities.md#story-13-server-crud)
|
||||
- [Story 1.4: Account CRUD](./epic-1-foundation-core-entities.md#story-14-account-crud)
|
||||
- [Story 1.5: Character CRUD](./epic-1-foundation-core-entities.md#story-15-character-crud)
|
||||
- [Story 1.6: Navigation & Layout](./epic-1-foundation-core-entities.md#story-16-navigation-layout)
|
||||
- [Epic 2: Teams & Constraints](./epic-2-teams-constraints.md)
|
||||
- [Story 2.1: Team Database Schema](./epic-2-teams-constraints.md#story-21-team-database-schema)
|
||||
- [Story 2.2: Team CRUD - Basic](./epic-2-teams-constraints.md#story-22-team-crud-basic)
|
||||
- [Story 2.3: Team Member Management](./epic-2-teams-constraints.md#story-23-team-member-management)
|
||||
- [Story 2.4: Account Constraint Validation](./epic-2-teams-constraints.md#story-24-account-constraint-validation)
|
||||
- [Story 2.5: Team Status Overview](./epic-2-teams-constraints.md#story-25-team-status-overview)
|
||||
- [Epic 3: Filtering & Search](./epic-3-filtering-search.md)
|
||||
- [Story 3.1: Filter Sidebar Component](./epic-3-filtering-search.md#story-31-filter-sidebar-component)
|
||||
- [Story 3.2: Filter Logic Implementation](./epic-3-filtering-search.md#story-32-filter-logic-implementation)
|
||||
- [Story 3.3: Text Search](./epic-3-filtering-search.md#story-33-text-search)
|
||||
- [Story 3.4: Column Sorting](./epic-3-filtering-search.md#story-34-column-sorting)
|
||||
- [Story 3.5: Saved Filter Presets](./epic-3-filtering-search.md#story-35-saved-filter-presets)
|
||||
- [Epic 4: Progression Tracking](./epic-4-progression-tracking.md)
|
||||
- [Story 4.1: Progression Database Schema](./epic-4-progression-tracking.md#story-41-progression-database-schema)
|
||||
- [Story 4.2: Character Progression View](./epic-4-progression-tracking.md#story-42-character-progression-view)
|
||||
- [Story 4.3: Bulk Progression Update](./epic-4-progression-tracking.md#story-43-bulk-progression-update)
|
||||
- [Story 4.4: Team Progression Status](./epic-4-progression-tracking.md#story-44-team-progression-status)
|
||||
- [Story 4.5: Progression Filters in Character List](./epic-4-progression-tracking.md#story-45-progression-filters-in-character-list)
|
||||
- [Epic 5: Currencies & Aggregations](./epic-5-currencies-aggregations.md)
|
||||
- [Story 5.1: Currency Database Schema](./epic-5-currencies-aggregations.md#story-51-currency-database-schema)
|
||||
- [Story 5.2: Character Currency View](./epic-5-currencies-aggregations.md#story-52-character-currency-view)
|
||||
- [Story 5.3: Bulk Currency Update](./epic-5-currencies-aggregations.md#story-53-bulk-currency-update)
|
||||
- [Story 5.4: Account Currency Totals](./epic-5-currencies-aggregations.md#story-54-account-currency-totals)
|
||||
- [Story 5.5: Global Currency Dashboard](./epic-5-currencies-aggregations.md#story-55-global-currency-dashboard)
|
||||
- [Story 5.6: Currency Management (Admin)](./epic-5-currencies-aggregations.md#story-56-currency-management-admin)
|
||||
- [Epic 6: DofusDB Integration](./epic-6-dofusdb-integration.md)
|
||||
- [Story 6.1: DofusDB API Client](./epic-6-dofusdb-integration.md#story-61-dofusdb-api-client)
|
||||
- [Story 6.2: Dungeon Data Import](./epic-6-dofusdb-integration.md#story-62-dungeon-data-import)
|
||||
- [Story 6.3: Quest Data Import](./epic-6-dofusdb-integration.md#story-63-quest-data-import)
|
||||
- [Story 6.4: Wanted Posters Import](./epic-6-dofusdb-integration.md#story-64-wanted-posters-import)
|
||||
- [Story 6.5: Sync Settings & Automation](./epic-6-dofusdb-integration.md#story-65-sync-settings-automation)
|
||||
- [Story 6.6: Data Conflict Resolution](./epic-6-dofusdb-integration.md#story-66-data-conflict-resolution)
|
||||
- [Checklist Results Report](./checklist-results-report.md)
|
||||
- [Executive Summary](./checklist-results-report.md#executive-summary)
|
||||
- [Category Analysis](./checklist-results-report.md#category-analysis)
|
||||
- [Issues Identified](./checklist-results-report.md#issues-identified)
|
||||
- [Final Decision](./checklist-results-report.md#final-decision)
|
||||
- [Next Steps](./next-steps.md)
|
||||
- [UX Expert Prompt](./next-steps.md#ux-expert-prompt)
|
||||
- [Architect Prompt](./next-steps.md#architect-prompt)
|
||||
57
docs/prd/next-steps.md
Normal file
57
docs/prd/next-steps.md
Normal file
@@ -0,0 +1,57 @@
|
||||
# Next Steps
|
||||
|
||||
## UX Expert Prompt
|
||||
|
||||
```
|
||||
Je travaille sur Dofus Manager, une application web de gestion de personnages pour le MMORPG Dofus.
|
||||
|
||||
Contexte : L'application remplace un tableur Excel pour gérer 60+ personnages sur plusieurs comptes. Les fonctionnalités clés sont :
|
||||
- CRUD pour Serveurs, Comptes, Personnages, Teams
|
||||
- Filtrage multicritères et recherche
|
||||
- Tracking des progressions (quêtes, donjons, recherchés)
|
||||
- Gestion des monnaies avec agrégations
|
||||
- Validation de contrainte : pas 2 persos du même compte dans une team active
|
||||
|
||||
Design goals :
|
||||
- Desktop-first, responsive tablette
|
||||
- Dense en informations, inspiré outils pro
|
||||
- Filtres sidebar façon e-commerce
|
||||
- Multi-select et bulk actions façon Gmail
|
||||
- shadcn/ui comme design system
|
||||
|
||||
Peux-tu créer les wireframes ou maquettes pour les écrans principaux :
|
||||
1. Liste des personnages avec filtres
|
||||
2. Fiche personnage (infos + progressions + monnaies)
|
||||
3. Gestion des teams avec validation contrainte
|
||||
|
||||
Le PRD complet est disponible dans docs/prd.md
|
||||
```
|
||||
|
||||
## Architect Prompt
|
||||
|
||||
```
|
||||
Je travaille sur Dofus Manager, une application web full-stack pour gérer des personnages de MMORPG.
|
||||
|
||||
Stack technique validée :
|
||||
- Framework : TanStack Start (React full-stack, TypeScript)
|
||||
- ORM : Prisma avec PostgreSQL 16
|
||||
- UI : shadcn/ui + TanStack Table
|
||||
- Infra : Docker, Traefik, GitLab CI
|
||||
|
||||
Contexte métier :
|
||||
- 60+ personnages, dizaines de comptes, plusieurs serveurs
|
||||
- Teams avec contrainte : pas 2 persos du même compte simultanément
|
||||
- Progressions (quêtes, donjons, recherchés) et monnaies à tracker
|
||||
- Intégration API DofusDB pour données de référence
|
||||
|
||||
Besoins architecture :
|
||||
1. Schéma Prisma complet pour les entités (Server, Account, Character, Team, ProgressionType, CurrencyType, etc.)
|
||||
2. Structure du projet TanStack Start
|
||||
3. Patterns pour server functions et data fetching
|
||||
4. Stratégie de cache pour agrégations
|
||||
5. Configuration Docker + GitLab CI
|
||||
|
||||
Le PRD complet avec les 6 epics et 27 stories est disponible dans docs/prd.md.
|
||||
Peux-tu initier le mode architecture et proposer une conception technique ?
|
||||
```
|
||||
|
||||
49
docs/prd/requirements.md
Normal file
49
docs/prd/requirements.md
Normal file
@@ -0,0 +1,49 @@
|
||||
# Requirements
|
||||
|
||||
## Functional Requirements
|
||||
|
||||
- **FR1:** Le système doit permettre la création, lecture, modification et suppression (CRUD) des **comptes** avec les attributs : nom, ogrines, récompenses succès débloquées (Dofus, ressources).
|
||||
|
||||
- **FR2:** Le système doit permettre la gestion CRUD des **personnages** avec les attributs : pseudo, classe (17 classes Dofus), niveau, serveur associé, compte associé.
|
||||
|
||||
- **FR3:** Le système doit permettre la gestion CRUD des **teams** avec validation automatique de la contrainte "pas 2 personnages du même compte dans une team active".
|
||||
|
||||
- **FR4:** Le système doit offrir un **filtrage multicritères** des personnages par : classe, niveau, compte, team, serveur, statut de progression (quêtes, donjons, recherchés).
|
||||
|
||||
- **FR5:** Le système doit permettre la **recherche textuelle** sur les noms de personnages, comptes et teams.
|
||||
|
||||
- **FR6:** Le système doit permettre les **mises à jour groupées (bulk update)** : cocher/décocher plusieurs progressions pour une sélection de personnages ou une team entière.
|
||||
|
||||
- **FR7:** Le système doit tracker les **progressions par personnage** : quêtes Dofus (Turquoise, Pourpre, Émeraude, etc.), donjons par paliers avec types de succès, recherchés par région.
|
||||
|
||||
- **FR8:** Le système doit tracker les **monnaies par personnage** : Doplons, Almatons, Orichor, Kamas de glace, Perles des profondeurs, Alitons, Trukdivins, Pages calendrier.
|
||||
|
||||
- **FR9:** Le système doit afficher les **totaux agrégés des monnaies** au niveau compte et global.
|
||||
|
||||
- **FR10:** Le système doit s'intégrer avec **l'API DofusDB** pour importer les données de référence (liste des quêtes, donjons, succès, recherchés).
|
||||
|
||||
- **FR11:** Le système doit afficher une **vue statut team** avec pourcentage de complétion par objectif (ex: "Dofus Turquoise: 6/8 persos = 75%").
|
||||
|
||||
- **FR12:** Le système doit gérer les **métiers par couple compte+serveur** (et non par personnage) avec niveau de maîtrise.
|
||||
|
||||
- **FR13:** Le système doit permettre la gestion CRUD des **serveurs** (ex: Imagiro, Jahash, Draconiros) avec possibilité d'en ajouter de nouveaux.
|
||||
|
||||
## Non-Functional Requirements
|
||||
|
||||
- **NFR1:** L'application doit être **responsive** et utilisable sur desktop et tablette (usage sur second écran pendant le jeu).
|
||||
|
||||
- **NFR2:** L'application doit offrir une **latence de réponse < 500ms** pour les opérations courantes (filtrage, CRUD).
|
||||
|
||||
- **NFR3:** L'application doit supporter **100+ personnages** sans dégradation notable des performances.
|
||||
|
||||
- **NFR4:** L'application doit être **auto-hébergeable** sur un serveur dédié personnel via Docker.
|
||||
|
||||
- **NFR5:** L'application doit utiliser **PostgreSQL** comme base de données pour la persistance.
|
||||
|
||||
- **NFR6:** L'application doit être développée avec **React + TanStack Start** (full-stack TypeScript).
|
||||
|
||||
- **NFR7:** Les données doivent être **sauvegardables et restaurables** facilement (backup PostgreSQL).
|
||||
|
||||
- **NFR8:** L'application doit fonctionner en **mode mono-utilisateur** (pas d'authentification multi-users dans le MVP).
|
||||
|
||||
---
|
||||
62
docs/prd/technical-assumptions.md
Normal file
62
docs/prd/technical-assumptions.md
Normal file
@@ -0,0 +1,62 @@
|
||||
# Technical Assumptions
|
||||
|
||||
## Repository Structure: Monorepo
|
||||
|
||||
Projet organisé en **monorepo** :
|
||||
```
|
||||
/
|
||||
├── src/
|
||||
│ ├── routes/ # Pages et API routes (TanStack Start)
|
||||
│ ├── components/ # Composants React réutilisables
|
||||
│ ├── lib/ # Utilitaires, clients API, helpers
|
||||
│ └── server/ # Server functions, services
|
||||
├── prisma/ # Schéma et migrations Prisma
|
||||
├── docker/ # Configuration Docker
|
||||
└── docs/ # Documentation projet
|
||||
```
|
||||
|
||||
## Service Architecture: Monolith Full-Stack
|
||||
|
||||
**Architecture monolithique** avec TanStack Start :
|
||||
- **Frontend** : React avec TanStack Router (file-based routing)
|
||||
- **Backend** : Server functions intégrées à TanStack Start
|
||||
- **Base de données** : PostgreSQL avec Prisma ORM
|
||||
|
||||
## Testing Requirements: Unit + Integration
|
||||
|
||||
| Type | Scope | Outils |
|
||||
|------|-------|--------|
|
||||
| **Unit** | Logique métier, validations, helpers | Vitest |
|
||||
| **Integration** | API routes, queries DB | Vitest + testcontainers |
|
||||
| **E2E** | Non prioritaire MVP | (Playwright en V2) |
|
||||
|
||||
## Additional Technical Assumptions and Requests
|
||||
|
||||
**Stack technique :**
|
||||
- **Framework** : TanStack Start (React full-stack)
|
||||
- **ORM** : Prisma (type-safe, migrations robustes, écosystème mature)
|
||||
- **UI Components** : shadcn/ui (composants copiés, personnalisables)
|
||||
- **Tables** : TanStack Table (tri, filtres, pagination)
|
||||
- **Database** : PostgreSQL 16+
|
||||
- **Container** : Docker + Docker Compose
|
||||
|
||||
**Infrastructure :**
|
||||
- **Reverse proxy** : Traefik (existant sur le serveur)
|
||||
- **CI/CD** : GitLab personnel (pipelines de build et déploiement)
|
||||
- **Hébergement** : Serveur dédié personnel
|
||||
|
||||
**Intégration externe :**
|
||||
- **DofusDB API** : Client HTTP pour récupérer les données de référence
|
||||
- Sync manuelle ou cron pour mise à jour des données de jeu
|
||||
|
||||
**Conventions de code :**
|
||||
- TypeScript strict mode
|
||||
- ESLint + Prettier
|
||||
- Conventional commits (feat:, fix:, chore:, etc.)
|
||||
|
||||
**Déploiement :**
|
||||
- Docker Compose (app + postgres)
|
||||
- Pipeline GitLab CI pour build et push des images
|
||||
- Labels Traefik pour routing automatique
|
||||
|
||||
---
|
||||
51
docs/prd/user-interface-design-goals.md
Normal file
51
docs/prd/user-interface-design-goals.md
Normal file
@@ -0,0 +1,51 @@
|
||||
# User Interface Design Goals
|
||||
|
||||
## Overall UX Vision
|
||||
|
||||
L'application doit offrir une expérience **efficace et dense en informations**, inspirée des outils de gestion de données professionnels. L'objectif est de permettre à l'utilisateur de :
|
||||
- Trouver rapidement l'information cherchée (quel perso n'a pas fait X ?)
|
||||
- Effectuer des modifications en masse sans friction
|
||||
- Avoir une vue d'ensemble claire malgré le volume de données (60+ personnages)
|
||||
|
||||
Le design privilégie la **fonctionnalité sur l'esthétique** : interface sobre, contrastes clairs, densité d'information élevée, navigation rapide.
|
||||
|
||||
## Key Interaction Paradigms
|
||||
|
||||
- **Filtres sidebar façon e-commerce** — Panel latéral avec facettes cliquables (classe, serveur, team, compte, statut)
|
||||
- **Multi-select façon Gmail** — Checkboxes pour sélection multiple + barre d'actions groupées
|
||||
- **Tables interactives** — Tri, resize colonnes, pagination, colonnes masquables
|
||||
- **Actions au survol** — Boutons edit/delete apparaissent au hover pour réduire le bruit visuel
|
||||
- **Drill-down progressif** — Liste → Fiche détaillée → Sous-sections (progressions, monnaies)
|
||||
- **Feedback immédiat** — Toasts pour confirmations, indicateurs de chargement, états vides informatifs
|
||||
|
||||
## Core Screens and Views
|
||||
|
||||
1. **Dashboard** — Vue d'accueil avec KPIs (total persos, teams, progression globale)
|
||||
2. **Liste Personnages** — Vue principale avec filtres, recherche, tableau paginé
|
||||
3. **Fiche Personnage** — Détails complets : infos, progressions, monnaies, teams
|
||||
4. **Liste Comptes** — Gestion des comptes avec leurs personnages associés
|
||||
5. **Fiche Compte** — Détails compte : ogrines, métiers (par serveur), récompenses
|
||||
6. **Liste Teams** — Toutes les teams avec statut de complétion
|
||||
7. **Fiche Team** — Membres, validation contraintes, % progression par objectif
|
||||
8. **Gestion Serveurs** — CRUD des serveurs disponibles
|
||||
9. **Données de référence** — Gestion des quêtes/donjons/recherchés (sync DofusDB)
|
||||
|
||||
## Accessibility
|
||||
|
||||
**Niveau cible : Aucun (pas de conformité WCAG requise)**
|
||||
|
||||
Application à usage personnel. Bonnes pratiques de base respectées : contrastes suffisants, navigation clavier, labels sur formulaires.
|
||||
|
||||
## Branding
|
||||
|
||||
**Aucun branding spécifique.** Design system sobre et moderne (shadcn/ui ou similaire), palette neutre, pas de thématique Dofus (éviter copyright), focus sur lisibilité.
|
||||
|
||||
## Target Device and Platforms
|
||||
|
||||
**Web Responsive (Desktop-first)**
|
||||
|
||||
- **Priorité 1 : Desktop** — Usage principal sur grand écran pendant les sessions de jeu
|
||||
- **Priorité 2 : Tablette** — Consultation occasionnelle
|
||||
- **Priorité 3 : Mobile** — Consultation basique acceptable
|
||||
|
||||
---
|
||||
Reference in New Issue
Block a user