Skip to content

Commit 6eb92e0

Browse files
committed
feat: side bar accounts
1 parent 6b77301 commit 6eb92e0

12 files changed

+571
-310
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
import {
2+
EuiConfirmModal,
3+
EuiFieldPassword,
4+
EuiFieldText,
5+
EuiForm,
6+
EuiFormRow,
7+
} from '@elastic/eui';
8+
import { useCallback, useEffect } from 'react';
9+
import type { ReactNode } from 'react';
10+
import { Controller, useForm } from 'react-hook-form';
11+
import { runInBackground } from '../../../lib/async/run-in-background.js';
12+
13+
export interface ModalAddAccountInitialData {
14+
accountName?: string;
15+
accountPassword?: string;
16+
}
17+
18+
export interface ModalAddAccountConfirmData {
19+
accountName: string;
20+
accountPassword: string;
21+
}
22+
23+
export interface ModalAddAccountProps {
24+
initialData?: ModalAddAccountInitialData;
25+
onClose: () => void;
26+
onConfirm: (data: ModalAddAccountConfirmData) => void;
27+
}
28+
29+
export const ModalAddAccount: React.FC<ModalAddAccountProps> = (
30+
props: ModalAddAccountProps
31+
): ReactNode => {
32+
const { initialData, onClose, onConfirm } = props;
33+
34+
const form = useForm<ModalAddAccountConfirmData>();
35+
36+
useEffect(() => {
37+
form.reset(initialData);
38+
}, [form, initialData]);
39+
40+
const onModalClose = useCallback(
41+
(_event?: React.UIEvent) => {
42+
onClose();
43+
},
44+
[onClose]
45+
);
46+
47+
const onModalConfirm = useCallback(
48+
(event: React.UIEvent) => {
49+
runInBackground(async () => {
50+
const handler = form.handleSubmit(
51+
(data: ModalAddAccountConfirmData) => {
52+
onConfirm(data);
53+
}
54+
);
55+
await handler(event);
56+
});
57+
},
58+
[form, onConfirm]
59+
);
60+
61+
return (
62+
<EuiConfirmModal
63+
title="Add Account"
64+
onCancel={onModalClose}
65+
onConfirm={onModalConfirm}
66+
cancelButtonText="Cancel"
67+
confirmButtonText="Save"
68+
buttonColor="primary"
69+
>
70+
<EuiForm component="form">
71+
<EuiFormRow
72+
label="Name"
73+
isInvalid={!!form.formState.errors.accountName}
74+
>
75+
<Controller
76+
name="accountName"
77+
control={form.control}
78+
rules={{ required: true }}
79+
render={({ field, fieldState }) => {
80+
return (
81+
<EuiFieldText
82+
name={field.name}
83+
defaultValue={field.value}
84+
onBlur={field.onBlur}
85+
onChange={field.onChange}
86+
isInvalid={fieldState.invalid}
87+
autoFocus={true}
88+
/>
89+
);
90+
}}
91+
/>
92+
</EuiFormRow>
93+
<EuiFormRow
94+
label="Password"
95+
isInvalid={!!form.formState.errors.accountPassword}
96+
>
97+
<Controller
98+
name="accountPassword"
99+
control={form.control}
100+
rules={{ required: true }}
101+
render={({ field, fieldState }) => {
102+
return (
103+
<EuiFieldPassword
104+
name={field.name}
105+
defaultValue={field.value}
106+
onBlur={field.onBlur}
107+
onChange={field.onChange}
108+
isInvalid={fieldState.invalid}
109+
type="dual"
110+
/>
111+
);
112+
}}
113+
/>
114+
</EuiFormRow>
115+
</EuiForm>
116+
</EuiConfirmModal>
117+
);
118+
};
119+
120+
ModalAddAccount.displayName = 'ModalAddAccount';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
import {
2+
EuiConfirmModal,
3+
EuiFieldPassword,
4+
EuiFieldText,
5+
EuiForm,
6+
EuiFormRow,
7+
} from '@elastic/eui';
8+
import { useCallback, useEffect } from 'react';
9+
import type { ReactNode } from 'react';
10+
import { Controller, useForm } from 'react-hook-form';
11+
import { runInBackground } from '../../../lib/async/run-in-background.js';
12+
13+
export interface ModalEditAccountInitialData {
14+
accountName: string;
15+
accountPassword?: string;
16+
}
17+
18+
export interface ModalEditAccountConfirmData {
19+
accountName: string;
20+
accountPassword: string;
21+
}
22+
23+
export interface ModalEditAccountProps {
24+
initialData: Partial<ModalEditAccountInitialData>;
25+
onClose: () => void;
26+
onConfirm: (data: ModalEditAccountConfirmData) => void;
27+
}
28+
29+
export const ModalEditAccount: React.FC<ModalEditAccountProps> = (
30+
props: ModalEditAccountProps
31+
): ReactNode => {
32+
const { initialData = {}, onClose, onConfirm } = props;
33+
34+
const form = useForm<ModalEditAccountConfirmData>();
35+
36+
useEffect(() => {
37+
form.reset(initialData);
38+
}, [form, initialData]);
39+
40+
const onModalClose = useCallback(
41+
(_event?: React.UIEvent) => {
42+
onClose();
43+
},
44+
[onClose]
45+
);
46+
47+
const onModalConfirm = useCallback(
48+
(event: React.UIEvent) => {
49+
runInBackground(async () => {
50+
const handler = form.handleSubmit(
51+
(data: ModalEditAccountConfirmData) => {
52+
onConfirm(data);
53+
}
54+
);
55+
await handler(event);
56+
});
57+
},
58+
[form, onConfirm]
59+
);
60+
61+
return (
62+
<EuiConfirmModal
63+
title="Change Password"
64+
onCancel={onModalClose}
65+
onConfirm={onModalConfirm}
66+
cancelButtonText="Cancel"
67+
confirmButtonText="Save"
68+
buttonColor="primary"
69+
>
70+
<EuiForm component="form">
71+
<EuiFormRow
72+
label="Name"
73+
isInvalid={!!form.formState.errors.accountName}
74+
>
75+
<Controller
76+
name="accountName"
77+
control={form.control}
78+
rules={{ required: true }}
79+
render={({ field, fieldState }) => {
80+
return (
81+
<EuiFieldText
82+
name={field.name}
83+
defaultValue={field.value}
84+
onBlur={field.onBlur}
85+
onChange={field.onChange}
86+
isInvalid={fieldState.invalid}
87+
disabled={true}
88+
/>
89+
);
90+
}}
91+
/>
92+
</EuiFormRow>
93+
<EuiFormRow
94+
label="Password"
95+
isInvalid={!!form.formState.errors.accountPassword}
96+
>
97+
<Controller
98+
name="accountPassword"
99+
control={form.control}
100+
rules={{ required: true }}
101+
render={({ field, fieldState }) => {
102+
return (
103+
<EuiFieldPassword
104+
name={field.name}
105+
defaultValue={field.value}
106+
onBlur={field.onBlur}
107+
onChange={field.onChange}
108+
isInvalid={fieldState.invalid}
109+
autoFocus={true}
110+
type="dual"
111+
/>
112+
);
113+
}}
114+
/>
115+
</EuiFormRow>
116+
</EuiForm>
117+
</EuiConfirmModal>
118+
);
119+
};
120+
121+
ModalEditAccount.displayName = 'ModalEditAccount';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import { EuiConfirmModal } from '@elastic/eui';
2+
import { type ReactNode, useCallback } from 'react';
3+
import { useListCharacters } from '../../../hooks/list-characters.jsx';
4+
5+
export interface ModalRemoveAccountInitialData {
6+
accountName: string;
7+
}
8+
9+
export interface ModalRemoveAccountConfirmData {
10+
accountName: string;
11+
}
12+
13+
export interface ModalRemoveAccountProps {
14+
initialData: ModalRemoveAccountInitialData;
15+
onClose: () => void;
16+
onConfirm: (data: ModalRemoveAccountConfirmData) => void;
17+
}
18+
19+
export const ModalRemoveAccount: React.FC<ModalRemoveAccountProps> = (
20+
props: ModalRemoveAccountProps
21+
): ReactNode => {
22+
const { initialData, onClose, onConfirm } = props;
23+
24+
const characters = useListCharacters({
25+
accountName: initialData.accountName,
26+
});
27+
28+
const onModalClose = useCallback(
29+
(_event?: React.UIEvent) => {
30+
onClose();
31+
},
32+
[onClose]
33+
);
34+
35+
const onModalConfirm = useCallback(
36+
(_event: React.UIEvent) => {
37+
onConfirm({ accountName: initialData.accountName });
38+
},
39+
[initialData, onConfirm]
40+
);
41+
42+
return (
43+
<EuiConfirmModal
44+
title={<>Log out of account {initialData.accountName}?</>}
45+
onCancel={onModalClose}
46+
onConfirm={onModalConfirm}
47+
cancelButtonText="Cancel"
48+
confirmButtonText="Log out"
49+
buttonColor="danger"
50+
defaultFocusedButton="cancel"
51+
>
52+
Associated characters will also be removed.
53+
<ul>
54+
{characters.map(({ characterName }) => {
55+
return <li key={characterName}>{characterName}</li>;
56+
})}
57+
</ul>
58+
</EuiConfirmModal>
59+
);
60+
};
61+
62+
ModalRemoveAccount.displayName = 'ModalRemoveAccount';

0 commit comments

Comments
 (0)