제품상세페이지떄도 느꼈지만 백엔드와는 더많이 소통해야하는구나를 느꼈다.

//order.js
import React, { useState, useEffect } from "react";
import "./Order.scss";
import Count from "../../components/Count/Count";
import { Link, useNavigate } from "react-router-dom";

const Order = () => {
  const [items, setItems] = useState([]);
  const [originalItems, setOriginalItems] = useState([]);
  const [users, setUsers] = useState([]);
  const [weights, setTotalWeight] = useState(0);
  const [prices, setTotalPrice] = useState(0);
  const navigate = useNavigate();

  //카트에 GET, PATCH
  useEffect(() => {
    fetch("./data/order.json")
      .then((res) => res.json())
      .then((data) => {
        setItems(data.data);
        setOriginalItems(data.data);
        setTotalWeight(calculateTotalWeight(data.data));
        setTotalPrice(calculateTotalPrice(data.data));
      });
  }, []);

  useEffect(() => {
    fetch("./data/user.json")
      .then((res) => res.json())
      .then((data) => setUsers(data.user));
  }, []);

  useEffect(() => {
    if (items.length === 0) {
      setTotalWeight(0);
      setTotalPrice(0);
    }
  }, [items]);

  const setCountArray = (itemId, count) => {
    setItems((prevItems) => {
      const updatedItems = prevItems.map((item) => {
        if (item.id === itemId) {
          const originalItem = originalItems.find((i) => i.id === itemId);
          const updatedItem = { ...item, count: count };
          updatedItem.weight = originalItem.weight * count;
          updatedItem.price = Number(originalItem.price) * count;
          return updatedItem;
        }
        return item;
      });

      setTotalWeight(calculateTotalWeight(updatedItems));
      setTotalPrice(calculateTotalPrice(updatedItems));

      return updatedItems;
    });
  };

  const calculateTotalWeight = (items) => {
    return items.reduce((total, item) => total + Number(item.weight), 0);
  };

  const calculateTotalPrice = (items) => {
    return items.reduce((total, item) => total + Number(item.price), 0);
  };

  const [inputValues, setInputValues] = useState({});
  const handleInputValue = (e) => {
    const { name, value } = e.target;
    setInputValues((prevValues) => ({
      ...prevValues,
      [name]: value,
    }));
  };
  const totalWeight = weights;
  const showAlert = totalWeight > 1000;

  const onRemove = (itemId) => {
    setItems((prevItems) => {
      const itemsFilter = prevItems.filter((data) => data.id !== itemId);
      setTotalWeight(calculateTotalWeight(itemsFilter));
      setTotalPrice(calculateTotalPrice(itemsFilter));
      return itemsFilter;
    });
  };

  //order에 POST
  const postProduct = () => {
    fetch("api/oder/주문번호", {
      method: "POST",
      headers: {
        "Content-Type": "application/json;charset=utf-8",
      },
      body: JSON.stringify({
        address: inputValues.address,
        total_price: prices,
        total_weight: weights,
      }),
    })
      .then((res) => {
        return res.json();
      })
      .then((data) => {
        if (data.message === "CREATE_USER_SUCCESS!") {
          navigate("/orderResult");
        } else if (data.message === "백엔드 메세지") {
          alert("구매에 실패하였습니다.");
        }
      });
  };

  return (
    <div className="order">
      {users.map((el) => (
        <div className="buyerInfo" key={el.id}>
          <h1>주문자 정보</h1>
          <p className="userInfo"> {el.name} </p>
          <div className="shippingAddress">
            <h2>주문을 어디로 보내시겠습니까?</h2>
            <div className="orderTypeName"> 이름</div>
            <input
              className="name input"
              name="name"
              placeholder="받으실 분 성함을 적어주세요"
              onChange={handleInputValue}
            />
            <div className="orderTypeName">주소</div>
            <input
              className="address input"
              placeholder="배송 상세주소를 적어주세요"
              name="address"
              onChange={handleInputValue}
            />
            <div className="orderTypeName">배송 요청</div>
            <input
              className="detailAddress input"
              placeholder="경비실에 맡겨주세요"
              name="memo"
              onChange={handleInputValue}
            />
          </div>
        </div>
      ))}
      <div className="perchaseBox">
        <div className="payBox">
          <div className="indexBox">
            <p className="resultText"> 최종가격</p>
            <p className="resultText">  무게</p>
          </div>
          <div className="final">
            <p className="resultText">{prices} </p>
            <p className="resultText">{weights} KG</p>
          </div>
        </div>
        {items.length === 0 && (
          <div className="orderEmpty">
            <p>구매할 물품이 없습니다.</p>
          </div>
        )}
        {items.map((el) => (
          <div className="total" key={el.id}>
            <div className="item">
              <img
                src={el.image_url}
                alt="perchaseProduct"
                className="perchaseImage"
              />
              <div className="perchaseOption">
                <p className="descriptionOption">{el.name}</p>
                <p className="descriptionOption">{el.surface_type_id}</p>
                <p className="descriptionOption">{el.sub_category_id}</p>
              </div>
              <div className="perchaseOption">
                <Count
                  className="count"
                  count={el.sell_counts}
                  setCount={(newCount) => setCountArray(el.id, newCount)}
                  isDisabled={showAlert}
                />
                <p className="descriptionOption">{el.weight} KG</p>
                <p className="descriptionOption">{Number(el.price)} </p>
              </div>
              <div className="deleteBox">
                <button
                  type="submit"
                  className="deleteButton"
                  onClick={() => onRemove(el.id)}
                >
                  
                </button>
              </div>
            </div>
          </div>
        ))}
        <div className="buttonBox">
          <button
            type="submit"
            className="payment"
            onClick={() => {
              navigate("/orderResult");
            }}
            disabled={showAlert}
          >
            결제하기
          </button>
          {items.length === 0 && (
            <button
              className="gotoHome"
              onClick={() => {
                navigate("/");
              }}
            >
              홈으로
            </button>
          )}
          {showAlert && (
            <div className="alertTextBox">
              <p className="alertText">
                무게는 1000Kg 이상 구매하실  없습니다.
              </p>
            </div>
          )}
        </div>
      </div>
    </div>
  );
};

