diff --git a/e-commerce-app/src/App.tsx b/e-commerce-app/src/App.tsx index bab03eb..737c978 100644 --- a/e-commerce-app/src/App.tsx +++ b/e-commerce-app/src/App.tsx @@ -30,9 +30,9 @@ export const App = () => { getDetails(data.access_token).then((res) => { if ('data' in res) { dispatch(setAuth({ email: res.data.email })); + dispatch(setLogIn()); } }); - dispatch(setLogIn()); } }, [isSuccess, data]); diff --git a/e-commerce-app/src/api/cartApi.ts b/e-commerce-app/src/api/cartApi.ts new file mode 100644 index 0000000..0b548b5 --- /dev/null +++ b/e-commerce-app/src/api/cartApi.ts @@ -0,0 +1,84 @@ +import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'; +import { ICartApiResponse } from '../types/slicesTypes/cart'; +import { IUpdateCartApiObjectRequest } from '../types/slicesTypes/cart/updateCartApiTypes'; +import { RootStateType } from '../store/store'; + +export const cartApi = createApi({ + reducerPath: 'cartApi', + baseQuery: fetchBaseQuery({ + baseUrl: `${process.env.REACT_APP_CTP_API_URL}/${process.env.REACT_APP_CTP_PROJECT_KEY}`, + }), + tagTypes: ['activeCart'], + endpoints: (build) => ({ + getMyActiveCart: build.query({ + query(token: string) { + return { + url: '/me/active-cart', + method: 'GET', + headers: { + Authorization: `Bearer ${token}`, + }, + }; + }, + providesTags: ['activeCart'], + async onQueryStarted(token, { queryFulfilled, dispatch }) { + try { + queryFulfilled.catch(() => dispatch(cartApi.endpoints.createCart.initiate(token))); + } catch (e) { + dispatch(cartApi.endpoints.createCart.initiate(token)); + } + }, + }), + createCart: build.mutation({ + query(token: string) { + return { + url: '/me/carts', + method: 'POST', + headers: { + Authorization: `Bearer ${token}`, + 'Content-Type': 'application/json', + }, + body: { + currency: 'EUR', + }, + }; + }, + invalidatesTags: ['activeCart'], + }), + updateCart: build.mutation({ + query(queryObj: IUpdateCartApiObjectRequest) { + return { + url: `/me/carts/${queryObj.cartId}`, + method: 'POST', + headers: { + Authorization: `Bearer ${queryObj.token}`, + 'Content-Type': 'application/json', + }, + body: queryObj.data, + }; + }, + invalidatesTags: ['activeCart'], + }), + deleteCart: build.mutation({ + query(queryObj: { cartId: string; token: string }) { + return { + url: `/me/carts/${queryObj.cartId}`, + method: 'DELETE', + headers: { + Authorization: `Bearer ${queryObj.token}`, + }, + }; + }, + }), + }), +}); + +export const { useLazyGetMyActiveCartQuery, useCreateCartMutation, useUpdateCartMutation } = + cartApi; + +export const selectCart = (state: RootStateType) => + cartApi.endpoints.getMyActiveCart.select(state.user.access_token as string)(state).data; +export const findProductInCart = (state: RootStateType, productId: string) => + cartApi.endpoints.getMyActiveCart + .select(state.user.access_token as string)(state) + .data?.lineItems.find((item) => item.productId === productId); diff --git a/e-commerce-app/src/api/myCustomerApi.ts b/e-commerce-app/src/api/myCustomerApi.ts index b54d1da..f896050 100644 --- a/e-commerce-app/src/api/myCustomerApi.ts +++ b/e-commerce-app/src/api/myCustomerApi.ts @@ -1,7 +1,7 @@ import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'; import { + IAuthenticateMyCustomer, IMyCustomerBaseResponse, - IMyCustomerLoginRequest, ISignUpMyCustomer, } from '../types/slicesTypes/myCustomerApiSliceTypes'; import { @@ -16,16 +16,14 @@ export const myCustomerApi = createApi({ }), tagTypes: ['myCustomerDetails'], endpoints: (build) => ({ - authenticateMyCustomer: build.mutation({ - query(customerData: IMyCustomerLoginRequest) { + authenticateMyCustomer: build.mutation({ + query(queryObj) { return { url: '/login', method: 'POST', - body: JSON.stringify(customerData), + body: JSON.stringify(queryObj.customerData), headers: { - Authorization: `Bearer ${btoa( - process.env.REACT_APP_CTP_CLIENT_ID + ':' + process.env.REACT_APP_CTP_CLIENT_SECRET, - )}`, + Authorization: `Bearer ${queryObj.token}`, 'Content-Type': 'application/x-www-form-urlencoded', }, }; diff --git a/e-commerce-app/src/components/ProductCard/ProductCard.tsx b/e-commerce-app/src/components/ProductCard/ProductCard.tsx index c4eba6e..d2fc4fa 100644 --- a/e-commerce-app/src/components/ProductCard/ProductCard.tsx +++ b/e-commerce-app/src/components/ProductCard/ProductCard.tsx @@ -1,11 +1,12 @@ import { FC, useEffect, useState } from 'react'; import styles from './ProductCard.module.scss'; -import { Box, Typography, Button, CardMedia, CardContent, CardActions, Card } from '@mui/material'; +import { Box, Typography, CardMedia, CardContent, CardActions, Card } from '@mui/material'; import { useNavigate } from 'react-router-dom'; import { IProductApiResponse } from '../../types/slicesTypes/productsApiTypes'; import { getTaxes } from '../../store/slices/taxesSlice'; import { useAppSelector } from '../../store/hooks'; import { ITaxApiResponse } from '../../types/slicesTypes/taxApiTypes'; +import CartAddLineItem from '../../requestsComponents/CartAddLineItem/CartAddLineItem'; interface ICardProps { item: IProductApiResponse; @@ -107,9 +108,7 @@ export const ProductCard: FC = ({ item }) => { )} - + ); diff --git a/e-commerce-app/src/pages/LoginPage/LoginPage.tsx b/e-commerce-app/src/pages/LoginPage/LoginPage.tsx index ae6225b..9e1ecd0 100644 --- a/e-commerce-app/src/pages/LoginPage/LoginPage.tsx +++ b/e-commerce-app/src/pages/LoginPage/LoginPage.tsx @@ -19,6 +19,7 @@ import VisibilityIcon from '@mui/icons-material/Visibility'; import VisibilityOffIcon from '@mui/icons-material/VisibilityOff'; import { useLoginUserMutation } from '../../api/authApi'; import { + getAccessToken, getLoggedIn, isRememberedMe, setAuth, @@ -30,6 +31,8 @@ import { IResponseError } from '../../types/AuthTypes'; import { ILoginFormData } from '../../interfaces/ILoginFormData'; import { useAppDispatch, useAppSelector } from '../../store/hooks'; import { useLocalToken } from '../../hooks/useLocalToken'; +import { useAuthenticateMyCustomerMutation } from '../../api/myCustomerApi'; +import { IAuthenticateMyCustomer } from '../../types/slicesTypes/myCustomerApiSliceTypes'; const defaultFormState: ILoginFormData = { email: '', @@ -48,6 +51,7 @@ export const LoginPage: FC = () => { const navigate = useNavigate(); const from = '/'; + const accessToken = useAppSelector(getAccessToken) as string; const isLoggedIn = useAppSelector(getLoggedIn); const isRememberedUser = useAppSelector(isRememberedMe); @@ -68,6 +72,7 @@ export const LoginPage: FC = () => { }); const [loginUser, { isSuccess, error: errorApi, isError, data }] = useLoginUserMutation(); + const [authenticateUser] = useAuthenticateMyCustomerMutation(); const { register, @@ -155,7 +160,16 @@ export const LoginPage: FC = () => { }), ); try { - loginUser({ email: data.email, password: data.password }); + const authObj: IAuthenticateMyCustomer = { + token: accessToken, + customerData: { + email: data.email, + password: data.password, + }, + }; + authenticateUser(authObj).then(() => + loginUser({ email: data.email, password: data.password }), + ); } catch { console.log('er'); } diff --git a/e-commerce-app/src/pages/LogoutPage/LogoutPage.tsx b/e-commerce-app/src/pages/LogoutPage/LogoutPage.tsx index 24c4168..5837377 100644 --- a/e-commerce-app/src/pages/LogoutPage/LogoutPage.tsx +++ b/e-commerce-app/src/pages/LogoutPage/LogoutPage.tsx @@ -5,6 +5,7 @@ import { useNavigate } from 'react-router-dom'; import { CircularProgress } from '@mui/material'; import { useLocalToken } from '../../hooks/useLocalToken'; import { useLogoutUserMutation } from '../../api/authApi'; +import { resetCart } from '../../store/slices/cartSlice'; export const LogoutPage = (): JSX.Element => { const navigate = useNavigate(); @@ -28,6 +29,7 @@ export const LogoutPage = (): JSX.Element => { useEffect(() => { dispatch(setLogOut()); delTokenFromStorage(); + dispatch(resetCart()); }, [isSuccess, isError]); useEffect(() => { diff --git a/e-commerce-app/src/requestsComponents/CartAddLineItem/CartAddLineItem.tsx b/e-commerce-app/src/requestsComponents/CartAddLineItem/CartAddLineItem.tsx new file mode 100644 index 0000000..192a6f9 --- /dev/null +++ b/e-commerce-app/src/requestsComponents/CartAddLineItem/CartAddLineItem.tsx @@ -0,0 +1,75 @@ +import { FC, JSX } from 'react'; +import { IUpdateCartApiObjectRequest } from '../../types/slicesTypes/cart/updateCartApiTypes'; +import { useAppSelector } from '../../store/hooks'; +import { getAccessToken } from '../../store/slices/userSlice'; +import { findProductInCart, selectCart, useUpdateCartMutation } from '../../api/cartApi'; +import { + IAddLineItemCart, + ICartApiResponse, + IRemoveLineItemCart, +} from '../../types/slicesTypes/cart'; +import { ButtonProps } from '@mui/material'; +import Button from '@mui/material/Button'; +import CartQuery from '../CartQuery/CartQuery'; +interface ICartAddLineItemProps { + children?: string | JSX.Element | JSX.Element[] | React.ReactNode; + productId: string; + variantId?: number; + props?: ButtonProps; +} +const CartAddLineItem: FC = ({ + children, + productId, + variantId, + props, +}): JSX.Element => { + const accessToken = useAppSelector(getAccessToken) as string; + const cartId = (useAppSelector(selectCart) as ICartApiResponse)?.id as string; + const cartVersion = (useAppSelector(selectCart) as ICartApiResponse)?.version as number; + const productInCart = useAppSelector((state) => findProductInCart(state, productId)); + + const [updateCart, { isLoading }] = useUpdateCartMutation(); + + if (!cartId || !cartVersion) { + return ; + } + + const toggleLineItem = () => { + if (productInCart) { + const actionObject: IRemoveLineItemCart = { + action: 'removeLineItem', + lineItemId: productInCart.id, + quantity: productInCart.quantity, + }; + const queryObj: IUpdateCartApiObjectRequest = { + cartId, + token: accessToken, + data: { version: cartVersion, actions: [actionObject] }, + }; + updateCart(queryObj).then((a) => console.log(a)); + } else { + const actionObject: IAddLineItemCart = { + action: 'addLineItem', + productId, + quantity: 1, + }; + if (variantId) { + actionObject.variantId = variantId; + } + const queryObj: IUpdateCartApiObjectRequest = { + cartId, + token: accessToken, + data: { version: cartVersion, actions: [actionObject] }, + }; + updateCart(queryObj).then((a) => console.log(a)); + } + }; + + return ( + + ); +}; +export default CartAddLineItem; diff --git a/e-commerce-app/src/requestsComponents/CartQuery/CartQuery.tsx b/e-commerce-app/src/requestsComponents/CartQuery/CartQuery.tsx new file mode 100644 index 0000000..5ff690f --- /dev/null +++ b/e-commerce-app/src/requestsComponents/CartQuery/CartQuery.tsx @@ -0,0 +1,36 @@ +import { FC, JSX, useEffect } from 'react'; +import { selectCart, useLazyGetMyActiveCartQuery } from '../../api/cartApi'; +import { useAppDispatch, useAppSelector } from '../../store/hooks'; +import { getAccessToken } from '../../store/slices/userSlice'; +import { setCart } from '../../store/slices/cartSlice'; +import LoadingProgress from '../../components/LoadingProgress/LoadingProgress'; + +interface ICartQueryProps { + children?: string | JSX.Element | JSX.Element[] | React.ReactNode; +} + +const CartQuery: FC = ({ children }): JSX.Element => { + const [getMyActiveCart, { isLoading, isFetching, isSuccess, data }] = + useLazyGetMyActiveCartQuery(); + const accessToken = useAppSelector(getAccessToken) as string; + const dispatch = useAppDispatch(); + const cart = useAppSelector(selectCart); + + useEffect(() => { + if (isSuccess && data) { + dispatch(setCart(data)); + } + }, [isSuccess, data]); + + useEffect(() => { + if (cart) return; + getMyActiveCart(accessToken); + }, [cart]); + + if (isLoading || isFetching) { + return ; + } + + return <>{children}; +}; +export default CartQuery; diff --git a/e-commerce-app/src/store/slices/cartSlice.ts b/e-commerce-app/src/store/slices/cartSlice.ts new file mode 100644 index 0000000..3f11106 --- /dev/null +++ b/e-commerce-app/src/store/slices/cartSlice.ts @@ -0,0 +1,22 @@ +import { ICartApiResponse, ICartFromSlice } from '../../types/slicesTypes/cart'; +import { createSlice, PayloadAction } from '@reduxjs/toolkit'; + +const initialState: ICartFromSlice = { + cart: null, +}; + +export const cartSlice = createSlice({ + initialState, + name: 'cartSlice', + reducers: { + resetCart: (state) => { + state.cart = null; + }, + setCart: (state, action: PayloadAction) => { + state.cart = action.payload; + }, + }, +}); + +export const CartReducer = cartSlice.reducer; +export const { resetCart, setCart } = cartSlice.actions; diff --git a/e-commerce-app/src/store/store.ts b/e-commerce-app/src/store/store.ts index 11c3f9c..de9b4d6 100644 --- a/e-commerce-app/src/store/store.ts +++ b/e-commerce-app/src/store/store.ts @@ -11,6 +11,8 @@ import { QueryParamsReducer } from './slices/queryParamsSlice'; import { taxApi } from '../api/taxApi'; import { TaxesReducer } from './slices/taxesSlice'; import { MyCustomerReducer } from './slices/myCustomerSlice'; +import { cartApi } from '../api/cartApi'; +import { CartReducer } from './slices/cartSlice'; export const store = configureStore({ reducer: { @@ -20,12 +22,14 @@ export const store = configureStore({ [categoriesApi.reducerPath]: categoriesApi.reducer, [taxApi.reducerPath]: taxApi.reducer, [productProjectionApi.reducerPath]: productProjectionApi.reducer, + [cartApi.reducerPath]: cartApi.reducer, user: UserReducer, categories: CategoriesReducer, products: ProductsReducer, queryParams: QueryParamsReducer, taxes: TaxesReducer, myCustomer: MyCustomerReducer, + cart: CartReducer, }, middleware: (getDefaultMiddleware) => getDefaultMiddleware({}).concat([ @@ -35,6 +39,7 @@ export const store = configureStore({ categoriesApi.middleware, productProjectionApi.middleware, taxApi.middleware, + cartApi.middleware, ]), }); diff --git a/e-commerce-app/src/types/customerCartTypes.ts b/e-commerce-app/src/types/customerCartTypes.ts index 0cb2f3d..e949432 100644 --- a/e-commerce-app/src/types/customerCartTypes.ts +++ b/e-commerce-app/src/types/customerCartTypes.ts @@ -1,4 +1,5 @@ -export interface IAnonymousCartSignIn { - id: string; - typeId: 'cart' | string; +import { IBaseIdTypeResponse } from './slicesTypes/baseApiResponsesTypes'; + +export interface IAnonymousCartSignIn extends IBaseIdTypeResponse { + typeId: 'cart'; } diff --git a/e-commerce-app/src/types/slicesTypes/baseApiResponsesTypes.ts b/e-commerce-app/src/types/slicesTypes/baseApiResponsesTypes.ts index 1d5f5ca..155143e 100644 --- a/e-commerce-app/src/types/slicesTypes/baseApiResponsesTypes.ts +++ b/e-commerce-app/src/types/slicesTypes/baseApiResponsesTypes.ts @@ -6,7 +6,7 @@ export interface IBaseGetAllQueryResponse { results: Array; } -export interface ICategoryTypeResponse { +export interface IBaseIdTypeResponse { id: string; typeId: string; } @@ -14,3 +14,13 @@ export interface ICategoryTypeResponse { export interface IMetaDescriptionProductResponse { en: string; } + +export interface IBaseCurrency { + currencyCode: string | 'EUR' | 'USD'; + centAmount: number; +} + +export interface ICurrencyResponse extends IBaseCurrency { + type: string | 'centPrecision'; + fractionDigits: number | 2; +} diff --git a/e-commerce-app/src/types/slicesTypes/cart/cartApiTypes.ts b/e-commerce-app/src/types/slicesTypes/cart/cartApiTypes.ts new file mode 100644 index 0000000..875bb5b --- /dev/null +++ b/e-commerce-app/src/types/slicesTypes/cart/cartApiTypes.ts @@ -0,0 +1,27 @@ +import { ICurrencyResponse } from '../baseApiResponsesTypes'; +import { ICartLineItem } from './cartLineItemsTypes'; + +export interface ICartApiResponse { + cartState: 'Active' | 'Merged' | 'Ordered' | 'Frozen'; + customerId?: string; + anonymousId?: string; + deleteDaysAfterLastModification: number; + directDiscounts: []; + discountCodes: []; + id: string; + inventoryMode: string; + itemShippingAddresses: []; + lastMessageSequenceNumber: number; + lineItems: ICartLineItem[]; + origin: string | 'Customer'; + refusedGifts: []; + shipping: []; + shippingMode: 'Single' | 'Multiple'; + taxCalculationMode: string | 'LineItemLevel'; + taxMode: string | 'Platform'; + taxRoundingMode: string | 'HalfEven'; + totalPrice: ICurrencyResponse; + totalLineItemQuantity: number; + type: string | 'Cart'; + version: number; +} diff --git a/e-commerce-app/src/types/slicesTypes/cart/cartLineItemsTypes.ts b/e-commerce-app/src/types/slicesTypes/cart/cartLineItemsTypes.ts new file mode 100644 index 0000000..9b24b42 --- /dev/null +++ b/e-commerce-app/src/types/slicesTypes/cart/cartLineItemsTypes.ts @@ -0,0 +1,51 @@ +import { IBaseIdTypeResponse } from '../baseApiResponsesTypes'; +import { IImageProductApiResponse, IPriceProductApiResponse } from '../productsApiTypes'; + +export interface IProductType extends IBaseIdTypeResponse { + typeId: 'product-type'; + version: number; +} + +export interface IAttributeCartLineItem { + name: string; + value: string; +} + +export interface ISubState extends IBaseIdTypeResponse { + typeId: 'state'; +} +export interface IStateLineItem { + quantity: number; + state: ISubState; +} + +export interface ICartLineItem { + id: string; + productId: string; + productKey: string; + name: { + en: string; + }; + productType: IProductType; + productSlug: { + en: string; + }; + variant: { + id: number; + sku: string; + key: string; + prices: IPriceProductApiResponse[]; + images: IImageProductApiResponse[]; + attributes: IAttributeCartLineItem[]; + assets: []; + }; + price: IPriceProductApiResponse; + quantity: number; + discountedPricePerQuantity: []; + perMethodTaxRate: []; + state: []; + priceMode: string; + lineItemMode: string; + totalPrice: IPriceProductApiResponse; + taxedPricePortions: []; +} diff --git a/e-commerce-app/src/types/slicesTypes/cart/cartSliceTypes.ts b/e-commerce-app/src/types/slicesTypes/cart/cartSliceTypes.ts new file mode 100644 index 0000000..9835692 --- /dev/null +++ b/e-commerce-app/src/types/slicesTypes/cart/cartSliceTypes.ts @@ -0,0 +1,5 @@ +import { ICartApiResponse } from './cartApiTypes'; + +export interface ICartFromSlice { + cart: ICartApiResponse | null; +} diff --git a/e-commerce-app/src/types/slicesTypes/cart/index.ts b/e-commerce-app/src/types/slicesTypes/cart/index.ts new file mode 100644 index 0000000..783ca55 --- /dev/null +++ b/e-commerce-app/src/types/slicesTypes/cart/index.ts @@ -0,0 +1,65 @@ +import { ICartApiResponse } from './cartApiTypes'; +import { + IShippingMethod, + ISetShippingAddressCart, + IPaymentCart, + IAddItemShippingAddressCart, + IAddLineItemCart, + IAddPaymentCart, + IAddDiscountCodeCart, + IDiscountCodeCart, + IRemoveDiscountCodeCart, + IRemoveItemShippingAddressCart, + IRemoveLineItemCart, + IRemovePaymentCart, + ISetBillingAddressCart, + ISetCountryCart, + IRecalculateCart, + ISetLocaleCart, + ISetShippingMethodCart, + IUpdateItemShippingAddressCart, + IChangeTaxModeCart, + ISetDeleteDaysAfterLastModificationCart, + IActionCart, +} from './updateCartActionsTypes'; + +import { ICartFromSlice } from './cartSliceTypes'; + +import { + ISubState, + IStateLineItem, + ICartLineItem, + IAttributeCartLineItem, + IProductType, +} from './cartLineItemsTypes'; + +export type { + ICartApiResponse, + IRecalculateCart, + ISetLocaleCart, + ISetShippingMethodCart, + ISetShippingAddressCart, + ISetCountryCart, + ISetBillingAddressCart, + IRemoveItemShippingAddressCart, + IRemovePaymentCart, + IUpdateItemShippingAddressCart, + IRemoveLineItemCart, + IAddPaymentCart, + IAddDiscountCodeCart, + IAddItemShippingAddressCart, + IRemoveDiscountCodeCart, + IShippingMethod, + IAddLineItemCart, + IDiscountCodeCart, + IPaymentCart, + ISetDeleteDaysAfterLastModificationCart, + IChangeTaxModeCart, + IActionCart, + ICartFromSlice, + ISubState, + IStateLineItem, + ICartLineItem, + IAttributeCartLineItem, + IProductType, +}; diff --git a/e-commerce-app/src/types/slicesTypes/cart/updateCartActionsTypes.ts b/e-commerce-app/src/types/slicesTypes/cart/updateCartActionsTypes.ts new file mode 100644 index 0000000..0acd291 --- /dev/null +++ b/e-commerce-app/src/types/slicesTypes/cart/updateCartActionsTypes.ts @@ -0,0 +1,129 @@ +import { IBaseCurrency, IBaseIdTypeResponse } from '../baseApiResponsesTypes'; +import { IMyCustomerApiAddressRequest } from '../../addressesTypes'; + +export interface IAddLineItemCart { + action: 'addLineItem'; + productId: string; + variantId?: number; + quantity: number; +} + +export interface IRemoveLineItemCart { + action: 'removeLineItem'; + lineItemId: string; + quantity: number; + externalPrice?: IBaseCurrency; + shippingDetailsToRemove?: { + targets: { + addressKey: string; + quantity: number; + }; + }; +} + +export interface IAddDiscountCodeCart { + action: 'addDiscountCode'; + code: string; +} + +export interface IDiscountCodeCart extends IBaseIdTypeResponse { + typeId: 'discount-code'; +} + +export interface IRemoveDiscountCodeCart { + action: 'removeDiscountCode'; + discountCode: IDiscountCodeCart; +} + +export interface IPaymentCart extends IBaseIdTypeResponse { + typeId: 'payment'; +} + +export interface IAddPaymentCart { + action: 'addPayment'; + payment: IPaymentCart; +} + +export interface IRemovePaymentCart { + action: 'removePayment'; + payment: IPaymentCart; +} + +export interface IChangeTaxModeCart { + action: 'changeTaxMode'; + taxMode: 'Platform' | 'External' | 'ExternalAmount' | 'Disabled'; +} + +export interface ISetBillingAddressCart { + action: 'setBillingAddress'; + address: IMyCustomerApiAddressRequest; +} + +export interface ISetShippingAddressCart { + action: 'setShippingAddress'; + address: IMyCustomerApiAddressRequest; +} + +export interface IAddItemShippingAddressCart { + action: 'addItemShippingAddress'; + address: IMyCustomerApiAddressRequest; +} + +export interface IRemoveItemShippingAddressCart { + action: 'removeItemShippingAddress'; + addressKey: string; +} + +export interface IUpdateItemShippingAddressCart { + action: 'updateItemShippingAddress'; + address: string; +} + +export interface IShippingMethod extends IBaseIdTypeResponse { + typeId: 'shipping-method'; +} + +export interface ISetShippingMethodCart { + action: 'setShippingMethod'; + shippingMethod: IShippingMethod; +} + +export interface ISetLocaleCart { + action: 'setLocale'; + locale: string; +} + +export interface ISetCountryCart { + action: 'setCountry'; + country: 'DE'; +} + +export interface ISetDeleteDaysAfterLastModificationCart { + action: 'setDeleteDaysAfterLastModification'; + deleteDaysAfterLastModification: number; +} + +export interface IRecalculateCart { + action: 'recalculate'; + updateProductData: boolean; +} + +export type IActionCart = + | IRecalculateCart + | ISetDeleteDaysAfterLastModificationCart + | ISetCountryCart + | ISetLocaleCart + | ISetShippingMethodCart + | IPaymentCart + | IUpdateItemShippingAddressCart + | IRemoveItemShippingAddressCart + | IAddItemShippingAddressCart + | ISetShippingAddressCart + | ISetBillingAddressCart + | IChangeTaxModeCart + | IRemovePaymentCart + | IAddPaymentCart + | IRemoveDiscountCodeCart + | IAddDiscountCodeCart + | IRemoveLineItemCart + | IAddLineItemCart; diff --git a/e-commerce-app/src/types/slicesTypes/cart/updateCartApiTypes.ts b/e-commerce-app/src/types/slicesTypes/cart/updateCartApiTypes.ts new file mode 100644 index 0000000..8968c7a --- /dev/null +++ b/e-commerce-app/src/types/slicesTypes/cart/updateCartApiTypes.ts @@ -0,0 +1,12 @@ +import { IActionCart } from './updateCartActionsTypes'; + +export interface IUpdateCartApiDataRequest { + version: number; + actions: IActionCart[]; +} + +export interface IUpdateCartApiObjectRequest { + cartId: string; + token: string; + data: IUpdateCartApiDataRequest; +} diff --git a/e-commerce-app/src/types/slicesTypes/categoriesApiTypes.ts b/e-commerce-app/src/types/slicesTypes/categoriesApiTypes.ts index cdffbef..2b27682 100644 --- a/e-commerce-app/src/types/slicesTypes/categoriesApiTypes.ts +++ b/e-commerce-app/src/types/slicesTypes/categoriesApiTypes.ts @@ -1,17 +1,17 @@ -import { IBaseGetAllQueryResponse, ICategoryTypeResponse } from './baseApiResponsesTypes'; +import { IBaseGetAllQueryResponse, IBaseIdTypeResponse } from './baseApiResponsesTypes'; export interface ICategoryName { en: string; } export interface ICategoryApiResponse { - ancestors: ICategoryTypeResponse[]; + ancestors: IBaseIdTypeResponse[]; assets: []; id: string; key: string; name: ICategoryName; orderHint: string; - parent?: ICategoryTypeResponse; + parent?: IBaseIdTypeResponse; slug: ICategoryName; version: number; } diff --git a/e-commerce-app/src/types/slicesTypes/myCustomerApiSliceTypes.ts b/e-commerce-app/src/types/slicesTypes/myCustomerApiSliceTypes.ts index cb121c8..2a8a1f6 100644 --- a/e-commerce-app/src/types/slicesTypes/myCustomerApiSliceTypes.ts +++ b/e-commerce-app/src/types/slicesTypes/myCustomerApiSliceTypes.ts @@ -7,6 +7,11 @@ export interface IMyCustomerLoginRequest { anonymousCart?: IAnonymousCartSignIn; } +export interface IAuthenticateMyCustomer { + token: string; + customerData: IMyCustomerLoginRequest; +} + export interface IMyCustomerBaseResponse { addresses: IMyCustomerAddressResponse[]; authenticationMode: 'Password' | string; diff --git a/e-commerce-app/src/types/slicesTypes/productProjectionsApiTypes.ts b/e-commerce-app/src/types/slicesTypes/productProjectionsApiTypes.ts index 577640b..d47dbd2 100644 --- a/e-commerce-app/src/types/slicesTypes/productProjectionsApiTypes.ts +++ b/e-commerce-app/src/types/slicesTypes/productProjectionsApiTypes.ts @@ -1,11 +1,12 @@ -import { IBaseGetAllQueryResponse, ICategoryTypeResponse } from './baseApiResponsesTypes'; +import { IBaseGetAllQueryResponse, IBaseIdTypeResponse } from './baseApiResponsesTypes'; import { IProductApiDescriptionResponse } from './productsApiTypes'; export interface ISearchApiResponse extends IProductApiDescriptionResponse { id: string; key: string; - productType: ICategoryTypeResponse; - taxCategory: ICategoryTypeResponse; + productType: IBaseIdTypeResponse; + taxCategory: IBaseIdTypeResponse; + version: number; } export interface ISearchProductsResponse extends IBaseGetAllQueryResponse { diff --git a/e-commerce-app/src/types/slicesTypes/productsApiTypes.ts b/e-commerce-app/src/types/slicesTypes/productsApiTypes.ts index 6ebce6c..cd26c31 100644 --- a/e-commerce-app/src/types/slicesTypes/productsApiTypes.ts +++ b/e-commerce-app/src/types/slicesTypes/productsApiTypes.ts @@ -1,6 +1,7 @@ import { IBaseGetAllQueryResponse, - ICategoryTypeResponse, + IBaseIdTypeResponse, + ICurrencyResponse, IMetaDescriptionProductResponse, } from './baseApiResponsesTypes'; import { IBaseQueryParams } from './baseApiRequestsTypes'; @@ -18,13 +19,9 @@ export interface IImageProductApiResponse { }; } -export interface IValuePriceProductApiResponse { - type: string; - currencyCode: string; - centAmount: number; - fractionDigits: number; +export interface IValuePriceProductApiResponse extends ICurrencyResponse { country: string; - channel: ICategoryTypeResponse; + channel: IBaseIdTypeResponse; } export interface IPriceProductApiResponse { @@ -43,7 +40,7 @@ export interface IMasterVariantProductApiResponse { } export interface IProductApiDescriptionResponse { - categories: ICategoryTypeResponse[]; + categories: IBaseIdTypeResponse[]; categoryOrderHints: object; masterVariant: IMasterVariantProductApiResponse; metaDescription: IMetaDescriptionProductResponse; @@ -64,8 +61,9 @@ export interface IProductApiResponse { id: string; key: string; masterData: IMasterDataProductApiResponse; - productType: ICategoryTypeResponse; - taxCategory: ICategoryTypeResponse; + productType: IBaseIdTypeResponse; + taxCategory: IBaseIdTypeResponse; + version: number; } export interface IGetAllProductsResponse extends IBaseGetAllQueryResponse { diff --git a/e-commerce-app/src/utils/makeProductSliceObjectFromSearchApiRequest.ts b/e-commerce-app/src/utils/makeProductSliceObjectFromSearchApiRequest.ts index b657458..1baea2a 100644 --- a/e-commerce-app/src/utils/makeProductSliceObjectFromSearchApiRequest.ts +++ b/e-commerce-app/src/utils/makeProductSliceObjectFromSearchApiRequest.ts @@ -32,6 +32,7 @@ const makeFromSearchApiProductApiResponses = (el: ISearchApiResponse): IProductA masterData: masterData, productType: el.productType, taxCategory: el.taxCategory, + version: el.version, }; return newProduct; };