Fix: Type safety and unit validation

This commit is contained in:
gpt-engineer-app[bot]
2025-10-21 15:05:50 +00:00
parent bcba0a4f0c
commit 65a6ed1acb
10 changed files with 146 additions and 32 deletions

View File

@@ -1,4 +1,5 @@
import { Plus, Trash2 } from "lucide-react";
import { useState } from "react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
@@ -13,7 +14,8 @@ import {
getMetricUnit,
getDisplayUnit
} from "@/lib/units";
import { validateMetricUnit } from "@/lib/unitValidation";
import { validateMetricUnit, METRIC_UNITS } from "@/lib/unitValidation";
import { getErrorMessage } from "@/lib/errorHandler";
interface TechnicalSpec {
spec_name: string;
@@ -32,7 +34,6 @@ interface TechnicalSpecsEditorProps {
}
const DEFAULT_CATEGORIES = ['Performance', 'Safety', 'Design', 'Capacity', 'Technical', 'Other'];
const COMMON_UNITS = ['m', 'km/h', 'mph', 'ft', 'seconds', 'minutes', 'kg', 'lbs', 'passengers', '%'];
export function TechnicalSpecsEditor({
specs,
@@ -41,6 +42,7 @@ export function TechnicalSpecsEditor({
commonSpecs = []
}: TechnicalSpecsEditorProps) {
const { preferences } = useUnitPreferences();
const [unitErrors, setUnitErrors] = useState<Record<number, string>>({});
const addSpec = () => {
onChange([
@@ -70,8 +72,17 @@ export function TechnicalSpecsEditor({
try {
validateMetricUnit(value, 'Unit');
newSpecs[index] = { ...newSpecs[index], [field]: value };
} catch (error) {
toast.error(`Invalid unit: ${value}. Please use metric units only (m, km/h, cm, kg, celsius, etc.)`);
// Clear error for this index
setUnitErrors(prev => {
const updated = { ...prev };
delete updated[index];
return updated;
});
} catch (error: unknown) {
const message = getErrorMessage(error);
toast.error(message);
// Store error for visual feedback
setUnitErrors(prev => ({ ...prev, [index]: message }));
return;
}
} else {
@@ -220,10 +231,17 @@ export function TechnicalSpecsEditor({
onChange={(e) => updateSpec(index, 'unit', e.target.value)}
placeholder="Unit"
list={`units-${index}`}
className={unitErrors[index] ? 'border-destructive' : ''}
/>
<datalist id={`units-${index}`}>
{COMMON_UNITS.map(u => <option key={u} value={u} />)}
{METRIC_UNITS.map(u => <option key={u} value={u} />)}
</datalist>
{unitErrors[index] && (
<p className="text-xs text-destructive mt-1">{unitErrors[index]}</p>
)}
<p className="text-xs text-muted-foreground mt-1">
Metric units only
</p>
</div>
<Button
type="button"
@@ -242,3 +260,28 @@ export function TechnicalSpecsEditor({
</div>
);
}
/**
* Validates technical specs before submission
*/
export function validateTechnicalSpecs(specs: TechnicalSpec[]): { valid: boolean; errors: string[] } {
const errors: string[] = [];
specs.forEach((spec, index) => {
if (!spec.spec_name?.trim()) {
errors.push(`Spec ${index + 1}: Name is required`);
}
if (!spec.spec_value?.trim()) {
errors.push(`Spec ${index + 1} (${spec.spec_name}): Value is required`);
}
if (spec.unit) {
try {
validateMetricUnit(spec.unit, `Spec ${index + 1} (${spec.spec_name})`);
} catch (error: unknown) {
errors.push(getErrorMessage(error));
}
}
});
return { valid: errors.length === 0, errors };
}