const express = require('express');
const app = express();
const port = 3000

app.use(express.urlencoded({extended: false}));
app.use(express.json());

app.use(express.static('public'));

app.use((req, res, next) => {
    //console.log(req);

    next(); // to the next middleware
})

app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');

app.get('/', (req, res) => {
    res.send('<a href="/goods"> go to shopping mall </a>');
});

app.use('/goods', require('./routes/goods'));
app.use('/user', require('./routes/user'));

app.listen(port, () => {
    console.log(`listening at <http://localhost>:${port}`);
});
const express = require('express');
const router = express.Router();

router.get('/', (req, res, next) => {
    res.render('index');
});

router.get('/detail', (req, res, next) => {
    let goodsId = req.query.goodsId;

    res.render('detail', {goodsId});
});

module.exports = router;
const express = require('express')
const router = express.Router();

router.get('/login', (req, res, next) => {
    res.send('LOGIN');
});

router.get('/register', (req, res, next) => {
    res.send('REGISTER');
});

module.exports = router;
<!doctype html>
<html lang="en">

<head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <link rel="icon" href="/static/favicon.ico" type="image/x-icon">
    <link rel="shortcut icon" href="/static/favicon.ico" type="image/x-icon">
    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="<https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css>"
        integrity="sha384-TX8t27EcRE3e/ihU7zmQxVncDAy5uIKz4rEkgIXeMed4M0jlfIDPvg6uqKI2xXr2" crossorigin="anonymous">

    <!-- Font Awesome CSS -->
    <link href="//maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
    <!-- Optional JavaScript -->
    <!-- jQuery first, then Popper.js, then Bootstrap JS -->
    <script src="<https://code.jquery.com/jquery-3.5.1.js>"
        integrity="sha256-QWo7LDvxbWT2tbbQ97B53yJnYU3WhH/C8ycbRAkjPDc=" crossorigin="anonymous"></script>
    <script src="<https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js>"
        integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN"
        crossorigin="anonymous"></script>
    <script src="<https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js>"
        integrity="sha384-w1Q4orYjBQndcko6MimVbzY0tgp4pWB4lZ7lr30WKz0vr/aWKhXdBNmNb5D92v7s"
        crossorigin="anonymous"></script>
    <script src="<https://cdnjs.cloudflare.com/ajax/libs/jquery-cookie/1.4.1/jquery.cookie.js>"></script>
    <script src="<https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.4.0/socket.io.js>"></script>

    <link href="/static/mystyle.css" rel="stylesheet">
    <title>스파르타 쇼핑몰 | 상품 목록</title>
    <script>

        $(document).ready(function () {
            get_goods()
            $("#categorySelect").on("change", function () {
                get_goods($(this).val())
            })
        })

        function sign_out() {
            $.removeCookie('mytoken', { path: '/' });
            $.removeCookie('userName', { path: '/' });
            window.location.href = "/"
        }

        function get_goods(category) {
            $("#goodsList").empty()
            console.log(category)
            let goods = [
                {
                    "_id": "600fa6e49539b288e3c5a2cf",
                    "goodsId": 4,
                    "name": "상품 4",
                    "thumbnailUrl": "<https://cdn.pixabay.com/photo/2016/09/07/02/11/frogs-1650657_1280.jpg>",
                    "category": "drink",
                    "price": 0.1
                },
                {
                    "_id": "600fa6e49539b288e3c5a2ce",
                    "goodsId": 3,
                    "name": "상품 3",
                    "thumbnailUrl": "<https://cdn.pixabay.com/photo/2016/09/07/02/12/frogs-1650658_1280.jpg>",
                    "category": "drink",
                    "price": 2.2
                },
                {
                    "_id": "600fa6e49539b288e3c5a2cd",
                    "goodsId": 2,
                    "name": "상품 2",
                    "thumbnailUrl": "<https://cdn.pixabay.com/photo/2014/08/26/19/19/wine-428316_1280.jpg>",
                    "category": "drink",
                    "price": 0.11
                },
                {
                    "_id": "600fa6e49539b288e3c5a2cc",
                    "goodsId": 1,
                    "name": "상품 1",
                    "thumbnailUrl": "<https://cdn.pixabay.com/photo/2016/09/07/19/54/wines-1652455_1280.jpg>",
                    "category": "drink",
                    "price": 6.2
                }
            ]
            for (let i = 0; i < goods.length; i++) {
                make_card(goods[i])
            }
        }

        function make_card(item) {
            let htmlTemp = `<div>
                                    <div class="card mb-2" onclick="location.href='/goods/detail?goodsId=${item["goodsId"]}'">
                                        <div class="row no-gutters">
                                            <div class="col-sm-5" style="background: #868e96;">
                                                <img src="${item["thumbnailUrl"]}"
                                                     class="card-img-top h-100" alt="...">
                                            </div>
                                            <div class="col-sm-7 d-flex">
                                                <div class="card-body flex-fill">
                                                    <div class="card-title mb-auto">
                                                        <h5 style="display: inline">${item["name"]}</h5>
                                                        <span class="card-price ml-2">$${number2decimals(item["price"])}</span>
                                                    </div>
                                                    <span class="badge badge-secondary">${item["category"]}</span>
                                                    <!--                                <p class="card-text"><small class="text-muted">drink</small></p>-->
                                                </div>
                                            </div>
                                        </div>
                                    </div>
                                </div>`
            $("#goodsList").append(htmlTemp)
        }

        function makeNoti(data) {
            let htmlTemp = `<div class="alert alert-sparta alert-dismissible show fade" role="alert" id="customerAlert">
                                    ${data["userName"]}님이 방금 <a href="#" class="alert-link">${data["goodsName"]}</a>을 구매했어요!
                                    <button type="button" class="close" data-dismiss="alert" aria-label="Close">
                                        <span aria-hidden="true">&times;</span>
                                    </button>
                                </div>`
            $("body").append(htmlTemp)
        }

        function number2decimals(num) {
            return (Math.round(num * 100) / 100).toFixed(2);
        }
    </script>
    <style>
        .card {
            cursor: pointer;
        }

        html {
            overflow: auto;
        }
    </style>
