first commit

This commit is contained in:
2026-07-16 20:48:43 -03:00
commit 5696cee264
1111 changed files with 322270 additions and 0 deletions
@@ -0,0 +1,286 @@
"use client";
import { useEffect, useState } from "react";
import API from "@services/Api.Service";
import { useSessionStore } from "@core/Store/Sesion.Store";
import { useAlert } from "@store/Alert.Store";
export default function CheckPendingInvitations() {
const SessionInfo = useSessionStore();
const alert = useAlert();
const [isChecking, setIsChecking] = useState(false);
const [pendingOrg, setPendingOrg] = useState<any>(null);
const [isProcessing, setIsProcessing] = useState(false);
const checkInvitations = async () => {
if (!SessionInfo.userId || isChecking) return;
setIsChecking(true);
try {
const response = await API.post<any[]>("companies/get-by-user", { sessionUser: SessionInfo.userId });
const orgs = response || [];
// Buscar la primera organización donde la invitación esté pendiente de aceptación por parte del usuario
const foundOrg = orgs.find(org => org.guestOk === false);
if (foundOrg) {
setPendingOrg(foundOrg);
} else {
setPendingOrg(null);
}
} catch (error) {
console.error("Error comprobando invitaciones:", error);
} finally {
setIsChecking(false);
}
};
useEffect(() => {
if (SessionInfo.userId) {
checkInvitations();
}
}, [SessionInfo.userId]);
const handleAccept = async () => {
if (!pendingOrg || isProcessing) return;
setIsProcessing(true);
try {
await API.post("employees/validate-guest", {
employeeId: pendingOrg.employeeId,
sessionUser: SessionInfo.userId
});
alert.showSuccess("¡Invitación aceptada exitosamente!");
setPendingOrg(null);
setTimeout(() => checkInvitations(), 1000);
} catch (e: any) {
alert.showError(e.message || "Ocurrió un error al aceptar");
} finally {
setIsProcessing(false);
}
};
const handleReject = async () => {
if (!pendingOrg || isProcessing) return;
setIsProcessing(true);
try {
await API.post("employees/reject-guest", {
employeeId: pendingOrg.employeeId,
sessionUser: SessionInfo.userId
});
alert.showInfo("Invitación rechazada.");
setPendingOrg(null);
setTimeout(() => checkInvitations(), 1000);
} catch (e: any) {
alert.showError(e.message || "Ocurrió un error al rechazar");
} finally {
setIsProcessing(false);
}
};
const handleLater = () => {
setPendingOrg(null);
};
if (!pendingOrg) return <></>;
return (
<>
<style>{`
@keyframes slideUpFade {
from { opacity: 0; transform: translate(-50%, 20px) scale(0.95); }
to { opacity: 1; transform: translate(-50%, 0) scale(1); }
}
@keyframes floatParticle {
0% { transform: translateY(0) scale(1); opacity: 0; }
50% { opacity: 0.8; transform: translateY(-20px) scale(1.2); }
100% { transform: translateY(-40px) scale(0.8); opacity: 0; }
}
`}</style>
{/* Overlay */}
<div style={{
position: 'fixed',
top: 0, left: 0, right: 0, bottom: 0,
backgroundColor: 'rgba(255, 255, 255, 0.4)',
backdropFilter: 'blur(8px)',
zIndex: 10000,
display: 'flex',
alignItems: 'center',
justifyContent: 'center'
}}>
{/* Modal Container */}
<div style={{
position: 'absolute',
top: '30%',
left: '50%',
transform: 'translate(-50%, 0)',
width: '90%',
maxWidth: '420px',
backgroundColor: '#ffffff',
borderRadius: '24px',
boxShadow: '0 20px 40px rgba(0,0,0,0.1), 0 0 0 1px rgba(0,0,0,0.05), 0 0 40px rgba(255, 65, 108, 0.1)',
padding: '32px 24px',
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
animation: 'slideUpFade 0.5s cubic-bezier(0.16, 1, 0.3, 1) forwards',
overflow: 'hidden'
}}>
{/* Decorative Background Elements */}
<div style={{ position: 'absolute', top: '-50px', right: '-50px', width: '150px', height: '150px', background: 'radial-gradient(circle, var(--wine-lighterX2) 0%, transparent 70%)', borderRadius: '50%' }} />
<div style={{ position: 'absolute', bottom: '-50px', left: '-50px', width: '150px', height: '150px', background: 'radial-gradient(circle, var(--wine-lighterX2) 0%, transparent 70%)', borderRadius: '50%' }} />
{/* Particles */}
<div style={{ position: 'absolute', top: '20px', left: '20%', width: '8px', height: '8px', borderRadius: '50%', background: 'var(--wine-light)', animation: 'floatParticle 3s infinite ease-in-out' }} />
<div style={{ position: 'absolute', top: '40px', right: '20%', width: '6px', height: '6px', borderRadius: '50%', background: 'var(--wine-dark)', animation: 'floatParticle 4s infinite ease-in-out 1s' }} />
<div style={{ position: 'absolute', top: '60px', left: '80%', width: '10px', height: '10px', borderRadius: '50%', background: 'var(--wine-lighter)', animation: 'floatParticle 3.5s infinite ease-in-out 0.5s' }} />
{/* Icon */}
<div style={{
width: '64px',
height: '64px',
borderRadius: '16px',
background: 'linear-gradient(135deg, var(--wine-dark) 0%, var(--wine-light) 100%)',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
marginBottom: '20px',
boxShadow: '0 8px 16px var(--wine-lighterX2)',
position: 'relative',
zIndex: 1
}}>
<span style={{ fontSize: '32px', color: '#fff' }}></span>
</div>
<h2 style={{
fontSize: '24px',
fontWeight: '700',
color: '#1a1a1a',
textAlign: 'center',
marginBottom: '12px',
position: 'relative',
zIndex: 1
}}>
¡Tienes una nueva invitación!
</h2>
<p style={{
fontSize: '15px',
color: '#666',
textAlign: 'center',
marginBottom: '24px',
lineHeight: '1.5',
position: 'relative',
zIndex: 1
}}>
Has sido invitado a formar parte del equipo de colaboradores en:
</p>
{/* Company Card */}
<div style={{
width: '100%',
padding: '16px',
backgroundColor: '#f8f9fa',
borderRadius: '12px',
border: '1px solid #eaeaea',
display: 'flex',
alignItems: 'center',
marginBottom: '32px',
position: 'relative',
zIndex: 1
}}>
<div style={{
width: '40px',
height: '40px',
borderRadius: '50%',
backgroundColor: '#e2e8f0',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
marginRight: '16px',
color: '#64748b',
fontWeight: 'bold',
fontSize: '16px'
}}>
{pendingOrg.name.charAt(0).toUpperCase()}
</div>
<div>
<div style={{ fontWeight: '600', color: '#1e293b', fontSize: '16px' }}>{pendingOrg.name}</div>
<div style={{ fontSize: '13px', color: '#64748b' }}>Nueva Oportunidad</div>
</div>
</div>
{/* Buttons */}
<div style={{ display: 'flex', flexDirection: 'column', width: '100%', gap: '12px', position: 'relative', zIndex: 1 }}>
<button
onClick={handleAccept}
disabled={isProcessing}
style={{
width: '100%',
padding: '14px',
borderRadius: '12px',
background: 'linear-gradient(135deg, var(--wine-dark) 0%, var(--wine-light) 100%)',
color: '#fff',
border: 'none',
fontWeight: '600',
fontSize: '16px',
cursor: isProcessing ? 'not-allowed' : 'pointer',
boxShadow: '0 4px 12px var(--wine-lighterX2)',
transition: 'transform 0.2s, box-shadow 0.2s',
opacity: isProcessing ? 0.8 : 1
}}
onMouseOver={e => e.currentTarget.style.transform = 'translateY(-2px)'}
onMouseOut={e => e.currentTarget.style.transform = 'translateY(0)'}
>
{isProcessing ? 'Procesando...' : 'Aceptar Invitación'}
</button>
<div style={{ display: 'flex', gap: '12px' }}>
<button
onClick={handleReject}
disabled={isProcessing}
style={{
flex: 1,
padding: '12px',
borderRadius: '12px',
backgroundColor: 'transparent',
color: '#64748b',
border: '1px solid #cbd5e1',
fontWeight: '500',
fontSize: '14px',
cursor: isProcessing ? 'not-allowed' : 'pointer',
transition: 'all 0.2s'
}}
onMouseOver={e => { e.currentTarget.style.color = 'var(--wine-dark)'; e.currentTarget.style.borderColor = 'var(--wine-dark)'; }}
onMouseOut={e => { e.currentTarget.style.color = '#64748b'; e.currentTarget.style.borderColor = '#cbd5e1'; }}
>
Rechazar
</button>
<button
onClick={handleLater}
disabled={isProcessing}
style={{
flex: 1,
padding: '12px',
borderRadius: '12px',
backgroundColor: '#f1f5f9',
color: '#475569',
border: 'none',
fontWeight: '500',
fontSize: '14px',
cursor: isProcessing ? 'not-allowed' : 'pointer',
transition: 'background-color 0.2s'
}}
onMouseOver={e => e.currentTarget.style.backgroundColor = '#e2e8f0'}
onMouseOut={e => e.currentTarget.style.backgroundColor = '#f1f5f9'}
>
Más tarde
</button>
</div>
</div>
</div>
</div>
</>
);
}