You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

cart-context.tsx 4.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. import { createContext, useContext, useState, FC, ReactNode } from 'react';
  2. import { getStorage, setStorage } from '../utils/helpers/storage';
  3. import { ProductData } from '../utils/interface/productInterface';
  4. export interface ICart {
  5. product: ProductData;
  6. quantity: number;
  7. }
  8. interface IStorage {
  9. cartStorage: ICart[];
  10. totalPrice: number;
  11. totalQuantity: number;
  12. }
  13. interface IStorageDispatch {
  14. addCartValue: (x: ProductData, y: number) => void;
  15. clearCart: () => void;
  16. removeCartValue: (x: string) => void;
  17. updateItemQuantity: (x: string, y: number) => void;
  18. }
  19. interface Props {
  20. children: ReactNode;
  21. }
  22. const StorageContext = createContext<IStorage>({
  23. cartStorage: [],
  24. totalPrice: 0,
  25. totalQuantity: 0,
  26. });
  27. const StorageDispatchContext = createContext<IStorageDispatch>({
  28. addCartValue: (product: ProductData, quantity: number) => {},
  29. clearCart: () => {},
  30. removeCartValue: (productId: string) => {},
  31. updateItemQuantity: (productId: string, quantity: number) => {},
  32. });
  33. export const useStore = () => {
  34. return useContext(StorageContext);
  35. };
  36. export const useStoreUpdate = () => {
  37. return useContext(StorageDispatchContext);
  38. };
  39. const useStorage = () => {
  40. const CART_KEY = 'cart-products';
  41. const [cartStorage, setCartStorage] = useState<ICart[]>(getStorage(CART_KEY));
  42. const [totalPrice, setTotalPrice] = useState<number>(() => {
  43. const cart: ICart[] = getStorage(CART_KEY);
  44. if (cart && cart.length) {
  45. return cart
  46. .map((entry) => entry?.product.price * entry?.quantity)
  47. .reduce((accum: number, curValue: number) => accum + curValue);
  48. } else {
  49. return 0;
  50. }
  51. });
  52. const [totalQuantity, setTotalQuantity] = useState<number>(() => {
  53. const cart = getStorage(CART_KEY);
  54. if (cart && cart.length) {
  55. return cart.length;
  56. } else {
  57. return 0;
  58. }
  59. });
  60. const addCartValue = (product: ProductData, quantity: number) => {
  61. const items: ICart[] = getStorage(CART_KEY);
  62. if (!items) {
  63. setStorage(CART_KEY, { product, quantity });
  64. } else {
  65. const isItemDuplicate = items.some(
  66. (item) => item.product.customID === product.customID
  67. );
  68. if (!isItemDuplicate) {
  69. items.push({ product, quantity });
  70. setTotalQuantity((prevState: number) => prevState + 1);
  71. setStorage(CART_KEY, items);
  72. } else {
  73. return;
  74. }
  75. }
  76. const newTotalPrice = items
  77. .map((entry) => entry?.product.price * entry?.quantity)
  78. .reduce((accum, curValue) => accum + curValue);
  79. setTotalPrice(newTotalPrice);
  80. setCartStorage(items);
  81. };
  82. const updateItemQuantity = (productId: string, quantity: number) => {
  83. if (quantity < 0) return;
  84. const items: ICart[] = getStorage(CART_KEY);
  85. let updatedItems = items;
  86. if (items) {
  87. updatedItems = items.map((entry) => {
  88. if (entry?.product.customID === productId) {
  89. console.log('true');
  90. entry.quantity = quantity;
  91. }
  92. return entry;
  93. });
  94. setStorage(CART_KEY, updatedItems);
  95. }
  96. const newTotalPrice = updatedItems
  97. .map((entry) => entry?.product.price * entry?.quantity)
  98. .reduce((accum, curValue) => accum + curValue);
  99. setTotalPrice(newTotalPrice);
  100. setCartStorage(updatedItems);
  101. };
  102. const clearCart = () => {
  103. setStorage(CART_KEY, {});
  104. setTotalQuantity(0);
  105. setTotalPrice(0);
  106. setCartStorage([]);
  107. };
  108. const removeCartValue = (productId: string) => {
  109. const items: ICart[] = getStorage(CART_KEY);
  110. const newStorage = items?.filter(
  111. (item) => item.product.customID !== productId
  112. );
  113. if (newStorage.length === 0) {
  114. setTotalPrice(0);
  115. } else {
  116. const newTotalPrice = newStorage
  117. .map((entry) => entry?.product.price * entry?.quantity)
  118. .reduce((accum, curValue) => accum + curValue);
  119. setTotalPrice(newTotalPrice);
  120. }
  121. setTotalQuantity((prevState: number) => prevState - 1);
  122. setStorage(CART_KEY, newStorage);
  123. setCartStorage(newStorage);
  124. };
  125. return {
  126. addCartValue,
  127. cartStorage,
  128. totalPrice,
  129. totalQuantity,
  130. clearCart,
  131. removeCartValue,
  132. setCartStorage,
  133. updateItemQuantity,
  134. };
  135. };
  136. const StorageProvider: FC<Props> = ({ children }) => {
  137. const {
  138. cartStorage,
  139. totalPrice,
  140. totalQuantity,
  141. addCartValue,
  142. clearCart,
  143. setCartStorage,
  144. removeCartValue,
  145. updateItemQuantity,
  146. } = useStorage();
  147. return (
  148. <StorageContext.Provider value={{ cartStorage, totalPrice, totalQuantity }}>
  149. <StorageDispatchContext.Provider
  150. value={{
  151. addCartValue,
  152. clearCart,
  153. removeCartValue,
  154. updateItemQuantity,
  155. }}
  156. >
  157. {children}
  158. </StorageDispatchContext.Provider>
  159. </StorageContext.Provider>
  160. );
  161. };
  162. export default StorageProvider;