Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion .claude/rules/features/homepage-sections.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
paths:
- "backend/app/**/*HomepageSection*.php"
- "frontend/src/utilites/homepageSection*.ts"
- "frontend/src/components/layouts/EventHomepage/Sections/**"
- "frontend/src/components/layouts/EventHomepage/**"
- "frontend/src/components/layouts/HomepageFrame/**"
- "frontend/src/constants/eventLayouts.ts"
- "frontend/src/components/routes/event/HomepageDesigner/**"
- "frontend/src/components/routes/organizer/OrganizerHomepageDesigner/**"
---
Expand All @@ -11,3 +13,7 @@ paths:

- User-supplied `homepage_sections` (events and organizers) are saved only through `HomepageSectionsSanitizer`: it purifies HTML, keeps only image ids owned by this event/organizer, and only allows YouTube/Vimeo video links.
- The About section renders `event.description`; never copy the description into a section, because SEO, listings, emails and the API all read it. Extra copy belongs in `TEXT` sections.
- Event page layouts (Marquee, Flyer, Story, Invite) are rows of traits in `constants/eventLayouts.ts`; CSS keys off the traits (`data-rail`, `data-poster`, `data-width`, `data-centered`), never layout names. A new layout is a new row, a designer sketch in `LayoutPicker/LayoutPreview.tsx`, and a backend `HomepageLayout` case. `DEFAULT_EVENT_LAYOUT` applies to every event without a saved layout.
- Sections render in columns from ~350px (phones, Flyer on tablet) to ~690px, so their responsive rules use container queries (`hp.narrow`, `hp.compact`) on the section, never viewport media queries. Dialogs portal to `main` and keep viewport rules.
- Status labels ("This event has ended", "Happening now") come from the server's `lifecycle_status`, never the client clock, so SSR and hydration agree. An ended event renders no Tickets block and no ticket rail; Marquee drops to the medium width.
- The intro shows venue name and city when the Location section is on (the section carries the full address and directions), and the full address with directions when it is off.
1 change: 1 addition & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ Integrations call the API with API keys, so endpoints in the `auth:api,sanctum`
## Frontend

- SSR app: guard `window`/`document`, and keep per-request state in `AsyncLocalStorage` (`utilites/ssrRequestContext.ts`), never in axios defaults or module globals.
- Public routes set `handle: {styles: '<module path>'}` in `router.tsx` so production SSR links their CSS in `<head>` and skips the white `ssr-loader` overlay; without it the page paints unstyled and shifts (CLS) on hydration.
- React Query for all API calls (patterns: `queries/useGetCapacityAssignment.ts`, `mutations/useCreateAffiliate.ts`).
- Mantine components; SCSS modules for layout. Reuse existing components before adding new ones, and skip unnecessary React imports.
- Notifications via `showSuccess`/`showError` (`utilites/notifications.tsx`), never Mantine's `showNotification`; validation errors via `useFormErrorResponseHandler`. Handle errors in parent components.
Expand Down
13 changes: 13 additions & 0 deletions backend/app/DomainObjects/Enums/HomepageLayout.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

namespace HiEvents\DomainObjects\Enums;

