added custom styles for list

This commit is contained in:
PhilReact 2025-03-12 08:47:50 +02:00
parent d5f796281b
commit e4b781c41f
3 changed files with 114 additions and 40 deletions

View File

@ -1,5 +1,6 @@
import { Box, Typography } from "@mui/material"
import { BarSpinner } from "./Spinners/BarSpinner/BarSpinner"
import { Box, Typography } from "@mui/material";
import { BarSpinner } from "./Spinners/BarSpinner/BarSpinner";
import { CSSProperties } from "react";
interface ListLoaderProps {
isLoading: boolean;
@ -7,37 +8,55 @@ interface ListLoaderProps {
resultsLength: number;
noResultsMessage?: string; // Optional message when no results
children: React.ReactNode; // Required, to render the list content
loaderList?: (status: "LOADING" | "NO_RESULTS") => React.ReactNode; // Function type
loaderHeight?: CSSProperties
}
export const ListLoader = ({ isLoading, loadingMessage, resultsLength, children, noResultsMessage }: ListLoaderProps) => {
export const ListLoader = ({
isLoading,
loadingMessage,
resultsLength,
children,
noResultsMessage,
loaderList,
loaderHeight
}: ListLoaderProps) => {
return (
<>
{isLoading && (
<Box sx={{
display: 'flex',
gap: '20px',
alignItems: 'center',
overflow: "auto",
}}>
<BarSpinner width="22px" color="green" />
<Typography>{loadingMessage || `Fetching list`}</Typography>
</Box>
)}
{!isLoading && resultsLength === 0 && (
<Typography
style={{
display: "block",
}}
>
{noResultsMessage}
</Typography>
)}
{!isLoading && resultsLength > 0 && (
<>
{children}
</>
)}
{loaderList && isLoading && (
<>
{loaderList("LOADING")}
</>
)}
{loaderList && !isLoading && resultsLength === 0 && (
<>
{loaderList("NO_RESULTS")}
</>
)}
{!loaderList && isLoading && (
<Box
sx={{
display: "flex",
gap: "20px",
alignItems: "center",
overflow: "auto",
height: loaderHeight || "auto"
}}
>
<BarSpinner width="22px" color="green" />
<Typography>{loadingMessage || `Fetching list`}</Typography>
</Box>
)}
{!loaderList && !isLoading && resultsLength === 0 && (
<Typography
style={{
display: "block",
}}
>
{noResultsMessage}
</Typography>
)}
{!isLoading && resultsLength > 0 && <>{children}</>}
</>
)
}
);
};

15
src/common/Spacer.tsx Normal file
View File

@ -0,0 +1,15 @@
import { Box } from "@mui/material";
export const Spacer = ({ height, width, ...props }: any) => {
return (
<Box
sx={{
height: height ? height : '0px',
display: 'flex',
flexShrink: 0,
width: width ? width : '0px',
...(props || {})
}}
/>
);
};

View File

@ -15,16 +15,43 @@ import { ListLoader } from "../../common/ListLoader";
import { ListItem, useCacheStore } from "../../state/cache";
import { ResourceLoader } from "./ResourceLoader";
import { ItemCardWrapper } from "./ItemCardWrapper";
import { Spacer } from "../../common/Spacer";
interface ResourceListStyles {
gap?: number
listLoadingHeight?: CSSProperties
}
interface DefaultLoaderParams {
listLoadingText?: string
listNoResultsText?: string
listItemLoadingText?: string
listItemErrorText?: string
}
interface PropsResourceListDisplay {
params: QortalSearchParams;
listItem: (item: ListItem, index: number) => React.ReactNode; // Function type
styles?: ResourceListStyles
loaderItem?: (status: "LOADING" | "ERROR") => React.ReactNode; // Function type
defaultLoaderParams?: DefaultLoaderParams
loaderList?: (status: "LOADING" | "NO_RESULTS") => React.ReactNode; // Function type
}
export const ResourceListDisplay = ({
params,
listItem,
styles = {
gap: 1
},
defaultLoaderParams,
loaderItem,
loaderList
}: PropsResourceListDisplay) => {
const [list, setList] = useState<QortalMetadata[]>([]);
const { fetchResources } = useResources();
@ -50,10 +77,12 @@ export const ResourceListDisplay = ({
return (
<ListLoader
noResultsMessage="No results available"
noResultsMessage={defaultLoaderParams?.listNoResultsText || "No results available"}
resultsLength={list?.length}
isLoading={isLoading}
loadingMessage="Retrieving list. Please wait."
loadingMessage={defaultLoaderParams?.listLoadingText || "Retrieving list. Please wait."}
loaderList={loaderList}
loaderHeight={styles?.listLoadingHeight}
>
<div
style={{
@ -62,10 +91,15 @@ export const ResourceListDisplay = ({
width: "100%",
}}
>
<div style={{ display: "flex", flexGrow: isLoading ? 0 : 1 }}>
<div style={{ display: "flex", flexGrow: 1 }}>
<VirtualizedList list={list}>
{(item: QortalMetadata, index: number) => (
<ListItemWrapper item={item} index={index} render={listItem} />
<>
{styles?.gap && <Spacer height={`${styles.gap / 2}rem`} /> }
<Spacer/>
<ListItemWrapper defaultLoaderParams={defaultLoaderParams} item={item} index={index} render={listItem} renderListItemLoader={loaderItem} />
{styles?.gap && <Spacer height={`${styles.gap / 2}rem`} /> }
</>
)}
</VirtualizedList>
</div>
@ -78,38 +112,44 @@ interface ListItemWrapperProps {
item: QortalMetadata;
index: number;
render: (item: ListItem, index: number) => React.ReactNode;
defaultLoaderParams?: DefaultLoaderParams;
renderListItemLoader?:(status: "LOADING" | "ERROR")=> React.ReactNode;
}
const ListItemWrapper: React.FC<ListItemWrapperProps> = ({
item,
index,
render,
defaultLoaderParams,
renderListItemLoader
}) => {
console.log("Rendering wrapped item:", item, index);
const getResourceCache = useCacheStore().getResourceCache;
const findCachedResource = getResourceCache(
`${item.service}-${item.name}-${item.identifier}`,
true
);
if (findCachedResource === null)
if (findCachedResource === null && !renderListItemLoader)
return (
<ItemCardWrapper height={60} isInCart={false}>
<ResourceLoader
message="Fetching Data..."
message={defaultLoaderParams?.listItemLoadingText || "Fetching Data..."}
status="loading"
/>
</ItemCardWrapper>
);
if (findCachedResource === false)
if (findCachedResource === false && !renderListItemLoader)
return (
<ItemCardWrapper height={60} isInCart={false}>
<ResourceLoader
message="Product is unavailble at this moment... Try again later."
message={defaultLoaderParams?.listItemErrorText ||"Resource is unavailble at this moment... Try again later."}
status="error"
/>
</ItemCardWrapper>
);
if(renderListItemLoader && (findCachedResource === false || findCachedResource === null)){
return renderListItemLoader(findCachedResource === null ? "LOADING" : "ERROR")
}
// Example transformation (Modify item if needed)
const transformedItem = findCachedResource