Skip to content

Commit

Permalink
Now load more button adds more pokemon • working on pricing structure…
Browse files Browse the repository at this point in the history
… • Starting work on theming
  • Loading branch information
AnselmMarie committed Sep 10, 2024
1 parent 193177a commit 71d3800
Show file tree
Hide file tree
Showing 35 changed files with 388 additions and 159 deletions.
1 change: 0 additions & 1 deletion apps/api/src/api/v1/cart/database/cart.database.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ export const getCartDataCall = async (): Promise<CartDataApi> => {
export const updateCartDataCall = async (data): Promise<CartDataApi> => {
return new Promise((resolve) => {
setTimeout(() => {
console.log('data', data);
cartDatabase.data = data.data;
cartDatabase.total = data.total;
cartDatabase.counter = data.counter;
Expand Down
52 changes: 40 additions & 12 deletions apps/api/src/api/v1/cart/services/cart.service.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import { CartApiPayload, CartDataApi } from '@pokemon-pet-shop/typing';
import { CartApiPayload, CartDataApi, PricingApi } from '@pokemon-pet-shop/typing';
import { pricingFormatUtil } from '@pokemon-pet-shop/utils';
import { clone } from 'lodash';

import {
Expand All @@ -8,6 +9,8 @@ import {
} from '../../../../utils/err.format.response.util';
import { getPokemonSpeciesService } from '../../pokemon';
import { getPokemonDetailService } from '../../pokemon/services/pokemon.detail.service';
import { getPokemonEvolutionChainService } from '../../pokemon/services/pokemon.evolution.chain.service';
import { getPricingService } from '../../pricing/services/pricing.service';
import { getCartDataCall, updateCartDataCall } from '../database/cart.database';

const doesItemExistKeyFn = (data, id) => {
Expand Down Expand Up @@ -58,6 +61,7 @@ const updateCartItemService = async (payload: CartApiPayload) => {
})
);
const data = clone(currentCartData.data);

const { key, counter, total } = doesItemExistKeyFn(data, payload?.id);
const currentObj = data[key];

Expand All @@ -69,10 +73,38 @@ const updateCartItemService = async (payload: CartApiPayload) => {
});
}

const pricingData: PricingApi = await getPricingService().catch(() => {
throw errFormat500ResponseUtil();
});
const speciesData = await getSpeciesDetail(payload?.id).catch(() => {
throw errFormat500ResponseUtil();
});

const evolutionChainSplit = speciesData?.evolution_chain?.url?.split('/');

const evolutionData = await getPokemonEvolutionChainService({
id: evolutionChainSplit[evolutionChainSplit.length - 2],
}).catch(() => {
throw errFormat500ResponseUtil();
});

const pokemonPrice = Number(
pricingFormatUtil(
{
name: speciesData?.name,
isLegendary: speciesData?.is_legendary,
isMythical: speciesData?.is_mythical,
chainData: evolutionData?.chain,
},
pricingData,
true
)
);

if (key !== null) {
currentObj.quantity = payload.addToCart ? currentObj.quantity + 1 : currentObj.quantity - 1;
currentCartData.counter = payload.addToCart ? counter + 1 : counter - 1;
currentCartData.total = payload.addToCart ? total + 500 : total - 500;
currentCartData.total = payload.addToCart ? total + pokemonPrice : total - pokemonPrice;

await updateCartDataCall(currentCartData).catch(() => {
throw errFormat500ResponseUtil();
Expand All @@ -89,21 +121,17 @@ const updateCartItemService = async (payload: CartApiPayload) => {
});
}

const additionalData = await getSpeciesDetail(payload?.id).catch(() => {
throw errFormat500ResponseUtil();
});

const finalPayload = {
id: payload?.id,
name: additionalData?.name,
price: 500,
name: speciesData?.name,
price: pokemonPrice,
quantity: 1,
image: additionalData?.sprites?.other?.['official-artwork']?.front_default,
isLegendary: additionalData?.is_legendary,
isMythical: additionalData?.is_mythical,
image: speciesData?.sprites?.other?.['official-artwork']?.front_default,
isLegendary: speciesData?.is_legendary,
isMythical: speciesData?.is_mythical,
};
currentCartData.counter = counter + 1;
currentCartData.total = total + 500;
currentCartData.total = total + pokemonPrice;

currentCartData.data.push(finalPayload);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
errFormat500ResponseUtil,
errFormatResponseUtil,
} from '../../../../utils/err.format.response.util';
import { DEFAULT_LIMIT } from '../const/default.prop.const';
import { DEFAULT_LIMIT, DEFAULT_OFFSET } from '../const/default.prop.const';
import { PokemonListQueryProps } from '../interface/pokemon.interface';
import { getPokemonDetailService } from '../services/pokemon.detail.service';
import { getPokemonListService } from '../services/pokemon.list.service';
Expand All @@ -24,16 +24,18 @@ const getPokemonListController = async (
) => {
try {
const limitQuery = req?.query?.limit || DEFAULT_LIMIT;
const offset = req?.query?.offset || DEFAULT_OFFSET;

const pokemonList = await getPokemonListService({
offset: req?.query?.offset,
offset,
limit: limitQuery,
}).catch(() => {
throw errFormat500ResponseUtil();
});

const limitNumberQuery = Number(limitQuery) + 1;
const limitNumberQuery = Number(limitQuery) + 1 + Number(offset);
const detailPromises = [];
for (let loop = 0; loop < limitNumberQuery; loop++) {
for (let loop = Number(offset); loop < limitNumberQuery; loop++) {
const id = String(loop);
detailPromises.push(
await getPokemonDetailService({
Expand Down
4 changes: 2 additions & 2 deletions apps/api/src/api/v1/pricing/database/pricing.database.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { PricingApi } from '@pokemon-pet-shop/typing';

export const pricingDatabase = {
stages: { '1': { price: 49999 }, '2': { price: 99999 }, '3': { price: 149999 } },
legendary: { price: 150000 },
mythical: { price: 150000 },
legendary: { price: 15000000 },
mythical: { price: 15000000 },
};

export const getPricingDataCall = async (): Promise<PricingApi> => {
Expand Down
5 changes: 0 additions & 5 deletions apps/mobile-app/src/app/homepage.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,6 @@ import { StyleSheet } from 'react-native';

export const styles = StyleSheet.create({
contentWrapper: {
display: 'flex',
alignContent: 'space-between',
gap: 25,
flexWrap: 'wrap',
marginTop: 25,
justifyContent: 'center',
},
});
1 change: 0 additions & 1 deletion apps/mobile-app/src/app/homepage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { ReactElement } from 'react';

import { UiPokemonList } from '@pokemon-pet-shop/features';
import { UiContainer, UiElementLayout, UiTypography } from '@pokemon-pet-shop/ui';
import { Text } from 'react-native';

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

Expand Down
5 changes: 0 additions & 5 deletions apps/web-app/src/pages/homepage/homepage.module.css
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
.contentWrapper {
display: flex;
align-content: space-between;
gap: 25px;
flex-wrap: wrap;
margin-top: 25px;
justify-content: center;
}
13 changes: 12 additions & 1 deletion apps/web-app/src/styles/styles.css
Original file line number Diff line number Diff line change
@@ -1 +1,12 @@
/* You can add global styles to this file, and also import other style files */
:root,
html[data-theme='light'] {
--background-color: #fff;
--text-color: #121416d8;
--link-color: #543fd7;
}

html[data-theme='dark'] {
--background-color: #212a2e;
--text-color: #f7f8f8;
--link-color: #828fff;
}
5 changes: 3 additions & 2 deletions libs/features/src/lib/cart/cart.modal/cart.modal.view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
mobSrcTypeEnum,
TypographyTypeEnum,
} from '@pokemon-pet-shop/ui';
import { pricingFormatUSD } from '@pokemon-pet-shop/utils';

import styles from './cart.modal.module.css';
import useCartModalLogic from './use.cart.modal.logic';
Expand Down Expand Up @@ -39,7 +40,7 @@ const CartModal = (): ReactElement => {
{el?.name}
</UiTypography>
<UiTypography typographyType={TypographyTypeEnum.SPAN} className={styles.price}>
{el?.price}
{pricingFormatUSD(el?.price)}
</UiTypography>
<UiElementLayout>
<UiIcon
Expand Down Expand Up @@ -67,7 +68,7 @@ const CartModal = (): ReactElement => {
</UiElementLayout>
<UiElementLayout className={styles.totalContent}>
<UiTypography>Total</UiTypography>
<UiTypography>{data?.total}</UiTypography>
<UiTypography>{pricingFormatUSD(data?.total)}</UiTypography>
</UiElementLayout>
</UiElementLayout>
);
Expand Down
4 changes: 2 additions & 2 deletions libs/features/src/lib/navigation/header/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
UiIcon,
IconTypeEnum,
UiInput,
UiSwitch,
UiSwitchTheme,
UiTypography,
TypographyTypeEnum,
UiContainer,
Expand Down Expand Up @@ -59,7 +59,7 @@ const Header = () => {
</UiElementLayout>

<UiHideInMobile>
<UiSwitch
<UiSwitchTheme
className={styles.switchTheme}
iconLeft={IconTypeEnum.ICON_SUN}
iconRight={IconTypeEnum.ICON_MOON}
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
Expand Up @@ -7,7 +7,7 @@ import {
IconTypeEnum,
UiTypography,
UiModal,
UiSwitch,
UiSwitchTheme,
} from '@pokemon-pet-shop/ui';

import { NavMobileModalProps } from './nav.mobile.interface';
Expand All @@ -27,7 +27,7 @@ const NavMobileModal = ({ isModalShown = false }: NavMobileModalProps): ReactEle
</UiElementLayout>
</UiElementLayout>
<UiElementLayout className={styles.dropdownBtm}>
<UiSwitch
<UiSwitchTheme
className={styles.switchTheme}
iconLeft={IconTypeEnum.ICON_SUN}
iconRight={IconTypeEnum.ICON_MOON}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.cardListWrapper {
display: flex;
align-content: space-between;
gap: 25px;
flex-wrap: wrap;
justify-content: center;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { StyleSheet } from 'react-native';

export const styles = StyleSheet.create({
cardListWrapper: {
display: 'flex',
alignContent: 'space-between',
gap: 25,
flexWrap: 'wrap',
justifyContent: 'center',
},
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import styles from './pokemon.list.module.css';

export { styles };
38 changes: 33 additions & 5 deletions libs/features/src/lib/pokemon/pokemon.list/pokemon.list.view.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,46 @@
import { memo, ReactElement } from 'react';
import { Fragment, memo, ReactElement } from 'react';

import { PokemonListApi } from '@pokemon-pet-shop/typing';
import { UiButton, UiElementLayout } from '@pokemon-pet-shop/ui';

import { UiPokemonCard } from '../pokemon.card';

import { styles } from './pokemon.list.module';
import usePokemonList from './use.pokemon.list.logic';

/** Use tanstack virtual for long lists -> https://tanstack.com/virtual/latest/docs/introduction */
const PokemonList = (): ReactElement => {
const { data, isError, isLoading, isFetching } = usePokemonList();
const { data, isError, isLoading, isFetching, isFetchingNextPage, hasNextPage, onFetchNextPage } =
usePokemonList();

return (data || []).map((el: PokemonListApi): ReactElement => {
return <UiPokemonCard key={el?.name} data={el} />;
});
return (
<>
<UiElementLayout className={styles.cardListWrapper}>
{(data || []).map((arr: PokemonListApi[], i: number): ReactElement => {
return (
<Fragment key={i}>
{arr.map((el: PokemonListApi) => (
<UiPokemonCard key={el?.name} data={el} />
))}
</Fragment>
);
})}
</UiElementLayout>
<UiButton
isDisabled={!hasNextPage || isFetchingNextPage}
text={
isFetchingNextPage
? 'Loading more...'
: hasNextPage
? 'Load More'
: 'Nothing more to load'
}
onClick={() => {
onFetchNextPage((old: number) => old + 1);
}}
/>
</>
);
};

export default memo(PokemonList);
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,33 @@ interface PokemonListReturn {
isError: boolean;
isLoading: boolean;
isFetching: boolean;
isPlaceholderData?: boolean;
isFetchingNextPage?: boolean;
hasNextPage?: boolean;
onFetchNextPage: any;
}

const usePokemonList = (): PokemonListReturn => {
const { data, isError, isLoading, isFetching } = useGetPokemonList();
const {
data,
isError,
isLoading,
isFetching,
isPlaceholderData,
isFetchingNextPage,
hasNextPage,
fetchNextPage,
} = useGetPokemonList();

return {
data: data?.pages[0],
data: data?.pages,
isError,
isLoading,
isFetching,
isPlaceholderData,
isFetchingNextPage,
hasNextPage,
onFetchNextPage: fetchNextPage,
};
};

Expand Down
2 changes: 1 addition & 1 deletion libs/services/src/lib/pokemon/api.pokemon.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@ export const getPokemonList = async ({ pageParam }: { pageParam: number }) => {
).data;
};

export const getPokemonSpecies = async (id: number) => {
export const getPokemonSpecies = async (id: string | undefined) => {
return (await axiosInstance.get<PokemonSpeciesApi>(`pokemon/species/${id}`)).data;
};
1 change: 0 additions & 1 deletion libs/store/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
export * from './lib/theme.store';
export * from './lib/modal.store';
export * from './lib/cart.store';
export * from './lib/loading.submit.store';
Loading

0 comments on commit 71d3800

Please sign in to comment.