stat card + aside
This commit is contained in:
parent
6e9e18fe98
commit
25b7b797cc
|
|
@ -12,6 +12,7 @@
|
|||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-filterable-table": "^0.3.439",
|
||||
"react-icons": "^4.4.0",
|
||||
"react-router-dom": "^6.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
@ -3640,6 +3641,7 @@
|
|||
},
|
||||
"node_modules/npm/node_modules/lodash._baseindexof": {
|
||||
"version": "3.1.0",
|
||||
"extraneous": true,
|
||||
"inBundle": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
|
|
@ -3654,16 +3656,19 @@
|
|||
},
|
||||
"node_modules/npm/node_modules/lodash._bindcallback": {
|
||||
"version": "3.0.1",
|
||||
"extraneous": true,
|
||||
"inBundle": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/npm/node_modules/lodash._cacheindexof": {
|
||||
"version": "3.0.2",
|
||||
"extraneous": true,
|
||||
"inBundle": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/npm/node_modules/lodash._createcache": {
|
||||
"version": "3.1.2",
|
||||
"extraneous": true,
|
||||
"inBundle": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
|
|
@ -3677,6 +3682,7 @@
|
|||
},
|
||||
"node_modules/npm/node_modules/lodash._getnative": {
|
||||
"version": "3.9.1",
|
||||
"extraneous": true,
|
||||
"inBundle": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
|
|
@ -3692,6 +3698,7 @@
|
|||
},
|
||||
"node_modules/npm/node_modules/lodash.restparam": {
|
||||
"version": "3.6.1",
|
||||
"extraneous": true,
|
||||
"inBundle": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
|
|
@ -5764,6 +5771,14 @@
|
|||
"react-dom": "^15.0.0 || ^16.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-icons": {
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.4.0.tgz",
|
||||
"integrity": "sha512-fSbvHeVYo/B5/L4VhB7sBA1i2tS8MkT0Hb9t2H1AVPkwGfVHLJCqyr2Py9dKMxsyM63Eng1GkdZfbWj+Fmv8Rg==",
|
||||
"peerDependencies": {
|
||||
"react": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/react-is": {
|
||||
"version": "16.13.1",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||
|
|
@ -5854,7 +5869,8 @@
|
|||
"node_modules/safe-buffer": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
|
||||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/sass": {
|
||||
"version": "1.54.8",
|
||||
|
|
@ -5885,6 +5901,7 @@
|
|||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
|
||||
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
}
|
||||
|
|
@ -8559,7 +8576,8 @@
|
|||
},
|
||||
"lodash._baseindexof": {
|
||||
"version": "3.1.0",
|
||||
"bundled": true
|
||||
"bundled": true,
|
||||
"extraneous": true
|
||||
},
|
||||
"lodash._baseuniq": {
|
||||
"version": "4.6.0",
|
||||
|
|
@ -8571,15 +8589,18 @@
|
|||
},
|
||||
"lodash._bindcallback": {
|
||||
"version": "3.0.1",
|
||||
"bundled": true
|
||||
"bundled": true,
|
||||
"extraneous": true
|
||||
},
|
||||
"lodash._cacheindexof": {
|
||||
"version": "3.0.2",
|
||||
"bundled": true
|
||||
"bundled": true,
|
||||
"extraneous": true
|
||||
},
|
||||
"lodash._createcache": {
|
||||
"version": "3.1.2",
|
||||
"bundled": true,
|
||||
"extraneous": true,
|
||||
"requires": {
|
||||
"lodash._getnative": "^3.0.0"
|
||||
}
|
||||
|
|
@ -8590,7 +8611,8 @@
|
|||
},
|
||||
"lodash._getnative": {
|
||||
"version": "3.9.1",
|
||||
"bundled": true
|
||||
"bundled": true,
|
||||
"extraneous": true
|
||||
},
|
||||
"lodash._root": {
|
||||
"version": "3.0.1",
|
||||
|
|
@ -8602,7 +8624,8 @@
|
|||
},
|
||||
"lodash.restparam": {
|
||||
"version": "3.6.1",
|
||||
"bundled": true
|
||||
"bundled": true,
|
||||
"extraneous": true
|
||||
},
|
||||
"lodash.union": {
|
||||
"version": "4.6.0",
|
||||
|
|
@ -10146,6 +10169,12 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"react-icons": {
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.4.0.tgz",
|
||||
"integrity": "sha512-fSbvHeVYo/B5/L4VhB7sBA1i2tS8MkT0Hb9t2H1AVPkwGfVHLJCqyr2Py9dKMxsyM63Eng1GkdZfbWj+Fmv8Rg==",
|
||||
"requires": {}
|
||||
},
|
||||
"react-is": {
|
||||
"version": "16.13.1",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||
|
|
@ -10211,7 +10240,8 @@
|
|||
"safe-buffer": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
|
||||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
|
||||
"dev": true
|
||||
},
|
||||
"sass": {
|
||||
"version": "1.54.8",
|
||||
|
|
@ -10235,7 +10265,8 @@
|
|||
"semver": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
|
||||
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
|
||||
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
|
||||
"dev": true
|
||||
},
|
||||
"source-map-js": {
|
||||
"version": "1.0.2",
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-filterable-table": "^0.3.439",
|
||||
"react-icons": "^4.4.0",
|
||||
"react-router-dom": "^6.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import "./assets/styles/style.scss";
|
|||
// Pages
|
||||
import Login from "./pages/Login";
|
||||
import Main from "./pages/Main";
|
||||
import Dashboard from "./pages/Dashboard";
|
||||
|
||||
const App = () => {
|
||||
const [user, setUser] = useState({
|
||||
|
|
@ -31,6 +32,7 @@ const App = () => {
|
|||
<div className="App">
|
||||
<Routes>
|
||||
<Route path="/" element={<Main />} />
|
||||
<Route path="/dashboard" element={<Main child={<Dashboard />} />} />
|
||||
<Route path="/login" element={<Login />} />
|
||||
</Routes>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30"><path stroke="#869AB8" stroke-width="2.25" stroke-linecap="round" stroke-miterlimit="10" d="M4 7h22M4 15h22M4 23h22"/></svg>
|
||||
|
Before Width: | Height: | Size: 184 B |
|
|
@ -1 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g data-name="Layer 2"><g data-name="grid"><rect width="24" height="24" opacity="0"/><path d="M9 3H5a2 2 0 0 0-2 2v4a2 2 0 0 0 2 2h4a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2zM5 9V5h4v4z"/><path d="M19 3h-4a2 2 0 0 0-2 2v4a2 2 0 0 0 2 2h4a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2zm-4 6V5h4v4z"/><path d="M9 13H5a2 2 0 0 0-2 2v4a2 2 0 0 0 2 2h4a2 2 0 0 0 2-2v-4a2 2 0 0 0-2-2zm-4 6v-4h4v4z"/><path d="M19 13h-4a2 2 0 0 0-2 2v4a2 2 0 0 0 2 2h4a2 2 0 0 0 2-2v-4a2 2 0 0 0-2-2zm-4 6v-4h4v4z"/></g></g></svg>
|
||||
|
Before Width: | Height: | Size: 540 B |
|
|
@ -1 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="black" d="M256 250.8a73.34 73.34 0 1 1 73.33-73.34A73.41 73.41 0 0 1 256 250.8zm0-125.53a52.2 52.2 0 1 0 52.19 52.19A52.25 52.25 0 0 0 256 125.27zm117.07 282.6H138.93l-10.57-10.57a127.64 127.64 0 1 1 255.28 0zM150 386.73h212a106.51 106.51 0 0 0-212 0z"/></svg>
|
||||
|
Before Width: | Height: | Size: 334 B |
|
|
@ -2,12 +2,15 @@
|
|||
@include transition-std;
|
||||
overflow: hidden;
|
||||
max-width: 0;
|
||||
min-width: 0rem;
|
||||
width: 100%;
|
||||
|
||||
&__img {
|
||||
width: 3rem;
|
||||
height: 3rem;
|
||||
}
|
||||
|
||||
&.active {
|
||||
max-width: 100%;
|
||||
min-width: 20rem;
|
||||
max-width: 25rem;
|
||||
@include transition-std;
|
||||
}
|
||||
|
||||
|
|
@ -20,11 +23,15 @@
|
|||
&__element {
|
||||
@include transition-std;
|
||||
background: transparent;
|
||||
display: flex;
|
||||
gap: 0.6rem;
|
||||
align-items: center;
|
||||
|
||||
font-size: 1.6rem;
|
||||
cursor: pointer;
|
||||
|
||||
a {
|
||||
a,
|
||||
div {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
|
|
@ -50,6 +57,10 @@
|
|||
}
|
||||
|
||||
&--title {
|
||||
&:not(:first-child) {
|
||||
padding-top: 1rem;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
cursor: default !important;
|
||||
background: transparent !important;
|
||||
font-size: 1.4rem;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,58 @@
|
|||
.dashboard {
|
||||
&__head {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
|
||||
h1 {
|
||||
font-size: 3.2rem;
|
||||
}
|
||||
}
|
||||
|
||||
&__img {
|
||||
width: 4rem;
|
||||
height: 4rem;
|
||||
}
|
||||
|
||||
&__content {
|
||||
&__stats {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
&.inner {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4rem;
|
||||
}
|
||||
}
|
||||
|
||||
.statcard {
|
||||
cursor: default;
|
||||
@include transition-std;
|
||||
transform: translateY(0);
|
||||
border-radius: 0.5rem;
|
||||
color: #fff;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
padding: 2rem;
|
||||
|
||||
&:hover {
|
||||
@include transition-std;
|
||||
transform: translateY(-1rem);
|
||||
}
|
||||
|
||||
&.yellow {
|
||||
background: #c69500;
|
||||
}
|
||||
|
||||
span {
|
||||
font-size: 2.4rem;
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: 1.6rem;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
@import url("https://fonts.googleapis.com/css2?family=Montserrat&display=swap");
|
||||
@import url("https://fonts.googleapis.com/css2?family=Poppins&display=swap");
|
||||
|
||||
* {
|
||||
font-family: "Montserrat", sans-serif;
|
||||
font-family: "Poppins", sans-serif;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
border: 0.1rem solid #c8c8c8;
|
||||
|
||||
&.active {
|
||||
height: 15rem;
|
||||
height: 16.3rem;
|
||||
opacity: 1;
|
||||
@include transition-std;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,3 +3,4 @@
|
|||
@import "./nav";
|
||||
@import "./main";
|
||||
@import "./aside";
|
||||
@import "./dashboard";
|
||||
|
|
|
|||
|
|
@ -1,31 +1,60 @@
|
|||
// Modules
|
||||
import React from "react";
|
||||
import { useContext } from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import { UserContext } from "../context/UserContext";
|
||||
|
||||
// Icons
|
||||
import Grid from "../assets/icons/grid-outline.svg";
|
||||
import { BsFillFileEarmarkPostFill } from "react-icons/bs";
|
||||
import { AiOutlineBlock } from "react-icons/ai";
|
||||
import { MdOutlineManageAccounts } from "react-icons/md";
|
||||
import { CgDetailsLess } from "react-icons/cg";
|
||||
import { BiLogOut } from "react-icons/bi";
|
||||
|
||||
// Types
|
||||
import { userContextType } from "../types/user";
|
||||
interface Props {
|
||||
aside: boolean;
|
||||
setAside: React.Dispatch<boolean>;
|
||||
}
|
||||
|
||||
const Aside = ({ aside, setAside }: Props) => {
|
||||
const { setUser }: userContextType = useContext(UserContext);
|
||||
return (
|
||||
<aside className={aside ? "aside active" : "aside"}>
|
||||
<ul className="aside__list">
|
||||
<li className="aside__list__element aside__list__element--title">
|
||||
<AiOutlineBlock className="aside__img" />
|
||||
<h2>Elements</h2>
|
||||
</li>
|
||||
<li className="aside__list__element">
|
||||
<Link to={"/posts"}>
|
||||
<div className="aside__list__element__img">
|
||||
<img src={Grid} alt="" />
|
||||
</div>
|
||||
<BsFillFileEarmarkPostFill className="aside__list__element__img" />
|
||||
<span>Posts</span>
|
||||
</Link>
|
||||
</li>
|
||||
<li className="aside__list__element aside__list__element--title">
|
||||
<MdOutlineManageAccounts className="aside__img" />
|
||||
<h2>Account</h2>
|
||||
</li>
|
||||
<li className="aside__list__element">
|
||||
<Link to={"/user_details"}>
|
||||
<CgDetailsLess className="aside__list__element__img" />
|
||||
<span>Details</span>
|
||||
</Link>
|
||||
</li>
|
||||
<li
|
||||
className="aside__list__element"
|
||||
onClick={() => {
|
||||
localStorage.removeItem("userData");
|
||||
setUser({ username: "", accessLevel: "" });
|
||||
}}
|
||||
>
|
||||
<div>
|
||||
<BiLogOut className="aside__list__element__img" />
|
||||
<span>Log out</span>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</aside>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,14 +1,16 @@
|
|||
// Modules
|
||||
import { useContext, useState } from "react";
|
||||
import { UserContext } from "../context/UserContext";
|
||||
import { Link } from "react-router-dom";
|
||||
|
||||
// Icons
|
||||
import Orient from "../assets/icons/logo_orient.svg";
|
||||
import Burger from "../assets/icons/burger.svg";
|
||||
import Profile from "../assets/icons/profile.svg";
|
||||
import { GiHamburgerMenu } from "react-icons/gi";
|
||||
import { AiOutlineUser } from "react-icons/ai";
|
||||
|
||||
// Types
|
||||
import { userContextType } from "../types/user";
|
||||
|
||||
interface Props {
|
||||
aside: boolean;
|
||||
setAside: React.Dispatch<boolean>;
|
||||
|
|
@ -22,16 +24,14 @@ const Nav = ({ aside, setAside }: Props) => {
|
|||
<div className="container">
|
||||
<div className="nav inner">
|
||||
<div className="nav__left">
|
||||
<div className="nav__img">
|
||||
<Link to={"/dashboard"} className="nav__img">
|
||||
<img src={Orient} alt="orient" />
|
||||
</div>
|
||||
<button
|
||||
</Link>
|
||||
<GiHamburgerMenu
|
||||
type="button"
|
||||
className="nav__btn"
|
||||
onClick={() => setAside(!aside)}
|
||||
>
|
||||
<img src={Burger} alt="" />
|
||||
</button>
|
||||
/>
|
||||
</div>
|
||||
<div className="nav__right">
|
||||
<div
|
||||
|
|
@ -40,9 +40,7 @@ const Nav = ({ aside, setAside }: Props) => {
|
|||
setDropdown(!dropdown);
|
||||
}}
|
||||
>
|
||||
<div className="nav__right__user__img">
|
||||
<img src={Profile} alt="" />
|
||||
</div>
|
||||
<AiOutlineUser className="nav__right__user__img" />
|
||||
<span>Profile</span>
|
||||
<div
|
||||
className={dropdown ? "nav__dropdown active" : "nav__dropdown"}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
// Modules
|
||||
|
||||
// Types
|
||||
interface Props {
|
||||
topNumber?: number;
|
||||
text: string;
|
||||
color: string;
|
||||
}
|
||||
|
||||
const StatCard = ({ color, topNumber, text }: Props) => {
|
||||
return (
|
||||
<div className={`statcard ${color}`}>
|
||||
<span>{topNumber}</span>
|
||||
<p>{text}</p>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default StatCard;
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
// Modules
|
||||
|
||||
// Icons
|
||||
import { AiOutlineDashboard } from "react-icons/ai";
|
||||
|
||||
// Components
|
||||
import StatCard from "../components/StatCard";
|
||||
|
||||
const Dashboard = () => {
|
||||
return (
|
||||
<main className="dashboard">
|
||||
<div className="container">
|
||||
<div className="dashboard inner">
|
||||
<div className="dashboard__head">
|
||||
<AiOutlineDashboard className="dashboard__img" />
|
||||
<h1>Dashboard</h1>
|
||||
</div>
|
||||
<div className="dashboard__content__stats">
|
||||
<StatCard
|
||||
color="yellow"
|
||||
text="Lorem, ipsum dolor sit amet consectetur adipisicing elit."
|
||||
topNumber={123}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
);
|
||||
};
|
||||
|
||||
export default Dashboard;
|
||||
|
|
@ -1,6 +1,9 @@
|
|||
// Modules
|
||||
import { useState, useContext, useEffect } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import {
|
||||
useNavigate,
|
||||
// useLocation
|
||||
} from "react-router-dom";
|
||||
import { UserContext } from "../context/UserContext";
|
||||
|
||||
// Components
|
||||
|
|
@ -12,9 +15,14 @@ import { userContextType } from "../types/user";
|
|||
|
||||
const Main = ({ child }: any) => {
|
||||
const navigate = useNavigate();
|
||||
// const location = useLocation();
|
||||
const { user, setUser }: userContextType = useContext(UserContext);
|
||||
const [aside, setAside] = useState(true);
|
||||
|
||||
// useEffect(() => {
|
||||
// if(location.pathname.includes('dashboard'))
|
||||
// }, [])
|
||||
|
||||
useEffect(() => {
|
||||
if (!user.username) {
|
||||
navigate("/login");
|
||||
|
|
|
|||
Loading…
Reference in New Issue