create-crm-tmp 1.1.3 → 2.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 (276) hide show
  1. package/bin/create-crm-tmp.js +56 -35
  2. package/package.json +1 -1
  3. package/template/.prettierignore +2 -0
  4. package/template/README.md +230 -115
  5. package/template/components.json +22 -0
  6. package/template/eslint.config.mjs +13 -0
  7. package/template/exemple-contacts.csv +54 -0
  8. package/template/next.config.ts +41 -1
  9. package/template/package.json +63 -15
  10. package/template/prisma/migrations/20260318095700_init_db/migration.sql +978 -0
  11. package/template/prisma/schema.prisma +311 -67
  12. package/template/src/app/(auth)/invite/[token]/page.tsx +28 -29
  13. package/template/src/app/(auth)/layout.tsx +1 -1
  14. package/template/src/app/(auth)/reset-password/complete/page.tsx +21 -27
  15. package/template/src/app/(auth)/reset-password/page.tsx +14 -10
  16. package/template/src/app/(auth)/reset-password/verify/page.tsx +14 -10
  17. package/template/src/app/(auth)/signin/page.tsx +34 -23
  18. package/template/src/app/(dashboard)/agenda/page.tsx +3655 -2357
  19. package/template/src/app/(dashboard)/automatisation/[id]/page.tsx +10 -7
  20. package/template/src/app/(dashboard)/automatisation/_components/workflow-editor.tsx +609 -338
  21. package/template/src/app/(dashboard)/automatisation/new/page.tsx +11 -8
  22. package/template/src/app/(dashboard)/automatisation/page.tsx +463 -186
  23. package/template/src/app/(dashboard)/closing/page.tsx +517 -469
  24. package/template/src/app/(dashboard)/contacts/[id]/page.tsx +6151 -4210
  25. package/template/src/app/(dashboard)/contacts/companies/[id]/page.tsx +1702 -0
  26. package/template/src/app/(dashboard)/contacts/loading.tsx +13 -0
  27. package/template/src/app/(dashboard)/contacts/page.tsx +4124 -2130
  28. package/template/src/app/(dashboard)/dashboard/page.tsx +119 -105
  29. package/template/src/app/(dashboard)/dev/page.tsx +1291 -0
  30. package/template/src/app/(dashboard)/error.tsx +37 -0
  31. package/template/src/app/(dashboard)/layout.tsx +6 -2
  32. package/template/src/app/(dashboard)/loading.tsx +5 -0
  33. package/template/src/app/(dashboard)/settings/loading.tsx +19 -0
  34. package/template/src/app/(dashboard)/settings/page.tsx +1773 -3362
  35. package/template/src/app/(dashboard)/templates/page.tsx +504 -303
  36. package/template/src/app/(dashboard)/users/list/page.tsx +364 -355
  37. package/template/src/app/(dashboard)/users/page.tsx +279 -310
  38. package/template/src/app/(dashboard)/users/permissions/page.tsx +104 -99
  39. package/template/src/app/(dashboard)/users/roles/page.tsx +169 -140
  40. package/template/src/app/api/agenda/google-events/route.ts +92 -0
  41. package/template/src/app/api/audit-logs/route.ts +1 -1
  42. package/template/src/app/api/auth/check-active/route.ts +3 -2
  43. package/template/src/app/api/auth/google/callback/route.ts +8 -5
  44. package/template/src/app/api/auth/google/disconnect/route.ts +2 -2
  45. package/template/src/app/api/auth/google/route.ts +2 -1
  46. package/template/src/app/api/auth/google/status/route.ts +7 -31
  47. package/template/src/app/api/companies/[id]/activities/route.ts +129 -0
  48. package/template/src/app/api/companies/[id]/route.ts +194 -0
  49. package/template/src/app/api/companies/export/route.ts +206 -0
  50. package/template/src/app/api/companies/route.ts +196 -0
  51. package/template/src/app/api/contact-views/[id]/pin/route.ts +69 -0
  52. package/template/src/app/api/contact-views/[id]/route.ts +197 -0
  53. package/template/src/app/api/contact-views/route.ts +146 -0
  54. package/template/src/app/api/contacts/[id]/files/[fileId]/preview/route.ts +55 -0
  55. package/template/src/app/api/contacts/[id]/files/[fileId]/route.ts +20 -48
  56. package/template/src/app/api/contacts/[id]/files/route.ts +125 -186
  57. package/template/src/app/api/contacts/[id]/interactions/[interactionId]/route.ts +27 -1
  58. package/template/src/app/api/contacts/[id]/interactions/route.ts +45 -8
  59. package/template/src/app/api/contacts/[id]/kyc/route.ts +81 -0
  60. package/template/src/app/api/contacts/[id]/meet/route.ts +55 -29
  61. package/template/src/app/api/contacts/[id]/route.ts +184 -21
  62. package/template/src/app/api/contacts/[id]/send-email/route.ts +33 -11
  63. package/template/src/app/api/contacts/[id]/workflows/run/route.ts +67 -0
  64. package/template/src/app/api/contacts/export/route.ts +22 -31
  65. package/template/src/app/api/contacts/import/route.ts +77 -44
  66. package/template/src/app/api/contacts/import-preview/route.ts +139 -0
  67. package/template/src/app/api/contacts/origins/route.ts +63 -0
  68. package/template/src/app/api/contacts/route.ts +322 -57
  69. package/template/src/app/api/cron/cleanup-editor-images/route.ts +166 -0
  70. package/template/src/app/api/dashboard/stats/route.ts +9 -292
  71. package/template/src/app/api/dashboard/widgets/[id]/route.ts +0 -3
  72. package/template/src/app/api/dashboard/widgets/route.ts +19 -19
  73. package/template/src/app/api/dev/reminders/test/route.ts +114 -0
  74. package/template/src/app/api/editor/upload-image/route.ts +61 -0
  75. package/template/src/app/api/integrations/google-sheet/jobs/[jobId]/route.ts +47 -0
  76. package/template/src/app/api/integrations/google-sheet/jobs/usage/route.ts +50 -0
  77. package/template/src/app/api/integrations/google-sheet/sync/route.ts +28 -542
  78. package/template/src/app/api/invite/complete/route.ts +20 -23
  79. package/template/src/app/api/jobs/google-sheet/process/route.ts +84 -0
  80. package/template/src/app/api/jobs/google-sheet/schedule/route.ts +50 -0
  81. package/template/src/app/api/reminders/clear/route.ts +120 -0
  82. package/template/src/app/api/reminders/clear/undo/route.ts +112 -0
  83. package/template/src/app/api/reminders/route.ts +165 -39
  84. package/template/src/app/api/reminders/state/route.ts +164 -0
  85. package/template/src/app/api/reset-password/complete/route.ts +11 -13
  86. package/template/src/app/api/reset-password/request/route.ts +1 -1
  87. package/template/src/app/api/reset-password/verify/route.ts +1 -1
  88. package/template/src/app/api/send/route.ts +25 -47
  89. package/template/src/app/api/settings/closing-reasons/[id]/route.ts +10 -21
  90. package/template/src/app/api/settings/closing-reasons/route.ts +10 -21
  91. package/template/src/app/api/settings/company/route.ts +19 -26
  92. package/template/src/app/api/settings/google-ads/[id]/route.ts +20 -23
  93. package/template/src/app/api/settings/google-ads/route.ts +34 -23
  94. package/template/src/app/api/settings/google-calendar/calendars/route.ts +97 -0
  95. package/template/src/app/api/settings/google-calendar/route.ts +124 -0
  96. package/template/src/app/api/settings/google-sheet/[id]/route.ts +48 -23
  97. package/template/src/app/api/settings/google-sheet/auto-map/route.ts +56 -32
  98. package/template/src/app/api/settings/google-sheet/preview/route.ts +110 -0
  99. package/template/src/app/api/settings/google-sheet/route.ts +34 -23
  100. package/template/src/app/api/settings/integrations/logs/route.ts +93 -0
  101. package/template/src/app/api/settings/integrations/notifications/route.ts +67 -0
  102. package/template/src/app/api/settings/meta-leads/[id]/route.ts +20 -24
  103. package/template/src/app/api/settings/meta-leads/route.ts +34 -25
  104. package/template/src/app/api/settings/smtp/route.ts +53 -6
  105. package/template/src/app/api/settings/statuses/[id]/route.ts +29 -32
  106. package/template/src/app/api/settings/statuses/route.ts +24 -22
  107. package/template/src/app/api/statuses/route.ts +2 -5
  108. package/template/src/app/api/tasks/[id]/attendees/route.ts +36 -13
  109. package/template/src/app/api/tasks/[id]/route.ts +357 -145
  110. package/template/src/app/api/tasks/meet/route.ts +37 -26
  111. package/template/src/app/api/tasks/route.ts +201 -96
  112. package/template/src/app/api/templates/[id]/route.ts +22 -13
  113. package/template/src/app/api/templates/route.ts +22 -5
  114. package/template/src/app/api/users/[id]/resend-invite/route.ts +95 -0
  115. package/template/src/app/api/users/[id]/route.ts +22 -16
  116. package/template/src/app/api/users/commercials/route.ts +38 -0
  117. package/template/src/app/api/users/for-agenda/route.ts +1 -2
  118. package/template/src/app/api/users/list/route.ts +57 -19
  119. package/template/src/app/api/users/route.ts +89 -34
  120. package/template/src/app/api/webhooks/google-ads/route.ts +40 -1
  121. package/template/src/app/api/webhooks/meta-leads/route.ts +38 -1
  122. package/template/src/app/api/workflows/[id]/route.ts +29 -6
  123. package/template/src/app/api/workflows/process/route.ts +505 -170
  124. package/template/src/app/api/workflows/route.ts +42 -4
  125. package/template/src/app/globals.css +512 -32
  126. package/template/src/app/layout.tsx +28 -9
  127. package/template/src/app/page.tsx +37 -7
  128. package/template/src/components/address-autocomplete.tsx +233 -0
  129. package/template/src/components/config-error-alert.tsx +46 -0
  130. package/template/src/components/contacts/filter-bar.tsx +190 -0
  131. package/template/src/components/contacts/filter-builder.tsx +574 -0
  132. package/template/src/components/contacts/save-view-dialog.tsx +160 -0
  133. package/template/src/components/contacts/views-tab-bar.tsx +449 -0
  134. package/template/src/components/dashboard/activity-chart.tsx +6 -1
  135. package/template/src/components/dashboard/add-widget-dialog.tsx +13 -17
  136. package/template/src/components/dashboard/color-picker.tsx +7 -8
  137. package/template/src/components/dashboard/recent-activity.tsx +2 -5
  138. package/template/src/components/dashboard/stat-card.tsx +1 -3
  139. package/template/src/components/dashboard/status-distribution-chart.tsx +0 -1
  140. package/template/src/components/dashboard/top-contacts-list.tsx +7 -13
  141. package/template/src/components/dashboard/upcoming-tasks-list.tsx +2 -5
  142. package/template/src/components/dashboard/widget-wrapper.tsx +3 -6
  143. package/template/src/components/date-picker.tsx +399 -0
  144. package/template/src/components/editor/upload-editor-image.ts +42 -0
  145. package/template/src/components/editor.tsx +188 -35
  146. package/template/src/components/email-template.tsx +4 -2
  147. package/template/src/components/global-search.tsx +360 -0
  148. package/template/src/components/header.tsx +200 -107
  149. package/template/src/components/inactive-account-guard.tsx +58 -0
  150. package/template/src/components/integration-notifications-listener.tsx +12 -0
  151. package/template/src/components/invitation-email-template.tsx +4 -2
  152. package/template/src/components/lazy-editor.tsx +11 -0
  153. package/template/src/components/meet-cancellation-email-template.tsx +11 -3
  154. package/template/src/components/meet-confirmation-email-template.tsx +10 -3
  155. package/template/src/components/meet-update-email-template.tsx +10 -3
  156. package/template/src/components/page-header.tsx +19 -15
  157. package/template/src/components/protected-page.tsx +94 -0
  158. package/template/src/components/reset-password-email-template.tsx +4 -2
  159. package/template/src/components/settings/integrations/GoogleAdsIntegration.tsx +428 -0
  160. package/template/src/components/settings/integrations/GoogleSheetConfigMonitoringModal.tsx +680 -0
  161. package/template/src/components/settings/integrations/GoogleSheetIntegration.tsx +809 -0
  162. package/template/src/components/settings/integrations/ImportResultDialog.tsx +124 -0
  163. package/template/src/components/settings/integrations/IntegrationLogPanel.tsx +57 -0
  164. package/template/src/components/settings/integrations/IntegrationLogsTable.tsx +186 -0
  165. package/template/src/components/settings/integrations/MetaLeadIntegration.tsx +451 -0
  166. package/template/src/components/sidebar.tsx +117 -100
  167. package/template/src/components/skeleton.tsx +128 -45
  168. package/template/src/components/ui/accordion.tsx +64 -0
  169. package/template/src/components/ui/alert-dialog.tsx +139 -0
  170. package/template/src/components/ui/button.tsx +71 -0
  171. package/template/src/components/ui/components.tsx +1 -1
  172. package/template/src/components/ui/date-picker.tsx +422 -0
  173. package/template/src/components/ui/datetime-picker.tsx +338 -0
  174. package/template/src/components/ui/status-select.tsx +271 -0
  175. package/template/src/components/ui/tooltip.tsx +37 -0
  176. package/template/src/components/view-as-banner.tsx +1 -1
  177. package/template/src/components/view-as-modal.tsx +30 -19
  178. package/template/src/config/nav-pages.ts +108 -0
  179. package/template/src/contexts/app-toast-context.tsx +362 -0
  180. package/template/src/contexts/dashboard-theme-context.tsx +2 -7
  181. package/template/src/contexts/sidebar-context.tsx +27 -53
  182. package/template/src/contexts/task-reminder-context.tsx +134 -160
  183. package/template/src/contexts/view-as-context.tsx +32 -10
  184. package/template/src/hooks/use-alert.tsx +65 -0
  185. package/template/src/hooks/use-confirm.tsx +87 -0
  186. package/template/src/hooks/use-contact-views.ts +140 -0
  187. package/template/src/hooks/use-contacts.ts +69 -0
  188. package/template/src/hooks/use-fetch.ts +17 -0
  189. package/template/src/hooks/use-focus-trap.ts +73 -0
  190. package/template/src/hooks/use-statuses.ts +22 -0
  191. package/template/src/hooks/useIntegrationNotifications.ts +49 -0
  192. package/template/src/lib/address-api.ts +155 -0
  193. package/template/src/lib/auth.ts +8 -1
  194. package/template/src/lib/cache.ts +73 -0
  195. package/template/src/lib/check-permission.ts +12 -177
  196. package/template/src/lib/config-links.ts +14 -0
  197. package/template/src/lib/contact-duplicate.ts +79 -61
  198. package/template/src/lib/contact-interactions.ts +24 -22
  199. package/template/src/lib/contact-view-filters.ts +301 -0
  200. package/template/src/lib/contacts-list-url.ts +190 -0
  201. package/template/src/lib/dashboard-stats.ts +282 -0
  202. package/template/src/lib/dashboard-themes.ts +0 -5
  203. package/template/src/lib/date-utils.ts +176 -0
  204. package/template/src/lib/default-widgets.ts +0 -2
  205. package/template/src/lib/editor-html-image-dimensions.ts +172 -0
  206. package/template/src/lib/editor-image-limits.ts +19 -0
  207. package/template/src/lib/email-html-sanitize.ts +19 -0
  208. package/template/src/lib/encryption.ts +9 -6
  209. package/template/src/lib/fr-geography.ts +192 -0
  210. package/template/src/lib/get-auth-user.ts +25 -0
  211. package/template/src/lib/google-calendar-agenda.ts +201 -0
  212. package/template/src/lib/google-calendar.ts +309 -17
  213. package/template/src/lib/google-fetch.ts +63 -0
  214. package/template/src/lib/google-sheet-sync-jobs.ts +96 -0
  215. package/template/src/lib/google-sheet-sync-runner.ts +514 -0
  216. package/template/src/lib/integration-import-log.ts +21 -0
  217. package/template/src/lib/local-storage.ts +34 -0
  218. package/template/src/lib/permissions.ts +268 -40
  219. package/template/src/lib/prisma.ts +15 -12
  220. package/template/src/lib/qstash.ts +65 -0
  221. package/template/src/lib/reminder-state-server.ts +80 -0
  222. package/template/src/lib/reminder-state.ts +29 -0
  223. package/template/src/lib/roles.ts +12 -15
  224. package/template/src/lib/supabase-storage.ts +113 -0
  225. package/template/src/lib/template-variables.ts +204 -29
  226. package/template/src/lib/utils.ts +71 -11
  227. package/template/src/lib/widget-registry.ts +0 -4
  228. package/template/src/lib/workflow-executor.ts +391 -228
  229. package/template/src/proxy.ts +35 -73
  230. package/template/src/types/contact-views.ts +351 -0
  231. package/template/vercel.json +5 -0
  232. package/template/WORKFLOWS_CRON.md +0 -185
  233. package/template/prisma/migrations/20251126144728_init/migration.sql +0 -78
  234. package/template/prisma/migrations/20251126155204_add_user_roles/migration.sql +0 -5
  235. package/template/prisma/migrations/20251128095126_add_company_info/migration.sql +0 -19
  236. package/template/prisma/migrations/20251128123321_add_smtp_config/migration.sql +0 -22
  237. package/template/prisma/migrations/20251128132303_add_status/migration.sql +0 -23
  238. package/template/prisma/migrations/20251201102207_add_user_active/migration.sql +0 -75
  239. package/template/prisma/migrations/20251201105507_add_email_signature/migration.sql +0 -2
  240. package/template/prisma/migrations/20251201151122_add_tasks/migration.sql +0 -45
  241. package/template/prisma/migrations/20251202111854_add_task_reminder/migration.sql +0 -2
  242. package/template/prisma/migrations/20251202135859_add_google_meet_integration/migration.sql +0 -27
  243. package/template/prisma/migrations/20251203103317_add_meta_lead_integration/migration.sql +0 -20
  244. package/template/prisma/migrations/20251203104002_add_google_ads_integration/migration.sql +0 -18
  245. package/template/prisma/migrations/20251203112122_add_google_sheet_integration/migration.sql +0 -32
  246. package/template/prisma/migrations/20251203153853_allow_multiple_integration_configs/migration.sql +0 -20
  247. package/template/prisma/migrations/20251205141705_update_user_roles/migration.sql +0 -12
  248. package/template/prisma/migrations/20251205150000_add_commercial_and_telepro_assignment/migration.sql +0 -21
  249. package/template/prisma/migrations/20251205160000_add_interaction_logging/migration.sql +0 -11
  250. package/template/prisma/migrations/20251208090314_add_automatic_interaction_types/migration.sql +0 -12
  251. package/template/prisma/migrations/20251208094843_mg/migration.sql +0 -14
  252. package/template/prisma/migrations/20251208100000_add_company_support/migration.sql +0 -14
  253. package/template/prisma/migrations/20251208110000_add_templates/migration.sql +0 -26
  254. package/template/prisma/migrations/20251208141304_add_video_conference_task_type/migration.sql +0 -2
  255. package/template/prisma/migrations/20251209104759_add_internal_note_to_task/migration.sql +0 -2
  256. package/template/prisma/migrations/20251209134803_add_company_field/migration.sql +0 -2
  257. package/template/prisma/migrations/20251209150000_rename_company_to_company_name/migration.sql +0 -3
  258. package/template/prisma/migrations/20251209150016_add_email_tracking/migration.sql +0 -21
  259. package/template/prisma/migrations/20251209155908_add_notify_contact_to_task/migration.sql +0 -2
  260. package/template/prisma/migrations/20251210110019_add_appointment_types/migration.sql +0 -10
  261. package/template/prisma/migrations/20251210113928_add_contact_files/migration.sql +0 -26
  262. package/template/prisma/migrations/20251212132339_add_custom_roles/migration.sql +0 -24
  263. package/template/prisma/migrations/20251215104448_add_file_interaction_types/migration.sql +0 -11
  264. package/template/prisma/migrations/20251215145616_add_closing_reasons/migration.sql +0 -12
  265. package/template/prisma/migrations/20251216140850_add_log_users/migration.sql +0 -25
  266. package/template/prisma/migrations/20251216151000_rename_perdu_to_ferme/migration.sql +0 -8
  267. package/template/prisma/migrations/20251216162318_add_column_mappings_to_google_sheet/migration.sql +0 -2
  268. package/template/prisma/migrations/20251216185127_add_workflows/migration.sql +0 -80
  269. package/template/prisma/migrations/20251216192237_add_scheduled_workflow_actions/migration.sql +0 -32
  270. package/template/prisma/migrations/20251220000000_add_task_interaction_type/migration.sql +0 -4
  271. package/template/prisma/migrations/20251221000000_add_task_type/migration.sql +0 -3
  272. package/template/prisma/migrations/20251221000001_add_event_color/migration.sql +0 -23
  273. package/template/prisma/migrations/20260210114913_add_dashboard_widget/migration.sql +0 -20
  274. package/template/prisma/migrations/20260226093949_fix_cascade_on_user_delete/migration.sql +0 -69
  275. package/template/src/app/(dashboard)/users/layout.tsx +0 -30
  276. package/template/src/lib/google-drive.ts +0 -380
