import { useCallback } from "react"; import { Alert, Box, Button, Chip, Paper, Skeleton, Stack, Typography } from "@mui/material"; import { useNavigate } from "react-router-dom"; import { api } from "../api"; import { useViewResource } from "../hooks/useViewResource"; import { useI18n } from "../i18n/I18nProvider"; import type { JobApplication } from "../types"; type PagedJobs = { items: JobApplication[]; total: number; page: number; pageSize: number }; export default function OfferComparisonPage() { const navigate = useNavigate(); const { language, t } = useI18n(); const load = useCallback(() => api.get("/jobapplications", { params: { status: "Offer", page: 1, pageSize: 25, sortBy: "deadline", sortDir: "asc" } }).then((r) => r.data), []); const resource = useViewResource(load, { initialData: { items: [], total: 0, page: 1, pageSize: 25 }, errorMessage: t("offerComparisonLoadFailed"), deps: [t] }); const date = (value?: string | null) => value ? new Date(value).toLocaleDateString(language === "nb" ? "nb-NO" : "en") : "—"; return ( {t("offerComparisonTitle")} {t("offerComparisonHelp")} {resource.loading ? {[0, 1].map((n) => )} : null} {resource.error ? void resource.reload()}>{t("retry")}}>{resource.error.message} : null} {!resource.loading && !resource.error && resource.data.items.length === 0 ? ( {t("offerComparisonEmpty")} {t("offerComparisonEmptyHelp")} ) : null} {resource.data.items.map((offer) => ( {offer.jobTitle}{offer.company?.name} ))} ); } function Fact({ label, value, multiline = false }: { label: string; value: string; multiline?: boolean }) { return {label}{value}; } function formatSalary(job: JobApplication, fallback: string) { if (job.salaryMin != null || job.salaryMax != null) { const range = [job.salaryMin, job.salaryMax].filter((value) => value != null).map((value) => Number(value).toLocaleString()).join(" – "); return `${range} ${job.salaryCurrency || ""}${job.salaryPeriod ? ` / ${job.salaryPeriod}` : ""}`.trim(); } return job.salary || fallback; }