Skip to content

Commit e4fa6a9

Browse files
authored
Merge pull request #1 from Soliman3/develop
Pull develop
2 parents 733d975 + 16208cb commit e4fa6a9

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+3285
-459
lines changed

admin/.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
/node_modules
55
/.pnp
66
.pnp.js
7-
7+
firebase.js
88
# testing
99
/coverage
1010

admin/package-lock.json

Lines changed: 1881 additions & 100 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

admin/package.json

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,25 @@
99
"@mui/material": "^5.10.1",
1010
"@mui/styled-engine-sc": "^5.10.1",
1111
"@mui/x-data-grid": "^5.15.3",
12+
"@reduxjs/toolkit": "^1.8.5",
1213
"@testing-library/jest-dom": "^5.16.5",
1314
"@testing-library/react": "^13.3.0",
1415
"@testing-library/user-event": "^13.5.0",
16+
"axios": "^0.27.2",
17+
"firebase": "^9.9.4",
18+
"moment": "^2.29.4",
1519
"react": "^18.2.0",
1620
"react-dom": "^18.2.0",
21+
"react-redux": "^8.0.2",
1722
"react-router-dom": "^6.3.0",
1823
"react-scripts": "5.0.1",
1924
"recharts": "^2.1.13",
25+
"redux-persist": "^6.0.0",
2026
"styled-components": "^5.3.5",
2127
"web-vitals": "^2.1.4"
2228
},
2329
"scripts": {
24-
"start": "react-scripts start",
30+
"start": "set PORT=3001 && react-scripts start",
2531
"build": "react-scripts build",
2632
"test": "react-scripts test",
2733
"eject": "react-scripts eject"

admin/src/App.js

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
import styled from "styled-components";
1+
import { useSelector } from "react-redux";
22

33
// import React Router Dom for Routing...
44
import { BrowserRouter, Routes, Route } from "react-router-dom";
5+
import { PrivateRoutes, RedirectRoute } from "./utils/PrivateRoutes";
56

67
// import required Pages & main components...
78
import TopBar from "./components/TopBar";
@@ -13,27 +14,41 @@ import NewUser from "./pages/NewUser";
1314
import ProductList from "./pages/ProductList";
1415
import ProductSinglePage from "./pages/ProductSinglePage";
1516
import NewProduct from "./pages/NewProduct";
17+
import Login from "./pages/Login";
18+
import Page404 from "./pages/Page404";
19+
20+
// import styled components library for css styling...
21+
import styled from "styled-components";
1622

1723
// Styling..
1824
const Container = styled.div``;
1925
const Main = styled.div`
2026
display: flex;
21-
`;
27+
`
28+
// Main React component...
2229
function App() {
30+
const user = useSelector((state) => state.user?.currentUser?.isAdmin);
2331
return (
2432
<Container>
2533
<BrowserRouter>
2634
<TopBar />
2735
<Main>
28-
<SideBar />
36+
{user && <SideBar />}
37+
2938
<Routes>
30-
<Route exact path="/" element={<Home />} />
31-
<Route path="/users" element={<UserList />} />
32-
<Route path="/user/:id" element={<UserSinglePage />} />
33-
<Route path="/newuser" element={<NewUser />} />
34-
<Route path="/products" element={<ProductList />} />
35-
<Route path="/product/:id" element={<ProductSinglePage />} />
36-
<Route path="/newproduct" element={<NewProduct />} />
39+
<Route element={<PrivateRoutes/>}>
40+
<Route exact path="/" element={<Home />} />
41+
<Route path="/users" element={<UserList />} />
42+
<Route path="/user/:id" element={<UserSinglePage />} />
43+
<Route path="/newuser" element={<NewUser />} />
44+
<Route path="/products" element={<ProductList />} />
45+
<Route path="/product/:id" element={<ProductSinglePage />} />
46+
<Route path="/newproduct" element={<NewProduct />} />
47+
<Route path="/*" element={<Page404/>}/>
48+
</Route>
49+
<Route element={<RedirectRoute />}>
50+
<Route path="/login" element={<Login />} />
51+
</Route>
3752
</Routes>
3853
</Main>
3954
</BrowserRouter>

admin/src/components/Charts.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ export default function Charts({ data, title, firstLine, secondLine }) {
3838
<YAxis />
3939
<Tooltip />
4040
<Legend />
41-
<Line type="monotone" dataKey={secondLine} stroke="blue" activeDot={{ r: 8 }} />
41+
<Line type="monotone" dataKey={secondLine} stroke="blue" activeDot={{ r: 3 }} />
4242
<Line type="monotone" dataKey={firstLine} stroke="#1cdf0e" />
4343
</LineChart>
4444
</ResponsiveContainer>

admin/src/components/Figures.jsx

Lines changed: 81 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1-
import React from 'react'
1+
import React, { useEffect, useState } from 'react'
22
import styled from 'styled-components'
33

44
// import icons from mui5 library...
55
import {
66
ArrowUpward,
77
ArrowDownward
88
} from '@mui/icons-material'
9+
import { userRequest } from '../requestAxiosMethod'
910

1011
// Styled...
1112
const Container = styled.div`
@@ -52,37 +53,107 @@ const FigureCompare = styled.span`
5253

5354
// Figures React Functional Component...
5455
export default function Figures() {
56+
57+
// fetch total revenues & total Cost...
58+
// useSate for total revenues
59+
const [totalRevenues, setTotalRevenues] = useState([])
60+
const [progressRate, setProgressRate] = useState(0)
61+
62+
// useState for total Cost
63+
const [totalCost, setTotalCost] = useState([])
64+
const [costProgressRate, setCostProgressRate] = useState(0)
65+
66+
// useState for total Cost
67+
const [grossMargin, setGrossMargin] = useState([])
68+
const [grossMarginProgressRate, setGrossMarginProgressRate] = useState(0)
69+
70+
71+
useEffect(() => {
72+
const getTotalRevenues = async () => {
73+
// fetching orders total revenues and costs...
74+
const response = await userRequest.get('/orders/revenues')
75+
// determine the currentMonth & previous month...
76+
const ids = response.data.map(object => { return object._id })
77+
const currentMonth = Math.max.apply(null, ids)
78+
const previousMonth = currentMonth - 1
79+
// determine the index of currentMonth & previous month...
80+
const indexOfCurrentMonth = response.data.findIndex(object => { return object._id === currentMonth })
81+
const indexOfPreviousMonth =response.data.findIndex(object => { return object._id === previousMonth })
82+
83+
// setting new State for total revenues for currentMonth...
84+
setTotalRevenues(response.data[indexOfCurrentMonth].total)
85+
// setting progress rate...
86+
setProgressRate(
87+
Math.floor((response.data[indexOfCurrentMonth].total
88+
- response.data[indexOfPreviousMonth].total)
89+
/ (response.data[indexOfCurrentMonth].total)
90+
* 100)
91+
);
92+
93+
// setting new State for total costs for currentMonth...
94+
setTotalCost(response.data[indexOfCurrentMonth].directCost)
95+
// setting progress rate...
96+
setCostProgressRate(
97+
Math.floor((response.data[indexOfCurrentMonth].directCost
98+
- response.data[indexOfPreviousMonth].directCost)
99+
/ (response.data[indexOfCurrentMonth].directCost)
100+
* 100)
101+
);
102+
103+
// setting new State for total costs for currentMonth...
104+
setGrossMargin(
105+
response.data[indexOfCurrentMonth].total
106+
- response.data[indexOfCurrentMonth].directCost
107+
);
108+
// setting progress rate...
109+
setGrossMarginProgressRate(Math.floor(
110+
(
111+
(response.data[indexOfCurrentMonth].total - response.data[indexOfCurrentMonth].directCost)
112+
- (response.data[indexOfPreviousMonth].total - response.data[indexOfPreviousMonth].directCost)
113+
) / (response.data[indexOfCurrentMonth].total - response.data[indexOfCurrentMonth].directCost) * 100
114+
));
115+
116+
}
117+
getTotalRevenues()
118+
}, [])
119+
120+
55121
return (
56122
<Container>
57123
<FigureItem>
58124
<FigureTitle>Gross Margin</FigureTitle>
59125
<FigureAmountContainer>
60-
<FigureAmout>$675,402</FigureAmout>
126+
<FigureAmout>${grossMargin.toLocaleString()}</FigureAmout>
61127
<FigureAmountChange>
62-
-10.4
63-
<ArrowDownward style={{color: 'red'}}/>
128+
${grossMarginProgressRate}
129+
{grossMarginProgressRate > 0 ? (<ArrowUpward style={{ color: 'green' }} />)
130+
:(<ArrowDownward style={{ color: 'red' }} />)}
131+
64132
</FigureAmountChange>
65133
</FigureAmountContainer>
66134
<FigureCompare>Compare to last month</FigureCompare>
67135
</FigureItem>
68136
<FigureItem>
69137
<FigureTitle>Revenues</FigureTitle>
70138
<FigureAmountContainer>
71-
<FigureAmout>$1,675,000</FigureAmout>
139+
<FigureAmout>${totalRevenues.toLocaleString()}</FigureAmout>
72140
<FigureAmountChange>
73-
-8.6
74-
<ArrowDownward style={{color: 'red'}}/>
141+
%{progressRate}
142+
{progressRate > 0 ? (<ArrowUpward style={{ color: 'green' }} />)
143+
:(<ArrowDownward style={{ color: 'red' }} />)}
144+
75145
</FigureAmountChange>
76146
</FigureAmountContainer>
77147
<FigureCompare>Compare to last month</FigureCompare>
78148
</FigureItem>
79149
<FigureItem>
80150
<FigureTitle>Total Expenses</FigureTitle>
81151
<FigureAmountContainer>
82-
<FigureAmout>$1,000,402</FigureAmout>
152+
<FigureAmout>${totalCost.toLocaleString()}</FigureAmout>
83153
<FigureAmountChange>
84-
+13.02
85-
<ArrowUpward style={{color: 'green'}}/>
154+
%{costProgressRate}
155+
{costProgressRate > 0 ? (<ArrowUpward style={{ color: 'green' }} />)
156+
:(<ArrowDownward style={{ color: 'red' }} />)}
86157
</FigureAmountChange>
87158
</FigureAmountContainer>
88159
<FigureCompare>Compare to last month</FigureCompare>

admin/src/components/TopBar.jsx

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
11
import React from 'react'
22
import styled from 'styled-components'
33

4+
// useSelector to use redux toolkit in cart notification quantity...
5+
import { useDispatch, useSelector } from 'react-redux';
6+
7+
// use navigate...
8+
import { useNavigate } from 'react-router-dom';
9+
10+
// import userSlice actions...
11+
import { loginStart, logOut } from '../redux/userSlice'
12+
413
// import icons from mui5 library...
514
import {
615
SettingsOutlined,
@@ -10,6 +19,7 @@ import {
1019

1120
// import required image from images library...
1221
import profilePhoto from '../images/1.jpg'
22+
import { deleteAll } from '../redux/productSlice';
1323

1424
// Styling...
1525
const Container = styled.div`
@@ -80,18 +90,34 @@ const TopBarNotificationNumber = styled.span`
8090
margin-bottom: 2px;
8191
`
8292
export default function TopBar() {
93+
const user = useSelector((state) => state.user?.currentUser?.isAdmin)
94+
const dispatch = useDispatch()
95+
const navigate = useNavigate()
96+
// handle Log Out...
97+
const handleLogOut = () => {
98+
dispatch(loginStart())
99+
try {
100+
dispatch(logOut())
101+
.then(navigate('/login'))
102+
} catch (error) {
103+
}
104+
}
105+
// emty redux products...
106+
const handleClick = () => {
107+
dispatch(deleteAll())
108+
}
83109
return (
84110
<Container>
85111
<Wrapper>
86112
<TopBarLeft>
87113
<BrandLogo>SOLIMAN</BrandLogo>
88114
</TopBarLeft>
89-
<TopBarRight>
115+
{user && (<><TopBarRight>
90116
<TopBarRightIcons>
91-
<PowerSettingsNewOutlined style={{ fontSize: '20px' }} />
117+
<PowerSettingsNewOutlined onClick={handleLogOut} style={{ fontSize: '20px' }} />
92118
</TopBarRightIcons>
93119
<TopBarRightIcons>
94-
<SettingsOutlined style={{ fontSize: '20px' }} />
120+
<SettingsOutlined style={{ fontSize: '20px' }} onClick={handleClick} />
95121
</TopBarRightIcons>
96122
<TopBarRightIcons>
97123
<NotificationsNone style={{ fontSize: '20px' }} />
@@ -100,7 +126,7 @@ export default function TopBar() {
100126
</TopBarRightBadge>
101127
</TopBarRightIcons>
102128
<ProfileImage src={profilePhoto} alt='Profile Image' />
103-
</TopBarRight>
129+
</TopBarRight></>)}
104130
</Wrapper>
105131
</Container>
106132
)

0 commit comments

Comments
 (0)