Migrate to Next
This commit is contained in:
10
pages/_app.js
Normal file
10
pages/_app.js
Normal file
@@ -0,0 +1,10 @@
|
||||
import React from "react";
|
||||
import "@styles/globals.css";
|
||||
import "@fontsource/cooper-hewitt/400.css";
|
||||
import "@fontsource/cooper-hewitt/700.css";
|
||||
|
||||
function Application({ Component, pageProps }) {
|
||||
return <Component {...pageProps} />;
|
||||
}
|
||||
|
||||
export default Application;
|
||||
45
pages/about.js
Normal file
45
pages/about.js
Normal file
@@ -0,0 +1,45 @@
|
||||
import React from "react";
|
||||
import { Header, Layout, Section, Text } from "@components/index";
|
||||
import bannerImg from "../images/banner_bathroom.jpg";
|
||||
|
||||
export default function About() {
|
||||
return (
|
||||
<Layout title="About">
|
||||
<Header image={bannerImg} position="br">
|
||||
<Text size="xl" weight="bold" noMargin>
|
||||
<em>Easy as</em> ABC
|
||||
</Text>
|
||||
</Header>
|
||||
<Section title="About ABC Project Design">
|
||||
<Text>
|
||||
ABC Project Design Ltd is a medium sized family run business with more
|
||||
than 30 years experience in the building and construction industry. We
|
||||
offer a fully certified and accredited bathroom refurbishment service.
|
||||
</Text>
|
||||
<Text>
|
||||
We currently have 15 skilled tradesman within our workforce and
|
||||
operate in Essex, Hertfordshire, Kent and London. Our team include
|
||||
plumbers, carpenters, bathroom fitters, tilers, electricians,
|
||||
plasterers, painters and decorators. All our staff are vetted and have
|
||||
vast experience in there chosen fields.
|
||||
</Text>
|
||||
<Text>
|
||||
We specialise in bathroom refurbishments and floor tiling. Our
|
||||
stonemasons and tilers are specialists in ceramic, natural stone,
|
||||
marble, quartz, porcelain and mosaic tiles.
|
||||
</Text>
|
||||
<Text>
|
||||
Customer satisfaction is of paramount importance to us this and is
|
||||
reflected in our many five star reviews on Rated People and Bark. We
|
||||
strive to maximise our relationship with our customers by being honest
|
||||
and fair.
|
||||
</Text>
|
||||
<Text>
|
||||
We are fully insured and all work undertaken is guaranteed. Pricing is
|
||||
something we take extremely seriously and we aim to be ultra
|
||||
competitive.
|
||||
</Text>
|
||||
</Section>
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
30
pages/area-covered.js
Normal file
30
pages/area-covered.js
Normal file
@@ -0,0 +1,30 @@
|
||||
import React from "react";
|
||||
import { Header, Layout, Link, Map, Section, Text } from "@components/index";
|
||||
import { getGoogleAPIKey } from "../lib/env";
|
||||
|
||||
export default function AreaCovered({ apikey }) {
|
||||
return (
|
||||
<Layout title="Area covered">
|
||||
<Header map={<Map apikey={apikey} showRegion fullHeight />} />
|
||||
<Section title="Area covered">
|
||||
<Text>
|
||||
Our services are available, in London, Hertfordshire, Cambridgeshire,
|
||||
Essex and Kent.
|
||||
</Text>
|
||||
<Text>
|
||||
The area highlighted in the map is a rough guideline, if you are just
|
||||
outside the area then please do feel free to{" "}
|
||||
<Link href="/contact">get in touch</Link>.
|
||||
</Text>
|
||||
</Section>
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
|
||||
export async function getStaticProps() {
|
||||
return {
|
||||
props: {
|
||||
apikey: getGoogleAPIKey(),
|
||||
},
|
||||
};
|
||||
}
|
||||
254
pages/contact.js
Normal file
254
pages/contact.js
Normal file
@@ -0,0 +1,254 @@
|
||||
import React, { useRef, useState } from "react";
|
||||
import {
|
||||
Button,
|
||||
ContactButton,
|
||||
Grid,
|
||||
Header,
|
||||
Icon,
|
||||
IconWithText,
|
||||
InputField,
|
||||
Interrupt,
|
||||
Label,
|
||||
Layout,
|
||||
Link,
|
||||
Map,
|
||||
Section,
|
||||
Select,
|
||||
Text,
|
||||
} from "@components/index";
|
||||
import { getGoogleAPIKey } from "../lib/env";
|
||||
import { CheckCircleSvg, EnvelopeSvg, MobileSvg, TeamSvg } from "../icons";
|
||||
import bannerImg from "../images/banner_bathroom.jpg";
|
||||
|
||||
export default function About({ apikey }) {
|
||||
const formRef = useRef();
|
||||
const [formState, setFormState] = useState();
|
||||
|
||||
const handleSubmit = (e) => {
|
||||
e.preventDefault();
|
||||
setFormState("submitting");
|
||||
const body = new FormData(formRef.current);
|
||||
fetch("/contact", { method: "POST", body })
|
||||
.then((res) => {
|
||||
if (res.status !== 200) {
|
||||
setFormState("error");
|
||||
} else {
|
||||
setFormState("success");
|
||||
}
|
||||
})
|
||||
.catch(() => setFormState("error"));
|
||||
};
|
||||
|
||||
return (
|
||||
<Layout title="Contact us">
|
||||
<Header image={bannerImg} position="br">
|
||||
<Text size="xl" weight="bold" noMargin>
|
||||
<em>Get in</em> touch
|
||||
</Text>
|
||||
</Header>
|
||||
<Section>
|
||||
<Text size="xl">
|
||||
Are you planning a new bathroom? Are you looking for inspiration? Our
|
||||
team are ready to help you through every step of the journey.
|
||||
</Text>
|
||||
<Text>
|
||||
A typical bathroom refurbishment starts from £3,500, increasing up to
|
||||
£20,000. Our quotes include stripping out the old bathroom, disposal
|
||||
of rubbish, fitting the new bathroom, labour and building materials
|
||||
for tiling, plastering, painting and decorating. It does not include
|
||||
bathroom suites or tiles.
|
||||
</Text>
|
||||
<Grid md={2}>
|
||||
<div style={{ position: "relative" }}>
|
||||
{formState === "success" && (
|
||||
<>
|
||||
<IconWithText
|
||||
icon={
|
||||
<Icon color="dark" size="lg">
|
||||
<CheckCircleSvg />
|
||||
</Icon>
|
||||
}
|
||||
>
|
||||
<Text size="lg" color="dark" noMargin>
|
||||
Thank you for contacting us!
|
||||
</Text>
|
||||
</IconWithText>
|
||||
<Text>
|
||||
We will get back to you in the next two working days.
|
||||
</Text>
|
||||
</>
|
||||
)}
|
||||
|
||||
{formState !== "success" && (
|
||||
<>
|
||||
{formState === "submitting" && <Interrupt />}
|
||||
<IconWithText
|
||||
icon={
|
||||
<Icon size="lg" color="dark">
|
||||
<EnvelopeSvg />
|
||||
</Icon>
|
||||
}
|
||||
>
|
||||
<Text size="lg" color="dark" noMargin>
|
||||
Contact us
|
||||
</Text>
|
||||
</IconWithText>
|
||||
{formState === "error" && (
|
||||
<>
|
||||
<Text size="lg" color="primary" weight="bold">
|
||||
There was an error submitting the form, please try again
|
||||
later.
|
||||
</Text>
|
||||
<Text color="primary">
|
||||
Alternatively, please feel free to email us at{" "}
|
||||
<Link href="mailto:quotations@abcprojectdesign.com">
|
||||
quotations@abcprojectdesign.com
|
||||
</Link>
|
||||
.
|
||||
</Text>
|
||||
</>
|
||||
)}
|
||||
<form
|
||||
name="contact"
|
||||
method="POST"
|
||||
action="/contact"
|
||||
onSubmit={(e) => handleSubmit(e, scroll)}
|
||||
data-netlify="true"
|
||||
data-netlify-honeypot="bot-field"
|
||||
ref={formRef}
|
||||
>
|
||||
<input type="hidden" name="form-name" value="contact" />
|
||||
<Label htmlFor="contact-name">Name</Label>
|
||||
<InputField id="contact-name" name="name" />
|
||||
<Label htmlFor="contact-email">Email</Label>
|
||||
<InputField id="contact-email" name="email" />
|
||||
<Label htmlFor="contact-telephone">Telephone</Label>
|
||||
<InputField id="contact-telephone" name="telephone" />
|
||||
<Label htmlFor="contact-stage">
|
||||
What stage of planning are you at?
|
||||
</Label>
|
||||
<Select
|
||||
id="contact-stage"
|
||||
name="stage"
|
||||
options={[
|
||||
{ value: "", label: "" },
|
||||
{ value: "ready to hire", label: "I'm ready to hire" },
|
||||
{
|
||||
value: "budgeting and planning",
|
||||
label: "I'm planning and budgeting",
|
||||
},
|
||||
{
|
||||
value: "quote for insurance",
|
||||
label: "I need a quote for insurance",
|
||||
},
|
||||
]}
|
||||
/>
|
||||
<Label htmlFor="contact-start">
|
||||
When would you like the job to start?
|
||||
</Label>
|
||||
<Select
|
||||
id="contact-start"
|
||||
name="start"
|
||||
options={[
|
||||
{ value: "", label: "" },
|
||||
{ value: "urgently", label: "Urgently" },
|
||||
{ value: "within 1 week", label: "Within 1 week" },
|
||||
{ value: "within 2 weeks", label: "Within 2 weeks" },
|
||||
{ value: "within 1 month", label: "Within 1 month" },
|
||||
{ value: "within 2 months", label: "Within 2 months" },
|
||||
{ value: "not sure", label: "Not sure" },
|
||||
]}
|
||||
/>
|
||||
<Label htmlFor="contact-status">
|
||||
Are you the owner of the property?
|
||||
</Label>
|
||||
<Select
|
||||
id="contact-status"
|
||||
name="status"
|
||||
options={[
|
||||
{ value: "", label: "" },
|
||||
{ value: "owner", label: "I own the property" },
|
||||
{ value: "landlord", label: "I am the landlord" },
|
||||
{ value: "tenant", label: "I am a tenant" },
|
||||
{
|
||||
value: "council property",
|
||||
label: "It's a council property",
|
||||
},
|
||||
]}
|
||||
/>
|
||||
<Label htmlFor="contact-budget">What is your budget?</Label>
|
||||
<Select
|
||||
id="contact-budget"
|
||||
name="budget"
|
||||
options={[
|
||||
{ value: "under £2,000", label: "Under £2,000" },
|
||||
{ value: "under £3,000", label: "Under £3,000" },
|
||||
{ value: "under £4,000", label: "Under £4,000" },
|
||||
{ value: "under £5,000", label: "Under £5,000" },
|
||||
{ value: "under £6,000", label: "Under £6,000" },
|
||||
{ value: "under £7,000", label: "Under £7,000" },
|
||||
{ value: "under £8,000", label: "Under £8,000" },
|
||||
{ value: "under £9,000", label: "Under £9,000" },
|
||||
{ value: "under £10,000", label: "Under £10,000" },
|
||||
{ value: "under £15,000", label: "Under £15,000" },
|
||||
{ value: "under £20,000", label: "Under £20,000" },
|
||||
]}
|
||||
/>
|
||||
<Label htmlFor="contact-message">
|
||||
Describe what needs to be done
|
||||
</Label>
|
||||
<InputField id="contact-message" name="message" textArea />
|
||||
<Button type="submit">
|
||||
{formState === "submitting" ? "Submitting..." : "Submit"}
|
||||
</Button>
|
||||
</form>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
<div>
|
||||
<IconWithText
|
||||
icon={
|
||||
<Icon color="dark" size="lg">
|
||||
<TeamSvg />
|
||||
</Icon>
|
||||
}
|
||||
>
|
||||
<Text size="lg" color="dark" noMargin>
|
||||
The Team
|
||||
</Text>
|
||||
</IconWithText>
|
||||
<div>
|
||||
<Text noMargin>
|
||||
<strong>Daniel Costea</strong> – Project Director
|
||||
</Text>
|
||||
<ContactButton href="tel:+447378839358" size="sm">
|
||||
<Icon size="sm">
|
||||
<MobileSvg />
|
||||
</Icon>
|
||||
07378839358
|
||||
</ContactButton>
|
||||
<ContactButton
|
||||
href="mailto:quotations@abcprojectdesign.com"
|
||||
size="sm"
|
||||
>
|
||||
<Icon size="sm">
|
||||
<EnvelopeSvg />
|
||||
</Icon>
|
||||
quotations@abcprojectdesign.com
|
||||
</ContactButton>
|
||||
</div>
|
||||
</div>
|
||||
</Grid>
|
||||
</Section>
|
||||
<Map apikey={apikey} zoom={10} showMarker />
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
|
||||
export async function getStaticProps() {
|
||||
return {
|
||||
props: {
|
||||
apikey: getGoogleAPIKey(),
|
||||
},
|
||||
};
|
||||
}
|
||||
180
pages/index.js
Normal file
180
pages/index.js
Normal file
@@ -0,0 +1,180 @@
|
||||
import React from "react";
|
||||
import Image from "next/image";
|
||||
import {
|
||||
Button,
|
||||
Layout,
|
||||
Header,
|
||||
HeaderLogo,
|
||||
Heading,
|
||||
Section,
|
||||
Card,
|
||||
Grid,
|
||||
Text,
|
||||
Tile,
|
||||
Icon,
|
||||
Review,
|
||||
} from "@components/index";
|
||||
import {
|
||||
CheckCircleSvg,
|
||||
CalendarSvg,
|
||||
HammerSvg,
|
||||
PoundSvg,
|
||||
SmileSvg,
|
||||
SpySvg,
|
||||
} from "../icons";
|
||||
import bannerImg from "../images/banner_bathroom.jpg";
|
||||
import bathroomImg from "../images/bathroom.jpg";
|
||||
import tilingImg from "../images/tiling.jpg";
|
||||
import victorianImg from "../images/victorian_plumbing_logo.png";
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
<Layout>
|
||||
<Header image={bannerImg}>
|
||||
<HeaderLogo transition />
|
||||
</Header>
|
||||
<Section title="What we do">
|
||||
<Grid sm={2}>
|
||||
<Card
|
||||
heading={
|
||||
<Heading el="h3" size="md">
|
||||
Bathrooms
|
||||
</Heading>
|
||||
}
|
||||
image={bathroomImg}
|
||||
href="/services/bathrooms"
|
||||
>
|
||||
Fully accredited bathroom refurbishment service
|
||||
</Card>
|
||||
<Card
|
||||
heading={
|
||||
<Heading el="h3" size="md">
|
||||
Tiling
|
||||
</Heading>
|
||||
}
|
||||
image={tilingImg}
|
||||
href="/services/tiling"
|
||||
>
|
||||
We can install many different styles
|
||||
</Card>
|
||||
</Grid>
|
||||
</Section>
|
||||
<Section variant="secondary" title="Products">
|
||||
<Grid sm={2}>
|
||||
<div>
|
||||
<Image src={victorianImg} width={320} height={98} />
|
||||
</div>
|
||||
<div>
|
||||
<Text>
|
||||
Victorian Plumbing is a leading retailer of bathrooms online and
|
||||
our preferred supplier of bathroom suites.
|
||||
</Text>
|
||||
<Button href="https://www.victorianplumbing.co.uk/bathroom-suites">
|
||||
View products
|
||||
</Button>
|
||||
</div>
|
||||
</Grid>
|
||||
</Section>
|
||||
<Section title="All of our work is guaranteed!">
|
||||
<Text>
|
||||
If you are looking for a one-stop shop for your new bathroom, look no
|
||||
further. We can take care of all jobs required to complete your new
|
||||
bathroom, including plumbing, tiling and electrical works.
|
||||
</Text>
|
||||
<Grid sm={2} md={3}>
|
||||
<Tile>
|
||||
<Icon size="xl">
|
||||
<CheckCircleSvg />
|
||||
</Icon>
|
||||
<Heading el="h3" size="lg">
|
||||
100% Guaranteed
|
||||
</Heading>
|
||||
<Text>
|
||||
We guarantee all of our work. If you have any issues, we will fix
|
||||
it at no additional cost.
|
||||
</Text>
|
||||
</Tile>
|
||||
<Tile>
|
||||
<Icon size="xl">
|
||||
<PoundSvg />
|
||||
</Icon>
|
||||
<Heading el="h3" size="lg">
|
||||
Competitive Fees
|
||||
</Heading>
|
||||
<Text>
|
||||
We have affordable pricing and we strive to be as competitive as
|
||||
possible.
|
||||
</Text>
|
||||
</Tile>
|
||||
<Tile>
|
||||
<Icon size="xl">
|
||||
<SpySvg />
|
||||
</Icon>
|
||||
<Heading el="h3" size="lg">
|
||||
No hidden charges
|
||||
</Heading>
|
||||
<Text>
|
||||
All costs will be clearly stated up front in the contact.
|
||||
</Text>
|
||||
</Tile>
|
||||
<Tile>
|
||||
<Icon size="xl">
|
||||
<HammerSvg />
|
||||
</Icon>
|
||||
<Heading el="h3" size="lg">
|
||||
High Quality Craftmanship
|
||||
</Heading>
|
||||
<Text>
|
||||
Our skilled tradesmen have many years of experience in their craft
|
||||
and will ensure full compliance with industry standards and
|
||||
guidelines.
|
||||
</Text>
|
||||
</Tile>
|
||||
<Tile>
|
||||
<Icon size="xl">
|
||||
<CalendarSvg />
|
||||
</Icon>
|
||||
<Heading el="h3" size="lg">
|
||||
Transparent Deadlines
|
||||
</Heading>
|
||||
<Text>
|
||||
We will provide you with a start and finish date with your
|
||||
contract.
|
||||
</Text>
|
||||
</Tile>
|
||||
<Tile>
|
||||
<Icon size="xl">
|
||||
<SmileSvg />
|
||||
</Icon>
|
||||
<Heading el="h3" size="lg">
|
||||
Friendly Team
|
||||
</Heading>
|
||||
<Text>
|
||||
We will be friendly, respectful and curtious from start to finish.
|
||||
</Text>
|
||||
</Tile>
|
||||
</Grid>
|
||||
</Section>
|
||||
<Section variant="secondary" title="What our clients think of us">
|
||||
<Review
|
||||
type="Checkatrade"
|
||||
title="Full redecoration schedule bungalow"
|
||||
author="Mrs Ford"
|
||||
date="February 2021"
|
||||
>
|
||||
<Text italic>
|
||||
I have pleasure in providing this reference for Daniel. For the last
|
||||
7 weeks he has been working on the bungalow belonging to my aged
|
||||
uncle for whom I have Power of Attorney, to prepare the property,
|
||||
which was formerly a small holding, for the market. The house had to
|
||||
be cleared,of furniture, repairs carried out with a full
|
||||
redecoration schedule. In addition there were numerous outbuildings
|
||||
to clear and a 4 acre site, which was completely overgrown, to be
|
||||
brought up to standard. It was a huge undertaking but Daniel and his
|
||||
team took it on willingly.
|
||||
</Text>
|
||||
</Review>
|
||||
</Section>
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
81
pages/services/[service]/[slug].js
Normal file
81
pages/services/[service]/[slug].js
Normal file
@@ -0,0 +1,81 @@
|
||||
import React, { useState } from "react";
|
||||
import {
|
||||
CaseStudy,
|
||||
Content,
|
||||
GalleryOverlay,
|
||||
GalleryThumb,
|
||||
Grid,
|
||||
Header,
|
||||
Heading,
|
||||
Layout,
|
||||
Section,
|
||||
Text,
|
||||
} from "@components/index";
|
||||
import { getAllCaseStudyIds, getCaseStudyData } from "../../../lib/case-study";
|
||||
|
||||
export default function CaseStudyTemplate({ caseStudyData }) {
|
||||
const [openImage, setOpenImage] = useState(-1);
|
||||
const images = Array.from(new Array(caseStudyData.images)).map((_, i) => ({
|
||||
thumb: `/case-studies/${caseStudyData.id}/thumbs/${i}.jpg`,
|
||||
src: `/case-studies/${caseStudyData.id}/${i}.jpg`,
|
||||
}));
|
||||
const handleThumbClick = (i) => setOpenImage(i);
|
||||
const handlePrevClick = () =>
|
||||
setOpenImage(openImage === 0 ? images.length - 1 : openImage - 1);
|
||||
const handleNextClick = () =>
|
||||
setOpenImage(openImage === images.length - 1 ? 0 : openImage + 1);
|
||||
return (
|
||||
<Layout title={caseStudyData.title}>
|
||||
<Header
|
||||
image={`/case-studies/${caseStudyData.id}/${caseStudyData.image}.jpg`}
|
||||
>
|
||||
<Heading>{caseStudyData.title}</Heading>
|
||||
<Text>{caseStudyData.location}</Text>
|
||||
</Header>
|
||||
<CaseStudy data={caseStudyData} />
|
||||
<Section>
|
||||
<Content>
|
||||
<div dangerouslySetInnerHTML={{ __html: caseStudyData.content }} />
|
||||
</Content>
|
||||
</Section>
|
||||
<Section variant="secondary" title="Gallery">
|
||||
<Grid d={2} sm={3} md={4}>
|
||||
{images.map((img, i) => (
|
||||
<GalleryThumb
|
||||
key={img.thumb}
|
||||
image={img.thumb}
|
||||
label={`Show full picture from ${caseStudyData.title}`}
|
||||
onClick={() => handleThumbClick(i)}
|
||||
/>
|
||||
))}
|
||||
</Grid>
|
||||
{openImage > -1 && (
|
||||
<GalleryOverlay
|
||||
onClose={() => setOpenImage(-1)}
|
||||
onNext={handleNextClick}
|
||||
onPrev={handlePrevClick}
|
||||
image={images[openImage].src}
|
||||
desc={`Picture from ${caseStudyData.title}`}
|
||||
/>
|
||||
)}
|
||||
</Section>
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
|
||||
export async function getStaticPaths() {
|
||||
const paths = getAllCaseStudyIds({});
|
||||
return {
|
||||
paths,
|
||||
fallback: false,
|
||||
};
|
||||
}
|
||||
|
||||
export async function getStaticProps({ params }) {
|
||||
const caseStudyData = getCaseStudyData({ ...params });
|
||||
return {
|
||||
props: {
|
||||
caseStudyData,
|
||||
},
|
||||
};
|
||||
}
|
||||
73
pages/services/bathrooms.js
Normal file
73
pages/services/bathrooms.js
Normal file
@@ -0,0 +1,73 @@
|
||||
import React from "react";
|
||||
import {
|
||||
Card,
|
||||
Grid,
|
||||
Header,
|
||||
Heading,
|
||||
Layout,
|
||||
Section,
|
||||
Text,
|
||||
} from "@components/index";
|
||||
import { getAllCaseStudyIds } from "../../lib/case-study";
|
||||
import bannerImg from "../../images/banner_bathroom.jpg";
|
||||
|
||||
export default function Bathrooms({ caseStudies }) {
|
||||
return (
|
||||
<Layout title="Bathrooms">
|
||||
<Header title="Bathrooms" image={bannerImg} />
|
||||
<Section title="We build bespoke bathrooms">
|
||||
<Text>
|
||||
It's more than likely the most important room in your house and one of
|
||||
the biggest investments you will ever make. We offer a professional
|
||||
design service and an expert installation service. All our tradesman
|
||||
are vetted and handpicked based on their skills within their chosen
|
||||
fields.
|
||||
</Text>
|
||||
<Text>
|
||||
With over 30 years experience in bathroom installation we will help
|
||||
you choose the perfect bathroom for your home. We can complete your
|
||||
whole bathroom installation including electrics, plastering, plumbing
|
||||
and paint and decorating.
|
||||
</Text>
|
||||
<Text>
|
||||
If you want a high quality bathroom you have come to the right place.
|
||||
</Text>
|
||||
<Text>
|
||||
We provide an initial consultation followed by a competitive quote.
|
||||
</Text>
|
||||
<Text>
|
||||
To ensure complete satisfaction we insist on managing the entire
|
||||
installation process. All of our quotations are for a fully inclusive
|
||||
installation service, one price to deliver a fully functioning and
|
||||
completed bathroom.
|
||||
</Text>
|
||||
</Section>
|
||||
<Section variant="secondary" title="Case studies">
|
||||
<Grid sm={2} md={3}>
|
||||
{caseStudies.map((study) => (
|
||||
<Card
|
||||
heading={
|
||||
<Heading el="h3" size="md">
|
||||
{study.params.title}
|
||||
</Heading>
|
||||
}
|
||||
image={`/case-studies/${study.params.id}/thumbs/${study.params.image}.jpg`}
|
||||
href={`/services/bathrooms/${study.params.slug}`}
|
||||
key={study.params.id}
|
||||
>
|
||||
{study.params.location}
|
||||
</Card>
|
||||
))}
|
||||
</Grid>
|
||||
</Section>
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
|
||||
export const getStaticProps = async () => {
|
||||
const caseStudies = getAllCaseStudyIds({ service: "bathrooms" });
|
||||
|
||||
return {
|
||||
props: { caseStudies },
|
||||
};
|
||||
};
|
||||
38
pages/services/index.js
Normal file
38
pages/services/index.js
Normal file
@@ -0,0 +1,38 @@
|
||||
import React from "react";
|
||||
import {
|
||||
Card,
|
||||
Grid,
|
||||
Header,
|
||||
Heading,
|
||||
Layout,
|
||||
Section,
|
||||
} from "@components/index";
|
||||
import bannerImg from "../../images/banner_bathroom.jpg";
|
||||
import bathroomImg from "../../images/bathroom.jpg";
|
||||
import tilingImg from "../../images/tiling.jpg";
|
||||
|
||||
export default function Services() {
|
||||
return (
|
||||
<Layout title="Services">
|
||||
<Header title="Services" image={bannerImg} />
|
||||
<Section title="Our services">
|
||||
<Grid sm={2}>
|
||||
<Card
|
||||
heading={<Heading el="h3">Bathrooms</Heading>}
|
||||
image={bathroomImg}
|
||||
href="/services/bathrooms"
|
||||
>
|
||||
Fully accredited bathroom refurbishment service
|
||||
</Card>
|
||||
<Card
|
||||
heading={<Heading el="h3">Tiling</Heading>}
|
||||
image={tilingImg}
|
||||
href="/services/tiling"
|
||||
>
|
||||
We can install many different styles
|
||||
</Card>
|
||||
</Grid>
|
||||
</Section>
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
56
pages/services/tiling.js
Normal file
56
pages/services/tiling.js
Normal file
@@ -0,0 +1,56 @@
|
||||
import React from "react";
|
||||
import {
|
||||
Card,
|
||||
Grid,
|
||||
Header,
|
||||
Heading,
|
||||
Layout,
|
||||
Section,
|
||||
Text,
|
||||
} from "@components/index";
|
||||
import { getAllCaseStudyIds } from "../../lib/case-study";
|
||||
import tilingImg from "../../images/tiling.jpg";
|
||||
|
||||
export default function Tiling({ caseStudies }) {
|
||||
return (
|
||||
<Layout title="Tiling">
|
||||
<Header title="Tiling" image={tilingImg} light />
|
||||
<Section title="We specialise in floor tiling">
|
||||
<Text>
|
||||
We can install both floor and wall tiles, including ceramic, natural
|
||||
stone, marble, quartz, porcelain and mosaic tiles.
|
||||
</Text>
|
||||
<Text>
|
||||
Our elite team of 3 stonemasons and 3 tilers has a combined total of
|
||||
112 years of experience within the industry.
|
||||
</Text>
|
||||
</Section>
|
||||
<Section variant="secondary" title="Case studies">
|
||||
<Grid sm={2} md={3}>
|
||||
{caseStudies.map((study) => (
|
||||
<Card
|
||||
heading={
|
||||
<Heading el="h3" size="md">
|
||||
{study.params.title}
|
||||
</Heading>
|
||||
}
|
||||
image={`/case-studies/${study.params.id}/thumbs/${study.params.image}.jpg`}
|
||||
href={`/services/tiling/${study.params.slug}`}
|
||||
key={study.params.id}
|
||||
>
|
||||
{study.params.location}
|
||||
</Card>
|
||||
))}
|
||||
</Grid>
|
||||
</Section>
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
|
||||
export const getStaticProps = async () => {
|
||||
const caseStudies = getAllCaseStudyIds({ service: "tiling" });
|
||||
|
||||
return {
|
||||
props: { caseStudies },
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user