chore(dx): add .cursorrules and design system audit documentation

This commit is contained in:
senke 2026-02-05 14:20:06 +01:00
parent 6be3a9653f
commit 2964cec09a
335 changed files with 15443 additions and 2189 deletions

View file

@ -0,0 +1,48 @@
import React from 'react';
import { ThemeProvider } from '../src/components/theme/ThemeProvider';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { MemoryRouter } from 'react-router-dom';
import { ToastProvider } from '../src/components/feedback/ToastProvider';
import { AudioProvider } from '../src/context/AudioContext';
import { AuthProvider } from '../src/context/AuthContext';
// Create a singleton query client for Storybook to share cache if needed,
// or one per story. Since decorators run per story, creating it here might
// share it. Better to create inside if we want isolation, but for performance
// reuse is okay.
const queryClient = new QueryClient({
defaultOptions: {
queries: {
retry: false,
staleTime: Infinity,
// Phase 1: Silence network errors in react-query
throwOnError: false,
},
},
});
interface AppProvidersProps {
children: React.ReactNode;
isDark?: boolean;
}
export const AppProvidersForStorybook: React.FC<AppProvidersProps> = ({ children, isDark = true }) => {
return (
<ThemeProvider defaultTheme={isDark ? 'dark' : 'light'}>
<div className={isDark ? 'dark' : ''} style={{ minHeight: '100vh', padding: '1rem', background: isDark ? '#0a0a0a' : '#ffffff', color: isDark ? '#ffffff' : '#0a0a0a' }}>
<QueryClientProvider client={queryClient}>
<ToastProvider>
<AudioProvider>
<AuthProvider>
<MemoryRouter>
{children}
</MemoryRouter>
</AuthProvider>
</AudioProvider>
</ToastProvider>
</QueryClientProvider>
</div>
</ThemeProvider>
);
};

View file

@ -0,0 +1,48 @@
# Storybook Audit Report
## Summary
- **Total Stories**: 963
- **Failed Stories**: 310 (~32% failure rate)
- **Total Errors**: 1,040 (Network + Console)
## Failure Categories
### 1. Unmocked Network Requests (Critical)
**Count**: 463 Network Failures
**Diagnosis**: Stories are attempting to hit real production endpoints (`api.veza.com`) instead of using mocks.
- `ERR_NAME_NOT_RESOLVED`: `https://api.veza.com/api/v1/api/v1/logs/frontend`
- `ERR_ABORTED`: `https://api.veza.com/api/v1/auth/me`
- `ERR_ABORTED`: `https://picsum.photos/200` (External images)
**Impact**: Components depending on data stay in "Loading" state indefinitely or crash when data is missing.
### 2. Missing Context Providers
**Count**: ~15-20 identified instances (estimated from sample)
**Diagnosis**: Components accessing global state that isn't provided in the story decorator.
- `Error: useAuth must be used within AuthProvider`
- `TypeError: Cannot read properties of undefined (reading 'name')` (Likely missing user object from auth context)
### 3. Runtime Crashes
- `TypeError: Cannot read properties of undefined`: Cascading failures from missing API data.
## Remediation Plan
### Step 1: Configure Mock Service Worker (MSW)
- [ ] Initialize MSW in Storybook.
- [ ] Create `handlers.ts` to mock core endpoints:
- `/auth/me` (User profile)
- `/api/v1/logs/frontend` (Prevent logging noise)
- Domain specific endpoints for failing stories.
### Step 2: Global Decorators
- [ ] Wrap all stories in `preview.tsx` with:
- `AuthProvider` (Mocked)
- `QueryClientProvider` (React Query)
- `MemoryRouter` (already likely present but need verification)
### Step 3: Fix Specific Issues
- [ ] Fix double-path URL bug (`/api/v1/api/v1/...`)
- [ ] Mock external image services or provide local fallbacks.
## Priority
High. 30% of the component library is broken in documentation, making it unreliable for development.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1 +0,0 @@
import{j as e}from"./vendor-react-BHG7lGYR.js";import{L as i}from"./vendor-router-D-s5vIeO.js";import{d as n}from"./index-BWcMVITa.js";function m({title:t,subtitle:r,children:l,footerLinks:o,className:a}){return e.jsxs("div",{className:n("min-h-screen flex items-center justify-center bg-kodo-void py-12 px-4 sm:px-6 lg:px-8 relative overflow-hidden",a),role:"main","aria-label":"Page d'authentification",children:[e.jsxs("div",{className:"absolute inset-0 overflow-hidden pointer-events-none",children:[e.jsx("div",{className:"absolute top-0 right-0 w-96 h-96 bg-kodo-cyan/5 rounded-full blur-3xl"}),e.jsx("div",{className:"absolute bottom-0 left-0 w-96 h-96 bg-kodo-magenta/5 rounded-full blur-3xl"})]}),e.jsxs("div",{className:"max-w-2xl w-full space-y-8 relative z-10 animate-fade-in",children:[e.jsxs("header",{className:"text-center",children:[e.jsxs("div",{className:"flex items-center justify-center mb-6",children:[e.jsx("div",{className:"h-12 w-12 rounded-xl bg-gradient-to-br from-kodo-cyan to-kodo-cyan-dim flex items-center justify-center shadow-glow-cyan","aria-hidden":"true",children:e.jsx("span",{className:"text-kodo-void font-bold text-2xl",children:"V"})}),e.jsx("span",{className:"ml-3 font-bold text-3xl text-white",children:"Veza"})]}),e.jsx("h1",{id:"auth-form-title",className:"text-4xl font-bold text-white mb-2",children:t}),r&&e.jsx("p",{className:"text-sm text-kodo-secondary",role:"doc-subtitle",children:r})]}),e.jsx("section",{className:"glass rounded-2xl border border-white/10 py-8 px-6 sm:px-8 shadow-2xl backdrop-blur-xl w-full","aria-labelledby":"auth-form-title",children:l}),o&&o.length>0&&e.jsx("nav",{className:"text-center space-x-4","aria-label":"Navigation d'authentification",children:o.map(s=>e.jsx(i,{to:s.to,className:"text-sm text-kodo-steel dark:text-kodo-steel hover:text-white dark:hover:text-white transition-colors focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 rounded",children:s.label},s.to))})]})]})}function u({loading:t,variant:r="primary",className:l,children:o,disabled:a,...s}){return e.jsx("button",{className:n("w-full px-4 py-2 rounded-lg font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2",r==="primary"?"bg-kodo-cyan text-white hover:bg-kodo-cyan focus:ring-blue-500 dark:bg-kodo-cyan dark:hover:bg-kodo-cyan":"bg-kodo-slate text-kodo-text-main hover:bg-kodo-slate focus:ring-gray-500 dark:bg-kodo-steel dark:text-kodo-text-main dark:hover:bg-kodo-steel",(a||t)&&"opacity-50 cursor-not-allowed",l),disabled:a||t,"aria-busy":t,"aria-disabled":a||t?"true":"false",...s,children:t?e.jsxs(e.Fragment,{children:[e.jsx("span",{className:"sr-only",children:"Chargement en cours"}),e.jsx("span",{"aria-hidden":"true",children:"Chargement..."})]}):o})}export{m as A,u as a};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1 +0,0 @@
import{j as e}from"./vendor-react-BHG7lGYR.js";import{g as r,B as o}from"./index-BWcMVITa.js";import{K as i,b6 as a,b7 as l}from"./vendor-icons-DaGlTw4_.js";import"./vendor-IYr-MHu4.js";import"./vendor-router-D-s5vIeO.js";import"./vendor-tanstack-BzWBL1hV.js";import"./vendor-utils-CgOSfOkx.js";function u(){const t=r(),s=()=>{t.info("Course browsing feature coming soon")};return e.jsxs("div",{className:"min-h-screen p-8 space-y-8",children:[e.jsx("div",{className:"glass-hud rounded-2xl border-white/10 p-8 hud-corner",children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{className:"flex items-center gap-4",children:[e.jsx("div",{className:"w-12 h-12 rounded-xl bg-kodo-lime/20 flex items-center justify-center border border-kodo-lime/30",children:e.jsx(i,{className:"w-6 h-6 text-kodo-lime"})}),e.jsxs("div",{children:[e.jsx("h1",{className:"text-3xl font-display font-bold text-white",children:"Veza Academy"}),e.jsx("p",{className:"text-sm text-white opacity-80",children:"Learn production, mixing, and more"})]})]}),e.jsx(o,{onClick:s,className:"bg-kodo-lime hover:bg-kodo-lime/80 text-black",children:"Browse Courses"})]})}),e.jsxs("div",{className:"glass-hud rounded-xl border-white/10 p-12 text-center",children:[e.jsx(a,{className:"w-16 h-16 text-kodo-secondary mx-auto mb-4 opacity-50"}),e.jsx("h3",{className:"text-lg font-bold text-white mb-2",children:"Start Learning"}),e.jsx("p",{className:"text-sm text-white opacity-90 mb-4",children:"Explore courses from industry professionals"}),e.jsxs(o,{onClick:s,variant:"outline",className:"border-kodo-lime/30 text-kodo-lime hover:bg-kodo-lime/10",children:[e.jsx(l,{className:"w-4 h-4 mr-2"}),"View Courses"]})]})]})}export{u as EducationPage};

View file

@ -1 +0,0 @@
import{a as n,j as i}from"./vendor-react-BHG7lGYR.js";import{L as h}from"./vendor-router-D-s5vIeO.js";import{A as b,a as g}from"./AuthButton-ByJY1yM3.js";import{u as j,A as y}from"./usePasswordReset-CY5zVo2R.js";import"./vendor-IYr-MHu4.js";import"./index-BWcMVITa.js";import"./vendor-tanstack-BzWBL1hV.js";import"./vendor-utils-CgOSfOkx.js";import"./vendor-icons-DaGlTw4_.js";function B(){const{handleRequestReset:m,loading:d,error:l,success:u}=j(),[t,c]=n.useState({email:""}),[r,o]=n.useState({}),p=()=>{const e={};return t.email?/\S+@\S+\.\S+/.test(t.email)||(e.email="Email invalide"):e.email="Email requis",o(e),Object.keys(e).length===0},x=(e,a)=>{c({...t,[e]:a}),r[e]&&o({...r,[e]:void 0})},v=e=>{const a=t[e];let s;a?/\S+@\S+\.\S+/.test(a)||(s="Email invalide"):s="Email requis",o(s?{...r,[e]:s}:{...r,[e]:void 0})},f=async e=>{e.preventDefault(),p()&&await m(t)};return i.jsx(b,{title:"Mot de passe oublié",subtitle:"Entrez votre email pour recevoir un lien de réinitialisation",footerLinks:[{label:"Retour à la connexion",to:"/login"}],children:u?i.jsxs("div",{className:"text-center space-y-4",role:"status","aria-live":"polite",children:[i.jsxs("div",{className:"bg-kodo-lime/10 border border-kodo-lime text-kodo-lime px-4 py-4 rounded",role:"alert","aria-live":"assertive",children:[i.jsx("p",{className:"font-medium",children:"Email envoyé !"}),i.jsxs("p",{className:"text-sm mt-1",children:["Un lien de réinitialisation a été envoyé à ",t.email]})]}),i.jsx("p",{className:"text-sm text-kodo-content-dim",children:"Veuillez vérifier votre boîte mail et cliquer sur le lien pour réinitialiser votre mot de passe."}),i.jsx(h,{to:"/login",className:"text-kodo-cyan hover:underline text-sm block focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 rounded",children:"Retour à la connexion"})]}):i.jsxs("form",{onSubmit:f,className:"space-y-4","aria-label":"Formulaire de réinitialisation de mot de passe",children:[l&&i.jsx("div",{className:"bg-kodo-red/10 border border-kodo-red text-kodo-red px-4 py-4 rounded",role:"alert","aria-live":"assertive",children:l.message}),i.jsx(y,{type:"email",label:"Email",value:t.email,onChange:e=>x("email",e.target.value),onBlur:()=>v("email"),error:r.email,required:!0,autoComplete:"email"}),i.jsx(g,{type:"submit",loading:d,children:"Envoyer le lien de réinitialisation"})]})})}export{B as ForgotPasswordPage,B as default};

View file

@ -1 +0,0 @@
import{j as e}from"./vendor-react-BHG7lGYR.js";import{g as r,B as t}from"./index-BWcMVITa.js";import{y as a,ah as d,b5 as i}from"./vendor-icons-DaGlTw4_.js";import"./vendor-IYr-MHu4.js";import"./vendor-router-D-s5vIeO.js";import"./vendor-tanstack-BzWBL1hV.js";import"./vendor-utils-CgOSfOkx.js";function p(){const o=r(),s=()=>{o.info("Add gear feature coming soon")};return e.jsxs("div",{className:"min-h-screen p-8 space-y-8",children:[e.jsx("div",{className:"glass-hud rounded-2xl border-white/10 p-8 hud-corner",children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{className:"flex items-center gap-4",children:[e.jsx("div",{className:"w-12 h-12 rounded-xl bg-kodo-steel/20 flex items-center justify-center border border-kodo-steel/30",children:e.jsx(a,{className:"w-6 h-6 text-kodo-steel"})}),e.jsxs("div",{children:[e.jsx("h1",{className:"text-3xl font-display font-bold text-white",children:"Gear Locker"}),e.jsx("p",{className:"text-sm text-white opacity-80",children:"Manage your equipment and instruments"})]})]}),e.jsxs(t,{onClick:s,className:"bg-kodo-cyan hover:bg-kodo-cyan/80 text-black",children:[e.jsx(d,{className:"w-4 h-4 mr-2"}),"Add Gear"]})]})}),e.jsxs("div",{className:"glass-hud rounded-xl border-white/10 p-12 text-center",children:[e.jsx(i,{className:"w-16 h-16 text-kodo-secondary mx-auto mb-4 opacity-50"}),e.jsx("h3",{className:"text-lg font-bold text-white mb-2",children:"No Gear Yet"}),e.jsx("p",{className:"text-sm text-white opacity-90 mb-4",children:"Start adding your equipment to keep track of your studio setup"}),e.jsx(t,{onClick:s,variant:"outline",className:"border-kodo-steel/50 text-kodo-steel hover:bg-white/5",children:"Add Your First Gear"})]})]})}export{p as GearPage};

File diff suppressed because one or more lines are too long

View file

@ -1 +0,0 @@
import{j as e}from"./vendor-react-BHG7lGYR.js";import{g as i,B as o}from"./index-BWcMVITa.js";import{R as a,b3 as n,aO as d}from"./vendor-icons-DaGlTw4_.js";import"./vendor-IYr-MHu4.js";import"./vendor-router-D-s5vIeO.js";import"./vendor-tanstack-BzWBL1hV.js";import"./vendor-utils-CgOSfOkx.js";function v(){const s=i(),t=()=>{s.info("Live streaming feature coming soon")},r=()=>{s.info("Browse live sessions feature coming soon")};return e.jsxs("div",{className:"min-h-screen p-8 space-y-8",children:[e.jsx("div",{className:"glass-hud rounded-2xl border-white/10 p-8 hud-corner",children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{className:"flex items-center gap-4",children:[e.jsx("div",{className:"w-12 h-12 rounded-xl bg-kodo-red/20 flex items-center justify-center border border-kodo-red/30 animate-pulse",children:e.jsx(a,{className:"w-6 h-6 text-kodo-red"})}),e.jsxs("div",{children:[e.jsx("h1",{className:"text-3xl font-display font-bold text-white",children:"Live Sessions"}),e.jsx("p",{className:"text-sm text-kodo-secondary",children:"Stream and collaborate in real-time"})]})]}),e.jsxs(o,{onClick:t,className:"bg-kodo-red hover:bg-kodo-red/80 text-white",children:[e.jsx(n,{className:"w-4 h-4 mr-2"}),"Go Live"]})]})}),e.jsxs("div",{className:"glass-hud rounded-xl border-white/10 p-12 text-center",children:[e.jsx(d,{className:"w-16 h-16 text-kodo-secondary mx-auto mb-4 opacity-50"}),e.jsx("h3",{className:"text-lg font-bold text-white mb-2",children:"No Active Sessions"}),e.jsx("p",{className:"text-kodo-secondary mb-4",children:"Start a live session or join an ongoing stream"}),e.jsx(o,{onClick:r,variant:"outline",className:"border-kodo-red/30 text-kodo-red hover:bg-kodo-red/10",children:"Browse Live Sessions"})]})]})}export{v as LivePage};

