Разработано несколько компонентов интерфейса веб-приложения

Этот коммит содержится в:
Глеб Иваницкий 2024-08-17 00:52:52 +03:00
родитель 98bfb4196b
Коммит 7e7e3ef500
12 изменённых файлов: 216 добавлений и 24 удалений

Просмотреть файл

@ -19,6 +19,7 @@
link.type = 'text/css'
document.head.append(link)
window.Telegram.WebApp.expand()
window.Telegram.WebApp.ready()
})
</script>

Просмотреть файл

@ -12,10 +12,6 @@
scroll-behavior: smooth;
}
main {
padding: 1rem;
}
main > * {
width: 100%;
}

Просмотреть файл

@ -1,7 +1,7 @@
import React, { useEffect } from 'react';
import React, { useEffect } from 'react'
import { styles as typescaleStyles } from '@material/web/typography/md-typescale-styles.js'
import { styles as typescaleStyles } from '@material/web/typography/md-typescale-styles.js';
import '@material/web/switch/switch.js';
import PollList from "./PollList";
import './App.css'
@ -9,10 +9,11 @@ function App() {
useEffect(() => {
document.adoptedStyleSheets = [typescaleStyles.styleSheet]
}, [])
return (
<main className="App">
<md-outlined-text-field id="text" label="Favorite color"></md-outlined-text-field>
<md-switch id="switch"></md-switch>
<PollList />
</main>
// <div className="App">
// <header className="App-header">

45
frontend/src/FullScreenDialog.css Обычный файл
Просмотреть файл

@ -0,0 +1,45 @@
.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;
}
}

28
frontend/src/FullScreenDialog.js Обычный файл
Просмотреть файл

@ -0,0 +1,28 @@
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 (
<div className="full-screen-dialog">
<div className="top-app-bar">
<md-icon-button onClick={() => setEditPoll(false)}>
<md-icon>close</md-icon>
</md-icon-button>
<div className="title md-typescale-title-large">Изменить опрос</div>
<md-filled-button onClick={() => setEditPoll()}>Сохранить</md-filled-button>
<md-icon-button>
<md-icon>more_vert</md-icon>
</md-icon-button>
</div>
</div>
)
}

4
frontend/src/PollList.css Обычный файл
Просмотреть файл

@ -0,0 +1,4 @@
.poll-list {
display: flex;
flex-direction: column;
}

37
frontend/src/PollList.js Обычный файл
Просмотреть файл

@ -0,0 +1,37 @@
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 (
<div className="poll-list">
<PollContext.Provider value={{polls, fetchPolls}}>
{polls.map((poll) => (
PollListItem(poll, setEditPoll)
))}
</PollContext.Provider>
{editPoll ? <FullScreenDialog editPoll={editPoll} setEditPoll={setEditPoll} /> : null}
</div>
)
}

20
frontend/src/PollListItem.css Обычный файл
Просмотреть файл

@ -0,0 +1,20 @@
.poll-list-item {
position: relative;
display: flex;
justify-content: space-between;
align-items: center;
padding: 1rem;
}
.poll-list-item .name {
color: var(--md-sys-color-on-surface);
}
.poll-list-item .caption {
margin-top: .5rem;
color: var(--md-sys-color-on-surface-variant);
}
md-switch {
margin-left: 1rem;
}

22
frontend/src/PollListItem.js Обычный файл
Просмотреть файл

@ -0,0 +1,22 @@
import '@material/web/switch/switch.js'
import './PollListItem.css'
export default function PollListItem(data, setEditPoll) {
return (
<div className="poll-list-item" onClick={() => setEditPoll(true)}>
<md-ripple></md-ripple>
<div>
<div className="name md-typescale-title-large">{data.name}</div>
<div className="caption md-typescale-body-medium">
<span>{data.days_of_week}</span>
&nbsp;&bull;&nbsp;
<span>{data.time}</span>
&nbsp;&bull;&nbsp;
<span>{data.question_number}</span>
</div>
</div>
<md-switch></md-switch>
</div>
)
}

Просмотреть файл

@ -1,3 +1,7 @@
*:not(input, textarea, label) {
user-select: none;
}
body {
margin: 0;
scroll-behavior: smooth;

Просмотреть файл

@ -1,13 +1,13 @@
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import BottomNavBar from "./BottomNavBar";
import React from 'react'
import ReactDOM from 'react-dom/client'
import './index.css'
import App from './App'
import BottomNavBar from "./BottomNavBar"
const root = ReactDOM.createRoot(document.getElementById('root'));
const root = ReactDOM.createRoot(document.getElementById('root'))
root.render(
<React.StrictMode>
<App />
<BottomNavBar />
</React.StrictMode>
);
)

Просмотреть файл

@ -72,15 +72,49 @@ async def _():
)
@app.websocket(
path='/ws/sync',
polls = [
{
'id': 1,
'name': 'Текущее состояние сотрудников',
'days_of_week': 'ПН-ПТ',
'time': '11:00',
'question_number': '1 вопрос',
},
{
'id': 2,
'name': 'Планы на обед',
'days_of_week': 'ПН-ПТ',
'time': '11:45-12:00',
'question_number': '2 вопроса',
},
]
@app.get(
path='/api/polls',
)
async def _():
return polls
@app.post(
path='/api/polls',
)
async def _(
websocket: WebSocket,
poll: dict,
):
await connection_manager.connect(websocket)
try:
while True:
await connection_manager.broadcast(await websocket.receive_json())
except WebSocketDisconnect:
connection_manager.disconnect(websocket)
polls.append(poll)
# @app.websocket(
# path='/ws/sync',
# )
# async def _(
# websocket: WebSocket,
# ):
# await connection_manager.connect(websocket)
# try:
# while True:
# await connection_manager.broadcast(await websocket.receive_json())
# except WebSocketDisconnect:
# connection_manager.disconnect(websocket)