Misc. pizzazz

This commit is contained in:
Daniel Flanagan 2024-08-24 08:53:29 -05:00
parent e0a73c5032
commit cc539727ca
2 changed files with 64 additions and 14 deletions

View file

@ -1,7 +1,7 @@
import { useSignal } from 'https://esm.sh/v135/@preact/signals@1.2.2/X-ZS8q/dist/signals.js'
import { JSX } from 'preact'
import { Budget } from '../models.ts'
import { Budget, currency, percentage } from '../models.ts'
interface IconButtonProps {
active?: boolean
@ -15,30 +15,47 @@ function IconButton(
) {
return (
<button
class={'py-2 px-4 flex flex-col sm:flex-row flex-1 sm:flex-none bg-bg justify-center items-center sm:justify-start text-center sm:text-left rounded' +
class={'p-2 sm:px-4 flex flex-col sm:flex-row flex-1 sm:flex-none bg-mantle justify-center items-center sm:justify-start text-center sm:text-left rounded' +
(active ? ' text-primary' : '')}
{...props}
>
<span class='sm:mr-2'>{icon}</span>
<span class=''>{children}</span>
<div class='sm:mr-2'>{icon}</div>
<div class=''>{children}</div>
</button>
)
}
function BudgetCard(
{ children, ...props }:
{ budget, ...props }:
& { budget: Budget }
& JSX.HTMLAttributes<HTMLDivElement>,
) {
return (
<button
class={'py-2 px-4 flex flex-col sm:flex-row flex-1 sm:flex-none bg-bg justify-center items-center sm:justify-start text-center sm:text-left rounded' +
(active ? ' text-primary' : '')}
<div
class='bg-surface0 rounded shadow hover:bg-surface1 transition-colors flex justify-between'
{...props}
>
<span class='sm:mr-2'>{icon}</span>
<span class=''>{children}</span>
</button>
<div class='p-2'>
{budget.name}: {currency(budget.spent)} / {currency(budget.target)}{' '}
({percentage(budget.spent / budget.target)})
</div>
<button class='text-surface1 cursor-grab p-2'>
<svg
xmlns='http://www.w3.org/2000/svg'
fill='none'
viewBox='0 0 24 24'
strokeWidth={1.5}
stroke='currentColor'
className='size-6'
>
<path
strokeLinecap='round'
strokeLinejoin='round'
d='M3.75 9h16.5m-16.5 6.75h16.5'
/>
</svg>
</button>
</div>
)
}
@ -50,6 +67,21 @@ export default function Dashboard() {
target: 1000,
spent: 367.97,
},
{
name: 'Fast Food',
target: 300,
spent: 420.69,
},
{
name: 'Insurance',
target: 220.44,
spent: 0,
},
{
name: 'Mortgage',
target: 1310.47,
spent: 1310.47,
},
]
const navItems = [
{
@ -113,11 +145,11 @@ export default function Dashboard() {
return (
<div class='grid grid-rows-[1fr_auto] sm:grid-cols-2 sm:grid-rows-1 sm:grid-cols-[1fr_auto] h-[100vh]'>
<main class='p-2'>
This is the main content
<main class='p-2 sm:pr-0 flex flex-col gap-2'>
{budgets.map((budget, _i) => <BudgetCard budget={budget} />)}
</main>
<nav class='w-full flex flex-1 sm:flex-col bg-mantle gap-1 p-1'>
<nav class='w-full flex flex-1 sm:flex-col sm:bg-bg gap-2 p-2'>
{navItems.map(({ text, ...props }, i) => (
<IconButton
{...props}

View file

@ -16,3 +16,21 @@ export interface Transaction {
budget: string
amount: number
}
const currencyFormat = new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD',
maximumFractionDigits: 2,
minimumFractionDigits: 2,
})
export function currency(amount: number): string {
return currencyFormat.format(amount)
}
const percentageFormat = new Intl.NumberFormat('en-US', {
currency: 'USD',
maximumFractionDigits: 2,
})
export function percentage(ratio: number): string {
return percentageFormat.format(ratio * 100) + '%'
}