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
118 changes: 61 additions & 57 deletions frontend/messages/en.json
Original file line number Diff line number Diff line change
@@ -1,58 +1,62 @@
{
"$schema": "https://inlang.com/schema/inlang-message-format",
"accommodation_info": "Accommodation info",
"about": "About",
"agenda": "Agenda",
"an_error_has_occurred": "An error has occurred",
"cancel": "Cancel",
"check_your_email": "Check your email",
"close": "Close",
"code_of_conduct": "Code of Conduct",
"contact_info": "Contact info",
"cookie_policy": "Cookie policy",
"day": "Day",
"did_you_forget_password": "Did you forget your password?",
"email": "Email",
"email_or_password_incorrect": "Email or password incorrect",
"edit": "Edit",
"edit_pseudonym": "Tell us your pseudonym in STE",
"edit_menu_options": "Tell us if you have any requirements on the menu (allergies, intolerances..).",
"enter_your_email": "Enter your email",
"enter_your_email_and_password": "You need to enter your email and password to see your registration data",
"enter_your_email_to_send_you_link": "Enter your email and we'll send you a link to set a new password.",
"enter_your_password": "Enter your password",
"enter_your_password_again": "Enter it again, for security",
"enter_your_new_password": "Enter your new password to access the web:",
"error_404_not_found": "404 Not found",
"error_404_message": "Sorry, we can't find the requested page. Please go back and try a different thing.",
"error_500_internal_error": "500 Internal error",
"error_500_message": "Sorry, an error has ocurred. Please try again.",
"error_generic": "Error {status}",
"forgot_password": "Forgotten password",
"forgot_password_press_here": "Forgotten password? Press here.",
"get_magic_link": "Get a magic link for another email→",
"it_has_a_magic_link": "It has a magic link to log in without a password.",
"invalid_reset_link": "The reset password link is invalid or timed out.",
"legal": "Legal",
"login": "Login",
"logout": "Logout",
"new_password": "New password",
"new_password_set": "Your new password has been set. You can now log in.",
"org_team": "Org team",
"password": "Password",
"password_length": "Password length must be at least 6 characters",
"passwords_must_match": "Passwords must match",
"press_kit": "Press kit",
"price": "Price",
"prices": "Prices",
"privacy_policy": "Privacy policy",
"register": "Register",
"registration": "Registration",
"reset_password_sent": "If your email is registered, a message has been sent with a link to set a new password.",
"send": "Send",
"speakers": "Speakers",
"streaming": "Streaming",
"venue_info": "Venue info",
"we_sent_an_email": "We sent an email to you at {email}",
"you_need_to_register": "You need to register to be able to enter the tickets queue and get your tickets."
}
"$schema": "https://inlang.com/schema/inlang-message-format",
"accommodation_info": "Accommodation info",
"about": "About",
"agenda": "Agenda",
"an_error_has_occurred": "An error has occurred",
"cancel": "Cancel",
"check_your_email": "Check your email",
"close": "Close",
"code_of_conduct": "Code of Conduct",
"contact_info": "Contact info",
"cookie_policy": "Cookie policy",
"day": "Day",
"did_you_forget_password": "Did you forget your password?",
"email": "Email",
"email_or_password_incorrect": "Email or password incorrect",
"edit": "Edit",
"edit_pseudonym": "Tell us your pseudonym in STE",
"edit_menu_options": "Tell us if you have any requirements on the menu (allergies, intolerances..).",
"enter_your_email": "Enter your email",
"enter_your_email_and_password": "You need to enter your email and password to see your registration data",
"enter_your_email_to_send_you_link": "Enter your email and we'll send you a link to set a new password.",
"enter_your_password": "Enter your password",
"enter_your_password_again": "Enter it again, for security",
"enter_your_new_password": "Enter your new password to access the web:",
"error_403_forbidden": "Access not allowed",
"error_403_message": "You do not have permission to access this page or resource.",
"error_404_not_found": "404 Not found",
"error_404_message": "Sorry, we can't find the requested page. Please go back and try a different thing.",
"error_500_internal_error": "500 Internal error",
"error_500_message": "Sorry, an error has ocurred. Please try again.",
"error_generic": "Error {status}",
"forgot_password": "Forgotten password",
"forgot_password_forbidden": "We couldn’t send the recovery link. Please check that the email is registered or contact the organization.",
"forgot_password_press_here": "Forgotten password? Press here.",
"get_magic_link": "Get a magic link for another email→",
"it_has_a_magic_link": "It has a magic link to log in without a password.",
"invalid_reset_link": "The reset password link is invalid or timed out.",
"legal": "Legal",
"login": "Login",
"login_forbidden": "We couldn’t sign you in. Please check your password and make sure your account is active.",
"logout": "Logout",
"new_password": "New password",
"new_password_set": "Your new password has been set. You can now log in.",
"org_team": "Org team",
"password": "Password",
"password_length": "Password length must be at least 6 characters",
"passwords_must_match": "Passwords must match",
"press_kit": "Press kit",
"price": "Price",
"prices": "Prices",
"privacy_policy": "Privacy policy",
"register": "Register",
"registration": "Registration",
"reset_password_sent": "If your email is registered, a message has been sent with a link to set a new password.",
"send": "Send",
"speakers": "Speakers",
"streaming": "Streaming",
"venue_info": "Venue info",
"we_sent_an_email": "We sent an email to you at {email}",
"you_need_to_register": "You need to register to be able to enter the tickets queue and get your tickets."
}
8 changes: 6 additions & 2 deletions frontend/messages/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,22 @@
"enter_your_password": "Introduce tu contraseña",
"enter_your_password_again": "Introducela otra vez, por seguridad",
"enter_your_new_password": "Introduce tu nueva contraseña para acceder a la web:",
"error_404_not_found": "404 Página no encontrada",
"error_403_forbidden": "Acceso no permitido",
"error_403_message": "No tienes permiso para acceder a esta página o recurso.",
"error_404_not_found": "Página no encontrada",
"error_404_message": "Lo sentimos, no podemos encontrar la página solicitada. Por favor vuelve atrás e intenta algo diferente.",
"error_500_internal_error": "500 Error interno",
"error_500_internal_error": "Error interno",
"error_500_message": "Lo sentimos, ha ocurrido un error. Por favor intenta de nuevo.",
"error_generic": "Error {status}",
"forgot_password": "Contraseña olvidada",
"forgot_password_forbidden": "No se ha podido enviar el enlace de recuperación. Revisa que el email esté registrado o contacta con la organización.",
"forgot_password_press_here": "¿Olvidaste la contraseña? Pulsa aquí.",
"get_magic_link": "Obtener un enlace para otro correo→",
"it_has_a_magic_link": "Contiene un enlace para entrar sin contraseña.",
"invalid_reset_link": "El enlace de establecer contraseña es inválido o está caducado.",
"legal": "Aviso legal",
"login": "Entrar",
"login_forbidden": "No se ha podido iniciar sesión. Revisa tu contraseña o que tu cuenta esté activa.",
"logout": "Salir",
"new_password": "Nueva contraseña",
"new_password_set": "Se ha establecido tu nueva contraseña. Ahora puedes entrar.",
Expand Down
198 changes: 198 additions & 0 deletions frontend/src/lib/ErrorView.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
<script lang="ts">
import { onMount } from 'svelte';
import { encodeQuery, fetchBasic } from '../services/api';

