Skip to content
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions src/app/mocks/repositories/applicant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@ const applicants: ApplicantData[] = [
phoneNumber: '010-1010-1010',
email: 'ddd@naver.com',
status: 'PENDING',
confirmedTime: '2026-09-02T15:00:00',
interviewInfo: [
{
interviewDate: '2026-09-02',
availableTimes: ['10:00', '11:00', '15:00'],
},
],
},
{
applicantId: 2,
Expand All @@ -19,6 +26,13 @@ const applicants: ApplicantData[] = [
phoneNumber: '010-1010-1010',
email: 'ddd@naver.com',
status: 'APPROVED',
confirmedTime: '2026-09-03T14:00:00',
interviewInfo: [
{
interviewDate: '2026-09-03',
availableTimes: ['14:00', '15:00'],
},
],
},
{
applicantId: 3,
Expand All @@ -28,6 +42,13 @@ const applicants: ApplicantData[] = [
phoneNumber: '010-1010-1010',
email: 'ddd@naver.com',
status: 'REJECTED',
confirmedTime: '2026-09-02T16:00:00',
interviewInfo: [
{
interviewDate: '2026-09-02',
availableTimes: ['16:00'],
},
],
},
{
applicantId: 4,
Expand All @@ -37,6 +58,12 @@ const applicants: ApplicantData[] = [
phoneNumber: '010-1010-1010',
email: 'ddd@naver.com',
status: 'PENDING',
interviewInfo: [
{
interviewDate: '2026-09-04',
availableTimes: ['10:00', '11:00', '14:00'],
},
],
},
];

Expand Down
46 changes: 45 additions & 1 deletion src/app/mocks/repositories/dashboard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type {
DashboardSummary,
ApplicantsApiResponse,
ApplicantData,
InterviewSchedule,
} from '@/pages/admin/Dashboard/types/dashboard';

const MOCK_DASHBOARD_SUMMARY: DashboardSummary = {
Expand All @@ -11,6 +12,25 @@ const MOCK_DASHBOARD_SUMMARY: DashboardSummary = {
endDay: '2024-03-31',
};

const MOCK_INTERVIEW_SCHEDULE: InterviewSchedule[] = [
{
date: '2026-09-02',
slots: [
{ time: '14:00', assignedCount: 1 },
{ time: '15:00', assignedCount: 1 },
{ time: '16:00', assignedCount: 0 },
],
},
{
date: '2026-09-03',
slots: [
{ time: '10:00', assignedCount: 1 },
{ time: '11:00', assignedCount: 0 },
{ time: '14:00', assignedCount: 0 },
],
},
];

const MOCK_APPLICANTS: ApplicantData[] = [
{
applicantId: 1,
Expand All @@ -19,7 +39,15 @@ const MOCK_APPLICANTS: ApplicantData[] = [
department: '컴퓨터공학과',
phoneNumber: '010-1234-5678',
email: 'test1@example.com',
status: 'PENDING',
status: 'APPROVED',
confirmedTime: '2026-09-02T15:00:00',
interviewInfo: [
{
interviewDate: '2026-09-02',
availableTimes: ['14:00', '15:00', '16:00'],
},
],
interviewSchedule: MOCK_INTERVIEW_SCHEDULE,
},
{
applicantId: 2,
Expand All @@ -29,6 +57,14 @@ const MOCK_APPLICANTS: ApplicantData[] = [
phoneNumber: '010-2345-6789',
email: 'test2@example.com',
status: 'APPROVED',
confirmedTime: undefined,
interviewInfo: [
{
interviewDate: '2026-09-02',
availableTimes: ['10:00', '11:00'],
},
],
interviewSchedule: MOCK_INTERVIEW_SCHEDULE,
},
{
applicantId: 3,
Expand All @@ -38,6 +74,13 @@ const MOCK_APPLICANTS: ApplicantData[] = [
phoneNumber: '010-3456-7890',
email: 'test3@example.com',
status: 'REJECTED',
confirmedTime: '2026-09-03T10:00:00',
interviewInfo: [
{
interviewDate: '2026-09-03',
availableTimes: ['10:00', '11:00', '14:00'],
},
],
},
];

Expand All @@ -49,6 +92,7 @@ export const dashboardRepository = {
getApplicants: (): ApplicantsApiResponse => {
return {
applicants: MOCK_APPLICANTS,
interviewSchedule: MOCK_INTERVIEW_SCHEDULE,
message: null,
};
},
Expand Down
1 change: 0 additions & 1 deletion src/pages/admin/ApplicationDetail/Page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { ApplicantProfileSection } from './components/ApplicantProfileSection/in
import { ApplicantQuestionSection } from './components/ApplicationQuestionSection';
import { CommentSection } from './components/CommentSection';
import { useDetailApplications } from './hooks/useDetailApplication';

import * as S from './index.styled';

export const ApplicationDetailPage = () => {
Expand Down
4 changes: 2 additions & 2 deletions src/pages/admin/Dashboard/api/sentMessage.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { apiInstance } from '@/app/api/initInstance';
import { stageMap } from '../utils/stageMap';
import { STAGE_LABEL } from '../utils/labelMap';
import type { ApplicationStage } from '@/pages/admin/Dashboard/types/dashboard';

export const sentMessage = async (
clubId: number,
message: string,
stage: ApplicationStage,
): Promise<void> => {
const apiStage = stageMap[stage];
const apiStage = STAGE_LABEL[stage];

try {
await apiInstance.patch(`/clubs/${clubId}/club-apply-form/result?stage=${apiStage}`, {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import styled from '@emotion/styled';
import { useApplicants } from '@/pages/admin/Dashboard/hooks/useApplicants';
import { stageMap } from '@/pages/admin/Dashboard/utils/stageMap';
import { STAGE_LABEL } from '@/pages/admin/Dashboard/utils/labelMap';
import { ApplicantFilterButton } from './ApplicationFilterButton';

import type {
Expand All @@ -16,7 +16,7 @@ export type Props = {
};

export const ApplicationStatusFilter = ({ option, onOptionChange, stage, clubId }: Props) => {
const apiStage = stageMap[stage];
const apiStage = STAGE_LABEL[stage];
const { counts } = useApplicants(clubId, apiStage);

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export const Container = styled.div({

export const ApplicantInfoCategoryList = styled.div`
display: grid;
grid-template-columns: 1fr 1fr 1.5fr 1.5fr 2fr 1fr;
grid-template-columns: 1fr 1fr 1fr 1.2fr 1.5fr 1fr 1.2fr;
background-color: #f9fbfc;
border-bottom: 1.8px solid ${({ theme }) => theme.colors.gray100};
padding: 1.7rem 0 1.5rem 0;
Expand All @@ -16,29 +16,34 @@ export const ApplicantInfoCategoryList = styled.div`
}

@media (max-width: 1200px) {
grid-template-columns: 1fr 1fr 1.5fr 1.5fr 1fr;
& > div:nth-of-type(5) {
grid-template-columns: 1fr 1fr 1fr 1.5fr 1fr 1.2fr;

& > div:nth-of-type(4) {
display: none;
}
}

@media (max-width: ${({ theme }) => theme.breakpoints.web}) {
grid-template-columns: 1fr 1fr 1.5fr 1fr;
& > div:nth-of-type(4) {
grid-template-columns: 1fr 1fr 1.5fr 1fr 1.2fr;

& > div:nth-of-type(3) {
display: none;
}
}

@media (max-width: 768px) {
grid-template-columns: 1fr 1fr 1fr;
& > div:nth-of-type(3) {
grid-template-columns: 1fr 1.5fr 1fr 1.2fr;

& > div:nth-of-type(2) {
display: none;
}
}

@media (max-width: ${({ theme }) => theme.breakpoints.mobile}) {
grid-template-columns: 1.5fr 1fr;
& > div:nth-of-type(2) {
grid-template-columns: 1fr 1fr;

& > div:nth-of-type(5),
& > div:nth-of-type(7) {
display: none;
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { useCallback } from 'react';
import { useNavigate, useParams } from 'react-router-dom';
import { useApplicants } from '@/pages/admin/Dashboard/hooks/useApplicants';
import { stageMap } from '@/pages/admin/Dashboard/utils/stageMap';
import { STAGE_LABEL } from '@/pages/admin/Dashboard/utils/labelMap';
import { LoadingSpinner } from '@/shared/components/LoadingSpinner';
import { ApplicantListItem } from '../ApplicantListItem';
import * as S from './index.styled';
import type {
ApplicateInfoCategory,
ApplicationFilterOption,
ApplicationStage,
} from '@/pages/admin/Dashboard/types/dashboard';
Expand All @@ -15,22 +16,22 @@ type Props = {
stage: ApplicationStage;
};

type ApplicateInfoCategory = '이름' | '학번' | '학과' | '전화번호' | '이메일' | '결과';
const INFO_CATEGORY: ApplicateInfoCategory[] = [
'이름',
'학번',
'학과',
'전화번호',
'이메일',
'결과',
'면접 시간',
];

export const ApplicantList = ({ filterOption, stage }: Props) => {
const { clubId } = useParams();

const navigate = useNavigate();

const apiStage = stageMap[stage];
const apiStage = STAGE_LABEL[stage];

const {
data: applicants,
Expand Down Expand Up @@ -67,6 +68,9 @@ export const ApplicantList = ({ filterOption, stage }: Props) => {
phoneNumber={applicant.phoneNumber}
email={applicant.email}
status={applicant.status}
confirmedTime={applicant.confirmedTime}
interviewInfo={applicant.interviewInfo}
interviewSchedule={applicant.interviewSchedule}
onClick={handleItemClick}
/>
))
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import styled from '@emotion/styled';

export const Container = styled.div({
display: 'flex',
flexDirection: 'column',
gap: '1.8rem',
});

export const Section = styled.div({
display: 'flex',
flexDirection: 'column',
gap: '1rem',
});

export const SectionTitle = styled.h3(({ theme }) => ({
fontSize: theme.font.size.sm,
fontWeight: 600,
color: theme.colors.gray700,
paddingBottom: '0.5rem',
borderBottom: `1px solid ${theme.colors.gray200}`,
}));

export const ScheduleRow = styled.div({
display: 'flex',
alignItems: 'flex-start',
gap: '1rem',
});
export const SchedulDateLabel = styled.span(({ theme }) => ({
Comment thread
kanghaeun marked this conversation as resolved.
Outdated
fontSize: theme.font.size.sm,
fontWeight: 600,
color: theme.colors.gray700,
minWidth: '2.5rem',
paddingTop: '0.5rem',
}));

export const DateLabel = styled.span(({ theme }) => ({
fontSize: theme.font.size.sm,
fontWeight: 600,
color: theme.colors.gray700,
minWidth: '2.5rem',
}));

export const SlotsContainer = styled.div({
display: 'flex',
flexWrap: 'wrap',
gap: '0.5rem',
flex: 1,
});

export const TimeSlot = styled.button<{ $selected?: boolean }>(({ theme, $selected }) => ({
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
padding: '0.5rem 0.75rem',
borderRadius: theme.radius.md,
border: `1px solid ${$selected ? theme.colors.primary : theme.colors.gray300}`,
backgroundColor: $selected ? theme.colors.primary00 : theme.colors.bg,
cursor: 'pointer',
transition: 'all 0.2s',
minWidth: '4rem',

'&:hover': {
borderColor: theme.colors.primary,
backgroundColor: theme.colors.primary00,
},
}));

export const SlotTime = styled.span(({ theme }) => ({
fontSize: theme.font.size.sm,
fontWeight: 500,
color: theme.colors.gray800,
}));

export const SlotCount = styled.span(({ theme }) => ({
fontSize: theme.font.size.xs,
color: theme.colors.gray500,
marginTop: '0.125rem',
}));

export const AvailableTimesRow = styled.div({
display: 'flex',
alignItems: 'center',
gap: '1rem',
});

export const AvailableTimes = styled.span(({ theme }) => ({
fontSize: theme.font.size.sm,
color: theme.colors.gray600,
}));
Loading
Loading