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.
- package/bin/create-crm-tmp.js +56 -35
- package/package.json +1 -1
- package/template/README.md +230 -115
- package/template/eslint.config.mjs +13 -0
- package/template/next.config.ts +14 -0
- package/template/package.json +15 -2
- package/template/prisma/migrations/20260318095700_init_db/migration.sql +978 -0
- package/template/prisma/migrations/migration_lock.toml +3 -0
- package/template/prisma/schema.prisma +132 -637
- package/template/src/app/(auth)/invite/[token]/page.tsx +10 -8
- package/template/src/app/(auth)/layout.tsx +1 -1
- package/template/src/app/(auth)/reset-password/complete/page.tsx +11 -8
- package/template/src/app/(auth)/reset-password/page.tsx +4 -4
- package/template/src/app/(auth)/reset-password/verify/page.tsx +4 -4
- package/template/src/app/(auth)/signin/page.tsx +14 -6
- package/template/src/app/(dashboard)/agenda/page.tsx +2243 -988
- package/template/src/app/(dashboard)/automatisation/_components/workflow-editor.tsx +18 -104
- package/template/src/app/(dashboard)/automatisation/page.tsx +10 -26
- package/template/src/app/(dashboard)/closing/page.tsx +78 -62
- package/template/src/app/(dashboard)/contacts/[id]/page.tsx +2082 -1080
- package/template/src/app/(dashboard)/contacts/companies/[id]/page.tsx +46 -47
- package/template/src/app/(dashboard)/contacts/page.tsx +1062 -780
- package/template/src/app/(dashboard)/dashboard/page.tsx +533 -37
- package/template/src/app/(dashboard)/dev/page.tsx +1291 -0
- package/template/src/app/(dashboard)/layout.tsx +6 -2
- package/template/src/app/(dashboard)/settings/page.tsx +797 -2582
- package/template/src/app/(dashboard)/templates/page.tsx +55 -54
- package/template/src/app/(dashboard)/users/list/page.tsx +51 -48
- package/template/src/app/(dashboard)/users/page.tsx +1 -1
- package/template/src/app/(dashboard)/users/permissions/page.tsx +2 -2
- package/template/src/app/(dashboard)/users/roles/page.tsx +7 -5
- package/template/src/app/api/agenda/google-events/route.ts +92 -0
- package/template/src/app/api/auth/check-active/route.ts +3 -2
- package/template/src/app/api/auth/google/route.ts +2 -1
- package/template/src/app/api/auth/google/status/route.ts +7 -31
- package/template/src/app/api/companies/[id]/activities/route.ts +1 -3
- package/template/src/app/api/companies/[id]/route.ts +1 -2
- package/template/src/app/api/companies/route.ts +42 -12
- package/template/src/app/api/contacts/[id]/files/[fileId]/preview/route.ts +9 -31
- package/template/src/app/api/contacts/[id]/files/[fileId]/route.ts +14 -32
- package/template/src/app/api/contacts/[id]/files/route.ts +112 -212
- package/template/src/app/api/contacts/[id]/interactions/[interactionId]/route.ts +27 -1
- package/template/src/app/api/contacts/[id]/interactions/route.ts +16 -16
- package/template/src/app/api/contacts/[id]/kyc/route.ts +21 -11
- package/template/src/app/api/contacts/[id]/meet/route.ts +19 -2
- package/template/src/app/api/contacts/[id]/route.ts +106 -34
- package/template/src/app/api/contacts/[id]/send-email/route.ts +27 -11
- package/template/src/app/api/contacts/[id]/workflows/run/route.ts +6 -0
- package/template/src/app/api/contacts/export/route.ts +9 -13
- package/template/src/app/api/contacts/import/route.ts +55 -25
- package/template/src/app/api/contacts/import-preview/route.ts +1 -1
- package/template/src/app/api/contacts/origins/route.ts +63 -0
- package/template/src/app/api/contacts/route.ts +153 -41
- package/template/src/app/api/cron/cleanup-editor-images/route.ts +166 -0
- package/template/src/app/api/dashboard/widgets/[id]/route.ts +44 -0
- package/template/src/app/api/dashboard/widgets/route.ts +181 -0
- package/template/src/app/api/dev/reminders/test/route.ts +114 -0
- package/template/src/app/api/editor/upload-image/route.ts +61 -0
- package/template/src/app/api/integrations/google-sheet/jobs/[jobId]/route.ts +47 -0
- package/template/src/app/api/integrations/google-sheet/jobs/usage/route.ts +50 -0
- package/template/src/app/api/integrations/google-sheet/sync/route.ts +24 -556
- package/template/src/app/api/jobs/google-sheet/process/route.ts +84 -0
- package/template/src/app/api/jobs/google-sheet/schedule/route.ts +50 -0
- package/template/src/app/api/reminders/clear/route.ts +120 -0
- package/template/src/app/api/reminders/clear/undo/route.ts +112 -0
- package/template/src/app/api/reminders/route.ts +164 -39
- package/template/src/app/api/reminders/state/route.ts +164 -0
- package/template/src/app/api/reset-password/request/route.ts +1 -1
- package/template/src/app/api/reset-password/verify/route.ts +1 -1
- package/template/src/app/api/send/route.ts +16 -4
- package/template/src/app/api/settings/google-ads/route.ts +14 -0
- package/template/src/app/api/settings/google-calendar/calendars/route.ts +97 -0
- package/template/src/app/api/settings/google-calendar/route.ts +124 -0
- package/template/src/app/api/settings/google-sheet/[id]/route.ts +28 -0
- package/template/src/app/api/settings/google-sheet/auto-map/route.ts +37 -4
- package/template/src/app/api/settings/google-sheet/preview/route.ts +9 -3
- package/template/src/app/api/settings/google-sheet/route.ts +14 -0
- package/template/src/app/api/settings/integrations/logs/route.ts +93 -0
- package/template/src/app/api/settings/integrations/notifications/route.ts +67 -0
- package/template/src/app/api/settings/meta-leads/[id]/route.ts +0 -1
- package/template/src/app/api/settings/meta-leads/route.ts +14 -2
- package/template/src/app/api/settings/smtp/route.ts +53 -6
- package/template/src/app/api/tasks/[id]/attendees/route.ts +24 -8
- package/template/src/app/api/tasks/[id]/route.ts +234 -58
- package/template/src/app/api/tasks/meet/route.ts +27 -19
- package/template/src/app/api/tasks/route.ts +62 -17
- package/template/src/app/api/users/[id]/route.ts +20 -14
- package/template/src/app/api/users/list/route.ts +57 -19
- package/template/src/app/api/webhooks/google-ads/route.ts +34 -14
- package/template/src/app/api/webhooks/meta-leads/route.ts +32 -12
- package/template/src/app/api/workflows/[id]/route.ts +0 -4
- package/template/src/app/api/workflows/process/route.ts +22 -51
- package/template/src/app/api/workflows/route.ts +0 -4
- package/template/src/app/globals.css +342 -4
- package/template/src/app/layout.tsx +11 -3
- package/template/src/app/page.tsx +1 -1
- package/template/src/components/address-autocomplete.tsx +7 -6
- package/template/src/components/config-error-alert.tsx +46 -0
- package/template/src/components/contacts/filter-bar.tsx +12 -3
- package/template/src/components/contacts/filter-builder.tsx +28 -43
- package/template/src/components/contacts/save-view-dialog.tsx +1 -1
- package/template/src/components/contacts/views-tab-bar.tsx +15 -6
- package/template/src/components/dashboard/activity-chart.tsx +41 -28
- package/template/src/components/dashboard/add-widget-dialog.tsx +157 -0
- package/template/src/components/dashboard/color-picker.tsx +64 -0
- package/template/src/components/dashboard/contacts-chart.tsx +69 -0
- package/template/src/components/dashboard/interactions-by-type-chart.tsx +121 -0
- package/template/src/components/dashboard/recent-activity.tsx +154 -0
- package/template/src/components/dashboard/stat-card.tsx +40 -40
- package/template/src/components/dashboard/status-distribution-chart.tsx +81 -0
- package/template/src/components/dashboard/tasks-pie-chart.tsx +37 -34
- package/template/src/components/dashboard/top-contacts-list.tsx +113 -0
- package/template/src/components/dashboard/upcoming-tasks-list.tsx +72 -81
- package/template/src/components/dashboard/widget-wrapper.tsx +36 -0
- package/template/src/components/date-picker.tsx +9 -6
- package/template/src/components/editor/upload-editor-image.ts +42 -0
- package/template/src/components/editor.tsx +161 -22
- package/template/src/components/email-template.tsx +2 -2
- package/template/src/components/global-search.tsx +30 -28
- package/template/src/components/header.tsx +178 -80
- package/template/src/components/inactive-account-guard.tsx +58 -0
- package/template/src/components/integration-notifications-listener.tsx +12 -0
- package/template/src/components/invitation-email-template.tsx +2 -2
- package/template/src/components/meet-cancellation-email-template.tsx +3 -3
- package/template/src/components/meet-confirmation-email-template.tsx +3 -3
- package/template/src/components/meet-update-email-template.tsx +3 -3
- package/template/src/components/page-header.tsx +5 -5
- package/template/src/components/protected-page.tsx +1 -1
- package/template/src/components/reset-password-email-template.tsx +2 -2
- package/template/src/components/settings/integrations/GoogleAdsIntegration.tsx +428 -0
- package/template/src/components/settings/integrations/GoogleSheetConfigMonitoringModal.tsx +680 -0
- package/template/src/components/settings/integrations/GoogleSheetIntegration.tsx +809 -0
- package/template/src/components/settings/integrations/ImportResultDialog.tsx +124 -0
- package/template/src/components/settings/integrations/IntegrationLogPanel.tsx +57 -0
- package/template/src/components/settings/integrations/IntegrationLogsTable.tsx +186 -0
- package/template/src/components/settings/integrations/MetaLeadIntegration.tsx +451 -0
- package/template/src/components/sidebar.tsx +45 -26
- package/template/src/components/skeleton.tsx +40 -43
- package/template/src/components/ui/accordion.tsx +2 -2
- package/template/src/components/ui/alert-dialog.tsx +1 -1
- package/template/src/components/ui/button.tsx +20 -9
- package/template/src/components/ui/components.tsx +1 -1
- package/template/src/components/ui/date-picker.tsx +422 -0
- package/template/src/components/ui/datetime-picker.tsx +338 -0
- package/template/src/components/ui/status-select.tsx +271 -0
- package/template/src/components/ui/tooltip.tsx +37 -0
- package/template/src/components/view-as-modal.tsx +13 -7
- package/template/src/contexts/app-toast-context.tsx +245 -57
- package/template/src/contexts/dashboard-theme-context.tsx +53 -0
- package/template/src/contexts/sidebar-context.tsx +22 -17
- package/template/src/contexts/task-reminder-context.tsx +134 -160
- package/template/src/contexts/view-as-context.tsx +33 -6
- package/template/src/hooks/use-focus-trap.ts +2 -2
- package/template/src/hooks/useIntegrationNotifications.ts +49 -0
- package/template/src/lib/auth.ts +8 -1
- package/template/src/lib/config-links.ts +14 -0
- package/template/src/lib/contact-duplicate.ts +79 -61
- package/template/src/lib/contact-interactions.ts +21 -21
- package/template/src/lib/contact-view-filters.ts +24 -64
- package/template/src/lib/contacts-list-url.ts +190 -0
- package/template/src/lib/dashboard-stats.ts +65 -7
- package/template/src/lib/dashboard-themes.ts +135 -0
- package/template/src/lib/date-utils.ts +127 -0
- package/template/src/lib/default-widgets.ts +12 -0
- package/template/src/lib/editor-html-image-dimensions.ts +172 -0
- package/template/src/lib/editor-image-limits.ts +19 -0
- package/template/src/lib/email-html-sanitize.ts +19 -0
- package/template/src/lib/encryption.ts +9 -6
- package/template/src/lib/fr-geography.ts +192 -0
- package/template/src/lib/google-calendar-agenda.ts +201 -0
- package/template/src/lib/google-calendar.ts +255 -5
- package/template/src/lib/google-sheet-sync-jobs.ts +96 -0
- package/template/src/lib/google-sheet-sync-runner.ts +514 -0
- package/template/src/lib/integration-import-log.ts +21 -0
- package/template/src/lib/permissions.ts +40 -10
- package/template/src/lib/prisma.ts +4 -1
- package/template/src/lib/qstash.ts +65 -0
- package/template/src/lib/reminder-state-server.ts +80 -0
- package/template/src/lib/reminder-state.ts +29 -0
- package/template/src/lib/supabase-storage.ts +113 -0
- package/template/src/lib/template-variables.ts +164 -23
- package/template/src/lib/utils.ts +45 -0
- package/template/src/lib/widget-registry.ts +173 -0
- package/template/src/lib/workflow-executor.ts +16 -70
- package/template/src/proxy.ts +1 -0
- package/template/vercel.json +3 -10
- package/template/skills-lock.json +0 -25
- package/template/src/components/dashboard/dashboard-content.tsx +0 -79
- package/template/src/lib/google-drive.ts +0 -1101
- package/template/src/types/yousign.ts +0 -52
|
@@ -14,11 +14,13 @@ import {
|
|
|
14
14
|
Calendar,
|
|
15
15
|
Eye,
|
|
16
16
|
} from 'lucide-react';
|
|
17
|
-
import { cn } from '@/lib/utils';
|
|
17
|
+
import { cn, devToast } from '@/lib/utils';
|
|
18
18
|
import { PageLoader } from '@/components/skeleton';
|
|
19
|
+
import { StatusSelect } from '@/components/ui/status-select';
|
|
19
20
|
import { useUserRole } from '@/hooks/use-user-role';
|
|
20
21
|
import { ProtectedPage } from '@/components/protected-page';
|
|
21
22
|
import { useFetch } from '@/hooks/use-fetch';
|
|
23
|
+
import { useAppToast } from '@/contexts/app-toast-context';
|
|
22
24
|
|
|
23
25
|
interface Status {
|
|
24
26
|
id: string;
|
|
@@ -129,7 +131,7 @@ function KanbanContactCard({
|
|
|
129
131
|
onDragStart={canDrag ? onDragStart : undefined}
|
|
130
132
|
onDragEnd={canDrag ? onDragEnd : undefined}
|
|
131
133
|
className={cn(
|
|
132
|
-
'relative rounded-lg border
|
|
134
|
+
'border-border bg-card relative rounded-lg border p-4 text-[13px] shadow-(--shadow-card) transition-transform hover:-translate-y-0.5',
|
|
133
135
|
canDrag && 'cursor-grab active:cursor-grabbing',
|
|
134
136
|
!canDrag && 'cursor-default',
|
|
135
137
|
isDragging && 'opacity-80 ring-2 ring-blue-400',
|
|
@@ -138,7 +140,7 @@ function KanbanContactCard({
|
|
|
138
140
|
{/* Icône Eye en haut à droite */}
|
|
139
141
|
<Link
|
|
140
142
|
href={`/contacts/${contact.id}`}
|
|
141
|
-
className="absolute top-2 right-2 z-10 rounded p-1 transition-colors duration-200
|
|
143
|
+
className="hover:bg-muted absolute top-2 right-2 z-10 rounded p-1 transition-colors duration-200"
|
|
142
144
|
onClick={(e) => e.stopPropagation()}
|
|
143
145
|
>
|
|
144
146
|
<Eye className="h-4 w-4 stroke-gray-400" />
|
|
@@ -155,7 +157,9 @@ function KanbanContactCard({
|
|
|
155
157
|
{(contact.firstName?.[0] || contact.lastName?.[0] || '?').toUpperCase()}
|
|
156
158
|
</div>
|
|
157
159
|
<div className="min-w-0 flex-1">
|
|
158
|
-
<p className="truncate text-sm font-semibold
|
|
160
|
+
<p className="text-foreground truncate text-sm font-semibold">
|
|
161
|
+
{fullName || 'Sans nom'}
|
|
162
|
+
</p>
|
|
159
163
|
</div>
|
|
160
164
|
</div>
|
|
161
165
|
|
|
@@ -229,6 +233,7 @@ function createDefaultColumns(statuses: Status[]): ClosingColumn[] {
|
|
|
229
233
|
}
|
|
230
234
|
|
|
231
235
|
export default function ClosingPage() {
|
|
236
|
+
const toast = useAppToast();
|
|
232
237
|
const { hasPermission, isLoading: roleLoading } = useUserRole();
|
|
233
238
|
const {
|
|
234
239
|
data: statuses = [],
|
|
@@ -403,8 +408,10 @@ export default function ClosingPage() {
|
|
|
403
408
|
if (!res.ok) {
|
|
404
409
|
throw new Error('Erreur lors de la mise à jour du statut');
|
|
405
410
|
}
|
|
411
|
+
toast.success('Statut du contact mis à jour');
|
|
406
412
|
} catch (e) {
|
|
407
413
|
console.error(e);
|
|
414
|
+
toast.error(devToast('Erreur lors du déplacement du contact', e));
|
|
408
415
|
} finally {
|
|
409
416
|
setIsSavingDrag(false);
|
|
410
417
|
}
|
|
@@ -556,15 +563,41 @@ export default function ClosingPage() {
|
|
|
556
563
|
return Array.from(companyMap.values());
|
|
557
564
|
}, [contacts]);
|
|
558
565
|
|
|
566
|
+
const uniqueCommercials = useMemo(
|
|
567
|
+
() =>
|
|
568
|
+
Array.from(
|
|
569
|
+
new Map(
|
|
570
|
+
contacts
|
|
571
|
+
.filter((c) => c.assignedCommercial)
|
|
572
|
+
.map((c) => [c.assignedCommercialId, c.assignedCommercial!]),
|
|
573
|
+
).values(),
|
|
574
|
+
),
|
|
575
|
+
[contacts],
|
|
576
|
+
);
|
|
577
|
+
|
|
578
|
+
const uniqueTelepros = useMemo(
|
|
579
|
+
() =>
|
|
580
|
+
Array.from(
|
|
581
|
+
new Map(
|
|
582
|
+
contacts
|
|
583
|
+
.filter((c) => c.assignedTelepro)
|
|
584
|
+
.map((c) => [c.assignedTeleproId, c.assignedTelepro!]),
|
|
585
|
+
).values(),
|
|
586
|
+
),
|
|
587
|
+
[contacts],
|
|
588
|
+
);
|
|
589
|
+
|
|
559
590
|
return (
|
|
560
591
|
<ProtectedPage requiredPermission="contacts.view_closing_pipeline">
|
|
561
592
|
{statusesLoading || contactsLoading || roleLoading ? (
|
|
562
593
|
<div className="h-full">
|
|
563
|
-
<div className="border-
|
|
594
|
+
<div className="border-border bg-background/95 border-b px-4 py-4 backdrop-blur-sm sm:px-6 lg:px-8 lg:py-6">
|
|
564
595
|
<div className="flex items-start gap-3">
|
|
565
596
|
<div className="min-w-0 flex-1">
|
|
566
|
-
<h1 className="text-xl font-bold
|
|
567
|
-
|
|
597
|
+
<h1 className="text-foreground text-xl font-bold sm:text-2xl">
|
|
598
|
+
Pipeline de Closing
|
|
599
|
+
</h1>
|
|
600
|
+
<p className="text-muted-foreground mt-1 text-sm">
|
|
568
601
|
Visualisez et gérez vos opportunités commerciales
|
|
569
602
|
</p>
|
|
570
603
|
</div>
|
|
@@ -579,25 +612,25 @@ export default function ClosingPage() {
|
|
|
579
612
|
{' '}
|
|
580
613
|
{/* md:overflow-y-hidden */}
|
|
581
614
|
{/* En-tête personnalisé avec filtres intégrés */}
|
|
582
|
-
<div className="border-
|
|
615
|
+
<div className="border-border bg-background/95 border-b px-4 py-4 backdrop-blur-sm sm:px-6 lg:px-8 lg:py-6">
|
|
583
616
|
<div className="flex items-start gap-3">
|
|
584
617
|
<div className="flex min-w-0 flex-1 items-start justify-between gap-4">
|
|
585
618
|
<div className="min-w-0 flex-1">
|
|
586
|
-
<h1 className="text-xl font-bold
|
|
619
|
+
<h1 className="text-foreground text-xl font-bold sm:text-2xl">
|
|
587
620
|
Pipeline de Closing
|
|
588
621
|
</h1>
|
|
589
|
-
<p className="mt-1 text-sm
|
|
622
|
+
<p className="text-muted-foreground mt-1 text-sm">
|
|
590
623
|
Visualisez et gérez vos opportunités commerciales
|
|
591
624
|
</p>
|
|
592
625
|
|
|
593
626
|
{/* Filtres intégrés dans l'en-tête */}
|
|
594
627
|
<div className="mt-4 flex flex-col gap-3 sm:flex-row">
|
|
595
628
|
<div className="flex items-center gap-2">
|
|
596
|
-
<span className="text-xs font-medium
|
|
629
|
+
<span className="text-muted-foreground text-xs font-medium">Période:</span>
|
|
597
630
|
<div className="relative">
|
|
598
|
-
<Filter className="absolute top-1/2 left-2 h-3.5 w-3.5 -translate-y-1/2
|
|
631
|
+
<Filter className="text-muted-foreground absolute top-1/2 left-2 h-3.5 w-3.5 -translate-y-1/2" />
|
|
599
632
|
<select
|
|
600
|
-
className="
|
|
633
|
+
className="border-border bg-card text-foreground focus:border-primary/50 focus:ring-primary/20 rounded-lg border py-1.5 pr-2 pl-7 text-sm focus:ring-2 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/50"
|
|
601
634
|
value={selectedPeriod}
|
|
602
635
|
onChange={(e) => setSelectedPeriod(e.target.value)}
|
|
603
636
|
>
|
|
@@ -610,22 +643,16 @@ export default function ClosingPage() {
|
|
|
610
643
|
</div>
|
|
611
644
|
|
|
612
645
|
<div className="flex items-center gap-2">
|
|
613
|
-
<span className="text-xs font-medium
|
|
646
|
+
<span className="text-muted-foreground text-xs font-medium">Commercial:</span>
|
|
614
647
|
<select
|
|
615
|
-
className="
|
|
648
|
+
className="border-border bg-card text-foreground focus:border-primary/50 focus:ring-primary/20 rounded-lg border px-2 py-1.5 text-sm focus:ring-2 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/50"
|
|
616
649
|
value={selectedCommercialId}
|
|
617
650
|
onChange={(e) =>
|
|
618
651
|
setSelectedCommercialId(e.target.value === 'all' ? 'all' : e.target.value)
|
|
619
652
|
}
|
|
620
653
|
>
|
|
621
654
|
<option value="all">Tous</option>
|
|
622
|
-
{
|
|
623
|
-
new Map(
|
|
624
|
-
contacts
|
|
625
|
-
.filter((c) => c.assignedCommercial)
|
|
626
|
-
.map((c) => [c.assignedCommercialId, c.assignedCommercial!]),
|
|
627
|
-
).values(),
|
|
628
|
-
).map((user) => (
|
|
655
|
+
{uniqueCommercials.map((user) => (
|
|
629
656
|
<option key={user.id} value={user.id}>
|
|
630
657
|
{user.name}
|
|
631
658
|
</option>
|
|
@@ -634,22 +661,16 @@ export default function ClosingPage() {
|
|
|
634
661
|
</div>
|
|
635
662
|
|
|
636
663
|
<div className="flex items-center gap-2">
|
|
637
|
-
<span className="text-xs font-medium
|
|
664
|
+
<span className="text-muted-foreground text-xs font-medium">Télépro:</span>
|
|
638
665
|
<select
|
|
639
|
-
className="
|
|
666
|
+
className="border-border bg-card text-foreground focus:border-primary/50 focus:ring-primary/20 rounded-lg border px-2 py-1.5 text-sm focus:ring-2 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/50"
|
|
640
667
|
value={selectedTeleproId}
|
|
641
668
|
onChange={(e) =>
|
|
642
669
|
setSelectedTeleproId(e.target.value === 'all' ? 'all' : e.target.value)
|
|
643
670
|
}
|
|
644
671
|
>
|
|
645
672
|
<option value="all">Tous</option>
|
|
646
|
-
{
|
|
647
|
-
new Map(
|
|
648
|
-
contacts
|
|
649
|
-
.filter((c) => c.assignedTelepro)
|
|
650
|
-
.map((c) => [c.assignedTeleproId, c.assignedTelepro!]),
|
|
651
|
-
).values(),
|
|
652
|
-
).map((user) => (
|
|
673
|
+
{uniqueTelepros.map((user) => (
|
|
653
674
|
<option key={user.id} value={user.id}>
|
|
654
675
|
{user.name}
|
|
655
676
|
</option>
|
|
@@ -658,7 +679,7 @@ export default function ClosingPage() {
|
|
|
658
679
|
</div>
|
|
659
680
|
|
|
660
681
|
{isSavingDrag && (
|
|
661
|
-
<span className="self-end text-xs
|
|
682
|
+
<span className="text-muted-foreground self-end text-xs">
|
|
662
683
|
Sauvegarde des changements…
|
|
663
684
|
</span>
|
|
664
685
|
)}
|
|
@@ -669,7 +690,7 @@ export default function ClosingPage() {
|
|
|
669
690
|
<button
|
|
670
691
|
type="button"
|
|
671
692
|
onClick={openConfigModal}
|
|
672
|
-
className="inline-flex cursor-pointer items-center gap-2 rounded-lg border
|
|
693
|
+
className="border-border bg-card text-foreground hover:bg-muted focus-visible:ring-primary inline-flex cursor-pointer items-center gap-2 rounded-lg border px-3 py-2 text-sm font-semibold shadow-sm transition-colors duration-200 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none"
|
|
673
694
|
>
|
|
674
695
|
<SettingsIcon className="h-4 w-4" />
|
|
675
696
|
Configurer
|
|
@@ -697,21 +718,21 @@ export default function ClosingPage() {
|
|
|
697
718
|
`}</style>
|
|
698
719
|
{sortedColumns.length === 0 ? (
|
|
699
720
|
<div className="flex w-full items-center justify-center py-16">
|
|
700
|
-
<div className="max-w-md rounded-xl border-2 border-dashed
|
|
701
|
-
<div className="mx-auto mb-4 flex h-16 w-16 items-center justify-center rounded-full
|
|
702
|
-
<Filter className="h-8 w-8
|
|
721
|
+
<div className="border-border bg-card max-w-md rounded-xl border-2 border-dashed p-8 text-center shadow-(--shadow-card)">
|
|
722
|
+
<div className="bg-primary/15 mx-auto mb-4 flex h-16 w-16 items-center justify-center rounded-full">
|
|
723
|
+
<Filter className="text-primary h-8 w-8" />
|
|
703
724
|
</div>
|
|
704
|
-
<h3 className="mb-2 text-lg font-semibold
|
|
725
|
+
<h3 className="text-foreground mb-2 text-lg font-semibold">
|
|
705
726
|
Votre pipeline est vide
|
|
706
727
|
</h3>
|
|
707
|
-
<p className="mb-6 text-sm
|
|
728
|
+
<p className="text-muted-foreground mb-6 text-sm">
|
|
708
729
|
Commencez par configurer les colonnes de votre pipeline de closing en cliquant
|
|
709
730
|
sur le bouton ci-dessous.
|
|
710
731
|
</p>
|
|
711
732
|
<button
|
|
712
733
|
type="button"
|
|
713
734
|
onClick={openConfigModal}
|
|
714
|
-
className="inline-flex cursor-pointer items-center gap-2 rounded-lg
|
|
735
|
+
className="bg-primary text-primary-foreground hover:bg-primary/90 focus-visible:ring-primary inline-flex cursor-pointer items-center gap-2 rounded-lg px-4 py-2.5 text-sm font-semibold shadow-(--shadow-card) transition-colors duration-200 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none"
|
|
715
736
|
>
|
|
716
737
|
<SettingsIcon className="h-4 w-4" />
|
|
717
738
|
Configurer ma pipeline
|
|
@@ -727,10 +748,9 @@ export default function ClosingPage() {
|
|
|
727
748
|
<div
|
|
728
749
|
key={column.id}
|
|
729
750
|
className={cn(
|
|
730
|
-
'flex shrink-0 flex-col rounded-xl
|
|
751
|
+
'bg-muted flex shrink-0 flex-col rounded-xl shadow-sm transition-colors',
|
|
731
752
|
'h-auto max-h-[calc(100vh-220px)]',
|
|
732
|
-
dragOverStatusId === column.statusId &&
|
|
733
|
-
'ring-2 ring-blue-400 ring-offset-2',
|
|
753
|
+
dragOverStatusId === column.statusId && 'ring-2 ring-blue-400 ring-offset-2',
|
|
734
754
|
dragOverColumnId === column.id &&
|
|
735
755
|
draggedColumnId &&
|
|
736
756
|
'ring-2 ring-blue-500 ring-offset-2',
|
|
@@ -898,7 +918,7 @@ export default function ClosingPage() {
|
|
|
898
918
|
}
|
|
899
919
|
className={cn(
|
|
900
920
|
'flex w-80 shrink-0 flex-col rounded-xl border border-gray-200 bg-gray-50',
|
|
901
|
-
'cursor-grab transition-
|
|
921
|
+
'cursor-grab transition-[transform,box-shadow] duration-150 active:cursor-grabbing',
|
|
902
922
|
'hover:-translate-y-1 hover:shadow-lg',
|
|
903
923
|
dragOverConfigColumnId === column.id &&
|
|
904
924
|
'ring-2 ring-blue-400 ring-offset-2',
|
|
@@ -912,7 +932,7 @@ export default function ClosingPage() {
|
|
|
912
932
|
onChange={(e) =>
|
|
913
933
|
updateConfigColumn(column.id, { title: e.target.value })
|
|
914
934
|
}
|
|
915
|
-
className="w-full rounded-lg border border-gray-300 px-2 py-1.5 text-sm text-gray-900 focus:ring-2 focus:ring-gray-400/30 focus:outline-none"
|
|
935
|
+
className="w-full rounded-lg border border-gray-300 px-2 py-1.5 text-sm text-gray-900 focus:ring-2 focus:ring-gray-400/30 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/50"
|
|
916
936
|
placeholder="Nom de la colonne"
|
|
917
937
|
/>
|
|
918
938
|
<button
|
|
@@ -927,30 +947,26 @@ export default function ClosingPage() {
|
|
|
927
947
|
<label className="mb-2 block text-xs font-medium text-gray-600">
|
|
928
948
|
Statut associé
|
|
929
949
|
</label>
|
|
930
|
-
<
|
|
950
|
+
<StatusSelect
|
|
951
|
+
statuses={statuses}
|
|
931
952
|
value={column.statusId || ''}
|
|
932
|
-
onChange={(
|
|
953
|
+
onChange={(value) =>
|
|
933
954
|
updateConfigColumn(column.id, {
|
|
934
|
-
statusId:
|
|
955
|
+
statusId: value || null,
|
|
935
956
|
title:
|
|
936
|
-
|
|
937
|
-
? statusesById[
|
|
957
|
+
value && statusesById[value]
|
|
958
|
+
? statusesById[value].name
|
|
938
959
|
: column.title,
|
|
939
960
|
color:
|
|
940
|
-
|
|
941
|
-
? statusesById[
|
|
961
|
+
value && statusesById[value]
|
|
962
|
+
? statusesById[value].color
|
|
942
963
|
: column.color,
|
|
943
964
|
})
|
|
944
965
|
}
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
<option key={status.id} value={status.id}>
|
|
950
|
-
{status.name}
|
|
951
|
-
</option>
|
|
952
|
-
))}
|
|
953
|
-
</select>
|
|
966
|
+
placeholder="Sélectionnez un statut"
|
|
967
|
+
size="sm"
|
|
968
|
+
className="mb-3"
|
|
969
|
+
/>
|
|
954
970
|
|
|
955
971
|
<label className="mb-1 block text-xs font-medium text-gray-600">
|
|
956
972
|
Couleur de la colonne
|
|
@@ -970,7 +986,7 @@ export default function ClosingPage() {
|
|
|
970
986
|
onChange={(e) =>
|
|
971
987
|
updateConfigColumn(column.id, { color: e.target.value })
|
|
972
988
|
}
|
|
973
|
-
className="flex-1 rounded-lg border border-gray-300 px-2 py-1.5 text-xs text-gray-900 focus:ring-2 focus:ring-gray-400/30 focus:outline-none"
|
|
989
|
+
className="flex-1 rounded-lg border border-gray-300 px-2 py-1.5 text-xs text-gray-900 focus:ring-2 focus:ring-gray-400/30 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/50"
|
|
974
990
|
/>
|
|
975
991
|
</div>
|
|
976
992
|
|
|
@@ -1017,7 +1033,7 @@ export default function ClosingPage() {
|
|
|
1017
1033
|
<button
|
|
1018
1034
|
type="button"
|
|
1019
1035
|
onClick={handleSaveConfig}
|
|
1020
|
-
className="cursor-pointer rounded-lg
|
|
1036
|
+
className="bg-primary text-primary-foreground hover:bg-primary/90 cursor-pointer rounded-lg px-4 py-2 text-sm font-semibold shadow-sm transition-colors"
|
|
1021
1037
|
>
|
|
1022
1038
|
Enregistrer la configuration
|
|
1023
1039
|
</button>
|