View file

@ -1 +0,0 @@
import{a as h,j as e}from"./vendor-react-BHG7lGYR.js";import{u as g,L as E}from"./vendor-router-D-s5vIeO.js";import{G as C}from"./vendor-IYr-MHu4.js";import{t as S,o as L,b as A,s as p}from"./vendor-utils-CgOSfOkx.js";import{h as _,g as F,w as u,B as M,l as D,j as R,A as T,C as V}from"./index-BWcMVITa.js";import{u as q,F as f}from"./useFormValidation-B1Tm3VtD.js";import{C as B}from"./checkbox-DUBsARHw.js";import{aC as z,aA as I}from"./vendor-icons-DaGlTw4_.js";import"./vendor-tanstack-BzWBL1hV.js";const P=L({email:p().email("Email invalide"),password:p().min(1,"Le mot de passe est requis"),remember_me:A().optional()}),G=()=>{const o=g(),{login:t,isLoading:i,error:m}=_(),{toast:b}=F(),{register:d,handleSubmit:w,formState:{errors:k},watch:l,setValue:j}=C({resolver:S(P),defaultValues:{email:"",password:"",remember_me:!1}}),a=l(),{validate:c,errors:v}=q({type:"LoginRequest",debounceMs:300});h.useEffect(()=>{if(a.email||a.password){const s={email:a.email||"",password:a.password||"",remember_me:a.remember_me||!1};c(s)}},[a.email,a.password,a.remember_me,c]);const y=async r=>{try{const s={email:r.email,password:r.password,remember_me:r.remember_me||!1};await t(s),o("/dashboard")}catch(s){const n=u(s);D.error("Login error",{error:s instanceof Error?s.message:String(s),stack:s instanceof Error?s.stack:void 0}),b({title:"Erreur de connexion",description:n,variant:"destructive"})}},x=r=>{const s=k[r]?.message,n=v.find(N=>N.field===r)?.message;return s||n};return e.jsxs("form",{onSubmit:w(y),className:"w-full space-y-8",noValidate:!0,children:[m&&e.jsxs("div",{className:"bg-kodo-red/10 border border-kodo-red/20 text-kodo-red text-sm px-4 py-3 rounded-lg flex items-center gap-2 animate-in fade-in slide-in-from-top-1",role:"alert",children:[e.jsx("span",{className:"w-1.5 h-1.5 rounded-full bg-kodo-red shrink-0"}),e.jsx("span",{children:u(m)})]}),e.jsxs("div",{className:"space-y-4",children:[e.jsx(f,{label:"Email",type:"email",autoComplete:"email",icon:e.jsx(z,{className:"h-4 w-4"}),...d("email"),error:x("email")}),e.jsx(f,{label:"Mot de passe",type:"password",autoComplete:"current-password",icon:e.jsx(I,{className:"h-4 w-4"}),...d("password"),error:x("password")})]}),e.jsx("div",{className:"flex items-center justify-between",children:e.jsx(B,{id:"remember_me",checked:l("remember_me"),onCheckedChange:r=>j("remember_me",r===!0),label:"Se souvenir de moi"})}),e.jsx(M,{type:"submit",disabled:i,variant:"default",size:"lg",className:"w-full bg-gradient-to-r from-kodo-cyan to-kodo-cyan-dim hover:from-kodo-cyan/90 hover:to-kodo-cyan-dim/90 text-kodo-ink font-bold tracking-wide shadow-lg shadow-kodo-cyan/20 rounded-xl",children:i?e.jsxs("span",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"h-4 w-4 border-2 border-current border-t-transparent rounded-full animate-spin"}),"Connexion..."]}):"ACCÉDER AU TERMINAL"})]})},Y=()=>{const{isAuthenticated:o}=R(),t=g();return h.useEffect(()=>{o&&t("/")},[o,t]),e.jsxs("div",{className:"min-h-screen flex items-center justify-center bg-kodo-void relative overflow-hidden",children:[e.jsx(T,{}),e.jsxs("div",{className:"w-full max-w-md mx-auto relative z-10 px-4",children:[e.jsxs("div",{className:"text-center mb-8",children:[e.jsx("div",{className:"w-16 h-16 bg-gradient-to-br from-kodo-cyan to-kodo-magenta rounded-xl mx-auto mb-4 flex items-center justify-center shadow-lg shadow-kodo-cyan/20",children:e.jsx("span",{className:"text-3xl",children:"💠"})}),e.jsx("h1",{className:"text-4xl font-display font-bold text-white mb-2 tracking-wide text-glow",children:"VEZA"}),e.jsx("p",{className:"text-sm text-kodo-text-dim font-mono uppercase tracking-[0.2em]",children:"System v5.0 // Secure Login"})]}),e.jsx(V,{variant:"glass",className:"w-full backdrop-blur-3xl border-white/10 shadow-2xl p-8",children:e.jsx(G,{})}),e.jsx("div",{className:"mt-8 text-center space-y-4",children:e.jsxs("p",{className:"text-xs text-kodo-text-dim",children:["Pas encore de compte ?"," ",e.jsx(E,{to:"/register",className:"font-bold text-kodo-cyan hover:text-kodo-cyan-dim transition-colors uppercase tracking-wider",children:"S'inscrire"})]})})]})]})};export{Y as LoginPage};

File diff suppressed because one or more lines are too long

View file

@ -1 +0,0 @@
import{j as e}from"./vendor-react-BHG7lGYR.js";import{L as a}from"./vendor-router-D-s5vIeO.js";import{C as c,b as d,c as n,v as x,e as m,B as t}from"./index-BWcMVITa.js";import{n as o,H as r,aG as h,ad as u,af as p}from"./vendor-icons-DaGlTw4_.js";import"./vendor-IYr-MHu4.js";import"./vendor-tanstack-BzWBL1hV.js";import"./vendor-utils-CgOSfOkx.js";function C(){const i=[{to:"/dashboard",label:"Dashboard",icon:r},{to:"/library",label:"Ma bibliothèque",icon:u},{to:"/search",label:"Rechercher",icon:o},{to:"/marketplace",label:"Marketplace",icon:p}];return e.jsx("div",{className:"min-h-screen flex items-center justify-center bg-kodo-void dark:bg-kodo-ink p-4",children:e.jsx("div",{className:"w-full max-w-2xl",children:e.jsxs(c,{className:"text-center",children:[e.jsxs(d,{children:[e.jsx("div",{className:"mx-auto mb-4 flex h-16 w-16 items-center justify-center rounded-full bg-kodo-steel/20 dark:bg-kodo-steel",children:e.jsx(o,{className:"h-8 w-8 text-kodo-steel dark:text-kodo-steel"})}),e.jsx(n,{className:"text-2xl",children:"Page non trouvée"}),e.jsx(x,{children:"La page que vous recherchez n'existe pas ou a été déplacée."})]}),e.jsxs(m,{className:"space-y-6",children:[e.jsx("div",{className:"text-6xl font-bold text-kodo-text-main dark:text-kodo-text-main",children:"404"}),e.jsx("p",{className:"text-kodo-content-dim dark:text-kodo-content-dim",children:"Il semble que vous ayez suivi un lien cassé ou tapé une URL incorrecte. Voici quelques options pour continuer :"}),e.jsxs("div",{className:"flex flex-col sm:flex-row gap-2",children:[e.jsx(t,{asChild:!0,className:"flex-1",children:e.jsxs(a,{to:"/dashboard",children:[e.jsx(r,{className:"mr-2 h-4 w-4"}),"Retour au dashboard"]})}),e.jsxs(t,{variant:"outline",onClick:()=>window.history.back(),className:"flex-1",children:[e.jsx(h,{className:"mr-2 h-4 w-4"}),"Page précédente"]})]}),e.jsxs("div",{className:"border-t pt-4",children:[e.jsx("p",{className:"text-sm font-medium text-kodo-text-main dark:text-kodo-text-main mb-3",children:"Liens rapides :"}),e.jsx("div",{className:"grid grid-cols-2 sm:grid-cols-4 gap-2",children:i.map(s=>{const l=s.icon;return e.jsx(t,{variant:"outline",size:"sm",asChild:!0,className:"flex flex-col h-auto py-2",children:e.jsxs(a,{to:s.to,children:[e.jsx(l,{className:"h-4 w-4 mb-1"}),e.jsx("span",{className:"text-xs",children:s.label})]})},s.to)})})]}),e.jsxs("div",{className:"border-t pt-4 text-left",children:[e.jsx("p",{className:"text-sm font-medium text-kodo-text-main dark:text-kodo-text-main mb-2",children:"Suggestions :"}),e.jsxs("ul",{className:"text-sm text-kodo-content-dim dark:text-kodo-content-dim space-y-1 list-disc list-inside",children:[e.jsx("li",{children:"Vérifiez l'orthographe de l'URL"}),e.jsx("li",{children:"Utilisez la recherche pour trouver ce que vous cherchez"}),e.jsx("li",{children:"Consultez votre bibliothèque ou le marketplace"}),e.jsx("li",{children:"Contactez le support si le problème persiste"})]})]})]})]})})})}export{C as default};

File diff suppressed because one or more lines are too long

View file

@ -1 +0,0 @@
import{a as K,j as n}from"./vendor-react-BHG7lGYR.js";import{d as k,B as d}from"./index-BWcMVITa.js";import{u as x,al as C,v as m}from"./vendor-icons-DaGlTw4_.js";function B({currentPage:e,totalPages:s,onPageChange:a,maxVisiblePages:t=5,showFirstLast:c=!1,className:A,totalItems:l,itemsPerPage:u,showItemsInfo:y=!1}){const M=K.useMemo(()=>{if(s<=t)return Array.from({length:s},(p,z)=>z+1);const i=[],h=Math.floor(t/2);let r=Math.max(1,e-h);const f=Math.min(s,r+t-1);f===s&&(r=Math.max(1,s-t+1)),(c&&r>1||r>1)&&(i.push(1),r>2&&i.push("ellipsis-start"));for(let p=r;p<=f;p++)i.push(p);return f<s&&(f<s-1&&i.push("ellipsis-end"),i.push(s)),i},[e,s,t,c]),v=()=>{e>1&&a(e-1)},j=()=>{e<s&&a(e+1)},N=()=>{a(1)},w=()=>{a(s)},o=(i,h,r)=>{if(i.key==="ArrowLeft"||i.key==="ArrowUp"){i.preventDefault(),v();return}if(i.key==="ArrowRight"||i.key==="ArrowDown"){i.preventDefault(),j();return}if(i.key==="Home"){i.preventDefault(),N();return}if(i.key==="End"){i.preventDefault(),w();return}},b=l&&u?(e-1)*u+1:null,D=l&&u?Math.min(e*u,l):null;return s<=1&&!y?null:n.jsxs("div",{className:k("flex flex-col gap-4",A),children:[y&&l!==void 0&&b!==null&&D!==null&&n.jsxs("div",{className:"text-sm text-muted-foreground text-center",children:["Affichage de ",b," à ",D," sur ",l," résultat",l>1?"s":""]}),s>1&&n.jsxs("nav",{"aria-label":"Navigation de pagination",role:"navigation",className:"flex items-center justify-center gap-1",children:[c&&n.jsxs(d,{type:"button",variant:"outline",size:"icon",onClick:N,disabled:e===1,"aria-label":"Première page",onKeyDown:i=>o(i),children:[n.jsx(x,{className:"h-4 w-4","aria-hidden":"true"}),n.jsx(x,{className:"h-4 w-4 -ml-2","aria-hidden":"true"}),n.jsx("span",{className:"sr-only",children:"Première page"})]}),n.jsxs(d,{type:"button",variant:"outline",size:"icon",onClick:v,disabled:e===1,"aria-label":"Page précédente",onKeyDown:i=>o(i),children:[n.jsx(x,{className:"h-4 w-4","aria-hidden":"true"}),n.jsx("span",{className:"sr-only",children:"Page précédente"})]}),M.map((i,h)=>i==="ellipsis-start"||i==="ellipsis-end"?n.jsx("div",{className:"flex h-9 w-9 items-center justify-center",children:n.jsx(C,{className:"h-4 w-4 text-muted-foreground"})},`ellipsis-${h}`):n.jsx(d,{type:"button",variant:e===i?"default":"outline",size:"icon",onClick:()=>a(i),"aria-label":`Aller à la page ${i}`,"aria-current":e===i?"page":void 0,onKeyDown:r=>o(r),className:k("h-9 w-9",e===i&&"bg-primary text-primary-foreground"),children:i},i)),n.jsxs(d,{type:"button",variant:"outline",size:"icon",onClick:j,disabled:e===s,"aria-label":"Page suivante",onKeyDown:i=>o(i),children:[n.jsx(m,{className:"h-4 w-4","aria-hidden":"true"}),n.jsx("span",{className:"sr-only",children:"Page suivante"})]}),c&&n.jsxs(d,{type:"button",variant:"outline",size:"icon",onClick:w,disabled:e===s,"aria-label":"Dernière page",onKeyDown:i=>o(i),children:[n.jsx(m,{className:"h-4 w-4","aria-hidden":"true"}),n.jsx(m,{className:"h-4 w-4 -ml-2","aria-hidden":"true"}),n.jsx("span",{className:"sr-only",children:"Dernière page"})]})]})]})}export{B as P};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1 +0,0 @@
import{a as n,j as e}from"./vendor-react-BHG7lGYR.js";import{g as x,B as t,d as r}from"./index-BWcMVITa.js";import{u}from"./vendor-router-D-s5vIeO.js";import{V as b,a0 as p,a5 as f,a3 as g}from"./vendor-icons-DaGlTw4_.js";import"./vendor-IYr-MHu4.js";import"./vendor-tanstack-BzWBL1hV.js";import"./vendor-utils-CgOSfOkx.js";function S(){const l=u(),o=x(),[a,i]=n.useState(!1),[s,d]=n.useState(!1),c=()=>{i(!a),o.info(a?"Shuffle disabled":"Shuffle enabled")},m=()=>{d(!s),o.info(s?"Repeat disabled":"Repeat enabled")},h=()=>{l("/library")};return e.jsxs("div",{className:"min-h-screen p-8 space-y-8",children:[e.jsx("div",{className:"glass-hud rounded-2xl border-white/10 p-8 hud-corner",children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{className:"flex items-center gap-4",children:[e.jsx("div",{className:"w-12 h-12 rounded-xl bg-kodo-magenta/20 flex items-center justify-center border border-kodo-magenta/30",children:e.jsx(b,{className:"w-6 h-6 text-kodo-magenta"})}),e.jsxs("div",{children:[e.jsx("h1",{className:"text-3xl font-display font-bold text-white",children:"Play Queue"}),e.jsx("p",{className:"text-sm text-white opacity-80",children:"Manage your playback queue"})]})]}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx(t,{onClick:c,variant:"outline",size:"icon",className:r("border-white/10",a&&"bg-kodo-magenta/20 border-kodo-magenta/50"),children:e.jsx(p,{className:"w-4 h-4"})}),e.jsx(t,{onClick:m,variant:"outline",size:"icon",className:r("border-white/10",s&&"bg-kodo-magenta/20 border-kodo-magenta/50"),children:e.jsx(f,{className:"w-4 h-4"})})]})]})}),e.jsxs("div",{className:"glass-hud rounded-xl border-white/10 p-12 text-center",children:[e.jsx(g,{className:"w-16 h-16 text-kodo-secondary mx-auto mb-4 opacity-50"}),e.jsx("h3",{className:"text-lg font-bold text-white mb-2",children:"Queue is Empty"}),e.jsx("p",{className:"text-base text-white opacity-90 mb-4",children:"Add tracks to your queue to start playing"}),e.jsx(t,{onClick:h,variant:"outline",className:"border-kodo-magenta/30 text-kodo-magenta hover:bg-kodo-magenta/10",children:"Browse Library"})]})]})}export{S as QueuePage};

