fix(refactor): refactor code for isolation

This commit is contained in:
Thomas Frost 2024-07-20 20:54:32 -07:00
parent dfa42c2552
commit 4ffb965688
15 changed files with 117 additions and 102 deletions

View File

@ -3,78 +3,34 @@ import OpenCart from 'components/cart/open-cart';
import { GridTileImage } from 'components/grid/tile'; import { GridTileImage } from 'components/grid/tile';
import { Gallery } from 'components/product/gallery'; import { Gallery } from 'components/product/gallery';
import { ProductDescription } from 'components/product/product-description'; import { ProductDescription } from 'components/product/product-description';
import { getProductById, getProductRecommendations } from 'lib/shopify'; import { getContentLandingPageConfig } from 'lib/aspire';
import { ContentLandingPages, Image, Store } from 'lib/shopify/types'; import { Store } from 'lib/aspire/types';
import { getProductRecommendations } from 'lib/shopify';
import { Image } from 'lib/shopify/types';
import Link from 'next/link'; import Link from 'next/link';
import { Suspense } from 'react'; import { Suspense } from 'react';
const lookupContentLandingPage = async (contentLandingPageId: string) => {
const contentLandingPages: ContentLandingPages = {
ABC: {
contentLandingPageId: 'ABC',
content: {
contentId: 'ABC-123',
contentUrl: 'https://vercel.com'
},
brand: {
brandId: '123456789',
companyName: 'Vercel'
},
store: {
domain: 'https://test-app-furie.myshopify.com',
key: '30f0c9b2ee5c69d6c0de2e7a048eb6b4'
},
productId: 'gid://shopify/Product/8587441176812'
},
'123': {
contentLandingPageId: '123',
content: {
contentId: '123-ABC',
contentUrl: 'https://vercel.com'
},
brand: {
brandId: '123456789',
companyName: 'Vercel'
},
store: {
domain: 'https://quickstart-ba952e54.myshopify.com',
key: '8efbd119747c632000b04ed68313abf1'
},
productId: 'gid://shopify/Product/7913032548543'
}
};
const contentLandingPage = contentLandingPages[contentLandingPageId];
if (!contentLandingPage) {
throw new Error('Content Landing Page not found');
}
const product = await getProductById(contentLandingPage.store, contentLandingPage?.productId);
return { ...contentLandingPage, product };
};
export default async function Page({ params }: { params: { ContentLandingPage: string } }) { export default async function Page({ params }: { params: { ContentLandingPage: string } }) {
const instance = await lookupContentLandingPage(params.ContentLandingPage); const config = await getContentLandingPageConfig(params.ContentLandingPage);
if (!instance.product) { if (!config.product) {
return <div>Product not found</div>; return <div>Product not found</div>;
} }
const productJsonLd = { const productJsonLd = {
'@context': 'https://schema.org', '@context': 'https://schema.org',
'@type': 'Product', '@type': 'Product',
name: instance.product.title, name: config.product.title,
description: instance.product.description, description: config.product.description,
image: instance.product.featuredImage.url, image: config.product.featuredImage.url,
offers: { offers: {
'@type': 'AggregateOffer', '@type': 'AggregateOffer',
availability: instance.product.availableForSale availability: config.product.availableForSale
? 'https://schema.org/InStock' ? 'https://schema.org/InStock'
: 'https://schema.org/OutOfStock', : 'https://schema.org/OutOfStock',
priceCurrency: instance.product.priceRange.minVariantPrice.currencyCode, priceCurrency: config.product.priceRange.minVariantPrice.currencyCode,
highPrice: instance.product.priceRange.maxVariantPrice.amount, highPrice: config.product.priceRange.maxVariantPrice.amount,
lowPrice: instance.product.priceRange.minVariantPrice.amount lowPrice: config.product.priceRange.minVariantPrice.amount
} }
}; };
@ -93,7 +49,7 @@ export default async function Page({ params }: { params: { ContentLandingPage: s
<div className="flex w-full items-center"> <div className="flex w-full items-center">
<div className="flex justify-end md:w-1/3"> <div className="flex justify-end md:w-1/3">
<Suspense fallback={<OpenCart />}> <Suspense fallback={<OpenCart />}>
<Cart store={instance.store} /> <Cart store={config.store} />
</Suspense> </Suspense>
</div> </div>
</div> </div>
@ -107,7 +63,7 @@ export default async function Page({ params }: { params: { ContentLandingPage: s
} }
> >
<Gallery <Gallery
images={instance.product.images.map((image: Image) => ({ images={config.product.images.map((image: Image) => ({
src: image.url, src: image.url,
altText: image.altText altText: image.altText
}))} }))}
@ -116,10 +72,10 @@ export default async function Page({ params }: { params: { ContentLandingPage: s
</div> </div>
<div className="basis-full lg:basis-2/6"> <div className="basis-full lg:basis-2/6">
<ProductDescription product={instance.product} store={instance.store} /> <ProductDescription product={config.product} store={config.store} />
</div> </div>
</div> </div>
<RelatedProducts id={instance.product.id} store={instance.store} /> <RelatedProducts id={config.product.id} store={config.store} />
</div> </div>
</> </>
); );

View File

@ -1,5 +1,5 @@
import { Store } from 'lib/aspire/types';
import { getCollectionProducts } from 'lib/shopify'; import { getCollectionProducts } from 'lib/shopify';
import { Store } from 'lib/shopify/types';
import Link from 'next/link'; import Link from 'next/link';
import { GridTileImage } from './grid/tile'; import { GridTileImage } from './grid/tile';

View File

@ -1,8 +1,8 @@
'use server'; 'use server';
import { Store } from 'lib/aspire/types';
import { TAGS } from 'lib/constants'; import { TAGS } from 'lib/constants';
import { addToCart, createCart, getCart, removeFromCart, updateCart } from 'lib/shopify'; import { addToCart, createCart, getCart, removeFromCart, updateCart } from 'lib/shopify';
import { Store } from 'lib/shopify/types';
import { revalidateTag } from 'next/cache'; import { revalidateTag } from 'next/cache';
import { cookies } from 'next/headers'; import { cookies } from 'next/headers';

View File

@ -4,7 +4,8 @@ import { PlusIcon } from '@heroicons/react/24/outline';
import clsx from 'clsx'; import clsx from 'clsx';
import { addItem } from 'components/cart/actions'; import { addItem } from 'components/cart/actions';
import LoadingDots from 'components/loading-dots'; import LoadingDots from 'components/loading-dots';
import { ProductVariant, Store } from 'lib/shopify/types'; import { Store } from 'lib/aspire/types';
import { ProductVariant } from 'lib/shopify/types';
import { useSearchParams } from 'next/navigation'; import { useSearchParams } from 'next/navigation';
import { useFormState, useFormStatus } from 'react-dom'; import { useFormState, useFormStatus } from 'react-dom';

View File

@ -4,7 +4,8 @@ import { XMarkIcon } from '@heroicons/react/24/outline';
import clsx from 'clsx'; import clsx from 'clsx';
import { removeItem } from 'components/cart/actions'; import { removeItem } from 'components/cart/actions';
import LoadingDots from 'components/loading-dots'; import LoadingDots from 'components/loading-dots';
import type { CartItem, Store } from 'lib/shopify/types'; import { Store } from 'lib/aspire/types';
import type { CartItem } from 'lib/shopify/types';
import { useFormState, useFormStatus } from 'react-dom'; import { useFormState, useFormStatus } from 'react-dom';
function SubmitButton() { function SubmitButton() {

View File

@ -4,7 +4,8 @@ import { MinusIcon, PlusIcon } from '@heroicons/react/24/outline';
import clsx from 'clsx'; import clsx from 'clsx';
import { updateItemQuantity } from 'components/cart/actions'; import { updateItemQuantity } from 'components/cart/actions';
import LoadingDots from 'components/loading-dots'; import LoadingDots from 'components/loading-dots';
import type { CartItem, Store } from 'lib/shopify/types'; import { Store } from 'lib/aspire/types';
import type { CartItem } from 'lib/shopify/types';
import { useFormState, useFormStatus } from 'react-dom'; import { useFormState, useFormStatus } from 'react-dom';
function SubmitButton({ type }: { type: 'plus' | 'minus' }) { function SubmitButton({ type }: { type: 'plus' | 'minus' }) {

View File

@ -1,5 +1,5 @@
import { Store } from 'lib/aspire/types';
import { getCart } from 'lib/shopify'; import { getCart } from 'lib/shopify';
import { Store } from 'lib/shopify/types';
import { cookies } from 'next/headers'; import { cookies } from 'next/headers';
import CartModal from './modal'; import CartModal from './modal';

View File

@ -3,8 +3,9 @@
import { Dialog, Transition } from '@headlessui/react'; import { Dialog, Transition } from '@headlessui/react';
import { ShoppingCartIcon } from '@heroicons/react/24/outline'; import { ShoppingCartIcon } from '@heroicons/react/24/outline';
import Price from 'components/price'; import Price from 'components/price';
import { Store } from 'lib/aspire/types';
import { DEFAULT_OPTION } from 'lib/constants'; import { DEFAULT_OPTION } from 'lib/constants';
import type { Cart, Store } from 'lib/shopify/types'; import type { Cart } from 'lib/shopify/types';
import { createUrl } from 'lib/utils'; import { createUrl } from 'lib/utils';
import Image from 'next/image'; import Image from 'next/image';
import Link from 'next/link'; import Link from 'next/link';

View File

@ -1,6 +1,7 @@
import { GridTileImage } from 'components/grid/tile'; import { GridTileImage } from 'components/grid/tile';
import { Store } from 'lib/aspire/types';
import { getCollectionProducts } from 'lib/shopify'; import { getCollectionProducts } from 'lib/shopify';
import type { Product, Store } from 'lib/shopify/types'; import type { Product } from 'lib/shopify/types';
import Link from 'next/link'; import Link from 'next/link';
function ThreeItemGridItem({ function ThreeItemGridItem({

View File

@ -1,8 +1,7 @@
import clsx from 'clsx'; import clsx from 'clsx';
import { Suspense } from 'react'; import { Store } from 'lib/aspire/types';
import { getCollections } from 'lib/shopify'; import { getCollections } from 'lib/shopify';
import { Store } from 'lib/shopify/types'; import { Suspense } from 'react';
import FilterList from './filter'; import FilterList from './filter';
async function CollectionList({ store }: { store: Store }) { async function CollectionList({ store }: { store: Store }) {

View File

@ -1,7 +1,8 @@
import { AddToCart } from 'components/cart/add-to-cart'; import { AddToCart } from 'components/cart/add-to-cart';
import Price from 'components/price'; import Price from 'components/price';
import Prose from 'components/prose'; import Prose from 'components/prose';
import { Product, Store } from 'lib/shopify/types'; import { Store } from 'lib/aspire/types';
import { Product } from 'lib/shopify/types';
import { Suspense } from 'react'; import { Suspense } from 'react';
import { VariantSelector } from './variant-selector'; import { VariantSelector } from './variant-selector';

53
lib/aspire/index.ts Normal file
View File

@ -0,0 +1,53 @@
import { getProductById } from 'lib/shopify';
import { ContentLandingPages } from './types';
export async function getContentLandingPageConfig(contentLandingPageId: string) {
const contentLandingPages: ContentLandingPages = {
ABC: {
contentLandingPageId: '01J39NYS5HKXE9J4R0BMDKH845',
slug: 'ABC',
content: {
contentId: '01J39NY002BQ5FDH6BFJR78V8E',
contentUrl: 'https://vercel.com'
},
brand: {
brandId: '01J39NXQGAKT82JQWEYXP9MFE3',
companyName: 'Vercel'
},
store: {
storeId: '01J39NYCJY8ZW27ES9BB7KEVXN',
domain: 'https://test-app-furie.myshopify.com',
key: '30f0c9b2ee5c69d6c0de2e7a048eb6b4'
},
productId: 'gid://shopify/Product/8587441176812'
},
'123': {
contentLandingPageId: '123',
slug: '123',
content: {
contentId: '01J39P1K9DY9XM2B5Y9T5RVJNP',
contentUrl: 'https://vercel.com'
},
brand: {
brandId: '123456789',
companyName: 'Vercel'
},
store: {
storeId: 'quickstart-ba952e54',
domain: 'https://quickstart-ba952e54.myshopify.com',
key: '8efbd119747c632000b04ed68313abf1'
},
productId: 'gid://shopify/Product/7913032548543'
}
};
const contentLandingPage = contentLandingPages[contentLandingPageId];
if (!contentLandingPage) {
throw new Error('Content Landing Page not found');
}
const product = await getProductById(contentLandingPage.store, contentLandingPage?.productId);
return { ...contentLandingPage, product };
}

28
lib/aspire/types.ts Normal file
View File

@ -0,0 +1,28 @@
export type Brand = {
brandId: string;
companyName: string;
};
export type Content = {
contentId: string;
contentUrl: string;
};
export type ContentLandingPage = {
contentLandingPageId: string;
slug: string;
content: Content;
brand: Brand;
store: Store;
productId: string;
};
export type ContentLandingPages = {
[key: string]: ContentLandingPage;
};
export type Store = {
storeId: string;
domain: string;
key: string;
};

View File

@ -1,3 +1,4 @@
import { Store } from 'lib/aspire/types';
import { HIDDEN_PRODUCT_TAG, SHOPIFY_GRAPHQL_API_ENDPOINT, TAGS } from 'lib/constants'; import { HIDDEN_PRODUCT_TAG, SHOPIFY_GRAPHQL_API_ENDPOINT, TAGS } from 'lib/constants';
import { isShopifyError } from 'lib/type-guards'; import { isShopifyError } from 'lib/type-guards';
import { revalidateTag } from 'next/cache'; import { revalidateTag } from 'next/cache';
@ -47,8 +48,7 @@ import {
ShopifyProductRecommendationsOperation, ShopifyProductRecommendationsOperation,
ShopifyProductsOperation, ShopifyProductsOperation,
ShopifyRemoveFromCartOperation, ShopifyRemoveFromCartOperation,
ShopifyUpdateCartOperation, ShopifyUpdateCartOperation
Store
} from './types'; } from './types';
/* /*

View File

@ -8,33 +8,6 @@ export type Edge<T> = {
node: T; node: T;
}; };
export type Brand = {
brandId: string;
companyName: string;
};
export type Content = {
contentId: string;
contentUrl: string;
};
export type ContentLandingPage = {
contentLandingPageId: string;
content: Content;
brand: Brand;
store: Store;
productId: string;
};
export type ContentLandingPages = {
[key: string]: ContentLandingPage;
};
export type Store = {
domain: string;
key: string;
};
export type Cart = Omit<ShopifyCart, 'lines'> & { export type Cart = Omit<ShopifyCart, 'lines'> & {
lines: CartItem[]; lines: CartItem[];
}; };