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,
|
Unlock,
|
||||||
PenTool,
|
PenTool,
|
||||||
Maximize2,
|
Maximize2,
|
||||||
LayoutGrid,
|
|
||||||
Plus,
|
|
||||||
X,
|
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import { Button } from "@/shared/components/ui/button";
|
import { Button } from "@/shared/components/ui/button";
|
||||||
import { Input } from "@/shared/components/ui/input";
|
import { Input } from "@/shared/components/ui/input";
|
||||||
@@ -2550,14 +2547,15 @@ function ScaleCalculator() {
|
|||||||
customScale !== "" ? parseFloat(customScale) || scale : scale;
|
customScale !== "" ? parseFloat(customScale) || scale : scale;
|
||||||
const val = parseFloat(inputVal);
|
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)
|
const result = !isNaN(val)
|
||||||
? mode === "real-to-drawing"
|
? mode === "real-to-drawing"
|
||||||
? val / effectiveScale
|
? (val * 1000) / effectiveScale
|
||||||
: val * effectiveScale
|
: (val * effectiveScale) / 1000
|
||||||
: NaN;
|
: NaN;
|
||||||
|
|
||||||
const unitIn = mode === "real-to-drawing" ? "m (real)" : "mm (desen)";
|
const unitIn = mode === "real-to-drawing" ? "m (real)" : "mm (desen)";
|
||||||
const unitOut = mode === "real-to-drawing" ? "mm (desen)" : "m (real)";
|
|
||||||
|
|
||||||
const fmtDesen = (n: number) =>
|
const fmtDesen = (n: number) =>
|
||||||
isNaN(n)
|
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 ──────────────────────────────────────────────────────────────
|
// ─── Main Module ──────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
export function MiniUtilitiesModule() {
|
export function MiniUtilitiesModule() {
|
||||||
@@ -2865,9 +2699,6 @@ export function MiniUtilitiesModule() {
|
|||||||
<TabsTrigger value="scale">
|
<TabsTrigger value="scale">
|
||||||
<Maximize2 className="mr-1.5 h-3.5 w-3.5" /> Scară
|
<Maximize2 className="mr-1.5 h-3.5 w-3.5" /> Scară
|
||||||
</TabsTrigger>
|
</TabsTrigger>
|
||||||
<TabsTrigger value="rooms">
|
|
||||||
<LayoutGrid className="mr-1.5 h-3.5 w-3.5" /> Camere
|
|
||||||
</TabsTrigger>
|
|
||||||
</TabsList>
|
</TabsList>
|
||||||
<TabsList className="flex h-auto flex-wrap gap-1 rounded-lg bg-muted/50 p-1">
|
<TabsList className="flex h-auto flex-wrap gap-1 rounded-lg bg-muted/50 p-1">
|
||||||
{/* ── Documente & Unelte ── */}
|
{/* ── Documente & Unelte ── */}
|
||||||
@@ -3062,16 +2893,6 @@ export function MiniUtilitiesModule() {
|
|||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
</TabsContent>
|
</TabsContent>
|
||||||
<TabsContent value="rooms">
|
|
||||||
<Card>
|
|
||||||
<CardHeader>
|
|
||||||
<CardTitle className="text-base">Calculator suprafețe camere</CardTitle>
|
|
||||||
</CardHeader>
|
|
||||||
<CardContent>
|
|
||||||
<RoomAreaCalculator />
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
</TabsContent>
|
|
||||||
</Tabs>
|
</Tabs>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user