Files
waseel/components/map.tsx
T
Krikorios a0b297285a Add self-hosted auth, admin API, and owner web dashboard
- Replace Clerk with self-hosted JWT auth (register/login/verify, bcrypt
  passwords, Gmail OTP with console fallback)
- Add lib/db.ts pg pool + transaction helpers; seed script migrates legacy
  Clerk-era schema (drop clerk_id, enforce UUID ids and unique email)
- Add owner-gated admin API: stats, users, drivers CRUD, rides
- Add dashboard/ Vite React owner dashboard (login, overview, users,
  fleet, rides) with dev-server proxy to avoid Expo CORS middleware
- Add scripts/set-owner.mjs for role management
2026-08-23 16:38:41 +03:00

142 lines
3.6 KiB
TypeScript

import { useEffect, useState } from "react";
import { ActivityIndicator, Text, View } from "react-native";
import MapView, { Marker, PROVIDER_DEFAULT } from "react-native-maps";
import MapViewDirections from "react-native-maps-directions";
import { icons } from "@/constants";
import { useFetch } from "@/lib/fetch";
import {
calculateDriverTimes,
calculateRegion,
generateMarkersFromData,
} from "@/lib/map";
import { useDriverStore, useLocationStore } from "@/store";
import type { Driver, MarkerData } from "@/types/type";
export const Map = () => {
const { data: drivers, loading, error } = useFetch<Driver[]>("/(api)/driver");
const {
userLatitude,
userLongitude,
destinationLatitude,
destinationLongitude,
} = useLocationStore();
const { selectedDriver, setDrivers } = useDriverStore();
const [markers, setMarkers] = useState<MarkerData[]>([]);
const region = calculateRegion({
userLatitude,
userLongitude,
destinationLatitude,
destinationLongitude,
});
useEffect(() => {
if (Array.isArray(drivers)) {
if (!userLatitude || !userLongitude) return;
const newMarkers = generateMarkersFromData({
data: drivers,
userLatitude,
userLongitude,
});
setMarkers(newMarkers);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [drivers, userLatitude, userLongitude]);
useEffect(() => {
if (markers.length > 0 && destinationLatitude && destinationLongitude) {
calculateDriverTimes({
markers,
userLatitude,
userLongitude,
destinationLatitude,
destinationLongitude,
}).then((drivers) => {
setDrivers(drivers as MarkerData[]);
});
}
}, [
markers,
destinationLatitude,
destinationLongitude,
userLatitude,
userLongitude,
setDrivers,
]);
if (loading || !userLatitude || !userLongitude) {
return (
<View className="flex justify-between items-center w-full">
<ActivityIndicator size="small" color="#000" />
</View>
);
}
if (error) {
return (
<View className="flex justify-between items-center w-full">
<Text>Error: {error}</Text>
</View>
);
}
return (
<MapView
provider={PROVIDER_DEFAULT}
className="w-full h-full rounded-2xl"
tintColor="black"
mapType="mutedStandard"
showsPointsOfInterest={false}
initialRegion={region}
showsUserLocation
userInterfaceStyle="light"
>
{markers.map((marker) => (
<Marker
key={marker.id}
coordinate={{
latitude: marker.latitude,
longitude: marker.longitude,
}}
title={marker.title}
image={
selectedDriver === marker.id ? icons.selectedMarker : icons.marker
}
/>
))}
{destinationLatitude && destinationLongitude && (
<>
<Marker
key="destination"
coordinate={{
latitude: destinationLatitude,
longitude: destinationLongitude,
}}
title="Destination"
image={icons.pin}
/>
<MapViewDirections
origin={{
latitude: userLatitude,
longitude: userLongitude,
}}
destination={{
latitude: destinationLatitude,
longitude: destinationLongitude,
}}
apikey={process.env.EXPO_PUBLIC_GOOGLE_API_KEY!}
strokeColor="#0286FF"
strokeWidth={3}
/>
</>
)}
</MapView>
);
};