import React from "react";
import { Box, Button, Chip, CircularProgress, TextField, Typography } from "@mui/material";
import { useI18n } from "../i18n/I18nProvider";
import { MatchScore } from "../types";
function copyLines(items: string[]) {
void navigator.clipboard.writeText(items.join("\n"));
}
export function MatchScoreCard({ score, loading, onUpdateLearningRecommendation }: {
score: MatchScore | null;
loading: boolean;
onUpdateLearningRecommendation?: (id: number, status: "done" | "dismissed") => void;
}) {
const { t } = useI18n();
if (loading && !score) {
return (
{t("matchScoreLoading")}
);
}
if (!score) return null;
const color: "success" | "warning" | "error" | "inherit" =
!score.hasEnoughSignal ? "inherit" : score.score >= 75 ? "success" : score.score >= 50 ? "warning" : "error";
const bandLabel = t(`matchScoreBand_${score.band}` as any) || score.band;
const learningRecommendations = score.learningRecommendations ?? [];
const visibleRecommendations = learningRecommendations.filter(item => item.status !== "dismissed");
const dismissedCount = learningRecommendations.length - visibleRecommendations.length;
return (
{score.hasEnoughSignal ? (
{score.score}%
{t("matchScoreTitle")}
) : (
—
)}
{!score.hasEnoughSignal ? {t("matchScoreNoSignal")} : null}
{t("matchScoreDeterministicHint")}
{t("matchScoreMatched")}
{score.matchedKeywords.length ? score.matchedKeywords.map((k) => ) : {t("matchScoreNoneYet")}}
{t("matchScoreMissing")}
{score.missingKeywords.length ? score.missingKeywords.map((k) => ) : {t("matchScoreAllCovered")}}
{score.sectionCoverage.length ? (
{t("matchScoreSectionCoverage")}
{score.sectionCoverage.map((s) => )}
) : null}
{learningRecommendations.length ? (
{t("matchScoreLearningPath")}
{t("matchScoreLearningPathHint")}
{visibleRecommendations.map(item => (
{item.status === "done" ? {t("matchScoreLearned")} : (
)}
))}
{dismissedCount ? {t("matchScoreDismissedCount", { count: dismissedCount })} : null}
) : null}
);
}
export function SectionChips({ title, items, color, outlined }: { title: string; items: string[]; color: "success" | "warning"; outlined?: boolean }) {
const { t } = useI18n();
return (
{title}
{items.length ? items.map((item) => ) : {t("jobDetailsNothingHighlighted")}}
);
}
export function TwoColumnSection({ leftTitle, leftItems, rightTitle, rightItems }: { leftTitle: string; leftItems: string[]; rightTitle: string; rightItems: string[] }) {
return (
);
}
export function ListCard({ title, items, subtitle }: { title: string; items: string[]; subtitle?: string }) {
const { t } = useI18n();
return (
{title}
{subtitle ? {subtitle} : null}
{items.length ? items.map((item, index) => • {item}) : {t("jobDetailsNothingHighlighted")}}
);
}
export function WorkspaceDraftCard({ title, value, onChange, statusLabel, statusColor }: { title: string; value: string; onChange: (value: string) => void; statusLabel: string; statusColor: "default" | "success" | "warning" }) {
const { t } = useI18n();
return (
{title}
onChange(e.target.value)} multiline minRows={7} fullWidth />
);
}
export function DraftCard({ title, content, onSave, saving }: { title: string; content: string; onSave?: (content: string) => Promise | void; saving?: boolean }) {
const { t } = useI18n();
const [value, setValue] = React.useState(content);
React.useEffect(() => {
setValue(content);
}, [content]);
return (
{title}
{onSave ? : null}
setValue(e.target.value)} multiline minRows={6} fullWidth />
);
}
export function PaperRow({ type, oldValue, newValue, at, note }: { type: string; oldValue?: string; newValue?: string; at: string; note?: string }) {
return (
{type}
{oldValue || newValue ? {" "}({oldValue ?? ""} {oldValue || newValue ? "->" : ""} {newValue ?? ""}) : null}
{at ? new Date(at).toLocaleString() : ""}
{note ? ` - ${note}` : ""}
);
}