-
Mahmoud Aglan authored
S2 of the mobile-portal programme. Branding lived in four uncoordinated stores with no sync, and each layout resolved it itself in an `@php` block issuing one SettingsService::get() per field — about sixteen SELECTs per admin render, repeated on every Livewire round-trip, each with its own fallback. That is how primary_color came to be defined three times with three different defaults. BrandingService returns a readonly BrandProfile, cached under the academy's new `branding_version` and bumped on save, so it is held until branding actually changes rather than for a guessed number of minutes, and a queue worker cannot serve last week's colours. Verified on the restored oc_sport copy: a second resolve inside one request issues 0 queries. Defects fixed, each verified against that copy: - `academies.address` did not exist. AcademySettings has been reading and writing it on every save since it was written, and Eloquent silently dropped it — no academy has ever had an address stored. - `branding.academy_name` was read by the parent layout and by every printed sheet and written by nothing, so both showed the literal string "الكابتن" on every tenant. It is seeded from the academy's own name and is now editable. The login page now reads "او سي سبورت" on the verified tenant. - components/print/sheet.blade.php emitted the raw storage path into an <img src>, so the logo was broken on every printed sheet. Paths become URLs in BrandingService and nowhere else. - Guests had no academy bound at all, so the login screen — and the member portal's own sign-in, when it exists — rendered under the fallback brand on every client. An installation with exactly one academy now resolves it for guests too; more than one is ambiguous and binds nothing. - AcademySettings had no authorize() call while every sibling settings screen does. Dead fields: the plan's rule is wire it or delete it, and none of them survived as collect-but-ignore. login_background now grounds the login screen, invoice_header and invoice_footer_text and show_logo_in_invoice reach the printed invoice, header_bg colours the topbar, compact_sidebar narrows the rail, and success_color/danger_color colour the flash strip. Colour derivation. sidebar.blade.php hardcoded `color: #fff` on the brand accent — this is a tenant-branded product, so a client whose brand is yellow got white on yellow at 1.53:1. ColorRamp derives a 50…900 OKLCH ramp plus a foreground chosen by WCAG contrast: that same yellow now gets #111827 at 11.58:1. Nine brand colours are asserted at AA or better. The ramp is anchored on the tenant's own lightness rather than fixed targets, because fixed targets are non-monotonic for an inherently light brand: yellow sits at L 0.86, so a table putting 400 at L 0.70 makes 400 darker than 500. Chroma falls steeply at the pale end — at L 0.97 a chroma of 0.10 is outside sRGB and clips to mud. E1 decided as the addendum recommends: `@custom-variant dark` is declared against the `.dark` class. Roughly 900 `dark:` utilities have been compiling to prefers-color-scheme and rendering an untested dark ERP for every OS-dark user, while the toggle did nothing. The OS-driven rendering stops here and the toggle becomes the only thing that switches themes. App icons are generated with GD directly rather than by adding intervention/image: GD is the only image extension in the Dockerfile, and the whole job is decode, letterbox, resize, write PNG. Dimensions are read from the header before decoding, since a small file can declare enormous dimensions. Filenames are content-hashed because nginx serves assets `expires 1y; immutable`. SVG uploads are refused everywhere they were accepted. An SVG on the academy's own origin executes script with the site's privileges and clean_html() never sees it. npm run build byte baseline before portal.css exists: app.css 208.10 kB / 31.02 kB gzip, website.css 217.08 kB / 33.25 kB gzip. Suite: 67 passed, 0 failed. Co-Authored-By:Claude Opus 5 (1M context) <noreply@anthropic.com>
2dff900b
| Name |
Last commit
|
Last update |
|---|---|---|
| .. | ||
| sidebar.blade.php | ||
| topbar.blade.php |