create-crm-tmp 1.0.2 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/bin/create-crm-tmp.js +7 -3
  2. package/package.json +1 -1
  3. package/template/README.md +70 -5
  4. package/template/WORKFLOWS_CRON.md +49 -27
  5. package/template/package.json +18 -16
  6. package/template/prisma/migrations/20260210114913_add_dashboard_widget/migration.sql +20 -0
  7. package/template/prisma/schema.prisma +17 -0
  8. package/template/src/app/(dashboard)/agenda/page.tsx +279 -225
  9. package/template/src/app/(dashboard)/automatisation/[id]/page.tsx +1 -5
  10. package/template/src/app/(dashboard)/automatisation/_components/workflow-editor.tsx +20 -47
  11. package/template/src/app/(dashboard)/automatisation/new/page.tsx +0 -2
  12. package/template/src/app/(dashboard)/closing/page.tsx +5 -57
  13. package/template/src/app/(dashboard)/contacts/[id]/page.tsx +60 -44
  14. package/template/src/app/(dashboard)/contacts/page.tsx +156 -210
  15. package/template/src/app/(dashboard)/dashboard/page.tsx +438 -91
  16. package/template/src/app/(dashboard)/settings/page.tsx +179 -77
  17. package/template/src/app/(dashboard)/users/layout.tsx +30 -0
  18. package/template/src/app/(dashboard)/users/list/page.tsx +213 -159
  19. package/template/src/app/(dashboard)/users/page.tsx +13 -46
  20. package/template/src/app/(dashboard)/users/permissions/page.tsx +0 -2
  21. package/template/src/app/(dashboard)/users/roles/page.tsx +0 -2
  22. package/template/src/app/api/audit-logs/route.ts +0 -2
  23. package/template/src/app/api/auth/google/status/route.ts +46 -7
  24. package/template/src/app/api/closing-reasons/route.ts +0 -2
  25. package/template/src/app/api/contacts/[id]/files/[fileId]/route.ts +2 -1
  26. package/template/src/app/api/contacts/[id]/files/route.ts +25 -20
  27. package/template/src/app/api/contacts/[id]/route.ts +2 -3
  28. package/template/src/app/api/contacts/export/route.ts +14 -11
  29. package/template/src/app/api/contacts/import/route.ts +2 -6
  30. package/template/src/app/api/contacts/route.ts +1 -1
  31. package/template/src/app/api/dashboard/stats/route.ts +7 -0
  32. package/template/src/app/api/dashboard/widgets/[id]/route.ts +47 -0
  33. package/template/src/app/api/dashboard/widgets/route.ts +181 -0
  34. package/template/src/app/api/integrations/google-sheet/sync/route.ts +58 -28
  35. package/template/src/app/api/reminders/route.ts +4 -2
  36. package/template/src/app/api/roles/route.ts +1 -1
  37. package/template/src/app/api/settings/closing-reasons/[id]/route.ts +1 -6
  38. package/template/src/app/api/settings/closing-reasons/route.ts +0 -2
  39. package/template/src/app/api/settings/google-sheet/auto-map/route.ts +10 -5
  40. package/template/src/app/api/settings/google-sheet/route.ts +3 -3
  41. package/template/src/app/api/tasks/[id]/route.ts +4 -4
  42. package/template/src/app/api/tasks/meet/route.ts +1 -2
  43. package/template/src/app/api/tasks/route.ts +16 -18
  44. package/template/src/app/api/users/for-agenda/route.ts +1 -2
  45. package/template/src/app/api/workflows/[id]/route.ts +2 -9
  46. package/template/src/app/api/workflows/route.ts +0 -1
  47. package/template/src/app/globals.css +96 -0
  48. package/template/src/components/dashboard/activity-chart.tsx +37 -37
  49. package/template/src/components/dashboard/add-widget-dialog.tsx +161 -0
  50. package/template/src/components/dashboard/color-picker.tsx +65 -0
  51. package/template/src/components/dashboard/contacts-chart.tsx +36 -30
  52. package/template/src/components/dashboard/interactions-by-type-chart.tsx +121 -0
  53. package/template/src/components/dashboard/recent-activity.tsx +79 -86
  54. package/template/src/components/dashboard/sales-analytics-chart.tsx +4 -8
  55. package/template/src/components/dashboard/stat-card.tsx +42 -40
  56. package/template/src/components/dashboard/status-distribution-chart.tsx +64 -27
  57. package/template/src/components/dashboard/tasks-pie-chart.tsx +37 -34
  58. package/template/src/components/dashboard/top-contacts-list.tsx +41 -51
  59. package/template/src/components/dashboard/upcoming-tasks-list.tsx +71 -78
  60. package/template/src/components/dashboard/widget-wrapper.tsx +39 -0
  61. package/template/src/components/header.tsx +21 -12
  62. package/template/src/components/page-header.tsx +14 -47
  63. package/template/src/components/sidebar.tsx +3 -4
  64. package/template/src/contexts/dashboard-theme-context.tsx +58 -0
  65. package/template/src/lib/audit-log.ts +0 -2
  66. package/template/src/lib/dashboard-themes.ts +140 -0
  67. package/template/src/lib/default-widgets.ts +14 -0
  68. package/template/src/lib/google-drive.ts +38 -30
  69. package/template/src/lib/permissions.ts +56 -1
  70. package/template/src/lib/prisma.ts +0 -1
  71. package/template/src/lib/widget-registry.ts +177 -0
  72. package/template/src/lib/workflow-executor.ts +7 -13
  73. package/README.md +0 -89
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  const fs = require("fs-extra");
4
- const path = require("path");
4
+ const path = require("node:path");
5
5
  const chalk = require("chalk");
