Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 59dff13e22 | |||
| 5c39b04c31 | |||
| ae98c4b889 | |||
| c65effb0ed | |||
| 67dc554810 |
@@ -2,6 +2,7 @@
|
|||||||
import { site } from '../data/site';
|
import { site } from '../data/site';
|
||||||
import { t, contentImageUrl } from '../lib/content';
|
import { t, contentImageUrl } from '../lib/content';
|
||||||
import { landingFor } from '../lib/auth';
|
import { landingFor } from '../lib/auth';
|
||||||
|
import { linkConsulenza } from '../data/consulenza';
|
||||||
interface Props {
|
interface Props {
|
||||||
user: { username: string; role: string } | null;
|
user: { username: string; role: string } | null;
|
||||||
showTags: boolean;
|
showTags: boolean;
|
||||||
@@ -17,6 +18,8 @@ const path = Astro.url.pathname;
|
|||||||
// si cambia una riga — ed e' l'unico posto del sito che nomina l'area riservata.
|
// si cambia una riga — ed e' l'unico posto del sito che nomina l'area riservata.
|
||||||
const AREA_RISERVATA = 'https://piattaforme.tielogic.xyz';
|
const AREA_RISERVATA = 'https://piattaforme.tielogic.xyz';
|
||||||
const areaHref = user ? landingFor(user.role) : '/admin';
|
const areaHref = user ? landingFor(user.role) : '/admin';
|
||||||
|
// Consulenza con Nicola su ogni pagina, non solo sulla Reformer Class (Adriano 30/09, #22).
|
||||||
|
const consulenzaHref = linkConsulenza(t('global.consulenza.url'));
|
||||||
---
|
---
|
||||||
<header class="hdr" id="site-header">
|
<header class="hdr" id="site-header">
|
||||||
<div class="container hdr__in">
|
<div class="container hdr__in">
|
||||||
@@ -27,7 +30,9 @@ const areaHref = user ? landingFor(user.role) : '/admin';
|
|||||||
<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>
|
<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>
|
||||||
)
|
)
|
||||||
))}
|
))}
|
||||||
|
<a class="hdr__link hdr__consulenza-mob" href={consulenzaHref} target="_blank" rel="noopener noreferrer">{t('global.consulenza.cta-breve')}</a>
|
||||||
</nav>
|
</nav>
|
||||||
|
<a class="hdr__consulenza" href={consulenzaHref} target="_blank" rel="noopener noreferrer">{t('global.consulenza.cta-breve')}</a>
|
||||||
<div class="hdr__user">
|
<div class="hdr__user">
|
||||||
{user ? (
|
{user ? (
|
||||||
<details class="umenu">
|
<details class="umenu">
|
||||||
@@ -55,6 +60,8 @@ const areaHref = user ? landingFor(user.role) : '/admin';
|
|||||||
.hdr.is-scrolled { box-shadow: 0 2px 14px rgba(0,0,0,.08); }
|
.hdr.is-scrolled { box-shadow: 0 2px 14px rgba(0,0,0,.08); }
|
||||||
.hdr__in { display: flex; align-items: center; justify-content: space-between; height: var(--header-h); }
|
.hdr__in { display: flex; align-items: center; justify-content: space-between; height: var(--header-h); }
|
||||||
.hdr__nav { display: flex; gap: 34px; }
|
.hdr__nav { display: flex; gap: 34px; }
|
||||||
|
/* Col bottone Consulenza nella barra le voci non devono andare a capo (#22). */
|
||||||
|
@media (min-width: 992px) { .hdr__nav { gap: 22px; } .hdr__link, .hdr__login { white-space: nowrap; } .hdr__logo { flex-shrink: 0; margin-right: 28px; } }
|
||||||
.hdr__link { font-family: var(--font-heading); font-size: .72rem; font-weight: 600; letter-spacing: .18em; text-transform: uppercase; text-decoration: none; color: var(--c-heading); transition: color .3s ease; }
|
.hdr__link { font-family: var(--font-heading); font-size: .72rem; font-weight: 600; letter-spacing: .18em; text-transform: uppercase; text-decoration: none; color: var(--c-heading); transition: color .3s ease; }
|
||||||
.hdr__link:hover, .hdr__link.is-active { color: var(--c-accent-dark); }
|
.hdr__link:hover, .hdr__link.is-active { color: var(--c-accent-dark); }
|
||||||
.hdr__link--bio { color: var(--c-accent-dark); }
|
.hdr__link--bio { color: var(--c-accent-dark); }
|
||||||
@@ -79,6 +86,13 @@ const areaHref = user ? landingFor(user.role) : '/admin';
|
|||||||
.plat__panel { position: static; box-shadow: none; padding: 0 0 8px; min-width: 0; }
|
.plat__panel { position: static; box-shadow: none; padding: 0 0 8px; min-width: 0; }
|
||||||
.plat__item { padding: 10px 0 10px 14px; }
|
.plat__item { padding: 10px 0 10px 14px; }
|
||||||
}
|
}
|
||||||
|
.hdr__consulenza { font-family: var(--font-heading); font-size: .68rem; font-weight: 600; letter-spacing: .14em; text-transform: uppercase; text-decoration: none; color: #fff; background: #6b5d5b; padding: 10px 14px; margin: 0 18px; white-space: nowrap; transition: background .2s; }
|
||||||
|
.hdr__consulenza:hover { background: var(--c-accent-dark); }
|
||||||
|
.hdr__consulenza-mob { display: none; }
|
||||||
|
@media (max-width: 991px) {
|
||||||
|
.hdr__consulenza { display: none; }
|
||||||
|
.hdr__consulenza-mob { display: block; color: var(--c-accent-dark); }
|
||||||
|
}
|
||||||
.hdr__user { display: flex; align-items: center; }
|
.hdr__user { display: flex; align-items: center; }
|
||||||
.hdr__login { font-family: var(--font-heading); font-size: .72rem; font-weight: 600; letter-spacing: .18em; text-transform: uppercase; text-decoration: none; color: var(--c-heading); }
|
.hdr__login { font-family: var(--font-heading); font-size: .72rem; font-weight: 600; letter-spacing: .18em; text-transform: uppercase; text-decoration: none; color: var(--c-heading); }
|
||||||
.hdr__login:hover { color: var(--c-accent-dark); }
|
.hdr__login:hover { color: var(--c-accent-dark); }
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
// Consulenza conoscitiva gratuita con Nicola (prenotazione su Google Calendar).
|
||||||
|
//
|
||||||
|
// Il link vive nel pannello contenuti (tag `global.consulenza.url`): qui c'è il valore di
|
||||||
|
// partenza e la guardia. Il tag è modificabile da admin, quindi si accetta solo https.
|
||||||
|
export const CONSULENZA_URL_DEFAULT = 'https://calendar.app.google/nWXMGD2S5g2pVeeD7';
|
||||||
|
|
||||||
|
/** Slug delle pagine servizio che mostrano il bottone di prenotazione. */
|
||||||
|
export const PAGINE_CON_CONSULENZA = ['reformer-class'];
|
||||||
|
|
||||||
|
/** Link da usare: il valore del pannello se è https, altrimenti quello di default
|
||||||
|
* (niente javascript:, http:, vuoto). */
|
||||||
|
export function linkConsulenza(valore: string): string {
|
||||||
|
const v = (valore ?? '').trim();
|
||||||
|
return v.startsWith('https://') ? v : CONSULENZA_URL_DEFAULT;
|
||||||
|
}
|
||||||
@@ -7,6 +7,7 @@ import { partners } from './partners';
|
|||||||
import { disciplines, days, slots } from './agenda';
|
import { disciplines, days, slots } from './agenda';
|
||||||
import { services } from './services';
|
import { services } from './services';
|
||||||
import { performanceClassPricing } from './pricing';
|
import { performanceClassPricing } from './pricing';
|
||||||
|
import { CONSULENZA_URL_DEFAULT } from './consulenza';
|
||||||
|
|
||||||
export type ContentType = 'text' | 'html' | 'image';
|
export type ContentType = 'text' | 'html' | 'image';
|
||||||
export interface SeedEntry { tag: string; type: ContentType; value: string; styleOptions?: StyleGroup[] }
|
export interface SeedEntry { tag: string; type: ContentType; value: string; styleOptions?: StyleGroup[] }
|
||||||
@@ -270,6 +271,10 @@ export const contentSeed: SeedEntry[] = [
|
|||||||
T('service.pricing.entries-plural', 'ingressi settimanali', []),
|
T('service.pricing.entries-plural', 'ingressi settimanali', []),
|
||||||
T('service.pricing.buy-cta', 'Acquista', []),
|
T('service.pricing.buy-cta', 'Acquista', []),
|
||||||
T('service.contact-cta', 'Contattaci', []),
|
T('service.contact-cta', 'Contattaci', []),
|
||||||
|
T('service.consulenza-cta', 'Prenota una consulenza conoscitiva gratuita', []),
|
||||||
|
T('service.consulenza-note', '30-45 minuti con Nicola, in sede: via Leandro Alberti 76, primo piano', []),
|
||||||
|
T('global.consulenza.url', CONSULENZA_URL_DEFAULT, []),
|
||||||
|
T('global.consulenza.cta-breve', 'Consulenza gratuita', []),
|
||||||
|
|
||||||
// --- Pricing performance class (data-driven da pricing.ts; monthly/entries restano nel data file) ---
|
// --- Pricing performance class (data-driven da pricing.ts; monthly/entries restano nel data file) ---
|
||||||
T('pricing.heading', performanceClassPricing.heading),
|
T('pricing.heading', performanceClassPricing.heading),
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import TImg from '../../components/content/TImg.astro';
|
|||||||
import CalendarioModal from '../../components/CalendarioModal.astro';
|
import CalendarioModal from '../../components/CalendarioModal.astro';
|
||||||
import { calendariDaMostrare, PAGINE_CON_CALENDARIO } from '../../data/calendari';
|
import { calendariDaMostrare, PAGINE_CON_CALENDARIO } from '../../data/calendari';
|
||||||
import { t } from '../../lib/content';
|
import { t } from '../../lib/content';
|
||||||
|
import { PAGINE_CON_CONSULENZA, linkConsulenza } from '../../data/consulenza';
|
||||||
export const prerender = false;
|
export const prerender = false;
|
||||||
|
|
||||||
const service = getService(Astro.params.slug!);
|
const service = getService(Astro.params.slug!);
|
||||||
@@ -38,8 +39,18 @@ const tones = ['tan', 'taupe', 'dark'];
|
|||||||
<div>
|
<div>
|
||||||
<h2>{t(`service.${slug}.title`).toUpperCase()}</h2>
|
<h2>{t(`service.${slug}.title`).toUpperCase()}</h2>
|
||||||
<T tag={`service.${slug}.long-description`} as="p" class="prog__desc" />
|
<T tag={`service.${slug}.long-description`} as="p" class="prog__desc" />
|
||||||
{slug === 'reformer-class' && (
|
{(slug === 'reformer-class' || PAGINE_CON_CONSULENZA.includes(slug)) && (
|
||||||
<p class="prog__cta"><a class="btn" href="/contact">{t('service.contact-cta')}</a></p>
|
<div class="prog__cta">
|
||||||
|
<div class="prog__cta-row">
|
||||||
|
{slug === 'reformer-class' && <a class="btn" href="/contact">{t('service.contact-cta')}</a>}
|
||||||
|
{PAGINE_CON_CONSULENZA.includes(slug) && (
|
||||||
|
<div class="prog__cta-consulenza">
|
||||||
|
<a class="btn btn--consulenza" href={linkConsulenza(t('global.consulenza.url'))} target="_blank" rel="noopener noreferrer">{t('service.consulenza-cta')}</a>
|
||||||
|
<T tag="service.consulenza-note" as="p" class="prog__cta-note" />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
{service.features.length > 0 && (
|
{service.features.length > 0 && (
|
||||||
<ul class="prog__features">
|
<ul class="prog__features">
|
||||||
@@ -149,6 +160,14 @@ const tones = ['tan', 'taupe', 'dark'];
|
|||||||
.prog__calendario { display: flex; align-items: center; gap: 14px; width: 100%; margin-top: 36px; padding: 10px 16px 10px 10px; border: 0; cursor: pointer; text-align: left; background: #6b5d5b; color: #fff; font-family: var(--font-heading); font-size: .82rem; font-weight: 600; letter-spacing: .14em; text-transform: uppercase; transition: background .2s; }
|
.prog__calendario { display: flex; align-items: center; gap: 14px; width: 100%; margin-top: 36px; padding: 10px 16px 10px 10px; border: 0; cursor: pointer; text-align: left; background: #6b5d5b; color: #fff; font-family: var(--font-heading); font-size: .82rem; font-weight: 600; letter-spacing: .14em; text-transform: uppercase; transition: background .2s; }
|
||||||
.prog__calendario:hover { background: var(--c-accent-dark); }
|
.prog__calendario:hover { background: var(--c-accent-dark); }
|
||||||
.prog__cta { margin: 10px 0 30px; }
|
.prog__cta { margin: 10px 0 30px; }
|
||||||
|
.prog__cta-row { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 12px; }
|
||||||
|
/* La nota (durata, sede) sta sotto il suo bottone, non sotto Contattaci (Adriano 29/09). */
|
||||||
|
.prog__cta-consulenza { display: flex; flex-direction: column; }
|
||||||
|
.btn--consulenza { background: #6b5d5b; }
|
||||||
|
.btn--consulenza:hover { background: var(--c-accent-dark); }
|
||||||
|
/* Il paragrafo lo stampa il componente T: senza :global lo stile scoped della pagina non lo raggiunge. */
|
||||||
|
.prog__cta :global(.prog__cta-note) { font-size: .8rem; color: var(--c-text-light); margin: 8px 0 0; }
|
||||||
|
@media (max-width: 600px) { .prog__cta-row > .btn, .prog__cta-consulenza { flex: 1 1 100%; } .prog__cta-row .btn { justify-content: center; text-align: center; } }
|
||||||
.prog__icon { display: inline-flex; align-items: center; justify-content: center; width: 48px; height: 48px; background: var(--c-accent); color: #fff; flex-shrink: 0; }
|
.prog__icon { display: inline-flex; align-items: center; justify-content: center; width: 48px; height: 48px; background: var(--c-accent); color: #fff; flex-shrink: 0; }
|
||||||
.price__group { border-top: 1px solid #ddd5ca; padding-block: 18px; }
|
.price__group { border-top: 1px solid #ddd5ca; padding-block: 18px; }
|
||||||
.price__group summary { cursor: pointer; font-family: var(--font-heading); letter-spacing: .12em; text-transform: uppercase; font-size: .85rem; color: var(--c-heading); }
|
.price__group summary { cursor: pointer; font-family: var(--font-heading); letter-spacing: .12em; text-transform: uppercase; font-size: .85rem; color: var(--c-heading); }
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import { describe, it, expect } from 'vitest';
|
||||||
|
import { linkConsulenza, CONSULENZA_URL_DEFAULT, PAGINE_CON_CONSULENZA } from '../src/data/consulenza';
|
||||||
|
import { contentSeed } from '../src/data/content-seed';
|
||||||
|
import { services } from '../src/data/services';
|
||||||
|
|
||||||
|
describe('consulenza conoscitiva', () => {
|
||||||
|
it('accetta un link https, anche con spazi attorno', () => {
|
||||||
|
expect(linkConsulenza('https://example.com/x')).toBe('https://example.com/x');
|
||||||
|
expect(linkConsulenza(' https://example.com/x ')).toBe('https://example.com/x');
|
||||||
|
});
|
||||||
|
it.each(['javascript:alert(1)', 'http://x.it', '', ' '])('scarta %j e usa il default', (v) => {
|
||||||
|
expect(linkConsulenza(v)).toBe(CONSULENZA_URL_DEFAULT);
|
||||||
|
});
|
||||||
|
it('il seed ha i tre tag', () => {
|
||||||
|
const v = (tag: string) => contentSeed.find((e) => e.tag === tag)?.value;
|
||||||
|
expect(v('service.consulenza-cta')).toBe('Prenota una consulenza conoscitiva gratuita');
|
||||||
|
expect(v('service.consulenza-note')).toBe('30-45 minuti con Nicola, in sede: via Leandro Alberti 76, primo piano');
|
||||||
|
expect(v('global.consulenza.url')).toBe(CONSULENZA_URL_DEFAULT);
|
||||||
|
});
|
||||||
|
it('le pagine con consulenza esistono', () => {
|
||||||
|
expect(PAGINE_CON_CONSULENZA).toContain('reformer-class');
|
||||||
|
for (const slug of PAGINE_CON_CONSULENZA) {
|
||||||
|
const s = services.find((x) => x.slug === slug);
|
||||||
|
expect(s, slug).toBeDefined();
|
||||||
|
expect(s!.page).not.toBe(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user