@mui/material#SpeedDial TypeScript Examples
The following examples show how to use
@mui/material#SpeedDial.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: TransactionList.tsx From abrechnung with GNU Affero General Public License v3.0 | 4 votes |
export default function TransactionList({ group }) {
const [speedDialOpen, setSpeedDialOpen] = useState(false);
const toggleSpeedDial = () => setSpeedDialOpen((currValue) => !currValue);
const [showTransferCreateDialog, setShowTransferCreateDialog] = useState(false);
const [showPurchaseCreateDialog, setShowPurchaseCreateDialog] = useState(false);
const transactions = useRecoilValue(transactionsSeenByUser(group.id));
const currentUser = useRecoilValue(userData);
const userPermissions = useRecoilValue(currUserPermissions(group.id));
const userAccounts = useRecoilValue(accountsOwnedByUser({ groupID: group.id, userID: currentUser.id }));
const groupAccountMap = useRecoilValue(accountIDsToName(group.id));
const theme: Theme = useTheme();
const isSmallScreen = useMediaQuery(theme.breakpoints.down("md"));
const [filteredTransactions, setFilteredTransactions] = useState([]);
const [searchValue, setSearchValue] = useState("");
const [sortMode, setSortMode] = useState("last_changed"); // last_changed, description, value, billed_at
useEffect(() => {
let filtered = transactions;
if (searchValue != null && searchValue !== "") {
filtered = transactions.filter((t) => t.filter(searchValue, groupAccountMap));
}
filtered = [...filtered].sort(getTransactionSortFunc(sortMode));
setFilteredTransactions(filtered);
}, [searchValue, setFilteredTransactions, sortMode, transactions, userAccounts]);
useTitle(`${group.name} - Transactions`);
const openPurchaseCreateDialog = () => {
setShowPurchaseCreateDialog(true);
};
const openTransferCreateDialog = () => {
setShowTransferCreateDialog(true);
};
return (
<>
<MobilePaper>
<Box
sx={{
display: "flex",
flexDirection: { xs: "column", sm: "column", md: "row", lg: "row" },
alignItems: { md: "flex-end" },
pl: "16px",
justifyContent: "space-between",
}}
>
<Box sx={{ display: "flex-item" }}>
<Box sx={{ minWidth: "56px", pt: "16px" }}>
<SearchIcon sx={{ color: "action.active" }} />
</Box>
<Input
value={searchValue}
onChange={(e) => setSearchValue(e.target.value)}
placeholder="Search…"
inputProps={{
"aria-label": "search",
}}
sx={{ pt: "16px" }}
endAdornment={
<InputAdornment position="end">
<IconButton
aria-label="clear search input"
onClick={(e) => setSearchValue("")}
edge="end"
>
<Clear />
</IconButton>
</InputAdornment>
}
/>
<FormControl variant="standard" sx={{ minWidth: 120, ml: 3 }}>
<InputLabel id="select-sort-by-label">Sort by</InputLabel>
<Select
labelId="select-sort-by-label"
id="select-sort-by"
label="Sort by"
onChange={(evt) => setSortMode(evt.target.value)}
value={sortMode}
>
<MenuItem value="last_changed">Last changed</MenuItem>
<MenuItem value="description">Description</MenuItem>
<MenuItem value="value">Value</MenuItem>
<MenuItem value="billed_at">Date</MenuItem>
</Select>
</FormControl>
</Box>
{!isSmallScreen && (
<Box sx={{ display: "flex-item" }}>
<div style={{ padding: "8px" }}>
<Add color="primary" />
</div>
<Tooltip title="Create Purchase">
<IconButton color="primary" onClick={openPurchaseCreateDialog}>
<PurchaseIcon />
</IconButton>
</Tooltip>
<Tooltip title="Create Transfer">
<IconButton color="primary" onClick={openTransferCreateDialog}>
<TransferIcon />
</IconButton>
</Tooltip>
</Box>
)}
</Box>
<Divider sx={{ mt: 1 }} />
<List>
{transactions.length === 0 ? (
<Alert severity="info">No Transactions</Alert>
) : (
filteredTransactions.map((transaction) => (
<TransactionListEntry key={transaction.id} group={group} transaction={transaction} />
))
)}
</List>
<TransferCreateModal
group={group}
show={showTransferCreateDialog}
onClose={(evt, reason) => {
if (reason !== "backdropClick") {
setShowTransferCreateDialog(false);
}
}}
/>
<PurchaseCreateModal
group={group}
show={showPurchaseCreateDialog}
onClose={(evt, reason) => {
if (reason !== "backdropClick") {
setShowPurchaseCreateDialog(false);
}
}}
/>
</MobilePaper>
{userPermissions.can_write && (
<SpeedDial
ariaLabel="Create Account"
sx={{ position: "fixed", bottom: 20, right: 20 }}
icon={<SpeedDialIcon />}
// onClose={() => setSpeedDialOpen(false)}
// onOpen={() => setSpeedDialOpen(true)}
onClick={toggleSpeedDial}
open={speedDialOpen}
>
<SpeedDialAction
icon={<PurchaseIcon />}
tooltipTitle="Purchase"
tooltipOpen
onClick={openPurchaseCreateDialog}
/>
<SpeedDialAction
icon={<TransferIcon />}
tooltipTitle="Transfer"
tooltipOpen
onClick={openTransferCreateDialog}
/>
</SpeedDial>
)}
</>
);
}
Example #2
Source File: AccountList.tsx From abrechnung with GNU Affero General Public License v3.0 | 4 votes |
export default function AccountList({ group }) {
const [speedDialOpen, setSpeedDialOpen] = useState(false);
const toggleSpeedDial = () => setSpeedDialOpen((currValue) => !currValue);
const [showPersonalAccountCreationModal, setShowPersonalAccountCreationModal] = useState(false);
const [showClearingAccountCreationModal, setShowClearingAccountCreationModal] = useState(false);
const [activeTab, setActiveTab] = useState("personal");
const [searchValuePersonal, setSearchValuePersonal] = useState("");
const [searchValueClearing, setSearchValueClearing] = useState("");
const [showPersonalAccountEditModal, setShowPersonalAccountEditModal] = useState(false);
const [showClearingAccountEditModal, setShowClearingAccountEditModal] = useState(false);
const [clearingAccountToCopy, setClearingAccountToCopy] = useState(undefined);
const [accountToEdit, setAccountToEdit] = useState(null);
const [clearingAccountToEdit, setClearingAccountToEdit] = useState(null);
const setAccounts = useSetRecoilState(groupAccounts(group.id));
const personalAccounts = useRecoilValue(personalAccountsSeenByUser(group.id));
const clearingAccounts = useRecoilValue(clearingAccountsSeenByUser(group.id));
const allAccounts = useRecoilValue(accountsSeenByUser(group.id));
const [accountToDelete, setAccountToDelete] = useState(null);
const userPermissions = useRecoilValue(currUserPermissions(group.id));
const currentUser = useRecoilValue(userData);
const memberIDToUsername = useRecoilValue(groupMemberIDsToUsername(group.id));
const [filteredPersonalAccounts, setFilteredPersonalAccounts] = useState([]);
const [filteredClearingAccounts, setFilteredClearingAccounts] = useState([]);
useEffect(() => {
if (searchValuePersonal != null && searchValuePersonal !== "") {
setFilteredPersonalAccounts(
personalAccounts.filter((t) => {
return (
t.name.toLowerCase().includes(searchValuePersonal.toLowerCase()) ||
t.description.toLowerCase().includes(searchValuePersonal.toLowerCase())
);
})
);
} else {
return setFilteredPersonalAccounts(personalAccounts);
}
}, [personalAccounts, searchValuePersonal, setFilteredPersonalAccounts]);
useEffect(() => {
if (searchValueClearing != null && searchValueClearing !== "") {
setFilteredClearingAccounts(
clearingAccounts.filter((t) => {
return (
t.name.toLowerCase().includes(searchValueClearing.toLowerCase()) ||
t.description.toLowerCase().includes(searchValueClearing.toLowerCase())
);
})
);
} else {
return setFilteredClearingAccounts(clearingAccounts);
}
}, [clearingAccounts, searchValueClearing, setFilteredClearingAccounts]);
useTitle(`${group.name} - Accounts`);
const openAccountEdit = (account) => {
setAccountToEdit(account);
setShowPersonalAccountEditModal(true);
};
const closeAccountEdit = (evt, reason) => {
if (reason !== "backdropClick") {
setShowPersonalAccountEditModal(false);
setAccountToEdit(null);
}
};
const openClearingAccountEdit = (account) => {
setClearingAccountToEdit(account);
setShowClearingAccountEditModal(true);
};
const closeClearingAccountEdit = (evt, reason) => {
if (reason !== "backdropClick") {
setShowClearingAccountEditModal(false);
setClearingAccountToEdit(null);
}
};
const confirmDeleteAccount = () => {
if (accountToDelete !== null) {
deleteAccount({ accountID: accountToDelete })
.then((account) => {
updateAccount(account, setAccounts);
setAccountToDelete(null);
})
.catch((err) => {
toast.error(err);
});
}
};
const openCreateDialog = () => {
setClearingAccountToCopy(undefined);
setShowClearingAccountCreationModal(true);
};
const copyClearingAccount = (account) => {
setClearingAccountToCopy(account);
setShowClearingAccountCreationModal(true);
};
return (
<>
<MobilePaper>
<TabContext value={activeTab}>
<Box sx={{ borderBottom: 1, borderColor: "divider" }}>
<TabList onChange={(e, newValue) => setActiveTab(newValue)} centered>
<Tab
value="personal"
label={
<TextBadge badgeContent={personalAccounts.length} color="primary">
<span>Personal Accounts</span>
</TextBadge>
}
/>
<Tab
label={
<TextBadge badgeContent={clearingAccounts.length} color="primary">
<span>Clearing Accounts</span>
</TextBadge>
}
value="clearing"
/>
</TabList>
</Box>
<TabPanel value="personal">
<List>
{personalAccounts.length === 0 ? (
<Alert severity="info">No Accounts</Alert>
) : (
<>
<ListItem>
<Input
value={searchValuePersonal}
onChange={(e) => setSearchValuePersonal(e.target.value)}
placeholder="Search…"
inputProps={{
"aria-label": "search",
}}
endAdornment={
<InputAdornment position="end">
<IconButton
aria-label="clear search input"
onClick={(e) => setSearchValuePersonal("")}
edge="end"
>
<Clear />
</IconButton>
</InputAdornment>
}
/>
</ListItem>
<Divider />
{filteredPersonalAccounts.map((account) => (
<ListItem sx={{ padding: 0 }} key={account.id}>
<ListItemLink to={`/groups/${group.id}/accounts/${account.id}`}>
<ListItemText
primary={
<div>
<span>{account.name}</span>
{account.owning_user_id === currentUser.id ? (
<span>
, owned by{" "}
<Chip
size="small"
component="span"
color="primary"
label="you"
/>
</span>
) : (
account.owning_user_id !== null && (
<span>
, owned by{" "}
<Chip
size="small"
component="span"
color="secondary"
label={
memberIDToUsername[
account.owning_user_id
]
}
/>
</span>
)
)}
</div>
}
secondary={account.description}
/>
</ListItemLink>
{userPermissions.can_write && (
<ListItemSecondaryAction>
<IconButton
color="primary"
onClick={() => openAccountEdit(account)}
>
<Edit />
</IconButton>
<IconButton
color="error"
onClick={() => setAccountToDelete(account.id)}
>
<Delete />
</IconButton>
</ListItemSecondaryAction>
)}
</ListItem>
))}
</>
)}
</List>
{userPermissions.can_write && (
<>
<Grid container justifyContent="center">
<Tooltip title="Create Personal Account">
<IconButton
color="primary"
onClick={() => setShowPersonalAccountCreationModal(true)}
>
<Add />
</IconButton>
</Tooltip>
</Grid>
<CreateAccountModal
show={showPersonalAccountCreationModal}
onClose={(evt, reason) => {
if (reason !== "backdropClick") {
setShowPersonalAccountCreationModal(false);
}
}}
group={group}
/>
<EditAccountModal
show={showPersonalAccountEditModal}
onClose={closeAccountEdit}
account={accountToEdit}
group={group}
/>
</>
)}
</TabPanel>
<TabPanel value="clearing">
<List>
{clearingAccounts.length === 0 ? (
<Alert severity="info">No Accounts</Alert>
) : (
<>
<ListItem>
<Input
value={searchValueClearing}
onChange={(e) => setSearchValueClearing(e.target.value)}
placeholder="Search…"
inputProps={{
"aria-label": "search",
}}
endAdornment={
<InputAdornment position="end">
<IconButton
aria-label="clear search input"
onClick={(e) => setSearchValueClearing("")}
edge="end"
>
<Clear />
</IconButton>
</InputAdornment>
}
/>
</ListItem>
<Divider />
{filteredClearingAccounts.map((account) => (
<ListItem sx={{ padding: 0 }} key={account.id}>
<ListItemLink to={`/groups/${group.id}/accounts/${account.id}`}>
<ListItemText primary={account.name} secondary={account.description} />
</ListItemLink>
{userPermissions.can_write && (
<ListItemSecondaryAction>
<IconButton
color="primary"
onClick={() => openClearingAccountEdit(account)}
>
<Edit />
</IconButton>
<IconButton
color="primary"
onClick={() => copyClearingAccount(account)}
>
<ContentCopy />
</IconButton>
<IconButton
color="error"
onClick={() => setAccountToDelete(account.id)}
>
<Delete />
</IconButton>
</ListItemSecondaryAction>
)}
</ListItem>
))}
</>
)}
</List>
{userPermissions.can_write && (
<>
<Grid container justifyContent="center">
<Tooltip title="Create Clearing Account">
<IconButton color="primary" onClick={openCreateDialog}>
<Add />
</IconButton>
</Tooltip>
</Grid>
<CreateClearingAccountModal
show={showClearingAccountCreationModal}
onClose={(evt, reason) => {
if (reason !== "backdropClick") {
setShowClearingAccountCreationModal(false);
}
}}
initialValues={clearingAccountToCopy}
group={group}
/>
<EditClearingAccountModal
show={showClearingAccountEditModal}
onClose={closeClearingAccountEdit}
account={clearingAccountToEdit}
group={group}
/>
</>
)}
</TabPanel>
</TabContext>
</MobilePaper>
{userPermissions.can_write && (
<>
<SpeedDial
ariaLabel="Create Account"
sx={{ position: "fixed", bottom: 20, right: 20 }}
icon={<SpeedDialIcon />}
// onClose={() => setSpeedDialOpen(false)}
// onOpen={() => setSpeedDialOpen(true)}
onClick={toggleSpeedDial}
open={speedDialOpen}
>
<SpeedDialAction
icon={<PersonalAccountIcon />}
tooltipTitle="Personal"
tooltipOpen
onClick={() => setShowPersonalAccountCreationModal(true)}
/>
<SpeedDialAction
icon={<ClearingAccountIcon />}
tooltipTitle="Clearing"
tooltipOpen
onClick={openCreateDialog}
/>
</SpeedDial>
<Dialog maxWidth="xs" aria-labelledby="confirmation-dialog-title" open={accountToDelete !== null}>
<DialogTitle id="confirmation-dialog-title">Confirm delete account</DialogTitle>
<DialogContent dividers>
Are you sure you want to delete the account "
{allAccounts.find((acc) => acc.id === accountToDelete)?.name}"
</DialogContent>
<DialogActions>
<Button autoFocus onClick={() => setAccountToDelete(null)} color="primary">
Cancel
</Button>
<Button onClick={confirmDeleteAccount} color="error">
Ok
</Button>
</DialogActions>
</Dialog>
</>
)}
</>
);
}