135 lines
3.7 KiB
TypeScript
135 lines
3.7 KiB
TypeScript
import { observer } from 'mobx-react-lite';
|
|
import { useCloseOnClickOutside } from '@/components/utils';
|
|
import { AppState } from '@/ui_models/app_state';
|
|
import { WebApplication } from '@/ui_models/application';
|
|
import { useRef, useState } from 'preact/hooks';
|
|
import { GeneralAccountMenu } from './GeneralAccountMenu';
|
|
import { FunctionComponent } from 'preact';
|
|
import { SignInPane } from './SignIn';
|
|
import { CreateAccount } from './CreateAccount';
|
|
import { ConfirmPassword } from './ConfirmPassword';
|
|
import { JSXInternal } from 'preact/src/jsx';
|
|
|
|
export enum AccountMenuPane {
|
|
GeneralMenu,
|
|
SignIn,
|
|
Register,
|
|
ConfirmPassword,
|
|
}
|
|
|
|
type Props = {
|
|
appState: AppState;
|
|
application: WebApplication;
|
|
onClickOutside: () => void;
|
|
};
|
|
|
|
type PaneSelectorProps = {
|
|
appState: AppState;
|
|
application: WebApplication;
|
|
menuPane: AccountMenuPane;
|
|
setMenuPane: (pane: AccountMenuPane) => void;
|
|
closeMenu: () => void;
|
|
};
|
|
|
|
const MenuPaneSelector: FunctionComponent<PaneSelectorProps> = observer(
|
|
({ application, appState, menuPane, setMenuPane, closeMenu }) => {
|
|
const [email, setEmail] = useState('');
|
|
const [password, setPassword] = useState('');
|
|
|
|
switch (menuPane) {
|
|
case AccountMenuPane.GeneralMenu:
|
|
return (
|
|
<GeneralAccountMenu
|
|
appState={appState}
|
|
application={application}
|
|
setMenuPane={setMenuPane}
|
|
closeMenu={closeMenu}
|
|
/>
|
|
);
|
|
case AccountMenuPane.SignIn:
|
|
return (
|
|
<SignInPane
|
|
appState={appState}
|
|
application={application}
|
|
setMenuPane={setMenuPane}
|
|
/>
|
|
);
|
|
case AccountMenuPane.Register:
|
|
return (
|
|
<CreateAccount
|
|
appState={appState}
|
|
application={application}
|
|
setMenuPane={setMenuPane}
|
|
email={email}
|
|
setEmail={setEmail}
|
|
password={password}
|
|
setPassword={setPassword}
|
|
/>
|
|
);
|
|
case AccountMenuPane.ConfirmPassword:
|
|
return (
|
|
<ConfirmPassword
|
|
appState={appState}
|
|
application={application}
|
|
setMenuPane={setMenuPane}
|
|
email={email}
|
|
password={password}
|
|
/>
|
|
);
|
|
}
|
|
}
|
|
);
|
|
|
|
export const AccountMenu: FunctionComponent<Props> = observer(
|
|
({ application, appState, onClickOutside }) => {
|
|
const {
|
|
currentPane,
|
|
setCurrentPane,
|
|
shouldAnimateCloseMenu,
|
|
closeAccountMenu,
|
|
} = appState.accountMenu;
|
|
|
|
const ref = useRef<HTMLDivElement>(null);
|
|
useCloseOnClickOutside(ref, () => {
|
|
onClickOutside();
|
|
});
|
|
|
|
const handleKeyDown: JSXInternal.KeyboardEventHandler<HTMLDivElement> = (
|
|
event
|
|
) => {
|
|
switch (event.key) {
|
|
case 'Escape':
|
|
if (currentPane === AccountMenuPane.GeneralMenu) {
|
|
closeAccountMenu();
|
|
} else if (currentPane === AccountMenuPane.ConfirmPassword) {
|
|
setCurrentPane(AccountMenuPane.Register);
|
|
} else {
|
|
setCurrentPane(AccountMenuPane.GeneralMenu);
|
|
}
|
|
break;
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div ref={ref} id="account-menu" className="sn-component">
|
|
<div
|
|
className={`sn-menu-border sn-account-menu sn-dropdown ${
|
|
shouldAnimateCloseMenu
|
|
? 'slide-up-animation'
|
|
: 'sn-dropdown--animated'
|
|
} min-w-80 max-h-120 max-w-xs flex flex-col py-2 overflow-y-auto absolute`}
|
|
onKeyDown={handleKeyDown}
|
|
>
|
|
<MenuPaneSelector
|
|
appState={appState}
|
|
application={application}
|
|
menuPane={currentPane}
|
|
setMenuPane={setCurrentPane}
|
|
closeMenu={closeAccountMenu}
|
|
/>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
);
|