Skip to content

Commit

Permalink
70 undo approve reject account request (#84)
Browse files Browse the repository at this point in the history
* delay approved implemented but kinda buggy

* a lot better but multiple toasts

* fixed accept/decline all

* cleaned up code and commented out toasts

---------

Co-authored-by: Kristen Yee <[email protected]>
Co-authored-by: ThatMegamind <[email protected]>
  • Loading branch information
3 people authored Apr 18, 2024
1 parent af4c204 commit 457301b
Show file tree
Hide file tree
Showing 3 changed files with 220 additions and 94 deletions.
263 changes: 180 additions & 83 deletions src/components/Notifications/AccountNotification.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useState } from 'react';
import React, { useState, useEffect } from 'react';
import PropTypes from 'prop-types';
import { AccountNotificationBlock } from './NotificationElement';
import {
Expand All @@ -13,51 +13,101 @@ import {
Grid,
GridItem,
Text,
useToast,
Link,
// useToast,
} from '@chakra-ui/react';

const AccountNotification = ({ notificationBlock, today, removeEntry }) => {
const toast = useToast();
const AccountNotification = ({
notificationBlock,
today,
removeEntry,
approveAfterTimer,
idToRemove,
setApproveAfterTimer,
declineAfterTimer,
setDeclineAfterTimer,
}) => {
// const toast = useToast();
const [accounts, setAccounts] = useState(notificationBlock.getNotificationData().accounts);
const [disableChildrenButtons, setDisableChildrenButtons] = useState(false);

const blockDate = notificationBlock.getDate();
const diffTime = today - blockDate;
const diffDays = Math.floor(diffTime / (1000 * 60 * 60 * 24));

const acceptAll = async accounts => {
await Promise.all(
accounts.map(async account => {
await account.approveCallback();
}),
);

toast({
title: `Approved ${accounts?.length} accounts.`,
status: 'success',
duration: 9000,
isClosable: true,
});
const [removeNotificationBlock, setRemoveNotificationBlock] = useState(false);
const [timeoutId, setTimeoutId] = useState(undefined);

removeEntry(notificationBlock.key);
const acceptAll = async accounts => {
const timeId = setTimeout(async () => {
await Promise.all(
accounts.map(async account => {
await account.approveCallback();
}),
);
setRemoveNotificationBlock(true);
setApproveAfterTimer(true);
}, 5000); // set 5 sec timer for accept all requests
setTimeoutId(timeId);
};

const declineAll = async accounts => {
await Promise.all(
accounts.map(async account => {
await account.declineCallback();
}),
);
const timeId = setTimeout(async () => {
await Promise.all(
accounts.map(async account => {
await account.declineCallback();
}),
);
setRemoveNotificationBlock(true);
setDeclineAfterTimer(true);
}, 5000); // set 5 sec timer for accept all requests
setTimeoutId(timeId);
};

toast({
title: `Declined ${accounts?.length} accounts.`,
status: 'info',
duration: 9000,
isClosable: true,
});
removeEntry(notificationBlock.key);
const undoAll = async () => {
clearTimeout(timeoutId);
setTimeoutId(undefined);
setRemoveNotificationBlock(false);
setApproveAfterTimer(false);
setDeclineAfterTimer(false);
};

useEffect(() => {
if (approveAfterTimer && removeNotificationBlock) {
removeEntry(notificationBlock.key);
// toast({
// title: `Approved.`,
// status: 'success',
// duration: 9000,
// isClosable: true,
// });
} else if (declineAfterTimer && removeNotificationBlock) {
removeEntry(notificationBlock.key);
// toast({
// title: `Declined.`,
// status: 'info',
// duration: 9000,
// isClosable: true,
// });
} else if (approveAfterTimer) {
setAccounts(accounts => accounts.filter(account => account.id !== idToRemove));
// toast({
// title: `Approved.`,
// status: 'success',
// duration: 9000,
// isClosable: true,
// });
} else if (declineAfterTimer) {
setAccounts(accounts => accounts.filter(account => account.id !== idToRemove));
// toast({
// title: `Declined.`,
// status: 'info',
// duration: 9000,
// isClosable: true,
// });
}
}, [approveAfterTimer, declineAfterTimer, removeNotificationBlock]);

return (
<Container p="0" m="0" maxWidth="none" display="flex" flexDirection="column">
<div>
Expand All @@ -81,6 +131,9 @@ const AccountNotification = ({ notificationBlock, today, removeEntry }) => {
declineCallback={() => {
declineAll(accounts);
}}
undoCallback={() => {
undoAll(accounts);
}}
pl="3.25rem"
/>
</>
Expand Down Expand Up @@ -118,11 +171,15 @@ const AccountNotification = ({ notificationBlock, today, removeEntry }) => {
setDisableChildrenButtons(true);
declineAll(accounts);
}}
undoCallback={() => {
setDisableChildrenButtons(false);
undoAll(accounts);
}}
/>
</Container>
<AccordionPanel whiteSpace="wrap" paddingLeft="3.25rem">
<Grid templateColumns="1fr auto" gap={6}>
{accounts?.map(({ id, email, approveCallback, declineCallback }) => (
{accounts?.map(({ id, email, approveCallback, declineCallback, undoCallback }) => (
<React.Fragment key={id}>
<GridItem>
<Text color="blue.600" decoration="underline">
Expand All @@ -135,27 +192,12 @@ const AccountNotification = ({ notificationBlock, today, removeEntry }) => {
declineText="Decline"
acceptCallback={async () => {
await approveCallback();
toast({
title: `Approved ${email}.`,
status: 'success',
duration: 9000,
isClosable: true,
});
setAccounts(accounts =>
accounts.filter(account => account.id !== id),
);
}}
declineCallback={async () => {
await declineCallback();
toast({
title: `Declined ${email}.`,
status: 'info',
duration: 9000,
isClosable: true,
});
setAccounts(accounts =>
accounts.filter(account => account.id !== id),
);
}}
undoCallback={() => {
undoCallback();
}}
disableChildrenButtons={disableChildrenButtons}
/>
Expand Down Expand Up @@ -185,61 +227,116 @@ AccountNotification.propTypes = {
notificationBlock: PropTypes.instanceOf(AccountNotificationBlock),
today: PropTypes.instanceOf(Date),
removeEntry: PropTypes.func,
approveAfterTimer: PropTypes.bool,
idToRemove: PropTypes.string,
setApproveAfterTimer: PropTypes.func,
declineAfterTimer: PropTypes.bool,
setDeclineAfterTimer: PropTypes.func,
};

const AccountButtonGroup = ({
acceptText,
acceptCallback,
declineText,
declineCallback,
undoCallback,
disableChildrenButtons,
...chakraProps
}) => {
const [acceptState, setAcceptState] = useState(undefined);
const [declineState, setDeclineState] = useState(undefined);
const [approveClick, setApproveClicked] = useState(false);
const [declineClick, setDeclineClicked] = useState(false);

return (
<ButtonGroup gap="2" {...chakraProps}>
<Button
onClick={() => {
setAcceptState('loading');
setDeclineState('disabled');
acceptCallback();
}}
backgroundColor="blue.500"
color="white"
fontSize="sm"
h="6"
fontWeight="normal"
isLoading={acceptState === 'loading'}
isDisabled={acceptState === 'disabled' || disableChildrenButtons === true}
>
{acceptText}
</Button>
<Button
onClick={() => {
setDeclineState('loading');
setAcceptState('disabled');
declineCallback();
}}
backgroundColor="gray.200"
color="black"
fontSize="sm"
h="6"
fontWeight="normal"
isLoading={declineState === 'loading'}
isDisabled={declineState === 'disabled' || disableChildrenButtons === true}
>
{declineText}
</Button>
</ButtonGroup>
<>
{!approveClick && !declineClick ? (
<ButtonGroup gap="2" {...chakraProps}>
<Button
onClick={() => {
setAcceptState('loading');
setDeclineState('disabled');
setApproveClicked(true);
acceptCallback();
}}
backgroundColor="blue.500"
color="white"
fontSize="sm"
h="6"
fontWeight="normal"
isLoading={acceptState === 'loading'}
isDisabled={acceptState === 'disabled' || disableChildrenButtons === true}
>
{acceptText}
</Button>
<Button
onClick={() => {
setDeclineState('loading');
setAcceptState('disabled');
setDeclineClicked(true);
declineCallback();
}}
backgroundColor="gray.200"
color="black"
fontSize="sm"
h="6"
fontWeight="normal"
isLoading={declineState === 'loading'}
isDisabled={declineState === 'disabled' || disableChildrenButtons === true}
>
{declineText}
</Button>
</ButtonGroup>
) : (
<>
{approveClick ? (
<div>
<ButtonGroup gap="2" {...chakraProps}>
<Text>Accepted</Text>
<Link
color="blue.600"
decoration="underline"
onClick={() => {
setAcceptState(undefined);
setDeclineState(undefined);
setApproveClicked(false);
undoCallback();
}}
>
Undo
</Link>
</ButtonGroup>
</div>
) : (
<div>
<ButtonGroup gap="2" {...chakraProps}>
<Text>Declined</Text>
<Link
color="blue.600"
decoration="underline"
onClick={() => {
setAcceptState(undefined);
setDeclineState(undefined);
setDeclineClicked(false);
undoCallback();
}}
>
Undo
</Link>
</ButtonGroup>
</div>
)}
</>
)}
</>
);
};
AccountButtonGroup.propTypes = {
acceptText: PropTypes.string,
acceptCallback: PropTypes.func,
declineText: PropTypes.string,
declineCallback: PropTypes.func,
undoCallback: PropTypes.func,
disableChildrenButtons: PropTypes.bool,
chakraProps: PropTypes.any,
};
Expand Down
3 changes: 2 additions & 1 deletion src/components/Notifications/NotificationElement.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,13 @@ class AccountNotificationBlock extends NotificationBlock {
this.pendingAccounts = [];
}

addPendingAccount(id, email, approveCallback, declineCallback) {
addPendingAccount(id, email, approveCallback, declineCallback, undoCallback) {
this.pendingAccounts.push({
id: id,
email: email,
approveCallback: approveCallback,
declineCallback: declineCallback,
undoCallback: undoCallback,
});
}

Expand Down
Loading

0 comments on commit 457301b

Please sign in to comment.