@@ -10,7 +10,7 @@ async function main() {
10
10
  const projectName = args[0];
11
11
 
12
12
  if (!projectName) {
13
- console.error(chalk.red("Veuillez spécifier un nom de projet"));
13
+ console.error(chalk.red("Veuillez spécifier un nom de projet"));
14
14
  console.log(chalk.yellow("\nUsage: pnpm create crm-tmp@latest mon-crm\n"));
15
15
  process.exit(1);
16
16
  }
@@ -27,14 +27,14 @@ async function main() {
27
27
  });
28
28
 
29
29
  if (!overwrite) {
30
- console.log(chalk.yellow("Opération annulée"));
30
+ console.log(chalk.yellow("Opération annulée"));
31
31
  process.exit(1);
32
32
  }
33
33
 
34
34
  fs.removeSync(targetDir);
35
35
  }
36
36
 
37
- console.log(chalk.blue(`\n🚀 Création du projet CRM "${projectName}"...\n`));
37
+ console.log(chalk.blue(`\nCréation du projet CRM "${projectName}"...\n`));
38
38
 
39
39
  // Copier le template
40
40
  const templateDir = path.join(__dirname, "..", "template");
@@ -54,39 +54,57 @@ async function main() {
54
54
  JSON.stringify(packageJson, null, 2) + "\n"
55
55
  );
