Skip to content

Commit 1df855d

Browse files
committed
Copy in pet landing page stuff
1 parent 64b78db commit 1df855d

17 files changed

+355
-5
lines changed

package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/components/Footer.tsx

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import { Logo } from '@/components/Logo';
2+
import clsx from 'clsx';
3+
import { text } from '../fonts';
4+
import {
5+
FaFacebook,
6+
FaInstagram,
7+
FaLeaf,
8+
FaTwitter,
9+
FaYoutube,
10+
} from 'react-icons/fa';
11+
12+
export function Footer() {
13+
return (
14+
<section
15+
className={clsx(
16+
'section flex w-full flex-col items-start justify-center gap-10 p-10 py-12 text-secondary md:flex-row md:justify-between',
17+
text.className
18+
)}>
19+
<Logo />
20+
<div>
21+
<div className="text-xl font-bold">Contact Us</div>
22+
<div>
23+
<div>07542 819624</div>
24+
<div>[email protected]</div>
25+
</div>
26+
</div>
27+
<div>
28+
<div className="text-xl font-bold">Address</div>
29+
<div>
30+
<div>64 Zoo Lane</div>
31+
<div>Nottingham</div>
32+
</div>
33+
</div>
34+
<div>
35+
<div className="text-xl font-bold">Opening Hours</div>
36+
<div>
37+
<div>Mon - Fri: 8am - 8pm</div>
38+
<div>Sat - Sun: 9am - 5pm</div>
39+
</div>
40+
</div>
41+
</section>
42+
);
43+
}
44+
export function FooterOld() {
45+
return (
46+
<footer
47+
className={clsx(
48+
'flex h-96 w-full flex-col items-start gap-5 p-5 py-10',
49+
text.className
50+
)}>
51+
<Logo />
52+
53+
<FooterItem
54+
title="Address"
55+
content="1 Forest View, Blidworth, NG21 0QT"
56+
/>
57+
<FooterItem title="Contact" content="[email protected]" />
58+
</footer>
59+
);
60+
}
61+
62+
function FooterItem({ title, content }: { title: string; content: string }) {
63+
return (
64+
<div className="text-primary">
65+
<div className="text-xl font-bold">{title}</div>
66+
<div className="text-xl">{content}</div>
67+
</div>
68+
);
69+
}

src/components/ImageGallery.tsx

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { motion, useAnimationControls, Variants } from 'framer-motion';
2+
import grooming1 from 'images/grooming-1.webp';
3+
import grooming2 from 'images/grooming-2.webp';
4+
import grooming3 from 'images/grooming-3.webp';
5+
import grooming4 from 'images/grooming-4.webp';
6+
import Image, { ImageProps } from 'next/image';
7+
import { useEffect, useState } from 'react';
8+
9+
export function ImageGallery() {
10+
return (
11+
<div className="grid w-full max-w-screen-xl grid-cols-2 grid-rows-2 gap-2 p-4 lg:grid-cols-4 lg:grid-rows-1">
12+
<GalleryImage src={grooming1} alt="dog1" />
13+
<GalleryImage src={grooming2} alt="dog2" />
14+
<GalleryImage src={grooming3} alt="dog3" />
15+
<GalleryImage src={grooming4} alt="dog4" />
16+
</div>
17+
);
18+
}
19+
20+
const imageVariants: Variants = {
21+
noHover: { scale: 1, transition: { duration: 1, ease: 'easeInOut' } },
22+
hover: { scale: 1.1, transition: { duration: 1, ease: 'easeInOut' } },
23+
};
24+
25+
function GalleryImage({ src, alt }: ImageProps) {
26+
return (
27+
<div className="aspect-[4/3] h-full overflow-clip rounded">
28+
<motion.div
29+
variants={imageVariants}
30+
initial="nohover"
31+
whileHover="hover"
32+
className="h-full w-full object-cover">
33+
<Image src={src} alt={alt} className="h-full object-cover" />
34+
</motion.div>
35+
</div>
36+
);
37+
}

src/components/Logo.tsx

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import clsx from 'clsx';
2+
import { title } from '../fonts';
3+
import { FaDog } from 'react-icons/fa';
4+
5+
export function Logo({ className }: { className?: string }) {
6+
return (
7+
<div
8+
className={clsx(
9+
'flex items-center justify-center gap-2 text-2xl font-semibold text-primary',
10+
title.className,
11+
className
12+
)}>
13+
<div className="text-4xl">
14+
<FaDog />
15+
</div>
16+
Princess Paws
17+
</div>
18+
);
19+
}

