From 482f4bf04202e04ea9618638d81753612dac278c Mon Sep 17 00:00:00 2001 From: Stephanie Dietz <49788645+StephDietz@users.noreply.github.com> Date: Wed, 6 Sep 2023 07:06:56 -0500 Subject: [PATCH 1/4] Add customer table UI (#142) * add customers table * remove unused imports * fix width issue for prof image in small screens --- .../15-final/app/dashboard/customers/page.tsx | 8 ++- .../15-final/app/dashboard/invoices/page.tsx | 4 +- dashboard/15-final/app/ui/customers/table.tsx | 66 +++++++++++++++++++ dashboard/15-final/app/ui/invoices/table.tsx | 3 +- 4 files changed, 77 insertions(+), 4 deletions(-) create mode 100644 dashboard/15-final/app/ui/customers/table.tsx diff --git a/dashboard/15-final/app/dashboard/customers/page.tsx b/dashboard/15-final/app/dashboard/customers/page.tsx index ff5a46d..cfffe27 100644 --- a/dashboard/15-final/app/dashboard/customers/page.tsx +++ b/dashboard/15-final/app/dashboard/customers/page.tsx @@ -1,3 +1,9 @@ +import CustomersTable from "@/app/ui/customers/table"; + export default function Page() { - return
List of customers
+ return ( +
+ +
+ ) } diff --git a/dashboard/15-final/app/dashboard/invoices/page.tsx b/dashboard/15-final/app/dashboard/invoices/page.tsx index 695f8b6..393ab7d 100644 --- a/dashboard/15-final/app/dashboard/invoices/page.tsx +++ b/dashboard/15-final/app/dashboard/invoices/page.tsx @@ -1,9 +1,9 @@ -import Table from "@/app/ui/invoices/table"; +import InvoicesTable from "@/app/ui/invoices/table"; export default function Page() { return (
- + ); } diff --git a/dashboard/15-final/app/ui/customers/table.tsx b/dashboard/15-final/app/ui/customers/table.tsx new file mode 100644 index 0000000..eff06ba --- /dev/null +++ b/dashboard/15-final/app/ui/customers/table.tsx @@ -0,0 +1,66 @@ +import { customers, invoices } from "@/app/lib/dummy-data"; +import Image from "next/image"; + +export default function CustomersTable() { + function totalInvoices(customerId: number) { + const customerInvoices = invoices.filter((invoice) => { + return invoice.customerId === customerId + }); + return customerInvoices.length; + }; + return ( +
+
+

Customers

+
+
+
+
+
+ + + + + + + + + + {customers.map((customer) => ( + + + + + + + ))} + +
+ Profile + + Name + + Email + + Total Invoices +
+
+ {customer.name} +
+
+ {customer.name} + + {customer.email} + + {totalInvoices(customer.id)} +
+
+ + + + ); +} diff --git a/dashboard/15-final/app/ui/invoices/table.tsx b/dashboard/15-final/app/ui/invoices/table.tsx index 53964bb..e9f8c33 100644 --- a/dashboard/15-final/app/ui/invoices/table.tsx +++ b/dashboard/15-final/app/ui/invoices/table.tsx @@ -1,5 +1,6 @@ import { invoices, customers } from "@/app/lib/dummy-data"; import { Customer } from "@/app/lib/definitions"; + import Link from "next/link"; import { PencilSquareIcon, @@ -26,7 +27,7 @@ function renderInvoiceStatus(status: string) { } } -export default function Table() { +export default function InvoicesTable() { function getCustomerById(customerId: number): Customer | null { const customer = customers.find((customer) => customer.id === customerId); return customer ? customer : null; From 83293ab9242852cf5cb303b7f161d631426c7dc3 Mon Sep 17 00:00:00 2001 From: Delba de Oliveira <32464864+delbaoliveira@users.noreply.github.com> Date: Wed, 6 Sep 2023 14:18:40 +0100 Subject: [PATCH 2/4] Add "edit" invoice functionality (#144) * Organize components * Add delete invoice component and action * Update customer emails * Add delete button, pending/paid UI, and placeholder edit button * Fix build errors * More errors * Fix table corners * Rename add invoice form, and make it generic for edit or add * Wire it up! * Add server action placeholder * Fix TS errors * Misc --- .../app/dashboard/invoices/[id]/edit/page.tsx | 19 +++++- .../app/dashboard/invoices/[id]/page.tsx | 2 +- .../app/dashboard/invoices/create/page.tsx | 4 +- dashboard/15-final/app/lib/actions.tsx | 5 ++ .../{add-invoice-form.tsx => form.tsx} | 63 ++++++++++++++++--- dashboard/15-final/app/ui/invoices/table.tsx | 11 ++-- 6 files changed, 88 insertions(+), 16 deletions(-) rename dashboard/15-final/app/ui/invoices/{add-invoice-form.tsx => form.tsx} (54%) diff --git a/dashboard/15-final/app/dashboard/invoices/[id]/edit/page.tsx b/dashboard/15-final/app/dashboard/invoices/[id]/edit/page.tsx index 0d2c74b..9a179ca 100644 --- a/dashboard/15-final/app/dashboard/invoices/[id]/edit/page.tsx +++ b/dashboard/15-final/app/dashboard/invoices/[id]/edit/page.tsx @@ -1,3 +1,18 @@ -export default function Page() { - return
Edit Invoice Page
+import InvoiceForm from "@/app/ui/invoices/form"; +import { invoices } from "@/app/lib/dummy-data"; +import { notFound } from "next/navigation"; + +export default function Page({ params }: { params: { id: string } }) { + const id = params.id ? parseInt(params.id) : null; + const invoice = invoices.find((invoice) => invoice.id === id); + + if (!invoice) { + notFound(); + } + + return ( +
+ +
+ ); } diff --git a/dashboard/15-final/app/dashboard/invoices/[id]/page.tsx b/dashboard/15-final/app/dashboard/invoices/[id]/page.tsx index 188d95c..30de135 100644 --- a/dashboard/15-final/app/dashboard/invoices/[id]/page.tsx +++ b/dashboard/15-final/app/dashboard/invoices/[id]/page.tsx @@ -1,3 +1,3 @@ export default function Page() { - return
Individual Invoice Page
+ return
Individual Invoice Page
; } diff --git a/dashboard/15-final/app/dashboard/invoices/create/page.tsx b/dashboard/15-final/app/dashboard/invoices/create/page.tsx index 563cb0c..74a2a0d 100644 --- a/dashboard/15-final/app/dashboard/invoices/create/page.tsx +++ b/dashboard/15-final/app/dashboard/invoices/create/page.tsx @@ -1,5 +1,5 @@ -import AddInvoiceForm from "@/app/ui/invoices/add-invoice-form"; +import InvoiceForm from "@/app/ui/invoices/form"; export default function Page() { - return ; + return ; } diff --git a/dashboard/15-final/app/lib/actions.tsx b/dashboard/15-final/app/lib/actions.tsx index efebdd6..92e37c0 100644 --- a/dashboard/15-final/app/lib/actions.tsx +++ b/dashboard/15-final/app/lib/actions.tsx @@ -4,3 +4,8 @@ export async function deleteInvoice(id: number) { // TO DO: Add delete invoice logic console.log("Delete invoice", id); } + +export async function addOrUpdateInvoice(formData: FormData) { + // TO DO: Add create/update invoice logic + console.log("Edit Invoice"); +} diff --git a/dashboard/15-final/app/ui/invoices/add-invoice-form.tsx b/dashboard/15-final/app/ui/invoices/form.tsx similarity index 54% rename from dashboard/15-final/app/ui/invoices/add-invoice-form.tsx rename to dashboard/15-final/app/ui/invoices/form.tsx index 65519fd..96295b3 100644 --- a/dashboard/15-final/app/ui/invoices/add-invoice-form.tsx +++ b/dashboard/15-final/app/ui/invoices/form.tsx @@ -1,11 +1,30 @@ "use client"; + import { Invoice } from "@/app/lib/definitions"; import { customers } from "@/app/lib/dummy-data"; import { useState, FormEvent } from "react"; -export default function AddInvoiceForm() { - const [selectedCustomer, setSelectedCustomer] = useState(0); - const [amount, setAmount] = useState(""); +// import { addOrUpdateInvoice } from "@/app/lib/actions"; +// export const dynamic = "force-dynamic"; + +export default function InvoiceForm({ + type, + invoice, +}: { + type: "new" | "edit"; + invoice?: Invoice; +}) { + // TO DO: Replace state and handleSubmit with a Server Action + const customer = customers.find( + (customer) => customer.id === invoice?.customerId, + ); + const initialCustomer = customer ? customer.id : 0; + const initialAmount = invoice?.amount ? invoice.amount / 100 : 0; + const initialStatus = invoice?.status || "pending"; + + const [selectedCustomer, setSelectedCustomer] = useState(initialCustomer); + const [amount, setAmount] = useState(initialAmount); + const [status, setStatus] = useState<"pending" | "paid">(initialStatus); const handleSubmit = (e: FormEvent) => { e.preventDefault(); @@ -13,11 +32,11 @@ export default function AddInvoiceForm() { if (selectedCustomer && amount) { const newInvoice: Invoice = { customerId: selectedCustomer, - amount: parseInt(amount) * 100, // Convert to cents + amount: amount * 100, // Convert to cents // These would be generated on the server id: 1, // Record ID will be automatically incremented - status: "pending", // Default status for a new invoice + status: status, // Default status for a new invoice date: new Date().toISOString().split("T")[0], }; @@ -28,7 +47,9 @@ export default function AddInvoiceForm() { return (
-

New Invoice

+

+ {type === "new" ? "New Invoice" : "Edit Invoice"} +

+ { + const value = e.target.value; + + if (value === "paid" || value === "pending") { + setStatus(value); + } + }} + value={status} + > + + + +
+ ) : null} +