56
56
 
57
+ // Formater le nom du projet pour APP_NAME
58
+ const appName = projectName
59
+ .replace(/[-_]+/g, " ")
60
+ .replace(/(^\w|\s\w)/g, (m) => m.toUpperCase())
61
+ .trim();
62
+
57
63
  // Créer un fichier .env
58
- const envExamplePath = path.join(targetDir, ".env");
59
- if (!fs.existsSync(envExamplePath)) {
60
- const envExample = `# Database
61
- DATABASE_URL="" # Supabase Prod
62
- DIRECT_URL="" # Supabase Migration
64
+ const envPath = path.join(targetDir, ".env");
65
+ if (!fs.existsSync(envPath)) {
66
+ const envContent = `# Database (Supabase PostgreSQL)
67
+ DATABASE_URL="" # Supabase pooled connection string (Transaction mode)
68
+ DIRECT_URL="" # Supabase direct connection string (pour les migrations Prisma)
63
69
 
70
+ # Authentification (Better Auth)
64
71
  BETTER_AUTH_SECRET="" # openssl rand -base64 32
65
72
  BETTER_AUTH_URL="http://localhost:3000"
66
73
  NEXT_PUBLIC_APP_URL="http://localhost:3000"
67
74
 
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())}"
75
+ # Application
76
+ APP_NAME="${appName}"
72
77
 
