mirror of
https://github.com/Qortal/qapp-core.git
synced 2025-06-15 01:41:21 +00:00
added custom styles for list
This commit is contained in:
parent
d5f796281b
commit
e4b781c41f
@ -1,5 +1,6 @@
|
|||||||
import { Box, Typography } from "@mui/material"
|
import { Box, Typography } from "@mui/material";
|
||||||
import { BarSpinner } from "./Spinners/BarSpinner/BarSpinner"
|
import { BarSpinner } from "./Spinners/BarSpinner/BarSpinner";
|
||||||
|
import { CSSProperties } from "react";
|
||||||
|
|
||||||
interface ListLoaderProps {
|
interface ListLoaderProps {
|
||||||
isLoading: boolean;
|
isLoading: boolean;
|
||||||
@ -7,37 +8,55 @@ interface ListLoaderProps {
|
|||||||
resultsLength: number;
|
resultsLength: number;
|
||||||
noResultsMessage?: string; // Optional message when no results
|
noResultsMessage?: string; // Optional message when no results
|
||||||
children: React.ReactNode; // Required, to render the list content
|
children: React.ReactNode; // Required, to render the list content
|
||||||
|
loaderList?: (status: "LOADING" | "NO_RESULTS") => React.ReactNode; // Function type
|
||||||
|
loaderHeight?: CSSProperties
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const ListLoader = ({
|
||||||
export const ListLoader = ({ isLoading, loadingMessage, resultsLength, children, noResultsMessage }: ListLoaderProps) => {
|
isLoading,
|
||||||
|
loadingMessage,
|
||||||
|
resultsLength,
|
||||||
|
children,
|
||||||
|
noResultsMessage,
|
||||||
|
loaderList,
|
||||||
|
loaderHeight
|
||||||
|
}: ListLoaderProps) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{isLoading && (
|
{loaderList && isLoading && (
|
||||||
<Box sx={{
|
<>
|
||||||
display: 'flex',
|
{loaderList("LOADING")}
|
||||||
gap: '20px',
|
</>
|
||||||
alignItems: 'center',
|
)}
|
||||||
overflow: "auto",
|
{loaderList && !isLoading && resultsLength === 0 && (
|
||||||
}}>
|
<>
|
||||||
<BarSpinner width="22px" color="green" />
|
{loaderList("NO_RESULTS")}
|
||||||
<Typography>{loadingMessage || `Fetching list`}</Typography>
|
</>
|
||||||
</Box>
|
)}
|
||||||
)}
|
{!loaderList && isLoading && (
|
||||||
{!isLoading && resultsLength === 0 && (
|
<Box
|
||||||
<Typography
|
sx={{
|
||||||
style={{
|
display: "flex",
|
||||||
display: "block",
|
gap: "20px",
|
||||||
}}
|
alignItems: "center",
|
||||||
>
|
overflow: "auto",
|
||||||
{noResultsMessage}
|
height: loaderHeight || "auto"
|
||||||
</Typography>
|
}}
|
||||||
)}
|
>
|
||||||
{!isLoading && resultsLength > 0 && (
|
<BarSpinner width="22px" color="green" />
|
||||||
<>
|
<Typography>{loadingMessage || `Fetching list`}</Typography>
|
||||||
{children}
|
</Box>
|
||||||
</>
|
)}
|
||||||
)}
|
{!loaderList && !isLoading && resultsLength === 0 && (
|
||||||
|
<Typography
|
||||||
|
style={{
|
||||||
|
display: "block",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{noResultsMessage}
|
||||||
|
</Typography>
|
||||||
|
)}
|
||||||
|
{!isLoading && resultsLength > 0 && <>{children}</>}
|
||||||
</>
|
</>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
15
src/common/Spacer.tsx
Normal file
15
src/common/Spacer.tsx
Normal 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 || {})
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
@ -15,16 +15,43 @@ import { ListLoader } from "../../common/ListLoader";
|
|||||||
import { ListItem, useCacheStore } from "../../state/cache";
|
import { ListItem, useCacheStore } from "../../state/cache";
|
||||||
import { ResourceLoader } from "./ResourceLoader";
|
import { ResourceLoader } from "./ResourceLoader";
|
||||||
import { ItemCardWrapper } from "./ItemCardWrapper";
|
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 {
|
interface PropsResourceListDisplay {
|
||||||
params: QortalSearchParams;
|
params: QortalSearchParams;
|
||||||
listItem: (item: ListItem, index: number) => React.ReactNode; // Function type
|
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 = ({
|
export const ResourceListDisplay = ({
|
||||||
params,
|
params,
|
||||||
listItem,
|
listItem,
|
||||||
|
styles = {
|
||||||
|
gap: 1
|
||||||
|
},
|
||||||
|
defaultLoaderParams,
|
||||||
|
loaderItem,
|
||||||
|
loaderList
|
||||||
}: PropsResourceListDisplay) => {
|
}: PropsResourceListDisplay) => {
|
||||||
const [list, setList] = useState<QortalMetadata[]>([]);
|
const [list, setList] = useState<QortalMetadata[]>([]);
|
||||||
const { fetchResources } = useResources();
|
const { fetchResources } = useResources();
|
||||||
@ -50,10 +77,12 @@ export const ResourceListDisplay = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<ListLoader
|
<ListLoader
|
||||||
noResultsMessage="No results available"
|
noResultsMessage={defaultLoaderParams?.listNoResultsText || "No results available"}
|
||||||
resultsLength={list?.length}
|
resultsLength={list?.length}
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
loadingMessage="Retrieving list. Please wait."
|
loadingMessage={defaultLoaderParams?.listLoadingText || "Retrieving list. Please wait."}
|
||||||
|
loaderList={loaderList}
|
||||||
|
loaderHeight={styles?.listLoadingHeight}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
@ -62,10 +91,15 @@ export const ResourceListDisplay = ({
|
|||||||
width: "100%",
|
width: "100%",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div style={{ display: "flex", flexGrow: isLoading ? 0 : 1 }}>
|
<div style={{ display: "flex", flexGrow: 1 }}>
|
||||||
<VirtualizedList list={list}>
|
<VirtualizedList list={list}>
|
||||||
{(item: QortalMetadata, index: number) => (
|
{(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>
|
</VirtualizedList>
|
||||||
</div>
|
</div>
|
||||||
@ -78,38 +112,44 @@ interface ListItemWrapperProps {
|
|||||||
item: QortalMetadata;
|
item: QortalMetadata;
|
||||||
index: number;
|
index: number;
|
||||||
render: (item: ListItem, index: number) => React.ReactNode;
|
render: (item: ListItem, index: number) => React.ReactNode;
|
||||||
|
defaultLoaderParams?: DefaultLoaderParams;
|
||||||
|
renderListItemLoader?:(status: "LOADING" | "ERROR")=> React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ListItemWrapper: React.FC<ListItemWrapperProps> = ({
|
const ListItemWrapper: React.FC<ListItemWrapperProps> = ({
|
||||||
item,
|
item,
|
||||||
index,
|
index,
|
||||||
render,
|
render,
|
||||||
|
defaultLoaderParams,
|
||||||
|
renderListItemLoader
|
||||||
}) => {
|
}) => {
|
||||||
console.log("Rendering wrapped item:", item, index);
|
|
||||||
const getResourceCache = useCacheStore().getResourceCache;
|
const getResourceCache = useCacheStore().getResourceCache;
|
||||||
|
|
||||||
const findCachedResource = getResourceCache(
|
const findCachedResource = getResourceCache(
|
||||||
`${item.service}-${item.name}-${item.identifier}`,
|
`${item.service}-${item.name}-${item.identifier}`,
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
if (findCachedResource === null)
|
if (findCachedResource === null && !renderListItemLoader)
|
||||||
return (
|
return (
|
||||||
<ItemCardWrapper height={60} isInCart={false}>
|
<ItemCardWrapper height={60} isInCart={false}>
|
||||||
<ResourceLoader
|
<ResourceLoader
|
||||||
message="Fetching Data..."
|
message={defaultLoaderParams?.listItemLoadingText || "Fetching Data..."}
|
||||||
status="loading"
|
status="loading"
|
||||||
/>
|
/>
|
||||||
</ItemCardWrapper>
|
</ItemCardWrapper>
|
||||||
);
|
);
|
||||||
if (findCachedResource === false)
|
if (findCachedResource === false && !renderListItemLoader)
|
||||||
return (
|
return (
|
||||||
<ItemCardWrapper height={60} isInCart={false}>
|
<ItemCardWrapper height={60} isInCart={false}>
|
||||||
<ResourceLoader
|
<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"
|
status="error"
|
||||||
/>
|
/>
|
||||||
</ItemCardWrapper>
|
</ItemCardWrapper>
|
||||||
);
|
);
|
||||||
|
if(renderListItemLoader && (findCachedResource === false || findCachedResource === null)){
|
||||||
|
return renderListItemLoader(findCachedResource === null ? "LOADING" : "ERROR")
|
||||||
|
}
|
||||||
|
|
||||||
// Example transformation (Modify item if needed)
|
// Example transformation (Modify item if needed)
|
||||||
const transformedItem = findCachedResource
|
const transformedItem = findCachedResource
|
||||||
|
Loading…
x
Reference in New Issue
Block a user