Skip to content

Commit

Permalink
feat :: redisualStudentPage #88
Browse files Browse the repository at this point in the history
  • Loading branch information
wjzlskxk committed Nov 20, 2024
1 parent ed8aa36 commit a9b2b0e
Show file tree
Hide file tree
Showing 15 changed files with 355 additions and 19 deletions.
49 changes: 49 additions & 0 deletions src/components/Out/Redisual/RedisualItem/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import * as S from './style';
import { TBody, TD, TR } from '@b1nd/b1nd-dodamdodam-ui';
import profileImg from 'assets/profileImg.svg';
import { outSleepingDataFilter } from 'utils/Out/outSleepingDataFilter';
import { useGetRedisualQuery } from 'queries/Redisual/redisual.query';

interface OffBasePassProps {
studentName: string;
selectGrade: number;
selectApproval: string | undefined;
selectRoom: string;
}

const OffbaseRedisualItem = ({ selectApproval, selectGrade, studentName, selectRoom }: OffBasePassProps) => {
const { data: redisualStudent } = useGetRedisualQuery();

return (
<>
{!outSleepingDataFilter ||
outSleepingDataFilter(redisualStudent, studentName, selectGrade, selectApproval, selectRoom)?.length === 0 ? (
<S.NoneTile>ν˜„μž¬ μž”λ₯˜ 쀑인 학생이 μ—†μŠ΅λ‹ˆλ‹€.</S.NoneTile>
) : (
<>
<TBody customStyle={S.OffBaseTBody}>
{outSleepingDataFilter(redisualStudent, studentName, selectGrade, selectApproval, selectRoom)?.map(
(redisual) => (
<TR customStyle={S.OffBaseTR}>
<TD customStyle={S.OffBaseTD}>
<S.MemberImage src={profileImg} />
</TD>
<TD customStyle={S.OffBaseTD}>{redisual.student.name}</TD>
<TD customStyle={S.OffBaseTD}>
{redisual.student.grade}ν•™λ…„
{redisual.student.room}반{redisual.student.number}번
</TD>
<TD customStyle={S.OffBaseTD}>
<div>{redisual.phone}</div>
</TD>
</TR>
)
)}
</TBody>
</>
)}
</>
);
};

export default OffbaseRedisualItem;
110 changes: 110 additions & 0 deletions src/components/Out/Redisual/RedisualItem/style.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import styled from "styled-components";
import { CSSObject } from "styled-components";

export const OffBaseTBody: CSSObject = {
width: "100%",
fontSize: "14px",
fontWeight: "600",
marginTop: "5px",
display: "flex",
rowGap: "5px",
flexDirection: "column",
whiteSpace: "normal",
cursor: "pointer",
tr: {
"&:hover": {
filter: "unset",
},
},
};

export const OffBaseTR: CSSObject = {
width: "100%",
height: "80px",
display: "flex",
alignItems: "center",
justifyContent: "space-between",
columnGap: "10px",
borderTop: "1px solid #d9d9d9",
borderBottom: "1px solid #d9d9d9",
};

export const OffBaseTD: CSSObject = {
width: "14%",
fontSize: "16px",
lineHeight: "20px",
};

export const BusLeaveTime: CSSObject = {
width: "14%",
fontSize: "16px",
lineHeight: "20px",
whiteSpace: "nowrap",
};

export const PassengerStyle: CSSObject = {
width: "65px",
height: "30px",
borderRadius: "7px",
transition: "all 0.2s ease-in-out",
"&:hover": {
boxShadow: "0 0 0 1px #fff, 0 0 0 3px rgba(50, 100, 150, 0.4)",
},
};

export const ButtonContainerStyle: CSSObject = {
width: "14%",
display: "flex",
alignItems: "center",
columnGap: "5px",

marginRight: "10px",
};

export const EditStyle: CSSObject = {
width: "5rem",
height: "2rem",
borderRadius: "5px",
fontSize: "18px",
transition: "all 0.2s ease-in-out",

"&:hover": {
boxShadow: "0 0 0 1px #fff, 0 0 0 3px rgba(50, 100, 150, 0.4)",
},
};

export const DelStyle: CSSObject = {
width: "5rem",
height: "2rem",

fontSize: "18px",
borderRadius: "5px",
transition: "all 0.2s ease-in-out",
"&:hover": {
boxShadow: "0 0 0 1px #fff, 0 0 0 3px #ddd",
},
};

