namds/refactor-base-layout #8
|
|
@ -156,7 +156,7 @@
|
|||
{
|
||||
"Button": {
|
||||
"config": {
|
||||
"icon": "user",
|
||||
"icon": "User",
|
||||
"className": " flex items-center gap-1 shadow-none w-[50px]"
|
||||
}
|
||||
}
|
||||
|
|
@ -164,7 +164,7 @@
|
|||
{
|
||||
"Button": {
|
||||
"config": {
|
||||
"icon": "heart",
|
||||
"icon": "Heart",
|
||||
"className": " flex items-center gap-1 shadow-none w-[50px]"
|
||||
}
|
||||
}
|
||||
|
|
@ -204,7 +204,228 @@
|
|||
{
|
||||
"Footer": {
|
||||
"config": {
|
||||
"copyrightText": "© 2025 MyShop"
|
||||
"copyrightText": "© 2025 MyShop",
|
||||
"children": [
|
||||
{
|
||||
"Image": {
|
||||
"config": {
|
||||
"src": "/VibentecIT-logo.svg",
|
||||
"alt": "MyShop",
|
||||
"className": "h-[128px] w-[324px] ml-[3rem]",
|
||||
"objectFit": "contain"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"Section": {
|
||||
"config": {
|
||||
"className": "flex items-start px-[3rem] justify-between"
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"Section": {
|
||||
"config": {
|
||||
"className": "flex flex-col"
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"Link": {
|
||||
"config": {
|
||||
"label": "Der Wegbereiter für innovative IT-Lösungen",
|
||||
"href": "/",
|
||||
"className": "text-[24px] leading-[125%] text-[#11314E] flex mr-8 gap-1 hover:underline font-bold w-[336px] pl-[2rem] mb-[22px]"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"Link": {
|
||||
"config": {
|
||||
"label": "Tauchen Sie ein in eine Welt modernster Technologien, zuverlässiger Support und proaktiver Innovation – gemeinsam gestalten wir die digitale Zukunft Ihres Unternehmens.",
|
||||
"href": "/",
|
||||
"className": "text-[13px] leading-[160%] text-[#11314E] flex items-center mr-8 gap-1 w-[336px] pl-[2rem] hover:no-underline"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"Button": {
|
||||
"config": {
|
||||
"label": "Kontaktieren Sie Uns",
|
||||
"labelClassName": "order-[1]",
|
||||
"iconClassName": "order-[2]",
|
||||
"icon": "ChevronRight",
|
||||
"className": "mt-[24px] flex items-center w-fit hover:bg-black gap-1 shadow-none p-[1rem] bg-[#18181B] text-white ml-[2rem]"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"Section": {
|
||||
"config": {
|
||||
"className": "flex mt-[2rem]"
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"Section": {
|
||||
"config": {
|
||||
"className": "flex flex-col"
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"Link": {
|
||||
"config": {
|
||||
"label": "Unternehmen",
|
||||
"href": "/",
|
||||
"className": "text-[24px] leading-[125%] text-[#11314E] flex mr-8 gap-1 hover:underline font-bold w-[200px] pl-[2rem] mb-[16px]"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"Link": {
|
||||
"config": {
|
||||
"label": "Über Uns",
|
||||
"href": "/",
|
||||
"className": "text-[13px] leading-[160%] text-[#11314E] flex items-center mr-8 gap-1 w-[200px] pl-[2rem] hover:no-underline"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"Link": {
|
||||
"config": {
|
||||
"label": "Placeholder",
|
||||
"href": "/",
|
||||
"className": "text-[13px] leading-[160%] text-[#11314E] flex items-center mr-8 gap-1 w-[200px] pl-[2rem] hover:no-underline"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"Link": {
|
||||
"config": {
|
||||
"label": "Placeholder",
|
||||
"href": "/",
|
||||
"className": "text-[13px] leading-[160%] text-[#11314E] flex items-center mr-8 gap-1 w-[200px] pl-[2rem] hover:no-underline"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"Section": {
|
||||
"config": {
|
||||
"className": "flex flex-col gap-[16px]"
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"Link": {
|
||||
"config": {
|
||||
"label": "Social Media",
|
||||
"href": "/",
|
||||
"className": "text-[24px] leading-[125%] text-[#11314E] flex mr-8 gap-1 hover:underline font-bold w-[200px] pl-[2rem] mt-[-15px] mb-[-16px]"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"Button": {
|
||||
"config": {
|
||||
"label": "Über Uns",
|
||||
"icon": "Twitter",
|
||||
"className": "text-[13px] leading-[160%] text-[#11314E] flex justify-start font-semibold mr-8 gap-1 shadow-none w-[200px] pl-[2rem] hover:bg-transparent"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"Button": {
|
||||
"config": {
|
||||
"label": "Über Uns",
|
||||
"icon": "Twitter",
|
||||
"className": "text-[13px] leading-[160%] text-[#11314E] flex justify-start font-semibold mr-8 gap-1 shadow-none w-[200px] pl-[2rem] hover:bg-transparent"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"Button": {
|
||||
"config": {
|
||||
"label": "Über Uns",
|
||||
"icon": "Twitter",
|
||||
"className": "text-[13px] leading-[160%] text-[#11314E] flex justify-start font-semibold mr-8 gap-1 shadow-none w-[200px] pl-[2rem] hover:bg-transparent"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"Section": {
|
||||
"config": {
|
||||
"className": "flex flex-col"
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"Link": {
|
||||
"config": {
|
||||
"label": "Addresse",
|
||||
"href": "/",
|
||||
"className": "text-[24px] leading-[125%] text-[#11314E] flex mr-8 gap-1 hover:underline font-bold w-[200px] pl-[2rem] mb-[16px]"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"Link": {
|
||||
"config": {
|
||||
"label": "Über Uns",
|
||||
"href": "/",
|
||||
"className": "text-[13px] leading-[160%] text-[#11314E] flex items-center mr-8 gap-1 w-[200px] pl-[2rem] hover:no-underline"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"Link": {
|
||||
"config": {
|
||||
"label": "Social Media",
|
||||
"href": "/",
|
||||
"className": "text-[13px] leading-[160%] text-[#11314E] flex items-center mr-8 gap-1 w-[200px] pl-[2rem] hover:no-underline"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"Link": {
|
||||
"config": {
|
||||
"label": "Über Uns",
|
||||
"href": "/",
|
||||
"className": "text-[13px] leading-[160%] text-[#11314E] flex items-center mr-8 gap-1 w-[200px] pl-[2rem] hover:no-underline"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"Section": {
|
||||
"config": {
|
||||
"className": "flex flex-col mt-[5rem]"
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"Link": {
|
||||
"config": {
|
||||
"label": "Tauchen Sie ein in eine Welt modernster Technologien, zuverlässiger Support und proaktiver Innovation – gemeinsam gestalten wir die digitale Zukunft Ihres Unternehmens.",
|
||||
"href": "/",
|
||||
"className": "text-[13px] leading-[160%] text-[#11314E] flex items-center mr-8 gap-1 w-[336px] pl-[2rem] hover:no-underline"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,157 +3,28 @@ import { listCollections } from "@lib/data/collections"
|
|||
import { Text, clx } from "@medusajs/ui"
|
||||
import LocalizedClientLink from "@modules/common/components/localized-client-link"
|
||||
import MedusaCTA from "@modules/layout/components/medusa-cta"
|
||||
import { LayoutComponentDefinition, LayoutContext } from "vibentec/component-map";
|
||||
import { DynamicLayoutRenderer } from "@vibentec/renderer"
|
||||
import {
|
||||
LayoutComponentDefinition,
|
||||
LayoutContext,
|
||||
} from "vibentec/component-map"
|
||||
|
||||
export default async function VtFooter({ nodes, context }: { nodes?: LayoutComponentDefinition; context: LayoutContext }) {
|
||||
export default async function VtFooter({
|
||||
nodes,
|
||||
context,
|
||||
}: {
|
||||
nodes?: LayoutComponentDefinition
|
||||
context: LayoutContext
|
||||
}) {
|
||||
const { collections } = await listCollections({
|
||||
fields: "*products",
|
||||
})
|
||||
const productCategories = await listCategories()
|
||||
const props = nodes?.config ?? {}
|
||||
const copyrightText = props.copyrightText ?? "";
|
||||
|
||||
return (
|
||||
<footer className="border-t border-ui-border-base w-full">
|
||||
<div className="content-container flex flex-col w-full">
|
||||
<div className="flex flex-col gap-y-6 xsmall:flex-row items-start justify-between py-40">
|
||||
<div>
|
||||
<LocalizedClientLink
|
||||
href="/"
|
||||
className="txt-compact-xlarge-plus text-ui-fg-subtle hover:text-ui-fg-base uppercase"
|
||||
>
|
||||
Medusa Store
|
||||
</LocalizedClientLink>
|
||||
</div>
|
||||
<div className="text-small-regular gap-10 md:gap-x-16 grid grid-cols-2 sm:grid-cols-3">
|
||||
{productCategories && productCategories?.length > 0 && (
|
||||
<div className="flex flex-col gap-y-2">
|
||||
<span className="txt-small-plus txt-ui-fg-base">
|
||||
Categories
|
||||
</span>
|
||||
<ul
|
||||
className="grid grid-cols-1 gap-2"
|
||||
data-testid="footer-categories"
|
||||
>
|
||||
{productCategories?.slice(0, 6).map((c) => {
|
||||
if (c.parent_category) {
|
||||
return
|
||||
}
|
||||
|
||||
const children =
|
||||
c.category_children?.map((child) => ({
|
||||
name: child.name,
|
||||
handle: child.handle,
|
||||
id: child.id,
|
||||
})) || null
|
||||
|
||||
return (
|
||||
<li
|
||||
className="flex flex-col gap-2 text-ui-fg-subtle txt-small"
|
||||
key={c.id}
|
||||
>
|
||||
<LocalizedClientLink
|
||||
className={clx(
|
||||
"hover:text-ui-fg-base",
|
||||
children && "txt-small-plus"
|
||||
)}
|
||||
href={`/categories/${c.handle}`}
|
||||
data-testid="category-link"
|
||||
>
|
||||
{c.name}
|
||||
</LocalizedClientLink>
|
||||
{children && (
|
||||
<ul className="grid grid-cols-1 ml-3 gap-2">
|
||||
{children &&
|
||||
children.map((child) => (
|
||||
<li key={child.id}>
|
||||
<LocalizedClientLink
|
||||
className="hover:text-ui-fg-base"
|
||||
href={`/categories/${child.handle}`}
|
||||
data-testid="category-link"
|
||||
>
|
||||
{child.name}
|
||||
</LocalizedClientLink>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
)}
|
||||
</li>
|
||||
)
|
||||
})}
|
||||
</ul>
|
||||
</div>
|
||||
)}
|
||||
{collections && collections.length > 0 && (
|
||||
<div className="flex flex-col gap-y-2">
|
||||
<span className="txt-small-plus txt-ui-fg-base">
|
||||
Collections
|
||||
</span>
|
||||
<ul
|
||||
className={clx(
|
||||
"grid grid-cols-1 gap-2 text-ui-fg-subtle txt-small",
|
||||
{
|
||||
"grid-cols-2": (collections?.length || 0) > 3,
|
||||
}
|
||||
)}
|
||||
>
|
||||
{collections?.slice(0, 6).map((c) => (
|
||||
<li key={c.id}>
|
||||
<LocalizedClientLink
|
||||
className="hover:text-ui-fg-base"
|
||||
href={`/collections/${c.handle}`}
|
||||
>
|
||||
{c.title}
|
||||
</LocalizedClientLink>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
)}
|
||||
<div className="flex flex-col gap-y-2">
|
||||
<span className="txt-small-plus txt-ui-fg-base">Medusa</span>
|
||||
<ul className="grid grid-cols-1 gap-y-2 text-ui-fg-subtle txt-small">
|
||||
<li>
|
||||
<a
|
||||
href="https://github.com/medusajs"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className="hover:text-ui-fg-base"
|
||||
>
|
||||
GitHub
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="https://docs.medusajs.com"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className="hover:text-ui-fg-base"
|
||||
>
|
||||
Documentation
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="https://github.com/medusajs/nextjs-starter-medusa"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className="hover:text-ui-fg-base"
|
||||
>
|
||||
Source code
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex w-full mb-16 justify-between text-ui-fg-muted">
|
||||
<Text className="txt-compact-small">
|
||||
{copyrightText || `© ${new Date().getFullYear()} Medusa Store. All rights reserved.`}
|
||||
</Text>
|
||||
<MedusaCTA />
|
||||
</div>
|
||||
</div>
|
||||
<footer className="relative mx-auto border-b duration-200 bg-white border-ui-border-base border-t-2">
|
||||
{props.children && <DynamicLayoutRenderer nodes={props.children} context={context} />}
|
||||
</footer>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
import {
|
||||
LayoutComponentDefinition,
|
||||
LayoutContext,
|
||||
} from "@vibentec/component-map"
|
||||
import { DynamicLayoutRenderer } from "@vibentec/renderer"
|
||||
|
||||
export default function VtSection({
|
||||
nodes,
|
||||
context,
|
||||
}: {
|
||||
nodes: LayoutComponentDefinition
|
||||
context: LayoutContext
|
||||
}) {
|
||||
const props = nodes.config || {}
|
||||
return (
|
||||
<section className={props.className}>
|
||||
{nodes.children && (
|
||||
<DynamicLayoutRenderer nodes={nodes.children} context={context} />
|
||||
)}
|
||||
</section>
|
||||
)
|
||||
}
|
||||
|
|
@ -16,6 +16,7 @@ import VtImage from "@modules/layout/templates/vt-image"
|
|||
import VtDropdown from "@modules/layout/templates/vt-dropdown"
|
||||
import VtButton from "@modules/layout/templates/vt-button"
|
||||
import VtSearchInput from "@modules/layout/templates/vt-search-input"
|
||||
import VtSection from "@modules/layout/templates/vt-section"
|
||||
|
||||
type ComponentConfig = Record<string, any>;
|
||||
|
||||
|
|
@ -58,6 +59,7 @@ export const componentMap: Record<string, ComponentRenderer> = {
|
|||
HomeButton: nodesContextRenderer(HomeButton),
|
||||
AccountButton: nodesContextRenderer(AccountButton),
|
||||
Button: nodesContextRenderer(VtButton),
|
||||
Section: nodesContextRenderer(VtSection),
|
||||
SearchInput: nodesContextRenderer(VtSearchInput),
|
||||
VtCartButton: nodesContextRenderer(VtCartButton),
|
||||
Link: nodesContextRenderer(VtLink),
|
||||
|
|
|
|||
Loading…
Reference in New Issue