export default Order;
//order.scss
.order {
  padding-top: 5em;
  display: flex;
  justify-content: space-between;
  height: 100vh;

  .buyerInfo {
    padding: 3em 5em;

    h1 {
      margin-bottom: 1em;
      font-size: 1.7em;
    }

    .userInfo {
      font-size: 1.3em;
      margin-bottom: 0.5em;
    }

    .shippingAddress {
      display: flex;
      flex-direction: column;
      padding-top: 4em;
      width: 40em;

      h2 {
        font-size: 1.7em;
        margin-bottom: 1.5em;
      }

      .orderTypeName {
        margin-top: 1em;
        color: #9888;
      }

      .input {
        font-size: 1em;
        width: 100%;
        height: 4em;
        border: none;
        border-bottom: 1px solid rgb(180, 180, 180);
        background-color: transparent;
        &:focus {
          outline: none;
        }
      }
    }
  }

  .perchaseBox {
    width: 50%;
    height: 100vh;
    padding: 3em;
    background-color: rgb(246, 239, 223);

    .payBox {
      display: flex;
      flex-direction: row;
      justify-content: space-between;
      padding-right: 1em;
      padding-bottom: 1em;
      border-bottom: 1px solid grey;

      .resultText {
        font-size: 1.3em;
        padding-bottom: 0.7em;
      }

      .final {
        text-align: end;
      }
    }
    .orderEmpty {
      display: flex;
      justify-content: center;
      align-items: center;
      width: 100%;
      margin: 0 auto;
      height: 20em;
      font-size: 1em;
    }
    .total {
      .indexBox {
        border-bottom: 1px solid grey;
      }

      .item {
        display: flex;
        flex-direction: row;
        justify-content: space-between;
        border-bottom: 1px solid rgb(180, 180, 180);
        padding: 1em 0;

        .perchaseImage {
          width: 5.4em;
        }
      }

      .perchaseOption {
        display: grid;
        grid-template-rows: auto;
        text-align: center;
        align-items: center;
        width: 1500px;
        margin: 0 auto;

        .count {
          margin: 0;
          align-items: center;
          justify-content: center;
        }
      }

      .deleteBox {
        .deleteButton {
          font-size: 1em;
          color: #333;
          background-color: transparent;
          border: none;
        }
      }
    }

    .buttonBox {
      display: flex;
      flex-direction: column;
      justify-content: space-between;
      padding: 1em;
      align-items: center;

      .alertTextBox {
        .alertText {
          margin-top: 2em;
          color: #ff0000;
        }
      }

      .payment {
        background-color: #333;
        border: 0;
        color: white;
        margin-top: 3em;
        width: 20em;
        height: 4em;
        position: relative;
      }

      .gotoHome {
        background-color: #333;
        border: 0;
        color: white;
        margin-top: 3em;
        width: 20em;
        height: 4em;
        position: absolute;
        z-index: 1;
      }
    }
  }
}
{
  "data": [
    {
      "id": "363",
      "sub_category_id": "600*1200*20",
      "surface_type_id": "HARD MATT",
      "name": "P_1_CTN_01",
      "weight": "30",
      "type": "천장용",
      "price": "10000.00",
      "sell_counts": "5",
      "image_url": "images/6.jpg"
    },
    {
      "id": "2",
      "sub_category_id": 2,
      "surface_type_id": 2,
      "name": "SDH211",
      "weight": "60",
      "price": "30000.00",
      "sell_counts": "3",
      "image_url": "images/11.jpg"
    },
    {
      "id": "3",
      "sub_category_id": 3,
      "surface_type_id": 3,
      "name": "SDdasdsa",
      "weight": "90",
      "price": "300000.00",
      "sell_counts": "7",
      "image_url": "images/11.jpg"
    }
  ]
}
{
  "user": [
    {
      "id": 123,
      "name": "김최이서",
      "email": "asdf@naver.com",
      "phoneNumber": "0104032321",
      "payWay": "Point",
      "receiveMan": "배송받을 사람",
      "deliveryLocation": "서울시 송파구 어쩌구 저쩌구",
      "deliveryRequest": "경비실에 맡겨주세요"
    }
  ]
}

