Skip to content

Commit

Permalink
added pagination and performance updates
Browse files Browse the repository at this point in the history
  • Loading branch information
yurytut1993 committed Jun 28, 2024
1 parent 1f2c4bf commit 59e4f49
Show file tree
Hide file tree
Showing 9 changed files with 165 additions and 65 deletions.
5 changes: 5 additions & 0 deletions .changeset/odd-oranges-wonder.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@bigcommerce/catalyst-core": patch
---

add wishlist book
Original file line number Diff line number Diff line change
@@ -1,12 +1,31 @@
'use server';

import { revalidatePath } from 'next/cache';

import {
deleteWishlists as deleteWishlistsClient,
Input,
} from '~/client/mutations/delete-wishlists';

export const deleteWishlists = async (wishlists: Input) => {
const result = await deleteWishlistsClient(wishlists);
try {
const result = await deleteWishlistsClient(wishlists);

revalidatePath('/account/wishlists', 'page');

if (result === 'success') {
return {
status: 'success',
};
}
} catch (error: unknown) {
if (error instanceof Error) {
return {
status: 'error',
message: error.message,
};
}
}

return result;
return { status: 'error', message: 'Unknown error.' };
};
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
'use server';

import { revalidatePath } from 'next/cache';
import { z } from 'zod';

import { createWishlist as createWishlistClient } from '~/client/mutations/create-wishlist';
Expand All @@ -18,17 +19,25 @@ export const createWishlist = async (formData: FormData) => {
isPublic: true,
};

const newWishlist = await createWishlistClient(input);

