geolocation direkt von fs

This commit is contained in:
2025-11-11 10:14:58 +01:00
parent bbde08f89a
commit 8e308b0d99
7 changed files with 45 additions and 219 deletions

View File

@@ -93,9 +93,7 @@ const StoreWatchPage = ({
authorizedFetch,
knownStores = [],
userLocation,
onRequestLocation,
locationLoading = false,
locationSaving = false,
locationError = '',
notificationPanelOpen = false,
onToggleNotificationPanel = () => {},
@@ -125,12 +123,6 @@ const StoreWatchPage = ({
const initialTableState = useMemo(() => readWatchTableState(), []);
const [sorting, setSorting] = useState(initialTableState.sorting);
const [columnFilters, setColumnFilters] = useState(initialTableState.columnFilters);
const [locationPromptTriggered, setLocationPromptTriggered] = useState(false);
const [locationPromptPending, setLocationPromptPending] = useState(false);
const [locationPromptError, setLocationPromptError] = useState('');
const combinedLocationError = locationError || locationPromptError;
const locationActionBusy = locationSaving || locationPromptPending;
const formatCoordinate = (value) => (Number.isFinite(value) ? Number(value).toFixed(4) : '');
const aggregatedRegionStores = useMemo(() => {
const list = [];
Object.values(storesByRegion).forEach((entry) => {
@@ -182,63 +174,6 @@ const StoreWatchPage = ({
persistWatchTableState({ sorting, columnFilters });
}, [sorting, columnFilters]);
const requestLocation = useCallback(() => {
if (!onRequestLocation) {
return;
}
setLocationPromptTriggered(true);
if (typeof window === 'undefined' || typeof navigator === 'undefined' || !navigator.geolocation) {
setLocationPromptPending(false);
setLocationPromptError('Standortbestimmung wird von diesem Browser nicht unterstützt.');
return;
}
setLocationPromptPending(true);
setLocationPromptError('');
navigator.geolocation.getCurrentPosition(
async (position) => {
setLocationPromptPending(false);
try {
await onRequestLocation({
lat: position.coords.latitude,
lon: position.coords.longitude
});
} catch {
setLocationPromptError('Standort konnte nicht gespeichert werden.');
}
},
(geoError) => {
setLocationPromptPending(false);
setLocationPromptError(
geoError.code === geoError.PERMISSION_DENIED
? 'Zugriff auf den Standort wurde verweigert. Bitte erlaube den Zugriff im Browser.'
: 'Standort konnte nicht automatisch ermittelt werden.'
);
},
{
enableHighAccuracy: true,
timeout: 10000,
maximumAge: 0
}
);
}, [onRequestLocation]);
useEffect(() => {
if (userLocation || locationLoading || !onRequestLocation || locationPromptTriggered) {
return;
}
requestLocation();
}, [userLocation, locationLoading, onRequestLocation, locationPromptTriggered, requestLocation]);
const handleManualDetectLocation = useCallback(() => {
setLocationPromptError('');
requestLocation();
}, [requestLocation]);
const handleClearStoredLocation = useCallback(async () => {
setLocationPromptError('');
await onRequestLocation?.(null);
}, [onRequestLocation]);
const watchedIds = useMemo(
() => new Set(watchList.map((entry) => String(entry.storeId))),
[watchList]
@@ -964,10 +899,7 @@ const StoreWatchPage = ({
{...notificationProps}
location={displayLocation}
locationLoading={locationLoading}
locationSaving={locationActionBusy}
locationError={combinedLocationError}
onDetectLocation={handleManualDetectLocation}
onClearLocation={handleClearStoredLocation}
locationError={locationError}
/>
)}
@@ -984,25 +916,12 @@ const StoreWatchPage = ({
</div>
)}
{!userLocation && !locationLoading && onRequestLocation && (
{!userLocation && !locationLoading && (
<div className="mb-6 rounded-lg border border-blue-200 bg-blue-50 p-4 text-sm text-blue-900">
{locationActionBusy ? (
<p>Standort wird automatisch angefragt, um Entfernungen berechnen zu können...</p>
) : combinedLocationError ? (
<div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
<p className="flex-1">{combinedLocationError}</p>
<button
type="button"
onClick={handleManualDetectLocation}
className="inline-flex items-center justify-center rounded-md bg-blue-600 px-4 py-2 text-sm font-semibold text-white hover:bg-blue-700 disabled:opacity-60"
disabled={locationActionBusy}
>
Erneut versuchen
</button>
</div>
) : (
<p>Bitte bestätige die Standortabfrage deines Browsers für Entfernungssortierung.</p>
)}
<p>
Standortdaten für die Entfernungssortierung stammen automatisch aus deinem Foodsharing-Profil. Ergänze
dort deine Koordinaten, falls sie fehlen.
</p>
</div>
)}