mirror of
https://github.com/myfatemi04/wheelshare-frontend.git
synced 2025-04-21 11:20:17 -04:00
add grouphooks, groupprovider (probably will not be used)
This commit is contained in:
parent
efeaf4b3d6
commit
bafc26fb06
|
@ -1,5 +1,6 @@
|
|||
import { CSSProperties, lazy, Suspense } from 'react';
|
||||
import { BrowserRouter, Route, Switch } from 'react-router-dom';
|
||||
import GroupsProvider from '../state/GroupsProvider';
|
||||
import NotificationsProvider from '../state/Notifications/NotificationsProvider';
|
||||
import { useMe } from './hooks';
|
||||
import WheelShare from './WheelShare';
|
||||
|
@ -24,6 +25,7 @@ export default function App() {
|
|||
const user = useMe();
|
||||
return (
|
||||
<NotificationsProvider>
|
||||
<GroupsProvider>
|
||||
<div style={{ padding: '1rem', maxWidth: '100vw' }}>
|
||||
<div style={style}>
|
||||
<BrowserRouter>
|
||||
|
@ -46,6 +48,7 @@ export default function App() {
|
|||
</BrowserRouter>
|
||||
</div>
|
||||
</div>
|
||||
</GroupsProvider>
|
||||
</NotificationsProvider>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { useCallback, useState } from 'react';
|
||||
import { createEvent } from '../api';
|
||||
import { green, lightgrey } from '../../lib/colors';
|
||||
import { IGroup } from '../Group';
|
||||
import { createEvent } from '../api';
|
||||
import { IGroup } from '../types';
|
||||
import UIButton from '../UI/UIButton';
|
||||
import UIDateInput from '../UI/UIDateInput';
|
||||
import UIDatetimeInput from '../UI/UIDatetimeInput';
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import EventCreator from './EventCreator';
|
||||
import { IGroup } from '../Group';
|
||||
import { IGroup } from '../types';
|
||||
import useToggle from '../useToggle';
|
||||
|
||||
export default function EventCreatorLink({ group }: { group: IGroup }) {
|
||||
|
|
|
@ -5,15 +5,9 @@ import { getGroup, getGroupEvents } from './api';
|
|||
import EventCreatorLink from './EventCreator/EventCreatorLink';
|
||||
import EventStream from './EventStream';
|
||||
import GroupSettingsLink from './GroupSettings/GroupSettingsLink';
|
||||
import { IEvent } from './types';
|
||||
import { IEvent, IGroup } from './types';
|
||||
import UILink from './UI/UILink';
|
||||
|
||||
export type IGroup = {
|
||||
id: number;
|
||||
events: IEvent[];
|
||||
name: string;
|
||||
};
|
||||
|
||||
export default function Group() {
|
||||
const { id } = useParams<{ id: string }>();
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { IGroup } from '../Group';
|
||||
import { IGroup } from '../types';
|
||||
import useToggle from '../useToggle';
|
||||
import GroupSettings from './GroupSettings';
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { IGroup } from '../Group';
|
||||
import { IGroup } from '../types';
|
||||
import UISecondaryBox from '../UI/UISecondaryBox';
|
||||
|
||||
function GroupListItem({ group }: { group: IGroup }) {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { useEffect, useState } from 'react';
|
||||
import { getGroups } from '../api';
|
||||
import { IGroup } from '../Group';
|
||||
import { IGroup } from '../types';
|
||||
import GroupCreatorLink from '../GroupCreator/GroupCreatorLink';
|
||||
import GroupJoinerLink from '../GroupJoinerLink';
|
||||
import GroupList from './GroupList';
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { GroupPreview } from './GroupJoinerLink';
|
||||
import { IInvitation, IEventSignup, ICarpool, IEvent } from './types';
|
||||
import { IInvitation, IEventSignup, ICarpool, IEvent, IGroup } from './types';
|
||||
|
||||
const base = process.env.REACT_APP_API_DOMAIN + 'api';
|
||||
|
||||
|
@ -94,7 +94,7 @@ export async function getEvent(id: number): Promise<IEvent> {
|
|||
return await get('/events/' + id);
|
||||
}
|
||||
|
||||
export async function getGroup(id: number) {
|
||||
export async function getGroup(id: number): Promise<IGroup> {
|
||||
return await get('/groups/' + id);
|
||||
}
|
||||
|
||||
|
|
|
@ -49,6 +49,7 @@ export type ICarpool = {
|
|||
export type IGroup = {
|
||||
id: number;
|
||||
name: string;
|
||||
events: IEvent[];
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
74
src/state/EventsProvider.tsx
Normal file
74
src/state/EventsProvider.tsx
Normal file
|
@ -0,0 +1,74 @@
|
|||
import { createContext, ReactNode, useCallback, useState } from 'react';
|
||||
import * as immutable from 'immutable';
|
||||
import { useMemo } from 'react';
|
||||
|
||||
export class EventSignup extends immutable.Record({
|
||||
userId: 0,
|
||||
placeId: '',
|
||||
formattedAddress: '',
|
||||
latitute: 0,
|
||||
longitude: 0,
|
||||
}) {}
|
||||
|
||||
export class EventState extends immutable.Record({
|
||||
id: 0,
|
||||
name: '',
|
||||
signups: immutable.Map<string, EventSignup>(),
|
||||
}) {
|
||||
addSignup(
|
||||
userId: number,
|
||||
placeId: string,
|
||||
formattedAddress: string,
|
||||
latitute: number,
|
||||
longitude: number
|
||||
) {
|
||||
return this.set(
|
||||
'signups',
|
||||
this.signups.set(
|
||||
userId.toString(),
|
||||
new EventSignup({
|
||||
userId,
|
||||
placeId,
|
||||
formattedAddress,
|
||||
latitute,
|
||||
longitude,
|
||||
})
|
||||
)
|
||||
);
|
||||
}
|
||||
setName(name: string) {
|
||||
return this.set('name', name);
|
||||
}
|
||||
}
|
||||
|
||||
type EventsProps = {
|
||||
events: immutable.Map<number, EventState>;
|
||||
upsertEvent: (event: EventState) => void;
|
||||
};
|
||||
|
||||
export const EventsContext = createContext<EventsProps>({
|
||||
events: immutable.Map<number, EventState>(),
|
||||
upsertEvent: () => {},
|
||||
});
|
||||
|
||||
export default function EventsProvider({ children }: { children: ReactNode }) {
|
||||
const [events, setEvents] = useState(immutable.Map<number, EventState>());
|
||||
|
||||
const upsertEvent = useCallback(
|
||||
(event: EventState) => {
|
||||
setEvents(events.set(event.id, event));
|
||||
},
|
||||
[events]
|
||||
);
|
||||
|
||||
const value: EventsProps = useMemo(() => {
|
||||
return {
|
||||
events,
|
||||
upsertEvent,
|
||||
};
|
||||
}, [events, upsertEvent]);
|
||||
|
||||
return (
|
||||
<EventsContext.Provider value={value}>{children}</EventsContext.Provider>
|
||||
);
|
||||
}
|
7
src/state/GroupHooks.tsx
Normal file
7
src/state/GroupHooks.tsx
Normal file
|
@ -0,0 +1,7 @@
|
|||
import { useContext } from 'react';
|
||||
import { GroupsContext, GroupState } from './GroupsProvider';
|
||||
|
||||
export function useGroup(id: number): GroupState | null {
|
||||
const { groups } = useContext(GroupsContext);
|
||||
return groups.get(id, null);
|
||||
}
|
105
src/state/GroupsProvider.tsx
Normal file
105
src/state/GroupsProvider.tsx
Normal file
|
@ -0,0 +1,105 @@
|
|||
import * as immutable from 'immutable';
|
||||
import { ReactNode, useCallback, useMemo, useState } from 'react';
|
||||
import { createContext } from 'react';
|
||||
import { getGroup as fetchGroup } from '../components/api';
|
||||
|
||||
export class GroupState extends immutable.Record({
|
||||
id: 0,
|
||||
name: '',
|
||||
memberIds: immutable.Set<number>(),
|
||||
joinCode: null as string | null,
|
||||
}) {
|
||||
setJoinCode(joinCode: string) {
|
||||
return this.set('joinCode', joinCode);
|
||||
}
|
||||
setName(name: string) {
|
||||
return this.set('name', name);
|
||||
}
|
||||
addMember(memberId: number) {
|
||||
return this.set('memberIds', this.memberIds.add(memberId));
|
||||
}
|
||||
removeMember(memberId: number) {
|
||||
return this.set('memberIds', this.memberIds.remove(memberId));
|
||||
}
|
||||
setMemberIds(memberIds: immutable.Set<number>) {
|
||||
return this.set('memberIds', memberIds);
|
||||
}
|
||||
}
|
||||
|
||||
function u(name: string) {
|
||||
return () => {
|
||||
throw new Error(`${name} is not implemented`);
|
||||
};
|
||||
}
|
||||
|
||||
type GroupContextProps = {
|
||||
groups: immutable.Map<number, GroupState>;
|
||||
addGroup: (group: GroupState) => void;
|
||||
getGroup: (id: number) => Promise<GroupState | null>;
|
||||
renameGroup: (groupId: number, name: string) => void;
|
||||
generateJoinCode: (groupId: number) => void;
|
||||
};
|
||||
|
||||
// A React context that provides access to the current user's groups.
|
||||
export const GroupsContext = createContext<GroupContextProps>({
|
||||
groups: immutable.Map<number, GroupState>(),
|
||||
addGroup: u('addGroup'),
|
||||
getGroup: u('getGroup'),
|
||||
renameGroup: u('renameGroup'),
|
||||
generateJoinCode: u('generateJoinCode'),
|
||||
});
|
||||
|
||||
export default function GroupsProvider({ children }: { children: ReactNode }) {
|
||||
// usestates for all the properties in GroupsContext
|
||||
const [groups, setGroups] = useState(immutable.Map<number, GroupState>());
|
||||
|
||||
const addGroup = useCallback((group: GroupState) => {
|
||||
setGroups((groups) => groups.set(group.id, group));
|
||||
}, []);
|
||||
|
||||
const renameGroup = useCallback((groupId: number, name: string) => {
|
||||
setGroups((groups) => groups.setIn([groupId, 'name'], name));
|
||||
}, []);
|
||||
|
||||
const generateJoinCode = useCallback((groupId: number) => {
|
||||
// TODO actually use the API here, this was generated by copilot
|
||||
setGroups((groups) =>
|
||||
groups.setIn(
|
||||
[groupId, 'joinCode'],
|
||||
Math.random().toString(36).substr(2, 5)
|
||||
)
|
||||
);
|
||||
}, []);
|
||||
|
||||
const getGroup = useCallback(
|
||||
async (id: number) => {
|
||||
const group = groups.get(id);
|
||||
if (group) {
|
||||
return group;
|
||||
} else {
|
||||
const group = await fetchGroup(id);
|
||||
const state = new GroupState({
|
||||
id: group.id,
|
||||
name: group.name,
|
||||
});
|
||||
addGroup(state);
|
||||
return state;
|
||||
}
|
||||
},
|
||||
[addGroup, groups]
|
||||
);
|
||||
|
||||
const value: GroupContextProps = useMemo(() => {
|
||||
return {
|
||||
groups,
|
||||
addGroup,
|
||||
getGroup,
|
||||
renameGroup,
|
||||
generateJoinCode,
|
||||
};
|
||||
}, [addGroup, generateJoinCode, getGroup, groups, renameGroup]);
|
||||
|
||||
return (
|
||||
<GroupsContext.Provider value={value}>{children}</GroupsContext.Provider>
|
||||
);
|
||||
}
|
Loading…
Reference in New Issue
Block a user