From 1f00bf27f0091249582f10559f7640b543c349e8 Mon Sep 17 00:00:00 2001 From: Angel Penchev <26301867+angel-penchev@users.noreply.github.com> Date: Tue, 26 Oct 2021 15:25:53 +0300 Subject: [PATCH] [Feat] BluetoothConnectionOptions Created a button which opens a dialog for bluetooth device choice. References #24, #27. --- .../BluetoothConnectDialog.lazy.tsx | 15 ++++++ .../BluetoothConnectDialog.module.scss | 1 + .../BluetoothConnectDialog.stories.tsx | 12 +++++ .../BluetoothConnectDialog.test.tsx | 14 ++++++ .../BluetoothConnectDialog.tsx | 48 +++++++++++++++++++ .../BluetoothConnectionOptions.lazy.tsx | 11 +++++ .../BluetoothConnectionOptions.module.scss | 1 + .../BluetoothConnectionOptions.stories.tsx | 12 +++++ .../BluetoothConnectionOptions.test.tsx | 14 ++++++ .../BluetoothConnectionOptions.tsx | 48 +++++++++++++++++++ .../BluetoothDeviceSelection.tsx | 19 ++++---- .../HeadsetMonitor/HeadsetMonitor.lazy.tsx | 11 +++++ .../HeadsetMonitor/HeadsetMonitor.module.scss | 1 + .../HeadsetMonitor/HeadsetMonitor.stories.tsx | 12 +++++ .../HeadsetMonitor/HeadsetMonitor.test.tsx | 14 ++++++ .../HeadsetMonitor/HeadsetMonitor.tsx | 14 ++++++ .../UnsupportedPlatform.lazy.tsx | 11 +++++ .../UnsupportedPlatform.module.scss | 1 + .../UnsupportedPlatform.stories.tsx | 12 +++++ .../UnsupportedPlatform.test.tsx | 14 ++++++ .../UnsupportedPlatform.tsx | 19 ++++++++ 21 files changed, 296 insertions(+), 8 deletions(-) create mode 100644 client/src/components/BluetoothConnectDialog/BluetoothConnectDialog.lazy.tsx create mode 100644 client/src/components/BluetoothConnectDialog/BluetoothConnectDialog.module.scss create mode 100644 client/src/components/BluetoothConnectDialog/BluetoothConnectDialog.stories.tsx create mode 100644 client/src/components/BluetoothConnectDialog/BluetoothConnectDialog.test.tsx create mode 100644 client/src/components/BluetoothConnectDialog/BluetoothConnectDialog.tsx create mode 100644 client/src/components/BluetoothConnectionOptions/BluetoothConnectionOptions.lazy.tsx create mode 100644 client/src/components/BluetoothConnectionOptions/BluetoothConnectionOptions.module.scss create mode 100644 client/src/components/BluetoothConnectionOptions/BluetoothConnectionOptions.stories.tsx create mode 100644 client/src/components/BluetoothConnectionOptions/BluetoothConnectionOptions.test.tsx create mode 100644 client/src/components/BluetoothConnectionOptions/BluetoothConnectionOptions.tsx create mode 100644 client/src/components/HeadsetMonitor/HeadsetMonitor.lazy.tsx create mode 100644 client/src/components/HeadsetMonitor/HeadsetMonitor.module.scss create mode 100644 client/src/components/HeadsetMonitor/HeadsetMonitor.stories.tsx create mode 100644 client/src/components/HeadsetMonitor/HeadsetMonitor.test.tsx create mode 100644 client/src/components/HeadsetMonitor/HeadsetMonitor.tsx create mode 100644 client/src/components/UnsupportedPlatform/UnsupportedPlatform.lazy.tsx create mode 100644 client/src/components/UnsupportedPlatform/UnsupportedPlatform.module.scss create mode 100644 client/src/components/UnsupportedPlatform/UnsupportedPlatform.stories.tsx create mode 100644 client/src/components/UnsupportedPlatform/UnsupportedPlatform.test.tsx create mode 100644 client/src/components/UnsupportedPlatform/UnsupportedPlatform.tsx diff --git a/client/src/components/BluetoothConnectDialog/BluetoothConnectDialog.lazy.tsx b/client/src/components/BluetoothConnectDialog/BluetoothConnectDialog.lazy.tsx new file mode 100644 index 0000000..954c7fa --- /dev/null +++ b/client/src/components/BluetoothConnectDialog/BluetoothConnectDialog.lazy.tsx @@ -0,0 +1,15 @@ +import React, { lazy, Suspense } from 'react'; + +const LazyBluetoothConnectDialog = lazy( + () => import('./BluetoothConnectDialog'), +); + +const BluetoothConnectDialog = ( + props: JSX.IntrinsicAttributes & { children?: React.ReactNode }, +) => ( + + + +); + +export default BluetoothConnectDialog; diff --git a/client/src/components/BluetoothConnectDialog/BluetoothConnectDialog.module.scss b/client/src/components/BluetoothConnectDialog/BluetoothConnectDialog.module.scss new file mode 100644 index 0000000..8006276 --- /dev/null +++ b/client/src/components/BluetoothConnectDialog/BluetoothConnectDialog.module.scss @@ -0,0 +1 @@ +.BluetoothConnectDialog {} \ No newline at end of file diff --git a/client/src/components/BluetoothConnectDialog/BluetoothConnectDialog.stories.tsx b/client/src/components/BluetoothConnectDialog/BluetoothConnectDialog.stories.tsx new file mode 100644 index 0000000..acb4caf --- /dev/null +++ b/client/src/components/BluetoothConnectDialog/BluetoothConnectDialog.stories.tsx @@ -0,0 +1,12 @@ +/* eslint-disable */ +import BluetoothConnectDialog from './BluetoothConnectDialog'; + +export default { + title: "BluetoothConnectDialog", +}; + +export const Default = () => ; + +Default.story = { + name: 'default', +}; diff --git a/client/src/components/BluetoothConnectDialog/BluetoothConnectDialog.test.tsx b/client/src/components/BluetoothConnectDialog/BluetoothConnectDialog.test.tsx new file mode 100644 index 0000000..59b18d2 --- /dev/null +++ b/client/src/components/BluetoothConnectDialog/BluetoothConnectDialog.test.tsx @@ -0,0 +1,14 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import '@testing-library/jest-dom/extend-expect'; +import BluetoothConnectDialog from './BluetoothConnectDialog'; + +describe('', () => { + test('it should mount', () => { + render(); + + const bluetoothConnectDialog = screen.getByTestId('BluetoothConnectDialog'); + + expect(bluetoothConnectDialog).toBeInTheDocument(); + }); +}); diff --git a/client/src/components/BluetoothConnectDialog/BluetoothConnectDialog.tsx b/client/src/components/BluetoothConnectDialog/BluetoothConnectDialog.tsx new file mode 100644 index 0000000..2892357 --- /dev/null +++ b/client/src/components/BluetoothConnectDialog/BluetoothConnectDialog.tsx @@ -0,0 +1,48 @@ +import { Container, Dialog, DialogTitle } from '@mui/material'; +import React, { FC, useEffect, useState } from 'react'; +import styles from './BluetoothConnectDialog.module.scss'; +import BluetoothDeviceSelection from '../BluetoothDeviceSelection/BluetoothDeviceSelection'; +import UnsupportedPlatform from '../UnsupportedPlatform/UnsupportedPlatform'; + +interface BluetoothConnectDialogProps { + open: boolean; + onClose: (device: BluetoothDevice) => void; +} + +const BluetoothConnectDialog: FC = ( + props: BluetoothConnectDialogProps, +) => { + const { onClose, open } = props; + const [supportsBluetooth, setSupportsBluetooth] = useState(false); + + useEffect(() => { + if (navigator.bluetooth) { + navigator.bluetooth + .getAvailability() + .then((isAvailable) => setSupportsBluetooth(isAvailable)) + .catch(() => setSupportsBluetooth(false)); + } + }, []); + + const handleClose = (device: BluetoothDevice) => { + onClose(device); + }; + + return ( + + + Connect to headset + {supportsBluetooth ? ( + + ) : ( + + )} + + + ); +}; + +export default BluetoothConnectDialog; diff --git a/client/src/components/BluetoothConnectionOptions/BluetoothConnectionOptions.lazy.tsx b/client/src/components/BluetoothConnectionOptions/BluetoothConnectionOptions.lazy.tsx new file mode 100644 index 0000000..4c61a03 --- /dev/null +++ b/client/src/components/BluetoothConnectionOptions/BluetoothConnectionOptions.lazy.tsx @@ -0,0 +1,11 @@ +import React, { lazy, Suspense } from 'react'; + +const LazyBluetoothConnectionOptions = lazy(() => import('./BluetoothConnectionOptions')); + +const BluetoothConnectionOptions = (props: JSX.IntrinsicAttributes & { children?: React.ReactNode; }) => ( + + + +); + +export default BluetoothConnectionOptions; diff --git a/client/src/components/BluetoothConnectionOptions/BluetoothConnectionOptions.module.scss b/client/src/components/BluetoothConnectionOptions/BluetoothConnectionOptions.module.scss new file mode 100644 index 0000000..c12c47d --- /dev/null +++ b/client/src/components/BluetoothConnectionOptions/BluetoothConnectionOptions.module.scss @@ -0,0 +1 @@ +.BluetoothConnectionOptions {} \ No newline at end of file diff --git a/client/src/components/BluetoothConnectionOptions/BluetoothConnectionOptions.stories.tsx b/client/src/components/BluetoothConnectionOptions/BluetoothConnectionOptions.stories.tsx new file mode 100644 index 0000000..514b3b9 --- /dev/null +++ b/client/src/components/BluetoothConnectionOptions/BluetoothConnectionOptions.stories.tsx @@ -0,0 +1,12 @@ +/* eslint-disable */ +import BluetoothConnectionOptions from './BluetoothConnectionOptions'; + +export default { + title: "BluetoothConnectionOptions", +}; + +export const Default = () => ; + +Default.story = { + name: 'default', +}; diff --git a/client/src/components/BluetoothConnectionOptions/BluetoothConnectionOptions.test.tsx b/client/src/components/BluetoothConnectionOptions/BluetoothConnectionOptions.test.tsx new file mode 100644 index 0000000..d4e6cad --- /dev/null +++ b/client/src/components/BluetoothConnectionOptions/BluetoothConnectionOptions.test.tsx @@ -0,0 +1,14 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import '@testing-library/jest-dom/extend-expect'; +import BluetoothConnectionOptions from './BluetoothConnectionOptions'; + +describe('', () => { + test('it should mount', () => { + render(); + + const bluetoothConnectionOptions = screen.getByTestId('BluetoothConnectionOptions'); + + expect(bluetoothConnectionOptions).toBeInTheDocument(); + }); +}); \ No newline at end of file diff --git a/client/src/components/BluetoothConnectionOptions/BluetoothConnectionOptions.tsx b/client/src/components/BluetoothConnectionOptions/BluetoothConnectionOptions.tsx new file mode 100644 index 0000000..b367f02 --- /dev/null +++ b/client/src/components/BluetoothConnectionOptions/BluetoothConnectionOptions.tsx @@ -0,0 +1,48 @@ +import React, { FC, useContext } from 'react'; +import { Button, Container } from '@mui/material'; +import styles from './BluetoothConnectionOptions.module.scss'; +import { BluetoothSearching, BluetoothDisabled } from '@mui/icons-material'; +import BluetoothConnectDialog from '../BluetoothConnectDialog/BluetoothConnectDialog'; +import { HeadsetContext } from '../../contexts/HeadsetContext'; + +const BluetoothConnectionOptions: FC<{}> = () => { + const { headset, setHeadset } = useContext(HeadsetContext); + const [open, setOpen] = React.useState(false); + + const handleOpen = () => { + setOpen(true); + }; + + const handleClose = (device: BluetoothDevice) => { + setOpen(false); + connectDevice(device); + }; + + const connectDevice = (device: BluetoothDevice) => { + setHeadset(device); + }; + + const disconnectDevice = () => { + setHeadset(undefined); + }; + + return ( + + {!headset ? ( + + ) : ( + + )} + + + ); +}; + +export default BluetoothConnectionOptions; diff --git a/client/src/components/BluetoothDeviceSelection/BluetoothDeviceSelection.tsx b/client/src/components/BluetoothDeviceSelection/BluetoothDeviceSelection.tsx index c57196f..fdb6ddd 100644 --- a/client/src/components/BluetoothDeviceSelection/BluetoothDeviceSelection.tsx +++ b/client/src/components/BluetoothDeviceSelection/BluetoothDeviceSelection.tsx @@ -8,16 +8,24 @@ import { ListItemText, Typography, } from '@mui/material'; -import React, { FC, useState } from 'react'; +import React, { FC, useContext, useState } from 'react'; import styles from './BluetoothDeviceSelection.module.scss'; import { Bluetooth, Refresh } from '@mui/icons-material'; +import { HeadsetContext } from '../../contexts/HeadsetContext'; interface DevicesTable { [key: string]: BluetoothDevice; } -const BluetoothDeviceSelection: FC<{}> = () => { +interface BluetoothDeviceSelectionProps { + handleDeviceClick: (device: BluetoothDevice) => void; +} + +const BluetoothDeviceSelection: FC = ( + props: BluetoothDeviceSelectionProps, +) => { const [devices, setDevices] = useState({}); + const { setHeadset } = useContext(HeadsetContext); const refreshDevices = async () => { const requestDeviceOptions = { @@ -44,23 +52,18 @@ const BluetoothDeviceSelection: FC<{}> = () => { setDevices(result); }; - const connectDevice = (device: BluetoothDevice) => { - console.log(device); - }; - return ( - Select a bluetooth device {Object.values(devices).map((device) => ( - connectDevice(device)}> + props.handleDeviceClick(device)}> diff --git a/client/src/components/HeadsetMonitor/HeadsetMonitor.lazy.tsx b/client/src/components/HeadsetMonitor/HeadsetMonitor.lazy.tsx new file mode 100644 index 0000000..af2b07e --- /dev/null +++ b/client/src/components/HeadsetMonitor/HeadsetMonitor.lazy.tsx @@ -0,0 +1,11 @@ +import React, { lazy, Suspense } from 'react'; + +const LazyHeadsetMonitor = lazy(() => import('./HeadsetMonitor')); + +const HeadsetMonitor = (props: JSX.IntrinsicAttributes & { children?: React.ReactNode; }) => ( + + + +); + +export default HeadsetMonitor; diff --git a/client/src/components/HeadsetMonitor/HeadsetMonitor.module.scss b/client/src/components/HeadsetMonitor/HeadsetMonitor.module.scss new file mode 100644 index 0000000..aa2f096 --- /dev/null +++ b/client/src/components/HeadsetMonitor/HeadsetMonitor.module.scss @@ -0,0 +1 @@ +.HeadsetMonitor {} \ No newline at end of file diff --git a/client/src/components/HeadsetMonitor/HeadsetMonitor.stories.tsx b/client/src/components/HeadsetMonitor/HeadsetMonitor.stories.tsx new file mode 100644 index 0000000..335fa85 --- /dev/null +++ b/client/src/components/HeadsetMonitor/HeadsetMonitor.stories.tsx @@ -0,0 +1,12 @@ +/* eslint-disable */ +import HeadsetMonitor from './HeadsetMonitor'; + +export default { + title: "HeadsetMonitor", +}; + +export const Default = () => ; + +Default.story = { + name: 'default', +}; diff --git a/client/src/components/HeadsetMonitor/HeadsetMonitor.test.tsx b/client/src/components/HeadsetMonitor/HeadsetMonitor.test.tsx new file mode 100644 index 0000000..d1cedc1 --- /dev/null +++ b/client/src/components/HeadsetMonitor/HeadsetMonitor.test.tsx @@ -0,0 +1,14 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import '@testing-library/jest-dom/extend-expect'; +import HeadsetMonitor from './HeadsetMonitor'; + +describe('', () => { + test('it should mount', () => { + render(); + + const headsetMonitor = screen.getByTestId('HeadsetMonitor'); + + expect(headsetMonitor).toBeInTheDocument(); + }); +}); \ No newline at end of file diff --git a/client/src/components/HeadsetMonitor/HeadsetMonitor.tsx b/client/src/components/HeadsetMonitor/HeadsetMonitor.tsx new file mode 100644 index 0000000..e492cf1 --- /dev/null +++ b/client/src/components/HeadsetMonitor/HeadsetMonitor.tsx @@ -0,0 +1,14 @@ +import { Container } from '@mui/material'; +import React, { FC } from 'react'; +import BluetoothConnectionOptions from '../BluetoothConnectionOptions/BluetoothConnectionOptions'; +import styles from './HeadsetMonitor.module.scss'; + +const HeadsetMonitor: FC<{}> = () => { + return ( + + + + ); +}; + +export default HeadsetMonitor; diff --git a/client/src/components/UnsupportedPlatform/UnsupportedPlatform.lazy.tsx b/client/src/components/UnsupportedPlatform/UnsupportedPlatform.lazy.tsx new file mode 100644 index 0000000..0b19910 --- /dev/null +++ b/client/src/components/UnsupportedPlatform/UnsupportedPlatform.lazy.tsx @@ -0,0 +1,11 @@ +import React, { lazy, Suspense } from 'react'; + +const LazyUnsupportedPlatform = lazy(() => import('./UnsupportedPlatform')); + +const UnsupportedPlatform = (props: JSX.IntrinsicAttributes & { children?: React.ReactNode; }) => ( + + + +); + +export default UnsupportedPlatform; diff --git a/client/src/components/UnsupportedPlatform/UnsupportedPlatform.module.scss b/client/src/components/UnsupportedPlatform/UnsupportedPlatform.module.scss new file mode 100644 index 0000000..030e476 --- /dev/null +++ b/client/src/components/UnsupportedPlatform/UnsupportedPlatform.module.scss @@ -0,0 +1 @@ +.UnsupportedPlatform {} \ No newline at end of file diff --git a/client/src/components/UnsupportedPlatform/UnsupportedPlatform.stories.tsx b/client/src/components/UnsupportedPlatform/UnsupportedPlatform.stories.tsx new file mode 100644 index 0000000..bbcc320 --- /dev/null +++ b/client/src/components/UnsupportedPlatform/UnsupportedPlatform.stories.tsx @@ -0,0 +1,12 @@ +/* eslint-disable */ +import UnsupportedPlatform from './UnsupportedPlatform'; + +export default { + title: "UnsupportedPlatform", +}; + +export const Default = () => ; + +Default.story = { + name: 'default', +}; diff --git a/client/src/components/UnsupportedPlatform/UnsupportedPlatform.test.tsx b/client/src/components/UnsupportedPlatform/UnsupportedPlatform.test.tsx new file mode 100644 index 0000000..0c1c4ea --- /dev/null +++ b/client/src/components/UnsupportedPlatform/UnsupportedPlatform.test.tsx @@ -0,0 +1,14 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import '@testing-library/jest-dom/extend-expect'; +import UnsupportedPlatform from './UnsupportedPlatform'; + +describe('', () => { + test('it should mount', () => { + render(); + + const unsupportedPlatform = screen.getByTestId('UnsupportedPlatform'); + + expect(unsupportedPlatform).toBeInTheDocument(); + }); +}); \ No newline at end of file diff --git a/client/src/components/UnsupportedPlatform/UnsupportedPlatform.tsx b/client/src/components/UnsupportedPlatform/UnsupportedPlatform.tsx new file mode 100644 index 0000000..8d6f98a --- /dev/null +++ b/client/src/components/UnsupportedPlatform/UnsupportedPlatform.tsx @@ -0,0 +1,19 @@ +import { Container, Typography } from '@mui/material'; +import React, { FC } from 'react'; +import styles from './UnsupportedPlatform.module.scss'; + +const UnsupportedPlatform: FC<{}> = () => { + return ( + + + Sadly, the platform you are running this application on is currently + unsupported. + + + ); +}; + +export default UnsupportedPlatform;