View file

@ -1 +0,0 @@
import{a as x,j as e}from"./vendor-react-BHG7lGYR.js";import{u as j,L as _}from"./vendor-router-D-s5vIeO.js";import{G as S}from"./vendor-IYr-MHu4.js";import{t as R,o as A,s as m}from"./vendor-utils-CgOSfOkx.js";import{h as w,g as L,w as u,B as F,l as M,j as C,A as D,C as I}from"./index-BWcMVITa.js";import{u as V,F as l}from"./useFormValidation-B1Tm3VtD.js";import{aC as q,U as B,aA as h}from"./vendor-icons-DaGlTw4_.js";import"./vendor-tanstack-BzWBL1hV.js";const T=A({email:m().email("Email invalide"),username:m().min(3,"Le nom d'utilisateur doit contenir au moins 3 caractères"),password:m().min(12,"Le mot de passe doit contenir au moins 12 caractères"),password_confirm:m().min(1,"La confirmation est requise")}).refine(o=>o.password===o.password_confirm,{message:"Les mots de passe ne correspondent pas",path:["password_confirm"]}),z=()=>{const o=j(),{register:d,isLoading:f,error:t}=w(),{toast:p}=L(),{register:c,handleSubmit:b,formState:{errors:k},watch:v}=S({resolver:R(T),defaultValues:{email:"",username:"",password:"",password_confirm:""}}),s=v(),{validate:g,errors:N}=V({type:"RegisterRequest",debounceMs:300});x.useEffect(()=>{if(s.email||s.username||s.password||s.password_confirm){const r={email:s.email||"",username:s.username||"",password:s.password||"",password_confirmation:s.password_confirm||""};g(r)}},[s.email,s.username,s.password,s.password_confirm,g]);const y=async a=>{try{const r={email:a.email,username:a.username,password:a.password,password_confirm:a.password_confirm};await d(r);const{isAuthenticated:n}=w.getState();o(n?"/dashboard":"/login")}catch(r){const n=u(r);M.error("Register error",{error:r instanceof Error?r.message:String(r),stack:r instanceof Error?r.stack:void 0}),p({title:"Erreur d'inscription",description:n,variant:"destructive"})}};x.useEffect(()=>{if(t){const a=u(t);p({title:"Erreur d'inscription",description:a,variant:"destructive"})}},[t,p]);const i=a=>{const r=k[a]?.message,n=N.find(E=>E.field===a)?.message;return r||n};return e.jsxs("form",{onSubmit:b(y),className:"space-y-6",noValidate:!0,children:[t&&e.jsxs("div",{className:"bg-kodo-red/10 border border-kodo-red/20 text-kodo-red text-sm px-4 py-3 rounded-lg flex items-center gap-2 animate-in fade-in slide-in-from-top-1",role:"alert",children:[e.jsx("span",{className:"w-1.5 h-1.5 rounded-full bg-kodo-red shrink-0"}),e.jsx("span",{children:u(t)})]}),e.jsxs("div",{className:"space-y-4",children:[e.jsx(l,{label:"Email",type:"email",icon:e.jsx(q,{className:"h-4 w-4"}),...c("email"),error:i("email")}),e.jsx(l,{label:"Nom d'utilisateur",type:"text",icon:e.jsx(B,{className:"h-4 w-4"}),...c("username"),error:i("username")}),e.jsx(l,{label:"Mot de passe",type:"password",icon:e.jsx(h,{className:"h-4 w-4"}),...c("password"),error:i("password")}),e.jsx(l,{label:"Confirmer le mot de passe",type:"password",icon:e.jsx(h,{className:"h-4 w-4"}),...c("password_confirm"),error:i("password_confirm")||i("password_confirmation")})]}),e.jsx(F,{type:"submit",disabled:f,variant:"default",size:"lg",className:"w-full bg-gradient-to-r from-kodo-magenta to-kodo-magenta-dim hover:from-kodo-magenta/90 hover:to-kodo-magenta-dim/90 text-white font-bold tracking-wide shadow-lg shadow-kodo-magenta/20 rounded-xl",children:f?e.jsxs("span",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"h-4 w-4 border-2 border-current border-t-transparent rounded-full animate-spin"}),"Initialisation..."]}):"S'INSCRIRE"})]})},Q=()=>{const{isAuthenticated:o}=C(),d=j();return x.useEffect(()=>{o&&d("/")},[o,d]),e.jsxs("div",{className:"min-h-screen flex items-center justify-center bg-kodo-void relative overflow-hidden py-12",children:[e.jsx(D,{}),e.jsxs("div",{className:"w-full max-w-md mx-auto relative z-10 px-4",children:[e.jsxs("div",{className:"text-center mb-8",children:[e.jsx("div",{className:"w-16 h-16 bg-gradient-to-br from-kodo-cyan to-kodo-magenta rounded-xl mx-auto mb-4 flex items-center justify-center shadow-lg shadow-kodo-magenta/20",children:e.jsx("span",{className:"text-3xl",children:"💠"})}),e.jsx("h1",{className:"text-4xl font-display font-bold text-white mb-2 tracking-wide text-glow",children:"VEZA"}),e.jsx("p",{className:"text-sm text-kodo-text-dim font-mono uppercase tracking-[0.2em]",children:"Join the Network"})]}),e.jsx(I,{variant:"glass",className:"w-full backdrop-blur-3xl border-white/10 shadow-2xl p-8",children:e.jsx(z,{})}),e.jsx("div",{className:"mt-8 text-center space-y-4",children:e.jsxs("p",{className:"text-xs text-kodo-text-dim",children:["Déjà un compte ?"," ",e.jsx(_,{to:"/login",className:"font-bold text-kodo-cyan hover:text-kodo-cyan-dim transition-colors uppercase tracking-wider",children:"Se connecter"})]})})]})]})};export{Q as RegisterPage};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1 +0,0 @@
import{a as i,j as e}from"./vendor-react-BHG7lGYR.js";import{C as n,b as l,c,v as x,e as m,B as s}from"./index-BWcMVITa.js";import{u as k}from"./vendor-router-D-s5vIeO.js";import{a as u,g as h,a9 as p,H as j,f,aC as N}from"./vendor-icons-DaGlTw4_.js";import"./vendor-IYr-MHu4.js";import"./vendor-tanstack-BzWBL1hV.js";import"./vendor-utils-CgOSfOkx.js";function R(){const a=k(),[t,r]=i.useState(!1),o=async()=>{r(!0),setTimeout(()=>{window.location.reload()},500)},d=()=>{a("/dashboard")};return e.jsx("div",{className:"min-h-screen flex items-center justify-center bg-kodo-void dark:bg-kodo-ink p-4",children:e.jsx("div",{className:"w-full max-w-2xl",children:e.jsxs(n,{className:"text-center",children:[e.jsxs(l,{children:[e.jsx("div",{className:"mx-auto mb-4 flex h-16 w-16 items-center justify-center rounded-full bg-kodo-red/10 dark:bg-kodo-red/20",children:e.jsx(u,{className:"h-8 w-8 text-kodo-red dark:text-kodo-red"})}),e.jsx(c,{className:"text-2xl",children:"Erreur serveur"}),e.jsx(x,{children:"Une erreur interne s'est produite. Notre équipe a été notifiée."})]}),e.jsxs(m,{className:"space-y-6",children:[e.jsx("div",{className:"text-6xl font-bold text-kodo-text-main dark:text-kodo-text-main",children:"500"}),e.jsx("p",{className:"text-kodo-content-dim dark:text-kodo-content-dim",children:"Nous nous excusons pour la gêne occasionnée. Notre équipe technique a été automatiquement notifiée et travaille à résoudre le problème."}),e.jsx("div",{className:"bg-kodo-steel/10 dark:bg-kodo-steel/20 border border-kodo-steel dark:border-kodo-steel rounded-lg p-4",children:e.jsxs("div",{className:"flex items-start gap-4 text-left",children:[e.jsx(h,{className:"h-5 w-5 text-kodo-steel dark:text-kodo-steel mt-0.5"}),e.jsxs("div",{children:[e.jsx("p",{className:"text-sm font-medium text-kodo-steel dark:text-kodo-steel",children:"Que faire maintenant ?"}),e.jsxs("ul",{className:"text-sm text-kodo-steel dark:text-kodo-steel mt-2 space-y-1 list-disc list-inside",children:[e.jsx("li",{children:"Attendez quelques instants et réessayez"}),e.jsx("li",{children:"Vérifiez votre connexion internet"}),e.jsx("li",{children:"Si le problème persiste, contactez le support"})]})]})]})}),e.jsxs("div",{className:"flex flex-col sm:flex-row gap-2",children:[e.jsxs(s,{onClick:o,disabled:t,className:"flex-1",children:[e.jsx(p,{className:`mr-2 h-4 w-4 ${t?"animate-spin":""}`}),t?"Réessai...":"Réessayer"]}),e.jsxs(s,{onClick:d,variant:"outline",className:"flex-1",children:[e.jsx(j,{className:"mr-2 h-4 w-4"}),"Retour au dashboard"]})]}),e.jsxs("div",{className:"border-t pt-4 text-left",children:[e.jsx("p",{className:"text-sm font-medium text-kodo-text-main dark:text-kodo-text-main mb-3",children:"Besoin d'aide ?"}),e.jsxs("div",{className:"space-y-2",children:[e.jsxs("div",{className:"flex items-center gap-2 text-sm text-kodo-content-dim dark:text-kodo-content-dim",children:[e.jsx(f,{className:"h-4 w-4 text-kodo-lime"}),e.jsx("span",{children:"L'erreur a été automatiquement signalée à notre équipe"})]}),e.jsxs("div",{className:"flex items-center gap-2 text-sm text-kodo-content-dim dark:text-kodo-content-dim",children:[e.jsx(N,{className:"h-4 w-4 text-kodo-steel"}),e.jsx("span",{children:"Contactez le support si le problème persiste après plusieurs tentatives"})]})]})]}),e.jsxs("details",{className:"border-t pt-4 text-left",children:[e.jsx("summary",{className:"text-sm font-medium text-kodo-text-main dark:text-kodo-text-main cursor-pointer hover:text-kodo-text-main dark:hover:text-kodo-text-main",children:"Détails techniques"}),e.jsxs("div",{className:"mt-2 p-4 bg-kodo-void dark:bg-kodo-graphite rounded text-xs font-mono text-kodo-content-dim dark:text-kodo-content-dim",children:[e.jsx("p",{children:"Code d'erreur: 500 Internal Server Error"}),e.jsxs("p",{children:["Timestamp: ",new Date().toISOString()]}),e.jsxs("p",{children:["User Agent: ",navigator.userAgent]})]})]})]})]})})})}export{R as default};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1 +0,0 @@
import{j as e}from"./vendor-react-BHG7lGYR.js";import{d as o}from"./index-BWcMVITa.js";import{i as m}from"./vendor-icons-DaGlTw4_.js";function u({size:t="md",variant:r="default",className:s,"aria-label":a="Chargement en cours"}){const n={sm:"h-4 w-4",md:"h-5 w-5",lg:"h-6 w-6"},i={default:"text-kodo-cyan",muted:"text-muted-foreground",white:"text-white",current:"text-current"};return e.jsxs(e.Fragment,{children:[e.jsx(m,{className:o("animate-spin",n[t],i[r],s),"aria-hidden":"true"}),e.jsx("span",{className:"sr-only",children:a})]})}export{u as S};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1 +0,0 @@
import{a as t,j as e}from"./vendor-react-BHG7lGYR.js";import{c as k,u as N}from"./vendor-router-D-s5vIeO.js";import{A as c,a as g}from"./AuthButton-ByJY1yM3.js";import{x as V}from"./index-BWcMVITa.js";import"./vendor-IYr-MHu4.js";import"./vendor-tanstack-BzWBL1hV.js";import"./vendor-utils-CgOSfOkx.js";import"./vendor-icons-DaGlTw4_.js";function T(){const[d]=k(),u=N(),[n,o]=t.useState("verifying"),[l,s]=t.useState("Vérification de votre email en cours..."),[j,m]=t.useState(!1),[f,v]=t.useState(!1),[a,x]=t.useState(0),i=t.useRef(null),[p,b]=t.useState(null);t.useEffect(()=>{const r=d.get("token");r?(b(r),h(r)):(o("error"),s("Lien de vérification invalide ou manquant"))},[d]),t.useEffect(()=>()=>{i.current&&clearInterval(i.current)},[]),t.useEffect(()=>(a>0?i.current=setInterval(()=>{x(r=>r<=1?(i.current&&clearInterval(i.current),0):r-1)},1e3):i.current&&(clearInterval(i.current),i.current=null),()=>{i.current&&clearInterval(i.current)}),[a]),t.useEffect(()=>{if(n==="success"){const r=setTimeout(()=>{u("/login",{replace:!0})},3e3);return()=>clearTimeout(r)}},[n,u]);const h=async r=>{try{m(!0),o("verifying"),s("Vérification de votre email en cours..."),await verifyEmail(r),o("success"),s("Votre email a été vérifié avec succès !")}catch(y){o("error"),s(y.message||"La vérification a échoué")}finally{m(!1)}},E=async()=>{if(!(a>0||f))try{v(!0);const r=localStorage.getItem("pendingVerificationEmail");if(!r){s("Email non trouvé. Veuillez vous réinscrire ou contacter le support.");return}await V.resendVerification({email:r}),x(60),s("Email de vérification envoyé ! Veuillez vérifier votre boîte mail.")}catch(r){s(r.message||"Échec de l'envoi de l'email")}finally{v(!1)}};return n==="verifying"?e.jsx(c,{title:"Vérification de l'email",subtitle:"Vérification en cours...",footerLinks:[{label:"Retour à la connexion",to:"/login"}],children:e.jsxs("div",{className:"text-center space-y-4",role:"status","aria-live":"polite","aria-busy":"true",children:[e.jsx("div",{className:"flex justify-center","aria-hidden":"true",children:e.jsx("div",{className:"animate-spin rounded-full h-12 w-12 border-b-2 border-kodo-steel"})}),e.jsx("p",{className:"text-kodo-content-dim",children:l}),e.jsx("span",{className:"sr-only",children:"Vérification de votre email en cours, veuillez patienter"})]})}):n==="success"?e.jsx(c,{title:"Email vérifié",subtitle:"Votre email a été vérifié avec succès",footerLinks:[{label:"Retour à la connexion",to:"/login"}],children:e.jsx("div",{className:"text-center space-y-4",role:"status","aria-live":"polite",children:e.jsxs("div",{className:"bg-kodo-lime/10 border border-kodo-lime text-kodo-lime px-4 py-4 rounded",role:"alert",children:[e.jsx("p",{className:"font-medium",children:"Succès !"}),e.jsx("p",{className:"text-sm mt-1",children:l}),e.jsx("p",{className:"text-xs mt-2 text-kodo-content-dim",children:"Vous allez être redirigé vers la page de connexion..."})]})})}):e.jsx(c,{title:"Vérification de l'email",subtitle:"Une erreur s'est produite",footerLinks:[{label:"Retour à la connexion",to:"/login"}],children:e.jsxs("div",{className:"text-center space-y-4",children:[e.jsxs("div",{className:"bg-kodo-red/10 border border-kodo-red text-kodo-red px-4 py-4 rounded",role:"alert","aria-live":"assertive",children:[e.jsx("p",{className:"font-medium",children:"Erreur"}),e.jsx("p",{className:"text-sm mt-1",children:l})]}),e.jsxs("div",{className:"space-y-2",children:[p&&e.jsx(g,{onClick:()=>h(p),loading:j,type:"button",children:"Réessayer"}),e.jsx(g,{onClick:E,loading:f,disabled:a>0,type:"button",variant:"secondary","aria-label":a>0?`Renvoyer l'email de vérification dans ${a} secondes`:"Renvoyer l'email de vérification",children:a>0?e.jsxs(e.Fragment,{children:[e.jsxs("span",{className:"sr-only",children:["Renvoyer dans ",a," secondes"]}),e.jsxs("span",{"aria-hidden":"true",children:["Renvoyer dans ",a,"s"]})]}):"Renvoyer l'email de vérification"})]})]})})}export{T as VerifyEmailPage,T as default};

