forked from YJU-OKURA/project_minori-next-deployment-repo
-
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 YJU-OKURA#164 from dorimu0/feat/component
出席簿と出席統計ページを追加
- Loading branch information
Showing
23 changed files
with
677 additions
and
23 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
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 |
---|---|---|
@@ -1,5 +1,6 @@ | ||
const test = { | ||
user: '/images/navbar/user.png', | ||
school: '/images/navbar/schoolMark.png', | ||
}; | ||
|
||
export default test; |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
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,5 @@ | ||
const icons = { | ||
edit: '/svgs/attendance/edit.svg', | ||
}; | ||
|
||
export default icons; |
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,9 @@ | ||
import req from '../apiUtils'; | ||
|
||
const getAttendance = async (csId: number) => { | ||
const response = await req(`/at/attendance/${csId}`, 'get', 'gin'); | ||
|
||
return response; | ||
}; | ||
|
||
export default getAttendance; |
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,9 @@ | ||
import req from '../apiUtils'; | ||
|
||
const getAttendances = async (cId: number) => { | ||
const response = await req(`/at/${cId}`, 'get', 'gin'); | ||
|
||
return response; | ||
}; | ||
|
||
export default getAttendances; |
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,10 @@ | ||
import {Attendance} from '@/src/interfaces/attendance'; | ||
import req from '../apiUtils'; | ||
|
||
const postAttendance = async (users: Attendance[]) => { | ||
const response = await req('/at', 'post', 'gin', users); | ||
|
||
return response; | ||
}; | ||
|
||
export default postAttendance; |
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,151 @@ | ||
import icons from '@/public/svgs/attendance'; | ||
import getAttendance from '@/src/api/attendance/getAttendance'; | ||
import postAttendance from '@/src/api/attendance/postAttendance'; | ||
import type {Attendance, AttendanceUser} from '@/src/interfaces/attendance'; | ||
import Image from 'next/image'; | ||
import {useEffect, useState} from 'react'; | ||
|
||
const Attendance = () => { | ||
const [AttendanceUsers, setAttendanceUsers] = useState<AttendanceUser[]>([]); | ||
const [isModify, setIsModify] = useState<boolean[]>([]); | ||
const [selectedOption, setSelectedOption] = useState(''); | ||
const [isReload, setIsReload] = useState<boolean>(false); | ||
console.log(isModify); | ||
|
||
useEffect(() => { | ||
getAttendance(10).then(res => { | ||
console.log(res.data); | ||
setAttendanceUsers(res.data); | ||
setSelectedOption(res.data[0].IsAttendance); | ||
setIsModify(new Array(res.data.length).fill(false)); | ||
}); | ||
}, [isReload]); | ||
|
||
const handleClickModify = ( | ||
uid: number, | ||
cid: number, | ||
csid: number, | ||
status: string | ||
) => { | ||
console.log(uid, cid, csid, status); | ||
const user: Attendance[] = [ | ||
{ | ||
uid: uid, | ||
cid: cid, | ||
csid: csid, | ||
status: status, | ||
}, | ||
]; | ||
|
||
if (user) | ||
postAttendance(user).then(res => { | ||
setIsReload(!isReload); | ||
console.log(res); | ||
}); | ||
}; | ||
|
||
const handleSelectChange = (event: React.ChangeEvent<HTMLSelectElement>) => { | ||
setSelectedOption(event.target.value); | ||
}; | ||
|
||
const isModifyOpen = (index: number) => { | ||
console.log(index); | ||
setIsModify(prev => prev.map((open, i) => (i === index ? !open : open))); // クリックしたコメントの開閉状態を反転 | ||
}; | ||
|
||
return ( | ||
<div className="fixed inset-0 flex items-center justify-center bg-black bg-opacity-50 z-50"> | ||
<div | ||
className=" bg-white rounded-lg w-[800px] h-[600px] py-[30px] box-border flex items-center" | ||
id="modal-container" | ||
> | ||
<div className="w-full h-[500px]"> | ||
<div className="text-xl font-semibold text-center">Attendance</div> | ||
<div className="text-lg font-semibold text-green-400 text-center"> | ||
출석률 : 100% | ||
</div> | ||
<div className="p-5 overflow-scroll"> | ||
{AttendanceUsers.map((user, index) => ( | ||
<div key={index}> | ||
<div className="bg-gray-100 flex justify-between items-center p-3 rounded-lg mb-3 font-semibold text-lg"> | ||
<span className="flex justify-center items-center w-[450px]"> | ||
<span>{index + 1}.</span> | ||
<div className="w-[35px] h-[35px] ml-3 rounded-full overflow-hidden"> | ||
<Image | ||
src={user.ClassUser.User.Image} | ||
width={35} | ||
height={35} | ||
alt="image" | ||
/>{' '} | ||
</div> | ||
<span className="w-[350px] text-start px-5"> | ||
{user.ClassUser.Nickname} | ||
</span> | ||
</span> | ||
|
||
<span className="w-[120px]"> | ||
{isModify[index] ? ( | ||
<div className="flex"> | ||
<select | ||
name="" | ||
id="" | ||
onChange={handleSelectChange} | ||
value={user.IsAttendance} | ||
> | ||
<option value="ATTENDANCE">출석</option> | ||
<option value="TARDY">지각</option> | ||
<option value="ABSENCE">결석</option> | ||
</select> | ||
<div> | ||
<button | ||
className="px-2" | ||
onClick={() => | ||
handleClickModify( | ||
user.UID, | ||
user.CID, | ||
user.CSID, | ||
selectedOption | ||
) | ||
} | ||
> | ||
수정 | ||
</button> | ||
</div> | ||
</div> | ||
) : ( | ||
<div className="flex items-center"> | ||
<div> | ||
{user.IsAttendance === 'ATTENDANCE' | ||
? '출석' | ||
: user.IsAttendance === 'TARDY' | ||
? '지각' | ||
: '결석'} | ||
</div> | ||
<span | ||
className="px-2" | ||
onClick={() => { | ||
isModifyOpen(index); | ||
}} | ||
> | ||
<Image | ||
src={icons.edit} | ||
width={20} | ||
height={20} | ||
alt="icon" | ||
className="opacity-60" | ||
/> | ||
</span> | ||
</div> | ||
)} | ||
</span> | ||
</div> | ||
</div> | ||
))} | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
); | ||
}; | ||
|
||
export default Attendance; |
118 changes: 118 additions & 0 deletions
118
src/app/classes/[cId]/[mId]/components/AttendanceCard.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,118 @@ | ||
import getClassMember from '@/src/api/classUser/getClassMember'; | ||
import {useEffect, useState} from 'react'; | ||
import {ClassUser} from '@/src/interfaces/user'; | ||
import {Attendance} from '@/src/interfaces/attendance'; | ||
import postAttendance from '@/src/api/attendance/postAttendance'; | ||
|
||
const AttendanceCard = ({cid}: {cid: number; uid: number}) => { | ||
const [users, setUsers] = useState<ClassUser[]>([]); | ||
const [submitUsers, setSubmitUsers] = useState<Attendance[]>([]); | ||
const [isOpen, setIsOpen] = useState<boolean>(false); | ||
|
||
useEffect(() => { | ||
getClassMember(cid).then(res => { | ||
console.log(res); | ||
setUsers(res); | ||
|
||
// コンポーネントを結合した後、値を受け取って使用するように修正する必要があります。 | ||
const uids = res.map((user: ClassUser) => ({ | ||
uid: user.uid, | ||
cid: cid, | ||
csid: 10, | ||
status: '', | ||
})); | ||
setSubmitUsers(uids); | ||
}); | ||
}, []); | ||
|
||
const handleClickStatus = (id: number, status: string) => { | ||
const updatedUsers = submitUsers.map(user => | ||
user.uid === id ? {...user, status: status} : user | ||
); | ||
console.log(updatedUsers); | ||
setSubmitUsers(updatedUsers); | ||
}; | ||
|
||
const handleClickSave = () => { | ||
postAttendance(submitUsers).then(() => { | ||
console.log('save'); | ||
setIsOpen(false); | ||
}); | ||
}; | ||
|
||
return ( | ||
<div> | ||
<div> | ||
<button | ||
className="px-3 py-1 bg-blue-400 text-white rounded-lg" | ||
onClick={() => { | ||
setIsOpen(true); | ||
}} | ||
> | ||
출석부 | ||
</button> | ||
</div> | ||
{isOpen ? ( | ||
<div className="fixed inset-0 z-20 flex items-center justify-center bg-black bg-opacity-50"> | ||
<div | ||
className=" bg-white rounded-lg w-[500px] h-[630px] px-4 py-10 box-border" | ||
id="modal-container" | ||
> | ||
<div className="text-center text-lg text-gray-500">출석부</div> | ||
<div className="relative h-[calc(100%-28px)]"> | ||
{users.map((user, index) => ( | ||
<div | ||
className="border-b-2 flex justify-between items-center p-2" | ||
key={index} | ||
> | ||
<span className="w-[30px] text-center">{index + 1}.</span> | ||
<div className="w-[200px] text-start"> | ||
<p className="text-clip overflow-hidden">{user.nickname}</p> | ||
</div> | ||
<div> | ||
<button | ||
className="px-3 hover:bg-gray-200 border-s-2" | ||
onClick={() => handleClickStatus(user.uid, 'ATTENDANCE')} | ||
> | ||
출석 | ||
</button> | ||
<button | ||
className="px-2 hover:bg-gray-200 border-s-2" | ||
onClick={() => handleClickStatus(user.uid, 'TARDY')} | ||
> | ||
지각 | ||
</button> | ||
<button | ||
className="px-2 hover:bg-gray-200 border-s-2" | ||
onClick={() => handleClickStatus(user.uid, 'ABSENCE')} | ||
> | ||
결석 | ||
</button> | ||
</div> | ||
</div> | ||
))} | ||
<div className="absolute w-full bottom-0 pt-2 flex justify-center "> | ||
<button | ||
className="px-3 py-1 bg-red-400 text-white rounded-lg mr-4" | ||
onClick={() => { | ||
setIsOpen(false); | ||
}} | ||
> | ||
닫기 | ||
</button> | ||
<button | ||
className="px-3 py-1 bg-blue-400 text-white rounded-lg" | ||
onClick={handleClickSave} | ||
> | ||
저장 | ||
</button> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
) : null} | ||
</div> | ||
); | ||
}; | ||
|
||
export default AttendanceCard; |
Oops, something went wrong.