Merge branch 'v2-ui' of http://185.100.212.76:7776/Dwinzo-Beta/Dwinzo_dev into v2-ui
This commit is contained in:
commit
83f9c660b1
|
@ -18,6 +18,7 @@ import safety from "../../../assets/image/categories/safety.png";
|
||||||
import feneration from "../../../assets/image/categories/feneration.png";
|
import feneration from "../../../assets/image/categories/feneration.png";
|
||||||
import archThumbnail from "../../../assets/image/localAssets/arch.png";
|
import archThumbnail from "../../../assets/image/localAssets/arch.png";
|
||||||
import windowThumbnail from "../../../assets/image/localAssets/window.png";
|
import windowThumbnail from "../../../assets/image/localAssets/window.png";
|
||||||
|
import SkeletonUI from "../../templates/SkeletonUI";
|
||||||
// -------------------------------------
|
// -------------------------------------
|
||||||
|
|
||||||
interface AssetProp {
|
interface AssetProp {
|
||||||
|
@ -46,6 +47,7 @@ const Assets: React.FC = () => {
|
||||||
const [categoryAssets, setCategoryAssets] = useState<AssetProp[]>([]);
|
const [categoryAssets, setCategoryAssets] = useState<AssetProp[]>([]);
|
||||||
const [filtereredAssets, setFiltereredAssets] = useState<AssetProp[]>([]);
|
const [filtereredAssets, setFiltereredAssets] = useState<AssetProp[]>([]);
|
||||||
const [categoryList, setCategoryList] = useState<CategoryListProp[]>([]);
|
const [categoryList, setCategoryList] = useState<CategoryListProp[]>([]);
|
||||||
|
const [isLoading, setisLoading] = useState<boolean>(false); // Loading state for assets
|
||||||
|
|
||||||
const handleSearchChange = (value: string) => {
|
const handleSearchChange = (value: string) => {
|
||||||
const searchTerm = value.toLowerCase();
|
const searchTerm = value.toLowerCase();
|
||||||
|
@ -73,6 +75,7 @@ const Assets: React.FC = () => {
|
||||||
|
|
||||||
setCategoryAssets(filteredModels);
|
setCategoryAssets(filteredModels);
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const filteredAssets = async () => {
|
const filteredAssets = async () => {
|
||||||
try {
|
try {
|
||||||
|
@ -112,7 +115,9 @@ const Assets: React.FC = () => {
|
||||||
{ category: "Office", categoryImage: office },
|
{ category: "Office", categoryImage: office },
|
||||||
]);
|
]);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const fetchCategoryAssets = async (asset: any) => {
|
const fetchCategoryAssets = async (asset: any) => {
|
||||||
|
setisLoading(true);
|
||||||
setSelectedCategory(asset);
|
setSelectedCategory(asset);
|
||||||
if (asset === "Feneration") {
|
if (asset === "Feneration") {
|
||||||
const localAssets: AssetProp[] = [
|
const localAssets: AssetProp[] = [
|
||||||
|
@ -140,13 +145,15 @@ const Assets: React.FC = () => {
|
||||||
];
|
];
|
||||||
setCategoryAssets(localAssets);
|
setCategoryAssets(localAssets);
|
||||||
setFiltereredAssets(localAssets);
|
setFiltereredAssets(localAssets);
|
||||||
|
setisLoading(false);
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
const res = await getCategoryAsset(asset);
|
const res = await getCategoryAsset(asset);
|
||||||
setCategoryAssets(res);
|
setCategoryAssets(res);
|
||||||
setFiltereredAssets(res);
|
setFiltereredAssets(res);
|
||||||
|
setisLoading(false); // End loading
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
setisLoading(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -155,7 +162,9 @@ const Assets: React.FC = () => {
|
||||||
<Search onChange={handleSearchChange} />
|
<Search onChange={handleSearchChange} />
|
||||||
<div className="assets-list-section">
|
<div className="assets-list-section">
|
||||||
<section>
|
<section>
|
||||||
{searchValue ? (
|
{isLoading ? (
|
||||||
|
<SkeletonUI type="asset" /> // Show skeleton when loading
|
||||||
|
) : searchValue ? (
|
||||||
<div className="assets-result">
|
<div className="assets-result">
|
||||||
<div className="assets-wrapper">
|
<div className="assets-wrapper">
|
||||||
<div className="searched-content">
|
<div className="searched-content">
|
||||||
|
|
|
@ -31,10 +31,10 @@ const SideBarLeft: React.FC = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="sidebar-left-wrapper">
|
<div className={`sidebar-left-wrapper ${toggleUI ? "open" : "closed"}`}>
|
||||||
<Header />
|
<Header />
|
||||||
{toggleUI && (
|
{toggleUI && (
|
||||||
<div className="sidebar-left-container">
|
<div className={`sidebar-left-container `}>
|
||||||
{activeModule === "visualization" ? (
|
{activeModule === "visualization" ? (
|
||||||
<>
|
<>
|
||||||
<ToggleHeader
|
<ToggleHeader
|
||||||
|
@ -79,3 +79,5 @@ const SideBarLeft: React.FC = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
export default SideBarLeft;
|
export default SideBarLeft;
|
||||||
|
|
||||||
|
// sidebar-left-container opemn close sidebar-left-container smoothly
|
||||||
|
|
|
@ -55,7 +55,7 @@ const SideBarRight: React.FC = () => {
|
||||||
}, [activeModule, selectedEventData, selectedEventSphere, setSubModule]);
|
}, [activeModule, selectedEventData, selectedEventSphere, setSubModule]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="sidebar-right-wrapper">
|
<div className={`sidebar-right-wrapper ${toggleUI ? "open" : "closed"}`}>
|
||||||
<Header />
|
<Header />
|
||||||
{toggleUI && (
|
{toggleUI && (
|
||||||
<div className="sidebar-actions-container">
|
<div className="sidebar-actions-container">
|
||||||
|
|
|
@ -1,21 +1,70 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
|
// Define the prop types
|
||||||
|
interface SkeletonUIProps {
|
||||||
|
type: "asset" | "assetLibrary" | "assetWidget" | "default"; // You can expand this with other types as needed
|
||||||
|
}
|
||||||
|
|
||||||
const SkeletonUI = () => {
|
// Define the SkeletonUI component
|
||||||
return (
|
const SkeletonUI: React.FC<SkeletonUIProps> = ({ type }) => {
|
||||||
<div className="skeleton-wrapper">
|
console.log("type: ", type);
|
||||||
<div className="skeleton-header">
|
|
||||||
<div className="skeleton skeleton-title"></div>
|
|
||||||
<div className="skeleton skeleton-subtitle"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="skeleton-content">
|
// Function to render skeleton content based on 'type'
|
||||||
<div className="skeleton skeleton-card"></div>
|
const renderSkeleton = () => {
|
||||||
<div className="skeleton skeleton-card"></div>
|
switch (type) {
|
||||||
</div>
|
case "assetLibrary":
|
||||||
|
return (
|
||||||
</div>
|
<>
|
||||||
);
|
{Array(5)
|
||||||
|
.fill(null) // Create an array of 5 empty items
|
||||||
|
.map((_, index) => (
|
||||||
|
<div key={index} className="skeleton-content">
|
||||||
|
<div className="skeleton asset-image"></div>
|
||||||
|
<div className="skeleton asset-details"></div>
|
||||||
|
<div className="skeleton organization"></div>
|
||||||
|
<div className="skeleton asset-review"></div>
|
||||||
|
<div className="skeleton button"></div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
|
||||||
|
case "assetWidget":
|
||||||
|
return (
|
||||||
|
<div className="skeleton-content">
|
||||||
|
<div className="skeleton skeleton-widget"></div>
|
||||||
|
<div className="skeleton skeleton-widget"></div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
case "asset":
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className="skeleton-content">
|
||||||
|
<div className="skeleton asset-name"></div>
|
||||||
|
<div className="skeleton asset"></div>
|
||||||
|
</div>
|
||||||
|
<div className="skeleton-content">
|
||||||
|
<div className="skeleton asset-name"></div>
|
||||||
|
<div className="skeleton asset"></div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
|
||||||
|
default:
|
||||||
|
return (
|
||||||
|
<div className="skeleton-content">
|
||||||
|
<div className="skeleton-header">
|
||||||
|
<div className="skeleton skeleton-title"></div>
|
||||||
|
<div className="skeleton skeleton-subtitle"></div>
|
||||||
|
</div>
|
||||||
|
<div className="skeleton skeleton-card"></div>
|
||||||
|
<div className="skeleton skeleton-card"></div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return <div className="skeleton-wrapper">{renderSkeleton()}</div>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default SkeletonUI;
|
export default SkeletonUI;
|
||||||
|
|
|
@ -73,7 +73,7 @@ const ThroughputSummary = () => {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const isLoading = true;
|
const isLoading = false;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="production analysis-card">
|
<div className="production analysis-card">
|
||||||
|
@ -90,7 +90,7 @@ const ThroughputSummary = () => {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{isLoading ? (
|
{!isLoading ? (
|
||||||
<>
|
<>
|
||||||
<div className="process-container">
|
<div className="process-container">
|
||||||
<div className="throughput-value">
|
<div className="throughput-value">
|
||||||
|
@ -157,7 +157,7 @@ const ThroughputSummary = () => {
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<SkeletonUI />
|
<SkeletonUI type={"default"} />
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -8,56 +8,58 @@ import {
|
||||||
} from "../../icons/analysis";
|
} from "../../icons/analysis";
|
||||||
import SemiCircleProgress from "./SemiCircleProgress";
|
import SemiCircleProgress from "./SemiCircleProgress";
|
||||||
import { ArrowIcon } from "../../icons/ExportCommonIcons";
|
import { ArrowIcon } from "../../icons/ExportCommonIcons";
|
||||||
|
import SkeletonUI from "../../templates/SkeletonUI";
|
||||||
|
|
||||||
const ROISummary = ({
|
const ROISummary = ({
|
||||||
roiSummaryData = {
|
roiSummaryData = {
|
||||||
productName: "Product name",
|
productName: "Product name",
|
||||||
roiPercentage: 133,
|
roiPercentage: 133,
|
||||||
paybackPeriod: 50.3,
|
paybackPeriod: 50.3,
|
||||||
totalCost: "₹ 1,20,000",
|
totalCost: "1,20,000",
|
||||||
revenueGenerated: "₹ 2,80,000",
|
revenueGenerated: "2,80,000",
|
||||||
netProfit: "₹ 1,60,000",
|
netProfit: "1,60,000",
|
||||||
|
netLoss: null,
|
||||||
costBreakdown: [
|
costBreakdown: [
|
||||||
{
|
{
|
||||||
item: "Raw Material A",
|
item: "Raw Material A",
|
||||||
unitCost: "₹ 10/unit",
|
unitCost: "10/unit",
|
||||||
laborCost: "₹ 0",
|
laborCost: "0",
|
||||||
totalCost: "₹ 1000",
|
totalCost: "1000",
|
||||||
sellingPrice: "₹ 1500",
|
sellingPrice: "1500",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
item: "Labor",
|
item: "Labor",
|
||||||
unitCost: "₹ 10/unit",
|
unitCost: "10/unit",
|
||||||
laborCost: "₹ 500",
|
laborCost: "500",
|
||||||
totalCost: "₹ 500",
|
totalCost: "500",
|
||||||
sellingPrice: "N/A",
|
sellingPrice: "N/A",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
item: "Product 1",
|
item: "Product 1",
|
||||||
unitCost: "₹ 10/unit",
|
unitCost: "10/unit",
|
||||||
laborCost: "₹ 200",
|
laborCost: "200",
|
||||||
totalCost: "₹ 200",
|
totalCost: "200",
|
||||||
sellingPrice: "₹ 2000",
|
sellingPrice: "2000",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
item: "Machine",
|
item: "Machine",
|
||||||
unitCost: "-",
|
unitCost: "-",
|
||||||
laborCost: "-",
|
laborCost: "-",
|
||||||
totalCost: "₹ 20,000",
|
totalCost: "20,000",
|
||||||
sellingPrice: "N/A",
|
sellingPrice: "N/A",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
item: "Total",
|
item: "Total",
|
||||||
unitCost: "-",
|
unitCost: "-",
|
||||||
laborCost: "-",
|
laborCost: "-",
|
||||||
totalCost: "₹ 1,20,000",
|
totalCost: "1,20,000",
|
||||||
sellingPrice: "-",
|
sellingPrice: "-",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
item: "Net Profit",
|
item: "Net Profit",
|
||||||
unitCost: "-",
|
unitCost: "-",
|
||||||
laborCost: "-",
|
laborCost: "-",
|
||||||
totalCost: "₹ 1,60,000",
|
totalCost: "1,60,000",
|
||||||
sellingPrice: "-",
|
sellingPrice: "-",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -70,6 +72,7 @@ const ROISummary = ({
|
||||||
setIsTableOpen(!isTableOpen);
|
setIsTableOpen(!isTableOpen);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const isLoading = false;
|
||||||
return (
|
return (
|
||||||
<div className="roiSummary-container analysis-card">
|
<div className="roiSummary-container analysis-card">
|
||||||
<div className="roiSummary-wrapper analysis-card-wrapper">
|
<div className="roiSummary-wrapper analysis-card-wrapper">
|
||||||
|
@ -82,121 +85,140 @@ const ROISummary = ({
|
||||||
<ROISummaryIcon />
|
<ROISummaryIcon />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="product-info">
|
{!isLoading ? (
|
||||||
<ROISummaryProductName />
|
<>
|
||||||
<div className="product-label">Product :</div>
|
<div className="product-info">
|
||||||
<div className="product-name">{roiSummaryData.productName}</div>
|
<ROISummaryProductName />
|
||||||
</div>
|
<div className="product-label">Product :</div>
|
||||||
<div className="playBack">
|
<div className="product-name">{roiSummaryData.productName}</div>
|
||||||
<SonarCrownIcon />
|
|
||||||
<div className="icon"></div>
|
|
||||||
<div className="info">
|
|
||||||
<span>+{roiSummaryData.roiPercentage}%</span> ROI with payback in
|
|
||||||
just <span>{roiSummaryData.paybackPeriod}</span> months
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="roi-details">
|
|
||||||
<div className="progress-wrapper">
|
|
||||||
<SemiCircleProgress />
|
|
||||||
<div className="content">
|
|
||||||
you're on track to hit it by
|
|
||||||
<div className="key">July 2029</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div className="playBack">
|
||||||
<div className="metrics">
|
<SonarCrownIcon />
|
||||||
<div className="metric-wrapper">
|
<div className="icon"></div>
|
||||||
<div className="metric-item">
|
<div className="info">
|
||||||
<span className="metric-label">Total Cost Incurred</span>
|
<span>+{roiSummaryData.roiPercentage}%</span> ROI with payback
|
||||||
<span className="metric-value">{roiSummaryData.totalCost}</span>
|
in just <span>{roiSummaryData.paybackPeriod}</span> months
|
||||||
</div>
|
</div>
|
||||||
<div className="metric-item">
|
</div>
|
||||||
<span className="metric-label">Revenue Generated</span>
|
<div className="roi-details">
|
||||||
<span className="metric-value">
|
<div className="progress-wrapper">
|
||||||
{roiSummaryData.revenueGenerated}
|
<SemiCircleProgress />
|
||||||
|
<div className="content">
|
||||||
|
you're on track to hit it by
|
||||||
|
<div className="key">July 2029</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="metrics">
|
||||||
|
<div className="metric-wrapper">
|
||||||
|
<div className="metric-item">
|
||||||
|
<span className="metric-label">Total Cost Incurred</span>
|
||||||
|
<span className="metric-value">
|
||||||
|
<span>₹</span>
|
||||||
|
{roiSummaryData.totalCost}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div className="metric-item">
|
||||||
|
<span className="metric-label">Revenue Generated</span>
|
||||||
|
<span className="metric-value">
|
||||||
|
<span>₹</span>
|
||||||
|
|
||||||
|
{roiSummaryData.revenueGenerated}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className={`metric-item net-profit ${
|
||||||
|
roiSummaryData.netLoss ?? "loss"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
<div className="metric-label">
|
||||||
|
<span>↑</span>
|
||||||
|
Net Profit
|
||||||
|
</div>
|
||||||
|
<div className="metric-value">
|
||||||
|
<span>₹</span>
|
||||||
|
{roiSummaryData.netProfit}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="cost-breakdown">
|
||||||
|
<div className="breakdown-header" onClick={toggleTable}>
|
||||||
|
<div className="section-wrapper">
|
||||||
|
<CostBreakDownIcon />
|
||||||
|
<span className="section-title">Cost Breakdown</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<span className={`expand-icon ${isTableOpen ? "open" : ""}`}>
|
||||||
|
<ArrowIcon />
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
<div
|
||||||
|
className={`breakdown-table-wrapper ${
|
||||||
|
isTableOpen ? "open" : "closed"
|
||||||
|
}`}
|
||||||
|
style={{
|
||||||
|
transition: "max-height 0.3s ease-in-out",
|
||||||
|
overflow: "hidden",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<table className="breakdown-table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Item</th>
|
||||||
|
<th>Unit Cost</th>
|
||||||
|
<th>Labor Cost</th>
|
||||||
|
<th>Total Cost</th>
|
||||||
|
<th>Selling Price</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{roiSummaryData.costBreakdown.map((row, index) => (
|
||||||
|
<tr
|
||||||
|
key={index}
|
||||||
|
className={
|
||||||
|
row.item === "Total"
|
||||||
|
? "total-row"
|
||||||
|
: row.item === "Net Profit"
|
||||||
|
? "net-profit-row"
|
||||||
|
: ""
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<td>{row.item}</td>
|
||||||
|
<td>{row.unitCost}</td>
|
||||||
|
<td>{row.laborCost}</td>
|
||||||
|
<td>{row.totalCost}</td>
|
||||||
|
<td>{row.sellingPrice}</td>
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="metric-item net-profit">
|
<div className="tips-section">
|
||||||
<span className="metric-label">
|
<div className="tip-header">
|
||||||
<span>↑</span> Net Profit
|
<span className="lightbulb-icon">
|
||||||
</span>
|
<LightBulpIcon />
|
||||||
<span className="metric-value">{roiSummaryData.netProfit}</span>
|
</span>
|
||||||
|
<span className="tip-title">How to improve ROI?</span>
|
||||||
|
</div>
|
||||||
|
<div className="tip-description">
|
||||||
|
Increase CNC utilization by{" "}
|
||||||
|
<span className="highlight">10%</span> to shave{" "}
|
||||||
|
<span className="highlight">0.5</span> months of payback period
|
||||||
|
<div className="placeHolder-wrapper">
|
||||||
|
<div className="placeHolder"></div>
|
||||||
|
<div className="placeHolder"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<button className="get-tips-button">
|
||||||
|
<div className="btn">Get ROI Boost Tips</div>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</>
|
||||||
</div>
|
) : (
|
||||||
<div className="cost-breakdown">
|
<SkeletonUI type={"default"} />
|
||||||
<div className="breakdown-header" onClick={toggleTable}>
|
)}
|
||||||
<div className="section-wrapper">
|
|
||||||
<CostBreakDownIcon />
|
|
||||||
<span className="section-title">Cost Breakdown</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<span className={`expand-icon ${isTableOpen ? "open" : ""}`}>
|
|
||||||
<ArrowIcon />
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className={`breakdown-table-wrapper ${
|
|
||||||
isTableOpen ? "open" : "closed"
|
|
||||||
}`}
|
|
||||||
style={{
|
|
||||||
transition: "max-height 0.3s ease-in-out",
|
|
||||||
overflow: "hidden",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<table className="breakdown-table">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Item</th>
|
|
||||||
<th>Unit Cost</th>
|
|
||||||
<th>Labor Cost</th>
|
|
||||||
<th>Total Cost</th>
|
|
||||||
<th>Selling Price</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{roiSummaryData.costBreakdown.map((row, index) => (
|
|
||||||
<tr
|
|
||||||
key={index}
|
|
||||||
className={
|
|
||||||
row.item === "Total"
|
|
||||||
? "total-row"
|
|
||||||
: row.item === "Net Profit"
|
|
||||||
? "net-profit-row"
|
|
||||||
: ""
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<td>{row.item}</td>
|
|
||||||
<td>{row.unitCost}</td>
|
|
||||||
<td>{row.laborCost}</td>
|
|
||||||
<td>{row.totalCost}</td>
|
|
||||||
<td>{row.sellingPrice}</td>
|
|
||||||
</tr>
|
|
||||||
))}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="tips-section">
|
|
||||||
<div className="tip-header">
|
|
||||||
<span className="lightbulb-icon">
|
|
||||||
<LightBulpIcon />
|
|
||||||
</span>
|
|
||||||
<span className="tip-title">How to improve ROI?</span>
|
|
||||||
</div>
|
|
||||||
<div className="tip-description">
|
|
||||||
Increase CNC utilization by <span className="highlight">10%</span>{" "}
|
|
||||||
to shave <span className="highlight">0.5</span> months of payback
|
|
||||||
period
|
|
||||||
<div className="placeHolder-wrapper">
|
|
||||||
<div className="placeHolder"></div>
|
|
||||||
<div className="placeHolder"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<button className="get-tips-button">
|
|
||||||
<div className="btn">Get ROI Boost Tips</div>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -2,6 +2,7 @@ import {
|
||||||
ProductionCapacityIcon,
|
ProductionCapacityIcon,
|
||||||
ThroughputSummaryIcon,
|
ThroughputSummaryIcon,
|
||||||
} from "../../icons/analysis";
|
} from "../../icons/analysis";
|
||||||
|
import SkeletonUI from "../../templates/SkeletonUI";
|
||||||
|
|
||||||
const ProductionCapacity = ({
|
const ProductionCapacity = ({
|
||||||
progressPercent = 50,
|
progressPercent = 50,
|
||||||
|
@ -15,6 +16,7 @@ const ProductionCapacity = ({
|
||||||
const partialFillPercent =
|
const partialFillPercent =
|
||||||
((progressPercent / 100) * totalBars - barsToFill) * 100;
|
((progressPercent / 100) * totalBars - barsToFill) * 100;
|
||||||
|
|
||||||
|
const isLoading = false;
|
||||||
return (
|
return (
|
||||||
<div className="throughtputSummary-container analysis-card">
|
<div className="throughtputSummary-container analysis-card">
|
||||||
<div className="throughtputSummary-wrapper analysis-card-wrapper">
|
<div className="throughtputSummary-wrapper analysis-card-wrapper">
|
||||||
|
@ -29,39 +31,44 @@ const ProductionCapacity = ({
|
||||||
<ThroughputSummaryIcon />
|
<ThroughputSummaryIcon />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{isLoading ? (
|
||||||
<div className="process-container">
|
<>
|
||||||
<div className="throughput-value">
|
<div className="process-container">
|
||||||
<span className="value">{throughputValue}</span> Units/hour
|
<div className="throughput-value">
|
||||||
</div>
|
<span className="value">{throughputValue}</span> Units/hour
|
||||||
|
|
||||||
{/* Dynamic Progress Bar */}
|
|
||||||
<div className="progress-bar-wrapper">
|
|
||||||
{[...Array(totalBars)].map((_, i) => (
|
|
||||||
<div className="progress-bar" key={i}>
|
|
||||||
{i < barsToFill ? (
|
|
||||||
<div className="bar-fill full" />
|
|
||||||
) : i === barsToFill ? (
|
|
||||||
<div
|
|
||||||
className="bar-fill partial"
|
|
||||||
style={{ width: `${partialFillPercent}%` }}
|
|
||||||
/>
|
|
||||||
) : null}
|
|
||||||
</div>
|
</div>
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="metrics-section">
|
{/* Dynamic Progress Bar */}
|
||||||
<div className="metric">
|
<div className="progress-bar-wrapper">
|
||||||
<span className="label">Avg. Process Time</span>
|
{[...Array(totalBars)].map((_, i) => (
|
||||||
<span className="value">{avgProcessTime}</span>
|
<div className="progress-bar" key={i}>
|
||||||
</div>
|
{i < barsToFill ? (
|
||||||
<div className="metric">
|
<div className="bar-fill full" />
|
||||||
<span className="label">Machine Utilization</span>
|
) : i === barsToFill ? (
|
||||||
<span className="value">{machineUtilization}</span>
|
<div
|
||||||
</div>
|
className="bar-fill partial"
|
||||||
</div>
|
style={{ width: `${partialFillPercent}%` }}
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="metrics-section">
|
||||||
|
<div className="metric">
|
||||||
|
<span className="label">Avg. Process Time</span>
|
||||||
|
<span className="value">{avgProcessTime}</span>
|
||||||
|
</div>
|
||||||
|
<div className="metric">
|
||||||
|
<span className="label">Machine Utilization</span>
|
||||||
|
<span className="value">{machineUtilization}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<SkeletonUI type={"default"} />
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import React, { createContext, useContext, useState, useCallback, useMemo } from "react";
|
// LoggerProvider.tsx
|
||||||
|
import React, { createContext, useContext, useState, useCallback, useMemo, useEffect } from "react";
|
||||||
import { MathUtils } from "three";
|
import { MathUtils } from "three";
|
||||||
|
|
||||||
export type LogType = "log" | "info" | "warning" | "error" | "success";
|
export type LogType = "log" | "info" | "warning" | "error" | "success";
|
||||||
|
@ -60,6 +61,18 @@ export const LoggerProvider: React.FC<{ children: React.ReactNode }> = ({
|
||||||
[logs, setLogs, isLogListVisible, setIsLogListVisible, addLog]
|
[logs, setLogs, isLogListVisible, setIsLogListVisible, addLog]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Attach logger globally to window object
|
||||||
|
useEffect(() => {
|
||||||
|
(window as any).echo = {
|
||||||
|
log: loggerMethods.log,
|
||||||
|
info: loggerMethods.info,
|
||||||
|
warn: loggerMethods.warn,
|
||||||
|
error: loggerMethods.error,
|
||||||
|
success: loggerMethods.success,
|
||||||
|
clear: loggerMethods.clear,
|
||||||
|
};
|
||||||
|
}, [loggerMethods]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<LoggerContext.Provider value={loggerMethods}>
|
<LoggerContext.Provider value={loggerMethods}>
|
||||||
{children}
|
{children}
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
// import RegularDropDown from "./ui/inputs/RegularDropDown";
|
|
||||||
|
|
||||||
import Search from "../../components/ui/inputs/Search";
|
import Search from "../../components/ui/inputs/Search";
|
||||||
import { StarsIcon } from "../../components/icons/marketPlaceIcons";
|
import { StarsIcon } from "../../components/icons/marketPlaceIcons";
|
||||||
import RegularDropDown from "../../components/ui/inputs/RegularDropDown";
|
import RegularDropDown from "../../components/ui/inputs/RegularDropDown";
|
||||||
import { getSortedAssets } from "../../services/marketplace/getSortedAssets";
|
|
||||||
interface ModelData {
|
interface ModelData {
|
||||||
CreatedBy: string;
|
CreatedBy: string;
|
||||||
animated: string | null;
|
animated: string | null;
|
||||||
|
@ -19,47 +17,46 @@ interface ModelData {
|
||||||
_id: string;
|
_id: string;
|
||||||
price: number;
|
price: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ModelsProps {
|
interface ModelsProps {
|
||||||
models: ModelData[];
|
models: ModelData[];
|
||||||
setModels: React.Dispatch<React.SetStateAction<ModelData[]>>;
|
setModels: React.Dispatch<React.SetStateAction<ModelData[]>>;
|
||||||
filteredModels: ModelData[];
|
filteredModels: ModelData[];
|
||||||
}
|
}
|
||||||
|
|
||||||
const FilterSearch: React.FC<ModelsProps> = ({
|
const FilterSearch: React.FC<ModelsProps> = ({
|
||||||
models,
|
models,
|
||||||
setModels,
|
setModels,
|
||||||
filteredModels,
|
filteredModels,
|
||||||
}) => {
|
}) => {
|
||||||
const [activeOption, setActiveOption] = useState("Sort by"); // State for active option
|
const [activeOption, setActiveOption] = useState("Sort by");
|
||||||
|
const [rating, setRating] = useState(0);
|
||||||
|
|
||||||
const handleSelect = (option: string) => {
|
const handleSelect = (option: string) => {
|
||||||
setActiveOption(option);
|
setActiveOption(option);
|
||||||
|
|
||||||
// Alphabet ascending
|
|
||||||
// Alphabet descending
|
|
||||||
// All
|
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (activeOption == "Alphabet ascending") {
|
if (activeOption === "Alphabet ascending") {
|
||||||
let ascending = models
|
const ascending = [...models].sort((a, b) => a.filename.localeCompare(b.filename));
|
||||||
?.slice()
|
|
||||||
.sort((a, b) => a.filename.localeCompare(b.filename))
|
|
||||||
.map((val) => val);
|
|
||||||
setModels(ascending);
|
setModels(ascending);
|
||||||
} else if (activeOption == "Alphabet descending") {
|
} else if (activeOption === "Alphabet descending") {
|
||||||
let descending = models
|
const descending = [...models].sort((a, b) => b.filename.localeCompare(a.filename));
|
||||||
?.slice()
|
|
||||||
.sort((a, b) => b.filename.localeCompare(a.filename))
|
|
||||||
.map((val) => val);
|
|
||||||
setModels(descending);
|
setModels(descending);
|
||||||
}
|
}
|
||||||
}, [activeOption]);
|
}, [activeOption]);
|
||||||
|
|
||||||
const handleSearch = (val: string) => {
|
const handleSearch = (val: string) => {
|
||||||
const filteredModel = filteredModels?.filter((model) =>
|
const filteredModel = filteredModels.filter((model) =>
|
||||||
model.filename.toLowerCase().includes(val.toLowerCase())
|
model.filename.toLowerCase().includes(val.toLowerCase())
|
||||||
);
|
);
|
||||||
setModels(filteredModel);
|
setModels(filteredModel);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleStarClick = (index: number) => {
|
||||||
|
setRating(index + 1);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="filter-search-container">
|
<div className="filter-search-container">
|
||||||
<Search onChange={handleSearch} />
|
<Search onChange={handleSearch} />
|
||||||
|
@ -71,14 +68,19 @@ const FilterSearch: React.FC<ModelsProps> = ({
|
||||||
/>
|
/>
|
||||||
<div className="button">Free</div>
|
<div className="button">Free</div>
|
||||||
<div className="button">Animated</div>
|
<div className="button">Animated</div>
|
||||||
|
|
||||||
<div className="rating-container">
|
<div className="rating-container">
|
||||||
<div className="label">Rating</div>
|
<div className="label">Rating</div>
|
||||||
<div className="stars">
|
<div className="stars">
|
||||||
<StarsIcon />
|
{[0, 1, 2, 3, 4].map((i) => (
|
||||||
<StarsIcon />
|
<div
|
||||||
<StarsIcon />
|
key={i}
|
||||||
<StarsIcon />
|
onClick={() => handleStarClick(i)}
|
||||||
<StarsIcon />
|
className={`star-wrapper ${i < rating ? "filled" : "empty"}`}
|
||||||
|
>
|
||||||
|
<StarsIcon />
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -3,6 +3,7 @@ import FilterSearch from "./FilterSearch";
|
||||||
import CardsContainer from "./CardsContainer";
|
import CardsContainer from "./CardsContainer";
|
||||||
import { fetchAssets } from "../../services/marketplace/fetchAssets";
|
import { fetchAssets } from "../../services/marketplace/fetchAssets";
|
||||||
import { getAssetImages } from "../../services/factoryBuilder/assest/assets/getAssetImages";
|
import { getAssetImages } from "../../services/factoryBuilder/assest/assets/getAssetImages";
|
||||||
|
import SkeletonUI from "../../components/templates/SkeletonUI";
|
||||||
interface ModelData {
|
interface ModelData {
|
||||||
CreatedBy: string;
|
CreatedBy: string;
|
||||||
animated: string | null;
|
animated: string | null;
|
||||||
|
@ -20,14 +21,19 @@ interface ModelData {
|
||||||
const MarketPlace = () => {
|
const MarketPlace = () => {
|
||||||
const [models, setModels] = useState<ModelData[]>([]);
|
const [models, setModels] = useState<ModelData[]>([]);
|
||||||
const [filteredModels, setFilteredModels] = useState<ModelData[]>([]);
|
const [filteredModels, setFilteredModels] = useState<ModelData[]>([]);
|
||||||
|
const [isLoading, setisLoading] = useState<boolean>(false); // Loading state
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const filteredAssets = async () => {
|
const filteredAssets = async () => {
|
||||||
|
setisLoading(true);
|
||||||
try {
|
try {
|
||||||
const filt = await getAssetImages("67d934ad0f42a1fdadb19aa6");
|
const filt = await getAssetImages("67d934ad0f42a1fdadb19aa6");
|
||||||
setModels(filt.items);
|
setModels(filt.items);
|
||||||
setFilteredModels(filt.items);
|
setFilteredModels(filt.items);
|
||||||
} catch {}
|
setisLoading(false);
|
||||||
|
} catch {
|
||||||
|
setisLoading(false);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
filteredAssets();
|
filteredAssets();
|
||||||
}, []);
|
}, []);
|
||||||
|
@ -36,12 +42,18 @@ const MarketPlace = () => {
|
||||||
<div className="marketplace-wrapper">
|
<div className="marketplace-wrapper">
|
||||||
<div className="marketplace-container">
|
<div className="marketplace-container">
|
||||||
<div className="marketPlace">
|
<div className="marketPlace">
|
||||||
<FilterSearch
|
{isLoading ? (
|
||||||
models={models}
|
<SkeletonUI type="assetLibrary" /> // Show loading spinner while fetching
|
||||||
setModels={setModels}
|
) : (
|
||||||
filteredModels={filteredModels}
|
<>
|
||||||
/>
|
<FilterSearch
|
||||||
<CardsContainer models={models} />
|
models={models}
|
||||||
|
setModels={setModels}
|
||||||
|
filteredModels={filteredModels}
|
||||||
|
/>
|
||||||
|
<CardsContainer models={models} />
|
||||||
|
</>
|
||||||
|
)}{" "}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -99,7 +99,7 @@ export const DraggableWidget = ({
|
||||||
const deleteSelectedChart = async () => {
|
const deleteSelectedChart = async () => {
|
||||||
try {
|
try {
|
||||||
console.log("delete");
|
console.log("delete");
|
||||||
|
|
||||||
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 deleteWidget = {
|
let deleteWidget = {
|
||||||
|
@ -109,9 +109,9 @@ export const DraggableWidget = ({
|
||||||
};
|
};
|
||||||
|
|
||||||
if (visualizationSocket) {
|
if (visualizationSocket) {
|
||||||
setSelectedChartId(null)
|
setSelectedChartId(null);
|
||||||
visualizationSocket.emit("v2:viz-widget:delete", deleteWidget);
|
visualizationSocket.emit("v2:viz-widget:delete", deleteWidget);
|
||||||
console.log("delete widget",selectedChartId);
|
console.log("delete widget", selectedChartId);
|
||||||
}
|
}
|
||||||
const updatedWidgets = selectedZone.widgets.filter(
|
const updatedWidgets = selectedZone.widgets.filter(
|
||||||
(w: Widget) => w.id !== widget.id
|
(w: Widget) => w.id !== widget.id
|
||||||
|
@ -176,7 +176,7 @@ export const DraggableWidget = ({
|
||||||
|
|
||||||
const duplicatedWidget: Widget = {
|
const duplicatedWidget: Widget = {
|
||||||
...widget,
|
...widget,
|
||||||
title: name === '' ? widget.title : name,
|
title: name === "" ? widget.title : name,
|
||||||
Data: {
|
Data: {
|
||||||
duration: duration,
|
duration: duration,
|
||||||
measurements: { ...measurements },
|
measurements: { ...measurements },
|
||||||
|
@ -189,7 +189,7 @@ export const DraggableWidget = ({
|
||||||
zoneId: selectedZone.zoneId,
|
zoneId: selectedZone.zoneId,
|
||||||
widget: duplicatedWidget,
|
widget: duplicatedWidget,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (visualizationSocket) {
|
if (visualizationSocket) {
|
||||||
visualizationSocket.emit("v2:viz-widget:add", duplicateWidget);
|
visualizationSocket.emit("v2:viz-widget:add", duplicateWidget);
|
||||||
}
|
}
|
||||||
|
@ -309,9 +309,9 @@ export const DraggableWidget = ({
|
||||||
: undefined,
|
: undefined,
|
||||||
}}
|
}}
|
||||||
ref={chartWidget}
|
ref={chartWidget}
|
||||||
onClick={() => {setSelectedChartId(widget)
|
onClick={() => {
|
||||||
console.log('click');
|
setSelectedChartId(widget);
|
||||||
|
console.log("click");
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{/* Kebab Icon */}
|
{/* Kebab Icon */}
|
||||||
|
@ -333,10 +333,13 @@ export const DraggableWidget = ({
|
||||||
</div>
|
</div>
|
||||||
<div className="label">Duplicate</div>
|
<div className="label">Duplicate</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="edit btn" onClick={(e)=>{
|
<div
|
||||||
e.stopPropagation()
|
className="edit btn"
|
||||||
deleteSelectedChart();
|
onClick={(e) => {
|
||||||
}}>
|
e.stopPropagation();
|
||||||
|
deleteSelectedChart();
|
||||||
|
}}
|
||||||
|
>
|
||||||
<div className="icon">
|
<div className="icon">
|
||||||
<DeleteIcon />
|
<DeleteIcon />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -86,7 +86,7 @@ const Project: React.FC = () => {
|
||||||
{!selectedUser && (
|
{!selectedUser && (
|
||||||
<>
|
<>
|
||||||
<KeyPressListener />
|
<KeyPressListener />
|
||||||
{loadingProgress > 0 && <LoadingPage progress={loadingProgress} />}
|
{/* {loadingProgress > 0 && <LoadingPage progress={loadingProgress} />} */}
|
||||||
{!isPlaying && (
|
{!isPlaying && (
|
||||||
<>
|
<>
|
||||||
{toggleThreeD && <ModuleToggle />}
|
{toggleThreeD && <ModuleToggle />}
|
||||||
|
@ -122,7 +122,7 @@ const Project: React.FC = () => {
|
||||||
}
|
}
|
||||||
onDragOver={(event) => event.preventDefault()}
|
onDragOver={(event) => event.preventDefault()}
|
||||||
>
|
>
|
||||||
<Scene />
|
{/* <Scene /> */}
|
||||||
</div>
|
</div>
|
||||||
{selectedUser && <FollowPerson />}
|
{selectedUser && <FollowPerson />}
|
||||||
{isLogListVisible && (
|
{isLogListVisible && (
|
||||||
|
@ -130,7 +130,7 @@ const Project: React.FC = () => {
|
||||||
<LogList />
|
<LogList />
|
||||||
</RenderOverlay>
|
</RenderOverlay>
|
||||||
)}
|
)}
|
||||||
<Footer />
|
{activeModule != "market" && <Footer />}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,6 +2,9 @@
|
||||||
@use "../../abstracts/mixins.scss" as *;
|
@use "../../abstracts/mixins.scss" as *;
|
||||||
|
|
||||||
.marketplace-wrapper {
|
.marketplace-wrapper {
|
||||||
|
// transform: scale(0.65);
|
||||||
|
/* Start at 90% width */
|
||||||
|
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
width: 100vw;
|
width: 100vw;
|
||||||
z-index: #{$z-index-marketplace};
|
z-index: #{$z-index-marketplace};
|
||||||
|
@ -11,6 +14,7 @@
|
||||||
top: 0;
|
top: 0;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
padding-top: 100px;
|
padding-top: 100px;
|
||||||
|
// animation: growWidth 0.4s ease-in-out 0.5s forwards;
|
||||||
|
|
||||||
.marketplace-container {
|
.marketplace-container {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
@ -31,6 +35,58 @@
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 24px;
|
gap: 24px;
|
||||||
|
|
||||||
|
.skeleton-wrapper {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 18px;
|
||||||
|
margin: 0;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
.skeleton-content {
|
||||||
|
|
||||||
|
|
||||||
|
width: calc(25% - 14px) !important;
|
||||||
|
height: auto !important;
|
||||||
|
border-radius: #{$border-radius-xlarge};
|
||||||
|
padding: 12px;
|
||||||
|
box-shadow: 0px 2px 10.5px 0px #0000000d;
|
||||||
|
background: var(--background-color-solid-gradient);
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 6px;
|
||||||
|
|
||||||
|
.asset-image {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.asset-details {
|
||||||
|
width: 100%;
|
||||||
|
height: 33px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.organization {
|
||||||
|
width: 40%;
|
||||||
|
height: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.asset-review {
|
||||||
|
width: 100%;
|
||||||
|
height: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button {
|
||||||
|
|
||||||
|
width: 100%;
|
||||||
|
height: 35px;
|
||||||
|
border-radius: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.filter-search-container {
|
.filter-search-container {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -84,6 +140,13 @@
|
||||||
.stars {
|
.stars {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
|
.star-wrapper.filled {
|
||||||
|
svg {
|
||||||
|
|
||||||
|
fill: #F3A50C;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -226,6 +289,17 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@keyframes growWidth {
|
||||||
|
from {
|
||||||
|
transform: scale(0.65);
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
.assetPreview-wrapper {
|
.assetPreview-wrapper {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
|
@ -90,7 +90,7 @@
|
||||||
.dropdown-menu {
|
.dropdown-menu {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 103%;
|
left: 100%;
|
||||||
background: var(--background-color-solid);
|
background: var(--background-color-solid);
|
||||||
min-width: 220px;
|
min-width: 220px;
|
||||||
border-radius: #{$border-radius-medium};
|
border-radius: #{$border-radius-medium};
|
||||||
|
@ -141,7 +141,7 @@
|
||||||
|
|
||||||
.submenu {
|
.submenu {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 102%;
|
left: 100%;
|
||||||
top: 0;
|
top: 0;
|
||||||
background: var(--background-color-solid);
|
background: var(--background-color-solid);
|
||||||
min-width: 200px;
|
min-width: 200px;
|
||||||
|
|
|
@ -378,12 +378,30 @@
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.metric-label.loss {
|
||||||
|
background: #6D4343;
|
||||||
|
border: 1px solid #FF301D
|
||||||
|
}
|
||||||
|
|
||||||
.metric-value {
|
.metric-value {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
line-height: 20px;
|
line-height: 20px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.metric-item.loss {
|
||||||
|
background: #6D4343;
|
||||||
|
border: 1px solid #FF301D;
|
||||||
|
|
||||||
|
.metric-label {
|
||||||
|
span {
|
||||||
|
color: #FF311E;
|
||||||
|
display: inline-block;
|
||||||
|
transform: rotate(180deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.metric-wrapper {
|
.metric-wrapper {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 6px;
|
gap: 6px;
|
||||||
|
|
|
@ -456,7 +456,7 @@
|
||||||
padding: 18px 10px;
|
padding: 18px 10px;
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
top: -32px;
|
// top: -32px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.barOverflow {
|
.barOverflow {
|
||||||
|
@ -482,4 +482,3 @@
|
||||||
transition: transform 0.5s ease;
|
transition: transform 0.5s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
// progress should be progress {progress}
|
|
|
@ -1392,4 +1392,36 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.skeleton-wrapper {
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
.skeleton-content {}
|
||||||
|
|
||||||
|
.asset-name {
|
||||||
|
width: 40%;
|
||||||
|
height: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.asset {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.sidebar-left-wrapper,
|
||||||
|
.sidebar-right-wrapper {
|
||||||
|
height: calc(50vh + 150px);
|
||||||
|
overflow-y: hidden;
|
||||||
|
transition: height 0.4s ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-left-wrapper.closed,
|
||||||
|
.sidebar-right-wrapper.closed {
|
||||||
|
height: 52px;
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
.skeleton-wrapper {
|
.skeleton-wrapper {
|
||||||
max-width: 600px;
|
// max-width: 600px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue