Skip to content

Commit 5da8e4f

Browse files
authored
Merge pull request #12 from tutorcruncher/list-view
list view
2 parents 66c1daa + fbbe8d1 commit 5da8e4f

30 files changed

+652
-202
lines changed

config-overrides.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,13 @@ module.exports = function override (config, env) {
4848
filename: 'foobar/index.html'
4949
})
5050
)
51+
config.plugins.splice(2, 0,
52+
new HtmlWebpackPlugin({
53+
inject: true,
54+
template: path.resolve(__dirname, 'public', 'simple/index.html'),
55+
filename: 'simple/index.html'
56+
})
57+
)
5158
}
5259
// console.dir(config, { depth: 10, colors: true })
5360
return config

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
"react-router-dom": "^4.2.2",
4848
"react-scripts": "1.0.17",
4949
"react-select": "1.2.0",
50+
"react-tooltip": "^3.4.0",
5051
"sass-loader": "^6.0.6",
5152
"shelljs": "0.8.0",
5253
"webpack": "^3.10.0",

public/index.html

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,29 +13,43 @@
1313
* {
1414
box-sizing: border-box; /* bootstrap does this on most sites. */
1515
}
16-
main > div {
17-
background-color: white;
16+
main {
1817
max-width: 800px;
1918
margin: 20px auto;
19+
}
20+
main > div {
21+
background-color: white;
2022
border: 1px solid #aaa;
2123
}
2224
</style>
2325
</head>
2426
<body>
2527
<main>
26-
<a href="https://github.com/tutorcruncher/socket-frontend">github.com/tutorcruncher/socket-frontend</a>
28+
<p><a href="https://github.com/tutorcruncher/socket-frontend">github.com/tutorcruncher/socket-frontend</a></p>
29+
<p><a href="/simple/">view simple socket panel</a></p>
30+
<p>mode defined by options:</p>
2731
<div id="socket1"></div>
32+
<p>Grid mode:</p>
2833
<div id="socket2"></div>
34+
<p>Enquiry:</p>
2935
<div id="socket3"></div>
36+
<p>Enquiry Modal:</p>
37+
<div id="socket4"></div>
3038
</main>
3139
</body>
3240
<script>
3341
var public_key = '9c79f14df986a1ec693c' // '61e9d8d03109e44d7c67'
3442
var api_root = null // 'https://socket-beta.tutorcruncher.com' 'http://localhost:8000'
35-
var socket1 = socket(public_key, {
43+
window.socket1 = socket(public_key, {
3644
element: '#socket1',
3745
router_mode: 'history',
3846
api_root: api_root,
47+
pagination: 8,
48+
})
49+
socket(public_key, {
50+
element: '#socket2',
51+
router_mode: 'history',
52+
api_root: api_root,
3953
mode: 'grid',
4054
labels_include: [],
4155
labels_exclude: [],
@@ -44,13 +58,13 @@
4458
}
4559
})
4660
socket(public_key, {
47-
element: '#socket2',
61+
element: '#socket3',
4862
router_mode: 'history',
4963
mode: 'enquiry',
5064
api_root: api_root,
5165
})
5266
socket(public_key, {
53-
element: '#socket3',
67+
element: '#socket4',
5468
router_mode: 'history',
5569
mode: 'enquiry-modal',
5670
api_root: api_root,

public/simple/index.html

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
6+
<title>tutorcruncher-socket</title>
7+
<style>
8+
@import url(https://fonts.googleapis.com/css?family=Open+Sans:400,500);
9+
body {
10+
background: #eee;
11+
font-family: 'Open Sans', sans-serif;
12+
}
13+
* {
14+
box-sizing: border-box; /* bootstrap does this on most sites. */
15+
}
16+
main {
17+
max-width: 800px;
18+
margin: 20px auto;
19+
}
20+
main > div {
21+
background-color: white;
22+
border: 1px solid #aaa;
23+
}
24+
</style>
25+
</head>
26+
<body>
27+
<main>
28+
<p><a href="https://github.com/tutorcruncher/socket-frontend">github.com/tutorcruncher/socket-frontend</a></p>
29+
<p><a href="/">back to index</a></p>
30+
<p>simple socket view:</p>
31+
<div id="socket"></div>
32+
</main>
33+
</body>
34+
<script>
35+
window.socket = socket('9c79f14df986a1ec693c')
36+
</script>
37+
</html>

src/components/App.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,13 +61,13 @@ class App extends Component {
6161
render () {
6262
if (this.state.error) {
6363
return <Error>{this.state.error}</Error>
64-
} else if (this.props.config.mode === 'grid') {
65-
return <Contractors root={this} config={this.props.config} history={this.props.history}/>
6664
} else if (this.props.config.mode === 'enquiry') {
6765
return <PlainEnquiry root={this} config={this.props.config}/>
68-
} else {
69-
// enquiry-modal
66+
} else if (this.props.config.mode === 'enquiry-modal') {
7067
return <EnquiryButton root={this} config={this.props.config}/>
68+
} else {
69+
// grid or list
70+
return <Contractors root={this} config={this.props.config} history={this.props.history}/>
7171
}
7272
}
7373
}

src/components/contractors/ConModal.js

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import Modal from '../shared/Modal'
33
import { Location, IfElse } from '../shared/Tools'
44
import ConDetails from './ConDetails'
55
import EnquiryForm from '../shared/EnquiryForm'
6+
import Stars from './Stars'
67

78
const TRANSITION_TIME = 500
89

@@ -12,7 +13,7 @@ class ConModal extends Component {
1213
this.con_id = parseInt(this.props.id, 10)
1314
this.state = {
1415
show_enquiry: false,
15-
transition_class: ''
16+
transition_class: '',
1617
}
1718
this.get_contractor = this.get_contractor.bind(this)
1819
this.switch_view = this.switch_view.bind(this)
@@ -27,7 +28,7 @@ class ConModal extends Component {
2728
}
2829

2930
switch_view () {
30-
this.setState({transition_class: ' leave'})
31+
this.setState({transition_class: ' in-trans'})
3132
setTimeout(() => {
3233
this.setState({show_enquiry: !this.state.show_enquiry, transition_class: ''})
3334
}, TRANSITION_TIME)
@@ -56,24 +57,26 @@ class ConModal extends Component {
5657
<div className="tcs-extra">
5758
<img src={contractor.photo} alt={contractor.name}/>
5859

60+
<Stars contractor={contractor} root={this.props.root}/>
61+
5962
<div className="tcs-location">
6063
<Location/>
6164
<span>{contractor.town}</span>
6265
</div>
6366

6467
<IfElse v={this.state.show_enquiry}>
65-
<button onClick={this.switch_view}>
68+
<button className="tcs-button" onClick={this.switch_view}>
6669
{this.props.root.get_text('contractor_details_button', {contractor_name: contractor.name})}
6770
</button>
68-
<button onClick={this.switch_view}>
71+
<button className="tcs-button" onClick={this.switch_view}>
6972
{this.props.root.get_text('contractor_enquiry_button', {contractor_name: contractor.name})}
7073
</button>
7174
</IfElse>
7275
</div>
7376
<div className="tcs-content">
7477
<div className="tcs-aside tcs-md">{contractor.tag_line}</div>
7578
<div className={'tcs-scroll con-modal-transition' + this.state.transition_class}
76-
style={{transition: `all ${TRANSITION_TIME}ms ease`}}>
79+
style={{transition: `all ${TRANSITION_TIME}ms ease-in-out`}}>
7780

7881
<IfElse v={this.state.show_enquiry}>
7982
<EnquiryForm contractor={contractor} root={this.props.root} config={this.props.config}/>

src/components/contractors/Contractors.js

Lines changed: 67 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,27 @@
11
import React, { Component } from 'react'
2-
import {Route} from 'react-router-dom'
2+
import {Link, Route} from 'react-router-dom'
33
import {async_start, slugify} from '../../utils'
4-
import Grid from './Grid'
4+
import {If} from '../shared/Tools'
5+
import {Grid, List} from './List'
56
import ConModal from './ConModal'
7+
import SelectSubjects from './SelectSubjects'
68

79
class Contractors extends Component {
810
constructor (props) {
911
super(props)
1012
this.state = {
1113
contractors: [],
1214
got_contractors: false,
15+
page: 1,
16+
more_pages: false,
1317
subjects: [],
1418
selected_subject: null,
1519
}
1620
this.update_contractors = this.update_contractors.bind(this)
1721
this.get_contractor_details = this.get_contractor_details.bind(this)
1822
this.set_contractor_details = this.set_contractor_details.bind(this)
23+
this.subject_url = this.subject_url.bind(this)
24+
this.page_url = this.page_url.bind(this)
1925
this.subject_change = this.subject_change.bind(this)
2026
}
2127

@@ -29,12 +35,24 @@ class Contractors extends Component {
2935
await this.update_contractors()
3036
}
3137

32-
subject_change (selected_subject) {
38+
subject_url (selected_subject) {
3339
if (selected_subject) {
34-
this.props.history.push(this.props.root.url(`subject/${selected_subject.id}-${slugify(selected_subject.name)}`))
40+
return this.props.root.url(`subject/${selected_subject.id}-${slugify(selected_subject.name)}`)
3541
} else {
36-
this.props.history.push(this.props.root.url(''))
42+
return this.props.root.url('')
3743
}
44+
}
45+
46+
page_url (new_page) {
47+
let url = this.subject_url(this.state.selected_subject)
48+
if (new_page > 1) {
49+
url += `${url.substr(-1) === '/' ? '' : '/'}page/${new_page}`
50+
}
51+
return url
52+
}
53+
54+
subject_change (selected_subject) {
55+
this.props.history.push(this.subject_url(selected_subject))
3856
this.update_contractors(selected_subject)
3957
}
4058

@@ -47,15 +65,22 @@ class Contractors extends Component {
4765
}
4866
}
4967

50-
this.setState({selected_subject})
51-
const sub_id = selected_subject && selected_subject.id
52-
const args = Object.assign({}, this.props.config.contractor_filter, {subject: sub_id || null})
68+
const m = this.props.history.location.pathname.match(/page\/(\d+)/)
69+
const page = m ? parseInt(m[1], 10) : 1
70+
this.setState({selected_subject, page})
71+
const args = Object.assign({}, this.props.config.contractor_filter, {
72+
subject: selected_subject ? selected_subject.id : null,
73+
pagination: this.props.config.pagination,
74+
page: page,
75+
})
5376
const contractors = await this.props.root.requests.get('contractors', args)
5477
this.props.config.event_callback('updated_contractors', contractors)
55-
this.setState({
78+
this.setState({contractors: []})
79+
setTimeout(() => this.setState({
5680
contractors,
57-
got_contractors: true
58-
})
81+
got_contractors: true,
82+
more_pages: contractors.length === this.props.config.pagination,
83+
}), 0)
5984
}
6085

6186
get_contractor_details (con) {
@@ -75,16 +100,39 @@ class Contractors extends Component {
75100
}
76101

77102
render () {
103+
const DisplayComponent = this.props.config.mode === 'grid' ? Grid : List
78104
return (
79-
<div className="tcs-app">
80-
<Grid config={this.props.config}
81-
history={this.props.history}
82-
contractors={this.state.contractors}
83-
subjects={this.state.subjects}
84-
selected_subject={this.state.selected_subject}
85-
subject_change={this.subject_change}
86-
root={this.props.root}/>
105+
<div className="tcs-app tcs-contractors">
106+
<If v={this.state.got_contractors && this.props.config.subject_filter}>
107+
<SelectSubjects get_text={this.props.root.get_text}
108+
contractors={this.state.contractors}
109+
subjects={this.state.subjects}
110+
selected_subject={this.state.selected_subject}
111+
subject_change={this.subject_change}/>
112+
</If>
113+
<DisplayComponent contractors={this.state.contractors} root={this.props.root}/>
114+
<If v={this.state.got_contractors && this.state.contractors.length === 0}>
115+
<div className="tcs-no-contractors">
116+
{this.props.root.get_text('no_tutors_found')}
117+
</div>
118+
</If>
87119

120+
<If v={this.state.page > 1 || this.state.more_pages}>
121+
<div className="tcs-pagination">
122+
<Link
123+
to={this.page_url(this.state.page - 1)}
124+
onClick={() => setTimeout(() => this.update_contractors(), 0)}
125+
className={'tcs-previous' + (this.state.page > 1 ? '' : ' tcs-disable')}>
126+
&lsaquo;&lsaquo; {this.props.root.get_text('previous')}
127+
</Link>
128+
<Link
129+
to={this.page_url(this.state.page + 1)}
130+
onClick={() => setTimeout(() => this.update_contractors(), 0)}
131+
className={'tcs-next' + (this.state.more_pages ? '' : ' tcs-disable')}>
132+
{this.props.root.get_text('next')} &rsaquo;&rsaquo;
133+
</Link>
134+
</div>
135+
</If>
88136
<Route path={this.props.root.url(':id(\\d+):_extra')} render={props => (
89137
<ConModal id={props.match.params.id}
90138
contractors={this.state.contractors}

src/components/contractors/Grid.js

Lines changed: 0 additions & 47 deletions
This file was deleted.

0 commit comments

Comments
 (0)