Skip to content

Commit

Permalink
Merge pull request #4 from mwlt68/feature/product
Browse files Browse the repository at this point in the history
🎨 [Feature] Product Page
  • Loading branch information
mwlt68 authored Mar 12, 2023
2 parents 14b67f0 + 2e0041b commit 8cc1bac
Show file tree
Hide file tree
Showing 37 changed files with 1,328 additions and 328 deletions.
40 changes: 23 additions & 17 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,30 @@
import { BrowserRouter as Router, Routes,Route } from "react-router-dom";
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
import HomePage from "./pages/home/HomePage";
import LoginPage from "./pages/login/LoginPage";
import ProductPage from "./pages/product/ProductPage";
import RegisterPage from "./pages/register/RegisterPage";
import { NavigationConsts } from "./utils/consts/NavigationConsts";
import PrivateRoutes from "./utils/helpers/PrivateRoute";
import PrivateRoutes from "./components/ui/private-route/PrivateRoute";

function App(){

return (
<Router>
<Routes>
<Route path={NavigationConsts.LoginPage} element={<LoginPage />} />
<Route path={NavigationConsts.RegisterPage} element={<RegisterPage />} />
<Route
element={<PrivateRoutes/>}>
<Route element = {<HomePage/>} path = {NavigationConsts.HomePage} />
</Route>
</Routes>
</Router>
);
function App() {
return (
<Router>
<Routes>
<Route path={NavigationConsts.LoginPage} element={<LoginPage />} />
<Route
path={NavigationConsts.RegisterPage}
element={<RegisterPage />}
/>
<Route element={<PrivateRoutes />}>
<Route element={<HomePage />} path={NavigationConsts.HomePage} />
<Route
element={<ProductPage />}
path={NavigationConsts.ProductPage}
/>
</Route>
</Routes>
</Router>
);
}

export default App;
export default App;
1 change: 1 addition & 0 deletions src/assets/lotties/image-not-preview.json

Large diffs are not rendered by default.

26 changes: 26 additions & 0 deletions src/components/ui/alert-snackbar/AlertSnackbar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { Alert, AlertColor, Snackbar } from "@mui/material";

type Props = {
alertText?: string;
closeHandle: Function;
severity?: AlertColor;
autoHideDuration?: number;
}

export function AlertSnackBar(props:Props) {
return (
<Snackbar
open={props.alertText != null}
autoHideDuration={props.autoHideDuration ?? 4000}
onClose={(e) => props.closeHandle()}
anchorOrigin={{ vertical: "bottom", horizontal: "center" }}
>
<Alert
severity={props.severity ?? "error"}
sx={{ width: "100%", whiteSpace: "pre-line" }}
>
{props.alertText}
</Alert>
</Snackbar>
);
}
36 changes: 36 additions & 0 deletions src/components/ui/error-page/ErrorPageWithLottie.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { Alert, Box } from "@mui/material";
import Lottie from "lottie-react";
import errorAnimation from "../../../assets/lotties/error.json"

type Props = {
children: any;
message:string|null|undefined;
}
const styles={
container:{
display: "flex",
height: "100%",
width: "100%",
flexDirection: "column",
alignItems:"center",
justifyContent: "center",
gap: "1rem"
},
alert:{
maxWidth:"50%"
}
}

export function ErrorPageWithLottie(props:Props){
if(props.message != null){
return(
<Box sx={styles.container}>
<Lottie animationData={errorAnimation} loop={true}/>
<Alert variant="filled" severity="error" sx={styles.alert} >
{props.message}
</Alert>
</Box>
);
}
else return props.children
}
83 changes: 83 additions & 0 deletions src/components/ui/image-picker/ImagePicker.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import { Box, IconButton } from "@mui/material";
import { styles } from "./ImagePickerStyle";
import AddPhotoAlternateIcon from "@mui/icons-material/AddPhotoAlternate";
import RemoveCircleIcon from "@mui/icons-material/RemoveCircle";
import PhotoIcon from "@mui/icons-material/Photo";

export type ImageUrlHandleFunction = () => string | undefined;
export type ImageChangeHandleFunction = (file: File | undefined) => void;
export type ImageOperationProps = {
imageUrlHandle: ImageUrlHandleFunction;
imageChangeHandle: ImageChangeHandleFunction;
};

export function ImagePicker(props: ImageOperationProps) {
return (
<Box sx={styles.imagePickerContainer}>
{!props.imageUrlHandle() ? (
<ImagePick imageChangeHandle={props.imageChangeHandle} />
) : (
<ImageShow
imageUrlHandle={props.imageUrlHandle}
imageChangeHandle={props.imageChangeHandle}
/>
)}
</Box>
);
}

function ImageShow(props: {
imageUrlHandle: Function;
imageChangeHandle: Function;
}) {
return (
<Box sx={styles.imagePickedBox}>
<Box
component="img"
src={props.imageUrlHandle()}
sx={styles.imagePickerImageBox}
/>
<Box sx={styles.imagePickerOperationBox}>
<IconButton onClick={() => props.imageChangeHandle(undefined)}>
<RemoveCircleIcon fontSize="large" color="error" />
</IconButton>
<ImageInput imageChangeHandle={props.imageChangeHandle}>
<IconButton component="span">
<PhotoIcon fontSize="large" color="success" />
</IconButton>
</ImageInput>
</Box>
</Box>
);
}

function ImagePick(props: { imageChangeHandle: Function }) {
return (
<>
<ImageInput imageChangeHandle={props.imageChangeHandle}>
<IconButton
color="success"
sx={styles.imagePickerIconButton}
component="span"
>
<AddPhotoAlternateIcon fontSize="large" />
</IconButton>
</ImageInput>
</>
);
}

function ImageInput(props: { imageChangeHandle: Function; children: any }) {
return (
<>
<input
accept="image/*"
type="file"
id="select-image"
style={{ display: "none" }}
onChange={(e) => props.imageChangeHandle(e.target.files?.item(0))}
/>
<label htmlFor="select-image">{props.children}</label>
</>
);
}
34 changes: 34 additions & 0 deletions src/components/ui/image-picker/ImagePickerStyle.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
export const styles={
imagePickerContainer:{
display: "flex",
justifyContent: "center",
},
imagePickerIconButton:{
transform: "scale(2)",
margin: "0.5rem"
},
imagePickedBox:{
display: "flex",
justifyContent: "center",
alignItems: "start",
gap: "0.2rem",
},
imagePickerOperationBox:{
display: "flex",
justifyContent: "start",
flexDirection: "column",
alignItems: "start",
gap: "0.2rem",
},
imagePickerDeleteButton:{
color: "black",
backgroundColor: "#ff6961",
margin: "1rem"
},
imagePickerImageBox:{
height: "250px",
width: "250px",
padding: "0.3rem",
border: 1
}
}
37 changes: 34 additions & 3 deletions src/components/ui/page-loading/PageLoading.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,42 @@
import { Box } from "@mui/material";
import Lottie from "lottie-react";
import groovyWalkAnimation from "../../../assets/lotties/groovy-walk-cycle.json"

const styles = {
lottie : {
height:"300px"
},
container: {
display: "flex",
height: "100%",
width: "100%",
flexDirection: "column",
alignItems:"center",
justifyContent: "center",
gap: "1rem"
},
}
type Props = {
children: any;
isLoading:boolean;
}

function PageLoading(props: Props){
if(props.isLoading){
return <Lottie animationData={groovyWalkAnimation} loop={true} style={styles.lottie}/>
}
else return props.children;
}
export default function PageLoading(){
return <Lottie animationData={groovyWalkAnimation} loop={true} style={styles.lottie}/>
}

function CenterPageLoading(props: Props){
if(props.isLoading){
return(
<Box sx={styles.container}>
<Lottie animationData={groovyWalkAnimation} loop={true} style={styles.lottie}/>
</Box>
)
}
else return props.children;
}

export { PageLoading , CenterPageLoading}
14 changes: 14 additions & 0 deletions src/components/ui/private-route/PrivateRoute.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { Outlet, Navigate } from "react-router";
import { NavigationConsts } from "../../../utils/consts/NavigationConsts";
import { AuthManager } from "../../../utils/helpers/AuthManager";

const PrivateRoutes = () => {
let hasToken = AuthManager.hasToken();
return (
<div>
{hasToken ? <Outlet /> : <Navigate to={NavigationConsts.LoginPage} />}
</div>
);
};

export default PrivateRoutes;
34 changes: 34 additions & 0 deletions src/components/ui/side-bar/AdvancedSideBar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { AlertColor } from "@mui/lab";
import { useState } from "react";
import { AlertSnackBar } from "../alert-snackbar/AlertSnackbar";
import { ErrorPageWithLottie } from "../error-page/ErrorPageWithLottie";
import { CenterPageLoading } from "../page-loading/PageLoading";
import SideBar from "./SideBar";

type Props = {
children: any;
isLoading: boolean;
alertCloseHandler?:Function;
errorMessage?: string | null | undefined;
alertText?: string;
alertColor?: AlertColor;
};

export function AdvancedSideBar(props: Props) {
return (
<>
<SideBar>
<CenterPageLoading isLoading={props.isLoading}>
<ErrorPageWithLottie message={props.errorMessage}>
{props.children}
</ErrorPageWithLottie>
</CenterPageLoading>
</SideBar>
<AlertSnackBar
alertText={props.alertText}
closeHandle={props.alertCloseHandler ?? new Function()}
severity={props.alertColor}
/>
</>
);
}
17 changes: 11 additions & 6 deletions src/components/ui/side-bar/SideBar.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import Box from "@mui/material/Box";
import { Link } from "react-router-dom";
import { Link, useNavigate } from "react-router-dom";
import { Button, IconButton } from "@mui/material";
import { Menu, MenuItem, Sidebar, useProSidebar } from "react-pro-sidebar";
import LogoutIcon from "@mui/icons-material/Logout";
Expand All @@ -9,9 +9,9 @@ import ContactsOutlinedIcon from "@mui/icons-material/ContactsOutlined";
import { ProjectConsts } from "../../../utils/consts/ProjectConsts";
import { NavigationConsts } from "../../../utils/consts/NavigationConsts";
import { styles } from "./SideBarStyle";
import { AuthManager } from "../../../utils/helpers/AuthManager";

export default function SideBar(props:any) {

export default function SideBar(props: any) {
const menuItems = { home: "Home", contact: "Contacts" };

const { collapseSidebar, toggleSidebar, collapsed, toggled } =
Expand All @@ -21,6 +21,7 @@ export default function SideBar(props:any) {
toggleSidebar();
collapseSidebar();
};
const navigate = useNavigate();

return (
<Box sx={styles.container}>
Expand All @@ -32,9 +33,7 @@ export default function SideBar(props:any) {
<SideBarFooter />
</Box>
</Sidebar>
<main style={styles.main}>
{props.children}
</main>
<main style={styles.main}>{props.children}</main>
</Box>
);

Expand Down Expand Up @@ -67,12 +66,18 @@ export default function SideBar(props:any) {
);
}

function SignOutClickHandle() {
AuthManager.logout();
navigate(NavigationConsts.LoginPage);
}

function SideBarFooter() {
return (
<Button
style={styles.signOutButton}
variant="contained"
startIcon={!toggled && <LogoutIcon style={styles.signOutButtonIcon} />}
onClick={SignOutClickHandle}
>
Sign Out
</Button>
Expand Down
Loading

0 comments on commit 8cc1bac

Please sign in to comment.