Поправил фронтенд
This commit is contained in:
parent
61c7b04d34
commit
b60dfdfb42
5 changed files with 78 additions and 60 deletions
|
@ -1,16 +1,18 @@
|
|||
import { Navigate, Route, RouterProvider, createBrowserRouter, createRoutesFromElements, useLocation, useRouteLoaderData } from 'react-router-dom'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import { UserProvider } from './store/user'
|
||||
import { ajax } from './utils/fetch'
|
||||
|
||||
import Layout from './components/Layout'
|
||||
|
||||
import Index from './pages/Index'
|
||||
import Login from './pages/Login'
|
||||
import Register from './pages/Register'
|
||||
import NoMatch from './pages/NoMatch'
|
||||
import { UserProvider } from './store/user'
|
||||
import { ajax } from './utils/fetch'
|
||||
import Engine from './pages/Engine'
|
||||
import Quests from './pages/Quests'
|
||||
import User from './pages/User'
|
||||
|
||||
const router = createBrowserRouter(
|
||||
createRoutesFromElements(
|
||||
|
@ -30,6 +32,7 @@ const router = createBrowserRouter(
|
|||
element={<Auth><Quests /></Auth>}
|
||||
loader={() => ajax('/api/games').catch(x => { console.log(x); return null })}
|
||||
/>
|
||||
<Route path="me" element={<User />} />
|
||||
<Route path="login" element={<Login />} />
|
||||
<Route path="register" element={<Register />} />
|
||||
<Route
|
||||
|
|
|
@ -3,10 +3,11 @@
|
|||
padding-top: 0 !important;
|
||||
padding-bottom: 0 !important;
|
||||
height: 40px;
|
||||
width: 85px;
|
||||
width: 135px;
|
||||
background-image: url("./logo_small.png");
|
||||
background-size: 100%;
|
||||
background-size: cover;
|
||||
display: inline-block;
|
||||
margin-right: 50px;
|
||||
}
|
||||
|
||||
th.thin {
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import { useEffect } from 'react'
|
||||
import { Link, Outlet, useLoaderData, useLocation, useNavigate } from 'react-router-dom'
|
||||
import { UserProvider } from '../store/user'
|
||||
import { useEffect } from 'react'
|
||||
import { ajax } from '../utils/fetch'
|
||||
import { Layout, Menu, Progress, Space } from 'antd'
|
||||
import { FireTwoTone, StarTwoTone } from '@ant-design/icons'
|
||||
import { Layout, Menu } from 'antd'
|
||||
import { MenuOutlined } from '@ant-design/icons'
|
||||
import { Content, Header } from 'antd/es/layout/layout'
|
||||
|
||||
const AppLayout = () => {
|
||||
|
@ -34,65 +34,32 @@ const AppLayout = () => {
|
|||
link: '/quests'
|
||||
},
|
||||
{
|
||||
key: 'user',
|
||||
label: user.username,
|
||||
children: [
|
||||
{
|
||||
type: 'group',
|
||||
key: 'exp',
|
||||
label: (
|
||||
<Space>
|
||||
<Space title={`${user.level} уровень`}><StarTwoTone />{user.level} уровень</Space>
|
||||
<Space title={`${user.experience} опыта`}><FireTwoTone />{user.experience} опыт</Space>
|
||||
</Space>)
|
||||
},
|
||||
{
|
||||
type: 'group',
|
||||
key: 'progress',
|
||||
label: <Progress
|
||||
value={user.experience}
|
||||
percent={((user.experience - user.expToCurrentLevel) / (user.expToNextLevel - user.expToCurrentLevel) * 100)}
|
||||
size="small"
|
||||
showInfo={false}
|
||||
/>
|
||||
},
|
||||
{
|
||||
type: 'group',
|
||||
key: 'nextLevel',
|
||||
label: `Следующий уровень - ${user.expToNextLevel} очков опыта`
|
||||
key: 'me',
|
||||
label: `${user.username} [${user.level}]`,
|
||||
link: '/me'
|
||||
},
|
||||
{
|
||||
key: 'logout',
|
||||
label: 'Выход',
|
||||
handler: logout
|
||||
}
|
||||
]
|
||||
onClick: logout
|
||||
}
|
||||
]
|
||||
}
|
||||
const menuHandler = (x) => {
|
||||
const item = getItemByPath(items, x.keyPath)
|
||||
const item = items.find(y => y.key === x.key)
|
||||
if (item.link) { navigate(item.link) }
|
||||
if (item.handler) { item.handler() }
|
||||
}
|
||||
|
||||
const getItemByPath = (items, path) => {
|
||||
const x = path.pop()
|
||||
const item = items.find(y => y.key === x)
|
||||
if (path.length === 0) {
|
||||
return item
|
||||
}
|
||||
return getItemByPath(item.children, path)
|
||||
}
|
||||
|
||||
return (<Layout>
|
||||
<Header style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
|
||||
<Header style={{ display: 'flex', alignItems: 'center', width: '100%', justifyContent: 'space-between' }}>
|
||||
<Link to="/" className="navbar-brand"></Link>
|
||||
<Menu
|
||||
mode="horizontal"
|
||||
items={items}
|
||||
selectedKeys={location.pathname.replace('/', '')}
|
||||
onClick={menuHandler}
|
||||
overflowedIndicator={<MenuOutlined />}
|
||||
style={{ width: '100%' }}
|
||||
/>
|
||||
</Header>
|
||||
<Content style={{ padding: '0 24px' }}>
|
||||
|
|
|
@ -2,10 +2,10 @@ import { useLoaderData, useNavigate } from 'react-router-dom'
|
|||
import Markdown from 'react-markdown'
|
||||
import remarkGfm from 'remark-gfm'
|
||||
import moment from 'moment/min/moment-with-locales'
|
||||
import { Avatar, Typography, Button, Space, Card } from 'antd'
|
||||
import { Avatar, Typography, Button, Space, Card, Popover } from 'antd'
|
||||
import { UserProvider } from '../store/user'
|
||||
|
||||
const { Title } = Typography
|
||||
const { Title, Paragraph } = Typography
|
||||
|
||||
const Quests = () => {
|
||||
moment.locale('ru')
|
||||
|
@ -22,10 +22,25 @@ const Quests = () => {
|
|||
|
||||
const renderItem = (user, navigate, item) => {
|
||||
const actions = [
|
||||
<Space key='exp' title={`${item.points} опыта за выполнение квеста`}>Оп: {item.points}</Space>,
|
||||
<Space key='taskCount' title={`${item.taskCount} уровней в квесте`}>Ур: {item.taskCount}</Space>,
|
||||
<Popover
|
||||
key='type'
|
||||
content={<Paragraph>Квесты бывают двух типов: <ul><li><b>Виртуальные</b> - проходимые из дома</li><li><b>Полевые</b> - проходимые в городе Казани</li></ul></Paragraph>}
|
||||
title="Тип квеста">
|
||||
<Space>
|
||||
{item.type === 'city' ? 'Полевой' : 'Виртуальный'}
|
||||
</Space>
|
||||
</Popover>,
|
||||
<Popover
|
||||
key='exp'
|
||||
content={<Paragraph>Вы получите {item.points} очков опыта за выполнение этого квеста.<br />Чем сложнее квест - тем больше за него опыта!</Paragraph>}
|
||||
title='Опыт за выполнения квеста'>
|
||||
<Space>{item.points} ОО</Space>
|
||||
</Popover>,
|
||||
<Popover key='taskCount' content={`Этот квест состоит из ${item.taskCount} уровней`} title='Количество уровней в квесте'>
|
||||
<Space>{item.taskCount} ур</Space>
|
||||
</Popover>,
|
||||
<>{moment(item.createdAt).fromNow()}</>,
|
||||
<>Автор(ы) {item.authors.map(a => a.username)}</>
|
||||
<>Автор {item.authors.map(a => a.username)}</>
|
||||
]
|
||||
|
||||
let questAction = (<span>Необходимо войти</span>)
|
||||
|
@ -41,11 +56,9 @@ const renderItem = (user, navigate, item) => {
|
|||
<Card
|
||||
key={item.id}
|
||||
actions={actions}
|
||||
title={item.title}
|
||||
title={<><Avatar src={`/api/file/${item.icon}`} /> {item.title}</>}
|
||||
style={{ marginBottom: 8 }}
|
||||
>
|
||||
|
||||
<Avatar src={`/api/file/${item.icon}`} style={{ float: 'left', margin: '4px' }} />
|
||||
<Markdown
|
||||
remarkPlugins={[remarkGfm]}>
|
||||
{item.description}
|
||||
|
|
34
frontend/src/pages/User.jsx
Normal file
34
frontend/src/pages/User.jsx
Normal file
|
@ -0,0 +1,34 @@
|
|||
import { Avatar, Popover, Progress, Space, Typography } from 'antd'
|
||||
import { UserProvider } from '../store/user'
|
||||
import Markdown from 'react-markdown'
|
||||
|
||||
const { Paragraph } = Typography
|
||||
|
||||
const User = () => {
|
||||
const { user } = UserProvider.useContainer()
|
||||
if (user == null) {
|
||||
return (<Space>Загрузка...</Space>)
|
||||
}
|
||||
|
||||
return (<>
|
||||
<h1>{user.username}</h1>
|
||||
<Paragraph>Уровень: {user.level} ур</Paragraph>
|
||||
<Paragraph>Очков опыта: {user.experience} ОО</Paragraph>
|
||||
<Paragraph>Следующий уровень: {user.expToNextLevel} ОО</Paragraph>
|
||||
<Progress
|
||||
value={user.experience}
|
||||
percent={((user.experience - user.expToCurrentLevel) / (user.expToNextLevel - user.expToCurrentLevel) * 100)}
|
||||
size="small"
|
||||
showInfo={false}
|
||||
/>
|
||||
{user.games.map(item => <Popover
|
||||
key={item.id}
|
||||
title={item.title}
|
||||
content={<Markdown>{item.description}</Markdown>}
|
||||
>
|
||||
<Avatar size={64} style={{ marginRight: 4, marginBottom: 4 }} key={item.id} src={`/api/file/${item.icon}`} />
|
||||
</Popover>)}
|
||||
</>)
|
||||
}
|
||||
|
||||
export default User
|
Loading…
Reference in a new issue