Skip to content

Commit

Permalink
Open modal for budget category details
Browse files Browse the repository at this point in the history
  • Loading branch information
binary-koan committed Mar 8, 2024
1 parent c483cf4 commit e010050
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 10 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"dev": "concurrently -n api,web,codegen -c blue,magenta,yellow 'rails s' 'cd web && bun run watch' 'cd web && bun graphql-codegen --watch'",
"dev:test": "cd api && ENV_TYPE=test PORT=4445 bun run bin/dev-test.ts",
"deploy": "bun run deploy.js",
"typecheck": "web && bun typecheck",
"typecheck": "cd web && bun typecheck",
"lint": "cd web && bun lint"
},
"workspaces": ["web"]
Expand Down
29 changes: 23 additions & 6 deletions web/src/components/budgets/BudgetGroup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,30 @@ import { Component, For, Show } from "solid-js"
import { CATEGORY_BACKGROUND_COLORS, CategoryColor } from "../../utils/categoryColors"
import { getCssValue } from "../../utils/getCssValue"
import CategoryIndicator, { CategoryIndicatorProps } from "../CategoryIndicator"
import { LinkButton } from "../base/Button"
import { Button, LinkButton } from "../base/Button"
import { PieChart } from "./PieChart"
import { createSignal } from "solid-js"
import { TransactionsModal } from "./TransactionsModal"

interface BudgetGroupProps {
title: string
total: string
allTransactionsHref: string
items: Array<{
indicator: CategoryIndicatorProps
categoryId: string | null
name: string
color?: CategoryColor
budget?: { amountDecimal: number; formatted: string } | null | false
total: { amountDecimal: number; formatted: string }
href: string
}>
}

const NO_CATEGORY = Symbol("NO_CATEGORY")

const BudgetGroup: Component<BudgetGroupProps> = (props) => {
const [openCategory, setOpenCategory] = createSignal<string | symbol | false>(false)

return (
<div class="mt-6 flex flex-col lg:mt-0 lg:flex-row">
<div class="min-w-0 flex-none lg:flex-1">
Expand All @@ -44,7 +50,7 @@ const BudgetGroup: Component<BudgetGroupProps> = (props) => {
</Show>

<For each={props.items}>
{({ indicator, name, color, total, budget, href }) => (
{({ categoryId, indicator, name, color, total, budget }) => (
<div class="flex items-center pb-4">
<CategoryIndicator class="mr-3 h-6 w-6" {...indicator} />
<div class="min-w-0 flex-1">
Expand Down Expand Up @@ -93,16 +99,16 @@ const BudgetGroup: Component<BudgetGroupProps> = (props) => {
</div>
</Show>
</div>
<LinkButton
href={href}
<Button
size="square"
variant="ghost"
colorScheme="primary"
class="ml-4"
aria-label="View transactions"
onClick={() => setOpenCategory(categoryId || NO_CATEGORY)}
>
<IconListSearch />
</LinkButton>
</Button>
</div>
)}
</For>
Expand All @@ -116,6 +122,17 @@ const BudgetGroup: Component<BudgetGroupProps> = (props) => {
formattedValue: total.formatted
}))}
/>
<Show when={openCategory()}>
{(openCategory) => {
const category = openCategory()
return (
<TransactionsModal
categoryId={typeof category === "string" ? category : null}
onClose={() => setOpenCategory(false)}
/>
)
}}
</Show>
</div>
)
}
Expand Down
6 changes: 3 additions & 3 deletions web/src/components/budgets/Budgets.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export const Budgets: Component<{
color: category?.color as CategoryColor,
budget: category?.budget?.budget,
total: amountSpent,
href: filteredTransactions({ categoryIds: [category?.id || null] })
categoryId: category?.id || null
}))}
/>

Expand All @@ -72,7 +72,7 @@ export const Budgets: Component<{
color: category?.color as CategoryColor,
budget: category?.budget?.budget,
total: amountSpent,
href: filteredTransactions({ categoryIds: [category?.id || null] })
categoryId: category?.id || null
})
)}
/>
Expand All @@ -86,7 +86,7 @@ export const Budgets: Component<{
name: transaction.memo,
budget: false,
total: transaction.amount || { amountDecimal: 0, formatted: "?" },
href: `/transactions/${transaction.id}`
categoryId: null
}))}
/>
</>
Expand Down
50 changes: 50 additions & 0 deletions web/src/components/budgets/TransactionsModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { Show } from "solid-js"
import { useTransactionsQuery } from "../../graphql/queries/transactionsQuery"
import { Modal, ModalContent, ModalTitle } from "../base/Modal"
import LoadingBar from "../LoadingBar"
import { For } from "solid-js"

export const TransactionsModal = (props: { categoryId: string | null; onClose: () => void }) => {
const query = useTransactionsQuery(() => ({
limit: 1000,
filter: { categoryIds: [props.categoryId] }
}))

const transactionsToShow = () =>
query()
?.transactions.nodes.flatMap((transaction) => {
if (transaction.splitTo) {
return transaction.splitTo
.filter((split) => split.category?.id === props.categoryId)
.map((split) => ({ ...split, shop: transaction.shop }))
} else {
return [transaction]
}
})
.sort((a, b) => (a.amount?.amountDecimal || 0) - (b.amount?.amountDecimal || 0))

return (
<Modal isOpen={true} onClickOutside={props.onClose}>
<ModalContent class="!my-0 flex max-h-[90vh] flex-col">
<ModalTitle>Transactions</ModalTitle>
<Show when={transactionsToShow()} fallback={<LoadingBar />}>
{(transactionsToShow) => (
<ul class="min-h-0 flex-1 overflow-auto">
<For each={transactionsToShow()}>
{(transaction) => (
<li class="flex justify-between py-1">
<span>
{transaction.shop}{" "}
<span class="text-gray-600">&ndash; {transaction.memo}</span>
</span>
<span>{transaction.amount?.formatted}</span>
</li>
)}
</For>
</ul>
)}
</Show>
</ModalContent>
</Modal>
)
}

0 comments on commit e010050

Please sign in to comment.