export const MemberImage = styled.img`
width: 38px;
height: 38px;
object-fit: cover;
border-radius: 4rem;
`;

export const NoneTile = styled.p`
display: flex;
justify-content: center;
align-items: center;
height: 64vh;
font-size: 16px;
color: #212529;
`;

export const DateContainer = styled.div`
display: flex;
flex-direction: column;
margin-right: 60px;
`;
73 changes: 73 additions & 0 deletions src/components/Out/Redisual/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import * as S from './style';
import { Suspense, useState } from 'react';
import ErrorBoundary from 'components/common/ErrorBoundary';
import TableAttribute from 'components/common/TableAttribute';
import TodayOffBaseItem from './RedisualItem/index';
import { REDISUAL_ITEMS } from 'constants/Out/offbase.constant';
import { SearchBar, Select } from '@b1nd/b1nd-dodamdodam-ui';
import { useRecoilState } from 'recoil';
import { SelectApprovalAtom, SelectGradeAtom } from 'stores/Out/out.store';
import { changeApproval } from 'utils/Out/changeApproval';
import { changeGrade } from 'utils/Member/changeGrade';
import { GRADE_ITEMS } from 'constants/Grade/grade.constant';
import { CsvButtonContainer } from 'components/Bus/BusModal/BusPassenger/style';
import CsvButton from 'components/common/ExtractCsvData';
import dayjs from 'dayjs';
import useOffBaseLeave from 'hooks/Out/OutSleeping/useOutsleeping';
import { PointSelectRoom } from 'stores/Point/point.store';
import { useGetRedisualQuery } from 'queries/Redisual/redisual.query';
import { redisualMemberCalc } from 'utils/Out/redisualMemberCalc';
import useRedisual from 'hooks/Out/Redisual/useRedisual';

const OffbaseRedisual = () => {
const [studentName, setStudentName] = useState('');
const [selectGrade, setSelectGrade] = useRecoilState(SelectGradeAtom);
const [selectApproval, setSelectApproval] = useRecoilState(SelectApprovalAtom);
const [room, setRoom] = useRecoilState(PointSelectRoom);

const { redisualStudent } = useRedisual();

const { data: redesualStudent } = useGetRedisualQuery();

return (
<>
<S.OffBaseHeaderContainer>
<div style={{ display: 'flex', alignItems: 'center' }}>
<SearchBar value={studentName} onChange={setStudentName} />
<span style={{ marginLeft: 10 }}>
{redisualMemberCalc(redesualStudent?.data!).length === 0
? 'μ˜€λŠ˜μ€ μ™Έλ°• μž”λ₯˜μžκ°€ μ—†μŠ΅λ‹ˆλ‹€.'
: `였늘의 μ™Έλ°• μž”λ₯˜μž 수 : ${redisualMemberCalc(redesualStudent?.data!).length}λͺ…`}
</span>
</div>
<S.SelectContainer>
<CsvButtonContainer>
<CsvButton csvData={redisualStudent} fileName={dayjs().format('YYYY-MM-DD') + 'μž”λ₯˜ 쀑인 학생'} />
</CsvButtonContainer>
<Select items={GRADE_ITEMS} value={selectGrade} onChange={setSelectGrade} zIndex={2} />
<Select
items={['λͺ¨λ“  ν•™λ°˜', '1반', '2반', '3반', '4반']}
value={room || 'ν•™λ°˜μ„ μ„ νƒν•΄μ£Όμ„Έμš”'}
onChange={setRoom}
zIndex={2}
/>
</S.SelectContainer>
</S.OffBaseHeaderContainer>

<TableAttribute constant={REDISUAL_ITEMS} thStyle={{ width: '14%' }}>
<ErrorBoundary fallback={<>였늘의 μ™Έλ°• μž”λ₯˜μžλ₯Ό λΆˆλŸ¬μ˜€μ§€ λͺ»ν–ˆμŠ΅λ‹ˆλ‹€.</>}>
<Suspense fallback={<>λ‘œλ”©μ€‘...</>}>
<TodayOffBaseItem
selectRoom={room}
selectApproval={changeApproval(selectApproval)}
selectGrade={changeGrade(selectGrade)}
studentName={studentName}
/>
</Suspense>
</ErrorBoundary>
</TableAttribute>
</>
);
};

