dash home page UI (#185)

* dash home page UI

* add lusitana font

* move fonts file to ui

* Update dashboard/15-final/app/ui/dashboard/latest-invoices.tsx

Co-authored-by: Delba de Oliveira <32464864+delbaoliveira@users.noreply.github.com>

* Update dashboard/15-final/app/dashboard/(overview)/page.tsx

Co-authored-by: Delba de Oliveira <32464864+delbaoliveira@users.noreply.github.com>

* merge main

---------

Co-authored-by: Delba de Oliveira <32464864+delbaoliveira@users.noreply.github.com>
This commit is contained in:
Stephanie Dietz
2023-10-03 09:31:49 -05:00
committed by GitHub
parent 1180db9b88
commit 9e217511b4
7 changed files with 109 additions and 69 deletions

View File

@@ -7,6 +7,7 @@ import {
fetchTotalAmountByStatus,
} from '@/app/lib/data';
import { Suspense } from 'react';
import { lusitana } from '@/app/ui/fonts';
import { RevenueChartSkeleton } from '@/app/ui/dashboard/skeletons';
export const dynamic = 'force-dynamic';
@@ -19,6 +20,9 @@ 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">
<Card title="Collected" value={totalPaidInvoices} type="collected" />
<Card title="Pending" value={totalPendingInvoices} type="pending" />

View File

@@ -6,9 +6,7 @@ export default function Layout({ children }: { children: React.ReactNode }) {
<div className="w-full flex-none md:w-64">
<SideNav />
</div>
<div className="flex-grow p-4 sm:p-10 md:overflow-y-auto md:p-20">
{children}
</div>
<div className="flex-grow overflow-y-auto p-8 md:p-12">{children}</div>
</div>
);
}

View File

