diff --git a/src/components/App/index.tsx b/src/components/App/index.tsx index a23c3db..1f17551 100644 --- a/src/components/App/index.tsx +++ b/src/components/App/index.tsx @@ -5,11 +5,16 @@ import './App.css' import { Theater } from '../Theater' import { Auth } from '../Auth' -import { $user } from '../../models/auth' -import {AppGate} from '../../models/app' +import {$router} from '../../models/router' +import {AppGate, Route} from '../../models/app' export const App = () => { useGate(AppGate) - const {email} = useStore($user) - return email ? () : () + const [, route] = useStore($router) + useGate(Route, { name: route ? route : '' }) + + if (route === 'theater') { + return + } + return } \ No newline at end of file diff --git a/src/models/app/index.ts b/src/models/app/index.ts index e73b6bf..4584351 100644 --- a/src/models/app/index.ts +++ b/src/models/app/index.ts @@ -5,4 +5,6 @@ import { Config } from './types' export const initAppFx = createEffect() -export const AppGate = createGate() \ No newline at end of file +export const AppGate = createGate() + +export const Route = createGate<{name: string}>() \ No newline at end of file diff --git a/src/models/app/init.ts b/src/models/app/init.ts index 9e28b73..4736b0e 100644 --- a/src/models/app/init.ts +++ b/src/models/app/init.ts @@ -2,11 +2,13 @@ import { initializeApp } from 'firebase' import { forward } from 'effector' import { - initAppFx, AppGate + initAppFx, AppGate, Route } from './' import { fetchUsersFx } from '../users' +import { checkAuthFx } from '../auth' + import { appId, projectId, @@ -41,5 +43,9 @@ initAppFx({ forward({ from: AppGate.open, - to: fetchUsersFx + to: [fetchUsersFx, checkAuthFx] +}) + +Route.state.updates.watch(({name}) => { + history.pushState({}, '', `/${name}`) }) \ No newline at end of file diff --git a/src/models/auth/index.ts b/src/models/auth/index.ts index 126fca4..5878bb6 100644 --- a/src/models/auth/index.ts +++ b/src/models/auth/index.ts @@ -10,12 +10,20 @@ export const logout = createEvent() export const updateSignInForm = createEvent<{ value: string; fieldName: string }>() +export const checkAuth = createEvent() + +export const restoredAuth = createEvent() + export const manageGmailProviderFx = createEffect() export const manageEmailProviderFx = createEffect() export const signUpViaEmailFx = createEffect() +export const checkAuthFx = createEffect() + +export const dropUserAuthFx = createEffect() + export const $user = createStore({ email: '' }) diff --git a/src/models/auth/init.ts b/src/models/auth/init.ts index 551815a..3ad7fa7 100644 --- a/src/models/auth/init.ts +++ b/src/models/auth/init.ts @@ -1,4 +1,4 @@ -import { forward, sample } from 'effector' +import { forward, sample, guard } from 'effector' import { auth } from 'firebase' import { @@ -6,9 +6,13 @@ import { signIn, logout, updateSignInForm, + checkAuth, + restoredAuth, manageGmailProviderFx, manageEmailProviderFx, signUpViaEmailFx, + checkAuthFx, + dropUserAuthFx, $user, $signInForm } from './' @@ -17,9 +21,12 @@ import { addUserFx, updateUsersTableFx, deleteUserFx, - $firebaseUsers + $firebaseUsers, + $usersByEmail } from '../users' +import { User } from './types' + const gProvider = new auth.GoogleAuthProvider() manageGmailProviderFx.use(async () => { @@ -43,10 +50,22 @@ signUpViaEmailFx.use(async ({email, password}) => { return {email} }) +checkAuthFx.use(() => { + auth().onAuthStateChanged(value => { + if (value !== null) { + checkAuth(value as User) + } + }) +}) + +dropUserAuthFx.use(async () => { + await auth().signOut() +}) + $user .reset(logout) .on([ - manageGmailProviderFx.doneData, signUpViaEmailFx.doneData, manageEmailProviderFx.doneData + manageGmailProviderFx.doneData, signUpViaEmailFx.doneData, manageEmailProviderFx.doneData, restoredAuth ], (_, user) => user ) @@ -82,13 +101,32 @@ forward({ }) sample({ - source: $firebaseUsers, - clock: logout, - //@ts-ignore - fn: (users, email) => Object.keys(users).find((id) => { - if (email === users[id].email) { - return id - } + source: guard({ + source: sample({ + source: $usersByEmail, + clock: [ + manageGmailProviderFx.doneData, + signUpViaEmailFx.doneData, + manageEmailProviderFx.doneData + ], + fn: (users, user) => users[user.email] + }), + filter: Boolean }), + fn: (user) => user.id!, target: deleteUserFx +}) + +forward({ + from: logout, + to: dropUserAuthFx +}) + +forward({ + from: checkAuth.filterMap((user) => { + if (user !== null) { + return user + } + }), + to: restoredAuth }) \ No newline at end of file diff --git a/src/models/init.ts b/src/models/init.ts index 8d14fc7..dec0931 100644 --- a/src/models/init.ts +++ b/src/models/init.ts @@ -1,4 +1,5 @@ import './app/init' import './auth/init' import './users/init' -import './tables/init' \ No newline at end of file +import './tables/init' +import './router/init' \ No newline at end of file diff --git a/src/models/router/index.ts b/src/models/router/index.ts new file mode 100644 index 0000000..9bee945 --- /dev/null +++ b/src/models/router/index.ts @@ -0,0 +1,5 @@ +import {createEvent, createStore} from 'effector' + +export const redirect = createEvent() + +export const $router = createStore([]) \ No newline at end of file diff --git a/src/models/router/init.ts b/src/models/router/init.ts new file mode 100644 index 0000000..6ea479c --- /dev/null +++ b/src/models/router/init.ts @@ -0,0 +1,15 @@ +import {sample} from 'effector' + +import {$user} from '../auth' +import {redirect, $router} from './' + +$router.on(redirect, (routes, link) => ([ + ...routes, + link +])) + +sample({ + source: $user, + fn: (user) => user.email ? 'theater' : '', + target: redirect +}) \ No newline at end of file diff --git a/src/models/users/index.ts b/src/models/users/index.ts index 2063604..b72c3b7 100644 --- a/src/models/users/index.ts +++ b/src/models/users/index.ts @@ -15,7 +15,7 @@ export const $users = $firebaseUsers.map((fUsers) => Object.keys(fUsers).map((id) => fUsers[id]) ) export const $usersByEmail = $firebaseUsers.map((fUsers) => { - return Object.keys(fUsers).reduce((usersByEmail, id) => { + return Object.keys(fUsers).reduce((usersByEmail, id) => { const email = fUsers[id].email; return { [email]: {