Skip to content

Commit

Permalink
feature: Enhance post page.
Browse files Browse the repository at this point in the history
- Add new translations
- Implement comments with all functionalities,
- Create base functionality for reactions
- Create share button

Refs: CU-8697jhjf
Signed-off-by: Patryk Kłosiński <[email protected]>
  • Loading branch information
JimTheCat committed Jan 22, 2025
1 parent aff9898 commit 3a3d7e3
Show file tree
Hide file tree
Showing 28 changed files with 1,072 additions and 145 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,6 @@ export const CardProfileTop = (props: { userDetails: ProfileUser | null }) => {
);
}

const {login, name, surname, profilePicture, createdAt, friends} = props.userDetails;

return (
<Card shadow="sm" padding="lg" radius="md" w={"fit-content"} withBorder>
Expand All @@ -115,7 +114,7 @@ export const CardProfileTop = (props: { userDetails: ProfileUser | null }) => {
>
<AspectRatio ratio={1}>
<Avatar
src={profilePicture}
src={props.userDetails.profilePictureUrl}
w={"auto"}
size={100}
color="dark"
Expand Down Expand Up @@ -149,10 +148,10 @@ export const CardProfileTop = (props: { userDetails: ProfileUser | null }) => {
<Stack justify="flex-end" gap={0} mt={"lg"}>
<Group justify={"center"} gap={"xs"} align={"baseline"}>
<Text size={"xl"}>
{name} {surname}
{props.userDetails.name} {props.userDetails.surname}
</Text>
</Group>
<Text size={"md"} c="dimmed">@{login}</Text>
<Text size={"md"} c="dimmed">@{props.userDetails.login}</Text>
</Stack>
</Group>
{!isProfileOfLoggedUser &&
Expand All @@ -163,8 +162,8 @@ export const CardProfileTop = (props: { userDetails: ProfileUser | null }) => {
</Group>

<Stack justify={"flex-start"} gap={0} mt={'md'}>
<Text>{t('profileTop.joined', {date: new Date(createdAt).toLocaleDateString()})}</Text>
<Text>{t('profileTop.friends', {length: friends.length})}</Text>
<Text>{t('profileTop.joined', {date: new Date(props.userDetails.createdAt).toLocaleDateString()})}</Text>
<Text>{t('profileTop.friends', {length: props.userDetails.friends.length})}</Text>
</Stack>
</Box>
</Card>
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/Features/Root/Root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {MatchTests} from "../Matching/components/Tests";
import {MatchSettings} from "../Matching/components/Settings";
import {Multimedia} from "../Multimedia";
import {Privacy} from "../Privacy";
import {SharedPost} from "../SharedPost";

export const Root = () => {

Expand All @@ -44,6 +45,7 @@ export const Root = () => {
<Route path="/search" element={<Search/>}/>
<Route path="/profile/:userTag" element={<Profile/>}/>
<Route path="/profile/:userTag/multimedia" element={<Multimedia/>}/>
<Route path="/post/:postId" element={<SharedPost/>}/>
<Route path="/relations" element={<Relations/>}/>
<Route path="/groups" element={<Groups/>}/>
<Route path="/friends" element={<Friends/>}/>
Expand Down
36 changes: 36 additions & 0 deletions frontend/src/Features/SharedPost/SharedPost.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import {Center, Loader} from "@mantine/core";
import {useEffect, useState} from "react";
import {useParams} from "react-router-dom";
import {PostDTO} from "../shared/types";
import {Post} from "../shared/components/Cards/Post";
import api from "../shared/services/api.ts";

export const SharedPost = () => {
const [post, setPost] = useState<PostDTO | null>(null);
const [isPostLoading, setIsPostLoading] = useState(true);
const {postId} = useParams()

useEffect(() => {
api.get(`/api/posts/${postId}`).then(r => {
if (r.status === 200) {
setPost(r.data);
setIsPostLoading(false);
}
});
}, []);

return (
<Center h={'100vh'}>
{isPostLoading && <Loader size="xl"/>}
{post &&
<Post
id={post.id}
content={post.content}
createdAt={post.createdAt}
numberOfComments={post.numberOfComments}
author={post.author}
/>
}
</Center>
);
}
1 change: 1 addition & 0 deletions frontend/src/Features/SharedPost/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export {SharedPost} from './SharedPost';
145 changes: 145 additions & 0 deletions frontend/src/Features/shared/components/Cards/Post/DetailedPost.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
import {Avatar, Badge, Button, Divider, Group, Stack, Text, Textarea} from "@mantine/core";
import {PostDTO} from "../../../types";
import {TFunction} from "i18next";
import {useEffect, useState} from "react";
import {CommentDTO} from "./types";
import api from "../../../services/api.ts";
import {CommentsSection} from "./components/CommentsSection";
import {useAlert} from "../../../../../Providers/AlertProvider.tsx";
import {IconMessage} from "@tabler/icons-react";
import {DateFormatter, RenderPhotos} from "../../../utils";
import {InnerHtmlHandler} from "../../InnerHtmlHandler";
import {MenuPost} from "./components/MenuPost";
import {useAuthStore} from "../../../services/authStore.ts";
import {ReactionButton} from "./components/ReactionButton";
import {ShareButton} from "./components/ShareButton";

type PostProps = PostDTO & {
t: TFunction<string, undefined>
modal: string
}

export const DetailedPost = (props: PostProps) => {
const auth = useAuthStore();
const isOwner = auth.user?.login === props.author.login;
const [comments, setComments] = useState<CommentDTO[]>([]);
const [commentValue, setCommentValue] = useState("");
const alert = useAlert();

const handleCommentEdit = (id: string, content: string) => {
const updatedComments = comments.map((comment) =>
comment.id === id ? {...comment, content} : comment
);
setComments(updatedComments);
};

const handleCommentDelete = (id: string) => {
setComments(comments.filter((comment) => comment.id !== id));
};

const handleSentComment = async () => {
if (commentValue.length > 0) {
try {
const response = await api.post(`/api/comments`, null, {
params: {
postId: props.id,
content: commentValue,
},
});
if (response.status === 200) {
alert.showError({
title: props.t("detailedPost.alert.title"),
message: props.t("detailedPost.alert.message"),
level: "INFO",
timestamp: new Date().toISOString(),
});

setComments([...comments, response.data.content]);
setCommentValue("");
}
} catch (error) {
console.error("Failed to send comment", error);
}
}
};

useEffect(() => {
const fetchComments = async () => {
try {
const response = await api.get(`/api/comments/post/${props.id}`);
if (response.status === 200) {
setComments(response.data.content);
}
} catch (error) {
console.error("Failed to fetch comments", error);
}
};

fetchComments().then(r => r);
}, []);

return (
<Stack>
<Group justify="space-between">
<Group style={{cursor: "pointer"}}>
<Avatar src={props.author.profilePictureUrl} size={"lg"} radius={180}/>
<Stack gap={0}>
<Text>{props.author.name} {props.author.surname}</Text>
<Text c="dimmed">{DateFormatter(props.createdAt)}</Text>
</Stack>
</Group>
{isOwner &&
<MenuPost postId={props.id} content={props.content}/>
}
</Group>

<InnerHtmlHandler innerHtml={props.content}/>

{/*// Show photos if they exist*/}
{props.pictures && props.pictures.length > 0 && (
<RenderPhotos pictures={props.pictures}/>
)}

<Divider my={"xs"}/>

<Group grow preventGrowOverflow={false}>
<ReactionButton onReact={console.log}>
{props.t('buttons.reaction.label')}
</ReactionButton>
<Button
variant={"subtle"}
color={"gray"}
leftSection={<IconMessage stroke={1.5}/>}
rightSection={<Badge color={"gray"} circle>{props.numberOfComments}</Badge>}
>
{props.t('buttons.comment.label')}
</Button>
<ShareButton postId={props.id}>
{props.t('buttons.share.label')}
</ShareButton>
</Group>

<Divider my={"xs"}/>

<Textarea
radius="md"
label={props.t('detailedPost.textArea.label')}
placeholder={props.t('detailedPost.textArea.placeholder')}
value={commentValue}
onChange={(e) => setCommentValue(e.currentTarget.value)}
/>
<Group justify={"flex-end"}>
<Button variant="outline" color="blue" onClick={handleSentComment}>
{props.t('detailedPost.textArea.children')}
</Button>
</Group>
<Divider my={"xs"}/>
<CommentsSection
comments={comments}
onCommentDelete={handleCommentDelete}
onCommentEdit={handleCommentEdit}
modal={props.modal}
/>
</Stack>
);
};
Loading

0 comments on commit 3a3d7e3

Please sign in to comment.