diff --git a/Dockerfile b/Dockerfile index dc956b5..346187b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -19,6 +19,9 @@ RUN npm run build -- --configuration production # Etapa de producci贸n con nginx FROM nginx:alpine +# Instala curl +RUN apk add --no-cache curl + # Copiar configuraci贸n personalizada de nginx COPY nginx.conf /etc/nginx/nginx.conf diff --git a/src/app/components/home/home.html b/src/app/components/home/home.html index 01eace3..4d2d450 100644 --- a/src/app/components/home/home.html +++ b/src/app/components/home/home.html @@ -1,5 +1,21 @@
- @if (loading()) { + @if (gettingLocation()) { +
+
+

馃搷 Obtenint la teva ubicaci贸...

+
+ } + + @if (locationDenied() && !loading()) { +
+

鈿狅笍 Permisos d'ubicaci贸 denegats. Mostrant el temps de Lli莽脿 d'Amunt.

+ +
+ } + + @if (loading() && !gettingLocation()) {

Carregant informaci贸 meteorol貌gica...

diff --git a/src/app/components/home/home.scss b/src/app/components/home/home.scss index 0c40f7e..08fb11c 100644 --- a/src/app/components/home/home.scss +++ b/src/app/components/home/home.scss @@ -15,6 +15,46 @@ text-align: center; } +.location-denied { + position: fixed; + top: 0; + left: 0; + right: 0; + background: rgba(255, 152, 0, 0.95); + backdrop-filter: blur(10px); + padding: 16px; + text-align: center; + z-index: 1000; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); + + p { + margin: 0 0 12px 0; + font-size: 14px; + font-weight: 500; + } + + .location-button { + padding: 8px 20px; + background: white; + color: #ff9800; + border: none; + border-radius: 20px; + font-size: 14px; + font-weight: 600; + cursor: pointer; + transition: all 0.3s ease; + + &:hover { + transform: scale(1.05); + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2); + } + + &:active { + transform: scale(0.98); + } + } +} + .spinner { width: 50px; height: 50px; diff --git a/src/app/components/home/home.ts b/src/app/components/home/home.ts index ccb2c08..4d4494e 100644 --- a/src/app/components/home/home.ts +++ b/src/app/components/home/home.ts @@ -15,8 +15,8 @@ import { PrediccioHorariaComponent } from '../prediccio-horaria/prediccio-horari styleUrl: './home.scss', }) export class Home implements OnInit { - // Lli莽脿 d'Amunt por defecto - readonly municipiCodi = '081075'; + // Municipio din谩mico seg煤n GPS + municipiCodi = signal('081075'); // Lli莽脿 d'Amunt por defecto municipi = signal(null); prediccioDiaria = signal([]); @@ -25,19 +25,69 @@ export class Home implements OnInit { loading = signal(true); error = signal(null); + gettingLocation = signal(false); + locationDenied = signal(false); constructor(private meteocatService: MeteocatService) {} ngOnInit(): void { - this.loadWeatherData(); + this.getCurrentLocation(); } - loadWeatherData(): void { + getCurrentLocation(): void { + if (!navigator.geolocation) { + console.warn('Geolocalizaci贸n no disponible, usando municipio por defecto'); + this.loadWeatherData(this.municipiCodi()); + return; + } + + this.gettingLocation.set(true); + this.loading.set(true); + + navigator.geolocation.getCurrentPosition( + (position) => { + const lat = position.coords.latitude; + const lon = position.coords.longitude; + + console.log(`Ubicaci贸n GPS obtenida: ${lat}, ${lon}`); + + // Buscar municipio m谩s cercano + this.meteocatService.getMunicipiCercano(lat, lon).subscribe({ + next: (municipi) => { + console.log(`Municipio m谩s cercano: ${municipi.nom} (${municipi.codi})`); + this.municipiCodi.set(municipi.codi); + this.gettingLocation.set(false); + this.loadWeatherData(municipi.codi); + }, + error: (err) => { + console.error('Error al buscar municipio cercano:', err); + this.gettingLocation.set(false); + // Usar municipio por defecto si falla + this.loadWeatherData(this.municipiCodi()); + } + }); + }, + (error) => { + console.warn('Error obteniendo ubicaci贸n:', error.message); + this.gettingLocation.set(false); + this.locationDenied.set(true); + // Usar municipio por defecto si se deniega el permiso + this.loadWeatherData(this.municipiCodi()); + }, + { + enableHighAccuracy: true, + timeout: 10000, + maximumAge: 300000 // Cache de 5 minutos + } + ); + } + + loadWeatherData(codiMunicipi: string): void { this.loading.set(true); this.error.set(null); // Cargar municipio - this.meteocatService.getMunicipiByCode(this.municipiCodi).subscribe({ + this.meteocatService.getMunicipiByCode(codiMunicipi).subscribe({ next: (municipi) => { this.municipi.set(municipi); }, @@ -48,7 +98,7 @@ export class Home implements OnInit { }); // Cargar predicci贸n diaria - this.meteocatService.getPrediccioDiaria(this.municipiCodi).subscribe({ + this.meteocatService.getPrediccioDiaria(codiMunicipi).subscribe({ next: (prediccions) => { this.prediccioDiaria.set(prediccions); }, @@ -59,7 +109,7 @@ export class Home implements OnInit { }); // Cargar predicci贸n horaria - this.meteocatService.getPrediccioHoraria(this.municipiCodi).subscribe({ + this.meteocatService.getPrediccioHoraria(codiMunicipi).subscribe({ next: (prediccions) => { // Filtrar solo predicciones desde la hora actual y limitamos a 48 horas const now = new Date(); @@ -81,7 +131,7 @@ export class Home implements OnInit { }); // Cargar estaci贸n XEMA m谩s cercana - this.meteocatService.getEstacioCercana(this.municipiCodi).subscribe({ + this.meteocatService.getEstacioCercana(codiMunicipi).subscribe({ next: (response) => { this.estacioInfo.set(response); }, @@ -111,6 +161,13 @@ export class Home implements OnInit { } refresh(): void { - this.loadWeatherData(); + // Recargar datos con el municipio actual + this.loadWeatherData(this.municipiCodi()); + } + + requestLocation(): void { + // Solicitar ubicaci贸n nuevamente + this.locationDenied.set(false); + this.getCurrentLocation(); } } diff --git a/src/app/services/meteocat.service.ts b/src/app/services/meteocat.service.ts index 692726c..fcf7237 100644 --- a/src/app/services/meteocat.service.ts +++ b/src/app/services/meteocat.service.ts @@ -30,6 +30,13 @@ export class MeteocatService { return this.http.get(`${this.apiUrl}/municipis/search`, { params }); } + getMunicipiCercano(lat: number, lon: number): Observable { + const params = new HttpParams() + .set('lat', lat.toString()) + .set('lon', lon.toString()); + return this.http.get(`${this.apiUrl}/municipis/cercano`, { params }); + } + // === PREDICCIONS === getPrediccioDiaria(municipiCodi: string): Observable {