![]()
({
order: selectOrder(state),
error: selectRestaurantsListError(state),
isLoading: selectIsLoading(state),
+ altData: selectAltDataModal(state),
});
-const mapDispatchToProps = dispatch => ({
- deleteOrder: () => {
- dispatch(setModalWindow(false));
- dispatch(setOrder(null));
- },
-});
+const mapDispatchToProps = {
+ hideModalWindow,
+};
const Enhanced = connect(
mapStateToProps,
diff --git a/src/components/OrderCustomizationsOptions/OrderCustomizationsOptions.js b/src/components/OrderCustomizationsOptions/OrderCustomizationsOptions.js
new file mode 100644
index 0000000..9398a3c
--- /dev/null
+++ b/src/components/OrderCustomizationsOptions/OrderCustomizationsOptions.js
@@ -0,0 +1,24 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+
+import './OrderCustomizationsOptions.scss';
+
+export const OrderCustomizationsOptions = ({ option }) => {
+ const { title, uuid } = option;
+
+ return (
+
+ );
+};
+
+OrderCustomizationsOptions.propTypes = {
+ option: PropTypes.arrayOf(PropTypes.shape({
+ title: PropTypes.string,
+ uuid: PropTypes.string,
+ })).isRequired,
+};
diff --git a/src/components/OrderCustomizationsOptions/OrderCustomizationsOptions.scss b/src/components/OrderCustomizationsOptions/OrderCustomizationsOptions.scss
new file mode 100644
index 0000000..9425da4
--- /dev/null
+++ b/src/components/OrderCustomizationsOptions/OrderCustomizationsOptions.scss
@@ -0,0 +1,72 @@
+@import '../../styles/utils.scss';
+
+.option {
+ height: 48px;
+
+ display: flex;
+ align-items: center;
+
+ &__checkbox {
+ display: flex;
+
+ &-title {
+ display: flex;
+ position: relative;
+
+ font-size: 12px;
+ line-height: 21px;
+
+ &::before {
+ content: "";
+ display: inline-block;
+
+ height: 22px;
+ width: 22px;
+
+ margin-right: 14px;
+
+ border: 1px solid #d3d3d3;
+ }
+
+ &::after {
+ content: "";
+ display: inline-block;
+ height: 8px;
+ width: 12px;
+
+ position: absolute;
+ left: 5px;
+ top: 4px;
+
+ border-left: 2px solid #fff;
+ border-bottom: 2px solid #fff;
+
+ transform: rotate(-45deg);
+ }
+ }
+
+ &-input {
+ opacity: 0;
+
+ -moz-appearance: none;
+ -webkit-appearance: none;
+ }
+
+ &-input + &-title::after {
+ content: none;
+ }
+
+ &-input:checked + &-title::after {
+ content: "";
+ }
+
+ &-input:checked + &-title::before {
+ background: $color-green;
+ }
+
+ &-input:focus + &-title::before {
+ outline: $color-green auto 5px;
+ }
+ }
+
+}
diff --git a/src/components/OrderCustomizationsOptions/index.js b/src/components/OrderCustomizationsOptions/index.js
new file mode 100644
index 0000000..ca85945
--- /dev/null
+++ b/src/components/OrderCustomizationsOptions/index.js
@@ -0,0 +1 @@
+export * from './OrderCustomizationsOptions';
diff --git a/src/components/OrderCustomizationsSection/OrderCustomizationsSection.js b/src/components/OrderCustomizationsSection/OrderCustomizationsSection.js
new file mode 100644
index 0000000..f79e244
--- /dev/null
+++ b/src/components/OrderCustomizationsSection/OrderCustomizationsSection.js
@@ -0,0 +1,38 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+
+import { OrderCustomizationsOptions } from '../OrderCustomizationsOptions';
+
+import './OrderCustomizationsSection.scss';
+
+export const OrderCustomizationsSection = ({ customizations }) => {
+ const { title, maxPermitted, options } = customizations;
+ const maxCount = maxPermitted || 1;
+
+ return (
+
+
+
+
+ {title}
+
+
+ {`Choose up to ${maxCount}`}
+
+
+
+
+
+
+ {options.map(
+ item =>
+ )}
+
+
+
+ );
+};
+
+OrderCustomizationsSection.propTypes = {
+ customizations: PropTypes.arrayOf(PropTypes.shape()).isRequired,
+};
diff --git a/src/components/OrderCustomizationsSection/OrderCustomizationsSection.scss b/src/components/OrderCustomizationsSection/OrderCustomizationsSection.scss
new file mode 100644
index 0000000..e4bcd2a
--- /dev/null
+++ b/src/components/OrderCustomizationsSection/OrderCustomizationsSection.scss
@@ -0,0 +1,22 @@
+.customizations-sections {
+ &__head {
+ background: #f5f5f5;
+ padding: 17px 0;
+ }
+
+ &__title {
+ font-size: 18px;
+ font-weight: 500;
+ line-height: 21px;
+ }
+
+ &__count {
+ font-size: 14px;
+ line-height: 21px;
+ color: #757575;
+ }
+
+ &__options {
+ padding: 12px 0;
+ }
+}
diff --git a/src/components/OrderCustomizationsSection/index.js b/src/components/OrderCustomizationsSection/index.js
new file mode 100644
index 0000000..3ba4d91
--- /dev/null
+++ b/src/components/OrderCustomizationsSection/index.js
@@ -0,0 +1 @@
+export * from './OrderCustomizationsSection';
diff --git a/src/components/OrderFooter/OrderFooter.js b/src/components/OrderFooter/OrderFooter.js
new file mode 100644
index 0000000..e177fa1
--- /dev/null
+++ b/src/components/OrderFooter/OrderFooter.js
@@ -0,0 +1,74 @@
+import React, { useState } from 'react';
+import PropTypes from 'prop-types';
+
+import './OrderFooter.scss';
+
+export const OrderFooter = ({
+ hideModalWindow,
+ orderAmount,
+ currencyCode,
+ altPrice,
+}) => {
+ const [countItem, changeCountItem] = useState(1);
+ const totalAmount = orderAmount || altPrice;
+
+ return (
+ <>
+
+
+ Quantity
+
+

{
+ if (countItem > 1) {
+ changeCountItem(countItem - 1);
+ }
+ }}
+ onKeyPress={() => changeCountItem(countItem + 1)}
+ role="presentation"
+ />
+
{countItem}
+

changeCountItem(countItem + 1)}
+ onKeyPress={() => changeCountItem(countItem + 1)}
+ role="presentation"
+ />
+
+
+ >
+ );
+};
+
+OrderFooter.propTypes = {
+ hideModalWindow: PropTypes.func.isRequired,
+ orderAmount: PropTypes.number.isRequired,
+ currencyCode: PropTypes.string.isRequired,
+ altPrice: PropTypes.number,
+};
+
+OrderFooter.defaultProps = {
+ altPrice: 0,
+};
diff --git a/src/components/OrderFooter/OrderFooter.scss b/src/components/OrderFooter/OrderFooter.scss
new file mode 100644
index 0000000..b548d9f
--- /dev/null
+++ b/src/components/OrderFooter/OrderFooter.scss
@@ -0,0 +1,89 @@
+@import '../../styles/utils.scss';
+
+.counter {
+ display: flex;
+ align-items: center;
+
+ @media (max-width: $breack-point-phone) {
+ margin-bottom: 20px;
+ }
+
+ &__mobile {
+ display: none;
+ @media (max-width: $breack-point-phone) {
+ display: inline;
+ margin-right: auto;
+ }
+ }
+
+ &__button {
+
+ border-radius: 50%;
+
+ transition: box-shadow 300ms;
+
+ margin-right: 17px;
+
+ @media (max-width: $breack-point-phone) {
+ &:not(:last-of-type) {
+ margin-right: 26px;
+ }
+
+ &:last-of-type {
+ margin-right: 0;
+ }
+ }
+
+ &:hover {
+ cursor: pointer;
+ box-shadow: 0 0 10px rgba(0,0,0,0.5);
+ }
+
+ &:active {
+ box-shadow: inset 0 0 10px rgba(0,0,0,0.5);
+ }
+ }
+
+ &__item {
+ margin-right: 17px;
+
+ @media (max-width: $breack-point-phone) {
+ &:not(:last-of-type) {
+ margin-right: 26px;
+ }
+ }
+ }
+}
+
+.button-order {
+ display: flex;
+ justify-content: flex-end;
+
+ height: 55px;
+ width: 100%;
+ background: #247a00;
+ color: #fff;
+
+ font-weight: 500;
+
+ transition: box-shadow 300ms;
+
+ &:hover {
+ cursor: pointer;
+ box-shadow: 0 0 10px rgba(36,122,0, 0.5);
+ }
+
+ &:active {
+ box-shadow: inset 0 0 10px rgba(36,122,0, 0.5);
+ }
+
+ &__amount {
+ margin-right: 16px;
+ display: block;
+ white-space: nowrap;
+ }
+
+ &__wrapper-number {
+ width: 100%;
+ }
+}
diff --git a/src/components/OrderFooter/index.js b/src/components/OrderFooter/index.js
new file mode 100644
index 0000000..2a91dec
--- /dev/null
+++ b/src/components/OrderFooter/index.js
@@ -0,0 +1,21 @@
+import { connect } from 'react-redux';
+
+import { OrderFooter } from './OrderFooter';
+import { hideModalWindow } from '../../store/actions';
+import { selectOrderAmount, selectCurencyCode } from '../../store/selector';
+
+const mapStateToProps = state => ({
+ orderAmount: selectOrderAmount(state),
+ currencyCode: selectCurencyCode(state),
+});
+
+const mapDispatchToProps = {
+ hideModalWindow,
+};
+
+const Enhanced = connect(
+ mapStateToProps,
+ mapDispatchToProps
+)(OrderFooter);
+
+export { Enhanced as OrderFooter };
diff --git a/src/store/actions.js b/src/store/actions.js
index a0d89aa..d72bc9c 100644
--- a/src/store/actions.js
+++ b/src/store/actions.js
@@ -8,6 +8,7 @@ export const ACTION_TYPES = {
STOP_LOADING: 'STOP_LOADING',
SET_ORDER: 'SET_ORDER',
SET_MODAL_WINDOW: 'SET_MODAL_WINDOW',
+ SET_ALT_DATA_MODAL_WINDOW: 'SET_ALT_DATA_MODAL_WINDOW',
};
const saveRestaurants = data => ({
@@ -33,16 +34,27 @@ const stopLoading = () => ({
type: ACTION_TYPES.STOP_LOADING,
});
-export const setOrder = uuid => ({
+const setOrder = uuid => ({
type: ACTION_TYPES.SET_ORDER,
payload: uuid,
});
-export const setModalWindow = bool => ({
+const setModalWindow = bool => ({
type: ACTION_TYPES.SET_MODAL_WINDOW,
payload: bool,
});
+export const setAltDataModalWindow = data => ({
+ type: ACTION_TYPES.SET_ALT_DATA_MODAL_WINDOW,
+ payload: data,
+});
+
+export const hideModalWindow = () => (dispatch) => {
+ dispatch(setModalWindow(false));
+ dispatch(setOrder(null));
+ dispatch(setRestaurantsError(null));
+};
+
export const loadRestaurants = () => (dispatch) => {
dispatch(startLoading());
fetch(`${BASE_URL}restaurants/`)
diff --git a/src/store/rootReducer.js b/src/store/rootReducer.js
index 1893864..7f7c335 100644
--- a/src/store/rootReducer.js
+++ b/src/store/rootReducer.js
@@ -7,6 +7,13 @@ const initialState = {
error: null,
order: null,
showModalWindow: false,
+ orderAmount: 0,
+ altDataModalWindow: {
+ title: '',
+ imageUrl: '',
+ itemDescription: '',
+ price: 0,
+ },
};
export function rootReducer(state = initialState, action) {
@@ -39,7 +46,6 @@ export function rootReducer(state = initialState, action) {
...state,
error: payload,
restaurantsListData: null,
- restaurantPage: null,
order: null,
});
}
@@ -60,10 +66,12 @@ export function rootReducer(state = initialState, action) {
case ACTION_TYPES.SET_ORDER: {
const { payload } = action;
+ const price = payload ? payload.price : 0;
return ({
...state,
order: payload,
+ orderAmount: price,
});
}
@@ -76,6 +84,15 @@ export function rootReducer(state = initialState, action) {
});
}
+ case ACTION_TYPES.SET_ALT_DATA_MODAL_WINDOW: {
+ const { payload } = action;
+
+ return ({
+ ...state,
+ altDataModalWindow: payload,
+ });
+ }
+
default:
return state;
}
diff --git a/src/store/selector.js b/src/store/selector.js
index 5330065..617d083 100644
--- a/src/store/selector.js
+++ b/src/store/selector.js
@@ -92,3 +92,24 @@ export const selectStateModalWindow = createSelector(
rootSelector,
({ showModalWindow }) => showModalWindow
);
+
+export const selectOrderAmount = createSelector(
+ rootSelector,
+ ({ orderAmount }) => orderAmount
+);
+
+export const selectCurencyCode = createSelector(
+ rootSelector,
+ ({ restaurantPageData }) => {
+ if (!restaurantPageData) {
+ return [];
+ }
+
+ return restaurantPageData.currencyCode;
+ }
+);
+
+export const selectAltDataModal = createSelector(
+ rootSelector,
+ ({ altDataModalWindow }) => altDataModalWindow
+);