feat(storeContext.tsx): add hasApiKey state and setHasApiKey function to storeContext to track if API key is present

fix(StorePage/index.tsx): fix useEffect dependencies and add missing handleChangeTab function
fix(API/index.ts): rename getNumberOfComponents function to getCountComponents to improve semantics
This commit is contained in:
cristhianzl 2023-11-02 09:57:03 -03:00
commit b3bb568526
4 changed files with 107 additions and 149 deletions

View file

@ -8,6 +8,8 @@ const initialValue = {
setSavedFlows: () => {}, setSavedFlows: () => {},
hasStore: true, hasStore: true,
setHasStore: () => {}, setHasStore: () => {},
hasApiKey: true,
setHasApiKey: () => {},
}; };
export const StoreContext = createContext<storeContextType>(initialValue); export const StoreContext = createContext<storeContextType>(initialValue);
@ -16,14 +18,23 @@ export function StoreProvider({ children }) {
const [savedFlows, setSavedFlows] = useState<Set<string>>(new Set()); const [savedFlows, setSavedFlows] = useState<Set<string>>(new Set());
const [hasStore, setHasStore] = useState(true); const [hasStore, setHasStore] = useState(true);
const [hasApiKey, setHasApiKey] = useState(true);
checkHasStore().then((res) => { checkHasStore().then((res) => {
setHasStore(res["enabled"]); setHasStore(res["enabled"]);
setHasApiKey(res["has_api_key"]);
}); });
return ( return (
<StoreContext.Provider <StoreContext.Provider
value={{ savedFlows, setSavedFlows, hasStore, setHasStore }} value={{
savedFlows,
setSavedFlows,
hasStore,
setHasStore,
hasApiKey,
setHasApiKey,
}}
> >
{children} {children}
</StoreContext.Provider> </StoreContext.Provider>

View file

@ -713,9 +713,20 @@ export async function checkHasStore() {
} }
} }
export async function getNumberOfComponents() { export async function getCountComponents(is_component?: boolean | null) {
try { try {
const res = await api.get(`${BASE_URL_API}store/components/count`); let url = `${BASE_URL_API}store/components/count`;
const queryParams: any = [];
if (is_component !== undefined) {
queryParams.push(`is_component=${is_component}`);
}
if (queryParams.length > 0) {
url += `?${queryParams.join("&")}`;
}
const res = await api.get(url);
if (res.status === 200) { if (res.status === 200) {
return res.data; return res.data;
} }

View file

@ -20,7 +20,7 @@ import { alertContext } from "../../contexts/alertContext";
import { StoreContext } from "../../contexts/storeContext"; import { StoreContext } from "../../contexts/storeContext";
import { TabsContext } from "../../contexts/tabsContext"; import { TabsContext } from "../../contexts/tabsContext";
import { import {
getNumberOfComponents, getCountComponents,
getStoreComponents, getStoreComponents,
getStoreSavedComponents, getStoreSavedComponents,
getStoreTags, getStoreTags,
@ -32,25 +32,24 @@ import { cn } from "../../utils/utils";
import { MarketCardComponent } from "./components/market-card"; import { MarketCardComponent } from "./components/market-card";
export default function StorePage(): JSX.Element { export default function StorePage(): JSX.Element {
const { setTabId } = useContext(TabsContext); const { setTabId } = useContext(TabsContext);
// set null id
useEffect(() => { useEffect(() => {
setTabId(""); setTabId("");
}, []); }, []);
const [data, setData] = useState<storeComponent[]>([]);
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [filteredCategories, setFilterCategories] = useState<any[]>([]); const [filteredCategories, setFilterCategories] = useState<any[]>([]);
const [inputText, setInputText] = useState<string>(""); const [inputText, setInputText] = useState<string>("");
const [searchData, setSearchData] = useState(data); const [searchData, setSearchData] = useState<storeComponent[]>([]);
const { setErrorData } = useContext(alertContext); const { setErrorData } = useContext(alertContext);
const [totalRowsCount, setTotalRowsCount] = useState(0); const [totalRowsCount, setTotalRowsCount] = useState(0);
const [size, setPageSize] = useState(10); const [size, setPageSize] = useState(10);
const [index, setPageIndex] = useState(1); const [index, setPageIndex] = useState(1);
const [errorApiKey, setErrorApiKey] = useState(false); const [errorApiKey, setErrorApiKey] = useState(false);
const { setSavedFlows, savedFlows } = useContext(StoreContext); const { setSavedFlows, savedFlows, hasApiKey } = useContext(StoreContext);
const [tags, setTags] = useState<{ id: string; name: string }[]>([]); const [tags, setTags] = useState<{ id: string; name: string }[]>([]);
const tagListId = useRef<{ id: string; name: string }[]>([]); const tagListId = useRef<{ id: string; name: string }[]>([]);
const [renderPagination, setRenderPagination] = useState(false); const [renderPagination, setRenderPagination] = useState(false);
const filterComponent = useRef<boolean | null>(null); const filterComponent = useRef<boolean | null>(null);
const [tabActive, setTabActive] = useState("Flows");
useEffect(() => { useEffect(() => {
getStoreTags().then((res) => { getStoreTags().then((res) => {
@ -59,6 +58,16 @@ export default function StorePage(): JSX.Element {
}); });
}, []); }, []);
useEffect(() => {
filterComponent.current = false;
getSavedComponents()
.finally(() => handleGetComponents())
.catch((err) => {
setErrorApiKey(true);
console.error(err);
});
}, []);
async function getSavedComponents() { async function getSavedComponents() {
setLoading(true); setLoading(true);
const result = await getStoreSavedComponents(); const result = await getStoreSavedComponents();
@ -70,17 +79,12 @@ export default function StorePage(): JSX.Element {
setErrorApiKey(false); setErrorApiKey(false);
} }
useEffect(() => { async function getNumberSavedComponents() {
getNumberOfComponents().then((res) => { getCountComponents(filterComponent.current).then((res) => {
setTotalRowsCount(Number(res["count"])); setTotalRowsCount(Number(res["count"]));
setLoading(false);
}); });
getSavedComponents() }
.finally(() => handleGetComponents())
.catch((err) => {
setErrorApiKey(true);
console.error(err);
});
}, []);
const handleGetComponents = () => { const handleGetComponents = () => {
setLoading(true); setLoading(true);
@ -89,8 +93,7 @@ export default function StorePage(): JSX.Element {
getStoreComponents(index - 1, size, filterComponent.current) getStoreComponents(index - 1, size, filterComponent.current)
.then((res) => { .then((res) => {
setSearchData(res); setSearchData(res);
setData(res); getNumberSavedComponents();
setLoading(false);
setErrorApiKey(true); setErrorApiKey(true);
}) })
.catch((err) => { .catch((err) => {
@ -112,9 +115,9 @@ export default function StorePage(): JSX.Element {
searchComponent(inputText).then( searchComponent(inputText).then(
(res) => { (res) => {
setSearchData(res); setSearchData(res);
setData(res);
setLoading(false); setLoading(false);
setRenderPagination(false); setRenderPagination(false);
setTotalRowsCount(res.length);
}, },
(error) => { (error) => {
setLoading(false); setLoading(false);
@ -127,7 +130,6 @@ export default function StorePage(): JSX.Element {
setRenderPagination(true); setRenderPagination(true);
getStoreComponents(pageIndex, pageSize, filterComponent.current) getStoreComponents(pageIndex, pageSize, filterComponent.current)
.then((res) => { .then((res) => {
setData(res);
setSearchData(res); setSearchData(res);
setPageIndex(pageIndex); setPageIndex(pageIndex);
setPageSize(pageSize); setPageSize(pageSize);
@ -152,8 +154,8 @@ export default function StorePage(): JSX.Element {
searchComponent(null, 1, 10000, null, filterArray).then( searchComponent(null, 1, 10000, null, filterArray).then(
(res) => { (res) => {
setSearchData(res); setSearchData(res);
setData(res);
setLoading(false); setLoading(false);
setTotalRowsCount(res.length);
}, },
(error) => { (error) => {
setLoading(false); setLoading(false);
@ -162,7 +164,32 @@ export default function StorePage(): JSX.Element {
); );
} }
const [tabActive, setTabActive] = useState("Flows"); function handleChangeTab(tab: string) {
if (tab === "All") {
filterComponent.current = null;
} else if (tab === "Flows") {
filterComponent.current = false;
} else if (tab === "Components") {
filterComponent.current = true;
}
setPageIndex(1);
setPageSize(10);
handleGetComponents();
}
const handleOrderPage = (e) => {
let sortedData = cloneDeep(searchData);
if (e === "Popular") {
sortedData = sortedData.sort(
(a, b) => Number(b.liked_by_count) - Number(a.liked_by_count)
);
} else if (e === "Alphabetical") {
sortedData = sortedData.sort((a, b) => a.name.localeCompare(b.name));
}
setSearchData([...sortedData]);
};
return ( return (
<> <>
@ -181,7 +208,9 @@ export default function StorePage(): JSX.Element {
}} }}
> >
<Button <Button
className={`${errorApiKey ? "animate-pulse border-error" : ""}`} className={`${
errorApiKey && !hasApiKey ? "animate-pulse border-error" : ""
}`}
variant="primary" variant="primary"
> >
<IconComponent name="Key" className="main-page-nav-button" /> <IconComponent name="Key" className="main-page-nav-button" />
@ -209,12 +238,18 @@ export default function StorePage(): JSX.Element {
}} }}
value={inputText} value={inputText}
/> />
<Search className="absolute bottom-0 right-4 top-0 my-auto h-6 stroke-1 text-muted-foreground " /> <Search
onClick={() => {
handleSearch(inputText);
}}
className="absolute bottom-0 right-4 top-0 my-auto h-6 cursor-pointer stroke-1 text-muted-foreground"
/>
</div> </div>
<div className="ml-4 flex w-full gap-2 border-b border-border"> <div className="ml-4 flex w-full gap-2 border-b border-border">
<button <button
onClick={() => { onClick={() => {
setTabActive("All"); setTabActive("All");
handleChangeTab("All");
}} }}
className={ className={
tabActive === "All" tabActive === "All"
@ -227,6 +262,7 @@ export default function StorePage(): JSX.Element {
<button <button
onClick={() => { onClick={() => {
setTabActive("Flows"); setTabActive("Flows");
handleChangeTab("Flows");
}} }}
className={ className={
tabActive === "Flows" tabActive === "Flows"
@ -239,6 +275,7 @@ export default function StorePage(): JSX.Element {
<button <button
onClick={() => { onClick={() => {
setTabActive("Components"); setTabActive("Components");
handleChangeTab("Components");
}} }}
className={ className={
tabActive === "Components" tabActive === "Components"
@ -255,104 +292,7 @@ export default function StorePage(): JSX.Element {
</ShadTooltip> </ShadTooltip>
</div> </div>
</div> </div>
{/* <div className="flex items-center gap-3 text-sm">
<button className="flex h-8 items-center justify-between rounded-md border border-ring/60 px-4 py-2 text-sm text-primary hover:bg-muted">
<IconComponent name="CheckCircle2" className="mr-2 h-4 w-4 " />
Installed Locally
</button>
<Select
onValueChange={(value) => {
if (value === "Flow") {
filterComponent.current = false;
} else if (value === "Component") {
filterComponent.current = true;
} else {
filterComponent.current = null;
}
setPageIndex(1);
setPageSize(10);
handleGetComponents();
}}
>
<SelectTrigger>
<SelectValue placeholder="Component Types" />
</SelectTrigger>
<SelectContent>
<SelectItem value="">Both</SelectItem>
<SelectItem value="Flow">Flows</SelectItem>
<SelectItem value="Component">Components</SelectItem>
</SelectContent>
</Select>
<Select
onValueChange={(value) => {
if (value === "Flow") {
filterComponent.current = false;
} else if (value === "Component") {
filterComponent.current = true;
} else {
filterComponent.current = null;
}
setPageIndex(1);
setPageSize(10);
handleGetComponents();
}}
>
<SelectTrigger>
<SelectValue placeholder="Use Cases" />
</SelectTrigger>
<SelectContent>
<SelectItem value="">Both</SelectItem>
<SelectItem value="Flow">Flows</SelectItem>
<SelectItem value="Component">Components</SelectItem>
</SelectContent>
</Select>
<Select
onValueChange={(value) => {
if (value === "Flow") {
filterComponent.current = false;
} else if (value === "Component") {
filterComponent.current = true;
} else {
filterComponent.current = null;
}
setPageIndex(1);
setPageSize(10);
handleGetComponents();
}}
>
<SelectTrigger>
<SelectValue placeholder="Models" />
</SelectTrigger>
<SelectContent>
<SelectItem value="">Both</SelectItem>
<SelectItem value="Flow">Flows</SelectItem>
<SelectItem value="Component">Components</SelectItem>
</SelectContent>
</Select>
<Select
onValueChange={(value) => {
if (value === "Flow") {
filterComponent.current = false;
} else if (value === "Component") {
filterComponent.current = true;
} else {
filterComponent.current = null;
}
setPageIndex(1);
setPageSize(10);
handleGetComponents();
}}
>
<SelectTrigger>
<SelectValue placeholder="Payment" />
</SelectTrigger>
<SelectContent>
<SelectItem value="">Both</SelectItem>
<SelectItem value="Flow">Flows</SelectItem>
<SelectItem value="Component">Components</SelectItem>
</SelectContent>
</Select>
</div> */}
<div className="flex items-center gap-2 px-2"> <div className="flex items-center gap-2 px-2">
{!loading && {!loading &&
tags.map((i, idx) => ( tags.map((i, idx) => (
@ -383,29 +323,25 @@ export default function StorePage(): JSX.Element {
</div> </div>
<div className="flex items-end justify-between"> <div className="flex items-end justify-between">
<span className="px-0.5 text-sm text-muted-foreground"> <span className="px-0.5 text-sm text-muted-foreground">
2,117 results {!loading && (
<>
{totalRowsCount} {totalRowsCount > 0 ? "results" : "result"}
</>
)}
</span> </span>
<Select <Select
onValueChange={(value) => { onValueChange={(e) => {
if (value === "Flow") { handleOrderPage(e);
filterComponent.current = false;
} else if (value === "Component") {
filterComponent.current = true;
} else {
filterComponent.current = null;
}
setPageIndex(1);
setPageSize(10);
handleGetComponents();
}} }}
> >
<SelectTrigger> <SelectTrigger>
<SelectValue placeholder="Sort By" /> <SelectValue placeholder="Sort By" />
</SelectTrigger> </SelectTrigger>
<SelectContent> <SelectContent>
<SelectItem value="">Most Popular</SelectItem> <SelectItem value="Popular">Most Popular</SelectItem>
<SelectItem value="Flow">Most Recent</SelectItem> {/* <SelectItem value="Recent">Most Recent</SelectItem> */}
<SelectItem value="Component">Alphabetical</SelectItem> <SelectItem value="Alphabetical">Alphabetical</SelectItem>
</SelectContent> </SelectContent>
</Select> </Select>
</div> </div>
@ -418,17 +354,15 @@ export default function StorePage(): JSX.Element {
<SkeletonCardComponent /> <SkeletonCardComponent />
</> </>
) : ( ) : (
searchData searchData.map((item, idx) => {
.filter( console.log(item);
(f) =>
filteredCategories?.length === 0 || return (
filteredCategories.some( <>
(category) => category === f.is_component <MarketCardComponent key={idx} data={item} />
) </>
) );
.map((item, idx) => ( })
<MarketCardComponent key={idx} data={item} />
))
)} )}
</div> </div>
</div> </div>

View file

@ -3,4 +3,6 @@ export type storeContextType = {
setSavedFlows: (newState: Set<string>) => void; setSavedFlows: (newState: Set<string>) => void;
setHasStore: (store: boolean) => void; setHasStore: (store: boolean) => void;
hasStore: boolean; hasStore: boolean;
setHasApiKey: (key: boolean) => void;
hasApiKey: boolean;
}; };