- Create migration script for existing data - Update admin interface to show only short URLs - Implement redirect system to avoid code duplication - Maintain backward compatibility with old URLs
202 lines
8.0 KiB
Markdown
202 lines
8.0 KiB
Markdown
# Structure du Projet
|
|
|
|
## 📁 Organisation des fichiers
|
|
|
|
```
|
|
mes-budgets-participatifs/
|
|
├── src/
|
|
│ ├── app/ # Pages Next.js (App Router)
|
|
│ │ ├── page.tsx # Page d'accueil
|
|
│ │ ├── admin/ # Pages d'administration (protégées)
|
|
│ │ │ ├── page.tsx # Dashboard principal
|
|
│ │ │ ├── settings/ # Paramètres SMTP
|
|
│ │ │ └── campaigns/[id]/ # Pages de gestion par campagne
|
|
│ │ ├── api/ # API Routes
|
|
│ │ │ ├── send-participant-email/
|
|
│ │ │ ├── test-email/
|
|
│ │ │ └── test-smtp/
|
|
│ │ ├── campaigns/[id]/ # Pages publiques (anciennes routes)
|
|
│ │ │ ├── propose/ # Dépôt de propositions
|
|
│ │ │ └── vote/[participantId] # Vote public
|
|
│ │ ├── p/[slug]/ # Pages publiques (nouvelles routes courtes)
|
|
│ │ │ ├── page.tsx # Dépôt de propositions par slug
|
|
│ │ │ └── success/ # Page de succès pour dépôt
|
|
│ │ │ └── page.tsx
|
|
│ │ └── v/[shortId]/ # Pages de vote (nouvelles routes courtes)
|
|
│ │ ├── page.tsx # Vote par short_id
|
|
│ │ └── success/ # Page de succès pour vote
|
|
│ │ └── page.tsx
|
|
│ ├── components/ # Composants React
|
|
│ │ ├── ui/ # Composants Shadcn/ui
|
|
│ │ ├── AuthGuard.tsx # Protection des routes
|
|
│ │ ├── Navigation.tsx # Navigation principale
|
|
│ │ ├── SmtpSettingsForm.tsx # Configuration SMTP
|
|
│ │ └── [Modals] # Modales de gestion
|
|
│ ├── lib/ # Services et configuration
|
|
│ │ ├── supabase.ts # Configuration Supabase
|
|
│ │ ├── services.ts # Services de données
|
|
│ │ ├── email.ts # Service d'envoi d'emails
|
|
│ │ ├── encryption.ts # Chiffrement des données sensibles
|
|
│ │ └── utils.ts # Utilitaires
|
|
│ └── types/ # Types TypeScript
|
|
├── database/
|
|
│ └── supabase-schema.sql # Schéma de base de données
|
|
├── scripts/
|
|
│ ├── test-security.js # Tests de sécurité
|
|
│ └── migrate-short-links.js # Migration des liens courts
|
|
└── docs/ # Documentation
|
|
```
|
|
|
|
## 🔗 Routes de l'application
|
|
|
|
### Routes publiques
|
|
|
|
#### Nouvelles routes courtes (recommandées)
|
|
- **`/p/[slug]`** - Dépôt de propositions
|
|
- Exemple : `/p/budget-2024`
|
|
- Utilise le slug de la campagne pour un lien court et lisible
|
|
|
|
- **`/v/[shortId]`** - Vote public
|
|
- Exemple : `/v/ABC123`
|
|
- Utilise un identifiant court unique pour chaque participant
|
|
|
|
#### Anciennes routes (compatibilité)
|
|
- **`/campaigns/[id]/propose`** - Dépôt de propositions
|
|
- Exemple : `/campaigns/123e4567-e89b-12d3-a456-426614174000/propose`
|
|
|
|
- **`/campaigns/[id]/vote/[participantId]`** - Vote public
|
|
- Exemple : `/campaigns/123e4567-e89b-12d3-a456-426614174000/vote/987fcdeb-51a2-43d1-b789-123456789abc`
|
|
|
|
### Routes d'administration
|
|
- **`/admin`** - Dashboard principal
|
|
- **`/admin/settings`** - Paramètres SMTP
|
|
- **`/admin/campaigns/[id]/propositions`** - Gestion des propositions
|
|
- **`/admin/campaigns/[id]/participants`** - Gestion des participants
|
|
- **`/admin/campaigns/[id]/stats`** - Statistiques de la campagne
|
|
|
|
## 🗄️ Structure de la base de données
|
|
|
|
### Tables principales
|
|
|
|
#### `campaigns`
|
|
- `id` (UUID) - Identifiant unique
|
|
- `title` (TEXT) - Titre de la campagne
|
|
- `description` (TEXT) - Description
|
|
- `status` (TEXT) - Statut : 'deposit', 'voting', 'closed'
|
|
- `budget_per_user` (INTEGER) - Budget par utilisateur
|
|
- `spending_tiers` (TEXT) - Montants disponibles (ex: "10,25,50,100")
|
|
- **`slug` (TEXT, UNIQUE)** - Slug pour les liens courts
|
|
- `created_at`, `updated_at` (TIMESTAMP)
|
|
|
|
#### `participants`
|
|
- `id` (UUID) - Identifiant unique
|
|
- `campaign_id` (UUID) - Référence vers la campagne
|
|
- `first_name`, `last_name` (TEXT) - Nom et prénom
|
|
- `email` (TEXT) - Adresse email
|
|
- **`short_id` (TEXT, UNIQUE)** - Identifiant court pour les liens de vote
|
|
- `created_at` (TIMESTAMP)
|
|
|
|
#### `propositions`
|
|
- `id` (UUID) - Identifiant unique
|
|
- `campaign_id` (UUID) - Référence vers la campagne
|
|
- `title`, `description` (TEXT) - Titre et description
|
|
- `author_first_name`, `author_last_name`, `author_email` (TEXT) - Informations de l'auteur
|
|
- `created_at` (TIMESTAMP)
|
|
|
|
#### `votes`
|
|
- `id` (UUID) - Identifiant unique
|
|
- `campaign_id` (UUID) - Référence vers la campagne
|
|
- `participant_id` (UUID) - Référence vers le participant
|
|
- `proposition_id` (UUID) - Référence vers la proposition
|
|
- `amount` (INTEGER) - Montant voté
|
|
- `created_at`, `updated_at` (TIMESTAMP)
|
|
|
|
### Fonctions PostgreSQL
|
|
|
|
#### `generate_slug(title TEXT)`
|
|
Génère automatiquement un slug unique à partir du titre d'une campagne.
|
|
|
|
#### `generate_short_id()`
|
|
Génère automatiquement un identifiant court unique pour les participants.
|
|
|
|
## 🔧 Services et utilitaires
|
|
|
|
### Services principaux (`src/lib/services.ts`)
|
|
|
|
#### `campaignService`
|
|
- `getAll()` - Récupère toutes les campagnes
|
|
- `create(campaign)` - Crée une nouvelle campagne (génère automatiquement le slug)
|
|
- `update(id, updates)` - Met à jour une campagne
|
|
- `delete(id)` - Supprime une campagne
|
|
- `getBySlug(slug)` - Récupère une campagne par son slug
|
|
- `getStats(campaignId)` - Récupère les statistiques d'une campagne
|
|
|
|
#### `participantService`
|
|
- `getByCampaign(campaignId)` - Récupère les participants d'une campagne
|
|
- `create(participant)` - Crée un nouveau participant (génère automatiquement le short_id)
|
|
- `update(id, updates)` - Met à jour un participant
|
|
- `delete(id)` - Supprime un participant
|
|
- `getByShortId(shortId)` - Récupère un participant par son short_id
|
|
|
|
#### `propositionService`
|
|
- `getByCampaign(campaignId)` - Récupère les propositions d'une campagne
|
|
- `create(proposition)` - Crée une nouvelle proposition
|
|
- `update(id, updates)` - Met à jour une proposition
|
|
- `delete(id)` - Supprime une proposition
|
|
|
|
#### `voteService`
|
|
- `getByParticipant(campaignId, participantId)` - Récupère les votes d'un participant
|
|
- `create(vote)` - Crée un nouveau vote
|
|
- `deleteByParticipant(campaignId, participantId)` - Supprime tous les votes d'un participant
|
|
|
|
## 🚀 Scripts de migration
|
|
|
|
### `scripts/migrate-short-links.js`
|
|
Script pour migrer les données existantes et générer les slugs et short_ids manquants.
|
|
|
|
**Usage :**
|
|
```bash
|
|
node scripts/migrate-short-links.js
|
|
```
|
|
|
|
**Fonctionnalités :**
|
|
- Génère automatiquement les slugs pour les campagnes existantes
|
|
- Génère automatiquement les short_ids pour les participants existants
|
|
- Gère les conflits et génère des identifiants uniques
|
|
- Affiche un rapport détaillé de la migration
|
|
|
|
## 🔒 Sécurité
|
|
|
|
### Authentification
|
|
- Utilisation de Supabase Auth pour l'authentification des administrateurs
|
|
- Protection des routes d'administration avec `AuthGuard`
|
|
|
|
### Autorisation
|
|
- Row Level Security (RLS) activé sur toutes les tables
|
|
- Contrôle d'accès basé sur les rôles utilisateur
|
|
|
|
### Validation des données
|
|
- Validation côté client et serveur
|
|
- Sanitisation des entrées utilisateur
|
|
- Protection contre les injections SQL
|
|
|
|
## 📱 Interface utilisateur
|
|
|
|
### Composants UI
|
|
- Utilisation de Shadcn/ui pour une interface cohérente
|
|
- Design responsive et accessible
|
|
- Support du mode sombre
|
|
- Composants réutilisables
|
|
|
|
### Pages publiques
|
|
- Interface épurée et intuitive
|
|
- Formulaires de dépôt et de vote optimisés
|
|
- Feedback visuel en temps réel
|
|
- Gestion des erreurs et des états de chargement
|
|
|
|
### Interface d'administration
|
|
- Dashboard avec statistiques en temps réel
|
|
- Gestion complète des campagnes, propositions et participants
|
|
- Import/export de données
|
|
- Envoi d'emails personnalisés
|