create-crm-tmp 2.0.0 → 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 (190) hide show
  1. package/bin/create-crm-tmp.js +56 -35
  2. package/package.json +1 -1
  3. package/template/README.md +230 -115
  4. package/template/eslint.config.mjs +13 -0
  5. package/template/next.config.ts +14 -0
  6. package/template/package.json +15 -2
  7. package/template/prisma/migrations/20260318095700_init_db/migration.sql +978 -0
  8. package/template/prisma/migrations/migration_lock.toml +3 -0
  9. package/template/prisma/schema.prisma +132 -637
  10. package/template/src/app/(auth)/invite/[token]/page.tsx +10 -8
  11. package/template/src/app/(auth)/layout.tsx +1 -1
  12. package/template/src/app/(auth)/reset-password/complete/page.tsx +11 -8
  13. package/template/src/app/(auth)/reset-password/page.tsx +4 -4
  14. package/template/src/app/(auth)/reset-password/verify/page.tsx +4 -4
  15. package/template/src/app/(auth)/signin/page.tsx +14 -6
  16. package/template/src/app/(dashboard)/agenda/page.tsx +2243 -988
  17. package/template/src/app/(dashboard)/automatisation/_components/workflow-editor.tsx +18 -104
  18. package/template/src/app/(dashboard)/automatisation/page.tsx +10 -26
  19. package/template/src/app/(dashboard)/closing/page.tsx +78 -62
  20. package/template/src/app/(dashboard)/contacts/[id]/page.tsx +2082 -1080
  21. package/template/src/app/(dashboard)/contacts/companies/[id]/page.tsx +46 -47
  22. package/template/src/app/(dashboard)/contacts/page.tsx +1062 -780
  23. package/template/src/app/(dashboard)/dashboard/page.tsx +533 -37
  24. package/template/src/app/(dashboard)/dev/page.tsx +1291 -0
  25. package/template/src/app/(dashboard)/layout.tsx +6 -2
  26. package/template/src/app/(dashboard)/settings/page.tsx +797 -2582
  27. package/template/src/app/(dashboard)/templates/page.tsx +55 -54
  28. package/template/src/app/(dashboard)/users/list/page.tsx +51 -48
  29. package/template/src/app/(dashboard)/users/page.tsx +1 -1
  30. package/template/src/app/(dashboard)/users/permissions/page.tsx +2 -2
  31. package/template/src/app/(dashboard)/users/roles/page.tsx +7 -5
  32. package/template/src/app/api/agenda/google-events/route.ts +92 -0
  33. package/template/src/app/api/auth/check-active/route.ts +3 -2
  34. package/template/src/app/api/auth/google/route.ts +2 -1
  35. package/template/src/app/api/auth/google/status/route.ts +7 -31
  36. package/template/src/app/api/companies/[id]/activities/route.ts +1 -3
  37. package/template/src/app/api/companies/[id]/route.ts +1 -2
  38. package/template/src/app/api/companies/route.ts +42 -12
  39. package/template/src/app/api/contacts/[id]/files/[fileId]/preview/route.ts +9 -31
  40. package/template/src/app/api/contacts/[id]/files/[fileId]/route.ts +14 -32
  41. package/template/src/app/api/contacts/[id]/files/route.ts +112 -212
  42. package/template/src/app/api/contacts/[id]/interactions/[interactionId]/route.ts +27 -1
  43. package/template/src/app/api/contacts/[id]/interactions/route.ts +16 -16
  44. package/template/src/app/api/contacts/[id]/kyc/route.ts +21 -11
  45. package/template/src/app/api/contacts/[id]/meet/route.ts +19 -2
  46. package/template/src/app/api/contacts/[id]/route.ts +106 -34
  47. package/template/src/app/api/contacts/[id]/send-email/route.ts +27 -11
  48. package/template/src/app/api/contacts/[id]/workflows/run/route.ts +6 -0
  49. package/template/src/app/api/contacts/export/route.ts +9 -13
  50. package/template/src/app/api/contacts/import/route.ts +55 -25
  51. package/template/src/app/api/contacts/import-preview/route.ts +1 -1
  52. package/template/src/app/api/contacts/origins/route.ts +63 -0
  53. package/template/src/app/api/contacts/route.ts +153 -41
  54. package/template/src/app/api/cron/cleanup-editor-images/route.ts +166 -0
  55. package/template/src/app/api/dashboard/widgets/[id]/route.ts +44 -0
  56. package/template/src/app/api/dashboard/widgets/route.ts +181 -0
  57. package/template/src/app/api/dev/reminders/test/route.ts +114 -0
  58. package/template/src/app/api/editor/upload-image/route.ts +61 -0
  59. package/template/src/app/api/integrations/google-sheet/jobs/[jobId]/route.ts +47 -0
  60. package/template/src/app/api/integrations/google-sheet/jobs/usage/route.ts +50 -0
  61. package/template/src/app/api/integrations/google-sheet/sync/route.ts +24 -556
  62. package/template/src/app/api/jobs/google-sheet/process/route.ts +84 -0
  63. package/template/src/app/api/jobs/google-sheet/schedule/route.ts +50 -0
  64. package/template/src/app/api/reminders/clear/route.ts +120 -0
  65. package/template/src/app/api/reminders/clear/undo/route.ts +112 -0
  66. package/template/src/app/api/reminders/route.ts +164 -39
  67. package/template/src/app/api/reminders/state/route.ts +164 -0
  68. package/template/src/app/api/reset-password/request/route.ts +1 -1
  69. package/template/src/app/api/reset-password/verify/route.ts +1 -1
  70. package/template/src/app/api/send/route.ts +16 -4
  71. package/template/src/app/api/settings/google-ads/route.ts +14 -0
  72. package/template/src/app/api/settings/google-calendar/calendars/route.ts +97 -0
  73. package/template/src/app/api/settings/google-calendar/route.ts +124 -0
  74. package/template/src/app/api/settings/google-sheet/[id]/route.ts +28 -0
  75. package/template/src/app/api/settings/google-sheet/auto-map/route.ts +37 -4
  76. package/template/src/app/api/settings/google-sheet/preview/route.ts +9 -3
  77. package/template/src/app/api/settings/google-sheet/route.ts +14 -0
  78. package/template/src/app/api/settings/integrations/logs/route.ts +93 -0
  79. package/template/src/app/api/settings/integrations/notifications/route.ts +67 -0
  80. package/template/src/app/api/settings/meta-leads/[id]/route.ts +0 -1
  81. package/template/src/app/api/settings/meta-leads/route.ts +14 -2
  82. package/template/src/app/api/settings/smtp/route.ts +53 -6
  83. package/template/src/app/api/tasks/[id]/attendees/route.ts +24 -8
  84. package/template/src/app/api/tasks/[id]/route.ts +234 -58
  85. package/template/src/app/api/tasks/meet/route.ts +27 -19
  86. package/template/src/app/api/tasks/route.ts +62 -17
  87. package/template/src/app/api/users/[id]/route.ts +20 -14
  88. package/template/src/app/api/users/list/route.ts +57 -19
  89. package/template/src/app/api/webhooks/google-ads/route.ts +34 -14
  90. package/template/src/app/api/webhooks/meta-leads/route.ts +32 -12
  91. package/template/src/app/api/workflows/[id]/route.ts +0 -4
  92. package/template/src/app/api/workflows/process/route.ts +22 -51
  93. package/template/src/app/api/workflows/route.ts +0 -4
  94. package/template/src/app/globals.css +342 -4
  95. package/template/src/app/layout.tsx +11 -3
  96. package/template/src/app/page.tsx +1 -1
  97. package/template/src/components/address-autocomplete.tsx +7 -6
  98. package/template/src/components/config-error-alert.tsx +46 -0
  99. package/template/src/components/contacts/filter-bar.tsx +12 -3
  100. package/template/src/components/contacts/filter-builder.tsx +28 -43
  101. package/template/src/components/contacts/save-view-dialog.tsx +1 -1
  102. package/template/src/components/contacts/views-tab-bar.tsx +15 -6
  103. package/template/src/components/dashboard/activity-chart.tsx +41 -28
  104. package/template/src/components/dashboard/add-widget-dialog.tsx +157 -0
  105. package/template/src/components/dashboard/color-picker.tsx +64 -0
  106. package/template/src/components/dashboard/contacts-chart.tsx +69 -0
  107. package/template/src/components/dashboard/interactions-by-type-chart.tsx +121 -0
  108. package/template/src/components/dashboard/recent-activity.tsx +154 -0
  109. package/template/src/components/dashboard/stat-card.tsx +40 -40
  110. package/template/src/components/dashboard/status-distribution-chart.tsx +81 -0
  111. package/template/src/components/dashboard/tasks-pie-chart.tsx +37 -34
  112. package/template/src/components/dashboard/top-contacts-list.tsx +113 -0
  113. package/template/src/components/dashboard/upcoming-tasks-list.tsx +72 -81
  114. package/template/src/components/dashboard/widget-wrapper.tsx +36 -0
  115. package/template/src/components/date-picker.tsx +9 -6
  116. package/template/src/components/editor/upload-editor-image.ts +42 -0
  117. package/template/src/components/editor.tsx +161 -22
  118. package/template/src/components/email-template.tsx +2 -2
  119. package/template/src/components/global-search.tsx +30 -28
  120. package/template/src/components/header.tsx +178 -80
  121. package/template/src/components/inactive-account-guard.tsx +58 -0
  122. package/template/src/components/integration-notifications-listener.tsx +12 -0
  123. package/template/src/components/invitation-email-template.tsx +2 -2
  124. package/template/src/components/meet-cancellation-email-template.tsx +3 -3
  125. package/template/src/components/meet-confirmation-email-template.tsx +3 -3
  126. package/template/src/components/meet-update-email-template.tsx +3 -3
  127. package/template/src/components/page-header.tsx +5 -5
  128. package/template/src/components/protected-page.tsx +1 -1
  129. package/template/src/components/reset-password-email-template.tsx +2 -2
  130. package/template/src/components/settings/integrations/GoogleAdsIntegration.tsx +428 -0
  131. package/template/src/components/settings/integrations/GoogleSheetConfigMonitoringModal.tsx +680 -0
  132. package/template/src/components/settings/integrations/GoogleSheetIntegration.tsx +809 -0
  133. package/template/src/components/settings/integrations/ImportResultDialog.tsx +124 -0
  134. package/template/src/components/settings/integrations/IntegrationLogPanel.tsx +57 -0
  135. package/template/src/components/settings/integrations/IntegrationLogsTable.tsx +186 -0
  136. package/template/src/components/settings/integrations/MetaLeadIntegration.tsx +451 -0
  137. package/template/src/components/sidebar.tsx +45 -26
  138. package/template/src/components/skeleton.tsx +40 -43
  139. package/template/src/components/ui/accordion.tsx +2 -2
  140. package/template/src/components/ui/alert-dialog.tsx +1 -1
  141. package/template/src/components/ui/button.tsx +20 -9
  142. package/template/src/components/ui/components.tsx +1 -1
  143. package/template/src/components/ui/date-picker.tsx +422 -0
  144. package/template/src/components/ui/datetime-picker.tsx +338 -0
  145. package/template/src/components/ui/status-select.tsx +271 -0
  146. package/template/src/components/ui/tooltip.tsx +37 -0
  147. package/template/src/components/view-as-modal.tsx +13 -7
  148. package/template/src/contexts/app-toast-context.tsx +245 -57
  149. package/template/src/contexts/dashboard-theme-context.tsx +53 -0
  150. package/template/src/contexts/sidebar-context.tsx +22 -17
  151. package/template/src/contexts/task-reminder-context.tsx +134 -160
  152. package/template/src/contexts/view-as-context.tsx +33 -6
  153. package/template/src/hooks/use-focus-trap.ts +2 -2
  154. package/template/src/hooks/useIntegrationNotifications.ts +49 -0
  155. package/template/src/lib/auth.ts +8 -1
  156. package/template/src/lib/config-links.ts +14 -0
  157. package/template/src/lib/contact-duplicate.ts +79 -61
  158. package/template/src/lib/contact-interactions.ts +21 -21
  159. package/template/src/lib/contact-view-filters.ts +24 -64
  160. package/template/src/lib/contacts-list-url.ts +190 -0
  161. package/template/src/lib/dashboard-stats.ts +65 -7
  162. package/template/src/lib/dashboard-themes.ts +135 -0
  163. package/template/src/lib/date-utils.ts +127 -0
  164. package/template/src/lib/default-widgets.ts +12 -0
  165. package/template/src/lib/editor-html-image-dimensions.ts +172 -0
  166. package/template/src/lib/editor-image-limits.ts +19 -0
  167. package/template/src/lib/email-html-sanitize.ts +19 -0
  168. package/template/src/lib/encryption.ts +9 -6
  169. package/template/src/lib/fr-geography.ts +192 -0
  170. package/template/src/lib/google-calendar-agenda.ts +201 -0
  171. package/template/src/lib/google-calendar.ts +255 -5
  172. package/template/src/lib/google-sheet-sync-jobs.ts +96 -0
  173. package/template/src/lib/google-sheet-sync-runner.ts +514 -0
  174. package/template/src/lib/integration-import-log.ts +21 -0
  175. package/template/src/lib/permissions.ts +40 -10
  176. package/template/src/lib/prisma.ts +4 -1
  177. package/template/src/lib/qstash.ts +65 -0
  178. package/template/src/lib/reminder-state-server.ts +80 -0
  179. package/template/src/lib/reminder-state.ts +29 -0
  180. package/template/src/lib/supabase-storage.ts +113 -0
  181. package/template/src/lib/template-variables.ts +164 -23
  182. package/template/src/lib/utils.ts +45 -0
  183. package/template/src/lib/widget-registry.ts +173 -0
  184. package/template/src/lib/workflow-executor.ts +16 -70
  185. package/template/src/proxy.ts +1 -0
  186. package/template/vercel.json +3 -10
  187. package/template/skills-lock.json +0 -25
  188. package/template/src/components/dashboard/dashboard-content.tsx +0 -79
  189. package/template/src/lib/google-drive.ts +0 -1101
  190. package/template/src/types/yousign.ts +0 -52