</head>

<body>
    <nav class="navbar navbar-expand-sm navbar-dark bg-sparta justify-content-end">
        <a class="navbar-brand" href="/goods">
            <img src="/static/logo_big_tr.png" width="30" height="30" class="d-inline-block align-top" alt="">
            스파르타 쇼핑몰
        </a>
        <button class="navbar-toggler ml-auto" type="button" data-toggle="collapse"
            data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="true"
            aria-label="Toggle navigation"><span class="navbar-toggler-icon"></span></button>
        <div class="navbar-collapse collapse flex-grow-0 ml-auto" id="navbarSupportedContent" style="">
            <ul class="navbar-nav mr-auto text-right">
                <li class="nav-item" id="link-cart">
                    <a class="nav-link" href="/cart">
                        장바구니<i class="fa fa-shopping-cart ml-2" aria-hidden="true"></i>
                    </a>
                </li>
                <li class="nav-item" id="link-logout">
                    <a class="nav-link" data-toggle="modal" data-target="#signOutModal">
                        로그아웃<i class="fa fa-sign-out ml-2" aria-hidden="true"></i>
                    </a>
                    <div class="modal text-left" id="signOutModal" tabindex="-1" role="dialog"
                        aria-labelledby="signOutModalLabel" aria-hidden="true">
                        <div class="modal-dialog" role="document">
                            <div class="modal-content">
                                <div class="modal-header">
                                    <h5 class="modal-title" id="signOutModalLabel">로그아웃</h5>
                                    <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                                        <span aria-hidden="true">&times;</span>
                                    </button>
                                </div>
                                <div class="modal-body">
                                    로그아웃하시면 장바구니가 사라져요!
                                </div>
                                <div class="modal-footer">
                                    <button type="button" class="btn btn-outline-sparta" data-dismiss="modal">취소
                                    </button>
                                    <button type="button" class="btn btn-sparta" onclick="sign_out()">로그아웃하기
                                    </button>
                                </div>
                            </div>
                        </div>
                    </div>
                </li>
            </ul>
        </div>

    </nav>
    <div class="wrap">
        <div>
            <div class="form-group row mr-0">
                <label for="categorySelect" class="col-4 col-form-label">카테고리</label>
                <select class="form-control col-8" id="categorySelect">
                    <option value="" selected>전체</option>
                    <option value="drink">음료</option>
                    <option value="food">음식</option>
                </select>
            </div>
        </div>
        <div id="goodsList" class="mb-5">
            <div>
                <div class="card mb-2" onclick="location.href='#'">
                    <div class="row no-gutters">
                        <div class="col-sm-5" style="background: #868e96;">
                            <img src="<https://cdn.pixabay.com/photo/2016/09/07/19/54/wines-1652455_1280.jpg>"
                                class="card-img-top h-100" alt="...">
                        </div>
                        <div class="col-sm-7 d-flex">
                            <div class="card-body flex-fill">
                                <div class="card-title mb-auto">
                                    <h5 style="display: inline">상품 1</h5>
                                    <span class="card-price ml-2">$6.20</span>

                                </div>
                                <span class="badge badge-secondary">drink</span>
                                <!--                                <p class="card-text"><small class="text-muted">drink</small></p>-->
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>

