fix: homepage revamp

Signed-off-by: Chloe <pinkcloudvnn@gmail.com>
This commit is contained in:
Chloe 2024-06-04 18:39:01 +07:00
parent 4d9f4fe822
commit 578822d428
No known key found for this signature in database
GPG Key ID: CFD53CE570D42DF5
19 changed files with 188 additions and 49 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -2,7 +2,7 @@ import Banner from 'components/banner';
import Navbar from 'components/layout/navbar';
import { GeistSans } from 'geist/font/sans';
import { ensureStartsWith } from 'lib/utils';
import { League_Spartan } from 'next/font/google';
import Script from 'next/script';
import { ReactNode, Suspense } from 'react';
import './globals.css';
@ -13,12 +13,6 @@ const baseUrl = process.env.NEXT_PUBLIC_VERCEL_URL
const twitterCreator = TWITTER_CREATOR ? ensureStartsWith(TWITTER_CREATOR, '@') : undefined;
const twitterSite = TWITTER_SITE ? ensureStartsWith(TWITTER_SITE, 'https://') : undefined;
const league_spartan = League_Spartan({
subsets: ['latin'],
variable: '--font-league-spartan',
display: 'swap'
});
export const metadata = {
metadataBase: new URL(baseUrl),
title: {
@ -41,8 +35,13 @@ export const metadata = {
export default async function RootLayout({ children }: { children: ReactNode }) {
return (
<html lang="en" className={`${GeistSans.variable} ${league_spartan.variable}`}>
<html lang="en" className={GeistSans.variable}>
<body className="bg-neutral-50 text-black selection:bg-teal-300 dark:bg-neutral-900 dark:text-white dark:selection:bg-pink-500 dark:selection:text-white">
<Script
src="//widget.trustpilot.com/bootstrap/v5/tp.widget.bootstrap.min.js"
async
type="text/javascript"
/>
<header>
<Banner />
<Navbar />

View File

@ -1,5 +1,5 @@
import Hero from 'components/hero';
import HomePageContent from 'components/home-page-content';
import About from 'components/home-page/about';
import Footer from 'components/layout/footer';
import { getPage } from 'lib/shopify';
import { Metadata } from 'next';
@ -25,10 +25,8 @@ export default async function HomePage() {
<Suspense>
<Hero />
</Suspense>
<div className="my-3 min-h-96">
<Suspense>
<HomePageContent />
</Suspense>
<div className="mx-auto flex min-h-96 max-w-7xl flex-col space-y-16 px-6 py-12 lg:px-8">
<About />
</div>
<Suspense>
<Footer />

View File

@ -3,7 +3,7 @@ import Tooltip from './tooltip';
function Banner() {
return (
<div className="flex min-h-10 w-full flex-col items-center justify-center gap-x-8 bg-primary p-2 text-sm font-medium text-dark md:flex-row md:p-0">
<div className="flex min-h-10 w-full flex-col items-center justify-center gap-x-8 bg-primary p-2 text-sm font-medium text-white md:flex-row md:p-0">
<span>
Speak to a Specialist Now:{' '}
<a href={`tel:${8882422605}`} className="ml-1">

View File

@ -4,6 +4,7 @@ import { Suspense } from 'react';
import HomePageFilters, { HomePageFiltersPlaceholder } from './filters/hompage-filters';
import DynamicHeroIcon from './hero-icon';
import ImageDisplay from './page/image-display';
import TrustPilot from './trust-pilot';
const Hero = async () => {
const [offers, heroImage] = await Promise.all([
@ -63,9 +64,21 @@ const Hero = async () => {
/>
)}
</div>
<div aria-hidden="true" className="absolute inset-0 bg-gray-900 opacity-60" />
<div className="relative mx-auto flex max-w-4xl flex-col items-center px-6 py-32 text-center sm:py-64 lg:px-0">
<div aria-hidden="true" className="absolute inset-0 bg-dark opacity-80" />
<div className="flex flex-col gap-10 px-6 py-32 text-center sm:py-64 lg:px-0">
<div className="mx-auto hidden max-w-[800px] items-center justify-between gap-10 md:flex">
<div className="relative flex items-center">
<Image src="/best-price.svg" alt="Best Price" width={100} height={90} />
<div className="ml-4 text-left text-white">
<p className="tracking-wide">Best Price Guarantee</p>
<p className="max-w-[200px] text-sm tracking-wide">
We will match or beat any competitor&apos;s pricing.
</p>
</div>
</div>
<TrustPilot />
</div>
<div className="relative mx-auto flex max-w-4xl flex-col items-center ">
<Suspense fallback={<HomePageFiltersPlaceholder />}>
<HomePageFilters />
</Suspense>
@ -73,6 +86,7 @@ const Hero = async () => {
</div>
</div>
</div>
</div>
);
};

View File

@ -0,0 +1,42 @@
import Image from 'next/image';
import ButtonLink from './button-link';
import Tag from './tag';
const About = () => {
return (
<div className="grid grid-cols-1 items-start gap-x-0 gap-y-10 lg:grid-cols-2 lg:gap-x-10">
<div className="col-span-1">
<Image
src="/about.png"
alt="About Us"
sizes="(min-width: 1920px) 588px, (min-width: 770px) 50vw, 100vw"
width={588}
height={405}
className="w-full object-contain"
/>
</div>
<div className="flex h-full flex-col justify-between pb-2">
<div className="mb-3 flex flex-col gap-3">
<Tag text="About Us" />
<h3 className="text-3xl font-semibold lg:text-4xl">Engine & Transmission Experts</h3>
<p className="leading-6 text-slate-500">
{`Car Part Planet is your ultimate destination for all your drivetrain replacement needs.
Whether you're searching for a used engine, a remanufactured engine, a used
transmission, a remanufactured transmission, or seeking expert drivetrain fitment
guidance for your DIY replacement project, we've got you covered.`}
</p>
<p className="leading-6 text-slate-500">
Our dedicated team is committed to sourcing top-quality parts at affordable prices for a
wide range of gasoline and diesel vehicles, including those from American, Japanese, and
various other manufacturers. Our extensive inventory includes popular engines and
transmissions for GM, Chevrolet, Dodge, Ford, Chrysler, Jeep, Nissan, Toyota, Honda, and
many other manufacturers.
</p>
</div>
<ButtonLink link={{ text: 'Learn More', url: '/about' }} />
</div>
</div>
);
};
export default About;

View File

@ -0,0 +1,18 @@
import Image from 'next/image';
import Link from 'next/link';
const ButtonLink = ({ link }: { link: { text: string; url: string } }) => {
return (
<Link href={link.url} className="relative w-fit px-5 py-2 text-white">
<Image
src="background.svg"
alt="button background"
className="absolute inset-0 -z-10 h-full w-full rounded object-cover"
fill
/>
<div className="text-sm font-medium leading-5 tracking-wide">{link.text}</div>
</Link>
);
};
export default ButtonLink;

View File

@ -0,0 +1,7 @@
const Tag = ({ text }: { text: string }) => {
return (
<div className="w-fit border-l-4 border-l-primary bg-gray-100 px-2 py-0.5 text-sm">{text}</div>
);
};
export default Tag;

View File

@ -20,16 +20,13 @@ export default async function Footer() {
<div className="mx-auto flex w-full max-w-7xl flex-row flex-wrap items-start gap-6 px-6 py-12 text-sm md:gap-12 md:px-4 min-[1320px]:px-0">
<div className="flex flex-col gap-1">
<Link className="flex items-center text-white md:pt-1" href="/">
<LogoSquare sm />
<span className="font-league-spartan text-xl leading-tight tracking-tight">
{SITE_NAME}
</span>
<LogoSquare dark />
</Link>
<a href={`tel:${8882422605}`} className="ml-4 text-white">
<a href={`tel:${8882422605}`} className="ml-16 text-white">
(888) 242-2605
</a>
<p className="ml-4">Monday - Friday 9:00am - 8:00pm EST</p>
<p className="ml-4">Saturday 11:00am - 4:00pm EST</p>
<p className="ml-16">Monday - Friday 9:00am - 8:00pm EST</p>
<p className="ml-16">Saturday 11:00am - 4:00pm EST</p>
</div>
<Suspense
fallback={

View File

@ -9,7 +9,6 @@ import { Suspense } from 'react';
import MainMenu from './main-menu';
import MobileMenu from './mobile-menu';
import Search, { SearchSkeleton } from './search';
const { SITE_NAME } = process.env;
export default async function Navbar() {
const menu = await getMenu('main-menu');
@ -26,12 +25,9 @@ export default async function Navbar() {
<div className="flex w-full md:w-1/3">
<Link
href="/"
className="mr-2 flex w-full items-center justify-center md:w-auto lg:mr-6"
className="flex w-full items-center justify-center pl-3 sm:pl-0 md:w-auto lg:mr-6"
>
<LogoSquare />
<div className="flex-none font-league-spartan text-xl font-semibold tracking-tight text-dark dark:text-white md:hidden md:text-2xl lg:block lg:text-3xl lg:leading-tight">
{SITE_NAME}
</div>
</Link>
</div>
<div className="hidden justify-center md:flex md:w-1/3">

View File

@ -1,15 +1,13 @@
import clsx from 'clsx';
import LogoIcon from './icons/logo';
import Image from 'next/image';
export default function LogoSquare({ sm }: { sm?: boolean }) {
export default function LogoSquare({ dark = false }: { dark?: boolean }) {
return (
<div className={clsx('flex h-[40px] w-[40px] flex-none items-center justify-center')}>
<LogoIcon
className={clsx('h-[20px] w-[20px]', {
'lg:h-[26px] lg:w-[26px]': !sm,
'lg:h-[20px]lg:w-[20px]': sm
})}
/>
<div className="h-12 md:h-[55px]">
{dark ? (
<Image src="/dark-logo.svg" alt="Logo" width={327} height={61} className="h-full w-full" />
) : (
<Image src="/logo.svg" alt="Logo" width={327} height={61} className="h-full w-full" />
)}
</div>
);
}

View File

@ -0,0 +1,34 @@
'use client';
import { useEffect, useRef } from 'react';
const TrustPilot = () => {
const ref = useRef(null);
useEffect(() => {
// @ts-ignore
if (window.Trustpilot) {
// @ts-ignore
window.Trustpilot.loadFromElement(ref.current);
}
}, []);
return (
<div
ref={ref}
data-locale="en-US"
data-template-id="53aa8807dec7e10d38f59f32"
data-businessunit-id="58af38df0000ff00059d3de2"
data-style-height="120px"
data-style-width="100%"
data-style-font-size="10px"
data-theme="dark"
>
<a href="https://www.trustpilot.com/review/carpartplanet.com" target="_blank" rel="noopener">
Trustpilot
</a>
</div>
);
};
export default TrustPilot;

5
lib/styles.ts Normal file
View File

@ -0,0 +1,5 @@
export const colors = {
primary: '#EF6C02',
dark: '#091242',
secondary: '#EF6C02'
};

BIN
public/about.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 457 KiB

11
public/background.svg Normal file
View File

@ -0,0 +1,11 @@
<svg width="194" height="61" viewBox="0 0 194 61" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="Background">
<path id="Background_2" d="M0 4.83398C0 2.3487 2.01472 0.333984 4.5 0.333984H189.5C191.985 0.333984 194 2.3487 194 4.83398V55.834C194 58.3193 191.985 60.334 189.5 60.334H4.5C2.01472 60.334 0 58.3193 0 55.834V4.83398Z" fill="#091242"/>
<mask id="mask0_13_1494" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="194" height="61">
<path id="Background_3" d="M0 4.83398C0 2.3487 2.01472 0.333984 4.5 0.333984H189.5C191.985 0.333984 194 2.3487 194 4.83398V55.834C194 58.3193 191.985 60.334 189.5 60.334H4.5C2.01472 60.334 0 58.3193 0 55.834V4.83398Z" fill="#FFB629"/>
</mask>
<g mask="url(#mask0_13_1494)">
<circle id="Pattern" cx="185" cy="62.334" r="26" fill="#1F2A69"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 823 B

9
public/best-price.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 55 KiB

7
public/dark-logo.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 19 KiB

8
public/logo.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 32 KiB

View File

@ -1,4 +1,5 @@
const plugin = require('tailwindcss/plugin');
import { colors } from './lib/styles.ts';
/** @type {import('tailwindcss').Config} */
module.exports = {
@ -6,14 +7,9 @@ module.exports = {
content: ['./app/**/*.{js,ts,jsx,tsx}', './components/**/*.{js,ts,jsx,tsx}'],
theme: {
extend: {
colors: {
primary: '#17E4BB',
dark: '#08312B',
secondary: '#12baa9'
},
colors,
fontFamily: {
sans: ['var(--font-geist-sans)'],
'league-spartan': ['var(--font-league-spartan)']
sans: ['var(--font-geist-sans)']
},
keyframes: {
fadeIn: {