From ab1989d308e207f9f65920ce96f0c0d86fe513a7 Mon Sep 17 00:00:00 2001 From: Elliott Minns Date: Fri, 27 Jun 2025 16:27:52 -0500 Subject: [PATCH] feat: highlight creator messages --- README.md | 4 ++++ src/actions/guestbook.ts | 25 +++++++++++++++++++-- src/app/page.tsx | 35 +++++++++++++++++------------- src/app/user/[username]/page.tsx | 19 ++++++++++------ src/components/guestbook-entry.tsx | 11 +++++++--- 5 files changed, 67 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index e215bc4..0a03b53 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,10 @@ You can start editing the page by modifying `app/page.tsx`. The page auto-update This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel. +### Environment Variables + +Set `CREATOR_USERNAME` to the username that should receive the special highlight in the guestbook. + ## Learn More To learn more about Next.js, take a look at the following resources: diff --git a/src/actions/guestbook.ts b/src/actions/guestbook.ts index 404f992..e74f896 100644 --- a/src/actions/guestbook.ts +++ b/src/actions/guestbook.ts @@ -10,6 +10,8 @@ import { revalidatePath } from 'next/cache'; export async function getGuestbookEntries(page = 1, limit = 50) { const offset = (page - 1) * limit; + + const creatorUsername = process.env.CREATOR_USERNAME?.toLowerCase(); // Get ALL entries (both main messages and replies) in chronological order const entries = await db @@ -29,6 +31,7 @@ export async function getGuestbookEntries(page = 1, limit = 50) { .limit(limit) .offset(offset); + // For replies, we need to get the original message info const entriesWithReplyInfo = await Promise.all( entries.map(async (entry) => { @@ -57,13 +60,21 @@ export async function getGuestbookEntries(page = 1, limit = 50) { }) ); + const entriesWithCreator = entriesWithReplyInfo.map(entry => { + const entryUsername = (entry.displayUsername || entry.username || entry.name)?.toLowerCase(); + return { + ...entry, + isCreator: !!creatorUsername && entryUsername === creatorUsername, + }; + }); + // Get total count for pagination (all entries) const totalCount = await db .select({ count: sql`count(*)` }) .from(guestbook); return { - entries: entriesWithReplyInfo, + entries: entriesWithCreator, pagination: { page, limit, @@ -77,6 +88,8 @@ export async function getGuestbookEntries(page = 1, limit = 50) { export async function getUserPosts(userId: string, page = 1, limit = 50) { const offset = (page - 1) * limit; + + const creatorUsername = process.env.CREATOR_USERNAME?.toLowerCase(); const entries = await db .select({ @@ -95,6 +108,14 @@ export async function getUserPosts(userId: string, page = 1, limit = 50) { .limit(limit) .offset(offset); + const entriesWithCreator = entries.map(entry => { + const entryUsername = (entry.displayUsername || entry.username || entry.name)?.toLowerCase(); + return { + ...entry, + isCreator: !!creatorUsername && entryUsername === creatorUsername, + }; + }); + // Get total count for this user const totalCount = await db .select({ count: sql`count(*)` }) @@ -102,7 +123,7 @@ export async function getUserPosts(userId: string, page = 1, limit = 50) { .where(eq(guestbook.userId, userId)); return { - entries, + entries: entriesWithCreator, pagination: { page, limit, diff --git a/src/app/page.tsx b/src/app/page.tsx index eced001..f261d0b 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -24,6 +24,7 @@ interface GuestbookEntryType { replyToId: string | null; replyToMessage?: string; replyToUsername?: string | null; + isCreator: boolean; } interface PaginationInfo { @@ -353,23 +354,27 @@ export default function Home() {
- +
+ +
))} diff --git a/src/app/user/[username]/page.tsx b/src/app/user/[username]/page.tsx index 1cf5974..2b627a7 100644 --- a/src/app/user/[username]/page.tsx +++ b/src/app/user/[username]/page.tsx @@ -19,6 +19,7 @@ interface GuestbookEntryType { displayUsername: string | null; name: string | null; userId: string; + isCreator: boolean; } interface PaginationInfo { @@ -211,15 +212,19 @@ export default function UserPage() { {entries.map((entry, index) => (
- +
+ +
))} diff --git a/src/components/guestbook-entry.tsx b/src/components/guestbook-entry.tsx index 9946f44..2c6d73c 100644 --- a/src/components/guestbook-entry.tsx +++ b/src/components/guestbook-entry.tsx @@ -3,7 +3,7 @@ import { useState } from 'react'; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from '@/components/ui/dropdown-menu'; import { Button } from '@/components/ui/button'; -import { Eye, EyeOff, Reply, Send, X, Quote } from 'lucide-react'; +import { Eye, EyeOff, Reply, Send, X, Quote, Sparkles } from 'lucide-react'; interface GuestbookEntryProps { id: string; @@ -18,6 +18,7 @@ interface GuestbookEntryProps { replyToMessage?: string; replyToMessageId?: string; onScrollToMessage?: (messageId: string) => void; + isCreator?: boolean; } export function GuestbookEntry({ @@ -32,7 +33,8 @@ export function GuestbookEntry({ replyToUsername, replyToMessage, replyToMessageId, - onScrollToMessage + onScrollToMessage, + isCreator = false }: GuestbookEntryProps) { const [showReplyForm, setShowReplyForm] = useState(false); const [replyText, setReplyText] = useState(''); @@ -79,8 +81,11 @@ export function GuestbookEntry({ {username ? ( -