feat: tag contenuti header, footer e form contatti
This commit is contained in:
@@ -1,15 +1,25 @@
|
|||||||
---
|
---
|
||||||
|
import { t } from '../lib/content';
|
||||||
|
import T from './content/T.astro';
|
||||||
interface Props { variant?: 'full' | 'footer' }
|
interface Props { variant?: 'full' | 'footer' }
|
||||||
const { variant = 'full' } = Astro.props;
|
const { variant = 'full' } = Astro.props;
|
||||||
---
|
---
|
||||||
<form class:list={['cform', `cform--${variant}`]} method="post" action="/api/contact" novalidate>
|
<form
|
||||||
<input class="field" name="firstName" placeholder="Nome" required maxlength="100" />
|
class:list={['cform', `cform--${variant}`]}
|
||||||
{variant === 'full' && <input class="field" name="lastName" placeholder="Cognome" maxlength="100" />}
|
method="post"
|
||||||
{variant === 'full' && <input class="field" name="phone" placeholder="Telefono" maxlength="40" />}
|
action="/api/contact"
|
||||||
<input class="field" type="email" name="email" placeholder="E-mail" required maxlength="200" />
|
novalidate
|
||||||
<textarea class="field" name="message" placeholder="Messaggio" required maxlength="5000"></textarea>
|
data-msg-success={t('form.msg.success')}
|
||||||
|
data-msg-error-generic={t('form.msg.error-generic')}
|
||||||
|
data-msg-error-network={t('form.msg.error-network')}
|
||||||
|
>
|
||||||
|
<input class="field" name="firstName" placeholder={t('form.field.first-name')} required maxlength="100" />
|
||||||
|
{variant === 'full' && <input class="field" name="lastName" placeholder={t('form.field.last-name')} maxlength="100" />}
|
||||||
|
{variant === 'full' && <input class="field" name="phone" placeholder={t('form.field.phone')} maxlength="40" />}
|
||||||
|
<input class="field" type="email" name="email" placeholder={t('form.field.email')} required maxlength="200" />
|
||||||
|
<textarea class="field" name="message" placeholder={t('form.field.message')} required maxlength="5000"></textarea>
|
||||||
<input class="hp" type="text" name="website" tabindex="-1" autocomplete="off" />
|
<input class="hp" type="text" name="website" tabindex="-1" autocomplete="off" />
|
||||||
<button class="btn" type="submit">Invia messaggio</button>
|
<button class="btn" type="submit"><T tag="form.submit" as="span" /></button>
|
||||||
<p class="form-msg" hidden></p>
|
<p class="form-msg" hidden></p>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
@@ -28,11 +38,11 @@ const { variant = 'full' } = Astro.props;
|
|||||||
body: JSON.stringify(Object.fromEntries(new FormData(form))),
|
body: JSON.stringify(Object.fromEntries(new FormData(form))),
|
||||||
});
|
});
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
msg.textContent = res.ok ? 'Messaggio inviato, ti ricontatteremo al più presto.' : (data.error ?? 'Errore di invio, riprova più tardi.');
|
msg.textContent = res.ok ? form.dataset.msgSuccess! : (data.error ?? form.dataset.msgErrorGeneric);
|
||||||
msg.className = `form-msg ${res.ok ? 'form-msg--ok' : 'form-msg--err'}`;
|
msg.className = `form-msg ${res.ok ? 'form-msg--ok' : 'form-msg--err'}`;
|
||||||
if (res.ok) form.reset();
|
if (res.ok) form.reset();
|
||||||
} catch {
|
} catch {
|
||||||
msg.textContent = 'Errore di rete, riprova più tardi.';
|
msg.textContent = form.dataset.msgErrorNetwork!;
|
||||||
msg.className = 'form-msg form-msg--err';
|
msg.className = 'form-msg form-msg--err';
|
||||||
}
|
}
|
||||||
msg.hidden = false;
|
msg.hidden = false;
|
||||||
|
|||||||
+15
-12
@@ -1,34 +1,37 @@
|
|||||||
---
|
---
|
||||||
import { site } from '../data/site';
|
import { site } from '../data/site';
|
||||||
import ContactForm from './ContactForm.astro';
|
import ContactForm from './ContactForm.astro';
|
||||||
|
import { t, contentImageUrl } from '../lib/content';
|
||||||
|
import T from './content/T.astro';
|
||||||
const year = new Date().getFullYear();
|
const year = new Date().getFullYear();
|
||||||
---
|
---
|
||||||
<footer class="ftr">
|
<footer class="ftr">
|
||||||
<div class="container ftr__grid">
|
<div class="container ftr__grid">
|
||||||
<div>
|
<div>
|
||||||
<img src="/img/logo-light.png" alt="InsanityLab" width="140" loading="lazy" />
|
<img src={contentImageUrl('footer.logo.image', '/img/logo-light.png')} alt="InsanityLab" width="140" loading="lazy" />
|
||||||
<p class="ftr__tag">PERFORMANCE. BALANCE. LONGEVITY.</p>
|
<T tag="footer.tagline" as="p" class="ftr__tag" />
|
||||||
<p>Promuoviamo il movimento come cura di sé. Abitudini sostenibili per benessere fisico e mentale.</p>
|
<T tag="footer.about" as="p" />
|
||||||
<p>{site.phone}<br />{site.address}, {site.cityLine}</p>
|
<p>{t('global.contact.phone')}<br />{t('global.contact.address')}, {t('global.contact.city-line')}</p>
|
||||||
{site.hours.map((h) => <p class="ftr__hours">{h}</p>)}
|
<p class="ftr__hours">{t('global.hours.1')}</p>
|
||||||
|
<p class="ftr__hours">{t('global.hours.2')}</p>
|
||||||
</div>
|
</div>
|
||||||
<nav aria-label="training">
|
<nav aria-label="training">
|
||||||
<h4>Training</h4>
|
<T tag="footer.col.training-title" as="h4" />
|
||||||
{site.footerTraining.map((l) => <a href={l.href}>{l.label}</a>)}
|
{site.footerTraining.map((l, i) => <a href={l.href}>{t(`footer.training.${i + 1}.label`)}</a>)}
|
||||||
</nav>
|
</nav>
|
||||||
<nav aria-label="programmi">
|
<nav aria-label="programmi">
|
||||||
<h4>Programmi</h4>
|
<T tag="footer.col.programs-title" as="h4" />
|
||||||
{site.footerPrograms.map((l) => <a href={l.href}>{l.label}</a>)}
|
{site.footerPrograms.map((l, i) => <a href={l.href}>{t(`footer.programs.${i + 1}.label`)}</a>)}
|
||||||
</nav>
|
</nav>
|
||||||
<div>
|
<div>
|
||||||
<h4>Contact</h4>
|
<T tag="footer.col.contact-title" as="h4" />
|
||||||
<ContactForm variant="footer" />
|
<ContactForm variant="footer" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="ftr__bar">
|
<div class="ftr__bar">
|
||||||
<div class="container ftr__bar-in">
|
<div class="container ftr__bar-in">
|
||||||
<p>© {year} <strong>Insanitylab</strong>, All Rights Reserved</p>
|
<p>© {year} <T tag="footer.copyright" as="span" /></p>
|
||||||
<p>Seguici {site.socials.map((s) => <a href={s.url} rel="noopener" target="_blank">{s.label}</a>)}</p>
|
<p>{t('footer.social-label')} {site.socials.map((s) => <a href={s.url} rel="noopener" target="_blank">{s.label}</a>)}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
---
|
---
|
||||||
import { site } from '../data/site';
|
import { site } from '../data/site';
|
||||||
|
import { t, contentImageUrl } from '../lib/content';
|
||||||
const path = Astro.url.pathname;
|
const path = Astro.url.pathname;
|
||||||
---
|
---
|
||||||
<header class="hdr" id="site-header">
|
<header class="hdr" id="site-header">
|
||||||
<div class="container hdr__in">
|
<div class="container hdr__in">
|
||||||
<a href="/" class="hdr__logo"><img src="/img/logo-dark.png" alt="InsanityLab" width="150" /></a>
|
<a href="/" class="hdr__logo"><img src={contentImageUrl('header.logo.image', '/img/logo-dark.png')} alt={t('header.logo.alt')} width="150" /></a>
|
||||||
<nav class="hdr__nav" id="site-nav" aria-label="principale">
|
<nav class="hdr__nav" id="site-nav" aria-label="principale">
|
||||||
{site.navigation.map((item) => (
|
{site.navigation.map((item, i) => (
|
||||||
<a href={item.href} class:list={['hdr__link', { 'is-active': path === item.href || (item.href !== '/' && path.startsWith(item.href)) }]}>{item.label}</a>
|
<a href={item.href} class:list={['hdr__link', { 'is-active': path === item.href || (item.href !== '/' && path.startsWith(item.href)) }]}>{t(`global.nav.${i + 1}.label`)}</a>
|
||||||
))}
|
))}
|
||||||
</nav>
|
</nav>
|
||||||
<button class="hdr__burger" id="nav-toggle" aria-label="Apri menu" aria-expanded="false">
|
<button class="hdr__burger" id="nav-toggle" aria-label="Apri menu" aria-expanded="false">
|
||||||
|
|||||||
@@ -18,6 +18,46 @@ export const contentSeed: SeedEntry[] = [
|
|||||||
T('global.contact.city-line', site.cityLine, []),
|
T('global.contact.city-line', site.cityLine, []),
|
||||||
T('global.hours.1', site.hours[0], []),
|
T('global.hours.1', site.hours[0], []),
|
||||||
T('global.hours.2', site.hours[1], []),
|
T('global.hours.2', site.hours[1], []),
|
||||||
|
T('global.nav.1.label', site.navigation[0].label, []),
|
||||||
|
T('global.nav.2.label', site.navigation[1].label, []),
|
||||||
|
T('global.nav.3.label', site.navigation[2].label, []),
|
||||||
|
T('global.nav.4.label', site.navigation[3].label, []),
|
||||||
|
T('global.nav.5.label', site.navigation[4].label, []),
|
||||||
|
|
||||||
|
// --- Header ---
|
||||||
|
T('header.logo.alt', 'InsanityLab', []),
|
||||||
|
I('header.logo.image'),
|
||||||
|
|
||||||
|
// --- Footer ---
|
||||||
|
I('footer.logo.image'),
|
||||||
|
H('footer.tagline', 'PERFORMANCE. BALANCE. LONGEVITY.'),
|
||||||
|
T('footer.about', 'Promuoviamo il movimento come cura di sé. Abitudini sostenibili per benessere fisico e mentale.'),
|
||||||
|
T('footer.col.training-title', 'Training'),
|
||||||
|
T('footer.col.programs-title', 'Programmi'),
|
||||||
|
T('footer.col.contact-title', 'Contact'),
|
||||||
|
H('footer.copyright', '<strong>Insanitylab</strong>, All Rights Reserved'),
|
||||||
|
T('footer.social-label', 'Seguici', []),
|
||||||
|
T('footer.training.1.label', site.footerTraining[0].label, []),
|
||||||
|
T('footer.training.2.label', site.footerTraining[1].label, []),
|
||||||
|
T('footer.training.3.label', site.footerTraining[2].label, []),
|
||||||
|
T('footer.training.4.label', site.footerTraining[3].label, []),
|
||||||
|
T('footer.programs.1.label', site.footerPrograms[0].label, []),
|
||||||
|
T('footer.programs.2.label', site.footerPrograms[1].label, []),
|
||||||
|
T('footer.programs.3.label', site.footerPrograms[2].label, []),
|
||||||
|
T('footer.programs.4.label', site.footerPrograms[3].label, []),
|
||||||
|
T('footer.programs.5.label', site.footerPrograms[4].label, []),
|
||||||
|
T('footer.programs.6.label', site.footerPrograms[5].label, []),
|
||||||
|
|
||||||
|
// --- Contact form ---
|
||||||
|
T('form.field.first-name', 'Nome', []),
|
||||||
|
T('form.field.last-name', 'Cognome', []),
|
||||||
|
T('form.field.phone', 'Telefono', []),
|
||||||
|
T('form.field.email', 'E-mail', []),
|
||||||
|
T('form.field.message', 'Messaggio', []),
|
||||||
|
T('form.submit', 'Invia messaggio'),
|
||||||
|
T('form.msg.success', 'Messaggio inviato, ti ricontatteremo al più presto.', []),
|
||||||
|
T('form.msg.error-generic', 'Errore di invio, riprova più tardi.', []),
|
||||||
|
T('form.msg.error-network', 'Errore di rete, riprova più tardi.', []),
|
||||||
// I task di estrazione aggiungono qui le entry di header/footer/pagine/data file.
|
// I task di estrazione aggiungono qui le entry di header/footer/pagine/data file.
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user