import React, { useEffect, useMemo, useState } from "react"; import { useLocation, useNavigate } from "react-router-dom"; import { Box, Button, Dialog, DialogActions, DialogContent, DialogTitle, Paper, Table, TableBody, TableCell, TableHead, TableRow, TextField, Typography, IconButton, } from "@mui/material"; import { api, getApiErrorMessage } from "../api"; import { Company } from "../types"; import EditOutlinedIcon from "@mui/icons-material/EditOutlined"; import { useToast } from "../toast"; import { useI18n } from "../i18n/I18nProvider"; export default function CompaniesTable() { const { toast } = useToast(); const { t } = useI18n(); const location = useLocation(); const navigate = useNavigate(); const [companies, setCompanies] = useState([]); const [editOpen, setEditOpen] = useState(false); const [editing, setEditing] = useState(null); const [recruiterName, setRecruiterName] = useState(""); const [recruiterEmail, setRecruiterEmail] = useState(""); const [recruiterLinkedIn, setRecruiterLinkedIn] = useState(""); const [pipelineStage, setPipelineStage] = useState(""); const [lastContactedAt, setLastContactedAt] = useState(""); const [nextContactAt, setNextContactAt] = useState(""); useEffect(() => { api.get("/companies").then((r) => setCompanies(r.data)).catch((error) => toast(getApiErrorMessage(error, t("companiesUpdateFailed")), "error")); }, [t, toast]); useEffect(() => { const params = new URLSearchParams(location.search); const editId = Number(params.get("edit") || 0); if (!editId || companies.length === 0) return; const company = companies.find((c) => c.id === editId); if (!company) return; openEdit(company); params.delete("edit"); navigate({ pathname: location.pathname, search: params.toString() ? `?${params.toString()}` : "" }, { replace: true }); }, [companies, location.pathname, location.search, navigate]); const openEdit = (c: Company) => { setEditing(c); setRecruiterName(c.recruiterName ?? ""); setRecruiterEmail(c.recruiterEmail ?? ""); setRecruiterLinkedIn(c.recruiterLinkedIn ?? ""); setPipelineStage(c.pipelineStage ?? ""); setLastContactedAt((c.lastContactedAt ?? "").slice(0, 10)); setNextContactAt((c.nextContactAt ?? "").slice(0, 10)); setEditOpen(true); }; const canSave = useMemo(() => !!editing?.id, [editing]); const save = async () => { if (!editing?.id) return; try { const res = await api.put(`/companies/${editing.id}`, { name: editing.name, location: editing.location ?? null, source: editing.source ?? null, recruiterName: recruiterName.trim() || null, recruiterEmail: recruiterEmail.trim() || null, recruiterLinkedIn: recruiterLinkedIn.trim() || null, pipelineStage: pipelineStage.trim() || null, lastContactedAt: lastContactedAt || null, nextContactAt: nextContactAt || null, }); setCompanies((prev) => prev.map((x) => (x.id === res.data.id ? res.data : x))); toast(t("companiesUpdated"), "success"); setEditOpen(false); setEditing(null); } catch (error) { toast(getApiErrorMessage(error, t("companiesUpdateFailed")), "error"); } }; return ( {t("companiesName")} {t("companiesLocation")} {t("companiesSource")} {t("companiesPipeline")} {t("companiesRecruiter")} {t("companiesNextContact")} {companies.map((c) => ( {c.name} {c.location ?? ""} {c.source ?? ""} {c.pipelineStage ?? ""} {c.recruiterName ?? ""} {c.recruiterEmail ? ` (${c.recruiterEmail})` : ""} {c.nextContactAt ? new Date(c.nextContactAt).toLocaleDateString() : ""} openEdit(c)}> ))} {companies.length === 0 && ( {t("companiesEmpty")} )}
setEditOpen(false)} fullWidth maxWidth="sm"> {t("companiesEdit")} setEditing((p) => (p ? { ...p, name: e.target.value } : p))} sx={{ gridColumn: "1 / -1" }} /> setEditing((p) => (p ? { ...p, location: e.target.value } : p))} /> setEditing((p) => (p ? { ...p, source: e.target.value } : p))} /> setPipelineStage(e.target.value)} /> setRecruiterName(e.target.value)} /> setRecruiterEmail(e.target.value)} /> setRecruiterLinkedIn(e.target.value)} sx={{ gridColumn: "1 / -1" }} /> setLastContactedAt(e.target.value)} InputLabelProps={{ shrink: true }} /> setNextContactAt(e.target.value)} InputLabelProps={{ shrink: true }} />
); }