File diff suppressed because one or more lines are too long

View file

@ -1 +0,0 @@
import{a,j as e}from"./vendor-react-BHG7lGYR.js";import{d as t}from"./index-BWcMVITa.js";import{X as p,A as h,a as k,f as g,I as N}from"./vendor-icons-DaGlTw4_.js";const b=a.forwardRef(({variant:s="default",title:o,onClose:r,className:n,children:c,...x},m)=>{const f={destructive:"error",default:"info"}[s]||s,l={info:"bg-kodo-steel/10 border-kodo-steel/30 text-kodo-steel",success:"bg-kodo-lime/10 border-kodo-lime/30 text-kodo-lime",warning:"bg-kodo-gold/10 border-kodo-gold/30 text-kodo-gold",error:"bg-kodo-red/10 border-kodo-red/30 text-kodo-red"},i={info:e.jsx(N,{className:"w-5 h-5 flex-shrink-0"}),success:e.jsx(g,{className:"w-5 h-5 flex-shrink-0"}),warning:e.jsx(k,{className:"w-5 h-5 flex-shrink-0"}),error:e.jsx(h,{className:"w-5 h-5 flex-shrink-0"})},d=f;return e.jsxs("div",{ref:m,role:"alert",className:t("p-4 rounded-lg border flex gap-4",l[d]||l.info,n),...x,children:[i[d]||i.info,e.jsxs("div",{className:"flex-1",children:[o&&e.jsx("h5",{className:"font-bold mb-1",children:o}),e.jsx("div",{className:"text-sm opacity-90",children:c})]}),r&&e.jsx("button",{onClick:r,className:"opacity-70 hover:opacity-100 transition-opacity",children:e.jsx(p,{className:"w-4 h-4"})})]})});b.displayName="Alert";const j=a.forwardRef(({className:s,...o},r)=>e.jsx("h5",{ref:r,className:t("mb-1 font-bold leading-none tracking-tight text-white",s),...o}));j.displayName="AlertTitle";const w=a.forwardRef(({className:s,...o},r)=>e.jsx("div",{ref:r,className:t("text-sm opacity-90 [&_p]:leading-relaxed",s),...o}));w.displayName="AlertDescription";export{b as A,w as a};

View file

@ -1 +0,0 @@
import{R as w,j as e}from"./vendor-react-BHG7lGYR.js";import{d as r}from"./index-BWcMVITa.js";const u=w.forwardRef(({src:s,alt:l="Avatar",fallback:n,size:d="md",status:a,className:x="",onClick:i},b)=>{const h={xs:"w-6 h-6 text-[10px]",sm:"w-8 h-8 text-xs",md:"w-10 h-10 text-sm",lg:"w-12 h-12 text-base",xl:"w-16 h-16 text-lg","2xl":"w-24 h-24 text-xl","3xl":"w-32 h-32 text-2xl"},c={online:"bg-kodo-lime",offline:"bg-kodo-steel",away:"bg-kodo-gold",idle:"bg-kodo-gold",busy:"bg-kodo-red",dnd:"bg-kodo-red"},m={xs:"w-1.5 h-1.5 border",sm:"w-2 h-2 border",md:"w-2.5 h-2.5 border-2",lg:"w-3 h-3 border-2",xl:"w-4 h-4 border-2","2xl":"w-5 h-5 border-4","3xl":"w-6 h-6 border-4"},g=(o=>{if(!o)return"?";const t=o.trim().split(" ");return t.length>=2?(t[0][0]+t[t.length-1][0]).toUpperCase():o.substring(0,2).toUpperCase()})(n||l);return e.jsxs("div",{ref:b,className:r("relative inline-block",x,i?"cursor-pointer":""),onClick:i,children:[e.jsx("div",{className:r(`${h[d]} rounded-full overflow-hidden bg-kodo-graphite border border-kodo-steel flex items-center justify-center relative`),children:s?e.jsx("img",{src:s,alt:l,className:"w-full h-full object-cover"}):e.jsx("span",{className:"font-bold text-kodo-content-dim",children:g})}),a&&e.jsx("span",{className:r("absolute bottom-0 right-0 rounded-full border-kodo-void",c[a],m[d])})]})});u.displayName="Avatar";export{u as A};

View file

@ -1 +0,0 @@
import{a as b,j as e}from"./vendor-react-BHG7lGYR.js";import{d as y}from"./index-BWcMVITa.js";const u=b.forwardRef(({label:d,variant:a="cyan",icon:t,size:s="md",dot:n,count:o,children:l,className:m,...i},p)=>{const c={default:"cyan",primary:"cyan",success:"lime",warning:"gold",error:"magenta",secondary:"magenta"}[a]||a,r={cyan:"bg-kodo-steel/10 text-kodo-steel border-kodo-steel/30",magenta:"bg-kodo-magenta/10 text-kodo-magenta border-kodo-magenta/30",lime:"bg-kodo-lime/10 text-kodo-lime border-kodo-lime/30",gold:"bg-kodo-gold/10 text-kodo-gold border-kodo-gold/30",terminal:"bg-kodo-terminal/10 text-kodo-terminal border-kodo-terminal/30 font-mono"},x={sm:"px-2 py-0.5 text-[10px]",md:"px-2.5 py-0.5 text-[10px]",lg:"px-4 py-1 text-xs"},g=d||l,k=c;return e.jsxs("span",{ref:p,className:y("inline-flex items-center gap-1.5 rounded-full font-bold uppercase tracking-widest border",r[k]||r.cyan,x[s],m),...i,children:[n&&e.jsx("span",{className:"w-3 h-3 rounded-full bg-current"}),t&&e.jsx("span",{className:"w-3 h-3",children:t}),g,o!==void 0&&o>0&&e.jsx("span",{className:"ml-1 px-1.5 py-0.5 rounded-full bg-current/20 text-[10px]",children:o})]})});u.displayName="Badge";export{u as B};

View file

@ -1,6 +0,0 @@
import{a as n,j as e}from"./vendor-react-BHG7lGYR.js";import{d as p}from"./index-BWcMVITa.js";import{l as b}from"./vendor-icons-DaGlTw4_.js";const m=n.forwardRef(({label:o,className:c="",onCheckedChange:r,id:i,...t},l)=>{const d=n.useId(),a=i||d,s=`${a}-label`,x=h=>{r&&r(h.target.checked)};return e.jsxs("label",{htmlFor:a,id:s,className:p("inline-flex items-center gap-4 cursor-pointer group",t.disabled?"opacity-50 cursor-not-allowed":"",c),children:[e.jsxs("div",{className:"relative",children:[e.jsx("input",{ref:l,id:a,type:"checkbox",className:"peer sr-only",onChange:x,"aria-label":!o&&!t["aria-label"]&&!t["aria-labelledby"]?"Checkbox":void 0,"aria-labelledby":o?s:void 0,...t}),e.jsx("div",{className:`
w-5 h-5 rounded border border-kodo-steel bg-kodo-graphite
peer-checked:bg-kodo-cyan peer-checked:border-kodo-steel
peer-focus:ring-2 peer-focus:ring-kodo-steel/30
transition-all duration-200
`}),e.jsx(b,{className:"w-3.5 h-3.5 text-black absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 opacity-0 peer-checked:opacity-100 transition-opacity pointer-events-none",strokeWidth:3})]}),o&&e.jsx("span",{className:"text-sm text-kodo-text-main group-hover:text-white transition-colors select-none",children:o})]})});m.displayName="Checkbox";export{m as C};

View file

@ -1 +0,0 @@
import{j as e}from"./vendor-react-BHG7lGYR.js";import{D as d}from"./index-BWcMVITa.js";import{a as m}from"./vendor-icons-DaGlTw4_.js";function u({open:a,onClose:r,onConfirm:l,title:i,description:t,confirmLabel:n="Confirm",cancelLabel:x="Cancel",variant:c="destructive",isLoading:s=!1}){const o=()=>{s||l()};return e.jsx(d,{open:a,onClose:r,title:i,onConfirm:o,confirmLabel:s?"Processing...":n,onCancel:r,showCancel:!0,children:e.jsx("div",{className:"space-y-4 py-4",children:e.jsxs("div",{className:"flex items-start gap-4",children:[c==="destructive"&&e.jsx("div",{className:"flex-shrink-0",children:e.jsx("div",{className:"flex h-10 w-10 items-center justify-center rounded-full bg-kodo-red/10 dark:bg-kodo-red/20",children:e.jsx(m,{className:"h-5 w-5 text-kodo-red dark:text-kodo-red"})})}),e.jsx("div",{className:"flex-1",children:e.jsx("p",{className:"text-sm text-muted-foreground",children:t})})]})})})}export{u as C};

View file

@ -1 +0,0 @@
import{a as o,j as c}from"./vendor-react-BHG7lGYR.js";import{d}from"./index-BWcMVITa.js";function w({trigger:m,children:p,align:b="left",className:k,onOpenChange:i}){const[r,h]=o.useState(!1),l=o.useRef(null),a=o.useRef(null),f=o.useRef(null),t=o.useRef(-1),u=o.useCallback(e=>{h(e),i?.(e),e||(t.current=-1)},[i]);o.useEffect(()=>{if(!r)return;const e=s=>{l.current&&!l.current.contains(s.target)&&u(!1)};return document.addEventListener("mousedown",e),()=>{document.removeEventListener("mousedown",e)}},[r,u]),o.useEffect(()=>{if(!r)return;const e=s=>{if(!a.current)return;const v=a.current.querySelectorAll('button, [href], input, select, textarea, [role="menuitem"], [tabindex]:not([tabindex="-1"])'),n=Array.from(v);switch(s.key){case"Escape":s.preventDefault(),u(!1),f.current?.focus();break;case"ArrowDown":s.preventDefault(),t.current=t.current<n.length-1?t.current+1:0,n[t.current]?.focus();break;case"ArrowUp":s.preventDefault(),t.current=t.current>0?t.current-1:n.length-1,n[t.current]?.focus();break;case"Enter":case" ":s.preventDefault(),t.current>=0&&n[t.current]&&n[t.current].click();break;case"Home":s.preventDefault(),t.current=0,n[0]?.focus();break;case"End":s.preventDefault(),t.current=n.length-1,n[n.length-1]?.focus();break}};return document.addEventListener("keydown",e),()=>{document.removeEventListener("keydown",e)}},[r,u]),o.useEffect(()=>{if(r&&a.current){const e=a.current.querySelectorAll('button, [href], input, select, textarea, [role="menuitem"], [tabindex]:not([tabindex="-1"])');e.length>0&&(t.current=0,setTimeout(()=>{e[0]?.focus()},0))}},[r]);const x={left:"left-0",right:"right-0",center:"left-1/2 -translate-x-1/2"};return c.jsxs("div",{ref:l,className:d("relative",k),children:[c.jsx("div",{ref:f,onClick:()=>u(!r),role:"button","aria-haspopup":"true","aria-expanded":r,tabIndex:0,onKeyDown:e=>{e.key==="Enter"||e.key===" "?(e.preventDefault(),u(!r)):e.key==="ArrowDown"&&(e.preventDefault(),u(!0))},style:{display:"inline-block"},children:m}),r&&c.jsxs(c.Fragment,{children:[c.jsx("div",{className:"fixed inset-0 z-40",onClick:()=>u(!1),"aria-hidden":"true"}),c.jsx("div",{ref:a,className:d("absolute z-50 mt-2 min-w-[8rem] bg-kodo-ink border border-kodo-steel rounded-md shadow-lg","overflow-hidden",x[b]),role:"menu","aria-orientation":"vertical",children:p})]})]})}export{w as D};

View file

@ -1 +0,0 @@
const a={TWO_FACTOR_AUTH:!0,PLAYLIST_COLLABORATION:!0,PLAYLIST_SEARCH:!1,PLAYLIST_SHARE:!1,PLAYLIST_RECOMMENDATIONS:!1,HLS_STREAMING:!1,ROLE_MANAGEMENT:!1,NOTIFICATIONS:!1};function A(e){return!!a[e]}function r(e){if(!A(e))throw new Error(`Feature "${e}" is not enabled. This feature is not available in the MVP.`)}export{A as i,r};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1 +0,0 @@
import{a,j as t}from"./vendor-react-BHG7lGYR.js";import{d as l}from"./index-BWcMVITa.js";const d=a.forwardRef(({className:o,type:r,icon:e,...i},s)=>t.jsxs("div",{className:"relative group",children:[e&&t.jsx("div",{className:"absolute left-3 top-1/2 -translate-y-1/2 text-kodo-text-dim group-focus-within:text-kodo-cyan transition-colors pointer-events-none",children:e}),t.jsx("input",{type:r,className:l("flex h-11 w-full rounded-xl border border-white/10 bg-kodo-graphite/40 px-3 py-2 text-sm text-white placeholder:text-kodo-text-dim/50 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:cursor-not-allowed disabled:opacity-50","backdrop-blur-sm transition-all duration-200","focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-kodo-cyan/30 focus-visible:border-kodo-cyan/50","hover:bg-white/5 hover:border-white/20",e&&"pl-10",o),ref:s,...i})]}));d.displayName="Input";export{d as I};

View file

@ -1 +0,0 @@
import{a as t,j as s}from"./vendor-react-BHG7lGYR.js";import{d as r}from"./index-BWcMVITa.js";const d=t.forwardRef(({className:e,...a},o)=>s.jsx("label",{ref:o,className:r("text-sm font-medium leading-none text-kodo-content-dim peer-disabled:cursor-not-allowed peer-disabled:opacity-70",e),...a}));d.displayName="Label";export{d as L};

View file

@ -1 +0,0 @@
import{m as a,k as l,j as s,i as t,h as e,e as o,n as r,b as i,a as d,f as c,r as y,o as P,c as m,s as n,l as g,d as k,u as p,g as u}from"./PlaylistCard-z0bLl0kY.js";const f={create:a,get:u,update:p,delete:k,list:g,search:n,addTrack:m,removeTrack:P,reorderTracks:y,addCollaborator:c,removeCollaborator:d,updateCollaboratorPermission:i,getCollaborators:r,createShareLink:o,follow:e,unfollow:t,getFollowStatus:s,getRecommendations:l};export{f as p};

View file

