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.
- package/bin/create-crm-tmp.js +93 -0
- package/package.json +25 -0
- package/template/.prettierignore +33 -0
- package/template/.prettierrc.json +25 -0
- package/template/README.md +173 -0
- package/template/eslint.config.mjs +18 -0
- package/template/exemple-contacts.csv +11 -0
- package/template/next.config.ts +8 -0
- package/template/package.json +64 -0
- package/template/postcss.config.mjs +7 -0
- package/template/prisma/migrations/20251126144728_init/migration.sql +78 -0
- package/template/prisma/migrations/20251126155204_add_user_roles/migration.sql +5 -0
- package/template/prisma/migrations/20251128095126_add_company_info/migration.sql +19 -0
- package/template/prisma/migrations/20251128123321_add_smtp_config/migration.sql +22 -0
- package/template/prisma/migrations/20251128132303_add_status/migration.sql +23 -0
- package/template/prisma/migrations/20251201102207_add_user_active/migration.sql +75 -0
- package/template/prisma/migrations/20251201105507_add_email_signature/migration.sql +2 -0
- package/template/prisma/migrations/20251201151122_add_tasks/migration.sql +45 -0
- package/template/prisma/migrations/20251202111854_add_task_reminder/migration.sql +2 -0
- package/template/prisma/migrations/20251202135859_add_google_meet_integration/migration.sql +27 -0
- package/template/prisma/migrations/20251203103317_add_meta_lead_integration/migration.sql +20 -0
- package/template/prisma/migrations/20251203104002_add_google_ads_integration/migration.sql +18 -0
- package/template/prisma/migrations/20251203112122_add_google_sheet_integration/migration.sql +32 -0
- package/template/prisma/migrations/20251203153853_allow_multiple_integration_configs/migration.sql +20 -0
- package/template/prisma/migrations/20251205141705_update_user_roles/migration.sql +12 -0
- package/template/prisma/migrations/20251205150000_add_commercial_and_telepro_assignment/migration.sql +21 -0
- package/template/prisma/migrations/20251205160000_add_interaction_logging/migration.sql +11 -0
- package/template/prisma/migrations/20251208090314_add_automatic_interaction_types/migration.sql +12 -0
- package/template/prisma/migrations/20251208094843_mg/migration.sql +14 -0
- package/template/prisma/migrations/20251208100000_add_company_support/migration.sql +14 -0
- package/template/prisma/migrations/20251208110000_add_templates/migration.sql +26 -0
- package/template/prisma/migrations/20251208141304_add_video_conference_task_type/migration.sql +2 -0
- package/template/prisma/migrations/20251209104759_add_internal_note_to_task/migration.sql +2 -0
- package/template/prisma/migrations/20251209134803_add_company_field/migration.sql +2 -0
- package/template/prisma/migrations/20251209150000_rename_company_to_company_name/migration.sql +3 -0
- package/template/prisma/migrations/20251209150016_add_email_tracking/migration.sql +21 -0
- package/template/prisma/migrations/20251209155908_add_notify_contact_to_task/migration.sql +2 -0
- package/template/prisma/migrations/20251210110019_add_appointment_types/migration.sql +10 -0
- package/template/prisma/migrations/20251210113928_add_contact_files/migration.sql +26 -0
- package/template/prisma/migrations/20251212132339_add_custom_roles/migration.sql +24 -0
- package/template/prisma/migrations/20251215104448_add_file_interaction_types/migration.sql +11 -0
- package/template/prisma/migrations/20251215145616_add_closing_reasons/migration.sql +12 -0
- package/template/prisma/migrations/20251216140850_add_log_users/migration.sql +25 -0
- package/template/prisma/migrations/20251216151000_rename_perdu_to_ferme/migration.sql +8 -0
- package/template/prisma/migrations/20251216162318_add_column_mappings_to_google_sheet/migration.sql +2 -0
- package/template/prisma/migrations/20251216185127_add_workflows/migration.sql +80 -0
- package/template/prisma/migrations/20251216192237_add_scheduled_workflow_actions/migration.sql +32 -0
- package/template/prisma/migrations/migration_lock.toml +3 -0
- package/template/prisma/schema.prisma +582 -0
- package/template/prisma.config.ts +14 -0
- package/template/src/app/(auth)/invite/[token]/page.tsx +200 -0
- package/template/src/app/(auth)/layout.tsx +3 -0
- package/template/src/app/(auth)/reset-password/complete/page.tsx +213 -0
- package/template/src/app/(auth)/reset-password/page.tsx +146 -0
- package/template/src/app/(auth)/reset-password/verify/page.tsx +183 -0
- package/template/src/app/(auth)/signin/page.tsx +166 -0
- package/template/src/app/(dashboard)/agenda/page.tsx +3051 -0
- package/template/src/app/(dashboard)/automatisation/[id]/page.tsx +24 -0
- package/template/src/app/(dashboard)/automatisation/_components/workflow-editor.tsx +905 -0
- package/template/src/app/(dashboard)/automatisation/new/page.tsx +20 -0
- package/template/src/app/(dashboard)/automatisation/page.tsx +337 -0
- package/template/src/app/(dashboard)/closing/page.tsx +1052 -0
- package/template/src/app/(dashboard)/contacts/[id]/page.tsx +6028 -0
- package/template/src/app/(dashboard)/contacts/page.tsx +3713 -0
- package/template/src/app/(dashboard)/dashboard/page.tsx +186 -0
- package/template/src/app/(dashboard)/layout.tsx +30 -0
- package/template/src/app/(dashboard)/settings/page.tsx +4070 -0
- package/template/src/app/(dashboard)/templates/page.tsx +567 -0
- package/template/src/app/(dashboard)/users/list/page.tsx +507 -0
- package/template/src/app/(dashboard)/users/page.tsx +457 -0
- package/template/src/app/(dashboard)/users/permissions/page.tsx +181 -0
- package/template/src/app/(dashboard)/users/roles/page.tsx +434 -0
- package/template/src/app/api/audit-logs/route.ts +57 -0
- package/template/src/app/api/auth/[...all]/route.ts +4 -0
- package/template/src/app/api/auth/check-active/route.ts +31 -0
- package/template/src/app/api/auth/google/callback/route.ts +94 -0
- package/template/src/app/api/auth/google/disconnect/route.ts +32 -0
- package/template/src/app/api/auth/google/route.ts +34 -0
- package/template/src/app/api/auth/google/status/route.ts +32 -0
- package/template/src/app/api/closing-reasons/route.ts +27 -0
- package/template/src/app/api/contacts/[id]/files/[fileId]/route.ts +94 -0
- package/template/src/app/api/contacts/[id]/files/route.ts +269 -0
- package/template/src/app/api/contacts/[id]/interactions/[interactionId]/route.ts +91 -0
- package/template/src/app/api/contacts/[id]/interactions/route.ts +103 -0
- package/template/src/app/api/contacts/[id]/meet/route.ts +296 -0
- package/template/src/app/api/contacts/[id]/route.ts +322 -0
- package/template/src/app/api/contacts/[id]/send-email/route.ts +254 -0
- package/template/src/app/api/contacts/export/route.ts +270 -0
- package/template/src/app/api/contacts/import/route.ts +381 -0
- package/template/src/app/api/contacts/route.ts +283 -0
- package/template/src/app/api/dashboard/stats/route.ts +299 -0
- package/template/src/app/api/email/track/[id]/route.ts +68 -0
- package/template/src/app/api/integrations/google-sheet/sync/route.ts +526 -0
- package/template/src/app/api/invite/complete/route.ts +88 -0
- package/template/src/app/api/invite/validate/route.ts +55 -0
- package/template/src/app/api/reminders/route.ts +95 -0
- package/template/src/app/api/reset-password/complete/route.ts +73 -0
- package/template/src/app/api/reset-password/request/route.ts +84 -0
- package/template/src/app/api/reset-password/validate/route.ts +49 -0
- package/template/src/app/api/reset-password/verify/route.ts +74 -0
- package/template/src/app/api/roles/[id]/route.ts +183 -0
- package/template/src/app/api/roles/route.ts +140 -0
- package/template/src/app/api/send/route.ts +282 -0
- package/template/src/app/api/settings/change-password/route.ts +95 -0
- package/template/src/app/api/settings/closing-reasons/[id]/route.ts +84 -0
- package/template/src/app/api/settings/closing-reasons/route.ts +74 -0
- package/template/src/app/api/settings/company/route.ts +121 -0
- package/template/src/app/api/settings/google-ads/[id]/route.ts +117 -0
- package/template/src/app/api/settings/google-ads/route.ts +122 -0
- package/template/src/app/api/settings/google-sheet/[id]/route.ts +230 -0
- package/template/src/app/api/settings/google-sheet/auto-map/route.ts +196 -0
- package/template/src/app/api/settings/google-sheet/route.ts +254 -0
- package/template/src/app/api/settings/meta-leads/[id]/route.ts +123 -0
- package/template/src/app/api/settings/meta-leads/route.ts +132 -0
- package/template/src/app/api/settings/profile/route.ts +42 -0
- package/template/src/app/api/settings/smtp/route.ts +130 -0
- package/template/src/app/api/settings/smtp/test/route.ts +121 -0
- package/template/src/app/api/settings/statuses/[id]/route.ts +101 -0
- package/template/src/app/api/settings/statuses/route.ts +83 -0
- package/template/src/app/api/statuses/route.ts +25 -0
- package/template/src/app/api/tasks/[id]/attendees/route.ts +76 -0
- package/template/src/app/api/tasks/[id]/route.ts +728 -0
- package/template/src/app/api/tasks/meet/route.ts +240 -0
- package/template/src/app/api/tasks/route.ts +417 -0
- package/template/src/app/api/templates/[id]/route.ts +140 -0
- package/template/src/app/api/templates/route.ts +91 -0
- package/template/src/app/api/users/[id]/route.ts +168 -0
- package/template/src/app/api/users/list/route.ts +45 -0
- package/template/src/app/api/users/me/route.ts +48 -0
- package/template/src/app/api/users/route.ts +250 -0
- package/template/src/app/api/webhooks/google-ads/route.ts +208 -0
- package/template/src/app/api/webhooks/meta-leads/route.ts +258 -0
- package/template/src/app/api/workflows/[id]/route.ts +192 -0
- package/template/src/app/api/workflows/process/route.ts +293 -0
- package/template/src/app/api/workflows/route.ts +124 -0
- package/template/src/app/favicon.ico +0 -0
- package/template/src/app/globals.css +1416 -0
- package/template/src/app/layout.tsx +31 -0
- package/template/src/app/page.tsx +32 -0
- package/template/src/components/dashboard/activity-chart.tsx +67 -0
- package/template/src/components/dashboard/contacts-chart.tsx +63 -0
- package/template/src/components/dashboard/recent-activity.tsx +164 -0
- package/template/src/components/dashboard/sales-analytics-chart.tsx +81 -0
- package/template/src/components/dashboard/stat-card.tsx +61 -0
- package/template/src/components/dashboard/status-distribution-chart.tsx +45 -0
- package/template/src/components/dashboard/tasks-pie-chart.tsx +88 -0
- package/template/src/components/dashboard/top-contacts-list.tsx +129 -0
- package/template/src/components/dashboard/upcoming-tasks-list.tsx +126 -0
- package/template/src/components/editor.tsx +856 -0
- package/template/src/components/email-template.tsx +35 -0
- package/template/src/components/header.tsx +320 -0
- package/template/src/components/invitation-email-template.tsx +79 -0
- package/template/src/components/meet-cancellation-email-template.tsx +120 -0
- package/template/src/components/meet-confirmation-email-template.tsx +156 -0
- package/template/src/components/meet-update-email-template.tsx +209 -0
- package/template/src/components/page-header.tsx +61 -0
- package/template/src/components/reset-password-email-template.tsx +79 -0
- package/template/src/components/sidebar.tsx +294 -0
- package/template/src/components/skeleton.tsx +380 -0
- package/template/src/components/ui/commands.tsx +396 -0
- package/template/src/components/ui/components.tsx +150 -0
- package/template/src/components/ui/theme.tsx +5 -0
- package/template/src/components/view-as-banner.tsx +45 -0
- package/template/src/components/view-as-modal.tsx +186 -0
- package/template/src/contexts/mobile-menu-context.tsx +31 -0
- package/template/src/contexts/sidebar-context.tsx +107 -0
- package/template/src/contexts/task-reminder-context.tsx +239 -0
- package/template/src/contexts/view-as-context.tsx +84 -0
- package/template/src/hooks/use-user-role.ts +82 -0
- package/template/src/lib/audit-log.ts +45 -0
- package/template/src/lib/auth-client.ts +16 -0
- package/template/src/lib/auth.ts +35 -0
- package/template/src/lib/check-permission.ts +193 -0
- package/template/src/lib/contact-duplicate.ts +112 -0
- package/template/src/lib/contact-interactions.ts +371 -0
- package/template/src/lib/encryption.ts +99 -0
- package/template/src/lib/google-calendar.ts +300 -0
- package/template/src/lib/google-drive.ts +372 -0
- package/template/src/lib/permissions.ts +412 -0
- package/template/src/lib/prisma.ts +32 -0
- package/template/src/lib/roles.ts +120 -0
- package/template/src/lib/template-variables.ts +76 -0
- package/template/src/lib/utils.ts +46 -0
- package/template/src/lib/workflow-executor.ts +482 -0
- package/template/src/proxy.ts +91 -0
- package/template/tsconfig.json +34 -0
- 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
|
+
}
|