From e18c1c120b8006b471caf83e6e9fa2683747b46a Mon Sep 17 00:00:00 2001 From: David Frassi Date: Wed, 20 May 2026 16:17:34 +0200 Subject: [PATCH] =?UTF-8?q?feat:=20integrazione=20scalette=20comunit=C3=A0?= =?UTF-8?q?=20come=20playlist?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Aggiunto il parsing di lista_nome e lista_esecuzione dall'API parrocchiale in ComunitaService. - Le scalette vengono trasformate in ComunitaScaletta[] e persistite in localStorage. - PlaylistService espone comunitaPlaylists (computed) e allPlaylists (computed che unisce playlist personali e scalette comunità). - Le scalette della comunità appaiono nel dropdown Playlist SOLO quando il filtro comunità è attivo; scompaiono automaticamente alla disattivazione. - Le scalette sono read-only: i pulsanti Modifica e Elimina vengono nascosti per le playlist della comunità. - Icona people-outline e bordo sinistro secondario distinguono visivamente le scalette della comunità dalle playlist personali. --- src/app/home/home.page.html | 14 ++++---- src/app/home/home.page.scss | 11 +++++++ src/app/home/home.page.ts | 5 +++ src/app/services/comunita.service.ts | 48 ++++++++++++++++++++++++++++ src/app/services/playlist.service.ts | 28 +++++++++++++++- src/app/version.ts | 2 +- 6 files changed, 100 insertions(+), 8 deletions(-) diff --git a/src/app/home/home.page.html b/src/app/home/home.page.html index a524c88..436264b 100644 --- a/src/app/home/home.page.html +++ b/src/app/home/home.page.html @@ -115,11 +115,11 @@ {{ playlistService.activeListName() !== null ? playlistService.activeListName() : 'Playlist' }} - - + + @@ -160,23 +160,25 @@
- + - +
+ {{ activeFilterType() === 'playlist' ? item.name : item.tag_name }}
diff --git a/src/app/home/home.page.scss b/src/app/home/home.page.scss index 0683338..13b6dd5 100644 --- a/src/app/home/home.page.scss +++ b/src/app/home/home.page.scss @@ -355,6 +355,17 @@ ion-title { font-weight: 600; border-color: var(--ion-color-secondary); } + + &.comunita-chip { + display: inline-flex; + align-items: center; + border-left: 3px solid rgba(var(--ion-color-secondary-rgb), 0.6); + background: rgba(var(--ion-color-secondary-rgb), 0.08); + + &.active { + border-left-color: #000; + } + } } // Custom Item Layout diff --git a/src/app/home/home.page.ts b/src/app/home/home.page.ts index 96ad8e0..b612ef4 100644 --- a/src/app/home/home.page.ts +++ b/src/app/home/home.page.ts @@ -854,6 +854,11 @@ export class HomePage implements OnDestroy { this.isAddingSongs.set(false); } + isComunitaPlaylist(): boolean { + const id = this.playlistService.activePlaylistId(); + return !!id && id.startsWith('comunita_'); + } + clearSpecialList(event?: Event) { if (event) event.stopPropagation(); this.playlistService.activeListIds.set([]); diff --git a/src/app/services/comunita.service.ts b/src/app/services/comunita.service.ts index 32952ee..f35f2fa 100644 --- a/src/app/services/comunita.service.ts +++ b/src/app/services/comunita.service.ts @@ -23,6 +23,13 @@ export interface CantiSettingsItem { tonalita: number; } +export interface ComunitaScaletta { + id: string; + name: string; + date: string; + ids: string[]; +} + export interface GetAllAppTablesResponse { parrocchia?: { data: ParrocchiaItem[] }; parrocchia_canti?: { data: ParrocchiaCantiItem[] }; @@ -43,6 +50,7 @@ export class ComunitaService { public comunitaCantiInfo = signal([]); public comunitaCantiSettings = signal([]); public comunitaCantiPersonali = signal([]); + public comunitaScalette = signal([]); public isFilterActive = signal(false); public loading = signal(false); public loadingProgress = signal(0); @@ -55,6 +63,7 @@ export class ComunitaService { const savedInfo = localStorage.getItem('comunita-canti-info'); const savedSettings = localStorage.getItem('comunita-canti-settings'); const savedCantiPersonali = localStorage.getItem('comunita-canti-personali'); + const savedScalette = localStorage.getItem('comunita-scalette'); const savedFilterActive = localStorage.getItem('comunita-filter-active') === 'true'; if (savedCode) { @@ -85,6 +94,9 @@ export class ComunitaService { if (savedCantiPersonali) { try { this.comunitaCantiPersonali.set(JSON.parse(savedCantiPersonali)); } catch (e) {} } + if (savedScalette) { + try { this.comunitaScalette.set(JSON.parse(savedScalette)); } catch (e) {} + } this.isFilterActive.set(savedFilterActive); effect(() => { @@ -95,6 +107,7 @@ export class ComunitaService { localStorage.setItem('comunita-canti-info', JSON.stringify(this.comunitaCantiInfo())); localStorage.setItem('comunita-canti-settings', JSON.stringify(this.comunitaCantiSettings())); localStorage.setItem('comunita-canti-personali', JSON.stringify(this.comunitaCantiPersonali())); + localStorage.setItem('comunita-scalette', JSON.stringify(this.comunitaScalette())); localStorage.setItem('comunita-filter-active', this.isFilterActive().toString()); }); @@ -143,6 +156,7 @@ export class ComunitaService { this.comunitaCantiInfo.set([]); this.comunitaCantiSettings.set([]); this.comunitaCantiPersonali.set([]); + this.comunitaScalette.set([]); this.isFilterActive.set(false); return true; } @@ -182,6 +196,39 @@ export class ComunitaService { this.comunitaCantiIds.set(cantiList.map(c => c.id_canti)); this.comunitaCantiSettings.set(settingsList); this.comunitaCantiPersonali.set(mappedCantiPersonali); + + // Parse scalette (setlists) from lista_nome + lista_esecuzione + const listaNomelList = (data as any).lista_nome?.data || []; + const listaEsecuzioneList = (data as any).lista_esecuzione?.data || []; + + // Group lista_esecuzione by id_lista and keep order by progr + const esecuzioniByLista = new Map(); + for (const item of listaEsecuzioneList) { + if (!esecuzioniByLista.has(item.id_lista)) { + esecuzioniByLista.set(item.id_lista, []); + } + esecuzioniByLista.get(item.id_lista)!.push({ + id_canti: String(item.id_canti), + progr: Number(item.progr) || 0 + }); + } + + // Build scalette array sorted by date (most recent first) + const scalette: ComunitaScaletta[] = listaNomelList + .map((ln: any) => { + const songs = esecuzioniByLista.get(ln.id_lista) || []; + songs.sort((a: any, b: any) => a.progr - b.progr); + return { + id: `comunita_${ln.id_lista}`, + name: ln.nome || 'Scaletta', + date: ln.progr || '', + ids: songs.map((s: any) => s.id_canti) + }; + }) + .filter((s: ComunitaScaletta) => s.ids.length > 0) + .sort((a: ComunitaScaletta, b: ComunitaScaletta) => b.date.localeCompare(a.date)); + + this.comunitaScalette.set(scalette); this.isFilterActive.set(true); this.loading.set(false); return true; @@ -218,6 +265,7 @@ export class ComunitaService { this.comunitaCantiInfo.set(mockInfo); this.comunitaCantiSettings.set([]); this.comunitaCantiPersonali.set([]); + this.comunitaScalette.set([]); this.isFilterActive.set(true); this.loading.set(false); return true; diff --git a/src/app/services/playlist.service.ts b/src/app/services/playlist.service.ts index fee6ec1..fe46ea5 100644 --- a/src/app/services/playlist.service.ts +++ b/src/app/services/playlist.service.ts @@ -1,6 +1,7 @@ -import { Injectable, signal, inject } from '@angular/core'; +import { Injectable, signal, inject, computed } from '@angular/core'; import { Storage } from '@ionic/storage-angular'; import { Canto, CantiService } from './canti.service'; +import { ComunitaService } from './comunita.service'; import * as QRCode from 'qrcode'; @Injectable({ @@ -9,6 +10,7 @@ import * as QRCode from 'qrcode'; export class PlaylistService { private storage = inject(Storage); private cantiService = inject(CantiService); + private comunitaService = inject(ComunitaService); public selectionMode = signal(false); public selectedIds = signal>(new Set()); @@ -22,6 +24,30 @@ export class PlaylistService { private _storage: Storage | null = null; + // Community scalette exposed as playlists (only when community filter is active) + public comunitaPlaylists = computed(() => { + if (!this.comunitaService.comunitaCode() || !this.comunitaService.isFilterActive()) { + return []; + } + return this.comunitaService.comunitaScalette().map(s => ({ + id: s.id, + name: s.name, + ids: s.ids, + createdAt: s.date, + isComunita: true + })); + }); + + // Merged list: personal playlists + community scalette + public allPlaylists = computed(() => { + const community = this.comunitaPlaylists(); + const personal = this.playlists(); + if (community.length > 0) { + return [...community, ...personal.map(p => ({ ...p, isComunita: false }))]; + } + return personal.map(p => ({ ...p, isComunita: false })); + }); + constructor() { this.init(); } diff --git a/src/app/version.ts b/src/app/version.ts index a2e1727..9094611 100644 --- a/src/app/version.ts +++ b/src/app/version.ts @@ -1 +1 @@ -export const VERSION = '2026.05.20.1245'; +export const VERSION = '2026.05.20.1602';