Ela_Front/src/components/Emarge_QR_Code.js

850 lines
35 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 { gridClasses } from '@mui/x-data-grid';
import Link from '@mui/material/Link';
import { PiDotsThree } from "react-icons/pi";
function Emarge_QR_Code() {
const history = useHistory();
const { session_id, partner_owner_recid, my_safe_token } = useParams();
const [isLoading, setLoading] = useState();
const [selected_emargement_id, setselected_emargement_id] = 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);
function ExpandableCell_50({ value }) {
const [expanded, setExpanded] = React.useState(false);
return (
<nav>
{value && <div style={{ paddingLeft: "5px", paddingRight: "15px", "display": "block", wordBreak: "break-all" }}>
{expanded ? value : String(value).slice(0, 50)}&nbsp;
{value.length > 50 && (
// eslint-disable-next-line jsx-a11y/anchor-is-valid
<Link
type="button"
component="button"
sx={{ fontSize: 'inherit' }}
onClick={() => setExpanded(!expanded)}
>
{expanded ? <nav> <PiDotsThree />Réduire</nav> : <nav> <PiDotsThree />Voir</nav>}
</Link>
)}
</div>}
{!value && <div style={{ paddingLeft: "5px", paddingRight: "15px", "display": "block", wordBreak: "break-all" }}>
&nbsp;
</div>
}
</nav>
);
}
function Display_Colunm_text({ value }) {
return (
<div style={{ paddingLeft: "5px", paddingRight: "10px", "display": "block", wordBreak: "break-all" }}>
{value}&nbsp;
</div>
);
}
const columns_sequence = [
{ field: 'id', headerName: 'id', hide: true },
{ field: '_id', headerName: '_id', hide: true },
{ field: 'session_id', headerName: 'session_id', hide: true },
{ field: 'class_title', headerName: 'Formation', minWidth: 200, minWidth: 200, flex: 1, renderCell: (params) => <ExpandableCell_50 {...params} />, },
{ field: 'code_session', headerName: 'Session', minWidth: 200, minWidth: 200, flex: 1, renderCell: (params) => <ExpandableCell_50 {...params} />, },
{ field: 'sequence_start', headerName: 'Du', minWidth: 100, minWidth: 200, flex: 1, renderCell: (params) => <ExpandableCell_50 {...params} />, },
{ field: 'sequence_end', headerName: 'Au', minWidth: 100, minWidth: 200, flex: 1, renderCell: (params) => <ExpandableCell_50 {...params} />, },
]
const [selectionModel_sequence, setselectionModel_sequence] = React.useState([]);
const [New_Emargement_Data, setNew_Emargement_Data] = useState([]);
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/Check_Emargement_QR_Code_From_Inscription_No_Token/";
var form = new FormData();
const stored_cookie = getCookie('tokenmysypart');
form.append("partner_owner_recid", partner_owner_recid);
form.append("my_safe_token", my_safe_token);
form.append("session_id", session_id);
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");
setis_valide_e_document(true);
setget_E_Document_result(res.data.message);
var new_data2 = [];
const new_data = res.data.message.map((x) => {
//---
var localid = JSON.parse(x).id;
var local_id = JSON.parse(x)._id;
var local_sequence_start = JSON.parse(x).sequence_start;
var local_sequence_end = JSON.parse(x).sequence_end;
var local_email = JSON.parse(x).email;
var local_class_title = JSON.parse(x).class_title;
var local_code_session = JSON.parse(x).code_session;
//---
var node = {
"_id": local_id,
"id": localid,
"label": local_email + " " + local_sequence_start + " " + local_sequence_end,
"sequence_start": local_sequence_start,
"sequence_end": local_sequence_end,
"email": local_email,
"class_title": local_class_title,
"code_session": local_code_session,
};
new_data2.push(node);
});
if (new_data2.length > 0)
setNew_Emargement_Data(new_data2);
setDialog_1_open(false);
}
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")
})
}
function GetSelectedRows_Emarg_Ids() {
var tab_tmp = []
for (var i = 0; i < selectionModel_sequence.length; i++) {
var myid = parseInt(String(selectionModel_sequence[i]));
//var line = JSON.parse(rowss[myid]);
tab_tmp.push(myid);
}
return tab_tmp;
}
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(local_option) {
var myurl = process.env.REACT_APP_API_URL + "myclass/api/Update_Emargement_QR_Code_From_Inscription_No_Token/";
var liste_formation = GetSelectedRows_Emarg_Ids();
var tab_emargement = [];
for (var i = 0; i < liste_formation.length; i++) {
var line = JSON.parse(get_E_Document_result[liste_formation[i]]);
tab_emargement.push(line._id)
}
var form = new FormData();
const stored_cookie = getCookie('tokenmysypart');
form.append("partner_owner_recid", partner_owner_recid);
form.append("my_safe_token", my_safe_token);
form.append("tab_emargement_ids", tab_emargement);
form.append("is_present", local_option);
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("");
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");
};
const [isimgclassSaved, setisimgclassSaved] = useState("");
const [isimgclassSaved_message, setisimgclassSaved_message] = useState("");
return (
<div className="emarge_qr_code">
{/* POUR SIGNATURE E-DOCUMENT */}
<Dialog
open={Dialog_SIGN_VALIDATION_open}
onClose={Dialog_SIGN_VALIDATION_handleClose}
className="esign"
>
{!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>
<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"
>
{!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> Télephone </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>
<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>}
<Header />
<h3> Emargement électronique </h3>
<div className="div_row">
<div className="block_guide_line" >
<br />
<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 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 du code de validation de la signature</nav>
<nav style={{ "fontSize": "16px", "marginBottom": "0.8rem" }}> étape 4 Vous recevez par email la version pdf le document signé</nav>
</div>
<div className="block_data" >
{is_valide_e_document &&
<div className="div_row">
<div style={{ width: "80%", "marginLeft": "auto", "marginRight": "auto" }}>
<div className="div_row">
<div className="session_data">
{New_Emargement_Data && New_Emargement_Data.length > 0 && <div style={{ height: 550, width: '100%', paddingRight: '1px' }}>
&nbsp;
<Box
sx={{
height: "500px",
width: '100%',
paddingRight: '2px',
'& .line--statut--selected': {
backgroundColor: '#FBF2EF',
color: 'black',
}, [`& .${gridClasses.cell}`]: {
py: 1,
},
}}
>
<DataGrid
checkboxSelection={true}
disableRowSelectionOnClick
disableSelectionOnClick
onSelectionModelChange={(newSelectionModel) => {
setselectionModel_sequence(newSelectionModel);
}}
selectionModel={selectionModel_sequence}
localeText={frFR.components.MuiDataGrid.defaultProps.localeText}
rows={New_Emargement_Data.map((item, index) => (
{
id: index,
_id: (item)._id,
sequence_start: (item).sequence_start,
sequence_end: (item).sequence_end,
session_id: (item).session_id,
class_title: (item).class_title,
code_session: (item).code_session,
}
))}
columns={columns_sequence}
pageSize={10}
className="datagridclass"
onRowDoubleClick={(newSelectionModel) => {
}}
rowsPerPageOptions={[10]}
//disableSelectionOnClick
components={{
Toolbar: GridToolbar,
}}
//sx={datagridSx}
getCellClassName={(params) => {
}}
getRowClassName={(params) => {
}}
/>
</Box>
</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">
<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>}
{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) => {
Signature_E_Document(1);
}}>J'etais présent
</Button>
<Popup
trigger={
<Button variant="contained" className="bton_enreg" onClick={(e) => {
}}>J'etais présent
</Button>
}
modal
nested
position="center center"
>
{close => (
<div>
<button className="gest_close" onClick={close}>
&times;
</button>
<div className="gest_header"> MySy Information </div>
<div className="gest_content">
{' '}
En confirmant cette opération, vous validez votre présence aux {selectionModel_sequence.length} séquence(s) <br />
</div>
<div className="gest_actions">
<div style={{ "width": "45%", "float": "left" }}>
<button className="gest_bton_popup" onClick={(event) => {
Signature_E_Document(1);
close();
}}
> Valider </button>
</div>
<div style={{ "width": "45%", "float": "right" }}>
<button
className="gest_bton_popup"
onClick={() => {
//console.log('modal closed ');
close();
}}
>
Annuler
</button>
</div>
</div>
</div>
)}
</Popup>
</div>
<div className="div_row_droite" style={{ "textAlign": 'right', 'marginRight': '15px' }} >
<Button variant="contained" className="bton_annule" onClick={(e) => {
Signature_E_Document(0);
}}>J'etais Absent
</Button>
</div>
</div>
</div>
</div>}
{!is_valide_e_document && <div style={{ height: "40vh" }}>
&nbsp;
</div>}
</div>
</div>
<div className="div_row">
&nbsp;
</div>
<div className="pieddepage">
<Footer />
</div>
</div>
);
}
export default Emarge_QR_Code;