import React, { useEffect, useState } from "react"; import { Col, Row, Form, Input, Modal, Card, Avatar, Select, Button, DatePicker, message, Spin, } from "antd"; import { EditOutlined, DeliveredProcedureOutlined, BarChartOutlined, BellFilled, } from "@ant-design/icons"; import { useHistory } from "react-router-dom"; import { addDoc, collection, doc, getDoc, updateDoc, query as firebaseQuery, getDocs, where, orderBy, } from "firebase/firestore"; import { useQuery, useAuth } from "../../../hooks"; import { ViewLoading } from "../../../components"; import excelCondensado from "../../../services/excelCondensado"; import { DefaultLayout } from "../../../components/layouts"; import { firestore } from "../../../services/firebase"; import locale from "antd/es/date-picker/locale/es_ES"; import moment from "moment"; import "moment/locale/es-mx"; const { RangePicker } = DatePicker; const { REACT_APP_WEB_URL } = process.env; const EventoDetalleGrupo = () => { const query = useQuery(); const history = useHistory(); const { session } = useAuth(); const { TextArea } = Input; const { Meta } = Card; const { Option } = Select; const id = query.get("id"); const tag = query.get("tag"); const editando = !!id; const urlweb = "/administracion/eventos"; const [form] = Form.useForm(); const [formProcesar] = Form.useForm(); const [grupoEvento, setGrupoEvento] = useState([]); const [cargandoEvento, setCargandoEvento] = useState(true); const [eventos, setEventos] = useState([]); const [visible, setVisible] = useState(false); const [visibleReporte, setVisibleReporte] = useState(false); const [procesando, setProcesando] = useState(false); const [evento, setEvento] = useState(null); const [textAreaData, setTextAreaData] = useState(""); const [previaImg, setPreviaImg] = useState(null); const [guardando, setGuardando] = useState({ nuevo: false, faltante: false, felicitacion: false, condensado: false, }); const acciones = [ { id: 0, value: "Ver", label: "Ver", icon: "馃憗" }, { id: 1, value: "Me gusta", label: "Me gusta", icon: "馃憤" }, { id: 2, value: "Compartir", label: "Compartir", icon: "馃攧" }, ]; const buttons = [ { text: "Notificar nuevo evento", to: () => notificarNuevoEvento(), icon: , props: { disabled: false, style: { background: "#2196f3", color: "#fff" }, type: "default", size: "large", loading: guardando.nuevo, }, }, { text: "Enviar faltantes", to: () => enviarRecordatorios(), icon: , props: { disabled: false, type: "danger", size: "large", loading: guardando.faltante, }, }, { text: "Enviar felicitaci贸n", to: () => enviarFelicitacion(), icon: , props: { disabled: false, type: "primary", size: "large", loading: guardando.felicitacion, }, }, { text: "Reporte condensado", to: () => setVisibleReporte(true), icon: , props: { disabled: false, type: "dashed", size: "large" }, }, ]; function b64_to_utf8(str) { return decodeURIComponent(escape(window.atob(str))); } const guardarRegistro = async () => { try { const json = JSON.parse(textAreaData); const accion = b64_to_utf8(json.accion).split("."); const lista = json[json.tipo][accion[0]]; const body = { json: textAreaData, accion: accion, lista: lista, timestamp: new Date(), evento: evento, usuario: { uid: session?.uid, email: session?.email, displayName: session?.displayName, }, }; await addDoc(collection(firestore, "procesos"), body); } catch (error) { console.log("error al guardar registro: ", error); } }; const procesarUsuarios = async () => { try { setProcesando(true); let usuarios = await obtenerUsuariosGrupo(); const json = JSON.parse(textAreaData); const accion = b64_to_utf8(json.accion).split("."); const lista = json[json.tipo][accion[0]]; if (json?.tipo !== evento?.redSocial?.toLowerCase()) { message.warning({ content: "La red social es incorrecta", }); return; } let resultado = { ...evento.resultado }; for (let u = 0; u < usuarios?.length; u++) { let usuarioTipo = usuarios[u][json.tipo]?.toLowerCase(); if (resultado[usuarios[u]?.uid] === undefined) { resultado[usuarios[u]?.uid] = []; } if (usuarioTipo?.toLowerCase()) { for (let i = 0; i < lista.length; i++) { const nick = lista[i]?.replace("@", "").toLowerCase(); if (nick?.includes(usuarios[u][json.tipo])) { if (!resultado[usuarios[u]?.uid].includes(accion[0])) { resultado[usuarios[u]?.uid].push(accion[0]); } } } } } // Hay indices que salen en undefined y sali贸 error al guardar en firebase try { resultado = JSON.parse(JSON.stringify(resultado)); } catch (e) { } // Sale un error en firebase de que no puede guardar informaci贸n en undefined (no se encontr贸 d贸nde) try { usuarios = JSON.parse(JSON.stringify(usuarios)); } catch (e) { } let body = { usuarios, resultado, }; await updateDoc(doc(firestore, "eventos", evento?.id), body); history.push( urlweb + "/resultado-grupo-evento?id=" + evento?.id + "&tag=" + evento?.tag, ); setVisible(false); } catch (error) { console.log("Error al procesar: ", error); message.warning({ content: "Atenci贸n: hubo un problema al procesar la informaci贸n", }); } finally { setProcesando(false); } }; const obtenerUsuariosGrupo = async () => { const _grupos = grupoEvento?.grupos; // Verificar que el evento no tenga grupos if (_grupos?.length === 0) { message.warning({ content: "Atenci贸n: el evento no tiene grupos.", }); return; } try { const q = firebaseQuery( collection(firestore, "usuarios"), where("grupos", "array-contains-any", _grupos), ); const querySnapshot = await getDocs(q); const docs = []; querySnapshot.forEach((doc) => { const data = doc.data(); docs.push({ grupos: data?.grupos, facebook: data?.facebook?.toLowerCase().trim(), twitterVerificado: data?.twitterVerificado ? true : false, facebookVerificado: data?.facebookVerificado ? true : false, instagramVerificado: data?.instagramVerificado ? true : false, twitter: data?.twitter?.toLowerCase().trim(), instagram: data?.instagram?.toLowerCase().trim(), telefono: data?.telefono, verificado: data?.verificado, nombre: data?.nombre, uid: data?.uid, id: doc.id, }); }); return docs; } catch (error) { console.log("error al obtener grupos: ", error); } }; const abrirPublicacion = (e) => { window.open(e?.url, "_blank", "noopener,noreferrer"); }; const obtenerEnlaceYager = (e) => { const url = REACT_APP_WEB_URL + "evento-laud?id=" + e?.id; navigator.clipboard.writeText(url); message.info({ content: "Se ha copiado el enlace al portapapeles.", }); }; const notificarNuevoEvento = async () => { try { setGuardando({ ...guardando, nuevo: true }); const _usuarios = grupoEvento?.usuarios; const _redesEvento = grupoEvento?.redes; const plantilla = "nuevo_evento"; if (_usuarios?.length < 1) { message.info("Este evento no ha sido procesado a煤n."); return; } const arrUsuarios = []; const eventoFb = _redesEvento.find((i) => i?.redSocial === "Facebook") ? true : false; const eventoIg = _redesEvento.find((i) => i?.redSocial === "Instagram") ? true : false; const eventoTw = _redesEvento.find((i) => i?.redSocial === "Twitter") ? true : false; const eventoTt = _redesEvento.find((i) => i?.redSocial === "TikTok") ? true : false; _usuarios?.forEach((u) => { const uid = u?.uid; let tieneFb = false; let tieneIg = false; let tieneTw = false; if (u?.facebookVerificado) tieneFb = true; if (u?.instagramVerificado) tieneIg = true; if (u?.twitterVerificado) tieneTw = true; const usuario = { uid, nombre: u?.nombre, telefono: u?.telefono, fb: eventoFb && tieneFb, ig: eventoIg && tieneIg, tw: eventoTw && tieneTw, tt: eventoTt /* && tieneTw */, }; arrUsuarios.push(usuario); }); const body = { idEvento: id, plantilla: plantilla, titulo: grupoEvento?.nombre, estatus: "Nuevo", enviado: null, fecha: new Date(), url: eventos.map((e) => `${REACT_APP_WEB_URL}evento-laud?id=${e?.id}`), urlFB: `${REACT_APP_WEB_URL}evento-laud?id=${eventos?.find((e) => e.redSocial === "Facebook")?.id}`, urlIG: `${REACT_APP_WEB_URL}evento-laud?id=${eventos?.find((e) => e.redSocial === "Instagram")?.id}`, urlTW: `${REACT_APP_WEB_URL}evento-laud?id=${eventos?.find((e) => e.redSocial === "Twitter")?.id}`, urlTT: `${REACT_APP_WEB_URL}evento-laud?id=${eventos?.find((e) => e.redSocial === "TikTok")?.id}`, usuarios: arrUsuarios, }; if (!eventoFb) { body.urlFB = ""; } if (!eventoIg) { body.urlIG = ""; } if (!eventoTw) { body.urlTW = ""; } if (!eventoTt) { body.urlTT = ""; } // Buscamos si existe un registro con el ID del evento y la misma plantilla const q = firebaseQuery( collection(firestore, "notificaciones"), where("idEvento", "==", id), ); const querySnapshot = await getDocs(q); let c = 0; querySnapshot.forEach((doc) => { if (doc.data().plantilla === plantilla) { c++; } }); if (c > 0) { message.info("Ya hay un recordatorio de este evento."); return; } await addDoc(collection(firestore, "notificaciones"), body); message.success("Recordatorio enviado."); } catch (error) { message.error("Error al enviar la notificacion"); console.log("error al notificar: ", error); } finally { setGuardando({ ...guardando, nuevo: false }); } }; const enviarRecordatorios = async () => { try { setGuardando({ ...guardando, faltante: true }); const _usuarios = grupoEvento?.usuarios; const plantilla = "recordatorio"; if (_usuarios?.length < 1) { message.info("Este evento no ha sido procesado a煤n."); return; } let eventoFb = null; let eventoTw = null; let eventoIg = null; let eventoTt = null; for (let i = 0; i < eventos.length; i++) { if (eventos[i].redSocial === "Facebook") { eventoFb = eventos[i]; } else if (eventos[i].redSocial === "Instagram") { eventoIg = eventos[i]; } else if (eventos[i].redSocial === "Twitter") { eventoTw = eventos[i]; } else if (eventos[i].redSocial === "TikTok") { eventoTt = eventos[i]; } } const arrUsuarios = []; _usuarios?.forEach((u) => { const uid = u?.uid; let tieneFb = false; let tieneIg = false; let tieneTw = false; if (u?.facebookVerificado) { tieneFb = true; } if (u?.instagramVerificado) { tieneIg = true; } if (u?.twitterVerificado) { tieneTw = true; } const usuario = { uid, nombre: u?.nombre, telefono: u?.telefono, fb: tieneFb && eventoFb?.resultado[uid]?.length === 0, ig: tieneIg && eventoIg?.resultado[uid]?.length === 0, tw: tieneTw && eventoTw?.resultado[uid]?.length === 0, tt: /* tieneTw && */eventoTt?.resultado[uid]?.length === 0, }; /* if (!usuario.fb && !usuario.ig && !usuario.tw) { return true; } */ arrUsuarios.push(usuario); }); const body = { idEvento: id, plantilla: plantilla, titulo: grupoEvento?.nombre, estatus: "Nuevo", enviado: null, fecha: new Date(), urlFB: `${REACT_APP_WEB_URL}evento-laud?id=${eventos?.find((e) => e.redSocial === "Facebook")?.id}`, urlIG: `${REACT_APP_WEB_URL}evento-laud?id=${eventos?.find((e) => e.redSocial === "Instagram")?.id}`, urlTW: `${REACT_APP_WEB_URL}evento-laud?id=${eventos?.find((e) => e.redSocial === "Twitter")?.id}`, urlTT: `${REACT_APP_WEB_URL}evento-laud?id=${eventos?.find((e) => e.redSocial === "TikTok")?.id}`, usuarios: arrUsuarios, }; if (!eventoFb) { body.urlFB = ""; } if (!eventoIg) { body.urlIG = ""; } if (!eventoTw) { body.urlTW = ""; } if (!eventoTt) { body.urlTT = ""; } // Buscamos si existe un registro con el ID del evento y la misma plantilla const q = firebaseQuery( collection(firestore, "notificaciones"), where("idEvento", "==", id), ); const querySnapshot = await getDocs(q); let c = 0; querySnapshot.forEach((doc) => { if (doc.data().plantilla === plantilla) { c++; } }); if (c > 0) { message.info("Ya hay un recordatorio de este evento."); return; } await addDoc(collection(firestore, "notificaciones"), body); message.success("Recordatorio guardado."); } catch (error) { message.error("Error al enviar notifiaci贸n."); console.log("error al enviar notifiacion: ", error); } finally { setGuardando({ ...guardando, faltante: false }); } }; const enviarFelicitacion = async () => { try { setGuardando({ ...guardando, felicitacion: true }); const _usuarios = grupoEvento.usuarios; const plantilla = "evento_gracias"; if (_usuarios?.length < 1) { message.info("Este evento no ha sido procesaod a煤n."); return; } let eventoFb = null; let eventoTw = null; let eventoIg = null; let eventoTt = null; for (let i = 0; i < eventos.length; i++) { if (eventos[i]?.redSocial === "Facebook") { eventoFb = eventos[i]; } else if (eventos[i]?.redSocial === "Instagram") { eventoIg = eventos[i]; } else if (eventos[i]?.redSocial === "Twitter") { eventoTw = eventos[i]; } else if (eventos[i]?.redSocial === "TikTok") { eventoTt = eventos[i]; } } const arrUsuarios = []; _usuarios?.forEach((u) => { const uid = u?.uid; let tieneFb = false; let tieneIg = false; let tieneTw = false; let cr = 0; if (u?.facebookVerificado) { tieneFb = true; cr = cr + 1; } if (u?.instagramVerificado) { tieneIg = true; cr = cr + 1; } if (u?.twitterVerificado) { tieneTw = true; cr = cr + 1; } const res = eventoFb?.resultado[uid].length + eventoIg?.resultado[uid].length + eventoTw?.resultado[uid].length + eventoTt?.resultado[uid].length; const usuario = { uid, nombre: u?.nombre, telefono: u?.telefono, fb: tieneFb && eventoFb?.resultado[uid]?.length > 0, ig: tieneIg && eventoIg?.resultado[uid]?.length > 0, tw: tieneTw && eventoTw?.resultado[uid]?.length > 0, tt: /* tieneTw && */eventoTw?.resultado[uid]?.length > 0, }; // if( (res/cr) === 1 ) { arrUsuarios.push(usuario); // } }); if (arrUsuarios?.length < 1) { message.info("No hay usuarios para notificar."); return; } const body = { idEvento: id, plantilla: plantilla, titulo: grupoEvento?.nombre, enviado: null, estatus: "Nuevo", fecha: new Date(), urlFB: `${REACT_APP_WEB_URL}evento-laud?id=${eventos?.find((e) => e.redSocial === "Facebook")?.id}`, urlIG: `${REACT_APP_WEB_URL}evento-laud?id=${eventos?.find((e) => e.redSocial === "Instagram")?.id}`, urlTW: `${REACT_APP_WEB_URL}evento-laud?id=${eventos?.find((e) => e.redSocial === "Twitter")?.id}`, urlTT: `${REACT_APP_WEB_URL}evento-laud?id=${eventos?.find((e) => e.redSocial === "TikTok")?.id}`, usuarios: arrUsuarios, }; if (!eventoFb) { body.urlFB = ""; } if (!eventoIg) { body.urlIG = ""; } if (!eventoTw) { body.urlTW = ""; } if (!eventoTt) { body.urlTT = ""; } // Buscamos si existe un registro con el ID del evento y la misma plantilla const q = firebaseQuery( collection(firestore, "notificaciones"), where("idEvento", "==", id), ); const querySnapshot = await getDocs(q); let c = 0; querySnapshot.forEach((doc) => { if (doc.data().plantilla === plantilla) { c++; } }); if (c > 0) { message.info("Ya hay un recordatorio de este evento."); return; } await addDoc(collection(firestore, "notificaciones"), body); message.success("Recordatorio enviado."); } catch (error) { message.error("Error al enviar la notificacion"); console.log("error al enviar felicitaci贸n: ", error); } finally { setGuardando({ ...guardando, felicitacion: false }); } }; const reporteCondesado = async () => { try { setGuardando({ ...guardando, condensado: true }); // Obtener usuarios con sus redes sociales verificadas. const usuariosGrupo = await obtenerUsuariosGrupo(); const eventos = []; const usuarios = []; const dataExcel = []; const fechas = formProcesar.getFieldValue("fechas"); if (!fechas) { message.info("Debes de seleccionar un rango de fechas."); return; } const fechaInicio = new Date(fechas[0]?._d.setHours(0, 0, 0)); const fechaFin = new Date(fechas[1]?._d.setHours(23, 59, 59)); const queryConstraints = [ where("timestamp", ">=", fechaInicio), where("timestamp", "<=", fechaFin), ]; const ref = collection(firestore, "eventos"); const q = firebaseQuery( ref, ...queryConstraints, orderBy("timestamp", "desc"), ); const querySnapshot = await getDocs(q); // Crear arreglo de eventos. // * eventos [] querySnapshot.forEach((doc) => { const data = doc.data(); if (data?.estatus) { eventos.push({ ...data, id: doc.id }); } }); if (eventos.length < 1) { message.info("No hay eventos en el rango de fechas seleccionado."); return; } // Crear arreglo de usuarios. // * usuarios [] usuariosGrupo.forEach((u) => { const tieneFb = u?.facebookVerificado ? 1 : 0; const tieneIg = u?.instagramVerificado ? 1 : 0; const tieneTw = u?.twitterVerificado ? 1 : 0; let usr = { uid: u?.uid, nombre: u?.nombre, tipo: `${tieneFb + tieneTw + tieneIg} RRSS`, redesActivas: tieneFb + tieneTw + tieneIg, tieneFb, tieneTw, tieneIg, facebook: tieneFb ? u?.facebook : "", instagram: tieneIg ? u?.instagram : "", twitter: tieneTw ? u?.twitter : "", verificado: u?.verificado !== "" ? "Verificado" : "", }; usuarios.push(usr); }); let columnasExcel = [ { title: "UID", key: "uid" }, { title: "Nombre", key: "nombre" }, { title: "Tipo", key: "tipo" }, { title: "Facebook", key: "facebook" }, { title: "Instagram", key: "instagram" }, { title: "Twitter", key: "twitter" }, { title: "Verificado", key: "verificado" }, ]; // * columnasExcel [] let totalEventos = { Twitter: 0, Facebook: 0, Instagram: 0, }; eventos.forEach((e) => { const fecha = moment(e?.timestamp?.toDate()).format("DD-MM-YYYY"); let red = ""; if (e?.redSocial === "Twitter") { red = "TW"; } else if (e?.redSocial === "Facebook") { red = "FB"; } else if (e?.redSocial === "Instagram") { red = "INS"; } totalEventos[e?.redSocial] += 1; columnasExcel.push({ title: `${red} - ${fecha}`, key: `${e?.id}` }); }); const usuariosExcel = []; let arrResultados = {}; usuarios.forEach((u) => { const uid = u?.uid; columnasExcel.forEach((c) => { if ( c?.key === "nombre" || c?.key === "uid" || c?.key === "tipo" || c?.key === "facebook" || c?.key === "instagram" || c?.key === "twitter" || c?.key === "verificado" ) return true; if (!arrResultados[uid]) { arrResultados[uid] = {}; } const evento = eventos?.find((e) => e?.id === c?.key); let flag = false; if (evento?.redSocial === "Instagram" && u?.tieneIg) { flag = true; } if (evento?.redSocial === "Facebook" && u?.tieneFb) { flag = true; } if (evento?.redSocial === "Twitter" && u?.tieneTw) { flag = true; } arrResultados[uid][c?.key] = flag && evento?.resultado[uid]?.length > 0 ? 1 : 0; }); usuariosExcel.push({ ...u, totalFb: u?.tieneFb && totalEventos.Facebook, totalTw: u?.tieneTw && totalEventos.Twitter, totalIg: u?.tieneIg && totalEventos.Instagram, }); }); // * return dataExcel [] // Contamos participaciones (arreglo de usuarios) for (let i = 0; i < usuariosExcel.length; i++) { const resEvento = Object.keys(arrResultados[usuariosExcel[i]?.uid]).map( (key) => [key, arrResultados[usuariosExcel[i]?.uid][key]], ); // Contamos let z = 0; for (let r = 0, l = resEvento?.length; r < l; r++) { z += arrResultados[usuariosExcel[i]?.uid][resEvento[r][0]]; } const totalParticipacion = usuariosExcel[i]?.totalFb + usuariosExcel[i]?.totalIg + usuariosExcel[i]?.totalTw; const participacion = isNaN(z / totalParticipacion) ? 0 : z / totalParticipacion; const obj = Object.assign( { ...usuariosExcel[i], participo: z, participaEn: totalParticipacion, participacion: participacion, }, arrResultados[usuariosExcel[i]?.uid], ); dataExcel.push(obj); } columnasExcel.push({ title: "Participando", key: "participaEn" }); columnasExcel.push({ title: "Particip贸", key: "participo" }); columnasExcel.push({ title: "Total", key: "participacion" }); await excelCondensado( columnasExcel, dataExcel, totalEventos, eventos?.length, `Reporte condensado ${fechas[0].format("DD-MM-YYYY")}-${fechas[1].format("DD-MM-YYYY")}`, `Condensado de participaci贸n`, `Inicio: ${fechas[0].format("DD-MM-YYYY")} Fin:${fechas[1].format("DD-MM-YYYY")}`, "/LAUD-Logotipo.png", "", ); } catch (error) { console.log("error al generar reporte consendado: ", error); } finally { setGuardando({ ...guardando, condensado: false }); } }; // Obtener grupo useEffect(() => { let mounted = true; if (mounted && editando) { try { setTimeout(async () => { const docRef = doc(firestore, "gruposEvento", id); const docSnap = await getDoc(docRef); setGrupoEvento(docSnap.data()); }, 0); } catch (error) { console.log("error al obtener evento: ", error); } finally { setCargandoEvento(false); } } return () => (mounted = false); }, [editando, id]); // Obtener eventos del grupo useEffect(() => { let mounted = true; if (mounted && editando) { try { setTimeout(async () => { const q = firebaseQuery( collection(firestore, "eventos"), where("tag", "==", tag), ); const querySnapshot = await getDocs(q); const docs = []; querySnapshot.forEach((doc) => { docs.push({ ...doc.data(), id: doc.id, }); }); setEventos(docs); }, 0); } catch (error) { console.log("error al obtener evento: ", error); } finally { setCargandoEvento(false); } } return () => (mounted = false); }, [editando, tag]); useEffect(() => { let mounted = true; if (mounted && grupoEvento && editando) { setPreviaImg(grupoEvento?.pathFirebase); form.setFieldsValue({ ...grupoEvento, fechaFinal: moment(grupoEvento?.fechaFinal), fechaInicio: moment(grupoEvento?.fechaInicio), }); } return () => (mounted = false); }, [editando, grupoEvento, form]); if (cargandoEvento) return ; return ( <> {/* Modal Procesar */} { if (textAreaData === "") { message.warning({ content: "Atenci贸n: no dejar vacio", }); return; } procesarUsuarios(); guardarRegistro(); }} onCancel={() => { setVisible(false); }} width={1000} > setTextAreaData(e.target.value)} placeholder="Pegue el texto aqui" rows={6} /> {/* Modal Generar Reporte */} { reporteCondesado(); }} onCancel={() => { setVisibleReporte(false); }} okButtonProps={{ loading: guardando.condensado }} width={500} > {guardando.condensado && } {/* Imagen - Nombre - Ciudad - Descripci贸n - Url - Red social */} {/* Columna 1 */} {previaImg ? ( ) : null} {/* Columna 2 */} {/* Nombre evento - Ciuad */} {/* Descripci贸n */} {/* Fecha de inicio - Fecha fin - sin fecha - Accion */} {acciones?.map((item) => ( {item?.icon} {item?.label} ))} {/* Redes sociales */} {eventos.map((e, index) => ( { setVisible(true); setEvento(e); }} icon={} > Procesar , history.push( urlweb + "/detalle?id=" + e?.id + "&tag=" + e?.tag, ) } icon={} > Editar , history.push( urlweb + "/resultado-grupo-evento?id=" + e?.id + "&tag=" + e?.tag, ) } icon={} > Resultados , ]} > } title={ abrirPublicacion(e)}> Abrir publicaci贸n obtenerEnlaceYager(e)}> Enlace Laud } /> ))} > ); }; export default EventoDetalleGrupo;