Refactor and enhance components for better data handling

This commit refactors several components to improve data handling and flexibility. It primarily modifies the way data is passed as props to the components. By taking advantage of the flexibility that comes with the use of props, components such as HeroSection, FeaturesStatsAlt, and TestimonialsSectionAlt have been enhanced to adjust and render content dynamically. This creates an improvement in code reusability and maintainability across the application. Additionally, optional rendering has been added for secondary elements such as subtitles and buttons.
This commit is contained in:
Emil Gulamov 2024-02-21 22:01:09 +04:00
parent e0ec04119c
commit 2ec0e1975f
7 changed files with 138 additions and 106 deletions

View file

@ -1,19 +1,17 @@
--- ---
import { Image } from "astro:assets"; import { Image } from "astro:assets";
import product5 from "../../../images/features-image.avif"; import product5 from "../../../images/features-image.avif";
// Define the variables to be used in the component // Define props from Astro
const title: string = "Why Choose ScrewFast?"; const { title, subTitle, benefits } = Astro.props;
const subTitle: string = // Define TypeScript interface for props
"Transform your ideas into tangible results with ScrewFast tools. Whether you're starting with a sketch on a napkin or diving into a comprehensive construction project, our tools are engineered to help you build with confidence."; interface Props {
title: string;
subTitle?: string;
benefits?: Array<string>;
}
const benefits: string[] = [
"Robust and reliable tools for long-lasting performance.",
"Innovative solutions tailored to modern construction needs.",
"Customer support dedicated to your project's success.",
];
// Define SVG marker to be used in the component // Define SVG marker to be used in the component
const ListItemMarker: string = `<svg fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="mt-0.5 h-6 w-6 text-[#fa5a15] dark:text-[#fb713b]"><path stroke-linecap="round" stroke-linejoin="round" d="M9 12.75 11.25 15 15 9.75M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z"/></svg>`; const ListItemMarker: string = `<svg fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="mt-0.5 h-6 w-6 text-[#fa5a15] dark:text-[#fb713b]"><path stroke-linecap="round" stroke-linejoin="round" d="M9 12.75 11.25 15 15 9.75M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z"/></svg>`;
--- ---
@ -34,23 +32,28 @@ const ListItemMarker: string = `<svg fill="none" viewBox="0 0 24 24" stroke-widt
> >
{title} {title}
</h2> </h2>
{
subTitle && (
<p class="text-pretty text-neutral-600 dark:text-neutral-400"> <p class="text-pretty text-neutral-600 dark:text-neutral-400">
{subTitle} {subTitle}
</p> </p>
)
}
</div> </div>
<ul class="space-y-2 sm:space-y-4">
{ {
benefits.map((item) => ( benefits && (
<ul class="space-y-2 sm:space-y-4">
{benefits.map((item) => (
<li class="flex space-x-3"> <li class="flex space-x-3">
<Fragment set:html={ListItemMarker} /> <Fragment set:html={ListItemMarker} />
<span class="text-pretty text-base font-medium text-neutral-600 dark:text-neutral-400"> <span class="text-pretty text-base font-medium text-neutral-600 dark:text-neutral-400">
{item} {item}
</span> </span>
</li> </li>
)) ))}
}
</ul> </ul>
)
}
</div> </div>
</div> </div>
</div> </div>

View file

@ -5,7 +5,7 @@ const { title, subTitle } = Astro.props;
// Define TypeScript interface for props // Define TypeScript interface for props
interface Props { interface Props {
title: string; title: string;
subTitle: string; subTitle?: string;
} }
--- ---
@ -19,9 +19,13 @@ interface Props {
> >
{title} {title}
</h2> </h2>
{
subTitle && (
<p class="text-pretty leading-tight text-neutral-600 dark:text-neutral-400"> <p class="text-pretty leading-tight text-neutral-600 dark:text-neutral-400">
{subTitle} {subTitle}
</p> </p>
)
}
</div> </div>
<div <div
class="flex flex-col items-center justify-center gap-y-2 sm:flex-row sm:gap-x-12 sm:gap-y-0 lg:gap-x-24" class="flex flex-col items-center justify-center gap-y-2 sm:flex-row sm:gap-x-12 sm:gap-y-0 lg:gap-x-24"

View file

@ -17,9 +17,10 @@ const {
secondaryBtn, secondaryBtn,
secondaryBtnURL, secondaryBtnURL,
withReview, withReview,
avatars,
starCount = 0, starCount = 0,
rating, rating,
reviews, reviews
} = Astro.props; } = Astro.props;
// Define TypeScript interface for props // Define TypeScript interface for props
@ -31,6 +32,7 @@ interface Props {
secondaryBtn?: string; secondaryBtn?: string;
secondaryBtnURL?: string; secondaryBtnURL?: string;
withReview?: boolean; withReview?: boolean;
avatars?: Array<string>;
starCount?: number; starCount?: number;
rating?: string; rating?: string;
reviews?: string; reviews?: string;
@ -50,16 +52,21 @@ interface Props {
<!-- About Fragment: https://docs.astro.build/en/basics/astro-syntax/#fragments --> <!-- About Fragment: https://docs.astro.build/en/basics/astro-syntax/#fragments -->
<Fragment set:html={title} /> <Fragment set:html={title} />
</h1> </h1>
{subTitle &&
<p <p
class="mt-3 text-pretty text-lg leading-relaxed text-neutral-700 dark:text-neutral-400 lg:w-4/5" class="mt-3 text-pretty text-lg leading-relaxed text-neutral-700 dark:text-neutral-400 lg:w-4/5"
> >
{subTitle} {subTitle}
</p> </p>
}
<!-- Action Button Section: This section includes two CTAs with their own styles and URL --> <!-- Action Button Section: This section includes two CTAs with their own styles and URL -->
<div class="mt-7 grid w-full gap-3 sm:inline-flex"> <div class="mt-7 grid w-full gap-3 sm:inline-flex">
{primaryBtn &&
<PrimaryCTA title={primaryBtn} url={primaryBtnURL} /> <PrimaryCTA title={primaryBtn} url={primaryBtnURL} />
}
{secondaryBtn &&
<SecondaryCTA title={secondaryBtn} url={secondaryBtnURL} /> <SecondaryCTA title={secondaryBtn} url={secondaryBtnURL} />
}
</div> </div>
<!-- Review Section: This section presents avatars, review ratings and the number of reviews --> <!-- Review Section: This section presents avatars, review ratings and the number of reviews -->
@ -70,22 +77,7 @@ interface Props {
<div class="flex-shrink-0 pb-5 sm:flex sm:pb-0 sm:pe-5"> <div class="flex-shrink-0 pb-5 sm:flex sm:pb-0 sm:pe-5">
<!-- Avatar Group --> <!-- Avatar Group -->
<div class="flex justify-center -space-x-3"> <div class="flex justify-center -space-x-3">
<Avatar { avatars?.map(src => <Avatar src={src} alt="Avatar Description" />) }
src="https://images.unsplash.com/photo-1568602471122-7832951cc4c5?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=facearea&facepad=2&w=300&h=300&q=80"
alt="Avatar Description"
/>
<Avatar
src="https://images.unsplash.com/photo-1531927557220-a9e23c1e4794?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=facearea&facepad=2&w=300&h=300&q=80"
alt="Avatar Description"
/>
<Avatar
src="https://images.unsplash.com/photo-1541101767792-f9b2b1c4f127?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&&auto=format&fit=facearea&facepad=3&w=300&h=300&q=80"
alt="Avatar Description"
/>
<Avatar
src="https://images.unsplash.com/photo-1492562080023-ab3db95bfbce?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=facearea&facepad=2&w=300&h=300&q=80"
alt="Avatar Description"
/>
<span <span
class="inline-flex h-8 w-8 items-center justify-center rounded-full bg-zinc-800 ring-2 ring-white dark:bg-zinc-900 dark:ring-zinc-800" class="inline-flex h-8 w-8 items-center justify-center rounded-full bg-zinc-800 ring-2 ring-white dark:bg-zinc-900 dark:ring-zinc-800"
> >
@ -103,11 +95,9 @@ interface Props {
<div class="flex flex-col items-center sm:items-start"> <div class="flex flex-col items-center sm:items-start">
<div class="flex items-baseline space-x-1 pt-5 sm:ps-5 sm:pt-0"> <div class="flex items-baseline space-x-1 pt-5 sm:ps-5 sm:pt-0">
<div class="flex space-x-1"> <div class="flex space-x-1">
<!-- Replace with your star ratings --> <!-- Your star ratings -->
{ {
Array(starCount) Array(starCount).fill(0).map((_, i) => <FullStar key={i} />)
.fill(0)
.map((_, i) => <FullStar key={i} />)
} }
<!-- Adding additional half-star --> <!-- Adding additional half-star -->
<HalfStar /> <HalfStar />

View file

@ -8,12 +8,14 @@ const { title, subTitle, url } = Astro.props;
// Define TypeScript interface for props // Define TypeScript interface for props
interface Props { interface Props {
title: string; title: string;
subTitle: string; subTitle?: string;
url?: string; url?: string;
} }
--- ---
<section class="relative mx-auto max-w-[85rem] px-4 pb-24 pt-10 sm:px-6 lg:px-8"> <section
class="relative mx-auto max-w-[85rem] px-4 pb-24 pt-10 sm:px-6 lg:px-8"
>
<!-- Decorating SVG elements --> <!-- Decorating SVG elements -->
<div <div
class="absolute left-0 top-[55%] scale-90 md:top-[20%] xl:left-[10%] xl:top-[25%]" class="absolute left-0 top-[55%] scale-90 md:top-[20%] xl:left-[10%] xl:top-[25%]"
@ -122,12 +124,20 @@ interface Props {
</div> </div>
<!-- Hero Section Sub-heading --> <!-- Hero Section Sub-heading -->
<div class="mx-auto mt-5 max-w-3xl text-center"> <div class="mx-auto mt-5 max-w-3xl text-center">
{
subTitle && (
<p class="text-pretty text-lg text-neutral-600 dark:text-neutral-400"> <p class="text-pretty text-lg text-neutral-600 dark:text-neutral-400">
{subTitle} {subTitle}
</p> </p>
)
}
</div> </div>
<!-- Github Button --> <!-- Github Button -->
{
url && (
<div class="mt-8 flex justify-center gap-3"> <div class="mt-8 flex justify-center gap-3">
<GithubBtn url={url} /> <GithubBtn url={url} />
</div> </div>
)
}
</section> </section>

View file

@ -2,51 +2,23 @@
// Import AvatarTestimonialSection component for use in this module // Import AvatarTestimonialSection component for use in this module
import AvatarTestimonialSection from "../../ui/avatars/AvatarTestimonialSection.astro"; import AvatarTestimonialSection from "../../ui/avatars/AvatarTestimonialSection.astro";
// Set title for the testimonial section // Define props from Astro
const title: string = "What Our Customers Say"; const { title, testimonials } = Astro.props;
// Type definition for each testimonial // Define TypeScript interface for Testimonial
type Testimonial = { interface Testimonial {
content: string; content: string;
author: string; author: string;
role: string; role: string;
avatarSrc: string; avatarSrc: string;
avatarAlt: string; avatarAlt: string;
}; }
// Testimonial data that will be rendered in the component // Define TypeScript interface for props
const testimonials: Testimonial[] = [ interface Props {
// First testimonial data title: string;
{ testimonials: Testimonial[];
content: }
" \"Since switching to ScrewFast's hardware tools, the efficiency on our construction sites has skyrocketed. The durability of the hex bolts and precision of the machine screws are simply unmatched. It's refreshing to work with a company that truly understands the daily demands of the industry.\" ",
author: "Jason Clark",
role: "Site Foreman | TopBuild",
avatarSrc:
"https://images.unsplash.com/photo-1500648767791-00dcc994a43e?q=80&w=1374&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=facearea&facepad=2&w=320&h=320&q=80",
avatarAlt: "Image Description",
},
// Second testimonial data
{
content:
" \"As an interior designer, I'm always looking for high-quality materials and tools that help bring my visions to life. ScrewFast's mixed screws assortment has been a game-changer for my projects, providing the perfect blend of quality and variety. The outstanding customer support was just the cherry on top!\" ",
author: "Maria Gonzalez",
role: "Interior Designer | Creative Spaces",
avatarSrc:
"https://images.unsplash.com/photo-1544005313-94ddf0286df2?q=80&w=1376&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D8&auto=format&fit=facearea&facepad=2&w=320&h=320&q=80",
avatarAlt: "Image Description",
},
// Third testimonial data
{
content:
" \"Ive been a professional carpenter for over 15 years, and I can sincerely say that ScrewFasts tap bolts and nuts are some of the best I've used. They grip like no other, and I have full confidence in every joint and fixture. Plus, the service is impeccable they truly care about my project's success.\" ",
author: "Richard Kim",
role: "Master Carpenter | WoodWright",
avatarSrc:
"https://images.unsplash.com/photo-1474176857210-7287d38d27c6?q=80&w=1470&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D8&auto=format&fit=facearea&facepad=2&w=320&h=320&q=80",
avatarAlt: "Image Description",
},
];
--- ---
<!-- Main div that wraps the testimonials section --> <!-- Main div that wraps the testimonials section -->
<section <section

View file

@ -9,6 +9,13 @@ import FeaturesNavs from "../components/sections/features/FeaturesNavs.astro";
import TestimonialsSection from "../components/sections/testimonials/TestimonialsSection.astro"; import TestimonialsSection from "../components/sections/testimonials/TestimonialsSection.astro";
import PricingSection from "../components/sections/pricing/PricingSection.astro"; import PricingSection from "../components/sections/pricing/PricingSection.astro";
import FAQ from "../components/sections/FAQ.astro"; import FAQ from "../components/sections/FAQ.astro";
const avatarSrcs: Array<string> = [
"https://images.unsplash.com/photo-1568602471122-7832951cc4c5?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=facearea&facepad=2&w=300&h=300&q=80",
"https://images.unsplash.com/photo-1531927557220-a9e23c1e4794?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=facearea&facepad=2&w=300&h=300&q=80",
"https://images.unsplash.com/photo-1541101767792-f9b2b1c4f127?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&&auto=format&fit=facearea&facepad=3&w=300&h=300&q=80",
"https://images.unsplash.com/photo-1492562080023-ab3db95bfbce?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=facearea&facepad=2&w=300&h=300&q=80"
];
--- ---
<MainLayout> <MainLayout>
@ -21,6 +28,7 @@ import FAQ from "../components/sections/FAQ.astro";
secondaryBtn="Contact Sales Team" secondaryBtn="Contact Sales Team"
secondaryBtnURL="/contact" secondaryBtnURL="/contact"
withReview={true} withReview={true}
avatars={avatarSrcs}
rating=`<span class="font-bold">4.8</span> / 5` rating=`<span class="font-bold">4.8</span> / 5`
starCount={4} starCount={4}
reviews=`From Over <span class="font-bold">12.8k</span> Reviews` reviews=`From Over <span class="font-bold">12.8k</span> Reviews`

View file

@ -23,8 +23,41 @@ const product: CollectionEntry<"products">[] = (
const title: string = "Products"; const title: string = "Products";
const subTitle: string = const subTitle: string =
"Explore the durability and precision of ScrewFast tools, designed for both professionals and enthusiasts. Each of our products is crafted with precision and built to last, ensuring you have the right tool for every job."; "Explore the durability and precision of ScrewFast tools, designed for both professionals and enthusiasts. Each of our products is crafted with precision and built to last, ensuring you have the right tool for every job.";
---
// Testimonial data that will be rendered in the component
const testimonials = [
// First testimonial data
{
content:
" \"Since switching to ScrewFast's hardware tools, the efficiency on our construction sites has skyrocketed. The durability of the hex bolts and precision of the machine screws are simply unmatched. It's refreshing to work with a company that truly understands the daily demands of the industry.\" ",
author: "Jason Clark",
role: "Site Foreman | TopBuild",
avatarSrc:
"https://images.unsplash.com/photo-1500648767791-00dcc994a43e?q=80&w=1374&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=facearea&facepad=2&w=320&h=320&q=80",
avatarAlt: "Image Description",
},
// Second testimonial data
{
content:
" \"As an interior designer, I'm always looking for high-quality materials and tools that help bring my visions to life. ScrewFast's mixed screws assortment has been a game-changer for my projects, providing the perfect blend of quality and variety. The outstanding customer support was just the cherry on top!\" ",
author: "Maria Gonzalez",
role: "Interior Designer | Creative Spaces",
avatarSrc:
"https://images.unsplash.com/photo-1544005313-94ddf0286df2?q=80&w=1376&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D8&auto=format&fit=facearea&facepad=2&w=320&h=320&q=80",
avatarAlt: "Image Description",
},
// Third testimonial data
{
content:
" \"Ive been a professional carpenter for over 15 years, and I can sincerely say that ScrewFasts tap bolts and nuts are some of the best I've used. They grip like no other, and I have full confidence in every joint and fixture. Plus, the service is impeccable they truly care about my project's success.\" ",
author: "Richard Kim",
role: "Master Carpenter | WoodWright",
avatarSrc:
"https://images.unsplash.com/photo-1474176857210-7287d38d27c6?q=80&w=1470&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D8&auto=format&fit=facearea&facepad=2&w=320&h=320&q=80",
avatarAlt: "Image Description",
},
];
---
<MainLayout title="Products | ScrewFast"> <MainLayout title="Products | ScrewFast">
<div <div
@ -37,12 +70,13 @@ const subTitle: string =
> >
{title} {title}
</h1> </h1>
{
<p subTitle && (
class="hidden max-w-screen-sm text-pretty text-neutral-600 dark:text-neutral-400 md:block" <p class="hidden max-w-screen-sm text-pretty text-neutral-600 dark:text-neutral-400 md:block">
>
{subTitle} {subTitle}
</p> </p>
)
}
</div> </div>
<PrimaryCTA title="Customer Stories" url="#testimonials" noArrow={true} /> <PrimaryCTA title="Customer Stories" url="#testimonials" noArrow={true} />
</div> </div>
@ -62,7 +96,18 @@ const subTitle: string =
</section> </section>
</div> </div>
<!--Features statistics section--> <!--Features statistics section-->
<FeaturesStatsAlt /> <FeaturesStatsAlt
title="Why Choose ScrewFast?"
subTitle="Transform your ideas into tangible results with ScrewFast tools. Whether you're starting with a sketch on a napkin or diving into a comprehensive construction project, our tools are engineered to help you build with confidence."
benefits={[
"Robust and reliable tools for long-lasting performance.",
"Innovative solutions tailored to modern construction needs.",
"Customer support dedicated to your project's success.",
]}
/>
<!--Testimonials section--> <!--Testimonials section-->
<TestimonialsSectionAlt /> <TestimonialsSectionAlt
title="What Our Customers Say"
testimonials={testimonials}
/>
</MainLayout> </MainLayout>