Refactor compare components and version management
- Updated SVG attributes in SimulationIcons to use camelCase for color interpolation filters. - Refactored import paths for ComparePopUp and CompareLayOut to new directory structure. - Enhanced VersionHistory component to utilize version store for better state management. - Removed deprecated CompareLayOut and compare components, replacing them with new versions. - Implemented VersionSaved component to display notifications for newly saved versions. - Added functionality to save and edit version names and descriptions. - Updated styles for version notifications and editing popups. - Improved AddButtons component to dynamically set IDs based on side. - Enhanced Project component to integrate new version management features.
This commit is contained in:
77
app/src/components/ui/compareVersion/Compare.tsx
Normal file
77
app/src/components/ui/compareVersion/Compare.tsx
Normal file
@@ -0,0 +1,77 @@
|
||||
import React from "react";
|
||||
import { InfoIcon } from "../../icons/ShortcutIcons";
|
||||
import { SaveDiskIcon } from "../../icons/ExportCommonIcons";
|
||||
import { useCompareStore } from "../../../store/builder/store";
|
||||
import OuterClick from "../../../utils/outerClick";
|
||||
|
||||
interface ComparePopUpProps {
|
||||
onClose: () => void;
|
||||
}
|
||||
|
||||
const ComparePopUp: React.FC<ComparePopUpProps> = ({ onClose }) => {
|
||||
const { setComparePopUp } = useCompareStore();
|
||||
|
||||
OuterClick({
|
||||
contextClassName: ["compare-wrapper", "input"],
|
||||
setMenuVisible: () => setComparePopUp(false),
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="compare-container">
|
||||
<div className="compare-wrapper">
|
||||
<div className="grid-wrapper">
|
||||
<div className="header">
|
||||
Do you want to save this version before comparing?
|
||||
</div>
|
||||
|
||||
<div className="cards-container">
|
||||
<div className="card"></div>
|
||||
<div className="card"></div>
|
||||
|
||||
<div className="card-layout-wrapper">
|
||||
<div className="card-layout-container">
|
||||
<div className="tab-header">
|
||||
<div className="label-tab">Layout !</div>
|
||||
<div className="status"></div>
|
||||
</div>
|
||||
<div className="icon">
|
||||
<SaveDiskIcon />
|
||||
</div>
|
||||
<div className="skeleton-wrapper">
|
||||
<div className="skeleton"></div>
|
||||
<div className="skeleton"></div>
|
||||
<div className="skeleton"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="card"></div>
|
||||
<div className="card"></div>
|
||||
</div>
|
||||
|
||||
<div className="button-wrapper">
|
||||
<div className="button-group">
|
||||
<button className="save btn" onClick={onClose}>
|
||||
Save & Continue
|
||||
</button>
|
||||
<div className="replace btn">Replace Existing Version</div>
|
||||
</div>
|
||||
<button
|
||||
className="cancel btn"
|
||||
id="compare-cancel-btn"
|
||||
onClick={() => setComparePopUp(false)}
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="footer">
|
||||
<InfoIcon /> Save this version and proceed.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ComparePopUp;
|
||||
179
app/src/components/ui/compareVersion/CompareLayOut.tsx
Normal file
179
app/src/components/ui/compareVersion/CompareLayOut.tsx
Normal file
@@ -0,0 +1,179 @@
|
||||
import React, { useState, useRef, useEffect } from "react";
|
||||
import {
|
||||
CompareLayoutIcon,
|
||||
LayoutIcon,
|
||||
ResizerIcon,
|
||||
} from "../../icons/SimulationIcons";
|
||||
import { useSaveVersion } from "../../../store/builder/store";
|
||||
import Search from "../inputs/Search";
|
||||
import OuterClick from "../../../utils/outerClick";
|
||||
import RegularDropDown from "../inputs/RegularDropDown";
|
||||
|
||||
interface Layout {
|
||||
id: number;
|
||||
name: string;
|
||||
}
|
||||
interface CompareLayoutProps {
|
||||
dummyLayouts: Layout[];
|
||||
}
|
||||
|
||||
const CompareLayOut: React.FC<CompareLayoutProps> = ({ dummyLayouts }) => {
|
||||
const [width, setWidth] = useState("50vw");
|
||||
const [isResizing, setIsResizing] = useState(false);
|
||||
const [showLayoutDropdown, setShowLayoutDropdown] = useState(false);
|
||||
const [selectedLayout, setSelectedLayout] = useState<string | null>(null); // Track selected layout
|
||||
const wrapperRef = useRef<HTMLDivElement>(null);
|
||||
const startWidthRef = useRef<number>(0);
|
||||
const startXRef = useRef<number>(0);
|
||||
const { setIsVersionSaved } = useSaveVersion();
|
||||
|
||||
OuterClick({
|
||||
contextClassName: ["displayLayouts-container", "selectLayout"],
|
||||
setMenuVisible: () => setShowLayoutDropdown(false),
|
||||
});
|
||||
|
||||
const handleStartResizing = (e: React.MouseEvent) => {
|
||||
e.preventDefault();
|
||||
setIsResizing(true);
|
||||
startXRef.current = e.clientX;
|
||||
if (wrapperRef.current) {
|
||||
startWidthRef.current = wrapperRef.current.getBoundingClientRect().width;
|
||||
}
|
||||
};
|
||||
|
||||
const handleMouseMove = (e: MouseEvent) => {
|
||||
if (!isResizing || !wrapperRef.current) return;
|
||||
|
||||
const dx = startXRef.current - e.clientX;
|
||||
const newWidthPx = startWidthRef.current + dx;
|
||||
const viewportWidth = window.innerWidth;
|
||||
const newWidthVw = (newWidthPx / viewportWidth) * 100;
|
||||
|
||||
if (newWidthVw <= 10) {
|
||||
setWidth("0px");
|
||||
} else if (newWidthVw <= 90) {
|
||||
setWidth(`${newWidthPx}px`);
|
||||
}
|
||||
};
|
||||
|
||||
const handleMouseUp = () => {
|
||||
if (!isResizing) return;
|
||||
|
||||
if (wrapperRef.current) {
|
||||
const finalWidthPx = wrapperRef.current.getBoundingClientRect().width;
|
||||
const viewportWidth = window.innerWidth;
|
||||
const finalWidthVw = (finalWidthPx / viewportWidth) * 100;
|
||||
|
||||
if (finalWidthVw <= 10) {
|
||||
setWidth("0px");
|
||||
setIsVersionSaved(false);
|
||||
} else {
|
||||
setWidth(`${finalWidthVw}vw`);
|
||||
}
|
||||
}
|
||||
|
||||
setIsResizing(false);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (isResizing) {
|
||||
window.addEventListener("mousemove", handleMouseMove);
|
||||
window.addEventListener("mouseup", handleMouseUp);
|
||||
document.body.classList.add("resizing-active");
|
||||
}
|
||||
|
||||
return () => {
|
||||
window.removeEventListener("mousemove", handleMouseMove);
|
||||
window.removeEventListener("mouseup", handleMouseUp);
|
||||
document.body.classList.remove("resizing-active");
|
||||
};
|
||||
}, [isResizing]);
|
||||
|
||||
// Maintain proportional width on window resize
|
||||
useEffect(() => {
|
||||
const handleResize = () => {
|
||||
if (!wrapperRef.current || isResizing) return;
|
||||
|
||||
const currentWidth = wrapperRef.current.style.width;
|
||||
if (currentWidth === "0px" || currentWidth.endsWith("vw")) return;
|
||||
|
||||
const pxWidth = parseFloat(currentWidth);
|
||||
const vwWidth = (pxWidth / window.innerWidth) * 100;
|
||||
setWidth(`${vwWidth}vw`);
|
||||
};
|
||||
|
||||
window.addEventListener("resize", handleResize);
|
||||
return () => window.removeEventListener("resize", handleResize);
|
||||
}, [isResizing]);
|
||||
|
||||
const handleSelectLayout = (option: string) => {
|
||||
setSelectedLayout(option); // Set selected layout
|
||||
console.log("Selected layout:", option);
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`compareLayOut-wrapper ${width === "0px" ? "closed" : ""}`}
|
||||
ref={wrapperRef}
|
||||
style={{ width }}
|
||||
>
|
||||
<div className="chooseLayout-container">
|
||||
<div className="resizer" onMouseDown={handleStartResizing}>
|
||||
<ResizerIcon />
|
||||
</div>
|
||||
|
||||
{width !== "0px" &&
|
||||
!selectedLayout && ( // Show only if no layout selected
|
||||
<div className="chooseLayout-wrapper">
|
||||
<div className="icon">
|
||||
<CompareLayoutIcon />
|
||||
</div>
|
||||
<div className="value">Choose Layout to compare</div>
|
||||
<button
|
||||
className="selectLayout"
|
||||
onClick={() => setShowLayoutDropdown(!showLayoutDropdown)}
|
||||
>
|
||||
Select Layout
|
||||
</button>
|
||||
|
||||
{showLayoutDropdown && (
|
||||
<div className="displayLayouts-container">
|
||||
<div className="header">Layouts</div>
|
||||
<Search onChange={() => {}} />
|
||||
<div className="layouts-container">
|
||||
{dummyLayouts.map((layout) => (
|
||||
<button
|
||||
key={layout.id}
|
||||
className="layout-wrapper"
|
||||
onClick={() => {
|
||||
handleSelectLayout(layout.name);
|
||||
setShowLayoutDropdown(false);
|
||||
}}
|
||||
>
|
||||
<LayoutIcon />
|
||||
<div className="layout">{layout.name}</div>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Always show after layout is selected */}
|
||||
{width !== "0px" && selectedLayout && (
|
||||
<div className="selectLayout-wrapper">
|
||||
<RegularDropDown
|
||||
header={selectedLayout}
|
||||
options={dummyLayouts.map((l) => l.name)} // Pass layout names as options
|
||||
onSelect={handleSelectLayout}
|
||||
search={false}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default CompareLayOut;
|
||||
Reference in New Issue
Block a user