Random posts route
This commit is contained in:
parent
1ab8022b95
commit
a08e068030
81
enshi/package-lock.json
generated
81
enshi/package-lock.json
generated
@ -12,6 +12,7 @@
|
|||||||
"@radix-ui/react-form": "^0.1.0",
|
"@radix-ui/react-form": "^0.1.0",
|
||||||
"@radix-ui/react-icons": "^1.3.2",
|
"@radix-ui/react-icons": "^1.3.2",
|
||||||
"@radix-ui/react-navigation-menu": "^1.2.1",
|
"@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-toast": "^1.2.2",
|
||||||
"@radix-ui/react-tooltip": "^1.1.2",
|
"@radix-ui/react-tooltip": "^1.1.2",
|
||||||
"@radix-ui/themes": "^3.1.3",
|
"@radix-ui/themes": "^3.1.3",
|
||||||
@ -2044,17 +2045,17 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@radix-ui/react-scroll-area": {
|
"node_modules/@radix-ui/react-scroll-area": {
|
||||||
"version": "1.1.0",
|
"version": "1.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-scroll-area/-/react-scroll-area-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-scroll-area/-/react-scroll-area-1.2.1.tgz",
|
||||||
"integrity": "sha512-9ArIZ9HWhsrfqS765h+GZuLoxaRHD/j0ZWOWilsCvYTpYJp8XwCqNG7Dt9Nu/TItKOdgLGkOPCodQvDc+UMwYg==",
|
"integrity": "sha512-FnM1fHfCtEZ1JkyfH/1oMiTcFBQvHKl4vD9WnpwkLgtF+UmnXMCad6ECPTaAjcDjam+ndOEJWgHyKDGNteWSHw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@radix-ui/number": "1.1.0",
|
"@radix-ui/number": "1.1.0",
|
||||||
"@radix-ui/primitive": "1.1.0",
|
"@radix-ui/primitive": "1.1.0",
|
||||||
"@radix-ui/react-compose-refs": "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-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-primitive": "2.0.0",
|
||||||
"@radix-ui/react-use-callback-ref": "1.1.0",
|
"@radix-ui/react-use-callback-ref": "1.1.0",
|
||||||
"@radix-ui/react-use-layout-effect": "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": {
|
"node_modules/@radix-ui/react-select": {
|
||||||
"version": "2.1.1",
|
"version": "2.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-2.1.1.tgz",
|
"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": {
|
"node_modules/@radix-ui/themes/node_modules/@radix-ui/react-tooltip": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.1.1.tgz",
|
||||||
|
|||||||
@ -14,6 +14,7 @@
|
|||||||
"@radix-ui/react-form": "^0.1.0",
|
"@radix-ui/react-form": "^0.1.0",
|
||||||
"@radix-ui/react-icons": "^1.3.2",
|
"@radix-ui/react-icons": "^1.3.2",
|
||||||
"@radix-ui/react-navigation-menu": "^1.2.1",
|
"@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-toast": "^1.2.2",
|
||||||
"@radix-ui/react-tooltip": "^1.1.2",
|
"@radix-ui/react-tooltip": "^1.1.2",
|
||||||
"@radix-ui/themes": "^3.1.3",
|
"@radix-ui/themes": "^3.1.3",
|
||||||
|
|||||||
8
enshi/src/@types/PostTypes.ts
Normal file
8
enshi/src/@types/PostTypes.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
export type GetRandomPostsRow = {
|
||||||
|
post_id: string;
|
||||||
|
// blog_id: number;
|
||||||
|
user_id: string;
|
||||||
|
title: string;
|
||||||
|
// created_at: Date;
|
||||||
|
}
|
||||||
|
|
||||||
@ -14,7 +14,7 @@ type TArticleViewer = {
|
|||||||
|
|
||||||
export default function ArticleViewer(props: TArticleViewer) {
|
export default function ArticleViewer(props: TArticleViewer) {
|
||||||
let queryParams = useParams();
|
let queryParams = useParams();
|
||||||
const user = useAtomValue(userAtom)
|
const user = useAtomValue(userAtom);
|
||||||
|
|
||||||
const { data, isPending } = useQuery({
|
const { data, isPending } = useQuery({
|
||||||
queryKey: [`post_${queryParams["postId"]}`],
|
queryKey: [`post_${queryParams["postId"]}`],
|
||||||
@ -25,31 +25,32 @@ export default function ArticleViewer(props: TArticleViewer) {
|
|||||||
|
|
||||||
return response.data;
|
return response.data;
|
||||||
},
|
},
|
||||||
})
|
});
|
||||||
|
|
||||||
|
|
||||||
if (isPending) return <SkeletonPostLoader />;
|
if (isPending) return <SkeletonPostLoader />;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="ql-snow">
|
<Container size={"3"}>
|
||||||
<Container size={"2"} className="mt-4">
|
<div className="ql-snow ql-editor">
|
||||||
<Flex direction={"column"}>
|
<Container size={"2"} className="mt-4">
|
||||||
<Text className="mb-2" as="div" size={"9"}>
|
<Flex direction={"column"}>
|
||||||
{data.title}
|
<Text className="mb-2" as="div" size={"9"}>
|
||||||
</Text>
|
{data.title}
|
||||||
<Flex className="mt-4 mb-2">
|
</Text>
|
||||||
<div hidden={data.user_id != user?.id}>
|
<Flex className="mt-4 mb-2">
|
||||||
<ChangePostButton
|
<div hidden={data.user_id != user?.id}>
|
||||||
postId={queryParams["postId"] || ""}
|
<ChangePostButton
|
||||||
/>
|
postId={queryParams["postId"] || ""}
|
||||||
</div>
|
/>
|
||||||
|
</div>
|
||||||
|
</Flex>
|
||||||
</Flex>
|
</Flex>
|
||||||
</Flex>
|
<Separator size={"4"} className="mb-2" />
|
||||||
<Separator size={"4"} className="mb-2" />
|
<Interweave content={data.content} />
|
||||||
<Interweave content={data.content} />
|
</Container>
|
||||||
</Container>
|
</div>
|
||||||
</div>
|
</Container>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,6 +12,10 @@ const RETRY_INTERVAL_IN_SECONDS = 1;
|
|||||||
const SECONDS_IN_MINUTE = 60;
|
const SECONDS_IN_MINUTE = 60;
|
||||||
const MILLS_IN_SECOND = 1000;
|
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() {
|
export default function MainPage() {
|
||||||
const setUserData = useSetAtom(userAtom);
|
const setUserData = useSetAtom(userAtom);
|
||||||
|
|
||||||
@ -53,11 +57,14 @@ export default function MainPage() {
|
|||||||
<Spinner size={"3"} />
|
<Spinner size={"3"} />
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<Flex direction={"column"} className="min-h-[100vh] max-h-[100vh]">
|
<Flex
|
||||||
|
direction={"column"}
|
||||||
|
className="min-h-[100vh] max-h-[100vh] overflow-hidden"
|
||||||
|
>
|
||||||
<Box flexGrow={"1"} className="flex-[1]">
|
<Box flexGrow={"1"} className="flex-[1]">
|
||||||
<NavBar />
|
<NavBar />
|
||||||
</Box>
|
</Box>
|
||||||
<Box flexGrow={"100"} className="flex flex-col overflow-auto">
|
<Box flexGrow={"100"} className="flex overflow-hidden flex-">
|
||||||
<Outlet />
|
<Outlet />
|
||||||
</Box>
|
</Box>
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|||||||
30
enshi/src/Pages/RandomPostsPage/PostCard/PostCard.tsx
Normal file
30
enshi/src/Pages/RandomPostsPage/PostCard/PostCard.tsx
Normal file
@ -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 (
|
||||||
|
<Card className="h-32 mb-4" onClick={clickHandler}>
|
||||||
|
<Box className="flex size-full">
|
||||||
|
<Box>
|
||||||
|
<ImageIcon className="w-full h-full" />
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<Box className="px-4 pt-2">
|
||||||
|
<Heading>{post.title}</Heading>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
}
|
||||||
56
enshi/src/Pages/RandomPostsPage/RandomPostsPage.tsx
Normal file
56
enshi/src/Pages/RandomPostsPage/RandomPostsPage.tsx
Normal file
@ -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 (
|
||||||
|
<>
|
||||||
|
<ScrollArea.Root className="w-full overflow-hidden grow-1">
|
||||||
|
<ScrollArea.Viewport className="rounded size-full">
|
||||||
|
{data?.map((post, i) => {
|
||||||
|
return (
|
||||||
|
<Container size={"3"} key={`post${i}`}>
|
||||||
|
<PostCard post={post} />
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</ScrollArea.Viewport>
|
||||||
|
<ScrollArea.Scrollbar
|
||||||
|
className="flex touch-none select-none bg-blackA3 p-0.5 transition-colors duration-[160ms] ease-out hover:bg-blackA5 data-[orientation=horizontal]:h-2.5 data-[orientation=vertical]:w-2.5 data-[orientation=horizontal]:flex-col"
|
||||||
|
orientation="vertical"
|
||||||
|
>
|
||||||
|
<ScrollArea.Thumb className="relative flex-1 rounded-[10px] bg-mauve10 before:absolute before:left-1/2 before:top-1/2 before:size-full before:min-h-11 before:min-w-11 before:-translate-x-1/2 before:-translate-y-1/2" />
|
||||||
|
</ScrollArea.Scrollbar>
|
||||||
|
<ScrollArea.Scrollbar
|
||||||
|
className="flex touch-none select-none bg-blackA3 p-0.5 transition-colors duration-[160ms] ease-out hover:bg-blackA5 data-[orientation=horizontal]:h-2.5 data-[orientation=vertical]:w-2.5 data-[orientation=horizontal]:flex-col"
|
||||||
|
orientation="horizontal"
|
||||||
|
>
|
||||||
|
<ScrollArea.Thumb className="relative flex-1 rounded-[10px] bg-mauve10 before:absolute before:left-1/2 before:top-1/2 before:size-full before:min-h-[44px] before:min-w-[44px] before:-translate-x-1/2 before:-translate-y-1/2" />
|
||||||
|
</ScrollArea.Scrollbar>
|
||||||
|
<ScrollArea.Corner className="bg-blackA5" />
|
||||||
|
</ScrollArea.Root>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -11,6 +11,7 @@ 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 MainPage from "../Pages/MainPage/MainPage";
|
||||||
import PostCreatorPage from "../Pages/PostCreatorPage/PostCreatorPage";
|
import PostCreatorPage from "../Pages/PostCreatorPage/PostCreatorPage";
|
||||||
|
import RandomPostsPage from "../Pages/RandomPostsPage/RandomPostsPage";
|
||||||
|
|
||||||
function ErrorBoundary() {
|
function ErrorBoundary() {
|
||||||
let error = useRouteError();
|
let error = useRouteError();
|
||||||
@ -22,12 +23,12 @@ function ErrorBoundary() {
|
|||||||
export const routes = createRoutesFromElements(
|
export const routes = createRoutesFromElements(
|
||||||
<>
|
<>
|
||||||
<Route path="/" errorElement={<ErrorBoundary />} element={<MainPage />}>
|
<Route path="/" errorElement={<ErrorBoundary />} element={<MainPage />}>
|
||||||
<Route index element={<Text size={"5"}>Cringer path</Text>} />
|
<Route index element={<RandomPostsPage />} />
|
||||||
|
|
||||||
<Route
|
<Route
|
||||||
path="/a?/c"
|
path="/a?/c"
|
||||||
element={
|
element={
|
||||||
<Text weight={"regular"}>Cringer path, but this a</Text>
|
<Text weight={"regular"}>This page is yet to be created</Text>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|||||||
@ -146,6 +146,47 @@ func (q *Queries) GetPostsByUserId(ctx context.Context, userID int64) ([]Post, e
|
|||||||
return items, nil
|
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
|
const updatePostBlogId = `-- name: UpdatePostBlogId :exec
|
||||||
UPDATE public.posts
|
UPDATE public.posts
|
||||||
SET blog_id=$2, updated_at=CURRENT_TIMESTAMP
|
SET blog_id=$2, updated_at=CURRENT_TIMESTAMP
|
||||||
|
|||||||
@ -34,3 +34,9 @@ UPDATE public.posts
|
|||||||
SET blog_id=$2, updated_at=CURRENT_TIMESTAMP
|
SET blog_id=$2, updated_at=CURRENT_TIMESTAMP
|
||||||
WHERE post_id = $1
|
WHERE post_id = $1
|
||||||
RETURNING *;
|
RETURNING *;
|
||||||
|
|
||||||
|
-- name: GetRandomPosts :many
|
||||||
|
SELECT post_id, blog_id, user_id, title, created_at
|
||||||
|
FROM public.posts
|
||||||
|
ORDER BY RANDOM()
|
||||||
|
LIMIT $1;
|
||||||
43
enshi_back/routes/postsRoutes/getRandomPosts.go
Normal file
43
enshi_back/routes/postsRoutes/getRandomPosts.go
Normal file
@ -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)
|
||||||
|
|
||||||
|
}
|
||||||
@ -65,6 +65,12 @@ func SetupRotes(g *gin.Engine) error {
|
|||||||
"posts/:post-id",
|
"posts/:post-id",
|
||||||
postsRoutes.GetPost,
|
postsRoutes.GetPost,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
postsGroup.GET(
|
||||||
|
"posts/random",
|
||||||
|
postsRoutes.GetRandomPost,
|
||||||
|
)
|
||||||
|
|
||||||
postsGroup.PUT(
|
postsGroup.PUT(
|
||||||
"posts/:post-id",
|
"posts/:post-id",
|
||||||
postsRoutes.UpdatePost,
|
postsRoutes.UpdatePost,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user