tosanoob commited on
Commit
0dd6a66
1 Parent(s): 708809b

Update: reformating frontend

Browse files
frontend/.gitignore CHANGED
@@ -24,4 +24,5 @@ yarn-error.log*
24
 
25
  .env
26
  note_dev.txt
27
- object.json
 
 
24
 
25
  .env
26
  note_dev.txt
27
+ object.json
28
+ .json
frontend/public/about-us.jpg ADDED
frontend/public/header.jpg ADDED
frontend/src/index.js CHANGED
@@ -1,8 +1,9 @@
1
  import React from 'react';
2
  import ReactDOM from 'react-dom/client';
3
  import { createBrowserRouter, RouterProvider } from 'react-router-dom';
4
- import './styles/index.css';
5
  import 'bootstrap/dist/css/bootstrap.min.css';
 
 
6
  import ErrorPage from './pages/ErrorPage';
7
  import HomePage from './pages/HomePage';
8
  import reportWebVitals from './reportWebVitals';
@@ -13,48 +14,91 @@ import MenuPage from './pages/MenuPage';
13
  import CartPage from './pages/CartPage';
14
  import UserInfoPage from './pages/UserInfoPage';
15
 
 
 
 
 
 
 
 
16
  const router = createBrowserRouter([
17
- {
18
- path: "/",
19
- element: <HomePage />,
20
- errorElement: <ErrorPage />,
21
- },
22
- {
23
- path: "/login",
24
- element: <LoginPage />,
25
- errorElement: <ErrorPage />
26
- },
27
- {
28
- path: "/register",
29
- element: <RegisterPage/>,
30
- errorElement: <ErrorPage/>
31
- },
32
- {
33
- path: "/news",
34
- element: <NewsPage/>,
35
- errorElement: <ErrorPage/>
36
- },
37
- {
38
- path: "/menu",
39
- element: <MenuPage/>
40
- },
41
- {
42
- path: "/cart",
43
- element: <CartPage/>,
44
- errorElement: <ErrorPage/>
45
- },
46
- {
47
- path: "/userinfo",
48
- element: <UserInfoPage/>,
49
- errorElement: <ErrorPage/>
50
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51
  ]);
52
 
53
  const root = ReactDOM.createRoot(document.getElementById('root'));
54
  root.render(
55
- <React.StrictMode>
56
- <RouterProvider router={router}/>
57
- </React.StrictMode>
58
  );
59
 
60
  // If you want to start measuring performance in your app, pass a function
 
1
  import React from 'react';
2
  import ReactDOM from 'react-dom/client';
3
  import { createBrowserRouter, RouterProvider } from 'react-router-dom';
 
4
  import 'bootstrap/dist/css/bootstrap.min.css';
5
+ import './styles/index.css';
6
+ import './styles/styles.css';
7
  import ErrorPage from './pages/ErrorPage';
8
  import HomePage from './pages/HomePage';
9
  import reportWebVitals from './reportWebVitals';
 
14
  import CartPage from './pages/CartPage';
15
  import UserInfoPage from './pages/UserInfoPage';
16
 
17
+ import AdminSummaryPage from './pages/AdminSummaryPage';
18
+ import AdminFeedPage from './pages/AdminFeedPage';
19
+ import AdminMenuPage from './pages/AdminMenuPage';
20
+ import AdminStaffPage from './pages/AdminStaffPage';
21
+ import AdminOrderPage from './pages/AdminOrderPage';
22
+ import AdminSchedulePage from './pages/AdminSchedulePage';
23
+
24
  const router = createBrowserRouter([
25
+ {
26
+ path: "/",
27
+ element: <HomePage />,
28
+ errorElement: <ErrorPage />,
29
+ },
30
+ {
31
+ path: "/login",
32
+ element: <LoginPage />,
33
+ errorElement: <ErrorPage />
34
+ },
35
+ {
36
+ path: "/register",
37
+ element: <RegisterPage />,
38
+ errorElement: <ErrorPage />
39
+ },
40
+ {
41
+ path: "/news",
42
+ element: <NewsPage />,
43
+ errorElement: <ErrorPage />
44
+ },
45
+ {
46
+ path: "/menu",
47
+ element: <MenuPage />
48
+ },
49
+ {
50
+ path: "/cart",
51
+ element: <CartPage />,
52
+ errorElement: <ErrorPage />
53
+ },
54
+ {
55
+ path: "/userinfo",
56
+ element: <UserInfoPage />,
57
+ errorElement: <ErrorPage />
58
+ },
59
+
60
+ {
61
+ path: "/admin",
62
+ element: <AdminSummaryPage />,
63
+ errorElement: <ErrorPage />
64
+ },
65
+ {
66
+ path: "/admin-summary",
67
+ element: <AdminSummaryPage />,
68
+ errorElement: <ErrorPage />
69
+ },
70
+ {
71
+ path: "/admin-feed",
72
+ element: <AdminFeedPage />,
73
+ errorElement: <ErrorPage />
74
+ },
75
+ {
76
+ path: "/admin-schedule",
77
+ element: <AdminSchedulePage />,
78
+ errorElement: <ErrorPage />
79
+ },
80
+ {
81
+ path: "/admin-menu",
82
+ element: <AdminMenuPage />,
83
+ errorElement: <ErrorPage />
84
+ },
85
+ {
86
+ path: "/admin-staff",
87
+ element: <AdminStaffPage />,
88
+ errorElement: <ErrorPage />
89
+ },
90
+ {
91
+ path: "/admin-orders",
92
+ element: <AdminOrderPage />,
93
+ errorElement: <ErrorPage />
94
+ }
95
  ]);
96
 
97
  const root = ReactDOM.createRoot(document.getElementById('root'));
98
  root.render(
99
+ <React.StrictMode>
100
+ <RouterProvider router={router} />
101
+ </React.StrictMode>
102
  );
103
 
104
  // If you want to start measuring performance in your app, pass a function
frontend/src/molecules/AboutUsSection.js CHANGED
@@ -1,21 +1,46 @@
1
  import { Container, Row, Col } from "react-bootstrap";
2
 
3
- export default function AboutUsSection () {
4
  return (<>
5
- <Container id="about-us" className="my-5">
6
- <h1 className="my-4 text-cen">CATS Shop
7
- <small> - We code for fun </small>
8
- </h1>
 
 
 
 
 
 
 
 
 
9
 
10
- <Row className="align-items-center">
11
- <Col md={8}>
12
- <img className="img-fluid" src="/cats-logo.png" alt="" style={{width: "100%", height: "auto"}}></img>
13
- </Col>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
 
15
- <Col md={4} className="d-flex justify-content-center align-items-center">
16
- Chào mừng mọi người đến với Cats Shop, phương châm của chúng tôi là code at the sink and sleep at the sea.
17
- </Col>
18
- </Row>
19
- </Container>
20
  </>)
21
  }
 
1
  import { Container, Row, Col } from "react-bootstrap";
2
 
3
+ export default function AboutUsSection() {
4
  return (<>
5
+ <Container id="about-us" className="mb-5" style={{
6
+ maxWidth: "100%",
7
+ backgroundImage: "linear-gradient(rgba(0, 0, 0, 0.3), rgba(0, 0, 0, 0.3)), url('/about-us.jpg')", // Thay đường dẫn ảnh nền
8
+ backgroundSize: 'cover',
9
+ backgroundPosition: 'center',
10
+ backgroundAttachment: 'fixed',
11
+ width: '100%',
12
+ padding: '50px 0',
13
+ }}>
14
+ <div className="d-flex justify-content-center align-items-center" style={{
15
+ maxWidth: "90%",
16
+ minHeight: "50vh"
17
+ }} >
18
 
19
+ <Row className="align-items-center">
20
+ {/* <Col md={6}>
21
+ <img className="img-fluid" src="/cats-logo.png" alt="" style={{ width: "100%", height: "auto" }}></img>
22
+ </Col> */}
23
+ <Col md={3}></Col>
24
+ <Col md={6} className="align-items-center">
25
+ <h1 style={{
26
+ fontWeight: 'bold',
27
+ // fontFamily: 'Arial, sans-serif', /* Chọn font chữ */
28
+ 'fontSize': '72px', /* Kích thước chữ cho h1 */
29
+ }}
30
+ className='mb-3'>CATS Shop
31
+ </h1>
32
+ <br />
33
+ <p style={{
34
+ // fontFamily: 'Arial, sans-serif', /* Chọn font chữ */
35
+ 'fontSize': '36px', /* Kích thước chữ cho h1 */
36
+ }}>
37
+ Chào mừng mọi người đến với Cats Shop, phương châm của chúng tôi là code at the sink and sleep at the sea.
38
+ </p>
39
+ </Col>
40
+ <Col md={3}></Col>
41
+ </Row>
42
+ </div>
43
 
44
+ </Container>
 
 
 
 
45
  </>)
46
  }
frontend/src/molecules/AdminNavBar.js CHANGED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import {Container, Nav, Navbar, Button, Stack} from 'react-bootstrap'
2
+ import { useNavigate } from 'react-router-dom';
3
+ import DataStorage from '../organisms/DataStorage';
4
+
5
+ export default function AdminNavbar() {
6
+
7
+ const navigate = useNavigate();
8
+
9
+ function handleLogout() {
10
+ DataStorage.set('isLoggedInAdmin','false');
11
+ DataStorage.remove('accessTokenAdmin');
12
+ DataStorage.remove('roleAdmin');
13
+ DataStorage.remove('usernameAdmin');
14
+ DataStorage.remove('expiryDateAdmin');
15
+ navigate('/');
16
+ }
17
+
18
+ let username = DataStorage.get('usernameAdmin');
19
+ let isLoggedIn = DataStorage.get('isLoggedInAdmin');
20
+
21
+ let userContent;
22
+ if (isLoggedIn === 'true') {
23
+ userContent = <>
24
+ <Stack direction='horizontal' gap={2}>
25
+ <Button href="/userinfo" variant='primary'>
26
+ Xin chào, ADMIN {username}
27
+ </Button>
28
+ <Button onClick={handleLogout} variant='outline-primary'>
29
+ Đăng xuất
30
+ </Button>
31
+ </Stack>
32
+ </>
33
+ } else {
34
+ userContent = <></>
35
+ }
36
+ return (
37
+ <Navbar id="home" expand="lg" className="bg-body-tertiary" sticky='top' >
38
+ <Container>
39
+ <Navbar.Brand href="/admin">
40
+ <img
41
+ alt=""
42
+ src="/cats-logo.png"
43
+ width="30"
44
+ height="30"
45
+ className="d-inline-block align-top"
46
+ />{' '}
47
+ CATS-Shop
48
+ </Navbar.Brand>
49
+ <Navbar.Toggle aria-controls="basic-navbar-nav" />
50
+ <Navbar.Collapse id="basic-navbar-nav">
51
+ <Nav className="me-auto text-center">
52
+ {/* These are the navigators */}
53
+ <Nav.Link href="/admin-summary">Dashboard</Nav.Link>
54
+ <Nav.Link href="/admin-feed">Quản lý bài đăng</Nav.Link>
55
+ <Nav.Link href="/admin-menu">Quản lý thực đơn</Nav.Link>
56
+ <Nav.Link href="/admin-staff">Quản lý nhân viên</Nav.Link>
57
+ <Nav.Link href="/admin-schedule">Lịch làm việc</Nav.Link>
58
+ <Nav.Link href="/admin-orders">Danh sách đơn hàng</Nav.Link>
59
+ </Nav>
60
+ {userContent}
61
+ </Navbar.Collapse>
62
+ </Container>
63
+ </Navbar>
64
+ )
65
+ }
frontend/src/molecules/ContactSection.js CHANGED
@@ -2,10 +2,11 @@ import { Container, Row, Col } from "react-bootstrap";
2
 
3
  export default function ContactSection() {
4
  return (
5
- <Container id="contact" className="my-5 align-items-center">
6
  <h1 className="text-center mb-5">Thông tin liên hệ</h1>
7
- <Row md={3}>
8
  {/* Cột 1: Số điện thoại liên hệ */}
 
9
  <Col>
10
  <h5>Liên hệ</h5>
11
  <p>Số điện thoại: 0123-456-789</p>
@@ -26,6 +27,7 @@ export default function ContactSection() {
26
  </a>
27
  </p>
28
  </Col>
 
29
  </Row>
30
  </Container>
31
  );
 
2
 
3
  export default function ContactSection() {
4
  return (
5
+ <Container fluid id="contact" className="my-5 align-items-center">
6
  <h1 className="text-center mb-5">Thông tin liên hệ</h1>
7
+ <Row>
8
  {/* Cột 1: Số điện thoại liên hệ */}
9
+ <Col md={2}></Col>
10
  <Col>
11
  <h5>Liên hệ</h5>
12
  <p>Số điện thoại: 0123-456-789</p>
 
27
  </a>
28
  </p>
29
  </Col>
30
+ <Col md={1}></Col>
31
  </Row>
32
  </Container>
33
  );
frontend/src/molecules/Navbar.js CHANGED
@@ -49,8 +49,8 @@ export default function ANavbar() {
49
  }
50
 
51
  return (
52
- <Navbar id="home" expand="lg" className="bg-body-tertiary" sticky='top' >
53
- <Container>
54
  <Navbar.Brand href="/">
55
  <img
56
  alt=""
 
49
  }
50
 
51
  return (
52
+ <Navbar id="home" expand="lg" className="bg-body-tertiary" sticky='top' style={{'min-height':'6vh'}}>
53
+ <Container fluid style={{maxWidth:"90%"}}>
54
  <Navbar.Brand href="/">
55
  <img
56
  alt=""
frontend/src/organisms/MenuSection.js CHANGED
@@ -18,7 +18,7 @@ function MenuSection() {
18
  const countCarouselSlides = 4;
19
 
20
  return (
21
- <Container id="menu" className="text-center justify-content-center align-items-center my-5">
22
  <h1 className='mb-5'>Menu</h1>
23
  <Carousel activeIndex={index} onSelect={handleSelect} data-bs-theme="dark">
24
  {Array.from({ length: countCarouselSlides }).map((_, slideIndex) => (
 
18
  const countCarouselSlides = 4;
19
 
20
  return (
21
+ <Container fluid id="menu" className="text-center justify-content-center align-items-center my-5" style={{maxWidth:"90%"}}>
22
  <h1 className='mb-5'>Menu</h1>
23
  <Carousel activeIndex={index} onSelect={handleSelect} data-bs-theme="dark">
24
  {Array.from({ length: countCarouselSlides }).map((_, slideIndex) => (
frontend/src/organisms/NewsSection.js CHANGED
@@ -10,7 +10,7 @@ function NewsSection() {
10
  ];
11
 
12
  return (
13
- <Container id="news" className="text-center justify-content-center align-items-center my-5">
14
  <h1 className='mb-5'>Tin tức</h1>
15
  <Row xs={1} md={2} xl={3} className="g-4">
16
  {Array.from(newsFeeds).map((feed, idx) => (
 
10
  ];
11
 
12
  return (
13
+ <Container fluid id="news" className="text-center justify-content-center align-items-center my-5" style={{maxWidth:"90%"}}>
14
  <h1 className='mb-5'>Tin tức</h1>
15
  <Row xs={1} md={2} xl={3} className="g-4">
16
  {Array.from(newsFeeds).map((feed, idx) => (
frontend/src/organisms/StoreSection.js CHANGED
@@ -10,7 +10,7 @@ function StoreSection() {
10
  ];
11
 
12
  return (
13
- <Container id="store" className="text-center justify-content-center align-items-center my-5">
14
  <h1 className='mb-5'>Các chi nhánh</h1>
15
  <Row className="align-items-center">
16
  <Col xs={12} md={4} className="d-flex justify-content-center align-items-center">
@@ -18,7 +18,7 @@ function StoreSection() {
18
  </Col>
19
 
20
  <Col xs={12} md={8}>
21
- <Container>
22
  <Row xs={1} md={2} xl={3} className="g-4">
23
  {Array.from(stores).map((store, idx) => (
24
  <Col key={idx}>
 
10
  ];
11
 
12
  return (
13
+ <Container fluid id="store" className="text-center justify-content-center align-items-center my-5" style={{maxWidth:"90%"}}>
14
  <h1 className='mb-5'>Các chi nhánh</h1>
15
  <Row className="align-items-center">
16
  <Col xs={12} md={4} className="d-flex justify-content-center align-items-center">
 
18
  </Col>
19
 
20
  <Col xs={12} md={8}>
21
+ <Container fluid>
22
  <Row xs={1} md={2} xl={3} className="g-4">
23
  {Array.from(stores).map((store, idx) => (
24
  <Col key={idx}>
frontend/src/pages/AdminFeedPage.js ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { Container, Row, Col } from "react-bootstrap";
2
+ import AdminTemplate from "../templates/AdminTemplate";
3
+
4
+ export default function AdminFeedPage() {
5
+ return (
6
+ <AdminTemplate content={
7
+ (
8
+ <Container className='d-flex text-center align-items-center justify-content-center' style={{ 'min-height': '80vh' }}>
9
+ <Row>
10
+ <Col xs={12}>
11
+ <h1>This is a demo feed page</h1>
12
+ </Col>
13
+ <Col xs={12}>
14
+ <h3>In the future, we hope to view list of feed, add, edit or remove feeds.</h3>
15
+ </Col>
16
+ </Row>
17
+ </Container>
18
+ )
19
+ } />
20
+ );
21
+ }
frontend/src/pages/{AdminHomePage.js → AdminLoginPage.js} RENAMED
File without changes
frontend/src/pages/AdminMenuPage.js ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { Container, Row, Col } from "react-bootstrap";
2
+ import AdminTemplate from "../templates/AdminTemplate";
3
+
4
+ export default function AdminMenuPage() {
5
+ return (
6
+ <AdminTemplate content={
7
+ (
8
+ <Container className='d-flex text-center align-items-center justify-content-center' style={{ 'min-height': '80vh' }}>
9
+ <Row>
10
+ <Col xs={12}>
11
+ <h1>This is a demo menu page</h1>
12
+ </Col>
13
+ <Col xs={12}>
14
+ <h3>In the future, the menu should be retrieve from master-list, and branch admins can decide which item is available at this branch</h3>
15
+ </Col>
16
+ </Row>
17
+ </Container>
18
+ )
19
+ } />
20
+ );
21
+ }
frontend/src/pages/AdminOrderPage.js ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { Container, Row, Col } from "react-bootstrap";
2
+ import AdminTemplate from "../templates/AdminTemplate";
3
+
4
+ export default function AdminOrderPage() {
5
+ return (
6
+ <AdminTemplate content={
7
+ (
8
+ <Container className='d-flex text-center align-items-center justify-content-center' style={{ 'min-height': '80vh' }}>
9
+ <Row>
10
+ <Col xs={12}>
11
+ <h1>This is a demo orders page</h1>
12
+ </Col>
13
+ <Col xs={12}>
14
+ <h3>In the future, we hope to view orders daily/monthly on this page, with search and filters</h3>
15
+ </Col>
16
+ </Row>
17
+ </Container>
18
+ )
19
+ } />
20
+ );
21
+ }
frontend/src/pages/AdminSchedulePage.js ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { Container, Row, Col } from "react-bootstrap";
2
+ import AdminTemplate from "../templates/AdminTemplate";
3
+
4
+ export default function AdminSchedulePage() {
5
+ return (
6
+ <AdminTemplate content={
7
+ (
8
+ <Container className='d-flex text-center align-items-center justify-content-center' style={{ 'min-height': '80vh' }}>
9
+ <Row>
10
+ <Col xs={12}>
11
+ <h1>This is a demo schedule page</h1>
12
+ </Col>
13
+ <Col xs={12}>
14
+ <h3>In the future, we will view monthly work schedules from this page</h3>
15
+ </Col>
16
+ </Row>
17
+ </Container>
18
+ )
19
+ } />
20
+ );
21
+ }
frontend/src/pages/AdminStaffPage.js ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { Container, Row, Col } from "react-bootstrap";
2
+ import AdminTemplate from "../templates/AdminTemplate";
3
+
4
+ export default function AdminStaffPage() {
5
+ return (
6
+ <AdminTemplate content={
7
+ (
8
+ <Container className='d-flex text-center align-items-center justify-content-center' style={{ 'min-height': '80vh' }}>
9
+ <Row>
10
+ <Col xs={12}>
11
+ <h1>This is a demo staff page</h1>
12
+ </Col>
13
+ <Col xs={12}>
14
+ <h3>In the future, we are about to view staffs info, add, edit, and remove staffs in this page</h3>
15
+ </Col>
16
+ </Row>
17
+ </Container>
18
+ )
19
+ } />
20
+ );
21
+ }
frontend/src/pages/AdminSummaryPage.js ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { Container, Row, Col } from "react-bootstrap";
2
+ import AdminTemplate from "../templates/AdminTemplate";
3
+
4
+ export default function AdminSummaryPage() {
5
+ return (
6
+ <AdminTemplate content={
7
+ (
8
+ <Container className='d-flex text-center align-items-center justify-content-center' style={{ 'min-height': '80vh' }}>
9
+ <Row>
10
+ <Col xs={12}>
11
+ <h1>This is a demo summary page</h1>
12
+ </Col>
13
+ <Col xs={12}>
14
+ <h3>In the future, we hope to connect to PowerBI API and show the dashboard</h3>
15
+ </Col>
16
+ </Row>
17
+ </Container>
18
+ )
19
+ } />
20
+ );
21
+ }
frontend/src/pages/LoginPage.js CHANGED
@@ -51,11 +51,12 @@ export default function LoginPage() {
51
  }
52
  })
53
  .catch((error) => {
54
- if (error.status === 400) {
55
- setError('Lỗi đăng nhập, vui lòng kiểm tra lại tài khoản và mật khẩu');
56
- } else if (error.status === 500) {
57
- setError('Server đang tạm gặp vấn đề');
58
- }
 
59
  })
60
 
61
  }
@@ -76,10 +77,10 @@ export default function LoginPage() {
76
  {error && <Alert variant="danger">{error}</Alert>}
77
 
78
  <Form.Group controlId="username" className='mb-3'>
79
- <Form.Label>Tên đăng nhập</Form.Label>
80
  <Form.Control
81
  type="text"
82
- placeholder="Tên đăng nhập"
83
  onChange={(e) => setUsername(e.target.value)}
84
  />
85
  </Form.Group>
 
51
  }
52
  })
53
  .catch((error) => {
54
+ // if (error.status === 400) {
55
+ // setError('Lỗi đăng nhập, vui lòng kiểm tra lại tài khoản và mật khẩu');
56
+ // } else if (error.status === 500) {
57
+ // setError('Server đang tạm gặp vấn đề');
58
+ // }
59
+ setError(JSON.stringify(error));
60
  })
61
 
62
  }
 
77
  {error && <Alert variant="danger">{error}</Alert>}
78
 
79
  <Form.Group controlId="username" className='mb-3'>
80
+ <Form.Label>Email/Số điện thoại</Form.Label>
81
  <Form.Control
82
  type="text"
83
+ placeholder="Email/số điện thoại"
84
  onChange={(e) => setUsername(e.target.value)}
85
  />
86
  </Form.Group>
frontend/src/pages/RegisterPage.js CHANGED
@@ -3,6 +3,9 @@ import validator from 'validator';
3
  import { useNavigate } from 'react-router-dom';
4
  import { Container, Form, Button, Alert, Row, Col, Card } from 'react-bootstrap';
5
  import BasicTemplate from '../templates/BasicTemplate';
 
 
 
6
 
7
  const RegisterPage = () => {
8
  const [full_name, setFullname] = useState('');
@@ -14,13 +17,15 @@ const RegisterPage = () => {
14
 
15
  const navigator = useNavigate();
16
 
 
 
17
  const handleSubmit = (e) => {
18
  e.preventDefault();
19
  // Validate password and confirm password match
20
  if (full_name.length === 0) {
21
  setError('Họ và tên không thể để trống');
22
  } else if (!validator.isMobilePhone(phone_number, 'vi-VN')) {
23
- setError('Số điện thoại không hợp lệ');
24
  } else if (!validator.isEmail(email)) {
25
  setError('Email không hợp lệ');
26
  } else if (password.length < 8) {
@@ -30,7 +35,40 @@ const RegisterPage = () => {
30
  } else {
31
  setError('');
32
  // gọi API đăng ký ở đây
33
- console.log('Đăng thành công:', {full_name, password });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
  navigator('/');
35
  }
36
  };
@@ -57,7 +95,7 @@ const RegisterPage = () => {
57
  type="text"
58
  placeholder="Họ và tên"
59
  onChange={(e) => setFullname(e.target.value)}
60
-
61
  />
62
  </Form.Group>
63
 
@@ -68,7 +106,7 @@ const RegisterPage = () => {
68
  type="text"
69
  placeholder="Số điện thoại"
70
  onChange={(e) => setPhoneNumber(e.target.value)}
71
-
72
  />
73
  </Form.Group>
74
 
@@ -79,7 +117,7 @@ const RegisterPage = () => {
79
  type="text"
80
  placeholder="Email"
81
  onChange={(e) => setEmail(e.target.value)}
82
-
83
  />
84
  </Form.Group>
85
 
@@ -90,7 +128,7 @@ const RegisterPage = () => {
90
  type="password"
91
  placeholder="Nhập mật khẩu"
92
  onChange={(e) => setPassword(e.target.value)}
93
-
94
  />
95
  </Form.Group>
96
 
@@ -100,7 +138,7 @@ const RegisterPage = () => {
100
  type="password"
101
  placeholder="Xác nhận mật khẩu"
102
  onChange={(e) => setConfirmPassword(e.target.value)}
103
-
104
  />
105
  </Form.Group>
106
  <div className='d-flex justify-content-between align-items-center'>
 
3
  import { useNavigate } from 'react-router-dom';
4
  import { Container, Form, Button, Alert, Row, Col, Card } from 'react-bootstrap';
5
  import BasicTemplate from '../templates/BasicTemplate';
6
+ import axios from 'axios';
7
+ import DataStorage from '../organisms/DataStorage';
8
+ import jwtDecoder from '../organisms/jwtDecoder';
9
 
10
  const RegisterPage = () => {
11
  const [full_name, setFullname] = useState('');
 
17
 
18
  const navigator = useNavigate();
19
 
20
+ const domain = process.env.REACT_APP_API_URL;
21
+
22
  const handleSubmit = (e) => {
23
  e.preventDefault();
24
  // Validate password and confirm password match
25
  if (full_name.length === 0) {
26
  setError('Họ và tên không thể để trống');
27
  } else if (!validator.isMobilePhone(phone_number, 'vi-VN')) {
28
+ setError('Số điện thoại không hợp lệ');
29
  } else if (!validator.isEmail(email)) {
30
  setError('Email không hợp lệ');
31
  } else if (password.length < 8) {
 
35
  } else {
36
  setError('');
37
  // gọi API đăng ký ở đây
38
+ let data = {
39
+ "email": email,
40
+ "phone_number": phone_number,
41
+ "full_name": full_name,
42
+ "password": password
43
+ }
44
+
45
+ axios.post(domain + '/authentication/signup', data)
46
+ .then((response) => {
47
+ if (response.status === 200 || response.status === 201) {
48
+ const decodedToken = jwtDecoder(response.data.access_token);
49
+ const full_name = decodedToken.payload.username;
50
+ const role = decodedToken.payload.roles;
51
+ const expiryTime = decodedToken.payload.exp;
52
+ DataStorage.set('expiryDate', expiryTime, { expiryDate: expiryTime });
53
+ DataStorage.set('username', full_name);
54
+ DataStorage.set('role', role);
55
+ DataStorage.set('isLoggedIn', 'true');
56
+ DataStorage.set('accessToken', response.data.access_token);
57
+ DataStorage.set('cart', '{}');
58
+ navigator('/');
59
+ } else {
60
+ setError(JSON.stringify(response));
61
+ }
62
+ })
63
+ .catch((error) => {
64
+ if (error.status === 400) {
65
+ setError('Lỗi đăng ký');
66
+ } else if (error.status === 500) {
67
+ setError('Server đang tạm gặp vấn đề');
68
+ }
69
+ })
70
+
71
+ console.log('Đăng ký thành công:', { full_name, password });
72
  navigator('/');
73
  }
74
  };
 
95
  type="text"
96
  placeholder="Họ và tên"
97
  onChange={(e) => setFullname(e.target.value)}
98
+
99
  />
100
  </Form.Group>
101
 
 
106
  type="text"
107
  placeholder="Số điện thoại"
108
  onChange={(e) => setPhoneNumber(e.target.value)}
109
+
110
  />
111
  </Form.Group>
112
 
 
117
  type="text"
118
  placeholder="Email"
119
  onChange={(e) => setEmail(e.target.value)}
120
+
121
  />
122
  </Form.Group>
123
 
 
128
  type="password"
129
  placeholder="Nhập mật khẩu"
130
  onChange={(e) => setPassword(e.target.value)}
131
+
132
  />
133
  </Form.Group>
134
 
 
138
  type="password"
139
  placeholder="Xác nhận mật khẩu"
140
  onChange={(e) => setConfirmPassword(e.target.value)}
141
+
142
  />
143
  </Form.Group>
144
  <div className='d-flex justify-content-between align-items-center'>
frontend/src/styles/styles.css CHANGED
@@ -0,0 +1,170 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Thay đổi màu sắc chính của trang */
2
+ :root {
3
+ --primary-color: #300604;
4
+ /* Màu đỏ ấm, có thể chỉnh sửa */
5
+ --secondary-color: #b17219;
6
+ /* Màu cam nhạt */
7
+ --background-color: #222020;
8
+ /* Màu nền nhẹ nhàng */
9
+ --text-color: #fbf5f5;
10
+ /* Màu chữ chính */
11
+ --container-background-color: rgba(44, 41, 41, 0.5);
12
+ background-color: var(--background-color);
13
+ }
14
+
15
+ /* Đặt nền cho toàn bộ trang */
16
+ body {
17
+ color: var(--text-color);
18
+ /* background-image: url('../../public/header.jpg'); */
19
+ background-color: var(--background-color); /* Màu nền */
20
+ /* Hoặc sử dụng hình ảnh nền */
21
+ background-size: cover; /* Để hình ảnh phủ đầy toàn bộ trang */
22
+ background-repeat: no-repeat; /* Để hình ảnh không lặp lại */
23
+ background-attachment: fixed; /* Để nền cố định khi cuộn trang */
24
+ background-position: center; /* Căn giữa hình ảnh */
25
+ }
26
+
27
+
28
+ /* Container */
29
+ .container {
30
+ padding-top: 20px;
31
+ padding-bottom: 20px;
32
+ background-color: var(--container-background-color);
33
+ }
34
+
35
+ /* Navbar */
36
+ .navbar {
37
+ background-color: var(--primary-color) !important;
38
+ font-size: 1.1rem;
39
+ }
40
+
41
+ .navbar-brand,
42
+ .nav-link {
43
+ color: #fff !important;
44
+ font-weight: bold;
45
+ transition: color 0.3s;
46
+ }
47
+
48
+ .nav-link:hover {
49
+ color: var(--secondary-color) !important;
50
+ }
51
+
52
+ .navbar-toggler {
53
+ border-color: rgba(255, 255, 255, 0.5);
54
+ }
55
+
56
+ .navbar-light .navbar-toggler-icon {
57
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3E%3Cpath stroke='rgba%28255, 255, 255, 0.5%29' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E");
58
+ }
59
+
60
+ /* Button */
61
+ .btn-primary {
62
+ background-color: var(--secondary-color);
63
+ border-color: var(--secondary-color);
64
+ color: #fff;
65
+ font-weight: bold;
66
+ transition: background-color 0.3s, color 0.3s;
67
+ }
68
+
69
+ .btn-primary:hover {
70
+ background-color: #e99e40;
71
+ border-color: #e99e40;
72
+ }
73
+
74
+ /* .btn-outline-primary {
75
+ color: var(--primary-color);
76
+ border-color: var(--primary-color);
77
+ font-weight: bold;
78
+ }
79
+
80
+ .btn-outline-primary:hover {
81
+ background-color: var(--primary-color);
82
+ color: #fff;
83
+ } */
84
+
85
+ /* Style cho nút secondary */
86
+ .btn-outline-primary {
87
+ background-color: var(--text-color);
88
+ /* Màu nền trắng */
89
+ color: var(--primary-color);
90
+ /* Màu chữ đỏ */
91
+ font-weight: bold;
92
+ border-color: var(--secondary-color);
93
+ /* Màu viền đỏ */
94
+ }
95
+
96
+ .btn-outline-primary:hover {
97
+ background-color: #c2bdaf;
98
+ /* Màu nền nhạt hơn khi hover */
99
+ color: var(--primary-color);
100
+ /* Màu chữ đỏ khi hover */
101
+ border-color: var(--secondary-color);
102
+ /* Giữ màu viền đỏ khi hover */
103
+ }
104
+
105
+
106
+
107
+ /* Card */
108
+ .card {
109
+ border: none;
110
+ border-radius: 10px;
111
+ box-shadow: 0px 8px 16px rgba(0, 0, 0, 0.3);
112
+ transition: transform 0.3s;
113
+ }
114
+
115
+ .card:hover {
116
+ transform: scale(1.02);
117
+ }
118
+
119
+ .card-img-top {
120
+ border-top-left-radius: 10px;
121
+ border-top-right-radius: 10px;
122
+ height: 200px;
123
+ /* Tùy chỉnh chiều cao ảnh */
124
+ object-fit: cover;
125
+ }
126
+
127
+ .card-title {
128
+ font-size: 1.25rem;
129
+ font-weight: bold;
130
+ color: var(--primary-color);
131
+ }
132
+
133
+ .card-text {
134
+ color: var(--text-color);
135
+ }
136
+
137
+ .card-footer {
138
+ background-color: #fff;
139
+ border-top: none;
140
+ text-align: center;
141
+ }
142
+
143
+ /* Container cho các phần */
144
+ .menu-section {
145
+ padding: 40px 0;
146
+ background-color: #fff;
147
+ }
148
+
149
+ .header-section {
150
+ padding: 60px 0;
151
+ background-image: url('../../public/header.jpg');
152
+ /* Thêm hình nền nếu có */
153
+ background-size: cover;
154
+ background-position: center;
155
+ /* color: #fff; */
156
+ text-align: center;
157
+ }
158
+
159
+ .header-section h1 {
160
+ font-size: 2.5rem;
161
+ font-weight: bold;
162
+ }
163
+
164
+ .header-section p {
165
+ font-size: 1.2rem;
166
+ margin-top: 10px;
167
+ max-width: 600px;
168
+ margin: auto;
169
+ color: #f1f1f1;
170
+ }
frontend/src/templates/AdminTemplate.js ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // pages/HomePage.js
2
+ // import React, { useState } from 'react';
3
+ import AdminNavbar from '../molecules/AdminNavBar';
4
+ function AdminTemplate ({content}) {
5
+ // const [isLoggedIn, setIsLoggedIn] = useState(false);
6
+ // const [user, setUser] = useState({ name: 'User' });
7
+
8
+ return (
9
+ <>
10
+ <AdminNavbar></AdminNavbar>
11
+ {content}
12
+ </>
13
+ );
14
+ };
15
+
16
+ export default AdminTemplate;