mirror of
https://github.com/vercel/commerce.git
synced 2025-05-08 10:47:51 +00:00
fix(refactor): refactor code for isolation
This commit is contained in:
parent
dfa42c2552
commit
4ffb965688
@ -3,78 +3,34 @@ import OpenCart from 'components/cart/open-cart';
|
||||
import { GridTileImage } from 'components/grid/tile';
|
||||
import { Gallery } from 'components/product/gallery';
|
||||
import { ProductDescription } from 'components/product/product-description';
|
||||
import { getProductById, getProductRecommendations } from 'lib/shopify';
|
||||
import { ContentLandingPages, Image, Store } from 'lib/shopify/types';
|
||||
import { getContentLandingPageConfig } from 'lib/aspire';
|
||||
import { Store } from 'lib/aspire/types';
|
||||
import { getProductRecommendations } from 'lib/shopify';
|
||||
import { Image } from 'lib/shopify/types';
|
||||
import Link from 'next/link';
|
||||
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 } }) {
|
||||
const instance = await lookupContentLandingPage(params.ContentLandingPage);
|
||||
const config = await getContentLandingPageConfig(params.ContentLandingPage);
|
||||
|
||||
if (!instance.product) {
|
||||
if (!config.product) {
|
||||
return <div>Product not found</div>;
|
||||
}
|
||||
|
||||
const productJsonLd = {
|
||||
'@context': 'https://schema.org',
|
||||
'@type': 'Product',
|
||||
name: instance.product.title,
|
||||
description: instance.product.description,
|
||||
image: instance.product.featuredImage.url,
|
||||
name: config.product.title,
|
||||
description: config.product.description,
|
||||
image: config.product.featuredImage.url,
|
||||
offers: {
|
||||
'@type': 'AggregateOffer',
|
||||
availability: instance.product.availableForSale
|
||||
availability: config.product.availableForSale
|
||||
? 'https://schema.org/InStock'
|
||||
: 'https://schema.org/OutOfStock',
|
||||
priceCurrency: instance.product.priceRange.minVariantPrice.currencyCode,
|
||||
highPrice: instance.product.priceRange.maxVariantPrice.amount,
|
||||
lowPrice: instance.product.priceRange.minVariantPrice.amount
|
||||
priceCurrency: config.product.priceRange.minVariantPrice.currencyCode,
|
||||
highPrice: config.product.priceRange.maxVariantPrice.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 justify-end md:w-1/3">
|
||||
<Suspense fallback={<OpenCart />}>
|
||||
<Cart store={instance.store} />
|
||||
<Cart store={config.store} />
|
||||
</Suspense>
|
||||
</div>
|
||||
</div>
|
||||
@ -107,7 +63,7 @@ export default async function Page({ params }: { params: { ContentLandingPage: s
|
||||
}
|
||||
>
|
||||
<Gallery
|
||||
images={instance.product.images.map((image: Image) => ({
|
||||
images={config.product.images.map((image: Image) => ({
|
||||
src: image.url,
|
||||
altText: image.altText
|
||||
}))}
|
||||
@ -116,10 +72,10 @@ export default async function Page({ params }: { params: { ContentLandingPage: s
|
||||
</div>
|
||||
|
||||
<div className="basis-full lg:basis-2/6">
|
||||
<ProductDescription product={instance.product} store={instance.store} />
|
||||
<ProductDescription product={config.product} store={config.store} />
|
||||
</div>
|
||||
</div>
|
||||
<RelatedProducts id={instance.product.id} store={instance.store} />
|
||||
<RelatedProducts id={config.product.id} store={config.store} />
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Store } from 'lib/aspire/types';
|
||||
import { getCollectionProducts } from 'lib/shopify';
|
||||
import { Store } from 'lib/shopify/types';
|
||||
import Link from 'next/link';
|
||||
import { GridTileImage } from './grid/tile';
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
'use server';
|
||||
|
||||
import { Store } from 'lib/aspire/types';
|
||||
import { TAGS } from 'lib/constants';
|
||||
import { addToCart, createCart, getCart, removeFromCart, updateCart } from 'lib/shopify';
|
||||
import { Store } from 'lib/shopify/types';
|
||||
import { revalidateTag } from 'next/cache';
|
||||
import { cookies } from 'next/headers';
|
||||
|
||||
|
@ -4,7 +4,8 @@ import { PlusIcon } from '@heroicons/react/24/outline';
|
||||
import clsx from 'clsx';
|
||||
import { addItem } from 'components/cart/actions';
|
||||
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 { useFormState, useFormStatus } from 'react-dom';
|
||||
|
||||
|
@ -4,7 +4,8 @@ import { XMarkIcon } from '@heroicons/react/24/outline';
|
||||
import clsx from 'clsx';
|
||||
import { removeItem } from 'components/cart/actions';
|
||||
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';
|
||||
|
||||
function SubmitButton() {
|
||||
|
@ -4,7 +4,8 @@ import { MinusIcon, PlusIcon } from '@heroicons/react/24/outline';
|
||||
import clsx from 'clsx';
|
||||
import { updateItemQuantity } from 'components/cart/actions';
|
||||
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';
|
||||
|
||||
function SubmitButton({ type }: { type: 'plus' | 'minus' }) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Store } from 'lib/aspire/types';
|
||||
import { getCart } from 'lib/shopify';
|
||||
import { Store } from 'lib/shopify/types';
|
||||
import { cookies } from 'next/headers';
|
||||
import CartModal from './modal';
|
||||
|
||||
|
@ -3,8 +3,9 @@
|
||||
import { Dialog, Transition } from '@headlessui/react';
|
||||
import { ShoppingCartIcon } from '@heroicons/react/24/outline';
|
||||
import Price from 'components/price';
|
||||
import { Store } from 'lib/aspire/types';
|
||||
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 Image from 'next/image';
|
||||
import Link from 'next/link';
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { GridTileImage } from 'components/grid/tile';
|
||||
import { Store } from 'lib/aspire/types';
|
||||
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';
|
||||
|
||||
function ThreeItemGridItem({
|
||||
|
@ -1,8 +1,7 @@
|
||||
import clsx from 'clsx';
|
||||
import { Suspense } from 'react';
|
||||
|
||||
import { Store } from 'lib/aspire/types';
|
||||
import { getCollections } from 'lib/shopify';
|
||||
import { Store } from 'lib/shopify/types';
|
||||
import { Suspense } from 'react';
|
||||
import FilterList from './filter';
|
||||
|
||||
async function CollectionList({ store }: { store: Store }) {
|
||||
|
@ -1,7 +1,8 @@
|
||||
import { AddToCart } from 'components/cart/add-to-cart';
|
||||
import Price from 'components/price';
|
||||
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 { VariantSelector } from './variant-selector';
|
||||
|
||||
|
53
lib/aspire/index.ts
Normal file
53
lib/aspire/index.ts
Normal 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
28
lib/aspire/types.ts
Normal 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;
|
||||
};
|
@ -1,3 +1,4 @@
|
||||
import { Store } from 'lib/aspire/types';
|
||||
import { HIDDEN_PRODUCT_TAG, SHOPIFY_GRAPHQL_API_ENDPOINT, TAGS } from 'lib/constants';
|
||||
import { isShopifyError } from 'lib/type-guards';
|
||||
import { revalidateTag } from 'next/cache';
|
||||
@ -47,8 +48,7 @@ import {
|
||||
ShopifyProductRecommendationsOperation,
|
||||
ShopifyProductsOperation,
|
||||
ShopifyRemoveFromCartOperation,
|
||||
ShopifyUpdateCartOperation,
|
||||
Store
|
||||
ShopifyUpdateCartOperation
|
||||
} from './types';
|
||||
|
||||
/*
|
||||
|
@ -8,33 +8,6 @@ export type Edge<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'> & {
|
||||
lines: CartItem[];
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user