diff --git a/src/components/ContactForm.astro b/src/components/ContactForm.astro
index d7865ed..cb7c3ea 100644
--- a/src/components/ContactForm.astro
+++ b/src/components/ContactForm.astro
@@ -14,8 +14,8 @@ const { variant = 'full' } = Astro.props;
data-msg-error-network={t('form.msg.error-network')}
>
- {variant === 'full' && }
- {variant === 'full' && }
+
+
diff --git a/src/components/Header.astro b/src/components/Header.astro
index bfcbcdc..1729495 100644
--- a/src/components/Header.astro
+++ b/src/components/Header.astro
@@ -16,7 +16,9 @@ const areaHref = user?.role === 'superuser' ? '/admin/content' : '/admin';
diff --git a/src/components/home/HeroSlider.astro b/src/components/home/HeroSlider.astro
index 869d980..1d16bdf 100644
--- a/src/components/home/HeroSlider.astro
+++ b/src/components/home/HeroSlider.astro
@@ -1,10 +1,9 @@
---
-import hero1 from '../../assets/img/hero-1.png';
+// Foto hero rimossa ma conservata su disco per riuso futuro: assets/img/hero-1.png
import T from '../content/T.astro';
-import TImg from '../content/TImg.astro';
import { t } from '../../lib/content';
const slides = [
- { titleTags: ['home.hero.title-line-1', 'home.hero.title-line-2', 'home.hero.title-line-3'], image: hero1, alt: 'Atleti InsanityLab' },
+ { titleTags: ['home.hero.title-line-1', 'home.hero.title-line-2', 'home.hero.title-line-3'] },
];
---
-
))}
@@ -34,32 +32,28 @@ const slides = [
.hero__slide.is-active { display: block; }
/* Come nel Figma: figure a piena altezza ancorate in basso a destra,
testo sovrapposto sulla sinistra. */
- .hero__in { position: relative; display: flex; align-items: center; min-height: calc(100vh - var(--header-h)); }
+ .hero__in { position: relative; display: flex; align-items: center; min-height: 0; padding-block: 90px; }
/* Lo span .hero__line è reso dal componente e non riceve il data-astro-cid
di questo componente: si ancora a .hero__text (che il cid ce l'ha) + :global. */
.hero__text h1 :global(.hero__line) { display: block; }
- .hero__text { position: relative; z-index: 1; max-width: 46%; }
+ .hero__text { position: relative; z-index: 1; max-width: 640px; }
.hero__text h1 { font-weight: 500; }
- .hero__img { position: absolute; right: 0; bottom: 0; height: 100%; width: auto; max-width: 80%; object-fit: contain; object-position: right bottom; }
.hero__arrow { position: absolute; top: 50%; transform: translateY(-50%); background: none; border: 0; font-size: 3rem; color: var(--c-heading); cursor: pointer; }
.hero__arrow--prev { left: 12px; } .hero__arrow--next { right: 12px; }
@media (max-width: 991px) {
.hero__in { flex-direction: column; align-items: flex-start; padding-block: 40px; min-height: 0; gap: 24px; }
.hero__text { max-width: none; }
- .hero__img { position: static; max-width: 100%; height: auto; }
}
/* Ingresso al load stile Slider Revolution del template */
@keyframes hero-up { from { opacity: 0; transform: translateY(60px); } to { opacity: 1; transform: none; } }
- @keyframes hero-side { from { opacity: 0; transform: translateX(60px); } to { opacity: 1; transform: none; } }
:global(html.js) .hero__text h1 :global(.hero__line) { opacity: 0; animation: hero-up .8s ease forwards; }
:global(html.js) .hero__text h1 :global(.hero__line:nth-child(1)) { animation-delay: .15s; }
:global(html.js) .hero__text h1 :global(.hero__line:nth-child(2)) { animation-delay: .3s; }
:global(html.js) .hero__text h1 :global(.hero__line:nth-child(3)) { animation-delay: .45s; }
:global(html.js) .hero__text .btn { opacity: 0; animation: hero-up .8s ease .7s forwards; }
- :global(html.js) .hero__img { opacity: 0; animation: hero-side 1s ease .2s forwards; }
@media (prefers-reduced-motion: reduce) {
- :global(html.js) .hero__text h1 :global(.hero__line), :global(html.js) .hero__text .btn, :global(html.js) .hero__img { opacity: 1; animation: none; }
+ :global(html.js) .hero__text h1 :global(.hero__line), :global(html.js) .hero__text .btn { opacity: 1; animation: none; }
}
diff --git a/src/data/site.ts b/src/data/site.ts
index 3ecebb7..2ade69f 100644
--- a/src/data/site.ts
+++ b/src/data/site.ts
@@ -18,7 +18,8 @@ export const site = {
{ label: "Blog & Edugo", href: "/blog" },
{ label: "Promo ed eventi", href: "/promo-eventi" },
{ label: "Contatti", href: "/contact" },
- { label: "Promo 2 (test)", href: "/promo-eventi2" },
+ // Pagina di test: visibile solo agli admin loggati, nascosta al pubblico.
+ { label: "Promo 2 (test)", href: "/promo-eventi2", adminOnly: true },
],
footerTraining: [
{ label: "One to one", href: "/training#one-to-one" },
diff --git a/src/lib/contact.ts b/src/lib/contact.ts
index 96f9a32..1140aba 100644
--- a/src/lib/contact.ts
+++ b/src/lib/contact.ts
@@ -24,6 +24,8 @@ export function validateContact(data: unknown):
};
if (value.website) return { ok: false, error: 'Richiesta non valida.' };
if (!value.firstName) return { ok: false, error: 'Il nome è obbligatorio.' };
+ if (!value.lastName) return { ok: false, error: 'Il cognome è obbligatorio.' };
+ if (!value.phone) return { ok: false, error: 'Il telefono è obbligatorio.' };
if (!EMAIL_RE.test(value.email)) return { ok: false, error: 'Inserisci una e-mail valida.' };
if (!value.message) return { ok: false, error: 'Il messaggio è obbligatorio.' };
if (value.message.length > 5000) return { ok: false, error: 'Messaggio troppo lungo.' };
diff --git a/tests/contact.test.ts b/tests/contact.test.ts
index 9fdbf67..d848382 100644
--- a/tests/contact.test.ts
+++ b/tests/contact.test.ts
@@ -2,13 +2,13 @@ import { describe, it, expect } from 'vitest';
import { validateContact } from '../src/lib/contact';
describe('validateContact', () => {
- const good = { firstName: 'Mario', email: 'mario@example.com', message: 'Ciao, vorrei informazioni.' };
+ const good = { firstName: 'Mario', lastName: 'Rossi', phone: '3331234567', email: 'mario@example.com', message: 'Ciao, vorrei informazioni.' };
- it('accetta payload valido e normalizza i campi opzionali', () => {
+ it('accetta payload valido', () => {
const r = validateContact(good);
expect(r.ok).toBe(true);
if (r.ok) {
- expect(r.value.lastName).toBe('');
+ expect(r.value.lastName).toBe('Rossi');
expect(r.value.email).toBe('mario@example.com');
}
});
@@ -19,6 +19,8 @@ describe('validateContact', () => {
it('rifiuta campi obbligatori mancanti o vuoti', () => {
expect(validateContact({ ...good, firstName: ' ' }).ok).toBe(false);
+ expect(validateContact({ ...good, lastName: ' ' }).ok).toBe(false);
+ expect(validateContact({ ...good, phone: '' }).ok).toBe(false);
expect(validateContact({ ...good, message: '' }).ok).toBe(false);
expect(validateContact(null).ok).toBe(false);
});