import { useState } from "react"; import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { Switch } from "@/components/ui/switch"; import { AlertCircle, CheckCircle, Cloud, Settings, MapPin, Loader2 } from "lucide-react"; import { Alert, AlertDescription } from "@/components/ui/alert"; import { useToast } from "@/hooks/use-toast"; import { apiRequest } from "@/lib/queryClient"; interface WeatherSettings { id: number; apiKey: string; location: string; isActive: boolean; createdAt: string; updatedAt: string; } export default function WeatherSettings() { const { toast } = useToast(); const queryClient = useQueryClient(); const [testResult, setTestResult] = useState<{ success: boolean; message: string } | null>(null); const [isTesting, setIsTesting] = useState(false); // Fetch weather settings const { data: settings, isLoading } = useQuery({ queryKey: ['/api/weather/settings'], }); // Update settings mutation const updateSettingsMutation = useMutation({ mutationFn: async (data: Partial) => { const url = settings?.id ? `/api/weather/settings/${settings.id}` : '/api/weather/settings'; const method = settings?.id ? 'PUT' : 'POST'; const response = await fetch(url, { method, headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(data), }); if (!response.ok) { throw new Error('Failed to save settings'); } return response.json(); }, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['/api/weather/settings'] }); toast({ title: "Configuration sauvegardée", description: "Les paramètres météo ont été mis à jour avec succès.", }); }, onError: (error: any) => { toast({ title: "Erreur", description: error.message || "Impossible de sauvegarder les paramètres.", variant: "destructive", }); }, }); // Geolocation mutation const geoLocationMutation = useMutation({ mutationFn: async (coordinates: { latitude: number; longitude: number }) => { const response = await fetch('/api/weather/geolocation', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(coordinates), }); if (!response.ok) { const error = await response.json(); throw new Error(error.message || 'Erreur de géolocalisation'); } return response.json(); }, onSuccess: (data) => { toast({ title: "Localisation mise à jour", description: data.message, }); // Refresh settings to get updated location queryClient.invalidateQueries({ queryKey: ['/api/weather/settings'] }); // Update the form field const locationInput = document.getElementById('location') as HTMLInputElement; if (locationInput && data.location?.fullLocation) { locationInput.value = data.location.fullLocation; } }, onError: (error: any) => { toast({ title: "Erreur de géolocalisation", description: error.message || "Impossible de déterminer votre localisation", variant: "destructive", }); }, }); // Handle geolocation const handleGeolocation = () => { if (!navigator.geolocation) { toast({ title: "Géolocalisation non supportée", description: "Votre navigateur ne supporte pas la géolocalisation", variant: "destructive", }); return; } navigator.geolocation.getCurrentPosition( (position) => { const { latitude, longitude } = position.coords; geoLocationMutation.mutate({ latitude, longitude }); }, (error) => { let message = "Erreur de géolocalisation"; switch (error.code) { case error.PERMISSION_DENIED: message = "Autorisation de géolocalisation refusée"; break; case error.POSITION_UNAVAILABLE: message = "Position non disponible"; break; case error.TIMEOUT: message = "Délai d'attente dépassé"; break; } toast({ title: "Erreur de géolocalisation", description: message, variant: "destructive", }); }, { enableHighAccuracy: true, timeout: 10000, maximumAge: 300000, // 5 minutes } ); }; // Test API connection const testConnection = async (apiKey: string, location: string) => { setIsTesting(true); setTestResult(null); try { const response = await fetch('/api/weather/test-connection', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ apiKey, location }), }); if (!response.ok) { throw new Error('Test connection failed'); } const result = await response.json(); setTestResult(result); } catch (error: any) { setTestResult({ success: false, message: error.message || "Erreur lors du test de connexion" }); } finally { setIsTesting(false); } }; const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); const formData = new FormData(e.currentTarget); const data = { apiKey: formData.get('apiKey') as string, location: formData.get('location') as string, isActive: formData.get('isActive') === 'on', }; updateSettingsMutation.mutate(data); }; if (isLoading) { return (

Configuration Météo

); } return (

Configuration Météo

Paramètres API Visual Crossing Configurez l'API Visual Crossing pour afficher la météo du jour actuel et de l'année précédente.

Obtenez votre clé API gratuite sur{" "} visualcrossing.com

Ville ou région pour laquelle afficher la météo. Cliquez sur 📍 pour détecter automatiquement votre localisation.

{testResult && ( {testResult.success ? ( ) : ( )} {testResult.message} )}
À propos

Le widget météo affiche la température maximale du jour actuel ainsi que celle du même jour l'année précédente, permettant une comparaison rapide.

Les données sont mises en cache pour éviter les appels API répétés et optimiser les performances.

L'affichage météo apparaît en haut à gauche de l'interface, à côté du sélecteur de magasin.

); }