minor changes

This commit is contained in:
2025-11-10 21:30:43 +01:00
parent 7cdd18bf7f
commit 9a3903b761
4 changed files with 181 additions and 25 deletions

View File

@@ -8,6 +8,7 @@ import {
useReactTable
} from '@tanstack/react-table';
import { haversineDistanceKm } from '../utils/distance';
import NotificationPanel from './NotificationPanel';
const REGION_STORAGE_KEY = 'storeWatchRegionSelection';
const WATCH_TABLE_STATE_KEY = 'storeWatchTableState';
@@ -92,7 +93,12 @@ const StoreWatchPage = ({
knownStores = [],
userLocation,
onRequestLocation,
locationLoading = false
locationLoading = false,
locationSaving = false,
locationError = '',
notificationPanelOpen = false,
onToggleNotificationPanel = () => {},
notificationProps
}) => {
const [regions, setRegions] = useState([]);
const [selectedRegionId, setSelectedRegionId] = useState(() => {
@@ -120,6 +126,9 @@ const StoreWatchPage = ({
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) : '');
useEffect(() => {
if (typeof window === 'undefined') {
@@ -183,6 +192,16 @@ const StoreWatchPage = ({
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]
@@ -848,6 +867,58 @@ const StoreWatchPage = ({
</p>
</div>
<div className="mb-4 flex flex-wrap items-center justify-end gap-2">
<button
type="button"
onClick={onToggleNotificationPanel}
className={`flex items-center justify-center w-11 h-11 rounded-full border ${
notificationPanelOpen ? 'border-blue-500 text-blue-600' : 'border-gray-300 text-gray-600'
} hover:text-blue-700 hover:border-blue-500 focus:outline-none focus:ring-2 focus:ring-blue-400 transition`}
title="Benachrichtigungen konfigurieren"
>
<svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 0 0 2.573 1.066c1.543-.89 3.31.877 2.42 2.42a1.724 1.724 0 0 0 1.065 2.572c1.757.426 1.757 2.924 0 3.35a1.724 1.724 0 0 0-1.066 2.573c.89 1.543-.877 3.31-2.42 2.42a1.724 1.724 0 0 0-2.572 1.065c-.426 1.757-2.924 1.757-3.35 0a1.724 1.724 0 0 0-2.573-1.066c-1.543.89-3.31-.877-2.42-2.42a1.724 1.724 0 0 0-1.065-2.572c-1.757-.426-1.757-2.924 0-3.35a1.724 1.724 0 0 0 1.066-2.573c-.89-1.543.877-3.31 2.42-2.42.996.575 2.273.155 2.573-1.065z"
/>
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0z" />
</svg>
</button>
{notificationProps?.loading && <span className="text-sm text-gray-500">Lade</span>}
</div>
{notificationPanelOpen && notificationProps && (
<NotificationPanel
{...notificationProps}
location={userLocation}
locationLoading={locationLoading}
locationSaving={locationActionBusy}
locationError={combinedLocationError}
onDetectLocation={handleManualDetectLocation}
onClearLocation={handleClearStoredLocation}
/>
)}
{userLocation && !notificationPanelOpen && (
<div className="mb-4 rounded-lg border border-blue-100 bg-blue-50 p-4 text-sm text-blue-900">
<p>
Standort gespeichert:{' '}
{userLocation.label ? (
<span className="font-semibold">{userLocation.label}</span>
) : (
'Koordinaten'
)}{' '}
{formatCoordinate(userLocation.lat)}, {formatCoordinate(userLocation.lon)}
</p>
<p className="text-xs text-blue-800 mt-1">
Aktualisiert:{' '}
{userLocation.updatedAt ? new Date(userLocation.updatedAt).toLocaleString('de-DE') : 'Zeit unbekannt'}
</p>
</div>
)}
{(error || status) && (
<div className="mb-4 space-y-2">
{error && (
@@ -863,16 +934,16 @@ const StoreWatchPage = ({
{!userLocation && !locationLoading && onRequestLocation && (
<div className="mb-6 rounded-lg border border-blue-200 bg-blue-50 p-4 text-sm text-blue-900">
{locationPromptPending ? (
{locationActionBusy ? (
<p>Standort wird automatisch angefragt, um Entfernungen berechnen zu können...</p>
) : locationPromptError ? (
) : combinedLocationError ? (
<div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
<p className="flex-1">{locationPromptError}</p>
<p className="flex-1">{combinedLocationError}</p>
<button
type="button"
onClick={requestLocation}
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={locationPromptPending}
disabled={locationActionBusy}
>
Erneut versuchen
</button>