6
6
  const prompts = require("prompts");
7
7
 
@@ -61,11 +61,14 @@ async function main() {
61
61
  DATABASE_URL="" # Supabase Prod
62
62
  DIRECT_URL="" # Supabase Migration
63
63
 
64
- BETTER_AUTH_SECRET=""
64
+ BETTER_AUTH_SECRET="" # openssl rand -base64 32
65
65
  BETTER_AUTH_URL="http://localhost:3000"
66
66
  NEXT_PUBLIC_APP_URL="http://localhost:3000"
67
67
 
68
- APP_NAME="${projectName}"
68
+ APP_NAME="${projectName
69
+ .replaceAll(/\s+/g, "")
70
+ .replaceAll(/([a-z])([A-Z])/g, "$1 $2")
71
+ .replaceAll(/(^\w|\s\w)/g, (m) => m.toUpperCase())}"
69
72
 
70
73
  ENCRYPTION_KEY="" #openssl rand -base64 32
71
74
 
@@ -130,6 +133,7 @@ next-env.d.ts
130
133
 
131
134
  scripts/
132
135
  # vercel.json`;
136
+ fs.writeFileSync(gitIgnoreExemplePath, gitIgnore);
133
137
  }
134
138
 
135
139
  console.log(chalk.green("✅ Projet créé avec succès !\n"));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-crm-tmp",
3
- "version": "1.0.2",
3
+ "version": "1.1.0",
4
4
  "description": "Créer un nouveau projet CRM basé sur le template",
