account settings update

This commit is contained in:
maximus
2026-07-23 14:21:29 +02:00
parent 407f2b317a
commit b7cb2f4a83
3 changed files with 125 additions and 8 deletions
+51 -3
View File
@@ -1,4 +1,27 @@
import React from 'react'; import React, { useEffect, useState } from 'react';
import { pb } from '../config/pocketbase';
interface User {
id: string;
email: string;
emailVisibility: boolean;
verified: boolean;
name: string;
role: string;
company: string;
mfa_enabled: boolean;
created: string;
updated: string
}
interface Company {
id: string;
name: string;
no: string;
vip_level: string;
created: string;
updated: string
}
// Définition stricte des propriétés attendues par le Layout // Définition stricte des propriétés attendues par le Layout
interface DashboardLayoutProps { interface DashboardLayoutProps {
@@ -9,6 +32,27 @@ interface DashboardLayoutProps {
} }
export default function DashboardLayout({ children, activeView, onNavigate, onLogout }: DashboardLayoutProps) { export default function DashboardLayout({ children, activeView, onNavigate, onLogout }: DashboardLayoutProps) {
const [user, setUser] = useState<User | null>(null);
const [company, setCompany] = useState<Company | null>(null);
const [isLoading, setIsLoading] = useState(true);
const fetchInformations = async () => {
setIsLoading(true);
try {
const userRecords = await pb.collection('aegis_users').getFullList<User>();
setUser(userRecords[0]);
const companyRecords = await pb.collection('aegis_companies').getFullList<Company>();
setCompany(companyRecords[0])
} catch (error) {
console.error("Erreur lors de la récupération des infos utilisateur :", error);
} finally {
setIsLoading(false);
}
};
useEffect(()=>{
fetchInformations();
},[]);
const navItems = [ const navItems = [
{ id: 'dashboard', label: 'Tableau de bord', icon: ( { id: 'dashboard', label: 'Tableau de bord', icon: (
@@ -66,10 +110,14 @@ export default function DashboardLayout({ children, activeView, onNavigate, onLo
}`} }`}
> >
<div className="w-8 h-8 rounded-full bg-slate-200 flex items-center justify-center text-slate-600 font-bold text-sm shrink-0"> <div className="w-8 h-8 rounded-full bg-slate-200 flex items-center justify-center text-slate-600 font-bold text-sm shrink-0">
DC {isLoading? "":user?.name.split(" ").map((n)=>n[0]).join("")}
</div> </div>
<div className="ml-3 overflow-hidden"> <div className="ml-3 overflow-hidden">
<p className="text-sm font-medium text-slate-900 truncate">Direction Client</p> {isLoading?
<p className="text-sm font-medium text-slate-200 bg-slate-200 rounded ">*</p>
:
<p className="text-sm font-medium text-slate-900 truncate">{user?.name}</p>
}
<p className="text-xs text-slate-500 truncate">Paramètres du compte</p> <p className="text-xs text-slate-500 truncate">Paramètres du compte</p>
</div> </div>
</button> </button>
+73 -5
View File
@@ -1,7 +1,62 @@
import { useState, useEffect } from 'react'; import { useState, useEffect } from 'react';
import { pb } from '../../config/pocketbase'; import { pb } from '../../config/pocketbase';
interface User {
id: string;
email: string;
emailVisibility: boolean;
verified: boolean;
name: string;
role: string;
company: string;
mfa_enabled: boolean;
created: string;
updated: string
}
interface Company {
id: string;
name: string;
no: string;
vip_level: string;
created: string;
updated: string
}
function switchVip(vip_level:string | undefined){
switch (vip_level?.toLowerCase()) {
case "platinum":
return <span className="px-2 py-1 bg-amber-600 text-white text-xs font-bold rounded shadow-sm mr-2 tracking-wider">{vip_level?.toUpperCase()}</span>;
case "premium":
return <span className="px-2 py-1 bg-violet-600 text-white text-xs font-bold rounded shadow-sm mr-2 tracking-wider">{vip_level?.toUpperCase()}</span>;
default:
return <span className="px-2 py-1 bg-blue-600 text-white text-xs font-bold rounded shadow-sm mr-2 tracking-wider">{vip_level?.toUpperCase()}</span>;
}
}
export default function AccountSettings() { export default function AccountSettings() {
const [user, setUser] = useState<User | null>(null);
const [company, setCompany] = useState<Company | null>(null);
const [isLoading, setIsLoading] = useState(true);
const fetchInformations = async () => {
setIsLoading(true);
try {
const userRecords = await pb.collection('aegis_users').getFullList<User>();
setUser(userRecords[0]);
const companyRecords = await pb.collection('aegis_companies').getFullList<Company>();
setCompany(companyRecords[0])
} catch (error) {
console.error("Erreur lors de la récupération des infos utilisateur :", error);
} finally {
setIsLoading(false);
}
};
useEffect(()=>{
fetchInformations();
},[]);
return ( return (
<div className="min-h-screen bg-slate-50 font-sans text-slate-900 selection:bg-blue-900 selection:text-white"> <div className="min-h-screen bg-slate-50 font-sans text-slate-900 selection:bg-blue-900 selection:text-white">
@@ -17,6 +72,10 @@ export default function AccountSettings() {
{/* Contenu Principal */} {/* Contenu Principal */}
<main className="max-w-7xl mx-auto px-8 py-8 space-y-8"> <main className="max-w-7xl mx-auto px-8 py-8 space-y-8">
{isLoading?
<div className="flex-1 flex justify-center items-center py-8">
<div className="animate-spin rounded-full h-6 w-6 border-b-2 border-slate-900"></div>
</div>:
<div className="grid grid-cols-1 lg:grid-cols-2 gap-8"> <div className="grid grid-cols-1 lg:grid-cols-2 gap-8">
@@ -35,10 +94,16 @@ export default function AccountSettings() {
<p className="text-sm font-medium text-slate-900">Authentification à double facteur (MFA)</p> <p className="text-sm font-medium text-slate-900">Authentification à double facteur (MFA)</p>
<p className="text-xs text-slate-500 mt-1">Exigée par les politiques de sécurité GISE</p> <p className="text-xs text-slate-500 mt-1">Exigée par les politiques de sécurité GISE</p>
</div> </div>
{user?.mfa_enabled?
<span className="inline-flex items-center px-2.5 py-1 rounded-full text-xs font-semibold bg-emerald-50 text-emerald-700 border border-emerald-200"> <span className="inline-flex items-center px-2.5 py-1 rounded-full text-xs font-semibold bg-emerald-50 text-emerald-700 border border-emerald-200">
<span className="w-1.5 h-1.5 rounded-full bg-emerald-500 mr-1.5"></span> <span className="w-1.5 h-1.5 rounded-full bg-emerald-500 mr-1.5"></span>
Actif Actif
</span>:
<span className="inline-flex items-center px-2.5 py-1 rounded-full text-xs font-semibold bg-red-50 text-red-700 border border-red-200">
<span className="w-1.5 h-1.5 rounded-full bg-red-500 mr-1.5"></span>
Inactif
</span> </span>
}
</div> </div>
<div className="pt-4 border-t border-slate-100"> <div className="pt-4 border-t border-slate-100">
@@ -46,7 +111,6 @@ export default function AccountSettings() {
Générer de nouveaux codes de secours Générer de nouveaux codes de secours
</button> </button>
</div> </div>
{/* Mot de passe */} {/* Mot de passe */}
<div className="pt-4 border-t border-slate-100"> <div className="pt-4 border-t border-slate-100">
<p className="text-sm font-medium text-slate-900 mb-2">Mot de passe institutionnel</p> <p className="text-sm font-medium text-slate-900 mb-2">Mot de passe institutionnel</p>
@@ -70,16 +134,20 @@ export default function AccountSettings() {
<dl className="space-y-4 text-sm"> <dl className="space-y-4 text-sm">
<div> <div>
<dt className="text-slate-500 font-medium">Entité Légale</dt> <dt className="text-slate-500 font-medium">Entité Légale</dt>
<dd className="mt-1 font-semibold text-slate-900">Cabinet Juridique Example & Associés</dd> <dd className="mt-1 font-semibold text-slate-900">{company?.name}</dd>
</div> </div>
<div> <div>
<dt className="text-slate-500 font-medium">Administrateur du compte</dt> <dt className="text-slate-500 font-medium">Administrateur du compte</dt>
<dd className="mt-1 text-slate-900">Direction Générale (direction@example.com)</dd> <dd className="mt-1 text-slate-900">
<span className="px-2 py-1 bg-blue-900 text-white text-xs font-bold rounded shadow-sm mr-2 tracking-wider">{user?.role}</span>
<span className="text-slate-700 font-medium">{user?.name}</span>
</dd>
<dd className="mt-1 text-slate-900">{!user?.emailVisibility? user?.email : ""}</dd>
</div> </div>
<div> <div>
<dt className="text-slate-500 font-medium">Niveau d'Infogérance (SLA)</dt> <dt className="text-slate-500 font-medium">Niveau d'Infogérance (SLA)</dt>
<dd className="mt-1 flex items-center"> <dd className="mt-1 flex items-center">
<span className="px-2 py-1 bg-blue-900 text-white text-xs font-bold rounded shadow-sm mr-2 tracking-wider">VIP PLATINUM</span> {switchVip(company?.vip_level)}
<span className="text-slate-700 font-medium">Couverture 24/7 (99.99%)</span> <span className="text-slate-700 font-medium">Couverture 24/7 (99.99%)</span>
</dd> </dd>
</div> </div>
@@ -87,7 +155,7 @@ export default function AccountSettings() {
</section> </section>
</div> </div>
</div> </div>}
</main> </main>
</div> </div>
+1
View File
@@ -39,6 +39,7 @@ export default function TicketDetail({ ticketId, onBack }: TicketDetailProps) {
// Récupération du ticket et de ses messages associés // Récupération du ticket et de ses messages associés
const fetchTicketData = async () => { const fetchTicketData = async () => {
setIsLoading(true);
try { try {
const ticketData = await pb.collection('aegis_tickets').getOne<Ticket>(ticketId); const ticketData = await pb.collection('aegis_tickets').getOne<Ticket>(ticketId);
setTicket(ticketData); setTicket(ticketData);