Skip to content

Commit ec33240

Browse files
authored
Merge pull request #1186 from topcoder-platform/pm-1503_1
feat(PM-1503): View scorecard implementation
2 parents b257b51 + c199705 commit ec33240

File tree

15 files changed

+482
-6
lines changed

15 files changed

+482
-6
lines changed
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import useSWR, { SWRResponse } from 'swr'
2+
3+
import { EnvironmentConfig } from '~/config'
4+
import { xhrGetAsync } from '~/libs/core'
5+
6+
import { Scorecard } from '../models'
7+
8+
interface UseFetchScorecardParams {
9+
id: string;
10+
}
11+
const baseUrl = `${EnvironmentConfig.API.V6}/review`
12+
13+
export function useFetchScorecard(
14+
{
15+
id,
16+
}: UseFetchScorecardParams,
17+
): Scorecard {
18+
19+
const fetcher = (url: string): Promise<Scorecard> => xhrGetAsync<Scorecard>(url)
20+
21+
const { data }: SWRResponse<Scorecard, any> = useSWR<Scorecard>(
22+
`${baseUrl}/scorecards/${id}`,
23+
fetcher,
24+
)
25+
26+
return data as Scorecard
27+
}

src/apps/review/src/lib/models/Scorecard.model.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
* Scorecard
33
*/
44

