diff --git a/package.json b/package.json
index 22d80c8..a1f0e3f 100644
--- a/package.json
+++ b/package.json
@@ -15,6 +15,7 @@
"react-bootstrap": "1.0.1",
"react-dom": "^17.0.2",
"react-js-pagination": "^3.0.3",
+ "react-router-dom": "^6.2.1",
"react-scripts": "5.0.0",
"react-spinners": "^0.11.0",
"sweetalert": "^2.1.2",
diff --git a/public/assets/images/bg1.jpeg b/public/assets/images/bg1.jpeg
new file mode 100644
index 0000000..98691c1
Binary files /dev/null and b/public/assets/images/bg1.jpeg differ
diff --git a/public/img/bg1.jpeg b/public/img/bg1.jpeg
new file mode 100644
index 0000000..918dd89
Binary files /dev/null and b/public/img/bg1.jpeg differ
diff --git a/src/App.css b/src/App.css
index d761597..bb65a2d 100644
--- a/src/App.css
+++ b/src/App.css
@@ -179,3 +179,100 @@ img.opacity_img_click.active {
.pagination {
float: right;
}
+
+button.close {
+ color: red;
+ border: 1px solid red;
+ display: flex;
+ justify-content: center;
+ width: 35px;
+ height: 30px;
+ background-color: red;
+ color: white;
+}
+
+button.close:hover {
+ color: white
+}
+
+.disable-btn-upload {
+ color: #00000040;
+ border-color: #d9d9d9;
+ background: #f5f5f5;
+ text-shadow: none;
+ box-shadow: none;
+}
+
+.disable-btn-upload:hover, .disable-btn-upload:focus {
+ color: #00000040;
+ border-color: #d9d9d9;
+ background: #f5f5f5;
+ text-shadow: none;
+ box-shadow: none;
+}
+
+.login__page {
+ background: url("/public/assets/images/bg1.jpeg") top left repeat;
+
+ background-color: #eee;
+ width: 100%;
+ background-size: cover;
+ bottom: 0;
+ background-repeat: cover;
+ background-position: center;
+ min-height: 100vh;
+ position: relative;
+ display: flex;
+ justify-content: center;
+ top: 0;
+}
+.login__page .login__form {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 100%;
+ min-height: 100vh;
+ position: relative;
+}
+.login__page .login__form .login-form-button {
+ width: 100%;
+}
+.login__page .login__form .login__text {
+ margin-bottom: 30px;
+ font-weight: 800;
+ font-size: 30px;
+ color: #0695e2;
+ text-align: center;
+}
+.login__page .login__form .login__sec {
+ background: #d3d3d3 de;
+ padding: 50px 50px 30px 50px;
+ border-radius: 10px;
+ width: 400px;
+}
+.login__page .login__form .login__sec h2::after {
+ content: " ";
+ width: 100px;
+ height: 5px;
+ background: #0695e2;
+ display: block;
+ margin-top: 5px;
+ border-radius: 3px;
+ margin-left: auto;
+ margin-right: auto;
+}
+.login__page .login__form .login__sec .login__error {
+ margin-bottom: 20px;
+}
+.login__page .login__form .input__Cus {
+ padding: 10px 15px !important;
+ outline: none !important;
+ border: 1px solid transparent !important;
+ border-radius: 8px !important;
+}
+.login__page .login__form .login-form-button {
+ background-color: #0695e2 !important;
+ border-radius: 10px !important;
+ height: 50px !important;
+ font-weight: bold !important;
+}
diff --git a/src/App.js b/src/App.js
index 47550e7..d56de06 100644
--- a/src/App.js
+++ b/src/App.js
@@ -1,12 +1,21 @@
import React from 'react'
import ListItem from './components/List/ListItem';
+import Login from './components/Login/Login';
import 'antd/dist/antd.css';
import "./App.css";
+import { BrowserRouter as Router, Navigate, Route, Routes } from 'react-router-dom';
+
function App() {
return (
-
+
+
+ } />
+ } />
+ } />
+
+
);
}
diff --git a/src/components/List/ListItem.js b/src/components/List/ListItem.js
index 18169b4..7c378c2 100644
--- a/src/components/List/ListItem.js
+++ b/src/components/List/ListItem.js
@@ -7,7 +7,8 @@ import React, { useEffect, useState } from 'react';
import Pagination from "react-js-pagination";
import { PulseLoader } from 'react-spinners';
import { HOST } from '../../config/index';
-
+import swal from 'sweetalert';
+import { useLocation } from 'react-router-dom';
export default function ListItem() {
@@ -23,6 +24,23 @@ export default function ListItem() {
const [totalItems, setTotalItems] = useState(10)
const itemsPerPage = 5
+ const [token, setToken] = useState('');
+
+ const location = useLocation();
+
+ useEffect(() => {
+ if (location.search) {
+ let path = location.search.replace('?', '').split('&');
+ let obj = {}
+ path.forEach(value => {
+ let arr = value.split('=');
+ obj[arr[0]] = arr[1]
+ })
+ setToken(decodeURIComponent(obj.token))
+ setToken((obj.token))
+ }
+ }, [location])
+
useEffect(() => {
getData(1)
}, [])
@@ -32,6 +50,44 @@ export default function ListItem() {
setShowModal(true)
}
+ const onDelete = async (data) => {
+ let dataPost = {
+ obj_id: data._id,
+ id: data.id,
+ name: data.name,
+ birthday: data.birthday,
+ gender: data.gender,
+ is_deleted : 1
+ }
+ try {
+ const result = await axios({
+ method: 'POST',
+ url: `${HOST}/api/famous_persons/insert_or_update`,
+ headers: {
+ 'Accept': 'application/json',
+ 'Content-Type': 'application/json',
+ // 'Authorization': token,
+ },
+ data: dataPost,
+ })
+ if (result.data.status === 10000) {
+ swal({
+ icon: 'success',
+ title: 'Thành công',
+ text: 'Xoá thành công',
+ buttons: false,
+ })
+ getData(activePage)
+ } else if (result.data.status === 10004) {
+ swal("Thất bại", "Xoá thất bại!", "error");
+ } else {
+ swal("Thất bại", "Xoá thất bại!", "error");
+ }
+ } catch (error) {
+ console.log(error);
+ }
+ }
+
const handlePageChange = (pageNumber) => {
setActivePage(pageNumber)
getData(pageNumber)
@@ -83,8 +139,7 @@ export default function ListItem() {
var listImg
if (value.sample_images.length > 0) {
- listImg =
0 ? value.sample_images[0] : ""} src={`${value.sample_images.length > 0 && value.image_host + value.sample_images[1]}`} />
-
+ listImg =
0 ? value.sample_images[0] : ""} src={`${value.sample_images.length > 0 && value.image_host + value.sample_images[0]}`} />
} else {
listImg = } />
}
@@ -105,6 +160,21 @@ export default function ListItem() {
diff --git a/src/components/Login/Login.js b/src/components/Login/Login.js
new file mode 100644
index 0000000..c18c8ac
--- /dev/null
+++ b/src/components/Login/Login.js
@@ -0,0 +1,128 @@
+import { LockOutlined, UserOutlined } from '@ant-design/icons';
+import { Button, Form, Input, Typography } from 'antd';
+import axios from 'axios';
+// import { dispatchBox, dispatchToken } from 'features/Login/loginSlice';
+import React, { useState } from 'react';
+// import { useDispatch } from 'react-redux';
+// import { useHistory } from "react-router-dom";
+import { HOST } from '../../config/index';
+
+const { Text } = Typography;
+
+const Login = () => {
+
+ const [error, setError] = useState('');
+ const [loading, setLoading] = useState(false);
+
+ // const dispatch = useDispatch();
+
+ // let history = useHistory();
+
+ const onFinish = async (values) => {
+ setLoading(true);
+ const dataReq = {
+ email: values.email,
+ password: values.password,
+ }
+
+ await axios({
+ method: 'POST',
+ url: `${HOST}/api/login`,
+ headers: {},
+ data: dataReq
+ }).then((res) => {
+ if (res.data.status === 10000) {
+ // dispatch(dispatchToken({ token: 'Bearer ' + res.data.access_token }));
+ // dispatch(dispatchBox({ rule: res.data.user_info.rule }))
+ setError('');
+ localStorage.setItem('refresh_token', 'Bearer ' + res.data.refresh_token);
+ localStorage.setItem('access_token', 'Bearer ' + res.data.access_token);
+ localStorage.setItem('rule', res.data.user_info.rule);
+
+ // history.push('/preferential-management')
+ } else {
+ setError('Sai tài khoản hoặc mật khẩu');
+ }
+ })
+ .catch(err => {
+ setError('Vui lòng kiểm tra lại đường truyền mạng')
+ console.error(err);
+ })
+ setLoading(false);
+ };
+
+ const onFinishFailed = (errorInfo) => {
+ console.log('Failed:', errorInfo);
+ };
+
+
+ return (
+
+
+
+
Đăng nhập
+
+ }
+ placeholder="Email" />
+
+
+ }
+ type="password"
+ placeholder="Password"
+ />
+
+
+ {error && * Sai tài khoản mật khẩu }
+
+
+
+
+
+
+
+
+
+
+ );
+}
+
+export default Login;
\ No newline at end of file
diff --git a/src/components/Modal/ModalEdit.js b/src/components/Modal/ModalEdit.js
index 5be2c91..6f329a3 100644
--- a/src/components/Modal/ModalEdit.js
+++ b/src/components/Modal/ModalEdit.js
@@ -1,5 +1,6 @@
import { UploadOutlined, UserOutlined } from '@ant-design/icons';
-import { Avatar, Button as ButtonAntd, DatePicker, Form, Input, Radio } from 'antd';
+import { Avatar, Button as ButtonAntd, DatePicker, Form, Input, Radio, Upload } from 'antd';
+import { useLocation } from 'react-router-dom';
import viVN from 'antd/lib/locale/vi_VN';
import axios from 'axios';
import moment from 'moment';
@@ -26,10 +27,15 @@ const Modaledit = (props) => {
const [crrIdx, setCrrIdx] = useState(0)
const [listChecked, setListChecked] = useState({ url: [] });
+ const [disableBtn, setDisableBtn] = useState(true);
+
+ const [listImgUpload, setListImgUpload] = useState([]);
+
useEffect(() => {
setCrrData(data);
setCrrImages(data.sample_images)
setBirthday(data.birthday !== "" ? moment(data.birthday) : null)
+ setDisableBtn(data._id ? false : true)
return () => {
setCrrData(null);
}
@@ -51,33 +57,6 @@ const Modaledit = (props) => {
}
const click_handle = async () => {
- // axios.all([
- // axios.post(`${HOST}/api/famous_persons/insert_or_update`, {
- // myVar: 'myValue'
- // }),
- // axios.post(`/my-url2`, {
- // myVar: 'myValue'
- // })
- // ])
- // .then(axios.spread((data1, data2) => {
- // // output of req.
- // console.log('data1', data1, 'data2', data2)
- // }));
-
- // Promise.all([
- // fetch('https://api.github.com/users/MaksymRudnyi'),
- // fetch('https://api.github.com/users/taylorotwell')
- // ])
- // .then(async([res1, res2]) => {
- // const a = await res1.json();
- // const b = await res2.json();
- // console.log(a.login + ' has ' + a.public_repos + ' public repos on GitHub');
- // console.log(b.login + ' has ' + b.public_repos + ' public repos on GitHub');
- // })
- // .catch(error => {
- // console.log(error);
- // });
-
let dataPost = {
obj_id: crrData._id ? crrData._id : "",
id: crrData.id,
@@ -96,13 +75,22 @@ const Modaledit = (props) => {
data: dataPost,
})
if (result.data.status === 10000) {
- swal({
- icon: 'success',
- title: 'Thành công',
- text: 'Sửa thông tin thành công',
- buttons: false,
- })
- return onHide();
+ if (crrData._id) {
+ swal({
+ icon: 'success',
+ title: 'Thành công',
+ text: 'Sửa thông tin thành công',
+ buttons: false,
+ })
+ } else {
+ swal({
+ icon: 'success',
+ title: 'Thành công',
+ text: 'Thêm mới thành công',
+ buttons: false,
+ })
+ setDisableBtn(false)
+ }
} else if (result.data.status === 10004) {
swal("Thất bại", "Sửa thông tin thất bại!", "error");
} else {
@@ -111,7 +99,6 @@ const Modaledit = (props) => {
}
-
const bulletedImg = crrImages.map((value, index) => {
let renderImg = value.includes("data:image") ? value : data.image_host + value
return (
@@ -155,6 +142,71 @@ const Modaledit = (props) => {
}
}
+ const handleChange = (event) => {
+
+ }
+
+ const onUpload = async (file) => {
+ console.log(file)
+ const base64 = await convertBase64(file)
+
+ let dataUploadImg = {
+ obj_id: crrData._id ? crrData._id : "",
+ base64_image_list: [base64.split(',')[1]]
+ }
+
+ fetch(`${HOST}/api/face_images/famous_person`, {
+ method: 'POST',
+ headers: {
+ 'Accept': 'application/json',
+ 'Content-Type': 'application/json',
+ // 'Authorization': token
+ },
+ body: JSON.stringify(dataUploadImg)
+ })
+ .then(res => res.json())
+ .then(data => {
+ console.log(data)
+ if (data.status === 10000) {
+ let listImg = [...crrImages]
+ listImg.unshift(data.data.toString())
+ setCrrImages(listImg)
+ setCheckDeleteMulti(false)
+ }
+ })
+ }
+
+ const uploadImage = async (options) => {
+ const { file } = options;
+ const base64 = await convertBase64(file)
+
+ let dataUploadImg = {
+ obj_id: crrData._id ? crrData._id : "",
+ base64_image_list: [base64.split(',')[1]]
+ }
+
+ fetch(`${HOST}/api/face_images/famous_person`, {
+ method: 'POST',
+ headers: {
+ 'Accept': 'application/json',
+ 'Content-Type': 'application/json',
+ // 'Authorization': token
+ },
+ body: JSON.stringify(dataUploadImg)
+ })
+ .then(res => res.json())
+ .then(data => {
+ if (data.status === 10000) {
+ let listImg = [...crrImages]
+ listImg.unshift(data.data.toString())
+ setCrrImages(listImg)
+ setCheckDeleteMulti(false)
+ }
+ })
+ };
+
+
+
const convertBase64 = (file) => {
return new Promise((resolve, reject) => {
const fileReader = new FileReader();
@@ -170,10 +222,26 @@ const Modaledit = (props) => {
const deleteFaceMulti = () => {
- let arrImgDel = listChecked.url
- let listDetele = crrImages.filter(item => !arrImgDel.includes(item));
- setCrrImages(listDetele)
- setCheckDeleteMulti(false)
+ let listDelImg = listChecked.url
+ fetch(`${HOST}/api/face_images/ignore_face`, {
+ method: 'POST',
+ headers: {
+ 'Accept': 'application/json',
+ 'Content-Type': 'application/json',
+ // 'Authorization': token
+ },
+ body: JSON.stringify({
+ person_obj_id: crrData._id ? crrData._id : "",
+ images: listDelImg
+ })
+ })
+ .then(res => res.json())
+ .then(data => {
+ if (data.status === 10000) {
+ let listDetele = crrImages.filter(item => !listDelImg.includes(item));
+ setCrrImages(listDetele)
+ }
+ })
}
const UserHandle = (e) => {
@@ -268,20 +336,18 @@ const Modaledit = (props) => {
}
- onChangeFile(e)}
- type="file"
- accept="image/*"
- style={{ display: "none" }}
- // multiple={false}
- />
- onClickUpload()} icon={}>Tải ảnh lên
-
+
+ }>Tải ảnh lên
+
-
+
+
+
+
}
-
+ {/*
-
+ */}
);
}
diff --git a/yarn.lock b/yarn.lock
index a7c9d43..2fa8564 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1049,7 +1049,7 @@
core-js-pure "^3.19.0"
regenerator-runtime "^0.13.4"
-"@babel/runtime@^7.10.1", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.4", "@babel/runtime@^7.11.1", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.16.3", "@babel/runtime@^7.4.2", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.3", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2":
+"@babel/runtime@^7.10.1", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.4", "@babel/runtime@^7.11.1", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.16.3", "@babel/runtime@^7.4.2", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2":
version "7.16.7"
resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.16.7.tgz"
integrity sha512-9E9FJowqAsytyOY6LG+1KuueckRL+aQW+mKvXRXnuFGyRAyepJPmEo9vgMfXUA6O9u3IeEdv9MAkppFcaQwogQ==
@@ -4998,6 +4998,13 @@ he@^1.2.0:
resolved "https://registry.npmjs.org/he/-/he-1.2.0.tgz"
integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==
+history@^5.2.0:
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/history/-/history-5.2.0.tgz#7cdd31cf9bac3c5d31f09c231c9928fad0007b7c"
+ integrity sha512-uPSF6lAJb3nSePJ43hN3eKj1dTWpN9gMod0ZssbFTIsen+WehTmEadgL+kg78xLJFdRfrrC//SavDzmRVdE+Ig==
+ dependencies:
+ "@babel/runtime" "^7.7.6"
+
hoist-non-react-statics@^3.3.1:
version "3.3.2"
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45"
@@ -8326,6 +8333,21 @@ react-refresh@^0.11.0:
resolved "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz"
integrity sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A==
+react-router-dom@^6.2.1:
+ version "6.2.1"
+ resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-6.2.1.tgz#32ec81829152fbb8a7b045bf593a22eadf019bec"
+ integrity sha512-I6Zax+/TH/cZMDpj3/4Fl2eaNdcvoxxHoH1tYOREsQ22OKDYofGebrNm6CTPUcvLvZm63NL/vzCYdjf9CUhqmA==
+ dependencies:
+ history "^5.2.0"
+ react-router "6.2.1"
+
+react-router@6.2.1:
+ version "6.2.1"
+ resolved "https://registry.yarnpkg.com/react-router/-/react-router-6.2.1.tgz#be2a97a6006ce1d9123c28934e604faef51448a3"
+ integrity sha512-2fG0udBtxou9lXtK97eJeET2ki5//UWfQSl1rlJ7quwe6jrktK9FCCc8dQb5QY6jAv3jua8bBQRhhDOM/kVRsg==
+ dependencies:
+ history "^5.2.0"
+
react-scripts@5.0.0:
version "5.0.0"
resolved "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.0.tgz"