-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathranking.jsx
90 lines (80 loc) · 3.32 KB
/
ranking.jsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
import React, { useState, useEffect } from 'react'
import { createUseStyles } from 'react-jss'
import cx from 'classnames'
const responseOptions = ['Most', 'Neutral', 'Least']
const selectedOption = (
<>
<rect x="1" y="1" width="22" height="22" rx="11" stroke="#08447B" strokeWidth="2" />
<rect x="6" y="6" width="12" height="12" rx="6" fill="#08447B" />
</>
)
const unselectedOption = <rect x="1" y="1" width="22" height="22" rx="11" stroke="#06335C" strokeWidth="2" />
// table to map from data model properties, to the Rank Strings shown in the UI
const toRankString = {
undefined: '',
most: 'Most',
least: 'Least',
neutral: 'Neutral',
}
// table to map from UI's Rank Strings to the data model prpoerty names
const rankStringToCategory = Object.entries(toRankString).reduce((rS2C, [key, value]) => {
if (key === 'undefined') return rS2C // rankStringToCategory[''] will be undefined
rS2C[value] = key
return rS2C
}, {})
function Rank(props) {
const { onDone, rank, ...otherProps } = props
const handleOnDone = result => ({ valid: result.valid, value: rankStringToCategory[result.value] })
return <Ranking onDone={handleOnDone} rank={toRankString[rank]} {...otherProps}></Ranking>
}
export default function Ranking(props) {
//Isolate props and set initial state
const { disabled, defaultValue, className, onDone, ...otherProps } = props
let [response, setResponse] = useState(responseOptions.includes(defaultValue) ? defaultValue : '')
useEffect(() => {
if (defaultValue) {
if (!responseOptions.includes(defaultValue)) {
setResponse(undefined)
onDone && onDone({ valid: false, value: '' })
} else {
setResponse(defaultValue)
onDone && onDone({ valid: true, value: defaultValue })
}
}
}, [defaultValue])
//Introduce component styling
const styleClasses = rankingStyleClasses(props)
const onSelectionChange = e => {
if (e.target.disabled) {
return
}
setResponse(e.target.value)
if (!onDone) {
return console.warn(`Unhandled rank selection: ${e.target.value}. Please pass a handler function via the onDone prop.`)
} else onDone({ valid: true, value: e.target.value })
}
return (
<div data-value={response} className={cx(className, styleClasses.group, disabled && styleClasses.disabled)} onChange={onSelectionChange} {...otherProps}>
{responseOptions.map(option => {
return (
<label>
<input disabled={disabled || false} checked={response === option} type="radio" value={option} name={`importance-${option}`} className={cx(styleClasses.hideDefaultRadio, `ranking${option}`)}></input>
<span className={cx(styleClasses.option)}>
<svg className={cx(styleClasses.optionIcon)} viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
{response === option ? selectedOption : unselectedOption}
</svg>
{option}
</span>
</label>
)
})}
</div>
)
}
const rankingStyleClasses = createUseStyles({
optionIcon: { height: 'inherit', color: 'inherit', marginRight: '0.125rem' },
option: { display: 'flex', height: '1.5rem', lineHeight: '1.5rem', color: 'inherit' },
group: { display: 'flex', gap: '1.4375rem' },
disabled: { opacity: '30%' },
hideDefaultRadio: { display: 'none !important' },
})