feat: add TypeScript definitions and utility functions for date formatting
- Created a global TypeScript declaration for the txadmin interface on the Window object. - Implemented date formatting utilities using date-fns with Spanish locale support. - Added TypeScript configuration files for app, Electron, and Node environments. - Set up Vite configuration for React application.
This commit is contained in:
@@ -0,0 +1,127 @@
|
||||
import React, { useState } from 'react';
|
||||
import { motion } from 'framer-motion';
|
||||
import { X } from 'lucide-react';
|
||||
import { updateUserProfile, setVerifiedStatus } from '../../api/sysadmin';
|
||||
|
||||
export const EditUserModal = ({ user, onClose, onSaved }: { user: any, onClose: () => void, onSaved: () => void }) => {
|
||||
const [formData, setFormData] = useState({
|
||||
firstName: user.firstName || '',
|
||||
lastName: user.lastName || '',
|
||||
street: user.street || '',
|
||||
streetNumber: user.streetNumber || '',
|
||||
city: user.city || '',
|
||||
state: user.state || '',
|
||||
country: user.country || '',
|
||||
phoneCountryCode: user.phoneCountryCode || '',
|
||||
phoneAreaCode: user.phoneAreaCode || '',
|
||||
phoneNumber: user.phoneNumber || '',
|
||||
verificated: user.verificated || false,
|
||||
});
|
||||
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
const handleSubmit = async (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
setLoading(true);
|
||||
try {
|
||||
const promises: Promise<any>[] = [
|
||||
updateUserProfile({ userId: user._id, ...formData })
|
||||
];
|
||||
if (formData.verificated !== user.verificated) {
|
||||
promises.push(setVerifiedStatus(user._id, formData.verificated));
|
||||
}
|
||||
await Promise.all(promises);
|
||||
onSaved();
|
||||
onClose();
|
||||
} catch (err) {
|
||||
alert('Error guardando perfil');
|
||||
}
|
||||
setLoading(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<div style={{ position: 'fixed', inset: 0, zIndex: 50, display: 'flex', alignItems: 'center', justifyContent: 'center', background: 'rgba(0,0,0,0.5)', backdropFilter: 'blur(4px)' }}>
|
||||
<motion.div
|
||||
initial={{ scale: 0.9, opacity: 0 }}
|
||||
animate={{ scale: 1, opacity: 1 }}
|
||||
className="glass-panel"
|
||||
style={{ width: '90%', maxWidth: '600px', maxHeight: '90vh', overflowY: 'auto', padding: '2rem', position: 'relative' }}
|
||||
>
|
||||
<button onClick={onClose} style={{ position: 'absolute', top: '1.5rem', right: '1.5rem', background: 'transparent', color: 'var(--text-muted)' }}>
|
||||
<X size={24} />
|
||||
</button>
|
||||
|
||||
<h2 style={{ fontSize: '1.5rem', marginBottom: '1.5rem' }}>Editar Perfil: {user.email}</h2>
|
||||
|
||||
<form onSubmit={handleSubmit} style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '1rem' }}>
|
||||
<div>
|
||||
<label className="modal-label">Nombre</label>
|
||||
<input className="input-glass" value={formData.firstName} onChange={e => setFormData({...formData, firstName: e.target.value})} />
|
||||
</div>
|
||||
<div>
|
||||
<label className="modal-label">Apellido</label>
|
||||
<input className="input-glass" value={formData.lastName} onChange={e => setFormData({...formData, lastName: e.target.value})} />
|
||||
</div>
|
||||
|
||||
<div style={{ gridColumn: '1 / -1', display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
|
||||
<h3 style={{ margin: '1rem 0 0.5rem', color: 'var(--primary)', fontSize: '1.1rem' }}>Contacto</h3>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setFormData({...formData, verificated: !formData.verificated})}
|
||||
className="btn-secondary"
|
||||
style={{ display: 'flex', alignItems: 'center', gap: '8px', color: formData.verificated ? 'var(--success)' : 'var(--warning)', padding: '4px 12px' }}
|
||||
>
|
||||
{formData.verificated ? 'Usuario Verificado' : 'Usuario No Verificado'}
|
||||
</button>
|
||||
</div>
|
||||
<div>
|
||||
<label className="modal-label">Cód. País</label>
|
||||
<input className="input-glass" value={formData.phoneCountryCode} onChange={e => setFormData({...formData, phoneCountryCode: e.target.value})} />
|
||||
</div>
|
||||
<div>
|
||||
<label className="modal-label">Cód. Área</label>
|
||||
<input className="input-glass" value={formData.phoneAreaCode} onChange={e => setFormData({...formData, phoneAreaCode: e.target.value})} />
|
||||
</div>
|
||||
<div style={{ gridColumn: '1 / -1' }}>
|
||||
<label className="modal-label">Teléfono</label>
|
||||
<input className="input-glass" value={formData.phoneNumber} onChange={e => setFormData({...formData, phoneNumber: e.target.value})} />
|
||||
</div>
|
||||
|
||||
<div style={{ gridColumn: '1 / -1' }}>
|
||||
<h3 style={{ margin: '1rem 0 0.5rem', color: 'var(--primary)', fontSize: '1.1rem' }}>Dirección</h3>
|
||||
</div>
|
||||
<div>
|
||||
<label className="modal-label">Calle</label>
|
||||
<input className="input-glass" value={formData.street} onChange={e => setFormData({...formData, street: e.target.value})} />
|
||||
</div>
|
||||
<div>
|
||||
<label className="modal-label">Número</label>
|
||||
<input className="input-glass" value={formData.streetNumber} onChange={e => setFormData({...formData, streetNumber: e.target.value})} />
|
||||
</div>
|
||||
<div>
|
||||
<label className="modal-label">Ciudad</label>
|
||||
<input className="input-glass" value={formData.city} onChange={e => setFormData({...formData, city: e.target.value})} />
|
||||
</div>
|
||||
<div>
|
||||
<label className="modal-label">País</label>
|
||||
<input className="input-glass" value={formData.country} onChange={e => setFormData({...formData, country: e.target.value})} />
|
||||
</div>
|
||||
|
||||
<div style={{ gridColumn: '1 / -1', marginTop: '1.5rem', display: 'flex', justifyContent: 'flex-end', gap: '1rem' }}>
|
||||
<button type="button" className="btn-secondary" onClick={onClose}>Cancelar</button>
|
||||
<button type="submit" className="btn-primary" disabled={loading}>{loading ? 'Guardando...' : 'Guardar Cambios'}</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<style dangerouslySetInnerHTML={{__html: `
|
||||
.modal-label {
|
||||
display: block;
|
||||
font-size: 0.85rem;
|
||||
color: var(--text-muted);
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
`}} />
|
||||
</motion.div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user