create-crm-tmp 1.0.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 (187) hide show
  1. package/bin/create-crm-tmp.js +93 -0
  2. package/package.json +25 -0
  3. package/template/.prettierignore +33 -0
  4. package/template/.prettierrc.json +25 -0
  5. package/template/README.md +173 -0
  6. package/template/eslint.config.mjs +18 -0
  7. package/template/exemple-contacts.csv +11 -0
  8. package/template/next.config.ts +8 -0
  9. package/template/package.json +64 -0
  10. package/template/postcss.config.mjs +7 -0
  11. package/template/prisma/migrations/20251126144728_init/migration.sql +78 -0
  12. package/template/prisma/migrations/20251126155204_add_user_roles/migration.sql +5 -0
  13. package/template/prisma/migrations/20251128095126_add_company_info/migration.sql +19 -0
  14. package/template/prisma/migrations/20251128123321_add_smtp_config/migration.sql +22 -0
  15. package/template/prisma/migrations/20251128132303_add_status/migration.sql +23 -0
  16. package/template/prisma/migrations/20251201102207_add_user_active/migration.sql +75 -0
  17. package/template/prisma/migrations/20251201105507_add_email_signature/migration.sql +2 -0
  18. package/template/prisma/migrations/20251201151122_add_tasks/migration.sql +45 -0
  19. package/template/prisma/migrations/20251202111854_add_task_reminder/migration.sql +2 -0
  20. package/template/prisma/migrations/20251202135859_add_google_meet_integration/migration.sql +27 -0
  21. package/template/prisma/migrations/20251203103317_add_meta_lead_integration/migration.sql +20 -0
  22. package/template/prisma/migrations/20251203104002_add_google_ads_integration/migration.sql +18 -0
  23. package/template/prisma/migrations/20251203112122_add_google_sheet_integration/migration.sql +32 -0
  24. package/template/prisma/migrations/20251203153853_allow_multiple_integration_configs/migration.sql +20 -0
  25. package/template/prisma/migrations/20251205141705_update_user_roles/migration.sql +12 -0
  26. package/template/prisma/migrations/20251205150000_add_commercial_and_telepro_assignment/migration.sql +21 -0
  27. package/template/prisma/migrations/20251205160000_add_interaction_logging/migration.sql +11 -0
  28. package/template/prisma/migrations/20251208090314_add_automatic_interaction_types/migration.sql +12 -0
  29. package/template/prisma/migrations/20251208094843_mg/migration.sql +14 -0
  30. package/template/prisma/migrations/20251208100000_add_company_support/migration.sql +14 -0
  31. package/template/prisma/migrations/20251208110000_add_templates/migration.sql +26 -0
  32. package/template/prisma/migrations/20251208141304_add_video_conference_task_type/migration.sql +2 -0
  33. package/template/prisma/migrations/20251209104759_add_internal_note_to_task/migration.sql +2 -0
  34. package/template/prisma/migrations/20251209134803_add_company_field/migration.sql +2 -0
  35. package/template/prisma/migrations/20251209150000_rename_company_to_company_name/migration.sql +3 -0
  36. package/template/prisma/migrations/20251209150016_add_email_tracking/migration.sql +21 -0
  37. package/template/prisma/migrations/20251209155908_add_notify_contact_to_task/migration.sql +2 -0
  38. package/template/prisma/migrations/20251210110019_add_appointment_types/migration.sql +10 -0
  39. package/template/prisma/migrations/20251210113928_add_contact_files/migration.sql +26 -0
  40. package/template/prisma/migrations/20251212132339_add_custom_roles/migration.sql +24 -0
  41. package/template/prisma/migrations/20251215104448_add_file_interaction_types/migration.sql +11 -0
  42. package/template/prisma/migrations/20251215145616_add_closing_reasons/migration.sql +12 -0
  43. package/template/prisma/migrations/20251216140850_add_log_users/migration.sql +25 -0
  44. package/template/prisma/migrations/20251216151000_rename_perdu_to_ferme/migration.sql +8 -0
  45. package/template/prisma/migrations/20251216162318_add_column_mappings_to_google_sheet/migration.sql +2 -0
  46. package/template/prisma/migrations/20251216185127_add_workflows/migration.sql +80 -0
  47. package/template/prisma/migrations/20251216192237_add_scheduled_workflow_actions/migration.sql +32 -0
  48. package/template/prisma/migrations/migration_lock.toml +3 -0
  49. package/template/prisma/schema.prisma +582 -0
  50. package/template/prisma.config.ts +14 -0
  51. package/template/src/app/(auth)/invite/[token]/page.tsx +200 -0
  52. package/template/src/app/(auth)/layout.tsx +3 -0
  53. package/template/src/app/(auth)/reset-password/complete/page.tsx +213 -0
  54. package/template/src/app/(auth)/reset-password/page.tsx +146 -0
  55. package/template/src/app/(auth)/reset-password/verify/page.tsx +183 -0
  56. package/template/src/app/(auth)/signin/page.tsx +166 -0
  57. package/template/src/app/(dashboard)/agenda/page.tsx +3051 -0
  58. package/template/src/app/(dashboard)/automatisation/[id]/page.tsx +24 -0
  59. package/template/src/app/(dashboard)/automatisation/_components/workflow-editor.tsx +905 -0
  60. package/template/src/app/(dashboard)/automatisation/new/page.tsx +20 -0
  61. package/template/src/app/(dashboard)/automatisation/page.tsx +337 -0
  62. package/template/src/app/(dashboard)/closing/page.tsx +1052 -0
  63. package/template/src/app/(dashboard)/contacts/[id]/page.tsx +6028 -0
  64. package/template/src/app/(dashboard)/contacts/page.tsx +3713 -0
  65. package/template/src/app/(dashboard)/dashboard/page.tsx +186 -0
  66. package/template/src/app/(dashboard)/layout.tsx +30 -0
  67. package/template/src/app/(dashboard)/settings/page.tsx +4070 -0
  68. package/template/src/app/(dashboard)/templates/page.tsx +567 -0
  69. package/template/src/app/(dashboard)/users/list/page.tsx +507 -0
  70. package/template/src/app/(dashboard)/users/page.tsx +457 -0
  71. package/template/src/app/(dashboard)/users/permissions/page.tsx +181 -0
  72. package/template/src/app/(dashboard)/users/roles/page.tsx +434 -0
  73. package/template/src/app/api/audit-logs/route.ts +57 -0
  74. package/template/src/app/api/auth/[...all]/route.ts +4 -0
  75. package/template/src/app/api/auth/check-active/route.ts +31 -0
  76. package/template/src/app/api/auth/google/callback/route.ts +94 -0
  77. package/template/src/app/api/auth/google/disconnect/route.ts +32 -0
  78. package/template/src/app/api/auth/google/route.ts +34 -0
  79. package/template/src/app/api/auth/google/status/route.ts +32 -0
  80. package/template/src/app/api/closing-reasons/route.ts +27 -0
  81. package/template/src/app/api/contacts/[id]/files/[fileId]/route.ts +94 -0
  82. package/template/src/app/api/contacts/[id]/files/route.ts +269 -0
  83. package/template/src/app/api/contacts/[id]/interactions/[interactionId]/route.ts +91 -0
  84. package/template/src/app/api/contacts/[id]/interactions/route.ts +103 -0
  85. package/template/src/app/api/contacts/[id]/meet/route.ts +296 -0
  86. package/template/src/app/api/contacts/[id]/route.ts +322 -0
  87. package/template/src/app/api/contacts/[id]/send-email/route.ts +254 -0
  88. package/template/src/app/api/contacts/export/route.ts +270 -0
  89. package/template/src/app/api/contacts/import/route.ts +381 -0
  90. package/template/src/app/api/contacts/route.ts +283 -0
  91. package/template/src/app/api/dashboard/stats/route.ts +299 -0
  92. package/template/src/app/api/email/track/[id]/route.ts +68 -0
  93. package/template/src/app/api/integrations/google-sheet/sync/route.ts +526 -0
  94. package/template/src/app/api/invite/complete/route.ts +88 -0
  95. package/template/src/app/api/invite/validate/route.ts +55 -0
  96. package/template/src/app/api/reminders/route.ts +95 -0
  97. package/template/src/app/api/reset-password/complete/route.ts +73 -0
  98. package/template/src/app/api/reset-password/request/route.ts +84 -0
  99. package/template/src/app/api/reset-password/validate/route.ts +49 -0
  100. package/template/src/app/api/reset-password/verify/route.ts +74 -0
  101. package/template/src/app/api/roles/[id]/route.ts +183 -0
  102. package/template/src/app/api/roles/route.ts +140 -0
  103. package/template/src/app/api/send/route.ts +282 -0
  104. package/template/src/app/api/settings/change-password/route.ts +95 -0
  105. package/template/src/app/api/settings/closing-reasons/[id]/route.ts +84 -0
  106. package/template/src/app/api/settings/closing-reasons/route.ts +74 -0
  107. package/template/src/app/api/settings/company/route.ts +121 -0
  108. package/template/src/app/api/settings/google-ads/[id]/route.ts +117 -0
  109. package/template/src/app/api/settings/google-ads/route.ts +122 -0
  110. package/template/src/app/api/settings/google-sheet/[id]/route.ts +230 -0
  111. package/template/src/app/api/settings/google-sheet/auto-map/route.ts +196 -0
  112. package/template/src/app/api/settings/google-sheet/route.ts +254 -0
  113. package/template/src/app/api/settings/meta-leads/[id]/route.ts +123 -0
  114. package/template/src/app/api/settings/meta-leads/route.ts +132 -0
  115. package/template/src/app/api/settings/profile/route.ts +42 -0
  116. package/template/src/app/api/settings/smtp/route.ts +130 -0
  117. package/template/src/app/api/settings/smtp/test/route.ts +121 -0
  118. package/template/src/app/api/settings/statuses/[id]/route.ts +101 -0
  119. package/template/src/app/api/settings/statuses/route.ts +83 -0
  120. package/template/src/app/api/statuses/route.ts +25 -0
  121. package/template/src/app/api/tasks/[id]/attendees/route.ts +76 -0
  122. package/template/src/app/api/tasks/[id]/route.ts +728 -0
  123. package/template/src/app/api/tasks/meet/route.ts +240 -0
  124. package/template/src/app/api/tasks/route.ts +417 -0
  125. package/template/src/app/api/templates/[id]/route.ts +140 -0
  126. package/template/src/app/api/templates/route.ts +91 -0
  127. package/template/src/app/api/users/[id]/route.ts +168 -0
  128. package/template/src/app/api/users/list/route.ts +45 -0
  129. package/template/src/app/api/users/me/route.ts +48 -0
  130. package/template/src/app/api/users/route.ts +250 -0
  131. package/template/src/app/api/webhooks/google-ads/route.ts +208 -0
  132. package/template/src/app/api/webhooks/meta-leads/route.ts +258 -0
  133. package/template/src/app/api/workflows/[id]/route.ts +192 -0
  134. package/template/src/app/api/workflows/process/route.ts +293 -0
  135. package/template/src/app/api/workflows/route.ts +124 -0
  136. package/template/src/app/favicon.ico +0 -0
  137. package/template/src/app/globals.css +1416 -0
  138. package/template/src/app/layout.tsx +31 -0
  139. package/template/src/app/page.tsx +32 -0
  140. package/template/src/components/dashboard/activity-chart.tsx +67 -0
  141. package/template/src/components/dashboard/contacts-chart.tsx +63 -0
  142. package/template/src/components/dashboard/recent-activity.tsx +164 -0
  143. package/template/src/components/dashboard/sales-analytics-chart.tsx +81 -0
  144. package/template/src/components/dashboard/stat-card.tsx +61 -0
  145. package/template/src/components/dashboard/status-distribution-chart.tsx +45 -0
  146. package/template/src/components/dashboard/tasks-pie-chart.tsx +88 -0
  147. package/template/src/components/dashboard/top-contacts-list.tsx +129 -0
  148. package/template/src/components/dashboard/upcoming-tasks-list.tsx +126 -0
  149. package/template/src/components/editor.tsx +856 -0
  150. package/template/src/components/email-template.tsx +35 -0
  151. package/template/src/components/header.tsx +320 -0
  152. package/template/src/components/invitation-email-template.tsx +79 -0
  153. package/template/src/components/meet-cancellation-email-template.tsx +120 -0
  154. package/template/src/components/meet-confirmation-email-template.tsx +156 -0
  155. package/template/src/components/meet-update-email-template.tsx +209 -0
  156. package/template/src/components/page-header.tsx +61 -0
  157. package/template/src/components/reset-password-email-template.tsx +79 -0
  158. package/template/src/components/sidebar.tsx +294 -0
  159. package/template/src/components/skeleton.tsx +380 -0
  160. package/template/src/components/ui/commands.tsx +396 -0
  161. package/template/src/components/ui/components.tsx +150 -0
  162. package/template/src/components/ui/theme.tsx +5 -0
  163. package/template/src/components/view-as-banner.tsx +45 -0
  164. package/template/src/components/view-as-modal.tsx +186 -0
  165. package/template/src/contexts/mobile-menu-context.tsx +31 -0
  166. package/template/src/contexts/sidebar-context.tsx +107 -0
  167. package/template/src/contexts/task-reminder-context.tsx +239 -0
  168. package/template/src/contexts/view-as-context.tsx +84 -0
  169. package/template/src/hooks/use-user-role.ts +82 -0
  170. package/template/src/lib/audit-log.ts +45 -0
  171. package/template/src/lib/auth-client.ts +16 -0
  172. package/template/src/lib/auth.ts +35 -0
  173. package/template/src/lib/check-permission.ts +193 -0
  174. package/template/src/lib/contact-duplicate.ts +112 -0
  175. package/template/src/lib/contact-interactions.ts +371 -0
  176. package/template/src/lib/encryption.ts +99 -0
  177. package/template/src/lib/google-calendar.ts +300 -0
  178. package/template/src/lib/google-drive.ts +372 -0
  179. package/template/src/lib/permissions.ts +412 -0
  180. package/template/src/lib/prisma.ts +32 -0
  181. package/template/src/lib/roles.ts +120 -0
  182. package/template/src/lib/template-variables.ts +76 -0
  183. package/template/src/lib/utils.ts +46 -0
  184. package/template/src/lib/workflow-executor.ts +482 -0
  185. package/template/src/proxy.ts +91 -0
  186. package/template/tsconfig.json +34 -0
  187. package/template/vercel.json +8 -0
