Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update customers view #196

Merged
merged 6 commits into from
Oct 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions dashboard/15-final/app/dashboard/customers/page.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,23 @@
import { fetchFilteredCustomers } from '@/app/lib/data';
import CustomersTable from '@/app/ui/customers/table';

export default function Page() {
export default async function Page({
searchParams,
}: {
searchParams:
| {
query: string | undefined;
page: string | undefined;
}
| undefined;
}) {
const query = searchParams?.query || '';

const customers = await fetchFilteredCustomers(query);

return (
<main>
<CustomersTable />
<CustomersTable customers={customers} />
</main>
);
}
4 changes: 2 additions & 2 deletions dashboard/15-final/app/dashboard/invoices/page.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import Pagination from '@/app/ui/invoices/pagination';
import Search from '@/app/ui/invoices/search';
import Search from '@/app/ui/search';
import { CreateInvoice } from '@/app/ui/invoices/buttons';
import Table from '@/app/ui/invoices/table';
import { fetchFilteredInvoices } from '@/app/lib/data';
Expand Down Expand Up @@ -29,7 +29,7 @@ export default async function Page({
<h1 className={`${lusitana.className} text-2xl`}>Invoices</h1>
</div>
<div className="mt-4 flex items-center justify-between gap-2 md:mt-8">
<Search />
<Search placeholder="Search invoices..." />
<CreateInvoice />
</div>
<Table invoices={invoices} />
Expand Down
55 changes: 44 additions & 11 deletions dashboard/15-final/app/lib/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export async function fetchCounts() {

export async function fetchTotalAmountByStatus() {
try {
const data = await sql`SELECT
const data = await sql`SELECT
SUM(CASE WHEN status = 'paid' THEN amount ELSE 0 END) AS "paid",
SUM(CASE WHEN status = 'pending' THEN amount ELSE 0 END) AS "pending"
FROM invoices`;
Expand All @@ -61,8 +61,8 @@ export async function fetchTotalAmountByStatus() {
export async function fetchLatestInvoices() {
try {
const data = await sql<LatestInvoiceRaw>`
SELECT invoices.amount, customers.name, customers.image_url, customers.email
FROM invoices
SELECT invoices.amount, customers.name, customers.image_url, customers.email
FROM invoices
JOIN customers ON invoices.customer_id = customers.id
ORDER BY invoices.date DESC
LIMIT 5`;
Expand Down Expand Up @@ -92,7 +92,7 @@ export async function fetchFilteredInvoices(
invoices.amount,
invoices.date,
invoices.status,
customers.name,
customers.name,
customers.email,
customers.image_url
FROM invoices
Expand Down Expand Up @@ -161,7 +161,7 @@ export async function fetchInvoiceById(id: string) {
export async function fetchCustomerNames() {
try {
const data = await sql<CustomerName>`
SELECT
SELECT
id,
name
FROM customers
Expand All @@ -179,17 +179,17 @@ export async function fetchCustomerNames() {
export async function fetchCustomersTable() {
try {
const data = await sql<CustomersTable>`
SELECT
SELECT
customers.id,
customers.name,
customers.email,
customers.image_url,
COUNT(invoices.id) AS total_invoices,
SUM(CASE WHEN invoices.status = 'pending' THEN invoices.amount ELSE 0 END) AS total_pending,
SUM(CASE WHEN invoices.status = 'paid' THEN invoices.amount ELSE 0 END) AS total_paid
FROM customers
LEFT JOIN invoices ON customers.id = invoices.customer_id
GROUP BY customers.id, customers.name, customers.email, customers.image_url
SUM(CASE WHEN invoices.status = 'pending' THEN invoices.amount ELSE 0 END) AS total_pending,
SUM(CASE WHEN invoices.status = 'paid' THEN invoices.amount ELSE 0 END) AS total_paid
FROM customers
LEFT JOIN invoices ON customers.id = invoices.customer_id
GROUP BY customers.id, customers.name, customers.email, customers.image_url
ORDER BY customers.name ASC
`;

Expand All @@ -205,3 +205,36 @@ export async function fetchCustomersTable() {
throw new Error('Failed to fetch customer table.');
}
}

export async function fetchFilteredCustomers(query: string) {
try {
const data = await sql<CustomersTable>`
SELECT
customers.id,
customers.name,
customers.email,
customers.image_url,
COUNT(invoices.id) AS total_invoices,
SUM(CASE WHEN invoices.status = 'pending' THEN invoices.amount ELSE 0 END) AS total_pending,
SUM(CASE WHEN invoices.status = 'paid' THEN invoices.amount ELSE 0 END) AS total_paid
FROM customers
LEFT JOIN invoices ON customers.id = invoices.customer_id
WHERE
customers.name ILIKE ${`%${query}%`} OR
customers.email ILIKE ${`%${query}%`}
GROUP BY customers.id, customers.name, customers.email, customers.image_url
ORDER BY customers.name ASC
`;

const customers = data.rows.map((customer) => ({
...customer,
total_pending: formatCurrency(customer.total_pending),
total_paid: formatCurrency(customer.total_paid),
}));

return customers;
} catch (err) {
console.error('Database Error:', err);
throw new Error('Failed to fetch customer table.');
}
}
10 changes: 10 additions & 0 deletions dashboard/15-final/app/lib/definitions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,16 @@ export type CustomersTable = {
total_paid: number;
};

export type FormattedCustomersTable = {
id: string;
name: string;
email: string;
image_url: string;
total_invoices: number;
total_pending: string;
total_paid: string;
};

export type CustomerName = {
id: string;
name: string;
Expand Down
72 changes: 48 additions & 24 deletions dashboard/15-final/app/lib/dummy-data.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,28 +10,52 @@ const users = [

const customers = [
{
id: '93980f8c-a5e4-484c-a469-2d12ca8fdde3',
name: 'Ada Lovelace',
email: 'ada@lovelace.com',
image_url: '/customers/ada-lovelace.png',
id: '3958dc9e-712f-4377-85e9-fec4b6a6442a',
name: 'Delba de Oliveira',
email: 'delba@oliveira.com',
image_url: '/customers/delba-de-oliveira.png',
},
{
id: 'e53120f8-0301-437b-924a-0288f4ec6040',
name: 'Grace Hopper',
email: 'grace@hopper.com',
image_url: '/customers/grace-hopper.png',
id: '3958dc9e-742f-4377-85e9-fec4b6a6442a',
name: 'Lee Robinson',
email: 'lee@robinson.com',
image_url: '/customers/lee-robinson.png',
},
{
id: '030fab4c-18d7-4ed2-814c-4171cc67bca8',
name: 'Hedy Lammar',
email: 'hedy@lammar.com',
image_url: '/customers/hedy-lammar.png',
id: '3958dc9e-737f-4377-85e9-fec4b6a6442a',
name: 'Guillermo Rauch',
email: 'guillermo@rauch.com',
image_url: '/customers/guillermo-rauch.png',
},
{
id: '3958dc9e-737f-4377-85e9-fec4b6a6442a',
name: 'Margaret Hamilton',
email: 'margaret@hamilton.com',
image_url: '/customers/margaret-hamilton.png',
id: '50ca3e18-62cd-11ee-8c99-0242ac120002',
name: 'Jared Palmer',
email: 'jared@palmer.com',
image_url: '/customers/jared-palmer.png',
},
{
id: '3958dc9e-787f-4377-85e9-fec4b6a6442a',
name: 'Steph Dietz',
email: 'steph@dietz.com',
image_url: '/customers/steph-dietz.png',
},
{
id: '76d65c26-f784-44a2-ac19-586678f7c2f2',
name: 'Tom Occhino',
email: 'tom@occhino.com',
image_url: '/customers/tom-occhino.png',
},
emilkowalski marked this conversation as resolved.
Show resolved Hide resolved
{
id: 'd6e15727-9fe1-4961-8c5b-ea44a9bd81aa',
name: 'Evil Rabbit',
email: 'evil@rabbit.com',
image_url: '/customers/evil-rabbit.png',
},
{
id: '126eed9c-c90c-4ef6-a4a8-fcf7408d3c66',
name: 'Emil Kowalski',
email: 'emil@kowalski.com',
image_url: '/customers/emil-kowalski.png',
},
];

Expand All @@ -49,7 +73,7 @@ const invoices = [
date: '2022-11-14',
},
{
customer_id: customers[2].id,
customer_id: customers[4].id,
amount: 3040,
status: 'paid',
date: '2022-10-29',
Expand All @@ -61,19 +85,19 @@ const invoices = [
date: '2023-09-10',
},
{
customer_id: customers[0].id,
customer_id: customers[5].id,
amount: 34577,
status: 'pending',
date: '2023-08-05',
},
{
customer_id: customers[1].id,
customer_id: customers[7].id,
amount: 54246,
status: 'pending',
date: '2023-07-16',
},
{
customer_id: customers[2].id,
customer_id: customers[6].id,
amount: 8945,
status: 'pending',
date: '2023-06-27',
Expand All @@ -85,13 +109,13 @@ const invoices = [
date: '2023-06-09',
},
{
customer_id: customers[2].id,
customer_id: customers[4].id,
amount: 1250,
status: 'paid',
date: '2023-06-17',
},
{
customer_id: customers[0].id,
customer_id: customers[5].id,
amount: 8945,
status: 'paid',
date: '2023-06-07',
Expand All @@ -103,7 +127,7 @@ const invoices = [
date: '2023-08-19',
},
{
customer_id: customers[2].id,
customer_id: customers[5].id,
amount: 8945,
status: 'paid',
date: '2023-06-03',
Expand All @@ -115,7 +139,7 @@ const invoices = [
date: '2023-06-18',
},
{
customer_id: customers[3].id,
customer_id: customers[0].id,
amount: 8945,
status: 'paid',
date: '2023-10-04',
Expand Down
2 changes: 1 addition & 1 deletion dashboard/15-final/app/ui/button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export function Button({ children, className, ...rest }: ButtonProps) {
<button
{...rest}
className={clsx(
'flex h-10 items-center rounded-lg bg-blue-600 px-4 text-sm font-medium text-white transition-colors hover:bg-blue-500',
'flex h-10 items-center rounded-lg bg-blue-600 px-4 text-sm font-medium text-white transition-colors hover:bg-blue-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-600',
className,
)}
>
Expand Down
Loading
Loading