Skip to content

Commit

Permalink
Merge pull request #76 from DSM-PICK/feature/35-attendance-change-imp…
Browse files Browse the repository at this point in the history
…lement-fuctions

35 Attendance Change Implement Functions
  • Loading branch information
jcho0216 authored Jan 2, 2022
2 parents f2b03fb + 289e14b commit a886bd3
Show file tree
Hide file tree
Showing 21 changed files with 958 additions and 318 deletions.
96 changes: 96 additions & 0 deletions src/components/AttendanceChange/ACColumn/Add/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import React, { FC, useEffect, useRef, useState } from "react";
import { searchStudents } from "../../../../utils/api/AttendanceChange";
import {
searchStatus,
searchedStudents,
StudentObject,
SDateValue,
FDateValue,
ReasonAtom,
SClassValue,
FClassValue
} from "../../../../state/atom/ATChange";
import { useRecoilState, useRecoilValue } from "recoil";
import * as S from "./styles";
import { ACColumn } from "../../styles";
import SelectedStudent from '../../SelectedStudents/index';
import { SelectedStudentsType, StudentObjectType } from "../../../../interface/ATChange";

const Add: FC = (): JSX.Element => {
const searchContainer = useRef<HTMLDivElement>(null);
const [search, setSearch] = useRecoilState(searchStatus);
const [searchedStudentsArr, setSearchedStudentsArr] = useRecoilState(searchedStudents);
const [inputValue, setInputValue] = useState<string>("");
const [studentObject, setStudentObject] = useRecoilState<StudentObjectType | any>(StudentObject);
const sdate = useRecoilValue(SDateValue);
const fdate = useRecoilValue(FDateValue);
const Reason = useRecoilValue(ReasonAtom);
const sclass = useRecoilValue(SClassValue);
const fclass = useRecoilValue(FClassValue);

const selectStudent = (object: SelectedStudentsType) => {
if (studentObject.find((value : any) => value.id === object.id)) {
alert("이미 추가하신 학생입니다.");
return;
}
const data = {
id: object.id,
gcn: object.gcn,
name: object.name,
sdate: sdate,
fdate: fdate,
sclass: sclass,
fclass: fclass,
type: 0,
reason: Reason,
}
setSearch(!search);
setInputValue("");
setSearchedStudentsArr([]);
setStudentObject(studentObject.concat(data));
};

useEffect(() => {
console.log(studentObject);
}, [studentObject])

return (
<>
<ACColumn>
<S.ACTitle>결석자</S.ACTitle>
<S.AbsentsContainer ref={searchContainer}>
<S.AddAbsents onClick={() => setSearch(!search)}>추가</S.AddAbsents>
<S.SearchStudentsInput
placeholder="검색..."
display={search ? "block" : "none"}
onChange={(e) => {
setInputValue(e.target.value);
searchStudents(e.target.value)
.then((res) => {
setSearchedStudentsArr(res.data);
})
}}
value={inputValue}
/>
<S.SearchedContainer display={search ? "flex" : "none"}>
{searchedStudentsArr.map((value: any) => {
return (
<S.SearchedStudent
onClick={() => selectStudent(value)}
key={value.id}
>{`${value.gcn} ${value.name}`}</S.SearchedStudent>
);
})}
</S.SearchedContainer>
{studentObject.map((value: any) => {
return (
<SelectedStudent id={value.id} gcn={value.gcn} name={value.name} key={value.gcn}/>
);
})}
</S.AbsentsContainer>
</ACColumn>
</>
);
};

export default Add;
64 changes: 64 additions & 0 deletions src/components/AttendanceChange/ACColumn/Add/styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import styled from "@emotion/styled";
import { COLOR } from "../../../../style/index";

export const ACTitle = styled.div`
font-size: 16px;
width: 70px;
margin-right: 50px;
display: flex;
align-self: center;
`;

export const AbsentsContainer = styled.div`
display: flex;
gap: 10px;
width: 900px;
position: relative;
`;

export const SearchStudentsInput = styled.input<{ display: string }>`
width: 84px;
height: 24px;
text-align: center;
outline: none;
border: 1px solid ${COLOR.gray};
border-radius: 5px;
display: ${(props) => props.display};
`;

