First Commit

This commit is contained in:
cesnimda
2026-03-21 11:55:27 +01:00
commit 2e8a29b4d0
1757 changed files with 166084 additions and 0 deletions
@@ -0,0 +1,79 @@
import React, { useEffect, useState } from "react";
import { Box, Button, Paper, TextField, Typography } from "@mui/material";
import { api } from "../api";
import { useToast } from "../toast";
type RuleSettings = {
id: number;
appliedFollowUpDays: number;
appliedGhostDays: number;
offerFollowUpDays: number;
offerGhostDays: number;
feedbackFollowUpDays: number;
feedbackGhostDays: number;
};
export default function RulesSettingsCard() {
const { toast } = useToast();
const [s, setS] = useState<RuleSettings | null>(null);
const [saving, setSaving] = useState(false);
useEffect(() => {
api.get<RuleSettings>("/rules").then((r) => setS(r.data));
}, []);
const save = async () => {
if (!s) return;
setSaving(true);
try {
await api.put("/rules", s);
toast("Rules saved.", "success");
} catch {
toast("Failed to save rules.", "error");
} finally {
setSaving(false);
}
};
if (!s) return null;
const num = (k: keyof RuleSettings) => ({
value: s[k],
onChange: (e: React.ChangeEvent<HTMLInputElement>) =>
setS((p) => (p ? { ...p, [k]: Number(e.target.value) } : p)),
type: "number" as const,
inputProps: { min: 1, max: 365 },
});
return (
<Paper sx={{ mt: 2, p: 2 }}>
<Typography variant="h6" sx={{ mb: 1 }}>
Follow-up + Ghosting Rules
</Typography>
<Typography variant="body2" sx={{ color: "text.secondary", mb: 2 }}>
Jobs get a Follow up flag based on these thresholds. Ghosting is automatic.
</Typography>
<Box sx={{ display: "grid", gridTemplateColumns: { xs: "1fr", md: "1fr 1fr 1fr" }, gap: 2 }}>
<TextField label="Applied: follow-up days" {...num("appliedFollowUpDays")} />
<TextField label="Applied: ghost days" {...num("appliedGhostDays")} />
<Box />
<TextField label="Offer: follow-up days" {...num("offerFollowUpDays")} />
<TextField label="Offer: ghost days" {...num("offerGhostDays")} />
<Box />
<TextField label="Feedback: follow-up days" {...num("feedbackFollowUpDays")} />
<TextField label="Feedback: ghost days" {...num("feedbackGhostDays")} />
<Box />
</Box>
<Box sx={{ display: "flex", justifyContent: "flex-end", mt: 2 }}>
<Button variant="contained" onClick={save} disabled={saving}>
{saving ? "Saving..." : "Save Rules"}
</Button>
</Box>
</Paper>
);
}