diff --git a/FIX_2FA_INPUT_SIZE.md b/FIX_2FA_INPUT_SIZE.md
new file mode 100644
index 0000000..1e2f0ae
--- /dev/null
+++ b/FIX_2FA_INPUT_SIZE.md
@@ -0,0 +1,67 @@
+# Correction : Encadrés 2FA trop grands sur la page de connexion
+
+## đ ProblĂšme
+
+Sur la page de connexion (`/signin`), lors de la saisie du code 2FA (authentification à deux facteurs), les encadrés pour les 6 chiffres étaient beaucoup trop grands par rapport aux encadrés utilisés pour le code OTP par email.
+
+## đ Cause
+
+Les inputs du 2FA utilisaient la classe CSS `flex-1` qui les rendait extensibles pour remplir tout l'espace disponible, combiné avec `justify-between` au lieu de `justify-center`.
+
+**Code problématique** :
+```tsx
+
+
+
+```
+
+## â
Solution
+
+Alignement du style des inputs 2FA sur celui des inputs OTP en utilisant :
+- Des largeurs fixes (`w-12 sm:w-14` + style inline `width: 3rem`)
+- `justify-center` au lieu de `justify-between`
+- Les mĂȘmes classes de style pour une apparence cohĂ©rente
+
+### Changements apportés
+
+**Fichier** : `/app/signin/page.tsx`
+
+#### Avant :
+```tsx
+
+
+
+```
+
+#### AprĂšs :
+```tsx
+
+
+
+```
+
+## đŻ AmĂ©liorations
+
+- â
Encadrés 2FA de taille fixe (3rem / ~48px)
+- â
Cohérence visuelle entre OTP et 2FA
+- â
CentrĂ©s sur la page au lieu d'ĂȘtre Ă©tirĂ©s
+- â
MĂȘme espacement et style que les inputs OTP
+- â
Meilleure lisibilité et UX
+
+## đž DiffĂ©rences visuelles
+
+### Avant
+- Inputs 2FA : Largeur flexible (trop large)
+- Distribution : `justify-between` (étalés sur toute la largeur)
+
+### AprĂšs
+- Inputs 2FA : Largeur fixe de 3rem chacun
+- Distribution : `justify-center` (centrés et groupés)
+- Style identique aux inputs OTP pour cohérence
diff --git a/FIX_PASSWORD_DECONNEXION.md b/FIX_PASSWORD_DECONNEXION.md
new file mode 100644
index 0000000..500e298
--- /dev/null
+++ b/FIX_PASSWORD_DECONNEXION.md
@@ -0,0 +1,68 @@
+# Correction : Déconnexion automatique lors de la création d'un mot de passe
+
+## đ ProblĂšme
+
+Lorsqu'un utilisateur créait ou mettait à jour son mot de passe via la page **Compte > Sécurité**, il était automatiquement déconnecté de son compte.
+
+## đ Cause
+
+L'API `/api/auth/password-update` utilisait la méthode `admin.auth.admin.updateUserById()` de Supabase (Admin API) pour modifier le mot de passe.
+
+**Comportement de Supabase** : Par défaut, pour des raisons de sécurité, l'Admin API **invalide automatiquement toutes les sessions actives** d'un utilisateur lorsqu'on modifie son mot de passe. Ce comportement assume qu'un changement de mot de passe doit forcer une reconnexion.
+
+## â
Solution
+
+Remplacement de l'Admin API par la méthode `supabase.auth.updateUser()` qui permet de mettre à jour le mot de passe **sans invalider la session active**.
+
+### Changements apportés
+
+**Fichier** : `/app/api/auth/password-update/route.ts`
+
+#### Avant :
+```typescript
+// Utilisation de l'Admin API (invalide la session)
+const admin = createClient(url, serviceKey);
+const { error: updErr } = await admin.auth.admin.updateUserById(userId, {
+ password: newPassword,
+ user_metadata: {
+ ...session.user.user_metadata,
+ hasPassword: true
+ }
+});
+```
+
+#### AprĂšs :
+```typescript
+// Utilisation de updateUser() (préserve la session)
+const { error: updErr } = await supabase.auth.updateUser({
+ password: newPassword,
+ data: {
+ ...session.user.user_metadata,
+ hasPassword: true
+ }
+});
+```
+
+## đŻ RĂ©sultat
+
+- â
L'utilisateur peut crĂ©er/modifier son mot de passe sans ĂȘtre dĂ©connectĂ©
+- â
La session reste active aprĂšs la mise Ă jour
+- â
L'email de confirmation est toujours envoyé
+- â
Toutes les validations de sécurité du mot de passe sont conservées
+
+## đ Notes techniques
+
+- **`updateUser()`** : Met à jour les informations de l'utilisateur authentifié via sa session active
+- **`admin.updateUserById()`** : Met à jour un utilisateur via l'Admin API (invalide toutes les sessions pour sécurité)
+
+La méthode `updateUser()` est appropriée ici car :
+1. L'utilisateur est authentifié et modifie son propre mot de passe
+2. Il n'y a pas de raison de le déconnecter immédiatement
+3. C'est une action volontaire de l'utilisateur (pas une récupération de mot de passe compromise)
+
+## đ SĂ©curitĂ©
+
+Le changement de mot de passe reste sécurisé :
+- Validation stricte du mot de passe (12+ caractÚres, majuscules, minuscules, chiffres, caractÚres spéciaux)
+- Email de confirmation envoyé
+- L'utilisateur doit ĂȘtre authentifiĂ© pour accĂ©der Ă cette API
diff --git a/app/(app)/simulateur/page.tsx b/app/(app)/simulateur/page.tsx
new file mode 100644
index 0000000..f84a0e2
--- /dev/null
+++ b/app/(app)/simulateur/page.tsx
@@ -0,0 +1,118 @@
+"use client";
+
+import React from 'react';
+import { usePageTitle } from '@/hooks/usePageTitle';
+import { Calculator } from 'lucide-react';
+
+export default function SimulateurPage() {
+ usePageTitle("Simulateur de paie");
+
+ return (
+
+
+
+ {/* En-tĂȘte */}
+
+
+
+
Simulateur de paie intermittent
+
+
+ Calculez le coût de recrutement d'un intermittent du spectacle (CDDU)
+
+
+
+ {/* Layout 2 colonnes : simulateur Ă gauche, cards info Ă droite */}
+
+
+ {/* Colonne principale : Simulateur en iframe */}
+
+
+
+
+ {/* Colonne droite : Cards d'information modernes */}
+
+
+
+ );
+}
diff --git a/app/api/auth/password-update/route.ts b/app/api/auth/password-update/route.ts
index ad1fdae..6a800f4 100644
--- a/app/api/auth/password-update/route.ts
+++ b/app/api/auth/password-update/route.ts
@@ -1,7 +1,6 @@
import { NextResponse } from "next/server";
import { cookies } from "next/headers";
import { createRouteHandlerClient } from "@supabase/auth-helpers-nextjs";
-import { createClient } from "@supabase/supabase-js";
import { sendPasswordChangedEmail } from "@/lib/emailMigrationHelpers";
export async function POST(req: Request) {
@@ -45,19 +44,11 @@ export async function POST(req: Request) {
return NextResponse.json({ error: "Non authentifié" }, { status: 401 });
}
- const url = process.env.SUPABASE_URL!;
- const serviceKey = process.env.SUPABASE_SERVICE_ROLE_KEY!;
- if (!url || !serviceKey) {
- return NextResponse.json({ error: "Configuration Supabase manquante" }, { status: 500 });
- }
-
- const admin = createClient(url, serviceKey);
- const userId = session.user.id;
-
- // Mettre Ă jour le mot de passe via l'Admin API
- const { error: updErr } = await admin.auth.admin.updateUserById(userId, {
+ // Mettre à jour le mot de passe via updateUser() qui préserve la session active
+ // Note: Cette méthode n'invalide PAS la session actuelle contrairement à l'Admin API
+ const { error: updErr } = await supabase.auth.updateUser({
password: newPassword,
- user_metadata: {
+ data: {
...session.user.user_metadata,
hasPassword: true
}
diff --git a/components/Sidebar.tsx b/components/Sidebar.tsx
index a8b4eac..edeecda 100644
--- a/components/Sidebar.tsx
+++ b/components/Sidebar.tsx
@@ -388,7 +388,7 @@ export default function Sidebar({ clientInfo, isStaff = false, mobile = false, o
{/* Menu Staff */}
diff --git a/lib/emailMigrationHelpers.ts b/lib/emailMigrationHelpers.ts
index bd00c51..e0a3791 100644
--- a/lib/emailMigrationHelpers.ts
+++ b/lib/emailMigrationHelpers.ts
@@ -410,8 +410,8 @@ export async function sendPasswordChangedEmail(
userEmail: toEmail,
status: 'Modifié',
eventDate: data.eventDate || new Date().toLocaleString('fr-FR'),
- platform: data.platform || 'Odentas Paie',
- ctaUrl: `${process.env.NEXT_PUBLIC_BASE_URL || 'https://paie.odentas.fr'}/compte/securite`,
+ platform: data.platform || 'Espace Paie Odentas',
+ ctaUrl: 'https://paie.odentas.fr',
};
await sendUniversalEmailV2({
diff --git a/lib/emailTemplateService.ts b/lib/emailTemplateService.ts
index a0d746b..bf8eb94 100644
--- a/lib/emailTemplateService.ts
+++ b/lib/emailTemplateService.ts
@@ -178,7 +178,7 @@ const EMAIL_TEMPLATES_V2: Record = {
greeting: '{{#if firstName}}Bonjour {{firstName}},{{/if}}',
mainMessage: 'Votre mot de passe a été modifié avec succÚs.',
closingMessage: 'Si vous nâĂȘtes pas Ă lâorigine de cette modification, contactez le support immĂ©diatement.',
- ctaText: 'Gérer ma sécurité',
+ ctaText: 'AccĂšs Ă l\'Espace Paie',
footerText: 'Vous recevez cet e-mail pour confirmer une modification de mot de passe.',
preheaderText: 'Mot de passe modifié · Vérifiez la sécurité de votre compte',
colors: {
diff --git a/public/simulateur-embed.html b/public/simulateur-embed.html
new file mode 100644
index 0000000..a25279a
--- /dev/null
+++ b/public/simulateur-embed.html
@@ -0,0 +1,1374 @@
+
+
+
+
+
+Simulateur Paie
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Veuillez sélectionner les jours de travail.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Résultat de la simulation
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/simulateur.html b/simulateur.html
new file mode 100644
index 0000000..e5d258b
--- /dev/null
+++ b/simulateur.html
@@ -0,0 +1,1255 @@
+
+
+
+
+
+
+Simulateur paie Artiste
CDDU Intermittent du Spectacle (Annexe 10)
+Ce simulateur n'est pas adapté aux contrats des professions de l'Annexe 8 (techniciens du spectacle).
Reportez-vous au simulateur Technicien si besoin.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Veuillez sélectionner les jours de travail.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Résultat de la simulation
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file