Ela_Front/src/components/ESign.js

817 lines
30 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

import React, { useRef, useState, useEffect } from "react";
import TextField from '@mui/material/TextField';
import MenuItem from '@mui/material/MenuItem';
import 'react-confirm-alert/src/react-confirm-alert.css'; // Import css
import Button from '@mui/material/Button';
import axios from "axios";
import { getCookie, setCookie } from 'react-use-cookie';
import { useHistory } from "react-router-dom";
import CheckOut from "./CheckOut";
import { DataGrid, GridToolbar, frFR } from '@mui/x-data-grid';
import "react-draft-wysiwyg/dist/react-draft-wysiwyg.css";
import { Editor } from '@tinymce/tinymce-react';
import parse from 'html-react-parser';
import { FcViewDetails, FcDisapprove } from "react-icons/fc";
import 'react-tooltip/dist/react-tooltip.css'
import { Tooltip } from 'react-tooltip'
import add_plus from "../mysy_img/plus.png";
import excel_icone from "../mysy_img/excel_icone.png";
import participants from "../mysy_img/participants.png";
import fileDownload from 'js-file-download'
import Autocomplete from '@mui/material/Autocomplete';
import Popup from 'reactjs-popup';
import 'reactjs-popup/dist/index.css';
import img_loading_spin from "./../mysy_img/mysy_spin_loading.gif";
import { FcCancel, FcApproval, FcAcceptDatabase, FcPrint } from "react-icons/fc";
import DatePicker from "react-datepicker";
import "react-datepicker/dist/react-datepicker.css";
import { format } from 'date-fns'
import moment from "moment";
import InputAdornment from '@mui/material/InputAdornment';
import { AiFillCloseCircle } from "react-icons/ai";
import Box from '@mui/material/Box';
import { Typography, LinearProgress } from '@mui/material';
import styled from 'styled-components';
import { CiTrash } from "react-icons/ci";
import { MdAddCircleOutline, MdRemoveCircleOutline } from "react-icons/md";
import Dialog from '@mui/material/Dialog';
import DialogActions from '@mui/material/DialogActions';
import DialogContent from '@mui/material/DialogContent';
import DialogContentText from '@mui/material/DialogContentText';
import DialogTitle from '@mui/material/DialogTitle';
import { TransitionProps } from '@mui/material/transitions';
import { IoAddCircleOutline, IoCloseCircleOutline } from "react-icons/io5";
import { useParams } from 'react-router-dom'
import Header from "./Header";
import Footer from "./Fotter";
import { FcInfo } from "react-icons/fc";
import { Document, Page } from 'react-pdf'
import SignatureCanvas from 'react-signature-canvas';
import Module_Alert_Confirmation from "./Module_Alert_Confirmation";
import { makeStyles } from "@material-ui/core/styles";
import Paper from '@material-ui/core/Paper';
import Draggable from 'react-draggable';
import { IconButton } from '@material-ui/core';
import AutoFixHighOutlinedIcon from '@mui/icons-material/AutoFixHighOutlined';
import CancelPresentationIcon from '@mui/icons-material/CancelPresentation';
function PaperComponent(props) {
return (
<Draggable
handle="#draggable-dialog-title"
cancel={'[class*="MuiDialogContent-root"]'}
>
<Paper {...props} />
</Draggable>
);
}
const useStyles = makeStyles((theme) => ({
dialog: {
position: 'absolute',
// left: 10,
top: 400
},
paper: {
overflowY: 'unset',
},
customizedButton: {
position: 'absolute',
left: '98%',
top: '-3%',
backgroundColor: 'lightgray',
color: 'gray',
},
}));
function ESign() {
const classes = useStyles();
const history = useHistory();
const { document_id, local_secret_key_signature, local_partner_owner_recid } = useParams();
const [isLoading, setLoading] = useState();
const [get_E_Document_PDF, setget_E_Document_PDF] = useState();
const [selected_e_doc_id, setselected_e_doc_id] = useState();
const [selected_e_doc_email, setselected_e_doc_email] = useState();
const [selected_e_doc_secret, setselected_e_doc_secret] = useState();
const [is_valide_e_document, setis_valide_e_document] = useState(false);
const [get_E_Document_api, setget_E_Document_api] = useState();
const [get_E_Document_message, setget_E_Document_message] = useState();
const [get_E_Document_result, setget_E_Document_result] = useState();
function get_E_Document() {
var myurl = process.env.REACT_APP_API_URL + "myclass/api/Get_Given_E_Document_Not_Signed_No_Token/";
var form = new FormData();
const stored_cookie = getCookie('tokenmysypart');
form.append("token", stored_cookie);
form.append("e_doc_id", document_id);
form.append("secret_key_open", selected_e_doc_secret);
form.append("user_email", user_email);
setLoading(true);
axios.post(myurl, form).then(res => {
setLoading(false);
//console.log(" get_E_Document : In test res.data.status = " + res.data.status);
//console.log(" get_E_Document: res.data.message.img = " + res.data.message);
if (String(res.data.status) === "true") {
setget_E_Document_api("true");
if (JSON.parse(res.data.message).document_data) {
setis_valide_e_document(true);
var document_data = "data:application/pdf;base64," + JSON.parse(res.data.message).document_data;
setget_E_Document_PDF(document_data);
setselected_e_doc_id(JSON.parse(res.data.message)._id);
//setselected_e_doc_email(JSON.parse(res.data.message).email_destinataire);
//setselected_e_doc_secret(JSON.parse(res.data.message).secret_key_open);
setDialog_1_open(false);
seterreur_recup_e_doc();
setselected_e_doc_secret("");
setselected_e_doc_email("");
}
}
else if (String(res.data.status) === String("Err_Connexion")) {
alert('Erreur: ' + res.data.message);
history.push("/Connexion");
return;
}
else {
setget_E_Document_api("false");
seterreur_recup_e_doc(res.data.message);
get_E_Document_message(res.data.message)
alert(res.data.message);
}
}).catch((error) => {
setLoading(false);
console.warn('get_E_Document ee: Not good man :( = ', error);
setget_E_Document_api("false");
get_E_Document_message(" Impossible de recuperer le E-Document")
})
}
const [Signature_E_Document_api, setSignature_E_Document_api] = useState();
const [Signature_E_Document_message, setSignature_E_Document_message] = useState();
const [Signature_E_Document_result, setSignature_E_Document_result] = useState();
function Signature_E_Document(material_id) {
var myurl = process.env.REACT_APP_API_URL + "myclass/api/Create_E_Signature_For_E_Document/";
var form = new FormData();
const stored_cookie = getCookie('tokenmysypart');
form.append("token", stored_cookie);
form.append("e_doc_id", selected_e_doc_id);
form.append("secret_key_signature", selected_e_doc_secret);
form.append("email_destinataire", selected_e_doc_email);
form.append("signature_img_selected", userimgclassprofil);
if (isimgclassSelectedfile)
form.append('signature_img', isimgclassSelected);
else
form.append('signature_img', "");
// console.log(" isimgclassSelected #### = ", isimgclassSelected);
setLoading(true);
axios.post(myurl, form).then(res => {
setLoading(false);
//console.log(" Signature_E_Document : In test res.data.status = " + res.data.status);
//console.log(" Signature_E_Document: res.data.message.img = " + res.data.message);
if (String(res.data.status) === "true") {
setSignature_E_Document_api("true");
setDialog_Message_open(true);
// alert(" Le document a été correctement signé");
}
else if (String(res.data.status) === String("Err_Connexion")) {
alert('Erreur: ' + res.data.message);
history.push("/Connexion");
return;
}
else {
setSignature_E_Document_api("false");
Signature_E_Document_message(res.data.message);
seterreur_recup_e_doc(res.data.message);
alert(res.data.message);
}
}).catch((error) => {
setLoading(false);
console.warn('Signature_E_Document ee: Not good man :( = ', error);
setSignature_E_Document_api("false");
Signature_E_Document_message(" Impossible de signer le E-Document")
})
}
useEffect(() => {
setselected_e_doc_id(document_id);
// get_E_Document();
window.scrollTo({
top: 0,
behavior: "smooth",
});
}, [])
const [user_nom, setuser_nom] = React.useState("");
const [user_prenom, setuser_prenom] = React.useState("");
const [user_email, setuser_email] = React.useState("");
const [erreur_recup_e_doc, seterreur_recup_e_doc] = React.useState();
const [Dialog_1_message, setDialog_1_message] = React.useState(false);
const [Dialog_1_open, setDialog_1_open] = React.useState(true);
function Dialog_1_handle_change_participant_session(message) {
setDialog_1_message(message);
setDialog_1_open(true);
}
const Dialog_1_handleClose = () => {
//alert(" Utiliser le bouton 'fermer' ");
//setOpen(false);
};
const Dialog_1_handleClose_buton = () => {
setDialog_1_open(false);
history.push("/");
};
const [Dialog_Message_message, setDialog_Message_message] = React.useState(false);
const [Dialog_Message_open, setDialog_Message_open] = React.useState(false);
function Dialog_Message_handle_change_participant_session(message) {
setDialog_Message_message(message);
setDialog_Message_open(true);
}
const Dialog_Message_handleClose = () => {
//alert(" Utiliser le bouton 'fermer' ");
//setOpen(false);
};
const Dialog_Message_handleClose_buton = () => {
setDialog_Message_open(false);
history.push("/");
};
const [Dialog_SIGN_VALIDATION_open, setDialog_SIGN_VALIDATION_open] = React.useState(false);
const Dialog_SIGN_VALIDATION_handleClose = () => {
//alert(" Utiliser le bouton 'fermer' ");
//setOpen(false);
};
const Dialog_SIGN_VALIDATION_handleClose_buton = () => {
setDialog_SIGN_VALIDATION_open(false);
history.push("/");
};
const [isimgclassSelected, setisimgclassSelected] = useState(false);
const [isimgclassSelected_recid, setisimgclassSelected_recid] = useState("");
const [isimgclassSelectedfile, setisimgclassSelectedfile] = useState(false);
const [userimgclassprofil, setuserimgclassprofil] = useState();
const [userimgclassprofilchanged, setuserimgclassprofilchanged] = useState("");
function reader(file, callback) {
const fr = new FileReader();
fr.onload = () => callback(null, fr.result);
fr.onerror = (err) => callback(err);
fr.readAsDataURL(file);
}
const imglogoclasschangeHandler = (event) => {
let file_size = event.target.files[0].size;
//or if you like to have name and type
//console.log(event.target.files);
let file_name = event.target.files[0].name;
let file_type = event.target.files[0].type;
//alert("file_size = "+file_size+" file_type = "+file_type+" a = "+a);
if (file_size > 1000000) {
alert("L'image ne doit pas dépasser un 1 Méga octets");
return;
}
setisimgclassSelected(event.target.files[0]);
setisimgclassSelectedfile(true);
//setuserimgclassprofil(URL.createObjectURL(event.target.files[0]));
setuserimgclassprofilchanged("1");
reader(event.target.files[0], (err, res) => {
//console.log(res); // Base64 `data:image/...` String result.
setuserimgclassprofil(res);
});
};
const [isimgclassSaved, setisimgclassSaved] = useState("");
const [isimgclassSaved_message, setisimgclassSaved_message] = useState("");
const [Dialog_SIGN_MANUSCRITE_open, setDialog_SIGN_MANUSCRITE_open] = React.useState(false);
const Dialog_SIGN_MANUSCRITE_handleClose = () => {
//alert(" Utiliser le bouton 'fermer' ");
//setOpen(false);
};
const Dialog_SIGN_MANUSCRITE_handleClose_buton = () => {
setDialog_SIGN_MANUSCRITE_open(false);
};
const signatureCanvasRef = useRef(null);
// API method examples
const checkIfEmpty = () => {
const isEmpty = signatureCanvasRef.current.isEmpty();
if (signatureCanvasRef) {
setuserimgclassprofil(signatureCanvasRef.current.toDataURL());
setisimgclassSelected(signatureCanvasRef.current.toDataURL())
}
setuserimgclassprofilchanged("1");
Dialog_SIGN_MANUSCRITE_handleClose_buton();
};
const clearCanvas = () => {
signatureCanvasRef.current.clear();
};
return (
<div className="esign">
{/* POUR SIGNATURE MANUSCRITE */}
<Dialog
open={Dialog_SIGN_MANUSCRITE_open}
onClose={Dialog_SIGN_MANUSCRITE_handleClose}
className="esign"
>
<DialogTitle>Signature Manuscrite </DialogTitle>
<DialogContent className="DialogContent_width">
<div style={{ width: "100%" }}>
<SignatureCanvas ref={signatureCanvasRef} style={{ "border": "solid 1px red" }} penColor="blue"
canvasProps={{
width: 315,
height: 200,
style: { border: "1px solid black", borderRadius: "10px" },
}} />
</div>
<div style={{ width: "100%", marginLeft: 'auto', marginRight: 'auto', width: 315 }}>
<nav className="bton_supprime_image_class" style={{ width: '100%' }} onClick={(e) => {
clearCanvas();
}}>Effacer </nav>
</div>
</DialogContent>
<DialogActions>
<div className="div_row">
<div className="div_row_gauche">
<Button onClick={checkIfEmpty} className="bton_enreg_dialog">Valider &nbsp;</Button>
</div>
<div className="div_row_droite" style={{ "textAlign": 'center' }}>
<Button onClick={Dialog_SIGN_MANUSCRITE_handleClose_buton} className="bton_annule_dialog" >Annuler</Button>
</div>
</div>
</DialogActions>
</Dialog>
{/* FIN POUR SIGNATURE MANUSCRITE */}
{/* POUR SIGNATURE E-DOCUMENT */}
<Dialog
open={Dialog_SIGN_VALIDATION_open}
//onClose={Dialog_SIGN_VALIDATION_handleClose}
className="esign"
static
onClose={() => null}
PaperProps={{
className: classes.paper, // Apply the paper style
style: {
overflowY: 'unset',
position: 'absolute',
top: '10rem',
margin: "2px",
},
}}
hideBackdrop={true}
disableScrollLock
classes={{
paper: classes.dialog
}}
PaperComponent={PaperComponent}
aria-labelledby="draggable-dialog-title"
>
{!erreur_recup_e_doc && <DialogTitle>Signature </DialogTitle>}
{erreur_recup_e_doc && <DialogTitle>Signature - <font color="red"> Identifiants invalides </font></DialogTitle>}
<DialogContent className="DialogContent_width">
<div className="div_row_dialog">
<div className="session_caract_Dialog" > <b> Email </b>
<TextField
// autoFocus
margin="dense"
id="new_login"
//label="Prix Unitaire"
fullWidth
//variant="standard"
value={selected_e_doc_email}
onChange={(e) => {
setselected_e_doc_email(e.target.value);
}
}
/>
</div>
</div>
<div className="div_row_dialog">
<div className="session_caract_Dialog" > <b>Clé de signature </b>
<TextField
// autoFocus
margin="dense"
id="secrete_key"
//label="Prix Unitaire"
fullWidth
//variant="standard"
value={selected_e_doc_secret}
onChange={(e) => {
setselected_e_doc_secret(e.target.value);
}
}
/>
</div>
</div>
</DialogContent>
<DialogActions>
<IconButton
// autoFocus
onClick={Dialog_SIGN_VALIDATION_handleClose_buton}
color="primary"
className={classes.customizedButton}
>
<CancelPresentationIcon />
</IconButton>
<div className="div_row">
<div className="div_row_gauche">
<Button onClick={Signature_E_Document} className="bton_enreg_dialog">Valider &nbsp;</Button>
</div>
<div className="div_row_droite" style={{ "textAlign": 'center' }}>
<Button onClick={Dialog_SIGN_VALIDATION_handleClose_buton} className="bton_annule_dialog" >Annuler</Button>
</div>
</div>
</DialogActions>
</Dialog>
{/* FIN POUR SIGNATURE E-DOCUMENT */}
{/* POUR OUVERTURE E-DOCUMENT */}
<Dialog
open={Dialog_1_open}
// onClose={Dialog_1_handleClose}
className="esign"
static
onClose={() => null}
PaperProps={{
className: classes.paper, // Apply the paper style
style: {
overflowY: 'unset',
position: 'absolute',
top: '10rem',
margin: "2px",
},
}}
hideBackdrop={true}
disableScrollLock
classes={{
paper: classes.dialog
}}
PaperComponent={PaperComponent}
aria-labelledby="draggable-dialog-title"
>
{!erreur_recup_e_doc && <DialogTitle>Authentification </DialogTitle>}
{erreur_recup_e_doc && <DialogTitle>Authentification - <font color="red"> Identifiants invalides </font></DialogTitle>}
<DialogContent className="DialogContent_width">
<div className="div_row_dialog">
<div className="session_caract_Dialog" > <b>Email </b>
<TextField
// autoFocus
margin="dense"
id="new_login"
//label="Prix Unitaire"
fullWidth
//variant="standard"
value={user_email}
onChange={(e) => {
setuser_email(e.target.value);
}
}
/>
</div>
</div>
<div className="div_row_dialog">
<div className="session_caract_Dialog" > <b> Clé d'ouverture </b>
<TextField
// autoFocus
margin="dense"
id="secrete_key"
//label="Prix Unitaire"
fullWidth
//variant="standard"
value={selected_e_doc_secret}
onChange={(e) => {
setselected_e_doc_secret(e.target.value);
}
}
/>
</div>
</div>
</DialogContent>
<DialogActions>
<IconButton
// autoFocus
onClick={Dialog_1_handleClose_buton}
color="primary"
className={classes.customizedButton}
>
<CancelPresentationIcon />
</IconButton>
<div className="div_row">
<div className="div_row_gauche">
<Button onClick={get_E_Document} className="bton_enreg_dialog">Afficher</Button>
</div>
<div className="div_row_droite" style={{ "textAlign": 'center' }}>
<Button onClick={Dialog_1_handleClose_buton} className="bton_annule_dialog" >Annuler</Button>
</div>
</div>
</DialogActions>
</Dialog>
{/* FIN POUR OUVERTURE E-DOCUMENT */}
<Dialog
open={Dialog_Message_open}
onClose={Dialog_Message_handleClose}
className="esign"
>
<DialogTitle>Information </DialogTitle>
<DialogContent className="DialogContent_width">
<div className="div_row_dialog">
Le document a été signée. Vous allez recevoir le document par email
</div>
</DialogContent>
<DialogActions>
<div className="div_row">
<div className="div_row_gauche">
&nbsp;
</div>
<div className="div_row_droite" style={{ "textAlign": 'center' }}>
<Button onClick={Dialog_Message_handleClose_buton} className="bton_enreg_dialog"> Fermer &nbsp;</Button>
</div>
</div>
</DialogActions>
</Dialog>
{isLoading && <div className="loader-container">
<div className="mysy_spinner"> <img src={img_loading_spin} /> </div>
</div>}
<h3 style={{ fontFamily:'DM Sans' }}> Signature Electronique </h3>
<div className="div_row">
<div className="signature_block_explication" >
<nav style={{ "fontSize": "2rem", "marginBottom": "1rem", "fontWeight": "700" }}> Guide d'utilisation : </nav><br />
<nav>Pour vous permettre de signer électroniquement vos documents, MySy Training Technology met à disposition ce module. </nav>
<nav style={{ "fontSize": "2rem", "marginBottom": "1rem", "marginTop": "1rem", "fontWeight": "700" }}> Comment ça marche : </nav>
<nav style={{ "fontSize": "16px", "marginBottom": "0.8rem" }}> étape 1 Vous accédez au document à laide de votre adresse email et de la clé douverture </nav>
<nav style={{ "fontSize": "16px", "marginBottom": "0.8rem" }}> étape 2 Apres louverture du document vous recevez par email un code de validation de la signature</nav>
<nav style={{ "fontSize": "16px", "marginBottom": "0.8rem" }}> étape 3 Signez le document à laide de votre adresse email et du code de validation de la signature</nav>
<nav style={{ "fontSize": "16px", "marginBottom": "0.8rem" }}> étape 4 Vous recevez par email la version PDF du document signé</nav>
</div>
<div className="signature_block_document" >
{is_valide_e_document &&
<div className="div_row">
<div style={{ width: "95%", "marginLeft": "auto", "marginRight": "auto" }}>
<embed src={get_E_Document_PDF} width='100%' height='700px' type="application/pdf" />
</div>
<div className="div_row">
&nbsp;
</div>
<div style={{ width: "95%", "marginLeft": "auto", "marginRight": "auto" }}>
<div className="div_row" style={{ "border": "None", "color": "orange", "textAlign": "center" }}>
<div className="div_row">
<div className="div_row_bis" style={{ "marginBottom": "10px", "marginTop": "1rem" }} >
<div className="div_row_gauche_image">
<img class="img_class_logo" src={userimgclassprofil} /><br />
</div>
<div className="div_row_droite_image">
<input type="file" id="files_img_class" accept="image/*" onChange={imglogoclasschangeHandler} style={{ opacity: "0", zIndex: "-1", maxWidth: "5px", maxHeight: "0px" }} /><br />
{<nav>
<label for="files_img_class" className="bton_image_class">Charger une signature</label><br />
{String(userimgclassprofilchanged) === "1" &&
<nav className="bton_supprime_image_class" onClick={(e) => {
setuserimgclassprofil("");
setuserimgclassprofilchanged("");
}}>Supprimer la signature<br /> </nav>
}
<div className="div_row_bis tips_img_class">
<li>
L'image doit etre carrée.
</li>
<li>
Les formats autorisés sont : <i>['jpg', 'jpeg', 'png', 'jpe', 'webp']</i>
</li>
<li>
La taille de l'image ne doit pas dépasser 1 mega octet
</li>
</div>
</nav>}
<Button variant="contained" className="bton_image_class" onClick={(e) => {
setDialog_SIGN_MANUSCRITE_open(true);
}}>Signer manuellement
</Button>
{isimgclassSelected && String(isimgclassSaved) === "0" && <nav className="koUpdateData"> {isimgclassSaved_message}</nav>}
</div>
</div>
</div>
</div>
</div>
<div className="div_row">
&nbsp;
</div>
<div style={{ width: "80%", "marginLeft": "auto", "marginRight": "auto" }}>
<div className="div_row" style={{ "border": "None", "color": "orange", "textAlign": "center" }}>
<div className="div_row_gauche" style={{ "textAlign": 'left', 'marginLeft': '15px' }}>
<Button variant="contained" className="bton_enreg" onClick={(e) => {
setDialog_SIGN_VALIDATION_open(true);
}}>Signer
</Button>
</div>
<div className="div_row_droite" style={{ "textAlign": 'right', 'marginRight': '15px' }} >
<Button variant="contained" className="bton_annule" onClick={Dialog_Message_handleClose_buton}>Annuler
</Button>
</div>
</div>
</div>
</div>}
{!is_valide_e_document && <div style={{ height: "40vh" }}>
&nbsp;
</div>}
</div>
</div>
<div className="div_row">
&nbsp;
</div>
</div>
);
}
export default ESign;