@@ -0,0 +1,129 @@
1
+ 'use client';
2
+
3
+ import Link from 'next/link';
4
+ import { cn } from '@/lib/utils';
5
+
6
+ interface Contact {
7
+ id: string;
8
+ name: string;
9
+ phone: string;
10
+ email: string | null;
11
+ status: string;
12
+ interactionsCount: number;
13
+ assignedCommercial?: string;
14
+ assignedTelepro?: string;
15
+ }
16
+
17
+ interface TopContactsListProps {
18
+ contacts: Contact[];
19
+ }
20
+
21
+ const statusColors: Record<string, { bg: string; text: string }> = {
22
+ Nouveau: { bg: 'bg-blue-100', text: 'text-blue-700' },
23
+ Contacté: { bg: 'bg-orange-100', text: 'text-orange-700' },
24
+ Qualifié: { bg: 'bg-green-100', text: 'text-green-700' },
25
+ Prospect: { bg: 'bg-purple-100', text: 'text-purple-700' },
26
+ };
27
+
28
+ export function TopContactsList({ contacts }: TopContactsListProps) {
29
+ if (contacts.length === 0) {
30
+ return (
31
+ <div className="rounded-xl border border-gray-200/50 bg-white p-6 shadow-lg">
32
+ <div className="flex items-center justify-between">
33
+ <h3 className="text-lg font-bold text-gray-900">Prospects</h3>
34
+ <Link
35
+ href="/contacts"
36
+ className="text-sm font-semibold text-indigo-600 transition-colors hover:text-indigo-700"
37
+ >
38
+ Voir tout →
39
+ </Link>
40
+ </div>
41
+ <div className="mt-6 text-center text-sm text-gray-500">
42
+ <p className="mt-2">Aucun contact</p>
43
+ </div>
44
+ </div>
45
+ );
46
+ }
47
+
48
+ const getStatusColor = (status: string) => {
49
+ return statusColors[status] || { bg: 'bg-gray-100', text: 'text-gray-700' };
50
+ };
51
+
52
+ return (
53
+ <div className="rounded-xl border border-gray-200/50 bg-white p-6 shadow-lg transition-shadow duration-300 hover:shadow-xl">
54
+ <div className="mb-4 flex items-center justify-between">
55
+ <h3 className="text-lg font-bold text-gray-900">Prospects</h3>
56
+ <Link
57
+ href="/contacts"
58
+ className="text-sm font-semibold text-indigo-600 transition-colors hover:text-indigo-700"
59
+ >
60
+ Voir tout →
61
+ </Link>
62
+ </div>
63
+ <div className="overflow-x-auto">
64
+ <table className="min-w-full divide-y divide-gray-200">
65
+ <thead className="bg-gray-50">
66
+ <tr>
67
+ <th className="px-4 py-3 text-left text-xs font-semibold uppercase tracking-wider text-gray-700">
68
+ Nom du Prospect
69
+ </th>
70
+ <th className="px-4 py-3 text-left text-xs font-semibold uppercase tracking-wider text-gray-700">
71
+ Email
72
+ </th>
73
+ <th className="px-4 py-3 text-left text-xs font-semibold uppercase tracking-wider text-gray-700">
74
+ Télépro
75
+ </th>
76
+ <th className="px-4 py-3 text-left text-xs font-semibold uppercase tracking-wider text-gray-700">
77
+ Statut
78
+ </th>
79
+ </tr>
80
+ </thead>
81
+ <tbody className="divide-y divide-gray-200 bg-white">
82
+ {contacts.map((contact) => {
83
+ const statusColor = getStatusColor(contact.status);
84
+ const nameParts = contact.name.split(' ');
85
+ const firstName = nameParts[0] || '';
86
+ const lastName = nameParts.slice(1).join(' ') || '';
87
+ const initials = `${firstName[0] || ''}${lastName[0] || ''}`.toUpperCase();
88
+
89
+ return (
90
+ <tr key={contact.id} className="transition-colors hover:bg-gray-50">
91
+ <td className="whitespace-nowrap px-4 py-4">
92
+ <div className="flex items-center gap-3">
93
+ <div className="flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-gradient-to-br from-indigo-100 to-purple-100 text-xs font-semibold text-indigo-700">
94
+ {initials || '?'}
95
+ </div>
96
+ <Link
97
+ href={`/contacts/${contact.id}`}
98
+ className="font-semibold text-gray-900 transition-colors hover:text-indigo-600"
99
+ >
100
+ {contact.name}
101
+ </Link>
102
+ </div>
103
+ </td>
104
+ <td className="whitespace-nowrap px-4 py-4 text-sm text-gray-700">
105
+ {contact.email || '-'}
106
+ </td>
107
+ <td className="whitespace-nowrap px-4 py-4 text-sm text-gray-700">
108
+ {contact.assignedTelepro || '-'}
109
+ </td>
110
+ <td className="whitespace-nowrap px-4 py-4">
111
+ <span
112
+ className={cn(
113
+ 'inline-flex rounded-full px-2.5 py-0.5 text-xs font-semibold',
114
+ statusColor.bg,
115
+ statusColor.text,
116
+ )}
117
+ >
118
+ {contact.status}
119
+ </span>
120
+ </td>
121
+ </tr>
122
+ );
123
+ })}
124
+ </tbody>
125
+ </table>
126
+ </div>
127
+ </div>
128
+ );
129
+ }
@@ -0,0 +1,126 @@
1
+ 'use client';
2
+
3
+ import Link from 'next/link';
4
+ import { Calendar, Phone, Video, Mail, CheckCircle2, Clock } from 'lucide-react';
5
+ import { cn } from '@/lib/utils';
6
+
7
+ interface Task {
8
+ id: string;
9
+ title: string;
10
+ type: string;
11
+ scheduledAt: string;
12
+ contact: { id: string; name: string } | null;
13
+ priority: string;
14
+ }
15
+
16
+ interface UpcomingTasksListProps {
17
+ tasks: Task[];
18
+ }
19
+
20
+ const taskIcons = {
21
+ CALL: Phone,
22
+ MEETING: Calendar,
23
+ EMAIL: Mail,
24
+ VIDEO_CONFERENCE: Video,
25
+ OTHER: CheckCircle2,
26
+ };
27
+
28
+ const priorityColors = {
29
+ LOW: 'text-gray-500 bg-gray-100',
30
+ MEDIUM: 'text-blue-600 bg-blue-100',
31
+ HIGH: 'text-orange-600 bg-orange-100',
32
+ URGENT: 'text-red-600 bg-red-100',
33
+ };
34
+
35
+ const priorityLabels = {
36
+ LOW: 'Basse',
37
+ MEDIUM: 'Moyenne',
38
+ HIGH: 'Haute',
39
+ URGENT: 'Urgente',
40
+ };
41
+
42
+ export function UpcomingTasksList({ tasks }: UpcomingTasksListProps) {
43
+ if (tasks.length === 0) {
44
+ return (
45
+ <div className="rounded-lg border border-gray-200 bg-white p-6 shadow-sm">
46
+ <div className="flex items-center justify-between">
47
+ <h3 className="text-lg font-semibold text-gray-900">Tâches à Venir</h3>
48
+ <Link
49
+ href="/agenda"
50
+ className="text-sm font-medium text-indigo-600 hover:text-indigo-700"
51
+ >
52
+ Voir tout
53
+ </Link>
54
+ </div>
55
+ <div className="mt-6 text-center text-sm text-gray-500">
56
+ <Clock className="mx-auto h-12 w-12 text-gray-400" />
57
+ <p className="mt-2">Aucune tâche à venir</p>
58
+ </div>
59
+ </div>
60
+ );
61
+ }
62
+
63
+ return (
64
+ <div className="rounded-xl border border-gray-200/50 bg-white p-6 shadow-lg transition-shadow duration-300 hover:shadow-xl">
65
+ <div className="mb-4 flex items-center justify-between">
66
+ <h3 className="text-lg font-bold text-gray-900">Liste des Tâches</h3>
67
+ <Link
68
+ href="/agenda"
69
+ className="text-sm font-semibold text-indigo-600 transition-colors hover:text-indigo-700"
70
+ >
71
+ Voir tout →
72
+ </Link>
73
+ </div>
74
+ <div className="space-y-3">
75
+ {tasks.map((task) => {
76
+ const Icon = taskIcons[task.type as keyof typeof taskIcons] || CheckCircle2;
77
+ const scheduledDate = new Date(task.scheduledAt);
78
+
79
+ return (
80
+ <div
81
+ key={task.id}
82
+ className="group flex items-start gap-3 rounded-lg border border-gray-100 bg-gray-50/50 p-3 transition-all duration-200 hover:border-indigo-200 hover:bg-indigo-50/30"
83
+ >
84
+ <input
85
+ type="checkbox"
86
+ className="mt-1 h-4 w-4 cursor-pointer rounded border-gray-300 text-indigo-600 focus:ring-2 focus:ring-indigo-500"
87
+ />
88
+ <div className="flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-gradient-to-br from-indigo-100 to-purple-100">
89
+ <Icon className="h-4 w-4 text-indigo-600" />
90
+ </div>
91
+ <div className="flex-1">
92
+ <div className="flex items-start justify-between">
93
+ <div>
94
+ <p className="font-semibold text-gray-900">{task.title}</p>
95
+ {task.contact && (
96
+ <Link
97
+ href={`/contacts/${task.contact.id}`}
98
+ className="text-sm text-gray-600 transition-colors hover:text-indigo-600"
99
+ >
100
+ {task.contact.name}
101
+ </Link>
102
+ )}
103
+ </div>
104
+ <button className="opacity-0 transition-opacity group-hover:opacity-100">
105
+ <span className="text-gray-400">⋯</span>
106
+ </button>
107
+ </div>
108
+ <p className="mt-1 text-xs text-gray-500">
109
+ {scheduledDate.toLocaleDateString('fr-FR', {
110
+ day: 'numeric',
111
+ month: 'long',
112
+ })}{' '}
113
+ à{' '}
114
+ {scheduledDate.toLocaleTimeString('fr-FR', {
115
+ hour: '2-digit',
116
+ minute: '2-digit',
117
+ })}
118
+ </p>
119
+ </div>
120
+ </div>
121
+ );
122
+ })}
123
+ </div>
124
+ </div>
125
+ );
126
+ }