src/components/NavBar.tsx

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { FaDog } from 'react-icons/fa';
2+
import { WithChildrenProps } from '../types';
3+
import clsx from 'clsx';
4+
import { title } from '../fonts';
5+
import { Logo } from '@/components/Logo';
6+
7+
function NavItem({ children }: WithChildrenProps) {
8+
return (
9+
<button className="rounded-full px-8 py-1 transition-all hover:bg-primary">
10+
{children}
11+
</button>
12+
);
13+
}
14+
15+
export function NavBar() {
16+
return (
17+
<div className="text-md flex h-24 w-full items-center justify-between px-12">
18+
<Logo />
19+
<nav className="hidden gap-8 md:flex">
20+
<NavItem>Home</NavItem>
21+
<NavItem>Services</NavItem>
22+
<NavItem>About</NavItem>
23+
<NavItem>Contact</NavItem>
24+
</nav>
25+
</div>
26+
);
27+
}

src/components/SocialsFooter.tsx

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { FaFacebook, FaInstagram, FaTwitter, FaYoutube } from 'react-icons/fa';
2+
3+
export function SocialsFooter() {
4+
return (
5+
<section className="section flex w-full flex-row items-center justify-between bg-primary py-6 px-6 text-xl text-white md:px-10">
6+
<div className="text-base">© 2023 Princess Paws</div>
7+
<div className="flex flex-row gap-4">
8+
<FaFacebook />
9+
<FaTwitter />
10+
<FaYoutube />
11+
<FaInstagram />
12+
</div>
13+
</section>
14+
);
15+
}

src/dogandcat.png

1.41 MB
Loading

src/fonts.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import {
2+
Fredoka_One,
3+
Inter,
4+
Poppins,
5+
Rubik,
6+
Source_Sans_Pro,
7+
} from 'next/font/google';
8+
export const logo = Rubik({ subsets: ['latin'] });
9+
export const text = Source_Sans_Pro({
10+
subsets: ['latin'],
11+
weight: ['300', '400', '600', '700'],
12+
});
13+
export const title = Fredoka_One({ subsets: ['latin'], weight: '400' });

src/images/grooming-1.webp

16.3 KB
Binary file not shown.

src/images/grooming-2.webp

16.5 KB
Binary file not shown.

src/images/grooming-3.webp

15.6 KB
Binary file not shown.

src/images/grooming-4.webp

16.3 KB
Binary file not shown.

src/images/pet1.webp

26.3 KB
Binary file not shown.

src/images/pet2.webp

28.2 KB
Binary file not shown.

src/images/pet3.webp

41.1 KB
Binary file not shown.

src/pages/index.tsx

Lines changed: 169 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,180 @@
1+
import { NavBar } from '@/components/NavBar';
12
import Head from 'next/head';
3+
import clsx from 'clsx';
4+
import { text, title } from '../fonts';
5+
import pets from '../dogandcat.png';
6+
import Image, { ImageProps } from 'next/image';
7+
import { FaGlasses, FaHeart, FaShower } from 'react-icons/fa';
8+
import { ImageGallery } from '@/components/ImageGallery';
9+
import { WithChildrenProps } from '../types';
10+
11+
import pet1 from 'images/pet1.webp';
12+
import pet2 from 'images/pet2.webp';
13+
import pet3 from 'images/pet3.webp';
14+
import { useEffect, useState } from 'react';
15+
import { Footer } from '@/components/Footer';
16+
import { SocialsFooter } from '@/components/SocialsFooter';
217

