Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 18 additions & 14 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"lucide-react": "^0.552.0",
"react": "^19.1.1",
"react-dom": "^19.1.1",
"react-router-dom": "^7.9.5",
"react-router-dom": "^7.11.0",
"tailwindcss": "^4.1.16"
},
"devDependencies": {
Expand Down
25 changes: 23 additions & 2 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Routes, Route } from 'react-router'
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom'
import Home from './pages/Home.tsx'
import CreatePostPage from './pages/CreatePostPage.tsx'
import Navbar from './components/Navbar.tsx'
Expand All @@ -8,6 +8,7 @@ import CreateCommunityPage from './pages/CreateCommunityPage.tsx'
import {CommunityPage} from './pages/CommunityPage.tsx'
import { CommunitiesPage } from './pages/CommunitiesPage.tsx'
import MessagesPage from './pages/MessagesPage.tsx'
import NotFound from './components/NotFound.tsx' // Import the 404 page
import EventsPage from './pages/EventsPage.tsx'
import EventDetailPage from './pages/EventDetailPage.tsx'
import CreateEventPage from './pages/CreateEventPage.tsx'
Expand All @@ -21,6 +22,26 @@ import ProfilePage from './pages/ProfilePage.tsx'

function App() {
return (
<>
<div>
<Router> {/* Wrap everything with Router */}
<Navbar />
<div>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/create" element={<CreatePostPage />} />
<Route path="/post/:id" element={<PostPage />} />
<Route path="/communities/create" element={<CreateCommunityPage />} />
<Route path="/communities" element={<CommunitiesPage />} />
<Route path="/communities/:id" element={<CommunityPage />} />
<Route path="/messages" element={<MessagesPage />} />
{/* Add 404 route at the end - catches all undefined routes */}
<Route path="*" element={<NotFound />} />
</Routes>
</div>
</Router>
</div>
</>
<div className="min-h-screen flex flex-col bg-[var(--bg-primary)] text-[var(--text-primary)] transition-colors">
<Navbar />
<main className="flex-1">
Expand Down Expand Up @@ -54,4 +75,4 @@ function App() {
)
}

export default App
export default App
23 changes: 20 additions & 3 deletions src/components/CommunityDisplay.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useQuery } from "@tanstack/react-query";
import PostItem from "./PostItem";
import PostSkeleton from "./PostSkeleton"; // Import the skeleton component
import { fetchCommunityPost } from "../utils/communityApi";

interface Props {
Expand Down Expand Up @@ -27,8 +28,25 @@ const CommunityDisplay = ({ communityId }: Props) => {
queryFn: () => fetchCommunityPost(communityId),
});

if (isLoading)
return <div className="text-center py-4">Loading posts...</div>;
// Skeleton loading state
if (isLoading) {
return (
<div>
{/* Skeleton header */}
<div className="mb-10 text-center justify-center animate-pulse">
<div className="h-10 bg-cyan-900/30 rounded w-48 mx-auto mb-2"></div>
<div className="h-4 bg-slate-700/30 rounded w-40 mx-auto"></div>
</div>

{/* Skeleton posts */}
<div className="mx-auto flex flex-col gap-6">
{[...Array(3)].map((_, index) => (
<PostSkeleton key={`skeleton-${index}`} />
))}
</div>
</div>
);
}

if (error)
return (
Expand All @@ -52,7 +70,6 @@ const CommunityDisplay = ({ communityId }: Props) => {
</div>

{data && data.length > 0 ? (

<div className="mx-auto flex flex-col gap-6">
{data.map((post) => (
<PostItem key={post.id} post={post} />
Expand Down
72 changes: 72 additions & 0 deletions src/components/NotFound.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import React from 'react';
import { Link } from 'react-router-dom';

const NotFound = () => {
const styles = {
container: {
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
minHeight: '100vh',
backgroundColor: '#f5f5f5',
padding: '20px',
fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif'
} as React.CSSProperties,
content: {
textAlign: 'center' as const,
backgroundColor: 'white',
padding: '40px',
borderRadius: '12px',
boxShadow: '0 4px 20px rgba(0, 0, 0, 0.1)',
maxWidth: '500px',
width: '100%'
} as React.CSSProperties,
title: {
fontSize: '6rem',
fontWeight: 700,
color: '#dc3545',
margin: 0,
lineHeight: 1
} as React.CSSProperties,
subtitle: {
fontSize: '2rem',
fontWeight: 600,
color: '#333',
margin: '20px 0 10px'
} as React.CSSProperties,
message: {
fontSize: '1.1rem',
color: '#666',
marginBottom: '30px',
lineHeight: '1.5'
} as React.CSSProperties,
button: {
display: 'inline-block',
backgroundColor: '#007bff',
color: 'white',
padding: '12px 30px',
borderRadius: '6px',
textDecoration: 'none',
fontWeight: 500,
fontSize: '1rem',
transition: 'background-color 0.3s ease'
} as React.CSSProperties
};

return (
<div style={styles.container}>
<div style={styles.content}>
<h1 style={styles.title}>404</h1>
<h2 style={styles.subtitle}>Page Not Found</h2>
<p style={styles.message}>
Oops! The page you're looking for doesn't exist or has been moved.
</p>
<Link to="/" style={styles.button}>
Return to Feed
</Link>
</div>
</div>
);
};

export default NotFound;
44 changes: 44 additions & 0 deletions src/components/PostSkeleton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// src/components/PostSkeleton.tsx
import React from 'react';

const PostSkeleton: React.FC = () => {
return (
<div className="bg-gradient-to-br from-slate-900 to-slate-800 border border-cyan-900/30 rounded-lg p-6 animate-pulse">
{/* Header with user info */}
<div className="flex items-center mb-4">
<div className="w-10 h-10 bg-cyan-900/40 rounded-full"></div>
<div className="ml-3 flex-1">
<div className="h-4 bg-cyan-800/40 rounded w-1/4 mb-2"></div>
<div className="h-3 bg-slate-700/40 rounded w-1/6"></div>
</div>
</div>

{/* Post title */}
<div className="h-6 bg-cyan-800/30 rounded w-3/4 mb-3"></div>

{/* Post content lines */}
<div className="space-y-2 mb-4">
<div className="h-4 bg-slate-700/30 rounded w-full"></div>
<div className="h-4 bg-slate-700/30 rounded w-5/6"></div>
<div className="h-4 bg-slate-700/30 rounded w-4/6"></div>
</div>

{/* Tags */}
<div className="flex gap-2 mb-4">
<div className="h-6 bg-cyan-900/30 rounded w-16"></div>
<div className="h-6 bg-cyan-900/30 rounded w-20"></div>
</div>

{/* Action buttons */}
<div className="flex justify-between items-center pt-4 border-t border-cyan-900/20">
<div className="flex gap-4">
<div className="h-8 w-20 bg-cyan-900/30 rounded"></div>
<div className="h-8 w-20 bg-cyan-900/30 rounded"></div>
</div>
<div className="h-6 w-24 bg-slate-700/30 rounded"></div>
</div>
</div>
);
};

export default PostSkeleton;