Skip to content

Commit

Permalink
feat: implement post detail view and enhance recommendations display
Browse files Browse the repository at this point in the history
  • Loading branch information
deepraj21 committed Oct 31, 2024
1 parent c3ab85e commit 3113c4b
Show file tree
Hide file tree
Showing 12 changed files with 305 additions and 96 deletions.
2 changes: 2 additions & 0 deletions client/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import ProjectDisplay from './pages/ProjectDisplay';
import TermsAndConditions from './pages/TermsAndConditions';
import Feed from './pages/Feed';
import UserPosts from './pages/UserPosts';
import ShowPostByID from './components/Posts/ShowPostByID';

const App = () => {

Expand All @@ -32,6 +33,7 @@ const App = () => {
<Route path="/relations/:username" element={<Visualization />} />
<Route path="/feed" element={<Feed />} />
<Route path="/posts/:username" element={<UserPosts />} />
<Route path="/post/:postId" element={<ShowPostByID />} />
<Route path="/privacy-policy" element={<PrivacyPolicy/>} />
<Route path="/terms-and-conditions" element={<TermsAndConditions/>}/>
<Route path="*" element={<div>404</div>} />
Expand Down
7 changes: 6 additions & 1 deletion client/src/components/Chat/Chat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -166,12 +166,17 @@ export const Chat: React.FC = () => {
</div>
</div>
</main>
<div className="p-4">
<div className="pt-4 pr-4 pl-4 pb-1">
<PlaceholdersAndVanishInput
placeholders={placeholders}
onSubmit={onSubmit}
/>
</div>
<div className='text-[10px] items-center flex justify-center mb-1'>
<span>
<a href="/terms-and-conditions">T&C</a> | *Response may not be accurate everytime
</span>
</div>
</>
)
}
152 changes: 152 additions & 0 deletions client/src/components/Posts/ShowPostByID.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
import { useEffect, useState } from 'react'
import axios from 'axios'
import { Button } from "@/components/ui/button"
import { ChevronUp, ChevronDown, MessageCircle } from "lucide-react"
import {
AlertDialog,
AlertDialogCancel,
AlertDialogContent,
AlertDialogHeader,
AlertDialogTrigger,
} from "@/components/ui/alert-dialog"
import { Cross1Icon } from "@radix-ui/react-icons";
import { useParams } from 'react-router-dom';

const backendUrl = import.meta.env.VITE_BACKEND_URL || 'http://localhost:5000'

interface Post {
_id: string
author_username: string
author_profileImage: string
description: string
tags: string
image_link?: string
upvotes: number
downvotes: number
created_at: string
comments: Comment[]
}

interface Comment {
_id: string
post_id: string
user_username: string
text: string
created_at: string
}

const ShowPostByID = () => {
const { postId } = useParams<{ postId: string }>();
const [post, setPost] = useState<Post | null>(null);

useEffect(() => {
const fetchPost = () => {
axios.get(`${backendUrl}/posts/${postId}`)
.then(response => {
setPost(response.data);
})
.catch(error => {
console.error('Error fetching post:', error);
});
};
fetchPost();
}, [postId]);

if (!post) {
return <div>Loading...</div>;
}
return (
<div className="max-w-2xl mx-auto space-y-0 md:space-y-8">
<div key={post._id} className="bg-background shadow-lg md:rounded-lg overflow-hidden border">
<div className="flex items-center border-b p-4">
<div className="h-10 w-10 rounded-full overflow-hidden">
<img src={post.author_profileImage} alt={post.author_username} />
</div>
<div className="ml-3">
<p className="text-sm font-medium">{post.author_username}</p>
<p className="text-xs text-muted-foreground">
Posted {new Date(post.created_at).toLocaleDateString()}
</p>
</div>
</div>
{post.image_link && (
<img
src={post.image_link}
alt="Post image"
className="w-full h-96 object-cover mb-1 border-b"
/>
)}
<div className="flex items-center gap-4 ml-1">
<Button
variant="ghost"
size="sm"
className="flex items-center gap-1"
>
<ChevronUp className="h-5 w-5" />
<span>{post.upvotes}</span>
</Button>
<Button
variant="ghost"
size="sm"
className="flex items-center gap-1"
>
<ChevronDown className="h-5 w-5" />
<span>{post.downvotes}</span>
</Button>
<AlertDialog>
<AlertDialogTrigger asChild>
<Button variant="ghost" size="sm" className="flex items-center gap-1">
<MessageCircle className="h-5 w-5" />
<span>{post.comments ? post.comments.length : 0}</span>
</Button>
</AlertDialogTrigger>

<AlertDialogContent className="grid gap-6 sm:w-80">
<AlertDialogHeader>
<div className='flex items-center'>
<AlertDialogHeader className='text-2xl'>Comments</AlertDialogHeader>
<div className='flex-grow'></div>
<AlertDialogCancel>
<Cross1Icon className='h-3 w-3' />
</AlertDialogCancel>
</div>
</AlertDialogHeader>

{/* Set max height and make it scrollable if needed */}
<div className="max-h-56 overflow-y-auto">
{/* Reverse the comments to display the latest on top */}
{post.comments && post.comments.slice().reverse().map((comment: Comment) => (
<div key={comment._id} className="flex items-start gap-2 mb-4">
<div className="h-8 w-8">
<img src="/placeholder.svg?height=32&width=32" alt={comment.user_username} />
</div>
<div>
<p className="text-sm font-medium">{comment.user_username}</p>
<p className="text-sm">{comment.text}</p>
</div>
</div>
))}
</div>
</AlertDialogContent>
</AlertDialog>
</div>
<div className='p-4'>
<p className="text-sm mb-2">{post.description}</p>
<div className="flex flex-wrap gap-2 mb-2">
{JSON.parse(post.tags).map((tag: string, index: number) => (
<span
key={index}
className="bg-primary/10 text-primary text-xs px-2 py-1 rounded-full"
>
#{tag}
</span>
))}
</div>

</div>
</div>
</div>
)
}

export default ShowPostByID
4 changes: 3 additions & 1 deletion client/src/components/Posts/ShowUserPosts.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,15 @@ const ShowUserPosts = () => {
</p>
</div>
</div>
{post.image_link && (
<a href={`/post/${post._id}`}>
{post.image_link && (
<img
src={post.image_link}
alt="Post image"
className="w-full h-96 object-cover mb-1 border-b"
/>
)}
</a>
<div className="flex items-center gap-4 ml-1">
<Button
variant="ghost"
Expand Down
42 changes: 0 additions & 42 deletions client/src/components/Recomendations/RecomendationSidebar.tsx

This file was deleted.

20 changes: 16 additions & 4 deletions client/src/components/Recomendations/Recomendations.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React, { useEffect, useState } from 'react';
import axios from 'axios';
import Marquee from "@/components/ui/marquee";

const backendUrl = import.meta.env.VITE_BACKEND_URL || 'http://localhost:5000';

Expand Down Expand Up @@ -37,10 +38,21 @@ const Recomendations: React.FC = () => {
{loading && <p>Loading...</p>}
{error && <p>{error}</p>}
{suggestions.length > 0 && (
<ul>
{suggestions.map((suggestion, index) => (
<li key={index}>{suggestion}</li>
))}
<ul className='flex items-center justify-center'>
<Marquee pauseOnHover vertical className="[--duration:20s]">
{suggestions.map((suggestion, index) => (
<div className="flex items-center border border-gray-300 rounded-lg">
<div className="p-4 flex items-center space-x-4">
<div className="h-6 w-6 rounded-full bg-gradient-to-r from-pink-500 to-violet-500 flex-shrink-0" />
<a href={`/user/${suggestion}`}>
<li key={index} className="list-none">@{suggestion}</li>
</a>

</div>
</div>
))}
</Marquee>

</ul>
)}
{suggestions.length === 0 && !loading && <p>No suggestions available.</p>}
Expand Down
51 changes: 51 additions & 0 deletions client/src/components/ui/marquee.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { cn } from "@/lib/utils";

interface MarqueeProps {
className?: string;
reverse?: boolean;
pauseOnHover?: boolean;
children?: React.ReactNode;
vertical?: boolean;
repeat?: number;
[key: string]: any;
}

export default function Marquee({
className,
reverse,
pauseOnHover = false,
children,
vertical = false,
repeat = 4,
...props
}: MarqueeProps) {
return (
<div
{...props}
className={cn(
"group flex overflow-hidden p-2 [--duration:40s] [--gap:1rem] [gap:var(--gap)]",
{
"flex-row": !vertical,
"flex-col": vertical,
},
className,
)}
>
{Array(repeat)
.fill(0)
.map((_, i) => (
<div
key={i}
className={cn("flex shrink-0 justify-around [gap:var(--gap)]", {
"animate-marquee flex-row": !vertical,
"animate-marquee-vertical flex-col": vertical,
"group-hover:[animation-play-state:paused]": pauseOnHover,
"[animation-direction:reverse]": reverse,
})}
>
{children}
</div>
))}
</div>
);
}
Loading

0 comments on commit 3113c4b

Please sign in to comment.