veza/apps/web/dist_verification/assets/AdminDashboardPage-DO0rPMOR.js

1 line
20 KiB
JavaScript

import{a as o,j as e}from"./vendor-react-BHG7lGYR.js";import{a as h,B as y,C as n,b as l,c,e as d,v as m,i as P,N as ue,l as p,g as he,p as g,L as je}from"./index-BWcMVITa.js";import{I as fe}from"./input-BGBI2Wze.js";import{B as u}from"./badge-CPAgRIoX.js";import{T as pe,a as ge,b as v,c as N}from"./tabs-DP-eavm_.js";import{q as M}from"./vendor-IYr-MHu4.js";import{P as ve}from"./Pagination-i598iEQZ.js";import{a9 as O,aa as R,f as I,b1 as U,af as J,a as V,b0 as Ne,g as K,_ as ye,F as be,b2 as G,n as we}from"./vendor-icons-DaGlTw4_.js";import{u as Se}from"./vendor-router-D-s5vIeO.js";import{f as H,d as Q}from"./vendor-utils-CgOSfOkx.js";import"./vendor-tanstack-BzWBL1hV.js";async function Te(t){try{return(await h.get("/audit/logs",{params:t})).data}catch(i){throw i instanceof M&&i.response?.status===403?new Error("Forbidden: You do not have admin permissions to access audit logs"):i}}async function Re(t){try{return(await h.get("/audit/stats",{params:t})).data}catch(i){throw i instanceof M&&i.response?.status===403?new Error("Forbidden: You do not have admin permissions to access audit stats"):i}}async function Ae(t){try{return(await h.get("/audit/suspicious",{params:t})).data}catch(i){throw i instanceof M&&i.response?.status===403?new Error("Forbidden: You do not have admin permissions to detect suspicious activity"):i}}function Ce(){const[t,i]=o.useState(null),[j,b]=o.useState(new Date),x=()=>{try{const a=ue.getMetrics();i({validation:{total:a.totalValidations,successful:a.successfulValidations,failed:a.failedValidations,failureRate:a.failureRate,lastFailureTime:a.lastFailureTime,lastSuccessTime:a.lastSuccessTime,failuresByEndpoint:a.failuresByEndpoint},sentry:{enabled:!!P.SENTRY_DSN&&!0,dsnConfigured:!!P.SENTRY_DSN}}),b(new Date)}catch(a){p.error("[MonitoringDashboard] Failed to load metrics",{error:a instanceof Error?a.message:String(a)})}};if(o.useEffect(()=>{x();const a=setInterval(x,3e4);return()=>clearInterval(a)},[]),!t)return e.jsx("div",{className:"flex items-center justify-center h-[400px]",children:e.jsxs("div",{className:"text-center",children:[e.jsx(O,{className:"h-8 w-8 animate-spin mx-auto mb-4 text-muted-foreground"}),e.jsx("p",{className:"text-muted-foreground",children:"Chargement des métriques..."})]})});const A=a=>a===0?"text-green-600":a<1?"text-yellow-600":a<5?"text-orange-600":"text-red-600",w=a=>a===0?"success":a<1?"default":a<5?"warning":"error",S=Object.entries(t.validation.failuresByEndpoint).sort(([,a],[,f])=>f-a).slice(0,5);return e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsxs("h2",{className:"text-2xl font-bold flex items-center gap-2",children:[e.jsx(R,{className:"h-6 w-6"}),"Monitoring du Système"]}),e.jsx("p",{className:"text-muted-foreground text-sm mt-1",children:"Métriques de validation, performance API et suivi des erreurs"})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs("p",{className:"text-xs text-muted-foreground",children:["Dernière mise à jour: ",j.toLocaleTimeString("fr-FR")]}),e.jsxs(y,{variant:"outline",size:"sm",onClick:x,className:"gap-2",children:[e.jsx(O,{className:"h-4 w-4"}),"Actualiser"]})]})]}),e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4",children:[e.jsxs(n,{children:[e.jsx(l,{className:"pb-3",children:e.jsxs(c,{className:"text-sm font-medium flex items-center gap-2",children:[e.jsx(R,{className:"h-4 w-4"}),"Total Validations"]})}),e.jsxs(d,{children:[e.jsx("div",{className:"text-2xl font-bold",children:t.validation.total.toLocaleString()}),e.jsx("p",{className:"text-xs text-muted-foreground mt-1",children:"Validations depuis le démarrage"})]})]}),e.jsxs(n,{children:[e.jsx(l,{className:"pb-3",children:e.jsxs(c,{className:"text-sm font-medium flex items-center gap-2",children:[e.jsx(I,{className:"h-4 w-4 text-green-600"}),"Validations Réussies"]})}),e.jsxs(d,{children:[e.jsx("div",{className:"text-2xl font-bold text-green-600",children:t.validation.successful.toLocaleString()}),e.jsxs("p",{className:"text-xs text-muted-foreground mt-1",children:[t.validation.total>0?(t.validation.successful/t.validation.total*100).toFixed(1):0,"% de réussite"]})]})]}),e.jsxs(n,{children:[e.jsx(l,{className:"pb-3",children:e.jsxs(c,{className:"text-sm font-medium flex items-center gap-2",children:[e.jsx(U,{className:"h-4 w-4 text-red-600"}),"Validations Échouées"]})}),e.jsxs(d,{children:[e.jsx("div",{className:"text-2xl font-bold text-red-600",children:t.validation.failed.toLocaleString()}),e.jsxs("p",{className:"text-xs text-muted-foreground mt-1",children:[t.validation.failureRate.toFixed(2),"% d'échec"]})]})]}),e.jsxs(n,{children:[e.jsx(l,{className:"pb-3",children:e.jsxs(c,{className:"text-sm font-medium flex items-center gap-2",children:[e.jsx(J,{className:"h-4 w-4"}),"Taux d'Échec"]})}),e.jsxs(d,{children:[e.jsxs("div",{className:`text-2xl font-bold ${A(t.validation.failureRate)}`,children:[t.validation.failureRate.toFixed(2),"%"]}),e.jsx(u,{variant:w(t.validation.failureRate),className:"mt-2",children:t.validation.failureRate===0?"Parfait":t.validation.failureRate<1?"Bon":t.validation.failureRate<5?"Attention":"Critique"})]})]})]}),e.jsxs("div",{className:"grid grid-cols-1 lg:grid-cols-2 gap-6",children:[e.jsxs(n,{children:[e.jsxs(l,{children:[e.jsxs(c,{className:"flex items-center gap-2",children:[e.jsx(R,{className:"h-5 w-5"}),"Détails des Validations"]}),e.jsx(m,{children:"Statistiques détaillées des validations API"})]}),e.jsxs(d,{className:"space-y-4",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsxs("div",{className:"flex justify-between items-center",children:[e.jsx("span",{className:"text-sm text-muted-foreground",children:"Dernière validation réussie:"}),e.jsx("span",{className:"text-sm font-medium",children:t.validation.lastSuccessTime?new Date(t.validation.lastSuccessTime).toLocaleString("fr-FR"):"Aucune"})]}),e.jsxs("div",{className:"flex justify-between items-center",children:[e.jsx("span",{className:"text-sm text-muted-foreground",children:"Dernière validation échouée:"}),e.jsx("span",{className:"text-sm font-medium text-red-600",children:t.validation.lastFailureTime?new Date(t.validation.lastFailureTime).toLocaleString("fr-FR"):"Aucune"})]})]}),S.length>0&&e.jsxs("div",{className:"mt-4",children:[e.jsx("h4",{className:"text-sm font-medium mb-2",children:"Endpoints avec le plus d'échecs:"}),e.jsx("div",{className:"space-y-1",children:S.map(([a,f])=>e.jsxs("div",{className:"flex justify-between items-center p-2 bg-muted rounded text-sm",children:[e.jsx("code",{className:"text-xs",children:a}),e.jsx(u,{variant:"error",children:f})]},a))})]})]})]}),e.jsxs(n,{children:[e.jsxs(l,{children:[e.jsxs(c,{className:"flex items-center gap-2",children:[e.jsx(V,{className:"h-5 w-5"}),"Suivi des Erreurs"]}),e.jsx(m,{children:"Configuration et statut du suivi des erreurs"})]}),e.jsxs(d,{className:"space-y-4",children:[e.jsxs("div",{className:"space-y-3",children:[e.jsxs("div",{className:"flex items-center justify-between p-3 bg-muted rounded",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[t.sentry.enabled?e.jsx(I,{className:"h-5 w-5 text-green-600"}):e.jsx(U,{className:"h-5 w-5 text-muted-foreground"}),e.jsx("span",{className:"text-sm font-medium",children:"Sentry Error Tracking"})]}),e.jsx(u,{variant:t.sentry.enabled?"success":"secondary",children:t.sentry.enabled?"Actif":"Inactif"})]}),e.jsxs("div",{className:"flex items-center justify-between p-3 bg-muted rounded",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[t.sentry.dsnConfigured?e.jsx(I,{className:"h-5 w-5 text-green-600"}):e.jsx(U,{className:"h-5 w-5 text-muted-foreground"}),e.jsx("span",{className:"text-sm font-medium",children:"DSN Configuré"})]}),e.jsx(u,{variant:t.sentry.dsnConfigured?"success":"secondary",children:t.sentry.dsnConfigured?"Oui":"Non"})]})]}),t.sentry.enabled&&e.jsxs("div",{className:"mt-4 p-3 bg-blue-50 dark:bg-blue-950 rounded border border-blue-200 dark:border-blue-800",children:[e.jsx("p",{className:"text-xs text-blue-900 dark:text-blue-100 mb-2",children:"Les erreurs sont automatiquement envoyées à Sentry pour le suivi et l'analyse."}),e.jsxs(y,{variant:"outline",size:"sm",className:"w-full gap-2",onClick:()=>{const a=P.SENTRY_DSN,f=a?`https://sentry.io/organizations/${a.split("@")[1]?.split("/")[0]}/issues/`:"https://sentry.io";window.open(f,"_blank")},children:[e.jsx(Ne,{className:"h-4 w-4"}),"Ouvrir Sentry Dashboard"]})]}),!t.sentry.enabled&&e.jsx("div",{className:"mt-4 p-3 bg-yellow-50 dark:bg-yellow-950 rounded border border-yellow-200 dark:border-yellow-800",children:e.jsxs("p",{className:"text-xs text-yellow-900 dark:text-yellow-100",children:["Le suivi des erreurs Sentry n'est pas activé. Configurez"," ",e.jsx("code",{className:"bg-yellow-100 dark:bg-yellow-900 px-1 rounded",children:"VITE_SENTRY_DSN"})," ","pour activer le suivi des erreurs en production."]})})]})]})]}),e.jsxs(n,{children:[e.jsxs(l,{children:[e.jsxs(c,{className:"flex items-center gap-2",children:[e.jsx(K,{className:"h-5 w-5"}),"Performance Monitoring"]}),e.jsx(m,{children:"Les métriques de performance sont suivies automatiquement"})]}),e.jsx(d,{children:e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-3 gap-4",children:[e.jsxs("div",{className:"p-3 bg-muted rounded",children:[e.jsx("div",{className:"text-sm font-medium mb-1",children:"Temps de Rendu"}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"Suivi via Sentry Browser Tracing"})]}),e.jsxs("div",{className:"p-3 bg-muted rounded",children:[e.jsx("div",{className:"text-sm font-medium mb-1",children:"Temps de Réponse API"}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"Suivi dans le client API avec détection des requêtes lentes"})]}),e.jsxs("div",{className:"p-3 bg-muted rounded",children:[e.jsx("div",{className:"text-sm font-medium mb-1",children:"Erreurs Réseau"}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"Détection des pannes partielles vs complètes"})]})]})})]})]})}function Be(){const[t,i]=o.useState(!0),[j,b]=o.useState(null),[x,A]=o.useState(null),[w,S]=o.useState([]),[a,f]=o.useState([]),[C,X]=o.useState([]),[W,Z]=o.useState([]),[D,ee]=o.useState(""),[E,se]=o.useState("overview"),[F,te]=o.useState(1),[_,ae]=o.useState(0),T=50,{toast:re}=he(),L=Se();o.useEffect(()=>{ie()},[]);const ie=async()=>{i(!0),b(null);try{await Promise.all([ne(),le(),q(),B(),Y()])}catch(s){const r=g(s);p.error("Failed to load admin dashboard:",{error:r.message}),b(r.message),(r.code===403||r.message.includes("Forbidden"))&&(re({message:"Vous n'avez pas les permissions administrateur",type:"error"}),L("/dashboard"))}finally{i(!1)}},ne=async()=>{try{const[s,r,z]=await Promise.allSettled([h.get("/users",{params:{limit:1}}),h.get("/tracks",{params:{limit:1}}),h.get("/playlists",{params:{limit:1}})]),de=s.status==="fulfilled"&&s.value.data?.pagination?.total||0,oe=r.status==="fulfilled"&&r.value.data?.pagination?.total||0,me=z.status==="fulfilled"&&z.value.data?.pagination?.total||0,xe=(await h.get("/users",{params:{limit:1e3,is_active:!0}})).data?.users?.filter($=>$.last_login_at&&new Date($.last_login_at)>new Date(Date.now()-720*60*60*1e3)).length||0;A({total_users:de,active_users:xe,total_tracks:oe,total_playlists:me})}catch(s){const r=g(s);p.error("Failed to load system stats:",{error:r.message})}},le=async()=>{try{const s=await Re();S(s.stats||[])}catch(s){const r=g(s);p.error("Failed to load audit stats:",{error:r.message})}},q=async()=>{try{const s=await Ae({hours:24});f(s.activities||[])}catch(s){const r=g(s);p.error("Failed to load suspicious activities:",{error:r.message})}},B=async()=>{try{const s=await Te({limit:10});X(s.logs||[])}catch(s){const r=g(s);p.error("Failed to load recent logs:",{error:r.message})}},Y=async()=>{try{const s=await h.get("/users",{params:{page:F,limit:T,search:D||void 0}});Z(s.data?.users||[]),ae(s.data?.pagination?.total||0)}catch(s){const r=g(s);p.error("Failed to load users:",{error:r.message})}};o.useEffect(()=>{E==="users"&&Y()},[D,E,F]);const k=s=>s>=1e6?`${(s/1e6).toFixed(1)}M`:s>=1e3?`${(s/1e3).toFixed(1)}K`:s.toString(),ce=s=>{switch(s){case"admin":return"error";case"creator":return"default";default:return"secondary"}};return t?e.jsx("div",{className:"container mx-auto px-4 py-8",children:e.jsx("div",{className:"flex items-center justify-center h-[400px]",children:e.jsx(je,{})})}):j&&j.includes("Forbidden")?e.jsx("div",{className:"container mx-auto px-4 py-8",children:e.jsxs(n,{children:[e.jsxs(l,{children:[e.jsx(c,{className:"text-destructive",children:"Accès refusé"}),e.jsx(m,{children:"Vous n'avez pas les permissions nécessaires pour accéder à cette page."})]}),e.jsx(d,{children:e.jsx(y,{onClick:()=>L("/dashboard"),children:"Retour au dashboard"})})]})}):e.jsxs("div",{className:"container mx-auto px-4 py-8",children:[e.jsxs("div",{className:"mb-6",children:[e.jsxs("h1",{className:"text-3xl font-bold mb-2 flex items-center gap-2",children:[e.jsx(ye,{className:"h-8 w-8"}),"Dashboard Administrateur"]}),e.jsx("p",{className:"text-muted-foreground",children:"Gestion du système et surveillance des activités"})]}),j&&!j.includes("Forbidden")&&e.jsx(n,{className:"mb-6 border-destructive",children:e.jsxs(l,{children:[e.jsx(c,{className:"text-destructive",children:"Erreur"}),e.jsx(m,{children:j})]})}),e.jsxs(pe,{value:E,onValueChange:se,className:"space-y-4",children:[e.jsxs(ge,{children:[e.jsx(v,{value:"overview",children:"Vue d'ensemble"}),e.jsx(v,{value:"users",children:"Utilisateurs"}),e.jsx(v,{value:"audit",children:"Audit"}),e.jsx(v,{value:"security",children:"Sécurité"}),e.jsx(v,{value:"monitoring",children:"Monitoring"})]}),e.jsxs(N,{value:"overview",className:"space-y-4",children:[x&&e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4",children:[e.jsxs(n,{children:[e.jsxs(l,{className:"flex flex-row items-center justify-between space-y-0 pb-2",children:[e.jsx(c,{className:"text-sm font-medium",children:"Total utilisateurs"}),e.jsx(be,{className:"h-4 w-4 text-muted-foreground"})]}),e.jsxs(d,{children:[e.jsx("div",{className:"text-2xl font-bold",children:k(x.total_users)}),e.jsxs("p",{className:"text-xs text-muted-foreground",children:[x.active_users," actifs (30j)"]})]})]}),e.jsxs(n,{children:[e.jsxs(l,{className:"flex flex-row items-center justify-between space-y-0 pb-2",children:[e.jsx(c,{className:"text-sm font-medium",children:"Total pistes"}),e.jsx(G,{className:"h-4 w-4 text-muted-foreground"})]}),e.jsx(d,{children:e.jsx("div",{className:"text-2xl font-bold",children:k(x.total_tracks)})})]}),e.jsxs(n,{children:[e.jsxs(l,{className:"flex flex-row items-center justify-between space-y-0 pb-2",children:[e.jsx(c,{className:"text-sm font-medium",children:"Total playlists"}),e.jsx(G,{className:"h-4 w-4 text-muted-foreground"})]}),e.jsx(d,{children:e.jsx("div",{className:"text-2xl font-bold",children:k(x.total_playlists)})})]}),e.jsxs(n,{children:[e.jsxs(l,{className:"flex flex-row items-center justify-between space-y-0 pb-2",children:[e.jsx(c,{className:"text-sm font-medium",children:"Activités suspectes"}),e.jsx(V,{className:"h-4 w-4 text-muted-foreground"})]}),e.jsxs(d,{children:[e.jsx("div",{className:"text-2xl font-bold",children:a.length}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"Dernières 24h"})]})]})]}),w.length>0&&e.jsxs(n,{children:[e.jsxs(l,{children:[e.jsxs(c,{className:"flex items-center gap-2",children:[e.jsx(J,{className:"h-5 w-5"}),"Statistiques d'audit"]}),e.jsx(m,{children:"Actions les plus fréquentes"})]}),e.jsx(d,{children:e.jsx("div",{className:"space-y-2",children:w.slice(0,10).map((s,r)=>e.jsxs("div",{className:"flex items-center justify-between p-2 border rounded",children:[e.jsxs("div",{children:[e.jsx("p",{className:"font-medium",children:s.action}),e.jsx("p",{className:"text-sm text-muted-foreground",children:s.resource})]}),e.jsx(u,{variant:"default",children:s.count})]},r))})})]}),C.length>0&&e.jsxs(n,{children:[e.jsxs(l,{children:[e.jsxs(c,{className:"flex items-center gap-2",children:[e.jsx(K,{className:"h-5 w-5"}),"Logs récents"]}),e.jsx(m,{children:"Dernières activités enregistrées"})]}),e.jsx(d,{children:e.jsx("div",{className:"space-y-2",children:C.map(s=>e.jsxs("div",{className:"flex items-center justify-between p-2 border rounded",children:[e.jsxs("div",{className:"flex-1",children:[e.jsx("p",{className:"font-medium",children:s.action}),e.jsxs("p",{className:"text-sm text-muted-foreground",children:[s.resource," •"," ",H(new Date(s.timestamp||s.created_at),{addSuffix:!0,locale:Q})]})]}),e.jsx(u,{variant:"default",children:s.user_id?.slice(0,8)})]},s.id))})})]})]}),e.jsx(N,{value:"users",className:"space-y-4",children:e.jsxs(n,{children:[e.jsxs(l,{children:[e.jsx(c,{children:"Gestion des utilisateurs"}),e.jsx(m,{children:"Liste et gestion des utilisateurs du système"})]}),e.jsxs(d,{children:[e.jsx("div",{className:"mb-4",children:e.jsxs("div",{className:"relative",children:[e.jsx(we,{className:"absolute left-2 top-2.5 h-4 w-4 text-muted-foreground"}),e.jsx(fe,{placeholder:"Rechercher un utilisateur...",value:D,onChange:s=>ee(s.target.value),className:"pl-8"})]})}),e.jsx("div",{className:"space-y-2",children:W.map(s=>e.jsx("div",{className:"flex items-center justify-between p-4 border rounded hover:bg-accent cursor-pointer",onClick:()=>L(`/u/${s.username}`),children:e.jsxs("div",{className:"flex-1",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("p",{className:"font-medium",children:s.username}),e.jsx(u,{variant:ce(s.role),children:s.role}),!s.is_active&&e.jsx(u,{variant:"secondary",children:"Inactif"}),!s.is_verified&&e.jsx(u,{variant:"default",children:"Non vérifié"})]}),e.jsx("p",{className:"text-sm text-muted-foreground",children:s.email}),e.jsxs("p",{className:"text-xs text-muted-foreground",children:["Créé le"," ",new Date(s.created_at).toLocaleDateString("fr-FR")]})]})},s.id))}),_>T&&e.jsx(ve,{currentPage:F,totalPages:Math.ceil(_/T),onPageChange:te,totalItems:_,itemsPerPage:T,showItemsInfo:!0,className:"mt-4"})]})]})}),e.jsx(N,{value:"audit",className:"space-y-4",children:e.jsxs(n,{children:[e.jsxs(l,{children:[e.jsxs(c,{className:"flex items-center gap-2",children:[e.jsx(R,{className:"h-5 w-5"}),"Logs d'audit"]}),e.jsx(m,{children:"Historique complet des activités système"})]}),e.jsxs(d,{children:[e.jsx(y,{onClick:B,variant:"secondary",className:"mb-4",children:"Actualiser"}),e.jsx("div",{className:"space-y-2",children:C.map(s=>e.jsx("div",{className:"p-4 border rounded",children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsx("p",{className:"font-medium",children:s.action}),e.jsxs("p",{className:"text-sm text-muted-foreground",children:[s.resource," • ",s.user_id]}),s.metadata&&e.jsx("p",{className:"text-xs text-muted-foreground mt-1",children:JSON.stringify(s.metadata)})]}),e.jsx("p",{className:"text-xs text-muted-foreground",children:H(new Date(s.timestamp||s.created_at),{addSuffix:!0,locale:Q})})]})},s.id))})]})]})}),e.jsx(N,{value:"security",className:"space-y-4",children:e.jsxs(n,{children:[e.jsxs(l,{children:[e.jsxs(c,{className:"flex items-center gap-2",children:[e.jsx(V,{className:"h-5 w-5"}),"Activités suspectes"]}),e.jsx(m,{children:"Activités détectées comme suspectes dans les dernières 24 heures"})]}),e.jsxs(d,{children:[e.jsx(y,{onClick:q,variant:"secondary",className:"mb-4",children:"Actualiser"}),a.length===0?e.jsx("p",{className:"text-muted-foreground",children:"Aucune activité suspecte détectée"}):e.jsx("div",{className:"space-y-2",children:a.map((s,r)=>e.jsxs("div",{className:"p-4 border border-destructive rounded",children:[e.jsx("p",{className:"font-medium text-destructive",children:s.reason||"Activité suspecte"}),e.jsxs("p",{className:"text-sm text-muted-foreground",children:[s.user_id," • ",s.ip_address]}),e.jsx("p",{className:"text-xs text-muted-foreground mt-1",children:s.description})]},r))})]})]})}),e.jsx(N,{value:"monitoring",className:"space-y-4",children:e.jsx(Ce,{})})]})]})}export{Be as AdminDashboardPage};