148 lines
4.0 KiB
TypeScript
148 lines
4.0 KiB
TypeScript
import {
|
|
Button,
|
|
Dialog,
|
|
DialogActions,
|
|
DialogContent,
|
|
DialogTitle,
|
|
} from "@mui/material";
|
|
import React from "react";
|
|
import { Movement, MovementApi, MovementUpdate } from "../api/MovementsApi";
|
|
import { ServerApi } from "../api/ServerApi";
|
|
import { useAccounts } from "../hooks/AccountsListProvider";
|
|
import { useAlert } from "../hooks/context_providers/AlertDialogProvider";
|
|
import { useLoadingMessage } from "../hooks/context_providers/LoadingMessageProvider";
|
|
import { useSnackbar } from "../hooks/context_providers/SnackbarProvider";
|
|
import { AccountInput } from "../widgets/forms/AccountInput";
|
|
import { AmountInput } from "../widgets/forms/AmountInput";
|
|
import { DateInput } from "../widgets/forms/DateInput";
|
|
import { TextInput } from "../widgets/forms/TextInput";
|
|
|
|
export function UpdateMovementDialog(p: {
|
|
open: boolean;
|
|
updateId?: number;
|
|
initial: MovementUpdate;
|
|
onClose: () => void;
|
|
onFinished: (m: Movement) => void;
|
|
}): React.ReactElement {
|
|
const alert = useAlert();
|
|
const snackbar = useSnackbar();
|
|
const loadingMessage = useLoadingMessage();
|
|
const accounts = useAccounts();
|
|
|
|
const [movement, setMovement] = React.useState(p.initial);
|
|
|
|
const style: React.CSSProperties = { width: "100%", marginBottom: "15px" };
|
|
|
|
const canSubmit =
|
|
movement.amount !== 0 &&
|
|
movement.account_id &&
|
|
movement.time !== 0 &&
|
|
movement.label.length > 0;
|
|
|
|
const handleSubmit = async () => {
|
|
try {
|
|
loadingMessage.show(
|
|
`${p.updateId ? "Updating" : "Creating"} the movement...`
|
|
);
|
|
|
|
let res: Movement;
|
|
|
|
if (p.updateId) {
|
|
res = await MovementApi.Update({ ...movement, id: p.updateId });
|
|
} else {
|
|
res = await MovementApi.Create(movement);
|
|
}
|
|
|
|
accounts.reloadBalances();
|
|
|
|
snackbar("The movement was successfully saved!");
|
|
|
|
p.onFinished(res);
|
|
} catch (e) {
|
|
console.error("Failed to save movement!", e);
|
|
alert(`Failed to ${p.updateId ? "update" : "create"} movement! ${e}`);
|
|
} finally {
|
|
loadingMessage.hide();
|
|
}
|
|
};
|
|
|
|
return (
|
|
<Dialog open={p.open} onClose={p.onClose}>
|
|
<DialogTitle>
|
|
{p.updateId ? `Update a movement` : `Create a movement`}
|
|
</DialogTitle>
|
|
<DialogContent>
|
|
{/* Account */}
|
|
<AccountInput
|
|
value={movement.account_id}
|
|
label="Amount"
|
|
variant="standard"
|
|
style={style}
|
|
onChange={(a) =>
|
|
setMovement((m) => {
|
|
return {
|
|
...m,
|
|
account_id: a ?? 0,
|
|
};
|
|
})
|
|
}
|
|
/>
|
|
{/* Date input */}
|
|
<DateInput
|
|
autoFocus
|
|
editable
|
|
label="Movement date"
|
|
value={movement.time}
|
|
style={style}
|
|
onValueChange={(t) =>
|
|
setMovement((m) => {
|
|
return {
|
|
...m,
|
|
time: t ?? 0,
|
|
};
|
|
})
|
|
}
|
|
/>
|
|
{/* Label input */}
|
|
<TextInput
|
|
editable
|
|
placeholder={`Movement label`}
|
|
label="Movement label"
|
|
value={movement.label}
|
|
onValueChange={(l) =>
|
|
setMovement((m) => {
|
|
return {
|
|
...m,
|
|
label: l ?? "",
|
|
};
|
|
})
|
|
}
|
|
size={ServerApi.Config.constraints.movement_label}
|
|
/>
|
|
{/* Amount input */}
|
|
<AmountInput
|
|
editable
|
|
placeholder="Amount"
|
|
label="Amount"
|
|
style={style}
|
|
value={movement.amount}
|
|
onValueChange={(l) =>
|
|
setMovement((m) => {
|
|
return {
|
|
...m,
|
|
amount: l,
|
|
};
|
|
})
|
|
}
|
|
/>
|
|
</DialogContent>
|
|
<DialogActions>
|
|
<Button onClick={p.onClose}>Cancel</Button>
|
|
<Button onClick={handleSubmit} autoFocus disabled={!canSubmit}>
|
|
{p.updateId ? `Update` : `Create`}
|
|
</Button>
|
|
</DialogActions>
|
|
</Dialog>
|
|
);
|
|
}
|