Primera versión estable v1.1.5 - Aulas UNICABA

This commit is contained in:
2026-03-25 16:50:25 -03:00
commit d3243c0166
143 changed files with 22908 additions and 0 deletions
+142
View File
@@ -0,0 +1,142 @@
<ion-header [translucent]="true">
<ion-toolbar color="secondary">
<div class="header-content">
<img src="assets/logo_unicaba_mini.png" class="header-logo" alt="UNICABA Logo" (click)="openCredencial()"
style="cursor: pointer;" title="Ver Credencial Digital">
<ion-title class="ion-text-center">
Cartelera de Aulas
</ion-title>
<ion-buttons slot="end">
<ion-button (click)="isInfoModalOpen = true">
<ion-icon slot="icon-only" name="information-circle-outline"></ion-icon>
</ion-button>
</ion-buttons>
</div>
</ion-toolbar>
<ion-toolbar color="light" class="ion-no-padding">
<div class="view-segment">
<ion-segment [(ngModel)]="viewMode" (ionChange)="onViewModeChange()" color="primary">
<ion-segment-button value="favoritos">Favoritos</ion-segment-button>
<ion-segment-button value="todas">Cartelera</ion-segment-button>
</ion-segment>
</div>
</ion-toolbar>
<ion-toolbar color="light" class="ion-no-padding" *ngIf="viewMode === 'todas'">
<div class="filter-section">
<ion-searchbar placeholder="Buscar materia, aula o código..." (ionInput)="onSearchChange($event)"
[debounce]="250"></ion-searchbar>
</div>
</ion-toolbar>
</ion-header>
<ion-modal [isOpen]="isInfoModalOpen" (didDismiss)="isInfoModalOpen = false">
<ng-template>
<ion-header>
<ion-toolbar color="primary">
<ion-title>Información y Privacidad</ion-title>
<ion-buttons slot="end">
<ion-button (click)="isInfoModalOpen = false">Cerrar</ion-button>
</ion-buttons>
</ion-toolbar>
</ion-header>
<ion-content class="ion-padding privacy-content">
<h2>¿Qué hace esta aplicación?</h2>
<p><strong>Aulas UNICABA</strong> es un visor especializado e independiente para la cartelera de horarios, aulas y
uso de credencial de la Universidad de la Ciudad.</p>
<ul>
<li>Consulta materias, horarios y aulas rápidamente.</li>
<li>Sigue tus <strong>Favoritos</strong> y recibe <strong>alertas locales</strong> si cambian de aula.</li>
<li><strong>¡NUEVO!</strong> Visualiza tu <strong>Credencial Digital</strong> de estudiante tocando el logo de
la UNICABA en la cabecera.</li>
</ul>
<h2>Credencial Digital (Opcional)</h2>
<p>El inicio de sesión para obtener la credencial es <strong>100% opcional</strong> y completamente independiente
de la cartelera de aulas (que puedes seguir usando sin loguearte).</p>
<p>Tus credenciales (DNI y Clave) se comunican <strong>directamente</strong> con el Campus Virtual (Moodle) para
descargar el PDF de tu código QR, sin pasar por ningún servidor intermediario. Luego, la imagen queda guardada
localmente en tu celular para que puedas mostrarla incluso sin conexión a internet.</p>
<h2>Almacenamiento Seguro y Persistente</h2>
<p>Tus datos son tuyos. Aseguramos que tus materias favoritas se guarden automáticamente en un archivo
<code>.csv</code> seguro dentro de la carpeta "Documentos" de tu dispositivo.
</p>
<p>Gracias a esto, toda tu configuración y datos están a salvo y <strong>sobrevivirán a desinstalaciones</strong>
o actualizaciones de la aplicación sin tener que subirlos a la nube.</p>
<h2>Privacidad Absoluta</h2>
<p><strong>Sin Intermediarios:</strong> No recopilamos nombres, contraseñas, ni correos. Todo el procesamiento se
realiza en la memoria de tu teléfono.</p>
<p><strong>Sin Rastreadores:</strong> No incluimos publicidad, telemetría ni analíticas de terceros.</p>
<p class="ion-text-center"><small>Versión 1.1.5 - 25/03/2026</small></p>
</ion-content>
</ng-template>
</ion-modal>
<ion-content [fullscreen]="true" color="light">
<ion-refresher slot="fixed" (ionRefresh)="doRefresh($event)">
<ion-refresher-content pullingText="Desliza para actualizar" refreshingSpinner="crescent"
refreshingText="Actualizando..."></ion-refresher-content>
</ion-refresher>
<div class="loading-container" *ngIf="loading">
<ion-spinner name="crescent" color="primary"></ion-spinner>
<p>Cargando cartelera...</p>
</div>
<div class="error-state" *ngIf="!loading && errorMsg">
<p>{{ errorMsg }}</p>
</div>
<ion-list *ngIf="!loading && !errorMsg && horariosFiltrados.length > 0">
<ion-card *ngFor="let item of horariosFiltrados" [class.highlight-card]="item.codigo === highlightedCodigo"
class="subject-card">
<ion-card-header>
<div class="card-header-flex">
<div class="header-titles">
<ion-card-subtitle color="primary">{{ item.carrera }}</ion-card-subtitle>
<ion-card-title>{{ item.asignatura }}</ion-card-title>
</div>
<div class="card-actions">
<ion-icon class="share-icon" name="share-social-outline" color="medium"
(click)="shareItem(item)"></ion-icon>
<ion-icon class="fav-icon" [name]="isFavorito(item.codigo) ? 'star' : 'star-outline'"
[color]="isFavorito(item.codigo) ? 'warning' : 'medium'" (click)="toggleFavorito(item)"></ion-icon>
</div>
</div>
</ion-card-header>
<ion-card-content>
<p><strong>Código:</strong> {{ item.codigo }}</p>
<div class="aula-container">
<span class="aula-tag">{{ item.aula }}</span>
</div>
<p class="schedule-text">{{ item.dia }} - {{ item.horario }}</p>
<div *ngIf="item.link" class="link-container">
<ion-button fill="outline" color="primary" size="small" expand="block" (click)="openLink(item.link!)">
<ion-icon slot="start" name="videocam-outline"></ion-icon>
Ingresar a Clase Virtual
</ion-button>
</div>
</ion-card-content>
</ion-card>
</ion-list>
<div class="empty-state" *ngIf="!loading && !errorMsg && horariosFiltrados.length === 0">
<p>No se encontraron horarios para la selección actual.</p>
</div>
</ion-content>
<ion-footer>
<ion-toolbar color="primary" class="ion-no-padding">
<div class="footer-content" (click)="openLink('https://www.google.com/maps/place/UdelaCiudad/data=!4m2!3m1!1s0x0:0x6dab35ab5ab98245?sa=X&ved=1t:2428&ictx=111')" style="cursor: pointer;" title="Mostrar en el mapa">
<div class="footer-text">
<small><ion-icon name="location-outline" style="vertical-align: bottom;"></ion-icon> Tte. Gral. Juan Domingo Perón 802 (C1038AAR)<br />CABA - Argentina</small>
</div>
</div>
</ion-toolbar>
</ion-footer>