adding features store

This commit is contained in:
cristhianzl 2023-10-25 17:49:47 -03:00
commit 3e315012e1
10 changed files with 168 additions and 13 deletions

View file

@ -6,6 +6,7 @@ import { USER_PROJECTS_HEADER } from "../../constants/constants";
import { alertContext } from "../../contexts/alertContext";
import { AuthContext } from "../../contexts/authContext";
import { darkContext } from "../../contexts/darkContext";
import { StoreContext } from "../../contexts/storeContext";
import { TabsContext } from "../../contexts/tabsContext";
import { gradients } from "../../utils/styleUtils";
import IconComponent from "../genericIconComponent";
@ -27,6 +28,7 @@ export default function Header(): JSX.Element {
const { notificationCenter } = useContext(alertContext);
const location = useLocation();
const { logout, autoLogin, isAdmin, userData } = useContext(AuthContext);
const { hasStore } = useContext(StoreContext);
const { stars, gradientIndex } = useContext(darkContext);
const navigate = useNavigate();
@ -64,16 +66,18 @@ export default function Header(): JSX.Element {
<div className="flex-1">Community Examples</div>
</Button>
</Link>
<Link to="/store">
<Button
className="gap-2"
variant={location.pathname === "/store" ? "primary" : "secondary"}
size="sm"
>
<IconComponent name="Store" className="h-4 w-4" />
<div className="flex-1">Store</div>
</Button>
</Link>
{hasStore && (
<Link to="/store">
<Button
className="gap-2"
variant={location.pathname === "/store" ? "primary" : "secondary"}
size="sm"
>
<IconComponent name="Store" className="h-4 w-4" />
<div className="flex-1">Store</div>
</Button>
</Link>
)}
</div>
<div className="header-end-division">
<div className="header-end-display">

View file

@ -0,0 +1,12 @@
import { useContext } from "react";
import { Navigate } from "react-router-dom";
import { StoreContext } from "../../contexts/storeContext";
export const StoreGuard = ({ children }) => {
const { hasStore } = useContext(StoreContext);
if (!hasStore) {
return <Navigate to="/flows" replace />;
}
return children;
};

View file

@ -1,4 +1,5 @@
import { createContext, useState } from "react";
import { checkHasStore } from "../controllers/API";
import { storeContextType } from "../types/contexts/store";
import { FlowType } from "../types/flow";
@ -6,15 +7,24 @@ import { FlowType } from "../types/flow";
const initialValue = {
savedFlows: {},
setSavedFlows: () => {},
hasStore: false,
setHasStore: () => {},
};
export const StoreContext = createContext<storeContextType>(initialValue);
export function StoreProvider({ children }) {
const [savedFlows, setSavedFlows] = useState<{ [key: string]: FlowType }>({});
const [hasStore, setHasStore] = useState(false);
checkHasStore().then((res) => {
setHasStore(res[0].has_store);
});
return (
<StoreContext.Provider value={{ savedFlows, setSavedFlows }}>
<StoreContext.Provider
value={{ savedFlows, setSavedFlows, hasStore, setHasStore }}
>
{children}
</StoreContext.Provider>
);

View file

@ -662,3 +662,17 @@ export async function searchComponent(
throw error;
}
}
export async function checkHasStore() {
try {
const res = await api.get(
`https://65384701a543859d1bb15e63.mockapi.io/Store`
);
if (res.status === 200) {
return res.data;
}
} catch (error) {
console.log("Error:", error);
throw error;
}
}

View file

@ -19,6 +19,7 @@ export default function ComponentsComponent() {
isLoading,
} = useContext(TabsContext);
const { setErrorData } = useContext(alertContext);
const dropdownOptions = [
{
name: "Import from JSON",
@ -69,6 +70,7 @@ export default function ComponentsComponent() {
}
}
};
return (
<div
onDragOver={dragOver}

View file

@ -0,0 +1,70 @@
import { useContext, useEffect, useState } from "react";
import { alertContext } from "../../../../contexts/alertContext";
import { AuthContext } from "../../../../contexts/authContext";
import { TabsContext } from "../../../../contexts/tabsContext";
import { getStoreComponents } from "../../../../controllers/API";
import { FlowComponent } from "../../../../types/store";
import { MarketCardComponent } from "../../../StorePage/components/market-card";
export default function SavedComponents(): JSX.Element {
const { setTabId } = useContext(TabsContext);
const { setApiKey, apiKey } = useContext(AuthContext);
// set null id
useEffect(() => {
setTabId("");
}, []);
const [data, setData] = useState<FlowComponent[]>([]);
const [loading, setLoading] = useState(false);
const [filteredCategories, setFilteredCategories] = useState(new Set());
const { setErrorData } = useContext(alertContext);
useEffect(() => {
handleGetComponents();
}, []);
const handleGetComponents = () => {
setLoading(true);
getStoreComponents(1, 10)
.then((res) => {
setLoading(false);
setData(res);
})
.catch((err) => {
setLoading(false);
setErrorData({
title: "Error to get components.",
list: [err["response"]["data"]["detail"]],
});
});
};
const loadingWithApiKey = loading;
const renderComponents = !loading;
return (
<>
{renderComponents && (
<div className="flex w-full flex-col gap-4 p-4">
<div className="mt-6 grid w-full gap-4 md:grid-cols-2 lg:grid-cols-3">
{data
.filter(
(f) =>
Array.from(filteredCategories).length === 0 ||
filteredCategories.has(f.is_component)
)
.map((item, idx) => (
<MarketCardComponent key={idx} data={item} />
))}
</div>
</div>
)}
{loadingWithApiKey && (
<div className="flex w-full flex-col gap-4 p-4">Loading...</div>
)}
</>
);
}

View file

@ -8,6 +8,7 @@ import { Button } from "../../components/ui/button";
import { Separator } from "../../components/ui/separator";
import { USER_PROJECTS_HEADER } from "../../constants/constants";
import { alertContext } from "../../contexts/alertContext";
import { StoreContext } from "../../contexts/storeContext";
import { TabsContext } from "../../contexts/tabsContext";
export default function HomePage(): JSX.Element {
const {
@ -20,6 +21,7 @@ export default function HomePage(): JSX.Element {
isLoading,
} = useContext(TabsContext);
const { setErrorData } = useContext(alertContext);
const { hasStore } = useContext(StoreContext);
const dropdownOptions = [
{
name: "Import from JSON",
@ -40,6 +42,13 @@ export default function HomePage(): JSX.Element {
},
];
if (hasStore) {
sidebarNavItems.push({
title: "Saved Components",
href: "/saved-components",
});
}
// Set a null id
useEffect(() => {
setTabId("");

View file

@ -1,6 +1,7 @@
import { cloneDeep } from "lodash";
import { Link, Search } from "lucide-react";
import { useContext, useEffect, useState } from "react";
import PaginatorComponent from "../../components/PaginatorComponent";
import IconComponent from "../../components/genericIconComponent";
import Header from "../../components/headerComponent";
import { Badge } from "../../components/ui/badge";
@ -40,6 +41,11 @@ export default function StorePage(): JSX.Element {
const [errorApiKey, setErrorApiKey] = useState(false);
const { setErrorData } = useContext(alertContext);
const { addFlow } = useContext(TabsContext);
const [totalRowsCount, setTotalRowsCount] = useState(0);
const [size, setPageSize] = useState(10);
const [index, setPageIndex] = useState(1);
function handleChangePagination(pageIndex: number, pageSize: number) {}
useEffect(() => {
handleGetComponents();
@ -66,11 +72,15 @@ export default function StorePage(): JSX.Element {
};
const handleSearch = (inputText: string) => {
setLoading(true);
searchComponent(inputText).then(
(res) => {
setLoading(false);
setSearchData(res);
},
(error) => {}
(error) => {
setLoading(false);
}
);
};
@ -198,6 +208,15 @@ export default function StorePage(): JSX.Element {
<MarketCardComponent key={idx} data={item} />
))}
</div>
<PaginatorComponent
pageIndex={index}
pageSize={size}
totalRowsCount={totalRowsCount}
paginate={(pageSize, pageIndex) => {
handleChangePagination(pageIndex, pageSize);
}}
></PaginatorComponent>
</div>
)}

View file

@ -3,6 +3,7 @@ import { ProtectedAdminRoute } from "./components/authAdminGuard";
import { ProtectedRoute } from "./components/authGuard";
import { ProtectedLoginRoute } from "./components/authLoginGuard";
import { CatchAllRoute } from "./components/catchAllRoutes";
import { StoreGuard } from "./components/storeGuard";
import AdminPage from "./pages/AdminPage";
import LoginAdminPage from "./pages/AdminPage/LoginPage";
import ApiKeysPage from "./pages/ApiKeysPage";
@ -11,6 +12,7 @@ import FlowPage from "./pages/FlowPage";
import HomePage from "./pages/MainPage";
import ComponentsComponent from "./pages/MainPage/components/components";
import FlowsComponent from "./pages/MainPage/components/flows";
import SavedComponents from "./pages/MainPage/components/saved-components";
import ProfileSettingsPage from "./pages/ProfileSettingsPage";
import StorePage from "./pages/StorePage";
import ViewPage from "./pages/ViewPage";
@ -38,6 +40,14 @@ const Router = () => {
>
<Route path="flows" element={<FlowsComponent />} />
<Route path="components" element={<ComponentsComponent />} />
<Route
path="saved-components"
element={
<StoreGuard>
<SavedComponents />
</StoreGuard>
}
/>
</Route>
<Route
path="/community"
@ -51,10 +61,13 @@ const Router = () => {
path="/store"
element={
<ProtectedRoute>
<StorePage />
<StoreGuard>
<StorePage />
</StoreGuard>
</ProtectedRoute>
}
/>
<Route path="/flow/:id/">
<Route
path=""

View file

@ -3,4 +3,6 @@ import { FlowType } from "../flow";
export type storeContextType = {
savedFlows: { [key: string]: FlowType };
setSavedFlows: (newState: { [key: string]: FlowType }) => void;
setHasStore: (store: boolean) => void;
hasStore: boolean;
};