fix(utilities): fix scale calculator logic, remove rooms tab
Scale calculator: - Real→Desen: val(m) × 1000 ÷ scale = mm pe desen (ex: 5m la 1:100 → 50mm) - Desen→Real: val(mm) × scale ÷ 1000 = m real (ex: 50mm la 1:100 → 5m) - Previously both formulas were wrong (missing ×1000/÷1000 unit conversion) Remove RoomAreaCalculator (not useful) and its tab/imports Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -23,9 +23,6 @@ import {
|
||||
Unlock,
|
||||
PenTool,
|
||||
Maximize2,
|
||||
LayoutGrid,
|
||||
Plus,
|
||||
X,
|
||||
} from "lucide-react";
|
||||
import { Button } from "@/shared/components/ui/button";
|
||||
import { Input } from "@/shared/components/ui/input";
|
||||
@@ -2550,14 +2547,15 @@ function ScaleCalculator() {
|
||||
customScale !== "" ? parseFloat(customScale) || scale : scale;
|
||||
const val = parseFloat(inputVal);
|
||||
|
||||
// Real→Desen: val(m) × 1000 → mm, ÷ scale → mm pe desen
|
||||
// Desen→Real: val(mm) × scale → mm real, ÷ 1000 → m
|
||||
const result = !isNaN(val)
|
||||
? mode === "real-to-drawing"
|
||||
? val / effectiveScale
|
||||
: val * effectiveScale
|
||||
? (val * 1000) / effectiveScale
|
||||
: (val * effectiveScale) / 1000
|
||||
: NaN;
|
||||
|
||||
const unitIn = mode === "real-to-drawing" ? "m (real)" : "mm (desen)";
|
||||
const unitOut = mode === "real-to-drawing" ? "mm (desen)" : "m (real)";
|
||||
|
||||
const fmtDesen = (n: number) =>
|
||||
isNaN(n)
|
||||
@@ -2663,170 +2661,6 @@ function ScaleCalculator() {
|
||||
);
|
||||
}
|
||||
|
||||
// ─── Calculator Camere ────────────────────────────────────────────────────────
|
||||
|
||||
interface Room {
|
||||
id: string;
|
||||
name: string;
|
||||
width: string;
|
||||
length: string;
|
||||
height: string;
|
||||
}
|
||||
|
||||
function RoomAreaCalculator() {
|
||||
const [rooms, setRooms] = useState<Room[]>([
|
||||
{ id: "1", name: "Living", width: "", length: "", height: "" },
|
||||
]);
|
||||
|
||||
const addRoom = () => {
|
||||
setRooms((prev) => [
|
||||
...prev,
|
||||
{ id: String(Date.now()), name: "", width: "", length: "", height: "" },
|
||||
]);
|
||||
};
|
||||
|
||||
const removeRoom = (id: string) => {
|
||||
setRooms((prev) => prev.filter((r) => r.id !== id));
|
||||
};
|
||||
|
||||
const updateRoom = (id: string, field: keyof Room, value: string) => {
|
||||
setRooms((prev) =>
|
||||
prev.map((r) => (r.id === id ? { ...r, [field]: value } : r)),
|
||||
);
|
||||
};
|
||||
|
||||
const roomsWithArea = rooms.map((r) => {
|
||||
const w = parseFloat(r.width);
|
||||
const l = parseFloat(r.length);
|
||||
const h = parseFloat(r.height);
|
||||
const area = !isNaN(w) && !isNaN(l) ? w * l : NaN;
|
||||
const volume = !isNaN(area) && !isNaN(h) ? area * h : NaN;
|
||||
return { ...r, area, volume };
|
||||
});
|
||||
|
||||
const totalArea = roomsWithArea.reduce(
|
||||
(sum, r) => (isNaN(r.area) ? sum : sum + r.area),
|
||||
0,
|
||||
);
|
||||
const totalVolume = roomsWithArea.reduce(
|
||||
(sum, r) => (isNaN(r.volume) ? sum : sum + r.volume),
|
||||
0,
|
||||
);
|
||||
|
||||
const fmtM2 = (n: number) =>
|
||||
n.toLocaleString("ro-RO", { minimumFractionDigits: 2, maximumFractionDigits: 2 });
|
||||
|
||||
const copyAll = () => {
|
||||
const lines = roomsWithArea
|
||||
.filter((r) => !isNaN(r.area))
|
||||
.map((r) => `${r.name || "Cameră"}: ${fmtM2(r.area)} m²`)
|
||||
.join("\n");
|
||||
const text = lines + `\n\nTotal: ${fmtM2(totalArea)} m²`;
|
||||
navigator.clipboard.writeText(text).catch(() => {});
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<div className="space-y-2">
|
||||
{roomsWithArea.map((room, idx) => (
|
||||
<div key={room.id} className="flex flex-wrap items-center gap-2 rounded border p-2">
|
||||
<Input
|
||||
placeholder={`Cameră ${idx + 1}`}
|
||||
value={room.name}
|
||||
onChange={(e) => updateRoom(room.id, "name", e.target.value)}
|
||||
className="w-[130px] text-sm"
|
||||
/>
|
||||
<div className="flex items-center gap-1">
|
||||
<Input
|
||||
type="number"
|
||||
placeholder="L"
|
||||
value={room.width}
|
||||
onChange={(e) => updateRoom(room.id, "width", e.target.value)}
|
||||
className="w-[80px] text-sm"
|
||||
min={0}
|
||||
step={0.01}
|
||||
/>
|
||||
<span className="text-muted-foreground text-xs">×</span>
|
||||
<Input
|
||||
type="number"
|
||||
placeholder="l"
|
||||
value={room.length}
|
||||
onChange={(e) => updateRoom(room.id, "length", e.target.value)}
|
||||
className="w-[80px] text-sm"
|
||||
min={0}
|
||||
step={0.01}
|
||||
/>
|
||||
<span className="text-muted-foreground text-xs">m</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-1">
|
||||
<Input
|
||||
type="number"
|
||||
placeholder="H"
|
||||
value={room.height}
|
||||
onChange={(e) => updateRoom(room.id, "height", e.target.value)}
|
||||
className="w-[70px] text-sm"
|
||||
min={0}
|
||||
step={0.01}
|
||||
/>
|
||||
<span className="text-muted-foreground text-xs">m</span>
|
||||
</div>
|
||||
{!isNaN(room.area) && (
|
||||
<span className="text-sm font-medium text-primary min-w-[80px]">
|
||||
{fmtM2(room.area)} m²
|
||||
{!isNaN(room.volume) && (
|
||||
<span className="block text-[10px] text-muted-foreground font-normal">
|
||||
{fmtM2(room.volume)} m³
|
||||
</span>
|
||||
)}
|
||||
</span>
|
||||
)}
|
||||
<Button
|
||||
type="button"
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="h-7 w-7 text-destructive ml-auto"
|
||||
onClick={() => removeRoom(room.id)}
|
||||
disabled={rooms.length === 1}
|
||||
>
|
||||
<X className="h-3.5 w-3.5" />
|
||||
</Button>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
<Button type="button" variant="outline" size="sm" onClick={addRoom}>
|
||||
<Plus className="mr-1 h-3 w-3" /> Adaugă cameră
|
||||
</Button>
|
||||
</div>
|
||||
{totalArea > 0 && (
|
||||
<div className="rounded-md border bg-muted/30 p-4 space-y-1 text-sm">
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="font-medium">
|
||||
Total suprafață:{" "}
|
||||
<strong className="text-primary">{fmtM2(totalArea)} m²</strong>
|
||||
</span>
|
||||
<CopyButton text={fmtM2(totalArea)} />
|
||||
</div>
|
||||
{totalVolume > 0 && (
|
||||
<p className="text-xs text-muted-foreground">
|
||||
Volum total: {fmtM2(totalVolume)} m³
|
||||
</p>
|
||||
)}
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="mt-2"
|
||||
onClick={copyAll}
|
||||
>
|
||||
<Copy className="mr-1 h-3 w-3" /> Copiază tot
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// ─── Main Module ──────────────────────────────────────────────────────────────
|
||||
|
||||
export function MiniUtilitiesModule() {
|
||||
@@ -2865,9 +2699,6 @@ export function MiniUtilitiesModule() {
|
||||
<TabsTrigger value="scale">
|
||||
<Maximize2 className="mr-1.5 h-3.5 w-3.5" /> Scară
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="rooms">
|
||||
<LayoutGrid className="mr-1.5 h-3.5 w-3.5" /> Camere
|
||||
</TabsTrigger>
|
||||
</TabsList>
|
||||
<TabsList className="flex h-auto flex-wrap gap-1 rounded-lg bg-muted/50 p-1">
|
||||
{/* ── Documente & Unelte ── */}
|
||||
@@ -3062,16 +2893,6 @@ export function MiniUtilitiesModule() {
|
||||
</CardContent>
|
||||
</Card>
|
||||
</TabsContent>
|
||||
<TabsContent value="rooms">
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="text-base">Calculator suprafețe camere</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<RoomAreaCalculator />
|
||||
</CardContent>
|
||||
</Card>
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user