Official Solution
import React, { useReducer } from 'react';
const catalog = [
{ id: 'react', name: 'React Basics', price: 199 },
{ id: 'hooks', name: 'Hooks Practice', price: 249 },
{ id: 'forms', name: 'Forms Bundle', price: 149 }
];
function reducer(state, action) {
if (action.type === 'add') {
const found = state.items.find((x) => x.id === action.id);
if (found) return { ...state, items: state.items.map((x) => x.id === action.id ? { ...x, qty: x.qty + 1 } : x) };
return { ...state, items: [...state.items, { id: action.id, qty: 1 }] };
}
if (action.type === 'inc') return { ...state, items: state.items.map((x) => x.id === action.id ? { ...x, qty: x.qty + 1 } : x) };
if (action.type === 'dec') return { ...state, items: state.items.map((x) => x.id === action.id ? { ...x, qty: Math.max(1, x.qty - 1) } : x) };
if (action.type === 'remove') return { ...state, items: state.items.filter((x) => x.id !== action.id) };
return state;
}
export default function App() {
const [state, dispatch] = useReducer(reducer, { items: [] });
const lines = state.items.map((line) => {
const product = catalog.find((p) => p.id === line.id);
return { ...line, name: product.name, price: product.price, total: product.price * line.qty };
});
const grand = lines.reduce((sum, x) => sum + x.total, 0);
return (
<div style={{ padding: 16, width: 560 }}>
<h2 style={{ marginTop: 0 }}>meetcode cart</h2>
<div style={{ display: 'flex', gap: 10, flexWrap: 'wrap' }}>
{catalog.map((p) => (
<button key={p.id} type='button' onClick={() => dispatch({ type: 'add', id: p.id })} style={{ padding: '10px 14px', borderRadius: 12, border: '1px solid #ddd', background: '#fff' }}>
Add {p.name}
</button>
))}
</div>
<div style={{ marginTop: 14, border: '1px solid #eee', borderRadius: 16, padding: 12 }}>
{!lines.length ? <div style={{ color: '#555' }}>Cart is empty.</div> : null}
{lines.map((x) => (
<div key={x.id} style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 12, padding: '8px 0' }}>
<div style={{ minWidth: 220 }}>
<strong>{x.name}</strong>
<div style={{ color: '#555' }}>₹{x.price} each</div>
</div>
<div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
<button type='button' onClick={() => dispatch({ type: 'dec', id: x.id })} style={{ width: 36, height: 36, borderRadius: 12, border: '1px solid #ddd', background: '#fff' }}>−</button>
<strong style={{ width: 26, textAlign: 'center' }}>{x.qty}</strong>
<button type='button' onClick={() => dispatch({ type: 'inc', id: x.id })} style={{ width: 36, height: 36, borderRadius: 12, border: '1px solid #ddd', background: '#fff' }}>+</button>
<button type='button' onClick={() => dispatch({ type: 'remove', id: x.id })} style={{ padding: '8px 12px', borderRadius: 12, border: 0, background: '#ffe8ea', color: '#c1121f' }}>Remove</button>
</div>
<strong style={{ width: 90, textAlign: 'right' }}>₹{x.total}</strong>
</div>
))}
{lines.length ? <div style={{ borderTop: '1px solid #eee', marginTop: 10, paddingTop: 10, display: 'flex', justifyContent: 'space-between' }}><strong>Total</strong><strong>₹{grand}</strong></div> : null}
</div>
</div>
);
}
No comments yet. Start the discussion!