Update product display and blog contents functionality

Replaced the image components with card components in the product section to enhance product display. Modified the grid layout for enhanced product representation. Also, implemented the complete functionality of the blog section by defining the blog collection, adding blog cards and content, and refining meta data in MainLayout for SEO optimization. Adjusted animation timeline and script paths for better load performance.
This commit is contained in:
Emil Gulamov 2024-02-17 08:15:15 +04:00
parent 10708a3d35
commit c8e5d89c04
4 changed files with 172 additions and 30 deletions

View file

@ -52,13 +52,25 @@ const productsCollection = defineCollection({
}), }),
}); });
// const blogCollection = defineCollection({ const blogCollection = defineCollection({
// type: 'content', type: "content",
// schema: z.object({}) schema: ({ image }) => z.object ({
// }); title: z.string(),
description: z.string(),
contents: z.array(z.string()),
author: z.string(),
role: z.string().optional(),
authorImage: image(),
authorImageAlt: z.string(),
pubDate: z.date(),
cardImage: image(),
cardImageAlt: z.string(),
readTime: z.number(),
tags: z.array(z.string()).optional(),
}),
});
// 3. Export a single `collections` object to register your collection(s)
export const collections = { export const collections = {
'products': productsCollection, 'products': productsCollection,
// 'blog': blogCollection, 'blog': blogCollection,
}; };

View file

@ -1,7 +1,133 @@
--- ---
// Import section components // Import section components
import MainLayout from "../../layouts/MainLayout.astro"; import MainLayout from "../../layouts/MainLayout.astro";
import CardBlog from "../../components/ui/cards/CardBlog.astro";
import CardBlogRecent from "../../components/ui/cards/CardBlogRecent.astro";
import { getCollection } from "astro:content";
import type { CollectionEntry } from "astro:content";
const blogPosts: CollectionEntry<"blog">[] = (
await getCollection("blog")
).sort((a: CollectionEntry<"blog">, b: CollectionEntry<"blog">) => b.data.pubDate.valueOf() - a.data.pubDate.valueOf());
const mostRecentPost: CollectionEntry<"blog"> = blogPosts[0];
const otherPosts: CollectionEntry<"blog">[] = blogPosts.slice(1);
const title: string = "Your Gateway to Construction Excellence";
const subTitle: string =
"Explore the latest news, tips, and insights from ScrewFast to enhance your construction projects. From product spotlights to project management strategies, our blog is your go-to resource for all things hardware and construction.";
const secondTitle: string = "Insights";
const secondSubTitle: string =
"Stay up-to-date with the latest trends and developments in the construction industry with insights from ScrewFast's team of industry experts. ";
--- ---
<MainLayout title="Blog | ScrewFast"> <MainLayout title="Blog | ScrewFast" meta="ScrewFast offers top-tier hardware tools and expert construction services to meet all your project needs. Start exploring and contact our sales team for superior quality and reliability.">
<div class="max-w-[85rem] mx-auto px-4 sm:px-6 lg:px-8 py-16 space-y-8 2xl:max-w-full">
<div class="max-w-3xl text-center mx-auto">
<h1 class="block font-bold tracking-tight text-neutral-800 dark:text-neutral-200 text-4xl md:text-5xl lg:text-6xl text-balance">
{title}
</h1>
<p class="text-lg text-pretty text-neutral-600 mt-4 dark:text-neutral-400">{subTitle}</p>
</div>
</div>
<div class="max-w-[85rem] px-4 py-10 sm:px-6 lg:px-8 lg:py-14 mx-auto 2xl:max-w-full">
<div class="grid lg:grid-cols-2 gap-6">
{otherPosts.map(blogEntry => (
<CardBlog blogEntry={blogEntry} />
))}
</div>
</div>
<!-- Card Blog -->
<div class="max-w-[85rem] px-4 py-10 sm:px-6 lg:px-8 lg:py-14 mx-auto 2xl:max-w-full">
<CardBlogRecent blogEntry={mostRecentPost} />
</div>
<!-- Card Blog -->
<div class="max-w-[85rem] px-4 py-10 sm:px-6 lg:px-8 lg:py-14 mx-auto 2xl:max-w-full">
<!-- Title -->
<div class="max-w-2xl mx-auto text-center mb-10 lg:mb-14">
<h2 class="text-2xl font-bold md:text-4xl md:leading-tight dark:text-white">{secondTitle}</h2>
<p class="mt-1 text-gray-600 dark:text-gray-400">{secondSubTitle}</p>
</div>
<!-- End Title -->
<!-- Grid -->
<div class="grid sm:grid-cols-2 lg:grid-cols-3 gap-6">
<!-- Card -->
<a class="group dark:focus:outline-none dark:focus:ring-1 dark:focus:ring-gray-600" href="#">
<div class="relative pt-[50%] sm:pt-[70%] rounded-xl overflow-hidden">
<img class="size-full absolute top-0 start-0 object-cover group-hover:scale-105 transition-transform duration-500 ease-in-out rounded-xl" src="https://images.unsplash.com/photo-1586232702178-f044c5f4d4b7?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1035&q=80" alt="Image Description">
<span class="absolute top-0 end-0 rounded-se-xl rounded-es-xl text-xs font-medium bg-gray-800 text-white py-1.5 px-3 dark:bg-gray-900">
Sponsored
</span>
</div>
<div class="mt-7">
<h3 class="text-xl font-bold text-gray-800 group-hover:text-gray-600 dark:text-gray-200">
Studio by Preline
</h3>
<p class="mt-3 text-gray-800 dark:text-gray-200">
Produce professional, reliable streams easily leveraging Preline's innovative broadcast studio
</p>
<p class="mt-5 inline-flex items-center gap-x-1 text-blue-600 decoration-2 group-hover:underline font-medium">
Read more
<svg class="flex-shrink-0 size-4" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6"/></svg>
</p>
</div>
</a>
<!-- End Card -->
<!-- Card -->
<a class="group dark:focus:outline-none dark:focus:ring-1 dark:focus:ring-gray-600" href="#">
<div class="relative pt-[50%] sm:pt-[70%] rounded-xl overflow-hidden">
<img class="size-full absolute top-0 start-0 object-cover group-hover:scale-105 transition-transform duration-500 ease-in-out rounded-xl" src="https://images.unsplash.com/photo-1542125387-c71274d94f0a?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2070&q=80" alt="Image Description">
</div>
<div class="mt-7">
<h3 class="text-xl font-bold text-gray-800 group-hover:text-gray-600 dark:text-gray-200">
Onsite
</h3>
<p class="mt-3 text-gray-800 dark:text-gray-200">
Optimize your in-person experience with best-in-class capabilities like badge printing and lead retrieval
</p>
<p class="mt-5 inline-flex items-center gap-x-1 text-blue-600 decoration-2 group-hover:underline font-medium">
Read more
<svg class="flex-shrink-0 size-4" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6"/></svg>
</p>
</div>
</a>
<!-- End Card -->
<!-- Card -->
<a class="group relative flex flex-col w-full min-h-60 bg-center bg-cover rounded-xl hover:shadow-lg transition bg-[url('https://images.unsplash.com/photo-1634017839464-5c339ebe3cb4?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=3000&q=80')] dark:focus:outline-none dark:focus:ring-1 dark:focus:ring-gray-600" href="#">
<div class="flex-auto p-4 md:p-6">
<h3 class="text-xl text-white/[.9] group-hover:text-white"><span class="font-bold">Preline</span> Press publishes books about economic and technological advancement.</h3>
</div>
<div class="pt-0 p-4 md:p-6">
<div class="inline-flex items-center gap-2 text-sm font-medium text-white group-hover:text-white/[.7]">
Visit the site
<svg class="flex-shrink-0 size-4" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6"/></svg>
</div>
</div>
</a>
<!-- End Card -->
</div>
<!-- End Grid -->
</div>
<!-- End Card Blog -->
</MainLayout> </MainLayout>

