diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 0000000..3734baf --- /dev/null +++ b/.eslintrc @@ -0,0 +1,18 @@ +{ + "env": { + "node": true, + "browser": true, + "es6": true + }, + "parser": "babel-eslint", + "extends": "airbnb", + "rules": { + "react/prefer-stateless-function": "off", + "import/extensions": "off", + "jsx-a11y/anchor-is-valid": ["error", { + "components": ["Link"], + "specialLink": ["to"] + }], + "jsx-a11y/label-has-for": "off", + } +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b9e4a30 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +/node_modules +/dist +/.vscode +/npm-debug.log \ No newline at end of file diff --git a/README.md b/README.md index c74f6ea..c9c496e 100644 --- a/README.md +++ b/README.md @@ -1,31 +1,15 @@ -# Frontend Challenge +# Uso del front +El proyecto se encuentra utilizando _React_ y _Redux_, junto con _axios_ para realizar los request al backend. -This is our challenge for Frontend Developers at @get_crowder +## Requerimientos +* Nodejs 8 +* npm | yarn -#### About the challenge +## Correr en desarrollo +Se esta utilizando una variable de entrono que define en donde se encuentra la ruta del backend. +El env es __BACKEND_URL__ -We'll give you some requirements that must be done and for which you'll be evaluated, but you're free to choose a solution method. +Para correr el proyecto: -#### What we expect to learn from you with this challenge: +> yarn install && yarn run start -* Your work style. -* How you think and solve problems. -* How you communicate. - -#### Next steps - -* Fork this repository to your personal account. -* Follow the instructions in the challenge-description file. -* Solve the challenge in the best way you can. -* Send us a PR with your solution. - -#### How to face the challenge - -* You can use any resource you like, we do too. -* There are no rules in terms of libraries you can add to the project, but keep in mind we will evaluate coherence -* Think, then code. We will evaluate not only the code, but how you faced the problem and the solution you came up with. -* Write code that is clean and easy to read. Code that "just works" doesn't work for us. - -#### Doubts? - -Do you have in doubt related to the process? Open an issue and we'll be happy to help. \ No newline at end of file diff --git a/API.md b/challengeDescription/API.md similarity index 100% rename from API.md rename to challengeDescription/API.md diff --git a/challengeDescription/README.md b/challengeDescription/README.md new file mode 100644 index 0000000..c74f6ea --- /dev/null +++ b/challengeDescription/README.md @@ -0,0 +1,31 @@ +# Frontend Challenge + +This is our challenge for Frontend Developers at @get_crowder + +#### About the challenge + +We'll give you some requirements that must be done and for which you'll be evaluated, but you're free to choose a solution method. + +#### What we expect to learn from you with this challenge: + +* Your work style. +* How you think and solve problems. +* How you communicate. + +#### Next steps + +* Fork this repository to your personal account. +* Follow the instructions in the challenge-description file. +* Solve the challenge in the best way you can. +* Send us a PR with your solution. + +#### How to face the challenge + +* You can use any resource you like, we do too. +* There are no rules in terms of libraries you can add to the project, but keep in mind we will evaluate coherence +* Think, then code. We will evaluate not only the code, but how you faced the problem and the solution you came up with. +* Write code that is clean and easy to read. Code that "just works" doesn't work for us. + +#### Doubts? + +Do you have in doubt related to the process? Open an issue and we'll be happy to help. \ No newline at end of file diff --git a/challenge-description.md b/challengeDescription/challenge-description.md similarity index 100% rename from challenge-description.md rename to challengeDescription/challenge-description.md diff --git a/package.json b/package.json new file mode 100644 index 0000000..5697670 --- /dev/null +++ b/package.json @@ -0,0 +1,50 @@ +{ + "name": "frontend-challenge", + "version": "1.0.0", + "description": "This is our challenge for Frontend Developers at @get_crowder", + "main": "index.js", + "scripts": { + "start": "npm run build", + "build": "webpack --env BACKEND_URL=http://api-challenge.getcrowder.com -d && webpack-dev-server --content-base src/ --inline --hot", + "build:prod": "webpack -p && cp src/index.html dist/index.html && mkdir -p dist/static && cp -R src/static/* dist/static", + "lint": "eslint src/app/*" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/juanmottesi/frontend-challenge.git" + }, + "author": "", + "license": "ISC", + "bugs": { + "url": "https://github.com/juanmottesi/frontend-challenge/issues" + }, + "homepage": "https://github.com/juanmottesi/frontend-challenge#readme", + "dependencies": { + "axios": "^0.18.0", + "prop-types": "^15.6.1", + "react": "^16.3.2", + "react-dom": "^16.3.2", + "react-infinite-scroll-component": "^4.1.0", + "react-redux": "^5.0.7", + "react-router": "^4.0.0", + "react-router-dom": "^4.0.0", + "redux": "^4.0.0", + "redux-logger": "^3.0.6", + "redux-promise-middleware": "^5.1.1" + }, + "devDependencies": { + "babel-eslint": "^8.2.3", + "babel-loader": "^7.1.4", + "babel-preset-es2015": "^6.24.1", + "babel-preset-react": "^6.24.1", + "babel-preset-stage-2": "^6.24.1", + "eslint": "^4.19.1", + "eslint-config-airbnb": "^16.1.0", + "eslint-plugin-import": "^2.11.0", + "eslint-plugin-jsx-a11y": "^6.0.3", + "eslint-plugin-react": "^7.7.0", + "webpack": "^4.8.1", + "webpack-cli": "^2.1.3", + "webpack-dev-server": "^3.1.4" + } +} diff --git a/src/.DS_Store b/src/.DS_Store new file mode 100644 index 0000000..92c0abc Binary files /dev/null and b/src/.DS_Store differ diff --git a/src/app/actions/eventActions.js b/src/app/actions/eventActions.js new file mode 100644 index 0000000..2746707 --- /dev/null +++ b/src/app/actions/eventActions.js @@ -0,0 +1,16 @@ +import BackendService from '../services/backendService'; + +export default { + lookingEvents(page) { + return { + type: 'LOOKING_EVENTS', + payload: BackendService.getEvents(16, page * 16), + }; + }, + getEvent(eventId) { + return { + type: 'GET_EVENT', + payload: BackendService.getEvent(eventId), + }; + }, +}; diff --git a/src/app/actions/orderActions.js b/src/app/actions/orderActions.js new file mode 100644 index 0000000..18f242f --- /dev/null +++ b/src/app/actions/orderActions.js @@ -0,0 +1,64 @@ +import BackendService from '../services/backendService.js'; + +export default { + changeName(name) { + return { + type: 'CHANGE_NAME', + payload: name, + }; + }, + changeEmail(email) { + return { + type: 'CHANGE_EMAIL', + payload: email, + }; + }, + changePhone(phone) { + return { + type: 'CHANGE_PHONE', + payload: phone, + }; + }, + changeAddress(address) { + return { + type: 'CHANGE_ADDRESS', + payload: address, + }; + }, + changeCardholder(cardholder) { + return { + type: 'CHANGE_CARDHOLDER', + payload: cardholder, + }; + }, + changeCardNumber(cardNumber) { + return { + type: 'CHANGE_CARD_NUMBER', + payload: cardNumber, + }; + }, + changeCardExpiration(cardExpiration) { + return { + type: 'CHANGE_CARD_EXPIRATION', + payload: cardExpiration, + }; + }, + changeCVV(cvv) { + return { + type: 'CHANGE_CVV', + payload: cvv, + }; + }, + cleanUp() { + return { + type: 'CLEAN_UP', + payload: null, + }; + }, + executePay(information) { + return { + type: 'EXECUTE_PAY', + payload: BackendService.executePay(information), + }; + }, +}; diff --git a/src/app/actions/purchaseActions.js b/src/app/actions/purchaseActions.js new file mode 100644 index 0000000..125cc05 --- /dev/null +++ b/src/app/actions/purchaseActions.js @@ -0,0 +1,46 @@ +import BackendService from '../services/backendService'; + +export default { + getSectors(dateId) { + return { + type: 'GET_SECTORS', + payload: BackendService.getSectors(dateId), + }; + }, + getRates(eventId) { + return { + type: 'GET_RATES', + payload: BackendService.getRates(eventId), + }; + }, + setDate(date) { + return { + type: 'SET_DATE', + payload: date, + }; + }, + setSector(sector) { + return { + type: 'SET_SECTOR', + payload: sector, + }; + }, + setRate(rate) { + return { + type: 'SET_RATE', + payload: rate, + }; + }, + setQuantity(quantity) { + return { + type: 'SET_QUANTITY', + payload: quantity, + }; + }, + clearPurchase() { + return { + type: 'CLEAR_PURCHASE', + payload: null, + }; + }, +}; diff --git a/src/app/components/ErrorPage.jsx b/src/app/components/ErrorPage.jsx new file mode 100644 index 0000000..68f1401 --- /dev/null +++ b/src/app/components/ErrorPage.jsx @@ -0,0 +1,60 @@ +import React from 'react'; +import PropTypes from 'prop-types'; + +import { Link } from 'react-router-dom'; + +const styles = { color: '#f60' }; + +const ErrorPage = props => ( +
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. + Donec et imperdiet turpis. Quisque at arcu at mi porta dictum. + Duis venenatis mollis erat sed vehicula. +
++ Try Again + +
++ { props.event.description } +
++ So far we do not have more events +
+ } + style={{ overflow: false }} + > + {this.splitEventsOn(4).map(row =>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec et imperdiet turpis. Quisque at arcu at mi porta dictum. Duis venenatis mollis erat sed vehicula.
- -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec et imperdiet turpis. Quisque at arcu at mi porta dictum. Duis venenatis mollis erat sed vehicula.
+ +
- Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed in elit sit amet ligula faucibus semper. In aliquet sit amet purus non luctus. Quisque sit amet velit mattis, aliquam orci nec, tristique ipsum. Nulla ultrices odio neque, non venenatis ex eleifend vitae. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Proin faucibus dui at lacus pretium, sit amet vestibulum ligula vehicula. Morbi turpis urna, facilisis vitae elit imperdiet, molestie volutpat dolor. Nulla facilisi. Aliquam erat volutpat. Suspendisse potenti. Duis id porta dolor.
-Suspendisse ante mi, consectetur ac lectus nec, suscipit condimentum libero. Nullam malesuada urna ut dolor tincidunt sollicitudin. Morbi quis diam a felis eleifend mollis. Nam quis tempus quam. Proin consequat sapien sed felis fermentum, vel dapibus sem dapibus. Nullam molestie, justo eu egestas venenatis, felis ligula bibendum mi, et facilisis felis sapien non metus. Vivamus sit amet lectus quis turpis tempor mattis.
-Curabitur mi felis, lacinia at erat quis, placerat rhoncus dui. Pellentesque efficitur dui varius neque fermentum, commodo consequat metus porta. Donec congue fringilla metus, laoreet mattis ligula pulvinar eget. Aenean et sollicitudin libero. Praesent consequat orci libero, in finibus quam volutpat placerat. Donec vulputate felis et metus tristique, in congue sapien porttitor. Morbi a nulla velit. Integer nec tempor metus. Vestibulum ut est quis augue pretium lacinia. Donec at sollicitudin arcu, a convallis dolor. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec dui mauris, dictum et diam ac, condimentum porta augue. Quisque consequat risus nec neque maximus, in ultricies sem mollis.
-Venue Name
- Venue Address
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed in elit sit amet ligula faucibus semper. In aliquet sit amet purus non luctus. Quisque sit amet velit mattis, aliquam orci nec, tristique ipsum. Nulla ultrices odio neque, non venenatis ex eleifend vitae. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Proin faucibus dui at lacus pretium, sit amet vestibulum ligula vehicula. Morbi turpis urna, facilisis vitae elit imperdiet, molestie volutpat dolor. Nulla facilisi. Aliquam erat volutpat. Suspendisse potenti. Duis id porta dolor.
+Suspendisse ante mi, consectetur ac lectus nec, suscipit condimentum libero. Nullam malesuada urna ut dolor tincidunt sollicitudin. Morbi quis diam a felis eleifend mollis. Nam quis tempus quam. Proin consequat sapien sed felis fermentum, vel dapibus sem dapibus. Nullam molestie, justo eu egestas venenatis, felis ligula bibendum mi, et facilisis felis sapien non metus. Vivamus sit amet lectus quis turpis tempor mattis.
+Curabitur mi felis, lacinia at erat quis, placerat rhoncus dui. Pellentesque efficitur dui varius neque fermentum, commodo consequat metus porta. Donec congue fringilla metus, laoreet mattis ligula pulvinar eget. Aenean et sollicitudin libero. Praesent consequat orci libero, in finibus quam volutpat placerat. Donec vulputate felis et metus tristique, in congue sapien porttitor. Morbi a nulla velit. Integer nec tempor metus. Vestibulum ut est quis augue pretium lacinia. Donec at sollicitudin arcu, a convallis dolor. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec dui mauris, dictum et diam ac, condimentum porta augue. Quisque consequat risus nec neque maximus, in ultricies sem mollis.
+Venue Name
+ Venue Address