@ -1 +0,0 @@
import{a as h,j as o}from"./vendor-react-BHG7lGYR.js";import{d as e}from"./index-BWcMVITa.js";const f=h.forwardRef(({value:i,max:l=100,variant:c="default",color:x="cyan",labelLeft:s,labelRight:d,className:n,...r},t)=>{const a=Math.min(100,Math.max(0,i/l*100)),m={cyan:"bg-kodo-cyan",magenta:"bg-kodo-magenta",lime:"bg-kodo-lime",gold:"bg-kodo-gold"},g={gold:"from-kodo-gold to-orange-500"};return c==="gaming"?o.jsxs("div",{className:e("relative",n),ref:t,...r,children:[o.jsx("div",{className:"h-4 bg-kodo-void rounded-full overflow-hidden border border-kodo-gold/30",children:o.jsx("div",{className:e("h-full bg-gradient-to-r shadow-[0_0_10px_rgba(255,215,0,0.5)] transition-all duration-500",g.gold),style:{width:`${a}%`}})}),(s||d)&&o.jsxs("div",{className:"flex justify-between text-[10px] font-mono font-bold text-kodo-gold mt-1 uppercase tracking-wider",children:[o.jsx("span",{children:s}),o.jsx("span",{children:d})]})]}):o.jsxs("div",{className:e("w-full",n),ref:t,...r,children:[o.jsx("div",{className:"h-2 bg-kodo-steel rounded-full overflow-hidden",children:o.jsx("div",{className:e("h-full transition-all duration-300 shadow-[0_0_10px_currentColor]",m[x]),style:{width:`${a}%`}})}),(s||d)&&o.jsxs("div",{className:"flex justify-between text-xs text-kodo-content-dim mt-1 font-mono",children:[o.jsx("span",{children:s}),o.jsx("span",{children:d})]})]})});f.displayName="Progress";export{f as P};

View file

@ -1 +0,0 @@
.touch-manipulation{touch-action:manipulation;-webkit-tap-highlight-color:transparent}@media(max-width:640px){button,a[role=button],[role=button]{min-height:44px;min-width:44px}.playlist-card{-webkit-tap-highlight-color:rgba(0,0,0,.1)}.playlist-card,.playlist-track-item{-webkit-user-select:none;-moz-user-select:none;user-select:none}.playlist-list-container{-webkit-overflow-scrolling:touch;overflow-scrolling:touch}}@media(min-width:640px){button,a[role=button],[role=button]{min-height:auto;min-width:auto}}@supports (padding: max(0px)){.playlist-container{padding-left:max(1rem,env(safe-area-inset-left));padding-right:max(1rem,env(safe-area-inset-right))}}

File diff suppressed because one or more lines are too long

View file

@ -1 +0,0 @@
import{a as i,j as r}from"./vendor-react-BHG7lGYR.js";import{D as P}from"./dropdown-BYn_8IId.js";import{I as F}from"./input-BGBI2Wze.js";import{B as G,d as j}from"./index-BWcMVITa.js";import{X as U,c as X,l as S}from"./vendor-icons-DaGlTw4_.js";function T({options:a,value:s,onChange:d,multiple:o=!1,searchable:l=!1,placeholder:c="Select an option...",disabled:O=!1,className:E,name:m,"aria-label":w,"aria-labelledby":D}){const[u,k]=i.useState(!1),[h,g]=i.useState(""),y=i.useRef(null),f=i.useMemo(()=>{const e={},n=[];return a.forEach(t=>{t.group?(e[t.group]||(e[t.group]=[]),e[t.group].push(t)):n.push(t)}),{groups:e,ungrouped:n}},[a]),p=i.useMemo(()=>{if(!l||!h)return{groups:f.groups,ungrouped:f.ungrouped};const e=h.toLowerCase(),n={},t=[];return Object.entries(f.groups).forEach(([x,K])=>{const v=K.filter(M=>M.label.toLowerCase().includes(e));v.length>0&&(n[x]=v)}),t.push(...f.ungrouped.filter(x=>x.label.toLowerCase().includes(e))),{groups:n,ungrouped:t}},[l,h,f]),b=s?(Array.isArray(s)?s:[s]).map(n=>a.find(t=>t.value===n)?.label).filter(Boolean):[],I=o?b.length>0?`${b.length} selected`:c:b[0]||c,N=e=>s?o?Array.isArray(s)&&s.includes(e):s===e:!1,A=e=>{if(o){const n=Array.isArray(s)?s:[],t=n.includes(e)?n.filter(x=>x!==e):[...n,e];d(t)}else d(e),k(!1),g("")},L=e=>{e.stopPropagation(),d(o?[]:"")};i.useEffect(()=>{u&&l&&y.current&&y.current.focus()},[u,l]),i.useEffect(()=>{u||g("")},[u]);const B=r.jsxs(G,{variant:"outline",disabled:O,className:j("w-full justify-between",!s||Array.isArray(s)&&s.length===0?"text-muted-foreground":"",E),type:"button","aria-label":w,"aria-labelledby":D,"aria-haspopup":"listbox","aria-expanded":u,children:[r.jsx("span",{className:"truncate",children:I}),r.jsxs("div",{className:"flex items-center gap-1 ml-2",children:[s&&(Array.isArray(s)&&s.length>0||!Array.isArray(s))&&r.jsx(U,{className:"h-4 w-4 shrink-0 opacity-50 hover:opacity-100",onClick:L}),r.jsx(X,{className:"h-4 w-4 shrink-0 opacity-50"})]})]}),R=r.jsxs("div",{className:"w-full min-w-[200px] max-h-[300px] overflow-y-auto",role:"listbox","aria-label":w||m||c,children:[l&&r.jsx("div",{className:"p-2 border-b",children:r.jsx(F,{ref:y,type:"text",placeholder:"Search...",value:h,onChange:e=>g(e.target.value),onClick:e=>e.stopPropagation(),className:"w-full"})}),p.ungrouped.length>0&&r.jsx("div",{className:"py-1",children:p.ungrouped.map(e=>r.jsx(C,{option:e,isSelected:N(e.value),multiple:o,onSelect:A},e.value))}),Object.entries(p.groups).map(([e,n])=>r.jsxs("div",{className:"py-1",children:[r.jsx("div",{className:"px-4 py-1.5 text-xs font-semibold text-kodo-content-dim uppercase",children:e}),n.map(t=>r.jsx(C,{option:t,isSelected:N(t.value),multiple:o,onSelect:A},t.value))]},e)),p.ungrouped.length===0&&Object.keys(p.groups).length===0&&r.jsx("div",{className:"px-4 py-2 text-sm text-kodo-content-dim text-center",children:"No options found"})]});return r.jsxs(r.Fragment,{children:[r.jsx(P,{trigger:B,align:"left",onOpenChange:k,className:"w-full",children:R}),m&&r.jsx("input",{type:"hidden",name:m,value:Array.isArray(s)?s.join(","):s||""})]})}function C({option:a,isSelected:s,multiple:d,onSelect:o}){const l=c=>{a.disabled||(c.key==="Enter"||c.key===" ")&&(c.preventDefault(),o(a.value))};return r.jsxs("div",{role:"option","aria-selected":s,className:j("relative flex items-center px-4 py-2 text-sm cursor-pointer","hover:bg-white/5 hover:text-white","focus:bg-white/5 focus:text-white","transition-colors text-kodo-text-main",s&&"bg-kodo-steel/10 text-kodo-steel",a.disabled&&"opacity-50 cursor-not-allowed pointer-events-none"),onClick:()=>!a.disabled&&o(a.value),onKeyDown:l,tabIndex:a.disabled?-1:0,children:[d&&r.jsx("div",{className:j("mr-2 flex h-4 w-4 items-center justify-center rounded-sm border border-kodo-steel",s&&"bg-kodo-cyan border-kodo-steel text-kodo-void"),children:s&&r.jsx(S,{className:"h-3 w-3"})}),r.jsx("span",{className:"flex-1",children:a.label}),!d&&s&&r.jsx(S,{className:"h-4 w-4 text-kodo-steel"})]})}export{T as S};

View file

@ -1 +0,0 @@
import{a as e}from"./index-BWcMVITa.js";const m={getFeed:async t=>({posts:(await e.get("/social/feed",{params:t})).data.map(n=>({id:n.id,author:{name:"User",handle:"@user",avatar:""},content:n.content,timestamp:n.created_at,likes:0,comments:0,shares:0,type:"text"}))}),getPostsByUser:async(t,a=1,s)=>{const n=await e.get(`/social/posts/user/${t}`,{params:{page:a,limit:10}}),r=s?{name:s.first_name||s.last_name?`${s.first_name||""} ${s.last_name||""}`.trim():s.username,handle:`@${s.username}`,avatar:s.avatar_url||"",isVerified:!1}:{name:"User",handle:"@user",avatar:""};return{posts:n.data.map(o=>({id:o.id,author:r,content:o.content,timestamp:o.created_at,likes:o.like_count,comments:o.comment_count,shares:0,type:"text"})),total:100}},createPost:async t=>{const s=(await e.post("/social/posts",t)).data;return{post:{id:s.id,author:{name:"Me",handle:"@me",avatar:""},content:s.content,timestamp:s.created_at,likes:0,comments:0,shares:0,type:"text"}}},toggleLike:async(t,a)=>(await e.post("/social/like",{target_id:t,target_type:a})).data,getChatToken:async()=>(await e.post("/chat/token")).data,getChatStats:async()=>(await e.get("/chat/stats")).data,getComments:async t=>({comments:(await e.get(`/tracks/${t}/comments`)).data}),postComment:async(t,a)=>(await e.post(`/tracks/${t}/comments`,{content:a})).data,deleteComment:async t=>{await e.delete(`/comments/${t}`)},getNotifications:async()=>({notifications:(await e.get("/notifications")).data}),markRead:async t=>{await e.post(`/notifications/${t}/read`)},markAllRead:async()=>{await e.post("/notifications/read-all")},getWebhooks:async()=>(await e.get("/webhooks")).data,registerWebhook:async t=>{await e.post("/webhooks",t)},deleteWebhook:async t=>{await e.delete(`/webhooks/${t}`)},testWebhook:async t=>{await e.post(`/webhooks/${t}/test`)},getWebhookStats:async()=>(await e.get("/webhooks/stats")).data,regenerateWebhookKey:async t=>(await e.post(`/webhooks/${t}/regenerate-key`)).data};export{m as s};

View file

@ -1 +0,0 @@
import{a as e,j as d}from"./vendor-react-BHG7lGYR.js";import{d as c}from"./index-BWcMVITa.js";const g=e.forwardRef(({className:s,value:t,defaultValue:i,onValueChange:r,children:a,...l},o)=>{const[f,v]=e.useState(i||""),u=t!==void 0?t:f,x=n=>{t===void 0&&v(n),r?.(n)};return d.jsx("div",{ref:o,className:s,...l,children:e.Children.map(a,n=>{if(e.isValidElement(n)){if(n.type===m)return e.cloneElement(n,{activeValue:u,onValueChange:x});if(n.type===p)return e.cloneElement(n,{activeValue:u})}return n})})});g.displayName="Tabs";const m=e.forwardRef(({className:s,children:t,activeValue:i,onValueChange:r,...a},l)=>d.jsx("div",{ref:l,className:c("inline-flex h-10 items-center justify-center rounded-md bg-kodo-graphite p-1 text-kodo-content-dim border border-kodo-steel/30",s),...a,children:e.Children.map(t,o=>e.isValidElement(o)&&o.type===b?e.cloneElement(o,{activeValue:i,onValueChange:r}):o)}));m.displayName="TabsList";const b=e.forwardRef(({className:s,value:t,activeValue:i,onValueChange:r,children:a,...l},o)=>{const f=i===t;return d.jsx("button",{ref:o,onClick:()=>r?.(t),className:c("inline-flex items-center justify-center whitespace-nowrap rounded-sm px-4 py-1.5 text-sm font-bold uppercase tracking-wider","ring-offset-kodo-void transition-all duration-200","focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-kodo-steel focus-visible:ring-offset-2","disabled:pointer-events-none disabled:opacity-50",f?"bg-kodo-cyan text-kodo-void":"text-kodo-content-dim hover:text-kodo-text-main",s),...l,children:a})});b.displayName="TabsTrigger";const p=e.forwardRef(({className:s,value:t,activeValue:i,children:r,...a},l)=>i!==t?null:d.jsx("div",{ref:l,className:c("mt-2 ring-offset-kodo-void focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-kodo-steel focus-visible:ring-offset-2",s),...a,children:r}));p.displayName="TabsContent";export{g as T,m as a,b,p as c};

View file

@ -1 +0,0 @@
import{a as d,j as e}from"./vendor-react-BHG7lGYR.js";import{d as l}from"./index-BWcMVITa.js";const n=d.forwardRef(({label:t,error:o,className:s,...r},a)=>e.jsxs("div",{className:"w-full",children:[t&&e.jsx("label",{className:"block text-sm font-medium text-kodo-content-dim mb-2 font-body",children:t}),e.jsx("textarea",{ref:a,className:l("w-full px-4 py-4","bg-kodo-graphite border",o?"border-kodo-red":"border-kodo-steel","text-white placeholder-gray-500","font-body text-base","rounded-lg","focus:outline-none focus:border-kodo-steel focus:ring-1 focus:ring-kodo-steel","transition-all duration-200","min-h-[100px] resize-y",s),...r}),o&&e.jsx("p",{className:"mt-1 text-xs text-kodo-red",children:o})]}));n.displayName="Textarea";export{n as T};

File diff suppressed because one or more lines are too long

View file

@ -1 +0,0 @@
import{a as o}from"./vendor-react-BHG7lGYR.js";function c(e,t){const[u,r]=o.useState(e);return o.useEffect(()=>{const n=setTimeout(()=>{r(e)},t);return()=>{clearTimeout(n)}},[e,t]),u}export{c as u};

View file

@ -1 +0,0 @@
import{a as e,j as a}from"./vendor-react-BHG7lGYR.js";import{d as y,l as g,p as j}from"./index-BWcMVITa.js";const I=e.forwardRef(({className:m,label:o,error:t,icon:s,type:n,id:x,...l},h)=>{const i=e.useId(),d=x||i;return a.jsxs("div",{className:"relative group w-full mb-5",children:[a.jsxs("div",{className:"relative",children:[a.jsx("input",{type:n,id:d,className:y("block px-4 pb-2.5 pt-5 w-full text-sm text-white bg-kodo-graphite/40 rounded-xl border appearance-none focus:outline-none focus:ring-0 peer transition-all duration-200",t?"border-kodo-red focus:border-kodo-red":"border-white/10 hover:border-white/20 focus:border-kodo-cyan","backdrop-blur-sm",s?"pl-11":"",m),placeholder:" ",ref:h,...l}),s&&a.jsx("div",{className:"absolute left-3.5 top-1/2 -translate-y-1/2 text-kodo-text-dim peer-focus:text-kodo-cyan transition-colors pointer-events-none",children:s}),a.jsx("label",{htmlFor:d,className:y("absolute text-sm duration-200 transform -translate-y-3 scale-75 top-4 z-10 origin-[0] peer-placeholder-shown:scale-100 peer-placeholder-shown:translate-y-0 peer-focus:scale-75 peer-focus:-translate-y-3 pointer-events-none",s?"left-11 peer-focus:left-11 peer-placeholder-shown:left-11":"left-4 peer-focus:left-4 peer-placeholder-shown:left-4",t?"text-kodo-red":"text-kodo-text-dim peer-focus:text-kodo-cyan group-hover:text-white/70"),children:o})]}),t&&a.jsx("p",{className:"mt-1 text-xs text-kodo-red animate-slideDown",children:t})]})});I.displayName="FloatingInput";function N(m){const{type:o,debounceMs:t=300}=m,[s,n]=e.useState(!1),[x,l]=e.useState([]),[h,i]=e.useState(null),[d,b]=e.useState(null),u=e.useRef(null),r=e.useRef(0),k=e.useCallback(async(w,c)=>{if(!o)return g.warn("[useFormValidation] Validation type is required"),!1;n(!0),b(null);try{return l([]),i(!0),!0}catch(f){if(c!==r.current)return!1;const p=j(f);return b(p),l([]),i(!1),g.error("[useFormValidation] Validation request failed",{error:p.message,type:o}),!1}finally{c===r.current&&n(!1)}},[o]),V=e.useCallback(async w=>{if(t<=0)return r.current+=1,k(w,r.current);u.current&&clearTimeout(u.current),r.current+=1;const c=r.current;return new Promise(f=>{u.current=setTimeout(async()=>{if(c===r.current){const p=await k(w,c);f(p)}else f(!1)},t)})},[t,k]);e.useEffect(()=>()=>{u.current&&clearTimeout(u.current)},[]);const v=e.useCallback(()=>{l([]),i(null),b(null),n(!1)},[]);return{isValidating:s,errors:x,isValid:h,error:d,validate:V,clear:v}}export{I as F,N as u};