</body>

</html>
<!DOCTYPE html>
<html lang="en">
  <head>
    <!-- Required meta tags -->
    <meta charset="utf-8" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1, shrink-to-fit=no"
    />
    <link rel="icon" href="/static/favicon.ico" type="image/x-icon" />
    <link rel="shortcut icon" href="/static/favicon.ico" type="image/x-icon" />
    <!-- Bootstrap CSS -->
    <link
      rel="stylesheet"
      href="<https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css>"
      integrity="sha384-TX8t27EcRE3e/ihU7zmQxVncDAy5uIKz4rEkgIXeMed4M0jlfIDPvg6uqKI2xXr2"
      crossorigin="anonymous"
    />

    <!-- Font Awesome CSS -->
    <link
      href="//maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"
      rel="stylesheet"
    />
    <!-- Optional JavaScript -->
    <!-- jQuery first, then Popper.js, then Bootstrap JS -->
    <script
      src="<https://code.jquery.com/jquery-3.5.1.js>"
      integrity="sha256-QWo7LDvxbWT2tbbQ97B53yJnYU3WhH/C8ycbRAkjPDc="
      crossorigin="anonymous"
    ></script>
    <script
      src="<https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js>"
      integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN"
      crossorigin="anonymous"
    ></script>
    <script
      src="<https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js>"
      integrity="sha384-w1Q4orYjBQndcko6MimVbzY0tgp4pWB4lZ7lr30WKz0vr/aWKhXdBNmNb5D92v7s"
      crossorigin="anonymous"
    ></script>
    <script src="<https://cdnjs.cloudflare.com/ajax/libs/jquery-cookie/1.4.1/jquery.cookie.js>"></script>

    <link href="/static/mystyle.css" rel="stylesheet" />
    <script>
      const queryString = window.location.search;
      const urlParams = new URLSearchParams(queryString);
      const goodsId = urlParams.get("goodsId");

      $(document).ready(function() {
        get_detail();
        $("#numberSelect").on("change", function() {
          let orderNum = parseInt($(this).val());
          $("#orderNumber").html(
            `<small class="mr-2 text-muted">총 수량 ${orderNum}개</small>${number2decimals(
              orderNum * sessionStorage.getItem("goodsPrice")
            )}`
          );
          sessionStorage.setItem("orderNum", orderNum);
        });
      });

      function sign_out() {
        $.removeCookie("mytoken", { path: "/" });
        $.removeCookie("userName", { path: "/" });
        window.location.href = "/";
      }

      function get_detail() {
        let goods = [
                {
                    "_id": "600fa6e49539b288e3c5a2cf",
                    "goodsId": 4,
                    "name": "상품 4",
                    "thumbnailUrl": "<https://cdn.pixabay.com/photo/2016/09/07/02/11/frogs-1650657_1280.jpg>",
                    "category": "drink",
                    "price": 0.1
                },
                {
                    "_id": "600fa6e49539b288e3c5a2ce",
                    "goodsId": 3,
                    "name": "상품 3",
                    "thumbnailUrl": "<https://cdn.pixabay.com/photo/2016/09/07/02/12/frogs-1650658_1280.jpg>",
                    "category": "drink",
                    "price": 2.2
                },
                {
                    "_id": "600fa6e49539b288e3c5a2cd",
                    "goodsId": 2,
                    "name": "상품 2",
                    "thumbnailUrl": "<https://cdn.pixabay.com/photo/2014/08/26/19/19/wine-428316_1280.jpg>",
                    "category": "drink",
                    "price": 0.11
                },
                {
                    "_id": "600fa6e49539b288e3c5a2cc",
                    "goodsId": 1,
                    "name": "상품 1",
                    "thumbnailUrl": "<https://cdn.pixabay.com/photo/2016/09/07/19/54/wines-1652455_1280.jpg>",
                    "category": "drink",
                    "price": 6.2
                }
            ]

        let goodsDetail = goods.find((v) => v.goodsId == goodsId);
        if (!goodsDetail) {
            goodsDetail = goods[0]
        }
        
        $("#goodsUrl").attr("src", goodsDetail["thumbnailUrl"]);
        $("#goodsName").text(goodsDetail["name"]);
        $("#goodsPrice").text("$" + number2decimals(goodsDetail["price"]));

        sessionStorage.setItem("goodsId", goodsId);
        sessionStorage.setItem("goodsName", goodsDetail["name"]);
        sessionStorage.setItem("goodsPrice", goodsDetail["price"]);
        sessionStorage.setItem("orderNum", 1);
      }

      function addCart() {
        $.ajax({
          type: "POST",
          url: `/api/goods/${goodsId}/cart`,
          data: {
            quantity: sessionStorage.getItem("orderNum")
          },
          error: function(xhr, status, error) {
            if (status == 400) {
              alert("존재하지 않는 상품입니다.");
            }
            window.location.href = "/goods";
          },
          success: function(response) {
            if (response["result"] == "success") {
              $("#cartModal").modal("show");
            }
          }
        });
      }

      function buyNow() {
        sessionStorage.setItem(
          "priceSum",
          sessionStorage.getItem("goodsPrice")
        );
        sessionStorage.setItem(
          "cart",
          JSON.stringify([
            {
              goodsName: sessionStorage.getItem("goodsName"),
              quantity: sessionStorage.getItem("orderNum")
            }
          ])
        );
        window.location.href = "/order";
      }

      function number2decimals(num) {
        return (Math.round(num * 100) / 100).toFixed(2);
      }
    </script>
    <title>스파르타 쇼핑몰 | 상품 상세</title>

    <style></style>
  </head>

  <body>
    <nav
      class="navbar navbar-expand-sm navbar-dark bg-sparta justify-content-end"
    >
      <a class="navbar-brand" href="/goods">
        <img
          src="/static/logo_big_tr.png"
          width="30"
          height="30"
          class="d-inline-block align-top"
          alt=""
        />
        스파르타 쇼핑몰
      </a>
      <button
        class="navbar-toggler ml-auto"
        type="button"
        data-toggle="collapse"
        data-target="#navbarSupportedContent"
        aria-controls="navbarSupportedContent"
        aria-expanded="true"
        aria-label="Toggle navigation"
      >
        <span class="navbar-toggler-icon"></span>
      </button>
      <div
        class="navbar-collapse collapse flex-grow-0 ml-auto"
        id="navbarSupportedContent"
        style=""
      >
        <ul class="navbar-nav mr-auto text-right">
          <li class="nav-item" id="link-cart">
            <a class="nav-link" href="/cart">
              장바구니<i
                class="fa fa-shopping-cart ml-2"
                aria-hidden="true"
              ></i>
            </a>
          </li>
          <li class="nav-item" id="link-logout">
            <a class="nav-link" data-toggle="modal" data-target="#signOutModal">
              로그아웃<i class="fa fa-sign-out ml-2" aria-hidden="true"></i>
            </a>
            <div
              class="modal text-left"
              id="signOutModal"
              tabindex="-1"
              role="dialog"
              aria-labelledby="signOutModalLabel"
              aria-hidden="true"
            >
              <div class="modal-dialog" role="document">
                <div class="modal-content">
                  <div class="modal-header">
                    <h5 class="modal-title" id="signOutModalLabel">로그아웃</h5>
                    <button
                      type="button"
                      class="close"
                      data-dismiss="modal"
                      aria-label="Close"
                    >
                      <span aria-hidden="true">&times;</span>
                    </button>
                  </div>
                  <div class="modal-body">
                    로그아웃하시면 장바구니가 사라져요!
                  </div>
                  <div class="modal-footer">
                    <button
                      type="button"
                      class="btn btn-outline-sparta"
                      data-dismiss="modal"
                    >
                      취소
                    </button>
                    <button
                      type="button"
                      class="btn btn-sparta"
                      onclick="sign_out()"
                    >
                      로그아웃하기
                    </button>
                  </div>
                </div>
              </div>
            </div>
          </li>
        </ul>
      </div>
    </nav>
    <div class="wrap">
      <div class="row no-gutters">
        <div class="col-sm-5">
          <img
            src="<https://cdn.pixabay.com/photo/2016/09/07/19/54/wines-1652455_1280.jpg>"
            class="card-img-top h-100"
            alt="..."
            id="goodsUrl"
          />
        </div>
        <div class="col-sm-7 card-body px-3">
          <div class="flex-fill mt-3">
            <div class="d-flex justify-content-between mb-3">
              <h5 style="display: inline" id="goodsName">상품 1</h5>
              <span class="card-price" id="goodsPrice">$6.20</span>
            </div>

            <div class="form-group row mr-0">
              <label for="numberSelect" class="col-4 col-form-label"
                >수량</label
              >
              <select class="custom-select col-8" id="numberSelect">
                <option selected value="1">1개</option>
                <option value="2">2개</option>
                <option value="3">3개</option>
                <option value="4">4개</option>
                <option value="5">5개</option>
              </select>
            </div>
            <hr />
            <div class="row mb-3">
              <div class="col-5">총 상품금액</div>
              <div class="col-7 text-right" id="orderNumber">
                <small class="mr-2 text-muted">총 수량 1개</small>$6.20
              </div>
            </div>
            <div class="row d-flex justify-content-around">
              <div class="col-6 pr-2">
                <button
                  type="button"
                  class="btn btn-outline-sparta btn-block"
                  onclick="addCart()"
                >
                  장바구니
                </button>
              </div>
              <div class="col-6 pl-2">
                <button
                  type="button"
                  class="btn btn-sparta btn-block"
                  onclick="buyNow()"
                >
                  바로 구매
                </button>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
    <div
      class="modal text-left"
      id="cartModal"
      tabindex="-1"
      role="dialog"
      aria-labelledby="cartModalLabel"
      aria-hidden="true"
    >
      <div class="modal-dialog" role="document">
        <div class="modal-content">
          <div class="modal-header">
            <h5 class="modal-title" id="cartModalLabel">알림</h5>
            <button
              type="button"
              class="close"
              data-dismiss="modal"
              aria-label="Close"
            >
              <span aria-hidden="true">&times;</span>
            </button>
          </div>
          <div class="modal-body">
            장바구니에 담았습니다! 장바구니로 갈까요?
          </div>
          <div class="modal-footer">
            <button
              type="button"
              class="btn btn-outline-sparta"
              data-dismiss="modal"
            >
              취소
            </button>
            <button
              type="button"
              class="btn btn-sparta"
              onclick='window.location.href="/cart"'
            >
              장바구니
            </button>
          </div>
        </div>
      </div>
    </div>
  </body>
</html>