115 lines
3.7 KiB
TypeScript

import { createAction, createReducer } from '@reduxjs/toolkit';
import { CartItem, CatalogItem } from '../../../interfaces';
// ─── State ───────────────────────────────────────────────────────────────────
export interface CartState {
items: CartItem[];
couponCode: string | null;
discount: number;
providerId: string | null;
providerName: string | null;
}
const initialState: CartState = {
items: [],
couponCode: null,
discount: 0,
providerId: null,
providerName: null,
};
// ─── Actions ─────────────────────────────────────────────────────────────────
export const addItem = createAction<{
providerId: string;
providerName: string;
item: CatalogItem;
}>('cart/addItem');
export const removeItem = createAction<string>('cart/removeItem');
export const clearCart = createAction('cart/clearCart');
export const applyCoupon = createAction<string>('cart/applyCoupon');
export const removeCoupon = createAction('cart/removeCoupon');
// ─── Selector ────────────────────────────────────────────────────────────────
export const selectCartTotal = (state: { cart: CartState }) => {
const subtotal = state.cart.items.reduce(
(sum, item) => sum + item.item.price * item.quantity,
0,
);
const deliveryFee = 40;
const platformFee = 10;
const discount = state.cart.discount;
return {
subtotal,
deliveryFee,
platformFee,
discount,
total: Math.max(0, subtotal + deliveryFee + platformFee - discount),
itemCount: state.cart.items.reduce((sum, item) => sum + item.quantity, 0),
};
};
// ─── Reducer ─────────────────────────────────────────────────────────────────
const cartReducer = createReducer(initialState, builder => {
builder
.addCase(addItem, (state, action) => {
const { providerId, providerName, item } = action.payload;
// Clear cart if switching providers
if (state.providerId && state.providerId !== providerId) {
state.items = [];
}
state.providerId = providerId;
state.providerName = providerName;
const existing = state.items.find(i => i.item.id === item.id);
if (existing) {
existing.quantity += 1;
} else {
state.items.push({
id: `${providerId}-${item.id}`,
providerId,
providerName,
item,
quantity: 1,
});
}
})
.addCase(removeItem, (state, action) => {
const existing = state.items.find(i => i.item.id === action.payload);
if (existing) {
if (existing.quantity > 1) {
existing.quantity -= 1;
} else {
state.items = state.items.filter(i => i.item.id !== action.payload);
}
}
if (state.items.length === 0) {
state.providerId = null;
state.providerName = null;
}
})
.addCase(clearCart, state => {
state.items = [];
state.couponCode = null;
state.discount = 0;
state.providerId = null;
state.providerName = null;
})
.addCase(applyCoupon, (state, action) => {
state.couponCode = action.payload;
state.discount = 50;
})
.addCase(removeCoupon, state => {
state.couponCode = null;
state.discount = 0;
});
});
export default cartReducer;