Polish UI, harden company creation, and add error pages

This commit is contained in:
cesnimda
2026-03-23 19:34:29 +01:00
parent 8f5eab2fe4
commit fcafda6f52
38 changed files with 2293 additions and 1269 deletions
+10 -33
View File
@@ -16,6 +16,7 @@ import MoreHorizIcon from "@mui/icons-material/MoreHoriz";
import { api } from "../api";
import { JobApplication } from "../types";
import { useI18n } from "../i18n/I18nProvider";
const STATUSES = ["Applied", "Waiting", "Interview", "Offer", "Rejected", "Ghosted"] as const;
type Status = (typeof STATUSES)[number];
@@ -36,6 +37,7 @@ function toneColor(theme: any, status: Status | "Other"): string {
export default function KanbanBoard() {
const theme = useTheme();
const { t } = useI18n();
const [jobs, setJobs] = useState<JobApplication[]>([]);
const [dragJobId, setDragJobId] = useState<number | null>(null);
const [menuAnchor, setMenuAnchor] = useState<null | HTMLElement>(null);
@@ -64,9 +66,7 @@ export default function KanbanBoard() {
if (!dragJobId) return;
setDragJobId(null);
await api.patch(`/jobapplications/${dragJobId}/status`, { status });
setJobs((prev) =>
prev.map((j) => (j.id === dragJobId ? { ...j, status } : j)),
);
setJobs((prev) => prev.map((j) => (j.id === dragJobId ? { ...j, status } : j)));
};
const setStatus = async (id: number, status: Status) => {
@@ -74,9 +74,7 @@ export default function KanbanBoard() {
setJobs((prev) => prev.map((j) => (j.id === id ? { ...j, status } : j)));
};
const currentMenuStatus = menuJobId == null
? null
: normalizeStatus(jobs.find((j) => j.id === menuJobId)?.status ?? "");
const currentMenuStatus = menuJobId == null ? null : normalizeStatus(jobs.find((j) => j.id === menuJobId)?.status ?? "");
return (
<Box sx={{ mt: 2 }}>
@@ -84,14 +82,7 @@ export default function KanbanBoard() {
Drag cards between columns to update status.
</Typography>
<Box
sx={{
display: "grid",
gridTemplateColumns: { xs: "1fr", md: "repeat(3, 1fr)", xl: "repeat(6, 1fr)" },
gap: 2,
alignItems: "start",
}}
>
<Box sx={{ display: "grid", gridTemplateColumns: { xs: "1fr", md: "repeat(3, 1fr)", xl: "repeat(6, 1fr)" }, gap: 2, alignItems: "start" }}>
{STATUSES.map((status) => {
const c = toneColor(theme, status);
const list = groups.get(status) ?? [];
@@ -178,28 +169,14 @@ export default function KanbanBoard() {
})}
</Box>
<Menu
anchorEl={menuAnchor}
open={Boolean(menuAnchor)}
onClose={() => {
setMenuAnchor(null);
setMenuJobId(null);
}}
>
<Menu anchorEl={menuAnchor} open={Boolean(menuAnchor)} onClose={() => { setMenuAnchor(null); setMenuJobId(null); }}>
{(["Applied", "Waiting", "Interview", "Offer", "Rejected", "Ghosted"] as const)
.filter((s) => s !== currentMenuStatus)
.map((s) => (
<MenuItem
key={s}
onClick={() => {
if (menuJobId) void setStatus(menuJobId, s);
setMenuAnchor(null);
setMenuJobId(null);
}}
>
Set {s}
</MenuItem>
))}
<MenuItem key={s} onClick={() => { if (menuJobId) void setStatus(menuJobId, s); setMenuAnchor(null); setMenuJobId(null); }}>
{t("jobTableSetStatus", { status: s })}
</MenuItem>
))}
</Menu>
</Box>
);