feat: added post navigation buttons 9a2101c9
Steve · 2025-11-06 22:13 1 file(s) · +57 −1
src/components/dashboard.tsx +57 −1
15 15
	SidebarTrigger,
16 16
} from "@/components/ui/sidebar";
17 17
import { Button } from "@/components/ui/button";
18 -
import { Circle, CircleCheckBig } from "lucide-react";
18 +
import { Circle, CircleCheckBig, ChevronUp, ChevronDown } from "lucide-react";
19 19
import { useQuery } from "@evolu/react";
20 20
import {
21 21
	allFeedsQuery,
74 74
		if (!selectedPost?.feedId) return null;
75 75
		return allFeeds.find((f) => f.id === selectedPost.feedId);
76 76
	}, [selectedPost?.feedId, allFeeds]);
77 +
78 +
	// Get sorted posts for navigation
79 +
	const sortedPosts = React.useMemo(() => {
80 +
		return [...allPosts].sort((a, b) => {
81 +
			if (!a.publishedDate) return 1;
82 +
			if (!b.publishedDate) return -1;
83 +
			return b.publishedDate.localeCompare(a.publishedDate);
84 +
		});
85 +
	}, [allPosts]);
86 +
87 +
	// Get current post index and navigation info
88 +
	const currentPostIndex = React.useMemo(() => {
89 +
		if (!selectedPostId) return -1;
90 +
		return sortedPosts.findIndex((p) => p.id === selectedPostId);
91 +
	}, [selectedPostId, sortedPosts]);
92 +
93 +
	const hasPreviousPost = currentPostIndex > 0;
94 +
	const hasNextPost =
95 +
		currentPostIndex >= 0 && currentPostIndex < sortedPosts.length - 1;
96 +
97 +
	// Navigation handlers
98 +
	const goToPreviousPost = React.useCallback(() => {
99 +
		if (hasPreviousPost) {
100 +
			setSelectedPostId(sortedPosts[currentPostIndex - 1].id);
101 +
		}
102 +
	}, [hasPreviousPost, sortedPosts, currentPostIndex]);
103 +
104 +
	const goToNextPost = React.useCallback(() => {
105 +
		if (hasNextPost) {
106 +
			setSelectedPostId(sortedPosts[currentPostIndex + 1].id);
107 +
		}
108 +
	}, [hasNextPost, sortedPosts, currentPostIndex]);
77 109
78 110
	// Check if current post is read
79 111
	const isCurrentPostRead = React.useMemo(() => {
192 224
								)}
193 225
							</BreadcrumbList>
194 226
						</Breadcrumb>
227 +
						{selectedPost && (
228 +
							<div className="ml-auto flex items-center gap-1">
229 +
								<Button
230 +
									variant="ghost"
231 +
									size="icon"
232 +
									onClick={goToPreviousPost}
233 +
									disabled={!hasPreviousPost}
234 +
									className="h-8 w-8"
235 +
									title="Previous post"
236 +
								>
237 +
									<ChevronUp className="h-4 w-4" />
238 +
								</Button>
239 +
								<Button
240 +
									variant="ghost"
241 +
									size="icon"
242 +
									onClick={goToNextPost}
243 +
									disabled={!hasNextPost}
244 +
									className="h-8 w-8"
245 +
									title="Next post"
246 +
								>
247 +
									<ChevronDown className="h-4 w-4" />
248 +
								</Button>
249 +
							</div>
250 +
						)}
195 251
					</header>
196 252
					<div
197 253
						ref={mainContentRef}