diff --git a/backend/src/main/resources/config b/backend/src/main/resources/config
index 8858300d..f8b6ccd0 160000
--- a/backend/src/main/resources/config
+++ b/backend/src/main/resources/config
@@ -1 +1 @@
-Subproject commit 8858300d99fe63edca63b26f837adea13e71b950
+Subproject commit f8b6ccd0232837bbda578eb6f953ec27ef55d8fb
diff --git a/backend/src/main/resources/test-data.sql b/backend/src/main/resources/test-data.sql
index 03a7a557..a2dcc63d 100644
--- a/backend/src/main/resources/test-data.sql
+++ b/backend/src/main/resources/test-data.sql
@@ -7,7 +7,7 @@ insert into student_member (id, member_id, major_id, minor_id, double_major_id,
values (202055558, 1, 1, null, null, 'EMPLOYMENT_COMPANY', 'IT 기업 개발자');
insert into member (email, name, password, phone_number, is_deleted)
-values ( 'iddang@pusan.ac.kr', '이다은', '$2a$10$YyiOL/E5WjKrZPkB6eQSK.PwZtAO.z3JimFbq/Ky3u3rFf3XTGrWK', '010-0000-0000'
+values ( 'ddang@pusan.ac.kr', '이다은', '$2a$10$YyiOL/E5WjKrZPkB6eQSK.PwZtAO.z3JimFbq/Ky3u3rFf3XTGrWK', '010-0000-0000'
, false);
insert into student_member (id, member_id, major_id, minor_id, double_major_id, career, career_detail)
@@ -32,7 +32,7 @@ INSERT INTO sw_css.milestone_history (id, milestone_id, student_id, description,
VALUES (3, 5, 202055558, 'TOPCIT 수준 2', null, 'APPROVED', null, 1, '2024-06-03', 0, '2024-07-01 18:35:47.563444');
INSERT INTO sw_css.milestone_history (id, milestone_id, student_id, description, file_url, status, reject_reason, count,
activated_at, is_deleted, created_at)
-VALUES (4, 6, 202000000, 'PCC lv3', null, 'APPROVED', null, 1, '2024-06-04', 0, '2024-07-01 18:35:47.566673');
+VALUES (4, 6, 202055555, 'PCC lv3', null, 'APPROVED', null, 1, '2024-06-04', 0, '2024-07-01 18:35:47.566673');
INSERT INTO sw_css.milestone_history (id, milestone_id, student_id, description, file_url, status, reject_reason, count,
activated_at, is_deleted, created_at)
VALUES (5, 7, 202055558, 'PCC lv2', null, 'APPROVED', null, 1, '2024-06-05', 0, '2024-07-01 18:35:47.569843');
@@ -50,12 +50,12 @@ INSERT INTO sw_css.milestone_history (id, milestone_id, student_id, description,
VALUES (9, 15, 202055558, '글로벌 행사 참여', null, 'PENDING', null, 1, '2024-06-08', 0, '2024-07-01 18:35:47.580376');
INSERT INTO sw_css.milestone_history (id, milestone_id, student_id, description, file_url, status, reject_reason, count,
activated_at, is_deleted, created_at)
-VALUES (10, 7, 202000000, 'PCC lv2', null, 'PENDING', null, 1, '2024-06-11', 0, '2024-07-01 18:35:47.580376');
+VALUES (10, 7, 202055555, 'PCC lv2', null, 'PENDING', null, 1, '2024-06-11', 0, '2024-07-01 18:35:47.580376');
INSERT INTO sw_css.milestone_history (id, milestone_id, student_id, description, file_url, status, reject_reason, count,
activated_at, is_deleted, created_at)
-VALUES (11, 15, 202000000, '글로벌 행사 참여', null, 'APPROVED', null, 1, '2024-06-08', 0, '2024-07-01 18:35:47.580376');
+VALUES (11, 15, 202055555, '글로벌 행사 참여', null, 'APPROVED', null, 1, '2024-06-08', 0, '2024-07-01 18:35:47.580376');
INSERT INTO sw_css.milestone_history (id, milestone_id, student_id, description, file_url, status, reject_reason, count,
activated_at, is_deleted, created_at)
-VALUES (12, 3, 202000000, '비교과 SW 관련 창업', null, 'APPROVED', null, 2, '2024-06-08', 0, '2024-07-01 18:35:47.580376');
+VALUES (12, 3, 202055555, '비교과 SW 관련 창업', null, 'APPROVED', null, 2, '2024-06-08', 0, '2024-07-01 18:35:47.580376');
diff --git a/frontend/src/app/(withSidebar)/hackathon/page.tsx b/frontend/src/app/(withSidebar)/hackathon/page.tsx
index 03c8acd4..298aa125 100644
--- a/frontend/src/app/(withSidebar)/hackathon/page.tsx
+++ b/frontend/src/app/(withSidebar)/hackathon/page.tsx
@@ -13,7 +13,12 @@ const Page = async ({ searchParams }: { searchParams?: { [key: string]: string |
const page = searchParams?.page ? parseInt(searchParams.page, 10) : 1;
- const hackathons = await getHackathons(page, 6);
+ let hackathons;
+ try {
+ hackathons = await getHackathons(page, 6);
+ } catch (err) {
+ // TODO: server api error handling
+ }
const getHackathonState = (startDate: string, endDate: string) => {
const now = Date.now();
@@ -44,7 +49,10 @@ const Page = async ({ searchParams }: { searchParams?: { [key: string]: string |
description="소프트웨어융합교육원에서는 2018년부터 매년 창의융합 SW 해커톤을 개최해오고 있습니다."
/>
- {hackathons?.content && hackathons.content.length > 0 ? (
+
+ 개발 중인 기능입니다.
+
+ {/* {hackathons?.content && hackathons.content.length > 0 ? (
{hackathons.content.map((hackathon) => (
해커톤 정보가 없습니다.
)}
-
+ */}
);
};
diff --git a/frontend/src/app/(withSidebar)/hackathon/sw-contest/page.tsx b/frontend/src/app/(withSidebar)/hackathon/sw-contest/page.tsx
index 905905f6..3db07350 100644
--- a/frontend/src/app/(withSidebar)/hackathon/sw-contest/page.tsx
+++ b/frontend/src/app/(withSidebar)/hackathon/sw-contest/page.tsx
@@ -1,3 +1,14 @@
-const Page = () => test
;
+import Title from '@/components/Title';
+
+const Page = () => {
+ return (
+
+ );
+};
export default Page;
diff --git a/frontend/src/app/(withSidebar)/team-building/page.tsx b/frontend/src/app/(withSidebar)/team-building/page.tsx
new file mode 100644
index 00000000..ba587ac6
--- /dev/null
+++ b/frontend/src/app/(withSidebar)/team-building/page.tsx
@@ -0,0 +1,13 @@
+import Title from '@/components/Title';
+
+const Page = () => {
+ return (
+
+ );
+};
+
+export default Page;
diff --git a/frontend/src/app/components/Milestone/index.tsx b/frontend/src/app/components/Milestone/index.tsx
index e7eff076..f30025f2 100644
--- a/frontend/src/app/components/Milestone/index.tsx
+++ b/frontend/src/app/components/Milestone/index.tsx
@@ -1,17 +1,48 @@
import MilestoneChart from '@/components/MilestoneChart';
import MilestoneTable from '@/components/MilestoneTable';
import { getAuthFromCookie } from '@/lib/utils/auth';
-import { milestoneSummaryInfo } from '@/mocks/milestone';
import { AuthSliceState } from '@/store/auth.slice';
import { MilestoneChartWrapper } from './styled';
import GoPageIcon from '../GoPageIcon';
import SignIn from '../SignIn';
import { Description, Title, TitleContent, TitleWrapper } from '../styled';
+import { getMyMilestoneHistory } from '@/lib/api/server.api';
+import { DateTime } from 'luxon';
+import { MilestoneOverviewScore } from '@/types/milestone';
+import { initialMilestoneOverview } from '@/data/milestone';
-const Milestone = () => {
+const getMilestoneScores = async (studentId: number) => {
+ const startDate = DateTime.now().minus({ years: 1 }).toFormat('yyyy-MM-dd');
+ const endDate = DateTime.now().toFormat('yyyy-MM-dd');
+ try {
+ const milestoneScores = await getMyMilestoneHistory(studentId, startDate, endDate);
+ return milestoneScores;
+ } catch (err) {
+ // TODO: server api error handling
+ }
+ return null;
+};
+
+const getMilestoneOverviewScore = async (studentId: number) => {
+ const milestoneScores = await getMilestoneScores(studentId);
+ const milestoneOverviewScore = milestoneScores?.reduce(
+ (acc, cur) => {
+ const key = `${cur.group.toLowerCase()}Score` as keyof MilestoneOverviewScore;
+ acc[key] += cur.score;
+ acc.totalScore += cur.score;
+ return acc;
+ },
+ { ...initialMilestoneOverview },
+ );
+ return milestoneOverviewScore || initialMilestoneOverview;
+};
+
+const Milestone = async () => {
const auth: AuthSliceState = getAuthFromCookie();
+ const milestoneOverviewScore = await getMilestoneOverviewScore(auth.id);
+
return (
@@ -19,13 +50,12 @@ const Milestone = () => {
나의 마일스톤
나의 마일스톤 내역을 확인할 수 있어요.
- {/* TODO: url 자신의 마일스톤으로 이동하도록 수정하기 */}
- {auth.isAuth && }
+ {auth.isAuth && }
{auth.isAuth && (
-
-
+
+
)}
{!auth.isAuth &&
}
diff --git a/frontend/src/app/layout.tsx b/frontend/src/app/layout.tsx
index 1e84cd2e..a94e7084 100644
--- a/frontend/src/app/layout.tsx
+++ b/frontend/src/app/layout.tsx
@@ -18,6 +18,7 @@ export const metadata: Metadata = {
const RootLayout = ({ children }: Readonly<{ children: React.ReactNode }>) => (
+
diff --git a/frontend/src/app/page.tsx b/frontend/src/app/page.tsx
index 8a968f5c..f4d3cee3 100644
--- a/frontend/src/app/page.tsx
+++ b/frontend/src/app/page.tsx
@@ -18,9 +18,10 @@ const Page = () => (
+ {/* TODO: 팀빌딩 구현 완료 되면 주석 풀기
-
-
+
+ */}
diff --git a/frontend/src/components/Header/index.tsx b/frontend/src/components/Header/index.tsx
index ba0bf5f7..61fbdbcd 100644
--- a/frontend/src/components/Header/index.tsx
+++ b/frontend/src/components/Header/index.tsx
@@ -3,6 +3,7 @@
'use client';
+import { VscSettingsGear } from '@react-icons/all-files/vsc/VscSettingsGear';
import { VscAccount } from '@react-icons/all-files/vsc/VscAccount';
import { VscSignIn } from '@react-icons/all-files/vsc/VscSignIn';
import { VscSignOut } from '@react-icons/all-files/vsc/VscSignOut';
@@ -49,12 +50,19 @@ const Header = () => {
),
)}
- {auth.isAuth ? (
+ {auth.isAuth && auth.isModerator && (
+ <>
+ } title="관리" size="sm" link="/admin" />
+ } title="로그아웃" size="sm" link="/sign-out" />
+ >
+ )}
+ {auth.isAuth && !auth.isModerator && (
<>
} title="마이페이지" size="sm" link="/my-page" />
} title="로그아웃" size="sm" link="/sign-out" />
>
- ) : (
+ )}
+ {!auth.isAuth && (
로그인 /회원가입
@@ -66,6 +74,7 @@ const Header = () => {
style={{ display: `${isSidebarOpen ? 'block' : 'none'}` }}
onClick={() => setIsSideBarOpen(false)}
/>
+
{
/>
- {auth.isAuth ? (
+ {auth.isAuth && auth.isModerator && (
+ <>
+ } title="관리" size="sm" link="/admin" />
+ } title="로그아웃" size="sm" link="/sign-out" />
+ >
+ )}
+ {auth.isAuth && !auth.isModerator && (
<>
} title="마이페이지" size="sm" link="/my-page" />
} title="로그아웃" size="sm" link="/sign-out" />
>
- ) : (
- } title="로그인" size="sm" link="/sign-in" />
)}
+ {!auth.isAuth && } title="로그인" size="sm" link="/sign-in" />}
diff --git a/frontend/src/components/Title/index.tsx b/frontend/src/components/Title/index.tsx
index 6437b3d6..1c77647f 100644
--- a/frontend/src/components/Title/index.tsx
+++ b/frontend/src/components/Title/index.tsx
@@ -1,22 +1,11 @@
-import Link from 'next/link';
-
export interface TitleProps {
title: string;
description?: string;
- urlText?: string;
- url?: string;
}
-const Title = ({ title, description, urlText, url }: TitleProps) => (
-
-
-
{title}
- {urlText && url && (
-
- {urlText}
-
- )}
-
+const Title = ({ title, description }: TitleProps) => (
+
+
{title}
{description &&
{description}
}
);
diff --git a/frontend/src/data/externalLink.ts b/frontend/src/data/externalLink.ts
index 7aac8760..00e8e2f8 100644
--- a/frontend/src/data/externalLink.ts
+++ b/frontend/src/data/externalLink.ts
@@ -10,8 +10,8 @@ export const externalLinkInfos: { title: string; url: string; img: string }[] =
img: '/images/main/external_link_2_plato.png',
},
{
- title: '온라인강좌
(edwith)',
- url: 'http://edwith.org/ptnr/pnuswedu',
+ title: '온라인강좌
(Inflearn)',
+ url: 'https://www.inflearn.com/users/1370319',
img: '/images/main/external_link_3_edwith.png',
},
{ title: 'TOPCIT', url: 'http://topcit.or.kr/', img: '/images/main/external_link_4_topcit.png' },
@@ -20,7 +20,7 @@ export const externalLinkInfos: { title: string; url: string; img: string }[] =
url: 'http://bd.pusan.ac.kr/',
img: '/images/main/external_link_5_pnu_achieve.png',
},
- { title: 'PNU
Online Judge', url: 'http://oj.pusan.ac.kr/', img: '/images/main/external_link_6_pnu_oj.png' },
+ { title: 'PNU
Code Place', url: 'http://code.pusan.ac.kr/', img: '/images/main/external_link_6_pnu_oj.png' },
];
export const pnuLinkInfos: { title: string; url: string; img: string }[] = [
diff --git a/frontend/src/lib/api/server.api.ts b/frontend/src/lib/api/server.api.ts
index 2799fa4f..c11d309a 100644
--- a/frontend/src/lib/api/server.api.ts
+++ b/frontend/src/lib/api/server.api.ts
@@ -7,6 +7,7 @@ import {
MilestoneHistoryDto,
MilestoneHistoryOfStudentPageableDto,
MilestoneHistoryPageableDto,
+ MilestoneScoreDto,
} from '@/types/common.dto';
import { MilestoneHistorySortCriteria, SortDirection } from '@/types/milestone';
@@ -23,7 +24,7 @@ export async function getMilestoneHistoriesOfStudent(
page: number = 0,
size: number = 10,
) {
- const response = await server
+ return await server
.get
(`/milestones/histories/members/${memberId}`, {
params: removeEmptyField({
start_date: startDate,
@@ -37,11 +38,10 @@ export async function getMilestoneHistoriesOfStudent(
})
.then((res) => res.data)
.catch((err) => Promise.reject(err));
- return response;
}
export async function getMilestoneHistories(field?: number, keyword?: string, page: number = 0, size: number = 10) {
- const response = await server
+ return await server
.get('/admin/milestones/histories', {
params: removeEmptyField({
field,
@@ -52,28 +52,36 @@ export async function getMilestoneHistories(field?: number, keyword?: string, pa
})
.then((res) => res.data)
.catch((err) => Promise.reject(err));
- return response;
}
export async function getMilestoneHistory(historyId: number) {
- const response = await server
+ return await server
.get(`/admin/milestones/histories/${historyId}`)
.then((res) => res.data)
.catch((err) => Promise.reject(err));
- return response;
}
export async function getValidationStudentId(studentId: string) {
- const response = await server
+ return await server
.get(`/sign-up/exists/student-id`, {
params: removeEmptyField({
student_id: studentId,
}),
})
.then((res) => res.data)
- .catch((err) => {
- return Promise.reject(err);
- });
+ .catch((err) => Promise.reject(err));
+}
+
+export async function getMyMilestoneHistory(studentId: number, startDate: string, endDate: string) {
+ const response = await server
+ .get(`/milestones/histories/scores/members/${studentId}`, {
+ params: removeEmptyField({
+ start_date: startDate,
+ end_date: endDate,
+ }),
+ })
+ .then((res) => res.data)
+ .catch((err) => Promise.reject(err));
return response;
}
diff --git a/frontend/src/mocks/milestone.ts b/frontend/src/mocks/milestone.ts
deleted file mode 100644
index 141614dd..00000000
--- a/frontend/src/mocks/milestone.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import { MilestoneOverviewScore } from '@/types/milestone';
-
-export const milestoneSummaryInfo: MilestoneOverviewScore = {
- activityScore: 20,
- globalScore: 40,
- communityScore: 60,
- totalScore: 120,
-};