Misc. pizzazz
This commit is contained in:
parent
e0a73c5032
commit
cc539727ca
2 changed files with 64 additions and 14 deletions
|
@ -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}
|
||||
|
|
18
models.ts
18
models.ts
|
@ -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) + '%'
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue