Создание команды
This commit is contained in:
parent
9a705f5b03
commit
7c96c41230
9 changed files with 117 additions and 83 deletions
|
@ -49,6 +49,21 @@ paths:
|
|||
$ref: '#/components/responses/teamsListResponse'
|
||||
403:
|
||||
$ref: '#/components/responses/errorResponse'
|
||||
post:
|
||||
requestBody:
|
||||
content:
|
||||
'application/json':
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
required: [ name ]
|
||||
responses:
|
||||
200:
|
||||
$ref: '#/components/responses/teamResponse'
|
||||
404:
|
||||
$ref: '#/components/responses/errorResponse'
|
||||
/teams/{teamID}:
|
||||
get:
|
||||
parameters:
|
||||
|
|
|
@ -27,6 +27,9 @@ type ServerInterface interface {
|
|||
// (GET /teams)
|
||||
GetTeams(ctx echo.Context) error
|
||||
|
||||
// (POST /teams)
|
||||
PostTeams(ctx echo.Context) error
|
||||
|
||||
// (GET /teams/{teamID})
|
||||
GetTeamsTeamID(ctx echo.Context, teamID int) error
|
||||
|
||||
|
@ -74,6 +77,17 @@ func (w *ServerInterfaceWrapper) GetTeams(ctx echo.Context) error {
|
|||
return err
|
||||
}
|
||||
|
||||
// PostTeams converts echo context to params.
|
||||
func (w *ServerInterfaceWrapper) PostTeams(ctx echo.Context) error {
|
||||
var err error
|
||||
|
||||
ctx.Set(CookieAuthScopes, []string{})
|
||||
|
||||
// Invoke the callback with all the unmarshaled arguments
|
||||
err = w.Handler.PostTeams(ctx)
|
||||
return err
|
||||
}
|
||||
|
||||
// GetTeamsTeamID converts echo context to params.
|
||||
func (w *ServerInterfaceWrapper) GetTeamsTeamID(ctx echo.Context) error {
|
||||
var err error
|
||||
|
@ -196,6 +210,7 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL
|
|||
|
||||
router.GET(baseURL+"/games", wrapper.GetGames)
|
||||
router.GET(baseURL+"/teams", wrapper.GetTeams)
|
||||
router.POST(baseURL+"/teams", wrapper.PostTeams)
|
||||
router.GET(baseURL+"/teams/:teamID", wrapper.GetTeamsTeamID)
|
||||
router.DELETE(baseURL+"/teams/:teamID/members", wrapper.DeleteTeamsTeamIDMembers)
|
||||
router.POST(baseURL+"/teams/:teamID/members", wrapper.PostTeamsTeamIDMembers)
|
||||
|
@ -209,22 +224,22 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL
|
|||
// Base64 encoded, gzipped, json marshaled Swagger object
|
||||
var swaggerSpec = []string{
|
||||
|
||||
"H4sIAAAAAAAC/8xYTW/jNhD9KwXbo2B5d3PSbYsAQdAEaF23F8MHRpo4TC1S5YwSGIH+ezEUJUuRZEuO",
|
||||
"4+4pCjnkvPfmQ2O9idikmdGgCUX0Jiz8mwPSryZR4Ba2ZqM0P8RGE2jiR5llWxVLUkaHz2jcNsZPkEp+",
|
||||
"yqzJwJI/D6lUW36gXQYiEkhW6Y0oApFJxFdjk57NInBAlIVERCt/R+PEOqhOmIdniEkU7SNkc3ALG4UE",
|
||||
"9tLw95tfe3dzBKtlCseZ15ZBV4Sml1GCuBXMjEbPzVpjF37lAxrFJmlSUZpgA5aJpoAoNyN4uiv29v10",
|
||||
"EsDYqowxiUjw/RuZwp1COomEIkgd/l8sPIpI/BzuSyEszTBkD38reGVvHpK0Vu6GEBHI9BySWpAEyXfq",
|
||||
"zR+VDMmdPoDF0eQY7L0706UXiIEMDaoeMc3PojzUo2M7ExQntk/5ik/DZdCQZmyWsHv83DRhF1PShOv6",
|
||||
"DGky3J2GUoSBHiPD4JZsN6lVucB1+tW4GBWBp+hY1TXX4ds6N4E1krQ0UEwuO84Q6ECQou1YoUrbthJ7",
|
||||
"nBWqrnrlji/aiW3DmhLemNgv2NbHf8yZUpOet5fwfg8XbtU4yx4xkddFMfYn5mGAcW4taFr62vP7D8Zs",
|
||||
"QeqRDb27OaEsfUkeZleXfYfdELzhN8TkTDuA2l12CPDCewOdp3y4VI35yoyk0o3D7aTpj+UQ21NbYU8L",
|
||||
"DARCnFtFuz9ZjWqMMv8o+J7Tk0PBnbFcqqSIBAJi2Smq3pOp38C/ZZR+NA5b2YaE/sMVUyBewGLZab/M",
|
||||
"5rM5czEZaJkpEYlvsy+zuZsl6cnBcCNP2YfBpTNr415Ht4mIxA3QjTN4N0x+nc+HIl7bhZ15rSmFiFZr",
|
||||
"/j+sO/IQgKUzOAVAdxQoAnE1/3b8ZHtYLoo90vCN/9xeF0chL52dE9vKFMiV9srHmgOwjzRVpu0ZPmiM",
|
||||
"Au8ztFifqkhbjKuziBE2elcCWyDo6nLt1hvS3NcD3ycqVP3A3U0avLicb697by06v6wuqHwgMoM9Ofe7",
|
||||
"Qbq0sv9f7lUjwFD5/eXf8pMhtgb1D/UKvimsv6YMB42h3jmzTrL2e218sPH3F+dhOp/OtKebV7xNTqOI",
|
||||
"s10H/1Vn+heYxzEg/uSvPjfi5rejw5gXleUJ8aq9/Dghay+0x5LVmgsdwb5U7SO3WxGJkGeJYl38FwAA",
|
||||
"//8/OTdEThQAAA==",
|
||||
"H4sIAAAAAAAC/8xYXW+jOhD9K1e+9xGF9OOJt15VqqrbSnez2X2J8uDCNHU32Kw9tIoq/vtqjE2gQAJp",
|
||||
"+vFUao/tc47PDENeWKzSTEmQaFj0wjT8zsHgvyoRYAfWaiUkPcRKIkikR55laxFzFEqGj0bZaRM/QMrp",
|
||||
"KdMqA41uPaRcrOkBNxmwiBnUQq5YEbCMG/OsdNIxWQQWiNCQsGjh9qitWAZ+hbp7hBhZ0VyCOgc7sBIG",
|
||||
"QX80/O3kaedsbkBLnsJ+5lVk0BahfsogQeyIyZQ0jpvWSs/cyBs0ilVSpyIkwgo0EU3BGL4awNNusY3v",
|
||||
"ppOAibXICBOLGO2/4incCIMHkRAIqcX/j4Z7FrG/w20qhGWYCemEnwKe6TQHiWvNN32IEHh6DEk1cITk",
|
||||
"Ajv9I5I+udM70GYwOQJ7a9e06QWsx6GBrxHjzpmVizp0bDpBkLGd5T2f2pFBTZqhLqHjzfvahI4YYxPK",
|
||||
"6yPYpL869VmEgO4jQ+DmFDeqVNmLa9WrYXdUBI6iZVXlXItvY90I1ga5xp5ksu44wkUHDAWuhwpVxjaV",
|
||||
"2OL0qNrqlTMuaUeWDa1KeEPufkax7v6HrCk16Xh7MXfu7sT1hbOsESN5fSjGbmPuBhjnWoPEucs9N3+n",
|
||||
"1Bq4HFjQ25Mj0tKl5G52Vdq32PXB639DjHbaDtR2s12AZ+40kHlKi0vViC/PkAtZW9w0Tfdd9rE9tBR2",
|
||||
"lMCAGYhzLXDzndTwbZT6JeAixweLgipjOeSliJgBY8pK4WtPJv4D95YR8l5ZbGUZYvKbTaaAPYE2ZaU9",
|
||||
"mUwnU+KiMpA8EyxiZ5OTydT2kvhgYdiWp6zDYO1M2tjX0XXCInYFeGUDXjWTp9Np341XcWGrX6tLwaLF",
|
||||
"kv4Pq4rcB2BuAw4B0G4FioCdT8/2r2w2y1bwTJkOfP8rUwPov6Y2b3jLDzNdn9dabf9goZoanR+gUXWb",
|
||||
"4Qv9ub4s9l7r3MZZQ2qeAtryt3D5QCbdZgP60OZ3TlAT8nUWF8uvJEZYq+8JrAGhrculHa9Jc1s1xe+o",
|
||||
"0GG2pZJ3fdm566facG+qfqCyn+c93yb1pd8P1wmNhtj4mDm4nnqIYfWLU/+lEdQbG9Yya/eptR+13P7F",
|
||||
"cZhOxzPteON53irHQcQproX/vPWFxEwex2DMX27rYyOu/762G/PMRx5wX9UpX+fKmgPN1m2xpEQ3oJ98",
|
||||
"+cj1mkUspH6rWBZ/AgAA//94VTXBchUAAA==",
|
||||
}
|
||||
|
||||
// GetSwagger returns the content of the embedded swagger specification file
|
||||
|
|
|
@ -103,6 +103,11 @@ type Register struct {
|
|||
Username string `json:"username"`
|
||||
}
|
||||
|
||||
// PostTeamsJSONBody defines parameters for PostTeams.
|
||||
type PostTeamsJSONBody struct {
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
// DeleteTeamsTeamIDMembersJSONBody defines parameters for DeleteTeamsTeamIDMembers.
|
||||
type DeleteTeamsTeamIDMembersJSONBody = interface{}
|
||||
|
||||
|
@ -120,6 +125,9 @@ type PostUserRegisterJSONBody struct {
|
|||
Username string `json:"username"`
|
||||
}
|
||||
|
||||
// PostTeamsJSONRequestBody defines body for PostTeams for application/json ContentType.
|
||||
type PostTeamsJSONRequestBody PostTeamsJSONBody
|
||||
|
||||
// DeleteTeamsTeamIDMembersJSONRequestBody defines body for DeleteTeamsTeamIDMembers for application/json ContentType.
|
||||
type DeleteTeamsTeamIDMembersJSONRequestBody = DeleteTeamsTeamIDMembersJSONBody
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { Link, Outlet, useLoaderData } from "react-router-dom";
|
||||
import { Button } from "react-bootstrap";
|
||||
import { Button, Nav, Container, NavbarBrand, NavbarToggle, Navbar, NavbarCollapse, ButtonGroup } from "react-bootstrap";
|
||||
import { UserProvider } from "../store/user";
|
||||
import { useEffect } from "react";
|
||||
import { ajax } from "../utils/fetch";
|
||||
|
@ -15,53 +15,48 @@ export default () => {
|
|||
ajax("/api/user/logout", {
|
||||
method: "POST",
|
||||
}).
|
||||
then(() => setUser(null))
|
||||
then(() => setUser(null))
|
||||
}
|
||||
|
||||
return (<>
|
||||
<nav className="navbar navbar-expand-lg bg-primary" data-bs-theme="dark">
|
||||
<div className="container">
|
||||
<a className="navbar-brand" href="https://nquest.ru/">nQuest</a>
|
||||
<button className="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent"
|
||||
aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span className="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div className="collapse navbar-collapse" id="navbarSupportedContent">
|
||||
<ul className="navbar-nav me-auto mb-2 mb-lg-0">
|
||||
<li className="nav-item">
|
||||
<Navbar className="navbar navbar-expand-lg bg-primary" data-bs-theme="dark">
|
||||
<Container>
|
||||
<NavbarBrand href="https://nquest.ru/">nQuest</NavbarBrand>
|
||||
<Navbar.Toggle aria-controls="basic-navbar-nav" />
|
||||
<NavbarCollapse id="basic-navbar-nav" className="justify-content-end">
|
||||
<Nav className="me-auto">
|
||||
<Nav.Item>
|
||||
<Link className="nav-link" to="/">Игры</Link>
|
||||
</li>
|
||||
</Nav.Item>
|
||||
|
||||
<li className="nav-item">
|
||||
<Nav.Item>
|
||||
<Link className="nav-link" to="/teams">Команды</Link>
|
||||
</li>
|
||||
</ul>
|
||||
<div className="d-flex">
|
||||
{user ? (
|
||||
<>
|
||||
<span className="navbar-text me-2">
|
||||
</Nav.Item>
|
||||
</Nav>
|
||||
<Navbar.Text>
|
||||
{user ? (
|
||||
<>
|
||||
{user.username}
|
||||
{user.team ? (
|
||||
<>(<Link to={`teams/${user.team.id}`}>{user.team.name}</Link>)</>
|
||||
) : (
|
||||
<>(без команды)</>
|
||||
)}
|
||||
</span>
|
||||
<Button type="button" variant="outline-success" onClick={logout}>Выход</Button>
|
||||
</>
|
||||
) : (
|
||||
<div className="btn-group">
|
||||
<Link className="btn btn-success" to="login">Вход</Link>
|
||||
<Link className="btn btn-outline-success" to="register">Регистрация</Link>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
)}
|
||||
<Button type="button" variant="outline-success" onClick={logout}>Выход</Button>
|
||||
</>
|
||||
) : (
|
||||
<ButtonGroup>
|
||||
<Link className="btn btn-success" to="login">Вход</Link>
|
||||
<Link className="btn btn-outline-success" to="register">Регистрация</Link>
|
||||
</ButtonGroup>
|
||||
)}
|
||||
</Navbar.Text>
|
||||
</NavbarCollapse>
|
||||
</Container>
|
||||
</Navbar>
|
||||
|
||||
<div className="container my-5">
|
||||
<Container>
|
||||
<Outlet />
|
||||
</div>
|
||||
</Container>
|
||||
</>);
|
||||
}
|
|
@ -7,7 +7,7 @@ export default () => {
|
|||
|
||||
return (<>
|
||||
<h1 className="mb-4">Текущие игры</h1>
|
||||
{games.map(game => (
|
||||
{games && games.map(game => (
|
||||
<>
|
||||
<h3>{game.title}</h3>
|
||||
<Table className="table table-bordered mb-4">
|
||||
|
@ -43,6 +43,6 @@ export default () => {
|
|||
</Table>
|
||||
</>
|
||||
))}
|
||||
{games.length == 0 ? (<strong>Игр пока не анонсировано</strong>) : null}
|
||||
{!games ? (<strong>Игр пока не анонсировано</strong>) : null}
|
||||
</>);
|
||||
}
|
|
@ -10,20 +10,16 @@ export default () => {
|
|||
|
||||
const onCreate = (e) => {
|
||||
e.preventDefault();
|
||||
ajax("/api/teams/", {
|
||||
ajax("/api/teams", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({ name })
|
||||
}).then(({team}) => {
|
||||
if (!team) {
|
||||
setError("Ошибка создания команды")
|
||||
return
|
||||
}
|
||||
navigate(`/teams/${team.ID}`)
|
||||
})
|
||||
}).then((team) => {
|
||||
navigate(`/teams/${team.id}`)
|
||||
}).catch(e => setError(e.message))
|
||||
}
|
||||
return (<>
|
||||
<h1>Создание команды</h1>
|
||||
|
|
|
@ -7,8 +7,14 @@ export default () => {
|
|||
if (!teams) {
|
||||
return null
|
||||
}
|
||||
const { user } = UserProvider.useContainer();
|
||||
|
||||
return (<>
|
||||
<h1>Команды</h1>
|
||||
{user && !user.team
|
||||
? (<p>Вы не состоите в командах. <Link to="/teams/new">Создать свою команду.</Link></p>)
|
||||
: null}
|
||||
|
||||
<Table>
|
||||
<thead>
|
||||
<tr>
|
||||
|
|
|
@ -72,6 +72,26 @@ func (t *Team) PostTeamsTeamIDMembers(ctx echo.Context, teamID int) error {
|
|||
return t.getTeamResponse(ctx, teamID)
|
||||
}
|
||||
|
||||
func (t *Team) PostTeams(ctx echo.Context) error {
|
||||
req := &api.PostTeamsJSONRequestBody{}
|
||||
if err := ctx.Bind(req); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
user := contextlib.GetUser(ctx)
|
||||
|
||||
team, err := t.TeamService.Create(ctx.Request().Context(), req.Name, user)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return ctx.JSON(http.StatusCreated, api.TeamView{
|
||||
Id: int(team.ID),
|
||||
Name: team.Name,
|
||||
CreatedAt: team.CreatedAt.Format("02.01.06"),
|
||||
})
|
||||
}
|
||||
|
||||
func (t *Team) getTeamResponse(ctx echo.Context, teamID int) error {
|
||||
team, err := t.TeamService.GetByID(ctx.Request().Context(), uint(teamID))
|
||||
if err != nil {
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
{{ template "header" . }}
|
||||
<h1>Новая команда</h1>
|
||||
<form method="POST">
|
||||
<div class="col-lg-8 px-0">
|
||||
{{ if .Error }}
|
||||
<div class="alert alert-danger" role="alert">{{ .Error }}</div>
|
||||
{{ end }}
|
||||
<div class="mb-3 row">
|
||||
<label for="staticEmail" class="col-sm-4 col-form-label">Название команды</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="text" class="form-control" name="name" value="{{ .Name }}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-3 row">
|
||||
<div class="col-sm-8 offset-md-4">
|
||||
<input type="submit" class="form-control btn btn-primary" value="Регистрация">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
{{ template "footer" . }}
|
Loading…
Reference in a new issue