-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #76 from DSM-PICK/feature/35-attendance-change-imp…
…lement-fuctions 35 Attendance Change Implement Functions
- Loading branch information
Showing
21 changed files
with
958 additions
and
318 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
116
src/components/AttendanceChange/ACColumn/DatePick/index.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
52
src/components/AttendanceChange/ACColumn/DatePick/styles.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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}; | ||
`; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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}; | ||
`; |
Oops, something went wrong.