78
+ # Chiffrement (SMTP passwords, etc.)
73
79
  ENCRYPTION_KEY="" # openssl rand -base64 32
74
80
 
75
- # API Google à ajouter dans console.cloud.google : Google Drive API, Google Calendar API, Google Sheet API
81
+ # Google Cloud APIs (Calendar, Sheets, Drive)
82
+ # Voir README.md > Guide Google Cloud pour la configuration
76
83
  GOOGLE_CLIENT_ID=""
77
84
  GOOGLE_CLIENT_SECRET=""
78
85
  GOOGLE_REDIRECT_URI="http://localhost:3000/api/auth/google/callback"
79
86
 
87
+ # Vercel Cron (authentification des jobs planifiés)
80
88
  CRON_SECRET="" # openssl rand -base64 32
89
+
90
+ # QStash (Upstash) - Traitement asynchrone des jobs (Google Sheets sync)
91
+ # Voir README.md > Guide QStash pour la configuration
92
+ QSTASH_TOKEN=""
93
+ QSTASH_CURRENT_SIGNING_KEY=""
94
+ QSTASH_NEXT_SIGNING_KEY=""
95
+
96
+ # Supabase Storage - Upload de fichiers (contacts, images éditeur)
97
+ # Voir README.md > Guide Supabase Storage pour la configuration
98
+ NEXT_PUBLIC_SUPABASE_URL=""
99
+ SUPABASE_SERVICE_ROLE_KEY=""
81
100
  `;
82
- fs.writeFileSync(envExamplePath, envExample);
101
+ fs.writeFileSync(envPath, envContent);
83
102
  }
84
103
 
85
- const gitIgnoreExemplePath = path.join(targetDir, ".gitignore");
86
- if (!fs.existsSync(gitIgnoreExemplePath)) {
87
- const gitIgnore = `# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
88
-
89
- # dependencies
104
+ // Créer un fichier .gitignore
105
+ const gitIgnorePath = path.join(targetDir, ".gitignore");
106
+ if (!fs.existsSync(gitIgnorePath)) {
107
+ const gitIgnore = `# dependencies
90
108
  /node_modules
91
109
  /.pnp
92
110
  .pnp.*
@@ -116,7 +134,7 @@ yarn-debug.log*
116
134
  yarn-error.log*
117
135
  .pnpm-debug.log*
118
136
 
119
- # env files (can opt-in for committing if needed)
137
+ # env files
120
138
  .env*
121
139
 
122
140
  # vercel
@@ -126,29 +144,32 @@ yarn-error.log*
126
144
  *.tsbuildinfo
127
145
  next-env.d.ts
128
146
 
129
- /src/generated/prisma
130
-
131
- /src/generated/prisma
132
-
147
+ # prisma generated client
133
148
  /generated/prisma
134
-
135
- scripts/
136
- # vercel.json`;
137
- fs.writeFileSync(gitIgnoreExemplePath, gitIgnore);
149
+ /src/generated/prisma
150
+ `;
151
+ fs.writeFileSync(gitIgnorePath, gitIgnore);
138
152
  }
139
153
 
140
- console.log(chalk.green("Projet créé avec succès !\n"));
141
- console.log(chalk.yellow("📝 Prochaines étapes :\n"));
154
+ console.log(chalk.green("Projet créé avec succès !\n"));
155
+ console.log(chalk.yellow("Prochaines étapes :\n"));
142
156
  console.log(chalk.white(` cd ${projectName}`));
143
157
  console.log(chalk.white(" pnpm install"));
144
- console.log(chalk.white(" # Configurez votre fichier .env"));
145
- console.log(
146
- chalk.white(" # Migrer la base de données et générer le schéma Prisma")
147
- );
158
+ console.log(chalk.white(""));
159
+ console.log(chalk.white(" # Configurez votre fichier .env (voir README.md)"));
160
+ console.log(chalk.white(" # Services à configurer :"));
161
+ console.log(chalk.white(" # - Supabase (base de données + storage)"));
162
+ console.log(chalk.white(" # - Google Cloud (Calendar, Sheets, Drive APIs)"));
163
+ console.log(chalk.white(" # - Upstash QStash (jobs asynchrones)"));
164
+ console.log(chalk.white(""));
165
+ console.log(chalk.white(" # Migrer la base de données"));
166
+ console.log(chalk.white(" pnpm db:migrate"));
167
+ console.log(chalk.white(""));
168
+ console.log(chalk.white(" # Lancer le serveur de développement"));
148
169
  console.log(chalk.white(" pnpm dev\n"));
149
170
  }
150
171
 
151
172
  main().catch((error) => {
152
- console.error(chalk.red("Erreur :"), error);
173
+ console.error(chalk.red("Erreur :"), error);
153
174
  process.exit(1);
154
175
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-crm-tmp",
3
- "version": "1.1.3",
3
+ "version": "2.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"
@@ -2,6 +2,8 @@
2
2
  node_modules
3
3
  .pnp
4
4
  .pnp.js
5
+ .agents
6
+ generated
5
7
 
6
8
  # Production
7
9
  build
@@ -1,178 +1,293 @@
1
- # 📊 CRM Template
1
+ # CRM Template
2
2
 
3
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.
4
+ **Next.js 16**, **Better Auth**, **Prisma**, **PostgreSQL** et une UI inspirée d'un template CRM pro.
7
5
 
8
- ## Fonctionnalités
6
+ ## Fonctionnalités
9
7
 
10
- - 🔐 **Authentification sécurisée** avec Better Auth
8
+ - **Authentification sécurisée** avec Better Auth
11
9
  - Connexion par email / mot de passe
12
10
  - Sessions sécurisées côté serveur
13
11
  - Protection des routes via proxy Next.js
14
- - 👥 **Rôles & permissions**
12
+ - **Rôles & permissions**
15
13
  - Rôles natifs : USER, ADMIN, MANAGER, COMMERCIAL, TELEPRO, COMPTABLE
16
- - Rôles personnalisés avec permissions granulaires
14
+ - Rôles personnalisés avec permissions granulaires (40+ permissions)
17
15
  - Gestion des utilisateurs (activation / désactivation, invitation par email)
18
- - 📊 **Tableau de bord**
19
- - Vue synthétique de lactivité (contacts, tâches, rendez-vous, etc.)
20
- - 📇 **Contacts**
21
- - Vue tableau et cartes façon CRM moderne
22
- - Recherche, filtres (statut, origine, commercial, télépro…)
23
- - Tri (statut, commerciaux, dates de création / mise à jour)
16
+ - **Tableau de bord**
17
+ - Vue synthétique de l'activité (contacts, tâches, rendez-vous)
18
+ - Widgets personnalisables
19
+ - **Contacts**
20
+ - Vue tableau et cartes
21
+ - Recherche, filtres (statut, origine, commercial, télépro)
24
22
  - Import CSV / Excel avec mapping intelligent
25
- - Export CSV / Excel (contacts + notes + fichiers liés, réservé aux admins)
23
+ - Export CSV / Excel (réservé aux admins)
26
24
  - Gestion des statuts & motifs de fermeture
27
- - 📆 **Agenda**
28
- - Vues **Mois / Semaine / Jour**
29
- - Barre temporelle en temps réel
30
- - Différenciation visuelle des types (tâches, rendez-vous, visio)
31
- - Filtres par type et priorité
32
- - ⚙️ **Paramètres**
33
- - Paramètres généraux (profil, sécurité, informations d’entreprise)
25
+ - KYC : pièce d'identité, date de naissance, etc.
26
+ - Fichiers attachés (Supabase Storage)
27
+ - **Entreprises**
28
+ - Gestion de sociétés avec contacts rattachés
29
+ - Journal d'activité par entreprise
30
+ - **Agenda**
31
+ - Vues Mois / Semaine / Jour
32
+ - Synchronisation Google Calendar
33
+ - Création de liens Google Meet
34
+ - Différenciation visuelle des types de tâches
35
+ - **Automatisations (Workflows)**
36
+ - Déclencheurs : création contact, changement statut, tâche terminée, etc.
37
+ - Actions : email, SMS, changement statut, création tâche, notification, etc.
38
+ - Délais configurables entre actions
39
+ - Exécution planifiée via Vercel Cron (toutes les minutes)
40
+ - **Intégrations**
41
+ - Google Calendar / Sheets / Drive
42
+ - Meta Lead Ads (webhook)
43
+ - Google Ads Lead Forms (webhook)
44
+ - SMTP par utilisateur avec signature
45
+ - Suivi d'ouverture des emails
46
+ - **Templates**
47
+ - Templates email / SMS / note avec variables dynamiques
48
+ - **Paramètres**
49
+ - Profil, sécurité, informations d'entreprise
34
50
  - Configuration SMTP + signature email
35
51
  - Gestion des statuts & motifs de fermeture
36
- - Intégrations (Google Calendar & Drive, Google Sheets, Meta Lead Ads, Google
37
- Ads…)
38
- - 🤖 **Automatisations (Workflows)**
39
- - Workflows avec actions chaînées
40
- - Exécution planifiée via **Vercel Cron**
41
- - 🎨 **UI moderne**
42
- - Design type CRM (fond `bg-crms-bg`, cartes blanches, headers structurés)
43
- - Tailwind CSS v4
44
- - 📱 Design entièrement responsive
45
-
46
- ## 🛠️ Stack technique
47
-
48
- - **Framework**: Next.js 16 (App Router)
49
- - **React**: React 19
50
- - **Base de données**: PostgreSQL avec Prisma ORM
51
- - **Authentification**: Better Auth
52
- - **Styling**: Tailwind CSS v4
53
- - **Langage**: TypeScript
54
- - **Gestionnaire de paquets**: pnpm
55
-
56
- ## 🚀 Installation
57
-
58
- 1. **Cloner le projet**
52
+ - Configuration des intégrations
59
53
 
60
- ```bash
61
- git clone <votre-repo>
62
- cd crm-template
63
- ```
54
+ ## Stack technique
55
+
56
+ | Technologie | Version |
57
+ |-------------|---------|
58
+ | Next.js | 16 (App Router) |
59
+ | React | 19 |
60
+ | PostgreSQL | via Supabase |
61
+ | ORM | Prisma 7 |
62
+ | Authentification | Better Auth |
63
+ | Styling | Tailwind CSS v4 + Radix UI |
64
+ | Formulaires | react-hook-form + Zod |
65
+ | Data fetching | SWR |
66
+ | Éditeur texte | Lexical |
67
+ | Jobs async | Upstash QStash |
68
+ | Stockage fichiers | Supabase Storage |
69
+ | Package manager | pnpm |
64
70
 
65
- 2. **Installer les dépendances**
71
+ ---
72
+
73
+ ## Installation rapide
66
74
 
67
75
  ```bash
68
76
  pnpm install
77
+ # Configurer .env (voir sections ci-dessous)
78
+ pnpm db:migrate
79
+ pnpm dev
69
80
  ```
70
81
 
71
- 3. **Configurer les variables d'environnement**
82
+ ---
72
83
 
73
- Créez un fichier `.env` à la racine du projet :
84
+ ## Configuration des services
74
85
 
75
- ```env
76
- # Database
77
- DATABASE_URL="postgresql://postgres:password@localhost:5432/crm_db"
86
+ ### 1. Supabase (Base de données + Storage)
78
87
 
79
- # Better Auth (générer avec: openssl rand -base64 32)
80
- BETTER_AUTH_SECRET="votre-clé-secrète-minimum-32-caractères"
81
- BETTER_AUTH_URL="http://localhost:3000"
88
+ #### Base de données
82
89
 
83
- # Application
84
- NEXT_PUBLIC_APP_URL="http://localhost:3000"
85
- NODE_ENV="development"
90
+ 1. Créez un projet sur [supabase.com](https://supabase.com)
91
+ 2. Allez dans **Settings > Database**
92
+ 3. Copiez les connection strings :
93
+ - **Transaction mode (port 6543)** → `DATABASE_URL`
94
+ - **Session mode / Direct (port 5432)** → `DIRECT_URL`
95
+
96
+ ```env
97
+ DATABASE_URL="postgresql://postgres.[ref]:[password]@aws-0-[region].pooler.supabase.com:6543/postgres"
98
+ DIRECT_URL="postgresql://postgres.[ref]:[password]@aws-0-[region].pooler.supabase.com:5432/postgres"
86
99
  ```
87
100
 
88
- 4. **Créer la base de données**
101
+ #### Storage (fichiers contacts + images éditeur)
89
102
 
90
- ```bash
91
- createdb crm_db
92
- # Ou: psql -U postgres -c "CREATE DATABASE crm_db;"
103
+ 1. Allez dans **Storage** dans votre projet Supabase
104
+ 2. Créez **2 buckets** :
105
+ - `contacts` fichiers attachés aux contacts (privé)
106
+ - `editor-images` — images uploadées dans l'éditeur (privé)
107
+ 3. Pour chaque bucket, configurez les **policies RLS** :
108
+ - **SELECT** : `authenticated` (les utilisateurs connectés peuvent lire)
109
+ - **INSERT** : `authenticated` (les utilisateurs connectés peuvent uploader)
110
+ - **DELETE** : `authenticated` (les utilisateurs connectés peuvent supprimer)
111
+ 4. Copiez les variables :
112
+ - **Settings > API** → `NEXT_PUBLIC_SUPABASE_URL` (Project URL)
113
+ - **Settings > API** → `SUPABASE_SERVICE_ROLE_KEY` (service_role key, **secret**)
114
+
115
+ ```env
116
+ NEXT_PUBLIC_SUPABASE_URL="https://[ref].supabase.co"
117
+ SUPABASE_SERVICE_ROLE_KEY="eyJ..."
93
118
  ```
94
119
 
95
- 5. **Appliquer les migrations**
120
+ > **Important** : le `SUPABASE_SERVICE_ROLE_KEY` contourne les RLS policies. Ne l'exposez jamais côté client.
96
121
 
97
- ```bash
98
- pnpm prisma migrate deploy
122
+ ### 2. Google Cloud (Calendar, Sheets, Drive)
123
+
124
+ 1. Allez sur [console.cloud.google.com](https://console.cloud.google.com)
125
+ 2. Créez un nouveau projet (ou sélectionnez un existant)
126
+ 3. Activez les **3 APIs** :
127
+ - Google Calendar API
128
+ - Google Sheets API
129
+ - Google Drive API
130
+ 4. Allez dans **APIs & Services > Credentials**
131
+ 5. Créez des identifiants **OAuth 2.0** :
132
+ - Type d'application : **Application Web**
133
+ - URI de redirection autorisés :
134
+ - `http://localhost:3000/api/auth/google/callback` (dev)
135
+ - `https://votre-domaine.com/api/auth/google/callback` (prod)
136
+ 6. Copiez les identifiants :
137
+
138
+ ```env
139
+ GOOGLE_CLIENT_ID="123456789-xxx.apps.googleusercontent.com"
140
+ GOOGLE_CLIENT_SECRET="GOCSPX-xxx"
141
+ GOOGLE_REDIRECT_URI="http://localhost:3000/api/auth/google/callback"
99
142
  ```
100
143
 
101
- 6. **Lancer le serveur de développement**
144
+ > **Note** : En production, mettez à jour `GOOGLE_REDIRECT_URI` avec votre domaine de production.
102
145
 
103
- ```bash
104
- pnpm dev
146
+ #### Scopes OAuth demandés
147
+
148
+ L'application demande les scopes suivants lors de la connexion Google :
149
+ - `calendar` — Accès complet au calendrier (lecture/écriture)
150
+ - `spreadsheets` — Accès aux Google Sheets (lecture/écriture)
151
+ - `drive.file` — Accès aux fichiers créés par l'application
152
+
153
+ ### 3. QStash (Upstash) — Jobs asynchrones
154
+
155
+ QStash est utilisé pour le traitement asynchrone des imports Google Sheets.
156
+
157
+ 1. Créez un compte sur [upstash.com](https://upstash.com)
158
+ 2. Allez dans **QStash** (dans le menu de gauche)
159
+ 3. Copiez les 3 valeurs depuis la page **QStash** :
160
+
161
+ ```env
162
+ QSTASH_TOKEN="eyJ..."
163
+ QSTASH_CURRENT_SIGNING_KEY="sig_xxx"
164
+ QSTASH_NEXT_SIGNING_KEY="sig_xxx"
105
165
  ```
106
166
 
107
- Ouvrez [http://localhost:3000](http://localhost:3000) pour voir l'application.
167
+ #### Comment ça fonctionne
108
168
 
109
- 7. **Créer votre premier admin**
169
+ - Quand un utilisateur lance un import Google Sheets, le CRM publie un job via QStash
170
+ - QStash appelle le worker `POST /api/jobs/google-sheet/process` de façon asynchrone
171
+ - Le worker vérifie la signature QStash puis exécute l'import
172
+ - L'endpoint `GET /api/integrations/google-sheet/jobs/usage` permet de suivre les quotas (24h)
173
+ - Le bouton de synchronisation manuelle dans les paramètres d'intégration force un enqueue
110
174
 
111
- ```bash
112
- # Ouvrir Prisma Studio
113
- pnpm prisma studio
175
+ ### 4. Vercel (Déploiement + Cron Jobs)
176
+
177
+ #### Déploiement
178
+
179
+ 1. Connectez votre repo GitHub à [vercel.com](https://vercel.com)
180
+ 2. Configurez **toutes** les variables d'environnement dans **Settings > Environment Variables**
181
+ 3. Le `buildCommand` dans `vercel.json` exécute automatiquement les migrations Prisma
182
+
183
+ #### Cron Jobs
184
+
185
+ Le fichier `vercel.json` définit 2 crons qui sont auto-détectés par Vercel :
114
186
 
115
- # Modifier le champ "role" de votre utilisateur en "ADMIN"
187
+ | Cron | Schedule | Description |
188
+ |------|----------|-------------|
189
+ | `/api/workflows/process` | Toutes les minutes | Exécute les actions de workflow planifiées |
190
+ | `/api/cron/cleanup-editor-images` | Tous les jours à 3h | Nettoie les images éditeur orphelines |
191
+
192
+ Vérifiez dans **Vercel Dashboard > Cron Jobs** que les 2 crons sont actifs.
193
+
194
+ > **Note** : Les crons Vercel nécessitent le plan **Pro** (ou supérieur) pour une exécution toutes les minutes.
195
+
196
+ #### Variable CRON_SECRET
197
+
198
+ ```env
199
+ CRON_SECRET="votre-secret" # openssl rand -base64 32
116
200
  ```
117
201
 
118
- ## 📁 Structure du projet
202
+ Cette clé authentifie les appels cron de Vercel vers vos API routes.
203
+
204
+ ---
205
+
206
+ ## Variables d'environnement (récapitulatif)
207
+
208
+ | Variable | Obligatoire | Description |
209
+ |----------|:-----------:|-------------|
210
+ | `DATABASE_URL` | Oui | Supabase pooled connection (port 6543) |
211
+ | `DIRECT_URL` | Oui | Supabase direct connection (port 5432, migrations) |
212
+ | `BETTER_AUTH_SECRET` | Oui | Secret d'authentification (min 32 chars) |
213
+ | `BETTER_AUTH_URL` | Oui | URL de base pour Better Auth |
214
+ | `NEXT_PUBLIC_APP_URL` | Oui | URL publique de l'application |
215
+ | `APP_NAME` | Oui | Nom affiché de l'application |
216
+ | `ENCRYPTION_KEY` | Oui | Clé de chiffrement SMTP passwords (min 32 chars) |
217
+ | `GOOGLE_CLIENT_ID` | Oui | OAuth 2.0 Client ID |
218
+ | `GOOGLE_CLIENT_SECRET` | Oui | OAuth 2.0 Client Secret |
219
+ | `GOOGLE_REDIRECT_URI` | Oui | URI de callback Google OAuth |
220
+ | `CRON_SECRET` | Oui | Authentification des cron jobs Vercel |
221
+ | `QSTASH_TOKEN` | Oui | Token Upstash QStash |
222
+ | `QSTASH_CURRENT_SIGNING_KEY` | Oui | Signing key QStash (courante) |
223
+ | `QSTASH_NEXT_SIGNING_KEY` | Oui | Signing key QStash (rotation) |
224
+ | `NEXT_PUBLIC_SUPABASE_URL` | Oui | URL du projet Supabase |
225
+ | `SUPABASE_SERVICE_ROLE_KEY` | Oui | Service role key Supabase (secret) |
226
+
227
+ ---
228
+
229
+ ## Structure du projet
119
230
 
120
231
  ```
121
232
  src/
122
233
  ├── app/
123
- │ ├── (auth)/ # Groupe de routes d'authentification
234
+ │ ├── (auth)/ # Pages d'authentification (signin, reset-password, invite)
124
235
  │ ├── (dashboard)/ # Espace connecté (protégé)
125
236
  │ │ ├── dashboard/ # Tableau de bord
126
- │ │ ├── contacts/ # Gestion des contacts
237
+ │ │ ├── contacts/ # Gestion des contacts + entreprises
127
238
  │ │ ├── agenda/ # Agenda (mois / semaine / jour)
128
239
  │ │ ├── automatisation/ # Workflows / automatisations
129
- │ │ ├── templates/ # Templates demails
130
- │ │ ├── settings/ # Paramètres (profil, entreprise, intégrations)
131
- │ │ ├── users/ # Gestion des utilisateurs & rôles (admin)
132
- │ │ └── layout.tsx # Layout avec sidebar
133
- ├── api/ # API (contacts, workflows, intégrations, users, etc.)
134
- └── page.tsx # Page d'accueil (redirection)
135
- ├── components/ # Composants UI (sidebar, headers, skeletons…)
136
- ├── lib/ # Auth, Prisma, rôles, intégrations Google, workflows…
137
- └── proxy.ts # Protection des routes (proxy)
240
+ │ │ ├── templates/ # Templates d'emails
241
+ │ │ ├── settings/ # Paramètres (profil, entreprise, intégrations)
242
+ │ │ ├── users/ # Gestion des utilisateurs & rôles
243
+ │ │ ├── closing/ # Motifs de fermeture
244
+ │ └── layout.tsx # Layout avec sidebar + contexts
245
+ ├── api/ # API routes (REST)
246
+ │ │ ├── auth/ # Better Auth + Google OAuth
247
+ │ │ ├── contacts/ # CRUD contacts, import, export, fichiers
248
+ │ │ ├── companies/ # CRUD entreprises
249
+ │ │ ├── tasks/ # CRUD tâches + Google Meet
250
+ │ │ ├── workflows/ # CRUD workflows + processing cron
251
+ │ │ ├── webhooks/ # Meta Leads, Google Ads
252
+ │ │ ├── jobs/ # Workers QStash (Google Sheets)
253
+ │ │ ├── integrations/ # Google Sheets sync, logs
254
+ │ │ ├── settings/ # Configuration (SMTP, statuts, intégrations)
255
+ │ │ └── cron/ # Jobs planifiés (cleanup images)
256
+ │ └── page.tsx # Redirection vers /dashboard
257
+ ├── components/ # Composants UI (sidebar, header, éditeur, etc.)
258
+ ├── contexts/ # React contexts (toast, sidebar, reminders, view-as)
259
+ ├── hooks/ # Custom hooks (SWR, permissions, etc.)
260
+ ├── lib/ # Utilitaires (auth, prisma, workflows, intégrations)
261
+ ├── types/ # Types TypeScript
262
+ └── proxy.ts # Protection des routes (middleware)
138
263
  ```
139
264
 
140
- ## 🔒 Protection & rôles
265
+ ## Scripts disponibles
141
266
 
142
- - **Proxy Next.js** (`src/proxy.ts`) pour protéger les routes côté serveur :
143
- - Pages dans `(dashboard)/` automatiquement protégées
144
- - Redirection vers `/signin` si non authentifié
145
- - Redirection vers le dashboard si déjà connecté sur les pages d’auth
146
- - **Rôles & permissions** :
147
- - Rôles techniques + rôles personnalisés configurables via l’interface
148
- - Vérification des permissions côté API (ex : `users.view`,
149
- `users.manage_roles`, intégrations…)
150
- - Certaines sections (informations d’entreprise, paramètres d’application /
151
- système, intégrations, export contacts) sont réservées aux administrateurs
267
+ ```bash
268
+ pnpm dev # Serveur de développement
269
+ pnpm build # Build de production (+ prisma generate)
270
+ pnpm start # Serveur de production
271
+ pnpm db:migrate # Migrations Prisma (dev)
272
+ pnpm db:deploy # Migrations Prisma (prod)
273
+ pnpm lint # ESLint
274
+ pnpm format # Prettier
275
+ ```
152
276
 
153
- ## 🎨 Personnalisation
277
+ ## Personnalisation
154
278
 
155
279
  ### Ajouter une nouvelle page protégée
156
280
 
157
281
  1. Créez votre page dans `src/app/(dashboard)/ma-page/page.tsx`
158
- 2. Ajoutez-la dans la navigation (`src/components/sidebar.tsx`)
159
- 3. (Optionnel) Protégez-la par rôle dans `src/proxy.ts`
282
+ 2. Ajoutez-la dans la navigation (`src/config/nav-pages.ts`)
283
+ 3. (Optionnel) Protégez-la par permission dans `src/lib/permissions.ts`
160
284
 
161
285
  ### Modifier le thème
162
286
 
163
- Les couleurs principales sont configurées avec Tailwind. Modifiez les classes
164
- dans les composants pour personnaliser le thème.
165
-
166
- ## 📝 Scripts disponibles
287
+ Les couleurs sont configurées avec Tailwind CSS v4. Les variables CSS sont dans `src/app/globals.css`.
167
288
 
168
- ```bash
169
- pnpm dev # Lancer le serveur de développement
170
- pnpm build # Build de production
171
- pnpm start # Lancer le serveur de production
172
- pnpm lint # Linter le code
173
- pnpm format # Formater le code avec Prettier
174
- ```
289
+ ---
175
290
 
176
- ## 📄 Licence
291
+ ## Licence
177
292
 
178
293
  MIT
@@ -0,0 +1,22 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema.json",
3
+ "style": "new-york",
4
+ "rsc": true,
5
+ "tsx": true,
6
+ "tailwind": {
7
+ "config": "",
8
+ "css": "src/app/globals.css",
9
+ "baseColor": "neutral",
10
+ "cssVariables": true,
11
+ "prefix": ""
12
+ },
13
+ "iconLibrary": "lucide",
14
+ "aliases": {
15
+ "components": "@/components",
16
+ "utils": "@/lib/utils",
17
+ "ui": "@/components/ui",
18
+ "lib": "@/lib",
19
+ "hooks": "@/hooks"
20
+ },
21
+ "registries": {}
22
+ }
@@ -5,6 +5,18 @@ import nextTs from "eslint-config-next/typescript";
5
5
  const eslintConfig = defineConfig([
6
6
  ...nextVitals,
7
7
  ...nextTs,
8
+ {
9
+ rules: {
10
+ // Dette TypeScript large : garder visible sans bloquer la CI
11
+ "@typescript-eslint/no-explicit-any": "warn",
12
+ // Apostrophes françaises courantes dans le JSX (d', l', n', etc.)
13
+ "react/no-unescaped-entities": ["error", { forbid: [">", "}"] }],
14
+ // Règles React Compiler : refactors souvent lourds, à traiter au fil de l’eau
15
+ "react-hooks/set-state-in-effect": "warn",
16
+ "react-hooks/immutability": "warn",
17
+ "react-hooks/refs": "warn",
18
+ },
19
+ },
8
20
  // Override default ignores of eslint-config-next.
9
21
  globalIgnores([
10
22
  // Default ignores of eslint-config-next:
@@ -12,6 +24,7 @@ const eslintConfig = defineConfig([
12
24
  "out/**",
13
25
  "build/**",
14
26
  "next-env.d.ts",
27
+ "eslint-report.json",
15
28
  ]),
16
29
  ]);
17
30