Merge branch 'fe/studentReport' into 'frontend'
[Front-end] feat: 학생 퀴즈성적 전체 조회페이지 추가 See merge request s11-webmobile1-sub2/S11P12A701!89
This commit is contained in:
commit
69c6cee3ab
@ -37,6 +37,7 @@ const CreateFreeboardPage = lazy(async () => await import('./pages/CreateFreeboa
|
|||||||
const FreeboardDetailPage = lazy(async () => await import('./pages/FreeboardDetailPage'));
|
const FreeboardDetailPage = lazy(async () => await import('./pages/FreeboardDetailPage'));
|
||||||
const EditFreeboardPage = lazy(async () => await import('./pages/EditFreeboardPage'));
|
const EditFreeboardPage = lazy(async () => await import('./pages/EditFreeboardPage'));
|
||||||
const PasswordResetAuthPage = lazy(async () => await import('./pages/PasswordResetAuthPage'));
|
const PasswordResetAuthPage = lazy(async () => await import('./pages/PasswordResetAuthPage'));
|
||||||
|
const StudentReportPage = lazy(async () => await import('./pages/StudentReportPage'));
|
||||||
const LivePage = lazy(async () => await import('./pages/LivePage'));
|
const LivePage = lazy(async () => await import('./pages/LivePage'));
|
||||||
|
|
||||||
const router = createBrowserRouter([
|
const router = createBrowserRouter([
|
||||||
@ -77,6 +78,14 @@ const router = createBrowserRouter([
|
|||||||
index: true,
|
index: true,
|
||||||
element: <LearningLectureDetailPage />,
|
element: <LearningLectureDetailPage />,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'report',
|
||||||
|
element: <StudentReportPage />,
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// path: 'report/:reportId',
|
||||||
|
// element:
|
||||||
|
// },
|
||||||
{
|
{
|
||||||
path: 'edit',
|
path: 'edit',
|
||||||
element: <LectureEditPage />,
|
element: <LectureEditPage />,
|
||||||
|
@ -54,7 +54,8 @@ export default function LectureLayout() {
|
|||||||
<SideLink to={'notice'}>공지사항</SideLink>
|
<SideLink to={'notice'}>공지사항</SideLink>
|
||||||
<SideLink to={'qna'}>Q&A</SideLink>
|
<SideLink to={'qna'}>Q&A</SideLink>
|
||||||
<SideLink to={'freeboard'}>자유게시판</SideLink>
|
<SideLink to={'freeboard'}>자유게시판</SideLink>
|
||||||
<SideLink to={'quiz'}>퀴즈</SideLink>
|
{userType === 'student' && <SideLink to={'report'}>퀴즈 성적</SideLink>}
|
||||||
|
{userType === 'teacher' && <SideLink to={'quiz'}>퀴즈</SideLink>}
|
||||||
{userType === 'teacher' && <SideLink to={'enroll'}>수강신청관리</SideLink>}
|
{userType === 'teacher' && <SideLink to={'enroll'}>수강신청관리</SideLink>}
|
||||||
</SideBar>
|
</SideBar>
|
||||||
{userType === 'teacher' && (
|
{userType === 'teacher' && (
|
||||||
|
44
frontend/src/components/ReportCard/ReportCard.jsx
Normal file
44
frontend/src/components/ReportCard/ReportCard.jsx
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
import styles from './ReportCard.module.css';
|
||||||
|
|
||||||
|
export default function ReportCard({ allCount = 10, correctCount = 7 }) {
|
||||||
|
const radius = 2 * Math.PI * 100;
|
||||||
|
const percentage = allCount > 0 ? (correctCount / allCount) * 100 : 0;
|
||||||
|
const strokeDashoffset = radius - (percentage / 100) * radius;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={styles.wrapper}>
|
||||||
|
<div className={styles.svgWrapper}>
|
||||||
|
<svg
|
||||||
|
width="220"
|
||||||
|
height="220"
|
||||||
|
viewBox="0 0 220 220"
|
||||||
|
>
|
||||||
|
<circle
|
||||||
|
cx="110"
|
||||||
|
cy="110"
|
||||||
|
r="100"
|
||||||
|
strokeDasharray={radius}
|
||||||
|
strokeDashoffset={strokeDashoffset}
|
||||||
|
transform="rotate(-90 110 110)"
|
||||||
|
className={styles.circle}
|
||||||
|
/>
|
||||||
|
<text
|
||||||
|
x="50%"
|
||||||
|
y="50%"
|
||||||
|
textAnchor="middle"
|
||||||
|
dominantBaseline="middle"
|
||||||
|
className={`${styles.bodyStrong} ${styles.centerText}`}
|
||||||
|
>
|
||||||
|
{`점수 : ${Math.round(percentage)}`}
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<div className={styles.stats}>
|
||||||
|
<span className={styles.bodyStrong}>내 성적</span>
|
||||||
|
<span className={styles.body}>
|
||||||
|
{correctCount} / {allCount}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
44
frontend/src/components/ReportCard/ReportCard.module.css
Normal file
44
frontend/src/components/ReportCard/ReportCard.module.css
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
.wrapper {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
border-radius: 16px;
|
||||||
|
gap: 20px;
|
||||||
|
padding: 36px 40px;
|
||||||
|
width: 295px;
|
||||||
|
height: 388px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.svgWrapper {
|
||||||
|
position: relative;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.circle {
|
||||||
|
fill: none;
|
||||||
|
stroke: var(--success-color);
|
||||||
|
stroke-width: 20px;
|
||||||
|
stroke-linecap: round;
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stats {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bodyStrong {
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 1.4;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.body {
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 1.4;
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
1
frontend/src/components/ReportCard/index.js
Normal file
1
frontend/src/components/ReportCard/index.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
export { default as ReportCard } from './ReportCard';
|
10
frontend/src/hooks/api/useStudentReportDetail.js
Normal file
10
frontend/src/hooks/api/useStudentReportDetail.js
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import { useSuspenseQuery } from '@tanstack/react-query';
|
||||||
|
import instance from '../../utils/axios/instance';
|
||||||
|
import { API_URL } from '../../constants';
|
||||||
|
|
||||||
|
export function useStudentReportDetail(reportId) {
|
||||||
|
return useSuspenseQuery({
|
||||||
|
queryKey: ['studentreportdetail', reportId],
|
||||||
|
queryFn: () => instance.get(`${API_URL}/report/myreportdetail/${reportId}`),
|
||||||
|
});
|
||||||
|
}
|
10
frontend/src/hooks/api/useStudentReports.js
Normal file
10
frontend/src/hooks/api/useStudentReports.js
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import { useSuspenseQuery } from '@tanstack/react-query';
|
||||||
|
import instance from '../../utils/axios/instance';
|
||||||
|
import { API_URL } from '../../constants';
|
||||||
|
|
||||||
|
export function useStudentReports() {
|
||||||
|
return useSuspenseQuery({
|
||||||
|
queryKey: ['studentreports'],
|
||||||
|
queryFn: () => instance.get(`${API_URL}/report/myreport`),
|
||||||
|
});
|
||||||
|
}
|
71
frontend/src/pages/StudentReportPage/StudentReportPage.jsx
Normal file
71
frontend/src/pages/StudentReportPage/StudentReportPage.jsx
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
import { ArticleLink } from '../../components/ArticleLink';
|
||||||
|
import ArticleBoard from '../../components/ArticleBoard/ArticleBoard';
|
||||||
|
import { ReportCard } from '../../components/ReportCard';
|
||||||
|
import styles from './StudentReportPage.module.css';
|
||||||
|
import { useStudentReports } from '../../hooks/api/useStudentReports';
|
||||||
|
|
||||||
|
export default function StudentReportPage() {
|
||||||
|
const { data } = useStudentReports();
|
||||||
|
// const reports = data?.data;
|
||||||
|
const reports = [
|
||||||
|
{
|
||||||
|
reportId: 1,
|
||||||
|
title: '퀴즈 1',
|
||||||
|
correctCount: 8,
|
||||||
|
allCount: 10,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
reportId: 2,
|
||||||
|
title: '퀴즈 2',
|
||||||
|
correctCount: 7,
|
||||||
|
allCount: 10,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
reportId: 3,
|
||||||
|
title: '퀴즈 3',
|
||||||
|
correctCount: 9,
|
||||||
|
allCount: 10,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
reportId: 4,
|
||||||
|
title: '퀴즈 4',
|
||||||
|
correctCount: 6,
|
||||||
|
allCount: 10,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const totalCounts = reports.reduce(
|
||||||
|
(acc, report) => {
|
||||||
|
acc.correctCount += report.correctCount;
|
||||||
|
acc.allCount += report.allCount;
|
||||||
|
return acc;
|
||||||
|
},
|
||||||
|
{ correctCount: 0, allCount: 0 }
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ArticleBoard
|
||||||
|
title="퀴즈 성적"
|
||||||
|
canCreate={false}
|
||||||
|
>
|
||||||
|
<div className={styles.wrapper}>
|
||||||
|
<div className={styles.LinksContainer}>
|
||||||
|
{reports.map?.((report) => (
|
||||||
|
<ArticleLink
|
||||||
|
key={`${report.reportId}`}
|
||||||
|
title={report.title}
|
||||||
|
sub={`${Math.round((report.correctCount / report.allCount) * 100)}%`}
|
||||||
|
to={`${report.reportId}`}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
<div className={styles.reportCardContainer}>
|
||||||
|
<ReportCard
|
||||||
|
correctCount={totalCounts.correctCount}
|
||||||
|
allCount={totalCounts.allCount}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ArticleBoard>
|
||||||
|
);
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
.wrapper {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 40px;
|
||||||
|
flex: 1 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.LinksContainer {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reportCardContainer {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
}
|
1
frontend/src/pages/StudentReportPage/index.js
Normal file
1
frontend/src/pages/StudentReportPage/index.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
export { default } from './StudentReportPage';
|
Loading…
Reference in New Issue
Block a user