tweaks to product mocks

This commit is contained in:
Ghita Lucian 2023-08-14 12:46:08 +02:00
parent 176fc0ea42
commit e513d3b490
8 changed files with 236 additions and 97 deletions

View File

@ -6,7 +6,7 @@ import { Suspense } from 'react';
export const runtime = 'edge';
export const metadata = {
description: 'High-performance ecommerce store built with Next.js, Vercel, and Shopify.',
description: 'High-performance ecommerce store built with Next.js, Vercel.',
openGraph: {
type: 'website'
}

View File

@ -4,29 +4,30 @@ import { addToCart, createCart, getCart, removeFromCart, updateCart } from 'lib/
import { cookies } from 'next/headers';
export const addItem = async (variantId: string | undefined): Promise<String | undefined> => {
let cartId = cookies().get('cartId')?.value;
let cart;
if (cartId) {
cart = await getCart(cartId);
}
if (!cartId || !cart) {
cart = await createCart();
cartId = cart.id;
// TODO: this is not working under older Next.js versions
// cookies().set('cartId', cartId);
}
if (!variantId) {
return 'Missing product variant ID';
}
try {
await addToCart(cartId, [{ merchandiseId: variantId, quantity: 1 }]);
} catch (e) {
return 'Error adding item to cart';
}
// let cartId = cookies().get('cartId')?.value;
// let cart;
//
// if (cartId) {
// cart = await getCart(cartId);
// }
//
// if (!cartId || !cart) {
// cart = await createCart();
// cartId = cart.id;
// // TODO: this is not working under older Next.js versions
// // cookies().set('cartId', cartId);
// }
//
// if (!variantId) {
// return 'Missing product variant ID';
// }
//
// try {
// await addToCart(cartId, [{ merchandiseId: variantId, quantity: 1 }]);
// } catch (e) {
// return 'Error adding item to cart';
// }
return undefined;
};
export const removeItem = async (lineId: string): Promise<String | undefined> => {

View File

@ -31,7 +31,7 @@ export function GridTileImage({
{props.src ? (
// eslint-disable-next-line jsx-a11y/alt-text -- `alt` is inherited from `props`, which is being enforced with TypeScript
<Image
className={clsx('relative h-full w-full object-contain', {
className={clsx('relative h-full w-full object-cover', {
'transition duration-300 ease-in-out group-hover:scale-105': isInteractive
})}
{...props}

View File

@ -5,7 +5,10 @@ import LogoSquare from 'components/logo-square';
import { getMenu } from 'lib/shopify';
import { Suspense } from 'react';
const { COMPANY_NAME, SITE_NAME } = process.env;
// const { COMPANY_NAME, SITE_NAME } = process.env;
const COMPANY_NAME = 'WKND';
const SITE_NAME = 'WKND Adventures Commerce';
export default async function Footer() {
const currentYear = new Date().getFullYear();
@ -37,17 +40,17 @@ export default async function Footer() {
>
<FooterMenu menu={menu} />
</Suspense>
<div className="md:ml-auto">
<a
className="flex h-8 w-max flex-none items-center justify-center rounded-md border border-neutral-200 bg-white text-xs text-black dark:border-neutral-700 dark:bg-black dark:text-white"
aria-label="Deploy on Vercel"
href="https://vercel.com/templates/next.js/nextjs-commerce"
>
<span className="px-3"></span>
<hr className="h-full border-r border-neutral-200 dark:border-neutral-700" />
<span className="px-3">Deploy</span>
</a>
</div>
{/*<div className="md:ml-auto">*/}
{/* <a*/}
{/* className="flex h-8 w-max flex-none items-center justify-center rounded-md border border-neutral-200 bg-white text-xs text-black dark:border-neutral-700 dark:bg-black dark:text-white"*/}
{/* aria-label="Deploy on Vercel"*/}
{/* href="https://vercel.com/templates/next.js/nextjs-commerce"*/}
{/* >*/}
{/* <span className="px-3">▲</span>*/}
{/* <hr className="h-full border-r border-neutral-200 dark:border-neutral-700" />*/}
{/* <span className="px-3">Deploy</span>*/}
{/* </a>*/}
{/*</div>*/}
</div>
<div className="border-t border-neutral-200 py-6 text-sm dark:border-neutral-700">
<div className="mx-auto flex w-full max-w-7xl flex-col items-center gap-1 px-4 md:flex-row md:gap-0 md:px-4 xl:px-0">
@ -57,12 +60,12 @@ export default async function Footer() {
</p>
<hr className="mx-4 hidden h-4 w-[1px] border-l border-neutral-400 md:inline-block" />
<p>Designed in California</p>
<p className="md:ml-auto">
Crafted by{' '}
<a href="https://vercel.com" className="text-black dark:text-white">
Vercel
</a>
</p>
{/*<p className="md:ml-auto">*/}
{/* Crafted by{' '}*/}
{/* <a href="https://vercel.com" className="text-black dark:text-white">*/}
{/* ▲ Vercel*/}
{/* </a>*/}
{/*</p>*/}
</div>
</div>
</footer>

View File

@ -31,7 +31,7 @@ export function Gallery({ images }: { images: { src: string; altText: string }[]
<div className="relative aspect-square h-full max-h-[550px] w-full overflow-hidden">
{images[imageIndex] && (
<Image
className="h-full w-full object-contain"
className="h-full w-full object-cover"
fill
sizes="(min-width: 1024px) 66vw, 100vw"
alt={images[imageIndex]?.altText as string}

View File

@ -1,5 +1,3 @@
import * as console from 'console';
const baseImagePath = 'https://publish-p64257-e147834-cmstg.adobeaemcloud.com/';
const adventures = [
@ -571,7 +569,7 @@ export function transformToProduct(adventure: any): Product {
width: adventure.primaryImage.width,
height: adventure.primaryImage.height
},
images: [], // Only one image is provided, so not including that in the images array
images: [],
seo: {
title: adventure.title,
description: adventure.description.html
@ -581,16 +579,107 @@ export function transformToProduct(adventure: any): Product {
updatedAt: new Date().toISOString()
};
product.variants.push(variant);
product.images.push(product.featuredImage);
return product;
}
export const adventureProducts = adventures.map(transformToProduct);
export const adventureProducts: Product[] = adventures.map(transformToProduct) as Product[];
export const adventureProductNodes = adventureProducts.map((product) => ({
node: product
}));
// console.log(adventureProductNodes);
export function getProductNodesByKeyword(keyword: string | undefined): { node: Product }[] {
return getProductsByKeyword(keyword).map((product) => ({
node: product
}));
}
// const product = transformToProduct(adventure);
// console.log(product);
export function getProductByHandle(handle: string): Product | undefined {
const res = adventureProducts.find((product) => product.handle === handle);
return res;
}
export function getProductsByKeyword(keyword: string | undefined): Product[] {
//if keyword is empty, return all products
if (!keyword || keyword === undefined) {
return adventureProducts;
}
keyword = keyword || '';
if (keyword.includes('all')) {
return adventureProducts;
}
if (keyword.includes('hidden-homepage-featured-items')) {
// @ts-ignore
return [
adventureProducts[0] as Product,
adventureProducts[1] as Product,
adventureProducts[2] as Product
];
}
if (keyword.includes('hidden-homepage-carousel')) {
// @ts-ignore
return [
adventureProducts[4] as Product,
adventureProducts[5] as Product,
adventureProducts[6] as Product,
adventureProducts[7] as Product,
adventureProducts[8] as Product
];
}
//if keyword contains a dash, split it into an array of words, and use the first word
if (keyword.includes('-')) {
// @ts-ignore
keyword = keyword.split('-')[0];
}
keyword = keyword || '';
keyword = keyword.toLowerCase();
if (keyword.includes('winter')) {
return adventureProducts.filter(
(product) =>
product.title.toLowerCase().includes('ski') ||
product.title.toLowerCase().includes('winter')
);
}
if (keyword.includes('summer')) {
return adventureProducts.filter(
(product) =>
product.title.toLowerCase().includes('surf') ||
product.title.toLowerCase().includes('climbing') ||
product.title.toLowerCase().includes('summer') ||
product.title.toLowerCase().includes('hiking') ||
product.title.toLowerCase().includes('camping') ||
product.title.toLowerCase().includes('rafting') ||
product.title.toLowerCase().includes('tasting') ||
product.title.toLowerCase().includes('cycling') ||
product.title.toLowerCase().includes('gastro') ||
product.title.toLowerCase().includes('backpacking')
);
}
if (keyword.includes('europe')) {
return adventureProducts.filter(
(product) =>
product.title.toLowerCase().includes('tuscany') ||
product.title.toLowerCase().includes('marais') ||
product.title.toLowerCase().includes('basel') ||
product.title.toLowerCase().includes('mont')
);
}
return adventureProducts.filter(
(product) =>
product.title.toLowerCase().includes(<string>keyword) ||
product.description.toLowerCase().includes(<string>keyword)
);
}

View File

@ -7,8 +7,11 @@ import {
mockShopifyProduct,
mockCartItem,
mockShopifyCart,
mockShopifyCollection,
mockPage
winterCollection,
summerCollection,
europeCollection,
mockPage,
collections
} from './mock';
import {
Cart,
@ -26,7 +29,7 @@ import {
import { getCollectionsQuery } from './queries/collection';
import { TAGS } from '../constants';
import { shopifyFetch } from './index_old';
import { adventureProductNodes } from './adventures';
import { adventureProductNodes, getProductByHandle, getProductNodesByKeyword } from './adventures';
const HIDDEN_PRODUCT_TAG = 'hidden';
@ -39,8 +42,13 @@ const mockFetchResponse = (data) => ({
});
// @ts-ignore
const removeEdgesAndNodes = (connection) =>
connection?.edges ? connection?.edges.map((edge) => edge.node) : [];
const removeEdgesAndNodes = (connection) => {
if (!connection?.edges) {
return connection;
}
return connection?.edges ? connection?.edges.map((edge: any) => edge.node) : [];
};
export const createCart = async (): Promise<Cart> => {
const res = mockFetchResponse({
@ -93,7 +101,7 @@ export const getCart = async (cartId: string): Promise<Cart | undefined> => {
export const getCollection = async (handle: string): Promise<Collection | undefined> => {
const res = mockFetchResponse({
collection: mockShopifyCollection
collection: collections.find((collection) => collection.handle === handle)
});
return reshapeCollection(res.body.data.collection);
};
@ -110,8 +118,7 @@ export const getCollectionProducts = async ({
const res = mockFetchResponse({
collection: {
products: {
edges: adventureProductNodes
// edges: [{ node: mockShopifyProduct }]
edges: getProductNodesByKeyword(collection)
}
}
});
@ -125,7 +132,7 @@ export async function getCollections(): Promise<Collection[]> {
// });
const res = mockFetchResponse({
collections: {
edges: [{ node: mockShopifyCollection }]
edges: [{ node: winterCollection }, { node: summerCollection }, { node: europeCollection }]
}
});
const shopifyCollections = removeEdgesAndNodes(res.body?.data?.collections);
@ -138,7 +145,7 @@ export async function getCollections(): Promise<Collection[]> {
title: 'All',
description: 'All products'
},
path: '/search',
path: '/search/',
updatedAt: new Date().toISOString()
},
// Filter out the `hidden` collections.
@ -156,8 +163,20 @@ export const getMenu = async (handle: string): Promise<Menu[]> => {
menu: {
items: [
{
title: 'Sample Menu',
path: 'https://example.com/sample-menu'
title: 'All',
path: '/'
},
{
title: 'Summer',
path: '/search/summer-collection'
},
{
title: 'Winter',
path: '/search/winter-collection'
},
{
title: 'Europe',
path: '/search/europe-collection'
}
]
}
@ -183,14 +202,19 @@ export const getPages = async (): Promise<Page[]> => {
export const getProduct = async (handle: string): Promise<Product | undefined> => {
const res = mockFetchResponse({
product: mockShopifyProduct
product: getProductByHandle(handle)
});
return reshapeProduct(res.body.data.product, false);
};
export const getProductRecommendations = async (productId: string): Promise<Product[]> => {
const res = mockFetchResponse({
productRecommendations: [mockShopifyProduct]
productRecommendations: [
getProductByHandle('climbing-new-zealand'),
getProductByHandle('ski-touring-mont-blanc'),
getProductByHandle('downhill-skiing-wyoming'),
getProductByHandle('cycling-tuscany')
]
});
return reshapeProducts(res.body.data.productRecommendations);
};
@ -206,7 +230,7 @@ export const getProducts = async ({
}): Promise<Product[]> => {
const res = mockFetchResponse({
products: {
edges: [{ node: mockShopifyProduct }]
edges: getProductNodesByKeyword(query)
}
});
return reshapeProducts(removeEdgesAndNodes(res.body.data.products));
@ -254,11 +278,6 @@ const reshapeCollections = (collections: ShopifyCollection[]) => {
};
const reshapeImages = (images: Connection<Image>, productTitle: string) => {
try {
console.log('images', images);
} catch (e) {
// console.log('error', e);
}
const flattened = removeEdgesAndNodes(images);
// @ts-ignore
@ -272,7 +291,8 @@ const reshapeImages = (images: Connection<Image>, productTitle: string) => {
};
const reshapeProduct = (product: ShopifyProduct, filterHiddenProducts: boolean = true) => {
if (!product || (filterHiddenProducts && product.tags.includes(HIDDEN_PRODUCT_TAG))) {
// if (!product || (filterHiddenProducts && product.tags.includes(HIDDEN_PRODUCT_TAG))) {
if (!product) {
return undefined;
}

View File

@ -1,25 +1,25 @@
// Mock data for the defined types
const { adventureProducts } = require('./adventures');
const mockMoney = {
export const mockMoney = {
amount: '100.00',
currencyCode: 'USD'
};
const mockImage = {
export const mockImage = {
url: 'https://ssc-sparkle.vercel.app/_next/image?url=https%3A%2F%2Fpublish-p64257-e147834-cmstg.adobeaemcloud.com%2Fcontent%2Fdam%2Faem-demo-assets%2Fen%2Fadventures%2Fcycling-tuscany%2FAdobeStock_261097343.jpeg&w=2048&q=75',
altText: 'Sample Image',
width: 500,
height: 500
};
const mockProductOption = {
export const mockProductOption = {
id: 'option1',
name: 'Color',
values: ['Red', 'Blue', 'Green']
};
const mockProductVariant = {
export const mockProductVariant = {
id: 'variant1',
title: 'Red Variant',
availableForSale: true,
@ -32,7 +32,7 @@ const mockProductVariant = {
price: mockMoney
};
const mockShopifyProduct = adventureProducts[0];
export const mockShopifyProduct = adventureProducts[0];
// const mockShopifyProductOld = {
// id: 'product1',
@ -57,7 +57,7 @@ const mockShopifyProduct = adventureProducts[0];
// updatedAt: '2023-08-10T00:00:00Z'
// };
const mockCartItem = {
export const mockCartItem = {
id: 'item1',
quantity: 1,
cost: { totalAmount: mockMoney },
@ -74,7 +74,7 @@ const mockCartItem = {
}
};
const mockShopifyCart = {
export const mockShopifyCart = {
id: 'cart1',
checkoutUrl: 'https://example.com/checkout',
cost: {
@ -86,18 +86,40 @@ const mockShopifyCart = {
totalQuantity: 1
};
const mockShopifyCollection = {
handle: 'sample-collection',
title: 'Sample Collection',
description: 'This is a sample collection.',
export const winterCollection = {
handle: 'winter-collection',
title: 'Winter',
description: 'Adventures for the winter.',
seo: {
title: 'Sample Collection',
description: 'This is a sample collection.'
title: 'Winter Collection',
description: 'Adventures for the winter.'
},
updatedAt: '2023-08-10T00:00:00Z'
};
const mockPage = {
export const summerCollection = {
handle: 'summer-collection',
title: 'Summer',
description: 'Adventures for the summer.',
seo: {
title: 'Summer Collection',
description: 'Adventures for the summer.'
},
updatedAt: '2023-08-10T00:00:00Z'
};
export const europeCollection = {
handle: 'europe-collection',
title: 'Europe',
description: 'Adventures in Europe.',
seo: {
title: 'Europe Collection',
description: 'Adventures in Europe.'
},
updatedAt: '2023-08-10T00:00:00Z'
};
export const mockPage = {
id: 'page1',
title: 'Sample Page',
handle: 'sample-page',
@ -113,14 +135,18 @@ const mockPage = {
// Exporting the mock data
module.exports = {
mockMoney,
mockImage,
mockProductOption,
mockProductVariant,
mockShopifyProduct,
mockCartItem,
mockShopifyCart,
mockShopifyCollection,
mockPage
};
export const collections = [winterCollection, summerCollection, europeCollection];
//
// module.exports = {
// mockMoney,
// mockImage,
// mockProductOption,
// mockProductVariant,
// mockShopifyProduct,
// mockCartItem,
// mockShopifyCart,
// winterCollection: winterCollection,
// summerCollection: summerCollection,
// europeCollection: europeCollection,
// mockPage
// };