#4.Project(開発レビュー-サブスクリプションの管理と納期設定ページ)



カートページの実装後、購読管理ページは付加機能の実装事項として動作する.GETリクエストにより初回購読のユーザ情報と配送情報,および購読中の商品が表示され,定期配送サイクルの変更はPATCHリクエストにより変更の配送日時が伝達され,購読中の商品はDELETEリクエストにより削除される.カートページの後に購読管理ページを行うのは、最初の通信よりずっと簡単です.

「サブスクリプション管理と出荷サイクル設定」ページ



構成部品



「サブスクリプション管理と出荷サイクル設定」ページでは、SubscribeUserBox、SubscribeShipping、SubscribeCycle、SubscribeProductを使用してコンポーネントを細分化する複数のボックスに分割します.

Subscribe API GET

  useEffect(() => {
    fetch(API.SUBSCRIBE, {
      method: 'GET',
      headers: {
        Authorization: `Bearer ${sessionStorage.getItem('access_token')}`,
      },
    })
      .then(response => response.json())
      .then(data => {
        if (data.MESSAGE === 'INVALID_TOKEN') {
          alert('로그인이 필요합니다!');
          navigate('/signin');
          return;
        }
        if (data.RESULT.length === 0) {
          alert('구독중인 상품이 없습니다. 메인으로 이동합니다');
          navigate('/');
        } else {
          setSubscribeData(data.RESULT);
          setNextDeliveryDate(data.RESULT[0]?.next_ship_date);
          setDeliveryCycle(`${data.RESULT[0]?.interval}주 마다`);
          setNextPurchaseDate(data.RESULT[0]?.next_purchase_date);
        }
      });
  }, []);
当初,サブスクリプション中の商品,ユーザ情報,定期配送周期などの情報を受信するためにヘッダにトークンを入れ,サブスクリプションAPIにGET要求を出す.そしてメッセージに基づいてデータを送信します.MESSAGEが「INVALID TOKEN」の場合は、有効な土木工事データであっても登録ウィンドウにページを移動します.RESULT.lengthが0の場合、購読中の商品はないので、ホームページに切り替えます.購読中の商品があれば、それぞれのデータ情報を国の管理に組み入れる.

出荷サイクルの変更


「定期配送サイクル選択」ウィンドウでデフォルトの8週間間隔を変更する場合は、定期配送サイクルと次の配送日を画面に同時に表示します.
function SubscribeCycle({ setDeliveryCycle, setNextDeliveryDate }) {
  const cycle = [4, 12, 16];

  const navigate = useNavigate();

  const handleNextShipDate = week => {
    fetch(API.SUBSCRIBE, {
      method: 'PATCH',
      headers: {
        Authorization: `Bearer ${sessionStorage.getItem('access_token')}`,
      },
      body: JSON.stringify({
        interval: week,
      }),
    })
      .then(res => res.json())
      .then(data => {
        if (data.MESSAGE === 'INVALID_TOKEN') {
          alert('로그인이 필요합니다!');
          navigate('/signin');
          return;
        }
        data.MESSAGE === 'SUCCESS'
          ? setNextDeliveryDate(data.RESULT)
          : alert(data.MESSAGE);
      })
      .catch(error => alert(error));
  };

  return (
    <>
      <div className="cycleTitle">정기배송 주기</div>
      <div className="cycleBtn">
        {cycle.map(week => {
          return (
            <button
              key={week.id}
              onClick={() => {
                if (window.confirm(`정기배송 주기가 ${week}주로 바뀝니다.`)) {
                  setDeliveryCycle(`${week}주 마다`);
                  handleNextShipDate(week);
                } else {
                  return;
                }
              }}
            >
              {week}주마다
            </button>
          );
        })}
      </div>
      <div className="message">
        주기를 변경하더라도 다음 결제일은 변경되지 않습니다.
      </div>
    </>
  );
}
そこで,4,12,16週の変更可能な周期を含む配列を作成し,map法を用いて3つのUIを作成した.
次に、ボタンをクリックすると、「確認」ウィンドウで変更の有無を再度確認し、「OK」をクリックして「出荷サイクルステータス」deliveryCycleをクリックした数値に変更します.
PATCH要求を送信し、バックエンドで計算し、handleNextShipDateという関数を実行して出荷日データを受信します.
この関数は、クリック時に受信したweekというパラメータ間隔をbody,dataに送信します.MESSAGEがINVALID TOKENの場合はログインページに切り替え、SUCCESの場合は次の出荷日管理状態nextDeliveryDateの値を変更してログインします.