const storage_url = import.meta.env.VITE_STORAGE_URL;

type StrapiImage = {
url: string;
};

let {
status,
title,
message
}: {
status: number | string;
title: string;
message: string;
} = $props();

let errorImageUrl = $state('');

function getStrapiMediaUrl(image?: StrapiImage | null): string {
if (!image?.url) return '';

if (image.url.startsWith('http')) {
return image.url;
}

return `${storage_url}${image.url}`;
}

onMount(async () => {
const errorImagePath = `/upload/files?${encodeQuery({
filters: {
name: {
$eq: 'error.png'
}
}
})}`;

const images = await fetchBasic(errorImagePath);
errorImageUrl = getStrapiMediaUrl(images?.[0]);
});
</script>

<section class="section error-page">
<div class="container">
<div class="error-card">
{#if errorImageUrl}
<img src={errorImageUrl} alt="Oso bailando" class="error-card__image" />
{/if}

<p class="error-card__number">{status}</p>

<div class="error-card__content">
<h1 class="error-card__title">{title}</h1>
<p class="error-card__message">{message}</p>

<a href="/" class="button is-primary error-card__button">Volver al inicio</a>
</div>
</div>
</div>
</section>

<style>
.error-page {
display: flex;
align-items: center;
min-height: calc(100vh - 6rem);
padding-top: 2rem;
padding-bottom: 4rem;
}

.error-card {
position: relative;
max-width: 52rem;
margin-right: auto;
margin-left: auto;
padding: 2.25rem 1.5rem 1.9rem;
overflow: hidden;
border: 1px solid rgba(18, 63, 70, 0.12);
border-radius: 1.25rem;
background:
radial-gradient(circle at 50% 0%, rgba(215, 181, 109, 0.16), transparent 20rem),
rgba(255, 255, 255, 0.84);
box-shadow: 0 1rem 2rem rgba(0, 0, 0, 0.06);
backdrop-filter: blur(8px);
text-align: center;
}

.error-card::before {
content: '';
position: absolute;
top: 0;
right: 1.5rem;
left: 1.5rem;
height: 2px;
background: linear-gradient(90deg, transparent, #d7b56d, transparent);
opacity: 0.9;
pointer-events: none;
}

.error-card__image {
position: relative;
z-index: 1;
display: block;
width: min(100%, 28rem);
height: auto;
margin: 0 auto 0.4rem;
}

.error-card__number {
margin: 0;
color: #d7b56d;
font-family: var(--bulma-family-primary, inherit);
font-size: clamp(5.6rem, 14.4vw, 10.4rem);
font-weight: 900;
line-height: 0.82;
text-align: center;
text-shadow: 0 0.35rem 1rem rgba(77, 43, 19, 0.16);
}

.error-card__content {
max-width: 38rem;
margin: 0 auto;
padding: 0 1rem 0.35rem;
}

.error-card__title {
margin: 0 0 0.65rem;
color: #0d3b44;
font-family: var(--bulma-family-primary, inherit);
font-size: 1.55rem;
line-height: 1.2;
text-align: center;
text-transform: uppercase;
}

.error-card__message {
margin: 0;
color: rgba(18, 63, 70, 0.82);
font-size: 1.08rem;
line-height: 1.55;
text-align: center;
}

.error-card__button {
margin-top: 1.6rem;
height: auto;
min-height: 2.75rem;
padding: 0.75rem 1.4rem;
border-radius: 999px;
font-family: var(--bulma-family-primary, inherit);
font-weight: 800;
line-height: 1.2;
white-space: normal;
}

@media screen and (max-width: 768px) {
.error-page {
min-height: calc(100vh - 4rem);
padding-top: 1.5rem;
padding-bottom: 3rem;
}

.error-card {
padding: 1.5rem 1rem 1.35rem;
border-radius: 1rem;
}

.error-card__image {
width: min(100%, 20rem);
margin-bottom: 0.35rem;
}

.error-card__number {
font-size: clamp(4.4rem, 27.2vw, 6.4rem);
}

.error-card__content {
padding: 0 0.25rem 0.25rem;
}

.error-card__title {
font-size: 1.25rem;
}

.error-card__message {
font-size: 1rem;
line-height: 1.5;
}

.error-card__button {
width: 100%;
}
}
</style>
25 changes: 15 additions & 10 deletions frontend/src/lib/Header.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -67,19 +67,22 @@
: null
].filter(Boolean) as MenuItem[];

const featuredMenuItems: MenuItem[] = [
data.show_speakers
? {
label: m.speakers(),
href: i18n.resolveRoute('/speakers')
}
: null
].filter(Boolean) as MenuItem[];

const secondaryMenuItems: MenuItem[] = [
data.show_agenda
? {
label: m.agenda(),
href: i18n.resolveRoute('/agenda')
}
: null,
data.show_speakers
? {
label: m.speakers(),
href: i18n.resolveRoute('/speakers')
}
: null,
data.show_streaming
? {
label: m.streaming(),
Expand All @@ -95,13 +98,15 @@
]
.filter(Boolean)
.sort((a, b) => a.label.localeCompare(b.label, 'es', { sensitivity: 'base' })) as MenuItem[];

const menuItems: MenuItem[] = hasCustomNavMenu
? customMenuItems
: [...priorityMenuItems, ...secondaryMenuItems];
: [...priorityMenuItems, ...featuredMenuItems, ...secondaryMenuItems];

const hasHeaderCta = isRegistrationOpen && Boolean(data.register_cta);
const shouldUseDesktopOverflow = hasHeaderCta ? menuItems.length >= 5 : menuItems.length >= 6;

const desktopPrimaryMenuItems = menuItems.length > 5 ? menuItems.slice(0, 4) : menuItems;
const desktopOverflowMenuItems = menuItems.length > 5 ? menuItems.slice(4) : [];
const desktopPrimaryMenuItems = shouldUseDesktopOverflow ? menuItems.slice(0, 4) : menuItems;
const desktopOverflowMenuItems = shouldUseDesktopOverflow ? menuItems.slice(4) : [];

const showMenu = menuItems.length > 0;

Expand Down
Loading
Loading