1"use strict";(globalThis.webpackChunktest=globalThis.webpackChunktest||[]).push([[1807],{3343:(e,s,i)=>{i.r(s),i.d(s,{assets:()=>d,contentTitle:()=>a,default:()=>u,frontMatter:()=>o,metadata:()=>r,toc:()=>l});const r=JSON.parse('{"id":"TutorielJFTL2026/User_Stories/US008_Admin_Medias","title":"US008 - Upload medias admin","description":"User Story","source":"@site/docs/TutorielJFTL2026/User_Stories/US008_Admin_Medias.md","sourceDirName":"TutorielJFTL2026/User_Stories","slug":"/TutorielJFTL2026/User_Stories/US008_Admin_Medias","permalink":"/docs/TutorielJFTL2026/User_Stories/US008_Admin_Medias","draft":false,"unlisted":false,"editUrl":"https://github.com/CFTL-TAIA/cftl-taia.github.io/tree/main/docs/TutorielJFTL2026/User_Stories/US008_Admin_Medias.md","tags":[],"version":"current","frontMatter":{},"sidebar":"SidebarTAIA","previous":{"title":"US007 - Connexion Admin","permalink":"/docs/TutorielJFTL2026/User_Stories/US007_Admin_Connexion"},"next":{"title":"US009 - Persistance Postgres","permalink":"/docs/TutorielJFTL2026/User_Stories/US009_Persistance_Postgres"}}');var n=i(4848),t=i(8453);const o={},a="US008 - Upload medias admin",d={},l=[{value:"User Story",id:"user-story",level:2},{value:"Valeur attendue",id:"valeur-attendue",level:2},{value:"Criteres d'acceptation",id:"criteres-dacceptation",level:2}];function c(e){const s={code:"code",h1:"h1",h2:"h2",header:"header",li:"li",ol:"ol",p:"p",ul:"ul",...(0,t.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(s.header,{children:(0,n.jsx)(s.h1,{id:"us008---upload-medias-admin",children:"US008 - Upload medias admin"})}),"\n",(0,n.jsx)(s.h2,{id:"user-story",children:"User Story"}),"\n",(0,n.jsx)(s.p,{children:"En tant qu'administrateur du projet API TAIA, je veux charger et nettoyer automatiquement les photos de speakers et les logos d'entreprises depuis l'interface admin afin de garder des medias conformes, visibles rapidement et sans fichiers orphelins."}),"\n",(0,n.jsx)(s.h2,{id:"valeur-attendue",children:"Valeur attendue"}),"\n",(0,n.jsxs)(s.ul,{children:["\n",(0,n.jsx)(s.li,{children:"fiabiliser les uploads admin en local comme sur Vercel"}),"\n",(0,n.jsx)(s.li,{children:"publier les medias vers Blob en environnement cible tout en gardant un fallback local propre pour le preview"}),"\n",(0,n.jsx)(s.li,{children:"eviter les images trop lourdes ou trop grandes pour l'affichage cible"}),"\n",(0,n.jsx)(s.li,{children:"supprimer automatiquement les medias geres par TAIA quand la ressource metier disparait"}),"\n"]}),"\n",(0,n.jsx)(s.h2,{id:"criteres-dacceptation",children:"Criteres d'acceptation"}),"\n",(0,n.jsxs)(s.ol,{children:["\n",(0,n.jsxs)(s.li,{children:[(0,n.jsx)(s.code,{children:"POST /api/admin/media"})," exige un JWT admin avec permission ",(0,n.jsx)(s.code,{children:"update"}),"."]}),"\n",(0,n.jsxs)(s.li,{children:["Une photo de speaker inferieure ou egale a ",(0,n.jsx)(s.code,{children:"2 Mo"})," et a ",(0,n.jsx)(s.code,{children:"1200 x 1600 px"})," est acceptee."]}),"\n",(0,n.jsxs)(s.li,{children:["Un logo d'entreprise inferieur ou egal a ",(0,n.jsx)(s.code,{children:"2 Mo"})," et a ",(0,n.jsx)(s.code,{children:"1600 x 800 px"})," est accepte."]}),"\n",(0,n.jsx)(s.li,{children:"Une image trop lourde ou trop grande est refusee avec un message explicite cote UI et cote API."}),"\n",(0,n.jsxs)(s.li,{children:["Si ",(0,n.jsx)(s.code,{children:"taia_READ_WRITE_TOKEN"})," est present, l'URL retournee pointe vers Blob public ; sinon le fallback local utilise ",(0,n.jsx)(s.code,{children:"/assets/media/photos/"})," ou ",(0,n.jsx)(s.code,{children:"/assets/media/logos/"}),"."]}),"\n",(0,n.jsxs)(s.li,{children:["Apres un create, update ou delete reussi depuis l'admin, la page se recharge automatiquement avec un delai d'environ ",(0,n.jsx)(s.code,{children:"1 s"}),"."]}),"\n",(0,n.jsxs)(s.li,{children:["Lors de la suppression d'un ",(0,n.jsx)(s.code,{children:"speaker"})," ou d'une ",(0,n.jsx)(s.code,{children:"entreprise"}),", le media associe est aussi supprime s'il est gere par TAIA ; une URL externe reste intacte."]}),"\n"]})]})}function u(e={}){const{wrapper:s}={...(0,t.R)(),...e.components};return s?(0,n.jsx)(s,{...e,children:(0,n.jsx)(c,{...e})}):c(e)}},8453:(e,s,i)=>{i.d(s,{R:()=>o,x:()=>a});var r=i(6540);const n={},t=r.createContext(n);function o(e){const s=r.useContext(t);return r.useMemo(function(){return"function"==typeof e?e(s):{...s,...e}},[s,e])}function a(e){let s;return s=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:o(e.components),r.createElement(t.Provider,{value:s},e.children)}}}]);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.