Зато у нас можно подкрепиться вкусными бургерами
); -} \ No newline at end of file +} diff --git a/src/services/actions/ingredients.js b/src/services/actions/ingredients.js index 2dcbc57..d021872 100644 --- a/src/services/actions/ingredients.js +++ b/src/services/actions/ingredients.js @@ -8,7 +8,7 @@ import { GET_ORDER_FAILED } from '../../utils/constants'; import { getAccessToken, getCookie, setCookie } from "../../utils/cookie"; - import { getUserRequest, refreshTokenRequest } from "../../utils/api"; + import { refreshTokenRequest } from "../../utils/api"; export function getIngredients() { return function(dispatch) { diff --git a/src/utils/TIngredient.tsx b/src/utils/TIngredient.tsx new file mode 100644 index 0000000..916c899 --- /dev/null +++ b/src/utils/TIngredient.tsx @@ -0,0 +1,16 @@ +type TIngredient = { + _id: string; + name: string; + type: string; + proteins: number; + fat: number; + carbohydrates: number; + calories: number; + price: number; + image: string; + image_mobile: string; + image_large: string; + __v?: number; +}; + +export default TIngredient; diff --git a/src/utils/constants.js b/src/utils/constants.js deleted file mode 100644 index 982d55e..0000000 --- a/src/utils/constants.js +++ /dev/null @@ -1,81 +0,0 @@ -const BASEURL = 'https://norma.nomoreparties.space/api'; -export const GETINGREDIENTSURL = BASEURL + '/ingredients'; -export const SAVEORDERURL = BASEURL + '/orders'; -export const ADDUSERURL = BASEURL + '/auth/register'; -export const LOGINUSERURL = BASEURL + '/auth/login'; -export const LOGOUTUSERURL = BASEURL + '/auth/logout'; -export const REFRESHTOKENURL = BASEURL + '/auth/token'; -export const USERURL = BASEURL + '/auth/user'; -export const PASSWORDFORGOTURL = BASEURL + '/password-reset'; -export const PASSWORDRESETURL = BASEURL + '/password-reset/reset'; - -export const WSURL = 'wss://norma.nomoreparties.space'; -export const GET_ALL_ORDERS_URL = WSURL + '/orders/all'; -export const GET_USER_ORDERS_URL = WSURL + '/orders'; -export const WS_STATUS = { - CONNECTING : 'CONNECTING...', - ONLINE : 'ONLINE', - OFFLINE : 'OFFLINE' -} -export const WS_MESSAGE = 'WS_MESSAGE'; - -// Константы для обработки запроса для получения всех ингридиентов -export const GET_INGREDIENTS_REQUEST = 'GET_INGREDIENTS_REQUEST'; -export const GET_INGREDIENTS_SUCCESS = 'GET_INGREDIENTS_SUCCESS'; -export const GET_INGREDIENTS_FAILED = 'GET_INGREDIENTS_FAILED'; - -// Константы для обработки запроса оформления заказа -export const GET_ORDER_REQUEST = 'GET_ORDER_REQUEST'; -export const GET_ORDER_SUCCESS = 'GET_ORDER_SUCCESS'; -export const GET_ORDER_FAILED = 'GET_ORDER_FAILED'; - -// Константы для получения/удаления данных об отдельном ингридиенте -export const SHOW_INGREDIENT = 'SHOW_INGREDIENT'; -export const HIDE_INGREDIENT = 'HIDE_INGREDIENT'; - -// Константы для добавления ингридиента в конструктор бургера -export const ADD_INGREDIENT = 'ADD_INGREDIENT'; -export const DELETE_INGREDIENT = 'DELETE_INGREDIENT'; -export const ADD_BUN = 'ADD_BUN'; - -// Константы для сортировки ингридиентов бургера -export const CHANGE_INGREDIENT_ORDER = 'CHANGE_INGREDIENT_ORDER'; - -// Константа для изменения активного таба -export const SET_ACTIVE_TAB = 'SET_ACTIVE_TAB'; - -// Константы для обработки запроса получения данных о пользователе -export const SET_REGISTER_FORM_VALUE = 'SET_REGISTER_FORM_VALUE'; -export const SET_EDIT_USER_FORM = 'SET_EDIT_USER_FORM'; - -export const ADD_USER_REQUEST = 'ADD_USER_REQUEST'; -export const ADD_USER_SUCCESS = 'ADD_USER_SUCCESS'; -export const ADD_USER_FAILED = 'ADD_USER_FAILED'; - -export const LOGIN_USER_REQUEST = 'LOGIN_USER_REQUEST'; -export const LOGIN_USER_SUCCESS = 'LOGIN_USER_SUCCESS'; -export const LOGIN_USER_FAILED = 'LOGIN_USER_FAILED'; - -export const LOGOUT_USER_SUCCESS = 'LOGOUT_USER_SUCCESS'; -export const LOGOUT_USER_FAILED = 'LOGOUT_USER_FAILED'; - -export const GET_USER_SUCCESS = 'GET_USER_SUCCESS'; -export const GET_USER_FAILED = 'GET_USER_FAILED'; - -export const EDIT_USER_SUCCESS = 'EDIT_USER_SUCCESS'; -export const EDIT_USER_FAILED = 'EDIT_USER_FAILED'; -export const RESET_EDIT_USER_FORM = 'RESET_EDIT_USER_FORM'; - -export const FORGOT_PASSWORD_SUCCESS = 'FORGOT_PASSWORD_SUCCESS'; -export const FORGOT_PASSWORD_FAILED = 'FORGOT_PASSWORD_FAILED'; - -export const RESET_PASSWORD_SUCCESS = 'RESET_PASSWORD_SUCCESS'; -export const RESET_PASSWORD_FAILED = 'RESET_PASSWORD_FAILED'; - -export const GET_USER_ORDERS = 'GET_USER_ORDERS'; - -export const ORDER_STATUSES = { - done: 'Выполнен', - cancelled: 'Отменён', - progress: 'Готовится' -} diff --git a/src/utils/constants.tsx b/src/utils/constants.tsx new file mode 100644 index 0000000..0fdfb4f --- /dev/null +++ b/src/utils/constants.tsx @@ -0,0 +1,81 @@ +const BASEURL = 'https://norma.nomoreparties.space/api'; +export const GETINGREDIENTSURL = BASEURL + '/ingredients'; +export const SAVEORDERURL = BASEURL + '/orders'; +export const ADDUSERURL = BASEURL + '/auth/register'; +export const LOGINUSERURL = BASEURL + '/auth/login'; +export const LOGOUTUSERURL = BASEURL + '/auth/logout'; +export const REFRESHTOKENURL = BASEURL + '/auth/token'; +export const USERURL = BASEURL + '/auth/user'; +export const PASSWORDFORGOTURL = BASEURL + '/password-reset'; +export const PASSWORDRESETURL = BASEURL + '/password-reset/reset'; + +export const WSURL = 'wss://norma.nomoreparties.space'; +export const GET_ALL_ORDERS_URL = WSURL + '/orders/all'; +export const GET_USER_ORDERS_URL = WSURL + '/orders'; +export const WS_STATUS = { + CONNECTING : 'CONNECTING...', + ONLINE : 'ONLINE', + OFFLINE : 'OFFLINE' +} +export const WS_MESSAGE: 'WS_MESSAGE' = 'WS_MESSAGE'; + +// Константы для обработки запроса для получения всех ингридиентов +export const GET_INGREDIENTS_REQUEST: 'GET_INGREDIENTS_REQUEST' = 'GET_INGREDIENTS_REQUEST'; +export const GET_INGREDIENTS_SUCCESS: 'GET_INGREDIENTS_SUCCESS' = 'GET_INGREDIENTS_SUCCESS'; +export const GET_INGREDIENTS_FAILED: 'GET_INGREDIENTS_FAILED' = 'GET_INGREDIENTS_FAILED'; + +// Константы для обработки запроса оформления заказа +export const GET_ORDER_REQUEST: 'GET_ORDER_REQUEST'= 'GET_ORDER_REQUEST'; +export const GET_ORDER_SUCCESS: 'GET_ORDER_SUCCESS' = 'GET_ORDER_SUCCESS'; +export const GET_ORDER_FAILED: 'GET_ORDER_FAILED' = 'GET_ORDER_FAILED'; + +// Константы для получения/удаления данных об отдельном ингридиенте +export const SHOW_INGREDIENT: 'SHOW_INGREDIENT' = 'SHOW_INGREDIENT'; +export const HIDE_INGREDIENT: 'HIDE_INGREDIENT' = 'HIDE_INGREDIENT'; + +// Константы для добавления ингридиента в конструктор бургера +export const ADD_INGREDIENT: 'ADD_INGREDIENT' = 'ADD_INGREDIENT'; +export const DELETE_INGREDIENT: 'DELETE_INGREDIENT' = 'DELETE_INGREDIENT'; +export const ADD_BUN: 'ADD_BUN' = 'ADD_BUN'; + +// Константы для сортировки ингридиентов бургера +export const CHANGE_INGREDIENT_ORDER: 'CHANGE_INGREDIENT_ORDER' = 'CHANGE_INGREDIENT_ORDER'; + +// Константа для изменения активного таба +export const SET_ACTIVE_TAB: 'SET_ACTIVE_TAB' = 'SET_ACTIVE_TAB'; + +// Константы для обработки запроса получения данных о пользователе +export const SET_REGISTER_FORM_VALUE: 'SET_REGISTER_FORM_VALUE' = 'SET_REGISTER_FORM_VALUE'; +export const SET_EDIT_USER_FORM: 'SET_EDIT_USER_FORM' = 'SET_EDIT_USER_FORM'; + +export const ADD_USER_REQUEST: 'ADD_USER_REQUEST' = 'ADD_USER_REQUEST'; +export const ADD_USER_SUCCESS: 'ADD_USER_SUCCESS' = 'ADD_USER_SUCCESS'; +export const ADD_USER_FAILED: 'ADD_USER_FAILED' = 'ADD_USER_FAILED'; + +export const LOGIN_USER_REQUEST: 'LOGIN_USER_REQUEST' = 'LOGIN_USER_REQUEST'; +export const LOGIN_USER_SUCCESS: 'LOGIN_USER_SUCCESS' = 'LOGIN_USER_SUCCESS'; +export const LOGIN_USER_FAILED: 'LOGIN_USER_FAILED' = 'LOGIN_USER_FAILED'; + +export const LOGOUT_USER_SUCCESS: 'LOGOUT_USER_SUCCESS' = 'LOGOUT_USER_SUCCESS'; +export const LOGOUT_USER_FAILED: 'LOGOUT_USER_FAILED' = 'LOGOUT_USER_FAILED'; + +export const GET_USER_SUCCESS: 'GET_USER_SUCCESS' = 'GET_USER_SUCCESS'; +export const GET_USER_FAILED: 'GET_USER_FAILED' = 'GET_USER_FAILED'; + +export const EDIT_USER_SUCCESS: 'EDIT_USER_SUCCESS' = 'EDIT_USER_SUCCESS'; +export const EDIT_USER_FAILED: 'EDIT_USER_FAILED' = 'EDIT_USER_FAILED'; +export const RESET_EDIT_USER_FORM: 'RESET_EDIT_USER_FORM' = 'RESET_EDIT_USER_FORM'; + +export const FORGOT_PASSWORD_SUCCESS: 'FORGOT_PASSWORD_SUCCESS' = 'FORGOT_PASSWORD_SUCCESS'; +export const FORGOT_PASSWORD_FAILED: 'FORGOT_PASSWORD_FAILED' = 'FORGOT_PASSWORD_FAILED'; + +export const RESET_PASSWORD_SUCCESS: 'RESET_PASSWORD_SUCCESS' = 'RESET_PASSWORD_SUCCESS'; +export const RESET_PASSWORD_FAILED: 'RESET_PASSWORD_FAILED' = 'RESET_PASSWORD_FAILED'; + +export const GET_USER_ORDERS: 'GET_USER_ORDERS' = 'GET_USER_ORDERS'; + +export const ORDER_STATUSES = { + done: 'Выполнен', + cancelled: 'Отменён', + progress: 'Готовится' +} diff --git a/src/utils/propTypes.js b/src/utils/propTypes.js deleted file mode 100644 index 0954f1f..0000000 --- a/src/utils/propTypes.js +++ /dev/null @@ -1,18 +0,0 @@ -import PropTypes from 'prop-types'; - -const ingredientsPropTypes = PropTypes.shape({ - _id: PropTypes.string.isRequired, - name: PropTypes.string.isRequired, - type: PropTypes.string.isRequired, - proteins:PropTypes.number, - fat: PropTypes.number, - carbohydrates: PropTypes.number, - calories: PropTypes.number, - price: PropTypes.number.isRequired, - image: PropTypes.string.isRequired, - image_mobile: PropTypes.string.isRequired, - image_large: PropTypes.string.isRequired, - __v: PropTypes.number -}); - -export default ingredientsPropTypes; diff --git a/tsconfig.json b/tsconfig.json index a273b0c..34bbca6 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,6 +1,6 @@ { "compilerOptions": { - "target": "es5", + "target": "ESNext", "lib": [ "dom", "dom.iterable", From 428265899933adc90429ef959bd875cf97af5152 Mon Sep 17 00:00:00 2001 From: Yulia Berezhnaya
- {data.map((item) => {
+ {data?.map((item) => {
return ({
type: SEND_ORDER_FAILED
});
+// Типизация других действий с ингридиентами
+interface IShowIngredient {
+ readonly type: typeof SHOW_INGREDIENT;
+ id: string;
+}
+
+interface IHideIngredient {
+ readonly type: typeof HIDE_INGREDIENT;
+}
+
+interface IAddIngredient {
+ readonly type: typeof ADD_INGREDIENT;
+ id: string;
+}
+
+interface IDeleteIngredient {
+ readonly type: typeof DELETE_INGREDIENT;
+ index: number;
+}
+
+interface IAddBun {
+ readonly type: typeof ADD_BUN;
+ id: string;
+}
+
+interface IChangeOrderIngredients {
+ readonly type: typeof CHANGE_INGREDIENT_ORDER;
+ prevIndex: number;
+ newIndex: number;
+}
+
+interface ISetActiveTab {
+ readonly type: typeof SET_ACTIVE_TAB;
+ name: string;
+}
+export type TIngredientsAction =
+ IGetIngredientsAction
+ | IGetCountriesSuccessAction
+ | IGetIngredientsFailedAction
+ | ISendOrderAction
+ | ISendOrderSuccessAction
+ | ISendOrderFailedAction
+ | IShowIngredient
+ | IHideIngredient
+ | IAddIngredient
+ | IDeleteIngredient
+ | IAddBun
+ | IChangeOrderIngredients
+ | ISetActiveTab;
export function getIngredients() {
return function(dispatch: any) {
diff --git a/src/services/actions/ws.js b/src/services/actions/ws.js
deleted file mode 100644
index 3a2be81..0000000
--- a/src/services/actions/ws.js
+++ /dev/null
@@ -1,36 +0,0 @@
-import { createAction } from '@reduxjs/toolkit';
-import { refreshTokenRequest } from '../../utils/api';
-import { setCookie, getCookie, getAccessToken } from '../../utils/cookie';
-import { GET_USER_ORDERS_URL, WS_MESSAGE } from '../../utils/constants';
-
-
-export const wsConnect = createAction('WS_CONNECT');
-export const wsDisconnect = createAction('WS_DISCONNECT');
-export const wsConnecting = createAction('WS_CONNECTING');
-export const wsOpen = createAction('WS_OPEN');
-export const wsClose = createAction('WS_CLOSE');
-export const wsError = createAction('WS_ERROR');
-
-export const wsMessage = (action) => (dispatch) => {
-
- dispatch({type: WS_MESSAGE, payload: action});
-
- if (action.message === 'Invalid or missing token') {
- dispatch(wsDisconnect());
- refreshTokenRequest(getCookie('token'))
- .then((res) => {
- if (res && res.success) {
- setCookie('accessToken', getAccessToken(res.accessToken));
- setCookie('token', res.refreshToken);
-
- dispatch(wsConnect(`${GET_USER_ORDERS_URL}?token=${getCookie('accessToken')}`));
- } else {
- throw new Error('Произошла ошибка ', res.message);
- }
-
- })
- .catch((err) => {
- console.log('error!', err);
- });
- }
-}
diff --git a/src/services/actions/ws.tsx b/src/services/actions/ws.tsx
new file mode 100644
index 0000000..f01f912
--- /dev/null
+++ b/src/services/actions/ws.tsx
@@ -0,0 +1,103 @@
+import { createAction } from '@reduxjs/toolkit';
+import { refreshTokenRequest } from '../../utils/api';
+import { setCookie, getCookie, getAccessToken } from '../../utils/cookie';
+import {
+ GET_USER_ORDERS_URL,
+ WS_MESSAGE,
+ WS_CONNECT,
+ WS_DISCONNECT,
+ WS_CONNECTING,
+ WS_OPEN,
+ WS_CLOSE,
+ WS_ERROR
+} from '../../utils/constants';
+import { TOrder } from '../../utils/orderTypes';
+
+function withPayloadType() {
+ return (t: T) => ({ payload: t })
+}
+export const wsConnect = createAction(WS_CONNECT, withPayloadType());
+export const wsDisconnect = createAction(WS_DISCONNECT);
+export const wsConnecting = createAction(WS_CONNECTING);
+export const wsOpen = createAction(WS_OPEN);
+export const wsClose = createAction(WS_CLOSE);
+export const wsError = createAction(WS_ERROR);
+
+export interface IWSMessage {
+ success: boolean;
+ message?: string;
+ orders?: Array;
+}
+
+interface IWSMessageAction {
+ readonly type: typeof WS_MESSAGE;
+ payload: IWSMessage;
+}
+
+interface IWSErrorAction {
+ readonly type: typeof WS_ERROR;
+ payload: IWSMessage;
+}
+
+interface IWSOpenAction {
+ readonly type: typeof WS_OPEN;
+ payload: IWSMessage;
+}
+
+interface IWSCloseAction {
+ readonly type: typeof WS_CLOSE;
+ payload: IWSMessage;
+}
+
+interface IWSConnectingAction {
+ readonly type: typeof WS_CONNECTING;
+ payload: IWSMessage;
+}
+
+interface IWSConnectAction {
+ readonly type: typeof WS_CONNECT;
+ payload: IWSMessage;
+}
+
+interface IWSDisconnectAction {
+ readonly type: typeof WS_DISCONNECT;
+ payload: IWSMessage;
+}
+
+const wsMessageAction = (payload: IWSMessage): IWSMessageAction => ({
+ type: WS_MESSAGE,
+ payload
+});
+
+export type TWSAction =
+ IWSMessageAction
+ | IWSErrorAction
+ | IWSOpenAction
+ | IWSCloseAction
+ | IWSConnectingAction
+ | IWSConnectAction
+ | IWSDisconnectAction;
+
+export const wsMessage = (action: IWSMessage) => (dispatch: any) => {
+
+ dispatch(wsMessageAction(action));
+
+ if (action.message === 'Invalid or missing token') {
+ dispatch(wsDisconnect());
+ refreshTokenRequest(getCookie('token'))
+ .then((res) => {
+ if (res && res.success) {
+ setCookie('accessToken', getAccessToken(res.accessToken));
+ setCookie('token', res.refreshToken);
+
+ dispatch(wsConnect(`${GET_USER_ORDERS_URL}?token=${getCookie('accessToken')}`));
+ } else {
+ throw new Error('Произошла ошибка ', res.message);
+ }
+
+ })
+ .catch((err) => {
+ console.log('error!', err);
+ });
+ }
+}
diff --git a/src/services/reducers/index.js b/src/services/reducers/index.tsx
similarity index 80%
rename from src/services/reducers/index.js
rename to src/services/reducers/index.tsx
index c079b69..dd846f9 100644
--- a/src/services/reducers/index.js
+++ b/src/services/reducers/index.tsx
@@ -15,11 +15,33 @@ import {
ADD_BUN,
CHANGE_INGREDIENT_ORDER,
SET_ACTIVE_TAB
- } from '../../utils/constants';
+} from '../../utils/constants';
+import { TIngredientsByType, TIngredientsById } from '../../utils/ingredientsTypes';
+import { TIngredientsAction } from '../actions/ingredients';
-const initialMenuState = {
- ingredientsByType: null,
- ingredientsById: null,
+type TMenuState = {
+ ingredientsByType: TIngredientsByType ,
+ ingredientsById: TIngredientsById,
+ ingredientsRequest: boolean,
+ ingredientsFailed: boolean,
+
+ addedIngredients: {
+ bun: string| null,
+ others: Array
+ },
+ currentIngredient: string | null,
+
+ activeTab: 'bun' | 'main' | 'sauce',
+
+ orderId: number | null,
+ orderRequest: boolean,
+ orderFailed: boolean
+}
+
+
+const initialMenuState: TMenuState = {
+ ingredientsByType: {},
+ ingredientsById: {},
ingredientsRequest: false,
ingredientsFailed: false,
@@ -37,7 +59,8 @@ const initialMenuState = {
}
let uniqId = 0;
-export const ingredientsReducer = (state = initialMenuState, action) => {
+
+export const ingredientsReducer = (state = initialMenuState, action: TIngredientsAction) => {
switch (action.type) {
case GET_INGREDIENTS_REQUEST: {
return {
@@ -129,10 +152,10 @@ export const ingredientsReducer = (state = initialMenuState, action) => {
}
case CHANGE_INGREDIENT_ORDER: {
const items = state.addedIngredients.others.slice();
- const draggedItem = items.splice(action.prevId, 1)[0];
+ const draggedItem = items.splice(action.prevIndex, 1)[0];
items.splice(
- action.newId,
+ action.newIndex,
0,
draggedItem
);
diff --git a/src/services/reducers/user.js b/src/services/reducers/user.tsx
similarity index 83%
rename from src/services/reducers/user.js
rename to src/services/reducers/user.tsx
index 17d27df..e2564e2 100644
--- a/src/services/reducers/user.js
+++ b/src/services/reducers/user.tsx
@@ -27,9 +27,37 @@ import {
LOGOUT_USER_SUCCESS,
LOGOUT_USER_FAILED,
- GET_USER_ORDERS
- } from '../../utils/constants';
+ // GET_USER_ORDERS
+} from '../../utils/constants';
+import { TUserActions } from '../../utils/userTypes';
+type TUserState = {
+ name: string,
+ email: string,
+ password: string,
+ prevSavedName: string,
+ prevSavedEmail: string,
+ prevSavedPassword: string,
+
+ isAuthSuccess: boolean,
+ isUserLoaded: boolean,
+
+ addUserRequest: boolean,
+ addUserFailed: boolean,
+
+ loginUserRequest: boolean,
+ loginUserFailed: boolean,
+ loginErrorMessage: string,
+
+ logoutError: boolean,
+
+ editUserFailed: boolean,
+ isUserEdited: boolean,
+
+ canResetPassword: boolean,
+ resetPasswordSuccess: boolean,
+ code: number
+}
const initialUserState = {
name: '',
@@ -56,12 +84,12 @@ const initialUserState = {
canResetPassword: false,
resetPasswordSuccess: false,
- code: '',
+ code: 0,
- orders: []
+ // orders: []
}
-export const userReducer = (state = initialUserState, action) => {
+export const userReducer = (state: TUserState = initialUserState, action: TUserActions) => {
switch (action.type) {
case SET_REGISTER_FORM_VALUE: {
@@ -222,12 +250,12 @@ export const userReducer = (state = initialUserState, action) => {
- case GET_USER_ORDERS: {
- return {
- ...state,
- orders: action.action.orders
- }
- }
+ // case GET_USER_ORDERS: {
+ // return {
+ // ...state,
+ // orders: action.action.orders
+ // }
+ // }
default: return state;
diff --git a/src/services/reducers/ws.js b/src/services/reducers/ws.js
deleted file mode 100644
index bce4041..0000000
--- a/src/services/reducers/ws.js
+++ /dev/null
@@ -1,31 +0,0 @@
-import { WS_STATUS, WS_MESSAGE } from '../../utils/constants';
-import { wsClose, wsConnecting, wsError, wsOpen } from '../actions/ws';
-import { createReducer } from '@reduxjs/toolkit';
-
-const initialWSState = {
- status: WS_STATUS.OFFLINE,
- connectionError: '',
- feed: {}
-}
-
-export const wsReducer = createReducer(initialWSState, (builder) => {
-
- builder
- .addCase(wsConnecting, (state) => {
- state.status = WS_STATUS.CONNECTING
- })
- .addCase(wsOpen, (state) => {
- state.status = WS_STATUS.ONLINE;
- state.connectionError = ''
- })
- .addCase(wsClose, (state) => {
- state.status = WS_STATUS.OFFLINE;
- state.connectionError = ''
- })
- .addCase(wsError, (state, action) => {
- state.connectionError = action.payload
- })
- .addCase(WS_MESSAGE, (state, action) => {
- state.feed = action.payload;
- })
-})
diff --git a/src/services/reducers/ws.tsx b/src/services/reducers/ws.tsx
new file mode 100644
index 0000000..ca7583b
--- /dev/null
+++ b/src/services/reducers/ws.tsx
@@ -0,0 +1,32 @@
+import { WS_STATUS, WS_MESSAGE } from '../../utils/constants';
+import { wsClose, wsConnecting, wsError, wsOpen, TWSAction } from '../actions/ws';
+import { createReducer } from '@reduxjs/toolkit';
+import { TWSState } from '../../utils/orderTypes';
+
+const initialWSState: TWSState = {
+ status: WS_STATUS.OFFLINE,
+ connectionError: '',
+ feed: {}
+}
+
+export const wsReducer = createReducer(initialWSState, (builder: any) => {
+
+ builder
+ .addCase(wsConnecting, (state: TWSState) => {
+ state.status = WS_STATUS.CONNECTING
+ })
+ .addCase(wsOpen, (state: TWSState) => {
+ state.status = WS_STATUS.ONLINE;
+ state.connectionError = ''
+ })
+ .addCase(wsClose, (state: TWSState) => {
+ state.status = WS_STATUS.OFFLINE;
+ state.connectionError = ''
+ })
+ .addCase(wsError, (state: TWSState, action: TWSAction) => {
+ state.connectionError = action.payload
+ })
+ .addCase(WS_MESSAGE, (state: TWSState, action: TWSAction) => {
+ state.feed = action.payload;
+ })
+})
diff --git a/src/utils/constants.tsx b/src/utils/constants.tsx
index 6831976..08661c6 100644
--- a/src/utils/constants.tsx
+++ b/src/utils/constants.tsx
@@ -18,6 +18,12 @@ export const WS_STATUS = {
OFFLINE : 'OFFLINE'
}
export const WS_MESSAGE: 'WS_MESSAGE' = 'WS_MESSAGE';
+export const WS_CONNECT: 'WS_CONNECT' = 'WS_CONNECT';
+export const WS_DISCONNECT: 'WS_DISCONNECT' = 'WS_DISCONNECT';
+export const WS_CONNECTING: 'WS_CONNECTING' = 'WS_CONNECTING';
+export const WS_OPEN: 'WS_OPEN' = 'WS_OPEN';
+export const WS_CLOSE: 'WS_CLOSE' = 'WS_CLOSE';
+export const WS_ERROR: 'WS_ERROR' = 'WS_ERROR';
// Константы для обработки запроса для получения всех ингридиентов
export const GET_INGREDIENTS_REQUEST: 'GET_INGREDIENTS_REQUEST' = 'GET_INGREDIENTS_REQUEST';
diff --git a/src/utils/orderTypes.tsx b/src/utils/orderTypes.tsx
new file mode 100644
index 0000000..e09e8ee
--- /dev/null
+++ b/src/utils/orderTypes.tsx
@@ -0,0 +1,25 @@
+import { TIngredient } from "./ingredientsTypes";
+import { IWSMessage } from '../services/actions/ws';
+
+export type TOrder = {
+ _id: string;
+ status: string;
+ name: string;
+ createdAt: Date | string;
+ updatedAt: Date | string;
+ number: number;
+ ingredients: Array
+}
+
+export type TFeedData = {
+ success: boolean;
+ total: number;
+ totalToday: number;
+ orders: Array;
+}
+
+export type TWSState = {
+ status: string;
+ connectionError: string | IWSMessage;
+ feed: TFeedData | {};
+}
diff --git a/src/utils/userTypes.tsx b/src/utils/userTypes.tsx
index df794b1..a860b6b 100644
--- a/src/utils/userTypes.tsx
+++ b/src/utils/userTypes.tsx
@@ -20,7 +20,11 @@ import {
RESET_PASSWORD_FAILED,
LOGOUT_USER_SUCCESS,
- LOGOUT_USER_FAILED
+ LOGOUT_USER_FAILED,
+
+ SET_REGISTER_FORM_VALUE,
+ SET_EDIT_USER_FORM,
+ RESET_EDIT_USER_FORM
} from './constants';
export type TUser = {
@@ -178,3 +182,44 @@ export const logoutUserFailedAction = (errorMessage: string): ILogoutUserFailedA
type: LOGOUT_USER_FAILED,
errorMessage
});
+
+// Типизация экшнов работы с формами
+interface ISetRegisterFormAction {
+ readonly type: typeof SET_REGISTER_FORM_VALUE;
+ [name: string]: string;
+}
+
+type TSetEditFormAction = {
+ readonly type: typeof SET_EDIT_USER_FORM;
+ [name: string]: string;
+} & {
+ isUserEdited: boolean;
+}
+
+interface IResetEditUserFormUserAction {
+ readonly type: typeof RESET_EDIT_USER_FORM;
+ name: string;
+ email: string;
+ password: string;
+}
+
+export type TUserActions =
+ IAddUserAction
+ | IAddUserSuccessAction
+ | IAddUserFailedAction
+ | ILoginUserAction
+ | ILoginUserSuccessAction
+ | ILoginUserFailedAction
+ | IGetUserSuccessAction
+ | IGetUserFailedAction
+ | IEditUserSuccessAction
+ | IEditUserFailedAction
+ | IForgotPasswordSuccessAction
+ | IForgotPasswordFailedAction
+ | IResetPasswordSuccessAction
+ | IResetPasswordFailedAction
+ | ILogoutUserSuccessAction
+ | ILogoutUserFailedAction
+ | ISetRegisterFormAction
+ | TSetEditFormAction
+ | IResetEditUserFormUserAction;
From 7cc598dd06cd8f5f78558b6fe7573bb12f44645e Mon Sep 17 00:00:00 2001
From: Yulia Berezhnaya
Date: Sat, 1 Apr 2023 18:25:13 +0300
Subject: [PATCH 05/13] =?UTF-8?q?=D0=92=20services=20=D0=B2=D1=8B=D0=BD?=
=?UTF-8?q?=D0=B5=D1=81=D0=B5=D0=BD=D1=8B=20store=20=D0=B8=20=D1=82=D0=B8?=
=?UTF-8?q?=D0=BF=D1=8B=20user,=20ingredients=20=D0=B8=20ws?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../IngredientCard/IngredientCard.tsx | 2 +-
src/index.tsx | 26 +------------------
src/services/actions/ingredients.tsx | 2 +-
src/services/actions/user.tsx | 4 +--
src/services/actions/ws.tsx | 2 +-
src/services/reducers/index.tsx | 8 +++---
src/services/reducers/user.tsx | 4 +--
src/services/reducers/ws.tsx | 9 ++++++-
src/services/store.tsx | 24 +++++++++++++++++
src/services/types/index.tsx | 3 +++
.../types/ingredients.tsx} | 0
.../types/order.tsx} | 9 ++-----
.../types/request.tsx} | 2 +-
.../userTypes.tsx => services/types/user.tsx} | 2 +-
src/utils/api.tsx | 4 +--
15 files changed, 53 insertions(+), 48 deletions(-)
create mode 100644 src/services/store.tsx
create mode 100644 src/services/types/index.tsx
rename src/{utils/ingredientsTypes.tsx => services/types/ingredients.tsx} (100%)
rename src/{utils/orderTypes.tsx => services/types/order.tsx} (58%)
rename src/{utils/requestTypes.tsx => services/types/request.tsx} (93%)
rename src/{utils/userTypes.tsx => services/types/user.tsx} (99%)
diff --git a/src/components/IngredientCard/IngredientCard.tsx b/src/components/IngredientCard/IngredientCard.tsx
index 035ef40..825e8cd 100644
--- a/src/components/IngredientCard/IngredientCard.tsx
+++ b/src/components/IngredientCard/IngredientCard.tsx
@@ -1,6 +1,6 @@
import IngredientCardStyles from './IngredientCard.module.css';
-import { TIngredient } from '../../utils/ingredientsTypes';
+import { TIngredient } from '../../services/types/ingredients';
import { FC } from 'react';
import { useDrag } from 'react-dnd';
import { Link, useLocation } from 'react-router-dom';
diff --git a/src/index.tsx b/src/index.tsx
index 44467bb..4964e82 100644
--- a/src/index.tsx
+++ b/src/index.tsx
@@ -3,44 +3,20 @@ import ReactDOM from 'react-dom/client';
import './index.css';
import App from './components/App/App';
import reportWebVitals from './reportWebVitals';
-import { rootReducer } from './services/reducers';
-import { compose, createStore, applyMiddleware } from 'redux';
-import thunk from 'redux-thunk';
import { Provider } from 'react-redux';
import { BrowserRouter } from 'react-router-dom';
-import { socketMiddleware } from './services/middlewares/ws';
-import { wsConnect, wsDisconnect, wsConnecting, wsOpen, wsClose, wsError, wsMessage } from './services/actions/ws';
+import { store } from './services/store';
const root = ReactDOM.createRoot(
document.getElementById('root') as HTMLElement
);
-const composeEnhancers =
- typeof window === 'object' && (window as any)['__REDUX_DEVTOOLS_EXTENSION_COMPOSE__']
- ? (window as any)['__REDUX_DEVTOOLS_EXTENSION_COMPOSE__']({})
- : compose;
-
-const wsActions = {
- wsConnect,
- wsDisconnect,
- wsConnecting,
- onOpen: wsOpen,
- onClose: wsClose,
- onError: wsError,
- onMessage: wsMessage
-}
-const enhancer = composeEnhancers(applyMiddleware(thunk, socketMiddleware(wsActions)));
-
-const store = createStore(rootReducer, enhancer);
-
root.render(
- //
- //
);
// If you want to start measuring performance in your app, pass a function
diff --git a/src/services/actions/ingredients.tsx b/src/services/actions/ingredients.tsx
index 1c4ecc4..39a4b33 100644
--- a/src/services/actions/ingredients.tsx
+++ b/src/services/actions/ingredients.tsx
@@ -14,7 +14,7 @@ import {
CHANGE_INGREDIENT_ORDER,
SET_ACTIVE_TAB
} from '../../utils/constants';
- import { TIngredient, TIngredientsByType, TIngredientsById } from "../../utils/ingredientsTypes";
+ import { TIngredient, TIngredientsByType, TIngredientsById } from "../types/ingredients";
import { getAccessToken, getCookie, setCookie } from "../../utils/cookie";
import { refreshTokenRequest } from "../../utils/api";
diff --git a/src/services/actions/user.tsx b/src/services/actions/user.tsx
index 1c65380..e6c715d 100644
--- a/src/services/actions/user.tsx
+++ b/src/services/actions/user.tsx
@@ -27,13 +27,13 @@ import {
resetPasswordFailedAction,
logoutUserSuccessAction,
logoutUserFailedAction
- } from "../../utils/userTypes";
+ } from "../types/user";
import {
TRequestRetryOptions,
requestRetryOnFail,
requestRetryOnSuccess ,
requestRetry
-} from "../../utils/requestTypes";
+} from "../types/request";
import {
SET_REGISTER_FORM_VALUE,
SET_EDIT_USER_FORM,
diff --git a/src/services/actions/ws.tsx b/src/services/actions/ws.tsx
index f01f912..5178af5 100644
--- a/src/services/actions/ws.tsx
+++ b/src/services/actions/ws.tsx
@@ -11,7 +11,7 @@ import {
WS_CLOSE,
WS_ERROR
} from '../../utils/constants';
-import { TOrder } from '../../utils/orderTypes';
+import { TOrder } from '../types/order';
function withPayloadType() {
return (t: T) => ({ payload: t })
diff --git a/src/services/reducers/index.tsx b/src/services/reducers/index.tsx
index dd846f9..1f09dcf 100644
--- a/src/services/reducers/index.tsx
+++ b/src/services/reducers/index.tsx
@@ -16,17 +16,17 @@ import {
CHANGE_INGREDIENT_ORDER,
SET_ACTIVE_TAB
} from '../../utils/constants';
-import { TIngredientsByType, TIngredientsById } from '../../utils/ingredientsTypes';
+import { TIngredientsByType, TIngredientsById, TIngredient } from '../types/ingredients';
import { TIngredientsAction } from '../actions/ingredients';
-type TMenuState = {
+export type TMenuState = {
ingredientsByType: TIngredientsByType ,
ingredientsById: TIngredientsById,
ingredientsRequest: boolean,
ingredientsFailed: boolean,
addedIngredients: {
- bun: string| null,
+ bun: TIngredient | null,
others: Array
},
currentIngredient: string | null,
@@ -60,7 +60,7 @@ const initialMenuState: TMenuState = {
let uniqId = 0;
-export const ingredientsReducer = (state = initialMenuState, action: TIngredientsAction) => {
+export const ingredientsReducer = (state: TMenuState = initialMenuState, action: TIngredientsAction) => {
switch (action.type) {
case GET_INGREDIENTS_REQUEST: {
return {
diff --git a/src/services/reducers/user.tsx b/src/services/reducers/user.tsx
index e2564e2..4307510 100644
--- a/src/services/reducers/user.tsx
+++ b/src/services/reducers/user.tsx
@@ -29,9 +29,9 @@ import {
// GET_USER_ORDERS
} from '../../utils/constants';
-import { TUserActions } from '../../utils/userTypes';
+import { TUserActions } from '../types/user';
-type TUserState = {
+export type TUserState = {
name: string,
email: string,
password: string,
diff --git a/src/services/reducers/ws.tsx b/src/services/reducers/ws.tsx
index ca7583b..8f08981 100644
--- a/src/services/reducers/ws.tsx
+++ b/src/services/reducers/ws.tsx
@@ -1,7 +1,14 @@
import { WS_STATUS, WS_MESSAGE } from '../../utils/constants';
import { wsClose, wsConnecting, wsError, wsOpen, TWSAction } from '../actions/ws';
import { createReducer } from '@reduxjs/toolkit';
-import { TWSState } from '../../utils/orderTypes';
+import { IWSMessage } from '../actions/ws';
+import { TFeedData } from '../types/order';
+
+export type TWSState = {
+ status: string;
+ connectionError: string | IWSMessage;
+ feed: TFeedData | {};
+}
const initialWSState: TWSState = {
status: WS_STATUS.OFFLINE,
diff --git a/src/services/store.tsx b/src/services/store.tsx
new file mode 100644
index 0000000..2a10bdb
--- /dev/null
+++ b/src/services/store.tsx
@@ -0,0 +1,24 @@
+import { compose, createStore, applyMiddleware } from 'redux';
+import { socketMiddleware } from './middlewares/ws';
+import thunk from 'redux-thunk';
+import { rootReducer } from './reducers';
+import { wsConnect, wsDisconnect, wsConnecting, wsOpen, wsClose, wsError, wsMessage } from './actions/ws';
+
+const wsActions = {
+ wsConnect,
+ wsDisconnect,
+ wsConnecting,
+ onOpen: wsOpen,
+ onClose: wsClose,
+ onError: wsError,
+ onMessage: wsMessage
+}
+
+const composeEnhancers =
+ typeof window === 'object' && (window as any)['__REDUX_DEVTOOLS_EXTENSION_COMPOSE__']
+ ? (window as any)['__REDUX_DEVTOOLS_EXTENSION_COMPOSE__']({})
+ : compose;
+
+const enhancer = composeEnhancers(applyMiddleware(thunk, socketMiddleware(wsActions)));
+
+export const store = createStore(rootReducer, enhancer);
diff --git a/src/services/types/index.tsx b/src/services/types/index.tsx
new file mode 100644
index 0000000..80540a7
--- /dev/null
+++ b/src/services/types/index.tsx
@@ -0,0 +1,3 @@
+import { store } from '../store';
+
+export type TRootState = ReturnType
diff --git a/src/utils/ingredientsTypes.tsx b/src/services/types/ingredients.tsx
similarity index 100%
rename from src/utils/ingredientsTypes.tsx
rename to src/services/types/ingredients.tsx
diff --git a/src/utils/orderTypes.tsx b/src/services/types/order.tsx
similarity index 58%
rename from src/utils/orderTypes.tsx
rename to src/services/types/order.tsx
index e09e8ee..c83ab05 100644
--- a/src/utils/orderTypes.tsx
+++ b/src/services/types/order.tsx
@@ -1,5 +1,5 @@
-import { TIngredient } from "./ingredientsTypes";
-import { IWSMessage } from '../services/actions/ws';
+import { TIngredient } from "./ingredients";
+import { IWSMessage } from '../actions/ws';
export type TOrder = {
_id: string;
@@ -18,8 +18,3 @@ export type TFeedData = {
orders: Array;
}
-export type TWSState = {
- status: string;
- connectionError: string | IWSMessage;
- feed: TFeedData | {};
-}
diff --git a/src/utils/requestTypes.tsx b/src/services/types/request.tsx
similarity index 93%
rename from src/utils/requestTypes.tsx
rename to src/services/types/request.tsx
index cac5f57..782e6ec 100644
--- a/src/utils/requestTypes.tsx
+++ b/src/services/types/request.tsx
@@ -1,4 +1,4 @@
-import { TUser } from "./userTypes";
+import { TUser } from "./user";
export interface IGetUserOptions {
accessToken?: string;
diff --git a/src/utils/userTypes.tsx b/src/services/types/user.tsx
similarity index 99%
rename from src/utils/userTypes.tsx
rename to src/services/types/user.tsx
index a860b6b..17aba4e 100644
--- a/src/utils/userTypes.tsx
+++ b/src/services/types/user.tsx
@@ -25,7 +25,7 @@ import {
SET_REGISTER_FORM_VALUE,
SET_EDIT_USER_FORM,
RESET_EDIT_USER_FORM
- } from './constants';
+ } from '../../utils/constants';
export type TUser = {
name: string;
diff --git a/src/utils/api.tsx b/src/utils/api.tsx
index fd978bf..3511c06 100644
--- a/src/utils/api.tsx
+++ b/src/utils/api.tsx
@@ -9,8 +9,8 @@ import {
PASSWORDFORGOTURL,
PASSWORDRESETURL
} from "./constants";
-import { IEditUserOptions, IGetUserOptions, ILogoutUserOptions } from './requestTypes';
-import { TUser } from "./userTypes";
+import { IEditUserOptions, IGetUserOptions, ILogoutUserOptions } from '../services/types/request';
+import { TUser } from "../services/types/user";
// TODO: нужно ли типизировать data? Должен быть {ok: boolean, json?: () => any } ???
const checkResponse = async (data: any) => {
From 0c6de223cc648a5f695989fdc78b762dc3c50263 Mon Sep 17 00:00:00 2001
From: Yulia Berezhnaya
Date: Sun, 2 Apr 2023 01:00:14 +0300
Subject: [PATCH 06/13] =?UTF-8?q?=D0=A2=D0=B8=D0=BF=D0=B8=D0=B7=D0=B0?=
=?UTF-8?q?=D1=86=D0=B8=D1=8F=20=D1=81=D1=82=D1=80=D0=B0=D0=BD=D0=B8=D1=86?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/components/App/App.js | 2 +-
...{forgotPassword.jsx => forgotPassword.tsx} | 8 +-
src/pages/{login.jsx => login.tsx} | 8 +-
src/pages/{logoutPage.jsx => logoutPage.tsx} | 5 +-
src/pages/{profile.jsx => profile.tsx} | 15 +-
src/pages/{register.jsx => register.tsx} | 10 +-
.../{resetPassword.jsx => resetPassword.tsx} | 10 +-
...{userOrdersPage.jsx => userOrdersPage.tsx} | 12 +-
src/services/actions/ingredients.tsx | 252 +++++-------------
src/services/actions/user.tsx | 104 ++++----
src/services/hooks.tsx | 10 +
src/services/reducers/index.tsx | 7 +-
src/services/reducers/user.tsx | 4 +-
src/services/reducers/ws.tsx | 12 +-
src/services/types/index.tsx | 14 +
src/services/types/ingredients.tsx | 127 ++++++++-
src/services/types/order.tsx | 1 -
src/services/types/request.tsx | 17 +-
src/services/types/user.tsx | 8 +-
src/services/types/ws.tsx | 66 +++++
src/utils/constants.tsx | 2 +-
21 files changed, 385 insertions(+), 309 deletions(-)
rename src/pages/{forgotPassword.jsx => forgotPassword.tsx} (87%)
rename src/pages/{login.jsx => login.tsx} (89%)
rename src/pages/{logoutPage.jsx => logoutPage.tsx} (86%)
rename src/pages/{profile.jsx => profile.tsx} (81%)
rename src/pages/{register.jsx => register.tsx} (88%)
rename src/pages/{resetPassword.jsx => resetPassword.tsx} (88%)
rename src/pages/{userOrdersPage.jsx => userOrdersPage.tsx} (84%)
create mode 100644 src/services/hooks.tsx
create mode 100644 src/services/types/ws.tsx
diff --git a/src/components/App/App.js b/src/components/App/App.js
index 30a92b0..46a71c5 100644
--- a/src/components/App/App.js
+++ b/src/components/App/App.js
@@ -10,7 +10,7 @@ import ProtectedRoute from '../ProtectedRoute/ProtectedRoute';
import Orders from '../Orders/Orders';
-import { LoginPage } from '../../pages/login';
+import { LoginPage } from '../../pages/login.tsx';
import { RegisterPage } from '../../pages/register';
import { ForgotPasswordPage } from '../../pages/forgotPassword';
import { ResetPasswordPage } from '../../pages/resetPassword';
diff --git a/src/pages/forgotPassword.jsx b/src/pages/forgotPassword.tsx
similarity index 87%
rename from src/pages/forgotPassword.jsx
rename to src/pages/forgotPassword.tsx
index 7e8a6c6..fc4dd0e 100644
--- a/src/pages/forgotPassword.jsx
+++ b/src/pages/forgotPassword.tsx
@@ -1,5 +1,5 @@
-import React from 'react';
-import { useDispatch, useSelector } from 'react-redux';
+import { ChangeEvent, FormEvent } from 'react';
+import { useDispatch, useSelector } from '../services/hooks';
import ForgotPasswordPageStyles from './login.module.css';
import { Link, Navigate, useLocation } from 'react-router-dom';
@@ -12,13 +12,13 @@ export function ForgotPasswordPage() {
const {email, canResetPassword} = useSelector(state => state.user);
- const onFormSubmit = (e) => {
+ const onFormSubmit = (e: FormEvent) => {
e.preventDefault();
dispatch(forgotPassword(email));
}
- const onFormChange = (e) => {
+ const onFormChange = (e: ChangeEvent) => {
dispatch(setRegisterFormValue(e.target.name, e.target.value));
}
diff --git a/src/pages/login.jsx b/src/pages/login.tsx
similarity index 89%
rename from src/pages/login.jsx
rename to src/pages/login.tsx
index f888590..8fffe2e 100644
--- a/src/pages/login.jsx
+++ b/src/pages/login.tsx
@@ -1,5 +1,5 @@
-import React from 'react';
-import { useDispatch, useSelector } from 'react-redux';
+import { ChangeEvent, FormEvent } from 'react';
+import { useDispatch, useSelector } from '../services/hooks';
import LoginPageStyles from './login.module.css';
import { Link, Navigate } from 'react-router-dom';
@@ -11,13 +11,13 @@ export function LoginPage() {
const {email, password, isAuthSuccess} = useSelector(state => state.user);
- const onFormSubmit = (e) => {
+ const onFormSubmit = (e: FormEvent) => {
e.preventDefault();
dispatch(loginUser({email, password}));
}
- const onFormChange = (e) => {
+ const onFormChange = (e: ChangeEvent) => {
dispatch(setRegisterFormValue(e.target.name, e.target.value));
}
diff --git a/src/pages/logoutPage.jsx b/src/pages/logoutPage.tsx
similarity index 86%
rename from src/pages/logoutPage.jsx
rename to src/pages/logoutPage.tsx
index c57c6b7..0b66a8d 100644
--- a/src/pages/logoutPage.jsx
+++ b/src/pages/logoutPage.tsx
@@ -1,4 +1,5 @@
-import { useDispatch, useSelector } from 'react-redux';
+import { FormEvent } from 'react';
+import { useDispatch, useSelector } from '../services/hooks';
import LogoutPageStyles from './login.module.css';
import { Navigate } from 'react-router-dom';
@@ -10,7 +11,7 @@ export function LogoutPage() {
const {isAuthSuccess} = useSelector(state => state.user);
- const onFormSubmit = (e) => {
+ const onFormSubmit = (e: FormEvent) => {
e.preventDefault();
dispatch(logoutUser({}));
diff --git a/src/pages/profile.jsx b/src/pages/profile.tsx
similarity index 81%
rename from src/pages/profile.jsx
rename to src/pages/profile.tsx
index c18c08f..442cd0f 100644
--- a/src/pages/profile.jsx
+++ b/src/pages/profile.tsx
@@ -1,4 +1,5 @@
-import { useDispatch, useSelector } from 'react-redux';
+import { FormEvent, ChangeEvent } from 'react';
+import { useDispatch, useSelector } from '../services/hooks';
import ProfilePageStyles from './profile.module.css';
import { NavLink } from 'react-router-dom';
@@ -10,21 +11,21 @@ export function ProfilePage() {
const dispatch = useDispatch();
const {name, email, password, isUserEdited, editUserFailed} = useSelector(state => state.user);
- const onFormChange = (e) => {
+ const onFormChange = (e: ChangeEvent) => {
dispatch(setEditUserForm(e.target.name, e.target.value));
}
- const onFormSubmit = (e) => {
+ const onFormSubmit = (e: FormEvent) => {
e.preventDefault();
dispatch(editUser({name, email, password}));
}
- const onReset = (e) => {
+ const onReset = () => {
dispatch({type: RESET_EDIT_USER_FORM});
}
- const active = ProfilePageStyles.active + ' ' + ProfilePageStyles.link + ' pt-4 pb-4 text text_type_main-medium';
- const link = ProfilePageStyles.link + ' pt-4 pb-4 text text_type_main-medium text_color_inactive';
+ const active: string = ProfilePageStyles.active + ' ' + ProfilePageStyles.link + ' pt-4 pb-4 text text_type_main-medium';
+ const link: string = ProfilePageStyles.link + ' pt-4 pb-4 text text_type_main-medium text_color_inactive';
return (
);
-}
\ No newline at end of file
+}
diff --git a/src/pages/userOrdersPage.jsx b/src/pages/userOrdersPage.tsx
similarity index 84%
rename from src/pages/userOrdersPage.jsx
rename to src/pages/userOrdersPage.tsx
index b7505a0..8f53ed4 100644
--- a/src/pages/userOrdersPage.jsx
+++ b/src/pages/userOrdersPage.tsx
@@ -1,8 +1,8 @@
-import React, { useEffect } from 'react';
+import { useEffect } from 'react';
+import { useDispatch, useSelector } from '../services/hooks';
import UserOrdersPageStyles from './userOrdersPage.module.css';
import { NavLink } from 'react-router-dom';
-import { useDispatch, useSelector } from 'react-redux';
import { wsConnect, wsDisconnect } from '../services/actions/ws';
import { GET_USER_ORDERS_URL } from '../utils/constants';
@@ -19,10 +19,10 @@ export function UserOrdersPage() {
useEffect(() => {
dispatch(wsConnect(`${GET_USER_ORDERS_URL}?token=${token}`));
- return () => dispatch(wsDisconnect());
+ return () => { dispatch(wsDisconnect()); }
}, [dispatch]);
- const { orders } = useSelector(state => state.ws.feed);
+ const feed = useSelector(state => state.ws.feed);
return (
@@ -44,7 +45,7 @@ export function ProfilePage() {
@@ -41,8 +41,8 @@ export function UserOrdersPage() {
Заказов пока нет
}
- {orders && orders.map((item, index) => {
+ {!feed && Заказов пока нет
}
+ {feed?.orders && feed.orders.map((item, index) => {
return (
- {total}
-
-
- )
-}
-export default TotalPrice;
\ No newline at end of file
diff --git a/src/components/TotalPrice/TotalPrice.tsx b/src/components/TotalPrice/TotalPrice.tsx
new file mode 100644
index 0000000..156e0dd
--- /dev/null
+++ b/src/components/TotalPrice/TotalPrice.tsx
@@ -0,0 +1,28 @@
+import TotalPriceStyles from './TotalPrice.module.css';
+
+import { useMemo, FC } from 'react';
+import { useSelector } from 'react-redux';
+import { TRootState } from '../../services/types/index';
+
+import { CurrencyIcon } from '@ya.praktikum/react-developer-burger-ui-components';
+import { TMenuState } from '../../services/reducers';
+
+const TotalPrice: FC = () => {
+
+ const { addedIngredients: { bun, others } }: TMenuState = useSelector((state: TRootState) => state.menu);
+
+ const total = useMemo(() => (
+ others.reduce(
+ (res, {price}) => res += price,
+ bun ? bun.price * 2 : 0
+ )), [bun, others]);
+
+ return (
+
+ {total}
+
+
+ )
+}
+
+export default TotalPrice;
diff --git a/src/pages/userOrdersPage.tsx b/src/pages/userOrdersPage.tsx
index 8f53ed4..00696d7 100644
--- a/src/pages/userOrdersPage.tsx
+++ b/src/pages/userOrdersPage.tsx
@@ -4,7 +4,7 @@ import UserOrdersPageStyles from './userOrdersPage.module.css';
import { NavLink } from 'react-router-dom';
import { wsConnect, wsDisconnect } from '../services/actions/ws';
-import { GET_USER_ORDERS_URL } from '../utils/constants';
+import { GET_USER_ORDERS_URL, WS_STATUS_ONLINE } from '../utils/constants';
import OrderSnippet from '../components/OrderSnippet/OrderSnippet';
import { getCookie } from '../utils/cookie';
@@ -22,7 +22,9 @@ export function UserOrdersPage() {
return () => { dispatch(wsDisconnect()); }
}, [dispatch]);
- const feed = useSelector(state => state.ws.feed);
+ const feed = useSelector(({ ws }) => (
+ ws.status === WS_STATUS_ONLINE && ws.feed?.success ? ws.feed : undefined
+ ));
return (
diff --git a/src/services/actions/user.tsx b/src/services/actions/user.tsx
index bc72e63..5d43000 100644
--- a/src/services/actions/user.tsx
+++ b/src/services/actions/user.tsx
@@ -30,10 +30,8 @@ import {
logoutUserFailedAction
} from "../types/user";
import {
- TRequestRetryOptions,
requestRetryOnFail,
requestRetryOnSuccess ,
- requestRetry
} from "../types/request";
import {
SET_REGISTER_FORM_VALUE,
@@ -98,7 +96,7 @@ export const loginUser: AppThunk = (user: TUser) => (dispatch: AppDispatch) => {
export function getUser() {
return function(dispatch: AppDispatch) {
getRequestWithRetry(
- getUserRequest,
+ (accessToken) => getUserRequest(accessToken),
({user}) => dispatch(getUserSuccessAction(user)),
() => dispatch(getUserFailedAction())
);
@@ -109,10 +107,9 @@ export function getUser() {
export function editUser(user: TUser) {
return function(dispatch: AppDispatch) {
getRequestWithRetry(
- editUserRequest,
+ (accessToken) => editUserRequest(accessToken, user),
({user}) => dispatch(editUserSuccessAction(user)),
- () => dispatch(editUserFailedAction()),
- user
+ () => dispatch(editUserFailedAction())
);
}
}
@@ -147,7 +144,7 @@ export function resetPassword(password: string, code: string) {
export const logoutUser: AppThunk = () => (dispatch: AppDispatch) => {
getRequestWithRetry(
- logoutRequest,
+ (accessToken) => logoutRequest(accessToken, getCookie('token')),
() => {
setCookie('accessToken', '', {expires: 0});
setCookie('token', '', {expires: 0});
@@ -155,8 +152,7 @@ export const logoutUser: AppThunk = () => (dispatch: AppDispatch) => {
},
({message}) => {
dispatch(logoutUserFailedAction(message));
- },
- getCookie('token')
+ }
)
}
@@ -169,9 +165,9 @@ export const logoutUser: AppThunk = () => (dispatch: AppDispatch) => {
*/
// TODO что делать с options и getRequest???
-function getRequestWithRetry(getRequest: requestRetry, onSuccess: requestRetryOnSuccess, onFail: requestRetryOnFail, options?: TRequestRetryOptions) {
+function getRequestWithRetry(getRequest: ((accessToken: string) => Promise), onSuccess: requestRetryOnSuccess, onFail: requestRetryOnFail) {
- getRequest(getCookie('accessToken'), options)
+ getRequest(getCookie('accessToken'))
.then((res: any) => {
if (res && res.success) {
onSuccess(res);
@@ -184,7 +180,7 @@ function getRequestWithRetry(getRequest: requestRetry, onSuccess: requestRetryOn
setCookie('accessToken', getAccessToken(res.accessToken));
setCookie('token', res.refreshToken);
- return getRequest(getAccessToken(res.accessToken), options)
+ return getRequest(getAccessToken(res.accessToken))
.then((res: any) => {
if (res && res.success) {
onSuccess(res)
diff --git a/src/services/actions/ws.tsx b/src/services/actions/ws.tsx
index 5178af5..12067bf 100644
--- a/src/services/actions/ws.tsx
+++ b/src/services/actions/ws.tsx
@@ -1,9 +1,9 @@
+import { AppDispatch } from '../types/index';
import { createAction } from '@reduxjs/toolkit';
import { refreshTokenRequest } from '../../utils/api';
import { setCookie, getCookie, getAccessToken } from '../../utils/cookie';
import {
GET_USER_ORDERS_URL,
- WS_MESSAGE,
WS_CONNECT,
WS_DISCONNECT,
WS_CONNECTING,
@@ -11,7 +11,10 @@ import {
WS_CLOSE,
WS_ERROR
} from '../../utils/constants';
-import { TOrder } from '../types/order';
+import {
+ TWSMessage,
+ wsMessageAction
+} from '../types/ws';
function withPayloadType() {
return (t: T) => ({ payload: t })
@@ -23,81 +26,28 @@ export const wsOpen = createAction(WS_OPEN);
export const wsClose = createAction(WS_CLOSE);
export const wsError = createAction(WS_ERROR);
-export interface IWSMessage {
- success: boolean;
- message?: string;
- orders?: Array;
-}
-
-interface IWSMessageAction {
- readonly type: typeof WS_MESSAGE;
- payload: IWSMessage;
-}
-
-interface IWSErrorAction {
- readonly type: typeof WS_ERROR;
- payload: IWSMessage;
-}
-
-interface IWSOpenAction {
- readonly type: typeof WS_OPEN;
- payload: IWSMessage;
-}
-
-interface IWSCloseAction {
- readonly type: typeof WS_CLOSE;
- payload: IWSMessage;
-}
-
-interface IWSConnectingAction {
- readonly type: typeof WS_CONNECTING;
- payload: IWSMessage;
-}
-
-interface IWSConnectAction {
- readonly type: typeof WS_CONNECT;
- payload: IWSMessage;
-}
-
-interface IWSDisconnectAction {
- readonly type: typeof WS_DISCONNECT;
- payload: IWSMessage;
-}
-
-const wsMessageAction = (payload: IWSMessage): IWSMessageAction => ({
- type: WS_MESSAGE,
- payload
-});
-
-export type TWSAction =
- IWSMessageAction
- | IWSErrorAction
- | IWSOpenAction
- | IWSCloseAction
- | IWSConnectingAction
- | IWSConnectAction
- | IWSDisconnectAction;
-
-export const wsMessage = (action: IWSMessage) => (dispatch: any) => {
-
+export const wsMessage = (action: TWSMessage) => (dispatch: AppDispatch) => {
dispatch(wsMessageAction(action));
- if (action.message === 'Invalid or missing token') {
- dispatch(wsDisconnect());
- refreshTokenRequest(getCookie('token'))
- .then((res) => {
- if (res && res.success) {
- setCookie('accessToken', getAccessToken(res.accessToken));
- setCookie('token', res.refreshToken);
-
- dispatch(wsConnect(`${GET_USER_ORDERS_URL}?token=${getCookie('accessToken')}`));
- } else {
- throw new Error('Произошла ошибка ', res.message);
- }
-
- })
- .catch((err) => {
- console.log('error!', err);
- });
+ if (!action.success) {
+ if (action.message === 'Invalid or missing token') {
+ dispatch(wsDisconnect());
+ refreshTokenRequest(getCookie('token'))
+ .then((res) => {
+ if (res && res.success) {
+ setCookie('accessToken', getAccessToken(res.accessToken));
+ setCookie('token', res.refreshToken);
+
+ dispatch(wsConnect(`${GET_USER_ORDERS_URL}?token=${getCookie('accessToken')}`));
+ } else {
+ throw new Error('Произошла ошибка ', res.message);
+ }
+
+ })
+ .catch((err) => {
+ console.log('error!', err);
+ });
+ }
}
+
}
diff --git a/src/services/reducers/index.tsx b/src/services/reducers/index.tsx
index ee02513..3134a77 100644
--- a/src/services/reducers/index.tsx
+++ b/src/services/reducers/index.tsx
@@ -27,7 +27,7 @@ export type TMenuState = {
addedIngredients: {
bun: TIngredient | null,
- others: Array
+ others: Array
},
currentIngredient: string | null,
diff --git a/src/services/reducers/ws.tsx b/src/services/reducers/ws.tsx
index d5d803a..26b9982 100644
--- a/src/services/reducers/ws.tsx
+++ b/src/services/reducers/ws.tsx
@@ -1,39 +1,48 @@
-import { WS_STATUS, WS_MESSAGE } from '../../utils/constants';
+import { WS_STATUS_OFFLINE, WS_STATUS_CONNECTING, WS_STATUS_ONLINE, WS_MESSAGE } from '../../utils/constants';
import { wsClose, wsConnecting, wsError, wsOpen } from '../actions/ws';
import { createReducer } from '@reduxjs/toolkit';
-import { IWSMessage, TWSAction } from '../types/ws';
+import { TWSMessage, TWSAction, IWSErrorAction } from '../types/ws';
import { TFeedData } from '../types/order';
-export type TWSState = {
- status: string;
- connectionError: string | undefined;
- feed: TFeedData | IWSMessage | undefined;
-}
+type TWSStateOffline = {
+ status: typeof WS_STATUS_OFFLINE;
+ connectionError: string;
+};
+type TWSStateConnecting = {
+ status: typeof WS_STATUS_CONNECTING;
+ connectionError: string;
+};
+type TWSStateOnline = {
+ status: typeof WS_STATUS_ONLINE;
+ feed: TFeedData | TWSMessage;
+ connectionError: string;
+};
+
+export type TWSState = TWSStateOffline | TWSStateConnecting | TWSStateOnline;
const initialWSState: TWSState = {
- status: WS_STATUS.OFFLINE,
- connectionError: '',
- feed: undefined
+ status: WS_STATUS_OFFLINE,
+ connectionError: ''
}
-export const wsReducer = createReducer(initialWSState, (builder: any) => {
+export const wsReducer = createReducer(initialWSState as TWSState, (builder: any) => {
builder
- .addCase(wsConnecting, (state: TWSState) => {
- state.status = WS_STATUS.CONNECTING
- })
- .addCase(wsOpen, (state: TWSState) => {
- state.status = WS_STATUS.ONLINE;
- state.connectionError = ''
- })
- .addCase(wsClose, (state: TWSState) => {
- state.status = WS_STATUS.OFFLINE;
- state.connectionError = ''
- })
- .addCase(wsError, (state: TWSState, action: TWSAction) => {
- state.connectionError = action.payload?.message
- })
- .addCase(WS_MESSAGE, (state: TWSState, action: TWSAction) => {
- state.feed = action.payload;
- })
+ .addCase(wsConnecting, (state: TWSState) => {
+ state.status = WS_STATUS_CONNECTING
+ })
+ .addCase(wsOpen, (state: TWSState) => {
+ state.status = WS_STATUS_ONLINE;
+ state.connectionError = ''
+ })
+ .addCase(wsClose, (state: TWSState) => {
+ state.status = WS_STATUS_OFFLINE;
+ state.connectionError = ''
+ })
+ .addCase(wsError, (state: TWSState, action: TWSAction) => {
+ state.connectionError = action.payload.success ? '' : action.payload.message;
+ })
+ .addCase(WS_MESSAGE, (state: TWSStateOnline, action: TWSAction) => {
+ state.feed = action.payload;
+ })
})
diff --git a/src/services/types/ingredients.tsx b/src/services/types/ingredients.tsx
index b353473..95632cb 100644
--- a/src/services/types/ingredients.tsx
+++ b/src/services/types/ingredients.tsx
@@ -58,12 +58,14 @@ interface IGetCountriesSuccessAction {
export const getIngredientsAction = (): IGetIngredientsAction => ({
type: GET_INGREDIENTS_REQUEST
});
+
export const getIngredientsSuccessAction =
(ingredientsByType: TIngredientsByType, ingredientsById: TIngredientsById): IGetCountriesSuccessAction => ({
type: GET_INGREDIENTS_SUCCESS,
ingredientsByType,
ingredientsById
});
+
export const getIngredientsFailedAction = (): IGetIngredientsFailedAction => ({
type: GET_INGREDIENTS_FAILED
});
diff --git a/src/services/types/request.tsx b/src/services/types/request.tsx
index af803b4..bdb5774 100644
--- a/src/services/types/request.tsx
+++ b/src/services/types/request.tsx
@@ -1,11 +1,6 @@
-import { TUser } from "./user";
-
-export type TRequestRetryOptions = TUser | string | undefined;
-
export type TRequestRetryOnSuccess = {
[name: string]: string;
}
-export type requestRetry = (accessToken: string, options: TRequestRetryOptions) => Promise;
export type requestRetryOnFail = (error: any) => void;
export type requestRetryOnSuccess = (res: any) => void;
diff --git a/src/services/types/ws.tsx b/src/services/types/ws.tsx
index d0be5ec..980e1c3 100644
--- a/src/services/types/ws.tsx
+++ b/src/services/types/ws.tsx
@@ -9,49 +9,51 @@ import {
} from '../../utils/constants';
import { TOrder } from './order';
-
-export interface IWSMessage {
- success: boolean;
- message?: string;
- orders?: Array;
+export type TWSErrorMessage = {
+ success: false;
+ message: string;
}
+export type TWSMessage = {
+ success: true;
+ orders: Array;
+} | TWSErrorMessage;
interface IWSMessageAction {
readonly type: typeof WS_MESSAGE;
- payload: IWSMessage;
+ payload: TWSMessage;
}
-interface IWSErrorAction {
+export interface IWSErrorAction {
readonly type: typeof WS_ERROR;
- payload: IWSMessage;
+ payload: TWSErrorMessage;
}
interface IWSOpenAction {
readonly type: typeof WS_OPEN;
- payload: IWSMessage;
+ payload: TWSMessage;
}
interface IWSCloseAction {
readonly type: typeof WS_CLOSE;
- payload: IWSMessage;
+ payload: TWSMessage;
}
interface IWSConnectingAction {
readonly type: typeof WS_CONNECTING;
- payload: IWSMessage;
+ payload: TWSMessage;
}
interface IWSConnectAction {
readonly type: typeof WS_CONNECT;
- payload: IWSMessage;
+ payload: TWSMessage;
}
interface IWSDisconnectAction {
readonly type: typeof WS_DISCONNECT;
- payload: IWSMessage | undefined;
+ payload: TWSMessage;
}
-export const wsMessageAction = (payload: IWSMessage): IWSMessageAction => ({
+export const wsMessageAction = (payload: TWSMessage): IWSMessageAction => ({
type: WS_MESSAGE,
payload
});
diff --git a/src/utils/api.tsx b/src/utils/api.tsx
index 3511c06..13070a8 100644
--- a/src/utils/api.tsx
+++ b/src/utils/api.tsx
@@ -9,19 +9,22 @@ import {
PASSWORDFORGOTURL,
PASSWORDRESETURL
} from "./constants";
-import { IEditUserOptions, IGetUserOptions, ILogoutUserOptions } from '../services/types/request';
import { TUser } from "../services/types/user";
+import { TIngredient } from "../services/types/ingredients";
-// TODO: нужно ли типизировать data? Должен быть {ok: boolean, json?: () => any } ???
-const checkResponse = async (data: any) => {
+type TErrorResponse = { success: false; message: string; };
+type TIngredientsResponse = { success: true; data: Array; } | TErrorResponse;
+
+export type TResponse = TIngredientsResponse;
+
+const checkResponse = async (data: Response): Promise => {
if (!data.ok) {
- throw new Error(data.message, { cause: await data.json() });
+ throw new Error(data.status.toString(), { cause: await data.json() });
}
return data.json();
}
-// TODO: как вообще типизировать ответ сервера???
-const getIngredientsRequest = async (): Promise => {
+const getIngredientsRequest = async (): Promise => {
const res = await fetch(GETINGREDIENTSURL);
return await checkResponse(res);
@@ -42,7 +45,7 @@ const sendOrderRequest = async (ingredientIds: Array, accessToken: strin
return await checkResponse(res);
}
-const getUserRequest = async ({accessToken}: IGetUserOptions): Promise => {
+const getUserRequest = async (accessToken: string): Promise => {
const res = await fetch(USERURL, {
method: 'GET',
headers: {
@@ -54,7 +57,7 @@ const getUserRequest = async ({accessToken}: IGetUserOptions): Promise => {
return await checkResponse(res);
}
-const editUserRequest = async ({user, accessToken} : IEditUserOptions): Promise => {
+const editUserRequest = async (accessToken: string, user: TUser): Promise => {
const res = await fetch(USERURL, {
method: 'PATCH',
headers: {
@@ -91,7 +94,7 @@ const loginRequest = async (user: TUser): Promise => {
return await checkResponse(res);
}
-const logoutRequest = async ({token}: ILogoutUserOptions): Promise => {
+const logoutRequest = async (accessToken: string, token: string): Promise => {
const res = await fetch(LOGOUTUSERURL, {
method: 'POST',
headers: {
@@ -127,7 +130,7 @@ const passwordForgotRequest = async (email: string): Promise => {
return await checkResponse(res);
}
-const passwordResetRequest = async (password: string, token: number): Promise => {
+const passwordResetRequest = async (password: string, token: string): Promise => {
const res = await fetch(PASSWORDRESETURL, {
method: 'POST',
headers: {
diff --git a/src/utils/constants.tsx b/src/utils/constants.tsx
index 263ea95..c9ee3a6 100644
--- a/src/utils/constants.tsx
+++ b/src/utils/constants.tsx
@@ -1,5 +1,5 @@
const BASEURL = 'https://norma.nomoreparties.space/api';
-export const GETINGREDIENTSURL = BASEURL + '/ingredientsd';
+export const GETINGREDIENTSURL = BASEURL + '/ingredients';
export const SAVEORDERURL = BASEURL + '/orders';
export const ADDUSERURL = BASEURL + '/auth/register';
export const LOGINUSERURL = BASEURL + '/auth/login';
@@ -12,11 +12,14 @@ export const PASSWORDRESETURL = BASEURL + '/password-reset/reset';
export const WSURL = 'wss://norma.nomoreparties.space';
export const GET_ALL_ORDERS_URL = WSURL + '/orders/all';
export const GET_USER_ORDERS_URL = WSURL + '/orders';
-export const WS_STATUS = {
- CONNECTING : 'CONNECTING...',
- ONLINE : 'ONLINE',
- OFFLINE : 'OFFLINE'
-}
+export const WS_STATUS_OFFLINE: 'OFFLINE' = 'OFFLINE';
+export const WS_STATUS_ONLINE: 'ONLINE' = 'ONLINE';
+export const WS_STATUS_CONNECTING: 'CONNECTING...' = 'CONNECTING...';
+// export const WS_STATUS = {
+// CONNECTING : 'CONNECTING...',
+// ONLINE : 'ONLINE',
+// OFFLINE : 'OFFLINE'
+// }
export const WS_MESSAGE: 'WS_MESSAGE' = 'WS_MESSAGE';
export const WS_CONNECT: 'WS_CONNECT' = 'WS_CONNECT';
export const WS_DISCONNECT: 'WS_DISCONNECT' = 'WS_DISCONNECT';
From 4b044ec517254b42dc8066e9aceebd566e7b0dc9 Mon Sep 17 00:00:00 2001
From: Yulia Berezhnaya
Date: Sun, 2 Apr 2023 11:45:46 +0300
Subject: [PATCH 08/13] =?UTF-8?q?=D0=A4=D0=B8=D0=BA=D1=81=20=D0=BE=D1=88?=
=?UTF-8?q?=D0=B8=D0=B1=D0=BE=D0=BA=20=D1=82=D0=B8=D0=BF=D0=B8=D0=B7=D0=B0?=
=?UTF-8?q?=D1=86=D0=B8=D0=B8=20=D0=B4=D0=BB=D1=8F=20=D0=B2=D0=BE=D1=81?=
=?UTF-8?q?=D1=81=D1=82=D0=B0=D0=BD=D0=BE=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8?=
=?UTF-8?q?=D1=8F=20=D0=BF=D0=B0=D1=80=D0=BE=D0=BB=D1=8F;=20=D1=82=D0=B8?=
=?UTF-8?q?=D0=BF=D0=B8=D0=B7=D0=B0=D1=86=D0=B8=D1=8F=20=D0=90=D0=9F=D0=98?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../ProtectedRoute/ProtectedRoute.js | 3 +-
src/services/actions/user.tsx | 2 +-
src/services/actions/ws.tsx | 2 +-
src/services/reducers/user.tsx | 19 +-----
src/services/types/user.tsx | 12 ++--
src/utils/api.tsx | 62 ++++++++++++++++---
6 files changed, 63 insertions(+), 37 deletions(-)
diff --git a/src/components/ProtectedRoute/ProtectedRoute.js b/src/components/ProtectedRoute/ProtectedRoute.js
index 34f6518..3486792 100644
--- a/src/components/ProtectedRoute/ProtectedRoute.js
+++ b/src/components/ProtectedRoute/ProtectedRoute.js
@@ -14,7 +14,8 @@ function ProtectedRoute({element, isAuthPage, accessFrom}) {
if (!isUserLoaded && (accessToken || refreshToken)) {
return ;
}
diff --git a/src/services/actions/user.tsx b/src/services/actions/user.tsx
index 5d43000..517d114 100644
--- a/src/services/actions/user.tsx
+++ b/src/services/actions/user.tsx
@@ -118,7 +118,7 @@ export const forgotPassword: AppThunk = (email: string) => (dispatch: AppDispatc
passwordForgotRequest(email)
.then((res) => {
if (res && res.success) {
- dispatch(forgotPasswordSuccessAction(res.user));
+ dispatch(forgotPasswordSuccessAction());
}
})
.catch(() => {
diff --git a/src/services/actions/ws.tsx b/src/services/actions/ws.tsx
index 12067bf..49245ce 100644
--- a/src/services/actions/ws.tsx
+++ b/src/services/actions/ws.tsx
@@ -40,7 +40,7 @@ export const wsMessage = (action: TWSMessage) => (dispatch: AppDispatch) => {
dispatch(wsConnect(`${GET_USER_ORDERS_URL}?token=${getCookie('accessToken')}`));
} else {
- throw new Error('Произошла ошибка ', res.message);
+ throw new Error('Произошла ошибка ');
}
})
diff --git a/src/services/reducers/user.tsx b/src/services/reducers/user.tsx
index 90d8a7f..ebb0091 100644
--- a/src/services/reducers/user.tsx
+++ b/src/services/reducers/user.tsx
@@ -25,9 +25,7 @@ import {
RESET_PASSWORD_FAILED,
LOGOUT_USER_SUCCESS,
- LOGOUT_USER_FAILED,
-
- // GET_USER_ORDERS
+ LOGOUT_USER_FAILED
} from '../../utils/constants';
import { TUserActions } from '../types/user';
@@ -84,9 +82,7 @@ const initialUserState = {
canResetPassword: false,
resetPasswordSuccess: false,
- code: '',
-
- // orders: []
+ code: ''
}
export const userReducer = (state: TUserState = initialUserState, action: TUserActions) => {
@@ -246,17 +242,6 @@ export const userReducer = (state: TUserState = initialUserState, action: TUserA
logoutError: true
}
}
-
-
-
-
- // case GET_USER_ORDERS: {
- // return {
- // ...state,
- // orders: action.action.orders
- // }
- // }
-
default: return state;
}
diff --git a/src/services/types/user.tsx b/src/services/types/user.tsx
index 88dfb33..f13500a 100644
--- a/src/services/types/user.tsx
+++ b/src/services/types/user.tsx
@@ -129,17 +129,15 @@ export const editUserFailedAction = (): IEditUserFailedAction => ({
// Типизация экшнов для забытого юзером пароля
interface IForgotPasswordSuccessAction {
- readonly type: typeof RESET_PASSWORD_SUCCESS;
- user: TUser
+ readonly type: typeof FORGOT_PASSWORD_SUCCESS;
}
interface IForgotPasswordFailedAction {
readonly type: typeof FORGOT_PASSWORD_FAILED;
}
-export const forgotPasswordSuccessAction = (user: TUser): IForgotPasswordSuccessAction => ({
- type: RESET_PASSWORD_SUCCESS,
- user
+export const forgotPasswordSuccessAction = (): IForgotPasswordSuccessAction => ({
+ type: FORGOT_PASSWORD_SUCCESS
});
export const forgotPasswordFailedAction = (): IForgotPasswordFailedAction => ({
@@ -149,7 +147,7 @@ export const forgotPasswordFailedAction = (): IForgotPasswordFailedAction => ({
// Типизация экшнов для сброса пароля
interface IResetPasswordSuccessAction {
- readonly type: typeof FORGOT_PASSWORD_SUCCESS;
+ readonly type: typeof RESET_PASSWORD_SUCCESS;
}
interface IResetPasswordFailedAction {
@@ -157,7 +155,7 @@ interface IResetPasswordFailedAction {
}
export const resetPasswordSuccessAction = (): IResetPasswordSuccessAction => ({
- type: FORGOT_PASSWORD_SUCCESS
+ type: RESET_PASSWORD_SUCCESS
});
export const resetPasswordFailedAction = (): IResetPasswordFailedAction => ({
diff --git a/src/utils/api.tsx b/src/utils/api.tsx
index 13070a8..0e77ee9 100644
--- a/src/utils/api.tsx
+++ b/src/utils/api.tsx
@@ -11,11 +11,53 @@ import {
} from "./constants";
import { TUser } from "../services/types/user";
import { TIngredient } from "../services/types/ingredients";
+import { TOrder } from "../services/types/order";
type TErrorResponse = { success: false; message: string; };
type TIngredientsResponse = { success: true; data: Array; } | TErrorResponse;
+type TSendOrderResponse = {
+ success: true;
+ name: string;
+ order: TOrder;
+} | TErrorResponse;
+
+type TUserResponse = {
+ success: true;
+ user: TUser
+} | TErrorResponse;
+
+type TLoginUserResponse = {
+ success: true;
+ accessToken: string;
+ refreshToken: string;
+ user: TUser;
+} | TErrorResponse;
+
+type TLogoutUserResponse = {
+ success: true;
+ message: string;
+} | TErrorResponse;
+
+type TRefreshTokenResponse = {
+ success: true;
+ accessToken: string;
+ refreshToken: string;
+} | TErrorResponse;
+
+type TForgotPasswordResponse = {
+ success: boolean;
+ message: string;
+ user: TUser;
+}
-export type TResponse = TIngredientsResponse;
+export type TResponse =
+TIngredientsResponse
+& TSendOrderResponse
+& TUserResponse
+& TLoginUserResponse
+& TLogoutUserResponse
+& TRefreshTokenResponse
+& TForgotPasswordResponse;
const checkResponse = async (data: Response): Promise => {
if (!data.ok) {
@@ -30,7 +72,7 @@ const getIngredientsRequest = async (): Promise => {
return await checkResponse(res);
}
-const sendOrderRequest = async (ingredientIds: Array, accessToken: string): Promise => {
+const sendOrderRequest = async (ingredientIds: Array, accessToken: string): Promise => {
const res = await fetch(SAVEORDERURL, {
method: 'POST',
headers: {
@@ -45,7 +87,7 @@ const sendOrderRequest = async (ingredientIds: Array, accessToken: strin
return await checkResponse(res);
}
-const getUserRequest = async (accessToken: string): Promise => {
+const getUserRequest = async (accessToken: string): Promise => {
const res = await fetch(USERURL, {
method: 'GET',
headers: {
@@ -57,7 +99,7 @@ const getUserRequest = async (accessToken: string): Promise => {
return await checkResponse(res);
}
-const editUserRequest = async (accessToken: string, user: TUser): Promise => {
+const editUserRequest = async (accessToken: string, user: TUser): Promise => {
const res = await fetch(USERURL, {
method: 'PATCH',
headers: {
@@ -70,7 +112,7 @@ const editUserRequest = async (accessToken: string, user: TUser): Promise =
return checkResponse(res);
}
-const addUserRequest = async (user: TUser): Promise => {
+const addUserRequest = async (user: TUser): Promise => {
const res = await fetch(ADDUSERURL, {
method: 'POST',
headers: {
@@ -82,7 +124,7 @@ const addUserRequest = async (user: TUser): Promise => {
return await checkResponse(res);
}
-const loginRequest = async (user: TUser): Promise => {
+const loginRequest = async (user: TUser): Promise => {
const res = await fetch(LOGINUSERURL, {
method: 'POST',
headers: {
@@ -94,7 +136,7 @@ const loginRequest = async (user: TUser): Promise => {
return await checkResponse(res);
}
-const logoutRequest = async (accessToken: string, token: string): Promise => {
+const logoutRequest = async (accessToken: string, token: string): Promise => {
const res = await fetch(LOGOUTUSERURL, {
method: 'POST',
headers: {
@@ -106,7 +148,7 @@ const logoutRequest = async (accessToken: string, token: string): Promise =
return await checkResponse(res);
}
-const refreshTokenRequest = async (token: string): Promise => {
+const refreshTokenRequest = async (token: string): Promise => {
const res = await fetch(REFRESHTOKENURL, {
method: 'POST',
headers: {
@@ -118,7 +160,7 @@ const refreshTokenRequest = async (token: string): Promise => {
return await checkResponse(res);
}
-const passwordForgotRequest = async (email: string): Promise => {
+const passwordForgotRequest = async (email: string): Promise => {
const res = await fetch(PASSWORDFORGOTURL, {
method: 'POST',
headers: {
@@ -130,7 +172,7 @@ const passwordForgotRequest = async (email: string): Promise => {
return await checkResponse(res);
}
-const passwordResetRequest = async (password: string, token: string): Promise => {
+const passwordResetRequest = async (password: string, token: string): Promise => {
const res = await fetch(PASSWORDRESETURL, {
method: 'POST',
headers: {
From a073513f9328eb52560224f969181d0cb376e7c2 Mon Sep 17 00:00:00 2001
From: Yulia Berezhnaya
Date: Sun, 2 Apr 2023 22:31:00 +0300
Subject: [PATCH 09/13] =?UTF-8?q?=D0=A2=D0=B8=D0=BF=D0=B8=D0=B7=D0=B0?=
=?UTF-8?q?=D1=86=D0=B8=D1=8F=20=D1=87=D0=B0=D1=81=D1=82=D0=B8=20=D0=BA?=
=?UTF-8?q?=D0=BE=D0=BC=D0=BF=D0=BE=D0=BD=D0=B5=D0=BD=D1=82=D0=BE=D0=B2?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/components/App/{App.js => App.tsx} | 12 +++----
...erConstructor.js => BurgerConstructor.tsx} | 19 +++++-----
...erIngredients.js => BurgerIngredients.tsx} | 26 ++++++++------
.../{Ingredient.js => Ingredient.tsx} | 36 +++++++++----------
...ientCategory.js => IngredientCategory.tsx} | 30 ++++++++--------
...edientDetails.js => IngredientDetails.tsx} | 2 +-
...dientPreview.jsx => IngredientPreview.tsx} | 5 +--
src/components/Modal/Modal.tsx | 2 +-
.../OrderAccepted/OrderAccepted.jsx | 2 +-
src/components/OrderSnippet/OrderSnippet.jsx | 2 +-
src/components/Orders/Orders.js | 2 +-
src/components/TotalPrice/TotalPrice.tsx | 7 ++--
src/services/reducers/index.tsx | 35 +++++++++---------
src/services/types/index.tsx | 10 +++++-
src/services/types/ingredients.tsx | 3 ++
src/utils/constants.tsx | 8 ++---
16 files changed, 108 insertions(+), 93 deletions(-)
rename src/components/App/{App.js => App.tsx} (93%)
rename src/components/BurgerConstructor/{BurgerConstructor.js => BurgerConstructor.tsx} (84%)
rename src/components/BurgerIngredients/{BurgerIngredients.js => BurgerIngredients.tsx} (77%)
rename src/components/Ingredient/{Ingredient.js => Ingredient.tsx} (63%)
rename src/components/IngredientCategory/{IngredientCategory.js => IngredientCategory.tsx} (67%)
rename src/components/IngredientDetails/{IngredientDetails.js => IngredientDetails.tsx} (96%)
rename src/components/IngredientPreview/{IngredientPreview.jsx => IngredientPreview.tsx} (83%)
diff --git a/src/components/App/App.js b/src/components/App/App.tsx
similarity index 93%
rename from src/components/App/App.js
rename to src/components/App/App.tsx
index 9f9f38b..2f121dc 100644
--- a/src/components/App/App.js
+++ b/src/components/App/App.tsx
@@ -1,8 +1,8 @@
import AppStyles from './App.module.css';
-import React, { useEffect } from 'react';
+import { useEffect } from 'react';
import { Routes, Route, useLocation, useNavigate } from 'react-router-dom';
-import { useSelector, useDispatch } from 'react-redux';
+import { useSelector, useDispatch } from '../../services/hooks';
import { WS_STATUS_ONLINE } from '../../utils/constants';
@@ -12,7 +12,7 @@ import ProtectedRoute from '../ProtectedRoute/ProtectedRoute';
import Orders from '../Orders/Orders';
-import { LoginPage } from '../../pages/login.tsx';
+import { LoginPage } from '../../pages/login';
import { RegisterPage } from '../../pages/register';
import { ForgotPasswordPage } from '../../pages/forgotPassword';
import { ResetPasswordPage } from '../../pages/resetPassword';
@@ -28,16 +28,14 @@ import { getUser } from '../../services/actions/user';
function App() {
const dispatch = useDispatch();
-
const history = useNavigate();
-
const location = useLocation();
const modalBackground = location.state?.modalBackground;
const { ingredientsByType } = useSelector(state => state.menu);
- const { orders } = useSelector(({ status, feed }) => (
- status === WS_STATUS_ONLINE && feed?.success ? feed : {}
+ const { orders } = useSelector(({ws}) => (
+ ws.status === WS_STATUS_ONLINE && ws.feed?.success ? ws.feed : { orders: []}
));
useEffect(() => {
diff --git a/src/components/BurgerConstructor/BurgerConstructor.js b/src/components/BurgerConstructor/BurgerConstructor.tsx
similarity index 84%
rename from src/components/BurgerConstructor/BurgerConstructor.js
rename to src/components/BurgerConstructor/BurgerConstructor.tsx
index a6b6c89..96e5d7b 100644
--- a/src/components/BurgerConstructor/BurgerConstructor.js
+++ b/src/components/BurgerConstructor/BurgerConstructor.tsx
@@ -1,8 +1,9 @@
+import { FC } from 'react';
import BurgerConstructorStyles from './BurgerConstructor.module.css';
-import { useDispatch, useSelector } from 'react-redux';
+import { useDispatch, useSelector } from '../../services/hooks';
import PropTypes from 'prop-types';
-import { useDrop } from 'react-dnd';
+import { useDrop, DropTargetMonitor } from 'react-dnd';
import { ConstructorElement, Button } from '@ya.praktikum/react-developer-burger-ui-components';
import TotalPrice from '../TotalPrice/TotalPrice';
@@ -11,14 +12,15 @@ import Ingredient from '../Ingredient/Ingredient';
import { sendOrder } from '../../services/actions/ingredients';
import { ADD_BUN, ADD_INGREDIENT } from '../../utils/constants';
import { useNavigate } from 'react-router-dom';
+import { TIngredientList } from '../../services/types/ingredients';
-function BurgerConstructor({ openOrderDetailsModal }) {
+const BurgerConstructor: FC<{openOrderDetailsModal: () => void}> = ({ openOrderDetailsModal }) => {
const dispatch = useDispatch();
const navigate = useNavigate();
- const {addedIngredients, ingredientsById} = useSelector(state => state.menu);
- const {isAuthSuccess} = useSelector(state => state.user);
+ const { addedIngredients, ingredientsById } = useSelector(state => state.menu);
+ const { isAuthSuccess } = useSelector(state => state.user);
const ingredientIds = () => {
let res = addedIngredients.bun ? [addedIngredients.bun._id] : [];
@@ -43,13 +45,12 @@ function BurgerConstructor({ openOrderDetailsModal }) {
}
}
- const [{isHover}, dropTarget] = useDrop({
+ const [{ isHover }, dropTarget] = useDrop({
accept: 'ingredient',
- item: {},
- collect: monitor => ({
+ collect: (monitor: DropTargetMonitor) => ({
isHover: monitor.isOver()
}),
- drop(item) {
+ drop(item: TIngredientList) {
const type = ingredientsById[item.id].type === 'bun' ? ADD_BUN : ADD_INGREDIENT;
dispatch({type: type, id: item.id})
},
diff --git a/src/components/BurgerIngredients/BurgerIngredients.js b/src/components/BurgerIngredients/BurgerIngredients.tsx
similarity index 77%
rename from src/components/BurgerIngredients/BurgerIngredients.js
rename to src/components/BurgerIngredients/BurgerIngredients.tsx
index 192d380..73ebf80 100644
--- a/src/components/BurgerIngredients/BurgerIngredients.js
+++ b/src/components/BurgerIngredients/BurgerIngredients.tsx
@@ -1,6 +1,7 @@
+import { FC, Ref } from 'react';
import BurgerIngredientsStyles from './BurgerIngredients.module.css';
-import { useDispatch, useSelector } from 'react-redux';
+import { useDispatch, useSelector } from '../../services/hooks';
import PropTypes from 'prop-types';
import { useInView } from 'react-intersection-observer';
@@ -10,19 +11,24 @@ import IngredientCategory from '../IngredientCategory/IngredientCategory';
import { SET_ACTIVE_TAB } from '../../utils/constants';
+type TCategoriesTitles = {
+ bun: string;
+ main: string;
+ sauce: string;
+}
-function BurgerIngredients({ openIngredientModal }) {
+const BurgerIngredients: FC<{ openIngredientModal: () => void }> = ({ openIngredientModal }) => {
const dispatch = useDispatch();
const { ingredientsByType, activeTab } = useSelector(state => state.menu);
- const categoriesTitles = {
- 'bun': 'Булки',
- 'main': 'Начинки',
- 'sauce': 'Соусы'
+ const categoriesTitles: TCategoriesTitles = {
+ bun: 'Булки',
+ main: 'Начинки',
+ sauce: 'Соусы'
}
- const [bunsRef, inViewBuns] = useInView({
+ const [bunRef, inViewBun] = useInView({
threshold: 0.3
});
@@ -33,13 +39,13 @@ function BurgerIngredients({ openIngredientModal }) {
threshold: 0.3
});
- const categoriesOrder = [
- {name: 'bun', ref: bunsRef, inView: inViewBuns},
+ const categoriesOrder: Array<{name: keyof TCategoriesTitles; ref: Ref; inView: boolean}> = [
+ {name: 'bun', ref: bunRef, inView: inViewBun},
{name: 'main', ref: mainsRef, inView: inViewFilling},
{name: 'sauce', ref: saucesRef, inView: inViewSauces}
];
- const setActiveTab = (name) => {
+ const setActiveTab = (name: string) => {
dispatch({type: SET_ACTIVE_TAB, name})
}
diff --git a/src/components/Ingredient/Ingredient.js b/src/components/Ingredient/Ingredient.tsx
similarity index 63%
rename from src/components/Ingredient/Ingredient.js
rename to src/components/Ingredient/Ingredient.tsx
index 69c0dd8..b9929ea 100644
--- a/src/components/Ingredient/Ingredient.js
+++ b/src/components/Ingredient/Ingredient.tsx
@@ -1,26 +1,28 @@
import IngredientStyles from './Ingredient.module.css';
-import React, { useRef } from 'react';
-import { useDispatch, useSelector } from 'react-redux';
-import PropTypes from 'prop-types';
-import { useDrag, useDrop } from 'react-dnd';
+import { useRef, FC, BaseSyntheticEvent, MouseEvent } from 'react';
+import { useDispatch, useSelector } from '../../services/hooks';
+import { useDrag, useDrop, DropTargetMonitor } from 'react-dnd';
import { DragIcon, ConstructorElement } from '@ya.praktikum/react-developer-burger-ui-components';
import { CHANGE_INGREDIENT_ORDER, DELETE_INGREDIENT } from '../../utils/constants';
+import { TIngredientList } from '../../services/types/ingredients';
-
-function Ingredient({id, index}) {
+const Ingredient: FC = ({id, index}) => {
const dispatch = useDispatch();
- const ref = useRef(null);
+ const ref = useRef(null);
- const {ingredientsById} = useSelector(state => state.menu);
+ const { ingredientsById } = useSelector(state => state.menu);
- const moveItem = (prevIndex, newIndex) => {
- dispatch({type: CHANGE_INGREDIENT_ORDER, prevId: prevIndex, newId: newIndex});
+ const moveItem = (prevIndex: number, newIndex: number) => {
+ dispatch({type: CHANGE_INGREDIENT_ORDER, prevIndex, newIndex});
}
- const handleDeleteIngredient = (e) => {
- const targetElement = e.target.parentNode.parentNode;
+ // TODO
+ const handleDeleteIngredient = (e: MouseEvent) => {
+ console.log('e', e.target);
+ const targetElement = (e.target as HTMLLIElement).parentNode?.parentNode as HTMLElement;
+
if (targetElement.classList.contains('constructor-element__action')) {
dispatch({type: DELETE_INGREDIENT, index: e.currentTarget.id});
}
@@ -29,7 +31,7 @@ function Ingredient({id, index}) {
const [, dropRef] = useDrop({
accept: 'sortIngregient',
- hover(item, monitor) {
+ hover(item: TIngredientList, monitor: DropTargetMonitor) {
if (!ref.current) {
return
}
@@ -42,6 +44,7 @@ function Ingredient({id, index}) {
const hoverBoundingRect = ref.current?.getBoundingClientRect()
const hoverMiddleY = (hoverBoundingRect.bottom - hoverBoundingRect.top) / 2;
const clientOffset = monitor.getClientOffset();
+ if (!clientOffset) return;
const hoverClientY = clientOffset.y - hoverBoundingRect.top;
if (dragIndex < hoverIndex && hoverClientY < hoverMiddleY) {
@@ -71,7 +74,7 @@ function Ingredient({id, index}) {
dragRef(dropRef(ref));
return (
-
+
;
+ openIngredientModal: () => void;
+ link: Ref;
+ inView: boolean;
+}
-function IngredientCategory({ id, title, data, openIngredientModal, link, inView }) {
+const IngredientCategory: FC = ({ id, title, data, openIngredientModal, link, inView }) => {
const dispatch = useDispatch();
const { addedIngredients } = useSelector(store => store.menu);
const ingredientsCount = useMemo(() => {
- return data?.reduce((res, item) => {
+ return data?.reduce((res: {[name: string]: { count?: number}}, item) => {
res[item._id] = {};
if (item.type === 'bun' && item._id === addedIngredients.bun?._id) {
res[item._id].count = 1;
@@ -51,13 +58,4 @@ function IngredientCategory({ id, title, data, openIngredientModal, link, inView
);
}
-// IngredientCategory.propTypes = {
-// id: PropTypes.string.isRequired,
-// title: PropTypes.string.isRequired,
-// data: PropTypes.arrayOf(IngredientsPropTypes).isRequired,
-// openIngredientModal: PropTypes.func.isRequired,
-// link: PropTypes.func.isRequired,
-// inView: PropTypes.bool.isRequired
-// }
-
export default IngredientCategory;
diff --git a/src/components/IngredientDetails/IngredientDetails.js b/src/components/IngredientDetails/IngredientDetails.tsx
similarity index 96%
rename from src/components/IngredientDetails/IngredientDetails.js
rename to src/components/IngredientDetails/IngredientDetails.tsx
index f08bf2d..95737e2 100644
--- a/src/components/IngredientDetails/IngredientDetails.js
+++ b/src/components/IngredientDetails/IngredientDetails.tsx
@@ -1,6 +1,6 @@
import IngredientDetailsStyles from './IngredientDetails.module.css';
-import { useDispatch, useSelector } from 'react-redux';
+import { useDispatch, useSelector } from '../../services/hooks';
import { useParams } from 'react-router-dom';
import { SHOW_INGREDIENT } from '../../utils/constants';
diff --git a/src/components/IngredientPreview/IngredientPreview.jsx b/src/components/IngredientPreview/IngredientPreview.tsx
similarity index 83%
rename from src/components/IngredientPreview/IngredientPreview.jsx
rename to src/components/IngredientPreview/IngredientPreview.tsx
index 85dd410..eca5e92 100644
--- a/src/components/IngredientPreview/IngredientPreview.jsx
+++ b/src/components/IngredientPreview/IngredientPreview.tsx
@@ -1,8 +1,9 @@
import IngredientPreviewStyles from './IngredientPreview.module.css';
-import { useSelector } from 'react-redux';
+import { FC } from 'react';
+import { useSelector } from '../../services/hooks';
-function IngredientPreview({ id, hidedLength }) {
+const IngredientPreview: FC<{id: string; hidedLength: number}> = ({ id, hidedLength }) => {
const { ingredientsById } = useSelector((state) => state.menu);
return (
diff --git a/src/components/Modal/Modal.tsx b/src/components/Modal/Modal.tsx
index 72e5ae9..9316f21 100644
--- a/src/components/Modal/Modal.tsx
+++ b/src/components/Modal/Modal.tsx
@@ -7,7 +7,7 @@ import { CloseIcon } from '@ya.praktikum/react-developer-burger-ui-components';
const modalsContainer = document.querySelector('#modals') as HTMLElement;
type TModalProps = {
- title: string;
+ title?: string;
onClose: () => void;
children: ReactNode;
}
diff --git a/src/components/OrderAccepted/OrderAccepted.jsx b/src/components/OrderAccepted/OrderAccepted.jsx
index cb42103..24bc626 100644
--- a/src/components/OrderAccepted/OrderAccepted.jsx
+++ b/src/components/OrderAccepted/OrderAccepted.jsx
@@ -1,6 +1,6 @@
import OrderAcceptedStyles from './OrderAccepted.module.css';
-import { useSelector } from 'react-redux';
+import { useSelector } from '../../services/hooks';
import done from '../../images/done.svg';
diff --git a/src/components/OrderSnippet/OrderSnippet.jsx b/src/components/OrderSnippet/OrderSnippet.jsx
index bb4b40c..18a9ac8 100644
--- a/src/components/OrderSnippet/OrderSnippet.jsx
+++ b/src/components/OrderSnippet/OrderSnippet.jsx
@@ -1,7 +1,7 @@
import OrderSnippetStyles from './OrderSnippet.module.css';
import { Link, useLocation } from 'react-router-dom';
-import { useSelector } from 'react-redux';
+import { useSelector } from '../../services/hooks';
import { CurrencyIcon } from '@ya.praktikum/react-developer-burger-ui-components';
import IngredientPreview from '../IngredientPreview/IngredientPreview';
diff --git a/src/components/Orders/Orders.js b/src/components/Orders/Orders.js
index 2645218..97813f3 100644
--- a/src/components/Orders/Orders.js
+++ b/src/components/Orders/Orders.js
@@ -9,7 +9,7 @@ import OrderSnippet from '../OrderSnippet/OrderSnippet';
function Orders() {
const dispatch = useDispatch();
const { total, totalToday, orders } = useSelector(({ws}) => (
- ws.status === WS_STATUS_ONLINE && ws.feed.success ? ws.feed : {}
+ ws.status === WS_STATUS_ONLINE && ws.feed.success ? ws.feed : {orders: []}
));
const ordersByStatus = orders?.length && orders.reduce((res, item) => {
diff --git a/src/components/TotalPrice/TotalPrice.tsx b/src/components/TotalPrice/TotalPrice.tsx
index 156e0dd..a44bae9 100644
--- a/src/components/TotalPrice/TotalPrice.tsx
+++ b/src/components/TotalPrice/TotalPrice.tsx
@@ -1,19 +1,20 @@
import TotalPriceStyles from './TotalPrice.module.css';
import { useMemo, FC } from 'react';
-import { useSelector } from 'react-redux';
+import { useSelector } from '../../services/hooks';
import { TRootState } from '../../services/types/index';
import { CurrencyIcon } from '@ya.praktikum/react-developer-burger-ui-components';
import { TMenuState } from '../../services/reducers';
+import { TIngredient } from '../../services/types/ingredients';
const TotalPrice: FC = () => {
const { addedIngredients: { bun, others } }: TMenuState = useSelector((state: TRootState) => state.menu);
const total = useMemo(() => (
- others.reduce(
- (res, {price}) => res += price,
+ (others as TIngredient[]).reduce(
+ (res: number, {price}: TIngredient) => res += price,
bun ? bun.price * 2 : 0
)), [bun, others]);
diff --git a/src/services/reducers/index.tsx b/src/services/reducers/index.tsx
index 3134a77..d297548 100644
--- a/src/services/reducers/index.tsx
+++ b/src/services/reducers/index.tsx
@@ -19,26 +19,29 @@ import {
import { TIngredientsByType, TIngredientsById, TIngredient } from '../types/ingredients';
import { TIngredientsAction } from '../types/ingredients';
+
+type TAddedIngredients = {
+ bun: TIngredient | null;
+ others: Array | [];
+}
+
export type TMenuState = {
- ingredientsByType: {} & TIngredientsByType ,
- ingredientsById: {} & TIngredientsById,
- ingredientsRequest: boolean,
- ingredientsFailed: boolean,
+ ingredientsByType: TIngredientsByType;
+ ingredientsById: TIngredientsById;
+ ingredientsRequest: boolean;
+ ingredientsFailed: boolean;
- addedIngredients: {
- bun: TIngredient | null,
- others: Array
- },
- currentIngredient: string | null,
+ addedIngredients: TAddedIngredients;
+ currentIngredient: null | TIngredient;
- activeTab: 'bun' | 'main' | 'sauce',
+ activeTab: string;
- orderId: number | null,
- orderRequest: boolean,
- orderFailed: boolean
+ orderId: number | null;
+ orderRequest: boolean;
+ orderFailed: boolean;
}
-const initialMenuState: TMenuState = {
+const initialMenuState = {
ingredientsByType: {},
ingredientsById: {},
ingredientsRequest: false,
@@ -46,7 +49,7 @@ const initialMenuState: TMenuState = {
addedIngredients: {
bun: null,
- others: []
+ others: [],
},
currentIngredient: null,
@@ -59,7 +62,7 @@ const initialMenuState: TMenuState = {
let uniqId = 0;
-export const ingredientsReducer = (state: TMenuState = initialMenuState, action: TIngredientsAction) => {
+export const ingredientsReducer = (state: TMenuState = initialMenuState, action: TIngredientsAction): TMenuState => {
switch (action.type) {
case GET_INGREDIENTS_REQUEST: {
return {
diff --git a/src/services/types/index.tsx b/src/services/types/index.tsx
index e7a1aa8..ffe68a3 100644
--- a/src/services/types/index.tsx
+++ b/src/services/types/index.tsx
@@ -4,8 +4,16 @@ import { store } from '../store';
import { TIngredientsAction } from '../types/ingredients';
import { TUserActions } from './user';
import { TWSAction } from '../types/ws';
+import { TMenuState } from '../reducers';
+import { TUserState } from '../reducers/user';
+import { TWSState } from '../reducers/ws';
-export type TRootState = ReturnType
+// export type TRootState = ReturnType
+export type TRootState = {
+ menu: TMenuState;
+ user: TUserState;
+ ws: TWSState;
+};
// Типизация всех экшенов приложения
type TApplicationActions = TIngredientsAction | TUserActions | TWSAction;
diff --git a/src/services/types/ingredients.tsx b/src/services/types/ingredients.tsx
index 95632cb..34590bf 100644
--- a/src/services/types/ingredients.tsx
+++ b/src/services/types/ingredients.tsx
@@ -29,6 +29,7 @@ export type TIngredient = {
image_mobile: string;
image_large: string;
__v?: number;
+ key?: number;
};
export type TIngredientsByType = {
@@ -147,3 +148,5 @@ export type TIngredientsAction =
| IAddBun
| IChangeOrderIngredients
| ISetActiveTab;
+
+export type TIngredientList = {id: string, index: number};
diff --git a/src/utils/constants.tsx b/src/utils/constants.tsx
index c9ee3a6..3d87810 100644
--- a/src/utils/constants.tsx
+++ b/src/utils/constants.tsx
@@ -15,11 +15,7 @@ export const GET_USER_ORDERS_URL = WSURL + '/orders';
export const WS_STATUS_OFFLINE: 'OFFLINE' = 'OFFLINE';
export const WS_STATUS_ONLINE: 'ONLINE' = 'ONLINE';
export const WS_STATUS_CONNECTING: 'CONNECTING...' = 'CONNECTING...';
-// export const WS_STATUS = {
-// CONNECTING : 'CONNECTING...',
-// ONLINE : 'ONLINE',
-// OFFLINE : 'OFFLINE'
-// }
+
export const WS_MESSAGE: 'WS_MESSAGE' = 'WS_MESSAGE';
export const WS_CONNECT: 'WS_CONNECT' = 'WS_CONNECT';
export const WS_DISCONNECT: 'WS_DISCONNECT' = 'WS_DISCONNECT';
@@ -28,6 +24,8 @@ export const WS_OPEN: 'WS_OPEN' = 'WS_OPEN';
export const WS_CLOSE: 'WS_CLOSE' = 'WS_CLOSE';
export const WS_ERROR: 'WS_ERROR' = 'WS_ERROR';
+// export const CATEGORIES_TITLES: 'bun' | 'main' | 'sauce' = ;
+
// Константы для обработки запроса для получения всех ингридиентов
export const GET_INGREDIENTS_REQUEST: 'GET_INGREDIENTS_REQUEST' = 'GET_INGREDIENTS_REQUEST';
export const GET_INGREDIENTS_SUCCESS: 'GET_INGREDIENTS_SUCCESS' = 'GET_INGREDIENTS_SUCCESS';
From 6526381a9485585f1c42d7f54da537f769ef3d0c Mon Sep 17 00:00:00 2001
From: Yulia Berezhnaya
Date: Sun, 2 Apr 2023 23:46:25 +0300
Subject: [PATCH 10/13] =?UTF-8?q?=D0=A2=D0=B8=D0=BF=D0=B8=D0=B7=D0=B0?=
=?UTF-8?q?=D1=86=D0=B8=D1=8F=20=D0=BA=D0=BE=D0=BC=D0=BF=D0=BE=D0=BD=D0=B5?=
=?UTF-8?q?=D0=BD=D1=82=D0=BE=D0=B2=20=D0=B4=D0=BB=D1=8F=20=D0=BE=D1=82?=
=?UTF-8?q?=D0=BE=D0=B1=D1=80=D0=B0=D0=B6=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=B7?=
=?UTF-8?q?=D0=B0=D0=BA=D0=B0=D0=B7=D0=BE=D0=B2?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../IngredientPreview/IngredientPreview.tsx | 2 +-
src/components/ModalOverlay/ModalOverlay.tsx | 2 +-
.../{OrderAccepted.jsx => OrderAccepted.tsx} | 3 +-
.../{OrderDetails.js => OrderDetails.tsx} | 39 ++++++++++++-------
.../{OrderSnippet.jsx => OrderSnippet.tsx} | 11 +++++-
.../Orders/{Orders.js => Orders.tsx} | 33 +++++++++-------
src/services/types/order.tsx | 5 ++-
src/utils/constants.tsx | 3 +-
src/utils/date.tsx | 2 +-
9 files changed, 64 insertions(+), 36 deletions(-)
rename src/components/OrderAccepted/{OrderAccepted.jsx => OrderAccepted.tsx} (94%)
rename src/components/OrderDetails/{OrderDetails.js => OrderDetails.tsx} (77%)
rename src/components/OrderSnippet/{OrderSnippet.jsx => OrderSnippet.tsx} (91%)
rename src/components/Orders/{Orders.js => Orders.tsx} (70%)
diff --git a/src/components/IngredientPreview/IngredientPreview.tsx b/src/components/IngredientPreview/IngredientPreview.tsx
index eca5e92..ba1708d 100644
--- a/src/components/IngredientPreview/IngredientPreview.tsx
+++ b/src/components/IngredientPreview/IngredientPreview.tsx
@@ -3,7 +3,7 @@ import IngredientPreviewStyles from './IngredientPreview.module.css';
import { FC } from 'react';
import { useSelector } from '../../services/hooks';
-const IngredientPreview: FC<{id: string; hidedLength: number}> = ({ id, hidedLength }) => {
+const IngredientPreview: FC<{id: string; hidedLength?: number, key?: number}> = ({ id, hidedLength, key }) => {
const { ingredientsById } = useSelector((state) => state.menu);
return (
diff --git a/src/components/ModalOverlay/ModalOverlay.tsx b/src/components/ModalOverlay/ModalOverlay.tsx
index a46c1ec..2494911 100644
--- a/src/components/ModalOverlay/ModalOverlay.tsx
+++ b/src/components/ModalOverlay/ModalOverlay.tsx
@@ -5,7 +5,7 @@ type TModalProps = {
onClick: () => void;
}
-const ModalOverlay: FC = ({onClick}) => {
+const ModalOverlay: FC = ({ onClick }) => {
return (
diff --git a/src/components/OrderAccepted/OrderAccepted.jsx b/src/components/OrderAccepted/OrderAccepted.tsx
similarity index 94%
rename from src/components/OrderAccepted/OrderAccepted.jsx
rename to src/components/OrderAccepted/OrderAccepted.tsx
index 24bc626..7f0855e 100644
--- a/src/components/OrderAccepted/OrderAccepted.jsx
+++ b/src/components/OrderAccepted/OrderAccepted.tsx
@@ -1,10 +1,11 @@
+import { FC } from 'react';
import OrderAcceptedStyles from './OrderAccepted.module.css';
import { useSelector } from '../../services/hooks';
import done from '../../images/done.svg';
-function OrderAccepted() {
+const OrderAccepted: FC = () => {
const {orderId, orderRequest, orderFailed} = useSelector(state => state.menu);
return (
diff --git a/src/components/OrderDetails/OrderDetails.js b/src/components/OrderDetails/OrderDetails.tsx
similarity index 77%
rename from src/components/OrderDetails/OrderDetails.js
rename to src/components/OrderDetails/OrderDetails.tsx
index f7cd88f..c1f0d76 100644
--- a/src/components/OrderDetails/OrderDetails.js
+++ b/src/components/OrderDetails/OrderDetails.tsx
@@ -1,30 +1,40 @@
import OrderDetailsStyles from './OrderDetails.module.css';
-import { useEffect } from 'react';
-import { useDispatch, useSelector } from 'react-redux';
+import { useEffect, FC } from 'react';
+import { useDispatch, useSelector } from '../../services/hooks';
import { useLocation, useParams } from 'react-router-dom';
import IngredientPreview from '../IngredientPreview/IngredientPreview';
import { CurrencyIcon } from '@ya.praktikum/react-developer-burger-ui-components';
-import { ORDER_STATUSES, GET_ALL_ORDERS_URL, GET_USER_ORDERS_URL } from '../../utils/constants';
+import { ORDER_STATUSES, GET_ALL_ORDERS_URL, GET_USER_ORDERS_URL, WS_STATUS_ONLINE } from '../../utils/constants';
import { wsConnect, wsDisconnect } from '../../services/actions/ws';
import { getFormattedDate } from '../../utils/date';
import { getCookie } from '../../utils/cookie';
+import { TFeedData } from '../../services/types/order';
-function OrderDetails() {
+type TIngredientCounts = {
+ total: number;
+ ingredients: {
+ [name: string]: number;
+ }
+}
+
+const OrderDetails: FC = () => {
const dispatch = useDispatch();
const location = useLocation();
- const { orders } = useSelector(state => state.ws.feed);
+ const { orders } = useSelector(({ ws }) => (
+ ws.status === WS_STATUS_ONLINE && ws.feed.success ? ws.feed as TFeedData : {orders: [], total: 0, totalToday: 0}
+ ));
const { ingredientsById } = useSelector(state => state.menu);
const { orderId } = useParams();
const token = getCookie('accessToken');
let fullPageClass = location.state ? '' : 'fullPage';
- const currentOrder = orders?.find((el) => {
+ const currentOrder = orders.find((el) => {
return el._id === orderId;
});
- const ingredientCounts = currentOrder?.ingredients.reduce((res, item) => {
+ const ingredientCounts: TIngredientCounts | undefined = currentOrder ? currentOrder.ingredients.reduce((res: TIngredientCounts, item) => {
if (item) {
if (!res.ingredients[item]) {
res.ingredients[item] = 0
@@ -35,7 +45,7 @@ function OrderDetails() {
}
return res;
- }, {total: 0, ingredients: {}});
+ }, {total: 0, ingredients: {}}) : undefined;
useEffect(() => {
if (!orders && location.pathname.includes('/feed')) {
@@ -46,17 +56,18 @@ function OrderDetails() {
dispatch(wsConnect(`${GET_USER_ORDERS_URL}?token=${token}`));
}
- return () => {
- if (!location.state) {
- return dispatch(wsDisconnect());
- }
- };
+ return () => { dispatch(wsDisconnect()); }
+ // return () => {
+ // if (!location.state) {
+ // return dispatch(wsDisconnect());
+ // }
+ // };
}, [dispatch])
return (
<>
{ !currentOrder &&
= ({ order, needDetails, link }) => {
const location = useLocation();
const { ingredientsById } = useSelector(state => state.menu);
@@ -26,7 +34,6 @@ function OrderSnippet({ order, needDetails, link }) {
return res;
}, {hidedLength: order.ingredients.length - 6, maxLength: 6, ingredients: []});
- // console.log('OrderSnippet location', location);
return (
Загрузка
-} + } + if (isAuthPage && isAuthSuccess) { returnОбрабатываем запрос
} - { currentOrder && + { currentOrder && ingredientCounts &&#{currentOrder.number}
{currentOrder.name}
diff --git a/src/components/OrderSnippet/OrderSnippet.jsx b/src/components/OrderSnippet/OrderSnippet.tsx similarity index 91% rename from src/components/OrderSnippet/OrderSnippet.jsx rename to src/components/OrderSnippet/OrderSnippet.tsx index 18a9ac8..2576ee3 100644 --- a/src/components/OrderSnippet/OrderSnippet.jsx +++ b/src/components/OrderSnippet/OrderSnippet.tsx @@ -1,3 +1,4 @@ +import { FC } from 'react'; import OrderSnippetStyles from './OrderSnippet.module.css'; import { Link, useLocation } from 'react-router-dom'; @@ -7,8 +8,15 @@ import { CurrencyIcon } from '@ya.praktikum/react-developer-burger-ui-components import IngredientPreview from '../IngredientPreview/IngredientPreview'; import { ORDER_STATUSES } from '../../utils/constants'; import { getFormattedDate } from '../../utils/date'; +import { TOrder } from '../../services/types/order'; -function OrderSnippet({ order, needDetails, link }) { +type TOrderSnippet = { + order: TOrder; + needDetails?: boolean; + link: string; +} + +const OrderSnippet: FC
diff --git a/src/components/Orders/Orders.js b/src/components/Orders/Orders.tsx
similarity index 70%
rename from src/components/Orders/Orders.js
rename to src/components/Orders/Orders.tsx
index 97813f3..97bebb4 100644
--- a/src/components/Orders/Orders.js
+++ b/src/components/Orders/Orders.tsx
@@ -1,32 +1,39 @@
import OrdersStyles from './Orders.module.css';
import { GET_ALL_ORDERS_URL, WS_STATUS_ONLINE } from '../../utils/constants';
import { wsConnect, wsDisconnect } from '../../services/actions/ws';
-import { useEffect } from 'react';
-import { useDispatch, useSelector } from 'react-redux';
+import { useEffect, FC } from 'react';
+import { useDispatch, useSelector } from '../../services/hooks';
import OrderSnippet from '../OrderSnippet/OrderSnippet';
+import { TFeedData, TOrder } from '../../services/types/order';
+type TOrdersByStatus = {
+ done: Array;
+ progress: Array;
+ created: Array;
+ cancelled: Array;
+};
-function Orders() {
+const Orders: FC = () => {
const dispatch = useDispatch();
- const { total, totalToday, orders } = useSelector(({ws}) => (
- ws.status === WS_STATUS_ONLINE && ws.feed.success ? ws.feed : {orders: []}
+ const { total, totalToday, orders } = useSelector(({ ws }) => (
+ ws.status === WS_STATUS_ONLINE && ws.feed.success ? ws.feed as TFeedData : {orders: [], total: 0, totalToday: 0}
));
- const ordersByStatus = orders?.length && orders.reduce((res, item) => {
+ const ordersByStatus: TOrdersByStatus | undefined = orders?.length ? (orders as Array).reduce((res: TOrdersByStatus, item) => {
if (res[item.status].length < 20) {
res[item.status].push(item);
}
return res;
- }, {done: [], progress: [], created: []});
+ }, {done: [], progress: [], created: [], cancelled: []}) : undefined;
- const columnCountDone = Math.floor(ordersByStatus?.done.length / 10);
- const columnCountProgress = Math.floor(ordersByStatus?.progress.length / 10);
+ const columnCountDone = (ordersByStatus && ordersByStatus.done.length > 10 )? Math.floor(ordersByStatus.done.length / 10) : 1;
+ const columnCountProgress = (ordersByStatus && ordersByStatus.progress.length > 10 )? Math.floor(ordersByStatus.progress.length / 10) : 1;
useEffect(() => {
dispatch(wsConnect(GET_ALL_ORDERS_URL));
- return () => dispatch(wsDisconnect());
+ return () => { dispatch(wsDisconnect()); }
}, [dispatch])
return (
@@ -35,7 +42,7 @@ function Orders() {
{orders &&
orders.map((item, index) => {
- return
+ return
})
}
@@ -43,7 +50,7 @@ function Orders() {
Готовы:
--
+
- {item.number} @@ -53,7 +60,7 @@ function Orders() {
-
{ordersByStatus && ordersByStatus.done.map((item, index) => {
return (
В работе:
--
+
- {item.number} diff --git a/src/services/types/order.tsx b/src/services/types/order.tsx index 799e588..bde6c29 100644 --- a/src/services/types/order.tsx +++ b/src/services/types/order.tsx @@ -2,12 +2,13 @@ import { TIngredient } from "./ingredients"; export type TOrder = { _id: string; - status: string; + status: 'created' | 'done' | 'progress' | 'cancelled'; name: string; createdAt: Date | string; updatedAt: Date | string; number: number; - ingredients: Array
-
{ordersByStatus && ordersByStatus.progress.map((item, index) => {
return (