updates on the zone selector for the specific login

This commit is contained in:
2026-08-27 12:03:12 +05:30
parent 4be2e73712
commit 656e180675
7 changed files with 425 additions and 61 deletions

197
src/lib/ZoneContext.jsx Normal file
View File

@@ -0,0 +1,197 @@
import React, { createContext, useContext, useEffect, useMemo, useState } from 'react';
import { useHubs, useTenantLocations } from '@/lib/doormileHooks';
import { useAuth } from '@/lib/AuthContext';
const ZONE_STORAGE_KEY = 'doormile_active_zone_id';
const ALL_ZONE = Object.freeze({
hubid: 'all',
id: 'all',
hubname: 'All Zones',
city: 'All Cities',
hubtype: 'all',
status: 'Active',
});
const haversineKm = (lat1, lon1, lat2, lon2) => {
if (![lat1, lon1, lat2, lon2].every((v) => Number.isFinite(Number(v)))) return undefined;
const R = 6371;
const toRad = (deg) => (Number(deg) * Math.PI) / 180;
const dLat = toRad(lat2 - lat1);
const dLon = toRad(lon2 - lon1);
const a =
Math.sin(dLat / 2) ** 2 + Math.cos(toRad(lat1)) * Math.cos(toRad(lat2)) * Math.sin(dLon / 2) ** 2;
return R * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
};
const ZoneContext = createContext(null);
export function ZoneProvider({ children }) {
const { user } = useAuth();
const tenantId = user?.tenantid || localStorage.getItem('tenantid') || '';
const isTenantUser = Boolean(tenantId && tenantId !== '0');
// Staff loads global hubs; Tenant loads tenant locations / kitchen hubs
const { data: rawHubs = [], isLoading: isHubsLoading, refetch: refetchHubs } = useHubs({
enabled: !isTenantUser,
});
const { data: tenantLocations = [], isLoading: isLocationsLoading, refetch: refetchLocations } = useTenantLocations(
isTenantUser ? tenantId : null,
{ enabled: isTenantUser }
);
const [selectedZoneId, setSelectedZoneIdState] = useState(() => {
try {
return localStorage.getItem(ZONE_STORAGE_KEY) || 'all';
} catch {
return 'all';
}
});
const activeHubs = useMemo(() => {
if (isTenantUser) {
return (tenantLocations || []).map((loc) => ({
hubid: String(loc.tenantlocationid || loc.locationid || loc.id),
id: String(loc.tenantlocationid || loc.locationid || loc.id),
hubname: loc.locationname || loc.name || `Kitchen Hub #${loc.tenantlocationid || loc.locationid}`,
city: loc.city || '',
address: loc.address || '',
latitude: loc.latitude,
longitude: loc.longitude,
pincode: loc.pincode || '',
hubtype: 'kitchen_hub',
isTenantLocation: true,
status: 'Active',
}));
}
return (rawHubs || []).filter(
(hub) => String(hub.status || 'Active').toLowerCase() === 'active'
);
}, [isTenantUser, tenantLocations, rawHubs]);
const zones = useMemo(() => {
return [ALL_ZONE, ...activeHubs];
}, [activeHubs]);
const selectedZone = useMemo(() => {
if (selectedZoneId === 'all') return ALL_ZONE;
const found = activeHubs.find((h) => String(h.hubid) === String(selectedZoneId));
return found || ALL_ZONE;
}, [selectedZoneId, activeHubs]);
const setSelectedZoneId = (id) => {
const nextId = String(id || 'all');
setSelectedZoneIdState(nextId);
try {
localStorage.setItem(ZONE_STORAGE_KEY, nextId);
} catch {
// ignore storage errors
}
};
const isAllZones = selectedZone.hubid === 'all';
/**
* Matches an order, delivery, tripsheet or rider against the active zone.
*/
const matchesZone = (item) => {
if (!item) return false;
// Tenant check: if item carries tenantid and current session is a tenant, match tenant first
if (isTenantUser && item.tenantid != null && String(item.tenantid) !== String(tenantId)) {
return false;
}
if (isAllZones) return true;
const currentHub = selectedZone;
const targetHubId = String(currentHub.hubid);
// 1. Direct hub/location id match
const itemHubId =
item.hubid ??
item.sourcehubid ??
item.applocationid ??
item.tenantlocationid ??
item.locationid;
if (itemHubId != null && String(itemHubId) === targetHubId) {
return true;
}
// 2. City or Hub name match
const hubCity = String(currentHub.city || '').trim().toLowerCase();
const hubName = String(currentHub.hubname || '').trim().toLowerCase();
const hubPincode = String(currentHub.pincode || '').trim();
const addressText = `${item.pickupaddress || ''} ${item.deliveryaddress || ''} ${item.address || ''} ${item.pickuplocation || ''} ${item.deliverylocation || ''} ${item.suburb || ''} ${item.city || ''}`.toLowerCase();
if (hubPincode && addressText.includes(hubPincode)) {
return true;
}
if (hubCity && addressText.includes(hubCity)) {
return true;
}
if (hubName && addressText.includes(hubName)) {
return true;
}
// 3. Coordinate distance match (within 35km radius of hub)
const hubLat = Number(currentHub.latitude);
const hubLon = Number(currentHub.longitude);
if (Number.isFinite(hubLat) && Number.isFinite(hubLon)) {
const pickLat = Number(item.pickuplatitude ?? item.latitude);
const pickLon = Number(item.pickuplongitude ?? item.longitude);
const dropLat = Number(item.deliverylatitude ?? item.droplat);
const dropLon = Number(item.deliverylongitude ?? item.droplon);
const pickDist = haversineKm(hubLat, hubLon, pickLat, pickLon);
const dropDist = haversineKm(hubLat, hubLon, dropLat, dropLon);
if (pickDist !== undefined && pickDist <= 35) return true;
if (dropDist !== undefined && dropDist <= 35) return true;
}
return false;
};
const value = useMemo(
() => ({
selectedZone,
selectedZoneId,
setSelectedZoneId,
zones,
isAllZones,
isTenantUser,
tenantId,
isHubsLoading: isTenantUser ? isLocationsLoading : isHubsLoading,
refetchHubs: isTenantUser ? refetchLocations : refetchHubs,
matchesZone,
}),
[
selectedZone,
selectedZoneId,
zones,
isAllZones,
isTenantUser,
tenantId,
isLocationsLoading,
isHubsLoading,
refetchLocations,
refetchHubs,
matchesZone,
]
);
return <ZoneContext.Provider value={value}>{children}</ZoneContext.Provider>;
}
export function useZone() {
const context = useContext(ZoneContext);
if (!context) {
throw new Error('useZone must be used within a ZoneProvider');
}
return context;
}