Skip to content
Merged

Dev #56

Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
"use client";

import CloseIcon from "@/assets/Close.svg";
import SelectSection from "./selectSection";
import { useModalStore } from "@/store/modalStore";

export default function InfoChangeModal({
setIsModal,
}: {
isModal: boolean;
setIsModal: (value: boolean) => void;
}) {
export default function InfoChangeModal() {
const { isModal, setIsModal } = useModalStore();
return (
<div className="fixed inset-0 z-50 flex items-center justify-center">
<div
className={`fixed inset-0 z-50 flex items-center justify-center ${
isModal ? "block" : "hidden"
}`}
>
<div
onClick={() => {
setIsModal(false);
Expand Down
8 changes: 3 additions & 5 deletions src/app/(afterLogin)/_components/sideNav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,10 @@ import ClipboardText from "@/assets/ClipboardText.svg";
import House from "@/assets/House.svg";
import UserInfo from "./userInfo";
import { useSelectedLayoutSegments } from "next/navigation";
import { useModalStore } from "@/store/modalStore";

export default function SideNavigation({
setIsModal,
}: {
setIsModal: (value: boolean) => void;
}) {
export default function SideNavigation() {
const { setIsModal } = useModalStore();
const segments = useSelectedLayoutSegments();
const pathname = segments[0];

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
"use client";

import { useFetchAllApplications } from "@/hooks/useApplications";
import { useMemo } from "react";
import { CompanyApplication } from "@/type/applicationType";

export default function ApplicationStatusSection() {
const { data: ApplicationsData, isLoading } = useFetchAllApplications(0, "");

const applicationStatus = useMemo(() => {
if (!ApplicationsData?.data.content) {
return { APPLIED: 0, DOCUMENT_PASSED: 0, FINAL_PASSED: 0, REJECTED: 0 };
}

const applications = ApplicationsData.data
.content as Array<CompanyApplication>;

return applications.reduce(
(counts, app) => {
if (counts.hasOwnProperty(app.status)) {
counts[app.status as keyof typeof counts]++;
}
return counts;
},
{ APPLIED: 0, DOCUMENT_PASSED: 0, FINAL_PASSED: 0, REJECTED: 0 }
);
}, [ApplicationsData]);

const box_style = "w-60 border rounded-sm px-9 py-5 flex flex-col gap-4";
return (
<section className="relative top-10 flex flex-row gap-6">
<div
className={`${box_style} ${
applicationStatus.APPLIED
? "border-[#FF9016] font-semibold"
: "border-[#E0E0E0] text-[#696F8C]"
}`}
>
<span className="w-full text-left">지원 회사</span>
<span className="w-full text-right">{applicationStatus.APPLIED}개</span>
</div>
<div
className={`${box_style} ${
applicationStatus.DOCUMENT_PASSED
? "border-[#FF9016] font-semibold"
: "border-[#E0E0E0] text-[#696F8C]"
}`}
>
<span className="w-full text-left">서류 합격</span>
<span className="w-full text-right">
{applicationStatus.DOCUMENT_PASSED}개
</span>
</div>
<div
className={`${box_style} ${
applicationStatus.REJECTED
? "border-[#FF9016] font-semibold"
: "border-[#E0E0E0] text-[#696F8C]"
}`}
>
<span className="w-full text-left">불합격</span>
<span className="w-full text-right">
{applicationStatus.REJECTED}개
</span>
</div>
<div
className={`${box_style} ${
applicationStatus.FINAL_PASSED
? "border-[#FF9016] font-semibold"
: "border-[#E0E0E0] text-[#696F8C]"
}`}
>
<span className="w-full text-left">최종 합격</span>
<span className="w-full text-right">
{applicationStatus.FINAL_PASSED}개
</span>
</div>
</section>
);
}
80 changes: 80 additions & 0 deletions src/app/(afterLogin)/dashboard/_components/scheduleSection.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
"use client";

import { useSchedule } from "@/hooks/useSchedule";
import { Schedule } from "@/type/applicationType";
import CalendarIcon from "@/assets/CalendarCheck.svg";
import { useMemo } from "react";

function formatDateToApiString(date: Date) {
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, "0");
const day = String(date.getDate()).padStart(2, "0");
const hours = String(date.getHours()).padStart(2, "0");
const minutes = String(date.getMinutes()).padStart(2, "0");
const seconds = String(date.getSeconds()).padStart(2, "0");
return `${year}-${month}-${day}T${hours}:${minutes}:${seconds}`;
}

function getDDay(dateTime: string) {
const today = new Date();
const targetDate = new Date(dateTime);

const todayOnly = new Date(
today.getFullYear(),
today.getMonth(),
today.getDate()
);
const targetOnly = new Date(
targetDate.getFullYear(),
targetDate.getMonth(),
targetDate.getDate()
);

const diffTime = targetOnly.getTime() - todayOnly.getTime();
const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));

if (diffDays > 0) return `D-${diffDays}`;
else if (diffDays === 0) return `D-Day`;
else return `D+${Math.abs(diffDays)}`;
}

export default function ScheduleSection() {
const { startDate, endDate } = useMemo(() => {
const now = new Date();
const futureDate = new Date(now);
futureDate.setDate(now.getDate() + 7);

return {
startDate: formatDateToApiString(now),
endDate: formatDateToApiString(futureDate),
};
}, []);

const { data: ScheduleData, isLoading: scheduleLoading } = useSchedule(
startDate,
endDate
);

return (
<section className="relative top-28 flex flex-col">
<h2 className="text-3xl font-semibold mb-6">다가오는 일정</h2>

<div className="flex flex-col gap-4">
{ScheduleData?.data.content.map((schedule: Schedule) => (
<div
key={schedule.id}
className="w-full border border-[#E7E7E7] rounded-lg px-5 py-3.5 text-xl font-medium"
>
<span className="flex flex-row gap-2 items-center">
<CalendarIcon />
{schedule.title}
<div className="text-xs text-main bg-[#FFF2E3] px-2 rounded-full">
{getDDay(schedule.dateTime)}
</div>
</span>
</div>
))}
</div>
</section>
);
}
169 changes: 4 additions & 165 deletions src/app/(afterLogin)/dashboard/page.tsx
Original file line number Diff line number Diff line change
@@ -1,172 +1,11 @@
"use client";

import { useFetchAllApplications } from "@/hooks/useApplications";
import { useEffect, useState } from "react";
import { CompanyApplication, Schedule } from "@/type/applicationType";
import { useSchedule } from "@/hooks/useSchedule";
import CalendarIcon from "@/assets/CalendarCheck.svg";
import LoadingSpinner from "@/app/_components/loadingSpinner";
import ScheduleSection from "./_components/scheduleSection";
import ApplicationStatusSection from "./_components/applicationStatusSection";

export default function DashboardPage() {
const [applicationStatus, setApplicationStatus] = useState<{
APPLIED: number;
DOCUMENT_PASSED: number;
FINAL_PASSED: number;
REJECTED: number;
}>({
APPLIED: 0,
DOCUMENT_PASSED: 0,
FINAL_PASSED: 0,
REJECTED: 0,
});

function formatDateToApiString(date: Date) {
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, "0");
const day = String(date.getDate()).padStart(2, "0");
const hours = String(date.getHours()).padStart(2, "0");
const minutes = String(date.getMinutes()).padStart(2, "0");
const seconds = String(date.getSeconds()).padStart(2, "0");
return `${year}-${month}-${day}T${hours}:${minutes}:${seconds}`;
}

const startDate = formatDateToApiString(new Date());
const endDate = formatDateToApiString(
new Date(new Date().setDate(new Date().getDate() + 7))
);

function getDDay(dateTime: string) {
const today = new Date();
const targetDate = new Date(dateTime);


const todayOnly = new Date(
today.getFullYear(),
today.getMonth(),
today.getDate()
);
const targetOnly = new Date(
targetDate.getFullYear(),
targetDate.getMonth(),
targetDate.getDate()
);

const diffTime = targetOnly.getTime() - todayOnly.getTime();
const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));

if (diffDays > 0) return `D-${diffDays}`;
else if (diffDays === 0) return `D-Day`;
else return `D+${Math.abs(diffDays)}`;
}

const { data, isLoading } = useFetchAllApplications(0, "");
const { data: scheduleData, isLoading: scheduleLoading } = useSchedule(
startDate,
endDate
);

const applications = data?.data.content as Array<CompanyApplication>;

const statusCount = () => {
if (!applications) return;

const counts = {
APPLIED: 0,
DOCUMENT_PASSED: 0,
FINAL_PASSED: 0,
REJECTED: 0,
};

applications.forEach((app) => {
if (app.status === "APPLIED") counts.APPLIED += 1;
else if (app.status === "DOCUMENT_PASSED") counts.DOCUMENT_PASSED += 1;
else if (app.status === "FINAL_PASSED") counts.FINAL_PASSED += 1;
else if (app.status === "REJECTED") counts.REJECTED += 1;
});

setApplicationStatus(counts);
};

useEffect(() => {
statusCount();
}, [applications]);

if (isLoading || scheduleLoading) return <LoadingSpinner />;

const box_style = "w-60 border rounded-sm px-9 py-5 flex flex-col gap-4";
return (
<>
<section className="relative top-10 flex flex-row gap-6">
<div
className={`${box_style} ${
applicationStatus.APPLIED
? "border-[#FF9016] font-semibold"
: "border-[#E0E0E0] text-[#696F8C]"
}`}
>
<span className="w-full text-left">지원 회사</span>
<span className="w-full text-right">
{applicationStatus.APPLIED}개
</span>
</div>
<div
className={`${box_style} ${
applicationStatus.DOCUMENT_PASSED
? "border-[#FF9016] font-semibold"
: "border-[#E0E0E0] text-[#696F8C]"
}`}
>
<span className="w-full text-left">서류 합격</span>
<span className="w-full text-right">
{applicationStatus.DOCUMENT_PASSED}개
</span>
</div>
<div
className={`${box_style} ${
applicationStatus.REJECTED
? "border-[#FF9016] font-semibold"
: "border-[#E0E0E0] text-[#696F8C]"
}`}
>
<span className="w-full text-left">불합격</span>
<span className="w-full text-right">
{applicationStatus.REJECTED}개
</span>
</div>
<div
className={`${box_style} ${
applicationStatus.FINAL_PASSED
? "border-[#FF9016] font-semibold"
: "border-[#E0E0E0] text-[#696F8C]"
}`}
>
<span className="w-full text-left">최종 합격</span>
<span className="w-full text-right">
{applicationStatus.FINAL_PASSED}개
</span>
</div>
</section>

<section className="relative top-28 flex flex-col">
<h2 className="text-3xl font-semibold mb-6">다가오는 일정</h2>

<div className="flex flex-col gap-4">
{scheduleData?.data.content.map((schedule: Schedule) => (
<div
key={schedule.id}
className="w-full border border-[#E7E7E7] rounded-lg px-5 py-3.5 text-xl font-medium"
>
<span className="flex flex-row gap-2 items-center">
<CalendarIcon />
{schedule.title}
<div className="text-xs text-main bg-[#FFF2E3] px-2 rounded-full">
{getDDay(schedule.dateTime)}
</div>
</span>
</div>
))}
</div>
</section>
<ApplicationStatusSection />
<ScheduleSection />
</>
);
}
Loading