mirror of
https://github.com/R0m1k3/LogiFlow.git
synced 2026-10-15 19:29:54 +02:00
Add ability to detect user's city using geolocation
Implement geolocation functionality in the weather widget to automatically detect and set the user's city based on GPS coordinates, updating weather data accordingly. Replit-Commit-Author: Agent Replit-Commit-Session-Id: d43bd811-9372-45a7-8ac9-4a954c0538e1 Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/1957c339-2757-4d1f-8e92-e9f71a1ce58e/d43bd811-9372-45a7-8ac9-4a954c0538e1/zoZabWF
This commit is contained in:
1 parent
8eb0458ce2
commit
c65860cb85
4 files changed
+202
-6
No files matched your search
@@ -1,6 +1,9 @@
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { Cloud, CloudRain, Sun, CloudSnow, CloudSun, ThermometerSun, CloudDrizzle, Wind, Zap, Eye } from "lucide-react";
|
||||
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
|
||||
import { Cloud, CloudRain, Sun, CloudSnow, CloudSun, ThermometerSun, CloudDrizzle, Wind, Zap, Eye, MapPin, Loader2 } from "lucide-react";
|
||||
import { Card, CardContent } from "@/components/ui/card";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { useToast } from "@/hooks/use-toast";
|
||||
import { apiRequest } from "@/lib/queryClient";
|
||||
|
||||
interface WeatherData {
|
||||
id: number;
|
||||
@@ -118,12 +121,95 @@ const WeatherIcon = ({ condition, size = 20 }: { condition: string; size?: numbe
|
||||
};
|
||||
|
||||
export default function WeatherWidget() {
|
||||
const { toast } = useToast();
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
const { data: weather, isLoading, error } = useQuery<WeatherResponse>({
|
||||
queryKey: ['/api/weather/current'],
|
||||
refetchInterval: 30 * 60 * 1000, // Refetch every 30 minutes
|
||||
retry: 1,
|
||||
});
|
||||
|
||||
// Mutation pour la géolocalisation
|
||||
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,
|
||||
});
|
||||
|
||||
// Actualiser les données météo
|
||||
queryClient.invalidateQueries({ queryKey: ['/api/weather/current'] });
|
||||
},
|
||||
onError: (error: any) => {
|
||||
toast({
|
||||
title: "Erreur de géolocalisation",
|
||||
description: error.message || "Impossible de déterminer votre localisation",
|
||||
variant: "destructive",
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
// Fonction pour obtenir la géolocalisation
|
||||
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
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
<Card className="bg-gradient-to-r from-slate-50 to-slate-100 dark:from-slate-800 dark:to-slate-900 border-slate-200 dark:border-slate-700 shadow-sm">
|
||||
@@ -160,9 +246,25 @@ export default function WeatherWidget() {
|
||||
<WeatherIcon condition={weather.currentYear?.condition || ''} size={24} />
|
||||
</div>
|
||||
<div className="flex flex-col">
|
||||
<span className="text-slate-700 dark:text-slate-200 font-semibold text-sm">
|
||||
{location.split(',')[0]}
|
||||
</span>
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-slate-700 dark:text-slate-200 font-semibold text-sm">
|
||||
{location.split(',')[0]}
|
||||
</span>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={handleGeolocation}
|
||||
disabled={geoLocationMutation.isPending}
|
||||
className="h-6 w-6 p-0 hover:bg-slate-200 dark:hover:bg-slate-600"
|
||||
title="Détecter ma localisation"
|
||||
>
|
||||
{geoLocationMutation.isPending ? (
|
||||
<Loader2 className="h-3 w-3 animate-spin" />
|
||||
) : (
|
||||
<MapPin className="h-3 w-3" />
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
<span className="text-xs text-slate-500 dark:text-slate-400">
|
||||
{translateToFrench(weather.currentYear?.condition || 'Inconnu')}
|
||||
</span>
|
||||
|
||||
Reference in new issue
Block a user