318
export default function Home() {
419
return (
5-
<div className="dark flex min-h-screen w-full items-center justify-center">
20+
<div
21+
className={clsx(
22+
'flex min-h-screen w-full flex-col items-center justify-center',
23+
text.className
24+
)}>
625
<Head>
726
<title>Hello World!</title>
827
<link rel="icon" href="/favicon.ico" />
928
</Head>
10-
<main>hi!</main>
29+
<Intro />
30+
<Gallery />
31+
<Testimonials />
32+
<Footer />
33+
<SocialsFooter />
34+
</div>
35+
);
36+
}
37+
38+
function Intro() {
39+
return (
40+
<div className="text-light flex h-[36rem] w-full flex-col items-center justify-center bg-secondary md:h-[90vh]">
41+
<NavBar />
42+
<main className="relative flex w-full grow items-start justify-center py-12 px-4 md:items-center md:justify-start md:px-12">
43+
<header
44+
className={clsx(
45+
'z-10 flex flex-col gap-4 md:-mt-36',
46+
title.className
47+
)}>
48+
<h1 className="text-center text-5xl md:text-start md:text-8xl">
49+
The Best Pet <br /> Groomers <br /> in Town
50+
</h1>
51+
<p className={clsx('text-3xl font-light', text.className)}>
52+
For a pawfect look and feel!
53+
</p>
54+
</header>
55+
<div className="absolute right-0 -bottom-12 w-full sm:w-4/5 md:-bottom-36 md:w-[950px]">
56+
<Image src={pets} alt="Cat and dog" />
57+
</div>
58+
</main>
59+
</div>
60+
);
61+
}
62+
63+
function Gallery() {
64+
return (
65+
<div
66+
className={clsx(
67+
'mt-48 flex min-h-screen w-full flex-col items-center justify-center gap-14 px-4 text-primary md:px-12',
68+
text.className
69+
)}>
70+
<h1
71+
className={clsx(
72+
'text-center text-4xl md:text-8xl',
73+
title.className
74+
)}>
75+
Your pet deserves <br /> to be pampered!
76+
</h1>
77+
<div className="flex flex-col gap-12 text-3xl md:flex-row">
78+
<div className="flex flex-row items-center justify-center gap-5">
79+
<FaShower className="text-4xl" />
80+
Bath or Shower
81+
</div>
82+
<div className="flex flex-row items-center justify-center gap-5">
83+
<FaGlasses className="text-4xl" />
84+
Hands-On Assessment
85+
</div>
86+
<div className="flex flex-row items-center justify-center gap-5">
87+
<FaHeart className="text-4xl" />
88+
Safe Drying
89+
</div>
90+
</div>
91+
<button className="flex flex-row gap-12 rounded-full bg-primary px-8 py-4 text-2xl text-white">
92+
Book an Appointment
93+
</button>
94+
<ImageGallery />
95+
</div>
96+
);
97+
}
98+
const names = [
99+
'Abi',
100+
'Brian',
101+
'Carl',
102+
'Daniella',
103+
'Edward',
104+
'Ruby',
105+
'John',
106+
'Alan',
107+
];
108+
const locations = ['Nottingham', 'Manchester', 'London', 'York', 'Brighton'];
109+
110+
function Testimonial({
111+
className,
112+
children,
113+
}: WithChildrenProps & { className?: string }) {
114+
const [randomName, setRandomName] = useState('');
115+
const [randomLocation, setRandomLocation] = useState('');
116+
117+
useEffect(() => {
118+
setRandomName(names[Math.floor(Math.random() * names.length)]);
119+
setRandomLocation(
120+
locations[Math.floor(Math.random() * locations.length)]
121+
);
122+
}, []); //To make sure the random generation only runs on the client
123+
124+
return (
125+
<div
126+
className={clsx(
127+
'text-md flex aspect-[3/4] h-96 flex-col items-center justify-between gap-8 rounded-md bg-white p-6 font-light text-secondary shadow',
128+
className
129+
)}>
130+
{children}
131+
<div className="w-full text-start font-bold">
132+
{randomName}, {randomLocation}
133+
</div>
134+
</div>
135+
);
136+
}
137+
138+
function Testimonials() {
139+
return (
140+
<div className="flex min-h-[120vh] w-full flex-col items-center justify-center gap-12 bg-secondary px-4 py-24 md:p-24">
141+
<h2
142+
className={clsx(
143+
'text-center text-4xl text-primary md:w-1/2 md:text-7xl',
144+
title.className
145+
)}>
146+
What Our Happy Clients Say
147+
</h2>
148+
<div className="flex grow flex-wrap items-center items-center justify-center justify-center gap-24">
149+
<Testimonial className="md:mb-24">
150+
<TestimonialImage src={pet1} alt="" />
151+
&quot;They do a great job making Milo look so lovely. The
152+
staff are knowledgeable and friendly, always willing to give
153+
help and advice. Would definitely recommend!&quot;
154+
</Testimonial>
155+
<Testimonial className="md:mt-12">
156+
<TestimonialImage src={pet2} alt="" />
157+
&quot;They do a great job making Milo look so lovely. The
158+
staff are knowledgeable and friendly, always willing to give
159+
help and advice. Would definitely recommend!&quot;
160+
</Testimonial>
161+
<Testimonial className="md:mb-12">
162+
<TestimonialImage src={pet3} alt="" />
163+
&quot;They do a great job making Milo look so lovely. The
164+
staff are knowledgeable and friendly, always willing to give
165+
help and advice. Would definitely recommend!&quot;
166+
</Testimonial>
167+
</div>
168+
</div>
169+
);
170+
}
171+
172+
function TestimonialImage({ src, alt }: ImageProps) {
173+
return (
174+
<div className="flex h-full w-full items-center justify-center">
175+
<div className="aspect-square h-28 overflow-clip rounded-full">
176+
<Image src={src} alt={alt} className="object-cover" />
177+
</div>
11178
</div>
12179
);
13180
}

tailwind.config.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,11 @@ module.exports = {
1616
text: ['Inter', ...defaultTheme.fontFamily.sans],
1717
},
1818
colors: {
19-
primary: colors.red[500],
20-
secondary: colors.orange[500],
19+
primary: '#936A76',
20+
secondary: '#6F273D',
21+
three: '#B69196',
22+
four: '#D48960',
23+
light: '#E6E9E5',
2124
},
2225
},
2326
},

0 commit comments

Comments
 (0)