mirror of
https://github.com/myfatemi04/wheelshare-frontend.git
synced 2025-04-16 00:50:18 -04:00
add pickLatLong, other hooks
This commit is contained in:
parent
ac6717d527
commit
a37323fc07
|
@ -1,10 +1,9 @@
|
|||
import CancelIcon from '@material-ui/icons/Cancel';
|
||||
import PersonAddIcon from '@material-ui/icons/PersonAdd';
|
||||
import { useMemo } from 'react';
|
||||
import { useContext, useEffect, useState } from 'react';
|
||||
import { useContext, useEffect, useMemo } from 'react';
|
||||
import { getEventSignups } from '../api';
|
||||
import { useMe } from '../hooks';
|
||||
import { IEventSignup } from '../types';
|
||||
import useImmutable from '../useImmutable';
|
||||
import { CarpoolContext } from './Carpool';
|
||||
|
||||
function InvitationRow({
|
||||
|
@ -43,18 +42,15 @@ function InvitationRow({
|
|||
|
||||
export default function InvitationList() {
|
||||
const { carpool } = useContext(CarpoolContext);
|
||||
const me = useMe()!;
|
||||
|
||||
const eventId = carpool.event.id;
|
||||
|
||||
const [availableSignups, setAvailableSignups] =
|
||||
useState<IEventSignup[] | null>(null);
|
||||
useImmutable<IEventSignup[] | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
getEventSignups(eventId).then((signups) =>
|
||||
setAvailableSignups(signups.filter((signup) => signup.user.id !== me.id))
|
||||
);
|
||||
}, [eventId, me.id]);
|
||||
getEventSignups(eventId).then(setAvailableSignups);
|
||||
}, [eventId, setAvailableSignups]);
|
||||
|
||||
const invitedUserIDs = useMemo(
|
||||
() =>
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { useCallback, useEffect } from 'react';
|
||||
import { green, lightgrey } from '../../lib/colors';
|
||||
import getPlaceDetails from '../../lib/getPlaceDetails';
|
||||
import {
|
||||
addOrUpdateEventSignup,
|
||||
getEvent,
|
||||
|
@ -14,7 +15,6 @@ import UIPlacesAutocomplete from '../UI/UIPlacesAutocomplete';
|
|||
import UISecondaryBox from '../UI/UISecondaryBox';
|
||||
import UISecondaryHeader from '../UI/UISecondaryHeader';
|
||||
import useImmutable from '../useImmutable';
|
||||
import useThrottle from '../useThrottle';
|
||||
import EventCarpools from './EventCarpools';
|
||||
import EventContext from './EventContext';
|
||||
import EventDetails from './EventDetails';
|
||||
|
@ -51,20 +51,10 @@ export default function Event({
|
|||
duration: 0,
|
||||
...(initial || {}),
|
||||
});
|
||||
const [myPlaceId, setPlaceId] = useState<string | null>(null);
|
||||
const [interested, setInterested] = useState(false);
|
||||
const [updating, setUpdating] = useState(false);
|
||||
const [signups, setSignups] =
|
||||
useState<Record<string, IEventSignup>>(NOT_LOADED);
|
||||
const [hasCarpool, setHasCarpool] = useState(false);
|
||||
const toggleInterested = useCallback(() => setInterested((i) => !i), []);
|
||||
const toggleInterestedThrottled = useThrottle(toggleInterested, 500);
|
||||
const existingSignup = useRef({
|
||||
interested: false,
|
||||
placeId: null as string | null,
|
||||
eventId: null as number | null,
|
||||
});
|
||||
const me = useMe();
|
||||
useImmutable<Record<string, IEventSignup>>(NOT_LOADED);
|
||||
|
||||
const me = useMe()!;
|
||||
|
||||
const [tentativeInvites] = useImmutable<Record<number, boolean>>({});
|
||||
|
||||
|
@ -74,60 +64,44 @@ export default function Event({
|
|||
|
||||
useEffect(refresh, [refresh]);
|
||||
|
||||
useEffect(() => {
|
||||
if (signups === NOT_LOADED) {
|
||||
return;
|
||||
}
|
||||
const updateSignup = useCallback(
|
||||
async (placeId: string | null) => {
|
||||
await addOrUpdateEventSignup(id, placeId);
|
||||
|
||||
const removeSignup = () => {
|
||||
if (prev.interested) {
|
||||
removeEventSignup(id)
|
||||
.then(() => {
|
||||
prev.interested = false;
|
||||
})
|
||||
.finally(() => setUpdating(false));
|
||||
if (placeId) {
|
||||
const details = await getPlaceDetails(placeId);
|
||||
|
||||
signups[me.id] = {
|
||||
user: { id: me.id, name: me.name },
|
||||
placeId,
|
||||
...details,
|
||||
};
|
||||
} else {
|
||||
signups[me.id] = {
|
||||
user: { id: me.id, name: me.name },
|
||||
placeId: null,
|
||||
latitude: null,
|
||||
longitude: null,
|
||||
formattedAddress: null,
|
||||
};
|
||||
}
|
||||
};
|
||||
},
|
||||
[id, me.id, me.name, signups]
|
||||
);
|
||||
|
||||
const addOrUpdateSignup = () => {
|
||||
if (!prev.interested || prev.placeId !== myPlaceId) {
|
||||
console.log('Adding or updating signup.', prev, {
|
||||
interested,
|
||||
placeId: myPlaceId,
|
||||
eventId: id,
|
||||
signups,
|
||||
});
|
||||
addOrUpdateEventSignup(id, myPlaceId)
|
||||
.then(() => {
|
||||
prev.placeId = myPlaceId;
|
||||
prev.eventId = id;
|
||||
prev.interested = true;
|
||||
})
|
||||
.finally(() => setUpdating(false));
|
||||
}
|
||||
};
|
||||
const removeSignup = useCallback(async () => {
|
||||
await removeEventSignup(id);
|
||||
|
||||
const prev = existingSignup.current;
|
||||
|
||||
if (!interested) {
|
||||
removeSignup();
|
||||
} else {
|
||||
addOrUpdateSignup();
|
||||
if (signups[me.id]) {
|
||||
delete signups[me.id];
|
||||
}
|
||||
}, [id, interested, myPlaceId, signups, updating]);
|
||||
}, [id, me.id, signups]);
|
||||
|
||||
const interested = !!signups[me.id];
|
||||
|
||||
useEffect(() => {
|
||||
getEventSignups(id)
|
||||
.then((signups) => {
|
||||
for (let signup of signups) {
|
||||
if (signup.user.id === me?.id) {
|
||||
setInterested(true);
|
||||
setPlaceId(signup.placeId);
|
||||
existingSignup.current.eventId = id;
|
||||
existingSignup.current.placeId = signup.placeId;
|
||||
existingSignup.current.interested = true;
|
||||
}
|
||||
}
|
||||
const signupMap: Record<string, IEventSignup> = {};
|
||||
for (let signup of signups) {
|
||||
signupMap[signup.user.id] = signup;
|
||||
|
@ -135,7 +109,7 @@ export default function Event({
|
|||
setSignups(signupMap);
|
||||
})
|
||||
.catch(console.error);
|
||||
}, [id, me?.id]);
|
||||
}, [id, setSignups]);
|
||||
|
||||
if (!event) {
|
||||
return <UISecondaryBox>Loading...</UISecondaryBox>;
|
||||
|
@ -151,9 +125,6 @@ export default function Event({
|
|||
default: false,
|
||||
tentativeInvites,
|
||||
signups,
|
||||
hasCarpool,
|
||||
setHasCarpool,
|
||||
myPlaceId,
|
||||
}}
|
||||
>
|
||||
<UISecondaryBox>
|
||||
|
@ -163,7 +134,7 @@ export default function Event({
|
|||
</div>
|
||||
<EventDetails {...{ startTime, endTime, formattedAddress }} />
|
||||
<UIButton
|
||||
onClick={toggleInterestedThrottled}
|
||||
onClick={interested ? () => removeSignup() : () => updateSignup(null)}
|
||||
style={{
|
||||
backgroundColor: interested ? green : lightgrey,
|
||||
color: interested ? 'white' : 'black',
|
||||
|
@ -176,15 +147,19 @@ export default function Event({
|
|||
<>
|
||||
<UIPlacesAutocomplete
|
||||
placeholder="Pickup and dropoff location"
|
||||
onSelected={(_address, placeID) => {
|
||||
setPlaceId(placeID);
|
||||
onSelected={(_address, placeId) => {
|
||||
updateSignup(placeId);
|
||||
}}
|
||||
style={myPlaceId != null ? { border: '2px solid ' + green } : {}}
|
||||
placeId={myPlaceId}
|
||||
style={
|
||||
signups[me.id]?.placeId != null
|
||||
? { border: '2px solid ' + green }
|
||||
: {}
|
||||
}
|
||||
placeId={signups[me.id]?.placeId}
|
||||
/>
|
||||
<br />
|
||||
<EventCarpools />
|
||||
{signups !== null && <EventSignups myPlaceId={myPlaceId} />}
|
||||
{signups !== null && <EventSignups />}
|
||||
</>
|
||||
)}
|
||||
</UISecondaryBox>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { useCallback, useContext, useEffect, useMemo, useState } from 'react';
|
||||
import { useCallback, useContext, useMemo, useState } from 'react';
|
||||
import { lightgrey } from '../../lib/colors';
|
||||
import { createCarpool } from '../api';
|
||||
import { useMe } from '../hooks';
|
||||
|
@ -9,8 +9,7 @@ import EventContext from './EventContext';
|
|||
type CreationStatus = null | 'pending' | 'completed' | 'errored';
|
||||
|
||||
export default function EventCarpoolCreateButton() {
|
||||
const { event, setHasCarpool, tentativeInvites, signups } =
|
||||
useContext(EventContext);
|
||||
const { event, tentativeInvites } = useContext(EventContext);
|
||||
|
||||
const [creationStatus, setCreationStatus] = useState<CreationStatus>(null);
|
||||
const [createdCarpoolId, setCreatedCarpoolId] = useState<null | number>(null);
|
||||
|
@ -23,83 +22,29 @@ export default function EventCarpoolCreateButton() {
|
|||
),
|
||||
[event.carpools, me.id]
|
||||
);
|
||||
const alreadyInCarpool =
|
||||
myCarpool !== undefined || creationStatus === 'completed';
|
||||
|
||||
useEffect(() => {
|
||||
setHasCarpool(alreadyInCarpool);
|
||||
}, [alreadyInCarpool, setHasCarpool]);
|
||||
|
||||
const createCarpoolCallback = useCallback(() => {
|
||||
const createCarpoolCallback = useCallback(async () => {
|
||||
setCreationStatus('pending');
|
||||
|
||||
createCarpool({
|
||||
const { id } = await createCarpool({
|
||||
name: me.name + "'s Carpool",
|
||||
eventId: event.id,
|
||||
invitedUserIds: Object.keys(tentativeInvites).map(Number),
|
||||
})
|
||||
.then(({ id }) => {
|
||||
setCreatedCarpoolId(id);
|
||||
event.carpools.push({
|
||||
id,
|
||||
name: me.name + "'s Carpool",
|
||||
members: [{ id: me.id, name: me.name }],
|
||||
});
|
||||
setCreationStatus('completed');
|
||||
})
|
||||
.catch(() => {
|
||||
setCreationStatus('errored');
|
||||
});
|
||||
try {
|
||||
event.carpools.push({
|
||||
id,
|
||||
name: me.name + "'s Carpool",
|
||||
members: [{ id: me.id, name: me.name }],
|
||||
});
|
||||
setCreatedCarpoolId(id);
|
||||
setCreationStatus('completed');
|
||||
} catch (e) {
|
||||
setCreationStatus('errored');
|
||||
}
|
||||
}, [event.carpools, event.id, me.id, me.name, tentativeInvites]);
|
||||
|
||||
const tentativeInviteNames = useMemo(() => {
|
||||
if (!signups) return [];
|
||||
const names = Object.keys(tentativeInvites).map((id) => {
|
||||
const signup = signups[id];
|
||||
return signup?.user.name;
|
||||
});
|
||||
return names.filter((n) => n != null);
|
||||
}, [tentativeInvites, signups]);
|
||||
|
||||
let createCarpoolSection;
|
||||
|
||||
if (tentativeInviteNames.length > 0) {
|
||||
const inviteeCount = tentativeInviteNames.length;
|
||||
const peoplePlural = inviteeCount > 1 ? 'People' : 'Person';
|
||||
createCarpoolSection = (
|
||||
<>
|
||||
<br />
|
||||
<b>List:</b>
|
||||
<br />
|
||||
{tentativeInviteNames.join(',')}
|
||||
<UIButton
|
||||
onClick={createCarpoolCallback}
|
||||
style={{ backgroundColor: lightgrey }}
|
||||
>
|
||||
{creationStatus === null
|
||||
? `Create Carpool With ${inviteeCount} ${peoplePlural}`
|
||||
: creationStatus === 'pending'
|
||||
? 'Creating...'
|
||||
: 'Errored'}
|
||||
</UIButton>
|
||||
</>
|
||||
);
|
||||
} else
|
||||
createCarpoolSection = (
|
||||
<>
|
||||
<span>Available to drive?</span>
|
||||
<UIButton
|
||||
onClick={createCarpoolCallback}
|
||||
style={{ backgroundColor: lightgrey }}
|
||||
>
|
||||
{creationStatus === null
|
||||
? 'Create Empty Carpool'
|
||||
: creationStatus === 'pending'
|
||||
? 'Creating...'
|
||||
: 'Errored'}
|
||||
</UIButton>
|
||||
</>
|
||||
);
|
||||
const inviteCount = Object.keys(tentativeInvites).length;
|
||||
|
||||
return (
|
||||
<div>
|
||||
|
@ -114,7 +59,21 @@ export default function EventCarpoolCreateButton() {
|
|||
<UILink href={`/carpools/${myCarpool.id}`}>{myCarpool.name}</UILink>
|
||||
</span>
|
||||
) : (
|
||||
createCarpoolSection
|
||||
<>
|
||||
<span>Available to drive?</span>
|
||||
<UIButton
|
||||
onClick={createCarpoolCallback}
|
||||
style={{ backgroundColor: lightgrey }}
|
||||
>
|
||||
{creationStatus === null
|
||||
? inviteCount === 0
|
||||
? 'Create Empty Carpool'
|
||||
: 'Create With ' + inviteCount
|
||||
: creationStatus === 'pending'
|
||||
? 'Creating...'
|
||||
: 'Errored'}
|
||||
</UIButton>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -11,8 +11,8 @@ import {
|
|||
import { useMe } from '../hooks';
|
||||
import { IEvent } from '../types';
|
||||
import useOptimalPath from '../useOptimalPath';
|
||||
import usePlace from '../usePlace';
|
||||
import EventContext from './EventContext';
|
||||
import useMySignup from './useMySignup';
|
||||
|
||||
function useMemberLocations(members: IEvent['carpools'][0]['members']) {
|
||||
const { signups } = useContext(EventContext);
|
||||
|
@ -61,10 +61,17 @@ function CarpoolRow({
|
|||
|
||||
const {
|
||||
event: { latitude, longitude },
|
||||
myPlaceId,
|
||||
} = useContext(EventContext);
|
||||
|
||||
const myLocation = usePlace(myPlaceId);
|
||||
const mySignup = useMySignup();
|
||||
|
||||
const myLocation =
|
||||
mySignup && mySignup.latitude !== null
|
||||
? {
|
||||
latitude: mySignup.latitude,
|
||||
longitude: mySignup.longitude,
|
||||
}
|
||||
: null;
|
||||
|
||||
const memberLocations = useMemberLocations(carpool.members);
|
||||
|
||||
|
|
|
@ -9,11 +9,6 @@ const EventContext = createContext({
|
|||
default: true,
|
||||
signups: {} as Record<string, IEventSignup>,
|
||||
tentativeInvites: {} as Record<number, boolean>,
|
||||
hasCarpool: false,
|
||||
setHasCarpool: (has: boolean) => {
|
||||
console.error('not implemented: setHasCarpool');
|
||||
},
|
||||
myPlaceId: null as string | null,
|
||||
});
|
||||
|
||||
export default EventContext;
|
||||
|
|
|
@ -1,68 +1,42 @@
|
|||
import CancelIcon from '@material-ui/icons/Cancel';
|
||||
import PersonAddIcon from '@material-ui/icons/PersonAdd';
|
||||
import { useContext, useMemo } from 'react';
|
||||
import { PlaceDetails } from '../../lib/getPlaceDetails';
|
||||
import latlongdist, { R_miles } from '../../lib/latlongdist';
|
||||
import { useMe } from '../hooks';
|
||||
import { IEventSignup } from '../types';
|
||||
import usePlace from '../usePlace';
|
||||
import EventCarpoolCreateButton from './EventCarpoolCreateButton';
|
||||
import EventContext from './EventContext';
|
||||
import pickLatLong from './pickLatLong';
|
||||
import useMySignup from './useMySignup';
|
||||
|
||||
function EventSignup({
|
||||
signup,
|
||||
locationLatitude,
|
||||
locationLongitude,
|
||||
myPlaceDetails,
|
||||
}: {
|
||||
signup: IEventSignup;
|
||||
locationLatitude: number;
|
||||
locationLongitude: number;
|
||||
myPlaceDetails: PlaceDetails | null;
|
||||
}) {
|
||||
const { user, latitude, longitude } = signup;
|
||||
function EventSignup({ signup }: { signup: IEventSignup }) {
|
||||
const { user } = signup;
|
||||
const me = useMe();
|
||||
const { tentativeInvites, hasCarpool } = useContext(EventContext);
|
||||
const { tentativeInvites, event } = useContext(EventContext);
|
||||
const mySignup = useMySignup();
|
||||
const myLocation = pickLatLong(mySignup);
|
||||
const theirLocation = pickLatLong(signup);
|
||||
const eventLocation = pickLatLong(event)!;
|
||||
|
||||
const extraDistance = useMemo(() => {
|
||||
if (myPlaceDetails != null && !(latitude === null || longitude === null)) {
|
||||
const myLatitude = myPlaceDetails.latitude;
|
||||
const myLongitude = myPlaceDetails.longitude;
|
||||
const meToThem = latlongdist(
|
||||
latitude,
|
||||
longitude,
|
||||
locationLongitude,
|
||||
locationLatitude,
|
||||
R_miles
|
||||
);
|
||||
const themToLocation = latlongdist(
|
||||
latitude,
|
||||
longitude,
|
||||
myLatitude,
|
||||
myLongitude,
|
||||
R_miles
|
||||
);
|
||||
const totalWithThem = meToThem + themToLocation;
|
||||
const totalWithoutThem = latlongdist(
|
||||
locationLongitude,
|
||||
locationLatitude,
|
||||
myLatitude,
|
||||
myLongitude,
|
||||
R_miles
|
||||
);
|
||||
return totalWithThem - totalWithoutThem;
|
||||
if (myLocation != null && theirLocation != null) {
|
||||
const meToThem = latlongdist(myLocation, theirLocation, R_miles);
|
||||
const themToLocation = latlongdist(theirLocation, eventLocation, R_miles);
|
||||
const meToLocation = latlongdist(myLocation, eventLocation, R_miles);
|
||||
return meToThem + themToLocation - meToLocation;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}, [
|
||||
latitude,
|
||||
longitude,
|
||||
locationLatitude,
|
||||
locationLongitude,
|
||||
myPlaceDetails,
|
||||
]);
|
||||
}, [eventLocation, myLocation, theirLocation]);
|
||||
|
||||
const isTentativelyInvited = signup.user.id in tentativeInvites;
|
||||
const hasCarpool = useMemo(
|
||||
() =>
|
||||
event.carpools.some((carpool) =>
|
||||
carpool.members.some((member) => member.id === me?.id)
|
||||
),
|
||||
[event.carpools, me?.id]
|
||||
);
|
||||
|
||||
if (user.id === me?.id) {
|
||||
return null;
|
||||
|
@ -104,14 +78,9 @@ function EventSignup({
|
|||
);
|
||||
}
|
||||
|
||||
export default function EventSignups({
|
||||
myPlaceId,
|
||||
}: {
|
||||
myPlaceId: string | null;
|
||||
}) {
|
||||
export default function EventSignups() {
|
||||
const { event, signups } = useContext(EventContext);
|
||||
const carpools = event.carpools;
|
||||
const myPlaceDetails = usePlace(myPlaceId);
|
||||
|
||||
const signupsWithoutCarpool = useMemo(() => {
|
||||
// A list of users not in any carpool
|
||||
|
@ -128,13 +97,7 @@ export default function EventSignups({
|
|||
<h3 style={{ marginBlockEnd: '0' }}>People without a carpool</h3>
|
||||
<EventCarpoolCreateButton />
|
||||
{signupsWithoutCarpool.map((signup) => (
|
||||
<EventSignup
|
||||
key={signup.user.id}
|
||||
signup={signup}
|
||||
myPlaceDetails={myPlaceDetails}
|
||||
locationLatitude={event.latitude}
|
||||
locationLongitude={event.longitude}
|
||||
/>
|
||||
<EventSignup key={signup.user.id} signup={signup} />
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
|
|
11
src/components/Event/pickLatLong.ts
Normal file
11
src/components/Event/pickLatLong.ts
Normal file
|
@ -0,0 +1,11 @@
|
|||
export default function pickLatLong<
|
||||
T extends { latitude: number | null; longitude: number | null } | null
|
||||
>(e: T): { latitude: number; longitude: number } | null {
|
||||
if (e === null) {
|
||||
return null;
|
||||
}
|
||||
if (e.latitude === null || e.longitude === null) {
|
||||
return null;
|
||||
}
|
||||
return { latitude: e.latitude, longitude: e.longitude };
|
||||
}
|
10
src/components/Event/useMySignup.tsx
Normal file
10
src/components/Event/useMySignup.tsx
Normal file
|
@ -0,0 +1,10 @@
|
|||
import { useContext, useMemo } from 'react';
|
||||
import { useMe } from '../hooks';
|
||||
import EventContext from './EventContext';
|
||||
|
||||
export default function useMySignup() {
|
||||
const { signups } = useContext(EventContext);
|
||||
const me = useMe()!;
|
||||
|
||||
return useMemo(() => signups[me.id] ?? null, [signups, me.id]);
|
||||
}
|
|
@ -1,14 +1,19 @@
|
|||
import { useEffect, useState } from 'react';
|
||||
import { useEffect } from 'react';
|
||||
import { getEvents } from './api';
|
||||
import { IEvent } from './types';
|
||||
import EventStream from './EventStream';
|
||||
import useImmutable from './useImmutable';
|
||||
|
||||
export default function Events() {
|
||||
const [events, setEvents] = useState<IEvent[]>([]);
|
||||
const [events, setEvents] = useImmutable<IEvent[]>([]);
|
||||
|
||||
const hasEvents = events.length > 0;
|
||||
|
||||
useEffect(() => {
|
||||
getEvents().then(setEvents);
|
||||
}, []);
|
||||
if (!hasEvents) {
|
||||
getEvents().then(setEvents);
|
||||
}
|
||||
}, [hasEvents, setEvents]);
|
||||
|
||||
return (
|
||||
<>
|
||||
|
|
|
@ -86,17 +86,19 @@ export type IEvent = {
|
|||
*/
|
||||
|
||||
export type IEventSignup = {
|
||||
eventId: number;
|
||||
// userId: number;
|
||||
user: {
|
||||
id: number;
|
||||
name: string;
|
||||
};
|
||||
placeId: string | null;
|
||||
formattedAddress: string | null;
|
||||
latitude: number | null;
|
||||
longitude: number | null;
|
||||
};
|
||||
} & (
|
||||
| { placeId: null; formattedAddress: null; latitude: null; longitude: null }
|
||||
| {
|
||||
placeId: string;
|
||||
formattedAddress: string;
|
||||
latitude: number;
|
||||
longitude: number;
|
||||
}
|
||||
);
|
||||
|
||||
export type IInvitation = {
|
||||
user: {
|
||||
|
|
|
@ -6,13 +6,7 @@ export default function getDistance(...locations: Location[]): number {
|
|||
for (let i = 0; i < locations.length - 1; i++) {
|
||||
const from = locations[i];
|
||||
const to = locations[i + 1];
|
||||
distance += latlongdist(
|
||||
from.latitude,
|
||||
from.longitude,
|
||||
to.latitude,
|
||||
to.longitude,
|
||||
R_miles
|
||||
);
|
||||
distance += latlongdist(from, to, R_miles);
|
||||
}
|
||||
return distance;
|
||||
}
|
||||
|
|
|
@ -13,12 +13,12 @@ export const R_miles = 3958.8;
|
|||
* @returns The distance in meters between point 1 and point 2
|
||||
*/
|
||||
export default function latlongdist(
|
||||
lat1: number,
|
||||
lon1: number,
|
||||
lat2: number,
|
||||
lon2: number,
|
||||
firstLocation: { latitude: number; longitude: number },
|
||||
secondLocation: { latitude: number; longitude: number },
|
||||
R = R_meters
|
||||
) {
|
||||
const { latitude: lat1, longitude: lon1 } = firstLocation;
|
||||
const { latitude: lat2, longitude: lon2 } = secondLocation;
|
||||
const φ1 = (lat1 * Math.PI) / 180; // φ, λ in radians
|
||||
const φ2 = (lat2 * Math.PI) / 180;
|
||||
const Δφ = ((lat2 - lat1) * Math.PI) / 180;
|
||||
|
|
Loading…
Reference in New Issue
Block a user