Files
jobtrackingapp/job-tracker-ui/src/components/RulesSettingsCard.tsx
T

81 lines
3.1 KiB
TypeScript

import React from "react";
import { Alert, Box, Button, TextField, Typography } from "@mui/material";
import { PageSection } from "../layout/PageLayout";
import { useI18n } from "../i18n/I18nProvider";
export type RuleSettings = {
id: number;
appliedFollowUpDays: number;
appliedGhostDays: number;
offerFollowUpDays: number;
offerGhostDays: number;
feedbackFollowUpDays: number;
feedbackGhostDays: number;
};
export const RULE_FIELDS = ["appliedFollowUpDays", "appliedGhostDays", "offerFollowUpDays", "offerGhostDays", "feedbackFollowUpDays", "feedbackGhostDays"] as const;
export type RuleField = typeof RULE_FIELDS[number];
export type RuleDraft = Record<RuleField, string>;
type Props = {
draft: RuleDraft | null;
loadError: string | null;
saveError: boolean;
invalid: RuleField[];
saving: boolean;
dirty: boolean;
onChange: (field: RuleField, value: string) => void;
onSave: () => void;
onDiscard: () => void;
onRetry: () => void;
};
export default function RulesSettingsCard({ draft, loadError, saveError, invalid, saving, dirty, onChange, onSave, onDiscard, onRetry }: Props) {
const { t } = useI18n();
if (!draft) {
return (
<PageSection surface title={t("rulesTitle")}>
{loadError ? <Alert severity="error" action={<Button color="inherit" onClick={onRetry}>{t("retry")}</Button>}>{loadError}</Alert> : <Typography role="status" sx={{ color: "text.secondary" }}>{t("rulesLoading")}</Typography>}
</PageSection>
);
}
const num = (k: RuleField) => ({
value: draft[k],
onChange: (e: React.ChangeEvent<HTMLInputElement>) =>
onChange(k, e.target.value),
type: "number" as const,
error: invalid.includes(k),
helperText: invalid.includes(k) ? t("rulesDaysInvalid") : undefined,
inputProps: { min: 1, max: 365, step: 1, required: true },
});
return (
<PageSection surface title={t("rulesTitle")} description={t("rulesBody")}>
<Box component="form" noValidate onSubmit={(event) => { event.preventDefault(); onSave(); }}>
{saveError ? <Alert severity="error" sx={{ mb: 2 }}>{t("rulesSaveFailed")}</Alert> : null}
<Box sx={{ display: "grid", gridTemplateColumns: { xs: "1fr", md: "1fr 1fr 1fr" }, gap: 2 }}>
<TextField label={t("rulesAppliedFollowUpDays")} {...num("appliedFollowUpDays")} />
<TextField label={t("rulesAppliedGhostDays")} {...num("appliedGhostDays")} />
<Box />
<TextField label={t("rulesOfferFollowUpDays")} {...num("offerFollowUpDays")} />
<TextField label={t("rulesOfferGhostDays")} {...num("offerGhostDays")} />
<Box />
<TextField label={t("rulesFeedbackFollowUpDays")} {...num("feedbackFollowUpDays")} />
<TextField label={t("rulesFeedbackGhostDays")} {...num("feedbackGhostDays")} />
<Box />
</Box>
<Box sx={{ display: "flex", justifyContent: "flex-end", flexWrap: "wrap", gap: 1, mt: 2 }}>
<Button onClick={onDiscard} disabled={!dirty || saving}>{t("assetsDiscardChanges")}</Button>
<Button variant="contained" type="submit" disabled={saving}>
{saving ? t("rulesSaving") : t("rulesSave")}
</Button>
</Box>
</Box>
</PageSection>
);
}