Visual improvements
This commit is contained in:
parent
6054bc0403
commit
ad1aff3692
@ -3,3 +3,24 @@ export type TUser = {
|
||||
isAdmin: boolean;
|
||||
id?: string | number;
|
||||
}
|
||||
|
||||
export type TInfoUser = {
|
||||
user_id: number;
|
||||
username: string;
|
||||
email: string;
|
||||
createdAt: string;
|
||||
is_admin: boolean;
|
||||
display_name: string;
|
||||
};
|
||||
|
||||
export type TProfile = {
|
||||
user_id: number;
|
||||
bio: string;
|
||||
avatar_url: string;
|
||||
website_url: string;
|
||||
};
|
||||
|
||||
export type TGetUserInfoResponse = {
|
||||
user_info: TInfoUser;
|
||||
profile_info: TProfile;
|
||||
};
|
||||
@ -38,7 +38,7 @@ export default function ArticleViewer(props: TArticleViewer) {
|
||||
<>
|
||||
<Container size={"3"}>
|
||||
<div className="ql-snow ql-editor">
|
||||
<Container size={"2"} className="mt-4">
|
||||
<Container size={"2"} className="mt-0">
|
||||
<Flex direction={"column"}>
|
||||
<Text className="mb-2" as="div" size={"9"}>
|
||||
{data.title}
|
||||
|
||||
@ -1,15 +1,18 @@
|
||||
import { Flex } from "@radix-ui/themes";
|
||||
import CustomNavigationMenu from "./NavigationMenu/NavigationMenu";
|
||||
import RightButtonBar from "./RightButtonBar/RightButtonBar";
|
||||
import SearchField from "./SearchField/SearchField";
|
||||
|
||||
export default function NavBar() {
|
||||
return (
|
||||
<nav className="flex justify-center pt-2 pb-2 ml-4 mr-4 flex-[1] max-h-fit">
|
||||
<CustomNavigationMenu />
|
||||
<Flex className="justify-center w-full">
|
||||
<nav className="flex justify-center pt-2 pb-2 ml-4 mr-4 mb-4 mt-2 flex-[1] max-h-fit max-w-[70rem]">
|
||||
<CustomNavigationMenu />
|
||||
|
||||
<SearchField />
|
||||
<SearchField />
|
||||
|
||||
<RightButtonBar />
|
||||
</nav>
|
||||
<RightButtonBar />
|
||||
</nav>
|
||||
</Flex>
|
||||
);
|
||||
}
|
||||
|
||||
@ -8,7 +8,7 @@ export default function SearchField() {
|
||||
return (
|
||||
<div className="flex justify-center flex-1">
|
||||
<TextField.Root
|
||||
className="w-2/3 rounded-lg"
|
||||
className="hidden w-2/3 rounded-lg"
|
||||
placeholder={t("search")}
|
||||
>
|
||||
<TextField.Slot>
|
||||
|
||||
@ -38,10 +38,7 @@ export default function ProfileNavbar() {
|
||||
<UserCard />
|
||||
|
||||
<Box className="mx-2">
|
||||
<Separator
|
||||
orientation={"horizontal"}
|
||||
size={"4"}
|
||||
/>
|
||||
<Separator orientation={"horizontal"} size={"4"} />
|
||||
</Box>
|
||||
|
||||
<Flex gap={"2"} direction={"column"}>
|
||||
|
||||
@ -1,8 +1,18 @@
|
||||
import { Avatar, Badge, Card, Flex, Separator, Text } from "@radix-ui/themes";
|
||||
import {
|
||||
Avatar,
|
||||
Badge,
|
||||
Card,
|
||||
Flex,
|
||||
Separator,
|
||||
Skeleton,
|
||||
Text,
|
||||
} from "@radix-ui/themes";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { useAtomValue } from "jotai";
|
||||
import { TGetUserInfoResponse } from "../../@types/UserType";
|
||||
import { userAtom } from "../../AtomStore/AtomStore";
|
||||
import { axiosLocalhost } from "../../api/axios/axios";
|
||||
import { JSONWithInt64 } from "../../utils/idnex";
|
||||
|
||||
type TUserCard = {
|
||||
username?: string;
|
||||
@ -12,13 +22,22 @@ type TUserCard = {
|
||||
export default function UserCard(props: TUserCard) {
|
||||
const user = useAtomValue(userAtom);
|
||||
|
||||
const { data } = useQuery({
|
||||
queryKey: [`userCard${props.userId}`],
|
||||
const { data, isLoading } = useQuery({
|
||||
queryKey: [`userCard${props.userId || user?.id}`],
|
||||
queryFn: async () => {
|
||||
const response = await axiosLocalhost.get(`/users/${props.userId}`);
|
||||
return response.data;
|
||||
const response = await axiosLocalhost.get(
|
||||
`/users/info/${props.userId || user?.id?.toString()}`,
|
||||
{
|
||||
transformResponse: [(data) => data],
|
||||
}
|
||||
);
|
||||
|
||||
const parsedResponse = JSONWithInt64(response.data);
|
||||
|
||||
console.log("parsedResponse", parsedResponse);
|
||||
|
||||
return parsedResponse as TGetUserInfoResponse;
|
||||
},
|
||||
enabled: !!props.userId,
|
||||
});
|
||||
|
||||
const getInitials = (username: string): string => {
|
||||
@ -42,11 +61,22 @@ export default function UserCard(props: TUserCard) {
|
||||
<Avatar
|
||||
fallback={<div>{getInitials(getUsername())}</div>}
|
||||
radius="full"
|
||||
loading="lazy"
|
||||
/>
|
||||
<Flex className="flex-col ">
|
||||
<Text>Test User</Text>
|
||||
<Flex className="flex-col overflow-hidden">
|
||||
{isLoading ? (
|
||||
<Skeleton>
|
||||
<Text truncate>{`Temporal`}</Text>
|
||||
</Skeleton>
|
||||
) : (
|
||||
<Text truncate>
|
||||
{data?.user_info.display_name ||
|
||||
`Non specified`}
|
||||
</Text>
|
||||
)}
|
||||
|
||||
<Text size={"1"} color={"gray"}>
|
||||
@testuser123
|
||||
{`@${getUsername()}`}
|
||||
</Text>
|
||||
</Flex>
|
||||
</Flex>
|
||||
|
||||
@ -9,6 +9,7 @@ import { Link, useNavigate } from "react-router-dom";
|
||||
import { axiosLocalhost } from "../../../api/axios/axios";
|
||||
import { userAtom } from "../../../AtomStore/AtomStore";
|
||||
import UseCapsLock from "../../../hooks/useCapsLock";
|
||||
import { JSONWithInt64 } from "../../../utils/idnex";
|
||||
import ShowPasswordButton from "../ShowPasswordButton/ShowPasswordButton";
|
||||
|
||||
type TLoginData = {
|
||||
@ -28,12 +29,18 @@ export default function LoginPage() {
|
||||
mutationFn: async (data: TLoginData) => {
|
||||
let response = await axiosLocalhost.post(
|
||||
"/login",
|
||||
JSON.stringify(data)
|
||||
JSON.stringify(data),
|
||||
{
|
||||
transformResponse: [data => data]
|
||||
}
|
||||
);
|
||||
|
||||
const parsedData = JSONWithInt64(response.data);
|
||||
|
||||
setUserAtom({
|
||||
username: response.data.username,
|
||||
username: parsedData.username,
|
||||
isAdmin: false,
|
||||
id: response.data.id,
|
||||
id: parsedData.id,
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
@ -9,6 +9,7 @@ import { Link, useNavigate } from "react-router-dom";
|
||||
import { axiosLocalhost } from "../../../api/axios/axios";
|
||||
import { userAtom } from "../../../AtomStore/AtomStore";
|
||||
import UseCapsLock from "../../../hooks/useCapsLock";
|
||||
import { JSONWithInt64 } from "../../../utils/idnex";
|
||||
import ShowPasswordButton from "../ShowPasswordButton/ShowPasswordButton";
|
||||
|
||||
type TRegisterData = {
|
||||
@ -31,11 +32,16 @@ export default function RegisterPage() {
|
||||
|
||||
const registerMutation = useMutation({
|
||||
mutationFn: async (data: TRegisterData) => {
|
||||
let response = await axiosLocalhost.post("/users", JSON.stringify(data));
|
||||
let response = await axiosLocalhost.post("/users", JSON.stringify(data), {
|
||||
transformResponse: [data => data]
|
||||
});
|
||||
|
||||
const parsedResponse = JSONWithInt64(response.data)
|
||||
|
||||
setUserAtom({
|
||||
username: response.data.username,
|
||||
username: parsedResponse.username,
|
||||
isAdmin: false,
|
||||
id: response.data.id,
|
||||
id: parsedResponse.id,
|
||||
})
|
||||
},
|
||||
|
||||
|
||||
@ -15,7 +15,7 @@ export default function UserBlogsPage() {
|
||||
transformResponse: [(data) => data],
|
||||
});
|
||||
|
||||
let temp = JSONWithInt64(response.data);
|
||||
const temp = JSONWithInt64(response.data);
|
||||
|
||||
return temp as any[];
|
||||
},
|
||||
|
||||
@ -1,5 +1,13 @@
|
||||
import { Flex, ScrollArea, Text } from "@radix-ui/themes";
|
||||
import { loremText } from "../../constants/loremText";
|
||||
import {
|
||||
Badge,
|
||||
Box,
|
||||
DataList,
|
||||
Flex,
|
||||
ScrollArea,
|
||||
Separator,
|
||||
Text,
|
||||
TextArea,
|
||||
} from "@radix-ui/themes";
|
||||
|
||||
export default function UserProfilePage() {
|
||||
return (
|
||||
@ -7,11 +15,68 @@ export default function UserProfilePage() {
|
||||
<ScrollArea
|
||||
type="auto"
|
||||
scrollbars="vertical"
|
||||
className="flex-grow-[1] pr-5"
|
||||
className="flex-grow-[1] pt-4"
|
||||
>
|
||||
<Text>
|
||||
<p className="text-justify">{loremText}</p>
|
||||
<Text size={"8"}>Base info</Text>
|
||||
|
||||
<Separator className="w-full my-4" />
|
||||
|
||||
<Box className="mb-8">
|
||||
<DataList.Root size={"3"}>
|
||||
<DataList.Item className="items-center">
|
||||
<DataList.Label className="min-w-40">
|
||||
Username
|
||||
</DataList.Label>
|
||||
<DataList.Value>
|
||||
@Definitely_fake_user
|
||||
</DataList.Value>
|
||||
</DataList.Item>
|
||||
<DataList.Item>
|
||||
<DataList.Label className="min-w-40">
|
||||
Email
|
||||
</DataList.Label>
|
||||
<DataList.Value>fake@email.com</DataList.Value>
|
||||
</DataList.Item>
|
||||
<DataList.Item>
|
||||
<DataList.Label className="min-w-40">
|
||||
Display name
|
||||
</DataList.Label>
|
||||
<DataList.Value>Isaev</DataList.Value>
|
||||
</DataList.Item>
|
||||
<DataList.Item>
|
||||
<DataList.Label className="min-w-40">
|
||||
Badges
|
||||
</DataList.Label>
|
||||
<DataList.Value>
|
||||
<Flex
|
||||
gap={"2"}
|
||||
wrap={"wrap"}
|
||||
className="content-evenly"
|
||||
>
|
||||
<Badge size={"3"}>User</Badge>
|
||||
<Badge size={"3"} color="red">
|
||||
Admin
|
||||
</Badge>
|
||||
<Badge size={"3"} color="green">
|
||||
Writer
|
||||
</Badge>
|
||||
</Flex>
|
||||
</DataList.Value>
|
||||
</DataList.Item>
|
||||
</DataList.Root>
|
||||
</Box>
|
||||
|
||||
<Text size={"8"}>
|
||||
Bio
|
||||
</Text>
|
||||
|
||||
<Separator className="w-full my-4" />
|
||||
|
||||
<TextArea resize={"vertical"} placeholder="Add your bio here...">
|
||||
|
||||
</TextArea>
|
||||
|
||||
|
||||
</ScrollArea>
|
||||
</Flex>
|
||||
);
|
||||
|
||||
@ -5,6 +5,7 @@ import { Outlet } from "react-router-dom";
|
||||
import { axiosLocalhost } from "../../api/axios/axios";
|
||||
import { userAtom } from "../../AtomStore/AtomStore";
|
||||
import NavBar from "../../Components/NavBar/NavBar";
|
||||
import { JSONWithInt64 } from "../../utils/idnex";
|
||||
|
||||
const REFETCH_INTERVAL_IN_MINUTES = 5;
|
||||
const RETRY_INTERVAL_IN_SECONDS = 1;
|
||||
@ -19,12 +20,16 @@ export default function MainPage() {
|
||||
queryKey: ["authKey"],
|
||||
queryFn: async () => {
|
||||
try {
|
||||
const response = await axiosLocalhost.get("/auth/check");
|
||||
const response = await axiosLocalhost.get("/auth/check", {
|
||||
transformResponse: [data => data]
|
||||
});
|
||||
|
||||
const parsedResponse = JSONWithInt64(response.data)
|
||||
|
||||
setUserData({
|
||||
isAdmin: response.data["is_admin"],
|
||||
username: response.data["username"],
|
||||
id: response.data["id"],
|
||||
isAdmin: parsedResponse["is_admin"],
|
||||
username: parsedResponse["username"],
|
||||
id: parsedResponse["id"],
|
||||
});
|
||||
return true;
|
||||
} catch (error) {
|
||||
|
||||
@ -8,12 +8,13 @@ export default function ProfilePage() {
|
||||
className={`
|
||||
relative flex-col flex-1 gap-0 mx-4
|
||||
sm:flex-row sm:gap-4
|
||||
md:w-full md:min-w-[45rem] md:max-w-[50rem] md:mx-auto
|
||||
lg:min-w-[50rem] lg:mx-auto
|
||||
md:w-full md:min-w-[45rem] md:max-w-[70rem] md:mx-auto
|
||||
overflow-hidden
|
||||
`}
|
||||
>
|
||||
<ProfileNavbar />
|
||||
<Box className="">
|
||||
<ProfileNavbar />
|
||||
</Box>
|
||||
|
||||
<Box className="my-2 collapse sm:visible">
|
||||
<Separator orientation="vertical" size={"4"} />
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.27.0
|
||||
// sqlc v1.28.0
|
||||
// source: blogs_queries.sql
|
||||
|
||||
package db_repo
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.27.0
|
||||
// sqlc v1.28.0
|
||||
// source: bookmarks_queries.sql
|
||||
|
||||
package db_repo
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.27.0
|
||||
// sqlc v1.28.0
|
||||
// source: categories_queries.sql
|
||||
|
||||
package db_repo
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.27.0
|
||||
// sqlc v1.28.0
|
||||
// source: comments_queries.sql
|
||||
|
||||
package db_repo
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.27.0
|
||||
// sqlc v1.28.0
|
||||
|
||||
package db_repo
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.27.0
|
||||
// sqlc v1.28.0
|
||||
// source: favorites_queries.sql
|
||||
|
||||
package db_repo
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.27.0
|
||||
// sqlc v1.28.0
|
||||
// source: likes_queries.sql
|
||||
|
||||
package db_repo
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.27.0
|
||||
// sqlc v1.28.0
|
||||
|
||||
package db_repo
|
||||
|
||||
@ -83,10 +83,11 @@ type Tag struct {
|
||||
}
|
||||
|
||||
type User struct {
|
||||
UserID int64 `json:"user_id"`
|
||||
Username string `json:"username" validate:"required"`
|
||||
Email string `json:"email" validate:"required,email"`
|
||||
Password string `json:"password" validate:"required"`
|
||||
CreatedAt pgtype.Timestamp `json:"created_at"`
|
||||
IsAdmin bool `json:"is_admin"`
|
||||
UserID int64 `json:"user_id"`
|
||||
Username string `json:"username" validate:"required"`
|
||||
Email string `json:"email" validate:"required,email"`
|
||||
Password string `json:"password" validate:"required"`
|
||||
CreatedAt pgtype.Timestamp `json:"created_at"`
|
||||
IsAdmin bool `json:"is_admin"`
|
||||
DisplayName pgtype.Text `json:"display_name"`
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.27.0
|
||||
// sqlc v1.28.0
|
||||
// source: multi_queries.sql
|
||||
|
||||
package db_repo
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.27.0
|
||||
// sqlc v1.28.0
|
||||
// source: post_tags_queries.sql
|
||||
|
||||
package db_repo
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.27.0
|
||||
// sqlc v1.28.0
|
||||
// source: post_votes_queries.sql
|
||||
|
||||
package db_repo
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.27.0
|
||||
// sqlc v1.28.0
|
||||
// source: posts_queries.sql
|
||||
|
||||
package db_repo
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.27.0
|
||||
// sqlc v1.28.0
|
||||
// source: profiles_queries.sql
|
||||
|
||||
package db_repo
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.27.0
|
||||
// sqlc v1.28.0
|
||||
// source: tags_queries.sql
|
||||
|
||||
package db_repo
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.27.0
|
||||
// sqlc v1.28.0
|
||||
// source: users_queries.sql
|
||||
|
||||
package db_repo
|
||||
@ -13,7 +13,7 @@ const createUser = `-- name: CreateUser :one
|
||||
INSERT INTO public.users
|
||||
(user_id, username, email, "password", created_at, is_admin)
|
||||
VALUES($1, $2, $3, $4, CURRENT_TIMESTAMP, false)
|
||||
RETURNING user_id, username, email, password, created_at, is_admin
|
||||
RETURNING user_id, username, email, password, created_at, is_admin, display_name
|
||||
`
|
||||
|
||||
type CreateUserParams struct {
|
||||
@ -38,6 +38,7 @@ func (q *Queries) CreateUser(ctx context.Context, arg CreateUserParams) (User, e
|
||||
&i.Password,
|
||||
&i.CreatedAt,
|
||||
&i.IsAdmin,
|
||||
&i.DisplayName,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
@ -63,7 +64,7 @@ func (q *Queries) DeleteUserByUsername(ctx context.Context, username string) err
|
||||
}
|
||||
|
||||
const getAllUsers = `-- name: GetAllUsers :many
|
||||
SELECT user_id, username, email, password, created_at, is_admin FROM users
|
||||
SELECT user_id, username, email, password, created_at, is_admin, display_name FROM users
|
||||
`
|
||||
|
||||
func (q *Queries) GetAllUsers(ctx context.Context) ([]User, error) {
|
||||
@ -82,6 +83,7 @@ func (q *Queries) GetAllUsers(ctx context.Context) ([]User, error) {
|
||||
&i.Password,
|
||||
&i.CreatedAt,
|
||||
&i.IsAdmin,
|
||||
&i.DisplayName,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -94,7 +96,7 @@ func (q *Queries) GetAllUsers(ctx context.Context) ([]User, error) {
|
||||
}
|
||||
|
||||
const getUserByEmailOrNickname = `-- name: GetUserByEmailOrNickname :one
|
||||
SELECT user_id, username, email, password, created_at, is_admin FROM users WHERE username = $1 OR email = $2 LIMIT 1
|
||||
SELECT user_id, username, email, password, created_at, is_admin, display_name FROM users WHERE username = $1 OR email = $2 LIMIT 1
|
||||
`
|
||||
|
||||
type GetUserByEmailOrNicknameParams struct {
|
||||
@ -112,12 +114,13 @@ func (q *Queries) GetUserByEmailOrNickname(ctx context.Context, arg GetUserByEma
|
||||
&i.Password,
|
||||
&i.CreatedAt,
|
||||
&i.IsAdmin,
|
||||
&i.DisplayName,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getUserById = `-- name: GetUserById :one
|
||||
SELECT user_id, username, email, password, created_at, is_admin FROM users WHERE user_id = $1
|
||||
SELECT user_id, username, email, password, created_at, is_admin, display_name FROM users WHERE user_id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) GetUserById(ctx context.Context, userID int64) (User, error) {
|
||||
@ -130,12 +133,13 @@ func (q *Queries) GetUserById(ctx context.Context, userID int64) (User, error) {
|
||||
&i.Password,
|
||||
&i.CreatedAt,
|
||||
&i.IsAdmin,
|
||||
&i.DisplayName,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getUserByUsername = `-- name: GetUserByUsername :one
|
||||
SELECT user_id, username, email, password, created_at, is_admin FROM users WHERE username = $1
|
||||
SELECT user_id, username, email, password, created_at, is_admin, display_name FROM users WHERE username = $1
|
||||
`
|
||||
|
||||
func (q *Queries) GetUserByUsername(ctx context.Context, username string) (User, error) {
|
||||
@ -148,6 +152,7 @@ func (q *Queries) GetUserByUsername(ctx context.Context, username string) (User,
|
||||
&i.Password,
|
||||
&i.CreatedAt,
|
||||
&i.IsAdmin,
|
||||
&i.DisplayName,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
@ -167,7 +172,7 @@ const updateUserPasswordHash = `-- name: UpdateUserPasswordHash :one
|
||||
UPDATE public.users
|
||||
SET "password"=$1
|
||||
WHERE user_id=$2
|
||||
RETURNING user_id, username, email, password, created_at, is_admin
|
||||
RETURNING user_id, username, email, password, created_at, is_admin, display_name
|
||||
`
|
||||
|
||||
type UpdateUserPasswordHashParams struct {
|
||||
@ -185,6 +190,7 @@ func (q *Queries) UpdateUserPasswordHash(ctx context.Context, arg UpdateUserPass
|
||||
&i.Password,
|
||||
&i.CreatedAt,
|
||||
&i.IsAdmin,
|
||||
&i.DisplayName,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
@ -5,7 +5,7 @@ COMMENT ON SCHEMA "public" IS 'standard public schema';
|
||||
-- Create "categories" table
|
||||
CREATE TABLE "public"."categories" ("category_id" integer NOT NULL, "category_name" character varying(50) NOT NULL, PRIMARY KEY ("category_id"), CONSTRAINT "categories_category_name_key" UNIQUE ("category_name"));
|
||||
-- Create "users" table
|
||||
CREATE TABLE "public"."users" ("user_id" bigint NOT NULL, "username" character varying(50) NOT NULL, "email" character varying(100) NOT NULL, "password" character varying(255) NOT NULL, "created_at" timestamp NULL DEFAULT CURRENT_TIMESTAMP, "is_admin" boolean NOT NULL, PRIMARY KEY ("user_id"), CONSTRAINT "users_email_key" UNIQUE ("email"), CONSTRAINT "users_username_key" UNIQUE ("username"));
|
||||
CREATE TABLE "public"."users" ("user_id" bigint NOT NULL, "username" character varying(50) NOT NULL, "email" character varying(100) NOT NULL, "password" character varying(255) NOT NULL, "created_at" timestamp NULL DEFAULT CURRENT_TIMESTAMP, "is_admin" boolean NOT NULL, "display_name" character varying(32) NULL, PRIMARY KEY ("user_id"), CONSTRAINT "users_email_key" UNIQUE ("email"), CONSTRAINT "users_username_key" UNIQUE ("username"));
|
||||
-- Create "blogs" table
|
||||
CREATE TABLE "public"."blogs" ("blog_id" bigint NOT NULL, "user_id" bigint NOT NULL, "title" character varying(255) NULL, "description" text NULL, "category_id" integer NULL, "created_at" timestamp NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY ("blog_id"), CONSTRAINT "blogs_category_id_fkey" FOREIGN KEY ("category_id") REFERENCES "public"."categories" ("category_id") ON UPDATE NO ACTION ON DELETE NO ACTION, CONSTRAINT "blogs_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "public"."users" ("user_id") ON UPDATE NO ACTION ON DELETE CASCADE);
|
||||
-- Create "posts" table
|
||||
@ -23,7 +23,7 @@ CREATE TABLE "public"."tags" ("tag_id" integer NOT NULL, "tag_name" character va
|
||||
-- Create "post_tags" table
|
||||
CREATE TABLE "public"."post_tags" ("post_id" bigint NOT NULL, "tag_id" integer NOT NULL, PRIMARY KEY ("post_id", "tag_id"), CONSTRAINT "post_tags_post_id_fkey" FOREIGN KEY ("post_id") REFERENCES "public"."posts" ("post_id") ON UPDATE NO ACTION ON DELETE CASCADE, CONSTRAINT "post_tags_tag_id_fkey" FOREIGN KEY ("tag_id") REFERENCES "public"."tags" ("tag_id") ON UPDATE NO ACTION ON DELETE CASCADE);
|
||||
-- Create "post_votes" table
|
||||
CREATE TABLE "public"."post_votes" ("post_id" bigint NOT NULL, "user_id" bigint NOT NULL, "vote" boolean NOT NULL, PRIMARY KEY ("post_id", "user_id"), CONSTRAINT "post_votes_post_id_fkey" FOREIGN KEY ("post_id") REFERENCES "public"."posts" ("post_id") ON UPDATE NO ACTION ON DELETE NO ACTION, CONSTRAINT "post_votes_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "public"."users" ("user_id") ON UPDATE NO ACTION ON DELETE NO ACTION);
|
||||
CREATE TABLE "public"."post_votes" ("post_id" bigint NOT NULL, "user_id" bigint NOT NULL, "vote" boolean NOT NULL, PRIMARY KEY ("post_id", "user_id"), CONSTRAINT "post_votes_post_id_fkey" FOREIGN KEY ("post_id") REFERENCES "public"."posts" ("post_id") ON UPDATE NO ACTION ON DELETE CASCADE, CONSTRAINT "post_votes_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "public"."users" ("user_id") ON UPDATE NO ACTION ON DELETE NO ACTION);
|
||||
-- Create "profiles" table
|
||||
CREATE TABLE "public"."profiles" ("user_id" bigint NOT NULL, "bio" text NULL, "avatar_url" character varying(255) NULL, "website_url" character varying(100) NULL, PRIMARY KEY ("user_id"), CONSTRAINT "profiles_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "public"."users" ("user_id") ON UPDATE NO ACTION ON DELETE CASCADE);
|
||||
-- Create index "profiles_user_id_idx" to table: "profiles"
|
||||
|
||||
@ -22,7 +22,7 @@ func TargetMiddleware() gin.HandlerFunc {
|
||||
case "POST":
|
||||
c.Set("target", POST)
|
||||
case "GET":
|
||||
c.Set("target", DELETE)
|
||||
c.Set("target", GET)
|
||||
}
|
||||
|
||||
c.Next()
|
||||
|
||||
@ -16,7 +16,7 @@ func GetClaimsFromContext(c *gin.Context) (auth.UserInfoJWT, error) {
|
||||
claims, exists := c.Get(global.ContextTokenData)
|
||||
|
||||
if !exists {
|
||||
return auth.UserInfoJWT{}, fmt.Errorf("error getting user id")
|
||||
return auth.UserInfoJWT{}, fmt.Errorf("error getting user id 1")
|
||||
}
|
||||
|
||||
parsedUserId, err := strconv.ParseInt(
|
||||
|
||||
@ -12,7 +12,7 @@ func GetUserIdFromContext(c *gin.Context) (int64, error) {
|
||||
userId, exists := c.Get(global.ContextUserId)
|
||||
|
||||
if !exists {
|
||||
return -1, fmt.Errorf("error getting user id")
|
||||
return -1, fmt.Errorf("error getting user id 2")
|
||||
}
|
||||
|
||||
if parsedUserId, err := strconv.ParseInt(userId.(string), 10, 64); err != nil {
|
||||
|
||||
@ -14,6 +14,7 @@ const (
|
||||
POST_BLOG_MIDDLEWARE = "POST_BLOG_MIDDLEWARE"
|
||||
POST_VOTE_MIDDLEWARE = "POST_VOTE_MIDDLEWARE"
|
||||
POST_VOTES_MIDDLEWARE = "POST_VOTES_MIDDLEWARE"
|
||||
USER_MIDDLEWARE = "USER_MIDDLEWARE"
|
||||
)
|
||||
|
||||
var MiddlewareProvider = middleware.MiddlewareProvider{
|
||||
@ -152,6 +153,25 @@ var policiesToRegister = map[string]middleware.RulesToCheck{
|
||||
MustBeCompleted: rules.ALL_RULES_MUST_BE_COMPLETED,
|
||||
},
|
||||
},
|
||||
|
||||
USER_MIDDLEWARE: {
|
||||
middleware.GET: {
|
||||
Rules: make([]rules.RuleFunction, 0),
|
||||
MustBeCompleted: rules.ALL_RULES_MUST_BE_COMPLETED,
|
||||
},
|
||||
middleware.PUT: {
|
||||
Rules: []rules.RuleFunction{
|
||||
globalrules.AuthorizedRule,
|
||||
},
|
||||
MustBeCompleted: rules.ALL_RULES_MUST_BE_COMPLETED,
|
||||
},
|
||||
middleware.DELETE: {
|
||||
Rules: []rules.RuleFunction{
|
||||
globalrules.IsAdminRule,
|
||||
},
|
||||
MustBeCompleted: rules.ALL_RULES_MUST_BE_COMPLETED,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func InitMiddlewareProvider() {
|
||||
|
||||
@ -194,6 +194,14 @@ func SetupRotes(g *gin.Engine) error {
|
||||
voteroutes.GetVotes,
|
||||
)
|
||||
|
||||
userGroup := g.Group("/users/")
|
||||
userGroup.Use(MiddlewareProvider.GetMiddleware(USER_MIDDLEWARE))
|
||||
|
||||
userGroup.GET(
|
||||
"/info/:user-id",
|
||||
userroutes.GetUserInfo,
|
||||
)
|
||||
|
||||
// Admin group routes
|
||||
adminGroup := g.Group("/admin/")
|
||||
adminGroup.Use(middleware.AdminMiddleware())
|
||||
|
||||
35
enshi_back/routes/userRoutes/getUserInfo.go
Normal file
35
enshi_back/routes/userRoutes/getUserInfo.go
Normal file
@ -0,0 +1,35 @@
|
||||
package userroutes
|
||||
|
||||
import (
|
||||
"context"
|
||||
db_repo "enshi/db/go_queries"
|
||||
"enshi/db_connection"
|
||||
"enshi/middleware/getters"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func GetUserInfo(c *gin.Context) {
|
||||
userId, err := getters.GetInt64Param(c, "user-id")
|
||||
if err != nil {
|
||||
c.JSON(400, gin.H{"error": "Invalid user ID"})
|
||||
return
|
||||
}
|
||||
|
||||
userInfo, err := db_repo.New(db_connection.Dbx).GetUserById(context.Background(), userId)
|
||||
if err != nil {
|
||||
c.JSON(500, gin.H{"error": "Failed to retrieve user information"})
|
||||
return
|
||||
}
|
||||
|
||||
userProfileInfo, err := db_repo.New(db_connection.Dbx).GetProfileByUserId(context.Background(), userId)
|
||||
if err != nil {
|
||||
c.JSON(500, gin.H{"error": "Failed to retrieve user profile information"})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(200, gin.H{
|
||||
"user_info": userInfo,
|
||||
"profile_info": userProfileInfo,
|
||||
})
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user