@@ -6,7 +6,7 @@ import { Plus, Edit, Trash2, Mail, MessageSquare, FileText, X } from 'lucide-rea
6
6
  import { LazyEditor as Editor, type DefaultTemplateRef } from '@/components/lazy-editor';
7
7
  import { AVAILABLE_VARIABLES, VARIABLE_SECTIONS } from '@/lib/template-variables';
8
8
  import { TemplatesPageSkeleton } from '@/components/skeleton';
9
- import { cn } from '@/lib/utils';
9
+ import { cn, devToast } from '@/lib/utils';
10
10
  import { ProtectedPage } from '@/components/protected-page';
11
11
  import { useConfirm } from '@/hooks/use-confirm';
12
12
  import { useUserRole } from '@/hooks/use-user-role';
@@ -64,7 +64,7 @@ export default function TemplatesPage() {
64
64
  }
65
65
  } catch (error) {
66
66
  console.error('Erreur:', error);
67
- setError('Erreur lors du chargement des templates');
67
+ setError(devToast('Erreur lors du chargement des templates', error));
68
68
  } finally {
69
69
  setLoading(false);
70
70
  }
@@ -153,7 +153,7 @@ export default function TemplatesPage() {
153
153
 
154
154
  setTimeout(() => setSuccess(''), 5000);
155
155
  } catch (err: any) {
156
- setError(err.message);
156
+ setError(devToast("Erreur lors de l'enregistrement du template", err));
157
157
  }
