` to add yourself in the Contributor list below. The project follows [all-contributors](https://github.com/kentcdodds/all-contributors) format.
53 | - [VSCode](https://code.visualstudio.com/) is recommended as the editor for this project.
54 | - Please install [prettier](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode), [eslint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint), [jest](https://marketplace.visualstudio.com/items?itemName=Orta.vscode-jest) [plugins](https://marketplace.visualstudio.com/) for VSCode for improved developer experience.
55 | - Please follow [JSDoc](http://usejsdoc.org/) for your submitted code. Use [DocumentThis](https://marketplace.visualstudio.com/items?itemName=joelday.docthis) plugin if required.
56 | - Use [`CODETOUR.md`](CODETOUR.md) to get an understanding of the project folder structure.
57 | - Write tests for complicated components and modules.
58 |
59 | ## Contributors
60 |
61 | Thanks goes to these wonderful people ([emoji key](https://github.com/kentcdodds/all-contributors#emoji-key)):
62 |
63 |
64 |
65 |
66 | | [
MADHAV BAHL](http://madhavbahl.tech/)
[💻](https://github.com/GirlScriptSummerOfCode/Upay/commits?author=MadhavBahlMD "Code") | [
Minanshu Singh](https://github.com/kryptokinght)
[💻](https://github.com/GirlScriptSummerOfCode/Upay/commits?author=kryptokinght "Code") | [
Sambhav Jain](https://sourcerer.io/sambhav2612)
[📖](https://github.com/GirlScriptSummerOfCode/Upay/commits?author=sambhav2612 "Documentation") | [
Sakshi Shreya](https://github.com/SakshiShreya)
[💻](https://github.com/GirlScriptSummerOfCode/Upay/commits?author=SakshiShreya "Code") | [
Adarsh Lilha](https://github.com/adarshlilha)
[💻](https://github.com/GirlScriptSummerOfCode/Upay/commits?author=adarshlilha "Code") | [
Divjot Singh](http://bogas04.github.io)
[💻](https://github.com/GirlScriptSummerOfCode/Upay/commits?author=bogas04 "Code") | [
Anshul Mittal](https://github.com/Nshul)
[💻](https://github.com/GirlScriptSummerOfCode/Upay/commits?author=Nshul "Code") |
67 | | :---: | :---: | :---: | :---: | :---: | :---: | :---: |
68 | | [
Twisha](https://twishasaraiya.github.io/)
[💻](https://github.com/GirlScriptSummerOfCode/Upay/commits?author=twishasaraiya "Code") |
69 |
70 |
71 |
72 | This project follows the [all-contributors](https://github.com/kentcdodds/all-contributors) specification. Contributions of any kind welcome!
73 |
74 | ## License
75 |
76 | (c) GSSoC and Upay Contributors under MIT License
77 |
--------------------------------------------------------------------------------
/components/Breadcrumb/Breadcrumb.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import PropTypes from 'prop-types';
3 |
4 | export default class Breadcrumb extends React.Component {
5 | static propTypes = {
6 | path: PropTypes.string,
7 | };
8 |
9 | render() {
10 | const { path } = this.props;
11 | return (
12 |
13 |
18 |
19 | Home
20 | {path.replace(/%20/g, ' ')}
21 |
22 |
23 | );
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/components/Breadcrumb/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './Breadcrumb';
2 |
--------------------------------------------------------------------------------
/components/Carousel/Carousel.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import PropTypes from 'prop-types';
3 |
4 | export default class Carousel extends React.PureComponent {
5 | constructor(props){
6 | super(props);
7 | this.displayImage = React.createRef();
8 | }
9 | static propTypes = {
10 | imageUrls: PropTypes.array,
11 | };
12 |
13 | changeImage = e => {
14 | this.displayImage.current.src = e.target.src;
15 | };
16 |
17 | render() {
18 | const { imageUrls } = this.props;
19 | return (
20 |
21 |
41 |
42 |
47 |
48 | {imageUrls.map((src,i) => (
49 |
50 | )
51 | )}
52 |
53 |
54 |
55 | );
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/components/Carousel/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './Carousel';
2 |
--------------------------------------------------------------------------------
/components/Icons/Arrow.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | const Arrow = props => (
4 |
7 | );
8 |
9 | export default Arrow;
10 |
--------------------------------------------------------------------------------
/components/Icons/Bookmark.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | const Bookmark = props => (
4 |
7 | );
8 |
9 | export default Bookmark;
10 |
--------------------------------------------------------------------------------
/components/Icons/Chevron.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import PropTypes from 'prop-types';
3 |
4 | const getStyle = direction => {
5 | const { TOP, LEFT, RIGHT, BOTTOM } = Chevron.DIRECTIONS;
6 | let transform = '';
7 | switch (direction) {
8 | case TOP: {
9 | transform = 'rotate(0deg)';
10 | break;
11 | }
12 | case LEFT: {
13 | transform = 'rotate(-90deg)';
14 | break;
15 | }
16 | case RIGHT: {
17 | transform = 'rotate(90deg)';
18 | break;
19 | }
20 | case BOTTOM: {
21 | transform = 'rotate(180deg)';
22 | break;
23 | }
24 | }
25 |
26 | return {
27 | OTransform: transform,
28 | WebKitTransform: transform,
29 | MozTransform: transform,
30 | transform,
31 | };
32 | };
33 |
34 | const Chevron = props => (
35 |
46 | );
47 |
48 | Chevron.DIRECTIONS = {
49 | TOP: 0,
50 | RIGHT: 1,
51 | BOTTOM: 2,
52 | LEFT: 3,
53 | };
54 |
55 | Chevron.propTypes = {
56 | direction: PropTypes.oneOf([0, 1, 2, 3]),
57 | };
58 | export default Chevron;
59 |
--------------------------------------------------------------------------------
/components/Icons/Cog.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | const Cog = props => (
4 |
7 | );
8 |
9 | export default Cog;
10 |
--------------------------------------------------------------------------------
/components/Icons/Hamburger.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | const Hamburger = props => (
4 |
7 | );
8 |
9 | export default Hamburger;
10 |
--------------------------------------------------------------------------------
/components/Icons/Heart.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | const Heart = props => (
4 |
7 | );
8 |
9 | export default Heart;
10 |
--------------------------------------------------------------------------------
/components/Icons/Rupee.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | const Rupee = props => (
4 |
7 | );
8 |
9 | export default Rupee;
10 |
--------------------------------------------------------------------------------
/components/Icons/Save.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | const Save = props => (
4 |
7 | );
8 |
9 | export default Save;
10 |
--------------------------------------------------------------------------------
/components/Icons/Search.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | const Search = props => (
4 |
7 | );
8 |
9 | export default Search;
10 |
--------------------------------------------------------------------------------
/components/Icons/Share.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | const Share = props => (
4 |
7 | );
8 |
9 | export default Share;
10 |
--------------------------------------------------------------------------------
/components/Icons/User.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | const User = props => (
4 |
7 | );
8 |
9 | export default User;
10 |
--------------------------------------------------------------------------------
/components/Item/Item.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import Link from 'next/link';
3 | import Rupee from '../Icons/Rupee';
4 | import PropTypes from 'prop-types';
5 |
6 | const Item = props => (
7 |
8 |
82 |
83 |
84 |
85 |
86 |
87 |
88 | {props.name}
89 |
90 |
91 | {/* This code handles price. */}
92 | {/* If discounted price is available, it displays discounted price and strikes-through original price. */}
93 | {/* If discounted price is not available, it displays original price. */}
94 | {props.discountedPrice && (
95 |
96 |
97 | {props.discountedPrice}
98 |
99 | )}
100 | {props.discountedPrice ? (
101 |
102 |
103 | {props.originalPrice}
104 |
105 | ) : (
106 |
107 |
108 | {props.originalPrice}
109 |
110 | )}
111 |
112 |
113 |
114 | {/* Add the buttons later */}
115 | Add
116 | SaveForLater
117 |
118 |
119 |
120 | );
121 |
122 | Item.propTypes = {
123 | id: PropTypes.number,
124 | name: PropTypes.string,
125 | originalPrice: PropTypes.number,
126 | discountedPrice: PropTypes.number,
127 | imageUrls: PropTypes.arrayOf(PropTypes.string),
128 | };
129 | export default Item;
130 |
--------------------------------------------------------------------------------
/components/Item/README.md:
--------------------------------------------------------------------------------
1 | # Item
2 |
3 | Each item is an element from the list of items.
4 |
5 | ## Item call:
6 |
7 | ```
8 |
15 | ```
16 |
--------------------------------------------------------------------------------
/components/Item/__tests__/Item.test.js:
--------------------------------------------------------------------------------
1 | /* globals describe, it, expect */
2 | import React from 'react';
3 | import { mount } from 'enzyme';
4 | import Item from '../Item';
5 |
6 | describe(' ', () => {
7 | it('renders correctly', () => {
8 | const wrapper = mount( );
9 | expect(wrapper).toMatchSnapshot();
10 | });
11 | });
12 |
--------------------------------------------------------------------------------
/components/Item/__tests__/__snapshots__/Item.test.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[` renders correctly 1`] = `
4 | -
13 |
17 |
20 |
23 |
30 |
31 |
34 |
37 |
41 | Item one
42 |
43 |
44 |
47 |
50 |
53 |
62 |
63 |
64 |
65 |
66 |
69 |
72 | Add
73 |
74 |
77 | SaveForLater
78 |
79 |
80 |
81 |
82 | `;
83 |
--------------------------------------------------------------------------------
/components/Item/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './Item';
2 |
--------------------------------------------------------------------------------
/components/NavBar/NavBar.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import PropTypes from 'prop-types';
3 | import Link from 'next/link';
4 |
5 | /**
6 | *
7 | *
8 | * @export
9 | * @class NavBar
10 | * @augments {React.PureComponent}
11 | */
12 | export default class NavBar extends React.PureComponent {
13 | /**
14 | * @typedef {object} NavBarProps
15 | * @property {array} links
16 | *
17 | * @static
18 | * @memberof NavBar
19 | */
20 | static propTypes = {
21 | /** Links Array */
22 | links: PropTypes.arrayOf(
23 | PropTypes.shape({
24 | /** Link URL */
25 | url: PropTypes.string,
26 | /** Link Title */
27 | title: PropTypes.string,
28 | })
29 | ).isRequired,
30 | };
31 |
32 | render() {
33 | return (
34 |
35 |
53 |
64 |
65 | );
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/components/NavBar/README.md:
--------------------------------------------------------------------------------
1 | #
2 |
3 | NavBar showing two links
4 |
5 | ```jsx
6 |
14 | ```
15 |
--------------------------------------------------------------------------------
/components/NavBar/__tests__/Navbar.test.js:
--------------------------------------------------------------------------------
1 | /* globals describe, it, expect */
2 | import React from 'react';
3 | import { mount } from 'enzyme';
4 | import { shallowToJson } from 'enzyme-to-json'; // removes unnecessary JSON from snapshot
5 | import Navbar from '../';
6 | import links from '../../../constants/links';
7 |
8 | describe(' ', () => {
9 | it('renders correctly', () => {
10 | const wrapper = mount( );
11 | expect(shallowToJson(wrapper)).toMatchSnapshot();
12 | });
13 | });
14 |
--------------------------------------------------------------------------------
/components/NavBar/__tests__/__snapshots__/Navbar.test.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[` renders correctly 1`] = `
4 |
18 |
22 |
62 |
63 | `;
64 |
--------------------------------------------------------------------------------
/components/NavBar/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './NavBar';
2 |
--------------------------------------------------------------------------------
/components/ProductInfo/ProductInfo.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import PropTypes from 'prop-types';
3 | import Rupee from '../Icons/Rupee';
4 |
5 | export default class ProductInfo extends React.PureComponent {
6 | static propTypes = {
7 | name: PropTypes.string,
8 | originalPrice: PropTypes.number,
9 | discountedPrice: PropTypes.number,
10 | description: PropTypes.string,
11 | };
12 | static defaultProps = {
13 | description: 'No description available',
14 | };
15 | render() {
16 | const { name, originalPrice, discountedPrice, description } = this.props;
17 | return (
18 |
19 |
20 | {name}
21 | {originalPrice ? (
22 |
23 |
24 | {originalPrice}
25 |
26 | ) : (
27 |
28 |
29 | {originalPrice}
30 |
31 | )}
32 | {discountedPrice && (
33 |
34 |
35 | {discountedPrice}
36 |
37 | )}
38 | {description}
39 |
40 |
41 | );
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/components/ProductInfo/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './ProductInfo';
2 |
--------------------------------------------------------------------------------
/components/QuantityButton/QuantityButton.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import PropTypes from 'prop-types';
3 |
4 | export default class QuantityButton extends React.Component {
5 | static propTypes = {
6 | qty: PropTypes.number,
7 | increment: PropTypes.func,
8 | decrement: PropTypes.func,
9 | };
10 |
11 | render() {
12 | const { qty, increment, decrement } = this.props;
13 | return (
14 |
15 |
43 |
44 |
47 | {this.props.qty}
48 |
55 |
56 |
57 | );
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/components/QuantityButton/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './QuantityButton';
2 |
--------------------------------------------------------------------------------
/constants/links.js:
--------------------------------------------------------------------------------
1 | export default [{ title: 'Upay', url: '/' }, { title: 'About', url: '/about' }];
2 |
--------------------------------------------------------------------------------
/jest.setup.js:
--------------------------------------------------------------------------------
1 | import { configure } from 'enzyme';
2 | import Adapter from 'enzyme-adapter-react-16';
3 |
4 | configure({ adapter: new Adapter() });
5 |
--------------------------------------------------------------------------------
/now.json:
--------------------------------------------------------------------------------
1 | {
2 | "alias": ["upay-website"],
3 | "name": "upay-website",
4 | "public": true
5 | }
6 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "upay-website",
3 | "version": "1.0.0",
4 | "dependencies": {
5 | "babel-core": "7.0.0-bridge.0",
6 | "babel-jest": "22.4.3",
7 | "express": "^4.16.3",
8 | "isomorphic-unfetch": "^2.0.0",
9 | "next": "^6.0.3",
10 | "prop-types": "^15.6.2",
11 | "react": "^16.4.1",
12 | "react-dom": "^16.4.1"
13 | },
14 | "devDependencies": {
15 | "babel-eslint": "^8.2.3",
16 | "cross-env": "^5.2.0",
17 | "enzyme": "3.2.0",
18 | "enzyme-adapter-react-16": "1.1.1",
19 | "enzyme-to-json": "^3.3.4",
20 | "eslint": "^4.19.1",
21 | "eslint-plugin-react": "^7.10.0",
22 | "husky": "^0.14.3",
23 | "jest": "^22.0.1",
24 | "lint-staged": "^7.2.0",
25 | "npm-run-all": "^4.1.3",
26 | "react-addons-test-utils": "15.6.2",
27 | "react-styleguidist": "^7.0.19",
28 | "react-test-renderer": "16.2.0"
29 | },
30 | "scripts": {
31 | "prepush": "npm test",
32 | "test": "npm-run-all test:* --parallel",
33 | "test:lint": "eslint ./",
34 | "test:unit": "cross-env NODE_ENV=test jest",
35 | "watch": "npm-run-all watch:* --parallel",
36 | "watch:test": "npm run test:unit -- --watch",
37 | "dev": "node server",
38 | "build": "next build",
39 | "start": "cross-env NODE_ENV=production node server",
40 | "styleguide": "styleguidist server"
41 | },
42 | "babel": {
43 | "env": {
44 | "development": {
45 | "presets": [
46 | "next/babel"
47 | ]
48 | },
49 | "production": {
50 | "presets": [
51 | "next/babel"
52 | ]
53 | },
54 | "test": {
55 | "presets": [
56 | [
57 | "next/babel",
58 | {
59 | "preset-env": {
60 | "modules": "commonjs"
61 | }
62 | }
63 | ]
64 | ]
65 | }
66 | }
67 | },
68 | "jest": {
69 | "setupFiles": [
70 | "/jest.setup.js"
71 | ],
72 | "testPathIgnorePatterns": [
73 | "/.next/",
74 | "/node_modules/"
75 | ],
76 | "snapshotSerializers": [
77 | "enzyme-to-json/serializer"
78 | ]
79 | },
80 | "prettier": {
81 | "trailingComma": "es5",
82 | "singleQuote": true,
83 | "tabWidth": 2,
84 | "useTabs": false
85 | },
86 | "description": "[](#contributors)",
87 | "repository": {
88 | "type": "git",
89 | "url": "git+https://github.com/GirlScriptSummerOfCode/Upay.git"
90 | },
91 | "keywords": [
92 | "upay",
93 | "website"
94 | ],
95 | "author": "GSSoC and Upay Contributors",
96 | "license": "MIT",
97 | "bugs": {
98 | "url": "https://github.com/GirlScriptSummerOfCode/Upay/issues"
99 | },
100 | "homepage": "https://github.com/GirlScriptSummerOfCode/Upay#readme"
101 | }
102 |
--------------------------------------------------------------------------------
/pages/_document.js:
--------------------------------------------------------------------------------
1 | import Document, { Head, Main, NextScript } from 'next/document';
2 | import links from '../constants/links';
3 | import NavBar from '../components/NavBar';
4 |
5 | export default class MyDocument extends Document {
6 | static async getInitialProps(ctx) {
7 | const initialProps = await Document.getInitialProps(ctx);
8 | return { ...initialProps };
9 | }
10 |
11 | render() {
12 | return (
13 |
14 |
15 |
19 |
20 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 | );
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/pages/about.js:
--------------------------------------------------------------------------------
1 | /**
2 | * About page
3 | * @returns {React.ReactElement}
4 | */
5 | export default () => (
6 |
7 | About Page
8 |
9 | It mainly aims to provide opportunities to underprivileged children and
10 | bring some sunshine in those deprived lives. Ever since it's dawn, UPAY
11 | Team has been working wholeheartedly in achieving this aim. Its success
12 | story can be culminated by the mere fact that where children were unable
13 | to do basic arithmetic calculations are now, not just producing excellent
14 | academic results but also bringing laurels to these underprivileged areas.
15 | The main vision of UPAY is overcome disparities in education so that every
16 | child gets an opportunity to Learn, Grow and Succeed.
17 |
18 |
19 | );
20 |
--------------------------------------------------------------------------------
/pages/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import Item from '../components/Item';
3 | import Arrow from '../components/Icons/Arrow';
4 | import Bookmark from '../components/Icons/Bookmark';
5 | import Cog from '../components/Icons/Cog';
6 | import Hamburger from '../components/Icons/Hamburger';
7 | import Heart from '../components/Icons/Heart';
8 | import Rupee from '../components/Icons/Rupee';
9 | import Save from '../components/Icons/Save';
10 | import Search from '../components/Icons/Search';
11 | import Share from '../components/Icons/Share';
12 | import User from '../components/Icons/User';
13 | import Chevron from '../components/Icons/Chevron';
14 |
15 | /**
16 | * Home page
17 | *
18 | * @export
19 | * @class IndexPage
20 | * @extends {React.PureComponent}
21 | */
22 | export default class IndexPage extends React.PureComponent {
23 | state = {
24 | items: [],
25 | };
26 |
27 | render() {
28 | return (
29 |
30 |
35 |
36 |
37 |
38 |
39 | The foundation of development for every society is the education of
40 | its youth. Keeping this in mind, an
41 |
46 | {' NGO UPAY '}
47 |
48 | (Underprivileged Advancement by Youth), was established in May 2010
49 | by a group of young engineers from IITs and NITs.
50 |
51 |
52 | Items
53 |
54 | {this.state.items.map(
55 | (item) => (
56 |
60 | )
61 | )}
62 |
63 |
64 |
65 | Icons
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 | );
81 | }
82 |
83 | /**
84 | * This is for demo purposes.
85 | * Once the component has mounted, we fetch items from our API and sets them to state.
86 | */
87 | async componentDidMount() {
88 | const { data: items } = await fetch('/api/items').then(r => r.json());
89 | this.setState({ items });
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/pages/product.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import PropTypes from 'prop-types';
3 | import Error from 'next/error';
4 | import Bookmark from '../components/Icons/Bookmark';
5 | import QuantityButton from '../components/QuantityButton';
6 | import Breadcrumb from '../components/Breadcrumb';
7 | import Carousel from '../components/Carousel';
8 | import ProductInfo from '../components/ProductInfo';
9 | import { withRouter } from 'next/router';
10 | import fetch from 'isomorphic-unfetch';
11 | import { server } from '../server/config';
12 |
13 | /**
14 | * Product Details Page
15 | *
16 | * @export
17 | * @class ProductPage
18 | * @extends {React.PureComponent}
19 | */
20 | class ProductPage extends React.PureComponent {
21 | state = {
22 | qty: 0,
23 | };
24 |
25 | static propTypes = {
26 | Item: PropTypes.shape({
27 | id: PropTypes.number,
28 | name: PropTypes.string,
29 | imageUrls: PropTypes.array,
30 | originalPrice: PropTypes.number,
31 | discountedPrice: PropTypes.number,
32 | }),
33 | };
34 |
35 | static getInitialProps = async ({ query, res }) => {
36 | const { id } = query;
37 | if (!id && res) {
38 | res.statusCode = 404;
39 | return { Item: null };
40 | }
41 | const { data: Item } = await fetch(`${server}/api/items/${id}`).then(r =>
42 | r.json()
43 | );
44 | return { Item };
45 | };
46 | increment = () => {
47 | this.setState({
48 | qty: this.state.qty + 1,
49 | });
50 | };
51 | decrement = () => {
52 | this.setState({
53 | qty: this.state.qty - 1,
54 | });
55 | };
56 | render() {
57 | const { router, Item } = this.props;
58 | if (!Item) return ;
59 | return (
60 |
61 |
126 |
127 |
128 |
129 |
130 |
135 |
140 |
141 | Delivery Options
142 |
143 |
144 |
145 |
146 | Save
147 |
148 | Add To Cart
149 |
150 |
151 |
152 |
153 | );
154 | }
155 | }
156 |
157 | export default withRouter(ProductPage);
158 |
--------------------------------------------------------------------------------
/public/images/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GirlScriptSummerOfCode/Upay/353fd5a7ea4e8d8acb536436e383067e2ecac1d8/public/images/logo.png
--------------------------------------------------------------------------------
/public/images/placeholder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GirlScriptSummerOfCode/Upay/353fd5a7ea4e8d8acb536436e383067e2ecac1d8/public/images/placeholder.png
--------------------------------------------------------------------------------
/public/images/upay.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GirlScriptSummerOfCode/Upay/353fd5a7ea4e8d8acb536436e383067e2ecac1d8/public/images/upay.png
--------------------------------------------------------------------------------
/server/api/index.js:
--------------------------------------------------------------------------------
1 | const { Router } = require('express');
2 |
3 | const items = [
4 | {
5 | id: 1,
6 | name: 'Item 1',
7 | imageUrls: [
8 | '/images/placeholder.png',
9 | '/images/placeholder.png',
10 | '/images/upay.png',
11 | '/images/placeholder.png',
12 | ],
13 | originalPrice: 100,
14 | discountedPrice: undefined,
15 | },
16 | {
17 | id: 2,
18 | name: 'Item 2',
19 | imageUrls: [
20 | '/images/placeholder.png',
21 | '/images/placeholder.png',
22 | '/images/upay.png',
23 | '/images/placeholder.png',
24 | ],
25 | originalPrice: 200,
26 | discountedPrice: 150,
27 | },
28 | {
29 | id: 3,
30 | name: 'Item 3',
31 | imageUrls: [
32 | '/images/placeholder.png',
33 | '/images/placeholder.png',
34 | '/images/upay.png',
35 | '/images/placeholder.png',
36 | ],
37 | originalPrice: 300,
38 | discountedPrice: 250,
39 | },
40 | {
41 | id: 4,
42 | name: 'Item 4',
43 | imageUrls: [
44 | '/images/placeholder.png',
45 | '/images/placeholder.png',
46 | '/images/upay.png',
47 | '/images/placeholder.png',
48 | ],
49 | originalPrice: 400,
50 | discountedPrice: undefined,
51 | },
52 | {
53 | id: 5,
54 | name: 'Item 5',
55 | imageUrls: [
56 | '/images/placeholder.png',
57 | '/images/placeholder.png',
58 | '/images/upay.png',
59 | '/images/placeholder.png',
60 | ],
61 | originalPrice: 500,
62 | discountedPrice: 450,
63 | },
64 | {
65 | id: 6,
66 | name: 'Item 6',
67 | imageUrls: [
68 | '/images/placeholder.png',
69 | '/images/placeholder.png',
70 | '/images/upay.png',
71 | '/images/placeholder.png',
72 | ],
73 | originalPrice: 600,
74 | discountedPrice: 550,
75 | },
76 | ];
77 |
78 | const api = Router();
79 |
80 | /* Our demo API */
81 |
82 | api
83 | .get('/items/:id', (req, res) =>
84 | res.json({ data: items[req.params.id - 1] || null })
85 | )
86 | .get('/items', (req, res) => res.json({ data: items }));
87 |
88 | module.exports = api;
89 |
--------------------------------------------------------------------------------
/server/config.js:
--------------------------------------------------------------------------------
1 | const dev = process.env.NODE_ENV !== 'production';
2 | const PORT = parseInt(process.env.PORT, 10) || 3000;
3 | const NOWURL = process.env.NOW ? process.env.NOW_URL : '';
4 | export const server = dev ? `http://localhost:${PORT}` : NOWURL;
5 |
--------------------------------------------------------------------------------
/server/index.js:
--------------------------------------------------------------------------------
1 | const express = require('express');
2 | const next = require('next');
3 | const path = require('path');
4 | const api = require('./api');
5 |
6 | const PORT = parseInt(process.env.PORT, 10) || 3000;
7 | const dev = process.env.NODE_ENV !== 'production';
8 | const nextApp = next({ dev });
9 | const handleNextPages = nextApp.getRequestHandler();
10 |
11 | nextApp.prepare().then(() => {
12 | const expressServer = express();
13 |
14 | /* Static assets are kept at /public folder */
15 |
16 | expressServer.use(express.static(path.resolve(__dirname, '..', 'public')));
17 |
18 | /* APIs go there */
19 | expressServer.use('/api', api);
20 |
21 | /* Clean URL for rendering Product Information*/
22 | expressServer.get('/product/:id', (req, res) => {
23 | nextApp.render(req, res, '/product', req.params);
24 | });
25 |
26 | /* All website routes are automatically handled by next */
27 | expressServer.get('*', handleNextPages);
28 |
29 | /* Listen to the server now */
30 | expressServer.listen(PORT, err => {
31 | if (err) throw err;
32 | console.log(`> Ready on http://localhost:${PORT}`); // eslint-disable-line no-console
33 | });
34 | });
35 |
--------------------------------------------------------------------------------
/styleguide.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | components: 'components/**/[A-Z]*.js',
3 | webpackConfig: {
4 | module: {
5 | rules: [
6 | {
7 | test: /\.js$/,
8 | exclude: /node_modules/,
9 | loader: 'babel-loader',
10 | },
11 | ],
12 | },
13 | },
14 | };
15 |
--------------------------------------------------------------------------------