diff --git a/package.json b/package.json index 16a54ac..78406d8 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,7 @@ "main": "index.js", "scripts": { "test": "jest --config=jest.config.json", + "test:watch": "npm test -- --watch", "coverage": "npm run test -- --coverage", "coveralls": "npm run coverage && cat ./coverage/lcov.info | coveralls", "build": "webpack --config webpack.config.prod.js", @@ -23,6 +24,7 @@ }, "homepage": "https://github.com/akhilome/kiakiafood#readme", "dependencies": { + "prop-types": "^15.6.2", "react": "^16.7.0", "react-dom": "^16.7.0", "react-hot-loader": "^4.6.3", diff --git a/src/components/HomePage.jsx b/src/components/HomePage.jsx index 5c68371..3ab486c 100644 --- a/src/components/HomePage.jsx +++ b/src/components/HomePage.jsx @@ -1,5 +1,20 @@ import React from 'react'; +import { Link } from 'react-router-dom'; -const HomePage = () =>
This is the HomePage!
; +import Nav from './Nav'; + +const HomePage = () => ( +
+
+); export default HomePage; diff --git a/src/components/LoginPage.jsx b/src/components/LoginPage.jsx index cb0a4f3..cd7afdf 100644 --- a/src/components/LoginPage.jsx +++ b/src/components/LoginPage.jsx @@ -3,9 +3,9 @@ import { Link } from 'react-router-dom'; const LoginPage = () => (
- This is the login page See - {' '} - signup + This is the login page. +
+ Go Home
); diff --git a/src/components/Nav.jsx b/src/components/Nav.jsx new file mode 100644 index 0000000..38acfe3 --- /dev/null +++ b/src/components/Nav.jsx @@ -0,0 +1,24 @@ +import React from 'react'; +import { Link } from 'react-router-dom'; + +const Nav = () => ( +
+
+

+ Kiakia Food +

+
+ +
+); + +export default Nav; diff --git a/src/components/NotFoundPage.jsx b/src/components/NotFoundPage.jsx index 17e79db..7296254 100644 --- a/src/components/NotFoundPage.jsx +++ b/src/components/NotFoundPage.jsx @@ -1,5 +1,12 @@ import React from 'react'; +import { Link } from 'react-router-dom'; -const NotFoundPage = () =>
Four-oh-Four
; +const NotFoundPage = () => ( +
+ Four-oh-Four +
+ Go Home +
+); export default NotFoundPage; diff --git a/src/components/SignupPage.jsx b/src/components/SignupPage.jsx index dda1da4..4e221ea 100644 --- a/src/components/SignupPage.jsx +++ b/src/components/SignupPage.jsx @@ -1,5 +1,12 @@ import React from 'react'; +import { Link } from 'react-router-dom'; -const SignupPage = () =>
This is the signup page
; +const SignupPage = () => ( +
+ This is the signup page +
+ Go Home +
+); export default SignupPage; diff --git a/src/index.css b/src/index.css index 5dddba9..850c14b 100644 --- a/src/index.css +++ b/src/index.css @@ -1,5 +1,537 @@ body { - font-family: sans-serif; + background: #fff; + color: #333; + font-family: 'Open Sans', sans-serif; + font-size: 18px; + line-height: 1.75; + margin: 0; +} + +/* Navigation */ +header { + align-items: center; + display: flex; + font-family: 'Comfortaa', cursive; + justify-content: space-between; + padding: 5px 20px; + text-transform: lowercase; +} + +header.transparent { + position: absolute; + width: calc(100% - 40px); +} + +header.transparent .site-title a { + color: #fff; +} + +header.transparent nav a { + color: #fff; +} + +header.transparent nav a:hover { + color: #fff; + background: rgba(41, 152, 111, 0.5); +} + +.site-title a { + color: #1d6b4f; + font-size: 1.8rem; + letter-spacing: -2px; +} + +nav a { + border-radius: 6px; + color: #333; + padding: 8px 10px; +} + +nav a:hover { + color: #1d6b4f; + background: rgba(41, 152, 111, 0.226); +} + +nav ul { + display: inline-flex; + list-style-type: none; + padding-left: 0; +} + +.nav-mobile { + display: none; +} + +/* Buttons */ +button a { + color: #fff; +} + +input[type='submit'], +button { + background: #333; + border-radius: 6px; + border: none; + box-shadow: 0 2px 4px -2px rgba(36, 18, 77, 0.2); + color: #fff; + cursor: pointer; + font-family: 'Comfortaa', cursive; + font-weight: 700; + padding: 15px 20px; + text-transform: lowercase; +} + +button:hover { + background: #666; +} + +button.small { + font-size: 12px; + padding: 8px 12px; +} + +button.danger { + background: #b82e33; +} + +button.danger:hover { + background: rgba(184, 46, 51, 0.7); +} + +.btn-primary, +button.primary { + background: #1d6b4f; +} + +.btn-primary:hover, +button.primary:hover { + background: #2a9971; +} + +/* Misc */ +a { + color: #2a9971; + text-decoration: none; +} + +img.food { + height: auto; + width: 360px; +} + +/* Frontpage Hero Section */ +.hero { + align-items: center; + background: url('https://i.imgur.com/zDMLgBX.jpg'); + background-attachment: fixed; + background-repeat: no-repeat; + background-size: cover; + color: #fff; + display: flex; + flex-direction: column; + height: 100vh; + justify-content: center; + padding: 0 30px; +} + +.hero h2 { + font-size: 2.6rem; + margin-bottom: 50px; + text-align: center; +} + +/* Login & Sign Up Pages*/ +body.auth { + background: url('https://i.imgur.com/zDMLgBX.jpg'); + background-attachment: fixed; + background-repeat: no-repeat; + background-size: cover; + color: #fff; +} + +div.auth { + min-height: 100vh; + justify-content: center; +} + +/* Flash Messages */ +.flash-message { + width: 100%; + text-align: center; + height: 25px; + position: fixed; + background: #17a2b8; + padding: 20px 25px; + color: #fff; + font-family: 'Comfortaa', cursive; + font-size: 16px; + border-radius: 4px; + transition: all 0.5s ease-in-out; + top: calc(100vh - 65px); +} + +.flash-message_success { + background: #1d6b4f; +} + +.flash-message_error { + background: #b82e33; +} + +/* Wrapper */ +.wrapper { + align-items: center; + display: flex; + flex-direction: column; + min-height: calc(100vh - 200px); +} + +.container { + margin: 25px auto; + padding: 20px; + text-align: center; +} + +/* Form Elements */ +form { + display: block; +} + +input { + border: 1px solid #666; + border-radius: 6px; + display: block; + margin: 10px; + padding: 15px 20px; + text-align: center; + width: 200px; +} + +input::placeholder { + font-size: 16px; +} + +input[type='submit'] { + background: #1d6b4f; + margin: auto; + width: auto; +} + +input[type='checkbox'] { + width: auto; +} + +fieldset { + border: none; +} + +fieldset > div { + align-items: center; + border: 1px solid #2a9971; + border-radius: 6px; + display: flex; + padding: 10px 20px; + margin: 10px auto; +} + +/* Food Menu */ +.food-menu { + display: flex; + flex-wrap: wrap; + max-width: 860px; + justify-content: space-evenly; +} + +.food-card { + box-shadow: 0 2px 4px -2px rgba(36, 18, 77, 0.2); + display: flex; + flex-direction: column; + margin: 15px 10px; + max-height: 350px; + max-width: 250px; +} + +.food-image { + height: 200px; + width: 250px; +} + +.food-details { + align-items: center; + background: #2a9971; color: #fff; - background-color: #333; + border-radius: 0 0 6px 6px; + border-top: none; + display: flex; + justify-content: space-between; + max-height: 100px; + padding: 5px 15px; +} + +.food-details__legend { + line-height: 1.2; + text-align: left; +} + +.food-details__legend > * { + font-size: 16px; + margin: 10px auto; +} + +.food-details__legend > p { + font-size: 0.9rem; +} + +.food-details__action > button { + border: 1px dashed #fff; + background: transparent; + font-size: 12px; + padding: 8px 12px; +} + +.food-details__action > button:hover { + background: #fff; + color: #1d6b4f; +} + +/* Cart */ +.checkout { + max-width: 720px; + display: flex; + flex-wrap: wrap; + justify-content: space-evenly; +} + +.food-card-checkout { + align-items: center; + border: 1px solid #2a9971; + border-radius: 4px; + display: flex; + height: 100px; + justify-content: space-around; + margin: 20px 10px; + width: 300px; +} + +.food-card-checkout__details { + line-height: 1.5; + text-align: left; +} + +.food-card-checkout__details > * { + font-size: 16px; + margin: 10px auto; +} + +.food-card-checkout > button { + background: #b82e33; + font-size: 12px; + padding: 8px 12px; +} + +/* Order History */ +.order-history { + display: flex; + flex-wrap: wrap; + justify-content: space-evenly; + max-width: 1024px; +} + +.order-card { + border: 1px solid #ddd; + border-radius: 6px; + box-shadow: 0 2px 4px -2px rgba(36, 18, 77, 0.3); + color: #333; + display: table; + margin: 20px 15px; + padding: 20px 0; + width: 300px; +} + +.order-card > * { + border-bottom: 1px dotted #ddd; + margin: 5px auto; +} + +.order-card > *:last-child, +.order-card > *:nth-last-child(2) { + border-bottom: none; +} + +.order-card p { + font-size: 16px; +} + +.order-card_food-items h3 { + border-bottom: 1px dotted #ddd; + font-family: 'Comfortaa', cursive; + font-size: 1em; + letter-spacing: -1px; + margin: 10px auto; + text-transform: lowercase; +} + +.order-card_food-items_names { + display: flex; + flex-wrap: wrap; + justify-content: space-evenly; +} + +.order-card_food-items_names > p, +.order-card_price > p, +.order-card_date > p { + flex-basis: 45%; + margin: 15px auto; +} + +.order-card_food-items_names > p { + align-items: center; + border: 1px solid #ddd; + border-radius: 4px; + display: flex; + justify-content: center; + margin: 10px auto; +} + +.order-card_price, +.order-card_date { + display: flex; + flex-wrap: wrap; + justify-content: flex-start; + padding-left: 40px; + text-align: left; +} + +.order-status-new { + background: #333; +} + +.order-status-new::after { + content: 'new'; +} + +.order-status-progress { + background: #ffc900; +} + +.order-status-progress::after { + content: 'in progress'; +} + +.order-status-completed { + background: #1d6b4f; +} + +.order-status-completed::after { + content: 'completed'; +} + +.order-status-rejected { + background: #b82e33; +} + +.order-status-rejected::after { + content: 'rejected'; +} + +.order-status-new::after, +.order-status-progress::after, +.order-status-rejected::after, +.order-status-completed::after { + color: #fff; + font-family: 'Comfortaa', cursive; + font-size: 0.85rem; +} + +/* Admin Dashboard */ +.admin-orders, +.admin-menu { + display: flex; + flex-wrap: wrap; + justify-content: space-around; + max-width: 1024px; +} + +.order-card_admin-actions { + margin-bottom: -20px; +} + +.order-card_admin-actions { + display: flex; + flex-wrap: wrap; +} + +button.accept, +button.reject { + border-radius: 0; + width: 50%; +} + +button.accept { + background: #2a9971; + border-bottom-left-radius: 4px; +} + +button.reject { + background: #b82e33; + border-bottom-right-radius: 4px; +} + +button.done, +button.disabled { + background: #333; + border-radius: 0 0 4px 4px; + width: 100%; +} + +button.disabled { + background: #aaa; + cursor: not-allowed; +} + +button.accept:hover, +button.reject:hover, +button.done:hover { + opacity: 0.8; +} + +/* Footer */ +footer { + display: flex; + justify-content: space-between; + padding: 15px 30px; +} + +/* Media Queries */ +@media only screen and (max-width: 720px) { + body { + font-size: 16px; + } + + header { + align-items: baseline; + } + + nav ul { + display: none; + } + + nav a { + font-size: 14px; + } + + nav ul.open { + display: flex; + flex-direction: column; + } + + .nav-mobile { + display: block; + } +} + +@media only screen and (max-width: 480px) { + img.food { + width: 300px; + } } diff --git a/src/index.html b/src/index.html index 1db6d55..aaebc60 100644 --- a/src/index.html +++ b/src/index.html @@ -3,6 +3,10 @@ + KiaKiaFood diff --git a/src/tests/components/HomePage.test.jsx b/src/tests/components/HomePage.test.jsx index 5234951..c1a9929 100644 --- a/src/tests/components/HomePage.test.jsx +++ b/src/tests/components/HomePage.test.jsx @@ -1,10 +1,29 @@ import React from 'react'; -import { shallow } from 'enzyme'; import HomePage from '../../components/HomePage'; +import { mountWrap, shallowWrap } from '../helpers/contextWrapper'; describe('HomePage component', () => { + const wrappedShallow = () => shallowWrap(); + const wrappedMount = () => mountWrap(); it('should render homepage correctly', () => { - const wrapper = shallow(); - expect(wrapper).toMatchSnapshot(); + expect(wrappedShallow()).toMatchSnapshot(); + }); + + it('should show login and sign up links', () => { + const wrapper = wrappedMount(); + const navLinks = wrapper.find('nav ul li'); + const loginLink = navLinks.first().text(); + const signupLink = navLinks.last().text(); + + expect(navLinks).toHaveLength(2); + expect(loginLink).toEqual('Log In'); + expect(signupLink).toEqual('Sign Up'); + }); + + it('should should button to get food', () => { + const wrapper = wrappedMount(); + const getFoodButton = wrapper.find('button'); + + expect(getFoodButton.text()).toEqual('Get Food ⟶'); }); }); diff --git a/src/tests/components/__snapshots__/HomePage.test.jsx.snap b/src/tests/components/__snapshots__/HomePage.test.jsx.snap index d1562ad..b2f023f 100644 --- a/src/tests/components/__snapshots__/HomePage.test.jsx.snap +++ b/src/tests/components/__snapshots__/HomePage.test.jsx.snap @@ -2,6 +2,24 @@ exports[`HomePage component should render homepage correctly 1`] = `
- This is the HomePage! +
`; diff --git a/src/tests/helpers/contextWrapper.js b/src/tests/helpers/contextWrapper.js new file mode 100644 index 0000000..04ce86e --- /dev/null +++ b/src/tests/helpers/contextWrapper.js @@ -0,0 +1,20 @@ +import { BrowserRouter } from 'react-router-dom'; +import { shallow, mount } from 'enzyme'; +import { shape } from 'prop-types'; + +// Instantiate router context +const router = { + history: new BrowserRouter().history, + route: { + location: {}, + match: {}, + }, +}; + +const createContext = () => ({ + context: { router }, + childContextTypes: { router: shape({}) }, +}); + +export const mountWrap = node => mount(node, createContext()); +export const shallowWrap = node => shallow(node, createContext());