diff --git a/client/src/App.tsx b/client/src/App.tsx index 09a8ced..5a507c2 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -16,7 +16,12 @@ import { signupAction, userListAction, } from "./actions"; -import { homeLoader, profileLoader, userListLoader } from "./loaders"; +import { + feedLoader, + homeLoader, + profileLoader, + userListLoader, +} from "./loaders"; import { isError } from "./api/dto"; import { Feed } from "./Feed"; import { Messages } from "./Messages"; @@ -42,7 +47,7 @@ const router = createBrowserRouter([ }, element: , children: [ - { path: "feed", element: }, + { path: "feed", element: , loader: feedLoader }, { path: "messages", element: }, { path: "users", diff --git a/client/src/Feed.scss b/client/src/Feed.scss new file mode 100644 index 0000000..cc4ac9f --- /dev/null +++ b/client/src/Feed.scss @@ -0,0 +1,9 @@ +.feedView { + min-width: 100%; + display: flex; + flex-direction: column; + + .posts { + padding: 2.5rem 2rem 0; + } +} \ No newline at end of file diff --git a/client/src/Feed.tsx b/client/src/Feed.tsx index 8f78735..8ad6782 100644 --- a/client/src/Feed.tsx +++ b/client/src/Feed.tsx @@ -1,3 +1,21 @@ +import { useLoaderData } from "react-router-dom"; +import { feedLoader, LoaderToType } from "./loaders"; +import { useHomeContext } from "./HomeContext"; +import { PostList } from "./PostList"; +import { isError } from "./api/dto"; + +import "./Feed.scss"; + export function Feed() { - return feed; + const loaderData = useLoaderData() as LoaderToType; + if (!loaderData || isError(loaderData)) { + return
error
; + } + const homeContext = useHomeContext(); + + return ( +
+ +
+ ); } diff --git a/client/src/PostList.tsx b/client/src/PostList.tsx new file mode 100644 index 0000000..7cae320 --- /dev/null +++ b/client/src/PostList.tsx @@ -0,0 +1,29 @@ +import { TPostToArr } from "./api/dto"; +import { Post } from "./Post"; + +export function PostList({ + posts, + selfUuid, +}: { + posts: TPostToArr | null; + selfUuid: string; +}) { + const sortedPosts = posts?.sort((a, b) => b.createdAt - a.createdAt); + return ( +
+ {sortedPosts && + sortedPosts.map((p) => { + const date = new Date(p.createdAt * 1000); + return ( + + ); + })} +
+ ); +} diff --git a/client/src/Profile.tsx b/client/src/Profile.tsx index 4149eb1..56ff84d 100644 --- a/client/src/Profile.tsx +++ b/client/src/Profile.tsx @@ -4,6 +4,7 @@ import { LoaderToType, profileLoader } from "./loaders"; import { isError } from "./api/dto"; import { Post } from "./Post"; import { useHomeContext } from "./HomeContext"; +import { PostList } from "./PostList"; export interface IProfileProps { self: boolean; @@ -18,10 +19,6 @@ export function Profile({ self }: IProfileProps) { return
Error
; } - const sortedPosts = loaderData.posts?.sort( - (a, b) => b.createdAt - a.createdAt, - ); - return (
@@ -41,21 +38,10 @@ export function Profile({ self }: IProfileProps) {
)} -
- {sortedPosts && - sortedPosts.map((p) => { - const date = new Date(p.createdAt * 1000); - return ( - - ); - })} -
+
); } diff --git a/client/src/api/Post.ts b/client/src/api/Post.ts index e285e8a..7c530d3 100644 --- a/client/src/api/Post.ts +++ b/client/src/api/Post.ts @@ -13,6 +13,7 @@ export async function createPost(text: string): Promise { text, }); } + export async function deletePost(id: number): Promise { return fetchJSONAuth(`/post/${id.toString()}`, "DELETE", NoContentToResp); } @@ -27,6 +28,10 @@ export async function getPostsByAuthorUuid( ); } +export async function getPostsByFollowees(): Promise { + return fetchJSONAuth(`/post/by-following`, "GET", PostToArrResp); +} + export async function getPostsByAuthorUsername( author: string, ): Promise { diff --git a/client/src/loaders.ts b/client/src/loaders.ts index 0ff881b..453f97a 100644 --- a/client/src/loaders.ts +++ b/client/src/loaders.ts @@ -7,7 +7,11 @@ import { import { deleteToken, getToken, getTokenUserUuid } from "./api/utils"; import { redirect } from "react-router-dom"; import { isError } from "./api/dto"; -import { getPostsByAuthorUsername, getPostsByAuthorUuid } from "./api/Post"; +import { + getPostsByAuthorUsername, + getPostsByAuthorUuid, + getPostsByFollowees, +} from "./api/Post"; export type LoaderToType any> = | Exclude>, Response> @@ -40,7 +44,12 @@ export async function profileLoader({ }) { const selfUuid = getTokenUserUuid(); if (!selfUuid) return redirect("/"); - if (selfUuid == params.username) { + + const retUser = params.username + ? await getPersonByUsername(params.username) + : null; + + if (retUser && !isError(retUser) && retUser.uuid == selfUuid) { return redirect("/home/profile"); } @@ -48,10 +57,6 @@ export async function profileLoader({ ? await getPostsByAuthorUsername(params.username) : await getPostsByAuthorUuid(selfUuid); - const retUser = params.username - ? await getPersonByUsername(params.username) - : null; - if ( (params.username && !retUser) || retUser instanceof Response || @@ -66,3 +71,7 @@ export async function profileLoader({ return { user: retUser, posts }; } + +export async function feedLoader() { + return await getPostsByFollowees(); +} diff --git a/server/src/main/java/com/usatiuk/tjv/y/server/controller/PostController.java b/server/src/main/java/com/usatiuk/tjv/y/server/controller/PostController.java index 12e9920..a394e92 100644 --- a/server/src/main/java/com/usatiuk/tjv/y/server/controller/PostController.java +++ b/server/src/main/java/com/usatiuk/tjv/y/server/controller/PostController.java @@ -47,12 +47,12 @@ public class PostController { @GetMapping(path = "/by-author-username") public Stream readAllByAuthorUsername(@RequestParam Optional author) { if (author.isPresent()) - return postService.readByAuthorId(author.get()).stream().map(PostMapper::makeDto); + return postService.readByAuthorUsername(author.get()).stream().map(PostMapper::makeDto); else throw new ResponseStatusException(HttpStatus.BAD_REQUEST); } - @GetMapping(path = "/following") + @GetMapping(path = "/by-following") public Stream readAllByFollowees(Principal principal) { return postService.readByPersonFollowees(principal.getName()).stream().map(PostMapper::makeDto); }