Untitled

mail@pastecode.io avatar
unknown
javascript
8 days ago
7.1 kB
4
Indexable
Never
import {cn, fetchAPI, useSendGAEvent} from '~/utils';
import type {LoaderArgs} from '@shopify/remix-oxygen';
import {defer} from '@shopify/remix-oxygen';
import {useLoaderData, useParams} from '@remix-run/react';
import {
  TCollectionsList,
  TMetaobjectListing,
  TProductInfo,
  TSingleCollection,
} from '~/types';
import React, {useMemo} from 'react';
import {toHTML} from '~/ui/Utils/richtextToHTML';
import Breadcrumb from '~/ui/Breadcrumb';
import {ProductCardNew} from '~/components/product-card-new';
import ProductVideo from '~/ui/ProductVideo';
import {EventNames} from '~/utils/googleAnalytics';

export async function loader({params, context, request}: LoaderArgs) {
  const {handle} = params;
  const url = new URL(request.url);

  // We call 2 API's, one correctly fetches the video, the other
  // correctly fetches the product collection
  try {
    const reqCollection = await 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,
    );

    const reqVideo = await 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,
    );

    // eslint-disable-next-line no-var
    var category: any = [];

    if (reqVideo.status == 200) {
      const metaobject = (await reqVideo.json()) as any;
      const categoryData = metaobject.metaobjects.edges.find(
        (el: any) => el.node.handle === handle,
      );
      category = categoryData?.node;
    } else {
      throw new Response(null, {
        status: 404,
        statusText: 'Not Found',
      });
    }

    if (reqCollection.status == 200) {
      const check = (await reqCollection.json()) as any;
      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(JSON.stringify(reqCollection));
    }
  } 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 titolo_menu = category.fields.filter(
    (e: any) => e.key == 'titolo_menu',
  );
  const video = category.fields.filter((e: any) => e.key == 'video');
  const video_mobile = category.fields.filter(
    (e: any) => e.key == 'video_mobile',
  );
  const titolo_pagina = category.fields.filter((e: any) => e.key == 'titolo');
  const titolo_lista = category.fields.filter(
    (e: any) => e.key == 'titolo_lista',
  );
  const descrizione_pagina = category.fields.filter(
    (e: any) => e.key == 'descrizione',
  );
  const products = useMemo(() => {
    const collection = category.fields.filter(
      (e: any) => e.key == 'collection',
    );
    if (
      collection.length > 0 &&
      collection[0].reference &&
      collection[0].reference.products &&
      collection[0].reference.products.nodes
    ) {
      return collection[0].reference.products.nodes;
    }
    return [];
  }, []);

  const hasVideo =
    video.length > 0 &&
    video[0].reference?.sources &&
    video[0].reference.sources?.length > 0 &&
    video[0].reference.sources[0]?.url;

  useSendGAEvent(EventNames.ViewItemList, {
    item_list_id: titolo_lista?.[0]?.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">
        {titolo_pagina.length > 0 && (
          <div className="w-full pb-10">
            <Breadcrumb
              items={[
                {
                  label: titolo_pagina[0].value,
                  url: `/custom/${category.handle}`,
                },
              ]}
            />
            {/* Title, description and video (if present) */}
            <div
              className={cn(
                'max-w-[1138px] mx-auto',
                hasVideo ? 'flex flex-col gap-6 md:flex-row md:gap-4' : '',
              )}
            >
              <div
                className={cn(
                  'flex flex-col gap-2 font-light pb-6',
                  hasVideo ? 'md:max-w-[445px]' : '',
                )}
              >
                {titolo_menu && titolo_menu.length > 0 && (
                  <span className="text-[14px] leading-[18px] font-bold text-rhodamine uppercase">
                    {titolo_menu[0].value}
                  </span>
                )}
                {titolo_pagina && titolo_pagina.length > 0 && (
                  <h3 className="bold">{titolo_pagina[0].value}</h3>
                )}
                {descrizione_pagina && descrizione_pagina.length > 0 && (
                  <div
                    className="text-left"
                    dangerouslySetInnerHTML={{
                      __html: toHTML(descrizione_pagina[0].value),
                    }}
                  ></div>
                )}
              </div>
              {hasVideo && (
                <div className="flex items-center justify-center mx-auto w-[320px] xxxs:w-[359px] md:w-[670px]">
                  <ProductVideo
                    enabled={true}
                    video={video[0].reference.sources[0].url}
                  />
                </div>
              )}
            </div>
          </div>
        )}
        <div className="container-account mx-auto">
          <div className="flex flex-col md:flex-row justify-between mt-6 mb-[120px]">
            {products.length > 0 && (
              <div>
                {titolo_lista.length > 0 && (
                  <h4 className="mb-6">{titolo_lista[0].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, index: number) => {
                    return (
                      <React.Fragment key={product.id}>
                        <ProductCardNew product={product} />
                      </React.Fragment>
                    );
                  })}
                </div>
              </div>
            )}
          </div>
        </div>
      </div>
    </div>
  );
};

export default ListingPage;
Leave a Comment