if (newWishlist) {
return {
status: 'success',
data: newWishlist,
};
try {
const newWishlist = await createWishlistClient(input);

revalidatePath('/account/wishlists', 'page');

if (newWishlist) {
return {
status: 'success',
data: newWishlist,
};
}
} catch (error: unknown) {
if (error instanceof Error) {
return {
status: 'error',
message: error.message,
};
}
}

return {
status: 'error',
message: 'Wish list was not created. Please try again',
};
return { status: 'error', message: 'Unknown error.' };
};
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,12 @@ export const CreateWishlistForm = ({ onWishlistCreated }: Props) => {
const submit = await createWishlist(formData);

if (submit.status === 'success') {
setAccountState({
status: submit.status,
message: t('messages.created', { name: submit.data?.name }),
});

if (submit.data) {
onWishlistCreated(submit.data);
setAccountState({
status: submit.status,
message: t('messages.created', { name: submit.data.name }),
});
}
}

Expand All @@ -73,7 +72,7 @@ export const CreateWishlistForm = ({ onWishlistCreated }: Props) => {
};

return (
<Form action={onSubmit}>
<Form action={onSubmit} className="w-full">
<Field className="relative space-y-2 pb-7" name="name">
<FieldLabel>{t('inputLabel')}</FieldLabel>
<FieldControl asChild>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,44 @@
interface Props {
wishlists: Wishlists;
}
import { getLocale, getTranslations } from 'next-intl/server';

import { Pagination } from '../../../../(faceted)/_components/pagination';
import { getWishlistQuery } from '../../page-data';
import { TabHeading } from '../tab-heading';

import { WishlistBook } from './wishlist-book';

export type Wishlists = NonNullable<Awaited<ReturnType<typeof getWishlistQuery>>>;
type WishlistsDetails = NonNullable<Awaited<ReturnType<typeof getWishlistQuery>>>;
export type Wishlists = WishlistsDetails['wishlists'];

interface Props {
wishlists: Wishlists;
pageInfo: WishlistsDetails['pageInfo'];
}

export interface FormStatus {
status: 'success' | 'error';
message: string;
}

export const WishlistContent = ({ wishlists }: Props) => {
export const WISHLISTS_PER_PAGE = 4;

export const WishlistContent = async ({ pageInfo, wishlists }: Props) => {
const locale = await getLocale();
const t = await getTranslations({ locale, namespace: 'Pagination' });

const { hasNextPage, hasPreviousPage, startCursor, endCursor } = pageInfo;

return (
<>
<TabHeading heading="wishlists" />
<WishlistBook wishlists={wishlists} />
<WishlistBook hasPreviousPage={hasPreviousPage} key={endCursor} wishlists={wishlists} />
<Pagination
endCursor={endCursor}
hasNextPage={hasNextPage}
hasPreviousPage={hasPreviousPage}
nextLabel={t('next')}
prevLabel={t('prev')}
startCursor={startCursor}
/>
</>
);
};
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
'use client';

import { useRouter } from 'next/navigation';
import { useTranslations } from 'next-intl';
import { useState } from 'react';
import { useEffect, useState } from 'react';

import { BcImage } from '~/components/bc-image';
import { Link } from '~/components/link';
Expand All @@ -15,33 +16,34 @@ import { Modal } from '../modal';

import { CreateWishlistForm } from './create-wishlist-form';

import { Wishlists } from '.';
import { Wishlists, WISHLISTS_PER_PAGE } from '.';

interface Wishlist {
onDeleteWishlist?: (id: number, name: string) => Promise<void>;
wishlist: Wishlists[number];
}

interface WishlistBook {
hasPreviousPage: boolean;
wishlists: Wishlists;
}

interface WishlistItems {
itemsLength: number;
interface WishlistItemsCount {
itemsQuantity: number;
}

enum VisibleWishlistItemsPerDevice {
sm = 1,
xs = 1,
md = 3,
lg = 4,
xl = 5,
}

const QuantityDisplay = ({ itemsLength }: WishlistItems) => {
const smItems = itemsLength - VisibleWishlistItemsPerDevice.sm;
const mdItems = itemsLength - VisibleWishlistItemsPerDevice.md;
const lgItems = itemsLength - VisibleWishlistItemsPerDevice.lg;
const xlItems = itemsLength - VisibleWishlistItemsPerDevice.xl;
const HiddenQuantity = ({ itemsQuantity }: WishlistItemsCount) => {
const smItems = itemsQuantity - VisibleWishlistItemsPerDevice.xs;
const mdItems = itemsQuantity - VisibleWishlistItemsPerDevice.md;
const lgItems = itemsQuantity - VisibleWishlistItemsPerDevice.lg;
const xlItems = itemsQuantity - VisibleWishlistItemsPerDevice.xl;

return (
<>
Expand Down Expand Up @@ -132,7 +134,7 @@ const Wishlist = ({ onDeleteWishlist, wishlist: { items, entityId, name } }: Wis
);
})}
</ul>
<QuantityDisplay itemsLength={items.length} />
<HiddenQuantity itemsQuantity={items.length} />
</div>
)}
{onDeleteWishlist && (
Expand All @@ -154,15 +156,37 @@ const Wishlist = ({ onDeleteWishlist, wishlist: { items, entityId, name } }: Wis
);
};

export const WishlistBook = ({ wishlists }: WishlistBook) => {
export const WishlistBook = ({ hasPreviousPage, wishlists }: WishlistBook) => {
const t = useTranslations('Account.Wishlist');
const [wishlistBook, setWishlistBook] = useState(wishlists);
const { accountState, setAccountState } = useAccountStatusContext();
const [ceateWishlistModalOpen, setCreateWishlistModalOpen] = useState(false);
const router = useRouter();

useEffect(() => {
setWishlistBook(wishlists);
}, [wishlists]);

useEffect(() => {
if (hasPreviousPage && wishlistBook.length === 0) {
const timer = setTimeout(() => {
router.back();
}, 3000);

return () => clearTimeout(timer);
}
}, [hasPreviousPage, router, wishlistBook]);

const handleWishlistCreated = (newWishlist: Wishlists[number]) => {
setWishlistBook((prevWishlistBook) => [...prevWishlistBook, newWishlist]);
setWishlistBook((prevWishlistBook) => {
if (prevWishlistBook.length < WISHLISTS_PER_PAGE) {
return [...prevWishlistBook, newWishlist];
}

return prevWishlistBook;
});
setCreateWishlistModalOpen(false);

window.scrollTo({
top: 0,
behavior: 'smooth',
Expand All @@ -172,16 +196,24 @@ export const WishlistBook = ({ wishlists }: WishlistBook) => {
const handleDeleteWishlist = async (id: number, name: string) => {
const result = await deleteWishlists({ entityIds: [id] });

if (result === 'success') {
if (result.status === 'success') {
setWishlistBook((prevWishlistBook) =>
prevWishlistBook.filter(({ entityId }) => entityId !== id),
);
setAccountState({ status: 'success', message: t('messages.deleted', { name }) });
window.scrollTo({
top: 0,
behavior: 'smooth',
});

const message = t('messages.deleted', { name });

setAccountState({ status: 'success', message });
}

if (result.status === 'error') {
setAccountState({ status: result.status, message: result.message });
}

window.scrollTo({
top: 0,
behavior: 'smooth',
});
};

return (
Expand All @@ -193,7 +225,7 @@ export const WishlistBook = ({ wishlists }: WishlistBook) => {
)}

<ul className="mb-8">
{wishlistBook.length === 0 && (
{!hasPreviousPage && wishlistBook.length === 0 && (
<li className="border-y py-4">
<Wishlist wishlist={{ isPublic: true, items: [], name: t('favorites'), entityId: 0 }} />
</li>
Expand Down
41 changes: 26 additions & 15 deletions core/app/[locale]/(default)/account/[tab]/page-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,19 @@ const WishlistQuery = graphql(
[GalleryFragment, PricingFragment],
);

export const getWishlistQuery = cache(async () => {
export interface WishlistArgs {
after?: string;
before?: string;
limit?: number;
}

export const getWishlistQuery = cache(async ({ before, after, limit = 3 }: WishlistArgs) => {
const customerId = await getSessionCustomerId();
const paginationArgs = before ? { last: limit, before } : { first: limit, after };

const response = await client.fetch({
document: WishlistQuery,
variables: { ...paginationArgs },
fetchOptions: { cache: 'no-store' },
customerId,
});
Expand All @@ -73,20 +81,23 @@ export const getWishlistQuery = cache(async () => {
return undefined;
}

return removeEdgesAndNodes(customer.wishlists).map((wishlist) => {
return {
...wishlist,
items: removeEdgesAndNodes(wishlist.items).map((item) => {
return {
...item,
product: {
...item.product,
images: removeEdgesAndNodes(item.product.images),
},
};
}),
};
});
return {
pageInfo: customer.wishlists.pageInfo,
wishlists: removeEdgesAndNodes(customer.wishlists).map((wishlist) => {
return {
...wishlist,
items: removeEdgesAndNodes(wishlist.items).map((item) => {
return {
...item,
product: {
...item.product,
images: removeEdgesAndNodes(item.product.images),
},
};
}),
};
}),
};
});

const CustomerSettingsQuery = graphql(
Expand Down
14 changes: 10 additions & 4 deletions core/app/[locale]/(default)/account/[tab]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { getCustomerAddresses } from '~/client/queries/get-customer-addresses';
import { AddressesContent } from './_components/addresses-content';
import { SettingsContent } from './_components/settings-content';
import { TabHeading } from './_components/tab-heading';
import { WishlistContent } from './_components/wishlist-content';
import { WishlistContent, WISHLISTS_PER_PAGE } from './_components/wishlist-content';
import { TabType } from './layout';
import { getCustomerSettingsQuery, getWishlistQuery } from './page-data';

Expand Down Expand Up @@ -67,13 +67,19 @@ export default async function AccountTabPage({ params: { tab }, searchParams }:
}

case 'wishlists': {
const wishlists = await getWishlistQuery();
const { before, after } = searchParams;

if (!wishlists) {
const wishlistDetails = await getWishlistQuery({
...(after && { after }),
...(before && { before }),
limit: WISHLISTS_PER_PAGE,
});

if (!wishlistDetails) {
notFound();
}

return <WishlistContent wishlists={wishlists} />;
return <WishlistContent {...wishlistDetails} />;
}

case 'recently-viewed':
Expand Down
Loading

0 comments on commit 59e4f49

Please sign in to comment.