import { useState, useCallback } from 'react'; export const __trackCalls: { name: string; props: any }[] = []; export const __zipStore: string[] = []; export const analytics = { track: (name: string, props: any) => __trackCalls.push({ name, props }), }; export interface CartItem { id: string; price: number; quantity: number } export interface UseCartReturn { items: CartItem[]; addItem: (item: CartItem) => void; getItemById: (id: string) => CartItem | undefined; calculateShipping: (zipCode: string) => number; } // TODO: // - getItemById 와 calculateShipping 을 순수하게 만들어라 // - 트래킹/저장은 trackItemLookup / persistShippingZip 같은 별도 함수로 분리 // - hook return 객체에 추가 export 또는 모듈 레벨로 export export function useCart(initial: CartItem[] = []): UseCartReturn { const [items, setItems] = useState<CartItem[]>(initial); const addItem = useCallback((item: CartItem) => { setItems((prev) => [...prev, item]); }, []); const getItemById = useCallback( (id: string): CartItem | undefined => { const item = items.find((i) => i.id === id); analytics.track('cart_item_lookup', { id, found: !!item }); return item; }, [items] ); const calculateShipping = useCallback( (zipCode: string): number => { __zipStore.push(zipCode); analytics.track('shipping_calculated', { zipCode }); const base = 5.99; const distance = zipCode.startsWith('9') ? 1.5 : 1; const surcharge = items.length > 5 ? 2.99 : 0; return base * distance + surcharge; }, [items] ); return { items, addItem, getItemById, calculateShipping }; }
Tests