-
Notifications
You must be signed in to change notification settings - Fork 111
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[C-3255] Sub-route logic & redirects for sign up flow #6489
Changes from 11 commits
356a5be
f4c3957
8ae27f1
1270239
2e7c5df
02e8dd3
64e657d
8841255
e1de8df
96a2396
e620023
ab667af
8210ea4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,60 +1,128 @@ | ||
import { useState } from 'react' | ||
import { useSelector } from 'react-redux' | ||
import { Redirect, Route, RouteProps, Switch } from 'react-router-dom' | ||
|
||
import { AppCtaPage, AppCtaState } from './pages/AppCtaPage' | ||
import { getSignOn } from 'common/store/pages/signon/selectors' | ||
import SignOnPageState from 'common/store/pages/signon/types' | ||
import { AppState } from 'store/types' | ||
import { | ||
CreatePasswordPage, | ||
CreatePasswordState | ||
} from './pages/CreatePasswordPage' | ||
import { | ||
FinishProfilePage, | ||
FinishProfileState | ||
} from './pages/FinishProfilePage' | ||
import { PickHandlePage, PickHandleState } from './pages/PickHandlePage' | ||
import { | ||
SelectArtistsPage, | ||
SelectArtistsState | ||
} from './pages/SelectArtistsPage' | ||
import { SelectGenrePage, SelectGenreState } from './pages/SelectGenrePage' | ||
import { SignUpPage, SignUpState } from './pages/SignUpPage' | ||
|
||
type SignUpRootState = | ||
| SignUpState | ||
| CreatePasswordState | ||
| PickHandleState | ||
| FinishProfileState | ||
| SelectGenreState | ||
| SelectArtistsState | ||
| AppCtaState | ||
SIGN_UP_ARTISTS_PAGE, | ||
SIGN_UP_EMAIL_PAGE, | ||
SIGN_UP_FINISH_PROFILE_PAGE, | ||
SIGN_UP_GENRES_PAGE, | ||
SIGN_UP_HANDLE_PAGE, | ||
SIGN_UP_PASSWORD_PAGE, | ||
SignUpPath, | ||
TRENDING_PAGE | ||
} from 'utils/route' | ||
|
||
export const SignUpRootPage = () => { | ||
const [signUpState, setSignUpState] = useState<SignUpRootState>({ | ||
stage: 'sign-up' | ||
}) | ||
import { CreatePasswordPage } from './pages/CreatePasswordPage' | ||
import { FinishProfilePage } from './pages/FinishProfilePage' | ||
import { PickHandlePage } from './pages/PickHandlePage' | ||
import { SelectArtistsPage } from './pages/SelectArtistsPage' | ||
import { SelectGenrePage } from './pages/SelectGenrePage' | ||
import { SignUpPage } from './pages/SignUpPage' | ||
|
||
/** | ||
* Checks against existing sign up redux state, | ||
* then determines if the requested path should be allowed or not | ||
* if not allowed, also returns furthest step possible based on existing state | ||
*/ | ||
const determineAllowedRoute = ( | ||
signUpState: SignOnPageState, | ||
requestedRoute: string | SignUpPath // this string should have already trimmed out /signup/ | ||
) => { | ||
const attemptedPath = requestedRoute.replace('/signup/', '') | ||
// Have to type as string[] to avoid too narrow of a type for comparing against | ||
let allowedRoutes: string[] = [SignUpPath.createEmail] // create email is available by default | ||
if (signUpState.email.value) { | ||
// Already have email | ||
allowedRoutes.push(SignUpPath.createPassword) | ||
} | ||
if (signUpState.password.value) { | ||
// Already have password | ||
allowedRoutes.push(SignUpPath.pickHandle) | ||
} | ||
if (signUpState.handle.value) { | ||
// Already have handle | ||
allowedRoutes.push(SignUpPath.finishProfile) | ||
} | ||
if (signUpState.name.value) { | ||
// Already have display name | ||
// At this point the account is fully created & logged in; now user can't back to account creation steps | ||
allowedRoutes = [SignUpPath.selectGenres] | ||
} | ||
|
||
// TODO: These checks below here may need to fall under a different route umbrella separate from sign up | ||
if (signUpState.genres) { | ||
// Already have genres selected | ||
allowedRoutes.push(SignUpPath.selectArtists) | ||
} | ||
|
||
if (signUpState.followArtists?.selectedUserIds?.length >= 3) { | ||
// Already have 3 artists followed | ||
// Done with sign up if at this point so we return early (none of these routes are allowed anymore) | ||
// TODO: trigger welcome modal when redirecting from here | ||
return { isAllowedRoute: false, correctedRoute: TRENDING_PAGE } | ||
} | ||
|
||
const isAllowedRoute = allowedRoutes.includes(attemptedPath) | ||
// If requested route is allowed return that, otherwise return the last step in the route stack | ||
const correctedPath = isAllowedRoute | ||
? attemptedPath | ||
: allowedRoutes[allowedRoutes.length - 1] | ||
return { | ||
isAllowedRoute, | ||
correctedRoute: `/signup/${correctedPath}` | ||
} | ||
} | ||
|
||
/** | ||
* <Route> wrapper that handles redirecting through the sign up page flow | ||
*/ | ||
export function SignUpRoute({ children, ...rest }: RouteProps) { | ||
const existingSignUpState = useSelector((state: AppState) => getSignOn(state)) | ||
return ( | ||
<Route | ||
{...rest} | ||
render={({ location }) => { | ||
// Check if the route is allowed, if not we redirect accordingly | ||
const { isAllowedRoute, correctedRoute } = determineAllowedRoute( | ||
existingSignUpState, | ||
location.pathname | ||
) | ||
return isAllowedRoute ? ( | ||
<>{children}</> | ||
) : ( | ||
<Redirect to={correctedRoute} /> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, very nice |
||
) | ||
}} | ||
/> | ||
) | ||
} | ||
|
||
export const SignUpRootPage = () => { | ||
return ( | ||
<div> | ||
{signUpState.stage === 'sign-up' ? ( | ||
<SignUpPage onNext={setSignUpState} /> | ||
) : null} | ||
{signUpState.stage === 'create-password' ? ( | ||
<CreatePasswordPage | ||
onPrevious={setSignUpState} | ||
onNext={setSignUpState} | ||
/> | ||
) : null} | ||
{signUpState.stage === 'pick-handle' ? ( | ||
<PickHandlePage onNext={setSignUpState} /> | ||
) : null} | ||
{signUpState.stage === 'finish-profile' ? ( | ||
<FinishProfilePage onNext={setSignUpState} /> | ||
) : null} | ||
{signUpState.stage === 'select-genre' ? ( | ||
<SelectGenrePage onNext={setSignUpState} /> | ||
) : null} | ||
{signUpState.stage === 'select-artists' ? ( | ||
<SelectArtistsPage onNext={setSignUpState} /> | ||
) : null} | ||
{signUpState.stage === 'app-cta' ? <AppCtaPage /> : null} | ||
<Switch> | ||
<Route exact path={SIGN_UP_EMAIL_PAGE}> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. my expectations was that this would be the "SignupRoute" and each one would check if they are allowed to render, and if not, redirect? i think its probably fine to do this all in a root route like you did though. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah either way works technically. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also I guess since we're probably rearranging it anyways, the individual wrappers makes it simpler to move around |
||
<SignUpPage /> | ||
</Route> | ||
<Route exact path={SIGN_UP_PASSWORD_PAGE}> | ||
<CreatePasswordPage /> | ||
</Route> | ||
<Route exact path={SIGN_UP_HANDLE_PAGE}> | ||
<PickHandlePage /> | ||
</Route> | ||
<Route exact path={SIGN_UP_FINISH_PROFILE_PAGE}> | ||
<FinishProfilePage /> | ||
</Route> | ||
<Route exact path={SIGN_UP_GENRES_PAGE}> | ||
<SelectGenrePage /> | ||
</Route> | ||
<Route exact path={SIGN_UP_ARTISTS_PAGE}> | ||
<SelectArtistsPage /> | ||
</Route> | ||
</Switch> | ||
</div> | ||
) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Keeps all the links the same (i.e.
/signup
will redirect to/signup/create-account
)