Skip to content

Commit f8dcdaa

Browse files
authored
Merge pull request #14 from tutorcruncher/datetime-fields
supporting date and datetime fields
2 parents f59bcfe + 846daab commit f8dcdaa

File tree

6 files changed

+128
-61
lines changed

6 files changed

+128
-61
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "tutorcruncher-socket",
3-
"version": "1.0.5",
3+
"version": "1.1.0",
44
"description": "TutorCruncher socket",
55
"author": "Samuel Colvin <[email protected]>",
66
"private": false,

public/simple/index.html

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@
3232
</main>
3333
</body>
3434
<script>
35-
window.socket = socket('9c79f14df986a1ec693c')
35+
window.socket = socket('f028073b6cfeb13223cb', {
36+
mode: 'enquiry',
37+
api_root: 'https://socket-beta.tutorcruncher.com',
38+
})
3639
</script>
3740
</html>

src/components/shared/Input.js

Lines changed: 113 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,120 @@
11
import React, { Component } from 'react'
2-
import { If, Switch } from './Tools'
2+
3+
const GeneralInput = ({field, name, value, field_label, on_change}) => (
4+
<input type={field.type}
5+
name={name}
6+
placeholder={field_label}
7+
required={field.required}
8+
maxLength={field.max_length || 255}
9+
value={value}
10+
onChange={on_change}/>
11+
)
12+
13+
const TextInput = ({field, name, value, field_label, on_change}) => (
14+
field.max_length > 500 ? (
15+
<textarea name={name}
16+
placeholder={field_label}
17+
required={field.required}
18+
maxLength={field.max_length || 255}
19+
value={value}
20+
onChange={on_change}
21+
rows="5"/>
22+
) : (
23+
<GeneralInput field={field} name={name} value={value} field_label={field_label} on_change={on_change}/>
24+
)
25+
)
26+
27+
const Checkbox = ({field, name, value, field_label, on_change}) => (
28+
<label>
29+
<input type="checkbox"
30+
name={name}
31+
required={field.required}
32+
checked={value}
33+
onChange={on_change}/>
34+
{field_label}
35+
</label>
36+
)
37+
38+
const Select = ({field, name, value, field_label, on_change}) => (
39+
<label>
40+
{field_label}
41+
<select name={name} required={field.required} value={value} onChange={on_change}>
42+
<option value="">---------</option>
43+
{field.choices && field.choices.map((choice, i) => (
44+
<option key={i} value={choice.value}>
45+
{choice.display_name}
46+
</option>
47+
))}
48+
</select>
49+
</label>
50+
)
51+
52+
const DateInput = ({field, name, value, field_label, on_change}) => (
53+
<label>
54+
{field_label}
55+
<GeneralInput field={field} name={name} value={value} field_label={field_label} on_change={on_change}/>
56+
</label>
57+
)
58+
59+
const DatetimeInput = ({field, name, value, field_label, on_change}) => {
60+
// could use https://stackoverflow.com/a/31162426/949890
61+
const re_match = value.match(/(.*?)T(.*)/)
62+
const render_values = {
63+
date: re_match ? re_match[1] : '',
64+
time: re_match ? re_match[2] : '',
65+
}
66+
67+
const on_change_ = (event) => {
68+
render_values[event.target.getAttribute('type')] = event.target.value
69+
on_change({target: {value: render_values.date + 'T' + render_values.time}})
70+
}
71+
const required = field.required || render_values.date !== '' || render_values.time !== ''
72+
return (
73+
<label>
74+
{field_label}
75+
<div className="tcs-datetime">
76+
<input type="date"
77+
name={name + '-date'}
78+
required={required}
79+
value={render_values.date}
80+
onChange={on_change_}/>
81+
<input type="time"
82+
step="300"
83+
name={name + '-time'}
84+
required={required}
85+
value={render_values.time}
86+
onChange={on_change_}/>
87+
</div>
88+
</label>
89+
)
90+
}
91+
92+
const IntegerInput = ({field, name, value, field_label, on_change}) => (
93+
<input type="number"
94+
step="1"
95+
name={name}
96+
placeholder={field_label}
97+
required={field.required}
98+
value={value}
99+
onChange={on_change}/>
100+
)
101+
102+
const INPUT_LOOKUP = {
103+
'text': TextInput,
104+
'checkbox': Checkbox,
105+
'select': Select,
106+
'date': DateInput,
107+
'datetime': DatetimeInput,
108+
'integer': IntegerInput,
109+
}
3110

