diff --git a/dashboard/15-final/app/dashboard/customers/page.tsx b/dashboard/15-final/app/dashboard/customers/page.tsx index 6752b37..531ecce 100644 --- a/dashboard/15-final/app/dashboard/customers/page.tsx +++ b/dashboard/15-final/app/dashboard/customers/page.tsx @@ -2,8 +2,8 @@ import CustomersTable from '@/app/ui/customers/table'; export default function Page() { return ( -
+
-
+ ); } diff --git a/dashboard/15-final/app/dashboard/invoices/page.tsx b/dashboard/15-final/app/dashboard/invoices/page.tsx index d46e3cd..aee73a3 100644 --- a/dashboard/15-final/app/dashboard/invoices/page.tsx +++ b/dashboard/15-final/app/dashboard/invoices/page.tsx @@ -9,8 +9,8 @@ export default function Page({ }; }) { return ( -
+
-
+ ); } diff --git a/dashboard/15-final/app/dashboard/layout.tsx b/dashboard/15-final/app/dashboard/layout.tsx index f80441b..0300677 100644 --- a/dashboard/15-final/app/dashboard/layout.tsx +++ b/dashboard/15-final/app/dashboard/layout.tsx @@ -1,4 +1,3 @@ -import TopNav from '@/app/ui/dashboard/topnav'; import SideNav from '@/app/ui/dashboard/sidenav'; export default function Layout({ children }: { children: React.ReactNode }) { @@ -7,9 +6,8 @@ export default function Layout({ children }: { children: React.ReactNode }) {
-
- -
{children}
+
+ {children}
); diff --git a/dashboard/15-final/app/globals.css b/dashboard/15-final/app/global.css similarity index 100% rename from dashboard/15-final/app/globals.css rename to dashboard/15-final/app/global.css diff --git a/dashboard/15-final/app/layout.tsx b/dashboard/15-final/app/layout.tsx index e597742..43a3e24 100644 --- a/dashboard/15-final/app/layout.tsx +++ b/dashboard/15-final/app/layout.tsx @@ -1,6 +1,7 @@ -import './globals.css'; +import './global.css'; import type { Metadata } from 'next'; import { Inter } from 'next/font/google'; + const inter = Inter({ subsets: ['latin'] }); export const metadata: Metadata = { @@ -15,7 +16,7 @@ export default function RootLayout({ }) { return ( - {children} + {children} ); } diff --git a/dashboard/15-final/app/lib/definitions.tsx b/dashboard/15-final/app/lib/definitions.tsx index ef22934..a4c51a3 100644 --- a/dashboard/15-final/app/lib/definitions.tsx +++ b/dashboard/15-final/app/lib/definitions.tsx @@ -19,8 +19,9 @@ export type Invoice = { id: number; customerId: number; amount: number; - status: 'pending' | 'paid'; // In TypeScript, this is called a string union type. - // It means that the "status" property can only be one of the two strings. + // In TypeScript, this is called a string union type. + // It means that the "status" property can only be one of the two strings: 'pending' or 'paid'. + status: 'pending' | 'paid'; date: string; }; diff --git a/dashboard/15-final/app/lib/dummy-data.tsx b/dashboard/15-final/app/lib/dummy-data.tsx index 2ab62b2..4cc9669 100644 --- a/dashboard/15-final/app/lib/dummy-data.tsx +++ b/dashboard/15-final/app/lib/dummy-data.tsx @@ -43,105 +43,105 @@ export const invoices: Invoice[] = [ customerId: 1, amount: 15795, status: 'pending', - date: '2023-12-01', + date: '2023-12-06', }, { id: 2, customerId: 2, amount: 20348, status: 'pending', - date: '2023-11-01', + date: '2023-11-14', }, { id: 3, customerId: 3, amount: 3040, status: 'paid', - date: '2023-10-01', + date: '2023-10-29', }, { id: 4, customerId: 4, amount: 44800, status: 'paid', - date: '2023-09-01', + date: '2023-09-10', }, { id: 5, customerId: 1, amount: 34577, status: 'pending', - date: '2023-08-01', + date: '2023-08-05', }, { id: 6, customerId: 2, amount: 54246, status: 'pending', - date: '2023-07-01', + date: '2023-07-16', }, { id: 7, customerId: 3, amount: 8945, status: 'pending', - date: '2023-06-01', + date: '2023-06-27', }, { id: 8, customerId: 4, amount: 32545, status: 'paid', - date: '2023-06-01', + date: '2023-06-09', }, { id: 9, customerId: 3, amount: 1250, status: 'paid', - date: '2023-06-02', + date: '2023-06-17', }, { id: 10, customerId: 1, amount: 8945, status: 'paid', - date: '2023-06-01', + date: '2023-06-07', }, { id: 11, customerId: 2, amount: 500, status: 'paid', - date: '2023-08-01', + date: '2023-08-19', }, { id: 12, customerId: 3, amount: 8945, status: 'paid', - date: '2023-06-01', + date: '2023-06-03', }, { id: 13, customerId: 3, amount: 8945, status: 'paid', - date: '2023-06-01', + date: '2023-06-18', }, { id: 14, customerId: 4, amount: 8945, status: 'paid', - date: '2023-10-01', + date: '2023-10-04', }, { id: 15, customerId: 3, amount: 1000, status: 'paid', - date: '2022-06-12', + date: '2022-06-05', }, ]; diff --git a/dashboard/15-final/app/page.tsx b/dashboard/15-final/app/page.tsx index f3bbd67..7b32325 100644 --- a/dashboard/15-final/app/page.tsx +++ b/dashboard/15-final/app/page.tsx @@ -1,9 +1,28 @@ -import Hero from '@/app/ui/hero'; +import BackgroundBlur from '@/app/ui/background-blur'; +import Image from 'next/image'; +import HeroImage from '@/public/hero.png'; export default function Page() { return ( -
- +
+
+ +

+ Next.js Dashboard +

+

+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut vulputate + dapibus consectetur. Duis quis eros euismod. +

+ + + +
+
+ Dashboard Hero Image +
); } diff --git a/dashboard/15-final/app/ui/background-blur.tsx b/dashboard/15-final/app/ui/background-blur.tsx index 58a5766..a37716e 100644 --- a/dashboard/15-final/app/ui/background-blur.tsx +++ b/dashboard/15-final/app/ui/background-blur.tsx @@ -1,8 +1,8 @@ export default function BackgroundBlur() { return ( <> -
-
+
+
); } diff --git a/dashboard/15-final/app/ui/customers/table.tsx b/dashboard/15-final/app/ui/customers/table.tsx index 81cd5b7..47b65c5 100644 --- a/dashboard/15-final/app/ui/customers/table.tsx +++ b/dashboard/15-final/app/ui/customers/table.tsx @@ -11,69 +11,71 @@ export default function CustomersTable() {

Customers

-
+
-
- - - - - - - - - - - - - {customers.map((customer) => ( - - - - - - - +
+
+
- Profile - - Name - - Email - - Total Invoices - - Total Pending - - Total Paid -
-
- {customer.name} -
-
- {customer.name} - - {customer.email} - - {countCustomerInvoices(invoices, customer.id)} - - {calculateCustomerInvoices( - invoices, - 'pending', - customer.id, - )} - - {calculateCustomerInvoices(invoices, 'paid', customer.id)} -
+ + + + + + + - ))} - -
+ Name + + Email + + Total Invoices + + Total Pending + + Total Paid +
+ + + + {customers.map((customer) => ( + + +
+ {customer.name} +

{customer.name}

+
+ + + {customer.email} + + + {countCustomerInvoices(invoices, customer.id)} + + + {calculateCustomerInvoices( + invoices, + 'pending', + customer.id, + )} + + + {calculateCustomerInvoices( + invoices, + 'paid', + customer.id, + )} + + + ))} + + +
diff --git a/dashboard/15-final/app/ui/dashboard/card.tsx b/dashboard/15-final/app/ui/dashboard/card.tsx index 49d9652..18f8534 100644 --- a/dashboard/15-final/app/ui/dashboard/card.tsx +++ b/dashboard/15-final/app/ui/dashboard/card.tsx @@ -34,7 +34,6 @@ export default function Card({

{value}

-

+00% since last month

); } diff --git a/dashboard/15-final/app/ui/dashboard/latest-invoices.tsx b/dashboard/15-final/app/ui/dashboard/latest-invoices.tsx index af93631..3a5e4e4 100644 --- a/dashboard/15-final/app/ui/dashboard/latest-invoices.tsx +++ b/dashboard/15-final/app/ui/dashboard/latest-invoices.tsx @@ -34,14 +34,15 @@ export default function LatestInvoices({ height={32} />
-

{customer?.name}

+

+ {customer?.name} +

{customer?.email}

-

- +{' '} +

{(invoice.amount / 100).toLocaleString('en-US', { style: 'currency', currency: 'USD', diff --git a/dashboard/15-final/app/ui/dashboard/nav-links.tsx b/dashboard/15-final/app/ui/dashboard/nav-links.tsx new file mode 100644 index 0000000..79a2242 --- /dev/null +++ b/dashboard/15-final/app/ui/dashboard/nav-links.tsx @@ -0,0 +1,45 @@ +'use client'; + +import { + UserGroupIcon, + HomeIcon, + InboxIcon, +} from '@heroicons/react/24/outline'; +import Link from 'next/link'; +import { usePathname } from 'next/navigation'; +import clsx from 'clsx'; + +// Map of links to display in the side navigation. +// Depending on the size of the application, this would be stored in a database. +const links = [ + { name: 'Home', href: '/dashboard', icon: HomeIcon }, + { name: 'Invoices', href: '/dashboard/invoices', icon: InboxIcon }, + { name: 'Customers', href: '/dashboard/customers', icon: UserGroupIcon }, +]; + +export default function NavLinks() { + const pathname = usePathname(); + + return ( + <> + {links.map((link) => { + const LinkIcon = link.icon; + return ( + + +

{link.name}

+ + ); + })} + + ); +} diff --git a/dashboard/15-final/app/ui/dashboard/revenue-chart.tsx b/dashboard/15-final/app/ui/dashboard/revenue-chart.tsx index 3ba6415..5e8798c 100644 --- a/dashboard/15-final/app/ui/dashboard/revenue-chart.tsx +++ b/dashboard/15-final/app/ui/dashboard/revenue-chart.tsx @@ -15,7 +15,7 @@ export default function RevenueChart({ revenue }: { revenue: Revenue[] }) { } return ( -
+

Revenue

{/* y-axis */} @@ -23,16 +23,16 @@ export default function RevenueChart({ revenue }: { revenue: Revenue[] }) { className="mb-6 hidden flex-col justify-between text-sm text-gray-400 sm:flex" style={{ height: `${chartHeight}px` }} > - {yAxisLabels.map((label, index) => ( -

{label}

+ {yAxisLabels.map((label) => ( +

{label}

))}
- {revenue.map((month, index) => ( -
+ {revenue.map((month) => ( +
{/* bars */}
- -
- - -
-
- ); -} diff --git a/dashboard/15-final/app/ui/dashboard/sidenav.tsx b/dashboard/15-final/app/ui/dashboard/sidenav.tsx index 6adde5e..dac1ed0 100644 --- a/dashboard/15-final/app/ui/dashboard/sidenav.tsx +++ b/dashboard/15-final/app/ui/dashboard/sidenav.tsx @@ -1,25 +1,9 @@ -'use client'; - -import { - UserGroupIcon, - HomeIcon, - InboxIcon, - PowerIcon, -} from '@heroicons/react/24/outline'; -import Link from 'next/link'; +import { PowerIcon } from '@heroicons/react/24/outline'; import Image from 'next/image'; -import { usePathname } from 'next/navigation'; -import clsx from 'clsx'; +import Link from 'next/link'; +import NavLinks from '@/app/ui/dashboard/nav-links'; export default function SideNav() { - const pathname = usePathname(); - - const tabs = [ - { name: 'Home', href: '/dashboard', icon: HomeIcon }, - { name: 'Invoices', href: '/dashboard/invoices', icon: InboxIcon }, - { name: 'Customers', href: '/dashboard/customers', icon: UserGroupIcon }, - ]; - return (
@@ -32,24 +16,7 @@ export default function SideNav() { height={32} /> - {tabs.map((tab, i) => { - const TabIcon = tab.icon; - return ( - - -

{tab.name}

- - ); - })} +
- -
- ); -} diff --git a/dashboard/15-final/app/ui/hero.tsx b/dashboard/15-final/app/ui/hero.tsx deleted file mode 100644 index df7988a..0000000 --- a/dashboard/15-final/app/ui/hero.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import BackgroundBlur from '@/app/ui/background-blur'; - -export default function Hero() { - return ( -
-
- -

- Next.js Dashboard -

-

- Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut vulputate - dapibus consectetur. Duis quis eros euismod. -

- - - -
- -
- Dashboard image -
-
- ); -} diff --git a/dashboard/15-final/app/ui/invoices/delete-invoice-button.tsx b/dashboard/15-final/app/ui/invoices/delete-button.tsx similarity index 100% rename from dashboard/15-final/app/ui/invoices/delete-invoice-button.tsx rename to dashboard/15-final/app/ui/invoices/delete-button.tsx diff --git a/dashboard/15-final/app/ui/invoices/form.tsx b/dashboard/15-final/app/ui/invoices/form.tsx index 377be38..6f80bf9 100644 --- a/dashboard/15-final/app/ui/invoices/form.tsx +++ b/dashboard/15-final/app/ui/invoices/form.tsx @@ -46,7 +46,7 @@ export default function InvoiceForm({ }; return ( -
+

{type === 'new' ? 'New Invoice' : 'Edit Invoice'}

@@ -84,7 +84,7 @@ export default function InvoiceForm({ value={amount} placeholder="00.00" onChange={(e) => setAmount(Number(e.target.value))} - className="block w-full rounded-md border-0 py-1.5 pl-7 text-sm leading-6 ring-1 ring-inset ring-gray-300 placeholder:text-gray-400" + className="block w-full rounded-md border-0 py-1.5 pl-7 text-sm leading-6 ring-1 ring-inset ring-gray-200 placeholder:text-gray-400" />
diff --git a/dashboard/15-final/app/ui/invoices/pagination.tsx b/dashboard/15-final/app/ui/invoices/pagination.tsx index 2cd3416..3dd18a1 100644 --- a/dashboard/15-final/app/ui/invoices/pagination.tsx +++ b/dashboard/15-final/app/ui/invoices/pagination.tsx @@ -26,11 +26,11 @@ export default function PaginationButtons({ const NextPageTag = currentPage === totalPages ? 'p' : Link; return ( -
+
@@ -58,7 +59,7 @@ export default function PaginationButtons({
-
+
-
+
-
- - - - - - - - - - - - - - - {paginatedInvoices.map((invoice) => ( - - - - - - - - +
+
+
- # - - Customer - - Email - - Amount - - Date - - Status - - Edit -
- {invoice.id} - -
- Customer Image -

{getCustomerById(invoice.customerId)?.name}

-
-
- {getCustomerById(invoice.customerId)?.email} - - {(invoice.amount / 100).toLocaleString('en-US', { - style: 'currency', - currency: 'USD', - })} - - {formatDateToLocal(invoice.date)} - - {renderInvoiceStatus(invoice.status)} - - - - - -
+ + + + + + + + + - ))} - -
+ # + + Customer + + Email + + Amount + + Date + + Status + + Edit +
+ + + {paginatedInvoices.map((invoice) => ( + + + {invoice.id} + + +
+ Customer Image +

{getCustomerById(invoice.customerId)?.name}

+
+ + + {getCustomerById(invoice.customerId)?.email} + + + {(invoice.amount / 100).toLocaleString('en-US', { + style: 'currency', + currency: 'USD', + })} + + + {formatDateToLocal(invoice.date)} + + + {renderInvoiceStatus(invoice.status)} + + + + + + + + + ))} + + +
diff --git a/dashboard/15-final/public/hero.png b/dashboard/15-final/public/hero.png index dec1906..cd83d29 100644 Binary files a/dashboard/15-final/public/hero.png and b/dashboard/15-final/public/hero.png differ