11 |
{
12 | browserHistory.push('/item/123');
13 | }} />
14 |
15 | );
16 | }
17 | }
18 |
19 | export default Item;
20 |
--------------------------------------------------------------------------------
/src/components/Item/styles.sass:
--------------------------------------------------------------------------------
1 | @import '../../styles/variables.sass'
2 |
3 | .item
4 | padding-bottom: 4%
5 | height: 250px
6 | flex: 0 1 48%
7 | align-items: stretch
8 | &:nth-child(2n)
9 | padding-left: 4%
10 | padding-right: 0
11 |
12 | .content
13 | height: 100%
14 | background: #eee
15 | cursor: pointer
--------------------------------------------------------------------------------
/src/components/ItemPage/index.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { Link } from 'react-router';
3 | import './styles.sass';
4 |
5 | class ItemPage extends Component {
6 | componentDidMount() {
7 | document.body.scrollTop = 0;
8 | document.querySelector('.menu').classList.remove('open');
9 | }
10 | render() {
11 | return (
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | All Items
22 |
23 |
Eloquent Javascript
24 |
$40
25 |
26 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ea nulla modi, odit explicabo hic doloremque commodi ab molestiae. Iure voluptatem labore et aliquid soluta inventore expedita quam vel a earum!
27 |
28 |
By Arshad Khan
29 |
Request Trade
30 |
31 |
32 | );
33 | }
34 | }
35 |
36 | export default ItemPage;
37 |
--------------------------------------------------------------------------------
/src/components/ItemPage/styles.sass:
--------------------------------------------------------------------------------
1 | @import '../../styles/variables.sass'
2 |
3 | .itemPageWrapper
4 | padding: 1rem 0 2rem 0
5 | display: flex
6 | flex-direction: column
7 | .itemImgWrapper
8 | background: #eee
9 | flex: 1
10 | min-height: 50vh
11 | .itemInfoWrapper
12 | margin-top: 2rem
13 | flex: 1
14 | .itemName
15 | margin: 1rem 0 .5rem 0
16 | .seller
17 | margin-top: 1.5rem
18 | font-size: 1rem
19 | letter-spacing: 1px
20 | color: $grey
21 | span
22 | font-weight: 800
23 | color: $black
24 | .itemCost
25 | color: lighten($black, 20%)
26 | font-size: 1.5rem
27 | margin: 1rem 0
28 | font-weight: 500
29 |
30 | .backLink
31 | font-size: .9rem
32 | color: $grey
33 | cursor: pointer
34 | transition: color .2s
35 | font-weight: 500
36 | span.small
37 | svg
38 | transform: rotateZ(90deg)
39 | transition: color .2s
40 | fill: $grey
41 | font-weight: 800
42 | &:hover, &:active
43 | color: $black
44 | span svg
45 | fill: $black
46 |
47 | button
48 | font-size: .8rem
49 | font-weight: 600
50 | text-transform: uppercase
51 | padding: .5rem 1rem
52 | cursor: pointer
53 | transition: opacity .3s
54 | &:hover
55 | opacity: .8
56 | .reqTradeBtn
57 | margin: 3rem 0 0 0
58 | background: $black
59 | color: #fff
60 |
--------------------------------------------------------------------------------
/src/components/Login/index.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import './styles.sass';
3 |
4 | class Login extends Component {
5 | componentDidMount() {
6 | document.body.scrollTop = 0;
7 | document.querySelector('.menu').classList.remove('open');
8 | }
9 | render() {
10 | return (
11 |
12 |
Login with your social account
13 |
14 | Facebook Login
15 | Google Login
16 | Twitter Login
17 |
18 |
19 | );
20 | }
21 | }
22 |
23 | export default Login;
24 |
--------------------------------------------------------------------------------
/src/components/Login/styles.sass:
--------------------------------------------------------------------------------
1 | @import '../../styles/variables.sass'
2 |
3 | .loginWrapper
4 | min-height: 40vh
5 | margin: 1rem auto 2rem auto
6 | .loginHeading
7 | margin-bottom: 4rem
8 |
9 | .btnWrapper
10 | margin: 2rem 0 0 0
11 | display: flex
12 | flex-direction: column
13 | justify-content: flex-start
14 | button
15 | flex: 0
16 | max-width: 400px
17 | margin: 0 auto 2rem auto
18 | width: 100%
19 | padding: .8rem 1rem
20 | transition: all .3s
21 | font-size: .8rem
22 | font-weight: 700
23 | background: transparent
24 | border: solid 2px
25 | opacity: .75
26 | text-transform: uppercase
27 | &:hover
28 | cursor: pointer
29 | opacity: 1
30 | &:active
31 | transform: translateY(2px)
32 | &:focus
33 | opacity: .75
34 |
35 | .fbBtn
36 | color: $fbColor
37 | .twitterBtn
38 | color: $twitterColor
39 | .googleBtn
40 | color: $googleColor
41 |
--------------------------------------------------------------------------------
/src/components/Main/index.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import './styles.sass';
3 | import Item from '../Item/index';
4 |
5 | class Homepage extends Component {
6 | componentDidMount() {
7 | document.body.scrollTop = 0;
8 | document.querySelector('.menu').classList.remove('open');
9 | }
10 | render() {
11 | return (
12 |
13 | {"1234567890".split("").map((e, i) => )}
14 |
15 | );
16 | }
17 | }
18 |
19 | export default Homepage;
20 |
--------------------------------------------------------------------------------
/src/components/Main/styles.sass:
--------------------------------------------------------------------------------
1 | .main
2 | padding: 1rem 0
3 | display: flex
4 | flex-wrap: wrap
5 | justify-content: space-between
6 | min-height: 60vh
7 |
8 |
--------------------------------------------------------------------------------
/src/components/MyItems/index.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 |
3 | import UserItem from '../UserItem/index';
4 | import AddItemPage from '../AddItemPage/index';
5 | import './styles.sass';
6 |
7 | class MyItems extends Component {
8 | constructor(props) {
9 | super(props);
10 | this.state = {
11 | modalOpened: false
12 | };
13 | }
14 |
15 | componentDidMount() {
16 | document.body.scrollTop = 0;
17 | document.querySelector('.menu').classList.remove('open');
18 | }
19 |
20 | closeModal() {
21 | this.setState({ modalOpened: false });
22 | document.body.classList.remove('modal-opened');
23 | document.body.style.marginRight = 0;
24 | }
25 |
26 | getModal() {
27 | if (this.state.modalOpened) {
28 | return
;
29 | } else {
30 | return;
31 | }
32 | }
33 |
34 | openModal() {
35 | const scrollBar = document.querySelector('.scrollbar-measure');
36 | const scrollBarWidth = scrollBar.offsetWidth - scrollBar.clientWidth;
37 | document.body.classList.add('modal-opened');
38 | document.body.style.marginRight = `${scrollBarWidth}px`;
39 | this.setState({ modalOpened: true });
40 | }
41 |
42 | render() {
43 | return (
44 |
45 | {this.getModal()}
46 |
47 | {
49 | this.openModal();
50 | }}
51 | className="tradeBtn addItemBtn">
52 | + Add Item
53 |
54 |
55 | {[1, 2].map((e, i) =>
)}
56 |
57 | );
58 | }
59 | }
60 |
61 | export default MyItems;
62 |
--------------------------------------------------------------------------------
/src/components/MyItems/styles.sass:
--------------------------------------------------------------------------------
1 | @import '../../styles/variables.sass'
2 |
3 | .myItemsWrapper
4 | padding: 1rem 0 2rem 0
5 | min-height: 40vh
6 | .addTradeWrapper
7 | display: flex
8 | justify-content: flex-end
9 | margin: 0 0 3rem 0
10 | .allItemsBtn
11 | border-bottom: solid 2px
12 | .tradeBtn
13 | color: $light-grey
14 | font-size: .9rem
15 | font-weight: 700
16 | padding: 0
17 | background: transparent
18 | text-transform: uppercase
19 | transition: all, .3s
20 | cursor: pointer
21 | &:hover
22 | color: $black
23 |
--------------------------------------------------------------------------------
/src/components/OtherInfo/index.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 |
3 | import './styles.sass';
4 |
5 | class OtherInfo extends Component {
6 | constructor(props) {
7 | super(props);
8 | this.state = {
9 | locationEditing: false,
10 | contactEditing: false
11 | };
12 | }
13 |
14 | getLocationData() {
15 | if (this.state.locationEditing) {
16 | return (
17 |
43 | );
44 | } else {
45 | return (
46 |
47 |
48 |
Local Address:
49 |
House no 33
50 |
51 |
52 |
City:
53 |
New Delhi
54 |
55 |
56 |
State:
57 |
Delhi
58 |
59 |
60 |
Landmark:
61 |
Yasin Manzil
62 |
63 |
64 |
Country:
65 |
India
66 |
67 |
68 |
Pin Code:
69 |
100065
70 |
71 |
72 | );
73 | }
74 | }
75 |
76 | getContactData() {
77 | if (this.state.contactEditing) {
78 | return (
79 |
89 | );
90 | } else {
91 | return (
92 |
93 |
94 |
Email:
95 |
arshdkhn1@gmail.com
96 |
97 |
98 |
Phone no:
99 |
+91-9999999999
100 |
101 |
102 | );
103 | }
104 | }
105 |
106 | getButtons(info) {
107 | if (!this.state.locationEditing && info === 'LOCATION') {
108 | return (
109 |
{
111 | this.setState({ locationEditing: true });
112 | }}>
113 | Edit
114 |
115 | );
116 | } else if (!this.state.contactEditing && info === 'CONTACT') {
117 | return (
118 |
{
120 | this.setState({ contactEditing: true });
121 | }}>
122 | Edit
123 |
124 | );
125 | } else {
126 | let buttons;
127 | switch (info) {
128 | case 'LOCATION':
129 | buttons = ([
130 |
{
133 | this.setState({ locationEditing: false });
134 | }}>
135 | Save
136 | ,
137 |
{
140 | this.setState({ locationEditing: false });
141 | }}>
142 | Cancel
143 |
144 | ]);
145 |
146 | break;
147 | case 'CONTACT':
148 | buttons = ([
149 |
{
152 | this.setState({ contactEditing: false });
153 | }}>
154 | Save
155 | ,
156 |
{
159 | this.setState({ contactEditing: false });
160 | }}>
161 | Cancel
162 |
163 | ]);
164 | break;
165 | }
166 | return buttons;
167 | }
168 | }
169 |
170 | render() {
171 | return (
172 |
173 |
174 |
175 |
Location Info
176 | {this.getButtons('LOCATION')}
177 |
178 | {this.getLocationData()}
179 |
180 |
181 |
182 |
Contact Info
183 | {this.getButtons('CONTACT')}
184 |
185 | {this.getContactData()}
186 |
187 |
188 | );
189 | }
190 | }
191 |
192 | export default OtherInfo;
193 |
--------------------------------------------------------------------------------
/src/components/OtherInfo/styles.sass:
--------------------------------------------------------------------------------
1 | @import '../../styles/variables.sass'
2 |
3 | .otherInfo
4 | flex: 3
5 |
6 | .lIWrapper, .cIWrapper
7 | display: flex
8 | flex-wrap: wrap
9 | justify-content: space-between
10 |
11 | & > *
12 | flex: 0 1 calc(50% - 1rem)
13 |
14 | .contactInfo
15 | margin-top: 2rem
16 | padding-bottom: 1rem
17 |
18 | .heading
19 | display: flex
20 | h3
21 | flex: 1
22 | button
23 | padding: 0 !important
24 | background: transparent
25 | color: $light-grey
26 | border: none
27 | line-height: 1
28 | font-weight: 500
29 | font-size: .9rem
30 | text-transform: uppercase
31 | transition: color .3s
32 | cursor: pointer
33 | &:hover
34 | color: $black
35 |
36 | .inputWrapper
37 | display: flex
38 | flex-direction: column
39 | margin-bottom: 1rem
40 |
41 | p.inputData
42 | padding: .5rem 1rem
43 | color: $grey
44 | margin: 1rem 0
45 | font-size: .9rem
46 | font-weight: 400
47 | border-bottom: solid 2px transparent
48 | background: #fff
49 |
50 | .cancelBtn
51 | margin-left: 1rem
52 |
--------------------------------------------------------------------------------
/src/components/Profile/index.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 |
3 | import BasicInfo from '../BasicInfo/index';
4 | import OtherInfo from '../OtherInfo/index';
5 | import './styles.sass';
6 |
7 | class Profile extends Component {
8 | componentDidMount() {
9 | document.body.scrollTop = 0;
10 | document.querySelector('.menu').classList.remove('open');
11 | }
12 | render() {
13 | return (
14 |
15 |
16 |
17 |
18 | );
19 | }
20 | }
21 |
22 | export default Profile;
23 |
--------------------------------------------------------------------------------
/src/components/Profile/styles.sass:
--------------------------------------------------------------------------------
1 | .infoWrapper
2 | display: flex
3 | min-height: 40vh
4 | flex-direction: column
5 | padding: 1rem 0
6 |
--------------------------------------------------------------------------------
/src/components/ProposedTrade/index.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { Link } from 'react-router';
3 | import './styles.sass';
4 |
5 | class ProposedTrade extends Component {
6 | render() {
7 | return (
8 |
9 |
10 |
11 |
12 | You have proposed Arshad Khan for trading Eloquent Javascript
13 |
14 |
15 |
16 | Cancel Proposal
17 |
18 |
19 | );
20 | }
21 | }
22 |
23 | export default ProposedTrade;
24 |
--------------------------------------------------------------------------------
/src/components/ProposedTrade/styles.sass:
--------------------------------------------------------------------------------
1 | @import '../../styles/variables.sass'
2 |
3 | .ptWrapper
4 | &:first-child
5 | margin-top: 0
6 | margin-top: 2.5rem
7 | .upper
8 | margin: 1rem 0
9 | display: flex
10 | .userImg
11 | margin-top: .2rem
12 | flex: 0 0 3rem
13 | height: 3rem
14 | width: 3rem
15 | background: #eee
16 | border-radius: 50%
17 | margin-right: 1rem
18 | .lower
19 | display: flex
20 | h4
21 | line-height: 1.2
22 | font-size: .9rem
23 | letter-spacing: 1px
24 | a
25 | font-size: .9rem
26 | font-weight: 500
27 | color: $grey
28 | transition: all .3s
29 | &:hover
30 | color: $black
31 | cursor: pointer
32 | button
33 | font-size: .8rem
34 | font-weight: 600
35 | text-transform: uppercase
36 | padding: .2rem 1rem
37 | cursor: pointer
38 | transition: opacity .3s
39 | &:hover
40 | opacity: .8
41 | .cancelBtn
42 | margin: 0
43 | background: none
44 | border: solid 2px
45 | &:hover
46 | opacity: .7
47 |
48 |
--------------------------------------------------------------------------------
/src/components/TradeRequest/index.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { Link } from 'react-router';
3 | import './styles.sass';
4 |
5 | class TradeRequest extends Component {
6 | render() {
7 | return (
8 |
9 |
10 |
11 |
12 | Arshad Khan wants to trade with your item- Eloquent Javascript
13 |
14 |
15 |
16 | Accept
17 | Decline
18 |
19 |
20 | );
21 | }
22 | }
23 |
24 | export default TradeRequest;
25 |
--------------------------------------------------------------------------------
/src/components/TradeRequest/styles.sass:
--------------------------------------------------------------------------------
1 | @import '../../styles/variables.sass'
2 |
3 | .trWrapper
4 | &:first-child
5 | margin-top: 0
6 | margin-top: 2.5rem
7 | .upper
8 | margin: 1rem 0
9 | display: flex
10 | .userImg
11 | margin-top: .2rem
12 | flex: 0 0 3rem
13 | height: 3rem
14 | width: 3rem
15 | background: #eee
16 | border-radius: 50%
17 | margin-right: 1rem
18 | .lower
19 | display: flex
20 | h4
21 | line-height: 1.2
22 | font-size: .9rem
23 | letter-spacing: 1px
24 | a
25 | font-size: .9rem
26 | font-weight: 500
27 | color: $grey
28 | transition: all .3s
29 | &:hover
30 | color: $black
31 | cursor: pointer
32 | button
33 | font-size: .8rem
34 | font-weight: 600
35 | text-transform: uppercase
36 | padding: .2rem 1rem
37 | cursor: pointer
38 | transition: opacity .3s
39 | &:hover
40 | opacity: .8
41 | .acceptBtn
42 | background: $black
43 | color: #fff
44 | .declineBtn
45 | margin-left: 1rem
46 | background: none
47 | border: solid 2px
48 | &:hover
49 | opacity: .7
50 |
51 |
--------------------------------------------------------------------------------
/src/components/Trades/index.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { Link } from 'react-router';
3 |
4 | import TradeRequest from '../TradeRequest/index';
5 | import ProposedTrade from '../ProposedTrade/index';
6 | import AddItemPage from '../AddItemPage/index';
7 | import './styles.sass';
8 |
9 | class Trades extends Component {
10 | constructor(props) {
11 | super(props);
12 | this.state = {
13 | modalOpened: false
14 | };
15 | }
16 |
17 | componentDidMount() {
18 | document.body.scrollTop = 0;
19 | document.querySelector('.menu').classList.remove('open');
20 | }
21 |
22 | closeModal() {
23 | this.setState({ modalOpened: false });
24 | document.body.classList.remove('modal-opened');
25 | document.body.style.marginRight = 0;
26 | }
27 |
28 | getAllProposedTrades() {
29 | return ([
30 |
,
31 |
32 | ]);
33 | }
34 |
35 | getAllTradeRequests() {
36 | return ([
37 |
,
38 |
39 | ]);
40 | }
41 |
42 | getModal() {
43 | if (this.state.modalOpened) {
44 | return
;
45 | } else {
46 | return;
47 | }
48 | }
49 |
50 | openModal() {
51 | const scrollBar = document.querySelector('.scrollbar-measure');
52 | const scrollBarWidth = scrollBar.offsetWidth - scrollBar.clientWidth;
53 | document.body.classList.add('modal-opened');
54 | document.body.style.marginRight = `${scrollBarWidth}px`;
55 | this.setState({ modalOpened: true });
56 | }
57 |
58 | render() {
59 | return (
60 |
61 | {this.getModal()}
62 |
63 | My Items
64 | {
66 | this.openModal();
67 | }}
68 | className="tradeBtn addItemBtn">
69 | + Add Item
70 |
71 |
72 |
73 |
74 |
Trade Requests
75 |
76 | {this.getAllTradeRequests()}
77 |
78 |
79 |
80 |
Trades Proposed
81 |
82 | {this.getAllProposedTrades()}
83 |
84 |
85 |
86 |
87 | );
88 | }
89 | }
90 |
91 | export default Trades;
92 |
--------------------------------------------------------------------------------
/src/components/Trades/styles.sass:
--------------------------------------------------------------------------------
1 | @import '../../styles/variables.sass'
2 |
3 | .tradesWrapper
4 | min-height: 40vh
5 |
6 | .addTradeWrapper
7 | display: flex
8 | justify-content: space-between
9 | margin: 1rem 0 3rem 0
10 | .allItemsBtn
11 | border-bottom: solid 2px
12 | .tradeBtn
13 | color: $light-grey
14 | font-size: .9rem
15 | font-weight: 700
16 | padding: 0
17 | background: transparent
18 | text-transform: uppercase
19 | transition: all, .3s
20 | cursor: pointer
21 | &:hover
22 | color: $black
23 | .tradesInfoWrapper
24 | display: flex
25 | flex-direction: column
26 | h3
27 | letter-spacing: 1px
28 | .allTradeRequestsWrapper
29 | margin-bottom: 3rem
30 |
31 | .allProposedTradesWrapper
32 | margin-bottom: 2rem
33 |
34 |
35 |
--------------------------------------------------------------------------------
/src/components/UserItem/index.js:
--------------------------------------------------------------------------------
1 | import React, { Component, PropTypes} from 'react';
2 | import { Link } from 'react-router';
3 | import './styles.sass';
4 |
5 | class UserItem extends Component {
6 | constructor(props) {
7 | super(props);
8 | }
9 |
10 | render() {
11 | return (
12 |
13 |
14 |
15 |
16 |
17 | Eloquent Javascript
18 |
19 |
$40
20 |
23 Jan, 2017
21 |
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Neque nihil dicta temporibus incidunt fugit culpa similique ipsum sit? Hic ad beatae quidem repudiandae dignissimos tenetur consequuntur, ullam, accusantium earum at.
22 |
23 | Remove Item
24 | Edit Info
25 |
26 |
27 |
28 |
29 | );
30 | }
31 | }
32 |
33 | export default UserItem;
34 |
35 | UserItem.propTypes = {
36 | editModal: PropTypes.func
37 | };
38 |
39 |
--------------------------------------------------------------------------------
/src/components/UserItem/styles.sass:
--------------------------------------------------------------------------------
1 | @import '../../styles/variables.sass'
2 |
3 | .uIWrapper
4 | margin: 0 0 3rem 0
5 | .itemCost
6 | color: lighten($black, 20%)
7 | font-size: 1.2rem
8 | margin: .7rem 0
9 | font-weight: 500
10 | .addDate
11 | margin: .5rem 0
12 | font-weight: 500
13 | color: $grey
14 | letter-spacing: 1px
15 | .itemDescription
16 | margin: .5rem 0 1.5rem 0
17 | .upper
18 | margin: 0 0 1rem 0
19 | display: flex
20 | flex-direction: column
21 | .userImg
22 | flex: 0 0 10rem
23 | height: 10rem
24 | width: 10rem
25 | background: #eee
26 | border-radius: 50%
27 | margin: 1.5rem auto
28 | .lower
29 | display: flex
30 | h3.itemName
31 | line-height: 1.2
32 | font-size: 1.2rem
33 | letter-spacing: 2px
34 | a
35 | transition: none
36 | color: inherit
37 | font-size: inherit
38 | border-bottom: solid 2px transparent
39 | &:hover
40 | border-bottom: solid 2px
41 | a
42 | font-size: .9rem
43 | font-weight: 500
44 | color: $grey
45 | cursor: pointer
46 | transition: all .3s
47 | &:hover
48 | color: $black
49 | cursor: pointer
50 | button
51 | font-size: .8rem
52 | font-weight: 600
53 | text-transform: uppercase
54 | padding: .2rem 1rem
55 | cursor: pointer
56 | transition: opacity .3s
57 | &:hover
58 | opacity: .8
59 | .deleteBtn
60 | background: $black
61 | color: #fff
62 | .editBtn
63 | margin-left: 1rem
64 | background: none
65 | border: solid 2px
66 | &:hover
67 | opacity: .7
68 |
69 |
--------------------------------------------------------------------------------
/src/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ar5had/ecommerce-site-template/46f7c10a0d02fbd7aa56748cab42a9ea8c2aa803/src/favicon.ico
--------------------------------------------------------------------------------
/src/index.ejs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
13 | <% if (htmlWebpackPlugin.options.trackJSToken) { %>
14 |
15 |
16 | <% } %>
17 |
18 |
19 |
20 |
21 |
Trader
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { render } from 'react-dom';
3 | import { Router, browserHistory } from 'react-router';
4 |
5 | import routes from './routes';
6 |
7 | import './styles/global.sass';
8 | import './favicon.ico';
9 |
10 |
11 | render(
, document.getElementById('app'));
12 |
--------------------------------------------------------------------------------
/src/reducers/index.js:
--------------------------------------------------------------------------------
1 | // Set up your root reducer here...
2 | import { combineReducers } from 'redux';
3 | export default combineReducers;
--------------------------------------------------------------------------------
/src/routes.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Route, IndexRoute } from 'react-router';
3 |
4 | import App from './components/App/index';
5 | import Main from './components/Main/index';
6 | import Profile from './components/Profile/index';
7 | import Login from './components/Login/index';
8 | import Trades from './components/Trades/index';
9 | import ItemPage from './components/ItemPage/index';
10 | import MyItems from './components/MyItems/index';
11 | import ErrorPage from './components/ErrorPage/index';
12 |
13 | export default (
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | );
24 |
--------------------------------------------------------------------------------
/src/store/configureStore.js:
--------------------------------------------------------------------------------
1 | import {createStore, compose, applyMiddleware} from 'redux';
2 | import reduxImmutableStateInvariant from 'redux-immutable-state-invariant';
3 | import thunk from 'redux-thunk';
4 | import rootReducer from '../reducers';
5 |
6 | function configureStoreProd(initialState) {
7 | const middlewares = [
8 | // Add other middleware on this line...
9 |
10 | // thunk middleware can also accept an extra argument to be passed to each thunk action
11 | // https://github.com/gaearon/redux-thunk#injecting-a-custom-argument
12 | thunk,
13 | ];
14 |
15 | return createStore(rootReducer, initialState, compose(
16 | applyMiddleware(...middlewares)
17 | )
18 | );
19 | }
20 |
21 | function configureStoreDev(initialState) {
22 | const middlewares = [
23 | // Add other middleware on this line...
24 |
25 | // Redux middleware that spits an error on you when you try to mutate your state either inside a dispatch or between dispatches.
26 | reduxImmutableStateInvariant(),
27 |
28 | // thunk middleware can also accept an extra argument to be passed to each thunk action
29 | // https://github.com/gaearon/redux-thunk#injecting-a-custom-argument
30 | thunk,
31 | ];
32 |
33 | const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose; // add support for Redux dev tools
34 | const store = createStore(rootReducer, initialState, composeEnhancers(
35 | applyMiddleware(...middlewares)
36 | )
37 | );
38 |
39 | if (module.hot) {
40 | // Enable Webpack hot module replacement for reducers
41 | module.hot.accept('../reducers', () => {
42 | const nextReducer = require('../reducers').default; // eslint-disable-line global-require
43 | store.replaceReducer(nextReducer);
44 | });
45 | }
46 |
47 | return store;
48 | }
49 |
50 | const configureStore = process.env.NODE_ENV === 'production' ? configureStoreProd : configureStoreDev;
51 |
52 | export default configureStore;
--------------------------------------------------------------------------------
/src/styles/animation.sass:
--------------------------------------------------------------------------------
1 | // For Pages Content ********************************************************************************
2 |
3 | .content-enter
4 | opacity: 0.01
5 | transform: scale(.96)
6 |
7 | .content-enter.content-enter-active
8 | opacity: 1
9 | transform: scale(1)
10 | transition: transform .4s cubic-bezier(.82,0,.12,1),opacity .4s cubic-bezier(.82,0,.12,1)
11 |
12 | .content-leave
13 | opacity: 0.01
14 | transform: scale(.96)
15 |
16 | .content-leave.content-leave-active
17 | transform: scale(.96)
18 | opacity: 0.01
--------------------------------------------------------------------------------
/src/styles/fonts.sass:
--------------------------------------------------------------------------------
1 | @font-face
2 | font-family: 'robotoblack_italic'
3 | src: url('../assets/fonts/roboto-blackitalic-webfont.woff2') format('woff2'), url('../assets/fonts/roboto-blackitalic-webfont.woff') format('woff')
4 | font-weight: 900
5 | font-style: italic
6 |
7 |
8 | @font-face
9 | font-family: 'roboto'
10 | src: url('../assets/fonts/roboto-bold-webfont.woff2') format('woff2'), url('../assets/fonts/roboto-bold-webfont.woff') format('woff')
11 | font-weight: 700
12 | font-style: normal
13 |
14 |
15 | @font-face
16 | font-family: 'roboto'
17 | src: url('../assets/fonts/roboto-bolditalic-webfont.woff2') format('woff2'), url('../assets/fonts/roboto-bolditalic-webfont.woff') format('woff')
18 | font-weight: 700
19 | font-style: italic
20 |
21 |
22 | @font-face
23 | font-family: 'roboto'
24 | src: url('../assets/fonts/roboto-italic-webfont.woff2') format('woff2'), url('../assets/fonts/roboto-italic-webfont.woff') format('woff')
25 | font-weight: 400
26 | font-style: italic
27 |
28 |
29 | @font-face
30 | font-family: 'roboto'
31 | src: url('../assets/fonts/roboto-regular-webfont.woff2') format('woff2'), url('../assets/fonts/roboto-regular-webfont.woff') format('woff')
32 | font-weight: 400
33 | font-style: normal
34 |
35 |
36 | @font-face
37 | font-family: 'roboto'
38 | src: url('../assets/fonts/roboto-light-webfont.woff2') format('woff2'), url('../assets/fonts/roboto-light-webfont.woff') format('woff')
39 | font-weight: 300
40 | font-style: normal
41 |
42 |
43 | @font-face
44 | font-family: 'roboto'
45 | src: url('../assets/fonts/roboto-lightitalic-webfont.woff2') format('woff2'), url('../assets/fonts/roboto-lightitalic-webfont.woff') format('woff')
46 | font-weight: 300
47 | font-style: italic
48 |
49 |
50 | @font-face
51 | font-family: 'roboto'
52 | src: url('../assets/fonts/roboto-medium-webfont.woff2') format('woff2'), url('../assets/fonts/roboto-medium-webfont.woff') format('woff')
53 | font-weight: 500
54 | font-style: normal
55 |
56 |
57 | @font-face
58 | font-family: 'roboto'
59 | src: url('../assets/fonts/roboto-mediumitalic-webfont.woff2') format('woff2'), url('../assets/fonts/roboto-mediumitalic-webfont.woff') format('woff')
60 | font-weight: 500
61 | font-style: italic
62 |
63 |
64 | @font-face
65 | font-family: 'roboto_mono'
66 | src: url('../assets/fonts/robotomono-bold-webfont.woff2') format('woff2'), url('../assets/fonts/robotomono-bold-webfont.woff') format('woff')
67 | font-weight: 700
68 | font-style: normal
69 |
70 |
71 | @font-face
72 | font-family: 'roboto_mono'
73 | src: url('../assets/fonts/robotomono-bolditalic-webfont.woff2') format('woff2'), url('../assets/fonts/robotomono-bolditalic-webfont.woff') format('woff')
74 | font-weight: 700
75 | font-style: italic
76 |
77 |
78 | @font-face
79 | font-family: 'roboto_mono'
80 | src: url('../assets/fonts/robotomono-light-webfont.woff2') format('woff2'), url('../assets/fonts/robotomono-light-webfont.woff') format('woff')
81 | font-weight: 300
82 | font-style: normal
83 |
84 |
85 | @font-face
86 | font-family: 'roboto_mono'
87 | src: url('../assets/fonts/robotomono-lightitalic-webfont.woff2') format('woff2'), url('../assets/fonts/robotomono-lightitalic-webfont.woff') format('woff')
88 | font-weight: 500
89 | font-style: italic
90 |
91 |
92 | @font-face
93 | font-family: 'roboto_monomedium'
94 | src: url('../assets/fonts/robotomono-medium-webfont.woff2') format('woff2'), url('../assets/fonts/robotomono-medium-webfont.woff') format('woff')
95 | font-weight: 500
96 | font-style: normal
97 |
98 |
99 | @font-face
100 | font-family: 'roboto_monomedium_italic'
101 | src: url('../assets/fonts/robotomono-mediumitalic-webfont.woff2') format('woff2'), url('../assets/fonts/robotomono-mediumitalic-webfont.woff') format('woff')
102 | font-weight: 500
103 | font-style: italic
104 |
105 |
106 | @font-face
107 | font-family: 'roboto_mono'
108 | src: url('../assets/fonts/robotomono-regular-webfont.woff2') format('woff2'), url('../assets/fonts/robotomono-regular-webfont.woff') format('woff')
109 | font-weight: 400
110 | font-style: normal
111 |
112 |
113 | @font-face
114 | font-family: 'roboto_mono'
115 | src: url('../assets/fonts/robotomono-italic-webfont.woff2') format('woff2'), url('../assets/fonts/robotomono-italic-webfont.woff') format('woff')
116 | font-weight: 400
117 | font-style: italic
118 |
--------------------------------------------------------------------------------
/src/styles/global.sass:
--------------------------------------------------------------------------------
1 | @import './fonts.sass'
2 | @import './mediaqueries.sass'
3 | @import './variables.sass'
4 |
5 | // http://meyerweb.com/eric/tools/css/reset/
6 | // v2.0 | 20110126
7 | // License: none (public domain)
8 |
9 | html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed, figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video
10 | margin: 0
11 | padding: 0
12 | border: 0
13 | font-size: 100%
14 | font: inherit
15 | vertical-align: baseline
16 |
17 | // HTML5 display-role reset for older browsers
18 |
19 | article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section
20 | display: block
21 |
22 | body
23 | line-height: 1
24 | // set max height to more than 100vh to remove shift produced by scrollbar
25 | min-height: calc(100vh + 2px)
26 |
27 | ol, ul
28 | list-style: none
29 |
30 | blockquote, q
31 | quotes: none
32 |
33 | blockquote
34 | &:before, &:after
35 | content: ''
36 | content: none
37 |
38 | q
39 | &:before, &:after
40 | content: ''
41 | content: none
42 |
43 | table
44 | border-collapse: collapse
45 | border-spacing: 0
46 |
47 | // Global styles starts
48 |
49 | html
50 | font-size: 14px
51 |
52 | body
53 | background: $background-color
54 |
55 | *, p, h4, h5, h6, a
56 | font-size: 1rem
57 | letter-spacing: 1px
58 | font-family: roboto, helvetica, sans-serif
59 | line-height: 2
60 | text-decoration: none
61 | outline: none
62 | word-break: break-word
63 |
64 |
65 | h1, h2, h3
66 | text-transform: uppercase
67 | font-weight: 900
68 | letter-spacing: 4px
69 | line-height: 1.5
70 | font-family: roboto_mono, helvetica, sans-serif
71 |
72 | h1
73 | font-size: 1.5rem
74 |
75 | h2
76 | letter-spacing: 3px
77 | font-size: 1.5rem
78 | font-weight: 400
79 |
80 | h3
81 | font-size: 1.2rem
82 | letter-spacing: 2px
83 |
84 | h4
85 | letter-spacing: 2px
86 | font-size: 1.2rem
87 | font-weight: 400
88 |
89 | h5
90 | letter-spacing: 2px
91 | font-size: 1.2rem
92 | font-family: roboto_mono, helvetica, sans-serif
93 |
94 | h6
95 | font-size: 1rem
96 | font-weight: 800
97 | text-transform: uppercase
98 | letter-spacing: 1px
99 |
100 | p
101 | font-weight: 400
102 | letter-spacing: 1px
103 |
104 | .frm
105 | font-family: roboto_mono, helvetica, sans-serif
106 |
107 | .marB10
108 | margin-bottom: 10px
109 |
110 | .marT10
111 | margin-top: 10px
112 |
113 | .marB20
114 | margin-bottom: 20px
115 |
116 | .marT20
117 | margin-top: 20px
118 |
119 | .text-center
120 | text-align: center
121 |
122 | .text-left
123 | text-align: left
124 |
125 | .text-right
126 | text-align: right
127 |
128 | .has-link
129 | color: $grey
130 |
131 | .has-link > a
132 | text-decoration: none
133 | color: $black
134 | border-bottom: 1px dotted $black
135 | &:hover
136 | border-bottom: 1px solid $black
137 |
138 | .normal
139 | text-transform: none
140 | letter-spacing: 1px
141 | font-size: 1rem
142 |
143 | input, textarea
144 | padding: .5rem 1rem
145 | border: none
146 | color: $grey
147 | margin: 1rem 0
148 | font-size: .9rem
149 | font-weight: 400
150 | border-bottom: solid 2px $light-grey
151 | transition: color .3s, border-color .3s
152 | background: #fff
153 | &:active, &:focus
154 | outline: none
155 | color: $black
156 | border-color: $black
157 |
158 | label
159 | font-size: .9rem
160 | line-height: 1
161 | font-weight: 500
162 | font-family: roboto_mono, helvetica, sans-serif
163 |
164 | button
165 | outline: none
166 | border: none
167 | border-radius: 0
168 | &:focus, &:active
169 | outline: none
170 | &::-moz-focus-inner
171 | border: 0
172 |
173 | .unCap
174 | text-transform: none
175 |
176 | a
177 | white-space: nowrap
178 | cursor: pointer
179 | outline: none
180 | &:active, &:focus
181 | outline: none
182 |
183 | input
184 | outline: none
185 | box-sizing: border-box
186 | width: 100%
187 | &:invalid
188 | box-shadow: none
189 |
190 | .modal-opened
191 | overflow: hidden
192 |
193 | .scrollbar-measure
194 | width: 100px !important
195 | height: 100px !important
196 | overflow-y: scroll
197 | position: absolute
198 | top: -9999px
199 |
--------------------------------------------------------------------------------
/src/styles/mediaqueries.sass:
--------------------------------------------------------------------------------
1 | @import './variables.sass'
2 |
3 | @media screen and (max-width: 400px)
4 | .lIWrapper, .cIWrapper
5 | & > *
6 | flex-basis: 100%
7 | flex: 0 1 calc(50% -2rem)
8 | h3.error
9 | font-size: 2rem
10 | .priceWrapper
11 | flex-direction: column
12 | .inputWrapper
13 | flex: 1
14 | .input
15 | width: 100%
16 | &:first-child
17 | margin-right: 0 !important
18 | &:last-child
19 | margin-left: 0 !important
20 |
21 | @media screen and (min-width: 768px)
22 | button.normalBtn
23 | padding: .5rem 1rem !important
24 | .wrapper
25 | max-width: 1200px
26 | margin: 10px auto
27 | padding: 75px !important
28 | .footer
29 | margin: 90px 0 0 0
30 | padding: 0
31 | .header
32 | margin: 0px 0 20px 0
33 | display: flex
34 | flex-direction: row
35 | .header > h1
36 | flex: 1
37 | text-align: left
38 | .logo
39 | font-size: 2.5rem !important
40 | .menu
41 | flex: none
42 | height: auto
43 | display: flex
44 | width: auto
45 | .navLink
46 | margin-left: 20px
47 | font-size: .9rem
48 | &:last-child
49 | border: none
50 | padding: 0
51 | .item
52 | padding-bottom: 3.5%
53 | flex: 0 1 31%
54 | // to override the default css properties
55 | &:nth-child(2n)
56 | padding-right: 0
57 | padding-left: 0
58 | &:nth-child(3n - 1)
59 | padding-right: 3.5%
60 | padding-left: 3.5%
61 |
62 | .otherInfo
63 | margin: 0 2rem
64 |
65 | .basicInfo
66 | padding: 0 1.5rem
67 |
68 | .profilePic
69 | width: 150px
70 | height: 150px
71 |
72 | .infoWrapper
73 | flex-direction: row
74 |
75 | h3.error
76 | margin: 25vh 0
77 |
78 | .tradesInfoWrapper
79 | flex-direction: row
80 | justify-content: space-between
81 | .tradeReqWrapper, .tradeProposedWrapper
82 | flex: 0 1 calc(50% - 1rem)
83 |
84 | .trWrapper, .ptWrapper, .uIWrapper
85 | .userImg
86 | margin-top: .2rem
87 | flex: 0 0 4rem
88 | height: 4rem
89 | width: 4rem
90 | .lower
91 | display: flex
92 | h4
93 | font-size: 1rem
94 | a
95 | font-size: 1rem
96 | .tradeProposedWrapper
97 | margin-top: 0
98 |
99 | .itemPageWrapper
100 | flex-direction: row
101 | .itemInfoWrapper
102 | margin-left: 2rem
103 | margin-top: 0
104 | .reqTradeBtn
105 | margin: 3rem 0 2rem 0
106 | border: solid 2px $black
107 | .uIWrapper
108 | margin: 0 0 4rem 0
109 | .upper
110 | flex-direction: row
111 | .itemCost
112 | color: lighten($black, 20%)
113 | font-size: 1.2rem
114 | margin: 1rem 0
115 | font-weight: 500
116 | .addDate
117 | margin: .5rem 0
118 | font-weight: 500
119 | .itemDescription
120 | margin: 2rem 0
121 | .itemInfo
122 | margin-left: 3rem
123 | .userImg
124 | margin-top: .2rem
125 | flex: 0 0 10rem
126 | height: 10rem
127 | width: 10rem
128 | .myItemsWrapper
129 | padding: 0 0 2rem 0
130 |
131 | .addItemWrapper
132 | .itemWrapper
133 | display: flex
134 | flex-direction: row !important
135 | .itemPicWrapper
136 | .img
137 | height: 12rem !important
138 | width: 12rem !important
139 | .itemInfoWrapper
140 | margin-left: 2rem
141 | margin-top: 0 !important
142 |
143 |
--------------------------------------------------------------------------------
/src/styles/variables.sass:
--------------------------------------------------------------------------------
1 | $background-color: #fcfcfc
2 | $modal-background: #fafafa
3 | $modal-border-color: #f2f2f2
4 | $hider-background: #fcfcfc
5 | $black: #222
6 | $light-grey: rgba(0, 0, 0, .3)
7 | $grey: rgba(34, 34, 34, .55)
8 | $fbColor: rgba(59, 89, 152, 0.9)
9 | $twitterColor: rgba(85, 172, 238, 0.9)
10 | $googleColor: rgba(221, 75, 57, 0.9)
11 |
12 | =hider-gradient
13 | background: #f2f2f2
14 | background: -webkit-gradient(radial,50% 25%,0,50% 25%,800,from(rgba(252, 252, 252,.9)),to(#f2f2f2)) transparent
15 | background: -moz-radial-gradient(center 45deg,circle cover,rgba(252, 252, 252,.9) 0%,#f2f2f2 100%) transparent
16 |
17 | @function strip-units($number)
18 | @return $number / ($number * 0 + 1)
19 |
20 | @function get-vw($target)
21 | $vw-context: (1000*.01) * 1px
22 | @return ($target/$vw-context) * 1vw
23 |
24 | @function getMaxWidth($a, $b)
25 | @warn "a= #{strip-units($a)}, b= #{strip-units($b)}"
26 | @if $a > $b
27 | @return $b+px
28 | @else
29 | @return $a+px
--------------------------------------------------------------------------------
/src/webpack-public-path.js:
--------------------------------------------------------------------------------
1 | // Dynamically set the webpack public path at runtime below
2 | // This magic global is used by webpack to set the public path at runtime.
3 | // The public path is set dynamically to avoid the following issues:
4 | // 1. https://github.com/coryhouse/react-slingshot/issues/205
5 | // 2. https://github.com/coryhouse/react-slingshot/issues/181
6 | // 3. https://github.com/coryhouse/react-slingshot/pull/125
7 | // Documentation: http://webpack.github.io/docs/configuration.html#output-publicpath
8 | // eslint-disable-next-line no-undef
9 | __webpack_public_path__ = window.location.protocol + "//" + window.location.host + "/";
10 |
--------------------------------------------------------------------------------
/tools/.yarnclean:
--------------------------------------------------------------------------------
1 | !browser-sync-ui/lib/plugins/history # need this for now because of https://github.com/yarnpkg/yarn/issues/1396#issuecomment-255965666
2 |
--------------------------------------------------------------------------------
/tools/analyzeBundle.js:
--------------------------------------------------------------------------------
1 | import webpack from 'webpack';
2 | import {BundleAnalyzerPlugin} from 'webpack-bundle-analyzer';
3 | import config from '../webpack.config.prod';
4 |
5 | config.plugins.push(new BundleAnalyzerPlugin());
6 |
7 | const compiler = webpack(config);
8 |
9 | compiler.run((error, stats) => {
10 | if (error) {
11 | throw new Error(error);
12 | }
13 |
14 | console.log(stats); // eslint-disable-line no-console
15 | });
16 |
--------------------------------------------------------------------------------
/tools/build.js:
--------------------------------------------------------------------------------
1 | // More info on Webpack's Node API here: https://webpack.github.io/docs/node.js-api.html
2 | // Allowing console calls below since this is a build file.
3 | /* eslint-disable no-console */
4 | import webpack from 'webpack';
5 | import config from '../webpack.config.prod';
6 | import {chalkError, chalkSuccess, chalkWarning, chalkProcessing} from './chalkConfig';
7 |
8 | process.env.NODE_ENV = 'production'; // this assures React is built in prod mode and that the Babel dev config doesn't apply.
9 |
10 | console.log(chalkProcessing('Generating minified bundle. This will take a moment...'));
11 |
12 | webpack(config).run((error, stats) => {
13 | if (error) { // so a fatal error occurred. Stop here.
14 | console.log(chalkError(error));
15 | return 1;
16 | }
17 |
18 | const jsonStats = stats.toJson();
19 |
20 | if (jsonStats.hasErrors) {
21 | return jsonStats.errors.map(error => console.log(chalkError(error)));
22 | }
23 |
24 | if (jsonStats.hasWarnings) {
25 | console.log(chalkWarning('Webpack generated the following warnings: '));
26 | jsonStats.warnings.map(warning => console.log(chalkWarning(warning)));
27 | }
28 |
29 | console.log(`Webpack stats: ${stats}`);
30 |
31 | // if we got this far, the build succeeded.
32 | console.log(chalkSuccess('Your app is compiled in production mode in /dist. It\'s ready to roll!'));
33 |
34 | return 0;
35 | });
36 |
--------------------------------------------------------------------------------
/tools/chalkConfig.js:
--------------------------------------------------------------------------------
1 | // Centralized configuration for chalk, which is used to add color to console.log statements.
2 | import chalk from 'chalk';
3 | export const chalkError = chalk.red;
4 | export const chalkSuccess = chalk.green;
5 | export const chalkWarning = chalk.yellow;
6 | export const chalkProcessing = chalk.blue;
7 |
--------------------------------------------------------------------------------
/tools/distServer.js:
--------------------------------------------------------------------------------
1 | // This file configures a web server for testing the production build
2 | // on your local machine.
3 |
4 | import browserSync from 'browser-sync';
5 | import historyApiFallback from 'connect-history-api-fallback';
6 | import {chalkProcessing} from './chalkConfig';
7 |
8 | /* eslint-disable no-console */
9 |
10 | console.log(chalkProcessing('Opening production build...'));
11 |
12 | // Run Browsersync
13 | browserSync({
14 | port: 4000,
15 | ui: {
16 | port: 4001
17 | },
18 | server: {
19 | baseDir: 'dist'
20 | },
21 |
22 | files: [
23 | 'src/*.html'
24 | ],
25 |
26 | middleware: [historyApiFallback()]
27 | });
28 |
--------------------------------------------------------------------------------
/tools/fileMock.js:
--------------------------------------------------------------------------------
1 | // Return an empty string or other mock path to emulate the url that
2 | // webpack provides via the file-loader
3 | module.exports = '';
4 |
--------------------------------------------------------------------------------
/tools/nodeVersionCheck.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | var exec = require('child_process').exec;
3 |
4 | exec('node -v', function (err, stdout) {
5 | if (err) throw err;
6 |
7 | if (parseFloat(stdout.slice(1)) < 4) {
8 | throw new Error('React Slingshot requires node 4.0 or greater.');
9 | }
10 | });
11 |
--------------------------------------------------------------------------------
/tools/server.js:
--------------------------------------------------------------------------------
1 | // common server for both production and development
2 | import historyApiFallback from 'connect-history-api-fallback';
3 | import webpack from 'webpack';
4 | import webpackDevMiddleware from 'webpack-dev-middleware';
5 | import webpackHotMiddleware from 'webpack-hot-middleware';
6 | import { chalkSuccess } from './chalkConfig';
7 | import config from '../webpack.config.dev';
8 | import express from 'express';
9 | import http from 'http';
10 | import bodyParser from 'body-parser';
11 |
12 | const environment = process.argv[2];
13 | const app = express();
14 | const server = http.createServer(app);
15 |
16 | /* eslint-disable no-console */
17 | console.log(chalkSuccess(`Starting Express server in ${environment} mode...`));
18 |
19 | if (environment !== "production") {
20 | // add a .env file in root of the project
21 | // require('dotenv').load({path: path.resolve(process.cwd() ,".env")});
22 |
23 | const bundler = webpack(config);
24 |
25 | app.use(express.static('src/*.html'));
26 | app.use(historyApiFallback());
27 | app.use(webpackHotMiddleware(bundler));
28 | app.use(webpackDevMiddleware(bundler, {
29 | // Dev middleware can't access config, so we provide publicPath
30 | publicPath: config.output.publicPath,
31 |
32 | // These settings suppress noisy webpack output so only errors are displayed to the console.
33 | noInfo: false,
34 | quiet: false,
35 | stats: {
36 | assets: false,
37 | colors: true,
38 | version: false,
39 | hash: false,
40 | timings: false,
41 | chunks: false,
42 | chunkModules: false
43 | }
44 |
45 | // for other settings see
46 | // http://webpack.github.io/docs/webpack-dev-middleware.html
47 | }));
48 | } else {
49 | app.use(express.static('dist'));
50 | }
51 |
52 | // set up env vars first
53 | // require('../config/passport')(passport);
54 |
55 | app.use(bodyParser.urlencoded({ extended: true }));
56 |
57 |
58 | server.listen(process.env.PORT || 8080);
59 | /* eslint-disable no-console */
60 | console.log(chalkSuccess('Express server is listening on port: ' + server.address().port));
61 |
--------------------------------------------------------------------------------
/tools/srcServer.js:
--------------------------------------------------------------------------------
1 | // This file configures the development web server
2 | // which supports hot reloading and synchronized testing.
3 |
4 | // Require Browsersync along with webpack and middleware for it
5 | import browserSync from 'browser-sync';
6 | // Required for react-router browserHistory
7 | // see https://github.com/BrowserSync/browser-sync/issues/204#issuecomment-102623643
8 | import historyApiFallback from 'connect-history-api-fallback';
9 | import webpack from 'webpack';
10 | import webpackDevMiddleware from 'webpack-dev-middleware';
11 | import webpackHotMiddleware from 'webpack-hot-middleware';
12 | import config from '../webpack.config.dev';
13 |
14 | const bundler = webpack(config);
15 |
16 | // Run Browsersync and use middleware for Hot Module Replacement
17 | browserSync({
18 | port: 3000,
19 | ui: {
20 | port: 3001
21 | },
22 | server: {
23 | baseDir: 'src',
24 |
25 | middleware: [
26 | historyApiFallback(),
27 |
28 | webpackDevMiddleware(bundler, {
29 | // Dev middleware can't access config, so we provide publicPath
30 | publicPath: config.output.publicPath,
31 |
32 | // These settings suppress noisy webpack output so only errors are displayed to the console.
33 | noInfo: false,
34 | quiet: false,
35 | stats: {
36 | assets: false,
37 | colors: true,
38 | version: false,
39 | hash: false,
40 | timings: false,
41 | chunks: false,
42 | chunkModules: false
43 | },
44 |
45 | // for other settings see
46 | // http://webpack.github.io/docs/webpack-dev-middleware.html
47 | }),
48 |
49 | // bundler should be the same as above
50 | webpackHotMiddleware(bundler)
51 | ]
52 | },
53 |
54 | // no need to watch '*.js' here, webpack will take care of it for us,
55 | // including full page reloads if HMR won't work
56 | files: [
57 | 'src/*.html'
58 | ]
59 | });
60 |
--------------------------------------------------------------------------------
/tools/startMessage.js:
--------------------------------------------------------------------------------
1 | import {chalkSuccess} from './chalkConfig';
2 |
3 | /* eslint-disable no-console */
4 | console.log(chalkSuccess('Starting app in dev mode...'));
5 |
--------------------------------------------------------------------------------
/webpack.config.dev.js:
--------------------------------------------------------------------------------
1 | import webpack from 'webpack';
2 | import HtmlWebpackPlugin from 'html-webpack-plugin';
3 | import autoprefixer from 'autoprefixer';
4 | import path from 'path';
5 |
6 | export default {
7 | resolve: {
8 | extensions: ['*', '.js', '.jsx', '.json']
9 | },
10 | devtool: 'eval-source-map', // more info:https://webpack.github.io/docs/build-performance.html#sourcemaps and https://webpack.github.io/docs/configuration.html#devtool
11 | entry: [
12 | // must be first entry to properly set public path
13 | './src/webpack-public-path',
14 | 'webpack-hot-middleware/client?reload=true',
15 | path.resolve(__dirname, 'src/index.js') // Defining path seems necessary for this to work consistently on Windows machines.
16 | ],
17 | target: 'web', // necessary per https://webpack.github.io/docs/testing.html#compile-and-test
18 | output: {
19 | path: path.resolve(__dirname, 'dist'), // Note: Physical files are only output by the production build task `npm run build`.
20 | publicPath: '/',
21 | filename: 'bundle.js'
22 | },
23 | plugins: [
24 | new webpack.DefinePlugin({
25 | 'process.env.NODE_ENV': JSON.stringify('development'), // Tells React to build in either dev or prod modes. https://facebook.github.io/react/downloads.html (See bottom)
26 | __DEV__: true
27 | }),
28 | new webpack.HotModuleReplacementPlugin(),
29 | new webpack.NoEmitOnErrorsPlugin(),
30 | new HtmlWebpackPlugin({ // Create HTML file that includes references to bundled CSS and JS.
31 | template: 'src/index.ejs',
32 | minify: {
33 | removeComments: true,
34 | collapseWhitespace: true
35 | },
36 | inject: true
37 | }),
38 | new webpack.LoaderOptionsPlugin({
39 | minimize: false,
40 | debug: true,
41 | noInfo: true, // set to false to see a list of every file being bundled.
42 | options: {
43 | sassLoader: {
44 | includePaths: [path.resolve(__dirname, 'src', 'scss')]
45 | },
46 | context: '/',
47 | postcss: () => [autoprefixer],
48 | }
49 | })
50 | ],
51 | module: {
52 | rules: [
53 | {test: /\.jsx?$/, exclude: /node_modules/, loaders: ['babel-loader']},
54 | {test: /\.eot(\?v=\d+.\d+.\d+)?$/, loader: 'file-loader'},
55 | {test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: 'url-loader?limit=10000&mimetype=application/font-woff'},
56 | {test: /\.[ot]tf(\?v=\d+.\d+.\d+)?$/, loader: 'url-loader?limit=10000&mimetype=application/octet-stream'},
57 | {test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, loader: 'url-loader?limit=10000&mimetype=image/svg+xml'},
58 | {test: /\.(jpe?g|png|gif)$/i, loader: 'file-loader?name=[name].[ext]'},
59 | {test: /\.ico$/, loader: 'file-loader?name=[name].[ext]'},
60 | {test: /(\.css|\.scss|\.sass)$/, loaders: ['style-loader', 'css-loader?sourceMap', 'postcss-loader', 'sass-loader?sourceMap']}
61 | ]
62 | }
63 | };
64 |
--------------------------------------------------------------------------------
/webpack.config.prod.js:
--------------------------------------------------------------------------------
1 | // For info about this file refer to webpack and webpack-hot-middleware documentation
2 | // For info on how we're generating bundles with hashed filenames for cache busting: https://medium.com/@okonetchnikov/long-term-caching-of-static-assets-with-webpack-1ecb139adb95#.w99i89nsz
3 | import webpack from 'webpack';
4 | import ExtractTextPlugin from 'extract-text-webpack-plugin';
5 | import WebpackMd5Hash from 'webpack-md5-hash';
6 | import HtmlWebpackPlugin from 'html-webpack-plugin';
7 | import autoprefixer from 'autoprefixer';
8 | import path from 'path';
9 |
10 | const GLOBALS = {
11 | 'process.env.NODE_ENV': JSON.stringify('production'),
12 | __DEV__: false
13 | };
14 |
15 | export default {
16 | resolve: {
17 | extensions: ['*', '.js', '.jsx', '.json']
18 | },
19 | devtool: 'source-map', // more info:https://webpack.github.io/docs/build-performance.html#sourcemaps and https://webpack.github.io/docs/configuration.html#devtool
20 | entry: path.resolve(__dirname, 'src/index'),
21 | target: 'web', // necessary per https://webpack.github.io/docs/testing.html#compile-and-test
22 | output: {
23 | path: path.resolve(__dirname, 'dist'),
24 | publicPath: '/',
25 | filename: '[name].[chunkhash].js'
26 | },
27 | plugins: [
28 | // Hash the files using MD5 so that their names change when the content changes.
29 | new WebpackMd5Hash(),
30 |
31 | // Tells React to build in prod mode. https://facebook.github.io/react/downloads.html
32 | new webpack.DefinePlugin(GLOBALS),
33 |
34 | // Generate an external css file with a hash in the filename
35 | new ExtractTextPlugin('[name].[contenthash].css'),
36 |
37 | // Generate HTML file that contains references to generated bundles. See here for how this works: https://github.com/ampedandwired/html-webpack-plugin#basic-usage
38 | new HtmlWebpackPlugin({
39 | template: 'src/index.ejs',
40 | minify: {
41 | removeComments: true,
42 | collapseWhitespace: true,
43 | removeRedundantAttributes: true,
44 | useShortDoctype: true,
45 | removeEmptyAttributes: true,
46 | removeStyleLinkTypeAttributes: true,
47 | keepClosingSlash: true,
48 | minifyJS: true,
49 | minifyCSS: true,
50 | minifyURLs: true
51 | },
52 | inject: true,
53 | // Note that you can add custom options here if you need to handle other custom logic in index.html
54 | // To track JavaScript errors via TrackJS, sign up for a free trial at TrackJS.com and enter your token below.
55 | trackJSToken: ''
56 | }),
57 |
58 | // Minify JS
59 | new webpack.optimize.UglifyJsPlugin({ sourceMap: true }),
60 |
61 | new webpack.LoaderOptionsPlugin({
62 | minimize: true,
63 | debug: false,
64 | noInfo: true, // set to false to see a list of every file being bundled.
65 | options: {
66 | sassLoader: {
67 | includePaths: [path.resolve(__dirname, 'src', 'scss')]
68 | },
69 | context: '/',
70 | postcss: () => [autoprefixer],
71 | }
72 | })
73 | ],
74 | module: {
75 | rules: [
76 | {test: /\.jsx?$/, exclude: /node_modules/, loader: 'babel-loader'},
77 | {test: /\.eot(\?v=\d+.\d+.\d+)?$/, loader: 'url-loader?name=[name].[ext]'},
78 | {test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: 'url-loader?limit=10000&mimetype=application/font-woff&name=[name].[ext]'},
79 | {test: /\.[ot]tf(\?v=\d+.\d+.\d+)?$/, loader: 'url-loader?limit=10000&mimetype=application/octet-stream&name=[name].[ext]'},
80 | {test: /\.svg(\?v=\d+.\d+.\d+)?$/, loader: 'url-loader?limit=10000&mimetype=image/svg+xml&name=[name].[ext]'},
81 | {test: /\.(jpe?g|png|gif)$/i, loader: 'file-loader?name=[name].[ext]'},
82 | {test: /\.ico$/, loader: 'file-loader?name=[name].[ext]'},
83 | {test: /(\.css|\.scss|\.sass)$/, loader: ExtractTextPlugin.extract('css-loader?sourceMap!postcss-loader!sass-loader?sourceMap')}
84 | ]
85 | }
86 | };
87 |
--------------------------------------------------------------------------------