4111
class Input extends Component {
5112
constructor (props) {
6113
super(props)
7-
this.changed = this.changed.bind(this)
114+
this.on_change = this.on_change.bind(this)
8115
}
9116

10-
changed (event) {
11-
// this.setState({value: event.target.value})
117+
on_change (event) {
12118
const field = this.props.field
13119
const value = field.type === 'checkbox' ? event.target.checked : event.target.value
14120
if (field.prefix) {
@@ -31,52 +137,11 @@ class Input extends Component {
31137
value = this.props.enquiry_data[field.field] || ''
32138
}
33139

140+
const Input = INPUT_LOOKUP[field.type] || GeneralInput
141+
34142
return (
35143
<div className="tcs-field" id={'field-' + name}>
36-
<Switch>
37-
<If v={field.type === 'text' && field.max_length > 500}>
38-
<textarea name={name}
39-
placeholder={field_label}
40-
required={field.required}
41-
maxLength={field.max_length || 255}
42-
value={value}
43-
onChange={this.changed}
44-
rows="5"/>
45-
</If>
46-
47-
<If v={field.type === 'checkbox'}>
48-
<label>
49-
<input type="checkbox"
50-
name={name}
51-
required={field.required}
52-
checked={value}
53-
onChange={this.changed}/>
54-
{field_label}
55-
</label>
56-
</If>
57-
58-
<If v={field.type === 'select'}>
59-
<label>
60-
{field_label}
61-
<select name={name} required={field.required} value={value} onChange={this.changed}>
62-
<option value="">---------</option>
63-
{field.choices && field.choices.map((choice, i) => (
64-
<option key={i} value={choice.value}>
65-
{choice.display_name}
66-
</option>
67-
))}
68-
</select>
69-
</label>
70-
</If>
71-
72-
<input type={field.type}
73-
name={name}
74-
placeholder={field_label}
75-
required={field.required}
76-
maxLength={field.max_length || 255}
77-
value={value}
78-
onChange={this.changed}/>
79-
</Switch>
144+
<Input field={field} name={name} value={value} field_label={field_label} on_change={this.on_change}/>
80145
<div className={'help-text' + (field.prefix ? '' : ' muted')}>
81146
{field.help_text}
82147
</div>

src/components/shared/Modal.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ class Modal extends Component {
3838
close () {
3939
this.setState({show: false})
4040
const h = this.props.history
41-
const next_url = this.props.last_url ? this.props.last_url : h.location.pathname.replace(/\/[^/]+$/, '')
41+
const next_url = this.props.last_url ? this.props.last_url : h.location.pathname.replace(/\/[^/]+$/, '/')
4242
setTimeout(() => h.push(next_url), 200)
4343
}
4444

src/components/shared/Tools.js

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -57,16 +57,6 @@ export const IfElse = ({v, children}) => {
5757
}
5858
}
5959

60-
export const Switch = ({children}) => {
61-
// All but the last child of a Switch component must be "If" components
62-
for (let c of children.slice(0, children.length - 1)) {
63-
if (c.props.v) {
64-
return c.props.children
65-
}
66-
}
67-
return children[children.length - 1]
68-
}
69-
7060
export const Markdown = ({content}) => (
7161
<div className="tcs-md" dangerouslySetInnerHTML={{__html: to_markdown(content)}}/>
7262
)

src/styles/input.scss

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,13 @@ $border-colour: #66afe9;
4343
display: none;
4444
}
4545
}
46+
.tcs-datetime input {
47+
width: calc(50% - 5px);
48+
&:first-child {
49+
margin-right: 5px
50+
}
51+
&:last-child {
52+
margin-left: 5px;
53+
}
54+
}
4655
}

0 commit comments

Comments
 (0)