enum HomepageLayout: string
{
use BaseEnum;

case MARQUEE = 'MARQUEE';
case FLYER = 'FLYER';
case STORY = 'STORY';
case INVITE = 'INVITE';
}
3 changes: 2 additions & 1 deletion backend/app/DomainObjects/Enums/HomepageSectionType.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ enum HomepageSectionType: string
case SCHEDULE = 'SCHEDULE';
case LOCATION = 'LOCATION';
case ORGANIZER = 'ORGANIZER';
case MORE_EVENTS = 'MORE_EVENTS';
case EVENTS = 'EVENTS';
case CONTACT = 'CONTACT';
case PAST_EVENTS = 'PAST_EVENTS';
Expand All @@ -26,7 +27,7 @@ enum HomepageSectionType: string
*/
public static function eventBuiltIns(): array
{
return [self::TICKETS, self::ABOUT, self::LINEUP, self::SCHEDULE, self::LOCATION, self::ORGANIZER];
return [self::TICKETS, self::ABOUT, self::LINEUP, self::SCHEDULE, self::LOCATION, self::ORGANIZER, self::MORE_EVENTS];
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use HiEvents\DomainObjects\Enums\AttendeeDetailsCollectionMethod;
use HiEvents\DomainObjects\Enums\HomepageBackgroundType;
use HiEvents\DomainObjects\Enums\HomepageFontFamily;
use HiEvents\DomainObjects\Enums\HomepageLayout;
use HiEvents\DomainObjects\Enums\HomepageSectionType;
use HiEvents\DomainObjects\Enums\PaymentProviders;
use HiEvents\DomainObjects\Enums\Permission;
Expand Down Expand Up @@ -114,6 +115,7 @@ public function rules(): array
'homepage_theme_settings.mode' => ['nullable', 'string', Rule::in(['light', 'dark'])],
'homepage_theme_settings.background_type' => ['nullable', 'string', Rule::in(HomepageBackgroundType::valuesArray())],
'homepage_theme_settings.font_family' => ['nullable', 'string', Rule::in(HomepageFontFamily::valuesArray())],
'homepage_theme_settings.layout' => ['nullable', 'string', Rule::in(HomepageLayout::valuesArray())],
...HomepageSectionRules::rules(HomepageSectionType::eventValues()),

// Self-service settings
Expand Down Expand Up @@ -164,6 +166,7 @@ public function messages(): array
'homepage_theme_settings.mode.in' => __('The mode must be light or dark.'),
'homepage_theme_settings.background_type.in' => __('The background type must be COLOR or MIRROR_COVER_IMAGE.'),
'homepage_theme_settings.font_family.in' => __('The selected font is not supported.'),
'homepage_theme_settings.layout.in' => __('The selected layout is not supported.'),
...HomepageSectionRules::messages(),
];
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ public static function createWithDefaults(

// Homepage theme defaults (simplified 2-color + mode system)
homepage_theme_settings: [
'accent' => '#8b5cf6',
'accent' => '#7c3aed',
'background' => '#f5f3ff',
'mode' => 'light',
'background_type' => 'COLOR',
Expand Down
2 changes: 1 addition & 1 deletion backend/app/Services/Domain/Event/CreateEventService.php
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ private function createEventSettings(
$terminology = ProductTerminology::forCategory($event->getCategory());

$homepageThemeSettings = [
'accent' => $organizerThemeSettings['accent'] ?? '#8b5cf6',
'accent' => $organizerThemeSettings['accent'] ?? '#7c3aed',
'background' => $organizerThemeSettings['background'] ?? '#f5f3ff',
'mode' => $organizerThemeSettings['mode'] ?? 'light',
'background_type' => $eventCoverCreated
Expand Down
2 changes: 1 addition & 1 deletion backend/app/Validators/Rules/HomepageSectionRules.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class HomepageSectionRules
public static function rules(array $allowedTypes): array
{
return [
'homepage_sections' => ['nullable', 'array', 'max:40'],
'homepage_sections' => ['nullable', 'array', 'max:41'],
'homepage_sections.*.id' => ['required', 'string', 'max:40', 'regex:/^[A-Za-z0-9_-]+$/'],
'homepage_sections.*.type' => ['required', 'string', Rule::in($allowedTypes)],
'homepage_sections.*.enabled' => ['boolean'],
Expand Down
3 changes: 2 additions & 1 deletion backend/lang/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -1198,5 +1198,6 @@
"Offline payment instructions can only be changed from the dashboard, not with an API key.": "Anweisungen für Offline-Zahlungen können nur im Dashboard geändert werden, nicht mit einem API-Schlüssel.",
"Only members who can manage payments can change the offline payment instructions.": "Nur Mitglieder, die Zahlungen verwalten dürfen, können die Anweisungen für Offline-Zahlungen ändern.",
"Sign in with your email and password instead.": "Melden Sie sich stattdessen mit Ihrer E-Mail-Adresse und Ihrem Passwort an.",
"This ticket is sold out, so this attendee cannot be reactivated. Increase its quantity and try again.": "Dieses Ticket ist ausverkauft, daher kann dieser Teilnehmer nicht reaktiviert werden. Erhöhen Sie die Menge und versuchen Sie es erneut."
"This ticket is sold out, so this attendee cannot be reactivated. Increase its quantity and try again.": "Dieses Ticket ist ausverkauft, daher kann dieser Teilnehmer nicht reaktiviert werden. Erhöhen Sie die Menge und versuchen Sie es erneut.",
"The selected layout is not supported.": "Das ausgewählte Layout wird nicht unterstützt."
}
3 changes: 2 additions & 1 deletion backend/lang/el.json
Original file line number Diff line number Diff line change
Expand Up @@ -1198,5 +1198,6 @@
"Offline payment instructions can only be changed from the dashboard, not with an API key.": "Οι οδηγίες για τις εκτός σύνδεσης πληρωμές αλλάζουν μόνο από τον πίνακα ελέγχου, όχι με κλειδί API.",
"Only members who can manage payments can change the offline payment instructions.": "Μόνο τα μέλη που μπορούν να διαχειρίζονται πληρωμές μπορούν να αλλάξουν τις οδηγίες για τις εκτός σύνδεσης πληρωμές.",
"Sign in with your email and password instead.": "Συνδεθείτε με το email και τον κωδικό σας.",
"This ticket is sold out, so this attendee cannot be reactivated. Increase its quantity and try again.": "Αυτό το εισιτήριο έχει εξαντληθεί, οπότε ο συμμετέχων δεν μπορεί να επανενεργοποιηθεί. Αυξήστε την ποσότητά του και δοκιμάστε ξανά."
"This ticket is sold out, so this attendee cannot be reactivated. Increase its quantity and try again.": "Αυτό το εισιτήριο έχει εξαντληθεί, οπότε ο συμμετέχων δεν μπορεί να επανενεργοποιηθεί. Αυξήστε την ποσότητά του και δοκιμάστε ξανά.",
"The selected layout is not supported.": "Η επιλεγμένη διάταξη δεν υποστηρίζεται."
}
3 changes: 2 additions & 1 deletion backend/lang/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -1238,5 +1238,6 @@
"Offline payment instructions can only be changed from the dashboard, not with an API key.": "Las instrucciones de pago offline solo se pueden cambiar desde el panel, no con una clave de API.",
"Only members who can manage payments can change the offline payment instructions.": "Solo los miembros que pueden gestionar los pagos pueden cambiar las instrucciones de pago offline.",
"Sign in with your email and password instead.": "Inicia sesión con tu correo electrónico y contraseña.",
"This ticket is sold out, so this attendee cannot be reactivated. Increase its quantity and try again.": "Esta entrada está agotada, por lo que no se puede reactivar a este asistente. Aumenta su cantidad e inténtalo de nuevo."
"This ticket is sold out, so this attendee cannot be reactivated. Increase its quantity and try again.": "Esta entrada está agotada, por lo que no se puede reactivar a este asistente. Aumenta su cantidad e inténtalo de nuevo.",
"The selected layout is not supported.": "El diseño seleccionado no es compatible."
}
3 changes: 2 additions & 1 deletion backend/lang/fi.json
Original file line number Diff line number Diff line change
Expand Up @@ -1386,5 +1386,6 @@
"Offline payment instructions can only be changed from the dashboard, not with an API key.": "Offline-maksun ohjeita voi muuttaa vain hallintapaneelista, ei API-avaimella.",
"Only members who can manage payments can change the offline payment instructions.": "Vain jäsenet, joilla on oikeus hallita maksuja, voivat muuttaa offline-maksun ohjeita.",
"Sign in with your email and password instead.": "Kirjaudu sen sijaan sisään sähköpostiosoitteellasi ja salasanallasi.",
"This ticket is sold out, so this attendee cannot be reactivated. Increase its quantity and try again.": "Tämä lippu on myyty loppuun, joten tätä osallistujaa ei voi aktivoida uudelleen. Kasvata lipun määrää ja yritä uudelleen."
"This ticket is sold out, so this attendee cannot be reactivated. Increase its quantity and try again.": "Tämä lippu on myyty loppuun, joten tätä osallistujaa ei voi aktivoida uudelleen. Kasvata lipun määrää ja yritä uudelleen.",
"The selected layout is not supported.": "Valittua asettelua ei tueta."
}
3 changes: 2 additions & 1 deletion backend/lang/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -1198,5 +1198,6 @@
"Offline payment instructions can only be changed from the dashboard, not with an API key.": "Les instructions de paiement hors ligne ne peuvent être modifiées que depuis le tableau de bord, pas avec une clé API.",
"Only members who can manage payments can change the offline payment instructions.": "Seuls les membres autorisés à gérer les paiements peuvent modifier les instructions de paiement hors ligne.",
"Sign in with your email and password instead.": "Connectez-vous plutôt avec votre adresse e-mail et votre mot de passe.",
"This ticket is sold out, so this attendee cannot be reactivated. Increase its quantity and try again.": "Ce billet est épuisé, ce participant ne peut donc pas être réactivé. Augmentez sa quantité et réessayez."
"This ticket is sold out, so this attendee cannot be reactivated. Increase its quantity and try again.": "Ce billet est épuisé, ce participant ne peut donc pas être réactivé. Augmentez sa quantité et réessayez.",
"The selected layout is not supported.": "La mise en page sélectionnée n'est pas prise en charge."
}
3 changes: 2 additions & 1 deletion backend/lang/hu.json
Original file line number Diff line number Diff line change
Expand Up @@ -1203,5 +1203,6 @@
"Offline payment instructions can only be changed from the dashboard, not with an API key.": "Az offline fizetési utasításokat csak az irányítópulton lehet módosítani, API-kulccsal nem.",
"Only members who can manage payments can change the offline payment instructions.": "Az offline fizetési utasításokat csak a fizetések kezelésére jogosult tagok módosíthatják.",
"Sign in with your email and password instead.": "Jelentkezzen be inkább e-mail-címével és jelszavával.",
"This ticket is sold out, so this attendee cannot be reactivated. Increase its quantity and try again.": "Ez a jegy elfogyott, ezért a résztvevő nem aktiválható újra. Növelje a jegy mennyiségét, és próbálja újra."
"This ticket is sold out, so this attendee cannot be reactivated. Increase its quantity and try again.": "Ez a jegy elfogyott, ezért a résztvevő nem aktiválható újra. Növelje a jegy mennyiségét, és próbálja újra.",
"The selected layout is not supported.": "A kiválasztott elrendezés nem támogatott."
}
3 changes: 2 additions & 1 deletion backend/lang/it.json
Original file line number Diff line number Diff line change
Expand Up @@ -1199,5 +1199,6 @@
"Offline payment instructions can only be changed from the dashboard, not with an API key.": "Le istruzioni per il pagamento offline possono essere modificate solo dalla dashboard, non con una chiave API.",
"Only members who can manage payments can change the offline payment instructions.": "Solo i membri che possono gestire i pagamenti possono modificare le istruzioni per il pagamento offline.",
"Sign in with your email and password instead.": "Accedi invece con la tua email e password.",
"This ticket is sold out, so this attendee cannot be reactivated. Increase its quantity and try again.": "Questo biglietto è esaurito, quindi il partecipante non può essere riattivato. Aumentane la quantità e riprova."
"This ticket is sold out, so this attendee cannot be reactivated. Increase its quantity and try again.": "Questo biglietto è esaurito, quindi il partecipante non può essere riattivato. Aumentane la quantità e riprova.",
"The selected layout is not supported.": "Il layout selezionato non è supportato."
}
3 changes: 2 additions & 1 deletion backend/lang/ja.json
Original file line number Diff line number Diff line change
Expand Up @@ -1386,5 +1386,6 @@
"Offline payment instructions can only be changed from the dashboard, not with an API key.": "オフライン決済の案内はダッシュボードからのみ変更でき、APIキーでは変更できません。",
"Only members who can manage payments can change the offline payment instructions.": "オフライン決済の案内を変更できるのは、支払いを管理できるメンバーのみです。",
"Sign in with your email and password instead.": "代わりにメールアドレスとパスワードでサインインしてください。",
"This ticket is sold out, so this attendee cannot be reactivated. Increase its quantity and try again.": "このチケットは完売しているため、この参加者を再有効化できません。販売可能数を増やして、もう一度お試しください。"
"This ticket is sold out, so this attendee cannot be reactivated. Increase its quantity and try again.": "このチケットは完売しているため、この参加者を再有効化できません。販売可能数を増やして、もう一度お試しください。",
"The selected layout is not supported.": "選択されたレイアウトはサポートされていません。"
}
3 changes: 2 additions & 1 deletion backend/lang/ko.json
Original file line number Diff line number Diff line change
Expand Up @@ -1387,5 +1387,6 @@
"Offline payment instructions can only be changed from the dashboard, not with an API key.": "무통장 입금 안내는 API 키가 아닌 대시보드에서만 변경할 수 있습니다.",
"Only members who can manage payments can change the offline payment instructions.": "결제를 관리할 수 있는 구성원만 무통장 입금 안내를 변경할 수 있습니다.",
"Sign in with your email and password instead.": "대신 이메일과 비밀번호로 로그인하세요.",
"This ticket is sold out, so this attendee cannot be reactivated. Increase its quantity and try again.": "이 티켓이 매진되어 이 참석자를 다시 활성화할 수 없습니다. 티켓 수량을 늘린 후 다시 시도해 주세요."
"This ticket is sold out, so this attendee cannot be reactivated. Increase its quantity and try again.": "이 티켓이 매진되어 이 참석자를 다시 활성화할 수 없습니다. 티켓 수량을 늘린 후 다시 시도해 주세요.",
"The selected layout is not supported.": "선택한 레이아웃은 지원되지 않습니다."
}
3 changes: 2 additions & 1 deletion backend/lang/nl.json
Original file line number Diff line number Diff line change
Expand Up @@ -1198,5 +1198,6 @@
"Offline payment instructions can only be changed from the dashboard, not with an API key.": "Instructies voor offline betalingen kun je alleen via het dashboard wijzigen, niet met een API-sleutel.",
"Only members who can manage payments can change the offline payment instructions.": "Alleen leden die betalingen mogen beheren, kunnen de instructies voor offline betalingen wijzigen.",
"Sign in with your email and password instead.": "Log in plaats daarvan in met je e-mailadres en wachtwoord.",
"This ticket is sold out, so this attendee cannot be reactivated. Increase its quantity and try again.": "Dit ticket is uitverkocht, dus deze deelnemer kan niet opnieuw worden geactiveerd. Verhoog het aantal en probeer het opnieuw."
"This ticket is sold out, so this attendee cannot be reactivated. Increase its quantity and try again.": "Dit ticket is uitverkocht, dus deze deelnemer kan niet opnieuw worden geactiveerd. Verhoog het aantal en probeer het opnieuw.",
"The selected layout is not supported.": "De geselecteerde lay-out wordt niet ondersteund."
}
3 changes: 2 additions & 1 deletion backend/lang/pl.json
Original file line number Diff line number Diff line change
Expand Up @@ -1386,5 +1386,6 @@
"Offline payment instructions can only be changed from the dashboard, not with an API key.": "Instrukcje płatności offline można zmienić tylko w panelu, a nie za pomocą klucza API.",
"Only members who can manage payments can change the offline payment instructions.": "Tylko członkowie, którzy mogą zarządzać płatnościami, mogą zmieniać instrukcje płatności offline.",
"Sign in with your email and password instead.": "Zamiast tego zaloguj się za pomocą adresu e-mail i hasła.",
"This ticket is sold out, so this attendee cannot be reactivated. Increase its quantity and try again.": "Ten bilet jest wyprzedany, więc nie można ponownie aktywować tego uczestnika. Zwiększ liczbę dostępnych biletów i spróbuj ponownie."
"This ticket is sold out, so this attendee cannot be reactivated. Increase its quantity and try again.": "Ten bilet jest wyprzedany, więc nie można ponownie aktywować tego uczestnika. Zwiększ liczbę dostępnych biletów i spróbuj ponownie.",
"The selected layout is not supported.": "Wybrany układ nie jest obsługiwany."
}
Loading
Loading