From 70aac95661847e94e4ac814b61588a641b704b11 Mon Sep 17 00:00:00 2001 From: "Aidar Shaikhutdin @makeweb.space" Date: Tue, 9 May 2023 20:30:54 +0600 Subject: [PATCH] feat: integration with api server --- src/assets/site.webmanifest | 4 +- src/auth/AuthContext.ts | 25 +++++- src/auth/AuthProvider.tsx | 55 +++++++++++- src/components/App/index.tsx | 12 ++- src/components/BirthdayPage/index.tsx | 8 +- src/components/BirthtimePage/index.tsx | 6 +- .../CreateProfilePage/ProcessItem.tsx | 4 +- src/components/CreateProfilePage/styles.css | 63 -------------- src/components/DateTimePicker/DatePicker.tsx | 7 +- src/components/DateTimePicker/ErrorText.tsx | 15 ---- src/components/DateTimePicker/styles.css | 16 ---- src/components/EmailEnterPage/index.tsx | 35 +++++++- src/components/ErrorText/index.tsx | 18 ++++ src/components/ErrorText/styles.css | 27 ++++++ src/components/Loader/index.tsx | 21 +++++ src/components/Loader/styles.css | 74 +++++++++++++++++ src/components/MainButton/index.tsx | 8 +- src/components/MainButton/styles.css | 2 + src/components/SubscriptionPage/index.tsx | 8 +- src/locales/index.ts | 3 + src/routes.ts | 4 +- src/store/birthdate.ts | 20 ----- src/store/birthtime.ts | 20 ----- src/store/email.ts | 20 ----- src/store/form.ts | 32 +++++++ src/store/index.ts | 27 +++--- src/store/storageHelper.ts | 4 +- src/store/token.ts | 20 +++++ src/store/user.ts | 45 ++++++++++ src/types.ts | 83 +++++++++++++++++++ 30 files changed, 485 insertions(+), 201 deletions(-) delete mode 100644 src/components/DateTimePicker/ErrorText.tsx create mode 100644 src/components/ErrorText/index.tsx create mode 100644 src/components/ErrorText/styles.css create mode 100644 src/components/Loader/index.tsx create mode 100644 src/components/Loader/styles.css delete mode 100644 src/store/birthdate.ts delete mode 100644 src/store/birthtime.ts delete mode 100644 src/store/email.ts create mode 100644 src/store/form.ts create mode 100644 src/store/token.ts create mode 100644 src/store/user.ts diff --git a/src/assets/site.webmanifest b/src/assets/site.webmanifest index 1e9747b..df879ab 100644 --- a/src/assets/site.webmanifest +++ b/src/assets/site.webmanifest @@ -3,12 +3,12 @@ "short_name": "", "icons": [ { - "src": "/assets/android-chrome-192x192.png", + "src": "/src/assets/android-chrome-192x192.png", "sizes": "192x192", "type": "image/png" }, { - "src": "/assets/android-chrome-512x512.png", + "src": "/src/assets/android-chrome-512x512.png", "sizes": "512x512", "type": "image/png" } diff --git a/src/auth/AuthContext.ts b/src/auth/AuthContext.ts index 358e5ef..147741f 100644 --- a/src/auth/AuthContext.ts +++ b/src/auth/AuthContext.ts @@ -1,3 +1,26 @@ import { createContext } from 'react' +import { AuthToken, User } from '../types' -export const AuthContext = createContext({}) +export interface AuthContextValue { + user: User | null + token: AuthToken + logout: () => void + signUp: (payload: SignUpPayload) => Promise + addBirthday: (birthday: string) => Promise +} + +export interface SignUpPayload { + email: string + timezone: string + locale: string +} + +const initialContext: AuthContextValue = { + token: '', + user: null, + logout: () => undefined, + signUp: () => Promise.resolve(), + addBirthday: () => Promise.resolve(), +} + +export const AuthContext = createContext(initialContext) diff --git a/src/auth/AuthProvider.tsx b/src/auth/AuthProvider.tsx index b31bc8c..3d8b6ea 100644 --- a/src/auth/AuthProvider.tsx +++ b/src/auth/AuthProvider.tsx @@ -1,7 +1,58 @@ -import { AuthContext } from './AuthContext' +import { useDispatch, useSelector } from 'react-redux' +import { AuthContext, SignUpPayload } from './AuthContext' +import { RootState, actions } from '../store' +import routes from '../routes' export function AuthProvider({ children }: React.PropsWithChildren): JSX.Element { - const auth = {} + const dispatch = useDispatch() + const token = useSelector((state: RootState) => state.token) + const user = useSelector((state: RootState) => state.user) + const signUp = async ({ email, timezone, locale }: SignUpPayload): Promise => { + const response = await fetch(routes.server.token(), { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ auth: { email, timezone, locale } }) + }) + if (response.ok) { + const { auth: { token, user } } = await response.json() + dispatch(actions.token.update(token)) + dispatch(actions.user.update(user)) + } else { + const { errors } = await response.json() + if (Array.isArray(errors)) { + const [error] = errors + throw new Error(error.title) + } else { + const { base: [error] } = errors + throw new Error(error) + } + } + } + const addBirthday = async (birthday: string): Promise => { + const response = await fetch(routes.server.user(), { + method: 'PATCH', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${token}`, + }, + body: JSON.stringify({ user: { profile_attributes: { birthday } } }) + }) + if (response.ok) { + const { user } = await response.json() + dispatch(actions.user.update(user)) + } else { + const { errors } = await response.json() + if (Array.isArray(errors)) { + const [error] = errors + throw new Error(error.title) + } else { + const { base: [error] } = errors + throw new Error(error) + } + } + } + const logout = () => dispatch(actions.reset()) + const auth = { signUp, logout, addBirthday, token, user: user.id ? user : null } return ( {children} diff --git a/src/components/App/index.tsx b/src/components/App/index.tsx index 31ff347..0f9b9f8 100644 --- a/src/components/App/index.tsx +++ b/src/components/App/index.tsx @@ -1,4 +1,5 @@ -import { Routes, Route, Navigate } from 'react-router-dom' +import { Routes, Route, Navigate, Outlet } from 'react-router-dom' +import { useAuth } from '../../auth' import BirthdayPage from '../BirthdayPage' import BirthtimePage from '../BirthtimePage' import CreateProfilePage from '../CreateProfilePage' @@ -22,7 +23,9 @@ function App(): JSX.Element { } /> } /> } /> - } /> + }> + } /> + } /> @@ -30,4 +33,9 @@ function App(): JSX.Element { ) } +function PrivateOutlet(): JSX.Element { + const { user } = useAuth() + return user ? : +} + export default App diff --git a/src/components/BirthdayPage/index.tsx b/src/components/BirthdayPage/index.tsx index d91783d..b399387 100644 --- a/src/components/BirthdayPage/index.tsx +++ b/src/components/BirthdayPage/index.tsx @@ -15,7 +15,7 @@ function BirthdayPage(): JSX.Element { const { t } = useTranslation() const dispatch = useDispatch() const navigate = useNavigate() - const birthdate = useSelector((state: RootState) => state.birthdate) + const birthdate = useSelector((state: RootState) => state.form.birthdate) const [isDisabled, setIsDisabled] = useState(true) const links = [ { text: 'EULA', href: 'https://aura.wit.life/terms' }, @@ -24,7 +24,7 @@ function BirthdayPage(): JSX.Element { ] const handleNext = () => navigate(routes.client.birthtime()) const handleValid = (birthdate: string) => { - dispatch(actions.birthdate.update(birthdate)) + dispatch(actions.form.addDate(birthdate)) setIsDisabled(birthdate === '') } @@ -38,7 +38,9 @@ function BirthdayPage(): JSX.Element { onValid={handleValid} onInvalid={() => setIsDisabled(true)} /> - + + {t('next')} +