158
158
  };
159
159
 
@@ -184,7 +184,7 @@ export default function TemplatesPage() {
184
184
  fetchTemplates();
185
185
  setTimeout(() => setSuccess(''), 5000);
186
186
  } catch (err: any) {
187
- setError(err.message);
187
+ setError(devToast('Erreur lors de la suppression du template', err));
188
188
  }
189
189
  };
190
190
 
@@ -292,7 +292,7 @@ export default function TemplatesPage() {
292
292
  canCreate ? (
293
293
  <button
294
294
  onClick={handleNewTemplate}
295
- className="cursor-pointer rounded-xl bg-primary px-5 py-2.5 text-sm font-semibold text-primary-foreground shadow-(--shadow-card) transition-all duration-200 hover:bg-primary/90"
295
+ className="bg-primary text-primary-foreground hover:bg-primary/90 cursor-pointer rounded-xl px-5 py-2.5 text-sm font-semibold shadow-(--shadow-card) transition-colors duration-200"
296
296
  >
297
297
  <Plus className="mr-2 inline h-4 w-4" />
298
298
  Nouveau template
@@ -307,10 +307,10 @@ export default function TemplatesPage() {
307
307
  <button
308
308
  onClick={() => setFilterType('ALL')}
309
309
  className={cn(
310
- 'group cursor-pointer rounded-xl px-5 py-2.5 text-sm font-semibold transition-all duration-200',
310
+ 'group cursor-pointer rounded-xl px-5 py-2.5 text-sm font-semibold transition-[color,background-color,box-shadow] duration-200',
311
311
  filterType === 'ALL'
312
312
  ? 'bg-primary text-primary-foreground shadow-(--shadow-card)'
313
- : 'border border-border bg-card text-muted-foreground shadow-sm hover:bg-muted hover:text-foreground',
313
+ : 'border-border bg-card text-muted-foreground hover:bg-muted hover:text-foreground border shadow-sm',
314
314
  )}
315
315
  >
316
316
  <span className="flex items-center gap-2">
@@ -325,10 +325,10 @@ export default function TemplatesPage() {
325
325
  <button
326
326
  onClick={() => setFilterType('EMAIL')}
327
327
  className={cn(
328
- 'group cursor-pointer rounded-xl px-5 py-2.5 text-sm font-semibold transition-all duration-200',
328
+ 'group cursor-pointer rounded-xl px-5 py-2.5 text-sm font-semibold transition-[color,background-color,box-shadow] duration-200',
329
329
  filterType === 'EMAIL'
330
330
  ? 'bg-linear-to-r from-blue-600 to-blue-700 text-white shadow-md shadow-blue-500/30'
331
- : 'border border-border bg-card text-muted-foreground shadow-sm hover:bg-muted hover:text-foreground',
331
+ : 'border-border bg-card text-muted-foreground hover:bg-muted hover:text-foreground border shadow-sm',
332
332
  )}
333
333
  >
334
334
  <span className="flex items-center gap-2">
@@ -344,10 +344,10 @@ export default function TemplatesPage() {
344
344
  <button
345
345
  onClick={() => setFilterType('SMS')}
346
346
  className={cn(
347
- 'group cursor-pointer rounded-xl px-5 py-2.5 text-sm font-semibold transition-all duration-200',
347
+ 'group cursor-pointer rounded-xl px-5 py-2.5 text-sm font-semibold transition-[color,background-color,box-shadow] duration-200',
348
348
  filterType === 'SMS'
349
349
  ? 'bg-linear-to-r from-emerald-600 to-emerald-700 text-white shadow-md shadow-emerald-500/30'
350
- : 'border border-border bg-card text-muted-foreground shadow-sm hover:bg-muted hover:text-foreground',
350
+ : 'border-border bg-card text-muted-foreground hover:bg-muted hover:text-foreground border shadow-sm',
351
351
  )}
352
352
  >
353
353
  <span className="flex items-center gap-2">
@@ -363,10 +363,10 @@ export default function TemplatesPage() {
363
363
  <button
364
364
  onClick={() => setFilterType('NOTE')}
365
365
  className={cn(
366
- 'group cursor-pointer rounded-xl px-5 py-2.5 text-sm font-semibold transition-all duration-200',
366
+ 'group cursor-pointer rounded-xl px-5 py-2.5 text-sm font-semibold transition-[color,background-color,box-shadow] duration-200',
367
367
  filterType === 'NOTE'
368
368
  ? 'bg-linear-to-r from-violet-600 to-violet-700 text-white shadow-md shadow-violet-500/30'
369
- : 'border border-border bg-card text-muted-foreground shadow-sm hover:bg-muted hover:text-foreground',
369
+ : 'border-border bg-card text-muted-foreground hover:bg-muted hover:text-foreground border shadow-sm',
370
370
  )}
371
371
  >
372
372
  <span className="flex items-center gap-2">
@@ -383,19 +383,19 @@ export default function TemplatesPage() {
383
383
 
384
384
  {/* Liste des templates */}
385
385
  {filteredTemplates.length === 0 ? (
386
- <div className="rounded-2xl border border-dashed border-border bg-linear-to-br from-muted to-card p-16 text-center shadow-sm">
387
- <div className="mx-auto flex h-20 w-20 items-center justify-center rounded-full bg-primary/15">
388
- <FileText className="h-10 w-10 text-primary" />
386
+ <div className="border-border from-muted to-card rounded-2xl border border-dashed bg-linear-to-br p-16 text-center shadow-sm">
387
+ <div className="bg-primary/15 mx-auto flex h-20 w-20 items-center justify-center rounded-full">
388
+ <FileText className="text-primary h-10 w-10" />
389
389
  </div>
390
- <h2 className="mt-6 text-xl font-bold text-foreground">Aucun template</h2>
391
- <p className="mt-2 text-sm text-muted-foreground">
390
+ <h2 className="text-foreground mt-6 text-xl font-bold">Aucun template</h2>
391
+ <p className="text-muted-foreground mt-2 text-sm">
392
392
  {filterType === 'ALL'
393
393
  ? 'Commencez par créer votre premier template pour gagner du temps'
394
394
  : `Aucun template de type ${getTypeLabel(filterType)} trouvé`}
395
395
  </p>
396
396
  <button
397
397
  onClick={handleNewTemplate}
398
- className="mt-8 cursor-pointer rounded-xl bg-primary px-6 py-3 text-sm font-semibold text-primary-foreground shadow-(--shadow-card) transition-all duration-200 hover:bg-primary/90"
398
+ className="bg-primary text-primary-foreground hover:bg-primary/90 mt-8 cursor-pointer rounded-xl px-6 py-3 text-sm font-semibold shadow-(--shadow-card) transition-colors duration-200"
399
399
  >
400
400
  <Plus className="mr-2 inline h-4 w-4" />
401
401
  Créer un template
@@ -406,7 +406,7 @@ export default function TemplatesPage() {
406
406
  {filteredTemplates.map((template) => (
407
407
  <div
408
408
  key={template.id}
409
- className="group relative overflow-hidden rounded-2xl border border-border bg-card p-6 shadow-(--shadow-card) transition-all duration-300 hover:border-primary/30"
409
+ className="group border-border bg-card hover:border-primary/30 relative overflow-hidden rounded-2xl border p-6 shadow-(--shadow-card) transition-[border-color,box-shadow] duration-300"
410
410
  >
411
411
  {/* Badge de type avec icône */}
412
412
  <div className="mb-4 flex items-center justify-between">
@@ -426,7 +426,7 @@ export default function TemplatesPage() {
426
426
  </span>
427
427
  </div>
428
428
  <div>
429
- <h3 className="text-lg font-bold text-foreground transition-colors group-hover:text-primary">
429
+ <h3 className="text-foreground group-hover:text-primary text-lg font-bold transition-colors">
430
430
  {template.name}
431
431
  </h3>
432
432
  <span
@@ -443,15 +443,17 @@ export default function TemplatesPage() {
443
443
 
444
444
  {/* Sujet pour les emails */}
445
445
  {template.type === 'EMAIL' && template.subject && (
446
- <div className="mb-3 rounded-lg bg-muted p-3">
447
- <p className="text-xs font-medium text-muted-foreground">Sujet</p>
448
- <p className="mt-1 text-sm font-semibold text-foreground">{template.subject}</p>
446
+ <div className="bg-muted mb-3 rounded-lg p-3">
447
+ <p className="text-muted-foreground text-xs font-medium">Sujet</p>
448
+ <p className="text-foreground mt-1 text-sm font-semibold">
449
+ {template.subject}
450
+ </p>
449
451
  </div>
450
452
  )}
451
453
 
452
454
  {/* Aperçu du contenu */}
453
455
  <div className="mb-4">
454
- <p className="line-clamp-3 text-sm leading-relaxed text-muted-foreground">
456
+ <p className="text-muted-foreground line-clamp-3 text-sm leading-relaxed">
455
457
  {template.content.replace(/<[^>]+>/g, '').substring(0, 120)}
456
458
  {template.content.replace(/<[^>]+>/g, '').length > 120 && '...'}
457
459
  </p>
@@ -459,11 +461,11 @@ export default function TemplatesPage() {
459
461
 
460
462
  {/* Actions */}
461
463
  {(canEdit || canDelete) && (
462
- <div className="flex items-center justify-end gap-2 border-t border-border pt-4">
464
+ <div className="border-border flex items-center justify-end gap-2 border-t pt-4">
463
465
  {canEdit && (
464
466
  <button
465
467
  onClick={() => handleEdit(template)}
466
- className="cursor-pointer rounded-lg p-2 text-muted-foreground transition-all duration-200 hover:bg-primary/15 hover:text-primary"
468
+ className="text-muted-foreground hover:bg-primary/15 hover:text-primary cursor-pointer rounded-lg p-2 transition-colors duration-200"
467
469
  title="Modifier"
468
470
  >
469
471
  <Edit className="h-4 w-4" />
@@ -472,7 +474,7 @@ export default function TemplatesPage() {
472
474
  {canDelete && (
473
475
  <button
474
476
  onClick={() => handleDelete(template.id)}
475
- className="cursor-pointer rounded-lg p-2 text-gray-600 transition-all hover:bg-red-50 hover:text-red-600"
477
+ className="cursor-pointer rounded-lg p-2 text-gray-600 transition-colors hover:bg-red-50 hover:text-red-600"
476
478
  title="Supprimer"
477
479
  >
478
480
  <Trash2 className="h-4 w-4" />
@@ -488,16 +490,16 @@ export default function TemplatesPage() {
488
490
 
489
491
  {/* Modal de création/édition */}
490
492
  {showModal && (
491
- <div className="fixed inset-0 z-50 flex items-center justify-center bg-foreground/30 p-4 backdrop-blur-sm sm:p-6">
492
- <div className="flex max-h-[90vh] w-full max-w-5xl flex-col overflow-hidden rounded-2xl border border-border bg-card shadow-(--shadow-dropdown)">
493
+ <div className="bg-foreground/30 fixed inset-0 z-50 flex items-center justify-center p-4 backdrop-blur-sm sm:p-6">
494
+ <div className="border-border bg-card flex max-h-[90vh] w-full max-w-5xl flex-col overflow-hidden rounded-2xl border shadow-(--shadow-dropdown)">
493
495
  {/* En-tête fixe */}
494
- <div className="shrink-0 border-b border-border bg-linear-to-r from-muted to-card px-6 py-5 sm:px-8 sm:py-6">
496
+ <div className="border-border from-muted to-card shrink-0 border-b bg-linear-to-r px-6 py-5 sm:px-8 sm:py-6">
495
497
  <div className="flex items-center justify-between">
496
498
  <div>
497
- <h2 className="text-2xl font-bold text-foreground">
499
+ <h2 className="text-foreground text-2xl font-bold">
498
500
  {editingTemplate ? 'Modifier le template' : 'Nouveau template'}
499
501
  </h2>
500
- <p className="mt-1 text-sm text-muted-foreground">
502
+ <p className="text-muted-foreground mt-1 text-sm">
501
503
  {editingTemplate
502
504
  ? 'Modifiez les informations du template'
503
505
  : 'Créez un nouveau template réutilisable'}
@@ -510,7 +512,7 @@ export default function TemplatesPage() {
510
512
  setEditingTemplate(null);
511
513
  setError('');
512
514
  }}
513
- className="cursor-pointer rounded-xl p-2 text-muted-foreground transition-all duration-200 hover:bg-muted hover:text-foreground"
515
+ className="text-muted-foreground hover:bg-muted hover:text-foreground cursor-pointer rounded-xl p-2 transition-colors duration-200"
514
516
  >
515
517
  <X className="h-6 w-6" />
516
518
  </button>
@@ -524,7 +526,7 @@ export default function TemplatesPage() {
524
526
  className="flex-1 space-y-6 overflow-y-auto px-6 py-6 [-ms-overflow-style:none] [scrollbar-width:none] sm:px-8 sm:py-8 [&::-webkit-scrollbar]:hidden"
525
527
  >
526
528
  <div>
527
- <label className="block text-sm font-semibold text-foreground">
529
+ <label className="text-foreground block text-sm font-semibold">
528
530
  Nom du template <span className="text-red-500">*</span>
529
531
  </label>
530
532
  <input
@@ -532,13 +534,13 @@ export default function TemplatesPage() {
532
534
  required
533
535
  value={formData.name}
534
536
  onChange={(e) => setFormData({ ...formData, name: e.target.value })}
535
- className="mt-2 block w-full rounded-xl border border-border bg-background px-4 py-3 text-foreground shadow-sm transition-all focus:border-primary/50 focus:ring-2 focus:ring-primary/20 focus:outline-none"
537
+ className="border-border bg-background text-foreground focus:border-primary/50 focus:ring-primary/20 mt-2 block w-full rounded-xl border px-4 py-3 shadow-sm transition-[border-color,box-shadow] focus:ring-2 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/50"
536
538
  placeholder="Ex: Email de bienvenue"
537
539
  />
538
540
  </div>
539
541
 
540
542
  <div>
541
- <label className="block text-sm font-semibold text-foreground">
543
+ <label className="text-foreground block text-sm font-semibold">
542
544
  Type <span className="text-red-500">*</span>
543
545
  </label>
544
546
  <select
@@ -551,7 +553,7 @@ export default function TemplatesPage() {
551
553
  subject: e.target.value === 'EMAIL' ? formData.subject : '',
552
554
  });
553
555
  }}
554
- className="mt-2 block w-full rounded-xl border border-border bg-background px-4 py-3 text-foreground shadow-sm transition-all focus:border-primary/50 focus:ring-2 focus:ring-primary/20 focus:outline-none"
556
+ className="border-border bg-background text-foreground focus:border-primary/50 focus:ring-primary/20 mt-2 block w-full rounded-xl border px-4 py-3 shadow-sm transition-[border-color,box-shadow] focus:ring-2 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/50"
555
557
  >
556
558
  <option value="EMAIL">Email</option>
557
559
  <option value="SMS">SMS</option>
@@ -561,7 +563,7 @@ export default function TemplatesPage() {
561
563
 
562
564
  {formData.type === 'EMAIL' && (
563
565
  <div>
564
- <label className="block text-sm font-semibold text-foreground">
566
+ <label className="text-foreground block text-sm font-semibold">
565
567
  Sujet <span className="text-red-500">*</span>
566
568
  </label>
567
569
  <input
@@ -569,18 +571,18 @@ export default function TemplatesPage() {
569
571
  required
570
572
  value={formData.subject}
571
573
  onChange={(e) => setFormData({ ...formData, subject: e.target.value })}
572
- className="mt-2 block w-full rounded-xl border border-border bg-background px-4 py-3 text-foreground shadow-sm transition-all focus:border-primary/50 focus:ring-2 focus:ring-primary/20 focus:outline-none"
574
+ className="border-border bg-background text-foreground focus:border-primary/50 focus:ring-primary/20 mt-2 block w-full rounded-xl border px-4 py-3 shadow-sm transition-[border-color,box-shadow] focus:ring-2 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/50"
573
575
  placeholder="Ex: Bienvenue dans notre CRM"
574
576
  />
575
577
  </div>
576
578
  )}
577
579
 
578
580
  <div>
579
- <label className="block text-sm font-semibold text-foreground">
581
+ <label className="text-foreground block text-sm font-semibold">
580
582
  Contenu <span className="text-red-500">*</span>
581
583
  </label>
582
584
  {formData.type === 'EMAIL' || formData.type === 'NOTE' ? (
583
- <div className="mt-2 rounded-xl border border-border shadow-sm">
585
+ <div className="border-border mt-2 rounded-xl border shadow-sm">
584
586
  <Editor
585
587
  ref={formData.type === 'EMAIL' ? emailEditorRef : noteEditorRef}
586
588
  onReady={(methods) => {
@@ -603,21 +605,21 @@ export default function TemplatesPage() {
603
605
  value={formData.content}
604
606
  onChange={(e) => setFormData({ ...formData, content: e.target.value })}
605
607
  rows={6}
606
- className="mt-2 block w-full rounded-xl border border-border bg-background px-4 py-3 text-foreground shadow-sm transition-all focus:border-primary/50 focus:ring-2 focus:ring-primary/20 focus:outline-none"
608
+ className="border-border bg-background text-foreground focus:border-primary/50 focus:ring-primary/20 mt-2 block w-full rounded-xl border px-4 py-3 shadow-sm transition-[border-color,box-shadow] focus:ring-2 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/50"
607
609
  placeholder="Contenu du SMS..."
608
610
  />
609
611
  </div>
610
612
  )}
611
613
 
612
614
  {/* Section Variables */}
613
- <div className="mt-6 rounded-xl border border-primary/20 bg-linear-to-br from-primary/10 to-card p-5">
615
+ <div className="border-primary/20 from-primary/10 to-card mt-6 rounded-xl border bg-linear-to-br p-5">
614
616
  <div className="mb-4 flex items-center gap-2">
615
- <div className="flex h-8 w-8 items-center justify-center rounded-lg bg-primary/15">
616
- <FileText className="h-4 w-4 text-primary" />
617
+ <div className="bg-primary/15 flex h-8 w-8 items-center justify-center rounded-lg">
618
+ <FileText className="text-primary h-4 w-4" />
617
619
  </div>
618
620
  <div>
619
- <p className="text-sm font-bold text-foreground">Variables disponibles</p>
620
- <p className="text-xs text-muted-foreground">
621
+ <p className="text-foreground text-sm font-bold">Variables disponibles</p>
622
+ <p className="text-muted-foreground text-xs">
621
623
  Cliquez sur une variable pour l&apos;insérer dans le contenu
622
624
  </p>
623
625
  </div>
@@ -707,7 +709,7 @@ export default function TemplatesPage() {
707
709
  }
708
710
  }}
709
711
  className={cn(
710
- 'cursor-pointer rounded-lg border px-3 py-2 text-left shadow-sm transition-all hover:shadow-md',
712
+ 'cursor-pointer rounded-lg border px-3 py-2 text-left shadow-sm transition-[border-color,box-shadow] hover:shadow-md',
711
713
  colors.border,
712
714
  colors.bg,
713
715
  colors.hoverBg,
@@ -720,7 +722,7 @@ export default function TemplatesPage() {
720
722
  >
721
723
  {variable.key}
722
724
  </span>
723
- <p className="mt-1 max-w-[200px] text-[11px] leading-tight font-normal text-muted-foreground">
725
+ <p className="text-muted-foreground mt-1 max-w-[200px] text-[11px] leading-tight font-normal">
724
726
  {variable.description}
725
727
  </p>
726
728
  </button>
@@ -731,11 +733,10 @@ export default function TemplatesPage() {
731
733
  })}
732
734
  </div>
733
735
  </div>
734
-
735
736
  </form>
736
737
 
737
738
  {/* Pied de modal fixe */}
738
- <div className="shrink-0 border-t border-border bg-muted px-6 py-5 sm:px-8 sm:py-6">
739
+ <div className="border-border bg-muted shrink-0 border-t px-6 py-5 sm:px-8 sm:py-6">
739
740
  <div className="flex flex-col gap-3 sm:flex-row sm:justify-end">
740
741
  <button
741
742
  type="button"
@@ -744,14 +745,14 @@ export default function TemplatesPage() {
744
745
  setEditingTemplate(null);
745
746
  setError('');
746
747
  }}
747
- className="w-full cursor-pointer rounded-xl border border-border bg-card px-6 py-3 text-sm font-semibold text-foreground shadow-sm transition-all duration-200 hover:bg-background hover:shadow-md sm:w-auto"
748
+ className="border-border bg-card text-foreground hover:bg-background w-full cursor-pointer rounded-xl border px-6 py-3 text-sm font-semibold shadow-sm transition-[color,background-color,box-shadow] duration-200 hover:shadow-md sm:w-auto"
748
749
  >
749
750
  Annuler
750
751
  </button>
751
752
  <button
752
753
  type="submit"
753
754
  form="template-form"
754
- className="w-full cursor-pointer rounded-xl bg-primary px-6 py-3 text-sm font-semibold text-primary-foreground shadow-(--shadow-card) transition-all duration-200 hover:bg-primary/90 sm:w-auto"
755
+ className="bg-primary text-primary-foreground hover:bg-primary/90 w-full cursor-pointer rounded-xl px-6 py-3 text-sm font-semibold shadow-(--shadow-card) transition-colors duration-200 sm:w-auto"
755
756
  >
756
757
  {editingTemplate ? 'Modifier le template' : 'Créer le template'}
757
758
  </button>