-
-
{season}
-
-
-
-
-
- {recruitStatus} D-{dday(nearestSchedule?.deadLine!)}
-
-
-
-
-
{title}
-
-
- onRecruitStatusChange(id, status)}
- />
-
- onRecruitDelete(id)} />
-
+
router.push(`/my-recruit/${id}`)}>
+
+
+
+
{season}
+
+
+
+
+
+ {recruitStatus} D-{dday(nearestSchedule?.deadLine!)}
+
+
+
+
+
{title}
+
+
e.stopPropagation()}>
+ onRecruitStatusChange(id, status)}
+ />
+
+ onRecruitDelete(id)} />
-
+
);
}
diff --git a/src/app/(sidebar)/my-recruit/containers/components/DueDateDialog.tsx b/src/app/(sidebar)/my-recruit/containers/components/DueDateDialog.tsx
deleted file mode 100644
index 46fb9394..00000000
--- a/src/app/(sidebar)/my-recruit/containers/components/DueDateDialog.tsx
+++ /dev/null
@@ -1,105 +0,0 @@
-import { recruitStatusList } from '@/app/(sidebar)/my-recruit/constant';
-import { Button, Dropdown, Icon } from '@/system/components';
-import { Calendar } from '@/system/components/Calendar/Calendar';
-import { Popover, PopoverContent, PopoverTrigger } from '@/system/components/Popover/Popover';
-import { color } from '@/system/token/color';
-import { Spacing } from '@/system/utils/Spacing';
-import { cn } from '@/utils';
-import clsx from 'clsx';
-import { format } from 'date-fns/format';
-import { motion } from 'framer-motion';
-import { useState } from 'react';
-import { recruitScheduleStageList } from '../../constant';
-
-interface DueDateDialogProps {
- title?: string;
- onDuedateAppend: () => void;
-}
-
-export function DueDateDialog({ title }: DueDateDialogProps) {
- const [selectedDate, setSelectedDate] = useState
();
- const [currentRecruitStage, setCurrentRecruitStage] = useState(recruitStatusList[3].text);
- const [dueDateList, setDueDateList] = useState<
- Array<{
- recruitScheduleStage: string | null;
- deadLine: `${number}-${number}-${number}` | null;
- }>
- >([]);
-
- const isDateSelected = selectedDate != null;
- const activatedAddButton =
- dueDateList.length !== 0 && dueDateList[0].deadLine != null && dueDateList[0].recruitScheduleStage != null;
-
- return (
-
-
- {title && (
- <>
-
-
- >
- )}
-
- {title ? `${title}의 공고 일정 등록하기` : '공고 일정 등록하기'}
-
-
-
-
- 일정을 등록하면 잊지 않도록 알려드릴게요!
-
-
- {/* 마감일 입력 */}
-
-
-
-
- {currentRecruitStage}
- {title && }
-
-
-
- {recruitScheduleStageList.map((item, index) => (
- setCurrentRecruitStage(item)}>
- {item}
-
- ))}
-
-
-
-
-
-
-
- {isDateSelected ? format(selectedDate, 'yyyy.mm.dd') : '마감일을 선택해주세요'}
-
-
-
-
-
-
-
-
-
-
-
- );
-}
diff --git a/src/app/(sidebar)/my-recruit/containers/components/DueDateDialog/DueDateDialog.tsx b/src/app/(sidebar)/my-recruit/containers/components/DueDateDialog/DueDateDialog.tsx
new file mode 100644
index 00000000..3913d356
--- /dev/null
+++ b/src/app/(sidebar)/my-recruit/containers/components/DueDateDialog/DueDateDialog.tsx
@@ -0,0 +1,100 @@
+import { Button, Icon } from '@/system/components';
+import { color } from '@/system/token/color';
+import { Spacing } from '@/system/utils/Spacing';
+import { cn } from '@/utils';
+import clsx from 'clsx';
+import { useEffect, useState } from 'react';
+import { useGetRecruitSchedule } from '../../../api/useGetRecruitSchedule';
+import { Form } from '@/app/(sidebar)/my-recruit/containers/components/DueDateDialog/Form';
+import { If } from '@/system/utils/If';
+import { useQueryClient } from '@tanstack/react-query';
+import { GET_ALL_RECRUITS_KEY } from '../../../api/useGetAllRecruits';
+import { GET_PROGRESSING_RECRUITS_KEY } from '../../../api/useGetProgressingRecruits';
+import { useDeleteRecruitSchedule } from '../../../api/useDeleteRecruitSchedule';
+
+interface DueDateDialogProps {
+ id: number;
+ title?: string;
+ onDuedateAppend: () => void;
+}
+
+export function DueDateDialog({ id, title }: DueDateDialogProps) {
+ const [additonalScheduleForm, setAdditionalScheduleForm] = useState(false);
+ const scheduleList = useGetRecruitSchedule({ id }).data;
+
+ const { mutate: deleteRecruitSchedule } = useDeleteRecruitSchedule();
+
+ const activatedAddButton =
+ additonalScheduleForm === false &&
+ scheduleList.length !== 0 &&
+ scheduleList[0].deadLine != null &&
+ scheduleList[0].recruitScheduleStage != null;
+
+ const queryClient = useQueryClient();
+ useEffect(() => {
+ return () => {
+ queryClient.invalidateQueries({ queryKey: [GET_PROGRESSING_RECRUITS_KEY] });
+ queryClient.invalidateQueries({ queryKey: [GET_ALL_RECRUITS_KEY] });
+ };
+ }, []);
+
+ return (
+
+
+ {title && (
+ <>
+
+
+ >
+ )}
+
+ {title ? `${title}의 공고 일정 등록하기` : '공고 일정 등록하기'}
+
+
+
+
+ 일정을 등록하면 잊지 않도록 알려드릴게요!
+
+
+ {/* 마감일 입력 */}
+
+ {scheduleList.length === 0 ? (
+
+ ) : (
+ scheduleList.map((schedule, index) => (
+
+
+
+
+ );
+}
diff --git a/src/app/(sidebar)/my-recruit/containers/components/DueDateDialog/Form.tsx b/src/app/(sidebar)/my-recruit/containers/components/DueDateDialog/Form.tsx
new file mode 100644
index 00000000..4d210bd7
--- /dev/null
+++ b/src/app/(sidebar)/my-recruit/containers/components/DueDateDialog/Form.tsx
@@ -0,0 +1,129 @@
+import { Dropdown, Icon } from '@/system/components';
+import { Calendar } from '@/system/components/Calendar/Calendar';
+import { Popover, PopoverContent, PopoverTrigger } from '@/system/components/Popover/Popover';
+import { color } from '@/system/token/color';
+import clsx from 'clsx';
+import { format } from 'date-fns/format';
+import { motion } from 'framer-motion';
+import { recruitScheduleStageList } from '@/app/(sidebar)/my-recruit/constant';
+import { useState } from 'react';
+import { usePostRecruitSchedule } from '../../../api/usePostRecruitSchedule';
+import { usePutRecruitScheduleDeadline } from '../../../api/usePutRecruitScheduleDeadline';
+import { usePutRecruitScheduleStage } from '../../../api/usePutRecruitScheduleStage';
+import { If } from '@/system/utils/If';
+
+interface Props {
+ id?: number;
+ recruitId: number;
+ deadLine?: string;
+ recruitScheduleStage?: string;
+ hasDeleteButton?: boolean;
+ hasArrow: boolean;
+ onDeleteClick?: () => void;
+}
+
+// 매번 서버요청 안하도록 리팩토링
+export function Form({
+ id,
+ recruitId,
+ hasArrow,
+ deadLine,
+ recruitScheduleStage,
+ hasDeleteButton,
+ onDeleteClick,
+}: Props) {
+ const [selectedDate, setSelectedDate] = useState(deadLine != null ? new Date(deadLine) : undefined);
+ const [currentRecruitStage, setCurrentRecruitStage] = useState(
+ recruitScheduleStage ?? recruitScheduleStageList[0],
+ );
+
+ const isDateSelected = selectedDate != null;
+ const { mutate: postRecruitSchedule } = usePostRecruitSchedule();
+ const { mutate: putRecruitScheduleDeadline } = usePutRecruitScheduleDeadline();
+ const { mutate: putRecruitScheduleState } = usePutRecruitScheduleStage();
+
+ const handleStageClick = (item: string) => {
+ if (id != null) {
+ putRecruitScheduleState({ id: recruitId, recruitScheduleId: id, recruitScheduleStage: item });
+ return;
+ }
+ setCurrentRecruitStage(item);
+ if (selectedDate == null) {
+ return;
+ }
+ postRecruitSchedule({
+ id: recruitId,
+ deadLine: format(selectedDate, 'yyyy-MM-dd'),
+ recruitScheduleStage: currentRecruitStage,
+ });
+ };
+
+ const handleDeadlineClick = (date?: Date) => {
+ if (date == null) {
+ return;
+ }
+ if (id != null) {
+ putRecruitScheduleDeadline({ id: recruitId, recruitScheduleId: id, deadLine: format(date, 'yyyy-MM-dd') });
+ return;
+ }
+ setSelectedDate(date);
+ postRecruitSchedule({
+ id: recruitId,
+ deadLine: format(date, 'yyyy-MM-dd'),
+ recruitScheduleStage: currentRecruitStage,
+ });
+ };
+
+ return (
+
+
+
+
+ {currentRecruitStage}
+ {hasArrow && }
+
+
+
+ {recruitScheduleStageList.map((item, index) => (
+ handleStageClick(item)}>
+ {item}
+
+ ))}
+
+
+
+
+
+
+
+
+ {isDateSelected ? format(selectedDate, 'yyyy.MM.dd') : '마감일을 선택해주세요'}
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/src/container/Sidebar/Sidebar.tsx b/src/container/Sidebar/Sidebar.tsx
index f7b87500..e237431f 100644
--- a/src/container/Sidebar/Sidebar.tsx
+++ b/src/container/Sidebar/Sidebar.tsx
@@ -67,12 +67,12 @@ export function Sidebar() {
diff --git a/src/hooks/useScroll.ts b/src/hooks/useScroll.ts
index 97f04be2..a5a93ae1 100644
--- a/src/hooks/useScroll.ts
+++ b/src/hooks/useScroll.ts
@@ -3,7 +3,6 @@ import { RefObject, useEffect } from 'react';
export function useScroll(target: RefObject, callback: (topOffsetY: number) => void) {
useEffect(() => {
const element = target.current ?? window;
- console.log(element);
const callback2 = () => {
const topOffsetY = target.current?.scrollTop ?? window.scrollY;
diff --git a/src/lib/dnd-kit/Droppable.tsx b/src/lib/dnd-kit/Droppable.tsx
index c0d65697..d4fdd05e 100644
--- a/src/lib/dnd-kit/Droppable.tsx
+++ b/src/lib/dnd-kit/Droppable.tsx
@@ -6,11 +6,12 @@ import { motion, useAnimationControls } from 'framer-motion';
interface DroppableProps {
id: string | number;
children?: ReactNode;
+ dataForOverlay?: any;
}
-export function Droppable({ id, children }: DroppableProps) {
+export function Droppable({ id, children, dataForOverlay }: DroppableProps) {
const animationControl = useAnimationControls();
- const { setNodeRef } = useDroppable({ id });
+ const { setNodeRef } = useDroppable({ id, data: dataForOverlay });
const { selectedId } = useDndAdditionalContext();
useEffect(() => {
diff --git a/src/system/components/Dialog/Dialog.tsx b/src/system/components/Dialog/Dialog.tsx
index 483a3e03..a30cc878 100644
--- a/src/system/components/Dialog/Dialog.tsx
+++ b/src/system/components/Dialog/Dialog.tsx
@@ -43,10 +43,10 @@ const DialogContent = React.forwardRef<
)}
{...props}>
{children}
-
+ {/*
Close
-
+ */}
));
diff --git a/src/system/components/Icon/Icon.tsx b/src/system/components/Icon/Icon.tsx
index 68835c71..86f904fc 100644
--- a/src/system/components/Icon/Icon.tsx
+++ b/src/system/components/Icon/Icon.tsx
@@ -44,6 +44,7 @@ import { Trash } from './SVG/Trash';
import { Unlink } from './SVG/Unlink';
import { Up } from './SVG/Up';
import { WorkFill } from './SVG/WorkFill';
+import { Downloads } from './SVG/Downloads';
import { X } from './SVG/X';
const iconMap = {
@@ -89,6 +90,7 @@ const iconMap = {
rocket: Rocket,
logoOnly: LogoOnly,
workFill: WorkFill,
+ download: Downloads,
arrowUp: ArrowUp,
logout: Logout,
profileFill: ProfileFill,
diff --git a/src/system/components/Icon/SVG/Close.tsx b/src/system/components/Icon/SVG/Close.tsx
index 05f4524e..0cc8c4cd 100644
--- a/src/system/components/Icon/SVG/Close.tsx
+++ b/src/system/components/Icon/SVG/Close.tsx
@@ -2,9 +2,9 @@ import { IconBaseType } from '@/system/components/Icon/SVG/type';
export function Close({ size, color }: IconBaseType) {
return (
-