View file

@ -1 +0,0 @@
import{a as s,j as r}from"./vendor-react-BHG7lGYR.js";import{d,z as x}from"./index-BWcMVITa.js";import{D as w}from"./dropdown-BYn_8IId.js";import{l as h,au as b}from"./vendor-icons-DaGlTw4_.js";const C=({open:o,onOpenChange:e,children:t})=>{const[n,a]=s.useState(!1),m=o!==void 0,p=l=>{m||a(l),e?.(l)},i=s.Children.toArray(t).find(l=>s.isValidElement(l)&&l.type===c),u=s.Children.toArray(t).find(l=>s.isValidElement(l)&&l.type===f);return!i||!u?r.jsx(r.Fragment,{children:t}):r.jsx(w,{trigger:i,onOpenChange:p,children:s.isValidElement(u)?u.props.children:u})},c=s.forwardRef(({className:o,children:e,asChild:t,...n},a)=>t&&s.isValidElement(e)?s.cloneElement(e,{ref:a,className:d(o,e.props.className),...n}):r.jsx("button",{ref:a,className:d("outline-none",o),...n,children:e}));c.displayName="DropdownMenuTrigger";const f=s.forwardRef(({className:o,align:e="start",sideOffset:t=4,children:n,...a},m)=>r.jsx("div",{ref:m,className:d("z-50 min-w-[8rem] overflow-hidden rounded-md border border-kodo-steel bg-kodo-ink p-1 text-white shadow-lg","animate-fadeIn",o),style:{marginTop:`${t}px`},...a,children:n}));f.displayName="DropdownMenuContent";const y=s.forwardRef(({className:o,inset:e,onKeyDown:t,onClick:n,...a},m)=>{const p=i=>{(i.key==="Enter"||i.key===" ")&&(i.preventDefault(),n&&!a.disabled&&n(i)),t&&t(i)};return r.jsx("button",{ref:m,role:"menuitem",className:d("relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none","transition-colors focus:bg-white/5 focus:text-white disabled:pointer-events-none disabled:opacity-50","text-kodo-text-main hover:text-white w-full text-left",e&&"pl-8",o),onKeyDown:p,onClick:n,...a})});y.displayName="DropdownMenuItem";const D=s.forwardRef(({className:o,children:e,checked:t,onCheckedChange:n,...a},m)=>r.jsxs("button",{ref:m,onClick:()=>n?.(!t),className:d("relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none","transition-colors focus:bg-white/5 focus:text-white disabled:pointer-events-none disabled:opacity-50","text-kodo-text-main hover:text-white w-full text-left",o),...a,children:[r.jsx("span",{className:"absolute left-2 flex h-3.5 w-3.5 items-center justify-center",children:t&&r.jsx(h,{className:"h-4 w-4 text-kodo-steel"})}),e]}));D.displayName="DropdownMenuCheckboxItem";const N=s.forwardRef(({className:o,children:e,checked:t,...n},a)=>r.jsxs("button",{ref:a,className:d("relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none","transition-colors focus:bg-white/5 focus:text-white disabled:pointer-events-none disabled:opacity-50","text-kodo-text-main hover:text-white w-full text-left",o),...n,children:[r.jsx("span",{className:"absolute left-2 flex h-3.5 w-3.5 items-center justify-center",children:t&&r.jsx(b,{className:"h-2 w-2 fill-current text-kodo-steel"})}),e]}));N.displayName="DropdownMenuRadioItem";const g=s.forwardRef(({className:o,inset:e,...t},n)=>r.jsx("div",{ref:n,className:d("px-2 py-1.5 text-sm font-semibold text-kodo-content-dim",e&&"pl-8",o),...t}));g.displayName="DropdownMenuLabel";const j=s.forwardRef(({className:o,...e},t)=>r.jsx("div",{ref:t,className:d("-mx-1 my-1 h-px bg-kodo-steel",o),...e}));j.displayName="DropdownMenuSeparator";function I(){return x(e=>e.isLimited)}export{C as D,c as a,f as b,y as c,I as u};

View file

@ -1 +0,0 @@
import{a as l,j as d}from"./vendor-react-BHG7lGYR.js";import{d as c,x as m}from"./index-BWcMVITa.js";function b({error:s,label:r,className:i,id:a,...e}){const t=l.useId(),o=a||t;return d.jsxs("div",{className:"w-full",children:[r&&d.jsx("label",{htmlFor:o,className:"block text-sm font-medium text-kodo-text-main dark:text-kodo-text-main mb-1",children:r}),d.jsx("input",{id:o,className:c("w-full px-4 py-2 border rounded-lg focus-visible:outline-none focus-visible:ring-0 transition-colors","dark:bg-kodo-graphite dark:text-white dark:border-kodo-steel",s?"border-kodo-red focus-visible:border-kodo-red/80 dark:border-kodo-red":"border-kodo-steel focus-visible:border-kodo-cyan/60 dark:border-kodo-steel",i),"aria-invalid":s?"true":"false","aria-describedby":s?`${o}-error`:void 0,"aria-required":e.required?"true":void 0,...e,autoComplete:e.autoComplete!==void 0?e.autoComplete:e.type==="email"?"email":e.type==="password"?"current-password":void 0,required:e.required}),s&&d.jsx("p",{id:`${o}-error`,className:"mt-1 text-sm text-kodo-red dark:text-kodo-red",role:"alert",children:s})]})}function h(){const[s,r]=l.useState(!1),[i,a]=l.useState(null),[e,t]=l.useState(!1);return{handleRequestReset:async n=>{try{r(!0),a(null),t(!1),await requestPasswordReset(n),t(!0)}catch(u){a(u),t(!1)}finally{r(!1)}},handleReset:async n=>{try{r(!0),a(null),t(!1),await m.resetPassword(n),t(!0)}catch(u){a(u),t(!1)}finally{r(!1)}},loading:s,error:i,success:e}}export{b as A,h as u};

View file

@ -1 +0,0 @@
import{a as t}from"./index-BWcMVITa.js";import{q as u}from"./vendor-IYr-MHu4.js";async function l(r){return(await t.get(`/users/${r}`)).data.profile}async function p(r){const e=await t.get(`/users/by-username/${r}`);return e.data.profile||e.data}async function f(r,e){const s=await t.put(`/users/${r}`,e);return s.data.profile||s.data}async function d(r){return(await t.get(`/users/${r}/completion`)).data}async function w(r){return(await t.post(`/users/${r}/follow`)).data}async function g(r){return(await t.delete(`/users/${r}/follow`)).data}async function h(r,e=1,s=20){return(await t.get(`/users/${r}/followers`,{params:{page:e,limit:s}})).data}async function m(r,e=1,s=20){return(await t.get(`/users/${r}/following`,{params:{page:e,limit:s}})).data}async function E(r){try{return(await t.get(`/users/${r}/settings`)).data}catch(e){if(e instanceof u){if(e.response?.status===401)throw new Error("Unauthorized: Please log in to access settings");if(e.response?.status===403)throw new Error("Forbidden: You cannot access these settings");if(e.response?.status===404)throw new Error("Settings not found");const s=e.response?.data?.error||e.message||"Failed to fetch settings";throw new Error(s)}throw e}}async function y(r,e){try{await t.put("/users/settings",e)}catch(s){if(s instanceof u){if(s.response?.status===400){const o=s.response?.data?.error||"Invalid settings data";throw new Error(o)}if(s.response?.status===401)throw new Error("Unauthorized: Please log in to update settings");if(s.response?.status===403)throw new Error("Forbidden: You cannot update these settings");if(s.response?.status===404)throw new Error("Settings not found");const a=s.response?.data?.error||s.message||"Failed to update settings";throw new Error(a)}throw s}}class i extends Error{constructor(e,s){super(e),this.code=s,this.name="AvatarUploadError"}}async function $(r,e,s){const a=new FormData;a.append("avatar",e);try{return(await t.post(`/users/${r}/avatar`,a,{headers:{"Content-Type":"multipart/form-data"},onUploadProgress:n=>{if(n.total&&s){const c=Math.round(n.loaded*100/n.total);s(c)}}})).data}catch(o){if(o instanceof u){if(o.response){const n=o.response.status;throw n===400?new i(o.response.data?.error||"Format ou taille de fichier invalide","VALIDATION"):n===413?new i("Fichier trop volumineux (max 5MB)","VALIDATION"):n>=500?new i("Erreur serveur. Veuillez réessayer.","SERVER"):new i(o.response.data?.error||"Erreur lors de l'upload","SERVER")}else if(o.request)throw new i("Erreur de connexion. Vérifiez votre connexion internet.","NETWORK")}throw new i("Erreur inconnue","UNKNOWN")}}async function v(r){await t.delete(`/users/${r}/avatar`)}const U={getProfile:l,getProfileByUsername:p,updateProfile:f,calculateProfileCompletion:d,follow:w,unfollow:g,getFollowers:h,getFollowing:m,getSettings:E,updateSettings:y,uploadAvatar:$,deleteAvatar:v};export{g as a,w as f,l as g,U as u};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1,002 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 638 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 791 B

View file

@ -1,102 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Veza - Plateforme de streaming musical</title>
<!-- Google Fonts for Design System -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<!-- PERF: Preload fonts critiques uniquement, utiliser font-display: swap -->
<link
href="https://fonts.googleapis.com/css2?family=Orbitron:wght@400;500;600;700;900&family=Rajdhani:wght@300;400;500;600;700&family=Inter:wght@300;400;500;600;700;900&family=Source+Serif+4:opsz,wght@8..60,400;8..60,500;8..60,600&family=JetBrains+Mono:wght@300;400;500;600;700&family=IBM+Plex+Mono:wght@400;500&family=Noto+Sans+JP:wght@300;400;500;700;900&display=swap"
rel="stylesheet">
<!-- PERF: Preload stratégique des chunks vendors critiques (sera injecté par Vite en production) -->
<!-- Les hashs seront générés automatiquement lors du build -->
<!-- PWA Manifest -->
<link rel="manifest" href="/manifest.json" />
<!-- PWA Meta Tags -->
<meta name="theme-color" content="#1a1a1a" />
<meta name="mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
<meta name="apple-mobile-web-app-title" content="Veza" />
<!-- Apple Touch Icons -->
<link rel="apple-touch-icon" href="/icons/icon-152x152.png" />
<link rel="apple-touch-icon" sizes="72x72" href="/icons/icon-72x72.png" />
<link rel="apple-touch-icon" sizes="96x96" href="/icons/icon-96x96.png" />
<link rel="apple-touch-icon" sizes="128x128" href="/icons/icon-128x128.png" />
<link rel="apple-touch-icon" sizes="144x144" href="/icons/icon-144x144.png" />
<link rel="apple-touch-icon" sizes="152x152" href="/icons/icon-152x152.png" />
<link rel="apple-touch-icon" sizes="192x192" href="/icons/icon-192x192.png" />
<link rel="apple-touch-icon" sizes="384x384" href="/icons/icon-384x384.png" />
<link rel="apple-touch-icon" sizes="512x512" href="/icons/icon-512x512.png" />
<!-- Microsoft Tiles -->
<meta name="msapplication-TileColor" content="#1a1a1a" />
<meta name="msapplication-TileImage" content="/icons/icon-144x144.png" />
<!-- SEO and Social -->
<meta name="description" content="Plateforme de streaming, collaboration et distribution musicale moderne" />
<meta name="keywords" content="music, streaming, collaboration, audio, chat, veza" />
<meta name="author" content="Veza Platform Team" />
<!-- Open Graph -->
<meta property="og:title" content="Veza Platform" />
<meta property="og:description" content="Plateforme de streaming, collaboration et distribution musicale moderne" />
<meta property="og:type" content="website" />
<meta property="og:image" content="/icons/icon-512x512.png" />
<!-- Twitter Card -->
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="Veza Platform" />
<meta name="twitter:description" content="Plateforme de streaming, collaboration et distribution musicale moderne" />
<meta name="twitter:image" content="/icons/icon-512x512.png" />
<!-- Theme Script to prevent FOUC -->
<script>
(function() {
const storageKey = 'vite-ui-theme';
const defaultTheme = 'dark';
try {
const theme = localStorage.getItem(storageKey) || defaultTheme;
const root = window.document.documentElement;
root.classList.remove('light', 'dark');
if (theme === 'system') {
const systemTheme = window.matchMedia('(prefers-color-scheme: dark)').matches
? 'dark'
: 'light';
root.classList.add(systemTheme);
} else {
root.classList.add(theme);
}
} catch (e) {
console.error('Failed to set initial theme', e);
}
})();
</script>
<script type="module" crossorigin src="/assets/index-BWcMVITa.js"></script>
<link rel="modulepreload" crossorigin href="/assets/vendor-IYr-MHu4.js">
<link rel="modulepreload" crossorigin href="/assets/vendor-react-BHG7lGYR.js">
<link rel="modulepreload" crossorigin href="/assets/vendor-router-D-s5vIeO.js">
<link rel="modulepreload" crossorigin href="/assets/vendor-tanstack-BzWBL1hV.js">
<link rel="modulepreload" crossorigin href="/assets/vendor-utils-CgOSfOkx.js">
<link rel="modulepreload" crossorigin href="/assets/vendor-icons-DaGlTw4_.js">
<link rel="stylesheet" crossorigin href="/assets/vendor-BD_zwJK7.css">
<link rel="stylesheet" crossorigin href="/assets/index-COF3NoTx.css">
</head>
<body>
<div id="root"></div>
</body>
</html>

View file