export const AddAbsents = styled.div`
cursor: pointer;
min-width: 50px;
height: 24px;
padding: 1px 2px;
border: 1px solid ${COLOR.gray};
color: 1px solid ${COLOR.gray};
display: flex;
justify-content: center;
align-items: center;
border-radius: 5px;
`;


export const SearchedStudent = styled.div`
height: 20px;
padding: 2px;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
`;

export const SearchedContainer = styled.div<{ display : string }>`
max-height: 80px;
position: absolute;
display: ${props => props.display};
flex-direction: column;
transform: translate(75%, 110%);
left: 0;
bottom: 0;
background: ${COLOR.white};
overflow: auto;
border: 1px solid ${COLOR.gray};
border-radius: 3px;
`;
116 changes: 116 additions & 0 deletions src/components/AttendanceChange/ACColumn/DatePick/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import React, { FC, useEffect, useState, useLayoutEffect } from "react";
import * as S from "./styles";
import { ACColumn } from "../../styles";
import { useRecoilState, useRecoilValue } from "recoil";
import {
FModal,
SModal,
FDateValue,
SDateValue,
StudentObject,
SelectedIndex,
SClassValue,
FClassValue
} from "../../../../state/atom/ATChange";
import Calendar from "../../../Calendar/Calendar";
import { StudentObjectType } from "../../../../interface/ATChange";

const DatePick: FC = (): JSX.Element => {
const date = new Date();
const [isFOpen, setIsFOpen] = useRecoilState<boolean>(FModal);
const [isSOpen, setIsSOpen] = useRecoilState<boolean>(SModal);
const [fdateValue, setFdateValue] = useRecoilState<string>(FDateValue);
const [sdateValue, setSdateValue] = useRecoilState<string>(SDateValue);
const [studentObject, setStudentObject] = useRecoilState<StudentObjectType | any>(StudentObject);
const selectedIndex = useRecoilValue(SelectedIndex);
const [sdate, setSdate] = useState("결석자 추가");
const [fdate, setFdate] = useState("결석자 추가");
const [sclass, setSclass] = useRecoilState<number | any>(SClassValue);
const [fclass, setFclass] = useRecoilState<number | any>(FClassValue);

useEffect(() => {
setFdateValue(
`${date.getFullYear()}-${(date.getMonth() + 1) < 10 ? `0${date.getMonth() + 1}` : date.getMonth() + 1}-${date.getDate() < 10 ? `0${date.getDate()}` : date.getDate()}`
);
setSdateValue(
`${date.getFullYear()}-${(date.getMonth() + 1) < 10 ? `0${date.getMonth() + 1}` : date.getMonth() + 1}-${date.getDate() < 10 ? `0${date.getDate()}` : date.getDate()}`
);
}, []);

useLayoutEffect(() => {
return studentObject.length === 0
? (
setSdate(sdate),
setFdate(fdate)
)
: (setSdate(
`${studentObject.find((value : any) => value.id === selectedIndex).sdate.split("-")[0]}
${studentObject.find((value : any) => value.id === selectedIndex).sdate.split("-")[1]}
${studentObject.find((value : any) => value.id === selectedIndex).sdate.split("-")[2]}일`
),
setFdate(
`${studentObject.find((value : any) => value.id === selectedIndex).fdate.split("-")[0]}
${studentObject.find((value : any) => value.id === selectedIndex).fdate.split("-")[1]}
${studentObject.find((value : any) => value.id === selectedIndex).fdate.split("-")[2]}일`
))
}, [selectedIndex, fdateValue, sdateValue])

useEffect(() => {
setSclass("");
setFclass("");
if(studentObject.length === 0) return;
setSclass(studentObject.find((value : any) => value.id === selectedIndex).sclass === ""
? ""
: studentObject.find((value : any) => value.id === selectedIndex).sclass)
setFclass(studentObject.find((value : any) => value.id === selectedIndex).fclass === ""
? ""
: studentObject.find((value : any) => value.id === selectedIndex).fclass)
}, [selectedIndex])

const handleClassInputS = (e : any) => {
if(studentObject.length === 0) return;
setStudentObject((prevArr : any) => prevArr.map((value : any) => {
return value.id === selectedIndex ? { ...value, sclass: e.target.value } : value;
}))
setSclass(e.target.value);
}

const handleClassInputF = (e : any) => {
if(studentObject.length === 0) return;
setStudentObject((prevArr : any) => prevArr.map((value : any) => {
return value.id === selectedIndex ? { ...value, fclass: e.target.value } : value;
}))
setFclass(e.target.value);
}

return (
<ACColumn>
<S.ACTitle>날짜</S.ACTitle>
<S.DateBox>
<S.Date>
<S.DateText onClick={() => setIsFOpen(!isFOpen)}>
{sdate}
</S.DateText>
<Calendar isOpen={isFOpen} index={0} />
<div className="classContainer">
<S.ClassInput maxLength={1} value={sclass} onChange={handleClassInputS}/>
<div>교시</div>
</div>
</S.Date>
<span>~</span>
<S.Date>
<S.DateText onClick={() => setIsSOpen(!isSOpen)}>
{fdate}
</S.DateText>
<Calendar isOpen={isSOpen} index={1} />
<div className="classContainer">
<S.ClassInput maxLength={1} value={fclass} onChange={handleClassInputF}/>
<div>교시</div>
</div>
</S.Date>
</S.DateBox>
</ACColumn>
);
};

