From a08e068030f6ed96035f6bd7dcb0fe4ed0d6ae88 Mon Sep 17 00:00:00 2001 From: Max Date: Wed, 4 Dec 2024 23:01:05 +0300 Subject: [PATCH] Random posts route --- enshi/package-lock.json | 81 +++++++++++++++++-- enshi/package.json | 1 + enshi/src/@types/PostTypes.ts | 8 ++ .../ArticleViewer/ArticleViewer.tsx | 41 +++++----- enshi/src/Pages/MainPage/MainPage.tsx | 11 ++- .../RandomPostsPage/PostCard/PostCard.tsx | 30 +++++++ .../Pages/RandomPostsPage/RandomPostsPage.tsx | 56 +++++++++++++ enshi/src/routes/routes.tsx | 5 +- enshi_back/db/go_queries/posts_queries.sql.go | 41 ++++++++++ enshi_back/db/queries/posts_queries.sql | 8 +- .../routes/postsRoutes/getRandomPosts.go | 43 ++++++++++ enshi_back/routes/routesSetup.go | 6 ++ 12 files changed, 301 insertions(+), 30 deletions(-) create mode 100644 enshi/src/@types/PostTypes.ts create mode 100644 enshi/src/Pages/RandomPostsPage/PostCard/PostCard.tsx create mode 100644 enshi/src/Pages/RandomPostsPage/RandomPostsPage.tsx create mode 100644 enshi_back/routes/postsRoutes/getRandomPosts.go diff --git a/enshi/package-lock.json b/enshi/package-lock.json index 499cbe7..f4e7c72 100644 --- a/enshi/package-lock.json +++ b/enshi/package-lock.json @@ -12,6 +12,7 @@ "@radix-ui/react-form": "^0.1.0", "@radix-ui/react-icons": "^1.3.2", "@radix-ui/react-navigation-menu": "^1.2.1", + "@radix-ui/react-scroll-area": "^1.2.1", "@radix-ui/react-toast": "^1.2.2", "@radix-ui/react-tooltip": "^1.1.2", "@radix-ui/themes": "^3.1.3", @@ -2044,17 +2045,17 @@ } }, "node_modules/@radix-ui/react-scroll-area": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-scroll-area/-/react-scroll-area-1.1.0.tgz", - "integrity": "sha512-9ArIZ9HWhsrfqS765h+GZuLoxaRHD/j0ZWOWilsCvYTpYJp8XwCqNG7Dt9Nu/TItKOdgLGkOPCodQvDc+UMwYg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-scroll-area/-/react-scroll-area-1.2.1.tgz", + "integrity": "sha512-FnM1fHfCtEZ1JkyfH/1oMiTcFBQvHKl4vD9WnpwkLgtF+UmnXMCad6ECPTaAjcDjam+ndOEJWgHyKDGNteWSHw==", "license": "MIT", "dependencies": { "@radix-ui/number": "1.1.0", "@radix-ui/primitive": "1.1.0", "@radix-ui/react-compose-refs": "1.1.0", - "@radix-ui/react-context": "1.1.0", + "@radix-ui/react-context": "1.1.1", "@radix-ui/react-direction": "1.1.0", - "@radix-ui/react-presence": "1.1.0", + "@radix-ui/react-presence": "1.1.1", "@radix-ui/react-primitive": "2.0.0", "@radix-ui/react-use-callback-ref": "1.1.0", "@radix-ui/react-use-layout-effect": "1.1.0" @@ -2074,6 +2075,45 @@ } } }, + "node_modules/@radix-ui/react-scroll-area/node_modules/@radix-ui/react-context": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.1.tgz", + "integrity": "sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-scroll-area/node_modules/@radix-ui/react-presence": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.1.tgz", + "integrity": "sha512-IeFXVi4YS1K0wVZzXNrbaaUvIJ3qdY+/Ih4eHFhWA9SwGR9UDX7Ck8abvL57C4cv3wwMvUE0OG69Qc3NCcTe/A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-use-layout-effect": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-select": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-2.1.1.tgz", @@ -2678,6 +2718,37 @@ } } }, + "node_modules/@radix-ui/themes/node_modules/@radix-ui/react-scroll-area": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-scroll-area/-/react-scroll-area-1.1.0.tgz", + "integrity": "sha512-9ArIZ9HWhsrfqS765h+GZuLoxaRHD/j0ZWOWilsCvYTpYJp8XwCqNG7Dt9Nu/TItKOdgLGkOPCodQvDc+UMwYg==", + "license": "MIT", + "dependencies": { + "@radix-ui/number": "1.1.0", + "@radix-ui/primitive": "1.1.0", + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-context": "1.1.0", + "@radix-ui/react-direction": "1.1.0", + "@radix-ui/react-presence": "1.1.0", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-use-callback-ref": "1.1.0", + "@radix-ui/react-use-layout-effect": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/themes/node_modules/@radix-ui/react-tooltip": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.1.1.tgz", diff --git a/enshi/package.json b/enshi/package.json index 6effe72..6cc8117 100644 --- a/enshi/package.json +++ b/enshi/package.json @@ -14,6 +14,7 @@ "@radix-ui/react-form": "^0.1.0", "@radix-ui/react-icons": "^1.3.2", "@radix-ui/react-navigation-menu": "^1.2.1", + "@radix-ui/react-scroll-area": "^1.2.1", "@radix-ui/react-toast": "^1.2.2", "@radix-ui/react-tooltip": "^1.1.2", "@radix-ui/themes": "^3.1.3", diff --git a/enshi/src/@types/PostTypes.ts b/enshi/src/@types/PostTypes.ts new file mode 100644 index 0000000..9068e49 --- /dev/null +++ b/enshi/src/@types/PostTypes.ts @@ -0,0 +1,8 @@ +export type GetRandomPostsRow = { + post_id: string; + // blog_id: number; + user_id: string; + title: string; + // created_at: Date; +} + diff --git a/enshi/src/Components/ArticleViewer/ArticleViewer.tsx b/enshi/src/Components/ArticleViewer/ArticleViewer.tsx index 5e6cb85..15f8a4a 100644 --- a/enshi/src/Components/ArticleViewer/ArticleViewer.tsx +++ b/enshi/src/Components/ArticleViewer/ArticleViewer.tsx @@ -14,7 +14,7 @@ type TArticleViewer = { export default function ArticleViewer(props: TArticleViewer) { let queryParams = useParams(); - const user = useAtomValue(userAtom) + const user = useAtomValue(userAtom); const { data, isPending } = useQuery({ queryKey: [`post_${queryParams["postId"]}`], @@ -25,31 +25,32 @@ export default function ArticleViewer(props: TArticleViewer) { return response.data; }, - }) - + }); if (isPending) return ; return ( <> -
- - - - {data.title} - - - + +
+ + + + {data.title} + + + + - - - - -
+ + +
+
+ ); } diff --git a/enshi/src/Pages/MainPage/MainPage.tsx b/enshi/src/Pages/MainPage/MainPage.tsx index bf710a8..fe64d01 100644 --- a/enshi/src/Pages/MainPage/MainPage.tsx +++ b/enshi/src/Pages/MainPage/MainPage.tsx @@ -12,6 +12,10 @@ const RETRY_INTERVAL_IN_SECONDS = 1; const SECONDS_IN_MINUTE = 60; const MILLS_IN_SECOND = 1000; +const TAGS = Array.from({ length: 50 }).map( + (_, i, a) => `v1.2.0-beta.${a.length - i}` +); + export default function MainPage() { const setUserData = useSetAtom(userAtom); @@ -53,11 +57,14 @@ export default function MainPage() { ) : ( - + - + diff --git a/enshi/src/Pages/RandomPostsPage/PostCard/PostCard.tsx b/enshi/src/Pages/RandomPostsPage/PostCard/PostCard.tsx new file mode 100644 index 0000000..2b29f64 --- /dev/null +++ b/enshi/src/Pages/RandomPostsPage/PostCard/PostCard.tsx @@ -0,0 +1,30 @@ +import { ImageIcon } from "@radix-ui/react-icons"; +import { Box, Card, Heading } from "@radix-ui/themes"; +import { useNavigate } from "react-router-dom"; +import { GetRandomPostsRow } from "../../../@types/PostTypes"; + +type TPostCard = { + post: GetRandomPostsRow; +}; + +export default function PostCard({ post }: TPostCard) { + const navigate = useNavigate() + + const clickHandler = () => { + navigate(`/posts/${post.post_id.toString()}`) + } + + return ( + + + + + + + + {post.title} + + + + ); +} diff --git a/enshi/src/Pages/RandomPostsPage/RandomPostsPage.tsx b/enshi/src/Pages/RandomPostsPage/RandomPostsPage.tsx new file mode 100644 index 0000000..764b601 --- /dev/null +++ b/enshi/src/Pages/RandomPostsPage/RandomPostsPage.tsx @@ -0,0 +1,56 @@ +import * as ScrollArea from "@radix-ui/react-scroll-area"; +import { Container } from "@radix-ui/themes"; +import { useQuery } from "@tanstack/react-query"; +import { GetRandomPostsRow } from "../../@types/PostTypes"; +import { axiosLocalhost } from "../../api/axios/axios"; +import PostCard from "./PostCard/PostCard"; + +const LIMIT = 10; + +export default function RandomPostsPage() { + const { data, refetch } = useQuery({ + queryKey: ["random_posts_key"], + queryFn: async () => { + try { + const response = await axiosLocalhost.get( + `/posts/random?limit=${LIMIT}` + ); + + return response.data as GetRandomPostsRow[]; + } catch (error) { + console.log(`Something went wrong`); + } + + return []; + }, + }); + + return ( + <> + + + {data?.map((post, i) => { + return ( + + + + ); + })} + + + + + + + + + + + ); +} diff --git a/enshi/src/routes/routes.tsx b/enshi/src/routes/routes.tsx index a8f2323..86b324e 100644 --- a/enshi/src/routes/routes.tsx +++ b/enshi/src/routes/routes.tsx @@ -11,6 +11,7 @@ import PostRedactor from "../Pages/LoginRegisterPage/PostRedactor/PostRedactor"; import RegisterPage from "../Pages/LoginRegisterPage/RegisterPage/RegisterPage"; import MainPage from "../Pages/MainPage/MainPage"; import PostCreatorPage from "../Pages/PostCreatorPage/PostCreatorPage"; +import RandomPostsPage from "../Pages/RandomPostsPage/RandomPostsPage"; function ErrorBoundary() { let error = useRouteError(); @@ -22,12 +23,12 @@ function ErrorBoundary() { export const routes = createRoutesFromElements( <> } element={}> - Cringer path} /> + } /> Cringer path, but this a + This page is yet to be created } /> diff --git a/enshi_back/db/go_queries/posts_queries.sql.go b/enshi_back/db/go_queries/posts_queries.sql.go index 5dc478f..c778e15 100644 --- a/enshi_back/db/go_queries/posts_queries.sql.go +++ b/enshi_back/db/go_queries/posts_queries.sql.go @@ -146,6 +146,47 @@ func (q *Queries) GetPostsByUserId(ctx context.Context, userID int64) ([]Post, e return items, nil } +const getRandomPosts = `-- name: GetRandomPosts :many +SELECT post_id, blog_id, user_id, title, created_at +FROM public.posts +ORDER BY RANDOM() +LIMIT $1 +` + +type GetRandomPostsRow struct { + PostID int64 `json:"post_id"` + BlogID pgtype.Int8 `json:"blog_id"` + UserID int64 `json:"user_id"` + Title pgtype.Text `json:"title"` + CreatedAt pgtype.Timestamp `json:"created_at"` +} + +func (q *Queries) GetRandomPosts(ctx context.Context, limit int32) ([]GetRandomPostsRow, error) { + rows, err := q.db.Query(ctx, getRandomPosts, limit) + if err != nil { + return nil, err + } + defer rows.Close() + var items []GetRandomPostsRow + for rows.Next() { + var i GetRandomPostsRow + if err := rows.Scan( + &i.PostID, + &i.BlogID, + &i.UserID, + &i.Title, + &i.CreatedAt, + ); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + const updatePostBlogId = `-- name: UpdatePostBlogId :exec UPDATE public.posts SET blog_id=$2, updated_at=CURRENT_TIMESTAMP diff --git a/enshi_back/db/queries/posts_queries.sql b/enshi_back/db/queries/posts_queries.sql index bc260c1..9f22b8f 100644 --- a/enshi_back/db/queries/posts_queries.sql +++ b/enshi_back/db/queries/posts_queries.sql @@ -33,4 +33,10 @@ WHERE post_id=$1; UPDATE public.posts SET blog_id=$2, updated_at=CURRENT_TIMESTAMP WHERE post_id = $1 -RETURNING *; \ No newline at end of file +RETURNING *; + +-- name: GetRandomPosts :many +SELECT post_id, blog_id, user_id, title, created_at +FROM public.posts +ORDER BY RANDOM() +LIMIT $1; \ No newline at end of file diff --git a/enshi_back/routes/postsRoutes/getRandomPosts.go b/enshi_back/routes/postsRoutes/getRandomPosts.go new file mode 100644 index 0000000..f8f2139 --- /dev/null +++ b/enshi_back/routes/postsRoutes/getRandomPosts.go @@ -0,0 +1,43 @@ +package postsRoutes + +import ( + "context" + rest_api_stuff "enshi/REST_API_stuff" + db_repo "enshi/db/go_queries" + "enshi/db_connection" + "net/http" + "strconv" + + "github.com/gin-gonic/gin" +) + +func GetRandomPost(c *gin.Context) { + limit, err := strconv.Atoi(c.DefaultQuery("limit", "10")) + + if err != nil { + rest_api_stuff.InternalErrorAnswer(c, err) + return + } + + postsData, err := + db_repo.New(db_connection.Dbx). + GetRandomPosts(context.Background(), int32(limit)) + + if err != nil { + rest_api_stuff.InternalErrorAnswer(c, err) + return + } + + result := make([]any, 0) + + for _, post := range postsData { + result = append(result, gin.H{ + "post_id": strconv.Itoa(int(post.PostID)), + "title": post.Title, + "user_id": strconv.Itoa(int(post.UserID)), + }) + } + + c.IndentedJSON(http.StatusOK, result) + +} diff --git a/enshi_back/routes/routesSetup.go b/enshi_back/routes/routesSetup.go index 8ab6818..99e4133 100644 --- a/enshi_back/routes/routesSetup.go +++ b/enshi_back/routes/routesSetup.go @@ -65,6 +65,12 @@ func SetupRotes(g *gin.Engine) error { "posts/:post-id", postsRoutes.GetPost, ) + + postsGroup.GET( + "posts/random", + postsRoutes.GetRandomPost, + ) + postsGroup.PUT( "posts/:post-id", postsRoutes.UpdatePost,