5
5
  "bin": {
6
6
  "create-crm-tmp": "./bin/create-crm-tmp.js"
@@ -1,7 +1,9 @@
1
1
  # 📊 CRM Template
2
2
 
3
- Un CRM moderne, orienté **prospection & suivi commercial**, construit avec **Next.js 16**,
4
- **Better Auth**, **Prisma**, **PostgreSQL** et une UI inspirée d’un template CRM pro.
3
+ Un CRM moderne, orienté **prospection & suivi commercial**, construit avec
4
+ **Next.js 16**,
5
+ **Better Auth**, **Prisma**, **PostgreSQL** et une UI inspirée d’un template CRM
6
+ pro.
5
7
 
6
8
  ## ✨ Fonctionnalités
7
9
 
@@ -31,7 +33,8 @@ Un CRM moderne, orienté **prospection & suivi commercial**, construit avec **Ne
31
33
  - Paramètres généraux (profil, sécurité, informations d’entreprise)
32
34
  - Configuration SMTP + signature email
33
35
  - Gestion des statuts & motifs de fermeture
34
- - Intégrations (Google Calendar & Drive, Google Sheets, Meta Lead Ads, Google Ads…)
36
+ - Intégrations (Google Calendar & Drive, Google Sheets, Meta Lead Ads, Google
37
+ Ads…)
35
38
  - 🤖 **Automatisations (Workflows)**
36
39
  - Workflows avec actions chaînées
37
40
  - Exécution planifiée via **Vercel Cron**
@@ -50,6 +53,66 @@ Un CRM moderne, orienté **prospection & suivi commercial**, construit avec **Ne
50
53
  - **Langage**: TypeScript
51
54
  - **Gestionnaire de paquets**: pnpm
52
55
 
56
+ ## 🚀 Initialiser un projet via le package `create-crm-tmp`
57
+
58
+ Ce template est distribué sous forme de package `create-crm-tmp`.
59
+ Pour créer un nouveau projet basé sur ce CRM :
60
+
61
+ ```bash
62
+ pnpm create crm-tmp@latest mon-crm
63
+ ```
64
+
65
+ Puis :
66
+
67
+ ```bash
68
+ cd mon-crm
69
+ pnpm install
70
+ ```
71
+
72
+ À partir de là, vous pouvez suivre les étapes de configuration ci‑dessous (variables d’environnement, base de données et migrations).
73
+
74
+ ### 🔌 Utiliser Supabase comme base de données PostgreSQL
75
+
76
+ Vous pouvez utiliser **Supabase** uniquement comme **hébergeur PostgreSQL** (l’auth du projet reste gérée par Better Auth).
77
+
78
+ 1. **Créer un projet Supabase**
79
+ - Allez sur le dashboard Supabase.
80
+ - Créez un nouveau projet.
81
+ - Attendez que la base de données soit provisionnée.
82
+ 2. **Récupérer la connexion Postgres**
83
+ - Dans Supabase, ouvrez `Settings > Database`.
84
+ - Copiez la **connection string** en `postgresql://...` (par exemple, pour Node.js / server).
85
+ 3. **Configurer `DATABASE_URL`**
86
+ - Dans votre projet généré (`mon-crm`), créez ou mettez à jour le fichier `.env` :
87
+
88
+ ```env
89
+ # Database (Supabase)
90
+ DATABASE_URL="postgresql://<user>:<password>@<host>:<port>/<database>?sslmode=require"
91
+
92
+ # Better Auth
93
+ BETTER_AUTH_SECRET="votre-clé-secrète-minimum-32-caractères"
94
+ BETTER_AUTH_URL="http://localhost:3000"
95
+
96
+ # Application
97
+ NEXT_PUBLIC_APP_URL="http://localhost:3000"
98
+ NODE_ENV="development"
99
+ ```
100
+
101
+ - Remplacez la valeur de `DATABASE_URL` par celle fournie par Supabase (en gardant les paramètres de sécurité recommandés).
102
+ 4. **Appliquer les migrations Prisma sur Supabase**
103
+
104
+ ```bash
105
+ pnpm prisma migrate deploy
106
+ ```
107
+
108
+ 5. **Lancer l’application**
109
+
110
+ ```bash
111
+ pnpm dev
112
+ ```
113
+
114
+ L’application utilisera désormais la base PostgreSQL hébergée sur Supabase.
115
+
53
116
  ## 🚀 Installation
54
117
 
55
118
  1. **Cloner le projet**
@@ -142,8 +205,10 @@ src/
142
205
  - Redirection vers le dashboard si déjà connecté sur les pages d’auth
143
206
  - **Rôles & permissions** :
144
207
  - Rôles techniques + rôles personnalisés configurables via l’interface
145
- - Vérification des permissions côté API (ex : `users.view`, `users.manage_roles`, intégrations…)
146
- - Certaines sections (informations d’entreprise, paramètres d’application / système, intégrations, export contacts) sont réservées aux administrateurs
208
+ - Vérification des permissions côté API (ex : `users.view`,
209
+ `users.manage_roles`, intégrations)
210
+ - Certaines sections (informations d’entreprise, paramètres d’application /
211
+ système, intégrations, export contacts) sont réservées aux administrateurs
147
212
 
148
213
  ## 🎨 Personnalisation
149
214
 
@@ -1,22 +1,28 @@
1
1
  # Configuration des Workflows avec Vercel Cron
2
2
 
3
- Ce document explique comment fonctionne le système de planification des actions de workflow avec Vercel Cron.
3
+ Ce document explique comment fonctionne le système de planification des actions
4
+ de workflow avec Vercel Cron.
4
5
 
5
6
  ## Fonctionnement
6
7
 
7
- Le système utilise une table `ScheduledWorkflowAction` dans la base de données pour stocker les actions à exécuter plus tard. Un cron job Vercel appelle l'endpoint `/api/workflows/process` toutes les minutes pour traiter les actions dont la date d'exécution est arrivée.
8
+ Le système utilise une table `ScheduledWorkflowAction` dans la base de données
9
+ pour stocker les actions à exécuter plus tard. Un cron job Vercel appelle
10
+ l'endpoint `/api/workflows/process` toutes les minutes pour traiter les actions
11
+ dont la date d'exécution est arrivée.
8
12
 
9
13
  ## Configuration
10
14
 
11
15
  ### 1. Variables d'environnement
12
16
 
13
- Ajoutez cette variable dans votre fichier `.env` et dans les variables d'environnement Vercel :
17
+ Ajoutez cette variable dans votre fichier `.env` et dans les variables
18
+ d'environnement Vercel :
14
19
 
15
20
  ```env
16
21
  CRON_SECRET=votre_secret_aleatoire_ici
17
22
  ```
18
23
 
19
- **Important** : Utilisez un secret fort et aléatoire pour sécuriser l'endpoint cron. Vous pouvez générer un secret avec :
24
+ **Important** : Utilisez un secret fort et aléatoire pour sécuriser l'endpoint
25
+ cron. Vous pouvez générer un secret avec :
20
26
 
21
27
  ```bash
22
28
  openssl rand -base64 32
@@ -24,19 +30,22 @@ openssl rand -base64 32
24
30
 
25
31
  ### 2. Configuration du service de cron (si plan Hobby)
26
32
 
27
- Si vous êtes sur le plan Hobby de Vercel, vous devez utiliser un service externe comme cron-job.org.
33
+ Si vous êtes sur le plan Hobby de Vercel, vous devez utiliser un service externe
34
+ comme cron-job.org.
28
35
 
29
36
  #### Configuration cron-job.org
30
37
 
31
38
  1. Créez un compte sur [cron-job.org](https://cron-job.org/)
32
39
  2. Créez un nouveau cron job avec ces paramètres :
33
- - **URL** : `https://votre-domaine.vercel.app/api/workflows/process?secret=VOTRE_CRON_SECRET`
40
+ - **URL** :
41
+ `https://votre-domaine.vercel.app/api/workflows/process?secret=VOTRE_CRON_SECRET`
34
42
  - **Méthode** : `GET`
35
43
  - **Schedule** : `Every minute` ou `*/1 * * * *`
36
44
  - **Title** : "Workflow Actions Processor"
37
45
  - **Active** : ✓
38
46
 
39
- **Note** : Remplacez `VOTRE_CRON_SECRET` par la valeur de votre variable d'environnement `CRON_SECRET`.
47
+ **Note** : Remplacez `VOTRE_CRON_SECRET` par la valeur de votre variable
48
+ d'environnement `CRON_SECRET`.
40
49
 
41
50
  #### Autres services compatibles
42
51
 
@@ -46,7 +55,8 @@ Si vous êtes sur le plan Hobby de Vercel, vous devez utiliser un service extern
46
55
 
47
56
  ### 3. Migration Prisma
48
57
 
49
- Après avoir ajouté le modèle `ScheduledWorkflowAction` dans `schema.prisma`, créez et exécutez la migration :
58
+ Après avoir ajouté le modèle `ScheduledWorkflowAction` dans `schema.prisma`,
59
+ créez et exécutez la migration :
50
60
 
51
61
  ```bash
52
62
  pnpm prisma migrate dev --name add_scheduled_workflow_actions
@@ -54,7 +64,8 @@ pnpm prisma migrate dev --name add_scheduled_workflow_actions
54
64
 
55
65
  ### 4. Configuration Vercel (optionnel - plans Pro/Enterprise uniquement)
56
66
 
57
- Le fichier `vercel.json` est configuré pour exécuter le cron toutes les minutes :
67
+ Le fichier `vercel.json` est configuré pour exécuter le cron toutes les minutes
68
+ :
58
69
 
59
70
  ```json
60
71
  {
@@ -67,20 +78,26 @@ Le fichier `vercel.json` est configuré pour exécuter le cron toutes les minute
67
78
  }
68
79
  ```
69
80
 
70
- **Note** : Vercel Cron est disponible uniquement sur les plans Pro et Enterprise. Sur le plan Hobby, utilisez un service externe comme cron-job.org (voir section 2).
81
+ **Note** : Vercel Cron est disponible uniquement sur les plans Pro et
82
+ Enterprise. Sur le plan Hobby, utilisez un service externe comme cron-job.org
83
+ (voir section 2).
71
84
 
72
85
  ### 5. Déploiement
73
86
 
74
87
  1. Poussez vos changements sur votre repository
75
- 2. Si vous êtes sur plan Pro/Enterprise : Vercel détectera automatiquement le fichier `vercel.json` et configurera le cron
76
- 3. Si vous êtes sur plan Hobby : Configurez cron-job.org ou un autre service externe (voir section 2)
77
- 4. Vérifiez que `CRON_SECRET` est bien configuré dans les variables d'environnement Vercel
88
+ 2. Si vous êtes sur plan Pro/Enterprise : Vercel détectera automatiquement le
89
+ fichier `vercel.json` et configurera le cron
90
+ 3. Si vous êtes sur plan Hobby : Configurez cron-job.org ou un autre service
91
+ externe (voir section 2)
92
+ 4. Vérifiez que `CRON_SECRET` est bien configuré dans les variables
93
+ d'environnement Vercel
78
94
 
79
95
  ## Fonctionnement détaillé
80
96
 
81
97
  ### Planification d'une action
82
98
 
83
- Quand un workflow est déclenché et qu'une action a un délai (jours/heures), le système :
99
+ Quand un workflow est déclenché et qu'une action a un délai (jours/heures), le
100
+ système :
84
101
 
85
102
  1. Calcule la date d'exécution : `Date.now() + délai`
86
103
  2. Sauvegarde l'action dans `ScheduledWorkflowAction` avec :
@@ -114,26 +131,29 @@ Vous pouvez surveiller les actions planifiées via la base de données :
114
131
 
115
132
  ```sql
116
133
  -- Actions en attente
117
- SELECT * FROM scheduled_workflow_action
118
- WHERE executed = false
134
+ SELECT * FROM scheduled_workflow_action
135
+ WHERE executed = false
119
136
  ORDER BY executeAt ASC;
120
137
 
121
138
  -- Actions récemment exécutées
122
- SELECT * FROM scheduled_workflow_action
123
- WHERE executed = true
124
- ORDER BY executedAt DESC
139
+ SELECT * FROM scheduled_workflow_action
140
+ WHERE executed = true
141
+ ORDER BY executedAt DESC
125
142
  LIMIT 50;
126
143
 
127
144
  -- Actions en erreur
128
- SELECT * FROM scheduled_workflow_action
145
+ SELECT * FROM scheduled_workflow_action
129
146
  WHERE executed = true AND error IS NOT NULL;
130
147
  ```
131
148
 
132
149
  ## Limitations
133
150
 
134
- - **Précision** : Les actions sont exécutées avec une précision d'environ 1 minute (selon la fréquence du cron)
135
- - **Limite par exécution** : Maximum 50 actions traitées par exécution du cron (pour éviter les timeouts)
136
- - **Retry** : Les actions échouées ne sont pas automatiquement réessayées (elles sont marquées comme exécutées avec une erreur)
151
+ - **Précision** : Les actions sont exécutées avec une précision d'environ 1
152
+ minute (selon la fréquence du cron)
153
+ - **Limite par exécution** : Maximum 50 actions traitées par exécution du cron
154
+ (pour éviter les timeouts)
155
+ - **Retry** : Les actions échouées ne sont pas automatiquement réessayées (elles
156
+ sont marquées comme exécutées avec une erreur)
137
157
 
138
158
  ## Dépannage
139
159
 
@@ -141,14 +161,16 @@ WHERE executed = true AND error IS NOT NULL;
141
161
 
142
162
  1. **Si vous utilisez Vercel Cron** :
143
163
  - Vérifiez que vous êtes sur un plan Vercel Pro ou Enterprise
144
- - Vérifiez dans le dashboard Vercel que le cron est bien configuré (Settings → Cron Jobs)
164
+ - Vérifiez dans le dashboard Vercel que le cron est bien configuré (Settings
165
+ → Cron Jobs)
145
166
  - Vérifiez les logs Vercel pour voir les erreurs éventuelles
146
167
 
147
168
  2. **Si vous utilisez un service externe (cron-job.org, etc.)** :
148
169
  - Vérifiez que le job est actif dans votre service
149
170
  - Vérifiez l'URL utilisée (doit inclure `?secret=VOTRE_CRON_SECRET`)
150
171
  - Vérifiez les logs de votre service de cron
151
- - Testez manuellement l'URL dans votre navigateur (avec le secret) pour voir si elle répond
172
+ - Testez manuellement l'URL dans votre navigateur (avec le secret) pour voir
173
+ si elle répond
152
174
 
153
175
  ### Les actions ne s'exécutent pas
154
176
 
@@ -159,5 +181,5 @@ WHERE executed = true AND error IS NOT NULL;
159
181
 
160
182
  ### Erreurs d'exécution
161
183
 
162
- Les erreurs sont enregistrées dans le champ `error` de `ScheduledWorkflowAction`. Consultez ce champ pour diagnostiquer les problèmes.
163
-
184
+ Les erreurs sont enregistrées dans le champ `error` de
185
+ `ScheduledWorkflowAction`. Consultez ce champ pour diagnostiquer les problèmes.
@@ -21,42 +21,44 @@
21
21
  "@lexical/selection": "^0.38.2",
22
22
  "@lexical/utils": "^0.38.2",
23
23
  "@lexkit/editor": "^0.0.38",
24
- "@prisma/adapter-pg": "^7.1.0",
25
- "@prisma/client": "^7.1.0",
26
- "@react-email/render": "^2.0.0",
24
+ "@prisma/adapter-pg": "^7.3.0",
25
+ "@prisma/client": "^7.3.0",
26
+ "@react-email/render": "^2.0.4",
27
27
  "bcryptjs": "^3.0.3",
28
- "better-auth": "^1.4.6",
28
+ "better-auth": "^1.4.18",
29
29
  "clsx": "^2.1.1",
30
- "dotenv": "^17.2.3",
30
+ "dotenv": "^17.2.4",
31
31
  "iron-session": "^8.0.4",
32
32
  "lexical": "^0.38.2",
33
33
  "lucide-react": "^0.555.0",
34
34
  "next": "16.0.10",
35
- "nodemailer": "^7.0.11",
35
+ "nodemailer": "^7.0.13",
36
36
  "papaparse": "^5.5.3",
37
- "pg": "^8.16.3",
37
+ "pg": "^8.18.0",
38
38
  "react": "19.2.3",
39
39
  "react-dom": "19.2.3",
40
- "react-hook-form": "^7.68.0",
40
+ "react-grid-layout": "^2.2.2",
41
+ "react-hook-form": "^7.71.1",
41
42
  "recharts": "^2.15.4",
42
43
  "tailwind-merge": "^3.4.0",
43
44
  "xlsx": "^0.18.5",
44
- "zod": "^4.1.13"
45
+ "zod": "^4.3.6"
45
46
  },
46
47
  "devDependencies": {
47
48
  "@tailwindcss/postcss": "^4.1.18",
48
- "@types/node": "^20.19.26",
49
- "@types/nodemailer": "^7.0.4",
50
- "@types/papaparse": "^5.5.1",
49
+ "@types/node": "^20.19.33",
50
+ "@types/nodemailer": "^7.0.9",
51
+ "@types/papaparse": "^5.5.2",
51
52
  "@types/pg": "^8.16.0",
52
- "@types/react": "^19.2.7",
53
+ "@types/react": "^19.2.13",
53
54
  "@types/react-dom": "^19.2.3",
55
+ "@types/react-grid-layout": "^2.1.0",
54
56
  "babel-plugin-react-compiler": "1.0.0",
55
- "eslint": "^9.39.1",
57
+ "eslint": "^9.39.2",
56
58
  "eslint-config-next": "16.0.7",
57
- "prettier": "^3.7.4",
59
+ "prettier": "^3.8.1",
58
60
  "prettier-plugin-tailwindcss": "^0.7.2",
59
- "prisma": "^7.1.0",
61
+ "prisma": "^7.3.0",
60
62
  "tailwindcss": "^4.1.18",
61
63
  "tsx": "^4.21.0",
62
64
  "typescript": "^5.9.3"
@@ -0,0 +1,20 @@
1
+ -- CreateTable
2
+ CREATE TABLE "dashboard_widget" (
3
+ "id" TEXT NOT NULL,
4
+ "userId" TEXT NOT NULL,
5
+ "type" TEXT NOT NULL,
6
+ "x" INTEGER NOT NULL DEFAULT 0,
7
+ "y" INTEGER NOT NULL DEFAULT 0,
8
+ "w" INTEGER NOT NULL DEFAULT 6,
9
+ "h" INTEGER NOT NULL DEFAULT 4,
10
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
11
+ "updatedAt" TIMESTAMP(3) NOT NULL,
12
+
13
+ CONSTRAINT "dashboard_widget_pkey" PRIMARY KEY ("id")
14
+ );
15
+
16
+ -- CreateIndex
17
+ CREATE INDEX "dashboard_widget_userId_idx" ON "dashboard_widget"("userId");
18
+
19
+ -- AddForeignKey
20
+ ALTER TABLE "dashboard_widget" ADD CONSTRAINT "dashboard_widget_userId_fkey" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE CASCADE;
@@ -67,6 +67,7 @@ model User {
67
67
  auditLogsAsActor AuditLog[] @relation("AuditActor")
68
68
  auditLogsAsTargetUser AuditLog[] @relation("AuditTargetUser")
69
69
  workflows Workflow[] @relation("WorkflowOwner")
70
+ dashboardWidgets DashboardWidget[]
70
71
 
71
72
  @@unique([email])
72
73
  @@index([customRoleId])
@@ -583,3 +584,19 @@ model ScheduledWorkflowAction {
583
584
  @@index([workflowId])
584
585
  @@map("scheduled_workflow_action")
585
586
  }
587
+
588
+ model DashboardWidget {
589
+ id String @id @default(cuid())
590
+ userId String
591
+ user User @relation(fields: [userId], references: [id], onDelete: Cascade)
592
+ type String // Identifiant du type de widget (ex: stat_total_contacts, contacts_chart, etc.)
593
+ x Int @default(0)
594
+ y Int @default(0)
595
+ w Int @default(6) // Largeur sur grille de 12
596
+ h Int @default(4) // Hauteur en unités
597
+ createdAt DateTime @default(now())
598
+ updatedAt DateTime @updatedAt
599
+
600
+ @@index([userId])
601
+ @@map("dashboard_widget")
602
+ }