+
{event.name}
+
+
+
+
+ My location
+ {
+ api.joinEvent(placeId);
+ }}
+ style={{
+ border: '2px solid ' + (currentPlaceId ? '#30ff30' : 'gray'),
+ marginRight: '0.5rem',
+ }}
+ />
+
+ {!myCarpoolHasOtherMembers && (
+
+ Can I drive?
+ {
+ if (canDrive) {
+ setInvitedSignupIds({});
+ api.setDriving(false);
+ } else {
+ api.setDriving(true);
+ }
+ }}
+ style={{ border: '2px solid #30ff00' }}
+ >
+ {canDrive ? 'Yes' : 'No'}
+
+
+ )}
+
+ {myCarpoolHasOtherMembers && (
+ <>
+
My Carpool
+
+
+ Driver:
+ {myCarpool?.driverName}
+
+
Members:
+ {myCarpoolExtraInfo!.members.length > 1 ? (
+
+ {myCarpoolExtraInfo!.members.map((member) => {
+ if (member.signupId === event.me.signupId) {
+ return null;
+ }
+ const signup = event.signups[member.signupId];
+ const name = member.name;
+ return (
+ -
+ {name}
+
+ );
+ })}
+
+ ) : (
+ <>(no members)>
+ )}
+
+ >
+ )}
+ {canDrive && (
+ <>
+
People who need a ride
+
+ {invitedSignups.length === 1
+ ? '1 person'
+ : `${invitedSignups.length} people`}{' '}
+ in temporary carpool. Estimated distance (linear):{' '}
+ {optimalInvitedSignupPath?.distance.toFixed(1)} miles
+
+
+
+
+ {signupsWithoutCarpool.map((signup, index) => {
+ // Don't show people who don't have a location
+ if (!signup.latitude) {
+ return null;
+ }
+
+ const name = 'Person ' + (index + 1);
+ const distanceAdded = (() => {
+ if (signup.id in invitedSignupIds) {
+ return null;
+ }
+ if (optimalInvitedSignupPath) {
+ return distanceAddedByWaypoint(
+ optimalInvitedSignupPath.path,
+ signup
+ );
+ }
+ if (signup.latitude && mySignup.latitude) {
+ let distanceWithThem = getDistance(mySignup, signup, event);
+ let distanceWithoutThem = getDistance(mySignup, event);
+ return distanceWithThem - distanceWithoutThem;
+ }
+ return null;
+ })();
+ const invited = signup.id in invitedSignupIds;
+ return (
+
+
{name} has no carpool.{' '}
+ {distanceAdded !== null && (
+ <>+{distanceAdded.toFixed(1)} miles>
+ )}{' '}
+
+ focus(signup.id)}
+ style={{ marginRight: '0.5rem' }}
+ >
+ View on map
+
+ {!invited ? (
+
+ setInvitedSignupIds((ids) => ({
+ ...ids,
+ [signup.id]: true,
+ }))
+ }
+ >
+ Add
+
+ ) : (
+ {
+ setInvitedSignupIds((ids) => {
+ const newIds = { ...ids };
+ delete newIds[signup.id];
+ return newIds;
+ });
+ }}
+ >
+ Remove
+
+ )}
+
+
+ );
+ })}
+
+ >
+ )}
+
Carpools
+
+ {event.carpools.map((carpool) => {
+ const isMe = carpool.groupId === mySignup.groupId;
+ const driverDisplayName = isMe
+ ? carpool.driverName + ' (my group)'
+ : carpool.driverName;
+
+ const passengerCount = carpool.signupIds.length - 1;
+
+ if (passengerCount === 0) {
+ return (
+
+ {driverDisplayName}: Available to drive
+
+ );
+ }
+
+ return (
+
+ {driverDisplayName}: Driving
+
+ {passengerCount} member
+ {passengerCount !== 1 ? 's' : ''}
+
+ );
+ })}
+
+
+ );
+}
diff --git a/src/mvp/PlanEvent.tsx b/src/mvp/PlanEvent.tsx
new file mode 100644
index 0000000..2d2d4ca
--- /dev/null
+++ b/src/mvp/PlanEvent.tsx
@@ -0,0 +1,70 @@
+import { useCallback } from 'react';
+import { useContext } from 'react';
+import { useState } from 'react';
+import UIButton from '../components/UI/UIButton';
+import UIDatetimeInput from '../components/UI/UIDatetimeInput';
+import UIPlacesAutocomplete from '../components/UI/UIPlacesAutocomplete';
+import UITextInput from '../components/UI/UITextInput';
+import WheelShareContext from './WheelShareContext';
+
+export default function PlanEvent() {
+ const [name, setName] = useState('');
+ const [startTime, setStartTime] = useState