[TIL] 12주차 금요일. 알고리즘 탐험반 - 리스트 요소 순서 변경하기

Minji Kim·2024년 7월 7일

내배캠TIL

목록 보기
54/73

문제 1. 단순 순서 변경

위로 / 아래로 버튼을 눌러서 순서 변경!!

import { useState } from "react";
import { MOCK_DATA } from "./MOCK_DATA.js";

const ChangeListOrder = () => {
  const [pokemonData, setPokemonData] = useState(MOCK_DATA);

  // TODO '위로' 버튼을 눌렀을 때, 실행되는 로직을 작성합니다. 첫 번째 아이템은 위로 이동 할 수 없음을 기억해주세요!
  const moveItemUp = (i) => {
    if (i === 0) return;

    setPokemonData((prevPokemonData) => {
      const newPokemonData = [...prevPokemonData];
      [newPokemonData[i - 1], newPokemonData[i]] = [
        newPokemonData[i],
        newPokemonData[i - 1],
      ];
      return newPokemonData;
    });
  };

  // TODO '아래' 버튼을 눌렀을 때, 실행되는 로직을 작성합니다. 마지막 아이템은 아래로 이동 할 수 없음을 기억해주세요!
  const moveItemDown = (i) => {
    if (i === pokemonData.length - 1) return;

    setPokemonData((prevPokemonData) => {
      const newPokemonData = [...prevPokemonData];
      [newPokemonData[i], newPokemonData[i + 1]] = [
        newPokemonData[i + 1],
        newPokemonData[i],
      ];
      return newPokemonData;
    });
  };

  return (
    <div className="container mx-auto">
      <h2 className="w-full text-center py-10">리스트 순서 바꾸기</h2>
      <div className="flex flex-col gap-2">
        {/* TODO Index 도 필요하다면, 수정해주세요 */}
        {pokemonData.map((pokemon, index) => (
          <div
            key={index}
            className="pokemon p-4 border rounded-lg flex justify-between"
          >
            <div>
              <img
                src={pokemon.sprites.front_default}
                alt={pokemon.korean_name}
              />
              <p>{pokemon.korean_name}</p>
              <p>도감번호: {pokemon.id}</p>
            </div>
            <div className="flex gap-5 items-center">
              {/* TODO moveItemUp 함수에 매개변수로 넣어주고 싶은게 있으시면 추가 시키셔도 됩니다. */}
              <button
                className="bg-brand h-10 p-2 rounded text-[#ffffff] font-bold"
                onClick={() => moveItemUp(index)}
              >
                위로
              </button>
              {/* TODO moveItemDown 함수에 매개변수로 넣어주고 싶은게 있으시면 추가 시키셔도 됩니다. */}
              <button
                className="bg-state-warning h-10 p-2 rounded text-[#ffffff] font-bold"
                onClick={() => moveItemDown(index)}
              >
                아래로
              </button>
            </div>
          </div>
        ))}
      </div>
    </div>
  );
};

export default ChangeListOrder;

문제 2. 순서 변경: 수정, 저장, 취소 버튼으로

[수정] -> 수정 화면으로 변경
[위로] / [아래로] 버튼을 눌러서 순서 변경
[완료] -> 변경된 순서로 저장
[취소] -> [수정] 누르기 전 상태로 되돌아감

import { useState } from "react";
import { MOCK_DATA } from "./MOCK_DATA.js";

