From 5b281e3eeffb30a2baeeb1c798c3044f2d976968 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=BB=D0=B0=D0=B4=D0=B8=D1=81=D0=BB=D0=B0=D0=B2=20?= =?UTF-8?q?=D0=9C=D0=B5=D0=B4=D0=B2=D0=B5=D0=B4=D0=B5=D0=B2=D1=81=D0=BA?= =?UTF-8?q?=D0=B8=D0=B9?= Date: Wed, 22 May 2024 22:39:46 +0500 Subject: [PATCH] hw 7.2, added temporal favorite-offer mock --- package-lock.json | 23 +++++- package.json | 3 +- src/components/app/app.tsx | 19 ++--- .../dropdown-offers-filter.tsx | 9 +-- src/components/header/header-navigation.tsx | 47 ++++++++---- .../offer/offer-card-list/offer-card-list.tsx | 2 +- src/components/offer/offer-host.tsx | 4 +- .../private-route/private-route.tsx | 20 ++--- src/const.ts | 2 + src/hooks/use-authorization.ts | 6 ++ src/index.tsx | 13 ++-- src/pages/favorites-page/favorites-page.tsx | 9 +-- src/pages/login-page/login-page.tsx | 75 +++++++++++++++++-- src/pages/offer-page/offer-page.tsx | 48 +++++++++--- src/services/api.ts | 40 +++++++++- src/services/error-handle.ts | 20 +++++ src/services/token.ts | 16 ++++ src/store/acions.ts | 6 ++ src/store/api-actions.ts | 62 +++++++++++++-- src/store/index.tsx | 1 + src/store/reducer.ts | 26 ++++++- src/types/auth-data.ts | 4 + src/types/offers/offer-detailed.ts | 4 +- src/types/review.ts | 4 +- src/types/user-data.ts | 12 +++ src/types/user.ts | 5 -- 26 files changed, 382 insertions(+), 98 deletions(-) create mode 100644 src/hooks/use-authorization.ts create mode 100644 src/services/error-handle.ts create mode 100644 src/services/token.ts create mode 100644 src/types/auth-data.ts create mode 100644 src/types/user-data.ts delete mode 100644 src/types/user.ts diff --git a/package-lock.json b/package-lock.json index 7329578..71ed144 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,7 +19,8 @@ "react-helmet-async": "1.3.0", "react-loader-spinner": "^6.1.6", "react-redux": "8.1.3", - "react-router-dom": "6.16.0" + "react-router-dom": "6.16.0", + "react-toastify": "^10.0.5" }, "devDependencies": { "@jedmao/redux-mock-store": "3.0.5", @@ -2438,6 +2439,14 @@ "node": ">=0.8.0" } }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "engines": { + "node": ">=6" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -5401,6 +5410,18 @@ "react-dom": ">=16.8" } }, + "node_modules/react-toastify": { + "version": "10.0.5", + "resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-10.0.5.tgz", + "integrity": "sha512-mNKt2jBXJg4O7pSdbNUfDdTsK9FIdikfsIE/yUCxbAEXl4HMyJaivrVFcn3Elvt5xvCQYhUZm+hqTIu1UXM3Pw==", + "dependencies": { + "clsx": "^2.1.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + } + }, "node_modules/read-pkg": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", diff --git a/package.json b/package.json index bb76fab..05f07f6 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,8 @@ "react-helmet-async": "1.3.0", "react-loader-spinner": "^6.1.6", "react-redux": "8.1.3", - "react-router-dom": "6.16.0" + "react-router-dom": "6.16.0", + "react-toastify": "^10.0.5" }, "devDependencies": { "@jedmao/redux-mock-store": "3.0.5", diff --git a/src/components/app/app.tsx b/src/components/app/app.tsx index 2477afa..d05969f 100644 --- a/src/components/app/app.tsx +++ b/src/components/app/app.tsx @@ -6,23 +6,16 @@ import PrivateRoute from '../private-route/private-route.tsx'; import FavoritesPage from '../../pages/favorites-page/favorites-page.tsx'; import OfferPage from '../../pages/offer-page/offer-page.tsx'; import NotFoundPage from '../../pages/not-found-page/not-found-page.tsx'; -import {OffersShort} from '../../types/offers/offer-short.ts'; -import {OffersDetailed} from '../../types/offers/offer-detailed.ts'; import {useAppSelector} from '../../hooks/redux.ts'; import LoadingSpinner from '../loading-spinner/loading-spinner.tsx'; -type AppProps = { - offersDetailed: OffersDetailed; - allFavorites: OffersShort; -} - -function App({offersDetailed, allFavorites}: AppProps): JSX.Element { +function App(): JSX.Element { const isOffersLoading = useAppSelector((state) => state.isOffersLoading); - + const authStatus = useAppSelector((state) => state.authorizationStatus); return ( <> - {isOffersLoading && } + {(isOffersLoading || authStatus === AuthStatus.Unknown) && } - + + } /> }/> } + element={} /> store.offers); - const currentSortingOrder = useAppSelector((store) => store.sortingOrder); + const offers = useAppSelector((state) => state.offers); + const currentSortingOrder = useAppSelector((state) => state.sortingOrder); const [dropdownIsOpen, setDropdownIsOpen] = useState(false); const handleSortingOnClick = () => setDropdownIsOpen((value) => !value); useEffect(() => { if (currentSortingOrder === SortingOrder.popular && offers.length !== 0) { - dispatch(fetchOffers()); + dispatch(fetchOffersAction()); } else if (offers.length !== 0) { dispatch(setOffers(offers.toSorted(SortComparers[currentSortingOrder]))); } diff --git a/src/components/header/header-navigation.tsx b/src/components/header/header-navigation.tsx index b44c96f..c8361e0 100644 --- a/src/components/header/header-navigation.tsx +++ b/src/components/header/header-navigation.tsx @@ -1,23 +1,44 @@ import {Link} from 'react-router-dom'; import {AppRoute} from '../../const.ts'; +import {useAuthorization} from '../../hooks/use-authorization.ts'; +import {useAppDispatch, useAppSelector} from '../../hooks/redux.ts'; +import {logoutAction} from '../../store/api-actions.ts'; function HeaderNavigation(): JSX.Element { + const isAuthorized = useAuthorization(); + const dispatch = useAppDispatch(); + const userData = useAppSelector((state) => state.userData); + + const handleLinkClick = () => { + dispatch(logoutAction()); + }; + return ( ); diff --git a/src/components/offer/offer-card-list/offer-card-list.tsx b/src/components/offer/offer-card-list/offer-card-list.tsx index b8011f6..9ab9438 100644 --- a/src/components/offer/offer-card-list/offer-card-list.tsx +++ b/src/components/offer/offer-card-list/offer-card-list.tsx @@ -32,7 +32,7 @@ function OfferCardList({cityName, offers, variant, offersCount}: OfferCardListPr
{isHeaderActive &&

{headerContent}

} {isFoundActive && {offersCount} places to stay in {cityName}} - {isFormActive && } + {isFormActive && }
); diff --git a/src/components/offer/offer-host.tsx b/src/components/offer/offer-host.tsx index f3b9473..dbd2a6f 100644 --- a/src/components/offer/offer-host.tsx +++ b/src/components/offer/offer-host.tsx @@ -1,7 +1,7 @@ -import {User} from '../../types/user.ts'; +import {UserData} from '../../types/user-data.ts'; type OfferHostProps = { - host: User; + host: UserData; description: string; } diff --git a/src/components/private-route/private-route.tsx b/src/components/private-route/private-route.tsx index c36fa04..1ad313b 100644 --- a/src/components/private-route/private-route.tsx +++ b/src/components/private-route/private-route.tsx @@ -1,20 +1,14 @@ import {Navigate} from 'react-router-dom'; import {AppRoute, AuthStatus} from '../../const'; -import {PropsWithChildren} from 'react'; +import {PropsWithChildren, ReactNode} from 'react'; +import {useAppSelector} from '../../hooks/redux.ts'; -type PrivateRouteProps = { - authorizationStatus: AuthStatus; - children: JSX.Element; -} - -function PrivateRoute(props: PropsWithChildren): JSX.Element { - const {authorizationStatus, children} = props; +function PrivateRoute({children}: PropsWithChildren): ReactNode { + const authorizationStatus = useAppSelector((state) => state.authorizationStatus); - return ( - authorizationStatus === AuthStatus.Auth - ? children - : - ); + return authorizationStatus === AuthStatus.Auth + ? children + : ; } export default PrivateRoute; diff --git a/src/const.ts b/src/const.ts index b832ea3..e0511fe 100644 --- a/src/const.ts +++ b/src/const.ts @@ -78,6 +78,8 @@ export enum AuthStatus { export enum APIRoute { Offers = '/offers', + Login = '/login', + Logout = '/logout', } export const SortComparers : Record number> = { diff --git a/src/hooks/use-authorization.ts b/src/hooks/use-authorization.ts new file mode 100644 index 0000000..189cacb --- /dev/null +++ b/src/hooks/use-authorization.ts @@ -0,0 +1,6 @@ +import {useAppSelector} from './redux.ts'; +import {AuthStatus} from '../const.ts'; + +export function useAuthorization() { + return useAppSelector((state) => state.authorizationStatus) === AuthStatus.Auth; +} diff --git a/src/index.tsx b/src/index.tsx index 02b38b8..3fae2e7 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -3,21 +3,22 @@ import ReactDOM from 'react-dom/client'; import App from './components/app/app.tsx'; import {Provider} from 'react-redux'; import {store} from './store'; -import {fetchOffers} from './store/api-actions.ts'; +import {checkAuthStatusAction, fetchOffersAction} from './store/api-actions.ts'; +import {ToastContainer} from 'react-toastify'; +import 'react-toastify/dist/ReactToastify.css'; const root = ReactDOM.createRoot( document.getElementById('root') as HTMLElement ); -store.dispatch(fetchOffers()); +store.dispatch(checkAuthStatusAction()); +store.dispatch(fetchOffersAction()); root.render( - + + ); diff --git a/src/pages/favorites-page/favorites-page.tsx b/src/pages/favorites-page/favorites-page.tsx index 7919f46..3a02cb6 100644 --- a/src/pages/favorites-page/favorites-page.tsx +++ b/src/pages/favorites-page/favorites-page.tsx @@ -2,13 +2,8 @@ import Header from '../../components/header/header.tsx'; import {Link} from 'react-router-dom'; import {AppRoute} from '../../const.ts'; import FavoritesList from '../../components/favorites-list/favorites-list.tsx'; -import {OffersShort} from '../../types/offers/offer-short.ts'; -type FavoritesPageProps = { - allFavorites: OffersShort; -} - -function FavoritesPage({ allFavorites } : FavoritesPageProps) : JSX.Element { +function FavoritesPage() : JSX.Element { return (
@@ -16,7 +11,7 @@ function FavoritesPage({ allFavorites } : FavoritesPageProps) : JSX.Element {

Saved listing

- +
diff --git a/src/pages/login-page/login-page.tsx b/src/pages/login-page/login-page.tsx index db2cfcf..4284d86 100644 --- a/src/pages/login-page/login-page.tsx +++ b/src/pages/login-page/login-page.tsx @@ -1,6 +1,44 @@ import Header from '../../components/header/header.tsx'; +import {AppRoute, CityObject} from '../../const.ts'; +import {Link, useNavigate} from 'react-router-dom'; +import {FormEvent, useRef} from 'react'; +import {useAppDispatch} from '../../hooks/redux.ts'; +import {loginAction} from '../../store/api-actions.ts'; +import {setActiveCity} from '../../store/acions.ts'; +import {useAuthorization} from '../../hooks/use-authorization.ts'; + +function LoginPage(): JSX.Element { + const loginRef = useRef(null); + const passwordRef = useRef(null); + + const dispatch = useAppDispatch(); + const navigate = useNavigate(); + + const cities = Object.values(CityObject); + const chosenCity = cities[Math.floor(Math.random() * cities.length)]; + + const isAuthorized = useAuthorization(); + + if (isAuthorized) { + navigate(AppRoute.Main); + } + + const handleLinkOnClick = () => { + dispatch(setActiveCity(chosenCity)); + }; + + const handleSubmit = (evt: FormEvent) => { + evt.preventDefault(); + + if (loginRef.current !== null && passwordRef.current !== null) { + dispatch(loginAction({ + login: loginRef.current.value, + password: passwordRef.current.value + })); + } + }; + -function LoginPage() : JSX.Element { return (
@@ -9,23 +47,44 @@ function LoginPage() : JSX.Element {

Sign in

-
+
- +
- +
- +
- - Amsterdam - + + {chosenCity.name} +
diff --git a/src/pages/offer-page/offer-page.tsx b/src/pages/offer-page/offer-page.tsx index 1569e55..aee299f 100644 --- a/src/pages/offer-page/offer-page.tsx +++ b/src/pages/offer-page/offer-page.tsx @@ -1,5 +1,4 @@ import Header from '../../components/header/header.tsx'; -import {OffersDetailed} from '../../types/offers/offer-detailed.ts'; import {useParams} from 'react-router-dom'; import PremiumSign from '../../components/premium-sign/premium-sign.tsx'; import Rating from '../../components/rating/rating.tsx'; @@ -14,21 +13,52 @@ import OfferFeatures from '../../components/offer/offer-features.tsx'; import OfferInside from '../../components/offer/offer-inside.tsx'; import {Points} from '../../types/point.ts'; import {OffersShort} from '../../types/offers/offer-short.ts'; +import {OfferDetailed} from '../../types/offers/offer-detailed.ts'; +import {CityName} from '../../const.ts'; -type OfferPageProps = { - offersDetailed: OffersDetailed; -} - -function OfferPage({offersDetailed,}: OfferPageProps): JSX.Element | null { +function OfferPage(): JSX.Element | null { const {id} = useParams(); - const nearbyOffers : OffersShort = []; - const nearbyPoints : Points = nearbyOffers.map((offer) => ({id: offer.id, location: offer.location})); + const nearbyOffers: OffersShort = []; + const nearbyPoints: Points = nearbyOffers.map((offer) => ({id: offer.id, location: offer.location})); if (!id) { return null; } - const currentOffer = offersDetailed.get(id); + const currentOffer: OfferDetailed = { + id: 'string', + title: 'string', + type: 'string', + price: 0, + city: { + name: CityName.Amsterdam, + location: { + latitude: 0, + longitude: 0, + zoom: 0, + } + }, + location: { + latitude: 0, + longitude: 0, + zoom: 0, + }, + isFavorite: false, + isPremium: false, + rating: 0, + description: 'string', + bedrooms: 1, + goods: [''], + host: { + name: 'string', + avatarUrl: 'string', + isPro: false, + email: 'string', + token: 'string' + }, + images: [''], + maxAdults: 1, + }; if (!currentOffer) { return null; diff --git a/src/services/api.ts b/src/services/api.ts index 51ba0f7..915f51e 100644 --- a/src/services/api.ts +++ b/src/services/api.ts @@ -1,4 +1,7 @@ -import axios, {AxiosInstance} from 'axios'; +import axios, {AxiosError, AxiosInstance, InternalAxiosRequestConfig} from 'axios'; +import {getToken} from './token.ts'; +import {toast} from 'react-toastify'; +import {DetailMessageType, shouldDisplayError} from './error-handle.ts'; const BACKEND_URL = 'https://14.design.htmlacademy.pro/six-cities'; const REQUEST_TIMEOUT = 5000; @@ -9,5 +12,40 @@ export const createAPI = (): AxiosInstance => { timeout: REQUEST_TIMEOUT, }); + api.interceptors.request.use( + (config: InternalAxiosRequestConfig) => { + const token = getToken(); + + if (token && config.headers) { + config.headers['x-token'] = token; + } + + return config; + } + ); + + + api.interceptors.response.use( + (response) => response, + (error: AxiosError) => { + if (error.response && shouldDisplayError(error.response)) { + if (error.response.data.details.length) { + const messages = (error.response.data.details); + messages.map((property) => { + property.messages.map((message) => { + + toast.warning(message); + }); + }); + } else { + const detailMessage = (error.response.data); + toast.warn(detailMessage.message); + } + } + + throw error; + } + ); + return api; }; diff --git a/src/services/error-handle.ts b/src/services/error-handle.ts new file mode 100644 index 0000000..bef6b2b --- /dev/null +++ b/src/services/error-handle.ts @@ -0,0 +1,20 @@ +import {StatusCodes} from 'http-status-codes'; +import {AxiosResponse} from 'axios'; + +export type DetailMessageType = { + errorType: string; + message: string; + details: [{ + property: string; + value: string; + messages: [string]; + }]; +} + +const StatusCodeMapping: Record = { + [StatusCodes.BAD_REQUEST]: true, + [StatusCodes.UNAUTHORIZED]: true, + [StatusCodes.NOT_FOUND]: true +}; + +export const shouldDisplayError = (response: AxiosResponse) => StatusCodeMapping[response.status]; diff --git a/src/services/token.ts b/src/services/token.ts new file mode 100644 index 0000000..de45fe9 --- /dev/null +++ b/src/services/token.ts @@ -0,0 +1,16 @@ +const AUTH_TOKEN_KEY_NAME = '6-cities-token'; + +export type Token = string; + +export const getToken = (): Token => { + const token = localStorage.getItem(AUTH_TOKEN_KEY_NAME); + return token ?? ''; +}; + +export const saveToken = (token: Token): void => { + localStorage.setItem(AUTH_TOKEN_KEY_NAME, token); +}; + +export const dropToken = (): void => { + localStorage.removeItem(AUTH_TOKEN_KEY_NAME); +}; diff --git a/src/store/acions.ts b/src/store/acions.ts index 212e029..0df83d0 100644 --- a/src/store/acions.ts +++ b/src/store/acions.ts @@ -3,6 +3,8 @@ import {City} from '../types/city.ts'; import {Nullable} from '../types/nullable.ts'; import {SortingOrder} from '../types/sorting-order.ts'; import {OffersShort} from '../types/offers/offer-short.ts'; +import {AuthStatus} from '../const.ts'; +import {UserData} from '../types/user-data.ts'; export const setActiveCity = createAction('setCity'); export const setHoverCardId = createAction>('setHooverCardId'); @@ -12,3 +14,7 @@ export const setSortingOrder = createAction('setSortingOrder'); export const setOffers = createAction('setOffers'); export const setOffersLoading = createAction('setOffersLoading'); + +export const setAuthStatus = createAction('setAuthStatus'); + +export const setUserData = createAction>('setUserData'); diff --git a/src/store/api-actions.ts b/src/store/api-actions.ts index b4be976..b933a52 100644 --- a/src/store/api-actions.ts +++ b/src/store/api-actions.ts @@ -1,14 +1,17 @@ import {createAsyncThunk} from '@reduxjs/toolkit'; import {OffersShort} from '../types/offers/offer-short.ts'; import {AxiosInstance} from 'axios'; -import {APIRoute} from '../const.ts'; -import {AppDispatch} from './index.tsx'; -import {setOffersLoading} from './acions.ts'; +import {APIRoute, AuthStatus} from '../const.ts'; +import {AppDispatch, RootState} from './index.tsx'; +import {setAuthStatus, setOffersLoading, setUserData} from './acions.ts'; +import {dropToken, saveToken} from '../services/token.ts'; +import {UserData} from '../types/user-data.ts'; +import {AuthData} from '../types/auth-data.ts'; -export const fetchOffers = createAsyncThunk< +export const fetchOffersAction = createAsyncThunk< OffersShort, - undefined,{ + undefined, { dispatch: AppDispatch; extra: AxiosInstance; }>( @@ -20,3 +23,52 @@ export const fetchOffers = createAsyncThunk< return data; }, ); + +export const checkAuthStatusAction = createAsyncThunk( + 'user/checkAuth', + async (_arg, {dispatch, extra: api}) => { + try { + const {data} = await api.get(APIRoute.Login); + dispatch(setAuthStatus(AuthStatus.Auth)); + dispatch(setUserData(data)); + return data; + } catch { + dispatch(setAuthStatus(AuthStatus.NoAuth)); + return null; + } + }, +); + +export const loginAction = createAsyncThunk( + 'user/login', + async ({login: email, password}, {dispatch, extra: api}) => { + const {data} = await api.post(APIRoute.Login, {email, password}); + saveToken(data.token); + dispatch(setAuthStatus(AuthStatus.Auth)); + + dispatch(setUserData(data)); + return data; + }, +); + +export const logoutAction = createAsyncThunk( + 'user/logout', + async (_arg, {dispatch, extra: api}) => { + await api.delete(APIRoute.Logout); + dropToken(); + dispatch(setAuthStatus(AuthStatus.NoAuth)); + dispatch(setUserData(null)); + }, +); diff --git a/src/store/index.tsx b/src/store/index.tsx index 208f4d1..75ec8d7 100644 --- a/src/store/index.tsx +++ b/src/store/index.tsx @@ -15,4 +15,5 @@ export const store = configureStore({ }); export type RootState = ReturnType; + export type AppDispatch = typeof store.dispatch; diff --git a/src/store/reducer.ts b/src/store/reducer.ts index 4b55f39..d9899ca 100644 --- a/src/store/reducer.ts +++ b/src/store/reducer.ts @@ -1,11 +1,19 @@ -import {CityObject} from '../const.ts'; +import {AuthStatus, CityObject} from '../const.ts'; import {OffersShort} from '../types/offers/offer-short.ts'; import {createReducer} from '@reduxjs/toolkit'; -import {setActiveCity, setHoverCardId, setOffers, setOffersLoading, setSortingOrder} from './acions.ts'; +import { + setActiveCity, + setAuthStatus, + setHoverCardId, + setOffers, + setOffersLoading, + setSortingOrder, setUserData +} from './acions.ts'; import {City} from '../types/city.ts'; import {Nullable} from '../types/nullable.ts'; import {SortingOrder} from '../types/sorting-order.ts'; -import {fetchOffers} from './api-actions.ts'; +import {fetchOffersAction} from './api-actions.ts'; +import {UserData} from '../types/user-data.ts'; type AppState = { activeCity: City; @@ -13,6 +21,8 @@ type AppState = { hoverCardId: Nullable; sortingOrder: SortingOrder; isOffersLoading: boolean; + authorizationStatus: AuthStatus; + userData: Nullable; } const initialState : AppState = { @@ -21,6 +31,8 @@ const initialState : AppState = { hoverCardId: null, sortingOrder: SortingOrder.popular, isOffersLoading: false, + authorizationStatus: AuthStatus.Unknown, + userData: null, }; export const reducer = createReducer(initialState, (builder) => { @@ -37,10 +49,16 @@ export const reducer = createReducer(initialState, (builder) => { .addCase(setOffers, (state, action) => { state.offers = action.payload; }) - .addCase(fetchOffers.fulfilled, (state, action) => { + .addCase(fetchOffersAction.fulfilled, (state, action) => { state.offers = action.payload; }) .addCase(setOffersLoading, (state, action) => { state.isOffersLoading = action.payload; + }) + .addCase(setAuthStatus, (state, action) => { + state.authorizationStatus = action.payload; + }) + .addCase(setUserData, (state, action) => { + state.userData = action.payload; }); }); diff --git a/src/types/auth-data.ts b/src/types/auth-data.ts new file mode 100644 index 0000000..b8d2025 --- /dev/null +++ b/src/types/auth-data.ts @@ -0,0 +1,4 @@ +export type AuthData = { + login: string; + password: string; +}; diff --git a/src/types/offers/offer-detailed.ts b/src/types/offers/offer-detailed.ts index 55d70e3..c43dbce 100644 --- a/src/types/offers/offer-detailed.ts +++ b/src/types/offers/offer-detailed.ts @@ -1,11 +1,11 @@ -import {User} from '../user.ts'; +import {UserData} from '../user-data.ts'; import {OfferShort} from './offer-short.ts'; export type OfferDetailed = Omit & { description: string; bedrooms: number; goods: string[]; - host: User; + host: UserData; images: string[]; maxAdults: number; } diff --git a/src/types/review.ts b/src/types/review.ts index 6cbdb57..97a2db3 100644 --- a/src/types/review.ts +++ b/src/types/review.ts @@ -1,9 +1,9 @@ -import {User} from './user.ts'; +import {UserData} from './user-data.ts'; export type Review = { id: string; date: string; - user: User; + user: UserData; comment: string; rating: number; } diff --git a/src/types/user-data.ts b/src/types/user-data.ts new file mode 100644 index 0000000..1fdc9a3 --- /dev/null +++ b/src/types/user-data.ts @@ -0,0 +1,12 @@ +export type UserData = { + name: string; + avatarUrl: string; + isPro: boolean; + email: string; + token: string; +} + +export type AuthData = { + login: string; + password: string; +} diff --git a/src/types/user.ts b/src/types/user.ts deleted file mode 100644 index 9a1670e..0000000 --- a/src/types/user.ts +++ /dev/null @@ -1,5 +0,0 @@ -export type User = { - name: string; - avatarUrl: string; - isPro: boolean; -}