166 lines
4.7 KiB
TypeScript
166 lines
4.7 KiB
TypeScript
import { Injectable } from '@angular/core';
|
|
import { Filesystem, Directory, Encoding } from '@capacitor/filesystem';
|
|
import { FilePicker } from '@capawesome/capacitor-file-picker';
|
|
import { EventoAcademico } from './data';
|
|
|
|
|
|
@Injectable({
|
|
providedIn: 'root'
|
|
})
|
|
export class CsvStorageService {
|
|
|
|
private readonly FILE_NAME = 'aulas_unicaba_datos.csv';
|
|
|
|
constructor() {}
|
|
|
|
private async ensurePermissions(): Promise<boolean> {
|
|
try {
|
|
let status = await Filesystem.checkPermissions();
|
|
if (status.publicStorage !== 'granted') {
|
|
status = await Filesystem.requestPermissions();
|
|
}
|
|
return status.publicStorage === 'granted';
|
|
} catch (e) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
async saveUserDataToCsv(favoritos: string[], eventos: EventoAcademico[]) {
|
|
try {
|
|
const hasPermission = await this.ensurePermissions();
|
|
if (!hasPermission) {
|
|
console.warn('Permisos denegados para escribir en Documents');
|
|
return;
|
|
}
|
|
|
|
let csvContent = 'tipo,materia,id_o_valor,extra1,extra2,extra3,extra4\n';
|
|
|
|
// Filas de favoritos
|
|
favoritos.forEach(codigo => {
|
|
csvContent += `favorito,${codigo},,,,\n`;
|
|
});
|
|
|
|
// Filas de eventos
|
|
eventos.forEach(ev => {
|
|
// Formato: evento,CODIGO,ID,TIPO,FECHA,AULA,LINK,NOTAS
|
|
// Para simplificar el CSV sin escapar comas en notas, reemplazamos comas por punto y coma
|
|
const notasEscaped = (ev.notas || '').replace(/,/g, ';');
|
|
csvContent += `evento,${ev.materiaCodigo},${ev.id},${ev.tipo},${ev.fecha},${ev.aula || ''},${ev.link || ''},${notasEscaped}\n`;
|
|
});
|
|
|
|
// Intentamos borrar si existe
|
|
try {
|
|
await Filesystem.deleteFile({
|
|
path: this.FILE_NAME,
|
|
directory: Directory.Documents
|
|
});
|
|
} catch (e) {}
|
|
|
|
await Filesystem.writeFile({
|
|
path: this.FILE_NAME,
|
|
data: csvContent,
|
|
directory: Directory.Documents,
|
|
encoding: Encoding.UTF8
|
|
});
|
|
console.log('CSV con datos de usuario guardado en Documents');
|
|
} catch (e) {
|
|
console.error('Error al guardar el CSV:', e);
|
|
}
|
|
}
|
|
|
|
|
|
async loadUserDataFromCsv(): Promise<{ favoritos: string[], eventos: EventoAcademico[] } | null> {
|
|
try {
|
|
const hasPermission = await this.ensurePermissions();
|
|
if (!hasPermission) return null;
|
|
|
|
const contents = await Filesystem.readFile({
|
|
path: this.FILE_NAME,
|
|
directory: Directory.Documents,
|
|
encoding: Encoding.UTF8
|
|
});
|
|
|
|
if (!contents.data) return null;
|
|
|
|
const lines = contents.data.toString().split('\n');
|
|
const favs: string[] = [];
|
|
const evs: EventoAcademico[] = [];
|
|
|
|
for (let i = 1; i < lines.length; i++) {
|
|
const line = lines[i].trim();
|
|
if (!line) continue;
|
|
|
|
const parts = line.split(',');
|
|
const tipo = parts[0];
|
|
|
|
if (tipo === 'favorito') {
|
|
if (parts.length > 1 && parts[1]) {
|
|
favs.push(parts[1]);
|
|
}
|
|
} else if (tipo === 'evento') {
|
|
// evento,materia,id,tipo_ev,fecha,aula,link,notas
|
|
if (parts.length >= 5) {
|
|
evs.push({
|
|
materiaCodigo: parts[1],
|
|
id: parts[2],
|
|
tipo: parts[3] as any,
|
|
fecha: parts[4],
|
|
aula: parts[5] || '',
|
|
link: parts[6] || '',
|
|
notas: (parts[7] || '').replace(/;/g, ',')
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
return { favoritos: favs, eventos: evs };
|
|
} catch (e) {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
|
|
async importFavoritesFromFilePicker(): Promise<string[] | null> {
|
|
try {
|
|
const result = await FilePicker.pickFiles({
|
|
types: ['text/csv', 'text/comma-separated-values', '.csv'],
|
|
readData: true
|
|
});
|
|
|
|
const file = result.files[0];
|
|
if (!file || !file.data) return null;
|
|
|
|
const text = decodeURIComponent(escape(window.atob(file.data)));
|
|
|
|
const lines = text.split('\n');
|
|
const favs: string[] = [];
|
|
|
|
for (let i = 1; i < lines.length; i++) {
|
|
const line = lines[i].trim();
|
|
if (!line) continue;
|
|
|
|
const parts = line.split(',');
|
|
const tipo = parts[0];
|
|
|
|
if (tipo === 'favorito') {
|
|
if (parts.length > 1 && parts[1]) {
|
|
favs.push(parts[1]);
|
|
}
|
|
}
|
|
// Nota: para el Picker manual solo recuperamos favoritos por ahora para simplicidad,
|
|
// o podríamos reusar la lógica de loadUserDataFromCsv si el CSV es idéntico.
|
|
}
|
|
|
|
if (favs.length > 0) {
|
|
await this.saveUserDataToCsv(favs, []);
|
|
return favs;
|
|
}
|
|
|
|
return null;
|
|
} catch(e) {
|
|
console.warn('File picker cancelado o falló', e);
|
|
return null;
|
|
}
|
|
}
|
|
}
|