JOB

내 아들은 효자인가 #6 - Input 조작2

맹무 💦 2023. 2. 4. 23:10
728x90

저번에 예고했던 대로~

다른 컴포넌트에게 영향을 주는 이벤트들을 해보도록 하자~

 

< select >

이 부분

지금 보는 것과 같이 유닛과 아이돌이 따로 놀고 있는 것을 볼 수 있다.

유닛을 선택했을 때 소속 아이돌만 나오도록 바꿔보도록 하겠다~!

아이돌이 너무너무 많기 때문에... 일단은 유성대와 발키리로만 조작했다가 나중에 디비 연결하게 되면 넣어보도록 하자!

 

데이터를 어떻게 들여오면 좋을지 interface를 먼저 정의해보고, 그에 맞게 데이터를 설정했다.

// select item interface
interface SelectVal {
  value: string;
  name: string;
}
// 삭제 예정 =============
  const allIdol: SelectVal[] = [
    { value: "모리사와 치아키", name: "모리사와 치아키" },
    { value: "신카이 카나타", name: "신카이 카나타" },
    { value: "나구모 테토라", name: "나구모 테토라" },
    { value: "센고쿠 시노부", name: "센고쿠 시노부" },
    { value: "타카미네 미도리", name: "타카미네 미도리" },
    { value: "이츠키 슈", name: "이츠키 슈" },
    { value: "카게히라 미카", name: "카게히라 미카" },
  ];
  const ryuseitai: SelectVal[] = [
    { value: "모리사와 치아키", name: "모리사와 치아키" },
    { value: "신카이 카나타", name: "신카이 카나타" },
    { value: "나구모 테토라", name: "나구모 테토라" },
    { value: "센고쿠 시노부", name: "센고쿠 시노부" },
    { value: "타카미네 미도리", name: "타카미네 미도리" },
  ];
  const valkyrie: SelectVal[] = [
    { value: "이츠키 슈", name: "이츠키 슈" },
    { value: "카게히라 미카", name: "카게히라 미카" },
  ];

  // //삭제 예정 =============

 

그리고 아이돌 선택 부분의 목록이 계속 변경될 것이기 때문에 그 부분을 따로 state로 선언했다.

  // select 목록
  const [selectIdol, setSelectIdol] = useState<SelectVal[]>(allIdol);

대분류의 초기값이 전체이기 때문에 소분류도 그에 맞게 전체 목록을 불러오도록 하였다.

 

이제 대분류가 변경될 때마다 목록이 바뀌어야 하기 때문에, 대분류가 바뀔 때(onChange) 소분류의 목록을 가져오도록 코드를 추가해준다.

 <Select
    labelId="selectUnitLabel"
    id="selectUnit"
    label="Unit"
    value={unit}
    onChange={(event: SelectChangeEvent<string>) => {
      setUnit(event.target.value);
      setIdol("");

      switch (event.target.value) {
        case "유성대":
          setSelectIdol(ryuseitai);
          break;
        case "발키리":
          setSelectIdol(valkyrie);
          break;
        default:
          setSelectIdol(allIdol);
      }
    }}
  >
    <MenuItem value="all">all</MenuItem>
    <MenuItem value="유성대">유성대</MenuItem>
    <MenuItem value="발키리">발키리</MenuItem>
  </Select>

그럼 해당 set에 따라 소분류 다시 목록을 그리도록 마저 수정해준다.

<Select
    labelId="selectIdolLabel"
    id="selectIdol"
    label="Idol"
    value={idol}
    onChange={(event: SelectChangeEvent<string>) => {
      setIdol(event.target.value);
    }}
  >
    {selectIdol.map((option: SelectVal, index: number) => (
      <MenuItem key={"idolItem" + index} value={option.value}>
        {option.name}
      </MenuItem>
    ))}
  </Select>

(map을 이용하여 <MenuItem> 컴포넌트를 그릴 때  경고 메시지가 나와 key를 추가하였다.)

