Add table display for specifications

Restructured the display of product specifications into a table format, providing users with two choices: a list of items or a table.
This commit is contained in:
Emil Gulamov 2024-04-20 14:21:18 +04:00
parent 6a6f08d83f
commit 93121c1029
3 changed files with 205 additions and 156 deletions

View file

@ -46,6 +46,12 @@ const productsCollection = defineCollection({
subTitle: z.string(), subTitle: z.string(),
}) })
).optional(), ).optional(),
tableData: z.array(
z.object({
feature: z.array(z.string()),
description: z.array(z.array(z.string())),
})
).optional(),
blueprints: z.object({ blueprints: z.object({
first: image().optional(), first: image().optional(),
second: image().optional(), second: image().optional(),

View file

@ -1,6 +1,6 @@
--- ---
title: "SF-AB A765" title: "SF-AB A765"
description: "Assorted Screw Set" description: " "
main: main:
id: 2 id: 2
content: | content: |
@ -40,15 +40,14 @@ specificationsLeft:
subTitle: "Each set includes a sufficient quantity of screws to handle a wide range of projects and tasks." subTitle: "Each set includes a sufficient quantity of screws to handle a wide range of projects and tasks."
- title: "Sizes" - title: "Sizes"
subTitle: "Available in various sizes to suit different project requirements, ensuring compatibility and versatility." subTitle: "Available in various sizes to suit different project requirements, ensuring compatibility and versatility."
specificationsRight: tableData:
- title: "Thread Design" - feature: ["Specification", "Value"]
subTitle: "Precision-engineered threads ensure a tight and secure fit, providing reliable fastening for your projects." description:
- title: "Durability" - ["Length (mm)", "Various"]
subTitle: "Designed to withstand the rigors of everyday use, delivering long-lasting performance and reliability." - ["Weight (g)", "N/A"]
- title: "Quality Assurance" - ["Material", "Stainless Steel"]
subTitle: "Manufactured to meet or exceed industry standards, guaranteeing consistent quality and performance." - ["Finish", "Assorted"]
- title: "Applications" - ["Package Contents", "Various screws in a set"]
subTitle: "Suitable for a wide range of applications, including woodworking, metalworking, construction, and more."
blueprints: blueprints:
first: "@/images/blueprint-1.avif" first: "@/images/blueprint-1.avif"
second: "@/images/blueprint-2.avif" second: "@/images/blueprint-2.avif"

View file

@ -27,9 +27,7 @@ const { product } = Astro.props;
const pageTitle: string = `${product.data.title} | ${SITE.title}`; const pageTitle: string = `${product.data.title} | ${SITE.title}`;
--- ---
<MainLayout <MainLayout title={pageTitle}>
title={pageTitle}
>
<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>
@ -148,9 +146,11 @@ const pageTitle: string = `${product.data.title} | ${SITE.title}`;
)) ))
} }
</div> </div>
<div class="mt-6 max-w-md space-y-6 md:ml-auto md:mt-0">
{ {
product.data.specificationsRight?.map((spec) => ( product.data.specificationsRight ? (
<div class="mt-6 max-w-md space-y-6 md:ml-auto md:mt-0">
{product.data.specificationsRight?.map((spec) => (
<div> <div>
<h3 class="block font-bold text-neutral-800 dark:text-neutral-200"> <h3 class="block font-bold text-neutral-800 dark:text-neutral-200">
{spec.title} {spec.title}
@ -159,14 +159,59 @@ const pageTitle: string = `${product.data.title} | ${SITE.title}`;
{spec.subTitle} {spec.subTitle}
</p> </p>
</div> </div>
))}
</div>
) : product.data.tableData ? (
<div class="mt-6 space-y-6 md:ml-auto md:mt-0">
<div class="flex flex-col">
<div class="-m-1.5 overflow-x-auto">
<div class="inline-block min-w-full p-1.5 align-middle">
<div class="overflow-hidden">
<table class="min-w-full divide-y divide-neutral-300 dark:divide-neutral-700">
<thead>
<tr>
{product.data.tableData?.[0].feature?.map(
(header) => (
<th
scope="col"
class="px-6 py-3 text-start text-xs font-medium uppercase text-neutral-500 dark:text-neutral-500"
>
{header}
</th>
)
)}
</tr>
</thead>
<tbody class="divide-y divide-neutral-300 dark:divide-neutral-700">
{product.data.tableData?.map((row) =>
// Wrap each row's content in a separate <tr> element
row.description.map((rowData) => (
<tr>
{/* Iterate through each cell value in the row's description array */}
{rowData.map((cellValue) => (
// Render each cell value in its own <td> element
<td class="whitespace-nowrap px-6 py-4 text-sm font-medium text-neutral-600 dark:text-neutral-400">
{cellValue}
</td>
))}
</tr>
)) ))
)}
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
) : null
} }
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </MainLayout>
<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">
@ -234,13 +279,13 @@ const pageTitle: string = `${product.data.title} | ${SITE.title}`;
timeline.to( timeline.to(
"#fadeInUp", "#fadeInUp",
{ duration: 1.5, 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: 1.5, autoAlpha: 1, x: 0, ease: "power2.inOut" }, { duration: 1.5, autoAlpha: 1, x: 0, ease: "power2.inOut" },
"-=1.4", "-=1.4"
); );
timeline.to("#overlay", { duration: 1, autoAlpha: 0, delay: 0.2 }); timeline.to("#overlay", { duration: 1, autoAlpha: 0, delay: 0.2 });
@ -255,7 +300,7 @@ const pageTitle: string = `${product.data.title} | ${SITE.title}`;
"active", "active",
"bg-neutral-100", "bg-neutral-100",
"hover:border-transparent", "hover:border-transparent",
"dark:bg-white/[.05]", "dark:bg-white/[.05]"
); );
const tabId = btn.getAttribute("data-target"); const tabId = btn.getAttribute("data-target");
@ -269,7 +314,7 @@ const pageTitle: string = `${product.data.title} | ${SITE.title}`;
changeHeadingStyle( changeHeadingStyle(
btn, btn,
["text-neutral-800", "dark:text-neutral-200"], ["text-neutral-800", "dark:text-neutral-200"],
["text-orange-400", "dark:text-orange-300"], ["text-orange-400", "dark:text-orange-300"]
); );
} }
} }
@ -279,7 +324,7 @@ const pageTitle: string = `${product.data.title} | ${SITE.title}`;
"active", "active",
"bg-neutral-100", "bg-neutral-100",
",hover:border-transparent", ",hover:border-transparent",
"dark:bg-white/[.05]", "dark:bg-white/[.05]"
); );
const tabId = button.getAttribute("data-target"); const tabId = button.getAttribute("data-target");
@ -293,14 +338,14 @@ const pageTitle: string = `${product.data.title} | ${SITE.title}`;
changeHeadingStyle( changeHeadingStyle(
button, button,
["text-orange-400", "dark:text-orange-300"], ["text-orange-400", "dark:text-orange-300"],
["text-neutral-800", "dark:text-neutral-200"], ["text-neutral-800", "dark:text-neutral-200"]
); );
} }
function changeHeadingStyle( function changeHeadingStyle(
button: any, button: any,
addClasses: any, addClasses: any,
removeClasses: any, removeClasses: any
) { ) {
let heading = button.querySelector("span"); let heading = button.querySelector("span");
if (heading) { if (heading) {
@ -315,7 +360,7 @@ const pageTitle: string = `${product.data.title} | ${SITE.title}`;
changeHeadingStyle( changeHeadingStyle(
tabButtons[0], tabButtons[0],
["text-orange-400", "dark:text-orange-300"], ["text-orange-400", "dark:text-orange-300"],
[], []
); );
} }
@ -327,4 +372,3 @@ const pageTitle: string = `${product.data.title} | ${SITE.title}`;
}); });
}); });
</script> </script>
</MainLayout>