Coding apple ecommerce project
Reference
이 프로젝트는 코딩애플 리액트 강의를 참고하여 제작되었습니다.
https://codingapple.com/course/react-basic/
React 리액트 기초부터 쇼핑몰 프로젝트까지!
Next.js는 프론트엔드부터 서버까지 만들 수 있는 React기반 프레임워크입니다. 이것만 사용해도 풀스택 웹개발이 가능합니다. Next.js 사용시 서버사이드 렌더링이 쉽기 때문에 React, Vue만 사
codingapple.com
Final build
https://stackblitz.com/edit/vitejs-vite-w8s3td76?file=src%2FApp.jsx
coding-apple-ecommerce-project - StackBlitz
Next generation frontend tooling. It's fast!
stackblitz.com
Index
1
https://lshjju.tistory.com/280
2
https://lshjju.tistory.com/281
3
https://lshjju.tistory.com/282
4
https://lshjju.tistory.com/283
5
https://lshjju.tistory.com/286
6
https://lshjju.tistory.com/287
7
https://lshjju.tistory.com/288
8
https://lshjju.tistory.com/291
9
https://lshjju.tistory.com/292
Completion
import { useState } from 'react';
import reactLogo from './assets/react.svg';
import viteLogo from '/vite.svg';
import './App.css';
import 'bootstrap/dist/css/bootstrap.min.css';
import { Routes, Route, Link, Outlet } from 'react-router-dom';
import data from './data.jsx';
import Detail from './routes/Detail';
import Remove from './routes/Remove';
import axios from 'axios';
import Cart from './routes/Cart';
export default function App() {
let [shoes, setShoes] = useState(data);
return (
<div className="App">
<nav class="navbar navbar-expand-lg bg-body-tertiary">
<div class="container-fluid">
<a class="navbar-brand" href="#">
Navbar
</a>
<button
class="navbar-toggler"
type="button"
data-bs-toggle="collapse"
data-bs-target="#navbarNavAltMarkup"
aria-controls="navbarNavAltMarkup"
aria-expanded="false"
aria-label="Toggle navigation"
>
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNavAltMarkup">
<div class="navbar-nav">
<Link to="/" class="nav-link active" aria-current="page">
Home
</Link>
<Link to="/detail" class="nav-link active" aria-current="page">
Detail
</Link>
<Link to="/cart" className="nav-link active" aria-current="page">
Cart
</Link>
<Link
to="/company/manpower"
class="nav-link active"
aria-current="page"
>
Manpower
</Link>
<Link
to="/company/map"
class="nav-link active"
aria-current="page"
>
Map
</Link>
<Link to="/remove" class="nav-link active" aria-current="page">
account remove
</Link>
</div>
</div>
</div>
</nav>
<Routes>
<Route
path="/"
element={
<>
<div className="main-bg"></div>
<h1 className="my-5">Nike shop</h1>
<div className="d-flex flex-column mb-3">
{shoes.map((shoe, i) => {
return <Goods shoes={shoe} i={i}></Goods>;
})}
</div>
<button
onClick={() => {
axios
.get(
'https://raw.githubusercontent.com/lshjju/cdn/refs/heads/main/ca-shop/data2.json'
)
.then((data2) => {
console.log(data2.data);
let copy = [...shoes, ...data2.data];
setShoes(copy);
})
.catch(() => {
console.log('what the...');
});
}}
>
VIEW MORE
</button>
</>
}
/>
<Route path="/detail/:id" element={<Detail shoes={shoes} />} />
<Route path="/cart" element={<Cart />} />
<Route path="/company" element={<Company />}>
<Route path="manpower" element={<Manpower />} />
<Route path="map" element={<Map />} />
</Route>
<Route path="*" element={<Nopage />} />
<Route path="/remove" element={<Remove />} />
</Routes>
<div class="card m-5">
<div class="card-header">Featured</div>
<div class="card-body">
<h5 class="card-title">Special title treatment</h5>
<p class="card-text">
With supporting text below as a natural lead-in to additional
content.
</p>
<a href="#" class="btn btn-primary">
Go somewhere
</a>
</div>
</div>
</div>
);
}
function Goods(props) {
return (
<div className="p-2">
<img
src={
'https://raw.githubusercontent.com/lshjju/cdn/refs/heads/main/ca-shop/s' +
(props.i + 1) +
'.PNG'
}
width="80%"
/>
<h4 className="my-3">{props.shoes.title}</h4>
<p>{props.shoes.price}</p>
</div>
);
}
function Company() {
return (
<div>
<h4 className="my-3">company</h4>
<p>It's a company</p>
<Outlet></Outlet>
</div>
);
}
function Manpower() {
return (
<div>
<img
src="https://plus.unsplash.com/premium_photo-1688821131205-52f5c633ce69?q=80&w=2070&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
width="80%"
/>
</div>
);
}
function Map() {
return (
<div>
<img
src="https://images.unsplash.com/photo-1548345680-f5475ea5df84?q=80&w=2073&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
width="80%"
/>
</div>
);
}
function Nopage() {
return (
<div>
<h4 className="my-2">No page</h4>
<p>hmmm....</p>
<img
src="https://cdn.maily.so/ixmvzk5qh83mee5kcjw8pp55fihe"
width="80%"
/>
</div>
);
}
App.jsx
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import './index.css';
import App from './App.jsx';
import { BrowserRouter } from 'react-router-dom';
import { Provider } from "react-redux";
import Store from "./Store";
createRoot(document.getElementById('root')).render(
<Provider store={Store}>
<BrowserRouter>
<App />
</BrowserRouter>
</Provider>
);
main.jsx
let data = [
{
id: 0,
title: "White and Black",
content: "Born in France",
price: 120000,
},
{
id: 1,
title: "Red Knit",
content: "Born in Seoul",
price: 110000,
},
{
id: 2,
title: "Grey Yordan",
content: "Born in the States",
price: 130000,
},
];
export default data;
data.jsx
import { createSlice, configureStore } from '@reduxjs/toolkit';
let user = createSlice({
name: 'userss',
initialState: 'kim',
});
let cart = createSlice({
name: 'cartss',
initialState: [
{ id: 0, name: 'White and Black', count: 2 },
{ id: 2, name: 'Grey Yordan', count: 1 },
],
reducers: {
addCount(state, action) {
let cartId = state.findIndex((a) => {
return a.id === action.payload;
});
state[cartId].count++;
},
addItem(state, action) {
state.push(action.payload);
},
},
});
export default configureStore({
reducer: {
users: user.reducer,
carts: cart.reducer,
},
});
export let { addCount, addItem } = cart.actions;
Store.jsx
import { useParams } from 'react-router-dom';
import { addItem } from '../Store';
import { useDispatch } from 'react-redux';
export default function Detail(props) {
let { id } = useParams();
console.log(id);
let dataId = props.shoes.find((x) => x.id == id);
let dispatch = useDispatch();
return (
<div className="container">
<div className="row">
<div className="col-md-6">
<img
src={
'https://raw.githubusercontent.com/lshjju/cdn/refs/heads/main/ca-shop/s' +
(dataId.id + 1) +
'.PNG'
}
width="100%"
/>
</div>
<div className="col-md-6">
<h4 className="pt-5">{dataId.title}</h4>
<p>{dataId.content}</p>
<p>{dataId.price}</p>
<button
className="btn btn-danger"
onClick={() => {
dispatch(addItem({ id: 1, name: 'Red Knit', count: 1 }));
}}
>
CART
</button>
</div>
</div>
</div>
);
}
Detail.jsx
import { useSelector, useDispatch } from "react-redux";
import { addCount } from "../Store";
export default function Cart() {
let states = useSelector((state) => state);
// console.log(states);
// console.log(states.users);
// console.log(states.carts);
let dispatch = useDispatch();
return (
<div className="container">
<h2 className="my-4">Your cart</h2>
<table class="table table-striped">
<thead>
<tr>
<th scope="col">No</th>
<th scope="col">Title</th>
<th scope="col">Count</th>
<th scope="col">Change</th>
</tr>
</thead>
<tbody>
{states.carts.map((item, index) => (
<tr key={index}>
<th scope="row">{item.id}</th>
<td>{item.name}</td>
<td>{item.count}</td>
<td>
<button
onClick={() => {
dispatch(addCount(item.id));
}}
>
+
</button>
</td>
</tr>
))}
</tbody>
</table>
</div>
);
}
Cart.jsx
import { useState } from "react";
import { useEffect } from "react";
export default function Remove() {
let [modals, setModals] = useState(true);
useEffect(() => {
let a = setTimeout(() => {
setModals(false);
}, 2000);
return () => {
clearTimeout(a);
};
}, []);
return (
<div className="container">
{modals == true ? (
<div className="bg-warning p-4">
<h2 style={{ marginBottom: "400px" }}>
If you want remove your account please tab button{" "}
</h2>
<button>remove</button>
</div>
) : null}
<h2 className="my-2">sorry time out</h2>
<img
src="https://mblogthumb-phinf.pstatic.net/MjAyMjA3MDhfMjM1/MDAxNjU3MjY2NDMwMTUw.TMpPAEviN8RMubZbZS_qtyHYVh9oc8XCGGTm7Qc2EhAg.2HNlyzepoH0sbkNazZGpBBPQ0u2loljFcHOwfvJJo8cg.JPEG.ahtskswl/%25EB%258B%25A4%25EC%259A%25B4%25EB%25A1%259C%25EB%2593%259C_(17).jpg?type=w966"
width="100%"
/>
</div>
);
}
Remove.jsx
.App {
font-family: sans-serif;
text-align: center;
}
.main-bg {
height: 300px;
background-image: url("https://raw.githubusercontent.com/lshjju/cdn/refs/heads/main/ca-shop/s-main2.PNG");
background-size: cover;
background-position: center;
}
App.css
/* null */
index.css

'Index' 카테고리의 다른 글
| Product detail page design Index (0) | 2025.11.21 |
|---|---|
| Next.js project index (0) | 2025.09.27 |
| Do it! 자바스크립트 웹 표준의 정석 (0) | 2025.08.11 |
| 생활코딩! React 리액트 프로그래밍 index (0) | 2025.06.20 |
| UI Design project index (0) | 2025.06.17 |