├── .gitignore
├── .vscode
└── launch.json
├── README.md
├── package-lock.json
├── package.json
├── public
├── favicon.ico
├── index.html
├── logo192.png
├── logo512.png
├── manifest.json
└── robots.txt
├── screenshot
├── Icon.png
├── Screenshot_1.png
├── Screenshot_2.png
├── Screenshot_3.png
└── Screenshot_4.png
└── src
├── AppRouter.js
├── Components
├── Layout
│ ├── CardOrder.js
│ ├── CardProduct.js
│ ├── DataCategory.js
│ ├── DataProduct.js
│ ├── ListMenu.js
│ ├── MainPage.js
│ ├── Message.js
│ ├── Statistic.js
│ └── TestPagination.js
├── Page
│ ├── Dashboard.js
│ ├── Login.js
│ ├── Logout.js
│ └── SignUp.js
├── Redux
│ ├── Actions
│ │ ├── auth.js
│ │ ├── categories.js
│ │ ├── order.js
│ │ └── product.js
│ ├── Reducers
│ │ ├── auth.js
│ │ ├── categories.js
│ │ ├── index.js
│ │ ├── order.js
│ │ └── product.js
│ └── store.js
└── Styles
│ ├── StyleDashboard.js
│ ├── StyleDataCategory.js
│ ├── StyleLogout.js
│ ├── StyleMainPage.js
│ ├── StyleMessage.js
│ ├── StyleOrderCard.js
│ ├── StyleProductCard.js
│ └── StyleSignUp.js
├── index.js
└── serviceWorker.js
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # production
12 | /build
13 |
14 | # misc
15 | .DS_Store
16 | .env.local
17 | .env.development.local
18 | .env.test.local
19 | .env.production.local
20 |
21 | npm-debug.log*
22 | yarn-debug.log*
23 | yarn-error.log*
24 |
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | // Use IntelliSense to learn about possible attributes.
3 | // Hover to view descriptions of existing attributes.
4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5 | "version": "0.2.0",
6 | "configurations": [
7 | {
8 | "type": "chrome",
9 | "request": "launch",
10 | "name": "Launch Chrome against localhost",
11 | "url": "http://localhost:8080",
12 | "webRoot": "${workspaceFolder}"
13 | }
14 | ]
15 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
MSG - Mart ( React JS Point of Sales - Web App)
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | MSG-Mart is an application in the form of a website and a mobile application for product management, category management and has a cashier system (point of sale), this application is made using React Js and React Native. There is only a website model in this area, if you interest and want to try the mobile app version of MSG-Mart, you can visit this link :
16 |
17 | Mobile App [MSG-Mart](https://github.com/aldoignatachandra/MSG-Mart-React_Native_POS)
18 |
19 | ## Features
20 | Product Management
21 | - Create data table
22 | - View data product
23 | - Update product
24 | - Delete product
25 | - Search product by id, name, category and Latest update
26 | - Sorting product by ascending and descending
27 |
28 | Category Management
29 | - Create data table
30 | - View data category
31 | - Update category
32 | - Delete category
33 |
34 | Transaction is Under Maintenance
35 |
36 | ## Get Started
37 | ### ( Localhost Version )
38 | 1. Download and Install RESTfull API from [MSG-Mart API](https://github.com/aldoignatachandra/RESTful_API_Point_of_Sales_APP)
39 | 2. Run backend (API) in local with (xampp or other)
40 | 3. Git clone [MSG-Mart - React Website](https://github.com/aldoignatachandra/MSG-Mart-React_JS_POS_Redux) or download zip
41 | 4. Open in your code editor (vscode, atom or other)
42 | 5. Install node modules with type `npm install` or `yarn install`
43 | 6. Run App with type `npm start`
44 |
45 | ### ( Online Version )
46 | 1. Prepare your internet and browser (prefer use chrome)
47 | 2. You can visit this [LINK](https://msg-mart.netlify.com/) for MSG-Mart online web app version
48 |
49 | ## Build with React Hooks & Redux
50 |
51 |
52 | ## Screenshot from the App
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 | ## License
67 | [ISC](https://en.wikipedia.org/wiki/ISC_license "ISC")
68 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "fronted-pointofsales",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@material-ui/core": "^4.5.2",
7 | "@material-ui/icons": "^4.5.1",
8 | "axios": "^0.19.0",
9 | "react": "^16.11.0",
10 | "react-dom": "^16.11.0",
11 | "react-redux": "^7.1.1",
12 | "react-router-dom": "^5.1.2",
13 | "react-scripts": "3.2.0",
14 | "redux": "^4.0.4",
15 | "redux-promise-middleware": "^6.1.1"
16 | },
17 | "scripts": {
18 | "start": "react-scripts start",
19 | "build": "react-scripts build",
20 | "test": "react-scripts test",
21 | "eject": "react-scripts eject"
22 | },
23 | "eslintConfig": {
24 | "extends": "react-app"
25 | },
26 | "browserslist": {
27 | "production": [
28 | ">0.2%",
29 | "not dead",
30 | "not op_mini all"
31 | ],
32 | "development": [
33 | "last 1 chrome version",
34 | "last 1 firefox version",
35 | "last 1 safari version"
36 | ]
37 | },
38 | "devDependencies": {
39 | "redux-logger": "^3.0.6"
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aldoignatachandra/ReactJS-MsgMart/1ec8b8220a68487f2534f572d62e380efe399936/public/favicon.ico
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
12 |
13 |
17 |
18 |
27 | MSG MART
28 |
29 |
30 | You need to enable JavaScript to run this app.
31 |
32 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/public/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aldoignatachandra/ReactJS-MsgMart/1ec8b8220a68487f2534f572d62e380efe399936/public/logo192.png
--------------------------------------------------------------------------------
/public/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aldoignatachandra/ReactJS-MsgMart/1ec8b8220a68487f2534f572d62e380efe399936/public/logo512.png
--------------------------------------------------------------------------------
/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | },
10 | {
11 | "src": "logo192.png",
12 | "type": "image/png",
13 | "sizes": "192x192"
14 | },
15 | {
16 | "src": "logo512.png",
17 | "type": "image/png",
18 | "sizes": "512x512"
19 | }
20 | ],
21 | "start_url": ".",
22 | "display": "standalone",
23 | "theme_color": "#000000",
24 | "background_color": "#ffffff"
25 | }
26 |
--------------------------------------------------------------------------------
/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 |
--------------------------------------------------------------------------------
/screenshot/Icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aldoignatachandra/ReactJS-MsgMart/1ec8b8220a68487f2534f572d62e380efe399936/screenshot/Icon.png
--------------------------------------------------------------------------------
/screenshot/Screenshot_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aldoignatachandra/ReactJS-MsgMart/1ec8b8220a68487f2534f572d62e380efe399936/screenshot/Screenshot_1.png
--------------------------------------------------------------------------------
/screenshot/Screenshot_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aldoignatachandra/ReactJS-MsgMart/1ec8b8220a68487f2534f572d62e380efe399936/screenshot/Screenshot_2.png
--------------------------------------------------------------------------------
/screenshot/Screenshot_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aldoignatachandra/ReactJS-MsgMart/1ec8b8220a68487f2534f572d62e380efe399936/screenshot/Screenshot_3.png
--------------------------------------------------------------------------------
/screenshot/Screenshot_4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aldoignatachandra/ReactJS-MsgMart/1ec8b8220a68487f2534f572d62e380efe399936/screenshot/Screenshot_4.png
--------------------------------------------------------------------------------
/src/AppRouter.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { BrowserRouter as Router , Redirect} from 'react-router-dom';
3 | import { Route } from 'react-router-dom';
4 | import { Switch } from 'react-router-dom';
5 |
6 | //Content Import
7 | import Login from "./Components/Page/Login";
8 | import SignUp from "./Components/Page/SignUp";
9 | import Dashboard from "./Components/Page/Dashboard";
10 | // import Register from './Component/Auth/Resgister';
11 |
12 | const AppRouter = () => (
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | )
24 |
25 | export default AppRouter;
--------------------------------------------------------------------------------
/src/Components/Layout/CardOrder.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { withRouter } from 'react-router-dom';
3 | import Card from '@material-ui/core/Card';
4 | import CardContent from '@material-ui/core/CardContent';
5 | import CardMedia from '@material-ui/core/CardMedia';
6 | import IconButton from '@material-ui/core/IconButton';
7 | import Typography from '@material-ui/core/Typography';
8 | import IndeterminateCheckBoxIcon from '@material-ui/icons/IndeterminateCheckBox';
9 | import AddBoxIcon from '@material-ui/icons/AddBox';
10 | import { useStyles } from '../Styles/StyleOrderCard';
11 |
12 | function CardOrder (props) {
13 | const classes = useStyles();
14 |
15 | return (
16 |
17 |
18 |
22 |
23 |
24 |
25 |
26 | {props.item.product_name}
27 |
28 |
29 | {props.item.price}
30 |
31 |
32 |
33 |
34 |
35 |
36 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 | )
53 | }
54 |
55 | export default withRouter (CardOrder);
--------------------------------------------------------------------------------
/src/Components/Layout/CardProduct.js:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect } from 'react';
2 | import { Redirect } from 'react-router-dom';
3 | import { useDispatch, useSelector } from 'react-redux';
4 | import axios from 'axios';
5 | import { useStyles } from '../Styles/StyleProductCard';
6 | import Card from '@material-ui/core/Card';
7 | import CardActionArea from '@material-ui/core/CardActionArea';
8 | import CardContent from '@material-ui/core/CardContent';
9 | import CardMedia from '@material-ui/core/CardMedia';
10 | import Typography from '@material-ui/core/Typography';
11 | import Divider from '@material-ui/core/Divider';
12 | import { Grid, Button, TextField } from '@material-ui/core';
13 | import ArrowUpwardRoundedIcon from '@material-ui/icons/ArrowUpwardRounded';
14 | import ArrowDownwardRoundedIcon from '@material-ui/icons/ArrowDownwardRounded';
15 | import SearchIcon from '@material-ui/icons/Search';
16 |
17 | import { addToCart } from '../Redux/Actions/order'
18 |
19 | function ProductCard (props) {
20 |
21 | const classes = useStyles();
22 | const [dataProduct, setDataProduct] = useState ([]);
23 | const [token, setToken] = useState (localStorage.getItem("jwt"));
24 | const [order, setOrder] = useState ('');
25 | const [sorting, setSorting] = useState ('ASC');
26 | const [search, setSearch] = useState ("");
27 | const apiProduct = `https://pointofsalesapp.herokuapp.com/api/product`;
28 |
29 | const dispatch = useDispatch();
30 |
31 |
32 | const fetchDataProduct = async () => {
33 | if (token === null) {
34 | return
35 | } else {
36 | const res = await axios (apiProduct,{
37 | params: {
38 | orderBy: order,
39 | sortBy: sorting,
40 | search: search
41 | },
42 | headers: {
43 | "x-access-token":token
44 | }
45 | })
46 | if (res.data.status == 200) {
47 | setDataProduct (res.data.result.response);
48 | } else {
49 | setDataProduct ([]);
50 | }
51 | }
52 | }
53 |
54 | const funSearch = (e) => {
55 | e.target.name = e.target.value;
56 | setSearch (e.target.name);
57 | }
58 |
59 | const handleSearch = () => {
60 | setSearch(search);
61 | setTimeout(() => {
62 | fetchDataProduct();
63 | }, 0);
64 | }
65 |
66 | const handleSortBy = (check) => {
67 | setSorting (check);
68 | setTimeout(() => {
69 | fetchDataProduct();
70 | }, 0);
71 | }
72 |
73 | const handleOrderBy = (check) => {
74 | setOrder (check);
75 | setTimeout(() => {
76 | fetchDataProduct();
77 | }, 0);
78 | }
79 |
80 | const handleAddToCart = async(selectedProduct) => {
81 | await dispatch (addToCart(selectedProduct));
82 | }
83 |
84 | useEffect(() => {
85 | fetchDataProduct ();
86 | },[])
87 |
88 | return (
89 |
90 |
91 |
92 |
93 |
101 |
102 |
103 |
104 |
105 | handleOrderBy('name')} variant="contained" className={classes.buttonOrderBy} color="secondary">
106 | Name
107 |
108 | handleOrderBy('category')} variant="contained" className={classes.buttonOrderBy} color="secondary">
109 | Category
110 |
111 | handleOrderBy('updated')} variant="contained" className={classes.buttonOrderBy} color="secondary">
112 | Last Update
113 |
114 | handleSortBy('ASC')} variant="contained" className={classes.buttonSort} color="secondary">
115 |
116 |
117 | handleSortBy('DESC')} variant="contained" className={classes.buttonSort} color="secondary">
118 |
119 |
120 |
121 |
122 |
128 | {dataProduct.length != 0 ?
129 | dataProduct.map ((data, index) => {
130 | return (
131 |
132 |
133 |
134 |
135 |
142 |
143 |
144 |
145 |
146 | {data.product_name}
147 |
148 |
149 | ({data.category})
150 |
151 |
152 | Quantity : {data.quantity}
153 |
154 |
155 |
156 |
161 |
162 | Rp.{data.price}
163 |
164 | handleAddToCart(data)}
169 | >
170 | Add
171 |
172 |
173 |
174 |
175 |
176 |
177 | )
178 | }) : Data Not Found }
179 |
180 |
181 | )
182 | }
183 |
184 | export default ProductCard;
--------------------------------------------------------------------------------
/src/Components/Layout/DataCategory.js:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect } from 'react';
2 | import { Redirect ,withRouter} from 'react-router-dom';
3 | import axios from 'axios';
4 | import clsx from 'clsx';
5 | import Typography from '@material-ui/core/Table';
6 | import Table from '@material-ui/core/Table';
7 | import TableBody from '@material-ui/core/TableBody';
8 | import TableCell from '@material-ui/core/TableCell';
9 | import TableHead from '@material-ui/core/TableHead';
10 | import TableRow from '@material-ui/core/TableRow';
11 | import DeleteIcon from '@material-ui/icons/Delete';
12 | import EditIcon from '@material-ui/icons/Edit';
13 | import IconButton from '@material-ui/core/IconButton';
14 | import Paper from '@material-ui/core/Paper';
15 | import Dialog from '@material-ui/core/Dialog';
16 | import DialogActions from '@material-ui/core/DialogActions';
17 | import DialogTitle from '@material-ui/core/DialogTitle';
18 | import Button from '@material-ui/core/Button';
19 | import TextField from '@material-ui/core/TextField';
20 | import DialogContent from '@material-ui/core/DialogContent';
21 | import { useStyles } from '../Styles/StyleDataCategory';
22 | import Snackbar from '@material-ui/core/Snackbar';
23 | import CheckCircleIcon from '@material-ui/icons/CheckCircle';
24 | import ErrorIcon from '@material-ui/icons/Error';
25 | import SnackbarContent from '@material-ui/core/SnackbarContent';
26 | import TablePagination from '@material-ui/core/TablePagination';
27 |
28 | import { connect } from 'react-redux';
29 | import { getCategories, postCategories, patchCategories, deleteCategories } from '../Redux/Actions/categories';
30 |
31 | const variantIcon = {
32 | success: CheckCircleIcon,
33 | error: ErrorIcon,
34 | };
35 |
36 | function MySnackbarContentWrapper(props) {
37 | const classes = useStyles();
38 | const { className, message, variant } = props;
39 | const Icon = variantIcon[variant];
40 |
41 | return (
42 |
47 |
48 | {message}
49 |
50 | }
51 | />
52 | );
53 | }
54 |
55 | function DataCategory (props) {
56 | const classes = useStyles();
57 | const token = localStorage.getItem("jwt");
58 | const [dataCategory, setDataCategory] = useState ([]);
59 | const [postDataCategory, setDataPostCategory] = useState ({name:''});
60 | const [selectedRow, setSelectedRow] = useState ({});
61 |
62 | const [page, setPage] = useState(0);
63 | const [infoPage, setInfoPage] = useState({maxPage: 0, totalAllCategories: 0});
64 | const [rowsPerPage, setRowsPerPage] = useState(5);
65 |
66 | const [add, setAdd] = useState (false);
67 | const [alert, setAlert] = useState (false);
68 | const [edit, setEdit] = useState (false);
69 | const [showStatus, setShowStatus] = useState(false);
70 | const [validate, setValidate] = useState ("");
71 | const [success, setSuccess] = useState ("error")
72 |
73 | const emptyRows = rowsPerPage - Math.min(rowsPerPage, infoPage.totalAllCategories - page * rowsPerPage);
74 |
75 | const addCategory = async() => {
76 | await props.dispatch( postCategories(postDataCategory))
77 | .then(res => {
78 | if (token === null) {
79 | console.log ("JWT Expires");
80 | } else {
81 | if (res.value.data.status !== 400) {
82 | setShowStatus(true);
83 | setSuccess("success");
84 | setValidate("Success Add New Category");
85 | handleAddClose();
86 | } else {
87 | setSuccess("error");
88 | setShowStatus(true);
89 | setValidate(res.value.data.error);
90 | }
91 | }
92 | })
93 | .catch((error) => setShowStatus(false))
94 | }
95 |
96 | const deleteCategory = async() => {
97 | await props.dispatch( deleteCategories(selectedRow))
98 | .then (res => {
99 | if (token === null) {
100 | console.log ("JWT Expires");
101 | } else {
102 | if (res.value.data.status !== 400) {
103 | setShowStatus(true);
104 | setSuccess("success");
105 | setValidate("Success Delete Category");
106 | handleAlertClose();
107 | } else {
108 | setSuccess("error");
109 | setShowStatus(true);
110 | setValidate(res.value.data.error);
111 | }
112 | }
113 | }).catch((error) => setShowStatus(false))
114 | }
115 |
116 | const editCategory = async() => {
117 | await props.dispatch( patchCategories(selectedRow))
118 | .then (res => {
119 | if (token === null) {
120 | console.log ("JWT Expires");
121 | } else {
122 | if (res.value.data.status !== 400) {
123 | setShowStatus(true);
124 | setSuccess("success");
125 | setValidate("Success Edit Category");
126 | handleEditClose();
127 | } else {
128 | setSuccess("error");
129 | setShowStatus(true);
130 | setValidate(res.value.data.error);
131 | }
132 | }
133 | }).catch((error) => setShowStatus(false))
134 | }
135 |
136 | const fetchDataCategory = async () => {
137 | if (token === null) {
138 | return
139 | } else {
140 | await props.dispatch( getCategories(rowsPerPage, page + 1))
141 | .then (result => {
142 | setDataCategory (result.value.data.result.response);
143 | setInfoPage (result.value.data.result.infoPage);
144 | })
145 | .catch (error => {
146 | console.log (error);
147 | })
148 | }
149 | }
150 |
151 | const handleChangePage = (event, newPage) => {
152 | setPage(newPage);
153 | };
154 |
155 | const handleChangeRowsPerPage = event => {
156 | setRowsPerPage(parseInt(event.target.value, 10));
157 | setPage(0);
158 | };
159 |
160 | useEffect(() => {
161 | fetchDataCategory ();
162 | },[page, rowsPerPage])
163 |
164 | const inputChangeAdd = (e) => {
165 | let newDataPost = {...postDataCategory};
166 | newDataPost [e.currentTarget.name] = e.currentTarget.value;
167 | setDataPostCategory(newDataPost);
168 | }
169 |
170 | const inputChangeEdit = (e) => {
171 | let newDataPost = {...selectedRow};
172 | newDataPost ["name"] = e.currentTarget.value;
173 | setSelectedRow(newDataPost);
174 | }
175 |
176 | //Handle Open Modal Add Category
177 | const handleAddOpen = () => { setAdd(true) }
178 | const handleAddClose = () => { setAdd(false) }
179 |
180 | //Handle Open Modal Edit Category
181 | const handleEditOpen = (row) => { setEdit(true); setSelectedRow (row) }
182 | const handleEditClose = () => { setEdit(false) }
183 |
184 | //Handle Open Modal Delete Category
185 | const handleAlertOpen = (row) => { setAlert(true); setSelectedRow (row) }
186 | const handleAlertClose = () => { setAlert(false) }
187 |
188 | const handleCloseSnackbar = () => { setShowStatus(false) }
189 |
190 | return (
191 |
192 |
193 |
202 |
207 |
208 |
209 |
210 | DATA CATEGORY
211 |
212 |
213 | Add Category
214 |
215 |
216 |
217 |
218 |
219 | Name
220 | Action
221 |
222 |
223 |
224 | {props.dataCategories.map((data, index) => {
225 | return(
226 |
227 |
228 | {data.name}
229 |
230 | handleAlertOpen(data)}>
231 |
232 |
233 | ||
234 | handleEditOpen(data)}>
235 |
236 |
237 |
238 |
239 |
240 | )
241 | })}
242 | {emptyRows > 0 && (
243 |
244 |
245 |
246 |
247 |
248 | )}
249 |
250 |
251 |
252 |
267 |
268 |
269 |
270 |
271 |
272 | {/* Modal Add Category */}
273 |
274 | Add New Category
275 |
276 |
277 |
278 |
279 |
280 | Name
281 |
282 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 | Cancel
298 |
299 |
300 | Add
301 |
302 |
303 |
304 |
305 | {/* Modal Delete */}
306 |
307 | Are You Sure Delete This Category ?
308 | ( {selectedRow.name} )
309 |
310 |
311 |
312 | Cancel
313 |
314 |
315 | Delete
316 |
317 |
318 |
319 |
320 | {/* Modal Edit */}
321 |
322 | Edit Category
323 |
324 |
325 |
326 |
327 | Name
328 |
329 |
337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 | Cancel
345 |
346 |
347 | Edit
348 |
349 |
350 |
351 |
352 |
353 |
354 | )
355 | }
356 |
357 | const mapStateToProps = state => {
358 | return {
359 | dataCategories: state.categories.listCategory
360 | };
361 | };
362 |
363 | export default connect (mapStateToProps) (DataCategory);
--------------------------------------------------------------------------------
/src/Components/Layout/DataProduct.js:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect } from 'react';
2 | import { Redirect ,withRouter } from 'react-router-dom';
3 | import clsx from 'clsx';
4 | import Typography from '@material-ui/core/Table';
5 | import Avatar from '@material-ui/core/Avatar';
6 | import Table from '@material-ui/core/Table';
7 | import TableBody from '@material-ui/core/TableBody';
8 | import TableCell from '@material-ui/core/TableCell';
9 | import TableHead from '@material-ui/core/TableHead';
10 | import TableRow from '@material-ui/core/TableRow';
11 | import DeleteIcon from '@material-ui/icons/Delete';
12 | import EditIcon from '@material-ui/icons/Edit';
13 | import IconButton from '@material-ui/core/IconButton';
14 | import Paper from '@material-ui/core/Paper';
15 | import Dialog from '@material-ui/core/Dialog';
16 | import DialogActions from '@material-ui/core/DialogActions';
17 | import DialogTitle from '@material-ui/core/DialogTitle';
18 | import Button from '@material-ui/core/Button';
19 | import TextField from '@material-ui/core/TextField';
20 | import DialogContent from '@material-ui/core/DialogContent';
21 | import { useStyles } from '../Styles/StyleDataCategory';
22 | import { MenuItem, FormControl, Select } from '@material-ui/core/';
23 | import Snackbar from '@material-ui/core/Snackbar';
24 | import CheckCircleIcon from '@material-ui/icons/CheckCircle';
25 | import ErrorIcon from '@material-ui/icons/Error';
26 | import SnackbarContent from '@material-ui/core/SnackbarContent';
27 | import TablePagination from '@material-ui/core/TablePagination';
28 |
29 | import { connect } from 'react-redux';
30 | import { getProducts, deleteProducts, postProducts, patchProducts} from '../Redux/Actions/product';
31 | import { getCategories } from '../Redux/Actions/categories';
32 |
33 | const variantIcon = {
34 | success: CheckCircleIcon,
35 | error: ErrorIcon,
36 | };
37 |
38 | function MySnackbarContentWrapper(props) {
39 | const classes = useStyles();
40 | const { className, message, variant } = props;
41 | const Icon = variantIcon[variant];
42 |
43 | return (
44 |
49 |
50 | {message}
51 |
52 | }
53 | />
54 | );
55 | }
56 |
57 | function DataProduct (props) {
58 | const classes = useStyles();
59 | const [token, setToken] = useState (localStorage.getItem("jwt"));
60 | const [dataProduct, setDataProduct] = useState ([]);
61 | const [dataCategory, setDataCategory] = useState ([]);
62 | const [postDataProduct, setPostDataProduct] = useState ({name:'', description:'',image: '', category_id:'', price:'', quantity:''});
63 | const [selectedRow, setSelectedRow] = useState ({});
64 | const [add, setAdd] = useState (false);
65 | const [alert, setAlert] = useState (false);
66 | const [edit, setEdit] = useState (false);
67 | const [showStatus, setShowStatus] = useState(false);
68 | const [validate, setValidate] = useState ("");
69 | const [success, setSuccess] = useState ("error")
70 |
71 | const [page, setPage] = useState(0);
72 | const [infoPage, setInfoPage] = useState({maxPage: 0, totalAllProduct: 0});
73 | const [rowsPerPage, setRowsPerPage] = useState(5);
74 |
75 | const emptyRows = rowsPerPage - Math.min(rowsPerPage, infoPage.totalAllProduct - page * rowsPerPage);
76 |
77 | const addProduct = async() => {
78 | await props.dispatch( postProducts(postDataProduct))
79 | .then(res => {
80 | if (token === null) {
81 | console.log ("JWT Expires");
82 | } else {
83 | if (res.value.data.status !== 400) {
84 | setShowStatus(true);
85 | setSuccess("success");
86 | setValidate("Success Add New Product");
87 | handleAddClose();
88 | } else {
89 | setSuccess("error");
90 | setShowStatus(true);
91 | setValidate(res.value.data.error);
92 | }
93 | }
94 | })
95 | .catch((error) => setShowStatus(false))
96 | }
97 |
98 | const deleteProduct = async() => {
99 | await props.dispatch( deleteProducts(selectedRow))
100 | .then (res => {
101 | if (token === null) {
102 | console.log ("JWT Expires");
103 | } else {
104 | if (res.value.data.status !== 400) {
105 | setShowStatus(true);
106 | setSuccess("success");
107 | setValidate("Success Delete Product");
108 | handleAlertClose();
109 | } else {
110 | setSuccess("error");
111 | setShowStatus(true);
112 | setValidate(res.value.data.error);
113 | }
114 | }
115 | }).catch((error) => setShowStatus(false))
116 | }
117 |
118 | const editProduct = async() => {
119 | await props.dispatch( patchProducts(selectedRow))
120 | .then (res => {
121 | if (token === null) {
122 | console.log ("JWT Expires");
123 | } else {
124 | if (res.value.data.status !== 400) {
125 | setShowStatus(true);
126 | setSuccess("success");
127 | setValidate("Success Edit Product");
128 | handleEditClose();
129 | } else {
130 | setSuccess("error");
131 | setShowStatus(true);
132 | setValidate(res.value.data.error);
133 | }
134 | }
135 | }).catch((error) => setShowStatus(false))
136 | }
137 |
138 | const fetchDataProduct = async () => {
139 | if (token === null) {
140 | return
141 | } else {
142 | await props.dispatch( getProducts(rowsPerPage, page + 1))
143 | .then(result => {
144 | setDataProduct (result.value.data.result.response);
145 | setInfoPage (result.value.data.result.infoPage);
146 | })
147 | .catch(error => {
148 | console.log (error);
149 | })
150 | }
151 | }
152 |
153 | const fetchDataCategory = async () => {
154 | if (token === null) {
155 | return
156 | } else {
157 | await props.dispatch( getCategories())
158 | .then(res => {
159 | setDataCategory (res.value.data.result.response);
160 | }).catch(error => {
161 | console.log(error);
162 | })
163 | }
164 | }
165 |
166 | useEffect(() => {
167 | fetchDataProduct ();
168 | fetchDataCategory ();
169 | },[page, rowsPerPage])
170 |
171 | const handleChangePage = (event, newPage) => {
172 | setPage(newPage);
173 | };
174 |
175 | const handleChangeRowsPerPage = event => {
176 | setRowsPerPage(parseInt(event.target.value, 10));
177 | setPage(0);
178 | };
179 |
180 | const inputChangeAdd = (e) => {
181 | let newDataPost = {...postDataProduct};
182 | newDataPost [e.currentTarget.name] = e.currentTarget.value;
183 | setPostDataProduct(newDataPost);
184 | }
185 |
186 | const inputChangeEdit = (e) => {
187 | let newDataPost = {...selectedRow};
188 | newDataPost [e.currentTarget.name] = e.currentTarget.value;
189 | setSelectedRow(newDataPost);
190 | }
191 |
192 | //Handle Category For Add Product
193 | const handleCategoryAdd = (e) => {
194 | let newDataCategory = {...postDataProduct};
195 | newDataCategory ["category_id"] = e.target.value;
196 | setPostDataProduct(newDataCategory);
197 | }
198 |
199 | //Handle Category For Edit Product
200 | const handleCategoryEdit = (e) => {
201 | let newDataCategory = {...selectedRow};
202 | newDataCategory.category_id = e.target.value;
203 | setSelectedRow(newDataCategory);
204 | }
205 |
206 | //Handle Open Modal Add Product
207 | const handleAddOpen = () => { setAdd(true) }
208 | const handleAddClose = () => { setAdd(false) }
209 |
210 | //Handle Open Modal Edit Product
211 | const handleEditOpen = (row) => { row.name = row.product_name; setEdit(true); setSelectedRow (row) }
212 | const handleEditClose = () => { setEdit(false) }
213 |
214 | //Handle Open Modal Delete Product
215 | const handleAlertOpen = (row) => { setAlert(true); setSelectedRow (row) }
216 | const handleAlertClose = () => { setAlert(false) }
217 |
218 | const handleCloseSnackbar = () => { setShowStatus(false) }
219 |
220 | return (
221 |
222 |
223 |
232 |
237 |
238 |
239 |
240 | DATA PRODUCT
241 |
242 |
243 | Add Product
244 |
245 |
246 |
247 |
248 |
249 | Name
250 | Category
251 | Description
252 | Quantity
253 | Image
254 | Price
255 | Actions
256 |
257 |
258 | {props.dataProducts.map((data, index) => {
259 | return(
260 |
261 |
262 | {data.product_name || data.name}
263 | {data.category}
264 | {data.description}
265 | {data.quantity}
266 |
267 |
268 |
269 | {data.price}
270 |
271 | handleAlertOpen(data)}>
272 |
273 |
274 | handleEditOpen(data)}>
275 |
276 |
277 |
278 |
279 |
280 | )
281 | })}
282 | {emptyRows > 0 && (
283 |
284 |
285 |
286 |
287 |
288 | )}
289 |
290 |
291 |
292 |
307 |
308 |
309 |
310 |
311 |
312 | {/* Modal Add Product */}
313 |
314 | Add New Product
315 |
316 |
317 |
318 |
319 | Name
320 |
321 |
330 |
331 |
332 |
333 | Description
334 |
335 |
346 |
347 |
348 |
349 | Image
350 |
351 |
360 |
361 |
362 |
363 | Price
364 |
365 |
380 |
381 |
382 |
383 | Quantity
384 |
385 |
400 |
401 |
402 |
403 | Category
404 |
405 |
406 |
413 | {props.dataCategories.map ((item, index) => (
414 | {item.name}
415 | ))}
416 |
417 |
418 |
419 |
420 |
421 |
422 |
423 |
424 |
425 | Cancel
426 |
427 |
428 | Add
429 |
430 |
431 |
432 |
433 | {/* Modal Delete */}
434 |
435 | Are You Sure Delete This Product ?
436 | ( {selectedRow.product_name} )
437 |
438 |
439 |
440 | Cancel
441 |
442 |
443 | Delete
444 |
445 |
446 |
447 |
448 | {/* Modal Edit */}
449 |
450 | Edit Category
451 |
452 |
453 |
454 |
455 | Name
456 |
457 |
467 |
468 |
469 |
470 | Description
471 |
472 |
484 |
485 |
486 |
487 | Image
488 |
489 |
499 |
500 |
501 |
502 | Price
503 |
504 |
521 |
522 |
523 |
524 | Quantity
525 |
526 |
543 |
544 |
545 |
546 | Category
547 |
548 |
549 |
556 | {dataCategory.map ((item, index) => (
557 | {item.name}
558 | ))}
559 |
560 |
561 |
562 |
563 |
564 |
565 |
566 |
567 |
568 | Cancel
569 |
570 |
571 | Edit
572 |
573 |
574 |
575 |
576 |
577 |
578 | )
579 | }
580 |
581 | const mapStateToProps = state => {
582 | return {
583 | dataProducts: state.product.listProduct,
584 | dataCategories: state.categories.listCategory
585 | };
586 | };
587 |
588 | export default withRouter (connect (mapStateToProps) (DataProduct));
--------------------------------------------------------------------------------
/src/Components/Layout/ListMenu.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Link } from "react-router-dom";
3 | import { Divider } from '@material-ui/core';
4 | import ListItem from '@material-ui/core/ListItem';
5 | import ListItemIcon from '@material-ui/core/ListItemIcon';
6 | import ListItemText from '@material-ui/core/ListItemText';
7 | import AssignmentOutlinedIcon from '@material-ui/icons/AssignmentOutlined';
8 | import InsertChartIcon from '@material-ui/icons/InsertChart';
9 | import FastfoodIcon from '@material-ui/icons/Fastfood';
10 |
11 | //Import Content Button
12 | import Logout from '../Page/Logout';
13 |
14 | export const mainListMenu = (
15 |
16 |
17 | {/* Button Snack */}
18 |
19 |
20 |
21 |
22 | List MSG
23 |
24 |
25 | {/* Button Management Product*/}
26 |
27 |
28 |
29 |
30 | Data Product
31 |
32 |
33 | {/* Button Management Category*/}
34 |
35 |
36 |
37 |
38 | Data Category
39 |
40 |
41 | {/* Button Statistic */}
42 |
43 |
44 |
45 |
46 | Statistic
47 |
48 |
49 |
50 |
51 | {/* Button Logout */}
52 |
53 |
54 |
55 | );
--------------------------------------------------------------------------------
/src/Components/Layout/MainPage.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import clsx from 'clsx';
3 | // import { useDispatch, useSelector } from 'react-redux';
4 | import { withRouter} from 'react-router-dom';
5 | import { useStyles } from '../Styles/StyleMainPage';
6 | import {Typography, Grid, Paper, Button} from '@material-ui/core/';
7 | import { connect } from 'react-redux';
8 |
9 | //Card
10 | import ProductCard from './CardProduct';
11 | import OrderCard from './CardOrder';
12 |
13 | function MainPage (props) {
14 |
15 | const classes = useStyles();
16 | const fixedHeightPaper = clsx(classes.paper, classes.fixedHeight);
17 | // const addProduct = useSelector(state => state.order.addedItem);
18 |
19 | return (
20 |
21 |
22 |
23 | {/* List Product */}
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 | CART
34 |
35 |
36 |
37 | {/* List Order */}
38 |
44 | {props.addedItem.length == 0 ? "EMPTY CART" : props.addedItem.map(item => (
45 |
46 | ))}
47 |
48 |
49 |
50 |
51 |
52 |
53 | CANCEL
54 |
55 |
56 | CHECKOUT
57 |
58 |
59 |
60 |
61 |
62 |
63 | )
64 | }
65 |
66 | const mapStateToProps = state => {
67 | return {
68 | addedItem: state.order.addedItem
69 | };
70 | };
71 |
72 | export default withRouter (connect (mapStateToProps) (MainPage));
73 | // export default withRouter(MainPage);
--------------------------------------------------------------------------------
/src/Components/Layout/Message.js:
--------------------------------------------------------------------------------
1 | import React, { useState } from 'react';
2 | import clsx from 'clsx';
3 | import { Redirect, withRouter } from 'react-router-dom';
4 | import { Typography, Grid, Paper} from '@material-ui/core/';
5 | import { useStyles } from '../Styles/StyleMessage';
6 |
7 | function Message (props) {
8 | const classes = useStyles();
9 | const fixedHeightPaper = clsx(classes.paper, classes.fixedHeight);
10 |
11 | return (
12 |
13 |
14 |
15 |
16 | Welcome To MSG MART !!
17 |
18 |
19 | @Aldo Ignata Chandra
20 |
21 |
22 |
23 |
24 | )
25 | }
26 |
27 | export default withRouter(Message);
--------------------------------------------------------------------------------
/src/Components/Layout/Statistic.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import clsx from 'clsx';
3 | import { withRouter } from 'react-router-dom';
4 | import { Typography } from '@material-ui/core/';
5 | import { useStyles } from '../Styles/StyleDataCategory';
6 |
7 | function Statistic (props) {
8 | const classes = useStyles();
9 |
10 | return (
11 |
12 |
13 | DATA STATISTIC
14 |
15 |
17 |
18 |
19 | )
20 | }
21 |
22 | export default withRouter(Statistic);
--------------------------------------------------------------------------------
/src/Components/Layout/TestPagination.js:
--------------------------------------------------------------------------------
1 | import React, {useState, useEffect} from 'react';
2 | import { makeStyles } from '@material-ui/core/styles';
3 | import Table from '@material-ui/core/Table';
4 | import TableBody from '@material-ui/core/TableBody';
5 | import TableCell from '@material-ui/core/TableCell';
6 | import TableHead from '@material-ui/core/TableHead';
7 | import TablePagination from '@material-ui/core/TablePagination';
8 | import TableRow from '@material-ui/core/TableRow';
9 | import Paper from '@material-ui/core/Paper';
10 | import axios from 'axios';
11 | import { Redirect } from 'react-router-dom';
12 |
13 | const useStyles = makeStyles(theme => ({
14 | root: {
15 | width: '100%',
16 | marginTop: theme.spacing(3),
17 | },
18 | paper: {
19 | width: '100%',
20 | marginBottom: theme.spacing(2),
21 | },
22 | table: {
23 | minWidth: 750,
24 | },
25 | tableWrapper: {
26 | overflowX: 'auto',
27 | },
28 | visuallyHidden: {
29 | border: 0,
30 | clip: 'rect(0 0 0 0)',
31 | height: 1,
32 | margin: -1,
33 | overflow: 'hidden',
34 | padding: 0,
35 | position: 'absolute',
36 | top: 20,
37 | width: 1,
38 | },
39 | }));
40 |
41 | const headCells = [
42 | { id: 'Name', numeric: false, disablePadding: true, label: 'Name' },
43 | { id: 'Action', numeric: true, disablePadding: false, label: 'Action' },
44 | ];
45 |
46 | function EnhancedTableHead(props) {
47 |
48 | return (
49 |
50 |
51 |
52 | {headCells.map(headCell => (
53 |
58 | {headCell.label}
59 |
60 | ))}
61 |
62 |
63 | );
64 | }
65 |
66 | export default function EnhancedTable() {
67 |
68 | const classes = useStyles();
69 | const [dataCategory, setDataCategory] = useState ([]);
70 | const [token, setToken] = useState (localStorage.getItem("jwt"));
71 | const [page, setPage] = useState(0);
72 | const [infoPage, setInfoPage] = useState({maxPage: 0, totalAllCategories: 0});
73 | const [rowsPerPage, setRowsPerPage] = useState(5);
74 | const apiCategory = `https://pointofsalesapp.herokuapp.com/api/category`
75 |
76 | const fetchDataCategory = async () => {
77 | console.log(rowsPerPage, page, "uye")
78 | if (token === null) {
79 | return
80 | } else {
81 | const res = await axios (apiCategory, {headers: {"x-access-token":token},
82 | params: {
83 | item: rowsPerPage,
84 | page: page+1
85 | }});
86 | setDataCategory (res.data.result.response);
87 | setInfoPage (res.data.result.infoPage);
88 | console.log (res);
89 | }
90 | }
91 |
92 | const handleChangePage = (event, newPage) => {
93 | setPage(newPage);
94 | };
95 |
96 | const handleChangeRowsPerPage = event => {
97 | setRowsPerPage(parseInt(event.target.value, 10));
98 | setPage(0);
99 | };
100 |
101 | const emptyRows = rowsPerPage - Math.min(rowsPerPage, infoPage.totalAllCategories - page * rowsPerPage);
102 |
103 | useEffect(() => {
104 | fetchDataCategory ();
105 | },[page, rowsPerPage])
106 |
107 | return (
108 |
109 |
110 |
111 |
117 |
118 |
119 | {dataCategory
120 | .map((row, index) => {
121 | const labelId = `enhanced-table-checkbox-${index}`;
122 |
123 | return (
124 |
129 |
130 |
131 |
132 | {row.name}
133 |
134 | Action
135 |
136 | );
137 | })}
138 | {emptyRows > 0 && (
139 |
140 |
141 |
142 | )}
143 |
144 |
145 |
146 |
147 |
162 |
163 |
164 |
165 | );
166 | }
--------------------------------------------------------------------------------
/src/Components/Page/Dashboard.js:
--------------------------------------------------------------------------------
1 | import React, {useState} from 'react';
2 | import clsx from 'clsx';
3 | import { withRouter, Redirect, Route } from "react-router-dom";
4 | import { useStyles } from '../Styles/StyleDashboard';
5 | import MenuIcon from '@material-ui/icons/Menu';
6 | import ChevronLeftIcon from '@material-ui/icons/ChevronLeft';
7 | import { CssBaseline, Drawer, AppBar, Toolbar, List, Typography,
8 | Divider, IconButton } from '@material-ui/core/';
9 |
10 | //Import Button Menu
11 | import { mainListMenu } from '../Layout/ListMenu';
12 |
13 | //Import Content
14 | import Message from '../Layout/Message';
15 | import MainPage from '../Layout/MainPage';
16 | import DataCategory from '../Layout/DataCategory';
17 | import DataProduct from '../Layout/DataProduct';
18 | import Statistic from '../Layout/Statistic';
19 |
20 | import EnhancedTable from '../Layout/TestPagination';
21 |
22 | function Dashboard (props) {
23 |
24 | const classes = useStyles();
25 | const [token, setToken] = useState (localStorage.getItem("jwt"));
26 | const [openDrawer, setOpenDrawer] = useState (false);
27 |
28 | //Handle Animation Open Menu List
29 | const handleDrawerOpen = () => {
30 | setOpenDrawer(true);
31 | };
32 |
33 | //Handle Animation Close Menu List
34 | const handleDrawerClose = () => {
35 | setOpenDrawer(false);
36 | };
37 |
38 | return (
39 |
40 |
41 |
42 |
43 |
44 |
51 |
52 |
53 |
54 | MSG MART
55 |
56 |
57 |
58 |
59 |
66 |
67 |
68 | Menu
69 |
70 |
71 |
72 |
73 |
74 |
75 | { mainListMenu }
76 |
77 |
78 |
79 |
80 | {/* CONTENT */}
81 |
82 | {!token ? : ( )}
83 |
84 |
85 | {!token ? : ( )}
86 |
87 |
88 | {!token ? : ( )}
89 |
90 |
91 | {!token ? : ( )}
92 |
93 |
94 | {!token ? : ( )}
95 |
96 |
97 | {!token ? : ( )}
98 |
99 |
100 |
101 | )
102 | }
103 |
104 | export default withRouter(Dashboard);
--------------------------------------------------------------------------------
/src/Components/Page/Login.js:
--------------------------------------------------------------------------------
1 | import React, { useState } from 'react';
2 | import clsx from 'clsx';
3 | import { Link, withRouter } from 'react-router-dom';
4 | import { Avatar, Button, CssBaseline, TextField,Grid, Typography, Container } from '@material-ui/core';
5 | import { useStyles } from '../Styles/StyleSignUp';
6 | import Snackbar from '@material-ui/core/Snackbar';
7 | import CheckCircleIcon from '@material-ui/icons/CheckCircle';
8 | import ErrorIcon from '@material-ui/icons/Error';
9 | import SnackbarContent from '@material-ui/core/SnackbarContent';
10 |
11 | import { connect } from 'react-redux';
12 | import { postLogin } from '../Redux/Actions/auth';
13 |
14 | const variantIcon = {
15 | success: CheckCircleIcon,
16 | error: ErrorIcon,
17 | };
18 |
19 | function MySnackbarContentWrapper(props) {
20 | const classes = useStyles();
21 | const { className, message, variant } = props;
22 | const Icon = variantIcon[variant];
23 |
24 | return (
25 |
30 |
31 | {message}
32 |
33 | }
34 | />
35 | );
36 | }
37 |
38 | function Login (props) {
39 | const classes = useStyles();
40 | const [input, setInput] = useState({username:'', password:''})
41 | const [showStatus, setShowStatus] = useState(false);
42 | const [validate, setValidate] = useState ("");
43 | const [success, setSuccess] = useState ("error")
44 |
45 | const login = async (e) => {
46 | e.preventDefault();
47 |
48 | await props.dispatch(postLogin (input))
49 | .then((result) => {
50 | if (result.value.data.status !== 400){
51 | localStorage.setItem("jwt", result.value.data.result.token);
52 | setSuccess("success");
53 | setValidate("Login Success");
54 | setShowStatus(true);
55 | setTimeout(() => {
56 | props.history.push('/dashboard')
57 | }, 500);
58 | } else {
59 | setValidate(result.value.data.error);
60 | setShowStatus(true);
61 | }
62 | })
63 | .catch((error) => setShowStatus(false))
64 | }
65 |
66 | const onChangeLogin = (e) => {
67 | e.persist()
68 | setInput({...input, [e.target.name] : e.target.value})
69 | }
70 |
71 | const handleCloseSnackbar = () => {
72 | setShowStatus(false);
73 | };
74 |
75 | return (
76 |
77 |
86 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 | Login
99 |
100 |
136 |
137 |
138 |
139 | );
140 | }
141 |
142 | const mapStateToProps = state => {
143 | return {
144 | response: state.auth.loginResponse
145 | };
146 | };
147 |
148 | export default connect (mapStateToProps) (Login);
--------------------------------------------------------------------------------
/src/Components/Page/Logout.js:
--------------------------------------------------------------------------------
1 | import React, { useState } from 'react';
2 | import clsx from 'clsx';
3 | import { withRouter } from 'react-router-dom';
4 | import { ListItem, ListItemIcon, ListItemText } from '@material-ui/core';
5 | import Dialog from '@material-ui/core/Dialog';
6 | import DialogActions from '@material-ui/core/DialogActions';
7 | import DialogTitle from '@material-ui/core/DialogTitle';
8 | import ExitToAppIcon from '@material-ui/icons/ExitToApp';
9 | import Button from '@material-ui/core/Button';
10 | import Snackbar from '@material-ui/core/Snackbar';
11 | import CheckCircleIcon from '@material-ui/icons/CheckCircle';
12 | import ErrorIcon from '@material-ui/icons/Error';
13 | import SnackbarContent from '@material-ui/core/SnackbarContent';
14 | import { useStyles } from '../Styles/StyleLogout';
15 |
16 | const variantIcon = {
17 | success: CheckCircleIcon,
18 | error: ErrorIcon,
19 | };
20 |
21 | function MySnackbarContentWrapper(props) {
22 | const classes = useStyles();
23 | const { className, message, variant } = props;
24 | const Icon = variantIcon[variant];
25 |
26 | return (
27 |
32 |
33 | {message}
34 |
35 | }
36 | />
37 | );
38 | }
39 |
40 | function Logout (props) {
41 |
42 | // const classes = useStyles();
43 | const [token, setToken] = useState (localStorage.getItem("jwt"));
44 | const [alert, setAlert] = useState (false);
45 | const [showStatus, setShowStatus] = useState(false);
46 |
47 | const logout = () => {
48 | setAlert (false)
49 | setShowStatus (true);
50 | setToken (localStorage.clear());
51 | setTimeout(() => {
52 | props.history.push ('/');
53 | }, 750);
54 | }
55 |
56 | const handleAlertOpen = () => { setAlert (true) }
57 | const handleAlertClose = () => { setAlert (false) }
58 | const handleCloseSnackbar = () => { setShowStatus (false) }
59 |
60 | const classes = useStyles();
61 |
62 | return (
63 |
64 |
73 |
78 |
79 |
80 | {/* Button Logout */}
81 |
82 |
83 |
84 |
85 | Logout
86 |
87 |
88 | {/* Modal Logout */}
89 |
90 |
91 | Are You Sure Want To Logout From MSG MART ?
92 |
93 |
94 |
95 |
96 | Cancel
97 |
98 |
99 | Logout
100 |
101 |
102 |
103 |
104 | )
105 | }
106 |
107 | export default withRouter(Logout);
--------------------------------------------------------------------------------
/src/Components/Page/SignUp.js:
--------------------------------------------------------------------------------
1 | import React, { useState } from 'react';
2 | import clsx from 'clsx';
3 | import { Link, withRouter } from "react-router-dom";
4 | import { Avatar, Button, CssBaseline ,TextField, Grid, Typography, Container } from '@material-ui/core';
5 | import { useStyles } from '../Styles/StyleSignUp';
6 | import Snackbar from '@material-ui/core/Snackbar';
7 | import CheckCircleIcon from '@material-ui/icons/CheckCircle';
8 | import ErrorIcon from '@material-ui/icons/Error';
9 | import SnackbarContent from '@material-ui/core/SnackbarContent';
10 |
11 | import { connect } from 'react-redux';
12 | import { postRegister } from '../Redux/Actions/auth';
13 |
14 | const variantIcon = {
15 | success: CheckCircleIcon,
16 | error: ErrorIcon,
17 | };
18 |
19 | function MySnackbarContentWrapper(props) {
20 | const classes = useStyles();
21 | const { className, message, variant } = props;
22 | const Icon = variantIcon[variant];
23 |
24 | return (
25 |
30 |
31 | {message}
32 |
33 | }
34 | />
35 | );
36 | }
37 |
38 | function SignUp (props) {
39 |
40 | const classes = useStyles();
41 | const [input, setInput] = useState({ username: "", password: "", role: "" });
42 | const [showStatus, setShowStatus] = useState(false);
43 | const [validate, setValidate] = useState ("");
44 | const [success, setSuccess] = useState ("error")
45 |
46 | const register = async(e) => {
47 | e.preventDefault();
48 |
49 | await props.dispatch(postRegister (input))
50 | .then((result) => {
51 | console.log(result);
52 | if (result.value.data.status !== 400){
53 | setValidate(result.value.data.result);
54 | setSuccess("success");
55 | setShowStatus(true);
56 | setTimeout(() => {
57 | props.history.push('/')
58 | }, 1000);
59 | } else {
60 | setValidate(result.value.data.error)
61 | setShowStatus(true);
62 | }
63 | }).catch((error) => setShowStatus(false));
64 | }
65 |
66 | const onChangeSignup = (e) => {
67 | e.persist()
68 | setInput({...input, [e.target.name] : e.target.value})
69 | }
70 |
71 | const handleCloseSnackbar = () => {
72 | setShowStatus(false);
73 | };
74 |
75 | return (
76 |
77 |
86 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 | Sign Up
99 |
100 |
144 |
145 |
146 |
147 | );
148 | }
149 |
150 | const mapStateToProps = state => {
151 | return {
152 | response: state.auth.registerResponse
153 | };
154 | };
155 |
156 | export default connect (mapStateToProps) (SignUp);
--------------------------------------------------------------------------------
/src/Components/Redux/Actions/auth.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios';
2 |
3 | export const postRegister = (input) => {
4 | return {
5 | type: 'POST_REGISTER',
6 | payload: axios.post ('https://pointofsalesapp.herokuapp.com/api/user/register/',input),
7 | };
8 | };
9 |
10 | export const postLogin = (input) => {
11 | return {
12 | type: 'POST_LOGIN',
13 | payload: axios.post ('https://pointofsalesapp.herokuapp.com/api/user/login/',input),
14 | };
15 | };
--------------------------------------------------------------------------------
/src/Components/Redux/Actions/categories.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios';
2 |
3 | export const getCategories = (item, page) => {
4 | const token = localStorage.getItem("jwt");
5 | return {
6 | type: 'GET_CATEGORIES',
7 | payload: axios.get ('https://pointofsalesapp.herokuapp.com/api/category/',{
8 | params: {
9 | item,
10 | page
11 | },
12 | headers: {"x-access-token":token},
13 | })
14 | };
15 | };
16 |
17 | export const postCategories = (input) => {
18 | const token = localStorage.getItem("jwt");
19 | return {
20 | type: 'POST_CATEGORIES',
21 | payload: axios.post ('https://pointofsalesapp.herokuapp.com/api/category/', input, { headers: {"x-access-token":token} } )
22 | };
23 | };
24 |
25 | export const patchCategories = (input) => {
26 | const token = localStorage.getItem("jwt");
27 | const id = input.id;
28 | return {
29 | type: 'PATCH_CATEGORIES',
30 | payload: axios.put ('https://pointofsalesapp.herokuapp.com/api/category/'+id, input, { headers: {"x-access-token":token} })
31 | };
32 | };
33 |
34 | export const deleteCategories = (input) => {
35 | const token = localStorage.getItem("jwt");
36 | const id = input.id;
37 | return {
38 | type: 'DELETE_CATEGORIES',
39 | payload: axios.delete ('https://pointofsalesapp.herokuapp.com/api/category/'+id, { headers: {"x-access-token":token} })
40 | };
41 | };
42 |
--------------------------------------------------------------------------------
/src/Components/Redux/Actions/order.js:
--------------------------------------------------------------------------------
1 | export const addToCart = (item) => {
2 | return {
3 | type: 'ADD_TO_CART',
4 | item
5 | }
6 | }
7 |
8 | //remove item action
9 | export const removeItem = (item) =>{
10 | return{
11 | type: 'REMOVE_ITEM',
12 | item
13 | }
14 | }
15 |
16 | //subtract qt action
17 | export const subtractQuantity = (item) => {
18 | return{
19 | type: 'SUB_QUANTITY',
20 | item
21 | }
22 | }
23 |
24 | //add qt action
25 | export const addQuantity = (item) => {
26 | return{
27 | type: 'ADD_QUANTITY',
28 | item
29 | }
30 | }
--------------------------------------------------------------------------------
/src/Components/Redux/Actions/product.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios';
2 |
3 | export const getProducts = (item, page) => {
4 | const token = localStorage.getItem("jwt");
5 | return {
6 | type: 'GET_PRODUCT',
7 | payload: axios.get ('https://pointofsalesapp.herokuapp.com/api/product/',{
8 | params: {
9 | item,
10 | page
11 | },
12 | headers: {"x-access-token":token},
13 | })
14 | };
15 | };
16 |
17 | export const postProducts = (input) => {
18 | const token = localStorage.getItem("jwt");
19 | return {
20 | type: 'POST_PRODUCT',
21 | payload: axios.post ('https://pointofsalesapp.herokuapp.com/api/product/', input, { headers: {"x-access-token":token} } )
22 | };
23 | };
24 |
25 | export const patchProducts = (input) => {
26 | const token = localStorage.getItem("jwt");
27 | const id = input.id;
28 | return {
29 | type: 'PATCH_PRODUCT',
30 | payload: axios.put ('https://pointofsalesapp.herokuapp.com/api/product/'+id, input, { headers: {"x-access-token":token} })
31 | };
32 | };
33 |
34 | export const deleteProducts = (input) => {
35 | const token = localStorage.getItem("jwt");
36 | const id = input.id;
37 | return {
38 | type: 'DELETE_PRODUCT',
39 | payload: axios.delete ('https://pointofsalesapp.herokuapp.com/api/product/'+id, { headers: {"x-access-token":token} })
40 | };
41 | };
42 |
--------------------------------------------------------------------------------
/src/Components/Redux/Reducers/auth.js:
--------------------------------------------------------------------------------
1 | const initialState = {
2 | registerResponse: [],
3 | loginResponse: [],
4 | isLoading: false,
5 | isRejected: false,
6 | isFulfilled: false,
7 | };
8 |
9 | const auth = (state = initialState, action) => {
10 | switch (action.type) {
11 | case 'POST_REGISTER_PENDING':
12 | return {
13 | ...state,
14 | isLoading: true,
15 | isRejected: false,
16 | isFulfilled: false,
17 | };
18 | case 'POST_REGISTER_REJECTED':
19 | return {
20 | ...state,
21 | isLoading: false,
22 | isRejected: true,
23 | };
24 | case 'POST_REGISTER_FULFILLED':
25 | return {
26 | ...state,
27 | isLoading: false,
28 | isFulfilled: true,
29 | registerResponse: action.payload,
30 | };
31 | //-------------------------------------------------------------
32 | case 'POST_LOGIN_PENDING':
33 | return {
34 | ...state,
35 | isLoading: true,
36 | isRejected: false,
37 | isFulfilled: false,
38 | };
39 | case 'POST_LOGIN_REJECTED':
40 | return {
41 | ...state,
42 | isLoading: false,
43 | isRejected: true,
44 | };
45 | case 'POST_LOGIN_FULFILLED':
46 | return {
47 | ...state,
48 | isLoading: false,
49 | isFulfilled: true,
50 | loginResponse: action.payload,
51 | };
52 |
53 | default:
54 | return state;
55 | }
56 | };
57 |
58 | export default auth;
--------------------------------------------------------------------------------
/src/Components/Redux/Reducers/categories.js:
--------------------------------------------------------------------------------
1 | const initialState = {
2 | listCategory: [],
3 | isLoading: false,
4 | isRejected: false,
5 | isFulfilled: false,
6 | };
7 |
8 | const categories = (state = initialState, action) => {
9 | switch (action.type) {
10 | // GET CATEGORIES
11 | case 'GET_CATEGORIES_PENDING':
12 | return {
13 | ...state,
14 | isLoading: true,
15 | isRejected: false,
16 | isFulfilled: false,
17 | };
18 | case 'GET_CATEGORIES_REJECTED':
19 | return {
20 | ...state,
21 | isLoading: false,
22 | isRejected: true,
23 | };
24 | case 'GET_CATEGORIES_FULFILLED':
25 | return {
26 | ...state,
27 | isLoading: false,
28 | isFulfilled: true,
29 | listCategory: action.payload.data.result.response,
30 | };
31 |
32 | // POST CATEGORIES
33 | case 'POST_CATEGORIES_PENDING':
34 | return {
35 | ...state,
36 | isLoading: true,
37 | isRejected: false,
38 | isFulfilled: false,
39 | };
40 | case 'POST_CATEGORIES_REJECTED':
41 | return {
42 | ...state,
43 | isLoading: false,
44 | isRejected: true,
45 | };
46 | case 'POST_CATEGORIES_FULFILLED':
47 | if (action.payload.data.status == 200)
48 | state.listCategory.push (action.payload.data.result[0])
49 | return {
50 | ...state,
51 | isLoading: false,
52 | isFulfilled: true,
53 | listCategory: state.listCategory,
54 | };
55 |
56 | // EDIT CATEGORIES
57 | case 'PATCH_CATEGORIES_PENDING':
58 | return {
59 | ...state,
60 | isLoading: true,
61 | isRejected: false,
62 | isFulfilled: false,
63 | };
64 | case 'PATCH_CATEGORIES_REJECTED':
65 | return {
66 | ...state,
67 | isLoading: false,
68 | isRejected: true,
69 | };
70 | case 'PATCH_CATEGORIES_FULFILLED':
71 | const listCategoryAfterPatch = state.listCategory.map (categories => {
72 | if (action.payload.data.status == 200) {
73 | if (categories.id == action.payload.data.response.id) {
74 | return action.payload.data.response;
75 | }
76 | }
77 | return categories;
78 | });
79 | return {
80 | ...state,
81 | isLoading: false,
82 | isFulfilled: true,
83 | listCategory: listCategoryAfterPatch
84 | };
85 |
86 | // DELETE CATEGORIES
87 | case 'DELETE_CATEGORIES_PENDING':
88 | return {
89 | ...state,
90 | isLoading: true,
91 | isRejected: false,
92 | isFulfilled: false,
93 | };
94 | case 'DELETE_CATEGORIES_REJECTED':
95 | return {
96 | ...state,
97 | isLoading: false,
98 | isRejected: true,
99 | };
100 | case 'DELETE_CATEGORIES_FULFILLED':
101 | const dataAfterDelete = state.listCategory.filter((value) => {
102 | return value.id != action.payload.data.id });
103 | return {
104 | ...state,
105 | isLoading: false,
106 | isFulfilled: true,
107 | listCategory: dataAfterDelete,
108 | };
109 |
110 | default:
111 | return state;
112 | }
113 | };
114 |
115 | export default categories;
--------------------------------------------------------------------------------
/src/Components/Redux/Reducers/index.js:
--------------------------------------------------------------------------------
1 |
2 | import { combineReducers } from 'redux';
3 |
4 | import auth from './auth';
5 | import product from './product';
6 | import categories from './categories';
7 | import order from './order';
8 |
9 | const appReducer = combineReducers ({
10 | auth,
11 | product,
12 | categories,
13 | order
14 | });
15 |
16 | export default appReducer;
--------------------------------------------------------------------------------
/src/Components/Redux/Reducers/order.js:
--------------------------------------------------------------------------------
1 | const initialState = {
2 | addedItem: [],
3 | total: 0,
4 | isLoading: false,
5 | isRejected: false,
6 | isFulfilled: false,
7 | };
8 |
9 | const order = (state = initialState, action) => {
10 | switch (action.type) {
11 | //Add Selected Product To Cart
12 | case 'ADD_TO_CART':
13 | let existed_item = state.addedItem.find( product => action.item.id === product.id )
14 |
15 | state.addedItem.push ({
16 | id: action.item.id,
17 | product_name: action.item.product_name,
18 | image: action.item.image,
19 | price: action.item.price,
20 | quantity: action.item.quantity,
21 | totalQty: 1
22 | });
23 |
24 | if(existed_item)
25 | {
26 | state.addedItem.quantity += 1
27 | return {
28 | ...state,
29 | // total: state.total + state.addedItem.price
30 | }
31 | } else {
32 | // state.addedItem.quantity = 1;
33 | return {
34 | ...state,
35 | addedItem: state.addedItem,
36 | // total : state.total + state.addedItem.price
37 | }
38 | }
39 | case 'ADD_QUANTITY':
40 | let addeQuantity = state.addedItems.find(item=> item.id_product === action.id)
41 | addeQuantity.quantity += 1
42 | let Totaladd = state.total + addeQuantity.price
43 | return{
44 | ...state,
45 | total: Totaladd
46 | }
47 | case 'SUB_QUANTITY':
48 | let subQuantity = state.addedItems.find(item=> item.id_product === action.id)
49 | subQuantity.quantity -= 1
50 | let Totalsub = state.total - subQuantity.price
51 | return {
52 | ...state,
53 | total: Totalsub
54 | }
55 | case 'REMOVE_ITEM':
56 | let itemToRemove= state.addedItems.find(item=> action.id === item.id_product)
57 | let new_items = state.addedItems.filter(item=> action.id !== item.id_product)
58 |
59 | //calculating the total
60 | let newTotal = state.total - (itemToRemove.price * itemToRemove.quantity )
61 | return {
62 | ...state,
63 | addedItems: new_items,
64 | total: newTotal
65 | }
66 |
67 | default:
68 | return state;
69 | }
70 | };
71 |
72 | export default order;
--------------------------------------------------------------------------------
/src/Components/Redux/Reducers/product.js:
--------------------------------------------------------------------------------
1 | const initialState = {
2 | listProduct: [],
3 | isLoading: false,
4 | isRejected: false,
5 | isFulfilled: false,
6 | addedItem: [],
7 | total: 0,
8 | };
9 |
10 | const product = (state = initialState, action) => {
11 | switch (action.type) {
12 | // GET PRODUCT
13 | case 'GET_PRODUCT_PENDING':
14 | return {
15 | ...state,
16 | isLoading: true,
17 | isRejected: false,
18 | isFulfilled: false,
19 | };
20 | case 'GET_PRODUCT_REJECTED':
21 | return {
22 | ...state,
23 | isLoading: false,
24 | isRejected: true,
25 | };
26 | case 'GET_PRODUCT_FULFILLED':
27 | return {
28 | ...state,
29 | isLoading: false,
30 | isFulfilled: true,
31 | listProduct: action.payload.data.result.response,
32 | };
33 |
34 | //POST PRODUCT
35 | case 'POST_PRODUCT_PENDING':
36 | return {
37 | ...state,
38 | isLoading: true,
39 | isRejected: false,
40 | isFulfilled: false,
41 | };
42 | case 'POST_PRODUCT_REJECTED':
43 | return {
44 | ...state,
45 | isLoading: false,
46 | isRejected: true,
47 | };
48 | case 'POST_PRODUCT_FULFILLED':
49 | if (action.payload.data.status == 200)
50 | state.listProduct.push (action.payload.data.result[0])
51 | return {
52 | ...state,
53 | isLoading: false,
54 | isFulfilled: true,
55 | listProduct: state.listProduct,
56 | };
57 |
58 | //EDIT PRODUCT
59 | case 'PATCH_PRODUCT_PENDING':
60 | return {
61 | ...state,
62 | isLoading: true,
63 | isRejected: false,
64 | isFulfilled: false,
65 | };
66 | case 'PATCH_PRODUCT_REJECTED':
67 | return {
68 | ...state,
69 | isLoading: false,
70 | isRejected: true,
71 | };
72 | case 'PATCH_PRODUCT_FULFILLED':
73 | const listProductAfterPatch = state.listProduct.map (products => {
74 | if (action.payload.data.status == 200) {
75 | if (products.id == action.payload.data.result[0].id) {
76 | return action.payload.data.result[0];
77 | }
78 | }
79 | return products;
80 | });
81 | return {
82 | ...state,
83 | isLoading: false,
84 | isFulfilled: true,
85 | listProduct: listProductAfterPatch
86 | };
87 |
88 | //DELETE PRODUCT
89 | case 'DELETE_PRODUCT_PENDING':
90 | return {
91 | ...state,
92 | isLoading: true,
93 | isRejected: false,
94 | isFulfilled: false,
95 | };
96 | case 'DELETE_PRODUCT_REJECTED':
97 | return {
98 | ...state,
99 | isLoading: false,
100 | isRejected: true,
101 | };
102 | case 'DELETE_PRODUCT_FULFILLED':
103 | const dataAfterDelete = state.listProduct.filter((value) => {
104 | return value.id != action.payload.data.id });
105 | return {
106 | ...state,
107 | isLoading: false,
108 | isFulfilled: true,
109 | listProduct: dataAfterDelete,
110 | };
111 |
112 | default:
113 | return state;
114 | }
115 | };
116 |
117 | export default product;
--------------------------------------------------------------------------------
/src/Components/Redux/store.js:
--------------------------------------------------------------------------------
1 | import {createStore, applyMiddleware} from 'redux';
2 | import {createLogger} from 'redux-logger';
3 | import promiseMiddleware from 'redux-promise-middleware';
4 |
5 | import Reducers from './Reducers';
6 |
7 | const logger = createLogger ();
8 | const middleware = applyMiddleware (logger, promiseMiddleware);
9 | const store = createStore (Reducers, middleware);
10 |
11 | export default store;
--------------------------------------------------------------------------------
/src/Components/Styles/StyleDashboard.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from '@material-ui/core/styles';
2 |
3 | const drawerWidth = 240;
4 | export const useStyles = makeStyles(theme => ({
5 | root: {
6 | display: 'flex',
7 | },
8 | toolbar: {
9 | paddingRight: 24, // keep right padding when drawer closed
10 | },
11 | toolbarIcon: {
12 | display: 'flex',
13 | alignItems: 'center',
14 | justifyContent: 'flex-end',
15 | padding: '0 8px',
16 | ...theme.mixins.toolbar,
17 | },
18 | appBar: {
19 | backgroundColor: "#ffce1e",
20 | zIndex: theme.zIndex.drawer + 1,
21 | transition: theme.transitions.create(['width', 'margin'], {
22 | easing: theme.transitions.easing.sharp,
23 | duration: theme.transitions.duration.leavingScreen,
24 | }),
25 | },
26 | appBarShift: {
27 | marginLeft: drawerWidth,
28 | width: `calc(100% - ${drawerWidth}px)`,
29 | transition: theme.transitions.create(['width', 'margin'], {
30 | easing: theme.transitions.easing.sharp,
31 | duration: theme.transitions.duration.enteringScreen,
32 | }),
33 | },
34 | menuButton: {
35 | marginRight: 36,
36 | },
37 | menuButtonHidden: {
38 | display: 'none',
39 | },
40 | title: {
41 | color: "#34495e",
42 | flexGrow: 1,
43 | fontFamily: "Airbnb Cereal App",
44 | fontWeight: "bold",
45 | textAlign: "center",
46 | fontSize: "40px"
47 | },
48 | subMenu: {
49 | flexGrow: 1,
50 | fontFamily: "Airbnb Cereal App",
51 | fontWeight: "bold",
52 | textAlign: "center",
53 | fontSize: "30px"
54 | },
55 | drawerPaper: {
56 | position: 'relative',
57 | whiteSpace: 'nowrap',
58 | width: drawerWidth,
59 | transition: theme.transitions.create('width', {
60 | easing: theme.transitions.easing.sharp,
61 | duration: theme.transitions.duration.enteringScreen,
62 | }),
63 | },
64 | drawerPaperClose: {
65 | overflowX: 'hidden',
66 | transition: theme.transitions.create('width', {
67 | easing: theme.transitions.easing.sharp,
68 | duration: theme.transitions.duration.leavingScreen,
69 | }),
70 | width: theme.spacing(7),
71 | [theme.breakpoints.up('sm')]: {
72 | width: theme.spacing(9),
73 | },
74 | },
75 | appBarSpacer: theme.mixins.toolbar,
76 | content: {
77 | flexGrow: 1,
78 | height: '100vh',
79 | overflow: 'auto',
80 | },
81 | container: {
82 | paddingTop: theme.spacing(4),
83 | paddingBottom: theme.spacing(4),
84 | },
85 | paper: {
86 | padding: theme.spacing(1),
87 | display: 'flex',
88 | overflow: 'auto',
89 | flexDirection: 'column',
90 | border: "1px solid #CECECE"
91 | },
92 | fixedHeight: {
93 | height: "89vh",
94 | width: "90wh",
95 | },
96 | bigavatar: {
97 | margin: theme.spacing(1),
98 | width: 70,
99 | height: 70,
100 | },
101 | button: {
102 | height: 50,
103 | width: 170,
104 | margin: theme.spacing(2)
105 | },
106 | }));
--------------------------------------------------------------------------------
/src/Components/Styles/StyleDataCategory.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from '@material-ui/core/styles';
2 | import { green } from '@material-ui/core/colors';
3 |
4 | export const useStyles = makeStyles(theme => ({
5 | root: {
6 | width: '100%',
7 | },
8 | paper: {
9 | marginTop: theme.spacing(3),
10 | margin : theme.spacing(3),
11 | width: '95%',
12 | overflowX: 'auto',
13 | marginBottom: theme.spacing(2),
14 | },
15 | table: {
16 | minWidth: 650,
17 | },
18 | tableHeader: {
19 | fontWeight:"bold",
20 | fontSize:"17px"
21 | },
22 | bigAvatar: {
23 | margin: 10,
24 | width: 60,
25 | height: 60,
26 | },
27 | title: {
28 | margin : theme.spacing(3),
29 | },
30 | modal: {
31 | display: 'flex',
32 | alignItems: 'center',
33 | justifyContent: 'center',
34 | },
35 | textField: {
36 | marginLeft: theme.spacing(1),
37 | marginRight: theme.spacing(1),
38 | width: 400,
39 | height: 50
40 | },
41 | boldText: {
42 | fontWeight: "bold",
43 | fontSize: "17px"
44 | },
45 | button: {
46 | borderStyle: "solid",
47 | borderWidth: "2px"
48 | },
49 | buttonAdd: {
50 | marginLeft: theme.spacing(3),
51 | borderStyle: "solid",
52 | borderWidth: "2px",
53 | color: "#ffce1e",
54 | fontWeight:"bold",
55 | background: "white"
56 | },
57 | dialogTitle: {
58 | display: 'flex',
59 | alignItems: 'center',
60 | justifyContent: 'center',
61 | },
62 | success: {
63 | backgroundColor: green[600],
64 | },
65 | error: {
66 | backgroundColor: theme.palette.error.dark,
67 | },
68 | icon: {
69 | fontSize: 20,
70 | },
71 | iconVariant: {
72 | opacity: 0.9,
73 | marginRight: theme.spacing(1),
74 | },
75 | message: {
76 | display: 'flex',
77 | alignItems: 'center',
78 | },
79 | maintenance: {
80 | marginLeft: "340px",
81 | width: "500px"
82 | },
83 | }));
--------------------------------------------------------------------------------
/src/Components/Styles/StyleLogout.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from '@material-ui/core/styles';
2 | import { green } from '@material-ui/core/colors';
3 |
4 | export const useStyles = makeStyles(theme => ({
5 | dialogTitle: {
6 | fontFamily: "Arial",
7 | textAlign: "center",
8 | fontWeight: "bold",
9 | color: "red"
10 | },
11 | buttonText: {
12 | fontWeight: "bold"
13 | },
14 | button: {
15 | color: "red"
16 | },
17 | success: {
18 | backgroundColor: green[600],
19 | },
20 | error: {
21 | backgroundColor: theme.palette.error.dark,
22 | },
23 | icon: {
24 | fontSize: 20,
25 | },
26 | iconVariant: {
27 | opacity: 0.9,
28 | marginRight: theme.spacing(1),
29 | },
30 | message: {
31 | display: 'flex',
32 | alignItems: 'center',
33 | },
34 | }));
--------------------------------------------------------------------------------
/src/Components/Styles/StyleMainPage.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from '@material-ui/core/styles';
2 |
3 | export const useStyles = makeStyles(theme => ({
4 | container: {
5 | paddingTop: theme.spacing(4),
6 | paddingBottom: theme.spacing(4),
7 | },
8 | paper: {
9 | padding: theme.spacing(3),
10 | display: 'flex',
11 | overflow: 'auto',
12 | flexDirection: 'column',
13 | border: "0px solid #CECECE"
14 | },
15 | fixedHeight: {
16 | height: "89vh",
17 | width: "90wh",
18 | },
19 | button: {
20 | height: 45,
21 | width: 150,
22 | margin: theme.spacing(1)
23 | },
24 | cartMaintenance: {
25 | marginTop: "70px",
26 | marginLeft: "60px",
27 | width: "300px"
28 | }
29 | }));
--------------------------------------------------------------------------------
/src/Components/Styles/StyleMessage.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from '@material-ui/core/styles';
2 |
3 | export const useStyles = makeStyles(theme => ({
4 | container: {
5 | paddingTop: theme.spacing(4),
6 | paddingBottom: theme.spacing(4),
7 | },
8 | paper: {
9 | padding: theme.spacing(1),
10 | display: 'flex',
11 | overflow: 'auto',
12 | flexDirection: 'column',
13 | textAlign: "center",
14 | },
15 | fixedHeight: {
16 | height: "50vh",
17 | width: "90wh",
18 | },
19 | info: {
20 | fontWeight:"bold",
21 | marginTop:"80px"
22 | }
23 | }));
--------------------------------------------------------------------------------
/src/Components/Styles/StyleOrderCard.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from '@material-ui/core/styles';
2 |
3 | export const useStyles = makeStyles(theme => ({
4 | card: {
5 | display: 'flex',
6 | margin: "3px",
7 | },
8 | details: {
9 | display: 'flex',
10 | flexDirection: 'column',
11 | },
12 | content: {
13 | flex: '1 0 auto',
14 | },
15 | image: {
16 | width: 170,
17 | height: 110,
18 | margin: "5px",
19 | },
20 | controls: {
21 | display: 'flex',
22 | alignItems: 'center',
23 | justifyContent: "center"
24 | },
25 | }));
--------------------------------------------------------------------------------
/src/Components/Styles/StyleProductCard.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from '@material-ui/core/styles';
2 |
3 | export const useStyles = makeStyles(theme => ({
4 | root: {
5 | position: 'fixed',
6 | bottom: theme.spacing(2),
7 | right: theme.spacing(2),
8 | },
9 | card: {
10 | width: "100%",
11 | maxHeight: 300,
12 | borderRadius: 10,
13 | margin: "5px",
14 | },
15 | button: {
16 | fontSize: "12px",
17 | height: 30,
18 | width: 50,
19 | background: "#e74c3c"
20 | },
21 | buttonOrderBy: {
22 | margin: theme.spacing(1),
23 | marginBottom: "10px",
24 | background: "#e67e22",
25 | fontWeight: "bold",
26 | },
27 | buttonSort: {
28 | margin: theme.spacing(1),
29 | marginBottom: "10px",
30 | background: "#e74c3c",
31 | fontWeight: "bold"
32 | },
33 | buttonSearch: {
34 | margin: theme.spacing(1),
35 | marginBottom: "10px",
36 | },
37 | searchField: {
38 | width:"430px",
39 | },
40 | textError: {
41 | fontWeight: "bold",
42 | margin: "auto",
43 | marginTop: "100px",
44 | color: "#e67e22",
45 | border: "solid"
46 | }
47 | }));
--------------------------------------------------------------------------------
/src/Components/Styles/StyleSignUp.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from '@material-ui/core/styles';
2 | import { green } from '@material-ui/core/colors';
3 |
4 | export const useStyles = makeStyles(theme => ({
5 | '@global': {
6 | body: {
7 | backgroundColor: "#ffce1e",
8 | },
9 | },
10 | paper: {
11 | marginTop: theme.spacing(8),
12 | display: 'flex',
13 | flexDirection: 'column',
14 | alignItems: 'center',
15 | },
16 | bigavatar: {
17 | margin: theme.spacing(1),
18 | width: 70,
19 | height: 70,
20 | },
21 | form: {
22 | width: '100%', // Fix IE 11 issue.
23 | marginTop: theme.spacing(3),
24 | },
25 | submit: {
26 | margin: theme.spacing(3, 0, 2),
27 | },
28 | linkinfo: {
29 | display: 'flex',
30 | flexDirection: 'column',
31 | alignItems: 'center'
32 | },
33 | success: {
34 | backgroundColor: green[600],
35 | },
36 | error: {
37 | backgroundColor: theme.palette.error.dark,
38 | },
39 | icon: {
40 | fontSize: 20,
41 | },
42 | iconVariant: {
43 | opacity: 0.9,
44 | marginRight: theme.spacing(1),
45 | },
46 | message: {
47 | display: 'flex',
48 | alignItems: 'center',
49 | },
50 | }));
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import AppRouter from './AppRouter';
4 | import * as serviceWorker from './serviceWorker';
5 | import { Provider } from 'react-redux';
6 | import store from './Components/Redux/store';
7 |
8 | const WappedApp = () => {
9 | return (
10 |
11 |
12 |
13 | )
14 | }
15 |
16 | ReactDOM.render( , document.getElementById('root'));
17 |
18 | // If you want your app to work offline and load faster, you can change
19 | // unregister() to register() below. Note this comes with some pitfalls.
20 | // Learn more about service workers: https://bit.ly/CRA-PWA
21 | serviceWorker.unregister();
22 |
--------------------------------------------------------------------------------
/src/serviceWorker.js:
--------------------------------------------------------------------------------
1 | // This optional code is used to register a service worker.
2 | // register() is not called by default.
3 |
4 | // This lets the app load faster on subsequent visits in production, and gives
5 | // it offline capabilities. However, it also means that developers (and users)
6 | // will only see deployed updates on subsequent visits to a page, after all the
7 | // existing tabs open on the page have been closed, since previously cached
8 | // resources are updated in the background.
9 |
10 | // To learn more about the benefits of this model and instructions on how to
11 | // opt-in, read https://bit.ly/CRA-PWA
12 |
13 | const isLocalhost = Boolean(
14 | window.location.hostname === 'localhost' ||
15 | // [::1] is the IPv6 localhost address.
16 | window.location.hostname === '[::1]' ||
17 | // 127.0.0.1/8 is considered localhost for IPv4.
18 | window.location.hostname.match(
19 | /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
20 | )
21 | );
22 |
23 | export function register(config) {
24 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
25 | // The URL constructor is available in all browsers that support SW.
26 | const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);
27 | if (publicUrl.origin !== window.location.origin) {
28 | // Our service worker won't work if PUBLIC_URL is on a different origin
29 | // from what our page is served on. This might happen if a CDN is used to
30 | // serve assets; see https://github.com/facebook/create-react-app/issues/2374
31 | return;
32 | }
33 |
34 | window.addEventListener('load', () => {
35 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
36 |
37 | if (isLocalhost) {
38 | // This is running on localhost. Let's check if a service worker still exists or not.
39 | checkValidServiceWorker(swUrl, config);
40 |
41 | // Add some additional logging to localhost, pointing developers to the
42 | // service worker/PWA documentation.
43 | navigator.serviceWorker.ready.then(() => {
44 | console.log(
45 | 'This web app is being served cache-first by a service ' +
46 | 'worker. To learn more, visit https://bit.ly/CRA-PWA'
47 | );
48 | });
49 | } else {
50 | // Is not localhost. Just register service worker
51 | registerValidSW(swUrl, config);
52 | }
53 | });
54 | }
55 | }
56 |
57 | function registerValidSW(swUrl, config) {
58 | navigator.serviceWorker
59 | .register(swUrl)
60 | .then(registration => {
61 | registration.onupdatefound = () => {
62 | const installingWorker = registration.installing;
63 | if (installingWorker == null) {
64 | return;
65 | }
66 | installingWorker.onstatechange = () => {
67 | if (installingWorker.state === 'installed') {
68 | if (navigator.serviceWorker.controller) {
69 | // At this point, the updated precached content has been fetched,
70 | // but the previous service worker will still serve the older
71 | // content until all client tabs are closed.
72 | console.log(
73 | 'New content is available and will be used when all ' +
74 | 'tabs for this page are closed. See https://bit.ly/CRA-PWA.'
75 | );
76 |
77 | // Execute callback
78 | if (config && config.onUpdate) {
79 | config.onUpdate(registration);
80 | }
81 | } else {
82 | // At this point, everything has been precached.
83 | // It's the perfect time to display a
84 | // "Content is cached for offline use." message.
85 | console.log('Content is cached for offline use.');
86 |
87 | // Execute callback
88 | if (config && config.onSuccess) {
89 | config.onSuccess(registration);
90 | }
91 | }
92 | }
93 | };
94 | };
95 | })
96 | .catch(error => {
97 | console.error('Error during service worker registration:', error);
98 | });
99 | }
100 |
101 | function checkValidServiceWorker(swUrl, config) {
102 | // Check if the service worker can be found. If it can't reload the page.
103 | fetch(swUrl)
104 | .then(response => {
105 | // Ensure service worker exists, and that we really are getting a JS file.
106 | const contentType = response.headers.get('content-type');
107 | if (
108 | response.status === 404 ||
109 | (contentType != null && contentType.indexOf('javascript') === -1)
110 | ) {
111 | // No service worker found. Probably a different app. Reload the page.
112 | navigator.serviceWorker.ready.then(registration => {
113 | registration.unregister().then(() => {
114 | window.location.reload();
115 | });
116 | });
117 | } else {
118 | // Service worker found. Proceed as normal.
119 | registerValidSW(swUrl, config);
120 | }
121 | })
122 | .catch(() => {
123 | console.log(
124 | 'No internet connection found. App is running in offline mode.'
125 | );
126 | });
127 | }
128 |
129 | export function unregister() {
130 | if ('serviceWorker' in navigator) {
131 | navigator.serviceWorker.ready.then(registration => {
132 | registration.unregister();
133 | });
134 | }
135 | }
136 |
--------------------------------------------------------------------------------