Initial commit
This commit is contained in:
311
src/features/order/orderSlice.ts
Normal file
311
src/features/order/orderSlice.ts
Normal file
@@ -0,0 +1,311 @@
|
||||
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
|
||||
import { RootState } from "redux/store";
|
||||
import { CartItem } from "utils/types/appTypes";
|
||||
|
||||
interface LocationData {
|
||||
lat: number;
|
||||
lng: number;
|
||||
address: string;
|
||||
}
|
||||
|
||||
export interface RoomDetailsType {
|
||||
roomNo: string;
|
||||
floorNo: string;
|
||||
guestName: string;
|
||||
note: string;
|
||||
}
|
||||
|
||||
export interface OfficeDetailsType {
|
||||
officeNo: string;
|
||||
floorNo: string;
|
||||
note: string;
|
||||
company: string;
|
||||
contactPerson: string;
|
||||
phone: string;
|
||||
}
|
||||
|
||||
export interface GiftDetailsType {
|
||||
receiverName: string;
|
||||
receiverPhone: string;
|
||||
message: string;
|
||||
senderName: string;
|
||||
senderPhone: string;
|
||||
isSecret: boolean;
|
||||
}
|
||||
|
||||
interface CartState {
|
||||
items: CartItem[];
|
||||
tmp: unknown;
|
||||
specialRequest: string;
|
||||
location: LocationData | null;
|
||||
roomDetails: RoomDetailsType | null;
|
||||
officeDetails: OfficeDetailsType | null;
|
||||
giftDetails: GiftDetailsType | null;
|
||||
coupon: string;
|
||||
tip: string;
|
||||
tables: string[];
|
||||
estimateTime: Date;
|
||||
estimateTimeDate: Date;
|
||||
estimateTimeTime: string;
|
||||
collectionMethod: string;
|
||||
}
|
||||
|
||||
// localStorage keys
|
||||
const CART_STORAGE_KEYS = {
|
||||
ITEMS: 'fascano_cart_items',
|
||||
SPECIAL_REQUEST: 'fascano_special_request',
|
||||
COUPON: 'fascano_coupon',
|
||||
TIP: 'fascano_tip',
|
||||
TABLES: 'fascano_tables',
|
||||
LOCATION: 'fascano_location',
|
||||
ROOM_DETAILS: 'fascano_room_details',
|
||||
OFFICE_DETAILS: 'fascano_office_details',
|
||||
GIFT_DETAILS: 'fascano_gift_details',
|
||||
ESTIMATE_TIME: 'fascano_estimate_time',
|
||||
ESTIMATE_TIME_DATE: 'fascano_estimate_time_date',
|
||||
ESTIMATE_TIME_TIME: 'fascano_estimate_time_time',
|
||||
COLLECTION_METHOD: 'fascano_collection_method',
|
||||
} as const;
|
||||
|
||||
// Utility functions for localStorage
|
||||
const getFromLocalStorage = <T>(key: string, defaultValue: T): T => {
|
||||
if (typeof window === 'undefined') return defaultValue;
|
||||
|
||||
try {
|
||||
const item = localStorage.getItem(key);
|
||||
return item ? JSON.parse(item) : defaultValue;
|
||||
} catch (error) {
|
||||
console.warn(`Error reading ${key} from localStorage:`, error);
|
||||
return defaultValue;
|
||||
}
|
||||
};
|
||||
|
||||
const initialState: CartState = {
|
||||
items: getFromLocalStorage(CART_STORAGE_KEYS.ITEMS, []),
|
||||
tmp: null,
|
||||
specialRequest: getFromLocalStorage(CART_STORAGE_KEYS.SPECIAL_REQUEST, ""),
|
||||
location: getFromLocalStorage(CART_STORAGE_KEYS.LOCATION, null),
|
||||
roomDetails: getFromLocalStorage(CART_STORAGE_KEYS.ROOM_DETAILS, null),
|
||||
officeDetails: getFromLocalStorage(CART_STORAGE_KEYS.OFFICE_DETAILS, null),
|
||||
giftDetails: getFromLocalStorage(CART_STORAGE_KEYS.GIFT_DETAILS, null),
|
||||
coupon: getFromLocalStorage(CART_STORAGE_KEYS.COUPON, ""),
|
||||
tip: getFromLocalStorage(CART_STORAGE_KEYS.TIP, ""),
|
||||
tables: getFromLocalStorage(CART_STORAGE_KEYS.TABLES, []),
|
||||
estimateTime: new Date(getFromLocalStorage(CART_STORAGE_KEYS.ESTIMATE_TIME, new Date().toISOString())),
|
||||
estimateTimeDate: new Date(getFromLocalStorage(CART_STORAGE_KEYS.ESTIMATE_TIME_DATE, new Date().toISOString())),
|
||||
estimateTimeTime: getFromLocalStorage(CART_STORAGE_KEYS.ESTIMATE_TIME_TIME, ""),
|
||||
collectionMethod: getFromLocalStorage(CART_STORAGE_KEYS.COLLECTION_METHOD, ""),
|
||||
};
|
||||
|
||||
const orderSlice = createSlice({
|
||||
name: "order",
|
||||
initialState,
|
||||
reducers: {
|
||||
reset() {
|
||||
return initialState;
|
||||
},
|
||||
addItem(state, action: PayloadAction<{ item: Omit<CartItem, "quantity">; quantity: number }>) {
|
||||
const { item, quantity } = action.payload;
|
||||
const existingItem = state.items.find((i) => i.id === item.id);
|
||||
|
||||
if (existingItem) {
|
||||
state.items = state.items.map((i) =>
|
||||
i.id === item.id ? { ...i, quantity: i.quantity + quantity } : i
|
||||
);
|
||||
} else {
|
||||
state.items = [...state.items, { ...item, quantity }];
|
||||
}
|
||||
|
||||
// Sync to localStorage
|
||||
if (typeof window !== 'undefined') {
|
||||
localStorage.setItem(CART_STORAGE_KEYS.ITEMS, JSON.stringify(state.items));
|
||||
}
|
||||
},
|
||||
updateQuantity(state, action: PayloadAction<{ id: number | string; quantity: number }>) {
|
||||
const { id, quantity } = action.payload;
|
||||
state.items = state.items.map((item) =>
|
||||
item.id === id ? { ...item, quantity } : item
|
||||
);
|
||||
|
||||
// Sync to localStorage
|
||||
if (typeof window !== 'undefined') {
|
||||
localStorage.setItem(CART_STORAGE_KEYS.ITEMS, JSON.stringify(state.items));
|
||||
}
|
||||
},
|
||||
removeItem(state, action: PayloadAction<number | string>) {
|
||||
state.items = state.items.filter((item) => item.id !== action.payload);
|
||||
|
||||
// Sync to localStorage
|
||||
if (typeof window !== 'undefined') {
|
||||
localStorage.setItem(CART_STORAGE_KEYS.ITEMS, JSON.stringify(state.items));
|
||||
}
|
||||
},
|
||||
clearCart(state) {
|
||||
state.items = [];
|
||||
state.specialRequest = "";
|
||||
state.coupon = "";
|
||||
state.tip = "";
|
||||
state.tables = [];
|
||||
state.location = null;
|
||||
state.roomDetails = null;
|
||||
state.officeDetails = null;
|
||||
state.giftDetails = null;
|
||||
state.estimateTime = new Date();
|
||||
state.estimateTimeDate = new Date();
|
||||
state.estimateTimeTime = "";
|
||||
state.collectionMethod = "";
|
||||
|
||||
// Clear all cart data from localStorage
|
||||
if (typeof window !== 'undefined') {
|
||||
Object.values(CART_STORAGE_KEYS).forEach(key => {
|
||||
localStorage.removeItem(key);
|
||||
});
|
||||
}
|
||||
},
|
||||
updateSpecialRequest(state, action: PayloadAction<string>) {
|
||||
state.specialRequest = action.payload;
|
||||
|
||||
// Sync to localStorage
|
||||
if (typeof window !== 'undefined') {
|
||||
localStorage.setItem(CART_STORAGE_KEYS.SPECIAL_REQUEST, JSON.stringify(state.specialRequest));
|
||||
}
|
||||
},
|
||||
clearSpecialRequest(state) {
|
||||
state.specialRequest = "";
|
||||
|
||||
// Sync to localStorage
|
||||
if (typeof window !== 'undefined') {
|
||||
localStorage.removeItem(CART_STORAGE_KEYS.SPECIAL_REQUEST);
|
||||
}
|
||||
},
|
||||
updateCoupon(state, action: PayloadAction<string>) {
|
||||
state.coupon = action.payload;
|
||||
|
||||
// Sync to localStorage
|
||||
if (typeof window !== 'undefined') {
|
||||
localStorage.setItem(CART_STORAGE_KEYS.COUPON, JSON.stringify(state.coupon));
|
||||
}
|
||||
},
|
||||
updateTip(state, action: PayloadAction<string>) {
|
||||
state.tip = action.payload;
|
||||
|
||||
// Sync to localStorage
|
||||
if (typeof window !== 'undefined') {
|
||||
localStorage.setItem(CART_STORAGE_KEYS.TIP, JSON.stringify(state.tip));
|
||||
}
|
||||
},
|
||||
updateTables(state, action: PayloadAction<string[]>) {
|
||||
state.tables = [...state.tables, ...action.payload];
|
||||
|
||||
// Sync to localStorage
|
||||
if (typeof window !== 'undefined') {
|
||||
localStorage.setItem(CART_STORAGE_KEYS.TABLES, JSON.stringify(state.tables));
|
||||
}
|
||||
},
|
||||
removeTable(state) {
|
||||
state.tables = [];
|
||||
|
||||
// Sync to localStorage
|
||||
if (typeof window !== 'undefined') {
|
||||
localStorage.removeItem(CART_STORAGE_KEYS.TABLES);
|
||||
}
|
||||
},
|
||||
setTmp(state, action: PayloadAction<unknown>) {
|
||||
state.tmp = action.payload;
|
||||
},
|
||||
updateLocation(state, action: PayloadAction<LocationData | null>) {
|
||||
state.location = action.payload;
|
||||
|
||||
// Sync to localStorage
|
||||
if (typeof window !== 'undefined') {
|
||||
localStorage.setItem(CART_STORAGE_KEYS.LOCATION, JSON.stringify(state.location));
|
||||
}
|
||||
},
|
||||
clearLocation(state) {
|
||||
state.location = null;
|
||||
|
||||
// Sync to localStorage
|
||||
if (typeof window !== 'undefined') {
|
||||
localStorage.removeItem(CART_STORAGE_KEYS.LOCATION);
|
||||
}
|
||||
},
|
||||
updateRoomDetails(state, action: PayloadAction<RoomDetailsType | null>) {
|
||||
state.roomDetails = action.payload;
|
||||
|
||||
// Sync to localStorage
|
||||
if (typeof window !== 'undefined') {
|
||||
localStorage.setItem(CART_STORAGE_KEYS.ROOM_DETAILS, JSON.stringify(state.roomDetails));
|
||||
}
|
||||
},
|
||||
updateOfficeDetails(state, action: PayloadAction<OfficeDetailsType | null>) {
|
||||
state.officeDetails = action.payload;
|
||||
|
||||
// Sync to localStorage
|
||||
if (typeof window !== 'undefined') {
|
||||
localStorage.setItem(CART_STORAGE_KEYS.OFFICE_DETAILS, JSON.stringify(state.officeDetails));
|
||||
}
|
||||
},
|
||||
updateGiftDetails(state, action: PayloadAction<GiftDetailsType | null>) {
|
||||
state.giftDetails = action.payload;
|
||||
|
||||
// Sync to localStorage
|
||||
if (typeof window !== 'undefined') {
|
||||
localStorage.setItem(CART_STORAGE_KEYS.GIFT_DETAILS, JSON.stringify(state.giftDetails));
|
||||
}
|
||||
},
|
||||
updateEstimateTime(state, action: PayloadAction<{ date: Date; time: string }>) {
|
||||
state.estimateTime = action.payload.date;
|
||||
state.estimateTimeDate = action.payload.date;
|
||||
state.estimateTimeTime = action.payload.time;
|
||||
|
||||
// Sync to localStorage
|
||||
if (typeof window !== 'undefined') {
|
||||
localStorage.setItem(CART_STORAGE_KEYS.ESTIMATE_TIME, JSON.stringify(state.estimateTime.toISOString()));
|
||||
localStorage.setItem(CART_STORAGE_KEYS.ESTIMATE_TIME_DATE, JSON.stringify(state.estimateTimeDate.toISOString()));
|
||||
localStorage.setItem(CART_STORAGE_KEYS.ESTIMATE_TIME_TIME, JSON.stringify(state.estimateTimeTime));
|
||||
}
|
||||
},
|
||||
updateCollectionMethod(state, action: PayloadAction<string>) {
|
||||
state.collectionMethod = action.payload;
|
||||
|
||||
// Sync to localStorage
|
||||
if (typeof window !== 'undefined') {
|
||||
localStorage.setItem(CART_STORAGE_KEYS.COLLECTION_METHOD, JSON.stringify(state.collectionMethod));
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export const {
|
||||
addItem,
|
||||
updateQuantity,
|
||||
removeItem,
|
||||
clearCart,
|
||||
updateSpecialRequest,
|
||||
clearSpecialRequest,
|
||||
updateCoupon,
|
||||
updateTip,
|
||||
updateTables,
|
||||
removeTable,
|
||||
setTmp,
|
||||
updateLocation,
|
||||
clearLocation,
|
||||
updateRoomDetails,
|
||||
updateOfficeDetails,
|
||||
updateGiftDetails,
|
||||
updateEstimateTime,
|
||||
updateCollectionMethod,
|
||||
reset,
|
||||
} = orderSlice.actions;
|
||||
|
||||
// Selectors
|
||||
export const selectCart = (state: RootState) => state.order;
|
||||
export const selectCartItems = (state: RootState) => state.order.items;
|
||||
export const selectCartTotal = (state: RootState) =>
|
||||
state.order.items.reduce((total, item) => total + item.price * item.quantity, 0);
|
||||
export const selectCartItemsQuantity = (id: number | string) => (state: RootState) => {
|
||||
const item = state.order.items.find((i) => i.id === id);
|
||||
return item ? item.quantity : 0;
|
||||
};
|
||||
|
||||
export default orderSlice.reducer;
|
||||
Reference in New Issue
Block a user