export default OffbaseRedisual;
13 changes: 13 additions & 0 deletions src/components/Out/Redisual/style.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import styled from "styled-components";
export const SelectContainer = styled.div`
display: flex;
column-gap: 10px;
`;

export const OffBaseHeaderContainer = styled.div`
display: flex;
align-items: center;
justify-content: space-between;
z-index: 900;
`;
28 changes: 15 additions & 13 deletions src/components/Router/index.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import { Routes, Route } from "react-router-dom";
import MemberPage from "pages/MemberPage";
import BusListPage from "pages/Bus/BusListPage";
import BusDatePage from "pages/Bus/BusDatePage";
import AuthPage from "pages/Auth/AuthPage";
import OffBasePassPage from "pages/Out/OutGoingPage";
import OffBaseLeavePage from "pages/Out/OutSleepingPage";
import TodayOffBaseLeavePage from "pages/Out/TodayOutSleepingPage";
import { NightStudyAllowPage } from "pages/NightStudy/NightStudyAllowPage";
import { NightStudyTodayPage } from "pages/NightStudy/NightStudyTodayPage";
import PointScore from "components/Point/PointScore";
import PointReason from "components/Point/PointReason";
import ScheduleManage from "components/Schedule/ScheduleManage";
import { Routes, Route } from 'react-router-dom';
import MemberPage from 'pages/MemberPage';
import BusListPage from 'pages/Bus/BusListPage';
import BusDatePage from 'pages/Bus/BusDatePage';
import AuthPage from 'pages/Auth/AuthPage';
import OffBasePassPage from 'pages/Out/OutGoingPage';
import OffBaseLeavePage from 'pages/Out/OutSleepingPage';
import TodayOffBaseLeavePage from 'pages/Out/TodayOutSleepingPage';
import { NightStudyAllowPage } from 'pages/NightStudy/NightStudyAllowPage';
import { NightStudyTodayPage } from 'pages/NightStudy/NightStudyTodayPage';
import PointScore from 'components/Point/PointScore';
import PointReason from 'components/Point/PointReason';
import ScheduleManage from 'components/Schedule/ScheduleManage';
import OffbaseRedisualPage from 'pages/Out/RedisualPage';

