first commit
This commit is contained in:
@@ -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>
|
||||
</>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user