@ -1,99 +0,0 @@
{
"name": "Veza Platform",
"short_name": "Veza",
"description": "Plateforme de streaming, collaboration et distribution musicale moderne",
"theme_color": "#1a1a1a",
"background_color": "#ffffff",
"display": "standalone",
"orientation": "portrait",
"scope": "/",
"start_url": "/",
"icons": [
{
"src": "/icons/icon-72x72.png",
"sizes": "72x72",
"type": "image/png",
"purpose": "maskable any"
},
{
"src": "/icons/icon-96x96.png",
"sizes": "96x96",
"type": "image/png",
"purpose": "maskable any"
},
{
"src": "/icons/icon-128x128.png",
"sizes": "128x128",
"type": "image/png",
"purpose": "maskable any"
},
{
"src": "/icons/icon-144x144.png",
"sizes": "144x144",
"type": "image/png",
"purpose": "maskable any"
},
{
"src": "/icons/icon-152x152.png",
"sizes": "152x152",
"type": "image/png",
"purpose": "maskable any"
},
{
"src": "/icons/icon-192x192.png",
"sizes": "192x192",
"type": "image/png",
"purpose": "maskable any"
},
{
"src": "/icons/icon-384x384.png",
"sizes": "384x384",
"type": "image/png",
"purpose": "maskable any"
},
{
"src": "/icons/icon-512x512.png",
"sizes": "512x512",
"type": "image/png",
"purpose": "maskable any"
}
],
"shortcuts": [
{
"name": "Dashboard",
"short_name": "Dashboard",
"description": "Accéder au tableau de bord",
"url": "/dashboard",
"icons": [{ "src": "/icons/dashboard-96x96.png", "sizes": "96x96" }]
},
{
"name": "Chat",
"short_name": "Chat",
"description": "Ouvrir le chat",
"url": "/chat",
"icons": [{ "src": "/icons/chat-96x96.png", "sizes": "96x96" }]
},
{
"name": "Bibliothèque",
"short_name": "Library",
"description": "Parcourir la bibliothèque musicale",
"url": "/library",
"icons": [{ "src": "/icons/library-96x96.png", "sizes": "96x96" }]
}
],
"categories": ["music", "entertainment", "social"],
"screenshots": [
{
"src": "/screenshots/dashboard-wide.png",
"sizes": "1280x720",
"type": "image/png",
"form_factor": "wide"
},
{
"src": "/screenshots/dashboard-narrow.png",
"sizes": "375x812",
"type": "image/png",
"form_factor": "narrow"
}
]
}

View file

@ -1,349 +0,0 @@
/* eslint-disable */
/* tslint:disable */
/**
* Mock Service Worker.
* @see https://github.com/mswjs/msw
* - Please do NOT modify this file.
*/
const PACKAGE_VERSION = '2.12.3'
const INTEGRITY_CHECKSUM = '4db4a41e972cec1b64cc569c66952d82'
const IS_MOCKED_RESPONSE = Symbol('isMockedResponse')
const activeClientIds = new Set()
addEventListener('install', function () {
self.skipWaiting()
})
addEventListener('activate', function (event) {
event.waitUntil(self.clients.claim())
})
addEventListener('message', async function (event) {
const clientId = Reflect.get(event.source || {}, 'id')
if (!clientId || !self.clients) {
return
}
const client = await self.clients.get(clientId)
if (!client) {
return
}
const allClients = await self.clients.matchAll({
type: 'window',
})
switch (event.data) {
case 'KEEPALIVE_REQUEST': {
sendToClient(client, {
type: 'KEEPALIVE_RESPONSE',
})
break
}
case 'INTEGRITY_CHECK_REQUEST': {
sendToClient(client, {
type: 'INTEGRITY_CHECK_RESPONSE',
payload: {
packageVersion: PACKAGE_VERSION,
checksum: INTEGRITY_CHECKSUM,
},
})
break
}
case 'MOCK_ACTIVATE': {
activeClientIds.add(clientId)
sendToClient(client, {
type: 'MOCKING_ENABLED',
payload: {
client: {
id: client.id,
frameType: client.frameType,
},
},
})
break
}
case 'CLIENT_CLOSED': {
activeClientIds.delete(clientId)
const remainingClients = allClients.filter((client) => {
return client.id !== clientId
})
// Unregister itself when there are no more clients
if (remainingClients.length === 0) {
self.registration.unregister()
}
break
}
}
})
addEventListener('fetch', function (event) {
const requestInterceptedAt = Date.now()
// Bypass navigation requests.
if (event.request.mode === 'navigate') {
return
}
// Opening the DevTools triggers the "only-if-cached" request
// that cannot be handled by the worker. Bypass such requests.
if (
event.request.cache === 'only-if-cached' &&
event.request.mode !== 'same-origin'
) {
return
}
// Bypass all requests when there are no active clients.
// Prevents the self-unregistered worked from handling requests
// after it's been terminated (still remains active until the next reload).
if (activeClientIds.size === 0) {
return
}
const requestId = crypto.randomUUID()
event.respondWith(handleRequest(event, requestId, requestInterceptedAt))
})
/**
* @param {FetchEvent} event
* @param {string} requestId
* @param {number} requestInterceptedAt
*/
async function handleRequest(event, requestId, requestInterceptedAt) {
const client = await resolveMainClient(event)
const requestCloneForEvents = event.request.clone()
const response = await getResponse(
event,
client,
requestId,
requestInterceptedAt,
)
// Send back the response clone for the "response:*" life-cycle events.
// Ensure MSW is active and ready to handle the message, otherwise
// this message will pend indefinitely.
if (client && activeClientIds.has(client.id)) {
const serializedRequest = await serializeRequest(requestCloneForEvents)
// Clone the response so both the client and the library could consume it.
const responseClone = response.clone()
sendToClient(
client,
{
type: 'RESPONSE',
payload: {
isMockedResponse: IS_MOCKED_RESPONSE in response,
request: {
id: requestId,
...serializedRequest,
},
response: {
type: responseClone.type,
status: responseClone.status,
statusText: responseClone.statusText,
headers: Object.fromEntries(responseClone.headers.entries()),
body: responseClone.body,
},
},
},
responseClone.body ? [serializedRequest.body, responseClone.body] : [],
)
}
return response
}
/**
* Resolve the main client for the given event.
* Client that issues a request doesn't necessarily equal the client
* that registered the worker. It's with the latter the worker should
* communicate with during the response resolving phase.
* @param {FetchEvent} event
* @returns {Promise<Client | undefined>}
*/
async function resolveMainClient(event) {
const client = await self.clients.get(event.clientId)
if (activeClientIds.has(event.clientId)) {
return client
}
if (client?.frameType === 'top-level') {
return client
}
const allClients = await self.clients.matchAll({
type: 'window',
})
return allClients
.filter((client) => {
// Get only those clients that are currently visible.
return client.visibilityState === 'visible'
})
.find((client) => {
// Find the client ID that's recorded in the
// set of clients that have registered the worker.
return activeClientIds.has(client.id)
})
}
/**
* @param {FetchEvent} event
* @param {Client | undefined} client
* @param {string} requestId
* @param {number} requestInterceptedAt
* @returns {Promise<Response>}
*/
async function getResponse(event, client, requestId, requestInterceptedAt) {
// Clone the request because it might've been already used
// (i.e. its body has been read and sent to the client).
const requestClone = event.request.clone()
function passthrough() {
// Cast the request headers to a new Headers instance
// so the headers can be manipulated with.
const headers = new Headers(requestClone.headers)
// Remove the "accept" header value that marked this request as passthrough.
// This prevents request alteration and also keeps it compliant with the
// user-defined CORS policies.
const acceptHeader = headers.get('accept')
if (acceptHeader) {
const values = acceptHeader.split(',').map((value) => value.trim())
const filteredValues = values.filter(
(value) => value !== 'msw/passthrough',
)
if (filteredValues.length > 0) {
headers.set('accept', filteredValues.join(', '))
} else {
headers.delete('accept')
}
}
return fetch(requestClone, { headers })
}
// Bypass mocking when the client is not active.
if (!client) {
return passthrough()
}
// Bypass initial page load requests (i.e. static assets).
// The absence of the immediate/parent client in the map of the active clients
// means that MSW hasn't dispatched the "MOCK_ACTIVATE" event yet
// and is not ready to handle requests.
if (!activeClientIds.has(client.id)) {
return passthrough()
}
// Notify the client that a request has been intercepted.
const serializedRequest = await serializeRequest(event.request)
const clientMessage = await sendToClient(
client,
{
type: 'REQUEST',
payload: {
id: requestId,
interceptedAt: requestInterceptedAt,
...serializedRequest,
},
},
[serializedRequest.body],
)
switch (clientMessage.type) {
case 'MOCK_RESPONSE': {
return respondWithMock(clientMessage.data)
}
case 'PASSTHROUGH': {
return passthrough()
}
}
return passthrough()
}
/**
* @param {Client} client
* @param {any} message
* @param {Array<Transferable>} transferrables
* @returns {Promise<any>}
*/
function sendToClient(client, message, transferrables = []) {
return new Promise((resolve, reject) => {
const channel = new MessageChannel()
channel.port1.onmessage = (event) => {
if (event.data && event.data.error) {
return reject(event.data.error)
}
resolve(event.data)
}
client.postMessage(message, [
channel.port2,
...transferrables.filter(Boolean),
])
})
}
/**
* @param {Response} response
* @returns {Response}
*/
function respondWithMock(response) {
// Setting response status code to 0 is a no-op.
// However, when responding with a "Response.error()", the produced Response
// instance will have status code set to 0. Since it's not possible to create
// a Response instance with status code 0, handle that use-case separately.
if (response.status === 0) {
return Response.error()
}
const mockedResponse = new Response(response.body, response)
Reflect.defineProperty(mockedResponse, IS_MOCKED_RESPONSE, {
value: true,
enumerable: true,
})
return mockedResponse
}
/**
* @param {Request} request
*/
async function serializeRequest(request) {
return {
url: request.url,
mode: request.mode,
method: request.method,
headers: Object.fromEntries(request.headers.entries()),
cache: request.cache,
credentials: request.credentials,
destination: request.destination,
integrity: request.integrity,
redirect: request.redirect,
referrer: request.referrer,
referrerPolicy: request.referrerPolicy,
body: await request.arrayBuffer(),
keepalive: request.keepalive,
}
}

View file

@ -1,396 +0,0 @@
// Veza Platform Service Worker
// Version 1.0.0
const CACHE_VERSION = '__BUILD_VERSION__';
const CACHE_NAME = `veza-platform-${CACHE_VERSION}`;
const STATIC_CACHE_NAME = `veza-static-${CACHE_VERSION}`;
const DYNAMIC_CACHE_NAME = `veza-dynamic-${CACHE_VERSION}`;
// Files to cache on install
const STATIC_ASSETS = [
'/',
'/dashboard',
'/chat',
'/library',
'/profile',
'/settings',
'/manifest.json',
'/icons/icon-192x192.png',
'/icons/icon-512x512.png'
];
// API endpoints to cache with network-first strategy
const API_CACHE_PATTERNS = [
/^https?:\/\/.*\/api\/v1\/user\/profile$/,
/^https?:\/\/.*\/api\/v1\/library\/files$/,
/^https?:\/\/.*\/api\/v1\/dashboard\/stats$/
];
// Install event - cache static assets
// CRITICAL FIX: Service Worker disabled - this code is kept for reference but should not execute
// The Service Worker registration is disabled in pwa.ts to prevent React.Children cache issues
self.addEventListener('install', (event) => {
console.log('[SW] Service Worker install event - DISABLED to prevent cache conflicts');
// CRITICAL FIX: Skip waiting and immediately activate to avoid caching old chunks
event.waitUntil(
Promise.all([
// Delete all existing caches to prevent serving old JS chunks
caches.keys().then((cacheNames) => {
return Promise.all(
cacheNames.map((cacheName) => {
console.log('[SW] Deleting old cache:', cacheName);
return caches.delete(cacheName);
})
);
}),
// Skip waiting immediately
self.skipWaiting()
]).then(() => {
console.log('[SW] All caches cleared, skipping waiting');
})
);
});
// Activate event - clean old caches
// CRITICAL FIX: Aggressively clear all caches to prevent serving old JS chunks
self.addEventListener('activate', (event) => {
console.log('[SW] Activating service worker - clearing all caches');
event.waitUntil(
Promise.all([
// Delete ALL caches to prevent serving old JS chunks
caches.keys().then((cacheNames) => {
return Promise.all(
cacheNames.map((cacheName) => {
console.log('[SW] Deleting cache:', cacheName);
return caches.delete(cacheName);
})
);
}),
// Take control immediately
self.clients.claim()
]).then(() => {
console.log('[SW] All caches cleared, service worker activated');
})
);
});
// Fetch event - handle requests with appropriate caching strategy
self.addEventListener('fetch', (event) => {
const { request } = event;
const url = new URL(request.url);
// Skip non-GET requests
if (request.method !== 'GET') {
return;
}
// Skip WebSocket connections
if (request.headers.get('upgrade') === 'websocket') {
return;
}
// CRITICAL FIX: Skip service worker registration and JS chunks to avoid blocking
// These must always come from network to ensure latest code
if (url.pathname.includes('/sw.js') ||
url.pathname.includes('/js/') ||
url.pathname.includes('/assets/')) {
return; // Let browser fetch directly from network
}
// Skip external requests (except API)
if (!url.origin.includes(self.location.origin) && !isApiRequest(request.url)) {
return;
}
event.respondWith(
handleRequest(request)
);
});
// Handle different types of requests with appropriate strategies
async function handleRequest(request) {
try {
// Strategy 1: Cache First for static assets
if (isStaticAsset(request.url)) {
return await cacheFirst(request, STATIC_CACHE_NAME);
}
// Strategy 2: Network First for API requests
if (isApiRequest(request.url)) {
return await networkFirst(request, DYNAMIC_CACHE_NAME);
}
// Strategy 3: Stale While Revalidate for pages
if (isPageRequest(request.url)) {
return await staleWhileRevalidate(request, DYNAMIC_CACHE_NAME);
}
// Default: Network only
return await fetch(request);
} catch (error) {
console.error('[SW] Request failed:', error);
// Return offline page for navigation requests
if (isPageRequest(request.url)) {
return await getOfflinePage();
}
// Return cached version if available
const cachedResponse = await caches.match(request);
if (cachedResponse) {
return cachedResponse;
}
// Return generic offline response
return new Response('Offline', {
status: 503,
statusText: 'Service Unavailable'
});
}
}
// Cache First strategy
async function cacheFirst(request, cacheName) {
const cachedResponse = await caches.match(request);
if (cachedResponse) {
return cachedResponse;
}
const networkResponse = await fetch(request);
if (networkResponse.ok) {
const cache = await caches.open(cacheName);
cache.put(request, networkResponse.clone());
}
return networkResponse;
}
// Network First strategy
async function networkFirst(request, cacheName) {
try {
const networkResponse = await fetch(request);
if (networkResponse.ok) {
const cache = await caches.open(cacheName);
cache.put(request, networkResponse.clone());
}
return networkResponse;
} catch (error) {
const cachedResponse = await caches.match(request);
if (cachedResponse) {
console.log('[SW] Serving cached API response');
return cachedResponse;
}
throw error;
}
}
// Stale While Revalidate strategy
// CORRECTION DURABLE: Clone la réponse IMMÉDIATEMENT pour éviter "Response body is already used"
async function staleWhileRevalidate(request, cacheName) {
const cachedResponse = await caches.match(request);
const networkResponsePromise = fetch(request)
.then((networkResponse) => {
if (networkResponse.ok) {
// ✅ Cloner IMMÉDIATEMENT la réponse avant toute autre opération
const responseToCache = networkResponse.clone();
// Mettre en cache de manière asynchrone (sans bloquer)
caches.open(cacheName).then((cache) => {
cache.put(request, responseToCache).catch((err) => {
console.warn('[SW] Failed to cache response:', err);
});
});
}
return networkResponse;
})
.catch(() => null);
return cachedResponse || await networkResponsePromise;
}
// Get offline page
async function getOfflinePage() {
const cache = await caches.open(STATIC_CACHE_NAME);
const offlineResponse = await cache.match('/');
if (offlineResponse) {
return offlineResponse;
}
return new Response(`
<!DOCTYPE html>
<html>
<head>
<title>Veza - Hors ligne</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
body {
font-family: system-ui, sans-serif;
text-align: center;
padding: 2rem;
background: #1a1a1a;
color: white;
}
.offline-container {
max-width: 400px;
margin: 0 auto;
padding: 2rem;
border-radius: 8px;
background: #2a2a2a;
}
.offline-icon {
font-size: 4rem;
margin-bottom: 1rem;
}
</style>
</head>
<body>
<div class="offline-container">
<div class="offline-icon">📱</div>
<h1>Veza - Mode Hors Ligne</h1>
<p>Vous êtes actuellement hors ligne. Certaines fonctionnalités peuvent être limitées.</p>
<button onclick="window.location.reload()">Réessayer</button>
</div>
</body>
</html>
`, {
headers: { 'Content-Type': 'text/html' }
});
}
// Helper functions
function isStaticAsset(url) {
return /\.(js|css|png|jpg|jpeg|gif|svg|woff|woff2|ttf|eot|ico)(\?.*)?$/.test(url);
}
function isApiRequest(url) {
return url.includes('/api/') || API_CACHE_PATTERNS.some(pattern => pattern.test(url));
}
function isPageRequest(url) {
const urlObj = new URL(url);
return urlObj.pathname.match(/^\/[^.]*$/) && !isApiRequest(url);
}
// Message handling for communication with the main thread
self.addEventListener('message', (event) => {
const { type } = event.data;
switch (type) {
case 'SKIP_WAITING':
self.skipWaiting();
break;
case 'GET_VERSION':
event.ports[0].postMessage({
type: 'VERSION',
payload: { version: CACHE_NAME }
});
break;
case 'CLEAR_CACHE':
caches.keys().then((cacheNames) => {
return Promise.all(
cacheNames.map((cacheName) => caches.delete(cacheName))
);
}).then(() => {
event.ports[0].postMessage({
type: 'CACHE_CLEARED',
payload: { success: true }
});
});
break;
default:
console.log('[SW] Unknown message type:', type);
}
});
// Background sync for offline actions
self.addEventListener('sync', (event) => {
if (event.tag === 'background-sync') {
event.waitUntil(doBackgroundSync());
}
});
async function doBackgroundSync() {
console.log('[SW] Performing background sync...');
// Implement background sync logic here
// For example: sync offline messages, upload queued files, etc.
}
// Push notifications
self.addEventListener('push', (event) => {
if (!event.data) {
return;
}
const data = event.data.json();
const options = {
body: data.body,
icon: '/icons/icon-192x192.png',
badge: '/icons/badge-72x72.png',
vibrate: [100, 50, 100],
data: {
dateOfArrival: Date.now(),
primaryKey: data.primaryKey || 1,
url: data.url || '/'
},
actions: [
{
action: 'explore',
title: 'Ouvrir',
icon: '/icons/checkmark.png'
},
{
action: 'close',
title: 'Fermer',
icon: '/icons/xmark.png'
}
]
};
event.waitUntil(
self.registration.showNotification(data.title, options)
);
});
// Notification click handling
self.addEventListener('notificationclick', (event) => {
event.notification.close();
if (event.action === 'close') {
return;
}
const urlToOpen = event.notification.data?.url || '/';
event.waitUntil(
self.clients.matchAll({ type: 'window' }).then((clientList) => {
// Check if a window is already open
for (const client of clientList) {
if (client.url === urlToOpen && 'focus' in client) {
return client.focus();
}
}
// Open a new window
if (self.clients.openWindow) {
return self.clients.openWindow(urlToOpen);
}
})
);
});
console.log('[SW] Veza Platform Service Worker loaded');

