Skip to content

Commit

Permalink
Fix for a circular issue for Alignment Enum • building out the cart e…
Browse files Browse the repository at this point in the history
…ndpoint • directory/code clean up
  • Loading branch information
AnselmMarie committed Sep 7, 2024
1 parent 4b6e8dd commit efabf05
Show file tree
Hide file tree
Showing 37 changed files with 422 additions and 76 deletions.
45 changes: 45 additions & 0 deletions apps/api/src/api/v1/cart/controllers/cart.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { Request, Response } from 'express';

import { errFormatResponseUtil } from '../../../../utils/err.format.response.util';
import { clearCartService, getCartService, updateCartService } from '../services/cart.service';

const getCartController = async (req: Request<null, null, null, null>, res: Response) => {
try {
const pokemonDetail = await getCartService();

res.status(200).json(pokemonDetail);
} catch (err) {
res.status(err?.status).json(errFormatResponseUtil(err));
}
};

interface CartBodyProps {
id: any;
}

const updateCartController = async (
req: Request<null, null, CartBodyProps, null>,
res: Response
) => {
const { body } = req;

try {
const pokemonDetail = await updateCartService(body);

res.status(200).json(pokemonDetail);
} catch (err) {
res.status(err?.status).json(errFormatResponseUtil(err));
}
};

const clearCartController = async (req: Request<null, null, null, null>, res: Response) => {
try {
const pokemonDetail = await clearCartService();

res.status(200).json(pokemonDetail);
} catch (err) {
res.status(err?.status).json(errFormatResponseUtil(err));
}
};

export { getCartController, updateCartController, clearCartController };
27 changes: 27 additions & 0 deletions apps/api/src/api/v1/cart/database/cart.database.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
export let cartDatabase = [];

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

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

export const clearCartDataCallUtil = async () => {
return new Promise((resolve) => {
setTimeout(() => {
cartDatabase = [];
resolve(cartDatabase);
}, 500);
});
};
1 change: 1 addition & 0 deletions apps/api/src/api/v1/cart/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './routes/cart.route';
20 changes: 20 additions & 0 deletions apps/api/src/api/v1/cart/interface/pokemon.interface.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
export interface PokemonListQueryProps {
offset?: string | string[];
limit?: string | string[];
}

export interface PokemonDetailQueryProps {
id: string;
}

export interface PokemonSpeciesParamsProps {
id: string;
}

export interface PokemonDetailsParamsProps {
id: string;
}

export interface PokemonEvolutionChainParamsProps {
id: string;
}
16 changes: 16 additions & 0 deletions apps/api/src/api/v1/cart/routes/cart.route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import express from 'express';

import {
clearCartController,
getCartController,
updateCartController,
} from '../controllers/cart.controller';

const cartRoute = express.Router();

cartRoute.get('/', getCartController);
cartRoute.put('/update/:id', updateCartController);
cartRoute.put('/clear', clearCartController);
// cartRoute.delete('/item/:id', clearCartController);