@@ -4,6 +4,8 @@ import {
UserGroupIcon,
InboxIcon,
} from '@heroicons/react/24/outline';
import { lusitana } from '@/app/ui/fonts';
import clsx from 'clsx';
const iconMap = {
collected: BanknotesIcon,
@@ -24,12 +26,17 @@ export default function Card({
const Icon = iconMap[type];
return (
<div className="rounded-xl border bg-white p-6 shadow-sm">
<div className="flex justify-between ">
<h3 className="text-sm font-medium">{title}</h3>
<div className="rounded-xl bg-gray-50 p-2 shadow-sm">
<div className="flex p-4">
{Icon ? <Icon className="h-5 w-5 text-gray-700" /> : null}
<h3 className="ml-2 text-sm font-medium">{title}</h3>
</div>
<p className="mt-2 truncate text-2xl font-semibold tracking-wide md:text-3xl">
<p
className={clsx(
lusitana.className,
'truncate rounded-xl bg-white px-4 py-8 text-center text-2xl',
)}
>
{value}
</p>
</div>

View File

@@ -1,5 +1,8 @@
import { LatestInvoice } from '@/app/lib/definitions';
import { ArrowPathIcon } from '@heroicons/react/24/outline';
import clsx from 'clsx';
import Image from 'next/image';
import { lusitana } from '@/app/ui/fonts';
export default async function LatestInvoices({
latestInvoices,
@@ -7,38 +10,57 @@ export default async function LatestInvoices({
latestInvoices: LatestInvoice[];
}) {
return (
<div className="w-full rounded-xl border bg-white p-6 shadow-sm md:col-span-4 lg:col-span-3">
<h2 className="font-semibold">Latest Invoices</h2>
{latestInvoices.map((invoice) => {
return (
<div
key={invoice.id}
className="mt-8 flex flex-row items-center justify-between"
>
<div className="flex items-center">
<Image
src={invoice.image_url}
alt={`${invoice.name}'s profile picture`}
className="mr-4 rounded-full"
width={32}
height={32}
/>
<div className="min-w-0">
<p className="truncate text-sm font-semibold md:text-base">
{invoice.name}
</p>
<p className="hidden text-sm text-gray-500 sm:block">
{invoice.email}
<div className="flex w-full flex-col md:col-span-4 lg:col-span-4">
<h2 className={clsx(lusitana.className, 'mb-4 text-xl md:text-2xl')}>
Latest Invoices
</h2>
<div className="flex grow flex-col justify-between rounded-xl bg-gray-50 p-4">
<div className="bg-white px-6">
{latestInvoices.map((invoice, i) => {
return (
<div
key={invoice.id}
className={clsx(
'flex flex-row items-center justify-between py-4',
{
'border-t': i !== 0,
},
)}
>
<div className="flex items-center">
<Image
src={invoice.image_url}
alt={`${invoice.name}'s profile picture`}
className="mr-4 rounded-full"
width={32}
height={32}
/>
<div className="min-w-0">
<p className="truncate text-sm font-semibold md:text-base">
{invoice.name}
</p>
<p className="hidden text-sm text-gray-500 sm:block">
{invoice.email}
</p>
</div>
</div>
<p
className={clsx(
lusitana.className,
'truncate text-sm font-medium md:text-base',
)}
>
{invoice.amount}
</p>
</div>
</div>
<p className="truncate text-sm font-medium md:text-base">
{invoice.amount}
</p>
</div>
);
})}
);
})}
</div>
<div className="flex items-center pb-2 pt-6">
<ArrowPathIcon className="h-5 w-5 text-gray-500" />
<h3 className="ml-2 text-sm text-gray-500 ">Updated just now</h3>
</div>
</div>
</div>
);
}

View File

@@ -1,6 +1,8 @@
import { generateYAxis } from '@/app/lib/utils';
import { fetchRevenue } from '@/app/lib/data';
import { CalendarIcon } from '@heroicons/react/24/outline';
import { lusitana } from '@/app/ui/fonts';
import clsx from 'clsx';
// This component is representational only.
// For data visualization UI, check out:
// https://www.tremor.so/
@@ -18,34 +20,42 @@ export default async function RevenueChart() {
}
return (
<div className="rounded-xl border bg-white p-6 shadow-sm md:col-span-5">
<h2 className="font-semibold">Revenue</h2>
<div className="sm:grid-cols-13 mt-4 grid grid-cols-12 items-end gap-2 md:gap-4">
{/* y-axis */}
<div
className="mb-6 hidden flex-col justify-between text-sm text-gray-400 sm:flex"
style={{ height: `${chartHeight}px` }}
>
{yAxisLabels.map((label) => (
<p key={label}>{label}</p>
<div className="w-full md:col-span-4">
<h2 className={clsx(lusitana.className, 'mb-4 text-xl md:text-2xl')}>
Recent Revenue
</h2>
<div className="rounded-xl bg-gray-50 p-4">
<div className="sm:grid-cols-13 mt-0 grid grid-cols-12 items-end gap-2 rounded-md bg-white p-4 md:gap-4">
{/* y-axis */}
<div
className="mb-6 hidden flex-col justify-between text-sm text-gray-400 sm:flex"
style={{ height: `${chartHeight}px` }}
>
{yAxisLabels.map((label) => (
<p key={label}>{label}</p>
))}
</div>
{revenue.map((month) => (
<div key={month.month} className="flex flex-col items-center gap-2">
{/* bars */}
<div
className="w-full rounded-md bg-blue-300"
style={{
height: `${(chartHeight / topLabel) * month.revenue}px`,
}}
></div>
{/* x-axis */}
<p className="-rotate-90 text-sm text-gray-400 sm:rotate-0">
{month.month}
</p>
</div>
))}
</div>
{revenue.map((month) => (
<div key={month.month} className="flex flex-col items-center gap-2">
{/* bars */}
<div
className="w-full rounded-md bg-blue-300"
style={{
height: `${(chartHeight / topLabel) * month.revenue}px`,
}}
></div>
{/* x-axis */}
<p className="-rotate-90 text-sm text-gray-400 sm:rotate-0">
{month.month}
</p>
</div>
))}
<div className="flex items-center pb-2 pt-6">
<CalendarIcon className="h-5 w-5 text-gray-500" />
<h3 className="ml-2 text-sm text-gray-500 ">Last 6 months</h3>
</div>
</div>
</div>
);

View File

@@ -1,8 +1,7 @@
import Image from 'next/image';
import Link from 'next/link';
import NavLinks from '@/app/ui/dashboard/nav-links';
import LogOutButton from './log-out-button';
import LogoIcon from './logo-icon';
import AcmeLogo from '../acme-logo';
export default function SideNav() {
return (
@@ -11,9 +10,9 @@ export default function SideNav() {
className="mb-2 flex h-20 items-end justify-center rounded-md bg-blue-600 p-4 md:h-40 md:justify-start"
href="/"
>
<span className="h-8">
<LogoIcon />
</span>
<div className="w-32 text-white md:w-40">
<AcmeLogo />
</div>
</Link>
<div className="flex grow flex-row justify-between space-x-2 md:flex-col md:space-x-0 md:space-y-2">
<NavLinks />