437 lines
20 KiB
JavaScript
437 lines
20 KiB
JavaScript
import { UploadOutlined, UserOutlined } from '@ant-design/icons';
|
|
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';
|
|
import 'moment/locale/vi';
|
|
import React, { useEffect, useRef, useState } from 'react';
|
|
import { Button, Modal } from 'react-bootstrap';
|
|
import swal from 'sweetalert';
|
|
import { HOST } from '../../config/index';
|
|
|
|
|
|
|
|
const ModalEditLabel = (props) => {
|
|
const { show, onHide, data } = props;
|
|
const [crrImages, setCrrImages] = useState([]);
|
|
|
|
const [form] = Form.useForm()
|
|
|
|
|
|
const [birthday, setBirthday] = useState(moment())
|
|
const [crrData, setCrrData] = useState(null);
|
|
|
|
const [checkDeleteMulti, setCheckDeleteMulti] = useState(false);
|
|
const [crrIdx, setCrrIdx] = useState(0)
|
|
const [listChecked, setListChecked] = useState({ url: [] });
|
|
|
|
const [disableBtn, setDisableBtn] = useState(true);
|
|
|
|
const [dateImage, setDateImg] = useState("")
|
|
|
|
const [dataUpload, setDataUpload] = useState([])
|
|
|
|
const [hostImg, setHostImg] = useState('');
|
|
|
|
useEffect(() => {
|
|
setCrrData(data);
|
|
setCrrImages(data.sample_images)
|
|
setBirthday(data.birthday !== "" ? moment(data.birthday) : null)
|
|
setDisableBtn(data._id ? false : true)
|
|
setHostImg(data.image_host)
|
|
return () => {
|
|
setCrrData(null);
|
|
}
|
|
}, [data]);
|
|
|
|
|
|
const handleCheckedImg = (event, value) => {
|
|
let newListChecked = { ...listChecked }
|
|
if (newListChecked.url.indexOf(event.target.value) === -1) {
|
|
newListChecked.url.push(event.target.value)
|
|
} else {
|
|
var i = newListChecked.url.indexOf(event.target.value);
|
|
if (i !== -1) {
|
|
newListChecked.url.splice(i, 1);
|
|
}
|
|
}
|
|
setListChecked(newListChecked)
|
|
|
|
}
|
|
|
|
useEffect(() => {
|
|
if (crrImages.length > 0) {
|
|
let crrDateImg = crrImages[crrIdx]
|
|
let getDateImg = crrDateImg !== "" && crrDateImg.split("_")
|
|
let dataImg = getDateImg.length > 0 && getDateImg[1].slice(0,6)
|
|
setDateImg(dataImg)
|
|
}
|
|
},[crrImages,crrIdx])
|
|
|
|
const click_handle = async () => {
|
|
let dataPost = {
|
|
obj_id: crrData._id ? crrData._id : "",
|
|
name: crrData.name,
|
|
birthday: crrData.birthday,
|
|
gender: crrData.gender ? crrData.gender : "",
|
|
id: crrData.id ? crrData.id : "",
|
|
person_type: 4
|
|
}
|
|
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) {
|
|
if (crrData._id) {
|
|
swal({
|
|
icon: 'success',
|
|
title: 'Thành công',
|
|
text: 'Sửa thông tin thành công',
|
|
timer: 1500,
|
|
buttons: false,
|
|
})
|
|
} else {
|
|
swal({
|
|
icon: 'success',
|
|
title: 'Thành công',
|
|
text: 'Thêm mới thành công',
|
|
timer: 1500,
|
|
buttons: false,
|
|
})
|
|
setCrrData({...crrData, _id: result.data.data})
|
|
setDisableBtn(false)
|
|
}
|
|
} else if (result.data.status === 10002) {
|
|
swal("Thất bại", "Lỗi hệ thống!", "error");
|
|
} else {
|
|
swal("Thất bại", "Sửa thông tin thất bại!", "error");
|
|
}
|
|
}
|
|
|
|
|
|
const bulletedImg = crrImages.map((value, index) => {
|
|
let getDateImg = value.split("_")
|
|
let dataImg = getDateImg.length > 0 && getDateImg[1].slice(0,6)
|
|
|
|
let renderImg = value.includes("data:image") ? value : hostImg +dataImg+ "/" + value
|
|
return (
|
|
<div className="img-res col-md-4 pl-0 mb-3" key={index + 1}>
|
|
<div style={{ 'height': 80 }}>
|
|
{
|
|
checkDeleteMulti === false ?
|
|
<img style={{objectFit: "contain"}} alt="" src={renderImg} onClick={() => { setCrrIdx(index) }} className={"opacity_img_click img_check " + (crrIdx === index ? 'active' : '')} />
|
|
:
|
|
<label className="m-checkbox img-checkbox m-checkbox-day pl-0 mb-0" style={{ 'width': '100%' }}>
|
|
<input type="checkbox"
|
|
defaultValue={value}
|
|
name="img_checked"
|
|
checked={listChecked.url.indexOf(value) === -1 ? false : true}
|
|
onClick={e => {
|
|
handleCheckedImg(e, value)
|
|
}} readOnly />
|
|
<img style={{objectFit: "contain"}} alt="" src={renderImg} className="opacity_img img_check" />
|
|
<span />
|
|
</label>
|
|
}
|
|
</div>
|
|
</div>
|
|
)
|
|
})
|
|
|
|
const checkLength= (file,fileList) => {
|
|
if (crrImages.length + fileList.length > 3) {
|
|
swal("Cảnh báo", "Bạn chỉ được tải lên tối đa 3 ảnh!", "warning");
|
|
return 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]]
|
|
}
|
|
|
|
let promises = [];
|
|
promises.push(
|
|
axios
|
|
.post(`${HOST}/api/face_images/famous_person`, dataUploadImg, {
|
|
headers: {
|
|
'Accept': 'application/json',
|
|
'Content-Type': 'application/json',
|
|
}
|
|
})
|
|
)
|
|
await Promise.all(promises)
|
|
.then((data) => {
|
|
let success = false
|
|
let manyFace = false
|
|
let noFace = false
|
|
for (let i = 0; i < data.length; i++) {
|
|
const element = data[i];
|
|
if (element.data.status === 10000) {
|
|
let listImg = dataUpload
|
|
setHostImg(element.data.image_host)
|
|
listImg.unshift(element.data.data.toString())
|
|
setDataUpload(...dataUpload)
|
|
success = true
|
|
} else if (element.data.status === 10003 && element.data.message === "Too many face in image") {
|
|
manyFace = true
|
|
} else if (element.data.status === 10003 && element.data.message === "No face in image") {
|
|
noFace = true
|
|
} else {
|
|
success = false
|
|
}
|
|
}
|
|
if (success) {
|
|
let originData = crrImages
|
|
originData.unshift(dataUpload[0].toString())
|
|
let arrSet = [...new Set(originData)]
|
|
setCrrImages(arrSet)
|
|
setCheckDeleteMulti(false)
|
|
} else if (manyFace) {
|
|
swal("Thất bại", "Ảnh có nhiều khuôn mặt!", "error");
|
|
} else if (noFace) {
|
|
swal("Thất bại", "Ảnh không có khuôn mặt!", "error");
|
|
} else {
|
|
swal("Thất bại", "Lỗi hệ thống!", "error");
|
|
}
|
|
})
|
|
.catch((err) => {
|
|
console.log(err)
|
|
});
|
|
};
|
|
|
|
|
|
|
|
const convertBase64 = (file) => {
|
|
return new Promise((resolve, reject) => {
|
|
const fileReader = new FileReader();
|
|
fileReader.readAsDataURL(file)
|
|
fileReader.onload = () => {
|
|
resolve(fileReader.result);
|
|
}
|
|
fileReader.onerror = (error) => {
|
|
reject(error);
|
|
}
|
|
})
|
|
}
|
|
|
|
|
|
const deleteFaceMulti = () => {
|
|
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));
|
|
if (crrIdx >= 1) {
|
|
setCrrIdx(crrIdx - 1)
|
|
}
|
|
setCrrImages(listDetele)
|
|
}
|
|
})
|
|
}
|
|
|
|
const UserHandle = (e) => {
|
|
setCrrData({ ...crrData, [e.target.name]: e.target.value })
|
|
}
|
|
|
|
const onChangeBirthday = (date) => {
|
|
setBirthday(date)
|
|
setCrrData({ ...crrData, birthday: moment(date).format("YYYY-MM-DD") })
|
|
}
|
|
|
|
if (!crrData) return <></>;
|
|
return (
|
|
<Modal
|
|
{...props}
|
|
animation={false}
|
|
size="lg"
|
|
// keyboard={false}
|
|
dialogClassName={`${window.innerWidth >= 1920 ? "modal-size-res" : "modal-size"}`}
|
|
aria-labelledby="contained-modal-title-vcenter"
|
|
>
|
|
<Modal.Header closeButton>
|
|
<Modal.Title id="contained-modal-title-vcenter">{crrData._id ? "Sửa thông tin" : "Thêm mới"}
|
|
</Modal.Title>
|
|
</Modal.Header>
|
|
{crrData &&
|
|
<Modal.Body>
|
|
<div id="formUpdateMeeting">
|
|
<div className="m-widget14 p-0">
|
|
<div className="row">
|
|
<div className="col-md-7 boder-right d-flex flex-column justify-content-between ">
|
|
<div className="row justify-content-center pb-3">
|
|
{
|
|
crrImages[crrIdx] ?
|
|
<img alt="" style={{objectFit: "contain", width: "180px", height: "180px"}} src={crrImages[crrIdx].includes("data:image") ? crrImages[crrIdx] : hostImg +dateImage+"/"+ crrImages[crrIdx]} size={180} icon={<UserOutlined />} /> :
|
|
<Avatar shape="square" size={180} icon={<UserOutlined />} />
|
|
}
|
|
|
|
</div>
|
|
<div className="row mr-4 ml-4">
|
|
{
|
|
crrImages.length > 0
|
|
?
|
|
<div className="col-md-12 mt-2 mb-2 p-0">
|
|
<label className="m-checkbox m-checkbox--success mt-3 ml-1">
|
|
<input type="checkbox"
|
|
onClick={(e) => {
|
|
setCheckDeleteMulti(!checkDeleteMulti)
|
|
setListChecked({
|
|
url: [],
|
|
})
|
|
}}
|
|
checked={checkDeleteMulti} /> <div style={{ 'paddingTop': '2px' }}>Chọn</div>
|
|
<span />
|
|
</label>
|
|
{
|
|
checkDeleteMulti === true
|
|
?
|
|
<div style={{ 'display': 'inline-flex' }} className="pull-right">
|
|
<button
|
|
onClick={(e) => {
|
|
e.preventDefault();
|
|
if (listChecked.url.length > 0) {
|
|
swal({
|
|
title: "Bạn chắc chắn muốn xóa ảnh này",
|
|
icon: "warning",
|
|
buttons: ["Huỷ", "Oke!"],
|
|
dangerMode: false,
|
|
})
|
|
.then((willDelete) => {
|
|
if (!willDelete) throw null;
|
|
deleteFaceMulti();
|
|
})
|
|
} else {
|
|
swal("Cảnh báo!", "Bạn chưa chọn ảnh để xóa", "warning");
|
|
}
|
|
}}
|
|
className="btn btn-sm btn-danger width-mobie--100 m-loader--light m-loader--right" id="btn_deleteMulti">
|
|
Xóa ảnh đã chọn
|
|
</button>
|
|
</div>
|
|
:
|
|
""
|
|
}
|
|
</div>
|
|
:
|
|
""
|
|
}
|
|
<div className="row col-md-12 pr-0 image_capture_small pull-left">
|
|
{
|
|
bulletedImg
|
|
}
|
|
|
|
</div>
|
|
<Upload
|
|
customRequest = {uploadImage}
|
|
accept="image/*"
|
|
multiple={true}
|
|
beforeUpload={checkLength}
|
|
showUploadList={false}
|
|
disabled={disableBtn}
|
|
>
|
|
<ButtonAntd className={`${disableBtn ? "disable-btn-upload" : ""}`} icon={<UploadOutlined />}>Tải ảnh lên</ButtonAntd>
|
|
</Upload>
|
|
{!disableBtn && <div className="pl-2 text-danger d-flex align-items-center">* Giới hạn 3 ảnh</div>}
|
|
</div>
|
|
</div>
|
|
|
|
<div className="col-md-5 d-flex flex-column justify-content-between">
|
|
<Form
|
|
id="formEdit"
|
|
form={form}
|
|
layout="vertical"
|
|
onFinish={() => click_handle()}
|
|
// onFinishFailed={onFinishFailed}
|
|
autoComplete="off"
|
|
initialValues={{
|
|
name: crrData.name,
|
|
id: crrData.id,
|
|
}}
|
|
>
|
|
<Form.Item
|
|
label="Họ tên"
|
|
name="name"
|
|
rules={[{ required: true, message: '' }]}
|
|
>
|
|
<Input placeholder="Họ tên" value={crrData.name} onChange={e => UserHandle(e)} name='name' />
|
|
</Form.Item>
|
|
|
|
<Form.Item
|
|
label="FacebookID"
|
|
name="id"
|
|
>
|
|
<Input placeholder="FacebookID" value={crrData.id} onChange={e => UserHandle(e)} name='id' />
|
|
</Form.Item>
|
|
|
|
<Form.Item name="radio-group" label="Giới tính">
|
|
<Radio.Group name="gender" onChange={e => UserHandle(e)} defaultValue={crrData.gender}>
|
|
<Radio name="gender" value={"1"}>Nam</Radio>
|
|
<Radio name="gender" value={"2"}>Nữ</Radio>
|
|
<Radio name="gender" value={"3"}>Giới tính khác</Radio>
|
|
</Radio.Group>
|
|
</Form.Item>
|
|
<Form.Item
|
|
label="Ngày sinh"
|
|
name="birthday"
|
|
>
|
|
<DatePicker className="form-control m-input"
|
|
locale={viVN}
|
|
defaultValue={birthday !== null ? moment(birthday, 'DD-MM-YYYY') : null}
|
|
format={'DD-MM-YYYY'}
|
|
onChange={e => onChangeBirthday(e)}
|
|
placeholder="Ngày sinh"
|
|
/>
|
|
</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>
|
|
<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>
|
|
);
|
|
}
|
|
|
|
export default ModalEditLabel;
|