feat: sincronización avanzada SIU por código ASIG, perfil con foto/nombre de Moodle y refinamiento visual violeta

This commit is contained in:
Carlos Tello
2026-03-29 23:03:40 -03:00
parent 490bf2355b
commit 678cc9898f
13 changed files with 972 additions and 223 deletions
+184
View File
@@ -0,0 +1,184 @@
import { Component, OnInit, OnDestroy } from '@angular/core';
import { ToastController, LoadingController, AlertController, NavController } from '@ionic/angular';
import { AuthService, AuthState } from '../services/auth.service';
import { SiuService } from '../services/siu-guarani.service';
import { CredencialService } from '../services/credencial.service';
import { LocalStorageService, AppData } from '../services/local-storage.service';
import { Subscription } from 'rxjs';
@Component({
selector: 'app-perfil',
templateUrl: './perfil.page.html',
styleUrls: ['./perfil.page.scss'],
standalone: false
})
export class PerfilPage implements OnInit, OnDestroy {
authState: AuthState | null = null;
private authSub: Subscription | null = null;
// Form states
siuDni: string = '';
siuPass: string = '';
showSiuPass: boolean = false;
moodleDni: string = '';
moodlePass: string = '';
showMoodlePass: boolean = false;
loading: boolean = false;
constructor(
private authService: AuthService,
private siuService: SiuService,
private credencialService: CredencialService,
private localStorageService: LocalStorageService,
private toastCtrl: ToastController,
private loadingCtrl: LoadingController,
private alertCtrl: AlertController,
private navCtrl: NavController
) { }
ngOnInit() {
this.authSub = this.authService.authState$.subscribe(state => {
this.authState = state;
// Pre-fill DNI if already connected
if (state.siuConnected && !this.siuDni) this.siuDni = state.siuDni || '';
if (state.moodleConnected && !this.moodleDni) this.moodleDni = state.moodleDni || '';
});
}
ngOnDestroy() {
if (this.authSub) this.authSub.unsubscribe();
}
async loginSiu() {
if (!this.siuDni || !this.siuPass) {
this.showToast('Por favor, ingresá DNI y Contraseña', 'warning');
return;
}
const loader = await this.loadingCtrl.create({ message: 'Validando con SIU Guaraní...' });
await loader.present();
try {
const materias = await this.siuService.getAcademicHistory(this.siuDni, this.siuPass);
await this.authService.saveSiuCredentials(this.siuDni, this.siuPass);
// Persistir datos en LocalStorage para que Home los vea
const currentData = await this.localStorageService.loadData() || this.getDefaultData();
currentData.siuMaterias = materias;
currentData.siuLastSync = new Date().toISOString();
// Aplicar auto-favoritos (opcional, pero recomendado para consistencia)
// Nota: Aquí se podría llamar a una versión compartida de autoCompletarDesdeSiu
// Por ahora guardamos para que Home lo procese al volver
await this.localStorageService.saveData(currentData);
this.showToast('¡SIU Guaraní conectado y sincronizado!', 'success');
this.siuPass = '';
} catch (e: any) {
console.error(e);
this.authService.setSiuError(e.message || 'Error de conexión');
this.showToast('Error al conectar con SIU: ' + (e.message || 'Credenciales inválidas'), 'danger');
} finally {
await loader.dismiss();
}
}
async logoutSiu() {
const alert = await this.alertCtrl.create({
header: 'Cerrar Sesión en SIU',
message: '¿Estás seguro de que deseas desconectar tu cuenta de SIU Guaraní? Se borrarán tus credenciales guardadas.',
buttons: [
{ text: 'Cancelar', role: 'cancel' },
{
text: 'Cerrar Sesión',
role: 'destructive',
handler: () => {
this.authService.logoutSiu();
this.siuDni = '';
this.siuPass = '';
}
}
]
});
await alert.present();
}
async loginMoodle() {
if (!this.moodleDni || !this.moodlePass) {
this.showToast('Por favor, ingresá DNI y Contraseña (Campus)', 'warning');
return;
}
const loader = await this.loadingCtrl.create({ message: 'Validando con Campus UNICABA...' });
await loader.present();
try {
// 1. Validar y generar credencial (descarga PDF)
await this.credencialService.generateCredential(this.moodleDni, this.moodlePass);
// 2. Obtener Perfil (Nombre y Foto)
const profile = await this.credencialService.getUserProfile(this.moodleDni, this.moodlePass);
await this.authService.saveUserProfile(profile.name, profile.photo);
// 3. Guardar credenciales de acceso
await this.authService.saveMoodleCredentials(this.moodleDni, this.moodlePass);
this.showToast('¡Perfil sincronizado y Campus conectado!', 'success');
this.moodlePass = '';
} catch (e: any) {
console.error(e);
this.authService.setMoodleError(e.message || 'Error de conexión');
this.showToast('Error al conectar con Campus: ' + (e.message || 'Credenciales inválidas'), 'danger');
} finally {
await loader.dismiss();
}
}
async logoutMoodle() {
const alert = await this.alertCtrl.create({
header: 'Cerrar Sesión en Campus',
message: '¿Estás seguro de que deseas desconectar tu cuenta del Campus? Se borrará tu credencial digital cacheada.',
buttons: [
{ text: 'Cancelar', role: 'cancel' },
{
text: 'Cerrar Sesión',
role: 'destructive',
handler: () => {
this.authService.logoutMoodle();
this.moodleDni = '';
this.moodlePass = '';
}
}
]
});
await alert.present();
}
goBack() {
this.navCtrl.back();
}
private async showToast(message: string, color: 'success' | 'warning' | 'danger') {
const toast = await this.toastCtrl.create({
message,
duration: 3000,
color,
position: 'bottom'
});
await toast.present();
}
private getDefaultData(): AppData {
return {
favoritos: [],
eventos: [],
aprobadas: [],
encurso: [],
optativas: [],
siuMaterias: [],
siuLastSync: null
};
}
}