Build the Favorites Page
Build the Favorites Page
Add a favorites-only filter
Open lib/contacts.ts. Add favoritesOnly to ContactQuery, and one more
condition to getContacts:
export type ContactQuery = {
q?: string;
page?: number;
favoritesOnly?: boolean;
};
Inside getContacts, alongside the existing if (opts.q) block:
if (opts.favoritesOnly) {
conditions.push(`c.favorite = TRUE`);
}
Since conditions is just an array joined with AND, this combines
cleanly with search and pagination — you can search within favorites,
and page through the results, for free.
Build the page
Replace the placeholder in app/favorites/page.tsx:
import { getContacts, PAGE_SIZE } from "@/lib/contacts";
import ContactList from "@/components/ContactList";
import SearchBar from "@/components/SearchBar";
import Pagination from "@/components/Pagination";
export const dynamic = "force-dynamic";
export default async function FavoritesPage({
searchParams,
}: {
searchParams: { q?: string; page?: string };
}) {
const q = searchParams.q || "";
const page = Number(searchParams.page) || 1;
const { contacts, total } = await getContacts({ q, page, favoritesOnly: true });
return (
<>
<div className="page-heading">
<h1>Favorites</h1>
<div className="meta">{total} {total === 1 ? "contact" : "contacts"}</div>
</div>
<SearchBar action="/favorites" defaultValue={q} />
<ContactList
contacts={contacts}
emptyTitle={q ? "No matches" : "No favorites yet"}
emptyBody={q ? `No favorites match "${q}".` : "Star a contact to pin them here."}
/>
<Pagination page={page} total={total} pageSize={PAGE_SIZE} basePath="/favorites" query={q} />
</>
);
}
This is nearly identical to app/page.tsx — same components, same
props — with two differences: favoritesOnly: true passed into
getContacts, and basePath/action pointing at /favorites instead of
/, so search and pagination links stay on this page.
Test it
Star a couple of contacts from their detail pages if you haven’t already,
then click “Favorites” in the nav. You should see only your starred
contacts, with search and pagination both still working, scoped to just
that filtered set.
Checkpoint
The Favorites page shows only favorited contacts, with its own working
search and pagination.