Untitled
unknown
javascript
8 months ago
7.3 kB
4
Indexable
// route.tsx export async function loader({ params, context, request }: LoaderArgs) { const { handle } = params; const url = new URL(request.url); let category: any = []; try { const [reqCollection, reqVideo] = await Promise.all([ fetchAPI('/api/shopify/custom-menu-metaobject', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ first: 26, type: 'custom_menu', handle, language: params.language ? params.language.toUpperCase() : 'IT', country: 'IT', }), }, context, request), fetchAPI('/api/shopify/metaobjects-new', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ first: 26, type: 'custom_menu', language: params.language ? params.language.toUpperCase() : 'IT', country: 'IT', }), }, context, request), ]); if (reqVideo.status == 200) { const metaobject: MetaobjectResponse = await reqVideo.json() as MetaobjectResponse; const categoryData = metaobject.metaobjects.edges.find( (el) => el.node.handle === handle, ); category = categoryData?.node || []; } else { throw new Response(null, { status: 404, statusText: 'Not Found' }); } if (reqCollection.status == 200) { const check: any = await reqCollection.json(); if (check) { const categoryWithCollections = { ...category, fields: [ ...category.fields.filter((el: any) => el.key !== 'collection'), { ...check?.fields?.find((item: any) => item.key === 'collection') }, ], }; category = categoryWithCollections; } } else { throw new Error(`Error fetching collection: ${reqCollection.statusText}`); } } catch (error) { console.error(error); throw new Error('E101: Errore nel recuperare le informazioni.'); } return defer({ category }); } const ListingPage = () => { const {category} = useLoaderData<typeof loader>(); const valuesRef = useRef<null | { memoizedFields: MemoizedFields; products: TProductInfo[]; hasVideo: boolean; }>(null); if (valuesRef.current === null) { const getField = (key: string) => category.fields.find((e: any) => e.key === key); const fields = { titolo_menu: getField('titolo_menu'), video: getField('video'), video_mobile: getField('video_mobile'), titolo_pagina: getField('titolo'), titolo_lista: getField('titolo_lista'), descrizione_pagina: getField('descrizione'), collection: getField('collection'), }; valuesRef.current = { memoizedFields: fields, products: fields.collection?.reference?.products?.nodes || [], hasVideo: Boolean(fields.video?.reference?.sources?.[0]?.url) }; } const { memoizedFields, products, hasVideo } = valuesRef.current; useSendGAEvent(EventNames.ViewItemList, { item_list_id: memoizedFields.titolo_lista?.value ?? 'custom menu products', items: products, }); return ( <div className="w-full bg-background" data-element="preferiti-di-cristina-listing-page"> <div className="container-site mx-auto relative"> {memoizedFields.titolo_pagina && <PageHeaderListingPage memoizedFields={memoizedFields} hasVideo={hasVideo} category={category} />} <ProductListListingPage products={products} titolo_lista={memoizedFields.titolo_lista} /> </div> </div> ); }; export default ListingPage; // PageHeader.tsx interface PageHeaderProps { memoizedFields: MemoizedFields; hasVideo: boolean; category: { handle: string }; } const PageHeaderListingPage: React.FC<PageHeaderProps> = React.memo(({ memoizedFields, hasVideo, category }) => ( <div className="w-full pb-10" data-element="preferiti-di-cristina-page-header"> <Breadcrumb items={[ { label: memoizedFields.titolo_menu?.value ?? '', url: `/custom/${category.handle}`, }, ]} /> <div className="flex flex-col md:container md:mx-auto"> {memoizedFields.titolo_menu && ( <span className="md:hidden text-[14px] leading-[18px] font-bold text-rhodamine uppercase"> {memoizedFields.titolo_menu.value} </span> )} <div className="flex flex-col md:flex-row items-center"> <ContentListingPage memoizedFields={memoizedFields} hasVideo={hasVideo} className="order-2 md:order-1 flex-1 mb-4 md:mb-0" /> {hasVideo && memoizedFields.video && ( <VideoSectionListingPage video={memoizedFields.video} className="order-1 md:order-2 flex-1 my-3 md:my-0" /> )} </div> </div> </div> )); export default PageHeaderListingPage; // Content.tsx interface ContentProps { memoizedFields: MemoizedFields; hasVideo: boolean; className?: string; } const ContentListingPage: React.FC<ContentProps> = React.memo(({ memoizedFields, hasVideo, className }) => ( <div className={`flex flex-col gap-2 font-light pb-6 ${hasVideo ? 'md:max-w-[445px]' : ''} ${className}`} data-element="preferiti-di-cristina-content" > {memoizedFields.titolo_menu && ( <span className="hidden md:block text-[14px] leading-[18px] font-bold text-rhodamine uppercase"> {memoizedFields.titolo_menu.value} </span> )} {memoizedFields.titolo_pagina && <h3 className="bold">{memoizedFields.titolo_pagina.value}</h3>} {memoizedFields.descrizione_pagina && ( <div className="text-left" dangerouslySetInnerHTML={{ __html: toHTML(memoizedFields.descrizione_pagina.value), }} ></div> )} </div> )); export default ContentListingPage; // VideoSection.tsx interface VideoSectionProps { video: { reference: { sources: { url: string }[] } }; className?: string; } const VideoSectionListingPage: React.FC<VideoSectionProps> = React.memo(({ video, className }) => ( <div className={`flex items-center justify-center mx-auto w-[320px] xxxs:w-[359px] md:w-[670px] ${className}`} data-element="preferiti-di-cristina-video-section" > <ProductVideo enabled={true} video={video.reference.sources[0].url} /> </div> )); export default VideoSectionListingPage; // ProductList interface ProductListProps { products: TProductInfo[]; titolo_lista?: { value: string }; } const ProductListListingPage: React.FC<ProductListProps> = React.memo(({ products, titolo_lista }) => ( <div className="container-account mx-auto" data-element="preferiti-di-cristina-product-list"> <div className="flex flex-col md:flex-row justify-between mt-6 mb-[120px]"> {products.length > 0 && ( <div> {titolo_lista && <h4 className="mb-6">{titolo_lista.value}</h4>} <div className="grid grid-cols-2 md:grid-cols-3 2xl:grid-cols-4 gap-4 justify-center items-center"> {products.map((product: TProductInfo) => ( <ProductCardNew key={product.id} product={product} /> ))} </div> </div> )} </div> </div> )); export default ProductListListingPage;
Editor is loading...
Leave a Comment