feat(gyms): show gym logos in navbar buttons and brand; accept JPEG XL uploads

This commit is contained in:
andre committed 2026-10-26 09:35:46 +00:00
1 parent a85bec6851
commit d445ba64b9
7 files changed
+51 -18

No files matched your search

+12 -4
View File
@@ -116,6 +116,14 @@ function gym_brand_vars(array $gym): string {
. ';--fitme-accent-ink:' . $shade($lum > .5 ? .5 : .85) . ';--fitme-on-accent:' . ($lum > .5 ? '#0B0B0D' : '#FFFFFF');
}
// The gym's logo (relative path). The main gym falls back to the site's own
// FitMe 3070 logo, so its navbar button has one before anything is uploaded.
function gym_logo(array $gym): string {
$logo = (string) ($gym['logo'] ?? '');
if ($logo === '' && !empty($gym['is_default'])) $logo = 'site/assets/img/logos/logo_black.svg';
return $logo;
}
function gym_brand_css(array $gym): string {
$v = gym_brand_vars($gym);
return $v === '' ? '' : ':root{' . $v . '}';
@@ -205,14 +213,14 @@ function gyms_from_post(PDO $pdo, array $post, array &$errors, ?int $id = null):
$other = db_gyms_by_slug($pdo, $slug);
if ($other && (int) $other['id'] !== (int) $id) $errors[] = 'Já existe um ginásio com essa pasta da URL.';
}
if ($data['logo'] !== '' && !preg_match('~^(site/assets/img|uploads)/[A-Za-z0-9_./ -]+\.(svg|png|webp|jpe?g)$~i', $data['logo'])) {
if ($data['logo'] !== '' && !preg_match('~^(site/assets/img|uploads)/[A-Za-z0-9_./ -]+\.(svg|png|webp|jpe?g|jxl)$~i', $data['logo'])) {
$errors[] = 'Logótipo: imagem inválida.';
}
if ($data['brand_color'] !== '' && !preg_match('/^#[0-9A-F]{6}$/', $data['brand_color'])) {
$errors[] = 'Cor da marca: formato #RRGGBB (ex.: #C2D500).';
}
if ($data['is_default'] && !$data['is_published']) $errors[] = 'O ginásio principal tem de estar publicado.';
if ($data['hero_image'] !== '' && !preg_match('~^(site/assets/img|uploads)/[A-Za-z0-9_./ -]+\.(jpe?g|png|webp)$~i', $data['hero_image'])) {
if ($data['hero_image'] !== '' && !preg_match('~^(site/assets/img|uploads)/[A-Za-z0-9_./ -]+\.(jpe?g|png|webp|jxl)$~i', $data['hero_image'])) {
$errors[] = 'Imagem do header: imagem inválida.';
}
return $data;
@@ -283,10 +291,10 @@ function gyms_save_image(array $file, string $kind, ?string &$error = null): ?st
return null;
}
if (($file['size'] ?? 0) > 6 * 1024 * 1024) { $error = 'máximo 6 MB.'; return null; }
$allowed = $kind === 'hero' ? ['jpg', 'jpeg', 'png', 'webp'] : ['svg', 'png', 'webp', 'jpg', 'jpeg'];
$allowed = $kind === 'hero' ? ['jpg', 'jpeg', 'png', 'webp', 'jxl'] : ['svg', 'png', 'webp', 'jpg', 'jpeg', 'jxl'];
$ext = upload_image_ext($file, $allowed);
if ($ext === null) {
$error = $kind === 'hero' ? 'usa JPG, PNG ou WebP.' : 'usa SVG, PNG, WebP ou JPG (SVG sem scripts).';
$error = $kind === 'hero' ? 'usa JPG, PNG, WebP ou JPEG XL.' : 'usa SVG, PNG, WebP, JPG ou JPEG XL (SVG sem scripts).';
return null;
}
$dir = gyms_upload_dir();