Design responsive, logo, et correctif RLS upload photo
Design & UX : - Renomme "Administration" en "Admin" (nav, page, docs). - Logo original (marteau de juge stylisé navy/or) en favicon (src/app/icon.svg, remplace le favicon.ico par défaut de create-next-app) et dans la navbar (components/logo.tsx). - Navbar : menu hamburger sur mobile (les liens débordaient à partir de ~4 entrées sur petit écran). - Leaderboard : lignes en deux niveaux sur mobile (infos membre / contrôles juges) au lieu d'un seul flex-wrap qui devenait illisible. - Contrôles de points juges (JudgePointControls) : boutons et champ montant réduits en mode compact pour tenir dans les colonnes du podium sur petit écran. - Podium : scroll horizontal de secours (overflow-x-auto) si le contenu dépasse malgré tout sur très petits écrans. - Table admin : pseudo/avatar sur une ligne, rôle/statut/actions sur une autre en mobile (le flex-1 sur l'input pseudo n'avait aucun effet en layout colonne). Correctif sécurité/fonctionnel : - storage.objects n'avait que des policies INSERT et UPDATE pour le bucket avatars, pas de policy SELECT. Postgres a besoin de lire la ligne existante pour évaluer la clause USING d'un UPDATE : sans SELECT, tout remplacement de photo (upsert) échouait avec "new row violates row-level security policy", même si les policies INSERT/UPDATE étaient correctes. Ajout d'une policy SELECT publique sur le bucket avatars (cohérent avec le fait que le bucket est déjà public en lecture). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -50,12 +50,16 @@ export function JudgePointControls({
|
||||
setReason("");
|
||||
}
|
||||
|
||||
const buttonHeight = compact ? "h-6" : "h-7";
|
||||
const buttonWidth = compact ? "w-6" : "w-7";
|
||||
const inputWidth = compact ? "w-9" : "w-12";
|
||||
|
||||
return (
|
||||
<div className="flex flex-wrap items-center gap-1.5">
|
||||
<div className="flex flex-wrap items-center gap-1 sm:gap-1.5">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setPending((p) => p - parsedAmount)}
|
||||
className="h-7 w-7 shrink-0 rounded-md border border-navy/20 text-sm font-bold text-navy hover:bg-navy/5"
|
||||
className={`${buttonHeight} ${buttonWidth} shrink-0 rounded-md border border-navy/20 text-sm font-bold text-navy hover:bg-navy/5`}
|
||||
aria-label={`Retirer ${parsedAmount} points`}
|
||||
>
|
||||
−
|
||||
@@ -65,12 +69,12 @@ export function JudgePointControls({
|
||||
min={1}
|
||||
value={amount}
|
||||
onChange={(event) => setAmount(event.target.value)}
|
||||
className="h-7 w-12 rounded-md border border-navy/20 px-1 text-center text-xs"
|
||||
className={`${buttonHeight} ${inputWidth} rounded-md border border-navy/20 px-1 text-center text-xs`}
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setPending((p) => p + parsedAmount)}
|
||||
className="h-7 w-7 shrink-0 rounded-md border border-navy/20 text-sm font-bold text-navy hover:bg-navy/5"
|
||||
className={`${buttonHeight} ${buttonWidth} shrink-0 rounded-md border border-navy/20 text-sm font-bold text-navy hover:bg-navy/5`}
|
||||
aria-label={`Ajouter ${parsedAmount} points`}
|
||||
>
|
||||
+
|
||||
|
||||
Reference in New Issue
Block a user