체크박스 typescript 참고
useState Type 지정하는 방법 참고하자. (인턴때 헤맸던 부분)
< 제약조건 >
1. DatePicker
기본값: 접속한 날짜를 기준으로 30일간의 데이터를 조회할 수 있도록 설정
- 예외처리
최대 기간: 최대로 조회할 수 있는 날짜의 범위는 1년
날짜 조회: 오늘 이후의 날짜는 조회할 수 없도록 예외처리
시작일과 종료일: 시작일이 종료일을 넘을 수 없도록 예외처리
2. 검색 창
글자 제한: 20글자 이상의 검색어를 입력할 수 없도록 예외처리
3. 검색 초기화
조회 기간 및 검색어, 필터링(성별, 광고 종류, 비고) 초기화 및 데이터 Reload
4. 필터링
기본값: 모든 체크박스들이 체크되도록 기본값 설정
예외처리: 각각의 필터링 조건들에는 최소 하나의 체크 박스가 선택되있어야 한다.
5. 테이블
No.: 페이지네이션을 위해 선택된 페이지 값을 기반으로 숫자 노출
Order By: No.를 제외한 나머지 조건들로 정렬 기능 추가
Pagination: 한 페이지 당 10개의 데이터를 노출 및 페이지 변경 시 다음 데이터 로딩
상태관리
import React, { useState } from "react";
import { SearchBtnList } from "./SearchBtnList/index";
import InputContainer from "./InputContainer";
import { DatePickerCustom } from "components";
import moment from "moment";
import "react-datepicker/dist/react-datepicker.css";
import styled from "styled-components";
import CheckBoxContent from "./CheckBox";
export default function SearchBoard() {
// 검색관련 state
const [inputValue, setInputValue] = useState("");
// 날짜관련 state
const defaultDate = moment().subtract(1, "month").toDate();
const [startDate, setStartDate] = useState(defaultDate);
const [endDate, setEndDate] = useState(new Date());
const onChangeStart = (date: Date) => setStartDate(date);
const onChangeEnd = (date: Date) => setEndDate(date);
// 체크박스관련 state
const [genderCheckedLists, setGenderCheckedLists] = useState<string[]>([
"MALE",
"FEMALE",
]);
const [adCheckedLists, setAdCheckedLists] = useState<string[]>([
"IMAGE",
"VIDEO",
]);
const [remarkCheckedLists, setRemarkCheckedLists] = useState<string[]>([
"CONNECT",
"EXPOSURE",
"CLICK",
"PLAY",
"SKIP",
"VISIT",
]);
// 검색창 입력글자 20자 제한
const inputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
if (e.target.value.length > 20) {
return;
}
setInputValue(e.target.value);
};
// 검색 초기화 버튼 핸들러
const inputInitialize = () => {
setInputValue("");
setStartDate(defaultDate);
setEndDate(new Date());
setGenderCheckedLists(["MALE", "FEMALE"]);
setAdCheckedLists(["IMAGE", "VIDEO"]);
setRemarkCheckedLists([
"CONNECT",
"EXPOSURE",
"CLICK",
"PLAY",
"SKIP",
"VISIT",
]);
};
// 날짜 제한
function maxDateRestrict(startDate: Date): Date {
let moreOneYear = new Date(startDate.valueOf());
moreOneYear.setDate(moreOneYear.getDate() + 365);
if (moreOneYear > new Date()) {
return new Date();
} else {
return moreOneYear;
}
}
// 필터링 핸들러
const changeHandler1 = (target: boolean, id: string): void => {
if (target) {
setGenderCheckedLists([...genderCheckedLists, id]);
} else {
if (genderCheckedLists.length === 1) {
return;
} else {
setGenderCheckedLists(
genderCheckedLists.filter((el: string) => el !== id),
);
}
}
};
const changeHandler2 = (target: boolean, id: string): void => {
if (target) {
setAdCheckedLists([...adCheckedLists, id]);
} else {
if (adCheckedLists.length === 1) {
return;
} else {
setAdCheckedLists(adCheckedLists.filter((el: string) => el !== id));
}
}
};
const changeHandler3 = (target: boolean, id: string): void => {
if (target) {
setRemarkCheckedLists([...remarkCheckedLists, id]);
} else {
if (remarkCheckedLists.length === 1) {
return;
} else {
setRemarkCheckedLists(
remarkCheckedLists.filter((el: string) => el !== id),
);
}
}
};
const DanbiDatePicker = () => {
return (
<>
<DateBoxContainer>
<DateBox>
<DatePickerCustom
dateFormat="yyyy-MM-dd"
selected={startDate}
onChange={onChangeStart}
selectsStart
startDate={startDate}
endDate={endDate}
maxDate={new Date()}
/>
<CalenderImg src="/calendar.svg" alt="calender" />
</DateBox>
<DateToDate>~</DateToDate>
<DateBox>
<DatePickerCustom
dateFormat="yyyy-MM-dd"
selected={endDate}
onChange={onChangeEnd}
selectsEnd
startDate={startDate}
endDate={endDate}
maxDate={maxDateRestrict(startDate)}
minDate={startDate}
/>
<CalenderImg src="/calendar.svg" alt="calender" />
</DateBox>
</DateBoxContainer>
</>
);
};
return (
<>
<Period>조회 기간</Period>
<BoxElement>
<DanbiDatePicker />
<InputContainer
inputValue={inputValue}
inputChange={inputChange}
></InputContainer>
<SearchBtnList inputInitialize={inputInitialize}></SearchBtnList>
</BoxElement>
<CheckBoxContent
genderCheckedLists={genderCheckedLists}
setGenderCheckedLists={setGenderCheckedLists}
adCheckedLists={adCheckedLists}
setAdCheckedLists={setAdCheckedLists}
remarkCheckedLists={remarkCheckedLists}
setRemarkCheckedLists={setRemarkCheckedLists}
changeHandler1={changeHandler1}
changeHandler2={changeHandler2}
changeHandler3={changeHandler3}
></CheckBoxContent>
</>
);
}
index.tsx
import React from "react";
import { CheckBoxContent as CheckBoxPresenter } from "./CheckBox";
import { PropType } from "./Types";
export default function CheckBox(CheckBoxProps: PropType) {
return <CheckBoxPresenter {...CheckBoxProps} />;
}
presenter
import React, { ChangeEvent } from "react";
import {
CheckBoxContainer,
Lists,
TitleFirst,
Title,
Name,
List1,
List2,
List3,
} from "./Styles";
import { PropType } from "./Types";
export function CheckBoxContent(props: PropType) {
const {
genderCheckedLists,
setGenderCheckedLists,
adCheckedLists,
setAdCheckedLists,
remarkCheckedLists,
setRemarkCheckedLists,
changeHandler1,
changeHandler2,
changeHandler3,
} = props;
const genders = [
{ id: "MALE", name: "남자" },
{ id: "FEMALE", name: "여자" },
];
const advertisings = [
{ id: "IMAGE", name: "이미지" },
{ id: "VIDEO", name: "영상" },
];
const remarks = [
{ id: "CONNECT", name: "접속" },
{ id: "EXPOSURE", name: "노출" },
{ id: "CLICK", name: "클릭" },
{ id: "PLAY", name: "재생" },
{ id: "SKIP", name: "스킵" },
{ id: "VISIT", name: "방문" },
];
return (
<CheckBoxContainer>
<Lists>
<List1>
<TitleFirst>성별</TitleFirst>
{genders.map((gender) => {
return (
<>
<input
type="checkbox"
key={gender.id}
checked={
genderCheckedLists.includes(gender.id) ? true : false
}
onChange={(e: ChangeEvent<HTMLInputElement>) => {
changeHandler1(e.currentTarget.checked, gender.id);
}}
/>
<Name>{gender.name}</Name>
</>
);
})}
</List1>
<List2>
<Title>광고종류</Title>
{advertisings.map((advertising) => {
return (
<>
<input
type="checkbox"
key={advertising.id}
checked={
adCheckedLists.includes(advertising.id) ? true : false
}
onChange={(e: ChangeEvent<HTMLInputElement>) => {
changeHandler2(e.currentTarget.checked, advertising.id);
}}
/>
<Name>{advertising.name}</Name>
</>
);
})}
</List2>
<List3>
<Title>비고</Title>
{remarks.map((remark) => {
return (
<>
<input
type="checkbox"
key={remark.id}
checked={
remarkCheckedLists.includes(remark.id) ? true : false
}
onChange={(e: ChangeEvent<HTMLInputElement>) => {
changeHandler3(e.currentTarget.checked, remark.id);
}}
/>
<Name>{remark.name}</Name>
</>
);
})}
</List3>
</Lists>
</CheckBoxContainer>
);
}
type
export interface PropType {
genderCheckedLists: string[];
adCheckedLists: string[];
remarkCheckedLists: string[];
setGenderCheckedLists: React.Dispatch<React.SetStateAction<string[]>>;
setAdCheckedLists: React.Dispatch<React.SetStateAction<string[]>>;
setRemarkCheckedLists: React.Dispatch<React.SetStateAction<string[]>>;
changeHandler1: (target: boolean, id: string) => void;
changeHandler2: (target: boolean, id: string) => void;
changeHandler3: (target: boolean, id: string) => void;
}
'🤹🏻♀️ Javascript > 🥎 Typescript' 카테고리의 다른 글
[TS] 조건부 타입 (0) | 2022.05.07 |
---|---|
[TS] 제네릭 (0) | 2022.05.07 |
타입 추론, 타입 단언 (0) | 2022.03.06 |
타입스크립트 에러 (0) | 2022.02.25 |
material ui - Pagination (0) | 2022.02.25 |