This commit is contained in:
Max 2024-12-06 20:43:02 +03:00
parent 1f7d95a4ff
commit d87663d3d4
9 changed files with 229 additions and 6 deletions

View File

@ -0,0 +1,13 @@
import { Box } from '@radix-ui/themes'
import { useParams } from 'react-router-dom'
export default function BlogPage() {
const queryParams = useParams()
return (
<Box>
</Box>
)
}

View File

@ -0,0 +1,21 @@
import { Card } from '@radix-ui/themes';
import { useNavigate } from 'react-router-dom';
type TBlogBox = {
title?: string;
blogId?: string;
}
export default function BlogBox(props: TBlogBox) {
const navigate = useNavigate()
return (
<Card className='w-full h-20'
onClick={() => navigate(``)}
>
{props?.title || "...No title..."}
{props?.blogId || "adqwwd"}
</Card>
)
}

View File

@ -0,0 +1,17 @@
import { Box, Skeleton } from "@radix-ui/themes";
export default function SkeletonBoxes() {
return (
<>
<Skeleton>
<Box className="w-full h-20 mb-2 rounded-lg"></Box>
</Skeleton>
<Skeleton>
<Box className="w-full h-20 mb-2 rounded-lg"></Box>
</Skeleton>
<Skeleton>
<Box className="w-full h-20 mb-2 rounded-lg"></Box>
</Skeleton>
</>
);
}

View File

@ -0,0 +1,69 @@
import { Box, Container, Flex } from "@radix-ui/themes";
import { useQuery } from "@tanstack/react-query";
import { useAtomValue } from "jotai";
import { userAtom } from "../../AtomStore/AtomStore";
import { axiosLocalhost } from "../../api/axios/axios";
import BlogBox from "./BlogBox/BlogBox";
import SkeletonBoxes from "./SkeletonBoxes/SkeletonBoxes";
export default function UserBlogsPage() {
const user = useAtomValue(userAtom);
const isBigNumber = (num: any) => !Number.isSafeInteger(+num);
const enquoteBigNumber = (jsonString: any, bigNumChecker: any) =>
jsonString.replaceAll(
/([:\s\[,]*)(\d+)([\s,\]]*)/g,
(matchingSubstr: any, prefix: any, bigNum: any, suffix: any) =>
bigNumChecker(bigNum)
? `${prefix}"${bigNum}"${suffix}`
: matchingSubstr
);
const parseWithBigInt = (jsonString: any, bigNumChecker: any) =>
JSON.parse(enquoteBigNumber(jsonString, bigNumChecker), (key, value) =>
!isNaN(value) && bigNumChecker(value)
? BigInt(value).toString()
: value
);
const { data, isPending, isFetching } = useQuery({
queryKey: ["userBlogs"],
queryFn: async () => {
const response = await axiosLocalhost.get("/user/blogs", {
transformResponse: [(data) => data],
});
let temp = parseWithBigInt(response.data, isBigNumber);
return temp as any[];
},
});
if (isFetching)
return (
<Container size={"1"}>
<SkeletonBoxes />
</Container>
);
return (
<Box className="size-full">
<Container size={"1"}>
<Flex direction={"column"} gap={"2"}>
{data
? data?.map((blog: any, b) => {
return (
<BlogBox
key={b}
title={blog.title}
blogId={blog.blog_id}
/>
);
})
: null}
</Flex>
</Container>
</Box>
);
}

View File

