import React, { useState } from "react"; import { Alert, Box, Button, Checkbox, FormControl, FormControlLabel, InputLabel, NativeSelect, TextField, Typography } from "@mui/material"; import { useI18n } from "../../i18n/I18nProvider"; export type MappingCategory = { category: string; fields: { name: string; multiple: boolean; currentValue?: string | null }[] }; export type MappingBlock = { id: string; text: string; kind: string; page: number | null }; export type MappingTarget = { category: string; index: number; label: string; values?: Record }; export type MappedField = { name: string; value: string; sourceBlockId: string; corrected: boolean }; export type MappingDraft = { clientId: string; category: string; targetIndex: number | null; fields: MappedField[]; confirmed: boolean }; const primary: Record = { jobs: ["title", "company"], education: ["qualification", "institution"], certifications: ["name"], projects: ["name"], contact: ["fullName"], languages: ["name"], otherSections: ["title", "items"] }; const clean = (value: string) => value.replace(/\s+/g, " ").trim().toLocaleLowerCase(); const supported = (source: string, value: string) => new RegExp(`(? ({ name, value: "", sourceBlockId: "", corrected: false }); export default function CvImportMappingEditor({ categories, blocks, targets, drafts, onChange, disabled, label }: { categories: MappingCategory[]; blocks: MappingBlock[]; targets: MappingTarget[]; drafts: MappingDraft[]; onChange: (drafts: MappingDraft[]) => void; disabled: boolean; label: (value: string) => string; }) { const { t } = useI18n(); const [errors, setErrors] = useState>({}); function update(index: number, value: Partial) { onChange(drafts.map((draft, i) => i === index ? { ...draft, ...value, confirmed: false } : draft)); } function defaultFields(category: MappingCategory) { return (primary[category.category] ?? [category.fields[0]?.name ?? "value"]).filter(name => category.fields.some(field => field.name === name)).map(empty); } function approve(index: number) { const draft = drafts[index]; const catalog = categories.find(category => category.category === draft.category); const valid = draft.fields.length > 0 && draft.fields.every(field => { const block = blocks.find(source => source.id === field.sourceBlockId); return catalog?.fields.some(item => item.name === field.name) && field.value.trim().length > 0 && field.value.length <= 8000 && block && (field.corrected || supported(block.text, field.value)); }); setErrors(current => ({ ...current, [draft.clientId]: !valid })); if (valid) onChange(drafts.map((item, i) => i === index ? { ...item, confirmed: true } : item)); } if (categories.length === 0) return null; return {t("cvImportMappingNotice")} {drafts.map((draft, index) => { const catalog = categories.find(category => category.category === draft.category); const id = `cv-mapping-${draft.clientId}`; return {t("cvImportMappingRecord", { number: index + 1 })} {t("cvImportMappingCategory")} { const category = categories.find(item => item.category === event.target.value)!; update(index, { category: category.category, targetIndex: null, fields: defaultFields(category) }); }}>{categories.map(category => )} {t("cvImportMappingTarget")} update(index, { targetIndex: event.target.value === "" ? null : Number(event.target.value) })}> {targets.filter(target => target.category === draft.category).map(target => )} {draft.fields.map((field, fieldIndex) => { const number = fieldIndex + 1; const currentValue = draft.targetIndex === null ? catalog?.fields.find(item => item.name === field.name)?.currentValue : targets.find(target => target.category === draft.category && target.index === draft.targetIndex)?.values?.[field.name]; function change(value: Partial) { update(index, { fields: draft.fields.map((item, i) => i === fieldIndex ? { ...item, ...value } : item) }); } return {t("cvImportMappingField", { number })} change({ name: event.target.value })}> {catalog?.fields.map(item => )} {t("careerImportCurrentValue", { value: currentValue || t("careerImportEmptyValue") })} change({ value: event.target.value })} multiline fullWidth minRows={1} maxRows={8} inputProps={{ maxLength: 8000 }} /> {t("cvImportMappingSource", { number })} change({ sourceBlockId: event.target.value, value: field.value || blocks.find(block => block.id === event.target.value)?.text || "" })}> {blocks.map(block => )} {field.sourceBlockId ? {blocks.find(block => block.id === field.sourceBlockId)?.text} : null} change({ corrected: event.target.checked })} />} label={t("cvImportMappingCorrection")} /> ; })} {errors[draft.clientId] ? {t("cvImportMappingEvidenceError")} : null} {draft.confirmed ? {t("cvImportMappingConfirmed")} : null} ; })} ; }