export default DatePick;
52 changes: 52 additions & 0 deletions src/components/AttendanceChange/ACColumn/DatePick/styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import styled from "@emotion/styled";
import { COLOR } from "../../../../style";

export const ACTitle = styled.div`
font-size: 16px;
width: 70px;
margin-right: 50px;
display: flex;
align-self: center;
`;

export const DateBox = styled.div`
display: flex;
width: 100%;
span {
margin: 0 10px;
}
`;

export const Date = styled.div`
display: flex;
justify-content: space-between;
width: 175px;
& .classContainer {
display: flex;
}
`;

export const DateText = styled.div`
cursor: pointer;
font-size: 16px;
text-align: center;
width: auto;
margin: 0 auto;
padding: 1px 2px;
&:hover {
transition: 0.3s;
background-color: ${COLOR.lighterGray};
border-radius: 5px;
}
`;

export const ClassInput = styled.input`
width: 15px;
text-align: center;
outline: none;
border: none;
font-size: 16px;
border-bottom: 1px solid ${COLOR.black};
`;
41 changes: 41 additions & 0 deletions src/components/AttendanceChange/ACColumn/Reason/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { FC, useLayoutEffect } from "react";
import { useRecoilState, useRecoilValue } from "recoil";
import { ReasonAtom } from "../../../../state/atom/ATChange";
import { StudentObject, SelectedIndex } from "../../../../state/atom/ATChange";
import * as S from "./styles";
import { ACColumn } from "../../styles";
import { StudentObjectType } from "../../../../interface/ATChange";

const Reason: FC = (): JSX.Element => {
const [reason ,setReason] = useRecoilState(ReasonAtom);
const [studentObject, setStudentObject] = useRecoilState<StudentObjectType | any>(StudentObject);
const selectedIndex = useRecoilValue(SelectedIndex);

const checkWordLength = (e: React.ChangeEvent<HTMLInputElement>) => {
setReason(e.target.value);
setStudentObject(studentObject.length === 0 ? studentObject : (prevArr : any) => prevArr.map((value : any) => {
return value.id === selectedIndex ? { ...value, reason: e.target.value } : value;
}))
};

useLayoutEffect(() => {
if(studentObject.length === 0) return;
setReason(studentObject.find((value : StudentObjectType) => value.id === selectedIndex).reason)
}, [selectedIndex])

return (
<ACColumn>
<S.ACTitle>비고</S.ACTitle>
<div>
<S.NoteInput
type="text"
placeholder="최대 10글자로 입력해주세요 (선택)"
onChange={checkWordLength}
value={reason}
/>
</div>
</ACColumn>
);
};

export default Reason;
20 changes: 20 additions & 0 deletions src/components/AttendanceChange/ACColumn/Reason/styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import styled from "@emotion/styled";
import { COLOR } from "../../../../style/index";

export const ACTitle = styled.div`
font-size: 16px;
width: 70px;
margin-right: 50px;
display: flex;
align-self: center;
`;

export const NoteInput = styled.input`
width: 97%;
height: 40px;
border: none;
border-bottom: 1px solid ${COLOR.darkerGray};
outline: none;
text-align: center;
color: ${COLOR.black};
`;
Loading

0 comments on commit a886bd3

Please sign in to comment.