Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
"react": "16.12.0",
"react-datetime": "2.16.3",
"react-dom": "16.12.0",
"react-hook-form": "^6.8.4",
"react-router": "5.1.2",
"react-router-dom": "5.1.2",
"react-scripts": "3.4.0",
Expand Down
3 changes: 2 additions & 1 deletion web/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import Footer from 'components/footer';
import Navbar from 'components/navbar';
import SleepAnalysis from 'views/sleep-analysis';
import Performance from 'views/performance';
import AnalyzeSleep from 'views/analyze-sleep';
import ScrollToTop from 'components/scroll_to_top';
import Emoji from 'components/emoji';

Expand Down Expand Up @@ -48,7 +49,7 @@ ReactDOM.render(
<Switch>
<Route exact path="/" render={() => <SleepAnalysis />} />
<Route exact path="/record-my-sleep" render={underConstruction} />
<Route exact path="/analyze-my-sleep" render={underConstruction} />
<Route exact path="/analyze-my-sleep" render={() => <AnalyzeSleep />} />
<Route exact path="/performance" render={() => <Performance />} />
<Redirect to="/" />
</Switch>
Expand Down
27 changes: 27 additions & 0 deletions web/src/views/analyze-sleep/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import React from 'react';
import { Container } from 'reactstrap';

import Header from 'components/header';
import WaitingForServerToBeReady from './waiting-for-server-to-be-ready';
import UploadForm from './upload-form';

import text from './text.json';

const isServerReady = true;

const AnalyzeSleep = () => {
return (
<div>
<Header
sizeClass={'pb-100'}
shapeQty={7}
title={text['header_title']}
subtitle={text['header_subtitle']}
description={text['header_description']}
/>
<Container className="mt-5 text-justify">{isServerReady ? <UploadForm /> : <WaitingForServerToBeReady />}</Container>
</div>
);
};

export default AnalyzeSleep;
5 changes: 5 additions & 0 deletions web/src/views/analyze-sleep/text.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"header_title": "Your night",
"header_subtitle": "visualized and compared",
"header_description": "Upload your night of sleep"
}
146 changes: 146 additions & 0 deletions web/src/views/analyze-sleep/upload-form.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
import React from 'react';
import { Button, Container, CustomInput, Form, FormGroup, Label, Input, InputGroup, Col, Row } from 'reactstrap';
import { useForm } from 'react-hook-form';

const dateFieldSuffix = '-date';
const timeFieldSuffix = '-time';

const filterInDateTimeFields = (data) =>
Object.keys(data)
.filter((field) => field.endsWith(timeFieldSuffix))
.map((field) => field.replace(timeFieldSuffix, ''));

const filterOutDateTimeFields = (data) =>
Object.entries(data).filter(([fieldName, value]) => !(fieldName.endsWith(dateFieldSuffix) || fieldName.endsWith(timeFieldSuffix)));

const mergeDateTimeFields = (data) =>
filterInDateTimeFields(data).map((fieldPrefix) => [
fieldPrefix,
new Date(
Object.entries(data)
.filter(([fieldName, value]) => fieldName.startsWith(fieldPrefix))
.map(([fieldName, value]) => value)
.join(' '),
),
]);

