duplicate zone rename bug resolved
This commit is contained in:
parent
ca3028985f
commit
db9c9fb8b5
|
@ -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>
|
||||||
|
|
|
@ -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;
|
|
||||||
|
|
|
@ -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">
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
|
@ -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"
|
||||||
})`
|
})`
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue