Brought app up to modern standards

This commit is contained in:
Ceferino Patino 2022-12-17 12:12:00 -06:00
commit f6c739bfe1
50 changed files with 812 additions and 794 deletions

View file

@ -12,6 +12,7 @@
"@testing-library/react": "^12.1.3",
"@testing-library/user-event": "^13.5.0",
"axios": "^0.26.1",
"buffer": "^6.0.3",
"js-cookie": "^3.0.1",
"mic-recorder-to-mp3": "^2.2.2",
"react": "^17.0.2",

View file

@ -1,20 +1,20 @@
import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom';
import { Layout } from './containers';
import {
Layout,
Login,
Register,
MainPage,
EditUser,
Recover,
Reset,
OwnedOrgs,
MemberOrgs,
OrgDashboard,
} from './containers';
import { ContextProvider } from './contexts';
import MainPage from './controllers/MainPage';
import Form from './components/Form';
import Login from './controllers/Login';
import Register from './controllers/Register';
import EditUser from './controllers/EditUser';
import Recover from './controllers/Recover';
import Reset from './controllers/Reset';
import OwnedOrgs from './controllers/OwnedOrgs';
import MemberOrgs from './controllers/MemberOrgs';
import OrgDashboard from './controllers/OrgDashboard';
import UpdateOrganization from './controllers/UpdateOrganization';
import UpdateOrganization from './controllers/UpdateOrganizationFormController';
function App() {
return (
@ -22,24 +22,24 @@ function App() {
<ContextProvider>
<Routes>
<Route path='' element={<Layout />}>
{/* <Route index element={<MainPage />} /> */}
<Route index element={<MainPage />} />
<Route path='/login' element={<Login />} />
<Route path='/register' element={<Register />} />
{/* <Route path='update' element={<EditUser />} /> */}
{/* <Route path='recover' element={<Form />}>
<Route path='/update' element={<EditUser />} />
<Route path='recover'>
<Route index element={<Recover />} />
<Route path=':id' element={<Reset />} />
</Route> */}
</Route>
{/* <Route path='org'>
<Route path='org'>
<Route index element={<OwnedOrgs />} />
<Route path='joined' element={<MemberOrgs />} />
<Route path=':orgID'>
<Route index element={<OrgDashboard />} />
<Route path='update' element={<UpdateOrganization />} />
</Route>
</Route> */}
</Route>
<Route path='*' element={<Navigate to='' />} />
</Route>

View file

@ -1,4 +1,3 @@
import React, { useState } from 'react';
import { Link } from 'react-router-dom';
import {
Accordion,
@ -18,11 +17,13 @@ import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
import PlayArrowIcon from '@mui/icons-material/PlayArrow';
import { DataGrid } from '@mui/x-data-grid';
import MemberUnit from './MemberUnit';
import { MemberUnit } from '.';
import { DynamicPaper, DynamicStack } from './StyledElements';
function Dashboard({
rows,
open,
handleOpen,
setSelection,
onClick,
org,
@ -37,8 +38,6 @@ function Dashboard({
const sm = useMediaQuery((theme) => theme.breakpoints.only('sm'));
const md = useMediaQuery((theme) => theme.breakpoints.only('md'));
const [open, setOpen] = useState(false);
const linkStyle = { textDecoration: 'none', color: 'inherit' };
const columns = [
{ field: 'id', headerName: 'ID', flex: 1 },
@ -67,10 +66,6 @@ function Dashboard({
{ field: 'email', headerName: 'Email', flex: 10, sortable: false },
];
function handleOpen() {
setOpen((initial) => (initial ? false : true));
}
const buttonGroupOrientation = () => {
if (xs) return 'vertical';
};
@ -86,25 +81,19 @@ function Dashboard({
}
return (
<React.Fragment>
<>
<Box sx={{ padding: '2vh' }}>
<Accordion expanded={open} onChange={handleOpen}>
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
<Typography variant='h6'>
Organizations/{org.name}
</Typography>
<Typography variant='h6'>Organizations / {org.name}</Typography>
</AccordionSummary>
<AccordionDetails>
<Box sx={{ marginTop: '1vh' }} fullWidth>
<Grid
container
columns={{ xs: 3, sm: 12, md: 12 }}
spacing={1}
>
<Grid container columns={{ xs: 3, sm: 12, md: 12 }} spacing={1}>
<Grid item xs={3}>
<Stack>
<Typography variant='body1'>
Organization ID: {org.orgID}
Organization ID: {org.id}
</Typography>
<Typography variant='body1'>
Members: {org.memberCount}
@ -117,8 +106,7 @@ function Dashboard({
<Grid item xs={3}>
<Stack>
<Typography variant='body1'>
Owner:{' '}
{`${org.owner.firstName} ${org.owner.lastName}`}
Owner: {`${org.owner.firstName} ${org.owner.lastName}`}
</Typography>
<Typography variant='body1'>
Email: {org.owner.email}
@ -128,23 +116,17 @@ function Dashboard({
<Grid item xs={3} sm={6} md={6}>
<DynamicStack spacing={1}>
{status ? (
<React.Fragment>
<>
<ButtonGroup
variant='outlined'
orientation={buttonGroupOrientation()}
>
<Button color='warning'>
<Link
to='update'
style={linkStyle}
>
<Link to='update' style={linkStyle}>
Edit {org.name}
</Link>
</Button>
<Button
color='error'
onClick={handleDelete}
>
<Button color='error' onClick={handleDelete}>
Delete {org.name}
</Button>
</ButtonGroup>
@ -152,31 +134,19 @@ function Dashboard({
variant='outlined'
orientation={buttonGroupOrientation()}
>
<Button
color='success'
onClick={copyID}
>
<Button color='success' onClick={copyID}>
Copy Org ID
</Button>
<Button
color='success'
onClick={copyJoinLink}
>
<Button color='success' onClick={copyJoinLink}>
Copy Org Join Link
</Button>
<Button
color='error'
onClick={removeSelected}
>
<Button color='error' onClick={removeSelected}>
Remove People
</Button>
</ButtonGroup>
</React.Fragment>
</>
) : (
<Button
color='error'
onClick={leaveOrg}
>
<Button color='error' onClick={leaveOrg}>
Leave Org
</Button>
)}
@ -187,16 +157,11 @@ function Dashboard({
</AccordionDetails>
</Accordion>
</Box>
<Collapse
collapsedSize={calculateCollapsedSize()}
in={open ? false : true}
>
<Collapse collapsedSize={calculateCollapsedSize()} in={open ? false : true}>
<DynamicPaper>
{(xs || sm) &&
rows.map((member) => {
return (
<MemberUnit member={member} onClick={onClick} />
);
return <MemberUnit member={member} onClick={onClick} />;
})}
{md && (
<Box height={calculateTableHeight()}>
@ -214,7 +179,7 @@ function Dashboard({
)}
</DynamicPaper>
</Collapse>
</React.Fragment>
</>
);
}

View file

@ -2,8 +2,8 @@ import React from 'react';
import { Link } from 'react-router-dom';
import { Box, Typography } from '@mui/material';
import Form from './Form';
import RecordMp3 from './RecordMp3';
import { Form } from '.';
import { RecordMp3 } from '../controllers';
import { FormSubmit, FormTextField } from './StyledElements';
function EditUserForm({ form, error, handleSubmit, handleChange }) {

View file

@ -1,22 +1,17 @@
import React from 'react';
import { Outlet } from 'react-router-dom';
import { Box, Grid, Paper, Typography } from '@mui/material';
import { Box, Grid, Card, Typography, CardContent, Alert } from '@mui/material';
import { useTheme } from '@mui/material/styles';
function Form({ children, text }) {
function Form({ children, text, error }) {
const theme = useTheme();
return (
<Box sx={{ flexGrow: 1 }}>
<Grid
container
spacing={2}
alignItems='center'
style={{ height: '95vh' }}
>
<Grid container spacing={2} alignItems='center' style={{ height: '95vh' }}>
<Grid item xs={0.5} sm={2} md={4} />
<Grid item xs={11} sm={8} md={4}>
<Paper
<Card
sx={{
...theme.typography.body2,
padding: '2vh',
@ -24,17 +19,20 @@ function Form({ children, text }) {
color: theme.palette.text.secondary,
}}
>
{text && (
<Typography
variant='h4'
sx={{ marginTop: '1vh 0vh' }}
>
{text}
</Typography>
)}
{children}
<Outlet />
</Paper>
<CardContent>
{text && (
<Typography
variant='h5'
sx={{ margin: '1vh 0vh', fontWeight: 'bold' }}
>
{text}
</Typography>
)}
{children}
<Outlet />
{error && <Alert severity='error'>{error}</Alert>}
</CardContent>
</Card>
</Grid>
<Grid item xs={0.5} sm={2} md={4} />
</Grid>

View file

@ -1,17 +1,14 @@
import React from 'react';
import { Link } from 'react-router-dom';
import { Box, Checkbox, FormControlLabel, Typography } from '@mui/material';
import { Checkbox, FormControlLabel, Typography } from '@mui/material';
import Form from './Form';
import { Form } from '.';
import { FormSubmit, FormTextField } from './StyledElements';
function Login({ form, error, handleSubmit, handleChange, handleCheckboxChange }) {
function Login({ form, handleSubmit, handleChange, handleCheckboxChange, error }) {
return (
<Form>
<Form text='Login' error={error}>
<form onSubmit={handleSubmit}>
<Typography variant='h5' sx={{ margin: '1vh 0vh', fontWeight: 'bold' }}>
Login
</Typography>
<FormTextField
required
label='Email'
@ -42,13 +39,6 @@ function Login({ form, error, handleSubmit, handleChange, handleCheckboxChange }
onChange={handleCheckboxChange}
/>
</div>
{error && (
<Box textAlign='right'>
<Typography variant='body2' color='error'>
{error}
</Typography>
</Box>
)}
<FormSubmit color='primary' type='submit'>
Login
</FormSubmit>

View file

@ -6,24 +6,12 @@ import OrgUnit from './OrgUnit';
import StackItem from './StackItem';
import { Form, FormButton, FormField } from './StyledElements';
function MainPageBase({
form,
orgs,
ownedOrgs,
joinOrg,
createOrg,
handleChange,
}) {
function MainPageBase({ form, orgs, ownedOrgs, joinOrg, createOrg, handleChange }) {
const linkStyle = { textDecoration: 'none', color: 'inherit' };
return (
<Box sx={{ flexGrow: 1 }}>
<Grid
container
spacing={2}
alignItems='center'
style={{ height: '95vh' }}
>
<Grid container spacing={2} alignItems='center' style={{ height: '95vh' }}>
<Grid item xs={0.5} sm={2} md={4} />
<Grid item xs={11} sm={8} md={4}>
<Stack spacing={2}>
@ -36,10 +24,7 @@ function MainPageBase({
value={form.id}
onChange={handleChange}
/>
<FormButton
type='submit'
variant='outlined'
>
<FormButton type='submit' variant='outlined'>
Join Organization
</FormButton>
</Form>
@ -54,10 +39,7 @@ function MainPageBase({
value={form.name}
onChange={handleChange}
/>
<FormButton
type='submit'
variant='outlined'
>
<FormButton type='submit' variant='outlined'>
Create Organization
</FormButton>
</Form>
@ -76,7 +58,7 @@ function MainPageBase({
)}
{ownedOrgs.map((org) => (
<OrgUnit org={org} />
<OrgUnit org={org} key={org.id} />
))}
</StackItem>
<StackItem>
@ -92,7 +74,7 @@ function MainPageBase({
)}
{orgs.map((org) => (
<OrgUnit org={org} />
<OrgUnit org={org} key={org.id} />
))}
</StackItem>
</Stack>

View file

@ -1,22 +1,26 @@
import DarkModeIcon from '@mui/icons-material/DarkMode';
import LightModeIcon from '@mui/icons-material/LightMode';
import MailIcon from '@mui/icons-material/Mail';
import MenuIcon from '@mui/icons-material/Menu';
import { AppBar, Box, Button, IconButton, Toolbar, Typography } from '@mui/material';
import { Link } from 'react-router-dom';
export default function Navbar({ logout, userData, mode, toggleMode }) {
function NavbarControls() {
return userData.username ? (
<Button
color='inherit'
component={Link}
to='/login'
onClick={logout}
sx={{ margin: '0 1vh' }}
>
Logout
</Button>
return userData.email ? (
<>
<Button color='inherit' component={Link} to='/update'>
Account
</Button>
<Button
color='inherit'
component={Link}
to='/login'
onClick={logout}
sx={{ margin: '0 1vh' }}
>
Logout
</Button>
</>
) : (
<>
<Button color='inherit' component={Link} to='/login'>

View file

@ -1,11 +1,5 @@
import React from 'react';
import { Link } from 'react-router-dom';
import {
Accordion,
AccordionDetails,
AccordionSummary,
Typography,
} from '@mui/material';
import { Accordion, AccordionDetails, AccordionSummary, Typography } from '@mui/material';
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
function OrgUnit({ org }) {

View file

@ -2,9 +2,9 @@ import React from 'react';
import { Box, Paper, Typography } from '@mui/material';
import { useTheme } from '@mui/material/styles';
import OrgUnit from './OrgUnit';
import { OrgUnit } from '.';
function Organizations({ orgs }) {
function OrganizationList({ orgs }) {
const theme = useTheme();
return (
@ -29,4 +29,4 @@ function Organizations({ orgs }) {
);
}
export default Organizations;
export default OrganizationList;

View file

@ -1,107 +1,10 @@
import React, { useEffect, useState } from 'react';
import axios from 'axios';
import Cookies from 'js-cookie';
import MicRecorder from 'mic-recorder-to-mp3';
import Mic from '@mui/icons-material/Mic';
import PlayArrow from '@mui/icons-material/PlayArrow';
import SaveAs from '@mui/icons-material/SaveAs';
import Upload from '@mui/icons-material/Upload';
import { IconButton } from '@mui/material';
function RecordMp3() {
const [recorder] = useState(
new MicRecorder({
bitRate: 128,
})
);
const [recording, setRecording] = useState(false);
const [uploadedFile, setUploadedFile] = useState(null);
const [audio, setAudio] = useState(null);
useEffect(() => {
axios
.get(
`${
process.env.REACT_APP_DOMAIN_ROOT
}/public/audio/${Cookies.get('userID')}.mp3`,
{
responseType: 'blob',
}
)
.then((res) => {
setUploadedFile(() => {
// Retrieve audio file of user if exists
return new File([res.data], 'userAudio.mp3', {
type: res.data.type,
lastModified: Date.now(),
});
});
});
}, []);
function togglePlay() {
if (audio && !audio.ended) {
// Reset audio and reset if track is playing
audio.pause();
audio.currentTime = 0;
setAudio(() => null);
} else {
// Set audio to file and play
const audioFile = new Audio(URL.createObjectURL(uploadedFile));
setAudio(() => audioFile);
audioFile.play();
}
}
function record() {
if (recording) {
// Stop recording then set uploaded file to mp3 instance
setRecording(() => false);
recorder
.stop()
.getMp3()
.then(([buffer, blob]) => {
setUploadedFile(() => {
return new File(buffer, 'userAudio.mp3', {
type: blob.type,
lastModified: Date.now(),
});
});
});
} else {
// Start recording
setRecording(() => true);
recorder.start().catch((e) => {
console.error(e);
});
}
}
function uploadRecord() {
setUploadedFile(() => {
return document.getElementById('icon-button-file').files[0];
});
}
async function handleSubmit(e) {
e.preventDefault();
// Create form data object and attach file and user token
var formData = new FormData();
formData.append('audioFile', uploadedFile, 'userAudio.mp3');
formData.append('token', Cookies.get('token'));
await axios.post(
`${process.env.REACT_APP_API_ROOT}/auth/audio`,
formData,
{
headers: {
'Content-Type': 'multipart/form-data',
},
}
);
}
function RecordMp3({ togglePlay, record, uploadRecord, handleSubmit }) {
return (
<form onSubmit={handleSubmit}>
<IconButton onClick={togglePlay}>

View file

@ -1,39 +1,22 @@
import React from 'react';
import { Box, Typography } from '@mui/material';
import { Form } from '.';
import { FormSubmit, FormTextField } from './StyledElements';
function RecoverForm({ form, error, success, handleSubmit, handleChange }) {
function RecoverForm({ form, error, handleSubmit, handleChange }) {
return (
<form onSubmit={handleSubmit}>
<Typography variant='h4' sx={{ marginTop: '1vh 0vh' }}>
Recover my Password
</Typography>
<FormTextField
required
label='Email'
name='email'
onChange={handleChange}
value={form.email}
/>
{error && (
<Box textAlign='right'>
<Typography variant='body2' color='error'>
{error}
</Typography>
</Box>
)}
{success && (
<Box textAlign='right'>
<Typography variant='body2' color='primary'>
{success}
</Typography>
</Box>
)}
<FormSubmit color='primary' type='submit'>
Recover my password
</FormSubmit>
</form>
<Form text='Recover Password' error={error}>
<form onSubmit={handleSubmit}>
<FormTextField
required
label='Email'
name='email'
onChange={handleChange}
value={form.email}
/>
<FormSubmit color='primary' type='submit'>
Recover my password
</FormSubmit>
</form>
</Form>
);
}

View file

@ -6,7 +6,7 @@ import { FormSubmit, FormTextField } from './StyledElements';
function RegisterForm({ form, handleSubmit, handleChange, error }) {
return (
<Form text='Create an Account'>
<Form text='Create an Account' error={error}>
<form onSubmit={handleSubmit}>
<FormTextField
required
@ -52,13 +52,6 @@ function RegisterForm({ form, handleSubmit, handleChange, error }) {
value={form.confirmPassword}
other={{ type: 'password' }}
/>
{error && (
<Box textAlign='right'>
<Typography variant='body2' color='secondary'>
{error}
</Typography>
</Box>
)}
<FormSubmit
color='primary'
type='submit'

View file

@ -1,45 +1,35 @@
import React from 'react';
import { Box, Typography } from '@mui/material';
import { Form } from '.';
import { FormSubmit, FormTextField } from './StyledElements';
function ResetForm({ form, handleSubmit, handleChange, error }) {
return (
<form onSubmit={handleSubmit}>
<Typography variant='h4' sx={{ marginTop: '1vh 0vh' }}>
Reset my Password
</Typography>
<FormTextField
required
label='Password'
name='password'
onChange={handleChange}
value={form.password}
other={{ type: 'password' }}
/>
<FormTextField
required
label='Confirm Password'
name='confirmPassword'
onChange={handleChange}
value={form.confirmPassword}
other={{ type: 'password' }}
/>
{error && (
<Box textAlign='right'>
<Typography variant='body2' color='error'>
{error}
</Typography>
</Box>
)}
<FormSubmit
color='primary'
type='submit'
other={{ disabled: form.password !== form.confirmPassword }}
>
Reset my Password
</FormSubmit>
</form>
<Form text='Reset Password' error={error}>
<form onSubmit={handleSubmit}>
<FormTextField
required
label='Password'
name='password'
onChange={handleChange}
value={form.password}
other={{ type: 'password' }}
/>
<FormTextField
required
label='Confirm Password'
name='confirmPassword'
onChange={handleChange}
value={form.confirmPassword}
other={{ type: 'password' }}
/>
<FormSubmit
color='primary'
type='submit'
other={{ disabled: form.password !== form.confirmPassword }}
>
Reset my Password
</FormSubmit>
</form>
</Form>
);
}

View file

@ -1,4 +1,3 @@
import React from 'react';
import { Paper, Typography } from '@mui/material';
import { useTheme } from '@mui/material/styles';

View file

@ -1,16 +1,10 @@
import React from 'react';
import { Typography } from '@mui/material';
import Form from './Form';
import { Form } from '.';
import { FormSubmit, FormTextField } from './StyledElements';
function UpdateOrganizationForm({ name, handleSubmit, handleChange }) {
return (
<Form text='Rename Organization'>
<form onSubmit={handleSubmit}>
<Typography variant='h4' sx={{ marginTop: '1vh 0vh' }}>
Rename Organization
</Typography>
<FormTextField
required
label='Name'

View file

@ -1,4 +1,33 @@
import Navbar from './Navbar';
import MobileNavbar from './MobileNavbar';
import LoginForm from './LoginForm';
import MainPageBase from './MainPageBase';
import EditUserForm from './EditUserForm';
import Form from './Form';
import OrgUnit from './OrgUnit';
import StackItem from './StackItem';
import RecordMp3 from './RecordMp3';
import RecoverForm from './RecoverForm';
import ResetForm from './ResetForm';
import OrganizationList from './OrganizationList';
import MemberUnit from './MemberUnit';
import Dashboard from './Dashboard';
import UpdateOrganizationForm from './UpdateOrganizationForm';
export { Navbar, MobileNavbar };
export {
Navbar,
MobileNavbar,
LoginForm,
MainPageBase,
EditUserForm,
Form,
OrgUnit,
StackItem,
RecordMp3,
RecoverForm,
ResetForm,
OrganizationList,
MemberUnit,
Dashboard,
UpdateOrganizationForm,
};

View file

@ -0,0 +1,16 @@
import Helmet from 'react-helmet';
import { EditUserForm } from '../controllers';
function Login() {
return (
<>
<Helmet>
<title>Edit User | KnowItAll</title>
</Helmet>
<EditUserForm />
</>
);
}
export default Login;

View file

@ -0,0 +1,16 @@
import Helmet from 'react-helmet';
import { LoginForm } from '../controllers';
function Login() {
return (
<>
<Helmet>
<title>Login | KnowItAll</title>
</Helmet>
<LoginForm />
</>
);
}
export default Login;

View file

@ -0,0 +1,27 @@
import Cookies from 'js-cookie';
import { useEffect } from 'react';
import Helmet from 'react-helmet';
import { useNavigate } from 'react-router-dom';
import { MainPageDisplay } from '../controllers';
function MainPage() {
const navigate = useNavigate();
useEffect(() => {
if (!Cookies.get('token')) {
navigate('/login');
}
}, []);
return (
<>
<Helmet>
<title>KnowItAll</title>
</Helmet>
<MainPageDisplay />
</>
);
}
export default MainPage;

View file

@ -0,0 +1,16 @@
import Helmet from 'react-helmet';
import { MemberOrgsDashboard } from '../controllers';
function MemberOrgs() {
return (
<>
<Helmet>
<title>Member Organizations | KnowItAll</title>
</Helmet>
<MemberOrgsDashboard />
</>
);
}
export default MemberOrgs;

View file

@ -0,0 +1,16 @@
import Helmet from 'react-helmet';
import { Dashboard } from '../controllers';
function OrgDashboard() {
return (
<>
<Helmet>
<title>Dashboard | KnowItAll</title>
</Helmet>
<Dashboard />
</>
);
}
export default OrgDashboard;

View file

@ -0,0 +1,16 @@
import Helmet from 'react-helmet';
import { OwnedOrgsDashboard } from '../controllers';
function OwnedOrgs() {
return (
<>
<Helmet>
<title>Owned Organizations | KnowItAll</title>
</Helmet>
<OwnedOrgsDashboard />
</>
);
}
export default OwnedOrgs;

View file

@ -0,0 +1,16 @@
import Helmet from 'react-helmet';
import { RecoverForm } from '../controllers';
function Login() {
return (
<>
<Helmet>
<title>Recover Password | KnowItAll</title>
</Helmet>
<RecoverForm />
</>
);
}
export default Login;

View file

@ -0,0 +1,16 @@
import Helmet from 'react-helmet';
import { RegisterForm } from '../controllers';
function Register() {
return (
<>
<Helmet>
<title>Register | KnowItAll</title>
</Helmet>
<RegisterForm />
</>
);
}
export default Register;

View file

@ -0,0 +1,16 @@
import Helmet from 'react-helmet';
import { ResetForm } from '../controllers';
function Reset() {
return (
<>
<Helmet>
<title>Reset | KnowItAll</title>
</Helmet>
<ResetForm />
</>
);
}
export default Reset;

View file

@ -0,0 +1,16 @@
import Helmet from 'react-helmet';
import { UpdateOrganizationForm } from '../controllers';
function UpdateOrganization() {
return (
<>
<Helmet>
<title>Update Organization | KnowItAll</title>
</Helmet>
<UpdateOrganizationForm />
</>
);
}
export default UpdateOrganization;

View file

@ -1,3 +1,25 @@
import Layout from './Layout';
import Login from './Login';
import Register from './Register';
import MainPage from './MainPage';
import EditUser from './EditUser';
import Recover from './Recover';
import Reset from './Reset';
import OwnedOrgs from './OwnedOrgs';
import MemberOrgs from './MemberOrgs';
import OrgDashboard from './OrgDashboard';
import UpdateOrganization from './UpdateOrganization';
export { Layout };
export {
Layout,
Login,
Register,
MainPage,
EditUser,
Recover,
Reset,
OwnedOrgs,
MemberOrgs,
OrgDashboard,
UpdateOrganization,
};

View file

@ -1,6 +1,8 @@
import { createContext, useContext, useEffect, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import Cookies from 'js-cookie';
import { remember } from '../services/userServices';
const initialUserData = { loading: true };
@ -14,12 +16,15 @@ export default function UserProvider({ children }) {
useEffect(() => {
const loadUserData = async () => {
const { user, error } = await remember();
if (error) {
navigate('/login');
Cookies.remove('token');
} else {
setUserData(user || { loading: false });
}
};
if (userData.loading) loadUserData();
}, [userData.loading]);

View file

@ -1,11 +1,11 @@
import React, { useEffect, useState } from 'react';
import { useNavigate, useParams } from 'react-router-dom';
import axios from 'axios';
import Cookies from 'js-cookie';
import Dashboard from '../components/Dashboard';
import { Dashboard } from '../components';
import { getAudio } from '../services/userServices';
import { getOrg, deleteOrg, removeMember } from '../services/orgServices';
function OrgDashboard() {
function DashboardController() {
const { orgID } = useParams();
const navigate = useNavigate();
@ -24,24 +24,18 @@ function OrgDashboard() {
const [rows, setRows] = useState([]);
const [status, setStatus] = useState(true);
const [selection, setSelection] = useState(null);
const [open, setOpen] = useState(false);
useEffect(() => {
async function getData() {
await axios
.get(
`${
process.env.REACT_APP_API_ROOT
}/org/${orgID}?token=${Cookies.get('token')}`
)
.then((response) => {
const res = response.data;
await getOrg(orgID)
.then((res) => {
setOrg(() => {
return { ...res.org, memberCount: res.memberCount };
});
setRows(() => res.org.member);
setStatus(() => res.status);
setStatus(() => res.owner);
})
.catch((e) => {
console.log(e);
@ -52,15 +46,12 @@ function OrgDashboard() {
getData();
}, [navigate, orgID]);
function handleOpen() {
setOpen((initial) => (initial ? false : true));
}
async function handleDelete() {
await axios
.delete(`${process.env.REACT_APP_API_ROOT}/org/delete`, {
params: {
token: Cookies.get('token'),
orgID,
},
})
.then(navigate('/'));
await deleteOrg(orgID).then(navigate('/'));
}
function copyID() {
@ -76,51 +67,30 @@ function OrgDashboard() {
async function removeSelected() {
const doomedUserIDs = selection.map((row) => row.id);
await axios.post(
`${process.env.REACT_APP_API_ROOT}/org/${orgID}/delete`,
{
token: Cookies.get('token'),
orgID,
doomedUserIDs,
}
);
await removeMember(orgID, doomedUserIDs);
}
async function leaveOrg() {
await axios
.post(`${process.env.REACT_APP_API_ROOT}/org/${orgID}/delete`, {
token: Cookies.get('token'),
orgID,
})
.then(() => navigate('/'))
.catch((e) => {
console.log(e);
navigate('/');
});
await removeMember(orgID, {}).then(navigate('/'));
}
async function play(id) {
await axios
.get(
`${process.env.REACT_APP_DOMAIN_ROOT}/public/audio/${id}.mp3`,
{
responseType: 'blob',
}
)
.then((res) => {
const uploadedFile = new File([res.data], 'userAudio.mp3', {
type: res.data.type,
lastModified: Date.now(),
});
const audioFile = new Audio(URL.createObjectURL(uploadedFile));
audioFile.play();
await getAudio(id).then((res) => {
const uploadedFile = new File([res], 'userAudio.mp3', {
type: res.type,
lastModified: Date.now(),
});
const audioFile = new Audio(URL.createObjectURL(uploadedFile));
audioFile.play();
});
}
return (
<Dashboard
org={org}
rows={rows}
open={open}
handleOpen={handleOpen}
setSelection={setSelection}
onClick={play}
status={status}
@ -133,4 +103,4 @@ function OrgDashboard() {
);
}
export default OrgDashboard;
export default DashboardController;

View file

@ -1,75 +0,0 @@
import React, { useEffect, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import axios from 'axios';
import Cookies from 'js-cookie';
import EditUserForm from '../components/EditUserForm';
function EditUser() {
const navigate = useNavigate();
const [form, setForm] = useState({
firstName: '',
lastName: '',
email: '',
pronouns: '',
});
const [error, setError] = useState('');
useEffect(() => {
async function getInfo() {
axios
.get(
`${process.env.REACT_APP_API_ROOT}/auth/${Cookies.get(
'userID'
)}?token=${Cookies.get('token')}`
)
.then((response) => {
const user = response.data;
setForm(() => {
return {
firstName: user.firstName,
lastName: user.lastName,
email: user.email,
pronouns: user.pronouns,
};
});
});
}
getInfo();
}, []);
function handleChange(e) {
const name = e.target.name;
const value = e.target.value;
setForm((form) => {
return { ...form, [name]: value };
});
}
async function handleSubmit(e) {
e.preventDefault();
await axios
.patch(`${process.env.REACT_APP_API_ROOT}/auth/update`, {
...form,
token: Cookies.get('token'),
})
.then(() => {
navigate('/');
})
.catch((e) => setError(() => e.response.data));
}
return (
<EditUserForm
form={form}
error={error}
handleSubmit={handleSubmit}
handleChange={handleChange}
/>
);
}
export default EditUser;

View file

@ -0,0 +1,62 @@
import { useState, useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
import { EditUserForm } from '../components';
import { useUser } from '../contexts';
import { updateUserDetails } from '../services/userServices';
function EditUserFormController() {
const navigate = useNavigate();
const { userData } = useUser();
const [form, setForm] = useState({
firstName: '',
lastName: '',
email: '',
pronouns: '',
});
const [error, setError] = useState('');
function handleChange(e) {
const name = e.target.name;
const value = e.target.value;
setForm((form) => {
return { ...form, [name]: value };
});
}
async function handleSubmit(e) {
e.preventDefault();
const { error } = await updateUserDetails(form);
if (error) {
setError(() => error);
} else {
navigate('/');
}
}
useEffect(() => {
if (!userData.loading) {
setForm(() => ({
firstName: userData.firstName,
lastName: userData.lastName,
email: userData.email,
pronouns: userData.pronouns,
}));
}
}, [userData]);
return (
<EditUserForm
form={form}
error={error}
handleSubmit={handleSubmit}
handleChange={handleChange}
/>
);
}
export default EditUserFormController;

View file

@ -1,85 +0,0 @@
import React, { useEffect, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import axios from 'axios';
import Cookies from 'js-cookie';
import LoginForm from '../components/LoginForm';
function Login({ setToken }) {
const navigate = useNavigate();
const [form, setForm] = useState({
email: '',
password: '',
remember: false,
});
const [error, setError] = useState('');
useEffect(() => {
async function logout() {
await axios
.post(`${process.env.REACT_APP_API_ROOT}/auth/logout`, {
token: Cookies.get('token'),
})
.catch((e) => {
console.log(e);
});
Cookies.remove('token');
Cookies.remove('userID');
setToken(() => false);
}
if (Cookies.get('token')) {
logout();
}
}, [setToken]);
function handleChange(e) {
const name = e.target.name;
const value = e.target.value;
setForm((form) => {
return { ...form, [name]: value };
});
}
function handleCheckboxChange(e) {
const name = e.target.name;
const checked = e.target.checked;
setForm(() => {
return { ...form, [name]: checked };
});
}
async function handleSubmit(e) {
e.preventDefault();
await axios
.post(`${process.env.REACT_APP_API_ROOT}/auth/login`, form)
.then((response) => {
Cookies.set('token', response.data.token, {
expires: form.remember ? 3650 : 1,
});
Cookies.set('userID', response.data.userID, {
expires: form.remember ? 3650 : 1,
});
setToken(true);
navigate('/');
})
.catch((e) => setError(() => e.response.data));
}
return (
<LoginForm
form={form}
error={error}
handleSubmit={handleSubmit}
handleChange={handleChange}
handleCheckboxChange={handleCheckboxChange}
/>
);
}
export default Login;

View file

@ -0,0 +1,51 @@
import { useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { LoginForm } from '../components';
import { useError } from '../contexts';
import { login } from '../services/userServices';
function LoginFormController({ setToken }) {
const navigate = useNavigate();
const { error, setError } = useError();
const [form, setForm] = useState({
email: '',
password: '',
remember: false,
});
function handleChange(e) {
const name = e.target.name;
const value = e.target.value;
setForm((form) => {
return { ...form, [name]: value };
});
}
function handleCheckboxChange(e) {
const name = e.target.name;
const checked = e.target.checked;
setForm(() => {
return { ...form, [name]: checked };
});
}
async function handleSubmit(e) {
e.preventDefault();
const { error } = await login(form);
if (error) {
setError(() => error);
} else {
navigate('/');
}
}
return <LoginForm {...{ form, handleSubmit, handleChange, handleCheckboxChange, error }} />;
}
export default LoginFormController;

View file

@ -1,101 +0,0 @@
import React, { useEffect, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import axios from 'axios';
import Cookies from 'js-cookie';
import MainPageBase from '../components/MainPageBase';
function MainPage() {
const navigate = useNavigate();
const [ownedOrgs, setOwnedOrgs] = useState([]);
const [orgs, setOrgs] = useState([]);
const [form, setForm] = useState({
name: '',
id: '',
});
useEffect(() => {
if (Cookies.get('token')) {
getMemberOrgs();
getOwnedOrgs();
} else {
navigate('/login');
}
}, [navigate]);
function handleChange(e) {
const name = e.target.name;
const value = e.target.value;
setForm((form) => {
return { ...form, [name]: value };
});
}
async function getOwnedOrgs() {
await axios
.get(
`${process.env.REACT_APP_API_ROOT}/auth?token=${Cookies.get(
'token'
)}`
)
.then((response) => {
setOwnedOrgs(() => response.data);
})
.catch((e) => {
console.log(e);
});
}
async function getMemberOrgs() {
await axios
.get(
`${
process.env.REACT_APP_API_ROOT
}/auth/orgs?token=${Cookies.get('token')}`
)
.then((response) => {
setOrgs(() => response.data);
});
}
async function createOrg(e) {
e.preventDefault();
console.log('create');
await axios
.post(`${process.env.REACT_APP_API_ROOT}/org/create`, {
token: Cookies.get('token'),
orgName: form.name,
})
.then(() => {
getOwnedOrgs();
});
}
async function joinOrg(e) {
e.preventDefault();
await axios
.post(`${process.env.REACT_APP_API_ROOT}/org/${form.id}/add`, {
token: Cookies.get('token'),
})
.then(() => {
getMemberOrgs();
});
}
return (
<MainPageBase
form={form}
orgs={orgs}
ownedOrgs={ownedOrgs}
joinOrg={joinOrg}
createOrg={createOrg}
handleChange={handleChange}
/>
);
}
export default MainPage;

View file

@ -0,0 +1,75 @@
import React, { useEffect, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import Cookies from 'js-cookie';
import { MainPageBase } from '../components';
import { getMemberOrgs, getOwnedOrgs } from '../services/userServices';
import { createOrg, addMember } from '../services/orgServices';
function MainPageController() {
const navigate = useNavigate();
const [ownedOrgs, setOwnedOrgs] = useState([]);
const [orgs, setOrgs] = useState([]);
const [form, setForm] = useState({
name: '',
id: '',
});
useEffect(() => {
if (Cookies.get('token')) {
retrieveMemberOrgs();
retrieveOwnedOrgs();
} else {
navigate('/login');
}
}, [navigate]);
function handleChange(e) {
const name = e.target.name;
const value = e.target.value;
setForm((form) => {
return { ...form, [name]: value };
});
}
async function retrieveOwnedOrgs() {
const { orgs } = await getOwnedOrgs().catch((e) => console.log(e));
setOwnedOrgs(() => orgs);
}
async function retrieveMemberOrgs() {
const { orgs } = await getMemberOrgs().catch((e) => console.log(e));
setOrgs(() => orgs);
}
async function makeOrg(e) {
e.preventDefault();
await createOrg({ orgName: form.name })
.then(retrieveOwnedOrgs)
.catch((e) => console.log(e));
}
async function joinOrg(e) {
e.preventDefault();
await addMember.then(retrieveMemberOrgs).catch((e) => console.log(e));
}
return (
<MainPageBase
form={form}
orgs={orgs}
ownedOrgs={ownedOrgs}
handleChange={handleChange}
joinOrg={joinOrg}
createOrg={makeOrg}
/>
);
}
export default MainPageController;

View file

@ -1,27 +0,0 @@
import React, { useEffect, useState } from 'react';
import axios from 'axios';
import Cookies from 'js-cookie';
import Organizations from '../components/Organizations';
function JoinedOrgs() {
const [orgs, setOrgs] = useState([]);
async function getOrgs() {
axios
.get(
`${
process.env.REACT_APP_API_ROOT
}/auth/orgs?token=${Cookies.get('token')}`
)
.then((response) => {
setOrgs(() => response.data);
});
}
useEffect(getOrgs);
return <Organizations orgs={orgs} />;
}
export default JoinedOrgs;

View file

@ -0,0 +1,20 @@
import React, { useEffect, useState } from 'react';
import { OrganizationList } from '../components';
import { getMemberOrgs } from '../services/userServices';
function MemberOrgsDashboard() {
const [orgs, setOrgs] = useState([]);
async function getOrgs() {
getMemberOrgs().then((res) => {
setOrgs(() => res.orgs);
});
}
useEffect(getOrgs);
return <OrganizationList orgs={orgs} />;
}
export default MemberOrgsDashboard;

View file

@ -1,27 +0,0 @@
import React, { useEffect, useState } from 'react';
import axios from 'axios';
import Cookies from 'js-cookie';
import Organizations from '../components/Organizations';
function JoinedOrgs() {
const [orgs, setOrgs] = useState([]);
async function getOrgs() {
axios
.get(
`${process.env.REACT_APP_API_ROOT}/auth?token=${Cookies.get(
'token'
)}`
)
.then((response) => {
setOrgs(() => response.data);
});
}
useEffect(getOrgs);
return <Organizations orgs={orgs} />;
}
export default JoinedOrgs;

View file

@ -0,0 +1,20 @@
import React, { useEffect, useState } from 'react';
import { OrganizationList } from '../components';
import { getOwnedOrgs } from '../services/userServices';
function OwnedOrgsDashboard() {
const [orgs, setOrgs] = useState([]);
async function getOrgs() {
getOwnedOrgs().then((res) => {
setOrgs(() => res.orgs);
});
}
useEffect(getOrgs);
return <OrganizationList orgs={orgs} />;
}
export default OwnedOrgsDashboard;

View file

@ -0,0 +1,94 @@
import React, { useEffect, useState } from 'react';
import axios from 'axios';
import Cookies from 'js-cookie';
import MicRecorder from 'mic-recorder-to-mp3';
import { useUser } from '../contexts';
import { RecordMp3 } from '../components';
import { setAudio, getAudio } from '../services/userServices';
function RecordMp3Controller() {
const { userData } = useUser();
const [recorder] = useState(
new MicRecorder({
bitRate: 128,
})
);
const [recording, setRecording] = useState(false);
const [uploadedFile, setUploadedFile] = useState(null);
const [audioRecording, setAudioRecording] = useState(null);
useEffect(() => {
if (!userData.loading) {
getAudio(userData.id).then((data) => {
setUploadedFile(() => {
// Retrieve audio file of user if exists
return new File([data], 'userAudio.mp3', {
type: data.type,
lastModified: Date.now(),
});
});
});
}
}, [userData]);
function togglePlay() {
if (audioRecording && !audioRecording.ended) {
// Reset audio and reset if track is playing
audioRecording.pause();
audioRecording.currentTime = 0;
setAudioRecording(() => null);
} else {
// Set audio to file and play
const audioFile = new Audio(URL.createObjectURL(uploadedFile));
setAudioRecording(() => audioFile);
audioFile.play();
}
}
function record() {
if (recording) {
// Stop recording then set uploaded file to mp3 instance
setRecording(() => false);
recorder
.stop()
.getMp3()
.then(([buffer, blob]) => {
setUploadedFile(() => {
return new File(buffer, 'userAudio.mp3', {
type: blob.type,
lastModified: Date.now(),
});
});
});
} else {
// Start recording
setRecording(() => true);
recorder.start().catch((e) => {
console.error(e);
});
}
}
function uploadRecord() {
setUploadedFile(() => {
return document.getElementById('icon-button-file').files[0];
});
}
async function handleSubmit(e) {
e.preventDefault();
// Create form data object and attach file and user token
var formData = new FormData();
formData.append('audioFile', uploadedFile, 'userAudio.mp3');
formData.append('token', Cookies.get('token'));
await setAudio(formData);
}
return <RecordMp3 {...{ togglePlay, record, uploadRecord, handleSubmit }} />;
}
export default RecordMp3Controller;

View file

@ -1,14 +1,13 @@
import React, { useState } from 'react';
import axios from 'axios';
import RecoverForm from '../components/RecoverForm';
import { RecoverForm } from '../components';
import { requestReset } from '../services/userServices';
function Recover() {
function RecoverFormController() {
const [form, setForm] = useState({
email: '',
});
const [error, setError] = useState('');
const [success, setSuccess] = useState('');
function handleChange(e) {
const name = e.target.name;
@ -21,25 +20,17 @@ function Recover() {
async function handleSubmit(e) {
e.preventDefault();
await axios
.get(
`${process.env.REACT_APP_API_ROOT}/auth/reset-password?${form.email}`
)
.then((response) => {
setSuccess(() => response.data);
})
.catch((e) => setError(() => e.response.data));
await requestReset(form);
}
return (
<RecoverForm
form={form}
error={error}
success={success}
handleChange={handleChange}
handleSubmit={handleSubmit}
/>
);
}
export default Recover;
export default RecoverFormController;

View file

@ -1,12 +1,14 @@
import React, { useState } from 'react';
import { useNavigate, useSearchParams } from 'react-router-dom';
import axios from 'axios';
import RegisterForm from '../components/RegisterForm';
import { useError } from '../contexts';
import { register } from '../services/userServices';
function Register() {
function RegisterFormController() {
const navigate = useNavigate();
const [params] = useSearchParams();
const { error, setError } = useError();
const [form, setForm] = useState({
firstName: '',
@ -16,7 +18,6 @@ function Register() {
password: '',
confirmPassword: '',
});
const [error, setError] = useState('');
function handleChange(e) {
const name = e.target.name;
@ -31,25 +32,16 @@ function Register() {
e.preventDefault();
const { confirmPassword, ...filteredForm } = form;
await axios
.post(`${process.env.REACT_APP_API_ROOT}/auth/register`, {
...filteredForm,
orgID: params.orgID,
})
.then(() => {
navigate('/login');
})
.catch((e) => setError(() => e.response.data));
const { error } = await register({ ...filteredForm, orgID: params.get('orgID') });
if (error) {
setError(() => error);
} else {
navigate('/login');
}
}
return (
<RegisterForm
form={form}
handleSubmit={handleSubmit}
handleChange={handleChange}
error={error}
/>
);
return <RegisterForm {...{ form, handleSubmit, handleChange, error }} />;
}
export default Register;
export default RegisterFormController;

View file

@ -1,10 +1,11 @@
import React, { useState } from 'react';
import { useNavigate, useParams } from 'react-router-dom';
import axios from 'axios';
import ResetForm from '../components/ResetForm';
import { ResetForm } from '../components';
import { resetPassword } from '../services/userServices';
import { useError } from '../contexts';
function Reset() {
function ResetFormController() {
const navigate = useNavigate();
const { id } = useParams();
@ -12,7 +13,7 @@ function Reset() {
password: '',
confirmPassword: '',
});
const [error, setError] = useState('');
const { error, setError } = useError();
function handleChange(e) {
const name = e.target.name;
@ -25,17 +26,14 @@ function Reset() {
async function handleSubmit(e) {
e.preventDefault();
await axios
.patch(
`${process.env.REACT_APP_API_ROOT}/auth/reset-password/${id}`,
{
password: form.password,
}
)
.then(() => {
navigate('/login');
})
.catch((e) => setError(() => e.response.data));
const error = await resetPassword(id, { password: form.password });
if (error) {
setError(() => error);
} else {
navigate('/login');
}
}
return (
@ -48,4 +46,4 @@ function Reset() {
);
}
export default Reset;
export default ResetFormController;

View file

@ -1,11 +1,10 @@
import React, { useState } from 'react';
import { useNavigate, useParams } from 'react-router-dom';
import axios from 'axios';
import Cookies from 'js-cookie';
import UpdateOrganizationForm from '../components/UpdateOrganizationForm';
import { UpdateOrganizationForm } from '../components';
import { updateOrgDetails } from '../services/orgServices';
function UpdateOrganization() {
function UpdateOrganizationFormController() {
const { orgID } = useParams();
const navigate = useNavigate();
@ -19,15 +18,10 @@ function UpdateOrganization() {
async function handleSubmit(e) {
e.preventDefault();
await axios
.patch(`${process.env.REACT_APP_API_ROOT}/org/update`, {
token: Cookies.get('token'),
orgName: name,
orgID,
})
.then(() => {
navigate(`/org/${orgID}`);
});
await updateOrgDetails(orgID, { orgName: name }).then(() => {
navigate(`/org/${orgID}`);
});
}
return (
@ -39,4 +33,4 @@ function UpdateOrganization() {
);
}
export default UpdateOrganization;
export default UpdateOrganizationFormController;

View file

@ -1,3 +1,27 @@
import Navbar from './NavbarController';
import LoginForm from './LoginFormController';
import RegisterForm from './RegisterFormController';
import MainPageDisplay from './MainPageController';
import EditUserForm from './EditUserFormController';
import RecordMp3 from './RecordMp3Controller';
import RecoverForm from './RecoverFormController';
import ResetForm from './ResetFormController';
import OwnedOrgsDashboard from './OwnedOrgsDashboard';
import MemberOrgsDashboard from './MemberOrgsDashboard';
import Dashboard from './DashboardController';
import UpdateOrganizationForm from './UpdateOrganizationFormController';
export { Navbar };
export {
Navbar,
LoginForm,
RegisterForm,
MainPageDisplay,
EditUserForm,
RecordMp3,
RecoverForm,
ResetForm,
OwnedOrgsDashboard,
MemberOrgsDashboard,
Dashboard,
UpdateOrganizationForm,
};

View file

@ -43,7 +43,9 @@ async function getOrg(id) {
instance.defaults.headers.common['Authorization'] = `bearer ${Cookies.get('token')}`;
try {
await instance.delete('/logout');
const response = await instance.get(`/${id}`);
console.log(response.data);
return response.data;
} catch (error) {
console.log(error.response.data);
return error;
@ -73,3 +75,5 @@ async function updateOrgDetails(id, data) {
return error;
}
}
export { addMember, createOrg, deleteOrg, getOrg, removeMember, updateOrgDetails };

View file

@ -1,9 +1,11 @@
import Cookies from 'js-cookie';
import { Buffer } from 'buffer';
import { createRequest } from './requests';
import axios from 'axios';
async function login({ username, password, remember }) {
const encoded = Buffer.from(`${username}:${password}`).toString('base64');
async function login({ email, password, remember }) {
const encoded = Buffer.from(`${email}:${password}`).toString('base64');
const instance = createRequest('/auth');
instance.defaults.headers.common['Authorization'] = `basic ${encoded}`;
@ -28,7 +30,7 @@ async function register(data) {
const instance = createRequest('/auth');
try {
await instance.post('/register', { data });
await instance.post('/register', data);
} catch (error) {
console.log(error.response.data);
return error;
@ -40,7 +42,7 @@ async function logout() {
instance.defaults.headers.common['Authorization'] = `bearer ${Cookies.get('token')}`;
try {
await instance.delete('/logout');
await instance.post('/logout');
} catch (error) {
console.log(error.response.data);
return error;
@ -53,9 +55,9 @@ async function remember() {
if (Cookies.get('token')) {
try {
const { data } = await instance.get('/remember');
const { data } = await instance.post('/remember');
return data.user;
return data;
} catch (error) {
console.log(error.response.data);
return error.response.data;
@ -80,7 +82,7 @@ async function requestReset(data) {
const instance = createRequest('/auth');
try {
await instance.post(`/reset`);
await instance.post(`/reset`, data);
} catch (error) {
console.log(error.response.data);
return error.response.data;
@ -91,7 +93,7 @@ async function resetPassword(id, data) {
const instance = createRequest('/auth');
try {
await instance.post(`/reset/${id}`, data);
await instance.patch(`/reset/${id}`, data);
} catch (error) {
console.log(error.response.data);
return error.response.data;
@ -104,13 +106,24 @@ async function setAudio(data) {
instance.defaults.headers.common['Authorization'] = `bearer ${Cookies.get('token')}`;
try {
await instance.post(`/update/audio`, data);
await instance.post('/audio', data);
} catch (error) {
console.log(error.response.data);
return error.response.data;
}
}
async function getAudio(userID) {
const response = await axios.get(
`${process.env.REACT_APP_DOMAIN_ROOT}/public/audio/${userID}.mp3`,
{
responseType: 'blob',
}
);
return response.data;
}
async function updateUserDetails(data) {
const instance = createRequest('/auth');
instance.defaults.headers.common['Authorization'] = `bearer ${Cookies.get('token')}`;
@ -128,9 +141,9 @@ async function getMemberOrgs() {
instance.defaults.headers.common['Authorization'] = `bearer ${Cookies.get('token')}`;
try {
const { data } = await instance.get(`/orgs`);
const { data } = await instance.get(`/orgs/member`);
return data.orgs;
return data;
} catch (error) {
console.log(error.response.data);
return error.response.data;
@ -142,9 +155,9 @@ async function getOwnedOrgs() {
instance.defaults.headers.common['Authorization'] = `bearer ${Cookies.get('token')}`;
try {
const { data } = await instance.get(`/orgs/member`);
const { data } = await instance.get(`/orgs`);
return data.orgs;
return data;
} catch (error) {
console.log(error.response.data);
return error.response.data;
@ -160,6 +173,7 @@ export {
requestReset,
resetPassword,
setAudio,
getAudio,
updateUserDetails,
getMemberOrgs,
getOwnedOrgs,

View file

@ -6,7 +6,7 @@ const config = require('../../config/error.json');
async function RequestReset(req, res, next) {
try {
// Make sure that the request contains an email
const email = req.query.email;
const email = req.body.email;
if (!email) {
return res.status(400).send(config.errorIncomplete);
}
@ -27,10 +27,11 @@ async function RequestReset(req, res, next) {
await courier.send({
message: {
to: { email: result.email },
template: 'FSTM4WF60KM570KS9DBQRH0T41GJ',
template: '484W41FM494HX6H1RFRNAXNGQ28C',
data: {
email: result.email,
resetRequest: resetRequest.id,
apiDomainRoot: process.env.CLIENT_DOMAIN_ROOT,
},
},
});

View file

@ -26,7 +26,7 @@ router.post('/remember', tokenAuth, Remember);
router.patch('/update', tokenAuth, UpdateUserDetails);
router.post('/audio', parseFormData, tokenAuth, SetAudio);
router.get('/reset', RequestReset);
router.post('/reset', RequestReset);
router.patch('/reset/:id', ResetPassword);
router.get('/orgs', tokenAuth, GetOwnedOrgs);