Skip to content

Commit

Permalink
Merge pull request #31 from team-aliens/#26/feature_select_student_modal
Browse files Browse the repository at this point in the history
학생 선택 모달 추가
  • Loading branch information
jikwan0327 authored Jun 4, 2023
2 parents 188beec + fe02254 commit 205bbad
Show file tree
Hide file tree
Showing 7 changed files with 235 additions and 1 deletion.
17 changes: 17 additions & 0 deletions services/admin/src/apis/points/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { instance } from '..';
import {
AllPointListResponse,
AllPointsOptionResponse,
RecentStudentPointResponse,
StudentPointHistoryResponse,
} from './response';
import { useToast } from '@/hooks/useToast';
Expand Down Expand Up @@ -38,6 +39,22 @@ export const getStudentPointHistory = async (
return data;
};

/** 학생 상/벌점 최근 내역 조회 */
export const getRecentStudentPointHistory = async (
student_id: string,
page?: number,
size?: number,
) => {
if (student_id) {
const { data } = await instance.get<Promise<RecentStudentPointResponse>>(
`${router}/history/students/${student_id}/recent${
page || size ? `?page=${page}&size=${size}` : ''
}`,
);
return data;
}
};

/** 상/벌점 전체 조회 */
export const getAllPoints = async () => {
const { data } = await instance.get<Promise<AllPointsOptionResponse>>(
Expand Down
8 changes: 8 additions & 0 deletions services/admin/src/apis/points/response.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@ export interface StudentPointHistoryResponse {
point_histories: StudentPointHistoryType[];
}

export interface RecentStudentPointResponse {
student_name: string;
student_gcn: string;
point_type: PointType;
point_score: number;
point_name: string;
}

export interface StudentPointHistoryType {
point_history_id: string;
date?: string;
Expand Down
59 changes: 59 additions & 0 deletions services/admin/src/components/main/DetailBox/PointItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
} from '@/apis/points/response';
import { PointEnum, PointType } from '@/apis/points';
import { usePointHistoryId } from '@/store/usePointHistoryId';
import { useRecentStudentPointHistory } from '@/hooks/usePointsApi';
import { useState } from 'react';

interface PropsType extends StudentPointHistoryType {
Expand Down Expand Up @@ -101,6 +102,31 @@ export function PointItem({
);
}

export function RecentPointItem({ studentId }: { studentId: string }) {
const { data: recentStudentPointHistory } =
useRecentStudentPointHistory(studentId);

return (
<_Student>
<>
<Text>{recentStudentPointHistory?.student_name}</Text>
<Text>{recentStudentPointHistory?.student_gcn}</Text>
</>
<_Divider />
<>
<_HollowBox width={80}>
<Text
color={recentStudentPointHistory?.point_name ? 'gray10' : 'gray5'}
>
{recentStudentPointHistory?.point_name || '내역 없음'}
</Text>
</_HollowBox>
<Text color="primary">{recentStudentPointHistory?.point_score}</Text>
</>
</_Student>
);
}

export function StudentPointItem({
isDeleteListOption = false,
canDelete = false,
Expand Down Expand Up @@ -289,3 +315,36 @@ const _Delete = styled.div`
background-color: ${({ theme }) => theme.color.gray2};
border-radius: 50%;
`;

const _Student = styled.div`
display: flex;
position: relative;
justify-content: space-between;
align-items: center;
width: 100%;
height: 57px;
background-color: #f9f9f9;
margin-bottom: 8px;
border: 1px solid #eeeeee;
border-radius: 5px;
padding: 0 28px;
`;

const _HollowBox = styled.div<{ width: number }>`
div {
width: ${({ width }) => width}px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
`;

const _Divider = styled.div`
position: absolute;
top: 50%;
left: 47%;
transform: translate(-50%, -50%);
width: 1px;
height: 28px;
background-color: ${({ theme }) => theme.color.gray3};
`;
2 changes: 2 additions & 0 deletions services/admin/src/components/main/Divider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ interface DividerProps {
width?: number;
height?: number;
margin?: string;
maxWidth?: number;
}
export function Divider({
height = 500,
margin = '0 20px 0 40px',
width = 1,
maxWidth = 1300,
}: DividerProps) {
return <_Divider height={height} width={width} margin={margin} />;
}
Expand Down
5 changes: 4 additions & 1 deletion services/admin/src/components/main/StudentList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ import {
import { usePointHistoryId } from '@/store/usePointHistoryId';
import { useQueryClient } from '@tanstack/react-query';
import { useDeleteTagIdStore } from '@/store/useDeleteTagId';
import StudentSelectModal from '../modals/StudentSelectModal';
import SideBarPortal from '../sidebar/SideBarPortal';
import { PointList } from './PointList';
import { SideBar } from '../sidebar';
Expand Down Expand Up @@ -97,9 +98,11 @@ export function StudentList({
state.appendStudentId,
state.deleteStudentId,
]);

const [clickedStudentId, setClickedStudentId] = useClickedStudentIdStore(
(state) => [state.clickedStudentId, state.setClickedStudentId],
);

const [pointHistoryId] = usePointHistoryId((state) => [state.pointHistoryId]);
const [tagId] = useDeleteTagIdStore((state) => [state.deleteTagId]);
const { modalState, selectModal, closeModal } = useModal();
Expand Down Expand Up @@ -345,6 +348,7 @@ export function StudentList({
tagModal={tagModal}
/>
)}
{Boolean(selectedStudentId.length) && <StudentSelectModal />}
<SideBarPortal>
{openAllPointHistorySideBar && (
<SideBar
Expand All @@ -360,7 +364,6 @@ export function StudentList({
</_Wrapper>
);
}

const _Wrapper = styled.div`
width: 1030px;
transition: width 0.7s ease-in-out;
Expand Down
127 changes: 127 additions & 0 deletions services/admin/src/components/modals/StudentSelectModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import styled from 'styled-components';
import { useState, useEffect } from 'react';
import { useSelectedStudentIdStore } from '@/store/useSelectedStudentIdStore';
import { Text, Button } from '@team-aliens/design-system';
import { fadeInRight } from '../../components/animation/fade';
import { Divider } from '../main/Divider';
import { useModal } from '@/hooks/useModal';
import OutsideClickHandler from 'react-outside-click-handler';
import { RecentPointItem } from '../main/DetailBox/PointItem';

export default function StudentSelectModal() {
const [selectedStudentId] = useSelectedStudentIdStore((state) => [
state.selectedStudentId,
state.resetStudentId,
state.appendStudentId,
state.deleteStudentId,
]);

const [click, setClick] = useState(false);
const { selectModal } = useModal();

return (
<OutsideClickHandler onOutsideClick={() => setClick(false)}>
<_Wrapper>
<_Header>
<Text color="gray6" margin={['left', 5]}>
기본정보
</Text>
<Text color="gray6" margin={[0, 80, 0, 5]}>
최근 부여 항목
</Text>
</_Header>
<_StudentWrapper>
{selectedStudentId.map((student) => {
return <RecentPointItem studentId={student} />;
})}
</_StudentWrapper>
<_UnderWrapper>
<Text size="BtnM">
{selectedStudentId.length}명이 선택되었습니다.
</Text>
<_ButtonWrapper>
{click && (
<_Items>
<_Item onClick={() => selectModal('GIVE_POINT')}>
<Text color="gray5" size="captionM" cursor="pointer">
상/벌점
</Text>
</_Item>
<_Item onClick={() => selectModal('GIVE_TAG_OPTIONS')}>
<Text color="gray5" size="captionM" cursor="pointer">
학생 태그
</Text>
</_Item>
</_Items>
)}
<Button onClick={() => setClick(!click)}>부여</Button>
</_ButtonWrapper>
</_UnderWrapper>
</_Wrapper>
</OutsideClickHandler>
);
}

const _Wrapper = styled.div`
display: flex;
flex-direction: column;
position: fixed;
bottom: 32px;
right: 28px;
background-color: white;
width: 418px;
height: 448px;
box-shadow: 0px 3px 20px rgba(0, 0, 0, 0.19);
border-radius: 8px;
z-index: 2;
padding: 36px 40px 23px;
/* animation: ${fadeInRight} 0.3s; */
`;

const _Header = styled.div`
display: flex;
justify-content: space-between;
`;

const _StudentWrapper = styled.div`
width: 338px;
height: 285px;
margin-bottom: 30px;
position: relative;
overflow-y: scroll;
margin-top: 10px;
`;

const _UnderWrapper = styled.div`
display: flex;
justify-content: space-between;
align-items: center;
`;

const _ButtonWrapper = styled.div`
display: flex;
position: relative;
`;

const _Items = styled.div`
position: absolute;
width: 132px;
max-height: 138px;
left: -137px;
top: -46px;
background-color: ${({ theme }) => theme.color.gray1};
box-shadow: 0px 2px 12px rgba(0, 0, 0, 0.1);
border-radius: 4px;
z-index: 3;
overflow-y: scroll;
`;

const _Item = styled.div`
display: flex;
justify-content: center;
align-items: center;
gap: 12px;
margin: 0 8px;
height: 46px;
border-bottom: 1px solid ${({ theme }) => theme.color.gray3};
`;
18 changes: 18 additions & 0 deletions services/admin/src/hooks/usePointsApi.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ import {
cancelPointHistory,
getAllPointHistory,
getAllPoints,
getRecentStudentPointHistory,
getStudentPointHistory,
PointType,
} from '@/apis/points';
import { usePointHistoryList } from './usePointHistoryList';
import { useToast } from './useToast';
import { useModal } from './useModal';
import { RecentStudentPointResponse } from '@/apis/points/response';

export const useAllPointHistory = (pointType: PointType) =>
useQuery(
Expand Down Expand Up @@ -44,6 +46,22 @@ export const useStudentPointHistory = (
);
};

export const useRecentStudentPointHistory = (
student_id: string,
isActive?: boolean,
page?: number,
size?: number,
) => {
return useQuery(
[`getRecentStudentPointHistory`, student_id],
() => getRecentStudentPointHistory(student_id, page, size),
{
refetchOnWindowFocus: true,
enabled: isActive && Boolean(student_id),
},
);
};

export const usePointOptionList = () =>
useQuery(['usePointList'], () => getAllPoints(), {
refetchOnWindowFocus: true,
Expand Down

0 comments on commit 205bbad

Please sign in to comment.