購読解除

<button
  className="subscribeCancel"
  onClick={() => fetchDelete(obj)}>
  x
</button>

......

const fetchDelete = obj => {
    window.confirm(`${obj.category_name} 제품구독을 취소하시겠습니까?`)
      ? fetch(`${API.SUBSCRIBE}?id=[${obj.subscribe_id}]`, {
          method: 'delete',
          headers: {
            Authorization: `Bearer ${sessionStorage.getItem('access_token')}`,
          },
        })
          .then(res => res.json())
          .then(data => {
            if (data.MESSAGE === 'INVALID_TOKEN') {
              alert('로그인이 필요합니다!');
              navigate('/signin');
              return;
            }
            data.MESSAGE === 'DELETED'
              ? handleDelete(obj.subscribe_id)
              : alert(data.MESSAGE);
          })
          .catch(error => alert(error))
      : setSubscribeData(subscribeData);
  };

  const handleDelete = productId => {
    const filteredProduct = subscribeData.filter(obj => {
      return obj.subscribe_id !== productId;
    });
    setSubscribeData(filteredProduct);
  };
購読中の商品のキャンセルはショッピングバスケットの削除とあまり変わらない.まず、「Xの購読解除」ボタンをクリックして、fetchDeleteという関数を実行してDELETE要求を送信し、パラメータとして製品データobjを次のように送信します.
その後、fetchDeleteはサブスクリプションを再度キャンセルするかどうかを尋ね、「OK」をクリックしてトークンをSubscribe APIに送信します.このAPIは、クエリー形式でパラメータとして受信したobjのsubscribe idとヘッダになります.MESSAGEが「INVALID TOKEN」の場合はログインウィンドウに切り替え、「DELETED」の場合はobjはサブスクリプション商品管理のステータス値を変更し、handleDeleteに再アップロードします.subscribe idをパラメータとして渡します.handleDeleteは、受信したパラメータsubscribe idを使用して新しい配列を作成し、その配列をsubscribeData stateに入れて再登録します.

product idフィルタの使用中に発生する問題


最初は、ショッピングバスケットの中の方法でproduct idを使ってフィルタリングしていましたが、問題が発生しました.同じ製品を2つ購入した場合、ユーザーが1つの購読をキャンセルしたい場合でも、2つの製品は削除され、この問題を解決するためにsubscribe idを使用してフィルタリングされます.また、当初はこの問題を防止するため、商品詳細ページでは、製品ごとに1つしか購読できませんでした.

subscribeDataの状態に応じて条件付きレンダリング




サブスクリプション商品とユーザ情報のSubscribeDataの状態長に応じて、異なる画面が表示されます.

出荷日、支払日などを00月00日に変換



次の配送日と決済日はこのように計算され、年-月-日の形で伝達されます.しかし、私の画面に必要な部分は月と日数しかかかりませんので、splitで区分して、次のようなインデックスしか使いませんでした.
<div className="shippingDate">
        <div className="manageDate">
          <h2>다음 결제일</h2>
          <p className="nextPurchaseDate">
            {nextPurchaseDate?.split('-')[1]}&nbsp;
            {nextPurchaseDate?.split('-')[2]}</p>
        </div>

        <div className="manageDate">
          <h2>정기배송 주기</h2>
          <p className="intervalDate">{deliveryCycle}</p>
        </div>

        <div className="manageDate">
          <h2>다음 배송일</h2>
          <p className="nextShipDate">
            {nextDeliveryDate?.split('-')[1]}&nbsp;
            {nextDeliveryDate?.split('-')[2]}</p>
        </div>
      </div>