(https://sheep-h.tistory.com/15)

 

 

< Radio >

다음은 이 부분을 조작해볼 것이다.

앙스타를 한스타, 일스타를 둘 다 해보면 알겠지만 한스타에는 스카우트 티켓이 있고, 일스타에는 없다.

때문에 한스타를 선택했을 시에만 사용 스카우트 티켓을 입력할 수 있는 부분을 노출하도록 만들겠다.

이번엔 state를 따로 선언하지 않고, 기존에 있던 cate state를 활용해본다.

- radio click event

한스타 클릭 시 노출, 일스타 클릭시 비노출 & 티켓 개수 초기화

 <RadioGroup
    row
    aria-labelledby="cate-radio-buttons-group"
    name="cate-radio-buttons-group"
    value={cate}
    onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
      setCate(event.target.value);

      //다이아 티켓 입력값 초기화
      setUseDiaCnt(0);
      setUseTicketCnt(0);
      setPickCnt(0);
    }}
  >
    <FormControlLabel value="ko" control={<Radio />} label="한스타" />
    <FormControlLabel value="jp" control={<Radio />} label="일스타" />
  </RadioGroup>

 

- input 노출 처리

 {cate === "ko" && (
    <Grid item xs={12}>
      <TextField
        label="사용 스카우트 티켓"
        id="useTicket"
        sx={{}}
        type="number"
        value={useTicketCnt}
        InputProps={{
          endAdornment: <InputAdornment position="end">개</InputAdornment>,
          inputProps: { min: 0, max: 1000000 },
        }}
        onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
          event.target.value
            ? setUseTicketCnt(parseInt(event.target.value))
            : setUseTicketCnt(0);
        }}
      />
    </Grid>
  )}

 

 

 

수정한 코드 전체를 보면 이런 식이다.

- InputBox.tsx

import {
  Grid,
  FormControl,
  InputLabel,
  Select,
  MenuItem,
  RadioGroup,
  Radio,
  TextField,
  FormControlLabel,
  InputAdornment,
  Button,
  SelectChangeEvent,
} from "@mui/material";
import { useState } from "react";

interface InputBoxProps {}

// select item interface
interface SelectVal {
  value: string;
  name: string;
}

// 삭제 예정 =============
const allIdol: SelectVal[] = [
  { value: "모리사와 치아키", name: "모리사와 치아키" },
  { value: "신카이 카나타", name: "신카이 카나타" },
  { value: "나구모 테토라", name: "나구모 테토라" },
  { value: "센고쿠 시노부", name: "센고쿠 시노부" },
  { value: "타카미네 미도리", name: "타카미네 미도리" },
  { value: "이츠키 슈", name: "이츠키 슈" },
  { value: "카게히라 미카", name: "카게히라 미카" },
];
const ryuseitai: SelectVal[] = [
  { value: "모리사와 치아키", name: "모리사와 치아키" },
  { value: "신카이 카나타", name: "신카이 카나타" },
  { value: "나구모 테토라", name: "나구모 테토라" },
  { value: "센고쿠 시노부", name: "센고쿠 시노부" },
  { value: "타카미네 미도리", name: "타카미네 미도리" },
];
const valkyrie: SelectVal[] = [
  { value: "이츠키 슈", name: "이츠키 슈" },
  { value: "카게히라 미카", name: "카게히라 미카" },
];

// //삭제 예정 =============

