fix(StorePage): fix pagination bug where incorrect index and pageSize were passed to getStoreComponents function
feat(StorePage): add support for dynamic pagination in StorePage by implementing handleChangePagination function feat(StorePage): add support for resetting filter in StorePage by implementing resetFilter function feat(StorePage): add support for displaying total rows count in StorePage feat(StorePage): add support for displaying loading message while fetching data in StorePage feat(StorePage): add support for displaying error message when there is an error fetching data in StorePage feat(StorePage): add support for displaying search input and search button in StorePage feat(StorePage): add support for filtering components by type in StorePage feat(StorePage): add support for displaying badges for each component type in StorePage feat(StorePage): add support for displaying market card components in StorePage feat(StorePage): add support for displaying paginator component in StorePage feat(StorePage): add support for displaying loading message while fetching data with API key in StorePage fix(types): add storeComponent property to PaginatorComponentType to differentiate between store and other components
This commit is contained in:
parent
3e315012e1
commit
1b69f02b16
2 changed files with 129 additions and 97 deletions
|
|
@ -45,20 +45,19 @@ export default function StorePage(): JSX.Element {
|
||||||
const [size, setPageSize] = useState(10);
|
const [size, setPageSize] = useState(10);
|
||||||
const [index, setPageIndex] = useState(1);
|
const [index, setPageIndex] = useState(1);
|
||||||
|
|
||||||
function handleChangePagination(pageIndex: number, pageSize: number) {}
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
handleGetComponents();
|
handleGetComponents();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleGetComponents = () => {
|
const handleGetComponents = () => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
getStoreComponents(1, 10)
|
getStoreComponents(index - 1, 10000)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
setSearchData(res);
|
setSearchData(res.slice(0, 10));
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
setErrorApiKey(false);
|
setErrorApiKey(false);
|
||||||
setData(res);
|
setData(res);
|
||||||
|
setTotalRowsCount(res.length);
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
setSearchData([]);
|
setSearchData([]);
|
||||||
|
|
@ -84,6 +83,34 @@ export default function StorePage(): JSX.Element {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function handleChangePagination(pageIndex: number, pageSize: number) {
|
||||||
|
setLoading(true);
|
||||||
|
getStoreComponents(pageIndex, pageSize)
|
||||||
|
.then((res) => {
|
||||||
|
setPageIndex(pageIndex);
|
||||||
|
setPageSize(pageSize);
|
||||||
|
setSearchData(res);
|
||||||
|
setLoading(false);
|
||||||
|
setErrorApiKey(false);
|
||||||
|
setData(res);
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
setSearchData([]);
|
||||||
|
setLoading(false);
|
||||||
|
setErrorApiKey(true);
|
||||||
|
setErrorData({
|
||||||
|
title: "Error to get components.",
|
||||||
|
list: [err["response"]["data"]["detail"]],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function resetFilter() {
|
||||||
|
setPageIndex(1);
|
||||||
|
setPageSize(10);
|
||||||
|
handleGetComponents();
|
||||||
|
}
|
||||||
|
|
||||||
const loadingWithApiKey = loading;
|
const loadingWithApiKey = loading;
|
||||||
const renderComponents = !loading;
|
const renderComponents = !loading;
|
||||||
|
|
||||||
|
|
@ -113,103 +140,108 @@ export default function StorePage(): JSX.Element {
|
||||||
<span className="community-page-description-text">
|
<span className="community-page-description-text">
|
||||||
Search flows and components from the community.
|
Search flows and components from the community.
|
||||||
</span>
|
</span>
|
||||||
{renderComponents && (
|
<div className="flex w-full flex-col gap-4 p-4">
|
||||||
<div className="flex w-full flex-col gap-4 p-4">
|
<div className="flex items-center justify-center gap-4">
|
||||||
<div className="flex items-center justify-center gap-4">
|
<div className="flex w-[13%] items-center justify-center gap-3 text-sm">
|
||||||
<div className="flex w-[13%] items-center justify-center gap-3 text-sm">
|
Added Only <Switch />
|
||||||
Added Only <Switch />
|
</div>
|
||||||
</div>
|
<div className="relative h-12 w-[35%]">
|
||||||
<div className="relative h-12 w-[35%]">
|
<Input
|
||||||
<Input
|
placeholder="Search Flows and Components"
|
||||||
placeholder="Search Flows and Components"
|
className="absolute h-12 px-5"
|
||||||
className="absolute h-12 px-5"
|
onChange={(e) => {
|
||||||
onChange={(e) => {
|
setInputText(e.target.value);
|
||||||
setInputText(e.target.value);
|
}}
|
||||||
}}
|
onKeyDown={(e) => {
|
||||||
onKeyDown={(e) => {
|
if (e.key === "Enter") {
|
||||||
if (e.key === "Enter") {
|
|
||||||
handleSearch(inputText);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
value={inputText}
|
|
||||||
/>
|
|
||||||
<Search className="absolute bottom-0 right-4 top-0 my-auto h-6 stroke-1 text-muted-foreground " />
|
|
||||||
</div>
|
|
||||||
<div className="flex items-center justify-center text-sm">
|
|
||||||
<Button
|
|
||||||
onClick={() => {
|
|
||||||
handleSearch(inputText);
|
handleSearch(inputText);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
value={inputText}
|
||||||
|
/>
|
||||||
|
<Search className="absolute bottom-0 right-4 top-0 my-auto h-6 stroke-1 text-muted-foreground " />
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center justify-center text-sm">
|
||||||
|
<Button
|
||||||
|
onClick={() => {
|
||||||
|
handleSearch(inputText);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Search
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
<div className="flex w-[13%] items-center justify-center gap-3 text-sm">
|
||||||
|
<Select
|
||||||
|
onValueChange={(value) => {
|
||||||
|
const filter = value === "Flow" ? false : true;
|
||||||
|
const search = data.filter((f) => f.is_component === filter);
|
||||||
|
value === "" ? setSearchData(data) : setSearchData(search);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<SelectTrigger className="w-[180px]">
|
||||||
|
<SelectValue placeholder="Flows" />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectItem value="Flow">Flows</SelectItem>
|
||||||
|
<SelectItem value="Component">Components</SelectItem>
|
||||||
|
<SelectItem value="">Both</SelectItem>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center justify-center gap-4">
|
||||||
|
{Array.from(new Set(searchData.map((i) => i.is_component))).map(
|
||||||
|
(i, idx) => (
|
||||||
|
<Badge
|
||||||
|
onClick={() => {
|
||||||
|
filteredCategories.has(i)
|
||||||
|
? setFilteredCategories((old) => {
|
||||||
|
let newFilteredCategories = cloneDeep(old);
|
||||||
|
newFilteredCategories.delete(i);
|
||||||
|
return newFilteredCategories;
|
||||||
|
})
|
||||||
|
: setFilteredCategories((old) => {
|
||||||
|
let newFilteredCategories = cloneDeep(old);
|
||||||
|
newFilteredCategories.add(i);
|
||||||
|
return newFilteredCategories;
|
||||||
|
});
|
||||||
}}
|
}}
|
||||||
|
variant="gray"
|
||||||
|
size="md"
|
||||||
|
className={cn(
|
||||||
|
"cursor-pointer border-none",
|
||||||
|
filteredCategories.has(i)
|
||||||
|
? "bg-beta-foreground text-background hover:bg-beta-foreground"
|
||||||
|
: ""
|
||||||
|
)}
|
||||||
>
|
>
|
||||||
Search
|
<Link className="mr-1.5 w-4" />
|
||||||
</Button>
|
{i}
|
||||||
</div>
|
</Badge>
|
||||||
<div className="flex w-[13%] items-center justify-center gap-3 text-sm">
|
)
|
||||||
<Select
|
)}
|
||||||
onValueChange={(value) => {
|
</div>
|
||||||
const filter = value === "Flow" ? false : true;
|
|
||||||
const search = data.filter(
|
|
||||||
(f) => f.is_component === filter
|
|
||||||
);
|
|
||||||
value === "" ? setSearchData(data) : setSearchData(search);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<SelectTrigger className="w-[180px]">
|
|
||||||
<SelectValue placeholder="Flows" />
|
|
||||||
</SelectTrigger>
|
|
||||||
<SelectContent>
|
|
||||||
<SelectItem value="Flow">Flows</SelectItem>
|
|
||||||
<SelectItem value="Component">Components</SelectItem>
|
|
||||||
<SelectItem value="">Both</SelectItem>
|
|
||||||
</SelectContent>
|
|
||||||
</Select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="flex items-center justify-center gap-4">
|
|
||||||
{Array.from(new Set(searchData.map((i) => i.is_component))).map(
|
|
||||||
(i, idx) => (
|
|
||||||
<Badge
|
|
||||||
onClick={() => {
|
|
||||||
filteredCategories.has(i)
|
|
||||||
? setFilteredCategories((old) => {
|
|
||||||
let newFilteredCategories = cloneDeep(old);
|
|
||||||
newFilteredCategories.delete(i);
|
|
||||||
return newFilteredCategories;
|
|
||||||
})
|
|
||||||
: setFilteredCategories((old) => {
|
|
||||||
let newFilteredCategories = cloneDeep(old);
|
|
||||||
newFilteredCategories.add(i);
|
|
||||||
return newFilteredCategories;
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
variant="gray"
|
|
||||||
size="md"
|
|
||||||
className={cn(
|
|
||||||
"cursor-pointer border-none",
|
|
||||||
filteredCategories.has(i)
|
|
||||||
? "bg-beta-foreground text-background hover:bg-beta-foreground"
|
|
||||||
: ""
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<Link className="mr-1.5 w-4" />
|
|
||||||
{i}
|
|
||||||
</Badge>
|
|
||||||
)
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<div className="mt-6 grid w-full gap-4 md:grid-cols-2 lg:grid-cols-3">
|
|
||||||
{searchData
|
|
||||||
.filter(
|
|
||||||
(f) =>
|
|
||||||
Array.from(filteredCategories).length === 0 ||
|
|
||||||
filteredCategories.has(f.is_component)
|
|
||||||
)
|
|
||||||
.map((item, idx) => (
|
|
||||||
<MarketCardComponent key={idx} data={item} />
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
{renderComponents && (
|
||||||
|
<>
|
||||||
|
<div className="mt-6 grid w-full gap-4 md:grid-cols-2 lg:grid-cols-3">
|
||||||
|
{searchData
|
||||||
|
.filter(
|
||||||
|
(f) =>
|
||||||
|
Array.from(filteredCategories).length === 0 ||
|
||||||
|
filteredCategories.has(f.is_component)
|
||||||
|
)
|
||||||
|
.map((item, idx) => (
|
||||||
|
<MarketCardComponent key={idx} data={item} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
{totalRowsCount > 0 && !loading && (
|
||||||
|
<div className="relative bottom-2">
|
||||||
<PaginatorComponent
|
<PaginatorComponent
|
||||||
|
storeComponent={true}
|
||||||
pageIndex={index}
|
pageIndex={index}
|
||||||
pageSize={size}
|
pageSize={size}
|
||||||
totalRowsCount={totalRowsCount}
|
totalRowsCount={totalRowsCount}
|
||||||
|
|
@ -219,7 +251,6 @@ export default function StorePage(): JSX.Element {
|
||||||
></PaginatorComponent>
|
></PaginatorComponent>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{loadingWithApiKey && (
|
{loadingWithApiKey && (
|
||||||
<div className="flex w-full flex-col gap-4 p-4">Loading...</div>
|
<div className="flex w-full flex-col gap-4 p-4">Loading...</div>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -271,6 +271,7 @@ export type PaginatorComponentType = {
|
||||||
rowsCount?: number[];
|
rowsCount?: number[];
|
||||||
totalRowsCount: number;
|
totalRowsCount: number;
|
||||||
paginate: (pageIndex: number, pageSize: number) => void;
|
paginate: (pageIndex: number, pageSize: number) => void;
|
||||||
|
storeComponent?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ConfirmationModalType = {
|
export type ConfirmationModalType = {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue