diff --git a/api/openapi.yaml b/api/openapi.yaml index 8adf291..7c368ff 100644 --- a/api/openapi.yaml +++ b/api/openapi.yaml @@ -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: diff --git a/api/server.go b/api/server.go index 7c17e9e..33de6d0 100644 --- a/api/server.go +++ b/api/server.go @@ -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 diff --git a/api/types.go b/api/types.go index 7bf989a..6d7d3be 100644 --- a/api/types.go +++ b/api/types.go @@ -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 diff --git a/frontend/src/components/Layout.jsx b/frontend/src/components/Layout.jsx index 774957c..3286ba9 100644 --- a/frontend/src/components/Layout.jsx +++ b/frontend/src/components/Layout.jsx @@ -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 (<> - + + {user ? ( + <> {user.username}  {user.team ? ( <>({user.team.name}) ) : ( <>(без команды) - )} - - - - ) : ( -
- Вход - Регистрация -
- )} - - - - + )}  + + + ) : ( + + Вход + Регистрация + + )} +
+ + + -
+ -
+ ); } \ No newline at end of file diff --git a/frontend/src/pages/Index.jsx b/frontend/src/pages/Index.jsx index 487c70e..44f7952 100644 --- a/frontend/src/pages/Index.jsx +++ b/frontend/src/pages/Index.jsx @@ -7,7 +7,7 @@ export default () => { return (<>

Текущие игры

- {games.map(game => ( + {games && games.map(game => ( <>

{game.title}

@@ -43,6 +43,6 @@ export default () => {
))} - {games.length == 0 ? (Игр пока не анонсировано) : null} + {!games ? (Игр пока не анонсировано) : null} ); } \ No newline at end of file diff --git a/frontend/src/pages/TeamNew.jsx b/frontend/src/pages/TeamNew.jsx index 28fe22d..673d14e 100644 --- a/frontend/src/pages/TeamNew.jsx +++ b/frontend/src/pages/TeamNew.jsx @@ -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 (<>

Создание команды

diff --git a/frontend/src/pages/Teams.jsx b/frontend/src/pages/Teams.jsx index 037ab35..96ab72d 100644 --- a/frontend/src/pages/Teams.jsx +++ b/frontend/src/pages/Teams.jsx @@ -7,8 +7,14 @@ export default () => { if (!teams) { return null } + const { user } = UserProvider.useContainer(); + return (<>

Команды

+ {user && !user.team + ? (

Вы не состоите в командах. Создать свою команду.

) + : null} + diff --git a/pkg/controller/team.go b/pkg/controller/team.go index 9d74189..f2ea036 100644 --- a/pkg/controller/team.go +++ b/pkg/controller/team.go @@ -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 { diff --git a/views/team/create.gotmpl b/views/team/create.gotmpl deleted file mode 100644 index 247b605..0000000 --- a/views/team/create.gotmpl +++ /dev/null @@ -1,21 +0,0 @@ -{{ template "header" . }} -

Новая команда

- -
- {{ if .Error }} - - {{ end }} -
- -
- -
-
-
-
- -
-
-
- -{{ template "footer" . }} \ No newline at end of file