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 (
-
-
-
-
- //
- )
-}
-
-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