View file

@ -7,7 +7,7 @@
* - Please do NOT modify this file.
*/
const PACKAGE_VERSION = '2.12.3'
const PACKAGE_VERSION = '2.12.7'
const INTEGRITY_CHECKSUM = '4db4a41e972cec1b64cc569c66952d82'
const IS_MOCKED_RESPONSE = Symbol('isMockedResponse')
const activeClientIds = new Set()

View file

@ -0,0 +1,53 @@
import fs from 'fs';
import path from 'path';
// Fix type: "module" issue by using readFileSync if running as module or just basic node
// but easier to just use standard require if not module, or import fs if module.
// Package.json says type: module, so imports are fine.
try {
const errorData = JSON.parse(fs.readFileSync('storybook_errors.json', 'utf8'));
const totalFailed = Object.keys(errorData).length;
const stats = {
totalFailed,
byType: {},
commonMessages: {}
};
for (const [storyId, errors] of Object.entries(errorData)) {
for (const error of errors) {
let type = 'Unknown';
if (error.startsWith('Console:')) type = 'Console';
if (error.startsWith('PageError:')) type = 'PageError';
if (error.startsWith('NetworkFail:')) type = 'NetworkFail';
if (error.startsWith('Navigation:')) type = 'Navigation';
stats.byType[type] = (stats.byType[type] || 0) + 1;
// Extract core message for grouping
const message = error.substring(error.indexOf(':') + 1).trim();
// Truncate simple variable parts
const cleanMessage = message.split(' at ')[0].substring(0, 100);
stats.commonMessages[cleanMessage] = (stats.commonMessages[cleanMessage] || 0) + 1;
}
}
console.log('--- Error Summary ---');
console.log(`Total Stories with Errors: ${stats.totalFailed}`);
console.log('\nErrors by Type:');
console.table(stats.byType);
console.log('\nTop 10 Common Error Messages:');
const sortedMessages = Object.entries(stats.commonMessages)
.sort((a, b) => b[1] - a[1])
.slice(0, 10);
sortedMessages.forEach(([msg, count]) => {
console.log(`${count}x: ${msg}`);
});
} catch (e) {
console.error('Failed to parse errors:', e);
}

View file

@ -0,0 +1,33 @@
import { chromium } from 'playwright';
async function debugStory(storyId) {
const browser = await chromium.launch();
const page = await browser.newPage();
const storyUrl = `http://localhost:6007/iframe.html?id=${storyId}&viewMode=story`;
console.log(`Navigating to ${storyUrl}`);
const errors = [];
page.on('pageerror', err => errors.push(`PageError: ${err.message}`));
page.on('console', msg => {
if (msg.type() === 'error') errors.push(`ConsoleError: ${msg.text()}`);
});
page.on('requestfailed', request => {
errors.push(`NetworkFail: ${request.failure().errorText} ${request.url()}`);
});
try {
await page.goto(storyUrl, { waitUntil: 'networkidle' });
// Wait a bit for async errors
await page.waitForTimeout(2000);
} catch (e) {
errors.push(`NavigationError: ${e.message}`);
}
console.log('Errors found:', JSON.stringify(errors, null, 2));
await browser.close();
}
const storyId = process.argv[2] || 'components-admin-adminauditlogsview--default';
debugStory(storyId);

View file

@ -0,0 +1,106 @@
#!/usr/bin/env python3
"""
Script to wrap MSW handler responses in the correct API format.
Converts: HttpResponse.json({ data })
To: HttpResponse.json({ success: true, data: { data } })
"""
import re
import sys
def wrap_handler_response(content):
"""
Find and wrap MSW handler responses that aren't already wrapped.
"""
# Pattern to match http.get/post/etc handlers
# This matches: http.METHOD('pattern', (...) => { return HttpResponse.json({ ... }); })
lines = content.split('\n')
result = []
i = 0
while i < len(lines):
line = lines[i]
# Check if this is a handler definition
if re.match(r'\s*http\.(get|post|put|delete|patch|all)\(', line):
# Find the return HttpResponse.json statement
handler_start = i
brace_count = 0
in_handler = False
for j in range(i, min(i + 100, len(lines))): # Look ahead up to 100 lines
current_line = lines[j]
# Track braces to know when we're inside the handler
brace_count += current_line.count('{') - current_line.count('}')
# Look for HttpResponse.json(
if 'HttpResponse.json(' in current_line:
# Check if already wrapped (has 'success: true')
# Look ahead a few lines to see if success: true exists
is_wrapped = False
for k in range(j, min(j + 5, len(lines))):
if 'success:' in lines[k] or 'success :' in lines[k]:
is_wrapped = True
break
if not is_wrapped and 'message:' not in current_line:
# This needs wrapping
# Find the opening brace after HttpResponse.json(
indent = len(current_line) - len(current_line.lstrip())
# Add the wrapper
result.append(current_line.replace(
'HttpResponse.json({',
'HttpResponse.json({\n' + ' ' * (indent + 2) + 'success: true,\n' + ' ' * (indent + 2) + 'data: {'
))
# Now we need to find the closing brace and add an extra }
json_brace_count = 1
for k in range(j + 1, len(lines)):
check_line = lines[k]
json_brace_count += check_line.count('{') - check_line.count('}')
if json_brace_count == 0:
# This is the closing brace
# Add extra closing brace before this one
result.append(' ' * (indent + 2) + '}')
result.append(check_line)
i = k + 1
break
else:
result.append(check_line)
break
else:
# Already wrapped or special case, just copy
result.append(current_line)
i = j + 1
break
elif j == i + 99 or (j > i and brace_count == 0):
# Didn't find HttpResponse.json, just copy the line
result.append(line)
i += 1
break
else:
result.append(line)
i += 1
return '\n'.join(result)
if __name__ == '__main__':
if len(sys.argv) != 2:
print("Usage: python wrap_msw_handlers.py <handlers_file>")
sys.exit(1)
filepath = sys.argv[1]
with open(filepath, 'r') as f:
content = f.read()
wrapped_content = wrap_handler_response(content)
with open(filepath, 'w') as f:
f.write(wrapped_content)
print(f"✅ Wrapped MSW handlers in {filepath}")

View file

@ -8,7 +8,7 @@ import { AdminAuditLogsView } from './AdminAuditLogsView';
* filtrage et détails contextuels.
*/
const meta: Meta<typeof AdminAuditLogsView> = {
title: 'Components/Admin/AdminAuditLogsView',
title: 'Components/Features/Admin/AdminAuditLogsView',
component: AdminAuditLogsView,
parameters: {
layout: 'fullscreen',

View file

@ -9,7 +9,7 @@ import { ToastProvider } from '../../components/feedback/ToastProvider';
* visualisation du trafic, queue de modération et logs système.
*/
const meta: Meta<typeof AdminDashboardView> = {
title: 'Components/Admin/AdminDashboardView',
title: 'Components/Features/Admin/AdminDashboardView',
component: AdminDashboardView,
parameters: {
layout: 'fullscreen',

View file

@ -9,7 +9,7 @@ import { ToastProvider } from '../../components/feedback/ToastProvider';
* pour pending/reviewed/resolved et actions de modération.
*/
const meta: Meta<typeof AdminModerationView> = {
title: 'Components/Admin/AdminModerationView',
title: 'Components/Features/Admin/AdminModerationView',
component: AdminModerationView,
parameters: {
layout: 'fullscreen',

View file

@ -8,7 +8,7 @@ import { AdminSettingsView } from './AdminSettingsView';
* mode maintenance et annonces globales.
*/
const meta: Meta<typeof AdminSettingsView> = {
title: 'Components/Admin/AdminSettingsView',
title: 'Components/Features/Admin/AdminSettingsView',
component: AdminSettingsView,
parameters: {
layout: 'padded',

View file

@ -8,7 +8,7 @@ import { AdminUsersView } from './AdminUsersView';
* et actions de modération (ban, suppression, rôles).
*/
const meta: Meta<typeof AdminUsersView> = {
title: 'Components/Admin/AdminUsersView',
title: 'Components/Features/Admin/AdminUsersView',
component: AdminUsersView,
parameters: {
layout: 'fullscreen',

View file

@ -25,7 +25,7 @@ const createMockUser = (overrides: Partial<User> = {}): User => ({
* avec menu d'actions contextuel.
*/
const meta: Meta<typeof UserTableRow> = {
title: 'Components/Admin/UserTableRow',
title: 'Components/Features/Admin/UserTableRow',
component: UserTableRow,
parameters: {
docs: {

View file

@ -9,7 +9,7 @@ import { BanUserModal } from './BanUserModal';
* d'un utilisateur avec raison, durée et notes internes.
*/
const meta: Meta<typeof BanUserModal> = {
title: 'Components/Admin/Modals/BanUserModal',
title: 'Components/Features/Admin/Modals/BanUserModal',
component: BanUserModal,
parameters: {
layout: 'centered',

View file

@ -2,7 +2,7 @@ import type { Meta, StoryObj } from '@storybook/react';
import { TrackAnalyticsView } from './TrackAnalyticsView';
const meta: Meta<typeof TrackAnalyticsView> = {
title: 'Components/Analytics/TrackAnalyticsView',
title: 'Components/Features/Analytics/TrackAnalyticsView',
component: TrackAnalyticsView,
parameters: { layout: 'padded' },
tags: ['autodocs'],

View file

@ -37,7 +37,7 @@ const MOCK_ITEM = {
};
const meta: Meta<typeof CartItem> = {
title: 'Components/Commerce/CartItem',
title: 'Components/Features/Commerce/CartItem',
component: CartItem,
parameters: { layout: 'padded' },
tags: ['autodocs'],

View file

@ -2,7 +2,7 @@ import type { Meta, StoryObj } from '@storybook/react';
import { OrderSummary } from './OrderSummary';
const meta: Meta<typeof OrderSummary> = {
title: 'Components/Commerce/OrderSummary',
title: 'Components/Features/Commerce/OrderSummary',
component: OrderSummary,
parameters: { layout: 'padded' },
tags: ['autodocs'],

View file

@ -4,7 +4,7 @@ import { WishlistView } from './WishlistView';
import { ToastProvider } from '../../components/feedback/ToastProvider';
const meta: Meta<typeof WishlistView> = {
title: 'Components/Commerce/WishlistView',
title: 'Components/Features/Commerce/WishlistView',
component: WishlistView,
parameters: { layout: 'fullscreen' },
tags: ['autodocs'],

View file

@ -2,7 +2,7 @@ import type { Meta, StoryObj } from '@storybook/react';
import { ActivityGraph } from './ActivityGraph';
const meta = {
title: 'Components/Dashboard/ActivityGraph',
title: 'Components/Features/Dashboard/ActivityGraph',
component: ActivityGraph,
tags: ['autodocs'],
decorators: [

View file

@ -3,7 +3,7 @@ import { StatCard } from './StatCard';
import { Activity, Music, Users, DollarSign } from 'lucide-react';
const meta = {
title: 'Components/Dashboard/StatCard',
title: 'Components/Features/Dashboard/StatCard',
component: StatCard,
tags: ['autodocs'],
decorators: [

View file

@ -2,7 +2,7 @@ import type { Meta, StoryObj } from '@storybook/react';
import { TrackList } from './TrackList';
const meta = {
title: 'Components/Dashboard/TrackList',
title: 'Components/Features/Dashboard/TrackList',
component: TrackList,
tags: ['autodocs'],
} satisfies Meta<typeof TrackList>;

View file

@ -2,7 +2,7 @@ import type { Meta, StoryObj } from '@storybook/react';
import { APIPlaygroundView } from './APIPlaygroundView';
const meta: Meta<typeof APIPlaygroundView> = {
title: 'Components/Developer/APIPlaygroundView',
title: 'Components/Features/Developer/APIPlaygroundView',
component: APIPlaygroundView,
parameters: { layout: 'fullscreen' },
tags: ['autodocs'],

View file

@ -3,7 +3,7 @@ import { DeveloperDashboardView } from './DeveloperDashboardView';
import { ToastProvider } from '../../components/feedback/ToastProvider';
const meta: Meta<typeof DeveloperDashboardView> = {
title: 'Components/Developer/DeveloperDashboardView',
title: 'Components/Features/Developer/DeveloperDashboardView',
component: DeveloperDashboardView,
parameters: { layout: 'fullscreen' },
tags: ['autodocs'],

View file

@ -2,7 +2,7 @@ import type { Meta, StoryObj } from '@storybook/react';
import { WebhooksView } from './WebhooksView';
const meta: Meta<typeof WebhooksView> = {
title: 'Components/Developer/WebhooksView',
title: 'Components/Features/Developer/WebhooksView',
component: WebhooksView,
parameters: { layout: 'fullscreen' },
tags: ['autodocs'],

Some files were not shown because too many files have changed in this diff Show more