Initial commit for homaroma
This commit is contained in:
commit
f2179cfe57
269 files changed
+22635
No files matched your search
@@ -0,0 +1,37 @@
|
||||
import { create } from "zustand";
|
||||
import { persist } from "zustand/middleware";
|
||||
|
||||
export interface Customer {
|
||||
id: number;
|
||||
lineUserId: string;
|
||||
displayName: string | null;
|
||||
pictureUrl: string | null;
|
||||
email: string | null;
|
||||
phone: string | null;
|
||||
}
|
||||
|
||||
interface AuthState {
|
||||
token: string | null;
|
||||
customer: Customer | null;
|
||||
isLiffInitialized: boolean;
|
||||
setAuth: (token: string, customer: Customer) => void;
|
||||
setLiffInitialized: (status: boolean) => void;
|
||||
logout: () => void;
|
||||
}
|
||||
|
||||
export const useAuthStore = create<AuthState>()(
|
||||
persist(
|
||||
(set) => ({
|
||||
token: null,
|
||||
customer: null,
|
||||
isLiffInitialized: false,
|
||||
setAuth: (token, customer) => set({ token, customer }),
|
||||
setLiffInitialized: (isLiffInitialized) => set({ isLiffInitialized }),
|
||||
logout: () => set({ token: null, customer: null }),
|
||||
}),
|
||||
{
|
||||
name: "irelax-auth-storage",
|
||||
partialize: (state) => ({ token: state.token, customer: state.customer }), // don't persist isLiffInitialized
|
||||
}
|
||||
)
|
||||
);
|
||||
@@ -0,0 +1,78 @@
|
||||
import { create } from 'zustand';
|
||||
import { persist } from 'zustand/middleware';
|
||||
import type { CartItem } from '@irelax/types';
|
||||
|
||||
interface CartState {
|
||||
items: CartItem[];
|
||||
isCartOpen: boolean;
|
||||
addToCart: (item: Omit<CartItem, 'cartItemId'>) => void;
|
||||
removeFromCart: (cartItemId: string) => void;
|
||||
updateQuantity: (cartItemId: string, quantity: number) => void;
|
||||
clearCart: () => void;
|
||||
toggleCart: (isOpen?: boolean) => void;
|
||||
getCartTotal: () => number;
|
||||
getCartCount: () => number;
|
||||
}
|
||||
|
||||
export const useCartStore = create<CartState>()(
|
||||
persist(
|
||||
(set, get) => ({
|
||||
items: [],
|
||||
isCartOpen: false,
|
||||
|
||||
addToCart: (item) => set((state) => {
|
||||
// Build a unique ID for the item. If variantId exists, use it. Otherwise, use productId.
|
||||
const exactIdMatch = state.items.find(i =>
|
||||
i.productId === item.productId && i.variantId === item.variantId
|
||||
);
|
||||
|
||||
if (exactIdMatch) {
|
||||
// Increment quantity if exact match exists
|
||||
return {
|
||||
items: state.items.map(i =>
|
||||
i.cartItemId === exactIdMatch.cartItemId
|
||||
? { ...i, quantity: i.quantity + item.quantity }
|
||||
: i
|
||||
),
|
||||
isCartOpen: true
|
||||
};
|
||||
}
|
||||
|
||||
// Add new item with a generated cartItemId
|
||||
const cartItemId = crypto.randomUUID();
|
||||
return {
|
||||
items: [...state.items, { ...item, cartItemId }],
|
||||
isCartOpen: true
|
||||
};
|
||||
}),
|
||||
|
||||
removeFromCart: (cartItemId) => set((state) => ({
|
||||
items: state.items.filter(i => i.cartItemId !== cartItemId)
|
||||
})),
|
||||
|
||||
updateQuantity: (cartItemId, quantity) => set((state) => ({
|
||||
items: state.items.map(i =>
|
||||
i.cartItemId === cartItemId ? { ...i, quantity: Math.max(1, quantity) } : i
|
||||
)
|
||||
})),
|
||||
|
||||
clearCart: () => set({ items: [] }),
|
||||
|
||||
toggleCart: (isOpen) => set((state) => ({
|
||||
isCartOpen: isOpen !== undefined ? isOpen : !state.isCartOpen
|
||||
})),
|
||||
|
||||
getCartTotal: () => {
|
||||
return get().items.reduce((total, item) => total + (item.price * item.quantity), 0);
|
||||
},
|
||||
|
||||
getCartCount: () => {
|
||||
return get().items.reduce((count, item) => count + item.quantity, 0);
|
||||
}
|
||||
}),
|
||||
{
|
||||
name: 'irelax-cart-storage',
|
||||
partialize: (state) => ({ items: state.items }), // Only persist items, not UI state
|
||||
}
|
||||
)
|
||||
);
|
||||
Reference in new issue
Block a user