const UploadForm = () => {
const { register, handleSubmit } = useForm();
const onSubmit = (data) => {
const newFormData = Object.fromEntries([...filterOutDateTimeFields(data), ...mergeDateTimeFields(data)]);
console.log(newFormData);
};

return (
<Container style={{ padding: '2em 0' }}>
<Row>
<Col sm="12" md={{ size: 8, offset: 2 }}>
<Form onSubmit={handleSubmit(onSubmit)}>
<h3>Please enter your EEG recorded data and the information related to it:</h3>

<CustomInput
innerRef={register}
required
accept=".csv, text/plain"
bsSize="lg"
type="file"
id="openbci-file"
name="openbci-file"
label="Upload an OpenBCI CSV file"
/>

<FormGroup>
<Label for="openbci-device">OpenBCI device</Label>
<Row>
<Col md={6}>
<CustomInput innerRef={register} required type="select" id="openbci-device" name="device">
<option></option>
<option>Cython</option>
<option>Ganglion</option>
</CustomInput>
</Col>
</Row>
</FormGroup>

<FormGroup inline>
<Label>Name</Label>
<Row form>
<Col md={6}>
<Input innerRef={register} required type="text" name="firstName" id="firstName" placeholder="First name" />
</Col>
<Col md={6}>
<Input innerRef={register} required type="text" name="lastName" id="lastName" placeholder="Last name" />
</Col>
</Row>
</FormGroup>

<Row form>
<Col md={6}>
<FormGroup inline>
<Label for="sex">Sex</Label>
<CustomInput required type="radio" id="male" name="sex" label="Male" />
<CustomInput required type="radio" id="female" name="sex" label="Female" />
</FormGroup>
</Col>
<Col md={6}>
<FormGroup>
<Label for="age">Age</Label>
<Input innerRef={register} required type="number" name="age" id="age" min="0" max="125" placeholder="Enter your age" />
</FormGroup>
</Col>
</Row>

<div>
<Row form>
<Col md={6}>
<FormGroup>
<Label>Time when OpenBCI stream started</Label>
<InputGroup>
<Input innerRef={register} required type="date" name={`stream-start${dateFieldSuffix}`} id={`stream-start${dateFieldSuffix}`} />
<Input innerRef={register} required type="time" name={`stream-start${timeFieldSuffix}`} id={`stream-start${timeFieldSuffix}`} />
</InputGroup>
</FormGroup>
</Col>
<Col md={6}>
<FormGroup>
<Label>I went to bed at</Label>
<InputGroup>
<Input innerRef={register} required type="date" name={`bedtime${dateFieldSuffix}`} id={`bedtime${dateFieldSuffix}`} />
<Input innerRef={register} required type="time" name={`bedtime${timeFieldSuffix}`} id={`bedtime${timeFieldSuffix}`} />
</InputGroup>
</FormGroup>
</Col>
</Row>
<Row form>
<Col md={6}>
<FormGroup>
<Label>I think I fell asleep at</Label>
<InputGroup>
<Input innerRef={register} required type="date" name={`sleeping${dateFieldSuffix}`} id={`sleeping${dateFieldSuffix}`} />
<Input innerRef={register} required type="time" name={`sleeping${timeFieldSuffix}`} id={`sleeping${timeFieldSuffix}`} />
</InputGroup>
</FormGroup>
</Col>
<Col md={6}>
<FormGroup>
<Label>And woke up at</Label>
<InputGroup>
<Input innerRef={register} required type="date" name={`wakeup${dateFieldSuffix}`} id={`wakeup${dateFieldSuffix}`} />
<Input innerRef={register} required type="time" name={`wakeup${timeFieldSuffix}`} id={`wakeup${timeFieldSuffix}`} />
</InputGroup>
</FormGroup>
</Col>
</Row>
</div>

<Button size="lg" color="primary">
Analyze my sleep
</Button>
</Form>
</Col>
</Row>
</Container>
);
};

export default UploadForm;
9 changes: 9 additions & 0 deletions web/src/views/analyze-sleep/waiting-for-server-to-be-ready.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import React from 'react';

const WaitingForServerToBeReady = () => (
<div>
<h1>Waiting for local server to be running...</h1>
</div>
);

export default WaitingForServerToBeReady;
5 changes: 5 additions & 0 deletions web/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -10057,6 +10057,11 @@ react-error-overlay@^6.0.7:
resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.7.tgz#1dcfb459ab671d53f660a991513cb2f0a0553108"
integrity sha512-TAv1KJFh3RhqxNvhzxj6LeT5NWklP6rDr2a0jaTfsZ5wSZWHOGeqQyejUp3xxLfPt2UpyJEcVQB/zyPcmonNFA==

react-hook-form@^6.8.4:
version "6.8.4"
resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-6.8.4.tgz#1aed2f7badba3622324e37d68f7637868ea54cf2"
integrity sha512-qFd5SPPQUZWe+yXF6yjuJXKK8cLXywrzQuw74nL1jptW9Fad4HsEzfh+53Jg3c5TFPIwdIxrMNUvQfd0/p1y/w==

react-is@^16.6.0, react-is@^16.6.3, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.4:
version "16.13.1"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
Expand Down