Refactor Assets component to streamline category fetching and enhance loading state handling; improve SkeletonUI styles for better asset representation
This commit is contained in:
parent
980d27c91f
commit
59a3cb4704
|
@ -90,24 +90,7 @@ const Assets: React.FC = () => {
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setCategoryList([
|
setCategoryList([
|
||||||
{
|
{ category: "Fenestration", categoryImage: feneration },
|
||||||
assetName: "Doors",
|
|
||||||
assetImage: "",
|
|
||||||
category: "Feneration",
|
|
||||||
categoryImage: feneration,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
assetName: "Windows",
|
|
||||||
assetImage: "",
|
|
||||||
category: "Feneration",
|
|
||||||
categoryImage: feneration,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
assetName: "Pillars",
|
|
||||||
assetImage: "",
|
|
||||||
category: "Feneration",
|
|
||||||
categoryImage: feneration,
|
|
||||||
},
|
|
||||||
{ category: "Vehicles", categoryImage: vehicle },
|
{ category: "Vehicles", categoryImage: vehicle },
|
||||||
{ category: "Workstation", categoryImage: workStation },
|
{ category: "Workstation", categoryImage: workStation },
|
||||||
{ category: "Machines", categoryImage: machines },
|
{ category: "Machines", categoryImage: machines },
|
||||||
|
@ -121,44 +104,15 @@ const Assets: React.FC = () => {
|
||||||
const fetchCategoryAssets = async (asset: any) => {
|
const fetchCategoryAssets = async (asset: any) => {
|
||||||
setisLoading(true);
|
setisLoading(true);
|
||||||
setSelectedCategory(asset);
|
setSelectedCategory(asset);
|
||||||
if (asset === "Feneration") {
|
try {
|
||||||
const localAssets: AssetProp[] = [
|
const res = await getCategoryAsset(asset);
|
||||||
{
|
setCategoryAssets(res);
|
||||||
filename: "arch",
|
setFiltereredAssets(res);
|
||||||
category: "Feneration",
|
setisLoading(false); // End loading
|
||||||
url: arch,
|
// eslint-disable-next-line
|
||||||
thumbnail: archThumbnail,
|
} catch (error) {
|
||||||
tags: "arch",
|
echo.error("failed to fetch assets");
|
||||||
},
|
|
||||||
{
|
|
||||||
filename: "door",
|
|
||||||
category: "Feneration",
|
|
||||||
url: door,
|
|
||||||
thumbnail: feneration,
|
|
||||||
tags: "door",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
filename: "window",
|
|
||||||
category: "Feneration",
|
|
||||||
url: window,
|
|
||||||
thumbnail: windowThumbnail,
|
|
||||||
tags: "window",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
setCategoryAssets(localAssets);
|
|
||||||
setFiltereredAssets(localAssets);
|
|
||||||
setisLoading(false);
|
setisLoading(false);
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
const res = await getCategoryAsset(asset);
|
|
||||||
setCategoryAssets(res);
|
|
||||||
setFiltereredAssets(res);
|
|
||||||
setisLoading(false); // End loading
|
|
||||||
// eslint-disable-next-line
|
|
||||||
} catch (error) {
|
|
||||||
echo.error("failed to fetch assets");
|
|
||||||
setisLoading(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -167,62 +121,19 @@ const Assets: React.FC = () => {
|
||||||
<Search onChange={handleSearchChange} />
|
<Search onChange={handleSearchChange} />
|
||||||
<div className="assets-list-section">
|
<div className="assets-list-section">
|
||||||
<section>
|
<section>
|
||||||
{isLoading ? (
|
{(() => {
|
||||||
<SkeletonUI type="asset" /> // Show skeleton when loading
|
if (isLoading) {
|
||||||
) : searchValue ? (
|
return <SkeletonUI type="asset" />; // Show skeleton when loading
|
||||||
<div className="assets-result">
|
}
|
||||||
<div className="assets-wrapper">
|
if (searchValue) {
|
||||||
<div className="searched-content">
|
return (
|
||||||
<p>Results for {searchValue}</p>
|
<div className="assets-result">
|
||||||
</div>
|
<div className="assets-wrapper">
|
||||||
<div className="assets-container">
|
<div className="searched-content">
|
||||||
{categoryAssets?.map((asset: any, index: number) => (
|
<p>Results for {searchValue}</p>
|
||||||
<div
|
|
||||||
key={index}
|
|
||||||
className="assets"
|
|
||||||
id={asset.filename}
|
|
||||||
title={asset.filename}
|
|
||||||
>
|
|
||||||
<img
|
|
||||||
src={asset?.thumbnail}
|
|
||||||
alt={asset.filename}
|
|
||||||
className="asset-image"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<div className="asset-name">
|
|
||||||
{asset.filename
|
|
||||||
.split("_")
|
|
||||||
.map(
|
|
||||||
(word: any) =>
|
|
||||||
word.charAt(0).toUpperCase() + word.slice(1)
|
|
||||||
)
|
|
||||||
.join(" ")}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
))}
|
<div className="assets-container">
|
||||||
</div>
|
{categoryAssets?.map((asset: any, index: number) => (
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<>
|
|
||||||
{selectedCategory ? (
|
|
||||||
<div className="assets-wrapper">
|
|
||||||
<h2>
|
|
||||||
{selectedCategory}{" "}
|
|
||||||
<div
|
|
||||||
className="back-button"
|
|
||||||
id="asset-backButtom"
|
|
||||||
onClick={() => {
|
|
||||||
setSelectedCategory(null);
|
|
||||||
setCategoryAssets([]);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
← Back
|
|
||||||
</div>
|
|
||||||
</h2>
|
|
||||||
<div className="assets-container">
|
|
||||||
{categoryAssets &&
|
|
||||||
categoryAssets?.map((asset: any, index: number) => (
|
|
||||||
<div
|
<div
|
||||||
key={index}
|
key={index}
|
||||||
className="assets"
|
className="assets"
|
||||||
|
@ -233,17 +144,8 @@ const Assets: React.FC = () => {
|
||||||
src={asset?.thumbnail}
|
src={asset?.thumbnail}
|
||||||
alt={asset.filename}
|
alt={asset.filename}
|
||||||
className="asset-image"
|
className="asset-image"
|
||||||
onPointerDown={() => {
|
|
||||||
setSelectedItem({
|
|
||||||
name: asset.filename,
|
|
||||||
id: asset.AssetID,
|
|
||||||
type:
|
|
||||||
asset.type === "undefined"
|
|
||||||
? undefined
|
|
||||||
: asset.type,
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className="asset-name">
|
<div className="asset-name">
|
||||||
{asset.filename
|
{asset.filename
|
||||||
.split("_")
|
.split("_")
|
||||||
|
@ -255,40 +157,104 @@ const Assets: React.FC = () => {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selectedCategory) {
|
||||||
|
return (
|
||||||
<div className="assets-wrapper">
|
<div className="assets-wrapper">
|
||||||
<h2>Categories</h2>
|
<h2>
|
||||||
<div className="categories-container">
|
{selectedCategory}
|
||||||
{Array.from(
|
<button
|
||||||
new Set(categoryList.map((asset) => asset.category))
|
className="back-button"
|
||||||
).map((category, index) => {
|
id="asset-backButtom"
|
||||||
const categoryInfo = categoryList.find(
|
onClick={() => {
|
||||||
(asset) => asset.category === category
|
setSelectedCategory(null);
|
||||||
);
|
setCategoryAssets([]);
|
||||||
return (
|
}}
|
||||||
<div
|
>
|
||||||
key={index}
|
← Back
|
||||||
className="category"
|
</button>
|
||||||
id={category}
|
</h2>
|
||||||
onClick={() => fetchCategoryAssets(category)}
|
<div className="assets-container">
|
||||||
>
|
{categoryAssets?.map((asset: any, index: number) => (
|
||||||
<img
|
<div
|
||||||
src={categoryInfo?.categoryImage || ""}
|
key={`${index}-${asset}`}
|
||||||
alt={category}
|
className="assets"
|
||||||
className="category-image"
|
id={asset.filename}
|
||||||
draggable={false}
|
title={asset.filename}
|
||||||
/>
|
>
|
||||||
<div className="category-name">{category}</div>
|
<img
|
||||||
|
src={asset?.thumbnail}
|
||||||
|
alt={asset.filename}
|
||||||
|
className="asset-image"
|
||||||
|
onPointerDown={() => {
|
||||||
|
setSelectedItem({
|
||||||
|
name: asset.filename,
|
||||||
|
id: asset.AssetID,
|
||||||
|
type:
|
||||||
|
asset.type === "undefined"
|
||||||
|
? undefined
|
||||||
|
: asset.type,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<div className="asset-name">
|
||||||
|
{asset.filename
|
||||||
|
.split("_")
|
||||||
|
.map(
|
||||||
|
(word: any) =>
|
||||||
|
word.charAt(0).toUpperCase() + word.slice(1)
|
||||||
|
)
|
||||||
|
.join(" ")}
|
||||||
</div>
|
</div>
|
||||||
);
|
</div>
|
||||||
})}
|
))}
|
||||||
|
{categoryAssets.length === 0 && (
|
||||||
|
<div className="no-asset">
|
||||||
|
🚧 The asset shelf is empty. We're working on filling it
|
||||||
|
up!
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
);
|
||||||
</>
|
}
|
||||||
)}
|
|
||||||
|
return (
|
||||||
|
<div className="assets-wrapper">
|
||||||
|
<h2>Categories</h2>
|
||||||
|
<div className="categories-container">
|
||||||
|
{Array.from(
|
||||||
|
new Set(categoryList.map((asset) => asset.category))
|
||||||
|
).map((category, index) => {
|
||||||
|
const categoryInfo = categoryList.find(
|
||||||
|
(asset) => asset.category === category
|
||||||
|
);
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
key={index}
|
||||||
|
className="category"
|
||||||
|
id={category}
|
||||||
|
onClick={() => fetchCategoryAssets(category)}
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
src={categoryInfo?.categoryImage ?? ""}
|
||||||
|
alt={category}
|
||||||
|
className="category-image"
|
||||||
|
draggable={false}
|
||||||
|
/>
|
||||||
|
<div className="category-name">{category}</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})()}
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -7,7 +7,6 @@ interface SkeletonUIProps {
|
||||||
|
|
||||||
// Define the SkeletonUI component
|
// Define the SkeletonUI component
|
||||||
const SkeletonUI: React.FC<SkeletonUIProps> = ({ type }) => {
|
const SkeletonUI: React.FC<SkeletonUIProps> = ({ type }) => {
|
||||||
|
|
||||||
// Function to render skeleton content based on 'type'
|
// Function to render skeleton content based on 'type'
|
||||||
const renderSkeleton = () => {
|
const renderSkeleton = () => {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
@ -38,17 +37,28 @@ const SkeletonUI: React.FC<SkeletonUIProps> = ({ type }) => {
|
||||||
case "asset":
|
case "asset":
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="skeleton-content">
|
<div className="skeleton asset-category-title"></div>
|
||||||
<div className="skeleton asset-name"></div>
|
<div className="skeleton-content-asset">
|
||||||
<div className="skeleton asset"></div>
|
<div className="skeleton-content">
|
||||||
</div>
|
<div className="skeleton asset-name"></div>
|
||||||
<div className="skeleton-content">
|
<div className="skeleton asset"></div>
|
||||||
<div className="skeleton asset-name"></div>
|
</div>
|
||||||
<div className="skeleton asset"></div>
|
<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>
|
||||||
|
<div className="skeleton-content">
|
||||||
|
<div className="skeleton asset-name"></div>
|
||||||
|
<div className="skeleton asset"></div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return (
|
return (
|
||||||
<div className="skeleton-content">
|
<div className="skeleton-content">
|
||||||
|
|
|
@ -1278,7 +1278,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.toggle-sidebar-ui-button {
|
.toggle-sidebar-ui-button {
|
||||||
svg{
|
svg {
|
||||||
transform: scaleX(-1);
|
transform: scaleX(-1);
|
||||||
}
|
}
|
||||||
.tooltip {
|
.tooltip {
|
||||||
|
@ -1455,7 +1455,11 @@
|
||||||
height: 100%;
|
height: 100%;
|
||||||
gap: 6px;
|
gap: 6px;
|
||||||
padding: 2px;
|
padding: 2px;
|
||||||
|
.no-asset {
|
||||||
|
text-align: center;
|
||||||
|
margin: 12px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
.assets {
|
.assets {
|
||||||
width: 122px;
|
width: 122px;
|
||||||
height: 95px;
|
height: 95px;
|
||||||
|
|
|
@ -1,18 +1,8 @@
|
||||||
.skeleton-wrapper {
|
.skeleton-wrapper {
|
||||||
// max-width: 600px;
|
// max-width: 600px;
|
||||||
display: flex;
|
margin: 0 auto;
|
||||||
margin: 0 auto;
|
width: 100%;
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
.asset-name {
|
|
||||||
width: 40%;
|
|
||||||
height: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.asset {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
.skeleton {
|
.skeleton {
|
||||||
background: var(--background-color-gray);
|
background: var(--background-color-gray);
|
||||||
|
|
||||||
|
@ -31,7 +21,7 @@
|
||||||
90deg,
|
90deg,
|
||||||
rgba(255, 255, 255, 0) 0%,
|
rgba(255, 255, 255, 0) 0%,
|
||||||
rgba(255, 255, 255, 0.2) 20%,
|
rgba(255, 255, 255, 0.2) 20%,
|
||||||
rgba(255, 255, 255, 0.5) 60%,
|
rgba(255, 255, 255, 0.39) 60%,
|
||||||
rgba(255, 255, 255, 0) 100%
|
rgba(255, 255, 255, 0) 100%
|
||||||
);
|
);
|
||||||
transform: translateX(-100%);
|
transform: translateX(-100%);
|
||||||
|
@ -66,6 +56,34 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.asset-category-title{
|
||||||
|
width: 60%;
|
||||||
|
height: 12px;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
margin-top: 4px;
|
||||||
|
}
|
||||||
|
.skeleton-content-asset{
|
||||||
|
display: flex;
|
||||||
|
height: calc(95px * 2 + 10px);
|
||||||
|
gap: 10px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
.skeleton-content {
|
||||||
|
gap: 8px;
|
||||||
|
flex-direction: column;
|
||||||
|
min-width: 122px;
|
||||||
|
min-height: 95px;
|
||||||
|
.asset-name {
|
||||||
|
width: 40%;
|
||||||
|
height: 10px;
|
||||||
|
}
|
||||||
|
.asset {
|
||||||
|
flex: 1;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@keyframes shimmer {
|
@keyframes shimmer {
|
||||||
100% {
|
100% {
|
||||||
transform: translateX(100%);
|
transform: translateX(100%);
|
||||||
|
|
Loading…
Reference in New Issue