diff --git a/package.json b/package.json
index 6f10d661..599d341b 100644
--- a/package.json
+++ b/package.json
@@ -53,6 +53,7 @@
]
},
"devDependencies": {
+ "axios": "0.24.0",
"babel-eslint": "10.1.0",
"eslint": "7.29.0",
"eslint-config-standard": "16.0.3",
diff --git a/src/sounds/epics/get.js b/src/sounds/epics/get.js
new file mode 100644
index 00000000..67c5f1a7
--- /dev/null
+++ b/src/sounds/epics/get.js
@@ -0,0 +1,18 @@
+import { of } from 'rxjs'
+import { catchError, mergeMap } from 'rxjs/operators'
+import { ofType } from 'redux-observable'
+
+import { actions } from 'sounds/slices/get'
+import { repository } from 'sounds/repository'
+
+export const get = actions$ => actions$
+ .pipe(ofType(actions.attempt))
+ .pipe(mergeMap(payload => execute(payload)))
+
+const execute = ({ payload }) => repository.get(payload)
+ .pipe(mergeMap(success))
+ .pipe(catchError(failure))
+
+const success = payload => of(actions.success(payload))
+
+const failure = payload => of(actions.failure(payload))
diff --git a/src/sounds/epics/index.js b/src/sounds/epics/index.js
new file mode 100644
index 00000000..8a326efe
--- /dev/null
+++ b/src/sounds/epics/index.js
@@ -0,0 +1,5 @@
+import { combineEpics } from 'redux-observable'
+
+import { get } from 'sounds/epics/get'
+
+export const soundPrediction = combineEpics(get)
diff --git a/src/sounds/index.jsx b/src/sounds/index.jsx
index ac6c5797..22dd9c09 100644
--- a/src/sounds/index.jsx
+++ b/src/sounds/index.jsx
@@ -1,15 +1,16 @@
import React from 'react'
-import YouTube from 'react-youtube'
-import { settings } from 'settings'
import { Intro } from 'sounds/intro'
-import { Grid } from '@material-ui/core'
-
-const Sounds = () => <>
-
-
-
-
->
+import { useOnOpen } from 'sounds/use-on-open'
+import { Livestream } from 'sounds/livestream'
+
+const Sounds = () => {
+ useOnOpen()
+
+ return <>
+
+
+ >
+}
export default Sounds
diff --git a/src/sounds/livestream.jsx b/src/sounds/livestream.jsx
new file mode 100644
index 00000000..a674d457
--- /dev/null
+++ b/src/sounds/livestream.jsx
@@ -0,0 +1,9 @@
+import React from 'react'
+import { Grid } from '@material-ui/core'
+import YouTube from 'react-youtube'
+import { settings } from 'settings'
+import { useStyle } from 'sounds/use-style'
+
+export const Livestream = () =>
+
+
diff --git a/src/sounds/repository/get.js b/src/sounds/repository/get.js
new file mode 100644
index 00000000..77d9a4fc
--- /dev/null
+++ b/src/sounds/repository/get.js
@@ -0,0 +1,7 @@
+import axios from 'axios'
+import { from } from 'rxjs'
+import { map } from 'rxjs/operators'
+
+export const get = () => from(axios.get(`http://localhost:5000/prediction`))
+ .pipe(map(({ data }) => data))
+
diff --git a/src/sounds/repository/index.js b/src/sounds/repository/index.js
new file mode 100644
index 00000000..709c9e2e
--- /dev/null
+++ b/src/sounds/repository/index.js
@@ -0,0 +1,3 @@
+import { get } from 'sounds/repository/get'
+
+export const repository = { get }
diff --git a/src/sounds/slices/get.js b/src/sounds/slices/get.js
new file mode 100644
index 00000000..19f85f91
--- /dev/null
+++ b/src/sounds/slices/get.js
@@ -0,0 +1,26 @@
+import { createSlice } from '@reduxjs/toolkit'
+
+const initialState = {
+ attempt: null,
+ data: null,
+ errors: null,
+ loading: false,
+}
+
+const attempt = (state, { payload }) => ({ ...state, attempt: payload, loading: true })
+
+const success = (state, { payload }) => ({ ...state, data: payload, loading: false })
+
+const failure = (state, { payload }) => ({ ...state, errors: payload, loading: false })
+
+export const get = createSlice({
+ initialState,
+ name: 'getPrediction',
+ reducers: {
+ attempt,
+ success,
+ failure,
+ },
+})
+
+export const { actions } = get
diff --git a/src/sounds/slices/index.js b/src/sounds/slices/index.js
new file mode 100644
index 00000000..2e403294
--- /dev/null
+++ b/src/sounds/slices/index.js
@@ -0,0 +1,5 @@
+import { combineReducers } from '@reduxjs/toolkit'
+
+import { get } from 'sounds/slices/get'
+
+export const soundPrediction = combineReducers({ get: get.reducer })
diff --git a/src/sounds/use-on-open.js b/src/sounds/use-on-open.js
new file mode 100644
index 00000000..47ce1c3a
--- /dev/null
+++ b/src/sounds/use-on-open.js
@@ -0,0 +1,12 @@
+import { useDispatch } from 'react-redux'
+
+import { actions } from 'sounds/slices/get'
+
+export const useOnOpen = () => {
+ const dispatch = useDispatch()
+ const { attempt } = actions
+
+ setInterval(() => dispatch(attempt()), 5000)
+
+ return ''
+}
diff --git a/src/sounds/use-style.js b/src/sounds/use-style.js
index 2147034b..0a1b4939 100644
--- a/src/sounds/use-style.js
+++ b/src/sounds/use-style.js
@@ -7,7 +7,12 @@ const root = {
const text = { marginTop: '80px' }
+const live = {
+ paddingRight: '300px',
+ marginBottom: '80px',
+}
export const useStyle = makeStyles(() => ({
root,
text,
+ live,
}))
diff --git a/src/startup/root-epic.js b/src/startup/root-epic.js
index bea4eb70..abfadd74 100644
--- a/src/startup/root-epic.js
+++ b/src/startup/root-epic.js
@@ -2,5 +2,6 @@ import { combineEpics } from 'redux-observable'
import { detections } from 'detections/epics'
import { cameras } from 'cameras/epics'
+import { soundPrediction } from 'sounds/epics'
-export const rootEpic = combineEpics(detections, cameras)
+export const rootEpic = combineEpics(detections, cameras, soundPrediction)
diff --git a/src/startup/root-reducer.js b/src/startup/root-reducer.js
index c8c30cb8..980af172 100644
--- a/src/startup/root-reducer.js
+++ b/src/startup/root-reducer.js
@@ -2,5 +2,6 @@ import { combineReducers } from '@reduxjs/toolkit'
import { detections } from 'detections/slices'
import { cameras } from 'cameras/slices'
+import { soundPrediction } from 'sounds/slices'
-export const rootReducer = combineReducers({ detections, cameras })
+export const rootReducer = combineReducers({ detections, cameras, soundPrediction })
diff --git a/yarn.lock b/yarn.lock
index b59013f9..3d570803 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2712,6 +2712,13 @@ axe-core@^4.0.2:
resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.3.2.tgz#fcf8777b82c62cfc69c7e9f32c0d2226287680e7"
integrity sha512-5LMaDRWm8ZFPAEdzTYmgjjEdj1YnQcpfrVajO/sn/LhbpGp0Y0H64c2hLZI1gRMxfA+w1S71Uc/nHaOXgcCvGg==
+axios@0.24.0:
+ version "0.24.0"
+ resolved "https://registry.yarnpkg.com/axios/-/axios-0.24.0.tgz#804e6fa1e4b9c5288501dd9dff56a7a0940d20d6"
+ integrity sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==
+ dependencies:
+ follow-redirects "^1.14.4"
+
axobject-query@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-2.2.0.tgz#943d47e10c0b704aa42275e20edf3722648989be"
@@ -5346,6 +5353,11 @@ follow-redirects@^1.0.0:
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.1.tgz#d9114ded0a1cfdd334e164e6662ad02bfd91ff43"
integrity sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg==
+follow-redirects@^1.14.4:
+ version "1.14.4"
+ resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.4.tgz#838fdf48a8bbdd79e52ee51fb1c94e3ed98b9379"
+ integrity sha512-zwGkiSXC1MUJG/qmeIFH2HBJx9u0V46QGUe3YR1fXG8bXQxq7fLj0RjLZQ5nubr9qNJUZrH+xUcwXEoXNpfS+g==
+
for-in@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80"