View file

@ -24,7 +24,7 @@ export async function getStaticPaths() {
const { product } = Astro.props; const { product } = Astro.props;
--- ---
<MainLayout title={product.data.main.title + " | ScrewFast"}> <MainLayout title={product.data.main.title + " | ScrewFast"} meta="ScrewFast offers top-tier hardware tools and expert construction services to meet all your project needs. Start exploring and contact our sales team for superior quality and reliability.">
<div id="overlay" class="fixed inset-0 bg-neutral-200 dark:bg-neutral-800"> <div id="overlay" class="fixed inset-0 bg-neutral-200 dark:bg-neutral-800">
</div> </div>
@ -166,32 +166,36 @@ const { product } = Astro.props;
<div id="tabs-with-card-3" class="hidden" role="tabpanel"> <div id="tabs-with-card-3" class="hidden" role="tabpanel">
<div class="mx-auto mb-20 flex w-full md:mb-28 2xl:w-4/5"> <div class="mx-auto mb-20 flex w-full md:mb-28 2xl:w-4/5">
<div <div
class="relative left-12 top-12 z-10 -ml-12 overflow-hidden rounded-xl shadow-lg md:left-12 md:top-16 lg:ml-0" class="relative left-12 top-12 z-10 overflow-hidden rounded-xl shadow-lg md:left-12 md:top-16 md:-ml-12 lg:ml-0"
> >
{product.data.blueprints.first && {
product.data.blueprints.first && (
<Image <Image
src={product.data.blueprints.first} src={product.data.blueprints.first}
class="h-full w-full object-cover object-center" class="h-full w-full object-cover object-center"
alt="Blueprint Illustration" alt="Blueprint Illustration"
format={"avif"} format={"avif"}
/> />
)
} }
</div> </div>
<div class="relative right-12 overflow-hidden rounded-xl shadow-xl"> <div class="relative right-12 overflow-hidden rounded-xl shadow-xl">
{product.data.blueprints.second && {
product.data.blueprints.second && (
<Image <Image
src={product.data.blueprints.second} src={product.data.blueprints.second}
class="h-full w-full object-cover object-center" class="h-full w-full object-cover object-center"
alt="Blueprint Illustration" alt="Blueprint Illustration"
format={"avif"} format={"avif"}
/> />
)
} }
</div> </div>
</div> </div>
</div> </div>
<script is:inline src="/assets/vendor/gsap/gsap.min.js"></script> <script is:inline src="/scripts/vendor/gsap/gsap.min.js"></script>
<script> <script>
window.addEventListener("load", (event) => { window.addEventListener("load", (event) => {
if (window.gsap) { if (window.gsap) {
@ -203,7 +207,7 @@ const { product } = Astro.props;
let timeline = gsap.timeline(); let timeline = gsap.timeline();
timeline.to("#fadeText", { timeline.to("#fadeText", {
duration: 2, duration: 1.5,
autoAlpha: 1, autoAlpha: 1,
y: 0, y: 0,
delay: 1, delay: 1,
@ -212,17 +216,17 @@ const { product } = Astro.props;
timeline.to( timeline.to(
"#fadeInUp", "#fadeInUp",
{ duration: 2, autoAlpha: 1, y: 0, ease: "power2.out" }, { duration: 1.5, autoAlpha: 1, y: 0, ease: "power2.out" },
"-=1.2", "-=1.2",
); );
timeline.to( timeline.to(
"#fadeInMoveRight", "#fadeInMoveRight",
{ duration: 2, autoAlpha: 1, x: 0, ease: "power2.out" }, { duration: 1.5, autoAlpha: 1, x: 0, ease: "power2.inOut" },
"-=1.2", "-=1.2",
); );
timeline.to("#overlay", { duration: 1, autoAlpha: 0, delay: 0.5 }); timeline.to("#overlay", { duration: 1, autoAlpha: 0, delay: 0.2 });
} }
}); });
</script> </script>

View file

@ -2,8 +2,8 @@
// Import section components // Import section components
import MainLayout from "../../layouts/MainLayout.astro"; import MainLayout from "../../layouts/MainLayout.astro";
import PrimaryCTA from "../../components/ui/buttons/PrimaryCTA.astro"; import PrimaryCTA from "../../components/ui/buttons/PrimaryCTA.astro";
import ImgSmall from "../../components/ui/images/ImgSmall.astro"; import CardSmall from "../../components/ui/cards/CardSmall.astro";
import ImgWide from "../../components/ui/images/ImgWide.astro"; import CardWide from "../../components/ui/cards/CardWide.astro";
import FeaturesStats2 from "../../components/FeaturesStats2.astro"; import FeaturesStats2 from "../../components/FeaturesStats2.astro";
import TestimonialsSection2 from "../../components/TestimonialsSection2.astro"; import TestimonialsSection2 from "../../components/TestimonialsSection2.astro";
@ -14,7 +14,7 @@ const product: CollectionEntry<"products">[] = (
await getCollection("products") await getCollection("products")
).sort( ).sort(
(a: CollectionEntry<"products">, b: CollectionEntry<"products">) => (a: CollectionEntry<"products">, b: CollectionEntry<"products">) =>
a.data.main.id - b.data.main.id, a.data.main.id - b.data.main.id
); );
const title: string = "Products"; const title: string = "Products";
@ -47,14 +47,14 @@ const subTitle: string =
<PrimaryCTA title="Customer Stories" url="#testimonials" noArrow={true} /> <PrimaryCTA title="Customer Stories" url="#testimonials" noArrow={true} />
</div> </div>
<div class="grid grid-cols-2 gap-4 sm:grid-cols-3 md:gap-6 xl:gap-8"> <div class="grid grid-cols-1 gap-4 sm:grid-cols-3 md:gap-6 xl:gap-8">
{ {
product.map((product, index) => { product.map((product, index) => {
const position = index % 4; const position = index % 4;
if (position === 0 || position === 3) { if (position === 0 || position === 3) {
return <ImgSmall product={product} />; return <CardSmall product={product} />;
} else { } else {
return <ImgWide product={product} />; return <CardWide product={product} />;
} }
}) })
} }