Index: nextjs-dashboard/app/dashboard/(overview)/loading.tsx
===================================================================
--- nextjs-dashboard/app/dashboard/(overview)/loading.tsx	(revision 1428dc1e1cd66f235e8a718bf6d0868418d5e5cc)
+++ nextjs-dashboard/app/dashboard/(overview)/loading.tsx	(revision 1428dc1e1cd66f235e8a718bf6d0868418d5e5cc)
@@ -0,0 +1,5 @@
+import DashboardSkeleton from "@/app/ui/skeletons";
+
+export default function Loading() {
+    return <DashboardSkeleton />;
+}
Index: nextjs-dashboard/app/dashboard/(overview)/page.tsx
===================================================================
--- nextjs-dashboard/app/dashboard/(overview)/page.tsx	(revision 1428dc1e1cd66f235e8a718bf6d0868418d5e5cc)
+++ nextjs-dashboard/app/dashboard/(overview)/page.tsx	(revision 1428dc1e1cd66f235e8a718bf6d0868418d5e5cc)
@@ -0,0 +1,33 @@
+import CardWrapper from '@/app/ui/dashboard/cards';
+import RevenueChart from '@/app/ui/dashboard/revenue-chart';
+import LatestInvoices from '@/app/ui/dashboard/latest-invoices';
+import { lusitana } from '@/app/ui/fonts';
+import { Suspense } from 'react';
+import {
+    CardsSkeleton,
+    LatestInvoicesSkeleton,
+    RevenueChartSkeleton
+} from '@/app/ui/skeletons';
+
+export default async function Page() {
+    return (
+        <main>
+            <h1 className={`${lusitana.className} mb-4 text-xl md:text-2xl`}>
+                Dashboard
+            </h1>
+            <div className="grid gap-6 sm:grid-cols-2 lg:grid-cols-4">
+                <Suspense fallback={<CardsSkeleton />}>
+                    <CardWrapper />
+                </Suspense>
+            </div>
+            <div className="mt-6 grid grid-cols-1 gap-6 md:grid-cols-4 lg:grid-cols-8">
+                <Suspense fallback={<RevenueChartSkeleton />}>
+                    <RevenueChart />
+                </Suspense>
+                <Suspense fallback={<LatestInvoicesSkeleton />}>
+                    <LatestInvoices />
+                </Suspense>
+            </div>
+        </main>
+    );
+}
Index: nextjs-dashboard/app/dashboard/invoices/page.tsx
===================================================================
--- nextjs-dashboard/app/dashboard/invoices/page.tsx	(revision ffbbf389e1d1d5cf4f5e4cb78738a2c45f41733e)
+++ nextjs-dashboard/app/dashboard/invoices/page.tsx	(revision 1428dc1e1cd66f235e8a718bf6d0868418d5e5cc)
@@ -1,3 +1,38 @@
-export default function Page() {
-    return <p>Invoices Page</p>;
+import Pagination from '@/app/ui/invoices/pagination';
+import Search from '@/app/ui/search';
+import Table from '@/app/ui/invoices/table';
+import { CreateInvoice } from '@/app/ui/invoices/buttons';
+import { lusitana } from '@/app/ui/fonts';
+import { InvoicesTableSkeleton } from '@/app/ui/skeletons';
+import { Suspense } from 'react';
+import { fetchInvoicesPages } from '@/app/lib/data';
+
+export default async function Page(props: {
+    searchParams?: Promise<{
+        query?: string;
+        page?: string;
+    }>;
+}) {
+    const searchParams = await props.searchParams;
+    const query = searchParams?.query || '';
+    const currentPage = Number(searchParams?.page) || 1;
+    const totalPages = await fetchInvoicesPages(query);
+
+    return (
+        <div className="w-full">
+            <div className="flex w-full items-center justify-between">
+                <h1 className={`${lusitana.className} text-2xl`}>Invoices</h1>
+            </div>
+            <div className="mt-4 flex items-center justify-between gap-2 md:mt-8">
+                <Search placeholder="Search invoices..." />
+                <CreateInvoice />
+            </div>
+            <Suspense key={query + currentPage} fallback={<InvoicesTableSkeleton />}>
+                <Table query={query} currentPage={currentPage} />
+            </Suspense>
+            <div className="mt-5 flex w-full justify-center">
+                <Pagination totalPages={totalPages} />
+            </div>
+        </div>
+    );
 }
Index: xtjs-dashboard/app/dashboard/page.tsx
===================================================================
--- nextjs-dashboard/app/dashboard/page.tsx	(revision ffbbf389e1d1d5cf4f5e4cb78738a2c45f41733e)
+++ 	(revision )
@@ -1,37 +1,0 @@
-import { Card } from '@/app/ui/dashboard/cards';
-import RevenueChart from '@/app/ui/dashboard/revenue-chart';
-import LatestInvoices from '@/app/ui/dashboard/latest-invoices';
-import { lusitana } from '@/app/ui/fonts';
-import {
-    fetchCardData,
-    fetchRevenue,
-    fetchLatestInvoices
-} from '@/app/lib/data';
-
-export default async function Page() {
-    const {
-        totalPaidInvoices,
-        totalPendingInvoices,
-        numberOfInvoices,
-        numberOfCustomers
-    } = await fetchCardData();
-    const revenue = await fetchRevenue();
-    const latestInvoices = await fetchLatestInvoices();
-    return (
-        <main>
-            <h1 className={`${lusitana.className} mb-4 text-xl md:text-2xl`}>
-                Dashboard
-            </h1>
-            <div className="grid gap-6 sm:grid-cols-2 lg:grid-cols-4">
-                <Card title="Collected" value={totalPaidInvoices} type="collected" />
-                <Card title="Pending" value={totalPendingInvoices} type="pending" />
-                <Card title="Total Invoices" value={numberOfInvoices} type="invoices" />
-                <Card title="Total Customers" value={numberOfCustomers} type="customers" />
-            </div>
-            <div className="mt-6 grid grid-cols-1 gap-6 md:grid-cols-4 lg:grid-cols-8">
-                <RevenueChart revenue={revenue} />
-                <LatestInvoices latestInvoices={latestInvoices} />
-            </div>
-        </main>
-    );
-}
Index: nextjs-dashboard/app/ui/dashboard/cards.tsx
===================================================================
--- nextjs-dashboard/app/ui/dashboard/cards.tsx	(revision ffbbf389e1d1d5cf4f5e4cb78738a2c45f41733e)
+++ nextjs-dashboard/app/ui/dashboard/cards.tsx	(revision 1428dc1e1cd66f235e8a718bf6d0868418d5e5cc)
@@ -6,4 +6,5 @@
 } from '@heroicons/react/24/outline';
 import { lusitana } from '@/app/ui/fonts';
