create-crm-tmp 1.1.3 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/create-crm-tmp.js +56 -35
- package/package.json +1 -1
- package/template/.prettierignore +2 -0
- package/template/README.md +230 -115
- package/template/components.json +22 -0
- package/template/eslint.config.mjs +13 -0
- package/template/exemple-contacts.csv +54 -0
- package/template/next.config.ts +41 -1
- package/template/package.json +63 -15
- package/template/prisma/migrations/20260318095700_init_db/migration.sql +978 -0
- package/template/prisma/schema.prisma +311 -67
- package/template/src/app/(auth)/invite/[token]/page.tsx +28 -29
- package/template/src/app/(auth)/layout.tsx +1 -1
- package/template/src/app/(auth)/reset-password/complete/page.tsx +21 -27
- package/template/src/app/(auth)/reset-password/page.tsx +14 -10
- package/template/src/app/(auth)/reset-password/verify/page.tsx +14 -10
- package/template/src/app/(auth)/signin/page.tsx +34 -23
- package/template/src/app/(dashboard)/agenda/page.tsx +3655 -2357
- package/template/src/app/(dashboard)/automatisation/[id]/page.tsx +10 -7
- package/template/src/app/(dashboard)/automatisation/_components/workflow-editor.tsx +609 -338
- package/template/src/app/(dashboard)/automatisation/new/page.tsx +11 -8
- package/template/src/app/(dashboard)/automatisation/page.tsx +463 -186
- package/template/src/app/(dashboard)/closing/page.tsx +517 -469
- package/template/src/app/(dashboard)/contacts/[id]/page.tsx +6151 -4210
- package/template/src/app/(dashboard)/contacts/companies/[id]/page.tsx +1702 -0
- package/template/src/app/(dashboard)/contacts/loading.tsx +13 -0
- package/template/src/app/(dashboard)/contacts/page.tsx +4124 -2130
- package/template/src/app/(dashboard)/dashboard/page.tsx +119 -105
- package/template/src/app/(dashboard)/dev/page.tsx +1291 -0
- package/template/src/app/(dashboard)/error.tsx +37 -0
- package/template/src/app/(dashboard)/layout.tsx +6 -2
- package/template/src/app/(dashboard)/loading.tsx +5 -0
- package/template/src/app/(dashboard)/settings/loading.tsx +19 -0
- package/template/src/app/(dashboard)/settings/page.tsx +1773 -3362
- package/template/src/app/(dashboard)/templates/page.tsx +504 -303
- package/template/src/app/(dashboard)/users/list/page.tsx +364 -355
- package/template/src/app/(dashboard)/users/page.tsx +279 -310
- package/template/src/app/(dashboard)/users/permissions/page.tsx +104 -99
- package/template/src/app/(dashboard)/users/roles/page.tsx +169 -140
- package/template/src/app/api/agenda/google-events/route.ts +92 -0
- package/template/src/app/api/audit-logs/route.ts +1 -1
- package/template/src/app/api/auth/check-active/route.ts +3 -2
- package/template/src/app/api/auth/google/callback/route.ts +8 -5
- package/template/src/app/api/auth/google/disconnect/route.ts +2 -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 +129 -0
- package/template/src/app/api/companies/[id]/route.ts +194 -0
- package/template/src/app/api/companies/export/route.ts +206 -0
- package/template/src/app/api/companies/route.ts +196 -0
- package/template/src/app/api/contact-views/[id]/pin/route.ts +69 -0
- package/template/src/app/api/contact-views/[id]/route.ts +197 -0
- package/template/src/app/api/contact-views/route.ts +146 -0
- package/template/src/app/api/contacts/[id]/files/[fileId]/preview/route.ts +55 -0
- package/template/src/app/api/contacts/[id]/files/[fileId]/route.ts +20 -48
- package/template/src/app/api/contacts/[id]/files/route.ts +125 -186
- package/template/src/app/api/contacts/[id]/interactions/[interactionId]/route.ts +27 -1
- package/template/src/app/api/contacts/[id]/interactions/route.ts +45 -8
- package/template/src/app/api/contacts/[id]/kyc/route.ts +81 -0
- package/template/src/app/api/contacts/[id]/meet/route.ts +55 -29
- package/template/src/app/api/contacts/[id]/route.ts +184 -21
- package/template/src/app/api/contacts/[id]/send-email/route.ts +33 -11
- package/template/src/app/api/contacts/[id]/workflows/run/route.ts +67 -0
- package/template/src/app/api/contacts/export/route.ts +22 -31
- package/template/src/app/api/contacts/import/route.ts +77 -44
- package/template/src/app/api/contacts/import-preview/route.ts +139 -0
- package/template/src/app/api/contacts/origins/route.ts +63 -0
- package/template/src/app/api/contacts/route.ts +322 -57
- package/template/src/app/api/cron/cleanup-editor-images/route.ts +166 -0
- package/template/src/app/api/dashboard/stats/route.ts +9 -292
- package/template/src/app/api/dashboard/widgets/[id]/route.ts +0 -3
- package/template/src/app/api/dashboard/widgets/route.ts +19 -19
- 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 +28 -542
- package/template/src/app/api/invite/complete/route.ts +20 -23
- 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 +165 -39
- package/template/src/app/api/reminders/state/route.ts +164 -0
- package/template/src/app/api/reset-password/complete/route.ts +11 -13
- 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 +25 -47
- package/template/src/app/api/settings/closing-reasons/[id]/route.ts +10 -21
- package/template/src/app/api/settings/closing-reasons/route.ts +10 -21
- package/template/src/app/api/settings/company/route.ts +19 -26
- package/template/src/app/api/settings/google-ads/[id]/route.ts +20 -23
- package/template/src/app/api/settings/google-ads/route.ts +34 -23
- 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 +48 -23
- package/template/src/app/api/settings/google-sheet/auto-map/route.ts +56 -32
- package/template/src/app/api/settings/google-sheet/preview/route.ts +110 -0
- package/template/src/app/api/settings/google-sheet/route.ts +34 -23
- 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 +20 -24
- package/template/src/app/api/settings/meta-leads/route.ts +34 -25
- package/template/src/app/api/settings/smtp/route.ts +53 -6
- package/template/src/app/api/settings/statuses/[id]/route.ts +29 -32
- package/template/src/app/api/settings/statuses/route.ts +24 -22
- package/template/src/app/api/statuses/route.ts +2 -5
- package/template/src/app/api/tasks/[id]/attendees/route.ts +36 -13
- package/template/src/app/api/tasks/[id]/route.ts +357 -145
- package/template/src/app/api/tasks/meet/route.ts +37 -26
- package/template/src/app/api/tasks/route.ts +201 -96
- package/template/src/app/api/templates/[id]/route.ts +22 -13
- package/template/src/app/api/templates/route.ts +22 -5
- package/template/src/app/api/users/[id]/resend-invite/route.ts +95 -0
- package/template/src/app/api/users/[id]/route.ts +22 -16
- package/template/src/app/api/users/commercials/route.ts +38 -0
- package/template/src/app/api/users/for-agenda/route.ts +1 -2
- package/template/src/app/api/users/list/route.ts +57 -19
- package/template/src/app/api/users/route.ts +89 -34
- package/template/src/app/api/webhooks/google-ads/route.ts +40 -1
- package/template/src/app/api/webhooks/meta-leads/route.ts +38 -1
- package/template/src/app/api/workflows/[id]/route.ts +29 -6
- package/template/src/app/api/workflows/process/route.ts +505 -170
- package/template/src/app/api/workflows/route.ts +42 -4
- package/template/src/app/globals.css +512 -32
- package/template/src/app/layout.tsx +28 -9
- package/template/src/app/page.tsx +37 -7
- package/template/src/components/address-autocomplete.tsx +233 -0
- package/template/src/components/config-error-alert.tsx +46 -0
- package/template/src/components/contacts/filter-bar.tsx +190 -0
- package/template/src/components/contacts/filter-builder.tsx +574 -0
- package/template/src/components/contacts/save-view-dialog.tsx +160 -0
- package/template/src/components/contacts/views-tab-bar.tsx +449 -0
- package/template/src/components/dashboard/activity-chart.tsx +6 -1
- package/template/src/components/dashboard/add-widget-dialog.tsx +13 -17
- package/template/src/components/dashboard/color-picker.tsx +7 -8
- package/template/src/components/dashboard/recent-activity.tsx +2 -5
- package/template/src/components/dashboard/stat-card.tsx +1 -3
- package/template/src/components/dashboard/status-distribution-chart.tsx +0 -1
- package/template/src/components/dashboard/top-contacts-list.tsx +7 -13
- package/template/src/components/dashboard/upcoming-tasks-list.tsx +2 -5
- package/template/src/components/dashboard/widget-wrapper.tsx +3 -6
- package/template/src/components/date-picker.tsx +399 -0
- package/template/src/components/editor/upload-editor-image.ts +42 -0
- package/template/src/components/editor.tsx +188 -35
- package/template/src/components/email-template.tsx +4 -2
- package/template/src/components/global-search.tsx +360 -0
- package/template/src/components/header.tsx +200 -107
- 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 +4 -2
- package/template/src/components/lazy-editor.tsx +11 -0
- package/template/src/components/meet-cancellation-email-template.tsx +11 -3
- package/template/src/components/meet-confirmation-email-template.tsx +10 -3
- package/template/src/components/meet-update-email-template.tsx +10 -3
- package/template/src/components/page-header.tsx +19 -15
- package/template/src/components/protected-page.tsx +94 -0
- package/template/src/components/reset-password-email-template.tsx +4 -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 +117 -100
- package/template/src/components/skeleton.tsx +128 -45
- package/template/src/components/ui/accordion.tsx +64 -0
- package/template/src/components/ui/alert-dialog.tsx +139 -0
- package/template/src/components/ui/button.tsx +71 -0
- 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-banner.tsx +1 -1
- package/template/src/components/view-as-modal.tsx +30 -19
- package/template/src/config/nav-pages.ts +108 -0
- package/template/src/contexts/app-toast-context.tsx +362 -0
- package/template/src/contexts/dashboard-theme-context.tsx +2 -7
- package/template/src/contexts/sidebar-context.tsx +27 -53
- package/template/src/contexts/task-reminder-context.tsx +134 -160
- package/template/src/contexts/view-as-context.tsx +32 -10
- package/template/src/hooks/use-alert.tsx +65 -0
- package/template/src/hooks/use-confirm.tsx +87 -0
- package/template/src/hooks/use-contact-views.ts +140 -0
- package/template/src/hooks/use-contacts.ts +69 -0
- package/template/src/hooks/use-fetch.ts +17 -0
- package/template/src/hooks/use-focus-trap.ts +73 -0
- package/template/src/hooks/use-statuses.ts +22 -0
- package/template/src/hooks/useIntegrationNotifications.ts +49 -0
- package/template/src/lib/address-api.ts +155 -0
- package/template/src/lib/auth.ts +8 -1
- package/template/src/lib/cache.ts +73 -0
- package/template/src/lib/check-permission.ts +12 -177
- 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 +24 -22
- package/template/src/lib/contact-view-filters.ts +301 -0
- package/template/src/lib/contacts-list-url.ts +190 -0
- package/template/src/lib/dashboard-stats.ts +282 -0
- package/template/src/lib/dashboard-themes.ts +0 -5
- package/template/src/lib/date-utils.ts +176 -0
- package/template/src/lib/default-widgets.ts +0 -2
- 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/get-auth-user.ts +25 -0
- package/template/src/lib/google-calendar-agenda.ts +201 -0
- package/template/src/lib/google-calendar.ts +309 -17
- package/template/src/lib/google-fetch.ts +63 -0
- 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/local-storage.ts +34 -0
- package/template/src/lib/permissions.ts +268 -40
- package/template/src/lib/prisma.ts +15 -12
- 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/roles.ts +12 -15
- package/template/src/lib/supabase-storage.ts +113 -0
- package/template/src/lib/template-variables.ts +204 -29
- package/template/src/lib/utils.ts +71 -11
- package/template/src/lib/widget-registry.ts +0 -4
- package/template/src/lib/workflow-executor.ts +391 -228
- package/template/src/proxy.ts +35 -73
- package/template/src/types/contact-views.ts +351 -0
- package/template/vercel.json +5 -0
- package/template/WORKFLOWS_CRON.md +0 -185
- package/template/prisma/migrations/20251126144728_init/migration.sql +0 -78
- package/template/prisma/migrations/20251126155204_add_user_roles/migration.sql +0 -5
- package/template/prisma/migrations/20251128095126_add_company_info/migration.sql +0 -19
- package/template/prisma/migrations/20251128123321_add_smtp_config/migration.sql +0 -22
- package/template/prisma/migrations/20251128132303_add_status/migration.sql +0 -23
- package/template/prisma/migrations/20251201102207_add_user_active/migration.sql +0 -75
- package/template/prisma/migrations/20251201105507_add_email_signature/migration.sql +0 -2
- package/template/prisma/migrations/20251201151122_add_tasks/migration.sql +0 -45
- package/template/prisma/migrations/20251202111854_add_task_reminder/migration.sql +0 -2
- package/template/prisma/migrations/20251202135859_add_google_meet_integration/migration.sql +0 -27
- package/template/prisma/migrations/20251203103317_add_meta_lead_integration/migration.sql +0 -20
- package/template/prisma/migrations/20251203104002_add_google_ads_integration/migration.sql +0 -18
- package/template/prisma/migrations/20251203112122_add_google_sheet_integration/migration.sql +0 -32
- package/template/prisma/migrations/20251203153853_allow_multiple_integration_configs/migration.sql +0 -20
- package/template/prisma/migrations/20251205141705_update_user_roles/migration.sql +0 -12
- package/template/prisma/migrations/20251205150000_add_commercial_and_telepro_assignment/migration.sql +0 -21
- package/template/prisma/migrations/20251205160000_add_interaction_logging/migration.sql +0 -11
- package/template/prisma/migrations/20251208090314_add_automatic_interaction_types/migration.sql +0 -12
- package/template/prisma/migrations/20251208094843_mg/migration.sql +0 -14
- package/template/prisma/migrations/20251208100000_add_company_support/migration.sql +0 -14
- package/template/prisma/migrations/20251208110000_add_templates/migration.sql +0 -26
- package/template/prisma/migrations/20251208141304_add_video_conference_task_type/migration.sql +0 -2
- package/template/prisma/migrations/20251209104759_add_internal_note_to_task/migration.sql +0 -2
- package/template/prisma/migrations/20251209134803_add_company_field/migration.sql +0 -2
- package/template/prisma/migrations/20251209150000_rename_company_to_company_name/migration.sql +0 -3
- package/template/prisma/migrations/20251209150016_add_email_tracking/migration.sql +0 -21
- package/template/prisma/migrations/20251209155908_add_notify_contact_to_task/migration.sql +0 -2
- package/template/prisma/migrations/20251210110019_add_appointment_types/migration.sql +0 -10
- package/template/prisma/migrations/20251210113928_add_contact_files/migration.sql +0 -26
- package/template/prisma/migrations/20251212132339_add_custom_roles/migration.sql +0 -24
- package/template/prisma/migrations/20251215104448_add_file_interaction_types/migration.sql +0 -11
- package/template/prisma/migrations/20251215145616_add_closing_reasons/migration.sql +0 -12
- package/template/prisma/migrations/20251216140850_add_log_users/migration.sql +0 -25
- package/template/prisma/migrations/20251216151000_rename_perdu_to_ferme/migration.sql +0 -8
- package/template/prisma/migrations/20251216162318_add_column_mappings_to_google_sheet/migration.sql +0 -2
- package/template/prisma/migrations/20251216185127_add_workflows/migration.sql +0 -80
- package/template/prisma/migrations/20251216192237_add_scheduled_workflow_actions/migration.sql +0 -32
- package/template/prisma/migrations/20251220000000_add_task_interaction_type/migration.sql +0 -4
- package/template/prisma/migrations/20251221000000_add_task_type/migration.sql +0 -3
- package/template/prisma/migrations/20251221000001_add_event_color/migration.sql +0 -23
- package/template/prisma/migrations/20260210114913_add_dashboard_widget/migration.sql +0 -20
- package/template/prisma/migrations/20260226093949_fix_cascade_on_user_delete/migration.sql +0 -69
- package/template/src/app/(dashboard)/users/layout.tsx +0 -30
- package/template/src/lib/google-drive.ts +0 -380
|
@@ -9,29 +9,22 @@ import { useMobileMenuContext } from '@/contexts/mobile-menu-context';
|
|
|
9
9
|
import { useSidebarContext } from '@/contexts/sidebar-context';
|
|
10
10
|
import { useViewAs } from '@/contexts/view-as-context';
|
|
11
11
|
import { ViewAsModal } from '@/components/view-as-modal';
|
|
12
|
-
import {
|
|
13
|
-
LayoutDashboard,
|
|
14
|
-
Users,
|
|
15
|
-
UserCog,
|
|
16
|
-
Settings,
|
|
17
|
-
Calendar as CalendarIcon,
|
|
18
|
-
FileText,
|
|
19
|
-
Eye,
|
|
20
|
-
Zap,
|
|
21
|
-
Columns3,
|
|
22
|
-
X,
|
|
23
|
-
} from 'lucide-react';
|
|
12
|
+
import { Eye, X, PanelLeftClose, PanelLeftOpen, FlaskConical } from 'lucide-react';
|
|
24
13
|
import { cn } from '@/lib/utils';
|
|
14
|
+
import { NAV_PAGES } from '@/config/nav-pages';
|
|
25
15
|
|
|
26
16
|
export function Sidebar() {
|
|
27
17
|
const pathname = usePathname();
|
|
28
18
|
const { data: session } = useSession();
|
|
29
19
|
const router = useRouter();
|
|
30
20
|
const { isOpen: isMobileMenuOpen, setIsOpen: setIsMobileMenuOpen } = useMobileMenuContext();
|
|
31
|
-
const {
|
|
21
|
+
const { isPinned, togglePin } = useSidebarContext();
|
|
32
22
|
const { viewAsUser, isViewingAsOther } = useViewAs();
|
|
33
23
|
const [showViewAsModal, setShowViewAsModal] = useState(false);
|
|
34
24
|
const [isMounted, setIsMounted] = useState(false);
|
|
25
|
+
/** Ouvert au survol uniquement (desktop, sans modifier le pin) */
|
|
26
|
+
const [expandedByHover, setExpandedByHover] = useState(false);
|
|
27
|
+
const isSidebarExpanded = isPinned || expandedByHover;
|
|
35
28
|
|
|
36
29
|
// Éviter l'erreur d'hydratation
|
|
37
30
|
useEffect(() => {
|
|
@@ -39,36 +32,15 @@ export function Sidebar() {
|
|
|
39
32
|
}, []);
|
|
40
33
|
|
|
41
34
|
// Obtenir le rôle de l'utilisateur via le hook personnalisé
|
|
42
|
-
const {
|
|
35
|
+
const { isRealAdmin, hasPermission } = useUserRole();
|
|
43
36
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
{ name: 'Automatisations', href: '/automatisation', icon: Zap },
|
|
52
|
-
{ name: 'Templates', href: '/templates', icon: FileText },
|
|
53
|
-
];
|
|
54
|
-
|
|
55
|
-
// Ajouter la gestion des droits d'accès seulement pour les admins
|
|
56
|
-
if (isAdmin) {
|
|
57
|
-
baseNav.push({
|
|
58
|
-
name: "Droits d'accès",
|
|
59
|
-
href: '/users',
|
|
60
|
-
icon: UserCog,
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
baseNav.push({
|
|
65
|
-
name: 'Paramètres',
|
|
66
|
-
href: '/settings',
|
|
67
|
-
icon: Settings,
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
return baseNav;
|
|
71
|
-
}, [isAdmin]);
|
|
37
|
+
const dashboardNav = useMemo(
|
|
38
|
+
() =>
|
|
39
|
+
NAV_PAGES.filter(
|
|
40
|
+
(page) => !page.parentLabel && page.permissions.some((p) => hasPermission(p)),
|
|
41
|
+
),
|
|
42
|
+
[hasPermission],
|
|
43
|
+
);
|
|
72
44
|
|
|
73
45
|
const handleSignOut = async () => {
|
|
74
46
|
await signOut();
|
|
@@ -84,7 +56,7 @@ export function Sidebar() {
|
|
|
84
56
|
{/* Overlay for mobile */}
|
|
85
57
|
{isMobileMenuOpen && (
|
|
86
58
|
<div
|
|
87
|
-
className="fixed inset-0 z-40
|
|
59
|
+
className="bg-foreground/10 ui-fade-in fixed inset-0 z-40 backdrop-blur-sm lg:hidden"
|
|
88
60
|
onClick={() => setIsMobileMenuOpen(false)}
|
|
89
61
|
/>
|
|
90
62
|
)}
|
|
@@ -92,70 +64,79 @@ export function Sidebar() {
|
|
|
92
64
|
{/* Sidebar */}
|
|
93
65
|
<div
|
|
94
66
|
className={cn(
|
|
95
|
-
'fixed top-0 left-0 z-40 flex h-screen flex-col border-r
|
|
67
|
+
'group border-sidebar-border bg-sidebar text-sidebar-foreground fixed top-0 left-0 z-40 flex h-screen flex-col border-r shadow-(--shadow-card) transition-[width,transform] duration-300 ease-(--ease-standard) lg:relative lg:translate-x-0',
|
|
96
68
|
isMobileMenuOpen ? 'translate-x-0' : '-translate-x-full lg:translate-x-0',
|
|
97
|
-
|
|
69
|
+
!isSidebarExpanded ? 'w-64 lg:w-16' : 'w-64 lg:w-64',
|
|
98
70
|
)}
|
|
99
71
|
onMouseEnter={() => {
|
|
100
|
-
if (
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
72
|
+
if (
|
|
73
|
+
typeof globalThis.window !== 'undefined' &&
|
|
74
|
+
globalThis.window.innerWidth >= 1024 &&
|
|
75
|
+
!isPinned
|
|
76
|
+
) {
|
|
77
|
+
setExpandedByHover(true);
|
|
104
78
|
}
|
|
105
79
|
}}
|
|
106
80
|
onMouseLeave={() => {
|
|
107
|
-
if (typeof window !== 'undefined' && window.innerWidth >= 1024) {
|
|
108
|
-
|
|
109
|
-
setIsCollapsed(true);
|
|
110
|
-
}
|
|
81
|
+
if (typeof globalThis.window !== 'undefined' && globalThis.window.innerWidth >= 1024) {
|
|
82
|
+
setExpandedByHover(false);
|
|
111
83
|
}
|
|
112
84
|
}}
|
|
113
85
|
>
|
|
114
|
-
{/* Bouton fermer - Mobile seulement */}
|
|
115
|
-
<div className="flex h-16 items-center justify-end border-b border-gray-200 px-4 lg:hidden">
|
|
116
|
-
<button
|
|
117
|
-
onClick={() => setIsMobileMenuOpen(false)}
|
|
118
|
-
className="cursor-pointer rounded-lg p-2 text-gray-500 transition-colors hover:bg-gray-100"
|
|
119
|
-
aria-label="Close menu"
|
|
120
|
-
>
|
|
121
|
-
<X className="h-5 w-5" />
|
|
122
|
-
</button>
|
|
123
|
-
</div>
|
|
124
|
-
|
|
125
86
|
{/* Navigation principale */}
|
|
126
87
|
<nav className="flex-1 space-y-6 overflow-y-auto py-4">
|
|
127
88
|
{/* Section Dashboard */}
|
|
128
|
-
<div className={cn('px-3',
|
|
129
|
-
|
|
130
|
-
<
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
89
|
+
<div className={cn('px-3', !isSidebarExpanded && 'lg:px-2')}>
|
|
90
|
+
<div className="flex items-center justify-end">
|
|
91
|
+
<button
|
|
92
|
+
onClick={() => setIsMobileMenuOpen(false)}
|
|
93
|
+
className="text-sidebar-foreground/70 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground cursor-pointer rounded-lg p-2 transition-colors duration-200 lg:hidden"
|
|
94
|
+
aria-label="Close menu"
|
|
95
|
+
>
|
|
96
|
+
<X className="h-5 w-5" />
|
|
97
|
+
</button>
|
|
98
|
+
</div>
|
|
134
99
|
<div className="space-y-1">
|
|
135
100
|
{dashboardNav.map((item) => {
|
|
136
101
|
const isActive = pathname === item.href;
|
|
137
102
|
const Icon = item.icon;
|
|
103
|
+
const displayName = item.name;
|
|
138
104
|
return (
|
|
139
105
|
<Link
|
|
140
106
|
key={item.name}
|
|
141
107
|
href={item.href}
|
|
142
108
|
onClick={handleLinkClick}
|
|
143
109
|
className={cn(
|
|
144
|
-
'flex items-center gap-3 rounded-lg py-2 text-sm font-medium transition-
|
|
145
|
-
|
|
110
|
+
'flex items-center gap-3 rounded-lg py-2 text-sm font-medium transition-[color,background-color,box-shadow] duration-(--duration-normal) ease-(--ease-standard)',
|
|
111
|
+
!isSidebarExpanded ? 'px-3 lg:justify-center lg:px-2' : 'px-3',
|
|
146
112
|
isActive
|
|
147
|
-
? 'bg-
|
|
148
|
-
: 'text-
|
|
113
|
+
? 'bg-sidebar-primary text-sidebar-primary-foreground shadow-sm'
|
|
114
|
+
: 'text-sidebar-foreground/80 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground active:scale-[0.97]',
|
|
149
115
|
)}
|
|
150
|
-
title={
|
|
116
|
+
title={!isSidebarExpanded ? displayName : undefined}
|
|
151
117
|
>
|
|
152
|
-
<Icon className="h-5 w-5 shrink-0" />
|
|
153
|
-
{
|
|
154
|
-
<span className="whitespace-nowrap">{item.name}</span>
|
|
155
|
-
)}
|
|
118
|
+
<Icon aria-hidden="true" className="h-5 w-5 shrink-0" />
|
|
119
|
+
{isSidebarExpanded && <span className="whitespace-nowrap">{displayName}</span>}
|
|
156
120
|
</Link>
|
|
157
121
|
);
|
|
158
122
|
})}
|
|
123
|
+
{process.env.NODE_ENV === 'development' && (
|
|
124
|
+
<Link
|
|
125
|
+
href="/dev"
|
|
126
|
+
onClick={handleLinkClick}
|
|
127
|
+
className={cn(
|
|
128
|
+
'flex items-center gap-3 rounded-lg py-2 text-sm font-medium transition-[color,background-color,box-shadow] duration-(--duration-normal) ease-(--ease-standard)',
|
|
129
|
+
!isSidebarExpanded ? 'px-3 lg:justify-center lg:px-2' : 'px-3',
|
|
130
|
+
pathname === '/dev'
|
|
131
|
+
? 'bg-sidebar-primary text-sidebar-primary-foreground shadow-sm'
|
|
132
|
+
: 'text-sidebar-foreground/80 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground active:scale-[0.97]',
|
|
133
|
+
)}
|
|
134
|
+
title={!isSidebarExpanded ? 'Dev' : undefined}
|
|
135
|
+
>
|
|
136
|
+
<FlaskConical aria-hidden="true" className="h-5 w-5 shrink-0" />
|
|
137
|
+
{isSidebarExpanded && <span className="whitespace-nowrap">Dev</span>}
|
|
138
|
+
</Link>
|
|
139
|
+
)}
|
|
159
140
|
</div>
|
|
160
141
|
</div>
|
|
161
142
|
</nav>
|
|
@@ -164,18 +145,18 @@ export function Sidebar() {
|
|
|
164
145
|
{isRealAdmin && (
|
|
165
146
|
<div
|
|
166
147
|
className={cn(
|
|
167
|
-
'border-
|
|
168
|
-
|
|
148
|
+
'border-sidebar-border border-t transition-[padding] duration-300',
|
|
149
|
+
!isSidebarExpanded ? 'p-3 lg:p-2' : 'p-3',
|
|
169
150
|
)}
|
|
170
151
|
>
|
|
171
|
-
{
|
|
152
|
+
{isSidebarExpanded ? (
|
|
172
153
|
<button
|
|
173
154
|
onClick={() => setShowViewAsModal(true)}
|
|
174
155
|
className={cn(
|
|
175
|
-
'w-full cursor-pointer rounded-lg border-2 p-3 text-left transition-
|
|
156
|
+
'w-full cursor-pointer rounded-lg border-2 p-3 text-left transition-colors',
|
|
176
157
|
isViewingAsOther
|
|
177
|
-
? 'border-
|
|
178
|
-
: 'border-
|
|
158
|
+
? 'border-sidebar-primary bg-sidebar-primary text-sidebar-primary-foreground hover:opacity-95'
|
|
159
|
+
: 'border-sidebar-border bg-sidebar text-sidebar-foreground hover:border-sidebar-ring hover:bg-sidebar-accent',
|
|
179
160
|
)}
|
|
180
161
|
aria-label="Changer de vue"
|
|
181
162
|
>
|
|
@@ -183,7 +164,9 @@ export function Sidebar() {
|
|
|
183
164
|
<div
|
|
184
165
|
className={cn(
|
|
185
166
|
'flex h-10 w-10 shrink-0 items-center justify-center rounded-full',
|
|
186
|
-
isViewingAsOther
|
|
167
|
+
isViewingAsOther
|
|
168
|
+
? 'bg-sidebar-primary-foreground/20 text-sidebar-primary-foreground'
|
|
169
|
+
: 'bg-sidebar-accent text-sidebar-accent-foreground',
|
|
187
170
|
)}
|
|
188
171
|
>
|
|
189
172
|
{!isMounted
|
|
@@ -196,7 +179,9 @@ export function Sidebar() {
|
|
|
196
179
|
<p
|
|
197
180
|
className={cn(
|
|
198
181
|
'text-xs font-medium',
|
|
199
|
-
isViewingAsOther
|
|
182
|
+
isViewingAsOther
|
|
183
|
+
? 'text-sidebar-primary-foreground/80'
|
|
184
|
+
: 'text-sidebar-foreground/70',
|
|
200
185
|
)}
|
|
201
186
|
>
|
|
202
187
|
{isViewingAsOther ? 'Vue:' : 'Ma vue'}
|
|
@@ -209,7 +194,7 @@ export function Sidebar() {
|
|
|
209
194
|
: session?.user?.name || 'Utilisateur'}
|
|
210
195
|
</p>
|
|
211
196
|
</div>
|
|
212
|
-
<Eye className="h-5 w-5 shrink-0" />
|
|
197
|
+
<Eye aria-hidden="true" className="h-5 w-5 shrink-0" />
|
|
213
198
|
</div>
|
|
214
199
|
</button>
|
|
215
200
|
) : (
|
|
@@ -218,57 +203,89 @@ export function Sidebar() {
|
|
|
218
203
|
className={cn(
|
|
219
204
|
'w-full cursor-pointer rounded-lg p-2 transition-colors',
|
|
220
205
|
isViewingAsOther
|
|
221
|
-
? 'bg-
|
|
222
|
-
: 'text-
|
|
206
|
+
? 'bg-sidebar-primary text-sidebar-primary-foreground hover:opacity-95'
|
|
207
|
+
: 'text-sidebar-foreground/70 hover:bg-sidebar-accent',
|
|
223
208
|
)}
|
|
224
209
|
title="Changer de vue"
|
|
225
210
|
aria-label="Changer de vue"
|
|
226
211
|
>
|
|
227
212
|
<div className="flex items-center justify-center">
|
|
228
|
-
<Eye className="h-5 w-5" />
|
|
213
|
+
<Eye aria-hidden="true" className="h-5 w-5" />
|
|
229
214
|
</div>
|
|
230
215
|
</button>
|
|
231
216
|
)}
|
|
232
217
|
</div>
|
|
233
218
|
)}
|
|
234
219
|
|
|
220
|
+
{/* Bouton Réduire / Développer la navigation (desktop uniquement) */}
|
|
221
|
+
<div
|
|
222
|
+
className={cn(
|
|
223
|
+
'border-sidebar-border hidden border-t lg:block',
|
|
224
|
+
!isSidebarExpanded ? 'p-3 lg:p-2' : 'p-3',
|
|
225
|
+
)}
|
|
226
|
+
>
|
|
227
|
+
<button
|
|
228
|
+
onClick={togglePin}
|
|
229
|
+
className={cn(
|
|
230
|
+
'text-sidebar-foreground/70 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground flex w-full cursor-pointer items-center gap-3 rounded-lg py-2 text-sm font-medium transition-colors duration-200',
|
|
231
|
+
!isSidebarExpanded ? 'justify-center px-2' : 'px-3',
|
|
232
|
+
)}
|
|
233
|
+
title={isPinned ? 'Réduire la navigation' : 'Développer la navigation'}
|
|
234
|
+
aria-label={isPinned ? 'Réduire la navigation' : 'Développer la navigation'}
|
|
235
|
+
>
|
|
236
|
+
{isPinned ? (
|
|
237
|
+
<>
|
|
238
|
+
<PanelLeftClose aria-hidden="true" className="h-5 w-5 shrink-0" />
|
|
239
|
+
<span className="whitespace-nowrap">Réduire la navigation</span>
|
|
240
|
+
</>
|
|
241
|
+
) : (
|
|
242
|
+
<div className="flex gap-2">
|
|
243
|
+
<PanelLeftOpen aria-hidden="true" className="h-5 w-5 shrink-0" />
|
|
244
|
+
<span className="hidden whitespace-nowrap group-hover:block">
|
|
245
|
+
Développer la navigation
|
|
246
|
+
</span>
|
|
247
|
+
</div>
|
|
248
|
+
)}
|
|
249
|
+
</button>
|
|
250
|
+
</div>
|
|
251
|
+
|
|
235
252
|
{/* User Profile */}
|
|
236
253
|
<div
|
|
237
254
|
className={cn(
|
|
238
|
-
'border-
|
|
239
|
-
|
|
255
|
+
'border-sidebar-border border-t transition-[padding] duration-300',
|
|
256
|
+
!isSidebarExpanded ? 'p-4 lg:p-2' : 'p-4',
|
|
240
257
|
)}
|
|
241
258
|
>
|
|
242
|
-
{
|
|
259
|
+
{isSidebarExpanded ? (
|
|
243
260
|
<>
|
|
244
261
|
<div className="flex items-center gap-3">
|
|
245
|
-
<div className="flex h-10 w-10 shrink-0 items-center justify-center rounded-full
|
|
262
|
+
<div className="bg-sidebar-accent text-sidebar-accent-foreground flex h-10 w-10 shrink-0 items-center justify-center rounded-full">
|
|
246
263
|
{!isMounted ? 'U' : session?.user?.name?.[0]?.toUpperCase() || 'U'}
|
|
247
264
|
</div>
|
|
248
265
|
<div className="min-w-0 flex-1">
|
|
249
|
-
<p className="truncate text-sm font-medium
|
|
266
|
+
<p className="text-sidebar-foreground truncate text-sm font-medium">
|
|
250
267
|
{!isMounted ? 'Utilisateur' : session?.user?.name || 'Utilisateur'}
|
|
251
268
|
</p>
|
|
252
|
-
<p className="truncate text-xs
|
|
269
|
+
<p className="text-sidebar-foreground/70 truncate text-xs">
|
|
253
270
|
{!isMounted ? '' : session?.user?.email}
|
|
254
271
|
</p>
|
|
255
272
|
</div>
|
|
256
273
|
</div>
|
|
257
274
|
<button
|
|
258
275
|
onClick={handleSignOut}
|
|
259
|
-
className="mt-3 w-full cursor-pointer rounded-lg
|
|
276
|
+
className="bg-sidebar-accent text-sidebar-accent-foreground hover:bg-sidebar-primary hover:text-sidebar-primary-foreground mt-3 w-full cursor-pointer rounded-lg px-3 py-2 text-sm font-medium transition-colors duration-200"
|
|
260
277
|
>
|
|
261
278
|
Déconnexion
|
|
262
279
|
</button>
|
|
263
280
|
</>
|
|
264
281
|
) : (
|
|
265
282
|
<div className="flex flex-col items-center gap-2">
|
|
266
|
-
<div className="flex h-10 w-10 shrink-0 items-center justify-center rounded-full
|
|
283
|
+
<div className="bg-sidebar-accent text-sidebar-accent-foreground flex h-10 w-10 shrink-0 items-center justify-center rounded-full">
|
|
267
284
|
{!isMounted ? 'U' : session?.user?.name?.[0]?.toUpperCase() || 'U'}
|
|
268
285
|
</div>
|
|
269
286
|
<button
|
|
270
287
|
onClick={handleSignOut}
|
|
271
|
-
className="cursor-pointer rounded-lg p-2
|
|
288
|
+
className="text-sidebar-foreground/70 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground cursor-pointer rounded-lg p-2 transition-colors duration-200"
|
|
272
289
|
title="Déconnexion"
|
|
273
290
|
aria-label="Déconnexion"
|
|
274
291
|
>
|