209 lines
6.4 KiB
TypeScript
209 lines
6.4 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";
|
|
import { useBuilderStore } from "../../../../../store/builder/useBuilderStore";
|
|
|
|
// Define Material type
|
|
type Material = {
|
|
texture: string;
|
|
textureName: string;
|
|
};
|
|
|
|
// Default and initial materials
|
|
const defaultMaterial: Material = {
|
|
texture: defaultTexture,
|
|
textureName: "Default Material",
|
|
};
|
|
|
|
const initialMaterial: Material = {
|
|
texture: wallTexture1,
|
|
textureName: "Grunge Concrete Wall",
|
|
};
|
|
|
|
const WallProperties = () => {
|
|
const { wallHeight, wallThickness, setWallHeight, setWallThickness } = useBuilderStore();
|
|
|
|
const [activeSide, setActiveSide] = useState<"side1" | "side2">("side1");
|
|
|
|
const [materials, setMaterials] = useState<Material[]>([
|
|
defaultMaterial,
|
|
initialMaterial,
|
|
]);
|
|
|
|
const [selectedMaterials, setSelectedMaterials] = useState<{
|
|
side1: Material | null;
|
|
side2: Material | null;
|
|
}>({
|
|
side1: null,
|
|
side2: null,
|
|
});
|
|
|
|
// Set default material initially for both sides
|
|
useEffect(() => {
|
|
setSelectedMaterials({
|
|
side1: defaultMaterial,
|
|
side2: defaultMaterial,
|
|
});
|
|
}, []);
|
|
|
|
const handleHeightChange = (newValue: string) => {
|
|
setWallHeight(parseFloat(newValue));
|
|
};
|
|
|
|
const handleThicknessChange = (newValue: string) => {
|
|
setWallThickness(parseFloat(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 removedTexture = materials[index].texture;
|
|
|
|
const updatedMaterials = materials.filter((_, i) => i !== index);
|
|
const newMaterials = updatedMaterials.length === 0 ? [defaultMaterial] : updatedMaterials;
|
|
setMaterials(newMaterials);
|
|
|
|
setSelectedMaterials((prev) => {
|
|
const updated = { ...prev };
|
|
["side1", "side2"].forEach((side) => {
|
|
if (updated[side as "side1" | "side2"]?.texture === removedTexture) {
|
|
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={`${wallHeight}`}
|
|
onChange={(val) => handleHeightChange(val)}
|
|
/>
|
|
<InputWithDropDown
|
|
label="Thickness"
|
|
value={`${wallThickness}`}
|
|
onChange={(val) => handleThicknessChange(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">
|
|
<button
|
|
className={`side-wrapper ${activeSide === "side1" ? "active" : ""}`}
|
|
onClick={() => setActiveSide("side1")}
|
|
>
|
|
<div className="label">Side 1</div>
|
|
<div className="texture-image">
|
|
{selectedMaterials.side1 && (
|
|
<img
|
|
draggable={false}
|
|
src={selectedMaterials.side1.texture}
|
|
alt={selectedMaterials.side1.textureName}
|
|
/>
|
|
)}
|
|
</div>
|
|
</button>
|
|
|
|
<button
|
|
className={`side-wrapper ${activeSide === "side2" ? "active" : ""}`}
|
|
onClick={() => setActiveSide("side2")}
|
|
>
|
|
<div className="label">Side 2</div>
|
|
<div className="texture-image">
|
|
{selectedMaterials.side2 && (
|
|
<img
|
|
draggable={false}
|
|
src={selectedMaterials.side2.texture}
|
|
alt={selectedMaterials.side2.textureName}
|
|
/>
|
|
)}
|
|
</div>
|
|
</button>
|
|
</div>
|
|
|
|
<div className="preview">
|
|
{selectedMaterials[activeSide] && (
|
|
<img
|
|
draggable={false}
|
|
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) => {
|
|
const isSelected = selectedMaterials[activeSide]?.texture === material.texture;
|
|
|
|
return (
|
|
<button
|
|
className={`material-wrapper ${isSelected ? "selectedMaterial" : ""}`}
|
|
key={`${material.textureName}_${index}`}
|
|
onClick={() => handleSelectMaterial(material)}
|
|
>
|
|
<div className="material-property">
|
|
<div className="material-image">
|
|
<img
|
|
draggable={false}
|
|
src={material.texture}
|
|
alt={material.textureName}
|
|
/>
|
|
</div>
|
|
<div className="material-name">{material.textureName}</div>
|
|
</div>
|
|
<button
|
|
className="delete-material"
|
|
onClick={(e) => {
|
|
e.stopPropagation();
|
|
handleRemoveMaterial(index);
|
|
}}
|
|
>
|
|
<RemoveIcon />
|
|
</button>
|
|
</button>
|
|
);
|
|
})}
|
|
</div>
|
|
)}
|
|
</div>
|
|
</section>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default WallProperties;
|