+import { fetchCardData } from '@/app/lib/data';
 
 const iconMap = {
@@ -15,9 +16,14 @@
 
 export default async function CardWrapper() {
+  const {
+    totalPaidInvoices,
+    totalPendingInvoices,
+    numberOfInvoices,
+    numberOfCustomers
+  } = await fetchCardData();
   return (
     <>
-      {/* NOTE: Uncomment this code in Chapter 9 */}
 
-      {/* <Card title="Collected" value={totalPaidInvoices} type="collected" />
+      <Card title="Collected" value={totalPaidInvoices} type="collected" />
       <Card title="Pending" value={totalPendingInvoices} type="pending" />
       <Card title="Total Invoices" value={numberOfInvoices} type="invoices" />
@@ -26,5 +32,5 @@
         value={numberOfCustomers}
         type="customers"
-      /> */}
+      />
     </>
   );
Index: nextjs-dashboard/app/ui/dashboard/latest-invoices.tsx
===================================================================
--- nextjs-dashboard/app/ui/dashboard/latest-invoices.tsx	(revision ffbbf389e1d1d5cf4f5e4cb78738a2c45f41733e)
+++ nextjs-dashboard/app/ui/dashboard/latest-invoices.tsx	(revision 1428dc1e1cd66f235e8a718bf6d0868418d5e5cc)
@@ -4,9 +4,8 @@
 import { lusitana } from '@/app/ui/fonts';
 import { LatestInvoice } from '@/app/lib/definitions';
-export default async function LatestInvoices({
-  latestInvoices,
-}: {
-  latestInvoices: LatestInvoice[];
-}) {
+import { fetchLatestInvoices } from '@/app/lib/data';
+
+export default async function LatestInvoices() {
+  const latestInvoices = await fetchLatestInvoices();
   return (
     <div className="flex w-full flex-col md:col-span-4">
Index: nextjs-dashboard/app/ui/dashboard/revenue-chart.tsx
===================================================================
--- nextjs-dashboard/app/ui/dashboard/revenue-chart.tsx	(revision ffbbf389e1d1d5cf4f5e4cb78738a2c45f41733e)
+++ nextjs-dashboard/app/ui/dashboard/revenue-chart.tsx	(revision 1428dc1e1cd66f235e8a718bf6d0868418d5e5cc)
@@ -3,4 +3,5 @@
 import { lusitana } from '@/app/ui/fonts';
 import { Revenue } from '@/app/lib/definitions';
+import { fetchRevenue } from '@/app/lib/data';
 
 // This component is representational only.
@@ -10,9 +11,6 @@
 // https://airbnb.io/visx/
 
-export default async function RevenueChart({
-  revenue,
-}: {
-  revenue: Revenue[];
-}) {
+export default async function RevenueChart() {
+  const revenue = await fetchRevenue();
   const chartHeight = 350;
 
Index: nextjs-dashboard/app/ui/invoices/pagination.tsx
===================================================================
--- nextjs-dashboard/app/ui/invoices/pagination.tsx	(revision ffbbf389e1d1d5cf4f5e4cb78738a2c45f41733e)
+++ nextjs-dashboard/app/ui/invoices/pagination.tsx	(revision 1428dc1e1cd66f235e8a718bf6d0868418d5e5cc)
@@ -5,15 +5,22 @@
 import Link from 'next/link';
 import { generatePagination } from '@/app/lib/utils';
+import { usePathname, useSearchParams } from 'next/navigation';
 
 export default function Pagination({ totalPages }: { totalPages: number }) {
-  // NOTE: Uncomment this code in Chapter 10
+  const pathname = usePathname();
+  const searchParams = useSearchParams();
+  const currentPage = Number(searchParams.get('page')) || 1;
 
-  // const allPages = generatePagination(currentPage, totalPages);
+  const createPageURL = (pageNumber: number | string) => {
+    const params = new URLSearchParams(searchParams);
+    params.set('page', pageNumber.toString());
+    return `${pathname}?${params.toString()}`;
+  }
+
+  const allPages = generatePagination(currentPage, totalPages);
 
   return (
     <>
-      {/*  NOTE: Uncomment this code in Chapter 10 */}
-
-      {/* <div className="inline-flex">
+      <div className="inline-flex">
         <PaginationArrow
           direction="left"
@@ -48,5 +55,5 @@
           isDisabled={currentPage >= totalPages}
         />
-      </div> */}
+      </div>
     </>
   );
Index: nextjs-dashboard/app/ui/search.tsx
===================================================================
--- nextjs-dashboard/app/ui/search.tsx	(revision ffbbf389e1d1d5cf4f5e4cb78738a2c45f41733e)
+++ nextjs-dashboard/app/ui/search.tsx	(revision 1428dc1e1cd66f235e8a718bf6d0868418d5e5cc)
@@ -2,6 +2,23 @@
 
 import { MagnifyingGlassIcon } from '@heroicons/react/24/outline';
+import { useSearchParams, useRouter, usePathname } from 'next/navigation';
+import { useDebouncedCallback } from 'use-debounce';
 
 export default function Search({ placeholder }: { placeholder: string }) {
+  const searchParams = useSearchParams();
+  const pathname = usePathname();
+  const { replace } = useRouter();
+
+  const handleSearch = useDebouncedCallback((term) => {
+    const params = new URLSearchParams(searchParams);
+    params.set('page', '1');
+    if (term) {
+      params.set('query', term);
+    } else {
+      params.delete('query');
+    }
+    replace(`${pathname}?${params.toString()}`);
+  }, 300);
+
   return (
     <div className="relative flex flex-1 flex-shrink-0">
@@ -12,4 +29,8 @@
         className="peer block w-full rounded-md border border-gray-200 py-[9px] pl-10 text-sm outline-2 placeholder:text-gray-500"
         placeholder={placeholder}
+        onChange={(e) => {
+          handleSearch(e.target.value);
+        }}
+        defaultValue={searchParams.get('query')?.toString()}
       />
       <MagnifyingGlassIcon className="absolute left-3 top-1/2 h-[18px] w-[18px] -translate-y-1/2 text-gray-500 peer-focus:text-gray-900" />
