MFA: shuffled components to avoid re-rendering closing the setup dialog

This commit is contained in:
gbuomprisco
2024-10-13 22:19:37 +08:00
parent fe2148730a
commit d137df2675
2 changed files with 93 additions and 97 deletions

View File

@@ -46,17 +46,25 @@ import { Trans } from '@kit/ui/trans';
import { MultiFactorAuthSetupDialog } from './multi-factor-auth-setup-dialog';
const MAX_FACTOR_COUNT = 10;
export function MultiFactorAuthFactorsList(props: { userId: string }) {
return (
<div className={'flex flex-col space-y-4'}>
<FactorsTableContainer userId={props.userId} />
<div>
<MultiFactorAuthSetupDialog userId={props.userId} />
</div>
</div>
);
}
function FactorsTableContainer(props: { userId: string }) {
const {
data: factors,
isLoading,
isError,
} = useFetchAuthFactors(props.userId);
const [unEnrolling, setUnenrolling] = useState<string>();
if (isLoading) {
return (
<div className={'flex items-center space-x-4'}>
@@ -103,37 +111,11 @@ export function MultiFactorAuthFactorsList(props: { userId: string }) {
<Trans i18nKey={'account:multiFactorAuthDescription'} />
</AlertDescription>
</Alert>
<div>
<MultiFactorAuthSetupDialog userId={props.userId} />
</div>
</div>
);
}
const canAddNewFactors = allFactors.length < MAX_FACTOR_COUNT;
return (
<div className={'flex flex-col space-y-4'}>
<FactorsTable factors={allFactors} setUnenrolling={setUnenrolling} />
<If condition={canAddNewFactors}>
<div>
<MultiFactorAuthSetupDialog userId={props.userId} />
</div>
</If>
<If condition={unEnrolling}>
{(factorId) => (
<ConfirmUnenrollFactorModal
userId={props.userId}
factorId={factorId}
setIsModalOpen={() => setUnenrolling(undefined)}
/>
)}
</If>
</div>
);
return <FactorsTable factors={allFactors} userId={props.userId} />;
}
function ConfirmUnenrollFactorModal(
@@ -157,7 +139,7 @@ function ConfirmUnenrollFactorModal(
const errorCode = response.data;
throw t(`auth:errors.${errorCode}`, {
defaultValue: t(`account:unenrollFactorError`)
defaultValue: t(`account:unenrollFactorError`),
});
}
});
@@ -205,75 +187,89 @@ function ConfirmUnenrollFactorModal(
}
function FactorsTable({
setUnenrolling,
factors,
userId,
}: React.PropsWithChildren<{
setUnenrolling: (factorId: string) => void;
factors: Factor[];
userId: string;
}>) {
const [unEnrolling, setUnenrolling] = useState<string>();
return (
<Table>
<TableHeader>
<TableRow>
<TableHead>
<Trans i18nKey={'account:factorName'} />
</TableHead>
<TableHead>
<Trans i18nKey={'account:factorType'} />
</TableHead>
<TableHead>
<Trans i18nKey={'account:factorStatus'} />
</TableHead>
<>
<Table>
<TableHeader>
<TableRow>
<TableHead>
<Trans i18nKey={'account:factorName'} />
</TableHead>
<TableHead>
<Trans i18nKey={'account:factorType'} />
</TableHead>
<TableHead>
<Trans i18nKey={'account:factorStatus'} />
</TableHead>
<TableHead />
</TableRow>
</TableHeader>
<TableBody>
{factors.map((factor) => (
<TableRow key={factor.id}>
<TableCell>
<span className={'block truncate'}>{factor.friendly_name}</span>
</TableCell>
<TableCell>
<Badge variant={'info'} className={'inline-flex uppercase'}>
{factor.factor_type}
</Badge>
</TableCell>
<td>
<Badge
className={'inline-flex capitalize'}
variant={factor.status === 'verified' ? 'success' : 'outline'}
>
{factor.status}
</Badge>
</td>
<td className={'flex justify-end'}>
<TooltipProvider>
<Tooltip>
<TooltipTrigger asChild>
<Button
variant={'ghost'}
size={'icon'}
onClick={() => setUnenrolling(factor.id)}
>
<X className={'h-4'} />
</Button>
</TooltipTrigger>
<TooltipContent>
<Trans i18nKey={'account:unenrollTooltip'} />
</TooltipContent>
</Tooltip>
</TooltipProvider>
</td>
<TableHead />
</TableRow>
))}
</TableBody>
</Table>
</TableHeader>
<TableBody>
{factors.map((factor) => (
<TableRow key={factor.id}>
<TableCell>
<span className={'block truncate'}>{factor.friendly_name}</span>
</TableCell>
<TableCell>
<Badge variant={'info'} className={'inline-flex uppercase'}>
{factor.factor_type}
</Badge>
</TableCell>
<td>
<Badge
className={'inline-flex capitalize'}
variant={factor.status === 'verified' ? 'success' : 'outline'}
>
{factor.status}
</Badge>
</td>
<td className={'flex justify-end'}>
<TooltipProvider>
<Tooltip>
<TooltipTrigger asChild>
<Button
variant={'ghost'}
size={'icon'}
onClick={() => setUnenrolling(factor.id)}
>
<X className={'h-4'} />
</Button>
</TooltipTrigger>
<TooltipContent>
<Trans i18nKey={'account:unenrollTooltip'} />
</TooltipContent>
</Tooltip>
</TooltipProvider>
</td>
</TableRow>
))}
</TableBody>
</Table>
<If condition={unEnrolling}>
{(factorId) => (
<ConfirmUnenrollFactorModal
userId={userId}
factorId={factorId}
setIsModalOpen={() => setUnenrolling(undefined)}
/>
)}
</If>
</>
);
}
@@ -291,13 +287,13 @@ function useUnenrollFactor(userId: string) {
return {
success: false as const,
data: error.code as string,
}
};
}
return {
success: true as const,
data,
}
};
};
return useMutation({

View File

@@ -53,7 +53,7 @@ export function MultiFactorAuthSetupDialog(props: { userId: string }) {
const onEnrollSuccess = useCallback(() => {
setIsOpen(false);
return toast.success(t(`multiFactorSetupSuccess`));
return toast.success(t(`account:multiFactorSetupSuccess`));
}, [t]);
return (