import { createSlice, configureStore } from '@reduxjs/toolkit' import { Provider, useSelector, useDispatch } from 'react-redux'
const userSlice = createSlice({ name: 'user', initialState: { currentUser: null, isLoading: false, error: null }, reducers: { loginStart: (state) => { state.isLoading = true state.error = null }, loginSuccess: (state, action) => { state.currentUser = action.payload state.isLoading = false state.error = null }, loginFailure: (state, action) => { state.isLoading = false state.error = action.payload }, logout: (state) => { state.currentUser = null } } })
const productSlice = createSlice({ name: 'products', initialState: { products: [], isLoading: false, error: null }, reducers: { fetchProductsStart: (state) => { state.isLoading = true }, fetchProductsSuccess: (state, action) => { state.products = action.payload state.isLoading = false state.error = null }, fetchProductsFailure: (state, action) => { state.isLoading = false state.error = action.payload } } })
const cartSlice = createSlice({ name: 'cart', initialState: { items: [], total: 0 }, reducers: { addToCart: (state, action) => { const item = state.items.find(item => item.id === action.payload.id) if (item) { item.quantity += 1 } else { state.items.push({ ...action.payload, quantity: 1 }) } state.total = state.items.reduce((total, item) => total + item.price * item.quantity, 0) }, removeFromCart: (state, action) => { state.items = state.items.filter(item => item.id !== action.payload) state.total = state.items.reduce((total, item) => total + item.price * item.quantity, 0) }, updateQuantity: (state, action) => { const { id, quantity } = action.payload const item = state.items.find(item => item.id === id) if (item) { item.quantity = quantity state.total = state.items.reduce((total, item) => total + item.price * item.quantity, 0) } }, clearCart: (state) => { state.items = [] state.total = 0 } } })
const orderSlice = createSlice({ name: 'orders', initialState: { orders: [], currentOrder: null, isLoading: false }, reducers: { createOrderStart: (state) => { state.isLoading = true }, createOrderSuccess: (state, action) => { state.currentOrder = action.payload state.orders.push(action.payload) state.isLoading = false }, createOrderFailure: (state, action) => { state.isLoading = false state.error = action.payload } } })
export const { loginStart, loginSuccess, loginFailure, logout } = userSlice.actions
export const { fetchProductsStart, fetchProductsSuccess, fetchProductsFailure } = productSlice.actions
export const { addToCart, removeFromCart, updateQuantity, clearCart } = cartSlice.actions
export const { createOrderStart, createOrderSuccess, createOrderFailure } = orderSlice.actions
export const store = configureStore({ reducer: { user: userSlice.reducer, products: productSlice.reducer, cart: cartSlice.reducer, orders: orderSlice.reducer } })
function ProductList() { const { products, isLoading, error } = useSelector(state => state.products) const dispatch = useDispatch() React.useEffect(() => { dispatch(fetchProductsStart()) setTimeout(() => { const mockProducts = [ { id: 1, name: 'iPhone 13', price: 5999, image: 'iphone.jpg' }, { id: 2, name: 'MacBook Pro', price: 12999, image: 'macbook.jpg' }, { id: 3, name: 'AirPods Pro', price: 1999, image: 'airpods.jpg' } ] dispatch(fetchProductsSuccess(mockProducts)) }, 1000) }, [dispatch]) if (isLoading) return <div>Loading products...</div> if (error) return <div>Error: {error}</div> return ( <div> <h2>Products</h2> <div style={{ display: 'flex', gap: '20px' }}> {products.map(product => ( <div key={product.id} style={{ border: '1px solid #ccc', padding: '10px' }}> <h3>{product.name}</h3> <p>¥{product.price}</p> <button onClick={() => dispatch(addToCart(product))}> Add to Cart </button> </div> ))} </div> </div> ) }
function ShoppingCart() { const { items, total } = useSelector(state => state.cart) const dispatch = useDispatch() return ( <div> <h2>Shopping Cart</h2> {items.length === 0 ? ( <p>Your cart is empty</p> ) : ( <> <ul> {items.map(item => ( <li key={item.id} style={{ display: 'flex', alignItems: 'center', gap: '10px' }}> <span>{item.name} - ¥{item.price}</span> <input type="number" value={item.quantity} onChange={(e) => dispatch(updateQuantity({ id: item.id, quantity: parseInt(e.target.value) || 1 }))} min="1" style={{ width: '50px' }} /> <button onClick={() => dispatch(removeFromCart(item.id))}>Remove</button> </li> ))} </ul> <div> <p>Total: ¥{total}</p> <button onClick={() => dispatch(clearCart())}>Clear Cart</button> </div> </> )} </div> ) }
function LoginForm() { const [email, setEmail] = React.useState('') const [password, setPassword] = React.useState('') const { isLoading, error } = useSelector(state => state.user) const dispatch = useDispatch() const handleSubmit = (e) => { e.preventDefault() dispatch(loginStart()) setTimeout(() => { dispatch(loginSuccess({ id: 1, name: '张三', email })) }, 1000) } return ( <div> <h2>Login</h2> {isLoading && <p>Loading...</p>} {error && <p style={{ color: 'red' }}>{error}</p>} <form onSubmit={handleSubmit}> <div> <label>Email:</label> <input type="email" value={email} onChange={(e) => setEmail(e.target.value)} required /> </div> <div> <label>Password:</label> <input type="password" value={password} onChange={(e) => setPassword(e.target.value)} required /> </div> <button type="submit" disabled={isLoading}>Login</button> </form> </div> ) }
function ECommerceApp() { const { currentUser } = useSelector(state => state.user) const dispatch = useDispatch() const handleLogout = () => { dispatch(logout()) } return ( <Provider store={store}> <div> <h1>E-commerce Store</h1> {currentUser ? ( <div> <div style={{ float: 'right' }}> <span>Welcome, {currentUser.name}</span> <button onClick={handleLogout}>Logout</button> </div> <div style={{ clear: 'both' }}> <ProductList /> <ShoppingCart /> </div> </div> ) : ( <LoginForm /> )} </div> </Provider> ) }
|