Skip to content

Commit

Permalink
building out cart modal • clean up • changes to cart service
Browse files Browse the repository at this point in the history
  • Loading branch information
AnselmMarie committed Sep 7, 2024
1 parent c1f9bf4 commit 60f0479
Show file tree
Hide file tree
Showing 14 changed files with 196 additions and 68 deletions.
14 changes: 8 additions & 6 deletions apps/api/src/api/v1/cart/database/cart.database.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,28 @@
export let cartDatabase = [];
export let cartDatabase = { data: [], total: 0, counter: 0 };

export const getCartDataCallUtil = async () => {
export const getCartDataCall = async () => {
return new Promise((resolve) => {
setTimeout(() => {
resolve(cartDatabase);
}, 500);
});
};

export const updateCartDataCallUtil = async (data) => {
export const updateCartDataCall = async ({ data, counter, total }) => {
return new Promise((resolve) => {
setTimeout(() => {
cartDatabase = data;
cartDatabase.data = data;
cartDatabase.counter = counter;
cartDatabase.total = total;
resolve(cartDatabase);
}, 500);
});
};

export const clearCartDataCallUtil = async () => {
export const clearCartDataCall = async () => {
return new Promise((resolve) => {
setTimeout(() => {
cartDatabase = [];
cartDatabase = { data: [], total: 0, counter: 0 };
resolve(cartDatabase);
}, 500);
});
Expand Down
46 changes: 28 additions & 18 deletions apps/api/src/api/v1/cart/services/cart.service.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import { getPokemonSpeciesService } from '../../pokemon';
import { getPokemonDetailService } from '../../pokemon/services/pokemon.detail.service';
import {
clearCartDataCallUtil,
getCartDataCallUtil,
updateCartDataCallUtil,
} from '../database/cart.database';
import { clearCartDataCall, getCartDataCall, updateCartDataCall } from '../database/cart.database';

interface CartDataProps {
id: string;
Expand All @@ -17,21 +13,30 @@ interface CartDataProps {
isMythical: boolean;
}

const doesItemExistKeyFn = (cartData, id) => {
const cartLength = cartData.length;
const doesItemExistKeyFn = (data, id) => {
const cartLength = data.length;
let key = null;
let counter = null;
let total = null;

for (let loop = 0; loop < cartLength; loop++) {
if (cartData[loop]?.id == id) {
const el = data[loop];

if (el?.id == id) {
key = loop;
break;
}
counter = counter + el?.quantity;
total = total + el?.price;
}
return key;
return {
key,
counter,
total,
};
};

const getCartService = async () => {
return await getCartDataCallUtil();
return await getCartDataCall();
};

const getSpeciesDetail = async (id: string) => {
Expand All @@ -47,13 +52,15 @@ const getSpeciesDetail = async (id: string) => {
};

const updateCartService = async (payload) => {
const currentCartData: any = await getCartDataCallUtil();
const doesItemExistKey = doesItemExistKeyFn(currentCartData, payload?.id);
const finalRes = currentCartData;
const currentCartData: any = await getCartDataCall();
const data = currentCartData.data;
const { key, counter, total } = doesItemExistKeyFn(data, payload?.id);

if (doesItemExistKey !== null) {
const currentObj = currentCartData[doesItemExistKey];
if (key !== null) {
const currentObj = data[key];
currentObj.quantity = currentObj.quantity + 1;
currentCartData.counter = counter + 1;
currentCartData.total = total + 500;

return currentObj;
}
Expand All @@ -69,13 +76,16 @@ const updateCartService = async (payload) => {
isLegendary: additionalData?.is_legendary,
isMythical: additionalData?.is_mythical,
};
finalRes.push(finalPayload);
currentCartData.counter = counter + 1;
currentCartData.total = total + 500;

data.push(finalPayload);

return finalPayload;
};

const clearCartService = async () => {
const res = await clearCartDataCallUtil();
const res = await clearCartDataCall();
return res;
};

Expand Down
3 changes: 0 additions & 3 deletions libs/features/src/lib/cart/cart.modal/cart.modal.interface.ts

This file was deleted.

34 changes: 27 additions & 7 deletions libs/features/src/lib/cart/cart.modal/cart.modal.module.css
Original file line number Diff line number Diff line change
@@ -1,20 +1,40 @@
.modal {
width: 500px;
background: white;
width: 390px;
max-width: 390px;
position: relative;
display: flex;
flex-direction: column;
height: calc(100% - 65px);
}

.dropdownTop {
.cartContent {
padding: 15px;
height: calc(100% - 60px);
}

.dropdownHeadline {
.middleRow {
flex: 1;
}

.cardContentRow {
display: flex;
justify-content: space-between;
align-items: center;
gap: 15px;
}

.image {
width: 115px;
height: 115px;
}

.sep {
background-color: #666;
width: 100%;
height: 1px;
margin-top: 25px;
margin-bottom: 25px;
}

.dropdownBtm {
.totalContent {
height: 60px;
background-color: grey;
border-radius: 0 0 8px 8px;
Expand Down
63 changes: 46 additions & 17 deletions libs/features/src/lib/cart/cart.modal/cart.modal.tsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,58 @@
import { ReactElement } from 'react';

import { AlignmentEnum } from '@pokemon-pet-shop/typing';
import { UiElementLayout, UiIcon, IconTypeEnum, UiTypography, UiModal } from '@pokemon-pet-shop/ui';
import { useGetCart } from '@pokemon-pet-shop/services';
import {
UiElementLayout,
UiIcon,
IconTypeEnum,
UiTypography,
UiImage,
mobSrcTypeEnum,
TypographyTypeEnum,
} from '@pokemon-pet-shop/ui';

import { CartModalProps } from './cart.modal.interface';
import styles from './cart.modal.module.css';

const CartModal = ({ isModalShown = false }: CartModalProps): ReactElement => {
const CartModal = (): ReactElement => {
const { data } = useGetCart();

return (
<UiModal
isModalShown={isModalShown}
classNameModal={styles.modal}
modalAlignment={AlignmentEnum.RIGHT}
>
<UiElementLayout className={styles.dropdownTop}>
<UiElementLayout className={styles.dropdownHeadline}>
<UiTypography>Pokecart</UiTypography>
<UiIcon icon={IconTypeEnum.ICON_X} />
</UiElementLayout>
<UiElementLayout className={styles.modal}>
<UiElementLayout className={styles.cartContent}>
{(data?.data || [])?.map((el: any, i: number) => {
return (
<UiElementLayout key={i} className={styles?.cartWrapper}>
<UiElementLayout className={styles.cardContentRow}>
<UiImage
src={el?.image}
className={styles.image}
alt={`${el?.name} Image`}
mobSrcType={mobSrcTypeEnum.URI}
/>
<UiElementLayout className={styles?.middleRow}>
<UiTypography
className={styles.cardHeadline}
typographyType={TypographyTypeEnum.H1}
>
{el?.name}
</UiTypography>
<UiTypography typographyType={TypographyTypeEnum.SPAN} className={styles.price}>
{el?.price}
</UiTypography>
</UiElementLayout>
<UiIcon icon={IconTypeEnum.ICON_TRASH} />
</UiElementLayout>

<UiElementLayout className={styles?.sep} />
</UiElementLayout>
);
})}
</UiElementLayout>
<UiElementLayout className={styles.dropdownBtm}>
<UiElementLayout className={styles.totalContent}>
<UiTypography>Total</UiTypography>
<UiTypography>$550.00</UiTypography>
<UiTypography>{data?.total}</UiTypography>
</UiElementLayout>
</UiModal>
</UiElementLayout>
);
};

Expand Down
36 changes: 25 additions & 11 deletions libs/features/src/lib/navigation/header/header.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useMemo } from 'react';

import { pokeshopLogo } from '@pokemon-pet-shop/assets';
import { useGetCart } from '@pokemon-pet-shop/services';
import { ModalHeadlineTypeEnum, useModalStore } from '@pokemon-pet-shop/store';
import { AlignmentEnum } from '@pokemon-pet-shop/typing';
import {
UiElementLayout,
ElementLayoutTypeEnum,
Expand All @@ -15,20 +15,34 @@ import {
UiContainer,
UiHideInMobile,
} from '@pokemon-pet-shop/ui';
import { noopUtil } from '@pokemon-pet-shop/utils';

import { UiCartModal } from '../../cart';

import { styles } from './header.module';

const Header = () => {
const { data } = useGetCart();

const getCartCounter = useMemo(() => {
let counter = 0;
(data || []).forEach((el) => {
counter = counter + el.quantity;
});
const openModal = useModalStore((state) => state.openModal);

return counter;
}, [data]);
const handleOpenDetailModalClick = () => {
openModal({
content: <UiCartModal />,
options: {
title: 'Pokecart',
data: data,
classNameShadow: '',
classNameModal: '',
isModalShown: false,
headlineType: ModalHeadlineTypeEnum.RELATIVE,
modalAlignment: AlignmentEnum.RIGHT,
},
onCallback: () => {
noopUtil();
},
});
};

return (
<UiElementLayout layoutType={ElementLayoutTypeEnum.HEADER} className={styles.headerWrapper}>
Expand All @@ -53,8 +67,8 @@ const Header = () => {
/>
</UiHideInMobile>

<UiElementLayout>
<UiTypography>{getCartCounter}</UiTypography>
<UiElementLayout onClick={handleOpenDetailModalClick}>
<UiTypography>{data?.counter}</UiTypography>
<UiIcon classNameIcon={styles.iconCart} />
</UiElementLayout>
</UiContainer>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ReactElement, useCallback, useMemo } from 'react';
import { ReactElement, useMemo } from 'react';

import { halfCircle } from '@pokemon-pet-shop/assets';
import { useCartStore, useModalStore } from '@pokemon-pet-shop/store';
import { useModalStore } from '@pokemon-pet-shop/store';
import {
PokemonDetailAbilityObj,
PokemonDetailTypesObj,
Expand Down Expand Up @@ -34,8 +34,6 @@ const PokemonDetailModal = (): ReactElement => {
...data,
} as PokemonListApi;

const { addQuantity } = useCartStore((state) => state);

const {
speciesData: dataD = {},
isError,
Expand Down
23 changes: 22 additions & 1 deletion libs/services/src/lib/cart/cart.mutate.service.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,42 @@
import { useMutation } from '@tanstack/react-query';
import { useMutation, useQueryClient } from '@tanstack/react-query';

import { clearCart, deleteCartItem, updateCart } from './api.cart.service';

export function useUpdateCart() {
const queryClient = useQueryClient();

return useMutation({
mutationFn: (data: any) => updateCart(data),
onSettled: async (_, error) => {
if (!error) {
await queryClient.invalidateQueries({ queryKey: ['cart'] });
}
},
});
}

export function useDeleteCartItem() {
const queryClient = useQueryClient();

return useMutation({
mutationFn: (id: number) => deleteCartItem(id),
onSettled: async (_, error) => {
if (!error) {
await queryClient.invalidateQueries({ queryKey: ['cart'] });
}
},
});
}

export function useClearCart() {
const queryClient = useQueryClient();

return useMutation({
mutationFn: () => clearCart(),
onSettled: async (_, error) => {
if (!error) {
await queryClient.invalidateQueries({ queryKey: ['cart'] });
}
},
});
}
3 changes: 2 additions & 1 deletion libs/store/src/lib/modal.store.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { ReactElement } from 'react';

import { AlignmentEnum } from '@pokemon-pet-shop/typing';
import { noopUtil } from '@pokemon-pet-shop/utils';
import { create } from 'zustand';

Expand Down Expand Up @@ -34,7 +35,7 @@ const modalStore = (set: any) => ({
title: '',
data: null,
headlineType: ModalHeadlineTypeEnum.RELATIVE,
modalAlignment: 'center',
modalAlignment: AlignmentEnum.CENTER,
},
onCallback: null,
changeTitle: (title: string) => {
Expand Down
Loading

0 comments on commit 60f0479

Please sign in to comment.