Index

ca-index

lshjju 2025. 9. 18. 16:12

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