Add candidateTeam field to evaluations; update related components and API endpoints for consistency
This commit is contained in:
BIN
prisma/dev.db
BIN
prisma/dev.db
Binary file not shown.
@@ -46,6 +46,7 @@ model Evaluation {
|
|||||||
id String @id @default(cuid())
|
id String @id @default(cuid())
|
||||||
candidateName String
|
candidateName String
|
||||||
candidateRole String
|
candidateRole String
|
||||||
|
candidateTeam String? // équipe du candidat
|
||||||
evaluatorName String
|
evaluatorName String
|
||||||
evaluationDate DateTime
|
evaluationDate DateTime
|
||||||
templateId String
|
templateId String
|
||||||
|
|||||||
@@ -175,9 +175,9 @@ async function main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const candidates = [
|
const candidates = [
|
||||||
{ name: "Alice Chen", role: "Senior ML Engineer", evaluator: "Jean Dupont" },
|
{ name: "Alice Chen", role: "Senior ML Engineer", team: "Cars Front", evaluator: "Jean Dupont" },
|
||||||
{ name: "Bob Martin", role: "Data Scientist", evaluator: "Marie Curie" },
|
{ name: "Bob Martin", role: "Data Scientist", team: "Cars Front", evaluator: "Marie Curie" },
|
||||||
{ name: "Carol White", role: "AI Product Manager", evaluator: "Jean Dupont" },
|
{ name: "Carol White", role: "AI Product Manager", team: "Cars Data", evaluator: "Jean Dupont" },
|
||||||
];
|
];
|
||||||
|
|
||||||
for (let i = 0; i < candidates.length; i++) {
|
for (let i = 0; i < candidates.length; i++) {
|
||||||
@@ -186,6 +186,7 @@ async function main() {
|
|||||||
data: {
|
data: {
|
||||||
candidateName: c.name,
|
candidateName: c.name,
|
||||||
candidateRole: c.role,
|
candidateRole: c.role,
|
||||||
|
candidateTeam: c.team,
|
||||||
evaluatorName: c.evaluator,
|
evaluatorName: c.evaluator,
|
||||||
evaluationDate: new Date(2025, 1, 15 + i),
|
evaluationDate: new Date(2025, 1, 15 + i),
|
||||||
templateId: template.id,
|
templateId: template.id,
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ export async function PUT(
|
|||||||
const { id } = await params;
|
const { id } = await params;
|
||||||
const body = await req.json();
|
const body = await req.json();
|
||||||
|
|
||||||
const { candidateName, candidateRole, evaluatorName, evaluationDate, status, findings, recommendations, dimensionScores } = body;
|
const { candidateName, candidateRole, candidateTeam, evaluatorName, evaluationDate, status, findings, recommendations, dimensionScores } = body;
|
||||||
|
|
||||||
const existing = await prisma.evaluation.findUnique({ where: { id } });
|
const existing = await prisma.evaluation.findUnique({ where: { id } });
|
||||||
if (!existing) {
|
if (!existing) {
|
||||||
@@ -90,8 +90,12 @@ export async function PUT(
|
|||||||
const updateData: Record<string, unknown> = {};
|
const updateData: Record<string, unknown> = {};
|
||||||
if (candidateName != null) updateData.candidateName = candidateName;
|
if (candidateName != null) updateData.candidateName = candidateName;
|
||||||
if (candidateRole != null) updateData.candidateRole = candidateRole;
|
if (candidateRole != null) updateData.candidateRole = candidateRole;
|
||||||
|
if (candidateTeam !== undefined) updateData.candidateTeam = candidateTeam || null;
|
||||||
if (evaluatorName != null) updateData.evaluatorName = evaluatorName;
|
if (evaluatorName != null) updateData.evaluatorName = evaluatorName;
|
||||||
if (evaluationDate != null) updateData.evaluationDate = new Date(evaluationDate);
|
if (evaluationDate != null) {
|
||||||
|
const d = new Date(evaluationDate);
|
||||||
|
if (!isNaN(d.getTime())) updateData.evaluationDate = d;
|
||||||
|
}
|
||||||
if (status != null) updateData.status = status;
|
if (status != null) updateData.status = status;
|
||||||
if (findings != null) updateData.findings = findings;
|
if (findings != null) updateData.findings = findings;
|
||||||
if (recommendations != null) updateData.recommendations = recommendations;
|
if (recommendations != null) updateData.recommendations = recommendations;
|
||||||
@@ -106,14 +110,12 @@ export async function PUT(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const evaluation = await prisma.evaluation.update({
|
if (Object.keys(updateData).length > 0) {
|
||||||
where: { id },
|
await prisma.evaluation.update({
|
||||||
data: updateData,
|
where: { id },
|
||||||
include: {
|
data: updateData as Record<string, unknown>,
|
||||||
template: { include: { dimensions: { orderBy: { orderIndex: "asc" } } } },
|
});
|
||||||
dimensionScores: { include: { dimension: true } },
|
}
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
if (dimensionScores && Array.isArray(dimensionScores)) {
|
if (dimensionScores && Array.isArray(dimensionScores)) {
|
||||||
for (const ds of dimensionScores) {
|
for (const ds of dimensionScores) {
|
||||||
@@ -157,7 +159,8 @@ export async function PUT(
|
|||||||
return NextResponse.json(updated);
|
return NextResponse.json(updated);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
return NextResponse.json({ error: "Failed to update evaluation" }, { status: 500 });
|
const msg = e instanceof Error ? e.message : "Failed to update evaluation";
|
||||||
|
return NextResponse.json({ error: msg }, { status: 500 });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ export async function GET(req: NextRequest) {
|
|||||||
export async function POST(req: NextRequest) {
|
export async function POST(req: NextRequest) {
|
||||||
try {
|
try {
|
||||||
const body = await req.json();
|
const body = await req.json();
|
||||||
const { candidateName, candidateRole, evaluatorName, evaluationDate, templateId } = body;
|
const { candidateName, candidateRole, candidateTeam, evaluatorName, evaluationDate, templateId } = body;
|
||||||
|
|
||||||
if (!candidateName || !candidateRole || !evaluatorName || !evaluationDate || !templateId) {
|
if (!candidateName || !candidateRole || !evaluatorName || !evaluationDate || !templateId) {
|
||||||
return NextResponse.json(
|
return NextResponse.json(
|
||||||
@@ -50,6 +50,7 @@ export async function POST(req: NextRequest) {
|
|||||||
data: {
|
data: {
|
||||||
candidateName,
|
candidateName,
|
||||||
candidateRole,
|
candidateRole,
|
||||||
|
candidateTeam: candidateTeam || null,
|
||||||
evaluatorName,
|
evaluatorName,
|
||||||
evaluationDate: new Date(evaluationDate),
|
evaluationDate: new Date(evaluationDate),
|
||||||
templateId,
|
templateId,
|
||||||
|
|||||||
@@ -28,7 +28,8 @@ export async function GET(req: NextRequest) {
|
|||||||
doc.setFontSize(18);
|
doc.setFontSize(18);
|
||||||
doc.text("Évaluation Maturité IA Gen", 14, 20);
|
doc.text("Évaluation Maturité IA Gen", 14, 20);
|
||||||
doc.setFontSize(10);
|
doc.setFontSize(10);
|
||||||
doc.text(`Candidat : ${evaluation.candidateName} | Rôle : ${evaluation.candidateRole}`, 14, 28);
|
const teamStr = evaluation.candidateTeam ? ` | Équipe : ${evaluation.candidateTeam}` : "";
|
||||||
|
doc.text(`Candidat : ${evaluation.candidateName} | Rôle : ${evaluation.candidateRole}${teamStr}`, 14, 28);
|
||||||
doc.text(`Évaluateur : ${evaluation.evaluatorName} | Date : ${format(evaluation.evaluationDate, "yyyy-MM-dd")}`, 14, 34);
|
doc.text(`Évaluateur : ${evaluation.evaluatorName} | Date : ${format(evaluation.evaluationDate, "yyyy-MM-dd")}`, 14, 34);
|
||||||
doc.text(`Modèle : ${evaluation.template?.name ?? ""} | Statut : ${evaluation.status === "submitted" ? "Soumise" : "Brouillon"}`, 14, 40);
|
doc.text(`Modèle : ${evaluation.template?.name ?? ""} | Statut : ${evaluation.status === "submitted" ? "Soumise" : "Brouillon"}`, 14, 40);
|
||||||
|
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ interface Evaluation {
|
|||||||
id: string;
|
id: string;
|
||||||
candidateName: string;
|
candidateName: string;
|
||||||
candidateRole: string;
|
candidateRole: string;
|
||||||
|
candidateTeam?: string | null;
|
||||||
evaluatorName: string;
|
evaluatorName: string;
|
||||||
evaluationDate: string;
|
evaluationDate: string;
|
||||||
templateId: string;
|
templateId: string;
|
||||||
@@ -70,10 +71,10 @@ export default function EvaluationDetailPage() {
|
|||||||
const tmpl = templatesData.find((t: { id: string }) => t.id === evalData.templateId);
|
const tmpl = templatesData.find((t: { id: string }) => t.id === evalData.templateId);
|
||||||
if (tmpl?.dimensions?.length) {
|
if (tmpl?.dimensions?.length) {
|
||||||
const dimMap = new Map(tmpl.dimensions.map((d: { id: string }) => [d.id, d]));
|
const dimMap = new Map(tmpl.dimensions.map((d: { id: string }) => [d.id, d]));
|
||||||
evalData.template.dimensions = evalData.template.dimensions.map((d: { id: string }) => ({
|
evalData.template.dimensions = evalData.template.dimensions.map((d: { id: string; suggestedQuestions?: string | null }) => ({
|
||||||
...d,
|
...d,
|
||||||
suggestedQuestions: d.suggestedQuestions ?? dimMap.get(d.id)?.suggestedQuestions,
|
suggestedQuestions: d.suggestedQuestions ?? dimMap.get(d.id)?.suggestedQuestions,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
@@ -117,26 +118,32 @@ export default function EvaluationDetailPage() {
|
|||||||
const scores = e.dimensionScores.map((ds) =>
|
const scores = e.dimensionScores.map((ds) =>
|
||||||
ds.dimensionId === dimensionId ? { ...ds, ...data } : ds
|
ds.dimensionId === dimensionId ? { ...ds, ...data } : ds
|
||||||
);
|
);
|
||||||
return { ...e, dimensionScores: scores };
|
const next = { ...e, dimensionScores: scores };
|
||||||
|
if (data.score !== undefined) {
|
||||||
|
setTimeout(() => handleSave(next, { skipRefresh: true }), 0);
|
||||||
|
}
|
||||||
|
return next;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSave = async () => {
|
const handleSave = async (evalOverride?: Evaluation | null, options?: { skipRefresh?: boolean }) => {
|
||||||
if (!evaluation) return;
|
const toSave = evalOverride ?? evaluation;
|
||||||
|
if (!toSave) return;
|
||||||
setSaving(true);
|
setSaving(true);
|
||||||
try {
|
try {
|
||||||
const res = await fetch(`/api/evaluations/${id}`, {
|
const res = await fetch(`/api/evaluations/${id}`, {
|
||||||
method: "PUT",
|
method: "PUT",
|
||||||
headers: { "Content-Type": "application/json" },
|
headers: { "Content-Type": "application/json" },
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
candidateName: evaluation.candidateName,
|
candidateName: toSave.candidateName,
|
||||||
candidateRole: evaluation.candidateRole,
|
candidateRole: toSave.candidateRole,
|
||||||
evaluatorName: evaluation.evaluatorName,
|
candidateTeam: toSave.candidateTeam ?? null,
|
||||||
evaluationDate: evaluation.evaluationDate,
|
evaluatorName: toSave.evaluatorName,
|
||||||
status: evaluation.status,
|
evaluationDate: typeof toSave.evaluationDate === "string" ? toSave.evaluationDate : new Date(toSave.evaluationDate).toISOString(),
|
||||||
findings: evaluation.findings,
|
status: toSave.status,
|
||||||
recommendations: evaluation.recommendations,
|
findings: toSave.findings,
|
||||||
dimensionScores: (evaluation.dimensionScores ?? []).map((ds) => ({
|
recommendations: toSave.recommendations,
|
||||||
|
dimensionScores: (toSave.dimensionScores ?? []).map((ds) => ({
|
||||||
dimensionId: ds.dimensionId,
|
dimensionId: ds.dimensionId,
|
||||||
evaluationId: id,
|
evaluationId: id,
|
||||||
score: ds.score,
|
score: ds.score,
|
||||||
@@ -148,11 +155,14 @@ export default function EvaluationDetailPage() {
|
|||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
fetchEval();
|
if (!options?.skipRefresh) fetchEval();
|
||||||
} else {
|
} else {
|
||||||
const data = await res.json();
|
const data = await res.json().catch(() => ({}));
|
||||||
alert(data.error ?? "Save failed");
|
alert(data.error ?? `Save failed (${res.status})`);
|
||||||
}
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error("Save error:", err);
|
||||||
|
alert("Erreur lors de la sauvegarde");
|
||||||
} finally {
|
} finally {
|
||||||
setSaving(false);
|
setSaving(false);
|
||||||
}
|
}
|
||||||
@@ -203,11 +213,15 @@ export default function EvaluationDetailPage() {
|
|||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
<div className="flex flex-wrap items-center justify-between gap-4">
|
<div className="flex flex-wrap items-center justify-between gap-4">
|
||||||
<h1 className="font-mono text-base font-medium text-zinc-800 dark:text-zinc-100">
|
<h1 className="font-mono text-base font-medium text-zinc-800 dark:text-zinc-100">
|
||||||
{evaluation.candidateName} <span className="text-zinc-500">/</span> {evaluation.candidateRole}
|
{evaluation.candidateName}
|
||||||
|
{evaluation.candidateTeam && (
|
||||||
|
<span className="text-zinc-500"> ({evaluation.candidateTeam})</span>
|
||||||
|
)}
|
||||||
|
<span className="text-zinc-500"> / </span> {evaluation.candidateRole}
|
||||||
</h1>
|
</h1>
|
||||||
<div className="flex gap-2">
|
<div className="flex gap-2">
|
||||||
<button
|
<button
|
||||||
onClick={handleSave}
|
onClick={() => handleSave()}
|
||||||
disabled={saving}
|
disabled={saving}
|
||||||
className="rounded border border-zinc-300 dark:border-zinc-600 bg-zinc-100 dark:bg-zinc-700 px-3 py-1.5 font-mono text-xs text-zinc-700 dark:text-zinc-300 hover:bg-zinc-200 dark:hover:bg-zinc-700 disabled:opacity-50"
|
className="rounded border border-zinc-300 dark:border-zinc-600 bg-zinc-100 dark:bg-zinc-700 px-3 py-1.5 font-mono text-xs text-zinc-700 dark:text-zinc-300 hover:bg-zinc-200 dark:hover:bg-zinc-700 disabled:opacity-50"
|
||||||
>
|
>
|
||||||
@@ -233,6 +247,7 @@ export default function EvaluationDetailPage() {
|
|||||||
<CandidateForm
|
<CandidateForm
|
||||||
candidateName={evaluation.candidateName}
|
candidateName={evaluation.candidateName}
|
||||||
candidateRole={evaluation.candidateRole}
|
candidateRole={evaluation.candidateRole}
|
||||||
|
candidateTeam={evaluation.candidateTeam ?? ""}
|
||||||
evaluatorName={evaluation.evaluatorName}
|
evaluatorName={evaluation.evaluatorName}
|
||||||
evaluationDate={evaluation.evaluationDate.split("T")[0]}
|
evaluationDate={evaluation.evaluationDate.split("T")[0]}
|
||||||
templateId={evaluation.templateId}
|
templateId={evaluation.templateId}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ export default function NewEvaluationPage() {
|
|||||||
const [form, setForm] = useState({
|
const [form, setForm] = useState({
|
||||||
candidateName: "",
|
candidateName: "",
|
||||||
candidateRole: "",
|
candidateRole: "",
|
||||||
|
candidateTeam: "",
|
||||||
evaluatorName: "",
|
evaluatorName: "",
|
||||||
evaluationDate: new Date().toISOString().split("T")[0],
|
evaluationDate: new Date().toISOString().split("T")[0],
|
||||||
templateId: "",
|
templateId: "",
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ interface EvalRow {
|
|||||||
id: string;
|
id: string;
|
||||||
candidateName: string;
|
candidateName: string;
|
||||||
candidateRole: string;
|
candidateRole: string;
|
||||||
|
candidateTeam?: string | null;
|
||||||
evaluatorName: string;
|
evaluatorName: string;
|
||||||
evaluationDate: string;
|
evaluationDate: string;
|
||||||
template?: { name: string };
|
template?: { name: string };
|
||||||
@@ -45,6 +46,7 @@ export default function DashboardPage() {
|
|||||||
<thead>
|
<thead>
|
||||||
<tr className="border-b border-zinc-200 dark:border-zinc-600 bg-zinc-50 dark:bg-zinc-700/80">
|
<tr className="border-b border-zinc-200 dark:border-zinc-600 bg-zinc-50 dark:bg-zinc-700/80">
|
||||||
<th className="px-4 py-2.5 text-left font-mono text-xs text-zinc-600 dark:text-zinc-400">Candidat</th>
|
<th className="px-4 py-2.5 text-left font-mono text-xs text-zinc-600 dark:text-zinc-400">Candidat</th>
|
||||||
|
<th className="px-4 py-2.5 text-left font-mono text-xs text-zinc-600 dark:text-zinc-400">Équipe</th>
|
||||||
<th className="px-4 py-2.5 text-left font-mono text-xs text-zinc-600 dark:text-zinc-400">Rôle</th>
|
<th className="px-4 py-2.5 text-left font-mono text-xs text-zinc-600 dark:text-zinc-400">Rôle</th>
|
||||||
<th className="px-4 py-2.5 text-left font-mono text-xs text-zinc-600 dark:text-zinc-400">Évaluateur</th>
|
<th className="px-4 py-2.5 text-left font-mono text-xs text-zinc-600 dark:text-zinc-400">Évaluateur</th>
|
||||||
<th className="px-4 py-2.5 text-left font-mono text-xs text-zinc-600 dark:text-zinc-400">Date</th>
|
<th className="px-4 py-2.5 text-left font-mono text-xs text-zinc-600 dark:text-zinc-400">Date</th>
|
||||||
@@ -56,13 +58,13 @@ export default function DashboardPage() {
|
|||||||
<tbody>
|
<tbody>
|
||||||
{loading ? (
|
{loading ? (
|
||||||
<tr>
|
<tr>
|
||||||
<td colSpan={7} className="px-4 py-12 text-center font-mono text-xs text-zinc-600 dark:text-zinc-500">
|
<td colSpan={8} className="px-4 py-12 text-center font-mono text-xs text-zinc-600 dark:text-zinc-500">
|
||||||
loading...
|
loading...
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
) : evaluations.length === 0 ? (
|
) : evaluations.length === 0 ? (
|
||||||
<tr>
|
<tr>
|
||||||
<td colSpan={7} className="px-4 py-12 text-center text-zinc-600 dark:text-zinc-500">
|
<td colSpan={8} className="px-4 py-12 text-center text-zinc-600 dark:text-zinc-500">
|
||||||
Aucune évaluation.{" "}
|
Aucune évaluation.{" "}
|
||||||
<Link href="/evaluations/new" className="text-cyan-600 dark:text-cyan-400 hover:underline">
|
<Link href="/evaluations/new" className="text-cyan-600 dark:text-cyan-400 hover:underline">
|
||||||
Créer
|
Créer
|
||||||
@@ -73,6 +75,7 @@ export default function DashboardPage() {
|
|||||||
evaluations.map((e) => (
|
evaluations.map((e) => (
|
||||||
<tr key={e.id} className="border-b border-zinc-200 dark:border-zinc-600/50 hover:bg-zinc-50 dark:hover:bg-zinc-700/50 transition-colors">
|
<tr key={e.id} className="border-b border-zinc-200 dark:border-zinc-600/50 hover:bg-zinc-50 dark:hover:bg-zinc-700/50 transition-colors">
|
||||||
<td className="px-4 py-2.5 text-sm font-medium text-zinc-800 dark:text-zinc-100">{e.candidateName}</td>
|
<td className="px-4 py-2.5 text-sm font-medium text-zinc-800 dark:text-zinc-100">{e.candidateName}</td>
|
||||||
|
<td className="px-4 py-2.5 text-sm text-zinc-600 dark:text-zinc-400">{e.candidateTeam ?? "—"}</td>
|
||||||
<td className="px-4 py-2.5 text-sm text-zinc-600 dark:text-zinc-400">{e.candidateRole}</td>
|
<td className="px-4 py-2.5 text-sm text-zinc-600 dark:text-zinc-400">{e.candidateRole}</td>
|
||||||
<td className="px-4 py-2.5 text-sm text-zinc-600 dark:text-zinc-400">{e.evaluatorName}</td>
|
<td className="px-4 py-2.5 text-sm text-zinc-600 dark:text-zinc-400">{e.evaluatorName}</td>
|
||||||
<td className="px-4 py-2.5 font-mono text-xs text-zinc-600 dark:text-zinc-400">
|
<td className="px-4 py-2.5 font-mono text-xs text-zinc-600 dark:text-zinc-400">
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
interface CandidateFormProps {
|
interface CandidateFormProps {
|
||||||
candidateName: string;
|
candidateName: string;
|
||||||
candidateRole: string;
|
candidateRole: string;
|
||||||
|
candidateTeam?: string;
|
||||||
evaluatorName: string;
|
evaluatorName: string;
|
||||||
evaluationDate: string;
|
evaluationDate: string;
|
||||||
templateId: string;
|
templateId: string;
|
||||||
@@ -20,6 +21,7 @@ const labelClass = "mb-0.5 block text-xs font-medium text-zinc-600 dark:text-zin
|
|||||||
export function CandidateForm({
|
export function CandidateForm({
|
||||||
candidateName,
|
candidateName,
|
||||||
candidateRole,
|
candidateRole,
|
||||||
|
candidateTeam = "",
|
||||||
evaluatorName,
|
evaluatorName,
|
||||||
evaluationDate,
|
evaluationDate,
|
||||||
templateId,
|
templateId,
|
||||||
@@ -52,6 +54,17 @@ export function CandidateForm({
|
|||||||
placeholder="ML Engineer"
|
placeholder="ML Engineer"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="min-w-[140px]">
|
||||||
|
<label className={labelClass}>Équipe</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
value={candidateTeam}
|
||||||
|
onChange={(e) => onChange("candidateTeam", e.target.value)}
|
||||||
|
className={inputClass}
|
||||||
|
disabled={disabled}
|
||||||
|
placeholder="Cars Front"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<div className="min-w-[120px]">
|
<div className="min-w-[120px]">
|
||||||
<label className={labelClass}>Évaluateur</label>
|
<label className={labelClass}>Évaluateur</label>
|
||||||
<input
|
<input
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ export function evaluationToCsvRows(evalData: EvaluationWithScores): string[][]
|
|||||||
rows.push([
|
rows.push([
|
||||||
"candidateName",
|
"candidateName",
|
||||||
"candidateRole",
|
"candidateRole",
|
||||||
|
"candidateTeam",
|
||||||
"evaluatorName",
|
"evaluatorName",
|
||||||
"evaluationDate",
|
"evaluationDate",
|
||||||
"template",
|
"template",
|
||||||
@@ -66,6 +67,7 @@ export function evaluationToCsvRows(evalData: EvaluationWithScores): string[][]
|
|||||||
rows.push([
|
rows.push([
|
||||||
evalData.candidateName,
|
evalData.candidateName,
|
||||||
evalData.candidateRole,
|
evalData.candidateRole,
|
||||||
|
(evalData as { candidateTeam?: string | null }).candidateTeam ?? "",
|
||||||
evalData.evaluatorName,
|
evalData.evaluatorName,
|
||||||
evalData.evaluationDate.toISOString().split("T")[0],
|
evalData.evaluationDate.toISOString().split("T")[0],
|
||||||
evalData.template?.name ?? "",
|
evalData.template?.name ?? "",
|
||||||
|
|||||||
Reference in New Issue
Block a user