276 lines
8.6 KiB
Svelte
276 lines
8.6 KiB
Svelte
<script lang="ts">
|
|
import SeoHead from '$lib/components/SeoHead.svelte';
|
|
import AboutPage from '$lib/components/AboutPage.svelte';
|
|
import Footer from '$lib/components/Footer.svelte';
|
|
import Header from '$lib/components/Header.svelte';
|
|
import BookingPage from '$lib/components/BookingPage.svelte';
|
|
import LegalPage from '$lib/components/LegalPage.svelte';
|
|
import PricingPage from '$lib/components/PricingPage.svelte';
|
|
import { aboutPageContent } from '$lib/content/about';
|
|
import ServiceLandingPage from '$lib/components/ServiceLandingPage.svelte';
|
|
import { dogWalkingContent } from '$lib/content/dog-walking';
|
|
import { ourPricingContent } from '$lib/content/our-pricing';
|
|
import { packWalksContent } from '$lib/content/pack-walks';
|
|
import { privacyPolicyContent } from '$lib/content/privacy-policy';
|
|
import { puppyVisitsContent } from '$lib/content/puppy-visits';
|
|
import { termsAndConditionsContent } from '$lib/content/terms-and-conditions';
|
|
import type { PageData } from './$types';
|
|
|
|
export let data: PageData;
|
|
|
|
const siteUrl = 'https://www.goodwalk.co.nz';
|
|
const defaultSeoImage = '/images/auckland-dog-walking-happy-dog-hero.png';
|
|
const defaultSeoImageAlt = 'Goodwalk Auckland dog walking services';
|
|
|
|
function absoluteUrl(value: string) {
|
|
if (value.startsWith('http://') || value.startsWith('https://')) {
|
|
return value;
|
|
}
|
|
|
|
return `${siteUrl}${value.startsWith('/') ? value : `/${value}`}`;
|
|
}
|
|
|
|
function aggregateOfferSchema(plans: { price: string }[]) {
|
|
const numericPrices = plans
|
|
.map((plan) => Number(plan.price.replace(/[^0-9.]/g, '')))
|
|
.filter((value) => Number.isFinite(value) && value > 0);
|
|
|
|
if (numericPrices.length === 0) {
|
|
return null;
|
|
}
|
|
|
|
const lowPrice = Math.min(...numericPrices);
|
|
const highPrice = Math.max(...numericPrices);
|
|
|
|
return {
|
|
'@type': 'AggregateOffer',
|
|
priceCurrency: 'NZD',
|
|
lowPrice: lowPrice.toFixed(2),
|
|
highPrice: highPrice.toFixed(2),
|
|
offerCount: numericPrices.length,
|
|
availability: 'https://schema.org/InStock'
|
|
};
|
|
}
|
|
|
|
function breadcrumbSchema(name: string, path: string) {
|
|
return {
|
|
'@context': 'https://schema.org',
|
|
'@type': 'BreadcrumbList',
|
|
itemListElement: [
|
|
{
|
|
'@type': 'ListItem',
|
|
position: 1,
|
|
name: 'Home',
|
|
item: siteUrl
|
|
},
|
|
{
|
|
'@type': 'ListItem',
|
|
position: 2,
|
|
name,
|
|
item: `${siteUrl}${path}`
|
|
}
|
|
]
|
|
};
|
|
}
|
|
|
|
let seoImage = defaultSeoImage;
|
|
let seoImageAlt = defaultSeoImageAlt;
|
|
let preloadHeroImage = false;
|
|
let pageStructuredData: Record<string, unknown>[] = [];
|
|
|
|
$: {
|
|
seoImage = defaultSeoImage;
|
|
seoImageAlt = defaultSeoImageAlt;
|
|
preloadHeroImage = false;
|
|
pageStructuredData = [
|
|
{
|
|
'@context': 'https://schema.org',
|
|
'@type': 'WebPage',
|
|
name: data.page.title,
|
|
description: data.page.description,
|
|
url: `${siteUrl}${data.page.canonicalPath}`
|
|
},
|
|
breadcrumbSchema(data.page.title, data.page.canonicalPath)
|
|
];
|
|
|
|
if (data.slug === 'pack-walks') {
|
|
preloadHeroImage = true;
|
|
seoImage = packWalksContent.hero.imageUrl;
|
|
seoImageAlt = packWalksContent.hero.imageAlt;
|
|
pageStructuredData = [
|
|
{
|
|
'@context': 'https://schema.org',
|
|
'@type': 'Service',
|
|
name: packWalksContent.hero.title,
|
|
description: data.page.description,
|
|
serviceType: 'Pack Walks',
|
|
provider: {
|
|
'@type': 'LocalBusiness',
|
|
name: 'Goodwalk',
|
|
url: siteUrl
|
|
},
|
|
areaServed: 'Auckland Central, New Zealand',
|
|
image: absoluteUrl(seoImage),
|
|
url: `${siteUrl}${data.page.canonicalPath}`,
|
|
offers: aggregateOfferSchema(packWalksContent.pricing.plans)
|
|
},
|
|
breadcrumbSchema('Pack Walks', data.page.canonicalPath)
|
|
];
|
|
} else if (data.slug === 'dog-walking') {
|
|
preloadHeroImage = true;
|
|
seoImage = dogWalkingContent.hero.imageUrl;
|
|
seoImageAlt = dogWalkingContent.hero.imageAlt;
|
|
pageStructuredData = [
|
|
{
|
|
'@context': 'https://schema.org',
|
|
'@type': 'Service',
|
|
name: dogWalkingContent.hero.title,
|
|
description: data.page.description,
|
|
serviceType: '1:1 Dog Walking',
|
|
provider: {
|
|
'@type': 'LocalBusiness',
|
|
name: 'Goodwalk',
|
|
url: siteUrl
|
|
},
|
|
areaServed: 'Auckland Central, New Zealand',
|
|
image: absoluteUrl(seoImage),
|
|
url: `${siteUrl}${data.page.canonicalPath}`,
|
|
offers: aggregateOfferSchema(dogWalkingContent.pricing.plans)
|
|
},
|
|
breadcrumbSchema('1:1 Walks', data.page.canonicalPath)
|
|
];
|
|
} else if (data.slug === 'puppy-visits') {
|
|
preloadHeroImage = true;
|
|
seoImage = puppyVisitsContent.hero.imageUrl;
|
|
seoImageAlt = puppyVisitsContent.hero.imageAlt;
|
|
pageStructuredData = [
|
|
{
|
|
'@context': 'https://schema.org',
|
|
'@type': 'Service',
|
|
name: puppyVisitsContent.hero.title,
|
|
description: data.page.description,
|
|
serviceType: 'Puppy Visits',
|
|
provider: {
|
|
'@type': 'LocalBusiness',
|
|
name: 'Goodwalk',
|
|
url: siteUrl
|
|
},
|
|
areaServed: 'Auckland Central, New Zealand',
|
|
image: absoluteUrl(seoImage),
|
|
url: `${siteUrl}${data.page.canonicalPath}`,
|
|
offers: aggregateOfferSchema(puppyVisitsContent.pricing.plans)
|
|
},
|
|
breadcrumbSchema('Puppy Visits', data.page.canonicalPath)
|
|
];
|
|
} else if (data.slug === 'our-pricing') {
|
|
pageStructuredData = [
|
|
{
|
|
'@context': 'https://schema.org',
|
|
'@type': 'CollectionPage',
|
|
name: data.page.title,
|
|
description: data.page.description,
|
|
url: `${siteUrl}${data.page.canonicalPath}`
|
|
},
|
|
breadcrumbSchema('Our Pricing', data.page.canonicalPath)
|
|
];
|
|
} else if (data.slug === 'about') {
|
|
seoImage = aboutPageContent.sections[0].imageUrl;
|
|
seoImageAlt = aboutPageContent.sections[0].imageAlt;
|
|
pageStructuredData = [
|
|
{
|
|
'@context': 'https://schema.org',
|
|
'@type': 'AboutPage',
|
|
name: data.page.title,
|
|
description: data.page.description,
|
|
url: `${siteUrl}${data.page.canonicalPath}`,
|
|
image: absoluteUrl(seoImage)
|
|
},
|
|
breadcrumbSchema('About Us', data.page.canonicalPath)
|
|
];
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<SeoHead
|
|
title={data.page.title}
|
|
description={data.page.description}
|
|
canonicalPath={data.page.canonicalPath}
|
|
image={seoImage}
|
|
imageAlt={seoImageAlt}
|
|
structuredData={pageStructuredData}
|
|
preloadImage={preloadHeroImage}
|
|
/>
|
|
|
|
<Header navigation={data.content.navigation} />
|
|
|
|
{#if data.slug === 'pack-walks'}
|
|
<ServiceLandingPage content={data.content} pageContent={packWalksContent} currentPath={data.page.canonicalPath} />
|
|
{:else if data.slug === 'dog-walking'}
|
|
<ServiceLandingPage content={data.content} pageContent={dogWalkingContent} currentPath={data.page.canonicalPath} />
|
|
{:else if data.slug === 'puppy-visits'}
|
|
<ServiceLandingPage content={data.content} pageContent={puppyVisitsContent} currentPath={data.page.canonicalPath} />
|
|
{:else if data.slug === 'our-pricing'}
|
|
<PricingPage content={data.content} pageContent={ourPricingContent} />
|
|
{:else if data.slug === 'about'}
|
|
<AboutPage content={data.content} pageContent={aboutPageContent} />
|
|
{:else if data.slug === 'terms-and-conditions'}
|
|
<LegalPage pageContent={termsAndConditionsContent} />
|
|
{:else if data.slug === 'privacy-policy'}
|
|
<LegalPage pageContent={privacyPolicyContent} />
|
|
{:else if data.slug === 'contact-us'}
|
|
<BookingPage
|
|
booking={data.content.booking}
|
|
info={data.content.info}
|
|
allowGeneralEnquiry={data.generalEnquiryEnabled}
|
|
/>
|
|
{:else}
|
|
<main class="static-page">
|
|
<section class="static-page-hero">
|
|
<div class="static-page-inner">
|
|
<h1>{data.page.title}</h1>
|
|
</div>
|
|
</section>
|
|
</main>
|
|
{/if}
|
|
|
|
<Footer footer={data.content.footer} />
|
|
|
|
<style>
|
|
.static-page {
|
|
min-height: 50vh;
|
|
background: var(--off-white);
|
|
}
|
|
|
|
.static-page-hero {
|
|
padding: 96px 0 120px;
|
|
}
|
|
|
|
.static-page-inner {
|
|
max-width: var(--max-w);
|
|
margin: 0 auto;
|
|
padding: 0 50px;
|
|
}
|
|
|
|
h1 {
|
|
font-family: var(--font-head);
|
|
font-size: 56px;
|
|
line-height: 1.05;
|
|
letter-spacing: -0.04em;
|
|
color: #000;
|
|
}
|
|
|
|
@media (max-width: 768px) {
|
|
.static-page-hero {
|
|
padding: 56px 0 72px;
|
|
}
|
|
|
|
.static-page-inner {
|
|
padding: 0 24px;
|
|
}
|
|
|
|
h1 {
|
|
font-size: 34px;
|
|
}
|
|
}
|
|
</style>
|