-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #167 from GDSC-Hongik/feature/student-statistics
[Feature] 멘토 페이지 스터디 통계 조회 기능 생성
- Loading branch information
Showing
15 changed files
with
1,374 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
67 changes: 67 additions & 0 deletions
67
apps/admin/app/studies/[studyId]/_components/statics/StudyAnalyticsGraph.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
import { css } from "@styled-system/css"; | ||
import { Flex } from "@styled-system/jsx"; | ||
import { Text } from "@wow-class/ui"; | ||
import type { StudyWeekStatisticsApiResponseDto } from "types/dtos/studyStatistics"; | ||
|
||
import BarGraph from "./graph/BarGraph"; | ||
|
||
const StudyAnalyticsGraph = ({ | ||
graphTitle, | ||
averageRate = 0, | ||
totalStudent, | ||
studyWeekStatisticsResponses, | ||
}: { | ||
graphTitle: string; | ||
averageRate?: number; | ||
totalStudent?: number; | ||
studyWeekStatisticsResponses?: StudyWeekStatisticsApiResponseDto[]; | ||
}) => { | ||
return ( | ||
<Flex direction="column" gap="md"> | ||
<Text className={staticsTitleStyle} typo="h3"> | ||
{graphTitle} | ||
</Text> | ||
<Flex direction="column" gap="xs"> | ||
<Flex alignItems="flex-start" direction="column" gap="md"> | ||
{studyWeekStatisticsResponses?.map((data) => ( | ||
<Flex direction="row" gap="lg" key={data.week} minWidth="340px"> | ||
<Text | ||
as="div" | ||
className={studyWeekStyle} | ||
color="sub" | ||
typo="body1" | ||
> | ||
{data.week}주차 | ||
</Text> | ||
<BarGraph | ||
isCurriculumCanceled={data.isCurriculumCanceled} | ||
percent={data.attendanceRate} | ||
totalStudent={totalStudent} | ||
/> | ||
</Flex> | ||
))} | ||
<Flex direction="row" gap="lg"> | ||
<Text className={studyWeekStyle} color="sub" typo="body1"> | ||
평균 | ||
</Text> | ||
<BarGraph | ||
barColor="average" | ||
isToolTipActive={false} | ||
percent={averageRate} | ||
/> | ||
</Flex> | ||
</Flex> | ||
</Flex> | ||
</Flex> | ||
); | ||
}; | ||
|
||
export default StudyAnalyticsGraph; | ||
|
||
const studyWeekStyle = css({ | ||
minWidth: "45px", | ||
}); | ||
|
||
const staticsTitleStyle = css({ | ||
marginBottom: "10px", | ||
}); |
44 changes: 44 additions & 0 deletions
44
apps/admin/app/studies/[studyId]/_components/statics/StudyCompleteRate.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
"use client"; | ||
import { Flex } from "@styled-system/jsx"; | ||
import { Text, Tooltip } from "@wow-class/ui"; | ||
import { Help } from "wowds-icons"; | ||
|
||
import CircleGraph from "./graph/CircleGraph"; | ||
|
||
const StudyCompleteRate = ({ | ||
studyCompleteCount, | ||
studyCompleteRate, | ||
}: { | ||
studyCompleteCount?: number; | ||
studyCompleteRate?: number; | ||
}) => { | ||
return ( | ||
<Flex direction="column" gap="md" minWidth="300px"> | ||
<Flex alignItems="center" gap="xs" marginLeft="8px"> | ||
<Text typo="h3">수료율</Text> | ||
<Tooltip | ||
content={ | ||
<Text color="white" typo="body1"> | ||
출석율과 과제제출률의 합이 | ||
<br /> | ||
70% 이상인 학생 비율 | ||
</Text> | ||
} | ||
> | ||
<Help fill="textBlack" height={20} stroke="textBlack" width={20} /> | ||
</Tooltip> | ||
</Flex> | ||
<Flex alignItems="center" direction="column" gap="lg"> | ||
<CircleGraph percentage={studyCompleteRate} /> | ||
<Text as="span" color="sub" typo="label1"> | ||
수료 가능한 인원{" "} | ||
<Text as="span" color="primary"> | ||
{studyCompleteCount}명 | ||
</Text> | ||
</Text> | ||
</Flex> | ||
</Flex> | ||
); | ||
}; | ||
|
||
export default StudyCompleteRate; |
50 changes: 50 additions & 0 deletions
50
apps/admin/app/studies/[studyId]/_components/statics/StudyStatics.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import { Flex } from "@styled-system/jsx"; | ||
import { Space, Text } from "@wow-class/ui"; | ||
import { studyApi } from "apis/study/studyApi"; | ||
|
||
import StudyAnalyticsGraph from "./StudyAnalyticsGraph"; | ||
import StudyCompleteRate from "./StudyCompleteRate"; | ||
|
||
const StudyStatics = async ({ studyId }: { studyId: string }) => { | ||
const studyStatistics = await studyApi.getStudyStatistics( | ||
parseInt(studyId, 10) | ||
); | ||
|
||
return ( | ||
<section aria-label="study-statics"> | ||
<Flex direction="column" gap="sm"> | ||
<Text typo="h2">스터디 통계</Text> | ||
<Text color="sub" typo="label2"> | ||
전체 {studyStatistics?.totalStudentCount}명, 수료 인원{" "} | ||
{studyStatistics?.completeStudentCount}명 | ||
</Text> | ||
</Flex> | ||
<Space height={33} /> | ||
<Flex alignItems="flex-start" gap="xl"> | ||
<StudyAnalyticsGraph | ||
averageRate={studyStatistics?.averageAttendanceRate} | ||
graphTitle="출석률" | ||
totalStudent={studyStatistics?.totalStudentCount} | ||
studyWeekStatisticsResponses={ | ||
studyStatistics?.studyWeekStatisticsResponses | ||
} | ||
/> | ||
<StudyAnalyticsGraph | ||
averageRate={studyStatistics?.averageAssignmentSubmissionRate} | ||
graphTitle="과제 제출률" | ||
totalStudent={studyStatistics?.totalStudentCount} | ||
studyWeekStatisticsResponses={ | ||
studyStatistics?.studyWeekStatisticsResponses | ||
} | ||
/> | ||
<StudyCompleteRate | ||
studyCompleteCount={studyStatistics?.completeStudentCount} | ||
studyCompleteRate={studyStatistics?.studyCompleteRate} | ||
/> | ||
</Flex> | ||
<Space height={33} /> | ||
</section> | ||
); | ||
}; | ||
|
||
export default StudyStatics; |
139 changes: 139 additions & 0 deletions
139
apps/admin/app/studies/[studyId]/_components/statics/graph/BarGraph.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
"use client"; | ||
import { css, cva } from "@styled-system/css"; | ||
import { Flex } from "@styled-system/jsx"; | ||
import { Text } from "@wow-class/ui"; | ||
import clsx from "clsx"; | ||
|
||
import GraphToolTip from "./GraphToolTip"; | ||
|
||
const BarGraph = ({ | ||
barColor = "default", | ||
totalStudent = 0, | ||
percent = 0, | ||
isCurriculumCanceled, | ||
isToolTipActive = true, | ||
}: { | ||
barColor?: "default" | "average"; | ||
totalStudent?: number; | ||
isToolTipActive?: boolean; | ||
percent?: number; | ||
isCurriculumCanceled?: boolean; | ||
}) => { | ||
return ( | ||
<Flex | ||
alignItems="center" | ||
flexShrink="0" | ||
gap="sm" | ||
justifyContent="flex-start" | ||
> | ||
<div | ||
className={BarGraphBackgroundStyle({ | ||
type: isCurriculumCanceled ? "canceled" : "default", | ||
})} | ||
> | ||
{percent > 0 ? ( | ||
<div | ||
style={{ width: `${50 + (232 - 50) * (percent / 100)}px` }} | ||
className={clsx( | ||
barGraphStyle({ | ||
type: barColor, | ||
}), | ||
isToolTipActive && | ||
css({ | ||
"&:hover .tooltip": { | ||
visibility: "visible !important", | ||
}, | ||
}) | ||
)} | ||
> | ||
<div className={barGraphInnerStyle}> | ||
<Text className={percentLabelStyle} color="white" typo="label2"> | ||
{percent}% | ||
</Text> | ||
<GraphToolTip | ||
studentCount={Math.ceil((percent / 100) * totalStudent)} | ||
/> | ||
</div> | ||
</div> | ||
) : ( | ||
<Text className={zeroPercentLabelStyle} color="sub" typo="label2"> | ||
0% | ||
</Text> | ||
)} | ||
</div> | ||
{isCurriculumCanceled && ( | ||
<Text as="div" color="sub" typo="label2"> | ||
휴강 | ||
</Text> | ||
)} | ||
</Flex> | ||
); | ||
}; | ||
|
||
export default BarGraph; | ||
|
||
const BarGraphBackgroundStyle = cva({ | ||
base: { | ||
position: "relative", | ||
minWidth: "232px", | ||
width: "232px", | ||
height: "32px", | ||
display: "flex", | ||
alignItems: "center", | ||
gap: "4px", | ||
flex: 2, | ||
zIndex: "5", | ||
borderRadius: "4px", | ||
}, | ||
variants: { | ||
type: { | ||
default: { | ||
backgroundColor: "monoBackgroundPressed", | ||
}, | ||
canceled: { | ||
backgroundColor: "lightDisabled", | ||
}, | ||
}, | ||
}, | ||
}); | ||
|
||
const barGraphStyle = cva({ | ||
base: { | ||
position: "absolute", | ||
zIndex: 10, | ||
top: 0, | ||
left: 0, | ||
height: "32px", | ||
padding: "4px 8px", | ||
display: "flex", | ||
alignItems: "center", | ||
borderRadius: "4px", | ||
}, | ||
|
||
variants: { | ||
type: { | ||
default: { | ||
backgroundColor: "primary", | ||
}, | ||
average: { | ||
backgroundColor: "secondaryYellow", | ||
}, | ||
}, | ||
}, | ||
}); | ||
|
||
const percentLabelStyle = css({ | ||
height: "100%", | ||
display: "flex", | ||
alignItems: "center", | ||
}); | ||
|
||
const barGraphInnerStyle = css({ | ||
position: "relative", | ||
width: "100%", | ||
height: "100%", | ||
}); | ||
|
||
const zeroPercentLabelStyle = css({ | ||
marginLeft: "8px", | ||
}); |
Oops, something went wrong.