duplicate zone rename bug resolved

This commit is contained in:
Gomathi 2025-04-15 18:28:37 +05:30
parent ca3028985f
commit db9c9fb8b5
7 changed files with 101 additions and 50 deletions

View File

@ -62,19 +62,25 @@ const ZoneProperties: React.FC = () => {
: zone : zone
) )
); );
}else{ } else {
// console.log(response?.message); // console.log(response?.message);
} }
} }
function handleVectorChange(key: "zoneViewPortTarget" | "zoneViewPortPosition", newValue: [number, number, number]) { function handleVectorChange(key: "zoneViewPortTarget" | "zoneViewPortPosition", newValue: [number, number, number]) {
setSelectedZone((prev) => ({ ...prev, [key]: newValue })); setSelectedZone((prev) => ({ ...prev, [key]: newValue }));
} }
const checkZoneNameDuplicate = (name: string) => {
return zones.some(
(zone: any) =>
zone.zoneName.trim().toLowerCase() === name.trim().toLowerCase() &&
zone.zoneId !== selectedZone.zoneId
);
};
return ( return (
<div className="zone-properties-container"> <div className="zone-properties-container">
<div className="header"> <div className="header">
<RenameInput value={selectedZone.zoneName} onRename={handleZoneNameChange} /> <RenameInput value={selectedZone.zoneName} onRename={handleZoneNameChange} checkDuplicate={checkZoneNameDuplicate} />
<div className="button" onClick={handleEditView}> <div className="button" onClick={handleEditView}>
{Edit ? "Cancel" : "Edit"} {Edit ? "Cancel" : "Edit"}
</div> </div>

View File

@ -1,26 +1,42 @@
import React, { useState, useRef, useEffect } from "react"; import React, { useState, useRef, useEffect } from "react";
// interface RenameInputProps {
// value: string;
// onRename?: (newText: string) => void;
// }
interface RenameInputProps { interface RenameInputProps {
value: string; value: string;
onRename?: (newText: string) => void; onRename?: (newText: string) => void;
checkDuplicate?: (name: string) => boolean;
} }
const RenameInput: React.FC<RenameInputProps> = ({ value, onRename }) => { const RenameInput: React.FC<RenameInputProps> = ({ value, onRename, checkDuplicate }) => {
const [isEditing, setIsEditing] = useState(false); const [isEditing, setIsEditing] = useState(false);
const [text, setText] = useState(value); const [text, setText] = useState(value);
const [isDuplicate, setIsDuplicate] = useState(false);
const inputRef = useRef<HTMLInputElement | null>(null); const inputRef = useRef<HTMLInputElement | null>(null);
useEffect(() => { useEffect(() => {
setText(value); // Ensure state updates when parent value changes setText(value);
}, [value]); }, [value]);
useEffect(() => {
if (checkDuplicate) {
setIsDuplicate(checkDuplicate(text));
}
}, [text, checkDuplicate]);
const handleDoubleClick = () => { const handleDoubleClick = () => {
setIsEditing(true); setIsEditing(true);
setTimeout(() => inputRef.current?.focus(), 0); // Focus the input after rendering setTimeout(() => inputRef.current?.focus(), 0);
}; };
const handleBlur = () => { const handleBlur = () => {
if(isDuplicate) return
setIsEditing(false); setIsEditing(false);
if (onRename) { if (onRename && !isDuplicate) {
onRename(text); onRename(text);
} }
}; };
@ -30,7 +46,7 @@ const RenameInput: React.FC<RenameInputProps> = ({ value, onRename }) => {
}; };
const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => { const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
if (e.key === "Enter") { if (e.key === "Enter" && !isDuplicate) {
setIsEditing(false); setIsEditing(false);
if (onRename) { if (onRename) {
onRename(text); onRename(text);
@ -41,6 +57,7 @@ const RenameInput: React.FC<RenameInputProps> = ({ value, onRename }) => {
return ( return (
<> <>
{isEditing ? ( {isEditing ? (
<>
<input <input
ref={inputRef} ref={inputRef}
type="text" type="text"
@ -48,8 +65,10 @@ const RenameInput: React.FC<RenameInputProps> = ({ value, onRename }) => {
onChange={handleChange} onChange={handleChange}
onBlur={handleBlur} onBlur={handleBlur}
onKeyDown={handleKeyDown} onKeyDown={handleKeyDown}
className="rename-input" className={`rename-input ${isDuplicate ? "input-error" : ""}`}
/> />
{/* {isDuplicate && <div className="error-msg">Name already exists!</div>} */}
</>
) : ( ) : (
<span onDoubleClick={handleDoubleClick} className="input-value"> <span onDoubleClick={handleDoubleClick} className="input-value">
{text} {text}
@ -58,5 +77,4 @@ const RenameInput: React.FC<RenameInputProps> = ({ value, onRename }) => {
</> </>
); );
}; };
export default RenameInput
export default RenameInput;

View File

@ -13,7 +13,7 @@ import {
RmoveIcon, RmoveIcon,
} from "../../icons/ExportCommonIcons"; } from "../../icons/ExportCommonIcons";
import { useThree } from "@react-three/fiber"; import { useThree } from "@react-three/fiber";
import { useFloorItems, useZoneAssetId } from "../../../store/store"; import { useFloorItems, useZoneAssetId, useZones } from "../../../store/store";
import { zoneCameraUpdate } from "../../../services/realTimeVisulization/zoneData/zoneCameraUpdation"; import { zoneCameraUpdate } from "../../../services/realTimeVisulization/zoneData/zoneCameraUpdation";
import { setFloorItemApi } from "../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi"; import { setFloorItemApi } from "../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi";
@ -40,7 +40,7 @@ const List: React.FC<ListProps> = ({ items = [], remove }) => {
const { activeModule, setActiveModule } = useModuleStore(); const { activeModule, setActiveModule } = useModuleStore();
const { selectedZone, setSelectedZone } = useSelectedZoneStore(); const { selectedZone, setSelectedZone } = useSelectedZoneStore();
const { zoneAssetId, setZoneAssetId } = useZoneAssetId(); const { zoneAssetId, setZoneAssetId } = useZoneAssetId();
const { zones, setZones } = useZones();
const { setSubModule } = useSubModuleStore(); const { setSubModule } = useSubModuleStore();
const [expandedZones, setExpandedZones] = useState<Record<string, boolean>>( const [expandedZones, setExpandedZones] = useState<Record<string, boolean>>(
{} {}
@ -100,19 +100,33 @@ const List: React.FC<ListProps> = ({ items = [], remove }) => {
function handleAssetClick(asset: Asset) { function handleAssetClick(asset: Asset) {
setZoneAssetId(asset) setZoneAssetId(asset)
} }
async function handleZoneNameChange(newName: string) { async function handleZoneNameChange(newName: string) {
//zone apiiiiii
const email = localStorage.getItem("email") || ""; const email = localStorage.getItem("email") || "";
const organization = email?.split("@")[1]?.split(".")[0]; const organization = email?.split("@")[1]?.split(".")[0];
let zonesdata = {
const isDuplicate = zones.some(
(zone: any) =>
zone.zoneName.trim().toLowerCase() === newName.trim().toLowerCase() &&
zone.zoneId !== selectedZone.zoneId
);
if (isDuplicate) {
alert("Zone name already exists. Please choose a different name.");
return; // DO NOT update state
}
const zonesdata = {
zoneId: selectedZone.zoneId, zoneId: selectedZone.zoneId,
zoneName: newName zoneName: newName,
}; };
let response = await zoneCameraUpdate(zonesdata, organization);
const response = await zoneCameraUpdate(zonesdata, organization);
if (response.message === "updated successfully") { if (response.message === "updated successfully") {
setSelectedZone((prev) => ({ ...prev, zoneName: newName })); setSelectedZone((prev) => ({ ...prev, zoneName: newName }));
} }
} }
async function handleZoneAssetName(newName: string) { async function handleZoneAssetName(newName: string) {
const email = localStorage.getItem("email") || ""; const email = localStorage.getItem("email") || "";
const organization = email?.split("@")[1]?.split(".")[0]; const organization = email?.split("@")[1]?.split(".")[0];
@ -132,6 +146,13 @@ const List: React.FC<ListProps> = ({ items = [], remove }) => {
console.log('newName: ', newName); console.log('newName: ', newName);
} }
const checkZoneNameDuplicate = (name: string) => {
return zones.some(
(zone: any) =>
zone.zoneName.trim().toLowerCase() === name.trim().toLowerCase() &&
zone.zoneId !== selectedZone.zoneId
);
};
return ( return (
<> <>
@ -146,7 +167,12 @@ const List: React.FC<ListProps> = ({ items = [], remove }) => {
className="value" className="value"
onClick={() => handleSelectZone(item.id)} onClick={() => handleSelectZone(item.id)}
> >
<RenameInput value={item.name} onRename={handleZoneNameChange} /> <RenameInput
value={item.name}
onRename={handleZoneNameChange}
checkDuplicate={checkZoneNameDuplicate}
/>
</div> </div>
</div> </div>
<div className="options-container"> <div className="options-container">

View File

@ -19,7 +19,7 @@ function NavMeshCreator({ lines }: NavMeshCreatorProps) {
<NavMeshDetails lines={lines} setNavMesh={setNavMesh} groupRef={groupRef} /> <NavMeshDetails lines={lines} setNavMesh={setNavMesh} groupRef={groupRef} />
<group ref={groupRef} visible={false} name="Meshes"> <group ref={groupRef} visible={false} name="Meshes">
<mesh rotation-x={CONSTANTS.planeConfig.rotation} position={CONSTANTS.planeConfig.position3D} name="Plane" receiveShadow> <mesh rotation-x={CONSTANTS.planeConfig.rotation} position={CONSTANTS.planeConfig.position3D} receiveShadow>
<planeGeometry args={[300, 300]} /> <planeGeometry args={[300, 300]} />
<meshBasicMaterial color={CONSTANTS.planeConfig.color} /> <meshBasicMaterial color={CONSTANTS.planeConfig.color} />
</mesh> </mesh>

View File

@ -104,8 +104,8 @@ const DisplayZone: React.FC<DisplayZoneProps> = ({
setShowLeftArrow(isOverflowing && canScrollLeft); setShowLeftArrow(isOverflowing && canScrollLeft);
setShowRightArrow(isOverflowing && canScrollRight); setShowRightArrow(isOverflowing && canScrollRight);
console.log('canScrollRight: ', canScrollRight); // console.log('canScrollRight: ', canScrollRight);
console.log('isOverflowing: ', isOverflowing); // console.log('isOverflowing: ', isOverflowing);
} }
}, []); }, []);

View File

@ -520,37 +520,37 @@ const DroppedObjects: React.FC = () => {
onPointerUp={handlePointerUp} onPointerUp={handlePointerUp}
className="floating-wrapper" className="floating-wrapper"
> >
{zone.objects.map((obj, index) => { {zone?.objects?.map((obj, index) => {
const topPosition = const topPosition =
typeof obj.position.top === "number" typeof obj?.position?.top === "number"
? `calc(${obj.position.top}px + ${ ? `calc(${obj?.position?.top}px + ${
isPlaying && selectedZone.activeSides.includes("top") isPlaying && selectedZone?.activeSides?.includes("top")
? `${heightMultiplier - 55}px` ? `${heightMultiplier - 55}px`
: "0px" : "0px"
})` })`
: "auto"; : "auto";
const leftPosition = const leftPosition =
typeof obj.position.left === "number" typeof obj?.position?.left === "number"
? `calc(${obj.position.left}px + ${ ? `calc(${obj?.position?.left}px + ${
isPlaying && selectedZone.activeSides.includes("left") isPlaying && selectedZone?.activeSides?.includes("left")
? `${widthMultiplier - 150}px` ? `${widthMultiplier - 150}px`
: "0px" : "0px"
})` })`
: "auto"; : "auto";
const rightPosition = const rightPosition =
typeof obj.position.right === "number" typeof obj?.position?.right === "number"
? `calc(${obj.position.right}px + ${ ? `calc(${obj?.position?.right}px + ${
isPlaying && selectedZone.activeSides.includes("right") isPlaying && selectedZone?.activeSides?.includes("right")
? `${widthMultiplier - 150}px` ? `${widthMultiplier - 150}px`
: "0px" : "0px"
})` })`
: "auto"; : "auto";
const bottomPosition = const bottomPosition =
typeof obj.position.bottom === "number" typeof obj?.position?.bottom === "number"
? `calc(${obj.position.bottom}px + ${ ? `calc(${obj?.position?.bottom}px + ${
isPlaying && selectedZone.activeSides.includes("bottom") isPlaying && selectedZone?.activeSides?.includes("bottom")
? `${heightMultiplier - 55}px` ? `${heightMultiplier - 55}px`
: "0px" : "0px"
})` })`

View File

@ -56,6 +56,12 @@ input {
padding: 0 8px; padding: 0 8px;
} }
.input-error {
border: 1px solid #f65648 !important;
outline: none !important;
color: #f65648;
}
.toggle-header-container { .toggle-header-container {
@include flex-center; @include flex-center;
padding: 6px 12px; padding: 6px 12px;
@ -344,7 +350,6 @@ input {
padding: 10px; padding: 10px;
} }
.loading { .loading {
position: absolute; position: absolute;
bottom: 0; bottom: 0;
@ -364,9 +369,7 @@ input {
left: -50%; left: -50%;
height: 100%; height: 100%;
width: 50%; width: 50%;
background: linear-gradient(to right, background: linear-gradient(to right, var(--accent-color), transparent);
var(--accent-color),
transparent);
animation: loadingAnimation 1.2s linear infinite; animation: loadingAnimation 1.2s linear infinite;
border-radius: 4px; border-radius: 4px;
} }
@ -381,8 +384,6 @@ input {
} }
} }
.dropdown-item { .dropdown-item {
display: block; display: block;
padding: 5px 10px; padding: 5px 10px;