const ChangeListOrderAdvanced = () => {
  const [pokemonData, setPokemonData] = useState(MOCK_DATA);
  const [isEditMode, setIsEditMode] = useState(false);
  const [editedPokemonData, setEditedPokemonData] = useState([...pokemonData]);

  // TODO '위로' 버튼을 눌렀을 때, 실행되는 로직을 작성합니다. 첫 번째 아이템은 위로 이동 할 수 없음을 기억해주세요!
  const moveItemUp = (i) => {
    if (i === 0) return;

    setEditedPokemonData((prevPokemonData) => {
      const newPokemonData = [...prevPokemonData];
      [newPokemonData[i - 1], newPokemonData[i]] = [
        newPokemonData[i],
        newPokemonData[i - 1],
      ];
      return newPokemonData;
    });
  };

  // TODO '아래' 버튼을 눌렀을 때, 실행되는 로직을 작성합니다. 마지막 아이템은 아래로 이동 할 수 없음을 기억해주세요!
  const moveItemDown = (i) => {
    if (i === pokemonData.length - 1) return;

    setEditedPokemonData((prevPokemonData) => {
      const newPokemonData = [...prevPokemonData];
      [newPokemonData[i], newPokemonData[i + 1]] = [
        newPokemonData[i + 1],
        newPokemonData[i],
      ];
      return newPokemonData;
    });
  };

  // TODO 변경 완료가 되었을 떄 로직을 작성해 주세요.
  const handleSubmit = () => {
    setPokemonData(editedPokemonData);
    setIsEditMode(false);
  };

  const toggleEditMode = () => {
    setIsEditMode((prevState) => {
      if (prevState) {
        setPokemonData(pokemonData);
      }
      return !prevState;
    });
  };

  return (
    <div className="container mx-auto">
      <h2 className="w-full text-center py-10">리스트 순서 바꾸기</h2>
      <div className="flex gap-2 justify-end pb-4">
        {isEditMode ? (
          <>
            {/* TODO 취소가 눌렸을 때 단순히, toggleEdit 을 불러주기 싫을 수도 있을 것 같아요. 마음대로 리팩토링 하셔도 됩니다. */}
            <button
              className="bg-state-error h-10 p-2 rounded text-[#ffffff] font-bold"
              onClick={toggleEditMode}
            >
              취소
            </button>
            {/* TODO 함수에 매개변수로 넣어주고 싶은게 있으시면 추가 시키셔도 됩니다. */}
            <button
              className="bg-section h-10 p-2 rounded text-[#ffffff] font-bold"
              onClick={() => {
                handleSubmit();
              }}
            >
              완료
            </button>
          </>
        ) : (
          <button
            className="bg-brand h-10 p-2 rounded text-[#ffffff] font-bold"
            onClick={toggleEditMode}
          >
            수정
          </button>
        )}
      </div>
      <div className="flex flex-col gap-2">
        {/* TODO Index 도 필요하다면, 수정해주세요 */}
        {editedPokemonData.map((pokemon, index) => (
          <div
            key={index}
            className="pokemon p-4 border rounded-lg flex justify-between"
          >
            <div>
              <img
                src={pokemon.sprites.front_default}
                alt={pokemon.korean_name}
              />
              <p>{pokemon.korean_name}</p>
              <p>도감번호: {pokemon.id}</p>
            </div>
            {isEditMode ? (
              <div className="flex gap-5 items-center">
                {/* TODO moveItemUp 함수에 매개변수로 넣어주고 싶은게 있으시면 추가 시키셔도 됩니다. */}
                <button
                  className="bg-brand h-10 p-2 rounded text-[#ffffff] font-bold"
                  onClick={() => moveItemUp(index)}
                >
                  위로
                </button>
                {/* TODO moveItemDown 함수에 매개변수로 넣어주고 싶은게 있으시면 추가 시키셔도 됩니다. */}
                <button
                  className="bg-state-warning h-10 p-2 rounded text-[#ffffff] font-bold"
                  onClick={() => moveItemDown(index)}
                >
                  아래로
                </button>
              </div>
            ) : null}
          </div>
        ))}
      </div>
    </div>
  );
};

export default ChangeListOrderAdvanced;

메모

지금 작은 사이드 프로젝트 기획 중인데, 딱 적용하기 좋은 문제였다.
사이드 프로젝트에선 버튼 클릭 대신 블록을 끌어서 순서를 바꿀 수 있는 로직을 구현해볼 계획이다.

0개의 댓글