@mui/material#TableContainer TypeScript Examples
The following examples show how to use
@mui/material#TableContainer.
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: table.component.tsx From master-frontend-lemoncode with MIT License | 6 votes |
TableComponent: React.FunctionComponent<Props> = (props) => {
const { memberList, className } = props;
return (
<TableContainer className={className}>
<Table>
<HeaderComponent />
<TableBody>
{memberList.map((member) => (
<RowComponent key={member.id} member={member} />
))}
</TableBody>
</Table>
</TableContainer>
);
}
Example #2
Source File: index.tsx From Search-Next with GNU General Public License v3.0 | 6 votes |
Table: React.FC<TableProps> = (props) => {
const { dataSource, columns, size } = props;
return (
<TableContainer component={Paper}>
<MTable sx={{ minWidth: 650 }} size={size}>
<TableHead>
<TableRow>
{columns.map(({ name, field, align = 'left', ...i }) => (
<StyledTableCell key={field} align={align}>
{name}
</StyledTableCell>
))}
</TableRow>
</TableHead>
<TableBody>
{dataSource.map((row, index) => (
<StyledTableRow
key={row.name}
sx={{ '&:last-child td, &:last-child th': { border: 0 } }}
>
{columns.map(({ name, field, align = 'left', render, ...i }) => (
<StyledTableCell key={field} align={align}>
{render ? render(row[field], row, index) : row[field]}
</StyledTableCell>
))}
</StyledTableRow>
))}
</TableBody>
</MTable>
{dataSource.length === 0 && (
<div className="w-full">
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
</div>
)}
</TableContainer>
);
}
Example #3
Source File: ClearingAccountDetail.tsx From abrechnung with GNU Affero General Public License v3.0 | 5 votes |
export default function ClearingAccountDetail({ group, account }) {
const classes = useStyles();
const accounts = useRecoilValue(accountsSeenByUser(group.id));
const balances = useRecoilValue(accountBalances(group.id));
const [showAdvanced, setShowAdvanced] = useState(false);
useEffect(() => {
for (const share of Object.values(account.clearing_shares)) {
if (share !== 1) {
setShowAdvanced(true);
break;
}
}
}, [account]);
const clearingShareValue = (accountID) => {
return account.clearing_shares?.hasOwnProperty(accountID) ? account.clearing_shares[accountID] : 0;
};
return (
<TableContainer>
<Table>
<TableHead>
<TableRow>
<TableCell>Account</TableCell>
{showAdvanced && <TableCell>Shares</TableCell>}
<TableCell width="100px" align="right">
Shared
</TableCell>
</TableRow>
</TableHead>
<TableBody>
{accounts
.filter((a) => balances[account.id].clearingResolution.hasOwnProperty(a.id))
.map((a) => (
<TableRow hover key={a.id}>
<TableCell className={classes.tableLinkCell}>
{/*TODO: proper link*/}
<Link className={classes.tableLink} to={`/groups/${group.id}/accounts/${a.id}`}>
<Grid container direction="row" alignItems="center">
<Grid item>
{a.type === "personal" ? (
<PersonalAccountIcon />
) : (
<ClearingAccountIcon />
)}
</Grid>
<Grid item sx={{ ml: 1 }}>
<Typography variant="body2" component="span">
{a.name}
</Typography>
</Grid>
</Grid>
</Link>
</TableCell>
{showAdvanced && <TableCell width="50px">{clearingShareValue(a.id)}</TableCell>}
<TableCell width="100px" align="right">
{balances[account.id].clearingResolution[a.id].toFixed(2)} {group.currency_symbol}
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
);
}
Example #4
Source File: EntityPreview.tsx From firecms with MIT License | 4 votes |
/**
* Use this component to render a preview of a property values
* @param entity
* @param schema
* @param path
* @constructor
* @category Components
*/
export function EntityPreview<M>(
{
entity,
schema: inputSchema,
path
}: EntityPreviewProps<M>) {
const classes = useStyles();
const appConfig: FireCMSContext | undefined = useFireCMSContext();
const schema: ResolvedEntitySchema<M> = useMemo(() => computeSchema({
schemaOrResolver: inputSchema,
path,
entityId: entity.id,
values: entity?.values,
previousValues: entity?.values
}), [inputSchema, path, entity]);
const properties: Properties = schema.properties;
return (
<TableContainer>
<Table aria-label="entity table">
<TableBody>
<TableRow>
<TableCell align="right"
component="td"
scope="row"
className={classes.titleCell}>
<Typography variant={"caption"}
color={"textSecondary"}>
Id
</Typography>
</TableCell>
<TableCell padding="none"
className={classes.iconCell}>
{getIdIcon("disabled", "small")}
</TableCell>
<TableCell className={classes.valuePreview}>
<Box display="flex" alignItems="center">
{entity.id}
{appConfig?.entityLinkBuilder &&
<a href={appConfig.entityLinkBuilder({ entity })}
rel="noopener noreferrer"
target="_blank">
<IconButton
aria-label="go-to-entity-datasource"
size="large">
<OpenInNewIcon
fontSize={"small"}/>
</IconButton>
</a>}
</Box>
</TableCell>
</TableRow>
{schema && Object.entries(properties)
.map(([key, property]) => {
const value = (entity.values as any)[key];
return (
<TableRow
key={"entity_prev" + property.title + key}>
<TableCell align="right"
component="td"
scope="row"
className={classes.titleCell}>
<Typography
style={{ paddingLeft: "16px" }}
variant={"caption"}
color={"textSecondary"}>
{property.title}
</Typography>
</TableCell>
<TableCell padding="none"
className={classes.iconCell}>
{getIconForProperty(property, "disabled", "small")}
</TableCell>
<TableCell
className={classes.valuePreview}>
<ErrorBoundary>
<PreviewComponent
name={key}
value={value}
property={property as AnyProperty}
size={"regular"}/>
</ErrorBoundary>
</TableCell>
</TableRow>
);
})}
</TableBody>
</Table>
</TableContainer>
);
}
Example #5
Source File: ClearingSharesFormElement.tsx From abrechnung with GNU Affero General Public License v3.0 | 4 votes |
export default function ClearingSharesFormElement({ group, clearingShares, setClearingShares, accountID = undefined }) {
const accounts = useRecoilValue(accountsSeenByUser(group.id));
const [showAdvanced, setShowAdvanced] = useState(false);
const [searchValue, setSearchValue] = useState("");
const [filteredAccounts, setFilteredAccounts] = useState([]);
useEffect(() => {
if (searchValue != null && searchValue !== "") {
setFilteredAccounts(
accounts.filter((acc) => {
return acc.name.toLowerCase().includes(searchValue.toLowerCase());
})
);
} else {
setFilteredAccounts(accounts);
}
}, [searchValue, accounts]);
return (
<>
<Grid container direction="row" justifyContent="space-between">
<Typography variant="subtitle1">Allocation to</Typography>
<FormControlLabel
control={<Checkbox name={`show-advanced`} />}
checked={showAdvanced}
onChange={(event: React.ChangeEvent<HTMLInputElement>) => setShowAdvanced(event.target.checked)}
label="Advanced"
/>
</Grid>
<TableContainer sx={{ maxHeight: 400 }}>
<Table size="small" stickyHeader>
<TableHead>
<TableRow>
<TableCell>
<TextField
placeholder="Search ..."
margin="none"
size="small"
value={searchValue}
onChange={(e) => setSearchValue(e.target.value)}
variant="standard"
InputProps={{
startAdornment: (
<InputAdornment position="start">
<SearchIcon />
</InputAdornment>
),
}}
/>
</TableCell>
<TableCell width="100px">Shares</TableCell>
</TableRow>
</TableHead>
<TableBody>
{filteredAccounts.map(
(account) =>
(accountID === undefined || account.id !== accountID) && (
<TableRow hover key={account.id}>
<TableCell>
<Grid container direction="row" alignItems="center">
<Grid item>
{account.type === "personal" ? <Person /> : <CompareArrows />}
</Grid>
<Grid item sx={{ ml: 1 }}>
<Typography variant="body2" component="span">
{account.name}
</Typography>
</Grid>
</Grid>
</TableCell>
<TableCell width="100px">
{showAdvanced ? (
<ShareInput
onChange={(value) =>
setClearingShares({
...(clearingShares !== undefined ? clearingShares : {}),
[account.id]: value,
})
}
value={
clearingShares && clearingShares.hasOwnProperty(account.id)
? clearingShares[account.id]
: 0.0
}
/>
) : (
<Checkbox
name={`${account.name}-checked`}
checked={
clearingShares &&
clearingShares.hasOwnProperty(account.id) &&
clearingShares[account.id] !== 0
}
onChange={(event) =>
setClearingShares({
...(clearingShares !== undefined ? clearingShares : {}),
[account.id]: event.target.checked ? 1.0 : 0.0,
})
}
/>
)}
</TableCell>
</TableRow>
)
)}
</TableBody>
</Table>
</TableContainer>
</>
);
}
Example #6
Source File: PurchaseDebitorShares.tsx From abrechnung with GNU Affero General Public License v3.0 | 4 votes |
export default function PurchaseDebitorShares({ group, transaction, showPositions = false }) {
const classes = useStyles();
const isSmallScreen = useMediaQuery((theme: Theme) => theme.breakpoints.down("sm"));
const accounts = useRecoilValue(accountsSeenByUser(group.id));
const [searchValue, setSearchValue] = useState("");
const [filteredAccounts, setFilteredAccounts] = useState([]);
const [showAdvanced, setShowAdvanced] = useState(false);
const transactionHasPositions =
transaction.positions != null && transaction.positions.find((item) => !item.deleted) !== undefined;
const setLocalTransactionDetails = useSetRecoilState(pendingTransactionDetailChanges(transaction.id));
useEffect(() => {
for (const share of Object.values(transaction.debitor_shares)) {
if (share !== 1) {
setShowAdvanced(true);
break;
}
}
}, [transaction]);
useEffect(() => {
if (searchValue != null && searchValue !== "") {
setFilteredAccounts(
accounts.filter((acc) => {
return acc.name.toLowerCase().includes(searchValue.toLowerCase());
})
);
} else {
setFilteredAccounts(accounts);
}
}, [searchValue, accounts]);
const debitorShareValueForAccount = (accountID) => {
return transaction.debitor_shares && transaction.debitor_shares.hasOwnProperty(accountID)
? transaction.debitor_shares[accountID]
: 0;
};
const debitorValueForAccount = (accountID) => {
if (!transaction.account_balances.hasOwnProperty(accountID)) {
return 0.0;
}
return transaction.account_balances[accountID].common_debitors;
};
const positionValueForAccount = (accountID) => {
if (!transaction.account_balances.hasOwnProperty(accountID)) {
return 0.0;
}
return transaction.account_balances[accountID].positions;
};
const updateDebShare = (accountID, value) => {
if (value === 0) {
setLocalTransactionDetails((currState) => {
let newDebitorShares;
if (currState.debitor_shares === undefined) {
newDebitorShares = {
...transaction.debitor_shares,
};
} else {
newDebitorShares = {
...currState.debitor_shares,
};
}
delete newDebitorShares[accountID];
return {
...currState,
debitor_shares: newDebitorShares,
};
});
} else {
setLocalTransactionDetails((currState) => {
let newDebitorShares;
if (currState.debitor_shares === undefined) {
newDebitorShares = {
...transaction.debitor_shares,
[accountID]: value,
};
} else {
newDebitorShares = {
...currState.debitor_shares,
[accountID]: value,
};
}
return {
...currState,
debitor_shares: newDebitorShares,
};
});
}
};
return (
<div>
<Box className={classes.listItem}>
<Grid container direction="row" justifyContent="space-between">
<Typography variant="subtitle1" className={classes.checkboxLabel}>
<Box sx={{ display: "flex", alignItems: "flex-end" }}>For whom</Box>
</Typography>
{transaction.is_wip && (
<FormControlLabel
control={<Checkbox name={`show-advanced`} />}
checked={showAdvanced}
onChange={(event: React.ChangeEvent<HTMLInputElement>) =>
setShowAdvanced(event.target.checked)
}
label="Advanced"
/>
)}
</Grid>
</Box>
<Divider variant="middle" className={classes.divider} />
<TableContainer sx={{ maxHeight: { md: 400 } }}>
<Table size="small" stickyHeader>
<TableHead>
<TableRow>
<TableCell>
{isSmallScreen ? (
"Account"
) : (
<TextField
placeholder="Search ..."
margin="none"
size="small"
value={searchValue}
onChange={(e) => setSearchValue(e.target.value)}
variant="standard"
InputProps={{
startAdornment: (
<InputAdornment position="start">
<SearchIcon />
</InputAdornment>
),
endAdornment: (
<InputAdornment position="end">
<IconButton
aria-label="clear search input"
onClick={(e) => setSearchValue("")}
edge="end"
>
<Clear />
</IconButton>
</InputAdornment>
),
}}
/>
)}
</TableCell>
<TableCell width="100px">Shares</TableCell>
{showPositions || transactionHasPositions ? (
<>
<TableCell width="100px" align="right">
Positions
</TableCell>
<TableCell width="3px" align="center">
+
</TableCell>
<TableCell width="100px" align="right">
Shared + Rest
</TableCell>
<TableCell width="3px" align="center">
=
</TableCell>
<TableCell width="100px" align="right">
Total
</TableCell>
</>
) : (
<TableCell width="100px" align="right">
Shared
</TableCell>
)}
</TableRow>
</TableHead>
<TableBody>
{filteredAccounts.map((account) => (
<AccountTableRow
key={account.id}
transaction={transaction}
account={account}
debitorValueForAccount={debitorValueForAccount}
debitorShareValueForAccount={debitorShareValueForAccount}
positionValueForAccount={positionValueForAccount}
showAdvanced={showAdvanced}
showPositions={showPositions}
updateDebShare={updateDebShare}
/>
))}
</TableBody>
</Table>
</TableContainer>
</div>
);
}
Example #7
Source File: PurchaseDebitorSharesReadOnly.tsx From abrechnung with GNU Affero General Public License v3.0 | 4 votes |
export default function PurchaseDebitorSharesReadOnly({ group, transaction }) {
const classes = useStyles();
const accounts = useRecoilValue(accountsSeenByUser(group.id));
const [debitorShareValues, setDebitorShareValues] = useState({});
const [showAdvanced, setShowAdvanced] = useState(false);
const transactionHasPositions =
transaction.positions != null && transaction.positions.find((item) => !item.deleted) !== undefined;
useEffect(() => {
setDebitorShareValues(transaction.debitor_shares);
for (const share of Object.values(transaction.debitor_shares)) {
if (share !== 1) {
setShowAdvanced(true);
break;
}
}
}, [transaction]);
const debitorShareValueForAccount = (accountID) => {
return debitorShareValues.hasOwnProperty(accountID) ? debitorShareValues[accountID] : 0;
};
return (
<List>
<ListItem className={classes.listItem}>
<Grid container direction="row" justifyContent="space-between">
<Typography variant="subtitle1" className={classes.checkboxLabel}>
<Box sx={{ display: "flex", alignItems: "flex-end" }}>For whom</Box>
</Typography>
</Grid>
</ListItem>
<Divider variant="middle" className={classes.divider} />
<TableContainer>
<Table>
<TableHead>
<TableRow>
<TableCell>Account</TableCell>
{showAdvanced && <TableCell>Shares</TableCell>}
{transactionHasPositions ? (
<>
<TableCell width="100px" align="right">
Positions
</TableCell>
<TableCell width="3px" align="center">
+
</TableCell>
<TableCell width="100px" align="right">
Shared Rest
</TableCell>
<TableCell width="3px" align="center">
=
</TableCell>
<TableCell width="100px" align="right">
Total
</TableCell>
</>
) : (
<TableCell width="100px" align="right">
Shared
</TableCell>
)}
</TableRow>
</TableHead>
<TableBody>
{accounts
.filter(
(account) =>
transaction.account_balances.hasOwnProperty(account.id) &&
(transaction.account_balances[account.id].common_debitors !== 0 ||
transaction.account_balances[account.id].positions)
)
.map((account) => (
<TableRow hover key={account.id}>
<TableCell className={classes.tableLinkCell}>
{/*TODO: proper link*/}
<Link
className={classes.tableLink}
to={`/groups/${group.id}/accounts/${account.id}`}
>
<Grid container direction="row" alignItems="center">
<Grid item>
{account.type === "personal" ? (
<PersonalAccountIcon />
) : (
<ClearingAccountIcon />
)}
</Grid>
<Grid item sx={{ ml: 1 }}>
<Typography variant="body2" component="span">
{account.name}
</Typography>
</Grid>
</Grid>
</Link>
</TableCell>
{showAdvanced && (
<TableCell width="50px">{debitorShareValueForAccount(account.id)}</TableCell>
)}
{transactionHasPositions ? (
<>
<TableCell align="right">
{transaction.account_balances[account.id].positions.toFixed(2)}{" "}
{transaction.currency_symbol}
</TableCell>
<TableCell></TableCell>
<TableCell align="right">
{transaction.account_balances[account.id].common_debitors.toFixed(2)}{" "}
{transaction.currency_symbol}
</TableCell>
<TableCell></TableCell>
<TableCell width="100px" align="right">
{(
transaction.account_balances[account.id].common_debitors +
transaction.account_balances[account.id].positions
).toFixed(2)}{" "}
{transaction.currency_symbol}
</TableCell>
</>
) : (
<TableCell width="100px" align="right">
{transaction.account_balances[account.id].common_debitors.toFixed(2)}{" "}
{transaction.currency_symbol}
</TableCell>
)}
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
</List>
);
}
Example #8
Source File: TransactionPositions.tsx From abrechnung with GNU Affero General Public License v3.0 | 4 votes |
export default function TransactionPositions({ group, transaction }: PropTypes) {
const classes = useStyles();
const accounts = useRecoilValue(accountsSeenByUser(group.id));
const [localPositionChanges, setLocalPositionChanges] = useRecoilState(
pendingTransactionPositionChanges(transaction.id)
);
const [showAdvanced, setShowAdvanced] = useState(false);
const [positions, setPositions] = useState([]);
useEffect(() => {
setPositions(
transaction.positions
.map((p) => ({ ...p, is_empty: false }))
.concat([
{
...localPositionChanges.empty,
is_empty: true,
},
])
);
}, [transaction, setPositions, localPositionChanges]);
// find all accounts that take part in the transaction, either via debitor shares or purchase items
// TODO: should we add creditor accounts as well?
const positionAccounts: Array<number> = Array.from(
new Set<number>(
positions
.map((item) => Object.keys(item.usages))
.flat()
.map((id) => parseInt(id))
)
);
const [additionalPurchaseItemAccounts, setAdditionalPurchaseItemAccounts] = useState([]);
const transactionAccounts: Array<number> = Array.from(
new Set<number>(
Object.keys(transaction.debitor_shares)
.map((id) => parseInt(id))
.concat(positionAccounts)
.concat(additionalPurchaseItemAccounts)
)
);
const showAddAccount = transactionAccounts.length < accounts.length;
const [showAccountSelect, setShowAccountSelect] = useState(false);
const totalPositionValue = positions.reduce((acc, curr) => acc + curr.price, 0);
const sharedTransactionValue = transaction.value - totalPositionValue;
const purchaseItemSumForAccount = (accountID) => {
return transaction.account_balances.hasOwnProperty(accountID)
? transaction.account_balances[accountID].positions
: 0;
};
const updatePosition = (position, name, price, communistShares) => {
if (position.is_empty) {
return updateEmptyPosition(position, name, price, communistShares);
}
if (position.only_local) {
setLocalPositionChanges((currPositions) => {
let mappedAdded = { ...currPositions.added };
mappedAdded[position.id] = {
...position,
name: name,
price: price,
communist_shares: communistShares,
};
return {
modified: currPositions.modified,
added: mappedAdded,
empty: currPositions.empty,
};
});
} else {
setLocalPositionChanges((currPositions) => {
let mappedModified = { ...currPositions.modified };
mappedModified[position.id] = {
...position,
name: name,
price: price,
communist_shares: communistShares,
};
return {
modified: mappedModified,
empty: currPositions.empty,
added: currPositions.added,
};
});
}
};
const updatePositionUsage = (position, accountID, shares) => {
if (position.is_empty) {
return updateEmptyPositionUsage(position, accountID, shares);
}
if (position.only_local) {
setLocalPositionChanges((currPositions) => {
let mappedAdded = { ...currPositions.added };
let usages = { ...currPositions.added[position.id].usages };
if (shares === 0) {
delete usages[accountID];
} else {
usages[accountID] = shares;
}
mappedAdded[position.id] = {
...currPositions.added[position.id],
usages: usages,
};
return {
modified: currPositions.modified,
added: mappedAdded,
empty: currPositions.empty,
};
});
} else {
setLocalPositionChanges((currPositions) => {
let mappedModified = { ...currPositions.modified };
let usages;
if (mappedModified.hasOwnProperty(position.id)) {
// we already did change something locally
usages = { ...currPositions.modified[position.id].usages };
} else {
// we first need to copy
usages = { ...position.usages };
}
if (shares === 0) {
delete usages[accountID];
} else {
usages[accountID] = shares;
}
mappedModified[position.id] = {
...position,
...currPositions.modified[position.id],
usages: usages,
};
return {
modified: mappedModified,
added: currPositions.added,
empty: currPositions.empty,
};
});
}
};
const deletePosition = (position) => {
if (position.is_empty) {
return resetEmptyPosition();
}
if (position.only_local) {
setLocalPositionChanges((currPositions) => {
let mappedAdded = { ...currPositions.added };
delete mappedAdded[position.id];
return {
modified: currPositions.modified,
added: mappedAdded,
empty: currPositions.empty,
};
});
} else {
setLocalPositionChanges((currPositions) => {
let mappedModified = { ...currPositions.modified };
mappedModified[position.id] = {
...position,
deleted: true,
};
return {
modified: mappedModified,
added: currPositions.added,
empty: currPositions.empty,
};
});
}
};
const nextEmptyPositionID = (localPositions: LocalPositionChanges) => {
return Math.min(...Object.values(localPositions.added).map((p) => p.id), -1, localPositions.empty.id) - 1;
};
const resetEmptyPosition = () => {
setLocalPositionChanges((currValue) => ({
modified: currValue.modified,
added: currValue.added,
empty: {
id: nextEmptyPositionID(currValue),
name: "",
price: 0,
communist_shares: 0,
usages: {},
deleted: false,
},
}));
};
const updateEmptyPosition = (position, name, price, communistShares) => {
if (name !== "" && name != null) {
const copyOfEmpty = { ...position, name: name, price: price, communist_shares: communistShares };
setLocalPositionChanges((currPositions) => {
let mappedAdded = { ...currPositions.added };
mappedAdded[position.id] = copyOfEmpty;
return {
modified: currPositions.modified,
added: mappedAdded,
empty: {
id: nextEmptyPositionID(currPositions),
name: "",
price: 0,
communist_shares: 0,
usages: {},
deleted: false,
},
};
});
} else {
setLocalPositionChanges((currPositions) => {
return {
modified: currPositions.modified,
added: currPositions.added,
empty: {
...position,
name: name,
price: price,
communist_shares: communistShares,
},
};
});
}
};
const updateEmptyPositionUsage = (position, accountID, value) => {
setLocalPositionChanges((currPositions) => {
let newUsages = { ...position.usages };
if (value === 0) {
delete newUsages[accountID];
} else {
newUsages[accountID] = value;
}
return {
modified: currPositions.modified,
added: currPositions.added,
empty: {
...position,
usages: newUsages,
},
};
});
};
const copyPosition = (position) => {
setLocalPositionChanges((currPositions) => {
const newPosition = {
...position,
id: nextEmptyPositionID(currPositions),
};
let mappedAdded = { ...currPositions.added };
mappedAdded[newPosition.id] = newPosition;
return {
modified: currPositions.modified,
added: mappedAdded,
empty: currPositions.empty,
};
});
};
const addPurchaseItemAccount = (account) => {
setShowAccountSelect(false);
setAdditionalPurchaseItemAccounts((currAdditionalAccounts) =>
Array.from(new Set<number>([...currAdditionalAccounts, parseInt(account.id)]))
);
};
return (
<MobilePaper sx={{ marginTop: 2 }}>
<Grid container direction="row" justifyContent="space-between">
<Typography>Positions</Typography>
{transaction.is_wip && (
<FormControlLabel
control={<Checkbox name={`show-advanced`} />}
checked={showAdvanced}
onChange={(event: React.ChangeEvent<HTMLInputElement>) => setShowAdvanced(event.target.checked)}
label="Advanced"
/>
)}
</Grid>
<TableContainer>
<Table className={classes.table} stickyHeader aria-label="purchase items" size="small">
<TableHead>
<TableRow>
<TableCell>Name</TableCell>
<TableCell align="right">Price</TableCell>
{(transaction.is_wip ? transactionAccounts : positionAccounts).map((accountID) => (
<TableCell align="right" sx={{ minWidth: 80 }} key={accountID}>
{accounts.find((account) => account.id === accountID).name}
</TableCell>
))}
{transaction.is_wip && (
<>
{showAccountSelect && (
<TableCell align="right">
<AccountSelect
group={group}
exclude={transactionAccounts}
onChange={addPurchaseItemAccount}
/>
</TableCell>
)}
{showAddAccount && (
<TableCell align="right">
<IconButton onClick={() => setShowAccountSelect(true)}>
<Add />
</IconButton>
</TableCell>
)}
</>
)}
<TableCell align="right">Shared</TableCell>
{transaction.is_wip && <TableCell></TableCell>}
</TableRow>
</TableHead>
<TableBody>
{transaction.is_wip
? positions.map((position, idx) => (
<TableRow hover key={position.id}>
<PositionTableRow
position={position}
deletePosition={deletePosition}
transactionAccounts={transactionAccounts}
copyPosition={copyPosition}
updatePosition={updatePosition}
updatePositionUsage={updatePositionUsage}
showAdvanced={showAdvanced}
showAccountSelect={showAccountSelect}
showAddAccount={showAddAccount}
/>
</TableRow>
))
: positions.map(
(position) =>
!position.is_empty && (
<TableRow hover key={position.id}>
<TableCell>{position.name}</TableCell>
<TableCell align="right" style={{ minWidth: 80 }}>
{position.price.toFixed(2)} {transaction.currency_symbol}
</TableCell>
{positionAccounts.map((accountID) => (
<TableCell align="right" key={accountID}>
{position.usages.hasOwnProperty(String(accountID))
? position.usages[String(accountID)]
: 0}
</TableCell>
))}
<TableCell align="right">{position.communist_shares}</TableCell>
</TableRow>
)
)}
<TableRow hover>
<TableCell>
<Typography sx={{ fontWeight: "bold" }}>Total:</Typography>
</TableCell>
<TableCell align="right">
{totalPositionValue.toFixed(2)} {transaction.currency_symbol}
</TableCell>
{(transaction.is_wip ? transactionAccounts : positionAccounts).map((accountID) => (
<TableCell align="right" key={accountID}>
{purchaseItemSumForAccount(accountID).toFixed(2)} {transaction.currency_symbol}
</TableCell>
))}
<TableCell align="right" colSpan={showAddAccount ? 2 : 1}>
{(
positions.reduce((acc, curr) => acc + curr.price, 0) -
Object.values(transaction.account_balances).reduce(
(acc, curr) => acc + curr.positions,
0
)
).toFixed(2)}{" "}
{transaction.currency_symbol}
</TableCell>
{transaction.is_wip && <TableCell></TableCell>}
</TableRow>
<TableRow hover>
<TableCell>
<Typography sx={{ fontWeight: "bold" }}>Remaining:</Typography>
</TableCell>
<TableCell align="right">
{sharedTransactionValue.toFixed(2)} {transaction.currency_symbol}
</TableCell>
{(transaction.is_wip ? transactionAccounts : positionAccounts).map((accountID) => (
<TableCell align="right" key={accountID}></TableCell>
))}
<TableCell align="right" colSpan={showAddAccount ? 2 : 1}></TableCell>
{transaction.is_wip && <TableCell></TableCell>}
</TableRow>
</TableBody>
</Table>
</TableContainer>
</MobilePaper>
);
}
Example #9
Source File: PlayerList.tsx From NekoMaid with MIT License | 4 votes |
Players: React.FC = () => {
const his = useHistory()
const plugin = usePlugin()
const [page, setPage] = useState(0)
const [loading, setLoading] = useState(true)
const [state, setState] = useState<number | null>(null)
const [activedPlayer, setActivedPlayer] = useState<PlayerData | null>(null)
const [anchorEl, setAnchorEl] = React.useState<HTMLButtonElement | null>(null)
const [data, setData] = useState<{ count: number, players: PlayerData[] }>(() => ({ count: 0, players: [] }))
const globalData = useGlobalData()
const { hasWhitelist } = globalData
const refresh = () => {
setLoading(true)
plugin.emit('playerList:fetchPage', (it: any) => {
if (it.players == null) it.players = []
setData(it)
setLoading(false)
}, page, state === 1 || state === 2 ? state : 0, null)
}
useMemo(refresh, [page, state])
const close = () => {
setAnchorEl(null)
setActivedPlayer(null)
}
return <Card>
<CardHeader
title={lang.playerList.title}
action={
<ToggleButtonGroup
size='small'
color={(state === 1 ? 'warning' : state === 2 ? 'error' : undefined) as any}
value={state}
exclusive
onChange={(_, it) => {
if (it === 3) return
setState(it)
if (state === 3) refresh()
}}
>
<ToggleButton disabled={loading} value={1}><Star /></ToggleButton>
<ToggleButton disabled={loading} value={2}><Block /></ToggleButton>
<ToggleButton disabled={loading} value={3} onClick={() => state !== 3 && dialog(lang.playerList.nameToSearch, lang.username)
.then(filter => {
if (filter == null) return
his.push('/NekoMaid/playerList/' + filter)
setState(3)
setLoading(true)
plugin.emit('playerList:fetchPage', (it: any) => {
if (it.players == null) it.players = []
setPage(0)
setData(it)
setLoading(false)
}, page, 0, filter.toLowerCase())
})}><Search /></ToggleButton>
</ToggleButtonGroup>
}
/>
<Divider />
<Box sx={{ position: 'relative' }}>
<CircularLoading loading={loading} />
<TableContainer>
<Table>
<TableHead>
<TableRow>
<TableCell padding='checkbox' />
<TableCell>{lang.username}</TableCell>
<TableCell align='right'>{minecraft['stat.minecraft.play_time']}</TableCell>
<TableCell align='right'>{lang.playerList.lastPlay}</TableCell>
<TableCell align='right'>{lang.operations}</TableCell>
</TableRow>
</TableHead>
<TableBody>
{data.players.map(it => <TableRow key={it.name}>
<TableCell sx={{ cursor: 'pointer', padding: theme => theme.spacing(1, 1, 1, 2) }} onClick={() => his.push('/NekoMaid/playerList/' + it.name)}>
<Avatar src={getSkin(globalData, it.name, true)} imgProps={{ crossOrigin: 'anonymous', style: { width: 40, height: 40 } }} variant='rounded' />
</TableCell>
<TableCell>{it.name}</TableCell>
<TableCell align='right'>{dayjs.duration(it.playTime / 20, 'seconds').humanize()}</TableCell>
<TableCell align='right'>{dayjs(it.lastOnline).fromNow()}</TableCell>
<TableCell align='right'>
{(state === 1 || hasWhitelist) && <Tooltip title={lang.playerList[it.whitelisted ? 'clickToRemoveWhitelist' : 'clickToAddWhitelist']}>
<IconButton onClick={() => whitelist(it.name, plugin, refresh, !it.whitelisted)}>
{it.whitelisted ? <Star color='warning' /> : <StarBorder />}
</IconButton>
</Tooltip>}
<Tooltip title={it.ban == null ? lang.playerList.clickToBan : lang.playerList.banned + ': ' + it.ban}>
<IconButton onClick={() => banPlayer(it.name, plugin, refresh, it.ban == null)}>
<Block color={it.ban == null ? undefined : 'error'} />
</IconButton>
</Tooltip>
{actions.length
? <IconButton onClick={e => {
setActivedPlayer(anchorEl ? null : it)
setAnchorEl(anchorEl ? null : e.currentTarget)
}}><MoreHoriz /></IconButton>
: null}
</TableCell>
</TableRow>)}
</TableBody>
</Table>
</TableContainer>
<TablePagination
rowsPerPageOptions={[]}
component='div'
count={data.count}
rowsPerPage={10}
page={page}
onPageChange={(_, it) => !loading && setPage(it)}
/>
</Box>
<Menu
anchorEl={anchorEl}
open={Boolean(anchorEl)}
onClose={() => setAnchorEl(null)}
>{actions.map((It, i) => <It key={i} onClose={close} player={activedPlayer} />)}</Menu>
</Card>
}
Example #10
Source File: Plugins.tsx From NekoMaid with MIT License | 4 votes |
Plugins: React.FC = () => {
const plugin = usePlugin()
const theme = useTheme()
const { canLoadPlugin } = useGlobalData()
const [plugins, setPlugins] = useState<Plugin[]>([])
useEffect(() => {
const offList = plugin.on('plugins:list', (plugins: Plugin[]) => {
const arr: Plugin[] = []
setPlugins(plugins.filter(it => {
const res = canPluginBeDisabled(it.name)
if (res) arr.push(it)
return !res
}).concat(arr))
})
plugin.emit('plugins:fetch')
return () => {
offList()
}
}, [])
const map: Record<string, number> = { }
let id = 0
const data = plugins.map(it => {
map[it.name] = id
return { id: id++, name: it.name, category: 1 - (it.enabled as any) }
})
const links: Array<{ source: number, target: number }> = []
plugins.forEach(it => {
const source = map[it.name]
it.depends.forEach(dep => {
if (!(dep in map)) {
map[dep] = id
data.push({ id: id++, name: dep, category: 3 })
}
links.push({ source, target: map[dep] })
})
it.softDepends.forEach(dep => {
if (!(dep in map)) {
map[dep] = id
data.push({ id: id++, name: dep, category: 2 })
}
links.push({ source, target: map[dep] })
})
})
return <Box sx={{ minHeight: '100%', py: 3 }}>
<Toolbar />
<Container maxWidth={false}>
<Grid container spacing={3}>
<Grid item xs={12}>
<Card>
<CardHeader title={lang.plugins.title} />
<Divider />
<TableContainer>
<Table>
<TableHead>
<TableRow>
<TableCell sx={{ paddingRight: 0 }}>{lang.plugins.enable}</TableCell>
<TableCell>{lang.plugins.name}</TableCell>
<TableCell>{lang.plugins.version}</TableCell>
<TableCell>{lang.plugins.author}</TableCell>
<TableCell>{lang.plugins.description}</TableCell>
<TableCell align='right'>{lang.operations}</TableCell>
</TableRow>
</TableHead>
<TableBody>
{plugins.map(it => {
const canBeDisabled = canPluginBeDisabled(it.name)
const disabledForever = it.file.endsWith('.disabled')
return <TableRow key={it.name}>
<TableCell padding='checkbox'>
<Checkbox
color='primary'
checked={it.enabled}
disabled={disabledForever || canBeDisabled}
onChange={() => plugin.emit('plugins:enable', it.file, it.name, action)
} />
</TableCell>
<TableCell><Tooltip title={it.file}><span>{it.name}</span></Tooltip></TableCell>
<TableCell>{it.website
? <Link underline='hover' rel='noopener' target='_blank' href={it.website}>{it.version}</Link>
: it.version
}</TableCell>
<TableCell>{it.author}</TableCell>
<TableCell>{it.description}</TableCell>
<TableCell align='right' sx={{ whiteSpace: 'nowrap' }}>
<Tooltip title={lang.plugins[disabledForever ? 'enablePlugin' : 'disableForever']}><span>
<IconButton
disabled={it.enabled || (it.loaded && !canLoadPlugin)}
onClick={() => plugin.emit('plugins:disableForever', it.file, action)}
>{disabledForever ? <LockOpen /> : <Lock />}</IconButton>
</span></Tooltip>
{disabledForever && <Tooltip title={lang.plugins.delete}><span>
<IconButton
color='error'
disabled={canBeDisabled}
onClick={() => dialog({
okButton: { color: 'error' },
content: <>{lang.plugins.confirmDelete(<span className='bold'>{it.file.replace(/\.disabled$/, '')}</span>)}
<span className='bold' style={{ color: theme.palette.error.main }}>({lang.unrecoverable})</span></>
}).then(res => res && plugin.emit('plugins:delete', it.file, action))}
><DeleteForever /></IconButton>
</span></Tooltip>}
</TableCell>
</TableRow>
})}
</TableBody>
</Table>
</TableContainer>
</Card>
</Grid>
<Grid item xs={12}>
<Card>
<CardHeader title={lang.plugins.dependency} />
<Divider />
<ReactECharts style={{ marginTop: theme.spacing(1), height: 450 }} theme={theme.palette.mode === 'dark' ? 'dark' : undefined} option={{
backgroundColor: 'rgba(0, 0, 0, 0)',
legend: { data: lang.plugins.categories },
series: [
{
edgeSymbol: ['none', 'arrow'],
symbolSize: 13,
type: 'graph',
layout: 'force',
data,
links,
categories: lang.plugins.categories.map(name => ({ name, base: name })),
roam: true,
label: {
show: true,
position: 'right',
formatter: '{b}'
},
labelLayout: {
hideOverlap: true
}
}
]
}} />
</Card>
</Grid>
</Grid>
</Container>
</Box>
}
Example #11
Source File: Worlds.tsx From NekoMaid with MIT License | 4 votes |
Worlds: React.FC = () => {
const plugin = usePlugin()
const globalData = useGlobalData()
const [worlds, setWorlds] = useState<World[]>([])
const [selected, setSelected] = useState('')
const [open, setOpen] = useState(false)
const update = () => plugin.emit('worlds:fetch', (data: World[]) => {
setWorlds(data)
if (data.length) setSelected(old => data.some(it => it.id === old) ? old : '')
})
useEffect(() => {
const offUpdate = plugin.on('worlds:update', update)
update()
return () => { offUpdate() }
}, [])
const sw = worlds.find(it => it.id === selected)
const getSwitch = (name: string, configId = name) => sw
? <ListItem
secondaryAction={<Switch disabled={!globalData.hasMultiverse} checked={(sw as any)[name]}
onChange={e => {
plugin.emit('worlds:set', sw.id, configId, e.target.checked.toString())
success()
}}
/>}><ListItemText primary={(lang.worlds as any)[name]} /></ListItem>
: null
return <Box sx={{ minHeight: '100%', py: 3 }}>
<Toolbar />
<Container maxWidth={false}>
<Grid container spacing={3}>
<Grid item lg={8} md={12} xl={9} xs={12}>
<Card>
<CardHeader title={lang.worlds.title} />
<Divider />
<Box sx={{ position: 'relative' }}>
<TableContainer>
<Table>
<TableHead>
<TableRow>
<TableCell padding='checkbox' />
<TableCell>{lang.worlds.name}</TableCell>
{globalData.hasMultiverse && <TableCell>{lang.worlds.alias}</TableCell>}
<TableCell>{lang.worlds.players}</TableCell>
<TableCell>{lang.worlds.chunks}</TableCell>
<TableCell>{lang.worlds.entities}</TableCell>
<TableCell>{lang.worlds.tiles}</TableCell>
<TableCell>{lang.worlds.time}</TableCell>
<TableCell>{lang.worlds.weather}</TableCell>
</TableRow>
</TableHead>
<TableBody>
{worlds.map(it => <TableRow key={it.id}>
<TableCell padding='checkbox'><Checkbox checked={selected === it.id} onClick={() => setSelected(it.id)} /></TableCell>
<TableCell><Tooltip title={it.id}><span>{it.name}</span></Tooltip></TableCell>
{globalData.hasMultiverse && <TableCell>{it.alias}
<IconButton size='small' onClick={() => dialog(lang.inputValue, lang.worlds.alias).then(res => {
if (res == null) return
plugin.emit('worlds:set', it.id, 'alias', res)
success()
})}><Edit fontSize='small' /></IconButton>
</TableCell>}
<TableCell>{it.players}</TableCell>
<TableCell>{it.chunks}</TableCell>
<TableCell>{it.entities}</TableCell>
<TableCell>{it.tiles}</TableCell>
<TableCell><Countdown time={it.time} max={24000} interval={50} /></TableCell>
<TableCell><IconButton size='small' onClick={() => {
plugin.emit('worlds:weather', it.id)
success()
}}>
{React.createElement((it.weather === 1 ? WeatherRainy : it.weather === 2 ? WeatherLightningRainy : WbSunny) as any)}
</IconButton></TableCell>
</TableRow>)}
</TableBody>
</Table>
</TableContainer>
</Box>
</Card>
</Grid>
<Grid item lg={4} md={6} xl={3} xs={12}>
<Card>
<CardHeader
title={lang.operations}
sx={{ position: 'relative' }}
action={<Tooltip title={lang.worlds.save} placement='left'>
<IconButton
size='small'
onClick={() => {
if (!sw) return
plugin.emit('worlds:save', sw.id)
success()
}}
sx={cardActionStyles}
><Save /></IconButton>
</Tooltip>}
/>
<Divider />
<Box sx={{ position: 'relative' }}>
{sw
? <List sx={{ width: '100%' }} component='nav'>
<ListItem secondaryAction={<ToggleButtonGroup
exclusive
color='primary'
size='small'
value={sw.difficulty}
onChange={(_, value) => {
plugin.emit('worlds:difficulty', sw.id, value)
success()
}}
>
{difficulties.map(it => <ToggleButton value={it.toUpperCase()} key={it}>{minecraft['options.difficulty.' + it]}</ToggleButton>)}
</ToggleButtonGroup>}><ListItemText primary={minecraft['options.difficulty']} /></ListItem>
<ListItem secondaryAction={<Switch checked={sw.pvp} onChange={e => {
plugin.emit('worlds:pvp', sw.id, e.target.checked)
success()
}} />}><ListItemText primary='PVP' /></ListItem>
{getSwitch('allowAnimals', 'spawning.animals.spawn')}
{getSwitch('allowMonsters', 'spawning.monsters.spawn')}
{globalData.hasMultiverse && <>
{getSwitch('allowFlight')}
{getSwitch('autoHeal')}
{getSwitch('hunger')}
</>}
<ListItem secondaryAction={globalData.canSetViewDistance
? <IconButton
onClick={() => dialog({
content: lang.inputValue,
input: {
error: true,
type: 'number',
helperText: lang.invalidValue,
validator: (it: string) => /^\d+$/.test(it) && +it > 1 && +it < 33
}
}).then(res => {
if (!res) return
plugin.emit('worlds:viewDistance', sw.id, parseInt(res as any))
success()
})}
><Edit /></IconButton>
: undefined}>
<ListItemText primary={lang.worlds.viewDistance + ': ' + sw.viewDistance} />
</ListItem>
<ListItem><ListItemText primary={minecraft['selectWorld.enterSeed']} secondary={sw.seed} /></ListItem>
<ListItemButton onClick={() => setOpen(!open)}>
<ListItemText primary={minecraft['selectWorld.gameRules']} />
{open ? <ExpandLess /> : <ExpandMore />}
</ListItemButton>
<Collapse in={open} timeout="auto" unmountOnExit>
<List component='div' dense disablePadding>
{sw.rules.map(([key, value]) => {
const isTrue = value === 'true'
const isBoolean = isTrue || value === 'false'
const isNumber = /^\d+$/.test(value)
return <ListItem
key={key}
sx={{ pl: 4 }}
secondaryAction={isBoolean
? <Switch
checked={isTrue}
onChange={e => {
plugin.emit('worlds:rule', sw.id, key, e.target.checked.toString())
success()
}}
/>
: <IconButton
onClick={() => dialog({
content: lang.inputValue,
input: isNumber
? {
error: true,
type: 'number',
helperText: lang.invalidValue,
validator: (it: string) => /^\d+$/.test(it)
}
: { }
}).then(res => {
if (res == null) return
plugin.emit('worlds:rule', sw.id, key, res)
success()
})}
><Edit /></IconButton>}
>
<ListItemText primary={(minecraft['gamerule.' + key] || key) + (isBoolean ? '' : ': ' + value)} />
</ListItem>
})}
</List>
</Collapse>
</List>
: <CardContent><Empty /></CardContent>
}
</Box>
</Card>
</Grid>
</Grid>
</Container>
</Box>
}
Example #12
Source File: CertificatesTab.tsx From frontend with MIT License | 4 votes |
export default function CertificatesTab() {
const { data = { donations: [], total: 0 } } = useUserDonations()
const [fromDate, setFromDate] = React.useState(new Date())
const [toDate, setToDate] = React.useState(new Date())
return (
<Root>
<Box className={classes.boxTitle}>
<Typography className={classes.h3}>История на сертификати</Typography>
</Box>
<ProfileTab name={ProfileTabs.certificates}>
<Box>
<Box sx={{ mt: 4 }}>
<h3 className={classes.thinFont}>Онлайн дарения</h3>
</Box>
<Box
sx={{
display: 'flex',
alignItems: 'baseline',
justifyContent: 'space-between',
mt: 2,
}}>
<span className={classes.smallText}>Покажи:</span>
<Box>
<Checkbox defaultChecked />
<span className={classes.smallText}>еднократни</span>
</Box>
<Box>
<Checkbox defaultChecked />
<span className={classes.smallText}>месечни</span>
</Box>
<LocalizationProvider dateAdapter={AdapterDateFns}>
<span className={classes.smallText}>от дата</span>
<DesktopDatePicker
label="от дата"
inputFormat="MM/dd/yyyy"
value={fromDate}
onChange={(date) => setFromDate(date as Date)}
renderInput={(params) => <TextField {...params} />}
/>
<span className={classes.smallText}>до дата</span>
<DesktopDatePicker
label="до дата"
inputFormat="MM/dd/yyyy"
value={toDate}
onChange={(date) => setToDate(date as Date)}
renderInput={(params) => <TextField {...params} />}
/>
</LocalizationProvider>
</Box>
{data.donations.length ? (
<TableContainer>
<Table sx={{ minWidth: 650, backgroundColor: 'white' }} aria-label="simple table">
<TableHead>
<TableRow>
<TableCell>№</TableCell>
<TableCell>Дата</TableCell>
<TableCell>Вид</TableCell>
<TableCell>Кауза</TableCell>
<TableCell>стойност</TableCell>
<TableCell>сертификат</TableCell>
</TableRow>
</TableHead>
<TableBody>
{data.donations.map((donation, index) => (
<TableRow
key={index}
sx={{ '&:last-child td, &:last-child th': { border: 0 } }}>
<TableCell component="th" scope="row">
{index + 1}
</TableCell>
<TableCell>{formatDateString(donation.createdAt)}</TableCell>
<TableCell>
<Avatar sx={{ background: '#F6992B' }}>
<StarIcon />
</Avatar>
</TableCell>
<TableCell>{donation.targetVault.campaign.title}</TableCell>
<TableCell>
{donation.amount} {donation.currency}
</TableCell>
<TableCell>
<Button variant="outlined">
Свали <ArrowForwardIcon />
</Button>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
) : (
<Box sx={{ fontSize: 20, mt: 4 }}>Към момента няма направени дарения</Box>
)}
</Box>
</ProfileTab>
</Root>
)
}
Example #13
Source File: DonationTable.tsx From frontend with MIT License | 4 votes |
function DonationTable({ donations }: DonationTableProps) {
const { t, i18n } = useTranslation()
const [fromDate, setFromDate] = React.useState<Date | null>(null)
const [toDate, setToDate] = React.useState<Date | null>(null)
const [monthly, setMonthly] = React.useState(true)
const [oneTime, setOneTime] = React.useState(true)
const filteredByTypeDonations = useMemo(() => {
if (monthly && oneTime) {
return donations
}
if (!monthly && !oneTime) {
return []
}
if (monthly) {
return donations?.filter((d) => d.type !== 'donation')
}
if (oneTime) {
return donations?.filter((d) => d.type === 'donation')
}
return donations
}, [donations, monthly, oneTime])
const filteredDonations = useMemo(() => {
if (!fromDate && !toDate) {
return filteredByTypeDonations
}
if (fromDate && toDate) {
return filteredByTypeDonations?.filter((d) => {
const createdAtDate = parseISO(d.createdAt)
return isAfter(createdAtDate, fromDate) && isBefore(createdAtDate, toDate)
})
}
if (fromDate) {
return filteredByTypeDonations?.filter((d) => {
const createdAtDate = parseISO(d.createdAt)
return isAfter(createdAtDate, fromDate)
})
}
if (toDate) {
return filteredByTypeDonations?.filter((d) => {
const createdAtDate = parseISO(d.createdAt)
return isBefore(createdAtDate, toDate)
})
}
}, [filteredByTypeDonations, fromDate, toDate])
return (
<Card sx={{ padding: theme.spacing(2) }}>
<Grid container alignItems={'flex-start'} spacing={theme.spacing(2)}>
<Grid item xs={6} sm={3}>
<CheckboxLabel>{t('profile:donations.oneTime')}</CheckboxLabel>
<Checkbox
onChange={(e, checked) => setOneTime(checked)}
checked={oneTime}
name="oneTime"
/>
</Grid>
<Grid item xs={6} sm={3}>
<CheckboxLabel>{t('profile:donations.monthly')}</CheckboxLabel>
<Checkbox
onChange={(e, checked) => setMonthly(checked)}
checked={monthly}
name="monthly"
/>
</Grid>
<LocalizationProvider
locale={i18n.language === 'bg' ? bg : enUS}
dateAdapter={AdapterDateFns}>
<Grid item xs={12} sm={3}>
<DatePicker
label={t('profile:donations.fromDate')}
value={fromDate}
onChange={setFromDate}
renderInput={(params) => <TextField size="small" {...params} />}
/>
</Grid>
<Grid item xs={12} sm={3}>
<DatePicker
label={t('profile:donations.toDate')}
value={toDate}
onChange={setToDate}
renderInput={(params) => <TextField size="small" {...params} />}
/>
</Grid>
</LocalizationProvider>
</Grid>
{filteredDonations?.length ? (
<TableContainer>
<Table sx={{ minWidth: 650, backgroundColor: 'white' }} aria-label="simple table">
<TableHead>
<TableRow>
<TableCell>№</TableCell>
<TableCell>{t('profile:donations.date')}</TableCell>
<TableCell>{t('profile:donations.type')}</TableCell>
<TableCell>{t('profile:donations.cause')}</TableCell>
<TableCell>{t('profile:donations.amount')}</TableCell>
<TableCell>{t('profile:donations.certificate')}</TableCell>
</TableRow>
</TableHead>
<TableBody>
{filteredDonations.map((donation, index) => (
<TableRow key={index} sx={{ '&:last-child td, &:last-child th': { border: 0 } }}>
<TableCell component="th" scope="row">
{index + 1}
</TableCell>
<TableCell>
{format(parseISO(donation.createdAt), 'd.LL.yyyy', {
locale: i18n.language === 'bg' ? bg : enUS,
})}
</TableCell>
<TableCell>
<Avatar sx={{ background: darken(theme.palette.secondary.main, 0.175) }}>
<StarIcon />
</Avatar>
</TableCell>
<TableCell>{donation.targetVault.campaign.title}</TableCell>
<TableCell>{money(donation.amount)}</TableCell>
<TableCell>
<Button variant="outlined" disabled={donation.status != 'succeeded'}>
<Link target="_blank" href={routes.donation.viewCertificate(donation.id)}>
{t('profile:donations.download')} <ArrowForwardIcon />
</Link>
</Button>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
) : (
<Box sx={{ fontSize: 20, mt: 4 }}>Към момента няма направени дарения</Box>
)}
</Card>
)
}
Example #14
Source File: index.tsx From yearn-watch-legacy with GNU Affero General Public License v3.0 | 4 votes |
GenericList = <T extends GenericListItem>( props: GenericListProps<T> ) => { const { defaultRowsPerPage = 10, defaultOrder = 'asc', defaultOrderBy = 'id', } = props; const classes = useStyles(); const [order, setOrder] = React.useState<Order>(defaultOrder); const [orderBy, setOrderBy] = React.useState<keyof GenericListItem>(defaultOrderBy); const [page, setPage] = React.useState(0); const [rowsPerPage, setRowsPerPage] = React.useState(defaultRowsPerPage); const { items, title, headCells, displayPagination = true } = props; const shouldCollapse = props.collapse !== undefined; const handleRequestSort = ( event: React.MouseEvent<unknown>, property: keyof GenericListItem ) => { const isAsc = orderBy === property && order === 'asc'; setOrder(isAsc ? 'desc' : 'asc'); setOrderBy(property); }; const handleChangePage = (event: unknown, newPage: number) => { setPage(newPage); }; const handleChangeRowsPerPage = ( event: React.ChangeEvent<HTMLInputElement> ) => { setRowsPerPage(parseInt(event.target.value, 10)); setPage(0); }; const emptyRows = rowsPerPage - Math.min(rowsPerPage, items.length - page * rowsPerPage); return ( <div className={classes.root}> <Paper className={classes.paper}> <EnhancedTableToolbar title={title} /> <TableContainer> <Table className={classes.table} aria-labelledby="tableTitle" size="small" aria-label="enhanced table" > <EnhancedTableHead classes={classes} order={order} orderBy={orderBy.toString()} headCells={props.headCells} onRequestSort={handleRequestSort} shouldCollapse={shouldCollapse} /> <TableBody> {stableSort(items, getComparator(order, orderBy)) .slice( page * rowsPerPage, page * rowsPerPage + rowsPerPage ) .map((row, index) => { const labelId = `enhanced-table-checkbox-${index}`; return ( <ItemRow headCells={headCells} item={row} index={index} key={labelId} collapse={props.collapse} getRowStyle={props.getRowStyle} /> ); })} {emptyRows > 0 && ( <TableRow style={{ height: 33 * emptyRows, }} > <TableCell colSpan={6} /> </TableRow> )} </TableBody> </Table> </TableContainer> {displayPagination ? ( <TablePagination rowsPerPageOptions={[5, 10, 20, 40, 60, 75, 100]} component="div" count={items.length} rowsPerPage={rowsPerPage} page={page} onPageChange={handleChangePage} onRowsPerPageChange={handleChangeRowsPerPage} /> ) : ( '' )} </Paper> </div> ); }