const InputBox: React.FC<InputBoxProps> = () => {
  //select
  const [unit, setUnit] = useState<string>("all");
  const [idol, setIdol] = useState<string>("");

  // select 목록
  const [selectIdol, setSelectIdol] = useState<SelectVal[]>(allIdol);

  //radio
  const [cate, setCate] = useState<string>("ko");

  //text
  const [useDiaCnt, setUseDiaCnt] = useState<number>(0);
  const [useTicketCnt, setUseTicketCnt] = useState<number>(0);
  const [pickCnt, setPickCnt] = useState<number>(0);

  return (
    <Grid container spacing={3}>
      <Grid item xs={6}>
        <FormControl fullWidth>
          <InputLabel id="selectUnitLabel">유닛</InputLabel>
          <Select
            labelId="selectUnitLabel"
            id="selectUnit"
            label="Unit"
            value={unit}
            onChange={(event: SelectChangeEvent<string>) => {
              setUnit(event.target.value);
              setIdol("");

              switch (event.target.value) {
                case "유성대":
                  setSelectIdol(ryuseitai);
                  break;
                case "발키리":
                  setSelectIdol(valkyrie);
                  break;
                default:
                  setSelectIdol(allIdol);
              }
            }}
          >
            <MenuItem value="all">all</MenuItem>
            <MenuItem value="유성대">유성대</MenuItem>
            <MenuItem value="발키리">발키리</MenuItem>
          </Select>
        </FormControl>
      </Grid>

      <Grid item xs={6}>
        <FormControl fullWidth>
          <InputLabel id="selectIdolLabel"> 아이돌 </InputLabel>
          <Select
            labelId="selectIdolLabel"
            id="selectIdol"
            label="Idol"
            value={idol}
            onChange={(event: SelectChangeEvent<string>) => {
              setIdol(event.target.value);
            }}
          >
            {selectIdol.map((option: SelectVal, index: number) => (
              <MenuItem key={"idolItem" + index} value={option.value}>
                {option.name}
              </MenuItem>
            ))}
          </Select>
        </FormControl>
      </Grid>
      <Grid item xs={12}>
        <FormControl>
          <RadioGroup
            row
            aria-labelledby="cate-radio-buttons-group"
            name="cate-radio-buttons-group"
            value={cate}
            onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
              setCate(event.target.value);

              //다이아 티켓 입력값 초기화
              setUseDiaCnt(0);
              setUseTicketCnt(0);
              setPickCnt(0);
            }}
          >
            <FormControlLabel value="ko" control={<Radio />} label="한스타" />
            <FormControlLabel value="jp" control={<Radio />} label="일스타" />
          </RadioGroup>
        </FormControl>
      </Grid>
      <Grid item xs={12}>
        <TextField
          label="사용 다이아"
          id="useDia"
          sx={{}}
          type="number"
          value={useDiaCnt}
          InputProps={{
            endAdornment: <InputAdornment position="end">개</InputAdornment>,
            inputProps: { min: 0, max: 1000000 },
          }}
          onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
            event.target.value
              ? setUseDiaCnt(parseInt(event.target.value))
              : setUseDiaCnt(0);
          }}
        />
      </Grid>
      {cate === "ko" && (
        <Grid item xs={12}>
          <TextField
            label="사용 스카우트 티켓"
            id="useTicket"
            sx={{}}
            type="number"
            value={useTicketCnt}
            InputProps={{
              endAdornment: <InputAdornment position="end">개</InputAdornment>,
              inputProps: { min: 0, max: 1000000 },
            }}
            onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
              event.target.value
                ? setUseTicketCnt(parseInt(event.target.value))
                : setUseTicketCnt(0);
            }}
          />
        </Grid>
      )}

      <Grid item xs={12}>
        <TextField
          label="뽑은 픽업 카드 수"
          id="pickCnt"
          sx={{}}
          type="number"
          value={pickCnt}
          InputProps={{
            endAdornment: <InputAdornment position="end">개</InputAdornment>,
            inputProps: { min: 0, max: 1000 },
          }}
          onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
            event.target.value
              ? setPickCnt(parseInt(event.target.value))
              : setPickCnt(0);
          }}
        />
      </Grid>
      <Grid item xs={12}>
        <Button
          variant="outlined"
          onClick={() => {
            console.log({
              unit: unit,
              idol: idol,
              cate: cate,
              useDiaCnt: useDiaCnt,
              useTicketCnt: useTicketCnt,
              pickCnt: pickCnt,
            });
          }}
        >
          확인
        </Button>
      </Grid>
    </Grid>
  );
};

export default InputBox;

+) 개수 입력하는 input에서 경고 메시지가 있어서 수정한 부분이 있다.

(https://sheep-h.tistory.com/16?category=1053878)

728x90