5+
import { ScorecardGroup } from './ScorecardGroup.model'
6+
57
export enum ProjectType {
68
DEVELOPMENT = 'DEVELOPMENT',
79
DATA_SCIENCE = 'DATA_SCIENCE',
@@ -94,4 +96,9 @@ export interface Scorecard {
9496
category: string
9597
status: ScorecardStatus
9698
index?: number
99+
version: string
100+
challengeType: string
101+
minScore: number
102+
maxScore: number
103+
scorecardGroups: ScorecardGroup[]
97104
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
.container {
2+
display: flex;
3+
flex-direction: row;
4+
padding: 32px;
5+
background-color: #F6F7F9;
6+
margin-top: 20px;
7+
border-radius: 8px;
8+
.left {
9+
display: flex;
10+
flex: 1;
11+
flex-direction: column;
12+
}
13+
14+
.item {
15+
display: flex;
16+
flex-direction: column;
17+
margin-bottom: 20px;
18+
.label {
19+
font-weight: 700;
20+
font-family: "Nunito Sans", sans-serif;
21+
font-size: 16px;
22+
color: #000000;
23+
margin-bottom: 6px;
24+
}
25+
.value {
26+
font-weight: 400;
27+
font-family: "Nunito Sans", sans-serif;
28+
font-size: 16px;
29+
color: #0A0A0A;
30+
text-transform: capitalize;
31+
&.active {
32+
color: #00797A;
33+
}
34+
35+
&.inactive, &.deleted {
36+
color: #767676;
37+
font-family: 'Inter', sans-serif;
38+
font-weight: 600;
39+
font-size: 14px;
40+
}
41+
}
42+
}
43+
44+
.right {
45+
display: flex;
46+
flex: 3;
47+
flex-direction: column;
48+
.item {
49+
display: flex;
50+
flex-direction: column;
51+
}
52+
}
53+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import { FC } from 'react'
2+
import cn from 'classnames'
3+
4+
import { ProjectTypeLabels, Scorecard, ScorecardStatusLabels, ScorecardTypeLabels } from '~/apps/review/src/lib/models'
5+
6+
import styles from './ScorecardDetails.module.scss'
7+
8+
interface ScorecardDetailsProps {
9+
scorecard: Scorecard
10+
}
11+
12+
const ScorecardDetails: FC<ScorecardDetailsProps> = (props: ScorecardDetailsProps) => {
13+
const getStatusClassname = (): string => styles[ScorecardStatusLabels[props.scorecard.status]?.toLowerCase()]
14+
return (
15+
<div className={styles.container}>
16+
<div className={styles.left}>
17+
<div className={styles.item}>
18+
<div className={styles.label}>Version</div>
19+
<div className={styles.value}>{props.scorecard.version}</div>
20+
</div>
21+
<div className={styles.item}>
22+
<div className={styles.label}>Type</div>
23+
<div className={styles.value}>{ScorecardTypeLabels[props.scorecard.type]}</div>
24+
</div>
25+
<div className={styles.item}>
26+
<div className={styles.label}>Project Type</div>
27+
<div className={styles.value}>{ProjectTypeLabels[props.scorecard.challengeTrack]}</div>
28+
</div>
29+
</div>
30+
<div className={styles.right}>
31+
<div className={styles.item}>
32+
<div className={styles.label}>Category</div>
33+
<div className={styles.value}>{props.scorecard.challengeType}</div>
34+
</div>
35+
<div className={styles.item}>
36+
<div className={styles.label}>Status</div>
37+
<div
38+
className={cn(styles.value, getStatusClassname())}
39+
>
40+
{ScorecardStatusLabels[props.scorecard.status]}
41+
</div>
42+
</div>
43+
<div className={styles.item}>
44+
<div className={styles.label}>Min - Max. Score</div>
45+
<div className={styles.value}>{`${props.scorecard.minScore} - ${props.scorecard.maxScore}`}</div>
46+
</div>
47+
</div>
48+
</div>
49+
)
50+
}
51+
52+
export default ScorecardDetails
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { default as ScorecardDetails } from './ScorecardDetails'
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
@import '@libs/ui/styles/includes';
2+
3+
.container {
4+
margin-top: 32px;
5+
.group {
6+
.heading {
7+
padding: 12px 16px;
8+
background-color: #0F172A;
9+
color: #ffffff;
10+
display: flex;
11+
flex-direction: column;
12+
border-top-left-radius: 8px;
13+
border-top-right-radius: 8px;
14+
.groupNumber {
15+
font-size: 14px;
16+
font-family: "Nunito Sans", sans-serif;
17+
font-weight: 400;
18+
}
19+
.groupInfo {
20+
display: flex;
21+
flex-direction: row;
22+
font-size: 16px;
23+
font-family: "Nunito Sans", sans-serif;
24+
margin-top: 4px;
25+
.name {
26+
display: flex;
27+
flex: 1;
28+
font-weight: 700;
29+
}
30+
}
31+
}
32+
}
33+
}
34+
35+
@media (max-width: #{$lg-max}) {
36+
.container {
37+
.group {
38+
.heading {
39+
.groupInfo {
40+
flex-direction: column;
41+
.name {
42+
margin-bottom: 8px;
43+
}
44+
}
45+
}
46+
}
47+
}
48+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { FC } from 'react'
2+
3+
import { ScorecardGroup } from '~/apps/review/src/lib/models'
4+
5+
import ScorecardSections from '../ScorecardSections/ScorecardSections'
6+
7+
import styles from './ScorecardGroups.module.scss'
8+
9+
interface ScorecardGroupsProps {
10+
groups: ScorecardGroup[]
11+
}
12+
13+
const ScorecardGroups: FC<ScorecardGroupsProps> = (props: ScorecardGroupsProps) => (
14+
<div className={styles.container}>
15+
{
16+
props.groups.map((group, index) => (
17+
<div key={group.id} className={styles.group}>
18+
<div className={styles.heading}>
19+
<div className={styles.groupNumber}>{`Group ${index + 1}`}</div>
20+
<div className={styles.groupInfo}>
21+
<div className={styles.name}>{group.name}</div>
22+
<div>{group.weight}</div>
23+
</div>
24+
</div>
25+
<ScorecardSections sections={group.sections} />
26+
</div>
27+
))
28+
}
29+
</div>
30+
)
31+
32+
export default ScorecardGroups
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { default as ScorecardGroups } from './ScorecardGroups'
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
@import '@libs/ui/styles/includes';
2+
3+
.container {
4+
background-color: #E0E4E84D;
5+
padding: 40px 32px;
6+
.section {
7+
.heading {
8+
padding: 12px 16px;
9+
background-color: #00797A;
10+
color: #ffffff;
11+
display: flex;
12+
flex-direction: column;
13+
border-top-left-radius: 8px;
14+
border-top-right-radius: 8px;
15+
.sectionInfo {
16+
display: flex;
17+
flex-direction: row;
18+
margin-top: 4px;
19+
font-size: 16px;
20+
font-family: "Nunito Sans", sans-serif;
21+
.name {
22+
display: flex;
23+
flex: 1;
24+
font-weight: 700;
25+
}
26+
}
27+
}
28+
.questions {
29+
background-color: #FFFFFF;
30+
padding: 32px 20px;
31+
.question {
32+
background-color: #F6F7F9;
33+
padding: 20px 16px;
34+
display: flex;
35+
flex-direction: row;
36+
color: #0A0A0A;
37+
margin-bottom: 0px;
38+
&.notLast {
39+
margin-bottom: 20px;
40+
}
41+
.left {
42+
display: flex;
43+
flex: 4;
44+
flex-direction: column;
45+
.description {
46+
font-weight: 700;
47+
font-size: 16px;
48+
}
49+
.detailItemsWrapper {
50+
margin-top: 16px;
51+
.detailItem {
52+
display: flex;
53+
flex-direction: row;
54+
font-family: "Nunito Sans", sans-serif;
55+
margin-bottom: 8px;
56+
.label {
57+
font-weight: 700;
58+
font-size: 14px;
59+
min-width: 142px;
60+
}
61+
.value {
62+
font-weight: 400;
63+
font-size: 14px;
64+
}
65+
}
66+
}
67+
}
68+
.right {
69+
display: flex;
70+
flex: 1;
71+
justify-content: flex-end;
72+
}
73+
}
74+
}
75+
}
76+
}
77+
78+
@media (max-width: #{$lg-max}) {
79+
.container {
80+
.section {
81+
.heading {
82+
.sectionInfo {
83+
flex-direction: column;
84+
.name {
85+
margin-bottom: 4px;
86+
}
87+
}
88+
}
89+
.questions {
90+
.question {
91+
flex-direction: column;
92+
.left {
93+
.detailItemsWrapper {
94+
.detailItem {
95+
flex-direction: column;
96+
min-width: auto;
97+
}
98+
}
99+
}
100+
.right {
101+
justify-content: flex-start;
102+
}
103+
}
104+
}
105+
}
106+
}
107+
}

0 commit comments

Comments
 (0)