mirror of
https://github.com/myfatemi04/wheelshare-frontend.git
synced 2025-04-21 11:20:17 -04:00
updated design for groups
This commit is contained in:
commit
7fc9f17f44
|
@ -5,6 +5,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@material-ui/core": "^4.11.3",
|
"@material-ui/core": "^4.11.3",
|
||||||
"@material-ui/icons": "^4.11.2",
|
"@material-ui/icons": "^4.11.2",
|
||||||
|
"@react-google-maps/api": "^2.1.1",
|
||||||
"@testing-library/jest-dom": "^5.11.4",
|
"@testing-library/jest-dom": "^5.11.4",
|
||||||
"@testing-library/react": "^11.1.0",
|
"@testing-library/react": "^11.1.0",
|
||||||
"@testing-library/user-event": "^12.1.10",
|
"@testing-library/user-event": "^12.1.10",
|
||||||
|
|
|
@ -16,6 +16,7 @@ import Main from './components/Main';
|
||||||
import './App.css';
|
import './App.css';
|
||||||
import Authenticator from './components/Authenticator';
|
import Authenticator from './components/Authenticator';
|
||||||
import AuthenticationWrapper from './components/AuthenticationWrapper';
|
import AuthenticationWrapper from './components/AuthenticationWrapper';
|
||||||
|
import Logout from './components/Logout';
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
return (
|
return (
|
||||||
|
@ -27,12 +28,13 @@ function App() {
|
||||||
<Route component={Authenticator} path="/auth/:provider/callback" />
|
<Route component={Authenticator} path="/auth/:provider/callback" />
|
||||||
<Route component={CreatePool} path="/create_pool" />
|
<Route component={CreatePool} path="/create_pool" />
|
||||||
<Route component={CreateGroup} path="/create_group" />
|
<Route component={CreateGroup} path="/create_group" />
|
||||||
<Route component={Groups} path="/groups" />
|
|
||||||
<Route component={MyGroups} path="/mygroups" />
|
<Route component={MyGroups} path="/mygroups" />
|
||||||
<Route component={UpdatePool} path="/update_pool" />
|
<Route component={UpdatePool} path="/update_pool" />
|
||||||
<Route component={Group} path="/group/:id" />
|
<Route component={Group} path="/groups/:id" />
|
||||||
<Route component={Pool} path="/pool/:id" />
|
<Route component={Pool} path="/pools/:id" />
|
||||||
|
<Route component={Groups} path="/groups" />
|
||||||
<Route component={Profile} path="/profile" />
|
<Route component={Profile} path="/profile" />
|
||||||
|
<Route component={Logout} path="/logout" />
|
||||||
<Route component={Home} path="/" />
|
<Route component={Home} path="/" />
|
||||||
</Switch>
|
</Switch>
|
||||||
</BrowserRouter>
|
</BrowserRouter>
|
||||||
|
|
|
@ -32,11 +32,11 @@ export async function createSession(
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getMe(): Promise<Carpool.User> {
|
export async function getMe(): Promise<Carpool.User> {
|
||||||
let result = await makeAPIGetCall('/user', { userID: '@me' });
|
let result = await makeAPIGetCall('/users/@me');
|
||||||
return result.data.data;
|
return result.data.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getPublicUser(id: string): Promise<Carpool.PublicUser> {
|
export async function getPublicUser(id: string): Promise<Carpool.PublicUser> {
|
||||||
let result = await makeAPIGetCall('/user', { userID: id });
|
let result = await makeAPIGetCall(`/users/${id}`);
|
||||||
return result.data.data;
|
return result.data.data;
|
||||||
}
|
}
|
||||||
|
|
16
src/api/google.ts
Normal file
16
src/api/google.ts
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
export const GOOGLE_MAPS_API_KEY = 'AIzaSyDUnWIrt-H4RuP2YFLpVPz4oAjBhpOOoyI';
|
||||||
|
|
||||||
|
export async function searchForPlaces(query: string) {
|
||||||
|
const url = new URL(
|
||||||
|
'https://maps.googleapis.com/maps/api/place/findplacefromtext/json'
|
||||||
|
);
|
||||||
|
url.searchParams.set('key', GOOGLE_MAPS_API_KEY);
|
||||||
|
url.searchParams.set('input', query);
|
||||||
|
url.searchParams.set('inputtype', 'textquery');
|
||||||
|
url.searchParams.set('fields', 'place_id,name,formatted_address');
|
||||||
|
|
||||||
|
let res = await fetch(url.toString(), { mode: 'no-cors' });
|
||||||
|
let json = await res.json();
|
||||||
|
|
||||||
|
return json;
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
import { useContext, useEffect, useState } from 'react';
|
import { useContext, useEffect, useState } from 'react';
|
||||||
import { Redirect, useLocation, useParams } from 'react-router-dom';
|
import { Redirect, useLocation, useParams } from 'react-router-dom';
|
||||||
import { API_ENDPOINT } from '../api/api';
|
import { makeAPIPostCall } from '../api/utils';
|
||||||
import AuthenticationContext from './AuthenticationContext';
|
import AuthenticationContext from './AuthenticationContext';
|
||||||
|
|
||||||
export default function Authenticator() {
|
export default function Authenticator() {
|
||||||
|
@ -13,26 +13,15 @@ export default function Authenticator() {
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetch(`${API_ENDPOINT}/create_session`, {
|
makeAPIPostCall('/create_session', { code, provider })
|
||||||
method: 'POST',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
},
|
|
||||||
body: JSON.stringify({
|
|
||||||
code,
|
|
||||||
provider,
|
|
||||||
}),
|
|
||||||
})
|
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
response.json().then((json) => {
|
if (response.data.status === 'success') {
|
||||||
if (json.status === 'success') {
|
localStorage.setItem('session_token', response.data.token);
|
||||||
localStorage.setItem('session_token', json.token);
|
refreshAuthState && refreshAuthState();
|
||||||
refreshAuthState && refreshAuthState();
|
setStatus('authenticated');
|
||||||
setStatus('authenticated');
|
} else {
|
||||||
} else {
|
setStatus('errored');
|
||||||
setStatus('errored');
|
}
|
||||||
}
|
|
||||||
});
|
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
setStatus('errored');
|
setStatus('errored');
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
import { useCallback } from 'react';
|
import Button from '@material-ui/core/Button';
|
||||||
import { makeAPIPostCall } from '../api/utils';
|
|
||||||
import Card from '@material-ui/core/Card';
|
import Card from '@material-ui/core/Card';
|
||||||
import CardContent from '@material-ui/core/CardContent';
|
import CardContent from '@material-ui/core/CardContent';
|
||||||
import { makeStyles } from '@material-ui/core/styles';
|
import { makeStyles } from '@material-ui/core/styles';
|
||||||
import Button from '@material-ui/core/Button';
|
|
||||||
import Typography from '@material-ui/core/Typography';
|
import Typography from '@material-ui/core/Typography';
|
||||||
import { useState, useEffect } from 'react';
|
|
||||||
import CloudUploadIcon from '@material-ui/icons/CloudUpload';
|
import CloudUploadIcon from '@material-ui/icons/CloudUpload';
|
||||||
|
import { useState } from 'react';
|
||||||
|
import { makeAPIPostCall } from '../api/utils';
|
||||||
|
|
||||||
const useStyles = makeStyles((theme) => ({
|
const useStyles = makeStyles((theme) => ({
|
||||||
root: {
|
root: {
|
||||||
|
@ -22,14 +21,9 @@ const useStyles = makeStyles((theme) => ({
|
||||||
const CreateGroup = () => {
|
const CreateGroup = () => {
|
||||||
const [title, setTitle] = useState('No Title');
|
const [title, setTitle] = useState('No Title');
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
useEffect(() => {}, []);
|
|
||||||
const onClick = () => {
|
const onClick = () => {
|
||||||
console.log({
|
makeAPIPostCall('/groups/', { title });
|
||||||
title: title,
|
|
||||||
});
|
|
||||||
makeAPIPostCall('/group', {
|
|
||||||
title,
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
import { makeAPIPostCall } from '../api/utils';
|
import Button from '@material-ui/core/Button';
|
||||||
import Card from '@material-ui/core/Card';
|
import Card from '@material-ui/core/Card';
|
||||||
import CardContent from '@material-ui/core/CardContent';
|
import CardContent from '@material-ui/core/CardContent';
|
||||||
import { makeStyles } from '@material-ui/core/styles';
|
import { makeStyles } from '@material-ui/core/styles';
|
||||||
import Button from '@material-ui/core/Button';
|
|
||||||
import Typography from '@material-ui/core/Typography';
|
|
||||||
import CloudUploadIcon from '@material-ui/icons/CloudUpload';
|
import CloudUploadIcon from '@material-ui/icons/CloudUpload';
|
||||||
import { useState, useEffect } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
|
import { searchForPlaces } from '../api/google';
|
||||||
|
import { makeAPIPostCall } from '../api/utils';
|
||||||
|
|
||||||
const useStyles = makeStyles((theme) => ({
|
const useStyles = makeStyles((theme) => ({
|
||||||
root: {
|
root: {
|
||||||
maxWidth: 345,
|
maxWidth: 345,
|
||||||
|
@ -30,7 +31,7 @@ const CreatePool = () => {
|
||||||
const [group, setGroup] = useState('');
|
const [group, setGroup] = useState('');
|
||||||
|
|
||||||
const onClick = () => {
|
const onClick = () => {
|
||||||
makeAPIPostCall('/pool', {
|
makeAPIPostCall('/pools/', {
|
||||||
title,
|
title,
|
||||||
description,
|
description,
|
||||||
start_time: start,
|
start_time: start,
|
||||||
|
@ -49,128 +50,140 @@ const CreatePool = () => {
|
||||||
style={{ margin: '0.5rem', background: '#F3F5F4' }}
|
style={{ margin: '0.5rem', background: '#F3F5F4' }}
|
||||||
>
|
>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<Typography gutterBottom variant="h5" component="h2"></Typography>
|
<div className="form-group">
|
||||||
<Typography variant="body2" color="textSecondary" component="p">
|
<h1 className="form-title">Create Pool</h1>
|
||||||
<form>
|
<label className="" htmlFor="title">
|
||||||
<div className="form-group">
|
Pool Title:{' '}
|
||||||
<h1 className="form-title" style={{ fontFamily: 'Impact' }}>
|
</label>
|
||||||
Create Pool
|
<input
|
||||||
</h1>
|
type="text"
|
||||||
<label className="" htmlFor="title">
|
id="title"
|
||||||
Pool Title:{' '}
|
name="title"
|
||||||
</label>
|
className="form-control d-flex"
|
||||||
<input
|
placeholder="Enter title here..."
|
||||||
type="text"
|
onChange={(event) => setTitle(event.target.value)}
|
||||||
id="title"
|
></input>
|
||||||
name="title"
|
</div>
|
||||||
className="form-control d-flex"
|
<div className="form-group">
|
||||||
placeholder="Enter title here..."
|
<label className="" htmlFor="capacity">
|
||||||
onChange={(event) => setTitle(event.target.value)}
|
Pool Capacity:
|
||||||
></input>
|
</label>
|
||||||
</div>
|
<input
|
||||||
<div className="form-group">
|
type="number"
|
||||||
<label className="" htmlFor="capacity">
|
id="capacity"
|
||||||
Pool Capacity:
|
name="capacity"
|
||||||
</label>
|
className="form-control d-flex"
|
||||||
<input
|
placeholder="0"
|
||||||
type="number"
|
onChange={(event) => setCapacity(parseInt(event.target.value))}
|
||||||
id="capacity"
|
></input>
|
||||||
name="capacity"
|
</div>
|
||||||
className="form-control d-flex"
|
<div className="form-group">
|
||||||
placeholder="0"
|
<label className="" htmlFor="pool_start">
|
||||||
onChange={(event) =>
|
Start Time:
|
||||||
setCapacity(parseInt(event.target.value))
|
</label>
|
||||||
}
|
<input
|
||||||
></input>
|
type="datetime-local"
|
||||||
</div>
|
id="pool_start"
|
||||||
<div className="form-group">
|
name="pool_start"
|
||||||
<label className="" htmlFor="pool_start">
|
className="form-control"
|
||||||
Start Time:
|
placeholder=""
|
||||||
</label>
|
onChange={(event) => setStart(event.target.value)}
|
||||||
<input
|
></input>
|
||||||
type="datetime-local"
|
</div>
|
||||||
id="pool_start"
|
<div className="form-group">
|
||||||
name="pool_start"
|
<label className="" htmlFor="pool_end">
|
||||||
className="form-control"
|
End Time:
|
||||||
placeholder=""
|
</label>
|
||||||
onChange={(event) => setStart(event.target.value)}
|
<input
|
||||||
></input>
|
type="datetime-local"
|
||||||
</div>
|
id="pool_end"
|
||||||
<div className="form-group">
|
name="pool_end"
|
||||||
<label className="" htmlFor="pool_end">
|
className="form-control"
|
||||||
End Time:
|
placeholder="Enter text here..."
|
||||||
</label>
|
onChange={(event) => setEnd(event.target.value)}
|
||||||
<input
|
></input>
|
||||||
type="datetime-local"
|
</div>
|
||||||
id="pool_end"
|
<div className="form-group">
|
||||||
name="pool_end"
|
<label className="" htmlFor="pool_direction">
|
||||||
className="form-control"
|
Direction:
|
||||||
placeholder="Enter text here..."
|
</label>
|
||||||
onChange={(event) => setEnd(event.target.value)}
|
<select
|
||||||
></input>
|
id="direction"
|
||||||
</div>
|
name="direction"
|
||||||
<div className="form-group">
|
onChange={(event) => setDirection(event.target.value)}
|
||||||
<label className="" htmlFor="pool_direction">
|
>
|
||||||
Direction:
|
<option value="pickup">Picking Up</option>
|
||||||
</label>
|
<option value="dropoff">Dropping Off</option>
|
||||||
<select
|
</select>
|
||||||
id="direction"
|
</div>
|
||||||
name="direction"
|
<div className="form-group">
|
||||||
onChange={(event) => setDirection(event.target.value)}
|
<label className="" htmlFor="pool_type">
|
||||||
>
|
Type:
|
||||||
<option value="pickup">Picking Up</option>
|
</label>
|
||||||
<option value="dropoff">Dropping Off</option>
|
<select
|
||||||
</select>
|
id="type"
|
||||||
</div>
|
name="type"
|
||||||
<div className="form-group">
|
onChange={(event) => setType(event.target.value)}
|
||||||
<label className="" htmlFor="pool_type">
|
>
|
||||||
Type:
|
<option value="offer">Offering carpool</option>
|
||||||
</label>
|
<option value="request">Requesting carpool</option>
|
||||||
<select
|
</select>
|
||||||
id="type"
|
</div>
|
||||||
name="type"
|
<div className="form-group">
|
||||||
onChange={(event) => setType(event.target.value)}
|
<label className="" htmlFor="title">
|
||||||
>
|
Pool Description:
|
||||||
<option value="offer">Offering carpool</option>
|
</label>
|
||||||
<option value="request">Requesting carpooll</option>
|
<textarea
|
||||||
</select>
|
onChange={(event) => setDescription(event.target.value)}
|
||||||
</div>
|
id="Pool-text"
|
||||||
<div className="form-group">
|
name="Pool-text"
|
||||||
<label className="" htmlFor="title">
|
style={{ height: '200px' }}
|
||||||
Pool Description:
|
className="form-control"
|
||||||
</label>
|
placeholder="Enter text here..."
|
||||||
<textarea
|
/>
|
||||||
onChange={(event) => setDescription(event.target.value)}
|
</div>
|
||||||
id="Pool-text"
|
<div className="form-group">
|
||||||
name="Pool-text"
|
<label className="" htmlFor="pool_start">
|
||||||
style={{ height: '200px' }}
|
Group:
|
||||||
className="form-control"
|
</label>
|
||||||
placeholder="Enter text here..."
|
<input
|
||||||
/>
|
type="text"
|
||||||
</div>
|
className="form-control"
|
||||||
<div className="form-group">
|
placeholder=""
|
||||||
<label className="" htmlFor="pool_start">
|
onChange={(event) => setGroup(event.target.value)}
|
||||||
Group:
|
></input>
|
||||||
</label>
|
</div>
|
||||||
<input
|
<div className="form-group">
|
||||||
type="text"
|
<label className="" htmlFor="location">
|
||||||
className="form-control"
|
Location:
|
||||||
placeholder=""
|
</label>
|
||||||
onChange={(event) => setGroup(event.target.value)}
|
<input
|
||||||
></input>
|
type="text"
|
||||||
</div>
|
className="form-control"
|
||||||
<Button
|
id="location_input"
|
||||||
variant="contained"
|
></input>
|
||||||
color="primary"
|
<button
|
||||||
className={classes.button}
|
onClick={(e) => {
|
||||||
onClick={onClick}
|
e.preventDefault();
|
||||||
startIcon={<CloudUploadIcon />}
|
let input = document.getElementById(
|
||||||
>
|
'location_input'
|
||||||
Submit
|
) as HTMLInputElement;
|
||||||
</Button>
|
let places = searchForPlaces(input.value);
|
||||||
<br />
|
console.log(places);
|
||||||
</form>
|
}}
|
||||||
</Typography>
|
>
|
||||||
|
Search
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
color="primary"
|
||||||
|
className={classes.button}
|
||||||
|
onClick={onClick}
|
||||||
|
startIcon={<CloudUploadIcon />}
|
||||||
|
>
|
||||||
|
Submit
|
||||||
|
</Button>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -10,7 +10,7 @@ const maybePluralize = (count: number, noun: string, suffix = 's') =>
|
||||||
|
|
||||||
const SAMPLE_POOLS: Carpool.Pool[] = [
|
const SAMPLE_POOLS: Carpool.Pool[] = [
|
||||||
{
|
{
|
||||||
id: '1234',
|
_id: '1234',
|
||||||
title: 'TJ Carpool',
|
title: 'TJ Carpool',
|
||||||
description: 'Carpool from TJ track to homes',
|
description: 'Carpool from TJ track to homes',
|
||||||
start_time: '4/10/2021 3:00 PM',
|
start_time: '4/10/2021 3:00 PM',
|
||||||
|
@ -43,7 +43,7 @@ export default function Group() {
|
||||||
const [pools, setPools] = useState<Carpool.Pool[]>(SAMPLE_POOLS);
|
const [pools, setPools] = useState<Carpool.Pool[]>(SAMPLE_POOLS);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
makeAPIGetCall('/group', { groupID: id }).then((res) => {
|
makeAPIGetCall(`/groups/${id}`).then((res) => {
|
||||||
if ('error' in res.data) {
|
if ('error' in res.data) {
|
||||||
setError(true);
|
setError(true);
|
||||||
} else {
|
} else {
|
||||||
|
@ -51,7 +51,7 @@ export default function Group() {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
makeAPIGetCall('/group_pools', { groupID: id }).then((res) => {
|
makeAPIGetCall(`/groups/${id}/pools`).then((res) => {
|
||||||
setPools(res.data.data);
|
setPools(res.data.data);
|
||||||
});
|
});
|
||||||
}, [id]);
|
}, [id]);
|
||||||
|
@ -90,7 +90,7 @@ export default function Group() {
|
||||||
{pools.map((pool, index) => {
|
{pools.map((pool, index) => {
|
||||||
return (
|
return (
|
||||||
<Card style={{ margin: '0.5em' }} key={index}>
|
<Card style={{ margin: '0.5em' }} key={index}>
|
||||||
<a href={'/Pool/' + pool.id} className="card-title">
|
<a href={'/pools/' + pool._id} className="card-title">
|
||||||
{pool.title}
|
{pool.title}
|
||||||
</a>
|
</a>
|
||||||
<p className="text-left">
|
<p className="text-left">
|
||||||
|
|
|
@ -8,6 +8,7 @@ import { makeStyles } from '@material-ui/core/styles';
|
||||||
import Typography from '@material-ui/core/Typography';
|
import Typography from '@material-ui/core/Typography';
|
||||||
import CloudUploadIcon from '@material-ui/icons/CloudUpload';
|
import CloudUploadIcon from '@material-ui/icons/CloudUpload';
|
||||||
import Box from '@material-ui/core/Box';
|
import Box from '@material-ui/core/Box';
|
||||||
|
import { makeAPIGetCall } from '../api/utils';
|
||||||
|
|
||||||
const useStyles = makeStyles((theme) => ({
|
const useStyles = makeStyles((theme) => ({
|
||||||
root: {
|
root: {
|
||||||
|
@ -45,10 +46,23 @@ const Groups = () => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
const [groups, setGroups] = useState<Carpool.Group[]>([
|
||||||
|
{
|
||||||
|
_id: '1234',
|
||||||
|
name: 'TJ',
|
||||||
|
creator_id: 'michael',
|
||||||
|
member_ids: [],
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
callAPI();
|
makeAPIGetCall('/browse/groups').then((res) => {
|
||||||
|
if (res.data.data) {
|
||||||
|
setGroups(res.data.data);
|
||||||
|
}
|
||||||
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className=""
|
className=""
|
||||||
|
@ -72,22 +86,17 @@ const Groups = () => {
|
||||||
</Box>
|
</Box>
|
||||||
<div className="container" style={{ fontFamily: 'Courier New' }}>
|
<div className="container" style={{ fontFamily: 'Courier New' }}>
|
||||||
<br></br>
|
<br></br>
|
||||||
{state.MyGroups.map((group, index) => {
|
|
||||||
let background;
|
{groups.map((group, index) => {
|
||||||
if (index % 2 === 0) {
|
|
||||||
background = '#F1EAE8';
|
|
||||||
} else {
|
|
||||||
background = '#FFFFFF';
|
|
||||||
}
|
|
||||||
return (
|
return (
|
||||||
<Card
|
<Card
|
||||||
className={classes.root + 'd-inline-flex'}
|
className={classes.root + 'd-inline-flex'}
|
||||||
style={{ margin: '0.5rem' }}
|
style={{ margin: '0.5rem' }}
|
||||||
>
|
>
|
||||||
<CardActionArea href={'/group/' + group.id}>
|
<CardActionArea href={'/group/' + group._id}>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<Typography gutterBottom variant="h5" component="h2">
|
<Typography gutterBottom variant="h5" component="h2">
|
||||||
{group.group_title}
|
{group.name}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography
|
<Typography
|
||||||
variant="body2"
|
variant="body2"
|
||||||
|
@ -102,19 +111,27 @@ const Groups = () => {
|
||||||
size="small"
|
size="small"
|
||||||
color="primary"
|
color="primary"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
let link: string = 'localhost:3000/group/' + group.id;
|
alert('Copied to Clipboard');
|
||||||
|
let link: string = 'localhost:3000/group/' + group._id;
|
||||||
navigator.clipboard.writeText(link);
|
navigator.clipboard.writeText(link);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Share
|
Share
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
href={'/group/' + group.id}
|
href={'/group/' + group._id}
|
||||||
size="small"
|
size="small"
|
||||||
color="primary"
|
color="primary"
|
||||||
>
|
>
|
||||||
Learn More
|
Learn More
|
||||||
</Button>
|
</Button>
|
||||||
|
<form action={'/requestgroup/' + group._id} method="POST">
|
||||||
|
<input
|
||||||
|
type="submit"
|
||||||
|
value="Request to Join"
|
||||||
|
className="btn btn-success d-flex"
|
||||||
|
/>
|
||||||
|
</form>
|
||||||
</CardActions>
|
</CardActions>
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
|
|
|
@ -8,6 +8,7 @@ import { makeStyles } from '@material-ui/core/styles';
|
||||||
import Typography from '@material-ui/core/Typography';
|
import Typography from '@material-ui/core/Typography';
|
||||||
import CloudUploadIcon from '@material-ui/icons/CloudUpload';
|
import CloudUploadIcon from '@material-ui/icons/CloudUpload';
|
||||||
import Box from '@material-ui/core/Box';
|
import Box from '@material-ui/core/Box';
|
||||||
|
import { makeAPIGetCall } from '../api/utils';
|
||||||
|
|
||||||
const useStyles = makeStyles((theme) => ({
|
const useStyles = makeStyles((theme) => ({
|
||||||
root: {
|
root: {
|
||||||
|
@ -45,10 +46,23 @@ const MyGroups = () => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
const [groups, setGroups] = useState<Carpool.Group[]>([
|
||||||
|
{
|
||||||
|
_id: '1234',
|
||||||
|
name: 'TJ',
|
||||||
|
creator_id: '12345Q',
|
||||||
|
member_ids: [],
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
callAPI();
|
makeAPIGetCall('/browse/groups').then((res) => {
|
||||||
|
if (res.data.data) {
|
||||||
|
setGroups(res.data.data);
|
||||||
|
}
|
||||||
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className=""
|
className=""
|
||||||
|
@ -72,7 +86,7 @@ const MyGroups = () => {
|
||||||
</Box>
|
</Box>
|
||||||
<div className="container" style={{ fontFamily: 'Courier New' }}>
|
<div className="container" style={{ fontFamily: 'Courier New' }}>
|
||||||
<br></br>
|
<br></br>
|
||||||
{state.MyGroups.map((group, index) => {
|
{groups.map((group, index) => {
|
||||||
let background;
|
let background;
|
||||||
if (index % 2 === 0) {
|
if (index % 2 === 0) {
|
||||||
background = '#F1EAE8';
|
background = '#F1EAE8';
|
||||||
|
@ -84,10 +98,10 @@ const MyGroups = () => {
|
||||||
className={classes.root + 'd-inline-flex'}
|
className={classes.root + 'd-inline-flex'}
|
||||||
style={{ margin: '0.5rem' }}
|
style={{ margin: '0.5rem' }}
|
||||||
>
|
>
|
||||||
<CardActionArea href={'/group/' + group.id}>
|
<CardActionArea href={'/group/' + group._id}>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<Typography gutterBottom variant="h5" component="h2">
|
<Typography gutterBottom variant="h5" component="h2">
|
||||||
{group.group_title}
|
{group.name}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography
|
<Typography
|
||||||
variant="body2"
|
variant="body2"
|
||||||
|
@ -102,14 +116,15 @@ const MyGroups = () => {
|
||||||
size="small"
|
size="small"
|
||||||
color="primary"
|
color="primary"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
let link: string = 'localhost:3000/group/' + group.id;
|
alert('Copied to Clipboard');
|
||||||
|
let link: string = 'localhost:3000/group/' + group._id;
|
||||||
navigator.clipboard.writeText(link);
|
navigator.clipboard.writeText(link);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Share
|
Share
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
href={'/group/' + group.id}
|
href={'/group/' + group._id}
|
||||||
size="small"
|
size="small"
|
||||||
color="primary"
|
color="primary"
|
||||||
>
|
>
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import { API_ENDPOINT } from '../api/api';
|
import { API_ENDPOINT } from '../api/api';
|
||||||
|
import { makeAPIGetCall } from '../api/utils';
|
||||||
|
|
||||||
const MyPools = () => {
|
const MyPools = () => {
|
||||||
// const id = props.match.params.id;
|
// const id = props.match.params.id;
|
||||||
|
@ -55,14 +56,11 @@ const MyPools = () => {
|
||||||
]);
|
]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log(process.env);
|
makeAPIGetCall('/users/@me/pools').then((res) => {
|
||||||
fetch(`${API_ENDPOINT}/my_pools`)
|
if (res.data.data) {
|
||||||
.then((response) => response.json())
|
setPools(res.data.data);
|
||||||
.then((json) => {
|
}
|
||||||
if (json) {
|
});
|
||||||
setPools(json.data);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const maybePluralize = (count: number, noun: string, suffix = 's') =>
|
const maybePluralize = (count: number, noun: string, suffix = 's') =>
|
||||||
|
@ -96,7 +94,7 @@ const MyPools = () => {
|
||||||
className="card card-body text-left"
|
className="card card-body text-left"
|
||||||
style={{ backgroundColor: background }}
|
style={{ backgroundColor: background }}
|
||||||
>
|
>
|
||||||
<a href={'/Pool/' + pool.id} className="card-title">
|
<a href={'/pools/' + pool.id} className="card-title">
|
||||||
{pool.pool_title}
|
{pool.pool_title}
|
||||||
</a>
|
</a>
|
||||||
<p className="text-left">
|
<p className="text-left">
|
||||||
|
|
|
@ -5,7 +5,7 @@ import Card from '@material-ui/core/Card';
|
||||||
import Textarea from '@material-ui/core/TextareaAutosize';
|
import Textarea from '@material-ui/core/TextareaAutosize';
|
||||||
import Typography from '@material-ui/core/Typography';
|
import Typography from '@material-ui/core/Typography';
|
||||||
import Comment from './Comment';
|
import Comment from './Comment';
|
||||||
import { makeAPIPostCall } from '../api/utils';
|
import { makeAPIGetCall, makeAPIPostCall } from '../api/utils';
|
||||||
import AuthenticationContext from './AuthenticationContext';
|
import AuthenticationContext from './AuthenticationContext';
|
||||||
|
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
|
@ -76,8 +76,8 @@ export default function Pool() {
|
||||||
|
|
||||||
const onRegister = useCallback(() => {
|
const onRegister = useCallback(() => {
|
||||||
if (user) {
|
if (user) {
|
||||||
let userID = user.id;
|
let userID = user._id;
|
||||||
makeAPIPostCall('/join_pool', { id }).then(() => {
|
makeAPIPostCall(`/pools/${id}/join`).then(() => {
|
||||||
if (pool) {
|
if (pool) {
|
||||||
setPool({
|
setPool({
|
||||||
...pool,
|
...pool,
|
||||||
|
@ -89,13 +89,11 @@ export default function Pool() {
|
||||||
}, [user, id, pool]);
|
}, [user, id, pool]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetch(`${process.env.REACT_APP_API_ENDPOINT}/pool/${id}`)
|
makeAPIGetCall(`/pools/${id}`).then((response) => {
|
||||||
.then((response) => response.json())
|
if (response.data.data) {
|
||||||
.then((data) => {
|
setPool(response.data.data);
|
||||||
if (data !== undefined) {
|
}
|
||||||
setPool(data);
|
});
|
||||||
}
|
|
||||||
});
|
|
||||||
}, [id]);
|
}, [id]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -106,7 +104,7 @@ export default function Pool() {
|
||||||
{pool.title}
|
{pool.title}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography variant="subtitle1">
|
<Typography variant="subtitle1">
|
||||||
<b>Capacity</b>: {pool.participant_ids.length} / {pool.capacity}
|
<b>Capacity</b>: {pool.participant_ids?.length} / {pool.capacity}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography variant="subtitle1">
|
<Typography variant="subtitle1">
|
||||||
<b>Start Time</b>: {pool.start_time}
|
<b>Start Time</b>: {pool.start_time}
|
||||||
|
@ -122,7 +120,7 @@ export default function Pool() {
|
||||||
style={{ marginTop: '0.5rem' }}
|
style={{ marginTop: '0.5rem' }}
|
||||||
onClick={onRegister}
|
onClick={onRegister}
|
||||||
>
|
>
|
||||||
{pool.participant_ids.includes(user.id)
|
{pool.participant_ids?.includes(user._id)
|
||||||
? 'Unregister'
|
? 'Unregister'
|
||||||
: 'Register'}
|
: 'Register'}
|
||||||
</Button>
|
</Button>
|
||||||
|
|
3
src/components/PoolMap.tsx
Normal file
3
src/components/PoolMap.tsx
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
export default function PoolMap() {
|
||||||
|
//
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
import { useState, useEffect } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
import { API_ENDPOINT } from '../api/api';
|
import { API_ENDPOINT } from '../api/api';
|
||||||
|
import { makeAPIGetCall } from '../api/utils';
|
||||||
|
|
||||||
const maybePluralize = (count: number, noun: string, suffix = 's') =>
|
const maybePluralize = (count: number, noun: string, suffix = 's') =>
|
||||||
`${count} ${noun}${count !== 1 ? suffix : ''}`;
|
`${count} ${noun}${count !== 1 ? suffix : ''}`;
|
||||||
|
@ -58,14 +59,11 @@ const Pools = () => {
|
||||||
]);
|
]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log(process.env);
|
makeAPIGetCall(`/users/@me/pools`).then((res) => {
|
||||||
fetch(`${API_ENDPOINT}/my_pools`)
|
if (res.data.data) {
|
||||||
.then((response) => response.json())
|
setPools(res.data.data);
|
||||||
.then((json) => {
|
}
|
||||||
if (json) {
|
});
|
||||||
setPools(json.data);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -97,7 +95,7 @@ const Pools = () => {
|
||||||
className="card card-body text-left"
|
className="card card-body text-left"
|
||||||
style={{ backgroundColor: background }}
|
style={{ backgroundColor: background }}
|
||||||
>
|
>
|
||||||
<a href={'/Pool/' + pool.id} className="card-title">
|
<a href={'/pools/' + pool._id} className="card-title">
|
||||||
{pool.title}
|
{pool.title}
|
||||||
</a>
|
</a>
|
||||||
<p className="text-left">
|
<p className="text-left">
|
||||||
|
@ -105,7 +103,7 @@ const Pools = () => {
|
||||||
</p>
|
</p>
|
||||||
<p className="text-left">Start Time: {pool.start_time}</p>
|
<p className="text-left">Start Time: {pool.start_time}</p>
|
||||||
<p className="text-left">End Time: {pool.end_time}</p>
|
<p className="text-left">End Time: {pool.end_time}</p>
|
||||||
<p className="" style={{color: '#9E6105'}}>
|
<p className="" style={{ color: '#9E6105' }}>
|
||||||
{maybePluralize(pool.comments.length, 'comment')}
|
{maybePluralize(pool.comments.length, 'comment')}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -20,14 +20,18 @@ const useStyles = makeStyles({
|
||||||
|
|
||||||
const Profile = () => {
|
const Profile = () => {
|
||||||
const { user } = useContext(AuthenticationContext);
|
const { user } = useContext(AuthenticationContext);
|
||||||
// const [groups, setGroups] = useState<Carpool.Group[]>([]);
|
const [groups, setGroups] = useState<Carpool.Group[]>([]);
|
||||||
const [pools, setPools] = useState<Carpool.Pool[]>([]);
|
const [pools, setPools] = useState<Carpool.Pool[]>([]);
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
makeAPIGetCall('/my_pools').then((res) => {
|
makeAPIGetCall('/users/@me/pools').then((res) => {
|
||||||
if (res.data.data) setPools(res.data.data);
|
if (res.data.data) setPools(res.data.data);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
makeAPIGetCall('/users/@me/groups').then((res) => {
|
||||||
|
if (res.data.data) setGroups(res.data.data);
|
||||||
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
if (!user) {
|
if (!user) {
|
||||||
|
@ -47,16 +51,16 @@ const Profile = () => {
|
||||||
</h1>
|
</h1>
|
||||||
<div className="container">
|
<div className="container">
|
||||||
<h2>
|
<h2>
|
||||||
<u>{user.username}'s Pools</u>
|
<u>My Pools (private)</u>
|
||||||
</h2>
|
</h2>
|
||||||
<div className="">
|
<div>
|
||||||
{pools.map((pool) => {
|
{pools.map((pool) => {
|
||||||
return (
|
return (
|
||||||
<Card
|
<Card
|
||||||
className={classes.root + 'd-inline-flex'}
|
className={classes.root + 'd-inline-flex'}
|
||||||
style={{ margin: '0.5rem' }}
|
style={{ margin: '0.5rem' }}
|
||||||
>
|
>
|
||||||
<CardActionArea href={'/pool/' + pool.id}>
|
<CardActionArea href={'/pools/' + pool._id}>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<Typography gutterBottom variant="h5" component="h2">
|
<Typography gutterBottom variant="h5" component="h2">
|
||||||
{pool.title}
|
{pool.title}
|
||||||
|
@ -75,14 +79,14 @@ const Profile = () => {
|
||||||
size="small"
|
size="small"
|
||||||
color="primary"
|
color="primary"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
let link: string = 'localhost:3000/pool/' + pool.id;
|
let link: string = 'localhost:3000/pools/' + pool._id;
|
||||||
navigator.clipboard.writeText(link);
|
navigator.clipboard.writeText(link);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Share
|
Share
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
href={'/pool/' + pool.id}
|
href={'/pools/' + pool._id}
|
||||||
size="small"
|
size="small"
|
||||||
color="primary"
|
color="primary"
|
||||||
>
|
>
|
||||||
|
@ -93,6 +97,24 @@ const Profile = () => {
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<h2>
|
||||||
|
<u>My Groups (private)</u>
|
||||||
|
<div>
|
||||||
|
{groups.map((group) => {
|
||||||
|
return (
|
||||||
|
<Card
|
||||||
|
key={group._id}
|
||||||
|
style={{ padding: '0.5rem', margin: '0.5rem' }}
|
||||||
|
>
|
||||||
|
<h1>
|
||||||
|
<a href={'/groups/' + group._id}>{group.name}</a>
|
||||||
|
</h1>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,10 +1,6 @@
|
||||||
import React, {
|
import { useState, useEffect, FormEventHandler } from 'react';
|
||||||
useState,
|
|
||||||
useEffect,
|
|
||||||
useCallback,
|
|
||||||
FormEventHandler,
|
|
||||||
} from 'react';
|
|
||||||
import { useParams } from 'react-router-dom';
|
import { useParams } from 'react-router-dom';
|
||||||
|
import { makeAPIGetCall } from '../api/utils';
|
||||||
|
|
||||||
const UpdatePool = () => {
|
const UpdatePool = () => {
|
||||||
const id = useParams<{ id: string }>().id;
|
const id = useParams<{ id: string }>().id;
|
||||||
|
@ -21,26 +17,17 @@ const UpdatePool = () => {
|
||||||
comments: ['What is the covid vaccination status of all the participants?'],
|
comments: ['What is the covid vaccination status of all the participants?'],
|
||||||
});
|
});
|
||||||
|
|
||||||
const callAPI = useCallback(() => {
|
|
||||||
fetch(`${process.env.REACT_APP_API_ENDPOINT}/pool/${id}`)
|
|
||||||
.then((response) => response.json())
|
|
||||||
.then((data) => {
|
|
||||||
if (data !== undefined) {
|
|
||||||
setPool(data);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}, [id]);
|
|
||||||
const onSubmit: FormEventHandler<HTMLFormElement> = (e) => {
|
const onSubmit: FormEventHandler<HTMLFormElement> = (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
fetch(`${process.env.REACT_APP_API_ENDPOINT}/update_pool`)
|
makeAPIGetCall(`/pools/${id}`).then((res) => {
|
||||||
.then((response) => response.json())
|
console.log(res);
|
||||||
.then((data) => {
|
});
|
||||||
console.log(data);
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
callAPI();
|
makeAPIGetCall(`/pools/${id}`).then((res) => {
|
||||||
}, [callAPI]);
|
if (res.data.data) setPool(res.data.data);
|
||||||
|
});
|
||||||
|
}, [id]);
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className="bg-dark"
|
className="bg-dark"
|
||||||
|
|
8
src/types.d.ts
vendored
8
src/types.d.ts
vendored
|
@ -1,6 +1,6 @@
|
||||||
declare namespace Carpool {
|
declare namespace Carpool {
|
||||||
export interface Group {
|
export interface Group {
|
||||||
id: string;
|
_id: string;
|
||||||
name: string;
|
name: string;
|
||||||
member_ids: string[];
|
member_ids: string[];
|
||||||
creator_id: string;
|
creator_id: string;
|
||||||
|
@ -8,14 +8,14 @@ declare namespace Carpool {
|
||||||
|
|
||||||
// Omits the email attribute
|
// Omits the email attribute
|
||||||
export interface PublicUser {
|
export interface PublicUser {
|
||||||
id: string;
|
_id: string;
|
||||||
username: string;
|
username: string;
|
||||||
first_name: string;
|
first_name: string;
|
||||||
last_name: string;
|
last_name: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface User {
|
export interface User {
|
||||||
id: string;
|
_id: string;
|
||||||
email: string;
|
email: string;
|
||||||
username: string;
|
username: string;
|
||||||
first_name: string;
|
first_name: string;
|
||||||
|
@ -31,7 +31,7 @@ declare namespace Carpool {
|
||||||
export type Status = 'pending' | 'cancelled' | 'completed' | 'interrupted';
|
export type Status = 'pending' | 'cancelled' | 'completed' | 'interrupted';
|
||||||
|
|
||||||
export interface Pool {
|
export interface Pool {
|
||||||
id: string;
|
_id: string;
|
||||||
title: string;
|
title: string;
|
||||||
description: string;
|
description: string;
|
||||||
participant_ids: string[];
|
participant_ids: string[];
|
||||||
|
|
Loading…
Reference in New Issue
Block a user