mirror of
https://github.com/myfatemi04/wheelshare-frontend.git
synced 2025-04-17 17:40:16 -04:00
Merge branch 'staging' into main
This commit is contained in:
commit
bfed3cdfb4
|
@ -20,6 +20,7 @@ const CarpoolPage = lazy(() => import('./Carpool/CarpoolPage'));
|
||||||
const EventPage = lazy(() => import('./Event/EventPage'));
|
const EventPage = lazy(() => import('./Event/EventPage'));
|
||||||
const GroupPage = lazy(() => import('./Group/GroupPage'));
|
const GroupPage = lazy(() => import('./Group/GroupPage'));
|
||||||
const GroupSharedLinkResolver = lazy(() => import('./GroupSharedLinkResolver'));
|
const GroupSharedLinkResolver = lazy(() => import('./GroupSharedLinkResolver'));
|
||||||
|
const ProfileForSelf = lazy(() => import('./ProfileForSelf/ProfileForSelf'));
|
||||||
|
|
||||||
const style: CSSProperties = {
|
const style: CSSProperties = {
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
|
@ -65,6 +66,7 @@ export default function App() {
|
||||||
<Switch>
|
<Switch>
|
||||||
<Route path="/" exact component={WheelShare} />
|
<Route path="/" exact component={WheelShare} />
|
||||||
<Route path="/error-report" component={ErrorReport} />
|
<Route path="/error-report" component={ErrorReport} />
|
||||||
|
<Route path="/me" exact component={ProfileForSelf} />
|
||||||
<Route
|
<Route
|
||||||
path="/join/:code"
|
path="/join/:code"
|
||||||
component={GroupSharedLinkResolver}
|
component={GroupSharedLinkResolver}
|
||||||
|
|
|
@ -3,6 +3,7 @@ import { createContext } from 'react';
|
||||||
export type User = {
|
export type User = {
|
||||||
name: string;
|
name: string;
|
||||||
id: number;
|
id: number;
|
||||||
|
bio: string;
|
||||||
email?: string;
|
email?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -10,9 +10,11 @@ import EventCarpools from './EventCarpools';
|
||||||
import { useMutableEvent } from './EventHooks';
|
import { useMutableEvent } from './EventHooks';
|
||||||
import EventSignups from './EventSignups';
|
import EventSignups from './EventSignups';
|
||||||
|
|
||||||
|
const defaultMe = { id: 0, name: '', bio: '' };
|
||||||
|
|
||||||
export default function EventInterestForm() {
|
export default function EventInterestForm() {
|
||||||
const event = useMutableEvent();
|
const event = useMutableEvent();
|
||||||
const me = useMe() || { id: 0, name: '' };
|
const me = useMe() || defaultMe;
|
||||||
const placeIdRef = useRef<string | null>(null);
|
const placeIdRef = useRef<string | null>(null);
|
||||||
const canDriveRef = useRef(false);
|
const canDriveRef = useRef(false);
|
||||||
const [note, setNote] = useState('');
|
const [note, setNote] = useState('');
|
||||||
|
@ -48,7 +50,7 @@ export default function EventInterestForm() {
|
||||||
const details = await getPlaceDetails(placeId);
|
const details = await getPlaceDetails(placeId);
|
||||||
|
|
||||||
event.signups[me.id] = {
|
event.signups[me.id] = {
|
||||||
user: { id: me.id, name: me.name },
|
user: me,
|
||||||
placeId,
|
placeId,
|
||||||
...details,
|
...details,
|
||||||
canDrive,
|
canDrive,
|
||||||
|
@ -56,7 +58,7 @@ export default function EventInterestForm() {
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
event.signups[me.id] = {
|
event.signups[me.id] = {
|
||||||
user: { id: me.id, name: me.name },
|
user: me,
|
||||||
placeId: null,
|
placeId: null,
|
||||||
latitude: null,
|
latitude: null,
|
||||||
longitude: null,
|
longitude: null,
|
||||||
|
@ -66,7 +68,7 @@ export default function EventInterestForm() {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[event.id, event.signups, me.id, me.name]
|
[event.id, event.signups, me]
|
||||||
);
|
);
|
||||||
|
|
||||||
const removeSignup = useCallback(async () => {
|
const removeSignup = useCallback(async () => {
|
||||||
|
|
|
@ -59,6 +59,8 @@ function EventSignup({ signup }: { signup: IEventSignup }) {
|
||||||
>
|
>
|
||||||
<span>
|
<span>
|
||||||
<b>{user.name}</b>
|
<b>{user.name}</b>
|
||||||
|
{user.bio && `, ${user.bio}`}
|
||||||
|
<br />
|
||||||
{extraDistance && ` +${extraDistance.toFixed(1)} miles`}{' '}
|
{extraDistance && ` +${extraDistance.toFixed(1)} miles`}{' '}
|
||||||
{signup.canDrive && ' (can drive)'}
|
{signup.canDrive && ' (can drive)'}
|
||||||
{signup.note && (
|
{signup.note && (
|
||||||
|
|
|
@ -30,6 +30,7 @@ export default function Header() {
|
||||||
{me.name}
|
{me.name}
|
||||||
{me.email && ` (${me.email})`}
|
{me.email && ` (${me.email})`}
|
||||||
<UIPressable onClick={logout}>Log out</UIPressable>
|
<UIPressable onClick={logout}>Log out</UIPressable>
|
||||||
|
<a href="/me">Profile</a>
|
||||||
<br />
|
<br />
|
||||||
{notifications.length > 0 ? (
|
{notifications.length > 0 ? (
|
||||||
<Notifications
|
<Notifications
|
||||||
|
|
93
src/components/ProfileForSelf/ProfileForSelf.tsx
Normal file
93
src/components/ProfileForSelf/ProfileForSelf.tsx
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
import { useCallback, useEffect, useState } from 'react';
|
||||||
|
import { updateBio } from '../api';
|
||||||
|
import {
|
||||||
|
AsyncCallbackStatus,
|
||||||
|
useAsyncCallback,
|
||||||
|
} from '../Event/EventAdminControls';
|
||||||
|
import { useAuth } from '../hooks';
|
||||||
|
import UIButton from '../UI/UIButton';
|
||||||
|
import UITextInput from '../UI/UITextInput';
|
||||||
|
|
||||||
|
export default function ProfileForSelf() {
|
||||||
|
const [editingBio, setEditingBio] = useState(false);
|
||||||
|
const [temporaryBio, setTemporaryBio] = useState('');
|
||||||
|
const { user: me, refresh: refreshLocalUser } = useAuth();
|
||||||
|
|
||||||
|
const [onClickedSaveBio, onClickedSaveBioStatus] = useAsyncCallback(
|
||||||
|
useCallback(
|
||||||
|
async (temporaryBio: string) => {
|
||||||
|
await updateBio(temporaryBio);
|
||||||
|
refreshLocalUser();
|
||||||
|
setEditingBio(false);
|
||||||
|
},
|
||||||
|
[refreshLocalUser]
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (me?.bio) {
|
||||||
|
setTemporaryBio(me?.bio);
|
||||||
|
}
|
||||||
|
}, [me?.bio]);
|
||||||
|
|
||||||
|
if (!me) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div style={{ minWidth: '16rem', width: '20rem' }}>
|
||||||
|
<h1>{me.name}</h1>
|
||||||
|
<p>{me.bio}</p>
|
||||||
|
{editingBio ? (
|
||||||
|
<>
|
||||||
|
{onClickedSaveBioStatus === AsyncCallbackStatus.REJECTED && (
|
||||||
|
<p>Error saving bio.</p>
|
||||||
|
)}
|
||||||
|
{onClickedSaveBioStatus !== AsyncCallbackStatus.PENDING ? (
|
||||||
|
<>
|
||||||
|
<UITextInput
|
||||||
|
onChangeText={setTemporaryBio}
|
||||||
|
value={temporaryBio}
|
||||||
|
style={{
|
||||||
|
border: '2px solid grey',
|
||||||
|
width: '100%',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<UIButton
|
||||||
|
onClick={() => onClickedSaveBio(temporaryBio)}
|
||||||
|
style={{
|
||||||
|
backgroundColor: '#f8f8f8',
|
||||||
|
width: '100%',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Save
|
||||||
|
</UIButton>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<UIButton
|
||||||
|
onClick={() => {}}
|
||||||
|
style={{
|
||||||
|
backgroundColor: '#f8f8f8',
|
||||||
|
width: '100%',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Saving...
|
||||||
|
</UIButton>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<UIButton
|
||||||
|
onClick={() => setEditingBio(true)}
|
||||||
|
style={{
|
||||||
|
backgroundColor: '#f8f8f8',
|
||||||
|
width: '100%',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Edit Bio
|
||||||
|
</UIButton>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
|
@ -312,3 +312,7 @@ export async function sendErrorReport(error: string) {
|
||||||
throw new Error(response.statusText);
|
throw new Error(response.statusText);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function updateBio(bio: string) {
|
||||||
|
return await post('/users/@me/bio', { bio });
|
||||||
|
}
|
||||||
|
|
|
@ -101,6 +101,7 @@ export type IEventSignupBase = {
|
||||||
user: {
|
user: {
|
||||||
id: number;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
|
bio: string;
|
||||||
};
|
};
|
||||||
canDrive: boolean;
|
canDrive: boolean;
|
||||||
note: string;
|
note: string;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user