@ -1,17 +1,20 @@
import { Text } from "@radix-ui/themes"; import { Text } from "@radix-ui/themes";
import { import {
createRoutesFromElements, createRoutesFromElements,
Outlet,
Route, Route,
useRouteError, useRouteError,
} from "react-router-dom"; } from "react-router-dom";
import ArticleViewer from "../Components/ArticleViewer/ArticleViewer"; import ArticleViewer from "../Components/ArticleViewer/ArticleViewer";
import MainPage from "../layout/MainPage/MainPage";
import AuthPageWrapper from "../Pages/AuthPageWrapper/AuthPageWrapper"; import AuthPageWrapper from "../Pages/AuthPageWrapper/AuthPageWrapper";
import BlogPage from "../Pages/BlogPage/BlogPage";
import LoginPage from "../Pages/LoginRegisterPage/LoginPage/LoginPage"; import LoginPage from "../Pages/LoginRegisterPage/LoginPage/LoginPage";
import PostRedactor from "../Pages/LoginRegisterPage/PostRedactor/PostRedactor"; import PostRedactor from "../Pages/LoginRegisterPage/PostRedactor/PostRedactor";
import RegisterPage from "../Pages/LoginRegisterPage/RegisterPage/RegisterPage"; import RegisterPage from "../Pages/LoginRegisterPage/RegisterPage/RegisterPage";
import MainPage from "../Pages/MainPage/MainPage";
import PostCreatorPage from "../Pages/PostCreatorPage/PostCreatorPage"; import PostCreatorPage from "../Pages/PostCreatorPage/PostCreatorPage";
import RandomPostsPage from "../Pages/RandomPostsPage/RandomPostsPage"; import RandomPostsPage from "../Pages/RandomPostsPage/RandomPostsPage";
import UserBlogsPage from "../Pages/UserBlogsPage/UserBlogsPage";
function ErrorBoundary() { function ErrorBoundary() {
let error = useRouteError(); let error = useRouteError();
@ -26,14 +29,16 @@ export const routes = createRoutesFromElements(
<Route index element={<RandomPostsPage />} /> <Route index element={<RandomPostsPage />} />
<Route <Route
path="/a?/c" path="a?/c"
element={ element={
<Text weight={"regular"}>This page is yet to be created</Text> <Text weight={"regular"}>
This page is yet to be created
</Text>
} }
/> />
<Route <Route
path="/create" path="create"
element={ element={
<AuthPageWrapper> <AuthPageWrapper>
<PostCreatorPage /> <PostCreatorPage />
@ -41,8 +46,21 @@ export const routes = createRoutesFromElements(
} }
/> />
<Route path="/posts/:postId" element={<ArticleViewer />} /> <Route path="blogs/:blogId" element={<BlogPage />} />
<Route path="/posts/change/:postId" element={<PostRedactor />} />
<Route path="user" element={<Outlet />}>
<Route
path="blogs"
element={
<AuthPageWrapper>
<UserBlogsPage />
</AuthPageWrapper>
}
/>
</Route>
<Route path="posts/:postId" element={<ArticleViewer />} />
<Route path="posts/change/:postId" element={<PostRedactor />} />
</Route> </Route>
<Route <Route

View File

@ -0,0 +1,29 @@
package blogRoutes
import (
"context"
rest_api_stuff "enshi/REST_API_stuff"
db_repo "enshi/db/go_queries"
"enshi/db_connection"
"enshi/middleware/getters"
"net/http"
"github.com/gin-gonic/gin"
)
func GetUserBlogs(c *gin.Context) {
userId, err := getters.GetUserIdFromContext(c)
if err != nil {
rest_api_stuff.BadRequestAnswer(c, err)
return
}
blogData, err := db_repo.New(db_connection.Dbx).
GetBlogsByUserId(context.Background(), userId)
if err != nil {
rest_api_stuff.InternalErrorAnswer(c, err)
return
}
c.IndentedJSON(http.StatusOK, blogData)
}

View File

@ -174,5 +174,12 @@ func SetupRotes(g *gin.Engine) error {
authGroup.Use(middleware.AuthMiddleware()) authGroup.Use(middleware.AuthMiddleware())
authGroup.GET("check", testAuth) authGroup.GET("check", testAuth)
temporal := g.Group("/")
temporal.Use(middleware.AuthMiddleware())
temporal.GET(
"/user/blogs",
blogRoutes.GetUserBlogs,
)
return nil return nil
} }

View File

@ -0,0 +1,49 @@
package utils
import (
"fmt"
"reflect"
)
func ConvertInt64ToStringInStruct(input any) (any, error) {
origVal := reflect.ValueOf(input)
// Ensure input is a struct or pointer to a struct
if origVal.Kind() == reflect.Ptr {
origVal = origVal.Elem()
}
if origVal.Kind() != reflect.Struct {
return nil, fmt.Errorf("input must be a struct or a pointer to a struct")
}
// Create a new instance of the same type
newStruct := reflect.New(origVal.Type()).Elem()
// Iterate through fields
for i := 0; i < origVal.NumField(); i++ {
field := origVal.Field(i)
newField := newStruct.Field(i)
if !newField.CanSet() {
// Skip unexported fields
continue
}
switch field.Kind() {
case reflect.Int64:
// Convert int64 fields to string if the target is compatible
// if newField.Kind() == reflect.Int64 {
// fmt.Print("aqwrqfwq", field)
// newField.Set(strconv.FormatInt(field.Int(), 10))
// }
newField.SetString("asd")
default:
// Copy other fields directly
if newField.Type() == field.Type() {
newField.Set(field)
}
}
}
return newStruct.Interface(), nil
}