// Vrai-Prix — méthode du coût : primitives de formulaire de l'atelier (champs éditoriaux, parts en %, blocs).
"use client";
import type { AttributeSource } from "@/lib/cost/types";
import { AttrBadge } from "./Provenance";
export function Block({ num, title, children, id, aside }: { num: string; title: string; children: React.ReactNode; id?: string; aside?: React.ReactNode }) {
return (
);
}
export function Field({ label, children, hint, source, fr }: { label: string; children: React.ReactNode; hint?: string; source?: AttributeSource | null; fr?: boolean }) {
return (
);
}
export function NumField({ value, onChange, min, max, step, unit, placeholder, disabled }: { value: number | null | undefined; onChange: (v: number | null) => void; min?: number; max?: number; step?: number; unit?: string; placeholder?: string; disabled?: boolean }) {
return (
onChange(e.target.value === "" ? null : Number(e.target.value))} className="vp-input vp-mono text-[14px]" />
{unit && {unit}}
);
}
export function SelectField({ value, onChange, options }: { value: T; onChange: (v: T) => void; options: { key: T; label: string }[] }) {
return (
);
}
export function Toggle({ checked, onChange, label }: { checked: boolean; onChange: (v: boolean) => void; label: string }) {
return (
);
}
/** Parts en % d'un mélange (revêtements, planchers) — la somme est normalisée par le moteur. */
export function MixField({ value, onChange, options, fr }: { value: Partial>; onChange: (v: Partial>) => void; options: { key: K; fr: string; en: string }[]; fr: boolean }) {
const total = Object.values(value as Record).reduce((s, v) => s + (v || 0), 0);
return (
);
}
export function PctField({ value, onChange, label, note, amount, fr, lang }: { value: number; onChange: (v: number) => void; label: string; note?: string; amount?: number; fr: boolean; lang: string }) {
return (
{label}{note && ⓘ}
onChange(Number(e.target.value) || 0)} className="vp-input vp-mono !min-h-0 !py-1 text-right text-[13px]" />%
{amount != null ? new Intl.NumberFormat(lang === "fr" ? "fr-CA" : "en-CA", { style: "currency", currency: "CAD", maximumFractionDigits: 0 }).format(amount) : (fr ? "—" : "—")}
);
}