| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119 |
- import makeClient from "@/lib/ApolloClientBrowser";
- import { type PayloadAction, createSlice, createAsyncThunk } from "@reduxjs/toolkit";
- import type {CartDetail} from "@/types/cart/type";
- import { GET_CART_ITEM } from "@/graphql";
- import { formatCartDetail } from "@/utils/cartDetailTools";
- /*
- idle 尚未初始化
- loading 正在请求购物车
- succeeded 请求成功,即使购物车为空也算成功
- failed 请求失败
- */
- export type CartStatus =
- | "idle"
- | "loading"
- | "succeeded"
- | "failed";
- export interface CartState {
- cart: CartDetail | null;
- loading: boolean;
- error: string | null;
- status: CartStatus;
- }
- // 定义异步 action
- export const fetchCartDetail = createAsyncThunk<
- ReturnType<typeof formatCartDetail> | null,
- void,
- {
- state: { cartDetail: CartState };
- rejectValue: string;
- }
- >(
- 'cartDetail/fetchCartDetail',
- async (_, { rejectWithValue }) => { //_ 占位,表示不需要参数
- try {
- const apolloClient = makeClient();
- const res = await apolloClient.mutate({
- mutation: GET_CART_ITEM,
- fetchPolicy: 'network-only', // 按需调整
- });
- const responseData = res.data?.createReadCart?.readCart;
- return responseData ? formatCartDetail(responseData) : null;
- } catch (error) {
- let errorMessage: string;
- if (error instanceof Error) {
- errorMessage = error.message;
- } else {
- errorMessage = String(error);
- }
- return rejectWithValue(errorMessage);
- }
- },
- {
- condition: (_, { getState }) => {
- const state = getState();
- const fetchStatus = state.cartDetail.status;
- if (fetchStatus === 'succeeded' || fetchStatus === 'loading') {
- // Already fetched or in progress, don't need to re-fetch
- return false
- }
- },
- },
- );
- const initialState: CartState = {
- cart: null,
- loading: false,
- status: "idle",
- error: null,
- };
- const cartSlice = createSlice({
- name: "cartDetail",
- initialState,
- reducers: {
- addItem: (state, action: PayloadAction<CartDetail>) => {
- state.cart = { ...action.payload };
- },
- updateCart: (state, action: PayloadAction<Partial<CartDetail>>) => {
- if (state.cart) {
- state.cart = { ...state.cart, ...action.payload };
- }
- },
- clearCart(state) {
- state.cart = null;
- state.loading = false;
- state.error = null;
- },
- },
- extraReducers: (builder) => {
- builder
- .addCase(fetchCartDetail.pending, (state) => {
- state.status = "loading";
- state.loading = true;
- state.error = null;
- })
- .addCase(fetchCartDetail.fulfilled, (state, action) => {
- state.status = "succeeded";
- state.loading = false;
- state.cart = action.payload;
- })
- .addCase(fetchCartDetail.rejected, (state, action) => {
- state.status = "failed";
- state.loading = false;
- state.error = (action.payload as string | undefined) ?? action.error.message ?? "Get cart detail failed!";
- });
- },
- });
- export const {
- addItem,
- updateCart,
- clearCart,
- } = cartSlice.actions;
- export default cartSlice.reducer;
|