🩹(frontend) disable submission button while a request is pending
If any request is taking longer than expected, the user could interact with the frontend, thinking the previous submission was not taken into account, and would re-submit a request. It happened to me while sending an invitation. Replaying request can either lead to inconsistencies in db for the user, or to errors in requests' response. I propose to disable all interactive button while submitting a request. It's good enough for this actual sprint, these types of interactivity issues could be improved later on.
This commit is contained in:
committed by
aleb_the_flash
parent
df15b41a87
commit
5ed05b96a5
@@ -57,6 +57,8 @@ export const ModalAddMembers = ({
|
||||
const { mutateAsync: createInvitation } = useCreateInvitation();
|
||||
const { mutateAsync: createTeamAccess } = useCreateTeamAccess();
|
||||
|
||||
const [isPending, setIsPending] = useState<boolean>(false);
|
||||
|
||||
const switchActions = (selectedMembers: OptionsSelect) =>
|
||||
selectedMembers.map(async (selectedMember) => {
|
||||
switch (selectedMember.type) {
|
||||
@@ -111,11 +113,15 @@ export const ModalAddMembers = ({
|
||||
};
|
||||
|
||||
const handleValidate = async () => {
|
||||
setIsPending(true);
|
||||
|
||||
const settledPromises = await Promise.allSettled<
|
||||
OptionInvitation | OptionNewMember
|
||||
>(switchActions(selectedMembers));
|
||||
|
||||
onClose();
|
||||
setIsPending(false);
|
||||
|
||||
settledPromises.forEach((settledPromise) => {
|
||||
switch (settledPromise.status) {
|
||||
case 'rejected':
|
||||
@@ -133,7 +139,12 @@ export const ModalAddMembers = ({
|
||||
<Modal
|
||||
isOpen
|
||||
leftActions={
|
||||
<Button color="secondary" fullWidth onClick={onClose}>
|
||||
<Button
|
||||
color="secondary"
|
||||
fullWidth
|
||||
onClick={onClose}
|
||||
disabled={isPending}
|
||||
>
|
||||
{t('Cancel')}
|
||||
</Button>
|
||||
}
|
||||
@@ -144,7 +155,7 @@ export const ModalAddMembers = ({
|
||||
<Button
|
||||
color="primary"
|
||||
fullWidth
|
||||
disabled={!selectedMembers.length}
|
||||
disabled={!selectedMembers.length || isPending}
|
||||
onClick={() => void handleValidate()}
|
||||
>
|
||||
{t('Validate')}
|
||||
@@ -166,6 +177,7 @@ export const ModalAddMembers = ({
|
||||
team={team}
|
||||
setSelectedMembers={setSelectedMembers}
|
||||
selectedMembers={selectedMembers}
|
||||
disabled={isPending}
|
||||
/>
|
||||
{selectedMembers.length > 0 && (
|
||||
<Box className="mt-s">
|
||||
@@ -174,7 +186,7 @@ export const ModalAddMembers = ({
|
||||
</Text>
|
||||
<ChooseRole
|
||||
currentRole={currentRole}
|
||||
disabled={false}
|
||||
disabled={isPending}
|
||||
defaultRole={Role.MEMBER}
|
||||
setRole={setSelectedRole}
|
||||
/>
|
||||
|
||||
@@ -15,12 +15,14 @@ interface SearchMembersProps {
|
||||
team: Team;
|
||||
selectedMembers: OptionsSelect;
|
||||
setSelectedMembers: (value: OptionsSelect) => void;
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
export const SearchMembers = ({
|
||||
team,
|
||||
selectedMembers,
|
||||
setSelectedMembers,
|
||||
disabled,
|
||||
}: SearchMembersProps) => {
|
||||
const { t } = useTranslation();
|
||||
const [input, setInput] = useState('');
|
||||
@@ -100,6 +102,7 @@ export const SearchMembers = ({
|
||||
|
||||
return (
|
||||
<AsyncSelect
|
||||
isDisabled={disabled}
|
||||
aria-label={t('Find a member to add to the team')}
|
||||
isMulti
|
||||
loadOptions={loadOptions}
|
||||
|
||||
@@ -37,6 +37,7 @@ export const ModalRole = ({
|
||||
mutate: updateTeamAccess,
|
||||
error: errorUpdate,
|
||||
isError: isErrorUpdate,
|
||||
isPending,
|
||||
} = useUpdateTeamAccess({
|
||||
onSuccess: () => {
|
||||
toast(t('The role has been updated'), VariantType.SUCCESS, {
|
||||
@@ -53,7 +54,12 @@ export const ModalRole = ({
|
||||
<Modal
|
||||
isOpen
|
||||
leftActions={
|
||||
<Button color="secondary" fullWidth onClick={() => onClose()}>
|
||||
<Button
|
||||
color="secondary"
|
||||
fullWidth
|
||||
onClick={() => onClose()}
|
||||
disabled={isPending}
|
||||
>
|
||||
{t('Cancel')}
|
||||
</Button>
|
||||
}
|
||||
@@ -71,7 +77,7 @@ export const ModalRole = ({
|
||||
accessId: access.id,
|
||||
});
|
||||
}}
|
||||
disabled={isNotAllowed}
|
||||
disabled={isNotAllowed || isPending}
|
||||
>
|
||||
{t('Validate')}
|
||||
</Button>
|
||||
|
||||
@@ -57,7 +57,10 @@ export const CardCreateTeam = () => {
|
||||
<StyledLink href="/">
|
||||
<Button color="secondary">{t('Cancel')}</Button>
|
||||
</StyledLink>
|
||||
<Button onClick={() => createTeam(teamName)} disabled={!teamName}>
|
||||
<Button
|
||||
onClick={() => createTeam(teamName)}
|
||||
disabled={!teamName || isPending}
|
||||
>
|
||||
{t('Create the team')}
|
||||
</Button>
|
||||
</Box>
|
||||
|
||||
Reference in New Issue
Block a user