blob: 929622d76d3861009434de0f740cda6bf728c943 [file] [log] [blame]
pineafana0e4b9b2021-11-02 21:10:49 +00001import Styles from "../../styles/clicksforms/form.module.css"
2import { Component } from "react"
3
4class Question extends Component {
5 constructor(props) {
6 super(props)
7 this.state = {
8 status: null,
pineafan9babd752022-10-21 21:47:52 +01009 answer: this.props.type === "multichoice" ? [] : null,
pineafana0e4b9b2021-11-02 21:10:49 +000010 errorString: null,
11 }
12 }
13
14 getCol(col) {
15 switch ( col ) {
16 case 'red':
17 return "#F27878";
18 case 'orange':
19 return "#E5AB71";
20 case 'yellow':
21 return "#F2D478";
22 case 'green':
23 return "#65CC76";
24 case 'blue':
25 return "#71AFE5";
26 case 'purple':
27 return "#A358B2";
28 case 'pink':
29 return "#D46899";
30 case 'grey':
31 return "#777777";
32 case 'default':
33 return "#D4D4D4";
34 }
35 }
36
37 onChange(answer) {
38 let valid = null;
39 let errorString = null;
40
41 switch ( this.props.type ) {
42 case 'text':
43 if ( !answer.length ) {
44 valid = null
45 } else if ( answer.length < this.props.options.min ) {
46 valid = false
47 errorString = `Your answer must be at least ${this.props.options.min} characters long. Your response is ${answer.length}.`
48 } else if ( answer.length > this.props.options.max ) {
49 valid = false
50 errorString = `Your answer must be at most ${this.props.options.max} characters long. Your response is ${answer.length}.`
51 } else {
52 valid = true
53 errorString = null
54 }
55 break
56 case 'number':
57 if ( !answer.length ) {
58 valid = null
59 } else if ( isNaN(parseInt(answer)) ) {
60 valid = false
61 errorString = `Your answer must be a number.`
62 } else if ( answer < this.props.options.min ) {
63 valid = false
64 errorString = `Your answer must be at least ${this.props.options.min}`
65 } else if ( answer > this.props.options.max ) {
66 valid = false
67 errorString = `Your answer must be at most ${this.props.options.max}`
68 } else {
69 valid = true
70 errorString = null
71 }
72 break
73 case 'multichoice':
pineafan9babd752022-10-21 21:47:52 +010074 if ( typeof answer !== 'object' ) {
pineafana0e4b9b2021-11-02 21:10:49 +000075 valid = null
76 } else if ( !answer.length ) {
77 valid = null
78 } else if ( answer.length < this.props.options.min ) {
79 valid = false
80 errorString = `You must select at least ${this.props.options.min} options.`
81 } else if ( answer.length > this.props.options.max ) {
82 valid = false
83 errorString = `You must select at most ${this.props.options.max} options.`
84 } else {
85 valid = true
86 errorString = null
87 }
88 break
89 case 'fileupload', 'date', 'time':
pineafan9babd752022-10-21 21:47:52 +010090 valid = answer !== null ? true : null
pineafana0e4b9b2021-11-02 21:10:49 +000091 break
92 }
93 this.setState({
94 answer: answer,
95 status: valid,
96 errorString: errorString,
97 })
98 }
99
100 render() {
pineafan9babd752022-10-21 21:47:52 +0100101 let borderColor = this.state.status === false ? this.getCol("red") : this.getCol("default");
pineafana0e4b9b2021-11-02 21:10:49 +0000102 return (
103 <div className={Styles.questionContainer} style={{
104 boxShadow: `0px 0px 10px ${borderColor}`,
105 }}>
106 <h1 className={Styles.title}><div style={{color: this.getCol(this.props.colour), display: "inline"}}>&gt;</div> {this.props.title}</h1>
107 <h2 className={Styles.description}>{this.props.description}</h2>
108 <hr className={Styles.hr} style={{borderColor: this.getCol("default")}}/>
109 {
110 (() => {
111 switch ( this.props.type ) {
112 case 'text':
113 return (
114 <textarea className={Styles.input} onChange={(e) => this.onChange(e.target.value)} style={{
115 borderColor: borderColor,
116 }}></textarea>
117 )
118 case 'number':
119 return (
120 <input
121 className={Styles.input}
122 type="number"
123 onChange={(e) => {
124 this.onChange(e.target.value)
125 }}
126 style={{borderColor: borderColor}}
127 />
128 )
129 case 'multichoice':
130 return "not yet"
131 case 'fileupload':
132 return (
133 <input className={Styles.input} type="file" onChange={(e) => {
134 this.onChange(e.target.files[0])
135 }} style={{
136 borderColor: borderColor
137 }} />
138 )
139 case 'date':
140 return (
141 <input className={Styles.input} type="date" onChange={(e) => {
142 this.onChange(e.target.value)
143 }} style={{
144 borderColor: borderColor
145 }} />
146 )
147 case 'time':
148 return (
149 <input className={Styles.input} type="time" onChange={(e) => {
150 this.onChange(e.target.value)
151 }} style={{
152 borderColor: borderColor
153 }} />
154 )
155 }
156 })()
157 }
158 <div className={Styles.errorContainer} style={{height: this.state.errorString ? "25px" : "0"}}>{this.state.errorString}</div>
159 </div>
160 )
161 }
162}
163
164export default Question;