uơdate code 2

This commit is contained in:
huyt 2022-01-08 19:36:39 +07:00
parent 305911da99
commit e8bc7e463a
9 changed files with 457 additions and 58 deletions

View File

@ -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",

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

BIN
public/img/bg1.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 KiB

View File

@ -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;
}

View File

@ -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 (
<div className="Container">
<ListItem />
<Router>
<Routes>
<Route path="/" element={<Navigate replace to="/list-famous" />} />
<Route path='/login' element={<Login />} />
<Route path="/list-famous" element={<ListItem />} />
</Routes>
</Router>
</div>
);
}

View File

@ -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 = <img key={index} style={{ width: "80px", height: "80px" }} alt={value.sample_images.length > 0 ? value.sample_images[0] : ""} src={`${value.sample_images.length > 0 && value.image_host + value.sample_images[1]}`} />
listImg = <img key={index} style={{ width: "80px", height: "80px" }} alt={value.sample_images.length > 0 ? value.sample_images[0] : ""} src={`${value.sample_images.length > 0 && value.image_host + value.sample_images[0]}`} />
} else {
listImg = <Avatar shape="square" size={80} icon={<UserOutlined />} />
}
@ -105,6 +160,21 @@ export default function ListItem() {
</Tooltip>
<Tooltip placement="top" title={"Xoá"}>
<button
onClick={f => {
f.preventDefault();
swal({
// title: "Are you sure?",
text: "Bạn có chắc muốn xoá " + value.name,
icon: "warning",
buttons: true,
dangerMode: true,
})
.then(willDelete => {
if (willDelete) {
onDelete(value);
}
});
}}
className="m-portlet__nav-link btn m-btn m-btn--hover-danger m-btn--icon m-btn--icon-only m-btn--pill" data-tip data-for="Edit" >
<i className="la la-trash" />
</button>

View File

@ -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 (
<div className="login__page">
<div className="login__form">
<div className="login__sec">
<h2 className="login__text">Đăng nhập</h2>
<Form
layout="vertical"
name="normal_login"
className="login-form"
initialValues={{
remember: true,
}}
onFinish={onFinish}
onFinishFailed={onFinishFailed}
>
<Form.Item
name="email"
label="Email"
rules={[
{
required: true,
message: '',
},
]}
>
<Input
className="input__Cus"
prefix={<UserOutlined className="site-form-item-icon" />}
placeholder="Email" />
</Form.Item>
<Form.Item
name="password"
label="Mật khẩu"
rules={[
{
required: true,
message: '',
},
]}
>
<Input.Password
className="input__Cus"
prefix={<LockOutlined className="site-form-item-icon" />}
type="password"
placeholder="Password"
/>
</Form.Item>
<div className="login__error">
{error && <Text strong="true" className="hide__error" type="danger">* Sai tài khoản mật khẩu </Text>}
</div>
<Form.Item>
<Button
type="primary"
htmlType="submit"
loading={loading}
className="login-form-button"
>
Đăng nhập
</Button>
</Form.Item>
</Form>
</div>
</div>
</div>
);
}
export default Login;

View File

@ -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) => {
}
</div>
<input
ref={fileInput}
onChange={e => onChangeFile(e)}
type="file"
accept="image/*"
style={{ display: "none" }}
// multiple={false}
/>
<ButtonAntd onClick={() => onClickUpload()} icon={<UploadOutlined />}>Tải ảnh lên</ButtonAntd>
<Upload
customRequest = {uploadImage}
accept="image/*"
showUploadList={false}
disabled={disableBtn}
>
<ButtonAntd className={`${disableBtn ? "disable-btn-upload" : ""}`} icon={<UploadOutlined />}>Tải ảnh lên</ButtonAntd>
</Upload>
</div>
</div>
<div className="col-md-5">
<div className="col-md-5 d-flex flex-column justify-content-between">
<Form
id="formEdit"
form={form}
@ -322,19 +388,25 @@ const Modaledit = (props) => {
</Form.Item>
</Form>
<div className="row d-flex justify-content-end mr-1">
<Button variant="accent" className={"m-loader--light m-loader--right "}
// disabled={loading}
onClick={() => form.submit()}
>Lưu</Button>
</div>
</div>
</div>
</div>
</div>
</Modal.Body>
}
<Modal.Footer>
{/* <Modal.Footer>
<Button variant="accent" className={"m-loader--light m-loader--right "}
// disabled={loading}
onClick={() => form.submit()}
>Lưu</Button>
<Button variant="secondary" onClick={onHide}>Đóng</Button>
</Modal.Footer>
</Modal.Footer> */}
</Modal>
);
}

View File

@ -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"