generated from polymech/site-template
cleanup
This commit is contained in:
parent
70e6c1d37b
commit
dbf2fb27cd
@ -23,7 +23,7 @@
|
|||||||
"format": "unix-time"
|
"format": "unix-time"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"default": "2025-12-26T17:53:03.149Z"
|
"default": "2025-12-27T07:01:36.602Z"
|
||||||
},
|
},
|
||||||
"description": {
|
"description": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@ -62,7 +62,7 @@
|
|||||||
"text": "Library"
|
"text": "Library"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"href": "/${LANG}/tutorials",
|
"href": "/${LANG}/howtos",
|
||||||
"text": "Tutorials"
|
"text": "Tutorials"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@ -6,7 +6,7 @@ interface Props {
|
|||||||
const { variant = "standard", class: extraClass = "" } = Astro.props;
|
const { variant = "standard", class: extraClass = "" } = Astro.props;
|
||||||
// Map each variant to its specific classes
|
// Map each variant to its specific classes
|
||||||
const variantClasses = {
|
const variantClasses = {
|
||||||
standard: "max-w-4xl 2xl:max-w-4xl mx-auto w-full",
|
standard: "2xl:max-w-4xl mx-auto w-full",
|
||||||
};
|
};
|
||||||
// Combine the classes for the specified variant with any extra classes
|
// Combine the classes for the specified variant with any extra classes
|
||||||
const classes = `${variantClasses[variant]} ${extraClass}`.trim();
|
const classes = `${variantClasses[variant]} ${extraClass}`.trim();
|
||||||
|
|||||||
@ -1,21 +1,22 @@
|
|||||||
---
|
---
|
||||||
import BaseHead from "../components/BaseHead.astro";
|
import BaseHead from "../components/BaseHead.astro";
|
||||||
import Navigation from "../components/global/Navigation.astro";
|
import Navigation from "@polymech/astro-base/components/global/Navigation.astro";
|
||||||
import Footer from "../components/global/Footer.astro";
|
import Footer from "@polymech/astro-base/components/global/Footer.astro";
|
||||||
import { isRTL } from "config/config.js"
|
import { isRTL } from "config/config.js";
|
||||||
|
|
||||||
const { item, additionalKeywords, ...rest } = Astro.props;
|
const { item, additionalKeywords, ...rest } = Astro.props;
|
||||||
const d = 2
|
|
||||||
|
|
||||||
---
|
---
|
||||||
<html lang={Astro.currentLocale} class="scroll-smooth" dir={isRTL(Astro.currentLocale) ? "rtl" : "ltr"}>
|
|
||||||
|
<html
|
||||||
|
lang={Astro.currentLocale}
|
||||||
|
class="scroll-smooth"
|
||||||
|
dir={isRTL(Astro.currentLocale) ? "rtl" : "ltr"}
|
||||||
|
>
|
||||||
<head>
|
<head>
|
||||||
<BaseHead
|
<BaseHead item={item} {...rest} />
|
||||||
item={item}
|
|
||||||
{...rest}
|
|
||||||
/>
|
|
||||||
</head>
|
</head>
|
||||||
<body class="bg-neutral-100 mx-auto 2xl:max-w-7xl flex flex-col min-h-svh p-4 text-neutral-500">
|
<body
|
||||||
|
class="bg-neutral-100 mx-auto 2xl:max-w-7xl flex flex-col min-h-svh p-4 text-neutral-500"
|
||||||
|
>
|
||||||
<Navigation />
|
<Navigation />
|
||||||
<main class="grow">
|
<main class="grow">
|
||||||
<slot />
|
<slot />
|
||||||
|
|||||||
@ -84,7 +84,6 @@ const Content_Debug = await createMarkdownComponent(str_debug);
|
|||||||
hideNavigation={true}
|
hideNavigation={true}
|
||||||
{...rest}
|
{...rest}
|
||||||
>
|
>
|
||||||
<Navigation />
|
|
||||||
<Wrapper>
|
<Wrapper>
|
||||||
<!-- Header with Breadcrumb on its own line -->
|
<!-- Header with Breadcrumb on its own line -->
|
||||||
<div
|
<div
|
||||||
|
|||||||
@ -9,10 +9,10 @@ import StoreEntries from "@/components/store/StoreEntries.astro";
|
|||||||
import CtaOne from "@/components/cta/CtaOne.astro";
|
import CtaOne from "@/components/cta/CtaOne.astro";
|
||||||
import { group_by_path } from "@/model/component/component.js";
|
import { group_by_path } from "@/model/component/component.js";
|
||||||
|
|
||||||
const view = "store"
|
const view = "library";
|
||||||
const items = await getCollection(view)
|
const items = await getCollection("store");
|
||||||
const locale = Astro.currentLocale;
|
const locale = Astro.currentLocale;
|
||||||
const store = `/${locale}/${view}/`
|
const store = `/${locale}/${view}/`;
|
||||||
|
|
||||||
export function getStaticPaths() {
|
export function getStaticPaths() {
|
||||||
const all: unknown[] = [];
|
const all: unknown[] = [];
|
||||||
@ -31,11 +31,11 @@ const frontmatter = {
|
|||||||
title: "Store",
|
title: "Store",
|
||||||
description: "Store",
|
description: "Store",
|
||||||
keywords: "Store",
|
keywords: "Store",
|
||||||
image:{
|
image: {
|
||||||
src: config.pages.home.hero,
|
src: config.pages.home.hero,
|
||||||
url: config.pages.home.hero,
|
url: config.pages.home.hero,
|
||||||
alt: config.metadata.keywords
|
alt: config.metadata.keywords,
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -50,10 +50,7 @@ const frontmatter = {
|
|||||||
{
|
{
|
||||||
Object.keys(groups).map((relKey) => (
|
Object.keys(groups).map((relKey) => (
|
||||||
<section>
|
<section>
|
||||||
<h3
|
<h3 aria-hidden="true" class="p-4 text-xs space-x-8 text-neutral-600">
|
||||||
aria-hidden="true"
|
|
||||||
class="p-4 text-xs space-x-8 text-neutral-600"
|
|
||||||
>
|
|
||||||
{relKey}
|
{relKey}
|
||||||
</h3>
|
</h3>
|
||||||
<div class="grid sm:grid-cols-2 lg:grid-cols-2 xl:grid-cols-2 gap-2">
|
<div class="grid sm:grid-cols-2 lg:grid-cols-2 xl:grid-cols-2 gap-2">
|
||||||
|
|||||||
301
src/pages/[locale]/library/[...path].astro
Normal file
301
src/pages/[locale]/library/[...path].astro
Normal file
@ -0,0 +1,301 @@
|
|||||||
|
---
|
||||||
|
import StoreLayout from '@/layouts/StoreLayout.astro'
|
||||||
|
import { getCollection } from 'astro:content'
|
||||||
|
import { LANGUAGES_PROD } from "config/config.js"
|
||||||
|
import StoreEntries from "@/components/store/StoreEntries.astro";
|
||||||
|
import BaseLayout from "@/layouts/BaseLayout.astro";
|
||||||
|
import Wrapper from "@polymech/astro-base/components/containers/Wrapper.astro";
|
||||||
|
import Navigation from "@polymech/astro-base/components/global/Navigation.astro";
|
||||||
|
import Translate from "@polymech/astro-base/components/i18n.astro";
|
||||||
|
import { slugify } from "@polymech/astro-base/base/strings.js"
|
||||||
|
|
||||||
|
const view = 'library'
|
||||||
|
|
||||||
|
export async function getStaticPaths()
|
||||||
|
{
|
||||||
|
const view = 'library'
|
||||||
|
const allProducts = await getCollection('store')
|
||||||
|
const all: unknown[] = []
|
||||||
|
|
||||||
|
LANGUAGES_PROD.forEach((lang) => {
|
||||||
|
// Add individual product routes
|
||||||
|
allProducts.forEach((product) => {
|
||||||
|
all.push({
|
||||||
|
params: {
|
||||||
|
locale: lang,
|
||||||
|
path: product.id,
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
page: product,
|
||||||
|
locale: lang,
|
||||||
|
path: product.id,
|
||||||
|
view,
|
||||||
|
type: 'product'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
// Add folder routes for categories
|
||||||
|
const folders = new Set<string>()
|
||||||
|
allProducts.forEach(product => {
|
||||||
|
const segments = product.id.split('/').filter(segment => segment !== '')
|
||||||
|
if (segments.length > 1) {
|
||||||
|
// Add all possible folder paths (e.g., products, products/sheetpress, etc.)
|
||||||
|
for (let i = 1; i < segments.length; i++) {
|
||||||
|
const folderPath = segments.slice(0, i).join('/')
|
||||||
|
folders.add(folderPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Add folder paths
|
||||||
|
Array.from(folders).forEach(folder => {
|
||||||
|
all.push({
|
||||||
|
params: {
|
||||||
|
locale: lang,
|
||||||
|
path: folder,
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
folderPath: folder,
|
||||||
|
products: allProducts.filter(product => {
|
||||||
|
const productFolder = product.id.split('/').slice(0, -1).join('/')
|
||||||
|
return productFolder === folder
|
||||||
|
}),
|
||||||
|
locale: lang,
|
||||||
|
view,
|
||||||
|
type: 'folder'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
// Add special case for store/ (root store) - shows all products
|
||||||
|
all.push({
|
||||||
|
params: {
|
||||||
|
locale: lang,
|
||||||
|
path: undefined,
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
folderPath: '',
|
||||||
|
products: allProducts, // All products
|
||||||
|
locale: lang,
|
||||||
|
view,
|
||||||
|
type: 'folder',
|
||||||
|
isRootStore: true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Add special case for store/products/ - shows all products
|
||||||
|
all.push({
|
||||||
|
params: {
|
||||||
|
locale: lang,
|
||||||
|
path: 'products',
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
folderPath: 'products',
|
||||||
|
products: allProducts, // All products
|
||||||
|
locale: lang,
|
||||||
|
view,
|
||||||
|
type: 'folder',
|
||||||
|
isProductsFolder: true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
return all
|
||||||
|
}
|
||||||
|
|
||||||
|
const { page, folderPath, products, locale, type, isRootStore, isProductsFolder, ...rest } = Astro.props as any
|
||||||
|
---
|
||||||
|
|
||||||
|
{type === 'folder' ? (
|
||||||
|
(() => {
|
||||||
|
// Handle folder view - show all products in category
|
||||||
|
let categoryTitle: string
|
||||||
|
const categoryDescription = 'Browse our complete collection of products'
|
||||||
|
if (isRootStore) {
|
||||||
|
// Root store - all products
|
||||||
|
categoryTitle = 'All Products'
|
||||||
|
} else if (isProductsFolder) {
|
||||||
|
// Products folder - all products
|
||||||
|
categoryTitle = 'Products'
|
||||||
|
} else {
|
||||||
|
// Regular category folder
|
||||||
|
const categoryName = folderPath.split('/').pop() || folderPath
|
||||||
|
categoryTitle = categoryName
|
||||||
|
}
|
||||||
|
categoryTitle = categoryTitle.charAt(0).toUpperCase() + categoryTitle.slice(1)
|
||||||
|
|
||||||
|
// Group products by category for all products views
|
||||||
|
let groupedProducts: any = {}
|
||||||
|
if (isRootStore || isProductsFolder) {
|
||||||
|
// Use the same grouping logic as homepage - simplified for now
|
||||||
|
groupedProducts = products.reduce((acc, item: any) => {
|
||||||
|
const id = item.id.split("/")[1]
|
||||||
|
const key = slugify(id)
|
||||||
|
.split('-')
|
||||||
|
.map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
|
||||||
|
.join(' ')
|
||||||
|
if (!acc[key]) {
|
||||||
|
acc[key] = []
|
||||||
|
}
|
||||||
|
acc[key].push(item)
|
||||||
|
return acc
|
||||||
|
}, {})
|
||||||
|
} else {
|
||||||
|
// For category views, just sort products by title
|
||||||
|
groupedProducts = {
|
||||||
|
[categoryTitle]: products.sort((a: any, b: any) =>
|
||||||
|
a.data.title.localeCompare(b.data.title)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const store = `/${locale}/${view}/`;
|
||||||
|
return (
|
||||||
|
<BaseLayout hideNavigation={true}>
|
||||||
|
<Wrapper variant="standard" class="py-4">
|
||||||
|
<!-- Header with Breadcrumb and Navigation on same line -->
|
||||||
|
<div class="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4 mb-4 py-4 border-b border-gray-200 dark:border-gray-700">
|
||||||
|
<!-- Breadcrumb on left -->
|
||||||
|
<div class="flex-1">
|
||||||
|
<nav class="breadcrumb-nav" aria-label="Breadcrumb navigation">
|
||||||
|
<ol class="breadcrumb-list flex flex-wrap items-center gap-1 m-0 p-0 list-none">
|
||||||
|
<li class="breadcrumb-item flex items-center gap-1">
|
||||||
|
<a href={`/${locale}/`} class="breadcrumb-link text-sm no-underline px-2 py-1 rounded hover:underline transition-all">
|
||||||
|
Home
|
||||||
|
</a>
|
||||||
|
<span class="breadcrumb-separator text-sm text-gray-400" aria-hidden="true">/</span>
|
||||||
|
</li>
|
||||||
|
<li class="breadcrumb-item flex items-center gap-1">
|
||||||
|
<a href={`/${locale}/library/`} class="breadcrumb-link text-sm no-underline px-2 py-1 rounded hover:underline transition-all">
|
||||||
|
Store
|
||||||
|
</a>
|
||||||
|
{folderPath && <span class="breadcrumb-separator text-sm text-gray-400" aria-hidden="true">/</span>}
|
||||||
|
</li>
|
||||||
|
{folderPath && folderPath.split('/').map((segment, index, arr) => {
|
||||||
|
const isLast = index === arr.length - 1;
|
||||||
|
const segmentPath = arr.slice(0, index + 1).join('/');
|
||||||
|
const label = segment.split('-').map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(' ');
|
||||||
|
return (
|
||||||
|
<li class="breadcrumb-item flex items-center gap-1">
|
||||||
|
{!isLast ? (
|
||||||
|
<>
|
||||||
|
<a href={`/${locale}/library/${segmentPath}/`} class="breadcrumb-link text-sm no-underline px-2 py-1 rounded hover:underline transition-all">
|
||||||
|
{label}
|
||||||
|
</a>
|
||||||
|
<span class="breadcrumb-separator text-sm text-gray-400" aria-hidden="true">/</span>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<span class="breadcrumb-current font-medium text-sm px-2 py-1" aria-current="page">
|
||||||
|
{label}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</ol>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const themeToggleBtn = document.getElementById('theme-toggle');
|
||||||
|
const themeToggleDarkIcon = document.getElementById('theme-toggle-dark-icon');
|
||||||
|
const themeToggleLightIcon = document.getElementById('theme-toggle-light-icon');
|
||||||
|
// Change the icons inside the button based on previous settings
|
||||||
|
if (localStorage.getItem('color-theme') === 'dark' || (!('color-theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
|
||||||
|
themeToggleLightIcon.classList.remove('hidden');
|
||||||
|
document.documentElement.classList.add('dark');
|
||||||
|
} else {
|
||||||
|
themeToggleDarkIcon.classList.remove('hidden');
|
||||||
|
document.documentElement.classList.remove('dark');
|
||||||
|
}
|
||||||
|
|
||||||
|
themeToggleBtn.addEventListener('click', function() {
|
||||||
|
// toggle icons inside button
|
||||||
|
themeToggleDarkIcon.classList.toggle('hidden');
|
||||||
|
themeToggleLightIcon.classList.toggle('hidden');
|
||||||
|
|
||||||
|
// if set via local storage previously
|
||||||
|
if (localStorage.getItem('color-theme')) {
|
||||||
|
if (localStorage.getItem('color-theme') === 'light') {
|
||||||
|
document.documentElement.classList.add('dark');
|
||||||
|
localStorage.setItem('color-theme', 'dark');
|
||||||
|
} else {
|
||||||
|
document.documentElement.classList.remove('dark');
|
||||||
|
localStorage.setItem('color-theme', 'light');
|
||||||
|
}
|
||||||
|
|
||||||
|
// if NOT set via local storage previously
|
||||||
|
} else {
|
||||||
|
if (document.documentElement.classList.contains('dark')) {
|
||||||
|
document.documentElement.classList.remove('dark');
|
||||||
|
localStorage.setItem('color-theme', 'light');
|
||||||
|
} else {
|
||||||
|
document.documentElement.classList.add('dark');
|
||||||
|
localStorage.setItem('color-theme', 'dark');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<section class="mb-12">
|
||||||
|
<h1 class="mb-6 text-2xl font-semibold">
|
||||||
|
<Translate>{categoryTitle}</Translate>
|
||||||
|
</h1>
|
||||||
|
<p class="text-lg text-gray-600 mb-8">
|
||||||
|
<Translate>{categoryDescription}</Translate>
|
||||||
|
</p>
|
||||||
|
{Object.keys(groupedProducts).length > 0 ? (
|
||||||
|
Object.keys(groupedProducts).map((categoryKey) => (
|
||||||
|
<section class="mb-12">
|
||||||
|
<div class="grid sm:grid-cols-2 lg:grid-cols-2 xl:grid-cols-2 gap-6">
|
||||||
|
{groupedProducts[categoryKey].map((product: any) => (
|
||||||
|
<StoreEntries
|
||||||
|
key={product.id}
|
||||||
|
url={store + product.id}
|
||||||
|
title={product.data.title}
|
||||||
|
type={product.data.type}
|
||||||
|
alt={product.data.title}
|
||||||
|
model={product.data}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
))
|
||||||
|
) : (
|
||||||
|
<div class="text-center py-12">
|
||||||
|
<div class="text-gray-400 mb-4">
|
||||||
|
<svg class="w-16 h-16 mx-auto" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<h3 class="text-lg font-medium text-gray-900 mb-2">
|
||||||
|
<Translate>No products in this category</Translate>
|
||||||
|
</h3>
|
||||||
|
<p class="text-gray-600">
|
||||||
|
<Translate>This category appears to be empty.</Translate>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<div class="mt-12 text-center">
|
||||||
|
<a
|
||||||
|
href={`/${locale}/library/`}
|
||||||
|
class="inline-flex items-center px-4 py-2 bg-gray-100 hover:bg-gray-200 text-gray-700 rounded-lg transition-colors"
|
||||||
|
>
|
||||||
|
<svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 19l-7-7m0 0l7-7m-7 7h18"/>
|
||||||
|
</svg>
|
||||||
|
<Translate>Back to Store</Translate>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</Wrapper>
|
||||||
|
</BaseLayout>
|
||||||
|
)
|
||||||
|
})()
|
||||||
|
) : (
|
||||||
|
(() => {
|
||||||
|
const { data } = page
|
||||||
|
return <StoreLayout frontmatter={data} {...rest}/>
|
||||||
|
})()
|
||||||
|
)}
|
||||||
@ -1,32 +0,0 @@
|
|||||||
---
|
|
||||||
import StoreLayout from '@/layouts/StoreLayout.astro'
|
|
||||||
import { getCollection } from 'astro:content'
|
|
||||||
import { LANGUAGES_PROD as LANGUAGES } from "config/config.js"
|
|
||||||
|
|
||||||
export async function getStaticPaths()
|
|
||||||
{
|
|
||||||
const view = 'store'
|
|
||||||
const allProducts = await getCollection(view)
|
|
||||||
const all: unknown[] = []
|
|
||||||
LANGUAGES.forEach((lang) => {
|
|
||||||
allProducts.forEach((product) => {
|
|
||||||
all.push({
|
|
||||||
params: {
|
|
||||||
locale: lang,
|
|
||||||
path: product.id,
|
|
||||||
},
|
|
||||||
props: {
|
|
||||||
page: product,
|
|
||||||
locale: lang,
|
|
||||||
path: product.id,
|
|
||||||
view
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
return all
|
|
||||||
}
|
|
||||||
const { page:page, ...rest } = Astro.props
|
|
||||||
const { data } = page
|
|
||||||
---
|
|
||||||
<StoreLayout frontmatter={data} {...rest}/>
|
|
||||||
@ -1,35 +1,29 @@
|
|||||||
---
|
---
|
||||||
import BaseLayout from "@/layouts/BaseLayout.astro"
|
import BaseLayout from "@/layouts/BaseLayout.astro";
|
||||||
import { getCollection } from "astro:content"
|
import { getCollection } from "astro:content";
|
||||||
|
|
||||||
import StoreEntries from "@/components/store/StoreEntries.astro"
|
import StoreEntries from "@/components/store/StoreEntries.astro";
|
||||||
|
|
||||||
import Howtos from "@/components/cta/CtaHowtos.astro"
|
import Howtos from "@/components/cta/CtaHowtos.astro";
|
||||||
import KB from "@/components/cta/CtaKB.astro"
|
import KB from "@/components/cta/CtaKB.astro";
|
||||||
|
import Directory from "@/components/cta/CtaDirectory.astro";
|
||||||
|
import Shop from "@/components/cta/CtaShop.astro";
|
||||||
|
|
||||||
import Directory from "@/components/cta/CtaDirectory.astro"
|
const allProducts = await getCollection("store");
|
||||||
import Shop from "@/components/cta/CtaShop.astro"
|
const locale = Astro.currentLocale || "en";
|
||||||
|
|
||||||
const allProducts = await getCollection("store")
|
|
||||||
const locale = Astro.currentLocale || "en"
|
|
||||||
---
|
---
|
||||||
<BaseLayout>
|
|
||||||
|
<BaseLayout>
|
||||||
<Howtos />
|
<Howtos />
|
||||||
<KB />
|
<KB />
|
||||||
<Directory />
|
<Directory />
|
||||||
<Shop />
|
<Shop />
|
||||||
<section>
|
<section>
|
||||||
<div class="py-2 space-y-2">
|
<div class="grid sm:grid-cols-2 lg:grid-cols-2 xl:grid-cols-2 gap-2">
|
||||||
<div class="grid md:grid-cols-2 lg:grid-cols-2 gap-2 ">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<div class="grid sm:grid-cols-2 lg:grid-cols-2 xl:grid-cols-2 gap-2">
|
|
||||||
{
|
{
|
||||||
allProducts.map((item) => (
|
allProducts.map((item) => (
|
||||||
<StoreEntries
|
<StoreEntries
|
||||||
url={ locale + "/store/" + item.id}
|
url={`${locale}/library/${item.id}`}
|
||||||
title={item.data.title}
|
title={item.data.title}
|
||||||
price={item.data.price}
|
price={item.data.price}
|
||||||
type={item.data.type}
|
type={item.data.type}
|
||||||
@ -40,5 +34,4 @@ const locale = Astro.currentLocale || "en"
|
|||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
</BaseLayout>
|
</BaseLayout>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user