diff --git a/.forgejo/workflows/build-and-deploy.yml b/.forgejo/workflows/build-and-deploy.yml index 0338440..e7d0a83 100644 --- a/.forgejo/workflows/build-and-deploy.yml +++ b/.forgejo/workflows/build-and-deploy.yml @@ -20,9 +20,9 @@ jobs: go-version: '^1.25' check-latest: false cache-dependency-path: | - go.sum + modules/backend/go.sum - - name: Build backend + - name: Build Go app run: | cd modules/backend go mod tidy @@ -35,19 +35,6 @@ jobs: name: nyanimedb-backend.tar.gz path: modules/backend/nyanimedb-backend.tar.gz - - name: Build auth - run: | - cd modules/auth - go mod tidy - go build -o auth . - tar -czvf nyanimedb-auth.tar.gz auth - - - name: Upload built auth to artifactory - uses: actions/upload-artifact@v3 - with: - name: nyanimedb-auth.tar.gz - path: modules/auth/nyanimedb-auth.tar.gz - # Build frontend - uses: actions/setup-node@v5 with: @@ -89,14 +76,6 @@ jobs: push: true tags: meowgit.nekoea.red/nihonium/nyanimedb-backend:latest - - name: Build and push auth image - uses: docker/build-push-action@v6 - with: - context: . - file: Dockerfiles/Dockerfile_auth - push: true - tags: meowgit.nekoea.red/nihonium/nyanimedb-auth:latest - - name: Build and push frontend image uses: docker/build-push-action@v6 with: diff --git a/api/_build/openapi.yaml b/api/_build/openapi.yaml index e2c7409..403a45c 100644 --- a/api/_build/openapi.yaml +++ b/api/_build/openapi.yaml @@ -86,7 +86,6 @@ paths: description: Unknown server error '/titles/{title_id}': get: - operationId: getTitle summary: Get title description parameters: - name: title_id @@ -117,7 +116,6 @@ paths: description: Unknown server error '/users/{user_id}': get: - operationId: getUsersId summary: Get user info parameters: - name: user_id diff --git a/api/paths/titles-id.yaml b/api/paths/titles-id.yaml index 235743f..01fa504 100644 --- a/api/paths/titles-id.yaml +++ b/api/paths/titles-id.yaml @@ -1,6 +1,5 @@ get: summary: Get title description - operationId: getTitle parameters: - in: path name: title_id diff --git a/api/paths/users-id-titles.yaml b/api/paths/users-id-titles.yaml index 2cff448..18c805e 100644 --- a/api/paths/users-id-titles.yaml +++ b/api/paths/users-id-titles.yaml @@ -128,6 +128,7 @@ post: application/json: schema: $ref: '../schemas/UserTitleMini.yaml' + '400': description: Invalid request body (missing fields, invalid types, etc.) '401': @@ -179,6 +180,7 @@ patch: application/json: schema: $ref: '../schemas/UserTitleMini.yaml' + '400': description: Invalid request body (missing fields, invalid types, etc.) '401': diff --git a/api/paths/users-id.yaml b/api/paths/users-id.yaml index fe62e46..06f4a19 100644 --- a/api/paths/users-id.yaml +++ b/api/paths/users-id.yaml @@ -1,6 +1,5 @@ get: summary: Get user info - operationId: getUsersId parameters: - in: path name: user_id diff --git a/api/schemas/Title.yaml b/api/schemas/Title.yaml index 877ee24..7497d1f 100644 --- a/api/schemas/Title.yaml +++ b/api/schemas/Title.yaml @@ -60,3 +60,4 @@ properties: additionalProperties: type: number format: double +additionalProperties: true diff --git a/api/schemas/UserTitleMini.yaml b/api/schemas/UserTitleMini.yaml index e1a5a74..e20bcbf 100644 --- a/api/schemas/UserTitleMini.yaml +++ b/api/schemas/UserTitleMini.yaml @@ -20,4 +20,4 @@ properties: format: int64 ctime: type: string - format: date-time + format: date-time \ No newline at end of file diff --git a/modules/backend/handlers/common.go b/modules/backend/handlers/common.go index f820db6..2cf2283 100644 --- a/modules/backend/handlers/common.go +++ b/modules/backend/handlers/common.go @@ -1,6 +1,7 @@ package handlers import ( + "context" "encoding/json" "fmt" oapi "nyanimedb/api" @@ -16,11 +17,11 @@ func NewServer(db *sqlc.Queries) Server { return Server{db: db} } -func sql2StorageType(s *sqlc.StorageTypeT) (*oapi.StorageType, error) { +func sql2StorageType(s *sqlc.StorageTypeT) (*oapi.ImageStorageType, error) { if s == nil { return nil, nil } - var t oapi.StorageType + var t oapi.ImageStorageType switch *s { case sqlc.StorageTypeTLocal: t = oapi.Local @@ -32,7 +33,7 @@ func sql2StorageType(s *sqlc.StorageTypeT) (*oapi.StorageType, error) { return &t, nil } -func (s Server) mapTitle(title sqlc.GetTitleByIDRow) (oapi.Title, error) { +func (s Server) mapTitle(ctx context.Context, title sqlc.GetTitleByIDRow) (oapi.Title, error) { oapi_title := oapi.Title{ EpisodesAired: title.EpisodesAired, diff --git a/modules/backend/handlers/titles.go b/modules/backend/handlers/titles.go index 03553fd..c67177f 100644 --- a/modules/backend/handlers/titles.go +++ b/modules/backend/handlers/titles.go @@ -144,7 +144,7 @@ func (s Server) GetTitlesTitleId(ctx context.Context, request oapi.GetTitlesTitl return oapi.GetTitlesTitleId500Response{}, nil } - oapi_title, err = s.mapTitle(sqlc_title) + oapi_title, err = s.mapTitle(ctx, sqlc_title) if err != nil { log.Errorf("%v", err) return oapi.GetTitlesTitleId500Response{}, nil @@ -238,7 +238,7 @@ func (s Server) GetTitles(ctx context.Context, request oapi.GetTitlesRequestObje // _title.TitleStorageType = string(s) // } - t, err := s.mapTitle(_title) + t, err := s.mapTitle(ctx, _title) if err != nil { log.Errorf("%v", err) return oapi.GetTitles500Response{}, nil diff --git a/modules/backend/handlers/users.go b/modules/backend/handlers/users.go index 7af705e..1881f36 100644 --- a/modules/backend/handlers/users.go +++ b/modules/backend/handlers/users.go @@ -2,7 +2,6 @@ package handlers import ( "context" - "errors" "fmt" oapi "nyanimedb/api" sqlc "nyanimedb/sql" @@ -10,12 +9,24 @@ import ( "time" "github.com/jackc/pgx/v5" - "github.com/jackc/pgx/v5/pgconn" "github.com/jackc/pgx/v5/pgtype" "github.com/oapi-codegen/runtime/types" log "github.com/sirupsen/logrus" ) +// type Server struct { +// db *sqlc.Queries +// } + +// func NewServer(db *sqlc.Queries) Server { +// return Server{db: db} +// } + +// func parseInt64(s string) (int32, error) { +// i, err := strconv.ParseInt(s, 10, 64) +// return int32(i), err +// } + func mapUser(u sqlc.GetUserByIDRow) (oapi.User, error) { i := oapi.Image{ Id: u.AvatarID, @@ -191,7 +202,7 @@ func (s Server) mapUsertitle(ctx context.Context, t sqlc.SearchUserTitlesRow) (o // StudioImagePath: title.StudioImagePath, } - oapi_title, err := s.mapTitle(_title) + oapi_title, err := s.mapTitle(ctx, _title) if err != nil { return oapi_usertitle, fmt.Errorf("mapUsertitle: %v", err) } @@ -357,26 +368,19 @@ func (s Server) AddUserTitle(ctx context.Context, request oapi.AddUserTitleReque } params := sqlc.InsertUserTitleParams{ - UserID: request.UserId, - TitleID: request.Body.TitleId, - Status: *status, - Rate: request.Body.Rate, + UserID: request.UserId, + TitleID: request.Body.TitleId, + Status: *status, + Rate: request.Body.Rate, + ReviewID: request.Body.ReviewId, } user_title, err := s.db.InsertUserTitle(ctx, params) if err != nil { - var pgErr *pgconn.PgError - if errors.As(err, &pgErr) { - // fmt.Println(pgErr.Message) // => syntax error at end of input - // fmt.Println(pgErr.Code) // => 42601 - if pgErr.Code == "23505" { //duplicate key value - return oapi.AddUserTitle409Response{}, nil - } - } else { - log.Errorf("%v", err) - return oapi.AddUserTitle500Response{}, nil - } + log.Errorf("%v", err) + return oapi.AddUserTitle500Response{}, nil } + oapi_status, err := sql2usertitlestatus(user_title.Status) if err != nil { log.Errorf("%v", err) @@ -402,13 +406,3 @@ func (s Server) AddUserTitle(ctx context.Context, request oapi.AddUserTitleReque return oapi.AddUserTitle200JSONResponse(oapi_usertitle), nil } - -// DeleteUserTitle implements oapi.StrictServerInterface. -func (s Server) DeleteUserTitle(ctx context.Context, request oapi.DeleteUserTitleRequestObject) (oapi.DeleteUserTitleResponseObject, error) { - panic("unimplemented") -} - -// UpdateUserTitle implements oapi.StrictServerInterface. -func (s Server) UpdateUserTitle(ctx context.Context, request oapi.UpdateUserTitleRequestObject) (oapi.UpdateUserTitleResponseObject, error) { - panic("unimplemented") -} diff --git a/modules/backend/queries.sql b/modules/backend/queries.sql index ef6e26d..0146b25 100644 --- a/modules/backend/queries.sql +++ b/modules/backend/queries.sql @@ -461,13 +461,21 @@ VALUES ( ) RETURNING user_id, title_id, status, rate, review_id, ctime; --- name: UpdateUserTitle :one --- Fails with sql.ErrNoRows if (user_id, title_id) not found -UPDATE usertitles -SET - status = COALESCE(sqlc.narg('status')::usertitle_status_t, status), - rate = COALESCE(sqlc.narg('rate')::int, rate) -WHERE - user_id = sqlc.arg('user_id') - AND title_id = sqlc.arg('title_id') -RETURNING *; \ No newline at end of file +-- -- name: UpdateUserTitle :one +-- UPDATE usertitles +-- SET +-- status = COALESCE(sqlc.narg('status'), status), +-- rate = COALESCE(sqlc.narg('rate'), rate), +-- review_id = COALESCE(sqlc.narg('review_id'), review_id) +-- WHERE user_id = $1 AND title_id = $2 +-- RETURNING *; + +-- -- name: DeleteUserTitle :exec +-- DELETE FROM usertitles +-- WHERE user_id = $1 AND ($2::int IS NULL OR title_id = $2); + +-- -- name: ListTags :many +-- SELECT tag_id, tag_names +-- FROM tags +-- ORDER BY tag_id +-- LIMIT $1 OFFSET $2; \ No newline at end of file diff --git a/modules/frontend/src/App.tsx b/modules/frontend/src/App.tsx index e2c909f..3ecfa2d 100644 --- a/modules/frontend/src/App.tsx +++ b/modules/frontend/src/App.tsx @@ -2,7 +2,6 @@ import React from "react"; import { BrowserRouter as Router, Routes, Route } from "react-router-dom"; import UsersIdPage from "./pages/UsersIdPage/UsersIdPage"; import TitlesPage from "./pages/TitlesPage/TitlesPage"; -import TitlePage from "./pages/TitlePage/TitlePage"; import { LoginPage } from "./pages/LoginPage/LoginPage"; import { Header } from "./components/Header/Header"; @@ -25,9 +24,7 @@ const App: React.FC = () => { /> } /> - } /> - } /> ); diff --git a/modules/frontend/src/api/core/OpenAPI.ts b/modules/frontend/src/api/core/OpenAPI.ts index 6ce873e..185e5c3 100644 --- a/modules/frontend/src/api/core/OpenAPI.ts +++ b/modules/frontend/src/api/core/OpenAPI.ts @@ -20,7 +20,7 @@ export type OpenAPIConfig = { }; export const OpenAPI: OpenAPIConfig = { - BASE: 'http://10.1.0.65:8081/api/v1', + BASE: '/api/v1', VERSION: '1.0.0', WITH_CREDENTIALS: false, CREDENTIALS: 'include', diff --git a/modules/frontend/src/api/index.ts b/modules/frontend/src/api/index.ts index 9013fc7..80ae491 100644 --- a/modules/frontend/src/api/index.ts +++ b/modules/frontend/src/api/index.ts @@ -12,7 +12,6 @@ export type { CursorObj } from './models/CursorObj'; export type { Image } from './models/Image'; export type { ReleaseSeason } from './models/ReleaseSeason'; export type { Review } from './models/Review'; -export type { StorageType } from './models/StorageType'; export type { Studio } from './models/Studio'; export type { Tag } from './models/Tag'; export type { Tags } from './models/Tags'; @@ -22,7 +21,6 @@ export type { TitleSort } from './models/TitleSort'; export type { TitleStatus } from './models/TitleStatus'; export type { User } from './models/User'; export type { UserTitle } from './models/UserTitle'; -export type { UserTitleMini } from './models/UserTitleMini'; export type { UserTitleStatus } from './models/UserTitleStatus'; export { DefaultService } from './services/DefaultService'; diff --git a/modules/frontend/src/api/models/Image.ts b/modules/frontend/src/api/models/Image.ts index 887bf2f..a94de74 100644 --- a/modules/frontend/src/api/models/Image.ts +++ b/modules/frontend/src/api/models/Image.ts @@ -2,10 +2,12 @@ /* istanbul ignore file */ /* tslint:disable */ /* eslint-disable */ -import type { StorageType } from './StorageType'; export type Image = { id?: number; - storage_type?: StorageType; + /** + * Image storage type + */ + storage_type?: 's3' | 'local'; image_path?: string; }; diff --git a/modules/frontend/src/api/models/StorageType.ts b/modules/frontend/src/api/models/StorageType.ts deleted file mode 100644 index f6d086b..0000000 --- a/modules/frontend/src/api/models/StorageType.ts +++ /dev/null @@ -1,8 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -/** - * Image storage type - */ -export type StorageType = 's3' | 'local'; diff --git a/modules/frontend/src/api/models/Title.ts b/modules/frontend/src/api/models/Title.ts index 9ffdeb6..4da7aa3 100644 --- a/modules/frontend/src/api/models/Title.ts +++ b/modules/frontend/src/api/models/Title.ts @@ -2,30 +2,4 @@ /* istanbul ignore file */ /* tslint:disable */ /* eslint-disable */ -import type { Image } from './Image'; -import type { ReleaseSeason } from './ReleaseSeason'; -import type { Studio } from './Studio'; -import type { Tags } from './Tags'; -import type { TitleStatus } from './TitleStatus'; -export type Title = { - /** - * Unique title ID (primary key) - */ - id: number; - /** - * Localized titles. Key = language (ISO 639-1), value = list of names - */ - title_names: Record>; - studio?: Studio; - tags: Tags; - poster?: Image; - title_status?: TitleStatus; - rating?: number; - rating_count?: number; - release_year?: number; - release_season?: ReleaseSeason; - episodes_aired?: number; - episodes_all?: number; - episodes_len?: Record; -}; - +export type Title = Record; diff --git a/modules/frontend/src/api/models/UserTitleMini.ts b/modules/frontend/src/api/models/UserTitleMini.ts deleted file mode 100644 index 2b223ce..0000000 --- a/modules/frontend/src/api/models/UserTitleMini.ts +++ /dev/null @@ -1,14 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { UserTitleStatus } from './UserTitleStatus'; -export type UserTitleMini = { - user_id: number; - title_id: number; - status: UserTitleStatus; - rate?: number; - review_id?: number; - ctime?: string; -}; - diff --git a/modules/frontend/src/api/services/DefaultService.ts b/modules/frontend/src/api/services/DefaultService.ts index 5070fae..874971e 100644 --- a/modules/frontend/src/api/services/DefaultService.ts +++ b/modules/frontend/src/api/services/DefaultService.ts @@ -9,7 +9,6 @@ import type { TitleSort } from '../models/TitleSort'; import type { TitleStatus } from '../models/TitleStatus'; import type { User } from '../models/User'; import type { UserTitle } from '../models/UserTitle'; -import type { UserTitleMini } from '../models/UserTitleMini'; import type { UserTitleStatus } from '../models/UserTitleStatus'; import type { CancelablePromise } from '../core/CancelablePromise'; import { OpenAPI } from '../core/OpenAPI'; @@ -79,7 +78,7 @@ export class DefaultService { * @returns Title Title description * @throws ApiError */ - public static getTitle( + public static getTitles1( titleId: number, fields: string = 'all', ): CancelablePromise { @@ -106,7 +105,7 @@ export class DefaultService { * @returns User User info * @throws ApiError */ - public static getUsersId( + public static getUsers( userId: string, fields: string = 'all', ): CancelablePromise<User> { @@ -249,17 +248,22 @@ export class DefaultService { * User adding title to list af watched, status required * @param userId ID of the user to assign the title to * @param requestBody - * @returns UserTitleMini Title successfully added to user + * @returns any Title successfully added to user * @throws ApiError */ public static addUserTitle( userId: number, - requestBody: { + requestBody: UserTitle, + ): CancelablePromise<{ + data?: { + user_id: number; title_id: number; status: UserTitleStatus; rate?: number; - }, - ): CancelablePromise<UserTitleMini> { + review_id?: number; + ctime?: string; + }; + }> { return __request(OpenAPI, { method: 'POST', url: '/users/{user_id}/titles', @@ -278,37 +282,4 @@ export class DefaultService { }, }); } - /** - * Update a usertitle - * User updating title list of watched - * @param userId ID of the user to assign the title to - * @param requestBody - * @returns UserTitleMini Title successfully updated - * @throws ApiError - */ - public static updateUserTitle( - userId: number, - requestBody: { - title_id: number; - status?: UserTitleStatus; - rate?: number; - }, - ): CancelablePromise<UserTitleMini> { - return __request(OpenAPI, { - method: 'PATCH', - url: '/users/{user_id}/titles', - path: { - 'user_id': userId, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Invalid request body (missing fields, invalid types, etc.)`, - 401: `Unauthorized — missing or invalid auth token`, - 403: `Forbidden — user not allowed to update title`, - 404: `User or Title not found`, - 500: `Internal server error`, - }, - }); - } } diff --git a/modules/frontend/src/auth/core/OpenAPI.ts b/modules/frontend/src/auth/core/OpenAPI.ts index 79aa305..2d0edf8 100644 --- a/modules/frontend/src/auth/core/OpenAPI.ts +++ b/modules/frontend/src/auth/core/OpenAPI.ts @@ -20,7 +20,7 @@ export type OpenAPIConfig = { }; export const OpenAPI: OpenAPIConfig = { - BASE: 'http://10.1.0.65:8081/auth', + BASE: '/auth', VERSION: '1.0.0', WITH_CREDENTIALS: false, CREDENTIALS: 'include', diff --git a/modules/frontend/src/pages/TitlePage/TitlePage.module.css b/modules/frontend/src/pages/TitlePage/TitlePage.module.css new file mode 100644 index 0000000..e69de29 diff --git a/modules/frontend/src/pages/TitlePage/TitlePage.tsx b/modules/frontend/src/pages/TitlePage/TitlePage.tsx index 5ea0e3d..7fe9de7 100644 --- a/modules/frontend/src/pages/TitlePage/TitlePage.tsx +++ b/modules/frontend/src/pages/TitlePage/TitlePage.tsx @@ -1,140 +1,64 @@ -import { useEffect, useState } from "react"; -import { useParams } from "react-router-dom"; -import { DefaultService } from "../../api/services/DefaultService"; -import type { Title, UserTitleStatus } from "../../api"; -import { - ClockIcon, - CheckCircleIcon, - PlayCircleIcon, - XCircleIcon, -} from "@heroicons/react/24/solid"; +// import React, { useEffect, useState } from "react"; +// import { useParams } from "react-router-dom"; +// import { DefaultService } from "../../api/services/DefaultService"; +// import type { User } from "../../api/models/User"; +// import styles from "./UserPage.module.css"; -const STATUS_BUTTONS: { status: UserTitleStatus; icon: React.ReactNode; label: string }[] = [ - { status: "planned", icon: <ClockIcon className="w-6 h-6" />, label: "Planned" }, - { status: "finished", icon: <CheckCircleIcon className="w-6 h-6" />, label: "Finished" }, - { status: "in-progress", icon: <PlayCircleIcon className="w-6 h-6" />, label: "In Progress" }, - { status: "dropped", icon: <XCircleIcon className="w-6 h-6" />, label: "Dropped" }, -]; +// const UserPage: React.FC = () => { +// const { id } = useParams<{ id: string }>(); +// const [user, setUser] = useState<User | null>(null); +// const [loading, setLoading] = useState(true); +// const [error, setError] = useState<string | null>(null); -export default function TitlePage() { - const params = useParams(); - const titleId = Number(params.id); +// useEffect(() => { +// if (!id) return; - const [title, setTitle] = useState<Title | null>(null); - const [loading, setLoading] = useState(true); - const [error, setError] = useState<string | null>(null); +// const getTitleInfo = async () => { +// try { +// const userInfo = await DefaultService.getTitle(id, "all"); +// setUser(userInfo); +// } catch (err) { +// console.error(err); +// setError("Failed to fetch user info."); +// } finally { +// setLoading(false); +// } +// }; +// getTitleInfo(); +// }, [id]); - const [userStatus, setUserStatus] = useState<UserTitleStatus | null>(null); - const [updatingStatus, setUpdatingStatus] = useState(false); +// if (loading) return <div className={styles.loader}>Loading...</div>; +// if (error) return <div className={styles.error}>{error}</div>; +// if (!user) return <div className={styles.error}>User not found.</div>; - useEffect(() => { - const fetchTitle = async () => { - setLoading(true); - try { - const data = await DefaultService.getTitle(titleId, "all"); - setTitle(data); - setError(null); - } catch (err: any) { - console.error(err); - setError(err?.message || "Failed to fetch title"); - } finally { - setLoading(false); - } - }; - fetchTitle(); - }, [titleId]); +// return ( +// <div className={styles.container}> +// <div className={styles.card}> +// <div className={styles.avatar}> +// {user.avatar_id ? ( +// <img +// src={`/images/${user.avatar_id}.png`} +// alt="User Avatar" +// className={styles.avatarImg} +// /> +// ) : ( +// <div className={styles.avatarPlaceholder}> +// {user.disp_name?.[0] || "U"} +// </div> +// )} +// </div> - const handleStatusClick = async (status: UserTitleStatus) => { - if (updatingStatus || userStatus === status) return; +// <div className={styles.info}> +// <h1 className={styles.name}>{user.disp_name || user.nickname}</h1> +// <p className={styles.nickname}>@{user.nickname}</p> +// {user.user_desc && <p className={styles.desc}>{user.user_desc}</p>} +// <p className={styles.created}> +// Joined: {new Date(user.creation_date).toLocaleDateString()} +// </p> +// </div> +// </div> +// </div> +// ); +// }; - const userId = Number(localStorage.getItem("userId")); - if (!userId) { - alert("You must be logged in to set status."); - return; - } - - setUpdatingStatus(true); - try { - await DefaultService.addUserTitle(userId, { - title_id: titleId, - status, - }); - setUserStatus(status); - } catch (err: any) { - console.error(err); - alert(err?.message || "Failed to set status"); - } finally { - setUpdatingStatus(false); - } - }; - - const getTagsString = () => - title?.tags?.map(tag => tag.en).filter(Boolean).join(", "); - - if (loading) return <div className="mt-20 font-medium text-black">Loading title...</div>; - if (error) return <div className="mt-20 text-red-600 font-medium">{error}</div>; - if (!title) return null; - - return ( - <div className="w-full min-h-screen bg-gray-50 p-6 flex justify-center"> - <div className="flex flex-col md:flex-row bg-white shadow-lg rounded-xl max-w-4xl w-full p-6 gap-6"> - {/* Постер */} - <div className="flex flex-col items-center"> - <img - src={title.poster?.image_path || "/default-poster.png"} - alt={title.title_names?.en?.[0] || "Title poster"} - className="w-48 h-72 object-cover rounded-lg mb-4" - /> - - {/* Статус кнопки с иконками */} - <div className="flex gap-2 mt-2 flex-wrap justify-center"> - {STATUS_BUTTONS.map(btn => ( - <button - key={btn.status} - onClick={() => handleStatusClick(btn.status)} - disabled={updatingStatus} - className={`p-2 rounded-lg transition flex items-center justify-center ${ - userStatus === btn.status - ? "bg-blue-600 text-white" - : "bg-gray-200 text-gray-700 hover:bg-gray-300" - }`} - title={btn.label} - > - {btn.icon} - </button> - ))} - </div> - </div> - - {/* Информация о тайтле */} - <div className="flex-1 flex flex-col"> - <h1 className="text-3xl font-bold mb-2"> - {title.title_names?.en?.[0] || "Untitled"} - </h1> - {title.studio && <p className="text-gray-700 mb-1">Studio: {title.studio.name}</p>} - {title.title_status && <p className="text-gray-700 mb-1">Status: {title.title_status}</p>} - {title.rating !== undefined && ( - <p className="text-gray-700 mb-1"> - Rating: {title.rating} ({title.rating_count} votes) - </p> - )} - {title.release_year && ( - <p className="text-gray-700 mb-1"> - Released: {title.release_year} {title.release_season || ""} - </p> - )} - {title.episodes_aired !== undefined && ( - <p className="text-gray-700 mb-1"> - Episodes: {title.episodes_aired}/{title.episodes_all} - </p> - )} - {title.tags && title.tags.length > 0 && ( - <p className="text-gray-700 mb-1"> - Tags: {getTagsString()} - </p> - )} - </div> - </div> - </div> - ); -} +// export default UserPage; diff --git a/modules/frontend/src/pages/UserPage/UserPage.tsx b/modules/frontend/src/pages/UserPage/UserPage.tsx index eafdf6b..2e39e6b 100644 --- a/modules/frontend/src/pages/UserPage/UserPage.tsx +++ b/modules/frontend/src/pages/UserPage/UserPage.tsx @@ -15,7 +15,7 @@ const UserPage: React.FC = () => { const getUserInfo = async () => { try { - const userInfo = await DefaultService.getUsersId(id, "all"); // <-- use dynamic id + const userInfo = await DefaultService.getUsers(id, "all"); // <-- use dynamic id setUser(userInfo); } catch (err) { console.error(err); diff --git a/modules/frontend/src/pages/UsersIdPage/UsersIdPage.tsx b/modules/frontend/src/pages/UsersIdPage/UsersIdPage.tsx index 729da20..342f22c 100644 --- a/modules/frontend/src/pages/UsersIdPage/UsersIdPage.tsx +++ b/modules/frontend/src/pages/UsersIdPage/UsersIdPage.tsx @@ -41,7 +41,7 @@ export default function UsersIdPage({ userId }: UsersIdPageProps) { if (!id) return; setLoadingUser(true); try { - const result = await DefaultService.getUsersId(id, "all"); + const result = await DefaultService.getUsers(id, "all"); setUser(result); setErrorUser(null); } catch (err: any) { diff --git a/sql/migrations/000001_init.up.sql b/sql/migrations/000001_init.up.sql index 3499fe2..f8781de 100644 --- a/sql/migrations/000001_init.up.sql +++ b/sql/migrations/000001_init.up.sql @@ -179,6 +179,6 @@ END; $$ LANGUAGE plpgsql; CREATE TRIGGER set_ctime_on_update -BEFORE UPDATE ON usertitles +AFTER UPDATE ON usertitles FOR EACH ROW EXECUTE FUNCTION set_ctime(); \ No newline at end of file diff --git a/sql/queries.sql.go b/sql/queries.sql.go index 89b16c9..a46da86 100644 --- a/sql/queries.sql.go +++ b/sql/queries.sql.go @@ -925,41 +925,3 @@ func (q *Queries) UpdateUser(ctx context.Context, arg UpdateUserParams) (UpdateU ) return i, err } - -const updateUserTitle = `-- name: UpdateUserTitle :one -UPDATE usertitles -SET - status = COALESCE($1::usertitle_status_t, status), - rate = COALESCE($2::int, rate) -WHERE - user_id = $3 - AND title_id = $4 -RETURNING user_id, title_id, status, rate, review_id, ctime -` - -type UpdateUserTitleParams struct { - Status NullUsertitleStatusT `json:"status"` - Rate *int32 `json:"rate"` - UserID int64 `json:"user_id"` - TitleID int64 `json:"title_id"` -} - -// Fails with sql.ErrNoRows if (user_id, title_id) not found -func (q *Queries) UpdateUserTitle(ctx context.Context, arg UpdateUserTitleParams) (Usertitle, error) { - row := q.db.QueryRow(ctx, updateUserTitle, - arg.Status, - arg.Rate, - arg.UserID, - arg.TitleID, - ) - var i Usertitle - err := row.Scan( - &i.UserID, - &i.TitleID, - &i.Status, - &i.Rate, - &i.ReviewID, - &i.Ctime, - ) - return i, err -}