//count.js
import React, { useState, useEffect } from "react";
import "./Count.scss";

const Count = ({ countNumber, setCount, isDisabled }) => {
  const [count, setInternalCount] = useState(Number(countNumber) || 1);

  useEffect(() => {
    setInternalCount(Number(countNumber) || 1);
  }, [countNumber]);

  const decrease = () => {
    if (count <= 1) {
      return;
    } else {
      const newCount = count - 1;
      setInternalCount(newCount);
      setCount(newCount);
    }
  };

  const increase = () => {
    const newCount = count + 1;
    setInternalCount(newCount);
    setCount(newCount);
  };

  return (
    <div className="count">
      <div className="countInput">
        <button onClick={decrease}>-</button>
        <div className="countInputText">{count}</div>
        <button onClick={increase} disabled={isDisabled}>
          +
        </button>
      </div>
    </div>
  );
};

export default Count;
//count.scss
.count {
  display: flex;
  height: 3em;
  gap: 10px;
  justify-content: flex-start;
  margin: 1.5em 0;

  &Input {
    display: flex;
    width: fit-content;
    height: 100%;
    padding: 8px;
    border-radius: 0.5em;
    gap: 8px;

    button {
      border: none;
      background-color: transparent;
      cursor: pointer;
      font-size: 1.3em;
    }

    &Text {
      width: 4em;
      height: 2em;
      border-width: 0 1px;
      text-align: center;
      padding-top: 0.5em;
      border: 1px solid rgb(199, 199, 199);
      border-radius: 0.5em;
    }
  }

  .resetBtn {
    width: 48px;
    height: 100%;
    border: 1px solid black;
    border-radius: 8px;
    background-color: transparent;
    cursor: pointer;
  }
}

카테고리:

업데이트:

댓글남기기