diff --git a/frontend/src/App.css b/frontend/src/App.css deleted file mode 100644 index 0320773..0000000 --- a/frontend/src/App.css +++ /dev/null @@ -1,17 +0,0 @@ -#root { - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - display: flex; - flex-direction: column; - justify-content: space-between; - margin: 0; - background-color: var(--md-sys-color-surface-container-high); - scroll-behavior: smooth; -} - -main > * { - width: 100%; -} diff --git a/frontend/src/App.js b/frontend/src/App.js deleted file mode 100644 index 5ecd634..0000000 --- a/frontend/src/App.js +++ /dev/null @@ -1,37 +0,0 @@ -import React, { useEffect } from 'react' -import { styles as typescaleStyles } from '@material/web/typography/md-typescale-styles.js' - -import PollList from "./PollList"; - -import './App.css' - -function App() { - useEffect(() => { - document.adoptedStyleSheets = [typescaleStyles.styleSheet] - }, []) - - return ( -
- - -
- //
- //
- // logo - //

- // Edit src/App.js and save to reload. - //

- // - // Learn React - // - //
- //
- ) -} - -export default App diff --git a/frontend/src/FullScreenDialog.css b/frontend/src/FullScreenDialog.css deleted file mode 100644 index fcfbd20..0000000 --- a/frontend/src/FullScreenDialog.css +++ /dev/null @@ -1,45 +0,0 @@ -.full-screen-dialog { - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - background-color: var(--md-sys-color-surface-container); - z-index: 1; - animation: .1s show ease; -} - -.full-screen-dialog > .top-app-bar { - position: absolute; - top: 0; - right: 0; - left: 0; - display: flex; - align-items: center; - gap: .5rem; - padding: .5rem; -} - -.full-screen-dialog > .top-app-bar > * { - flex-shrink: 0; -} - -.full-screen-dialog > .top-app-bar > .title { - flex-grow: 1; - flex-shrink: 1; - color: var(--md-sys-color-on-surface); - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -@keyframes show { - from { - opacity: 0; - scale: 0; - } - to { - opacity: 1; - scale: 1; - } -} diff --git a/frontend/src/FullScreenDialog.js b/frontend/src/FullScreenDialog.js deleted file mode 100644 index 155ea96..0000000 --- a/frontend/src/FullScreenDialog.js +++ /dev/null @@ -1,28 +0,0 @@ -import React, { useEffect, useState } from 'react' - -import '@material/web/iconbutton/icon-button.js' -import '@material/web/icon/icon.js' -import '@material/web/button/filled-button' - -import './FullScreenDialog.css' - -export default function ({ - editPoll, - setEditPoll, -}) { - // const [close, onClose] = useState(false) - return ( -
-
- setEditPoll(false)}> - close - -
Изменить опрос
- setEditPoll()}>Сохранить - - more_vert - -
-
- ) -} diff --git a/frontend/src/PollList.css b/frontend/src/PollList.css deleted file mode 100644 index a8188c6..0000000 --- a/frontend/src/PollList.css +++ /dev/null @@ -1,4 +0,0 @@ -.poll-list { - display: flex; - flex-direction: column; -} diff --git a/frontend/src/PollList.js b/frontend/src/PollList.js deleted file mode 100644 index a7bcec9..0000000 --- a/frontend/src/PollList.js +++ /dev/null @@ -1,37 +0,0 @@ -import React, { useEffect, useState } from 'react' - -import PollListItem from "./PollListItem" -import FullScreenDialog from "./FullScreenDialog" - -import './PollList.css' - -const PollContext = React.createContext({ - polls: [], - fetchPolls: () => {}, -}) - -export default function PollList() { - const [polls, setPolls] = useState([]) - const [editPoll, setEditPoll] = useState(false) - - const fetchPolls = async () => { - const response = await fetch('/api/polls') - const polls = await response.json() - setPolls(polls) - } - - useEffect(() => { - fetchPolls() - }, []) - - return ( -
- - {polls.map((poll) => ( - PollListItem(poll, setEditPoll) - ))} - - {editPoll ? : null} -
- ) -} diff --git a/frontend/src/PollListItem.js b/frontend/src/PollListItem.js deleted file mode 100644 index d2a457a..0000000 --- a/frontend/src/PollListItem.js +++ /dev/null @@ -1,22 +0,0 @@ -import '@material/web/switch/switch.js' - -import './PollListItem.css' - -export default function PollListItem(data, setEditPoll) { - return ( -
setEditPoll(true)}> - -
-
{data.name}
-
- {data.days_of_week} -  •  - {data.time} -  •  - {data.question_number} -
-
- -
- ) -} diff --git a/frontend/src/activities/MainActivity.css b/frontend/src/activities/MainActivity.css new file mode 100644 index 0000000..5164f5d --- /dev/null +++ b/frontend/src/activities/MainActivity.css @@ -0,0 +1,3 @@ +main > * { + width: 100%; +} diff --git a/frontend/src/activities/MainActivity.js b/frontend/src/activities/MainActivity.js new file mode 100644 index 0000000..d3bea6d --- /dev/null +++ b/frontend/src/activities/MainActivity.js @@ -0,0 +1,35 @@ +import React, { useEffect } from 'react' +import { styles as typescaleStyles } from '@material/web/typography/md-typescale-styles.js' + +import PollsScreen from '../screens/PollsScreen' +import Scaffold from '../components/Scaffold' +import NavigationBar from '../components/NavigationBar' + +import './MainActivity.css' + +const bottomBar = ( + +) + +const floatingActionButton = ( + + add + +) + +const content = ( + +) + +export default function MainActivity() { + useEffect(() => { + document.adoptedStyleSheets = [typescaleStyles.styleSheet] + }, []) + + return ( + + ) +} diff --git a/frontend/src/components/FullScreenDialog.css b/frontend/src/components/FullScreenDialog.css new file mode 100644 index 0000000..2723548 --- /dev/null +++ b/frontend/src/components/FullScreenDialog.css @@ -0,0 +1,36 @@ +.full-screen-dialog { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + display: flex; + flex-direction: column; + background-color: var(--md-sys-color-surface); + z-index: 2; + transition: + opacity .1s ease-in-out, + scale .1s ease-in-out; +} + +.full-screen-dialog.open { + opacity: 1; + scale: 1; +} + +.full-screen-dialog.close { + opacity: 0; + scale: 0; +} + +.full-screen-dialog > .content { + flex-grow: 1; + flex-shrink: 1; + display: flex; + flex-direction: column; + overflow-y: auto; +} + +.full-screen-dialog > .content > * { + padding: 1rem; +} diff --git a/frontend/src/components/FullScreenDialog.js b/frontend/src/components/FullScreenDialog.js new file mode 100644 index 0000000..19ed8f2 --- /dev/null +++ b/frontend/src/components/FullScreenDialog.js @@ -0,0 +1,22 @@ +import '@material/web/iconbutton/icon-button.js' +import '@material/web/icon/icon.js' +import '@material/web/button/filled-button' + +import TopAppBar from './TopAppBar' + +import './FullScreenDialog.css' + +export default function ({ + setEditPoll, + classList, + children, +}) { + return ( +
+ setEditPoll(false)} /> +
+ {children} +
+
+ ) +} diff --git a/frontend/src/BottomNavBar.css b/frontend/src/components/NavigationBar.css similarity index 84% rename from frontend/src/BottomNavBar.css rename to frontend/src/components/NavigationBar.css index fe7dd32..7be013d 100644 --- a/frontend/src/BottomNavBar.css +++ b/frontend/src/components/NavigationBar.css @@ -1,7 +1,7 @@ nav { display: flex; flex-direction: column; - background-color: var(--md-sys-color-surface-container); + background-color: var(--md-sys-color-surface-container-high); } nav ul { diff --git a/frontend/src/BottomNavBar.js b/frontend/src/components/NavigationBar.js similarity index 92% rename from frontend/src/BottomNavBar.js rename to frontend/src/components/NavigationBar.js index 007ec06..432bf4c 100644 --- a/frontend/src/BottomNavBar.js +++ b/frontend/src/components/NavigationBar.js @@ -1,9 +1,9 @@ import '@material/web/iconbutton/icon-button.js' import '@material/web/icon/icon.js' -import './BottomNavBar.css' +import './NavigationBar.css' -function BottomNavBar() { +export default function NavigationBar() { return ( ) } - -export default BottomNavBar diff --git a/frontend/src/PollListItem.css b/frontend/src/components/PollListItem.css similarity index 94% rename from frontend/src/PollListItem.css rename to frontend/src/components/PollListItem.css index 528d93a..244d65d 100644 --- a/frontend/src/PollListItem.css +++ b/frontend/src/components/PollListItem.css @@ -3,7 +3,6 @@ display: flex; justify-content: space-between; align-items: center; - padding: 1rem; } .poll-list-item .name { diff --git a/frontend/src/components/PollListItem.js b/frontend/src/components/PollListItem.js new file mode 100644 index 0000000..583e3f0 --- /dev/null +++ b/frontend/src/components/PollListItem.js @@ -0,0 +1,35 @@ +import '@material/web/list/list-item' +import '@material/web/ripple/ripple' +import '@material/web/switch/switch.js' + +import './PollListItem.css' +import React from "react"; + +export default function PollListItem( + poll, + setEditPoll, + updatePoll, +) { + return ( + setEditPoll(poll)}> + +
+
+
{poll.name}
+
+ {poll.daysOfWeek} +  •  + {poll.time} +  •  + {poll.questionNumber} +
+
+ { + event.nativeEvent.stopPropagation() + poll.isEnabled = !poll.isEnabled + updatePoll(poll) + }} {...(poll.isEnabled ? {selected: true} : {})}> +
+
+ ) +} diff --git a/frontend/src/components/Scaffold.css b/frontend/src/components/Scaffold.css new file mode 100644 index 0000000..7d8e321 --- /dev/null +++ b/frontend/src/components/Scaffold.css @@ -0,0 +1,46 @@ +.scaffold { + display: flex; + flex-direction: column; + width: 100%; + height: 100%; + background-color: var(--md-sys-color-surface); +} + +.scaffold > .top-bar { + flex-shrink: 0; +} + +.scaffold > .content { + flex-grow: 1; + flex-shrink: 1; + overflow-y: auto; +} + +.scaffold > .bottom-bar { + flex-shrink: 0; + position: relative; +} + +.scaffold > .bottom-bar > aside { + position: absolute; + right: 0; + bottom: 100%; + left: 0; + display: flex; + flex-direction: column; + gap: 1rem; + padding: 1rem; + pointer-events: none; +} + +.scaffold > .bottom-bar > aside > * { + z-index: 1; +} + +.scaffold > .bottom-bar > aside > * > * { + pointer-events: auto; +} + +.scaffold > .bottom-bar > aside > .floating-action-button { + text-align: right; +} diff --git a/frontend/src/components/Scaffold.js b/frontend/src/components/Scaffold.js new file mode 100644 index 0000000..ab5cfda --- /dev/null +++ b/frontend/src/components/Scaffold.js @@ -0,0 +1,25 @@ +import './Scaffold.css' + +export default function Scaffold({ + topBar, + bottomBar, + snackbarHost, + floatingActionButton, + content, +}) { + return ( +
+
{topBar}
+
+ {content} +
+
+ + {bottomBar} +
+
+ ) +} diff --git a/frontend/src/components/Snackbar.css b/frontend/src/components/Snackbar.css new file mode 100644 index 0000000..e69de29 diff --git a/frontend/src/components/Snackbar.js b/frontend/src/components/Snackbar.js new file mode 100644 index 0000000..e69de29 diff --git a/frontend/src/components/TopAppBar.css b/frontend/src/components/TopAppBar.css new file mode 100644 index 0000000..d6f8a8e --- /dev/null +++ b/frontend/src/components/TopAppBar.css @@ -0,0 +1,20 @@ +.top-app-bar { + flex-shrink: 0; + display: flex; + align-items: center; + gap: .5rem; + padding: .5rem; +} + +.top-app-bar > * { + flex-shrink: 0; +} + +.top-app-bar > .title { + flex-grow: 1; + flex-shrink: 1; + color: var(--md-sys-color-on-surface); + white-space: nowrap; + overflow-x: hidden; + text-overflow: ellipsis; +} diff --git a/frontend/src/components/TopAppBar.js b/frontend/src/components/TopAppBar.js new file mode 100644 index 0000000..0318197 --- /dev/null +++ b/frontend/src/components/TopAppBar.js @@ -0,0 +1,22 @@ +import '@material/web/iconbutton/icon-button' +import '@material/web/icon/icon' +import '@material/web/button/filled-button' + +import './TopAppBar.css' + +export default function TopAppBar({ + onDismissRequest, +}) { + return ( +
+ onDismissRequest()}> + close + +
Изменить опрос
+ onDismissRequest()}>Сохранить + + more_vert + +
+ ) +} diff --git a/frontend/src/index.css b/frontend/src/index.css index e22d5a4..9d9daf6 100644 --- a/frontend/src/index.css +++ b/frontend/src/index.css @@ -6,3 +6,17 @@ body { margin: 0; scroll-behavior: smooth; } + +#root { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + display: flex; + flex-direction: column; + justify-content: space-between; + margin: 0; + background-color: var(--md-sys-color-surface); + scroll-behavior: smooth; +} diff --git a/frontend/src/index.js b/frontend/src/index.js index 9f08a0c..126124f 100644 --- a/frontend/src/index.js +++ b/frontend/src/index.js @@ -1,13 +1,14 @@ import React from 'react' import ReactDOM from 'react-dom/client' +import '@material/web/fab/fab' + import './index.css' -import App from './App' -import BottomNavBar from "./BottomNavBar" +import MainActivity from "./activities/MainActivity"; const root = ReactDOM.createRoot(document.getElementById('root')) + root.render( - - + ) diff --git a/frontend/src/screens/ChatsScreen.css b/frontend/src/screens/ChatsScreen.css new file mode 100644 index 0000000..e69de29 diff --git a/frontend/src/screens/ChatsScreen.js b/frontend/src/screens/ChatsScreen.js new file mode 100644 index 0000000..e69de29 diff --git a/frontend/src/screens/DashboardScreen.css b/frontend/src/screens/DashboardScreen.css new file mode 100644 index 0000000..e69de29 diff --git a/frontend/src/screens/DashboardScreen.js b/frontend/src/screens/DashboardScreen.js new file mode 100644 index 0000000..e69de29 diff --git a/frontend/src/screens/PollsScreen.css b/frontend/src/screens/PollsScreen.css new file mode 100644 index 0000000..e69de29 diff --git a/frontend/src/screens/PollsScreen.js b/frontend/src/screens/PollsScreen.js new file mode 100644 index 0000000..ef5a7d4 --- /dev/null +++ b/frontend/src/screens/PollsScreen.js @@ -0,0 +1,138 @@ +import React, {useEffect, useState} from "react" +import '@material/web/textfield/outlined-text-field' +import '@material/web/fab/fab' +import '@material/web/icon/icon' +import '@material/web/select/outlined-select' +import '@material/web/select/select-option' +import '@material/web/list/list' +import '@material/web/list/list-item' + +import FullScreenDialog from "../components/FullScreenDialog" +import PollListItem from "../components/PollListItem" + +import './PollsScreen.css' + +const PollContext = React.createContext({ + polls: [], + fetchPolls: () => {}, +}) + +const apiUrl = new URL(location) +apiUrl.pathname = '/api/polls' + +export default function PollsScreen() { + const [polls, setPolls] = useState([]) + const [editPoll, setEditPoll] = useState(false) + + const fetchPolls = async () => { + const response = await fetch('/api/polls') + const polls = await response.json() + setPolls(polls) + } + + const updatePoll = async (poll) => { + await fetch(apiUrl, { + method: 'PUT', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(poll) + }) + await fetchPolls() + } + + useEffect(() => { + fetchPolls() + }, []) + + return ( +
+ + + + {polls.map((poll) => ( + PollListItem(poll, setEditPoll, updatePoll) + ))} + + + + + + + title + + + + + date_range + + +
Понедельник
+
+ + +
Вторник
+
+ + +
Среда
+
+ + +
Четверг
+
+ + +
Пятница
+
+ + +
Суббота
+
+ + +
Воскресенье
+
+ +
+ +
+
Сообщения
+ + + Fruits + + + + Apple + + + Banana + + +
Cucumber
+
Cucumbers are long green fruits that are just as long as this + multi-line description +
+
+ +
Shop for Kiwis
+
This will link you out in a new tab
+ open_in_new +
+
+
+ +
+ +
+ ) +} diff --git a/frontend/src/screens/UsersScreen.css b/frontend/src/screens/UsersScreen.css new file mode 100644 index 0000000..e69de29 diff --git a/frontend/src/screens/UsersScreen.js b/frontend/src/screens/UsersScreen.js new file mode 100644 index 0000000..e69de29