const Router = () => {
return (
Expand All @@ -22,6 +23,7 @@ const Router = () => {
<Route path="/offbase-pass" element={<OffBasePassPage />} />
<Route path="/offbase-leave" element={<OffBaseLeavePage />} />
<Route path="/offbase-leave-ing" element={<TodayOffBaseLeavePage />} />
<Route path="/offbase-redisual" element={<OffbaseRedisualPage />} />
<Route path="/nightStudy-allow" element={<NightStudyAllowPage />} />
<Route path="/nightStudy-today" element={<NightStudyTodayPage />} />
<Route path="/PointScore" element={<PointScore />} />
Expand Down
9 changes: 5 additions & 4 deletions src/components/common/SideBar/SideBarDropdown/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import MenuDropdownChild from "../../MenuDropdown/MenuDropdownChild";
import MenuDropdownWrapper from "../../MenuDropdown/MenuDropdownWrapper";
import MenuItem from "../../MenuItem";
import { SideBarDropdownContainer } from "./style";
import MenuDropdownChild from '../../MenuDropdown/MenuDropdownChild';
import MenuDropdownWrapper from '../../MenuDropdown/MenuDropdownWrapper';
import MenuItem from '../../MenuItem';
import { SideBarDropdownContainer } from './style';

const SideBarDropdown = () => {
return (
Expand All @@ -15,6 +15,7 @@ const SideBarDropdown = () => {
<MenuDropdownChild title="μ™ΈμΆœ" redirectUrl="/offbase-pass" />
<MenuDropdownChild title="μ™Έλ°•" redirectUrl="/offbase-leave" />
<MenuDropdownChild title="μ™Έλ°• 쀑인 학생" redirectUrl="/offbase-leave-ing" />
<MenuDropdownChild title="ν˜„μž¬ μž”λ₯˜ 쀑인 학생" redirectUrl="/offbase-redisual" />
</MenuDropdownWrapper>
<MenuDropdownWrapper title="μƒλ²Œμ ">
<MenuDropdownChild title="κΈ°μˆ™μ‚¬ 점수 관리" redirectUrl="/PointScore?type=DORMITORY" />
Expand Down
6 changes: 4 additions & 2 deletions src/constants/Out/offbase.constant.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
export const OUT_GOING_ITEMS = ["사진", "이름", "ν•™λ°˜", "좜발", "도착", "μ‚¬μœ ", "식사 μ—¬λΆ€", "μŠΉμΈμ—¬λΆ€"];
export const OUT_GOING_ITEMS = ['사진', '이름', 'ν•™λ°˜', '좜발', '도착', 'μ‚¬μœ ', '식사 μ—¬λΆ€', 'μŠΉμΈμ—¬λΆ€'];

export const OUT_SLEEPING_ITEMS = ["사진", "이름", "ν•™λ°˜", "좜발", "도착", "μ‚¬μœ ", "μŠΉμΈμ—¬λΆ€"];
export const OUT_SLEEPING_ITEMS = ['사진', '이름', 'ν•™λ°˜', '좜발', '도착', 'μ‚¬μœ ', 'μŠΉμΈμ—¬λΆ€'];

export const REDISUAL_ITEMS = ['사진', '이름', 'ν•™λ°˜', 'μ „ν™”λ²ˆν˜Έ'];
33 changes: 33 additions & 0 deletions src/hooks/Out/Redisual/useRedisual.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { QUERY_KEYS } from 'queries/queryKey';
import { useGetRedisualQuery } from 'queries/Redisual/redisual.query';
import { useEffect, useState } from 'react';

const useRedisual = () => {
const { data: redisual } = useGetRedisualQuery();
const [redisualStudent, setRedisualStudent] = useState([
{
이름: '',
반번호: '',
μ „ν™”λ²ˆν˜Έ: '',
λΉ„κ³ : '',
},
]);

useEffect(() => {
if (redisual?.data) {
const newData = redisual.data.map((data) => ({
이름: data.student.name,
반번호: `${data.student.grade}ν•™λ…„ ${data.student.room}반 ${data.student.number}번`,
μ „ν™”λ²ˆν˜Έ: data.phone,
λΉ„κ³ : '',
}));
setRedisualStudent(newData);
}
}, [redisual]);

return {
redisualStudent,
};
};

export default useRedisual;
12 changes: 12 additions & 0 deletions src/pages/Out/RedisualPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import OffbaseRedisual from 'components/Out/Redisual';
import SectionHeaderProvider from 'components/common/SectionHeaderProvider';

const OffbaseRedisualPage = () => {
return (
<SectionHeaderProvider title="μž”λ₯˜μ€‘" subTitle="ν˜„μž¬ μž”λ₯˜ 쀑인 학생이 λ³΄μ—¬μ§‘λ‹ˆλ‹€.">
<OffbaseRedisual />
</SectionHeaderProvider>
);
};

export default OffbaseRedisualPage;
12 changes: 12 additions & 0 deletions src/queries/Redisual/redisual.query.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { AxiosError } from 'axios';
import { QUERY_KEYS } from 'queries/queryKey';
import { useQuery, UseQueryOptions } from 'react-query';
import redisualRepositoryImpl from 'repositories/Redisual/redisual.repositoryImpl';
import { OutResponse } from 'types/Out/out.type';

export const useGetRedisualQuery = (options?: UseQueryOptions<OutResponse, AxiosError, OutResponse, string>) =>
useQuery(QUERY_KEYS.redisual.getResidual, () => redisualRepositoryImpl.getResdisual(), {
staleTime: 1000 * 60 * 60,
cacheTime: 1000 * 60 * 60,
...options,
});
3 changes: 3 additions & 0 deletions src/queries/queryKey.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ export const QUERY_KEYS = Object.freeze({
offbasemeal: {
getMealDemand: (date: string) => ["/out-going/meal-demand", date]
},
redisual: {
getResidual: "/out-sleeping/redisual",
},
nightstudy: {
getPendingNightStudy: "/night-study/pending",
getNightStudyList: "/night-study",
Expand Down
5 changes: 5 additions & 0 deletions src/repositories/Redisual/redisual.repository.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { OutResponse } from 'types/Out/out.type';

export interface RedisualRepository {
getResdisual(): Promise<OutResponse>;
}
Loading

0 comments on commit a9b2b0e

Please sign in to comment.