export { cartRoute };
82 changes: 82 additions & 0 deletions apps/api/src/api/v1/cart/services/cart.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/* 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';

interface CartDataProps {
id: string;
name: string;
price: number;
quantity: number;
image: string;
isLegendary: boolean;
isMythical: boolean;
}

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

for (let loop = 0; loop < cartLength; loop++) {
if (cartData[loop]?.id == id) {
key = loop;
break;
}
}
return key;
};

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

const getSpeciesDetail = async (id: string) => {
return Promise.all([
await getPokemonSpeciesService({ id }).catch(() => 'err'),
await getPokemonDetailService({ id }).catch(() => 'err'),
]).then((data) => {
if (data[0] === 'err' || data[1] === 'err') {
return 'err';
}
return { ...data[0], ...data[1] };
});
};

const updateCartService = async (payload) => {
const currentCartData: any = await getCartDataCallUtil();
const doesItemExistKey = doesItemExistKeyFn(currentCartData, payload?.id);
const finalRes = currentCartData;

if (doesItemExistKey !== null) {
const currentObj = currentCartData[doesItemExistKey];
currentObj.quantity = currentObj.quantity + 1;

return currentObj;
}

const additionalData = await getSpeciesDetail(payload?.id);

const finalPayload = {
id: payload?.id,
name: additionalData?.name,
price: 500,
quantity: 1,
image: additionalData?.sprites?.other?.['official-artwork']?.front_default,
isLegendary: additionalData?.is_legendary,
isMythical: additionalData?.is_mythical,
};
finalRes.push(finalPayload);

return finalPayload;
};

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

export { getCartService, updateCartService, clearCartService };
1 change: 1 addition & 0 deletions apps/api/src/api/v1/pokemon/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './routes/pokemon.route';
export * from './services/pokemon.species.service';
2 changes: 2 additions & 0 deletions apps/api/src/main.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import cors from 'cors';
import express from 'express';

import { cartRoute } from './api/v1/cart';
import { pokemonRoute } from './api/v1/pokemon';
import { cacheMiddleware } from './middleware/cache.middleware';

Expand All @@ -15,6 +16,7 @@ app.use(cacheMiddleware);

// Using Routes
app.use('/api/pokemon', pokemonRoute);
app.use('/api/cart', cartRoute);

// Error Handling Middleware
app.use((err, req, res, next) => {
Expand Down
9 changes: 7 additions & 2 deletions apps/api/src/middleware/cache.middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,25 @@ import NodeCache from 'node-cache';
const cache = new NodeCache({ stdTTL: 100, checkperiod: 120 });

const cacheMiddleware = (req, res, next) => {
const noCaching = req.originalUrl.includes('cart');
const key = req.originalUrl;
const cachedResponse = cache.get(key);
const cachedResponse = !noCaching ? cache.get(key) : null;

if (cachedResponse) {
console.log('cached');
res.send(cachedResponse);
} else {
res.sendResponse = res.send;
res.send = (body) => {
cache.set(key, body);
if (!noCaching) {
cache.set(key, body);
}
res.sendResponse(body);
};
next();
}
};

// const internalCacheMiddleware = () => {};

export { cacheMiddleware };
12 changes: 3 additions & 9 deletions libs/features/src/lib/cart/cart.modal/cart.modal.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
import { ReactElement } from 'react';

import {
UiElementLayout,
UiIcon,
IconTypeEnum,
UiTypography,
UiModal,
ModalAlignmentEnum,
} from '@pokemon-pet-shop/ui';
import { AlignmentEnum } from '@pokemon-pet-shop/typing';
import { UiElementLayout, UiIcon, IconTypeEnum, UiTypography, UiModal } from '@pokemon-pet-shop/ui';

import { CartModalProps } from './cart.modal.interface';
import styles from './cart.modal.module.css';
Expand All @@ -17,7 +11,7 @@ const CartModal = ({ isModalShown = false }: CartModalProps): ReactElement => {
<UiModal
isModalShown={isModalShown}
classNameModal={styles.modal}
modalAlignment={ModalAlignmentEnum.RIGHT}
modalAlignment={AlignmentEnum.RIGHT}
>
<UiElementLayout className={styles.dropdownTop}>
<UiElementLayout className={styles.dropdownHeadline}>
Expand Down
4 changes: 2 additions & 2 deletions libs/features/src/lib/navigation/nav.mobile/nav.mobile.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { ReactElement } from 'react';

import { AlignmentEnum } from '@pokemon-pet-shop/typing';
import {
UiElementLayout,
UiIcon,
IconTypeEnum,
UiTypography,
UiModal,
ModalAlignmentEnum,
UiSwitch,
} from '@pokemon-pet-shop/ui';

Expand All @@ -18,7 +18,7 @@ const NavMobileModal = ({ isModalShown = false }: NavMobileModalProps): ReactEle
<UiModal
isModalShown={isModalShown}
classNameModal={styles.modal}
modalAlignment={ModalAlignmentEnum.LEFT}
modalAlignment={AlignmentEnum.LEFT}
>
<UiElementLayout className={styles.dropdownTop}>
<UiElementLayout className={styles.dropdownHeadline}>
Expand Down
6 changes: 2 additions & 4 deletions libs/features/src/lib/pokemon/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,2 @@
import UiPokemonDetailModal from './pokemon.detail.modal/pokemon.detail.modal.view';
import UiPokemonList from './pokemon.list/pokemon.list.view';

export { UiPokemonList, UiPokemonDetailModal };
export * from './pokemon.list';
export * from './pokemon.detail.modal';
11 changes: 6 additions & 5 deletions libs/features/src/lib/pokemon/pokemon.card/pokemon.card.view.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { memo, ReactElement } from 'react';

import { ModalHeadlineTypeEnum, useModalStore } from '@pokemon-pet-shop/store';
import { PokemonDetailAbilityObj } from '@pokemon-pet-shop/typing';
import { AlignmentEnum, PokemonDetailAbilityObj } from '@pokemon-pet-shop/typing';
import {
UiElementLayout,
UiImage,
Expand All @@ -11,9 +11,8 @@ import {
UiButton,
UiCard,
mobSrcTypeEnum,
ModalAlignmentEnum,
} from '@pokemon-pet-shop/ui';
import { classNamesUtil } from '@pokemon-pet-shop/utils';
import { classNamesUtil, noopUtil } from '@pokemon-pet-shop/utils';

import { UiPokemonDetailModal } from '..';
import { UiPokemonAbilityName } from '../components/pokemon.ability.name';
Expand All @@ -36,9 +35,11 @@ const PokemonCard = ({ data = {} }: CardProps): ReactElement => {
classNameModal: '',
isModalShown: false,
headlineType: ModalHeadlineTypeEnum.ABSOLUTE,
modalAlignment: ModalAlignmentEnum.CENTER,
modalAlignment: AlignmentEnum.CENTER,
},
onCallback: () => {
noopUtil();
},
onCallback: () => {},
});
};

Expand Down
3 changes: 3 additions & 0 deletions libs/features/src/lib/pokemon/pokemon.detail.modal/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import UiPokemonDetailModal from './pokemon.detail.modal.view';

export { UiPokemonDetailModal };
Loading

0 comments on commit efabf05

Please sign in to comment.