From 434647d05450816c0fca13f2d593e70996e3a604 Mon Sep 17 00:00:00 2001 From: Fikri Karim Date: Mon, 23 Dec 2024 20:56:28 +0700 Subject: [PATCH] feat: add Makeswift site footer --- core/components/footer/footer.tsx | 2 +- core/lib/makeswift/components.ts | 1 + .../site-footer/site-footer.client.tsx | 82 +++++++++++++++++++ .../site-footer/site-footer.makeswift.tsx | 43 ++++++++++ .../components/site-footer/site-footer.tsx | 29 +++++++ core/lib/makeswift/utils/merge-sections.ts | 21 +++++ 6 files changed, 177 insertions(+), 1 deletion(-) create mode 100644 core/lib/makeswift/components/site-footer/site-footer.client.tsx create mode 100644 core/lib/makeswift/components/site-footer/site-footer.makeswift.tsx create mode 100644 core/lib/makeswift/components/site-footer/site-footer.tsx create mode 100644 core/lib/makeswift/utils/merge-sections.ts diff --git a/core/components/footer/footer.tsx b/core/components/footer/footer.tsx index 49738df82..3c22d6ef7 100644 --- a/core/components/footer/footer.tsx +++ b/core/components/footer/footer.tsx @@ -10,13 +10,13 @@ import { import { useTranslations } from 'next-intl'; import { cache, JSX } from 'react'; -import { Footer as FooterSection } from '@/vibes/soul/sections/footer'; import { LayoutQuery } from '~/app/[locale]/(default)/query'; import { getSessionCustomerAccessToken } from '~/auth'; import { client } from '~/client'; import { readFragment } from '~/client/graphql'; import { revalidate } from '~/client/revalidate-target'; import { logoTransformer } from '~/data-transformers/logo-transformer'; +import { SiteFooter as FooterSection } from '~/lib/makeswift/components/site-footer/site-footer'; import { FooterFragment } from './fragment'; import { AmazonIcon } from './payment-icons/amazon'; diff --git a/core/lib/makeswift/components.ts b/core/lib/makeswift/components.ts index ffc607449..95001311f 100644 --- a/core/lib/makeswift/components.ts +++ b/core/lib/makeswift/components.ts @@ -4,6 +4,7 @@ import './components/card-carousel/card-carousel.makeswift'; import './components/card/card.makeswift'; import './components/carousel/carousel.makeswift'; import './components/section/section.makeswift'; +import './components/site-footer/site-footer.makeswift'; import './components/site-header/site-header.makeswift'; import './components/slideshow/slideshow.makeswift'; import './components/sticky-sidebar/sticky-sidebar.makeswift'; diff --git a/core/lib/makeswift/components/site-footer/site-footer.client.tsx b/core/lib/makeswift/components/site-footer/site-footer.client.tsx new file mode 100644 index 000000000..d9e43d973 --- /dev/null +++ b/core/lib/makeswift/components/site-footer/site-footer.client.tsx @@ -0,0 +1,82 @@ +'use client'; + +import { + type ComponentPropsWithoutRef, + createContext, + forwardRef, + type PropsWithChildren, + type Ref, + useContext, +} from 'react'; + +import { Footer } from '@/vibes/soul/sections/footer'; + +import { mergeSections } from '../../utils/merge-sections'; + +type FooterProps = ComponentPropsWithoutRef; + +// MakeswiftFooter does not support streamable sections +type ContextProps = Omit & { + sections: Awaited; +}; + +const PropsContext = createContext({ + sections: [], +}); + +export const PropsContextProvider = ({ + value, + children, +}: PropsWithChildren<{ value: ContextProps }>) => ( + {children} +); + +interface Props { + logo?: { + show: boolean; + src?: string; + width?: number; + alt: string; + }; + sections: Array<{ + title: string; + links: Array<{ + label: string; + link: { href: string }; + }>; + }>; + copyright?: string; +} + +function combineSections( + passedSections: ContextProps['sections'], + makeswiftSections: Props['sections'], +): ContextProps['sections'] { + return mergeSections( + passedSections, + makeswiftSections.map(({ title, links }) => ({ + title, + links: links.map(({ label, link }) => ({ label, href: link.href })), + })), + (left, right) => ({ ...left, links: [...left.links, ...right.links] }), + ); +} + +export const MakeswiftFooter = forwardRef( + ({ logo: _logo, sections, copyright }: Props, ref: Ref) => { + const passedProps = useContext(PropsContext); + const logoObject = _logo?.src ? { src: _logo.src, alt: _logo.alt } : passedProps.logo; + const logo = _logo?.show ? logoObject : undefined; + + return ( +