214 lines
6.2 KiB
TypeScript
214 lines
6.2 KiB
TypeScript
|
import { useEffect, useState } from "react";
|
||
|
import InputWithDropDown from "../../../../ui/inputs/InputWithDropDown";
|
||
|
import { AddIcon, RemoveIcon } from "../../../../icons/ExportCommonIcons";
|
||
|
|
||
|
// Texture Imports
|
||
|
import wallTexture1 from "../../../../../assets/image/wallTextures/wallTexture.png";
|
||
|
import defaultTexture from "../../../../../assets/image/wallTextures/defaultTexture.jpg";
|
||
|
|
||
|
// Define Material type
|
||
|
type Material = {
|
||
|
texture: string;
|
||
|
textureName: string;
|
||
|
};
|
||
|
|
||
|
// Initial and default material
|
||
|
const initialMaterial: Material = {
|
||
|
texture: wallTexture1,
|
||
|
textureName: "Grunge Concrete Wall",
|
||
|
};
|
||
|
|
||
|
const defaultMaterial: Material = {
|
||
|
texture: defaultTexture,
|
||
|
textureName: "Default Material",
|
||
|
};
|
||
|
|
||
|
const WallProperties = () => {
|
||
|
const [wallProperties, setWallProperties] = useState({
|
||
|
height: "10",
|
||
|
thickness: "10",
|
||
|
length: "10",
|
||
|
});
|
||
|
|
||
|
const [activeSide, setActiveSide] = useState<"side1" | "side2">("side1");
|
||
|
|
||
|
const [materials, setMaterials] = useState<Material[]>([initialMaterial]);
|
||
|
|
||
|
const [selectedMaterials, setSelectedMaterials] = useState<{
|
||
|
side1: Material | null;
|
||
|
side2: Material | null;
|
||
|
}>({
|
||
|
side1: null,
|
||
|
side2: null,
|
||
|
});
|
||
|
|
||
|
// Select initial material for both sides on mount
|
||
|
useEffect(() => {
|
||
|
setSelectedMaterials({
|
||
|
side1: initialMaterial,
|
||
|
side2: initialMaterial,
|
||
|
});
|
||
|
}, []);
|
||
|
|
||
|
const handleInputChange = (
|
||
|
key: keyof typeof wallProperties,
|
||
|
newValue: string
|
||
|
) => {
|
||
|
setWallProperties((prev) => ({
|
||
|
...prev,
|
||
|
[key]: newValue,
|
||
|
}));
|
||
|
};
|
||
|
|
||
|
const handleAddMaterial = () => {
|
||
|
const newMaterial: Material = {
|
||
|
texture: defaultMaterial.texture,
|
||
|
textureName: `Material ${materials.length + 1}`,
|
||
|
};
|
||
|
setMaterials([...materials, newMaterial]);
|
||
|
};
|
||
|
|
||
|
const handleSelectMaterial = (material: Material) => {
|
||
|
setSelectedMaterials((prev) => ({
|
||
|
...prev,
|
||
|
[activeSide]: material,
|
||
|
}));
|
||
|
};
|
||
|
|
||
|
const handleRemoveMaterial = (index: number) => {
|
||
|
const updatedMaterials = materials.filter((_, i) => i !== index);
|
||
|
|
||
|
// Ensure there's always at least one material
|
||
|
const newMaterials =
|
||
|
updatedMaterials.length === 0 ? [defaultMaterial] : updatedMaterials;
|
||
|
setMaterials(newMaterials);
|
||
|
|
||
|
// Deselect the material if it's the one removed
|
||
|
setSelectedMaterials((prev) => {
|
||
|
const updated = { ...prev };
|
||
|
["side1", "side2"].forEach((side) => {
|
||
|
if (
|
||
|
updated[side as "side1" | "side2"]?.texture ===
|
||
|
materials[index].texture
|
||
|
) {
|
||
|
updated[side as "side1" | "side2"] = defaultMaterial;
|
||
|
}
|
||
|
});
|
||
|
return updated;
|
||
|
});
|
||
|
};
|
||
|
|
||
|
return (
|
||
|
<div className="wall-properties-container">
|
||
|
<div className="header">Wall</div>
|
||
|
<div className="wall-properties">
|
||
|
<InputWithDropDown
|
||
|
label="Height"
|
||
|
value={wallProperties.height}
|
||
|
onChange={(val) => handleInputChange("height", val)}
|
||
|
/>
|
||
|
<InputWithDropDown
|
||
|
label="Thickness"
|
||
|
value={wallProperties.thickness}
|
||
|
onChange={(val) => handleInputChange("thickness", val)}
|
||
|
/>
|
||
|
<InputWithDropDown
|
||
|
label="Length"
|
||
|
value={wallProperties.length}
|
||
|
onChange={(val) => handleInputChange("length", val)}
|
||
|
/>
|
||
|
</div>
|
||
|
|
||
|
<section>
|
||
|
<div className="header-wrapper">
|
||
|
<div className="header">Materials</div>
|
||
|
<button className="addMaterial" onClick={handleAddMaterial}>
|
||
|
<AddIcon />
|
||
|
</button>
|
||
|
</div>
|
||
|
|
||
|
<div className="material-preview">
|
||
|
<div className="sides-wrapper">
|
||
|
<div
|
||
|
className={`side-wrapper ${
|
||
|
activeSide === "side1" ? "active" : ""
|
||
|
}`}
|
||
|
onClick={() => setActiveSide("side1")}
|
||
|
>
|
||
|
<div className="label">Side 1</div>
|
||
|
<div className="texture-image">
|
||
|
{selectedMaterials.side1 && (
|
||
|
<img
|
||
|
src={selectedMaterials.side1.texture}
|
||
|
alt={selectedMaterials.side1.textureName}
|
||
|
/>
|
||
|
)}
|
||
|
</div>
|
||
|
</div>
|
||
|
|
||
|
<div
|
||
|
className={`side-wrapper ${
|
||
|
activeSide === "side2" ? "active" : ""
|
||
|
}`}
|
||
|
onClick={() => setActiveSide("side2")}
|
||
|
>
|
||
|
<div className="label">Side 2</div>
|
||
|
<div className="texture-image">
|
||
|
{selectedMaterials.side2 && (
|
||
|
<img
|
||
|
src={selectedMaterials.side2.texture}
|
||
|
alt={selectedMaterials.side2.textureName}
|
||
|
/>
|
||
|
)}
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
|
||
|
<div className="preview">
|
||
|
{selectedMaterials[activeSide] && (
|
||
|
<img
|
||
|
src={selectedMaterials[activeSide]!.texture}
|
||
|
alt={selectedMaterials[activeSide]!.textureName}
|
||
|
/>
|
||
|
)}
|
||
|
</div>
|
||
|
</div>
|
||
|
|
||
|
<div className="materials">
|
||
|
{materials.length === 0 ? (
|
||
|
<div className="no-materials">No materials added yet.</div>
|
||
|
) : (
|
||
|
<div className="material-container">
|
||
|
{materials.map((material, index) => (
|
||
|
<div
|
||
|
className="material-wrapper"
|
||
|
key={`${material.textureName}_${index}`}
|
||
|
onClick={() => handleSelectMaterial(material)}
|
||
|
>
|
||
|
<div className="material-property">
|
||
|
<div className="material-image">
|
||
|
<img src={material.texture} alt={material.textureName} />
|
||
|
</div>
|
||
|
<div className="material-name">{material.textureName}</div>
|
||
|
</div>
|
||
|
<div
|
||
|
className="delete-material"
|
||
|
onClick={(e) => {
|
||
|
e.stopPropagation();
|
||
|
handleRemoveMaterial(index);
|
||
|
}}
|
||
|
>
|
||
|
<RemoveIcon />
|
||
|
</div>
|
||
|
</div>
|
||
|
))}
|
||
|
</div>
|
||
|
)}
|
||
|
</div>
|
||
|
</section>
|
||
|
</div>
|
||
|
);
|
||
|
};
|
||
|
|
||
|
export default WallProperties;
|