mirror of
https://github.com/jeffvli/feishin.git
synced 2026-06-17 00:44:23 +02:00
Add edit profile form
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
import { Group } from '@mantine/core';
|
import { Group } from '@mantine/core';
|
||||||
import { openModal } from '@mantine/modals';
|
import { closeAllModals, openModal } from '@mantine/modals';
|
||||||
import { useQueryClient } from '@tanstack/react-query';
|
import { useQueryClient } from '@tanstack/react-query';
|
||||||
import {
|
import {
|
||||||
RiLock2Line,
|
RiLock2Line,
|
||||||
@@ -14,11 +14,13 @@ import {
|
|||||||
} from 'react-icons/ri';
|
} from 'react-icons/ri';
|
||||||
import { useNavigate } from 'react-router';
|
import { useNavigate } from 'react-router';
|
||||||
import { queryKeys } from '@/renderer/api/query-keys';
|
import { queryKeys } from '@/renderer/api/query-keys';
|
||||||
|
import { UserDetailResponse } from '@/renderer/api/users.api';
|
||||||
import { Button, DropdownMenu, Text } from '@/renderer/components';
|
import { Button, DropdownMenu, Text } from '@/renderer/components';
|
||||||
import { ServerList, useServerList } from '@/renderer/features/servers';
|
import { ServerList, useServerList } from '@/renderer/features/servers';
|
||||||
import { Settings } from '@/renderer/features/settings';
|
import { Settings } from '@/renderer/features/settings';
|
||||||
import { usePermissions } from '@/renderer/features/shared';
|
import { usePermissions } from '@/renderer/features/shared';
|
||||||
import { UserList } from '@/renderer/features/users';
|
import { UserList } from '@/renderer/features/users';
|
||||||
|
import { EditUserForm } from '@/renderer/features/users/components/edit-user-form';
|
||||||
import { useAuthStore } from '@/renderer/store';
|
import { useAuthStore } from '@/renderer/store';
|
||||||
|
|
||||||
export const AppMenu = () => {
|
export const AppMenu = () => {
|
||||||
@@ -30,6 +32,10 @@ export const AppMenu = () => {
|
|||||||
const serverCredentials = useAuthStore((state) => state.serverCredentials);
|
const serverCredentials = useAuthStore((state) => state.serverCredentials);
|
||||||
const permissions = usePermissions();
|
const permissions = usePermissions();
|
||||||
const { data: servers } = useServerList();
|
const { data: servers } = useServerList();
|
||||||
|
const userId = useAuthStore((state) => state.permissions.id);
|
||||||
|
const user = queryClient.getQueryData<UserDetailResponse>(
|
||||||
|
queryKeys.users.detail(userId)
|
||||||
|
);
|
||||||
|
|
||||||
const serverList =
|
const serverList =
|
||||||
servers?.data?.map((s) => ({
|
servers?.data?.map((s) => ({
|
||||||
@@ -54,6 +60,23 @@ export const AppMenu = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleEditProfileModal = () => {
|
||||||
|
openModal({
|
||||||
|
centered: true,
|
||||||
|
children: (
|
||||||
|
<EditUserForm
|
||||||
|
repeatPassword
|
||||||
|
user={user?.data}
|
||||||
|
onCancel={closeAllModals}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
exitTransitionDuration: 300,
|
||||||
|
overflow: 'inside',
|
||||||
|
title: 'Edit Profile',
|
||||||
|
transition: 'slide-down',
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const handleManageUsersModal = () => {
|
const handleManageUsersModal = () => {
|
||||||
openModal({
|
openModal({
|
||||||
centered: true,
|
centered: true,
|
||||||
@@ -130,7 +153,10 @@ export const AppMenu = () => {
|
|||||||
Settings
|
Settings
|
||||||
</DropdownMenu.Item>
|
</DropdownMenu.Item>
|
||||||
<DropdownMenu.Divider />
|
<DropdownMenu.Divider />
|
||||||
<DropdownMenu.Item rightSection={<RiProfileLine />}>
|
<DropdownMenu.Item
|
||||||
|
rightSection={<RiProfileLine />}
|
||||||
|
onClick={handleEditProfileModal}
|
||||||
|
>
|
||||||
Edit profile
|
Edit profile
|
||||||
</DropdownMenu.Item>
|
</DropdownMenu.Item>
|
||||||
{permissions.isAdmin && (
|
{permissions.isAdmin && (
|
||||||
|
|||||||
@@ -13,12 +13,17 @@ import { usePermissions } from '@/renderer/features/shared';
|
|||||||
import { useUpdateUser } from '@/renderer/features/users/mutations/update-user';
|
import { useUpdateUser } from '@/renderer/features/users/mutations/update-user';
|
||||||
import { randomString } from '@/renderer/utils';
|
import { randomString } from '@/renderer/utils';
|
||||||
|
|
||||||
interface AddUserFormProps {
|
interface EditUserFormProps {
|
||||||
onCancel: () => void;
|
onCancel: () => void;
|
||||||
|
repeatPassword?: boolean;
|
||||||
user?: User;
|
user?: User;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const EditUserForm = ({ user, onCancel }: AddUserFormProps) => {
|
export const EditUserForm = ({
|
||||||
|
user,
|
||||||
|
onCancel,
|
||||||
|
repeatPassword,
|
||||||
|
}: EditUserFormProps) => {
|
||||||
const permissions = usePermissions();
|
const permissions = usePermissions();
|
||||||
const focusTrapRef = useFocusTrap(true);
|
const focusTrapRef = useFocusTrap(true);
|
||||||
const clipboard = useClipboard({ timeout: 1000 });
|
const clipboard = useClipboard({ timeout: 1000 });
|
||||||
@@ -28,6 +33,7 @@ export const EditUserForm = ({ user, onCancel }: AddUserFormProps) => {
|
|||||||
displayName: user?.displayName || '',
|
displayName: user?.displayName || '',
|
||||||
isAdmin: user?.isAdmin || false,
|
isAdmin: user?.isAdmin || false,
|
||||||
password: '',
|
password: '',
|
||||||
|
repeatPassword: '',
|
||||||
username: user?.username || '',
|
username: user?.username || '',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -39,6 +45,11 @@ export const EditUserForm = ({ user, onCancel }: AddUserFormProps) => {
|
|||||||
toast.info({ message: 'Password copied to clipboard' });
|
toast.info({ message: 'Password copied to clipboard' });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const isSubmitValid = () => {
|
||||||
|
if (!repeatPassword) return true;
|
||||||
|
return form.values.password === form.values.repeatPassword;
|
||||||
|
};
|
||||||
|
|
||||||
const updateUserMutation = useUpdateUser();
|
const updateUserMutation = useUpdateUser();
|
||||||
|
|
||||||
const handleUpdateUser = form.onSubmit((values) => {
|
const handleUpdateUser = form.onSubmit((values) => {
|
||||||
@@ -48,6 +59,7 @@ export const EditUserForm = ({ user, onCancel }: AddUserFormProps) => {
|
|||||||
...values,
|
...values,
|
||||||
displayName: values.displayName || undefined,
|
displayName: values.displayName || undefined,
|
||||||
password: values.password || undefined,
|
password: values.password || undefined,
|
||||||
|
repeatPassword: values.repeatPassword || undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
updateUserMutation.mutate(
|
updateUserMutation.mutate(
|
||||||
@@ -82,6 +94,13 @@ export const EditUserForm = ({ user, onCancel }: AddUserFormProps) => {
|
|||||||
{...form.getInputProps('displayName')}
|
{...form.getInputProps('displayName')}
|
||||||
/>
|
/>
|
||||||
<PasswordInput label="Password" {...form.getInputProps('password')} />
|
<PasswordInput label="Password" {...form.getInputProps('password')} />
|
||||||
|
{repeatPassword && (
|
||||||
|
<PasswordInput
|
||||||
|
label="Repeat password"
|
||||||
|
{...form.getInputProps('repeatPassword')}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
<Group position="apart">
|
<Group position="apart">
|
||||||
{permissions.isAdmin && !user?.isSuperAdmin ? (
|
{permissions.isAdmin && !user?.isSuperAdmin ? (
|
||||||
<Group>
|
<Group>
|
||||||
@@ -93,14 +112,16 @@ export const EditUserForm = ({ user, onCancel }: AddUserFormProps) => {
|
|||||||
) : (
|
) : (
|
||||||
<Group />
|
<Group />
|
||||||
)}
|
)}
|
||||||
<Button
|
{!repeatPassword && (
|
||||||
compact
|
<Button
|
||||||
sx={{ height: '1.5rem' }}
|
compact
|
||||||
variant="subtle"
|
sx={{ height: '1.5rem' }}
|
||||||
onClick={handleGeneratePassword}
|
variant="subtle"
|
||||||
>
|
onClick={handleGeneratePassword}
|
||||||
Generate password
|
>
|
||||||
</Button>
|
Generate password
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
</Group>
|
</Group>
|
||||||
|
|
||||||
<Group mt={10} position="right">
|
<Group mt={10} position="right">
|
||||||
@@ -108,6 +129,7 @@ export const EditUserForm = ({ user, onCancel }: AddUserFormProps) => {
|
|||||||
Cancel
|
Cancel
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
|
disabled={!isSubmitValid()}
|
||||||
loading={updateUserMutation.isLoading}
|
loading={updateUserMutation.isLoading}
|
||||||
type="submit"
|
type="submit"
|
||||||
variant="filled"
|
variant="filled"
|
||||||
@@ -121,5 +143,6 @@ export const EditUserForm = ({ user, onCancel }: AddUserFormProps) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
EditUserForm.defaultProps = {
|
EditUserForm.defaultProps = {
|
||||||
|
repeatPassword: false,
|
||||||
user: undefined,
|
user: undefined,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -36,8 +36,11 @@ export const useUpdateUser = () => {
|
|||||||
|
|
||||||
return { previous };
|
return { previous };
|
||||||
},
|
},
|
||||||
onSuccess: () => {
|
onSuccess: (_data, variables) => {
|
||||||
queryClient.invalidateQueries(queryKeys.users.list());
|
queryClient.invalidateQueries(queryKeys.users.list());
|
||||||
|
queryClient.invalidateQueries(
|
||||||
|
queryKeys.users.detail(variables.query.userId)
|
||||||
|
);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user