mirror of
https://github.com/whekin/household-bot.git
synced 2026-03-31 21:14:02 +00:00
refactor(miniapp): split home and balances screens
This commit is contained in:
@@ -40,11 +40,11 @@ import { HeroBanner } from './components/layout/hero-banner'
|
||||
import { NavigationTabs } from './components/layout/navigation-tabs'
|
||||
import { ProfileCard } from './components/layout/profile-card'
|
||||
import { TopBar } from './components/layout/top-bar'
|
||||
import { FinanceSummaryCards } from './components/finance/finance-summary-cards'
|
||||
import { FinanceVisuals } from './components/finance/finance-visuals'
|
||||
import { BlockedState } from './components/session/blocked-state'
|
||||
import { LoadingState } from './components/session/loading-state'
|
||||
import { OnboardingState } from './components/session/onboarding-state'
|
||||
import { BalancesScreen } from './screens/balances-screen'
|
||||
import { HomeScreen } from './screens/home-screen'
|
||||
import {
|
||||
demoAdminSettings,
|
||||
demoCycleState,
|
||||
@@ -1854,122 +1854,17 @@ function App() {
|
||||
switch (activeNav()) {
|
||||
case 'balances':
|
||||
return (
|
||||
<div class="balance-list">
|
||||
<ShowDashboard
|
||||
dashboard={dashboard()}
|
||||
fallback={<p>{copy().emptyDashboard}</p>}
|
||||
render={(data) => (
|
||||
<>
|
||||
{currentMemberLine() ? (
|
||||
<article class="balance-item balance-item--accent">
|
||||
<header>
|
||||
<strong>{copy().yourBalanceTitle}</strong>
|
||||
<span>
|
||||
{currentMemberLine()!.netDueMajor} {data.currency}
|
||||
</span>
|
||||
</header>
|
||||
<p>{copy().yourBalanceBody}</p>
|
||||
<div class="balance-breakdown">
|
||||
<div class="stat-card">
|
||||
<span>{copy().baseDue}</span>
|
||||
<strong>
|
||||
{memberBaseDueMajor(currentMemberLine()!)} {data.currency}
|
||||
</strong>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<span>{copy().shareOffset}</span>
|
||||
<strong>
|
||||
{currentMemberLine()!.purchaseOffsetMajor} {data.currency}
|
||||
</strong>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<span>{copy().finalDue}</span>
|
||||
<strong>
|
||||
{currentMemberLine()!.netDueMajor} {data.currency}
|
||||
</strong>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<span>{copy().paidLabel}</span>
|
||||
<strong>
|
||||
{currentMemberLine()!.paidMajor} {data.currency}
|
||||
</strong>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<span>{copy().remainingLabel}</span>
|
||||
<strong>
|
||||
{currentMemberLine()!.remainingMajor} {data.currency}
|
||||
</strong>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
) : null}
|
||||
<div class="home-grid home-grid--summary">
|
||||
<FinanceSummaryCards
|
||||
dashboard={data}
|
||||
utilityTotalMajor={utilityTotalMajor()}
|
||||
purchaseTotalMajor={purchaseTotalMajor()}
|
||||
labels={{
|
||||
remaining: copy().remainingLabel,
|
||||
rent: copy().shareRent,
|
||||
utilities: copy().shareUtilities,
|
||||
purchases: copy().purchasesTitle
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<FinanceVisuals
|
||||
dashboard={data}
|
||||
memberVisuals={memberBalanceVisuals()}
|
||||
purchaseChart={purchaseInvestmentChart()}
|
||||
remainingClass={memberRemainingClass}
|
||||
labels={{
|
||||
financeVisualsTitle: copy().financeVisualsTitle,
|
||||
financeVisualsBody: copy().financeVisualsBody,
|
||||
membersCount: copy().membersCount,
|
||||
purchaseInvestmentsTitle: copy().purchaseInvestmentsTitle,
|
||||
purchaseInvestmentsBody: copy().purchaseInvestmentsBody,
|
||||
purchaseInvestmentsEmpty: copy().purchaseInvestmentsEmpty,
|
||||
purchaseTotalLabel: copy().purchaseTotalLabel,
|
||||
purchaseShareLabel: copy().purchaseShareLabel
|
||||
}}
|
||||
/>
|
||||
<article class="balance-item">
|
||||
<header>
|
||||
<strong>{copy().householdBalancesTitle}</strong>
|
||||
</header>
|
||||
<p>{copy().householdBalancesBody}</p>
|
||||
</article>
|
||||
{data.members.map((member) => (
|
||||
<article class="balance-item">
|
||||
<header>
|
||||
<strong>{member.displayName}</strong>
|
||||
<span>
|
||||
{member.remainingMajor} {data.currency}
|
||||
</span>
|
||||
</header>
|
||||
<p>
|
||||
{copy().baseDue}: {memberBaseDueMajor(member)} {data.currency}
|
||||
</p>
|
||||
<p>
|
||||
{copy().shareRent}: {member.rentShareMajor} {data.currency}
|
||||
</p>
|
||||
<p>
|
||||
{copy().shareUtilities}: {member.utilityShareMajor} {data.currency}
|
||||
</p>
|
||||
<p>
|
||||
{copy().shareOffset}: {member.purchaseOffsetMajor} {data.currency}
|
||||
</p>
|
||||
<p>
|
||||
{copy().paidLabel}: {member.paidMajor} {data.currency}
|
||||
</p>
|
||||
<p class={`balance-status ${memberRemainingClass(member)}`}>
|
||||
{copy().remainingLabel}: {member.remainingMajor} {data.currency}
|
||||
</p>
|
||||
</article>
|
||||
))}
|
||||
</>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<BalancesScreen
|
||||
copy={copy()}
|
||||
dashboard={dashboard()}
|
||||
currentMemberLine={currentMemberLine()}
|
||||
utilityTotalMajor={utilityTotalMajor()}
|
||||
purchaseTotalMajor={purchaseTotalMajor()}
|
||||
memberBalanceVisuals={memberBalanceVisuals()}
|
||||
purchaseChart={purchaseInvestmentChart()}
|
||||
memberBaseDueMajor={memberBaseDueMajor}
|
||||
memberRemainingClass={memberRemainingClass}
|
||||
/>
|
||||
)
|
||||
case 'ledger':
|
||||
return (
|
||||
@@ -3583,166 +3478,22 @@ function App() {
|
||||
)
|
||||
default:
|
||||
return (
|
||||
<div class="home-grid home-grid--summary">
|
||||
<ShowDashboard
|
||||
dashboard={dashboard()}
|
||||
fallback={
|
||||
<>
|
||||
<article class="stat-card">
|
||||
<span>{copy().remainingLabel}</span>
|
||||
<strong>—</strong>
|
||||
</article>
|
||||
<article class="stat-card">
|
||||
<span>{copy().shareRent}</span>
|
||||
<strong>—</strong>
|
||||
</article>
|
||||
<article class="stat-card">
|
||||
<span>{copy().shareUtilities}</span>
|
||||
<strong>—</strong>
|
||||
</article>
|
||||
<article class="stat-card">
|
||||
<span>{copy().purchasesTitle}</span>
|
||||
<strong>—</strong>
|
||||
</article>
|
||||
</>
|
||||
}
|
||||
render={(data) => (
|
||||
<FinanceSummaryCards
|
||||
dashboard={data}
|
||||
utilityTotalMajor={utilityTotalMajor()}
|
||||
purchaseTotalMajor={purchaseTotalMajor()}
|
||||
labels={{
|
||||
remaining: copy().remainingLabel,
|
||||
rent: copy().shareRent,
|
||||
utilities: copy().shareUtilities,
|
||||
purchases: copy().purchasesTitle
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
{readySession()?.member.isAdmin ? (
|
||||
<article class="stat-card">
|
||||
<span>{copy().pendingRequests}</span>
|
||||
<strong>{String(pendingMembers().length)}</strong>
|
||||
</article>
|
||||
) : null}
|
||||
|
||||
{currentMemberLine() ? (
|
||||
<article class="balance-item balance-item--accent">
|
||||
<header>
|
||||
<strong>{copy().yourBalanceTitle}</strong>
|
||||
<span>
|
||||
{currentMemberLine()!.remainingMajor} {dashboard()?.currency ?? ''}
|
||||
</span>
|
||||
</header>
|
||||
<p>{copy().yourBalanceBody}</p>
|
||||
<ShowDashboard
|
||||
dashboard={dashboard()}
|
||||
fallback={null}
|
||||
render={(data) => (
|
||||
<p>
|
||||
{copy().shareRent}: {data.rentSourceAmountMajor} {data.rentSourceCurrency}
|
||||
{data.rentSourceCurrency !== data.currency
|
||||
? ` -> ${data.rentDisplayAmountMajor} ${data.currency}`
|
||||
: ''}
|
||||
</p>
|
||||
)}
|
||||
/>
|
||||
<div class="balance-breakdown">
|
||||
<div class="stat-card">
|
||||
<span>{copy().baseDue}</span>
|
||||
<strong>
|
||||
{memberBaseDueMajor(currentMemberLine()!)} {dashboard()?.currency ?? ''}
|
||||
</strong>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<span>{copy().shareOffset}</span>
|
||||
<strong>
|
||||
{currentMemberLine()!.purchaseOffsetMajor} {dashboard()?.currency ?? ''}
|
||||
</strong>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<span>{copy().finalDue}</span>
|
||||
<strong>
|
||||
{currentMemberLine()!.netDueMajor} {dashboard()?.currency ?? ''}
|
||||
</strong>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<span>{copy().paidLabel}</span>
|
||||
<strong>
|
||||
{currentMemberLine()!.paidMajor} {dashboard()?.currency ?? ''}
|
||||
</strong>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<span>{copy().remainingLabel}</span>
|
||||
<strong>
|
||||
{currentMemberLine()!.remainingMajor} {dashboard()?.currency ?? ''}
|
||||
</strong>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
) : (
|
||||
<article class="balance-item">
|
||||
<header>
|
||||
<strong>{copy().overviewTitle}</strong>
|
||||
</header>
|
||||
<p>{copy().overviewBody}</p>
|
||||
</article>
|
||||
)}
|
||||
|
||||
<ShowDashboard
|
||||
dashboard={dashboard()}
|
||||
fallback={null}
|
||||
render={(data) => (
|
||||
<FinanceVisuals
|
||||
dashboard={data}
|
||||
memberVisuals={memberBalanceVisuals()}
|
||||
purchaseChart={purchaseInvestmentChart()}
|
||||
remainingClass={memberRemainingClass}
|
||||
labels={{
|
||||
financeVisualsTitle: copy().financeVisualsTitle,
|
||||
financeVisualsBody: copy().financeVisualsBody,
|
||||
membersCount: copy().membersCount,
|
||||
purchaseInvestmentsTitle: copy().purchaseInvestmentsTitle,
|
||||
purchaseInvestmentsBody: copy().purchaseInvestmentsBody,
|
||||
purchaseInvestmentsEmpty: copy().purchaseInvestmentsEmpty,
|
||||
purchaseTotalLabel: copy().purchaseTotalLabel,
|
||||
purchaseShareLabel: copy().purchaseShareLabel
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
|
||||
<article class="balance-item balance-item--wide">
|
||||
<header>
|
||||
<strong>{copy().latestActivityTitle}</strong>
|
||||
</header>
|
||||
<ShowDashboard
|
||||
dashboard={dashboard()}
|
||||
fallback={<p>{copy().latestActivityEmpty}</p>}
|
||||
render={(data) =>
|
||||
data.ledger.length === 0 ? (
|
||||
<p>{copy().latestActivityEmpty}</p>
|
||||
) : (
|
||||
<div class="activity-list">
|
||||
{data.ledger.slice(0, 3).map((entry) => (
|
||||
<article class="activity-row">
|
||||
<header>
|
||||
<strong>{ledgerTitle(entry)}</strong>
|
||||
<span>{ledgerPrimaryAmount(entry)}</span>
|
||||
</header>
|
||||
<Show when={ledgerSecondaryAmount(entry)}>
|
||||
{(secondary) => <p>{secondary()}</p>}
|
||||
</Show>
|
||||
<p>{entry.actorDisplayName ?? copy().ledgerActorFallback}</p>
|
||||
</article>
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
/>
|
||||
</article>
|
||||
</div>
|
||||
<HomeScreen
|
||||
copy={copy()}
|
||||
dashboard={dashboard()}
|
||||
readyIsAdmin={Boolean(readySession()?.member.isAdmin)}
|
||||
pendingMembersCount={pendingMembers().length}
|
||||
currentMemberLine={currentMemberLine()}
|
||||
utilityTotalMajor={utilityTotalMajor()}
|
||||
purchaseTotalMajor={purchaseTotalMajor()}
|
||||
memberBalanceVisuals={memberBalanceVisuals()}
|
||||
purchaseChart={purchaseInvestmentChart()}
|
||||
memberBaseDueMajor={memberBaseDueMajor}
|
||||
memberRemainingClass={memberRemainingClass}
|
||||
ledgerTitle={ledgerTitle}
|
||||
ledgerPrimaryAmount={ledgerPrimaryAmount}
|
||||
ledgerSecondaryAmount={ledgerSecondaryAmount}
|
||||
/>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
167
apps/miniapp/src/screens/balances-screen.tsx
Normal file
167
apps/miniapp/src/screens/balances-screen.tsx
Normal file
@@ -0,0 +1,167 @@
|
||||
import { For, Show } from 'solid-js'
|
||||
|
||||
import { FinanceSummaryCards } from '../components/finance/finance-summary-cards'
|
||||
import { FinanceVisuals } from '../components/finance/finance-visuals'
|
||||
import type { MiniAppDashboard } from '../miniapp-api'
|
||||
|
||||
type Props = {
|
||||
copy: Record<string, string | undefined>
|
||||
dashboard: MiniAppDashboard | null
|
||||
currentMemberLine: MiniAppDashboard['members'][number] | null
|
||||
utilityTotalMajor: string
|
||||
purchaseTotalMajor: string
|
||||
memberBalanceVisuals: {
|
||||
member: MiniAppDashboard['members'][number]
|
||||
totalMinor: bigint
|
||||
barWidthPercent: number
|
||||
segments: {
|
||||
key: string
|
||||
label: string
|
||||
amountMajor: string
|
||||
amountMinor: bigint
|
||||
widthPercent: number
|
||||
}[]
|
||||
}[]
|
||||
purchaseChart: {
|
||||
totalMajor: string
|
||||
slices: {
|
||||
key: string
|
||||
label: string
|
||||
amountMajor: string
|
||||
color: string
|
||||
percentage: number
|
||||
dasharray: string
|
||||
dashoffset: string
|
||||
}[]
|
||||
}
|
||||
memberBaseDueMajor: (member: MiniAppDashboard['members'][number]) => string
|
||||
memberRemainingClass: (member: MiniAppDashboard['members'][number]) => string
|
||||
}
|
||||
|
||||
export function BalancesScreen(props: Props) {
|
||||
if (!props.dashboard) {
|
||||
return (
|
||||
<div class="balance-list">
|
||||
<p>{props.copy.emptyDashboard ?? ''}</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div class="balance-list">
|
||||
<Show when={props.currentMemberLine}>
|
||||
{(member) => (
|
||||
<article class="balance-item balance-item--accent">
|
||||
<header>
|
||||
<strong>{props.copy.yourBalanceTitle ?? ''}</strong>
|
||||
<span>
|
||||
{member().netDueMajor} {props.dashboard!.currency}
|
||||
</span>
|
||||
</header>
|
||||
<p>{props.copy.yourBalanceBody ?? ''}</p>
|
||||
<div class="balance-breakdown">
|
||||
<article class="stat-card">
|
||||
<span>{props.copy.baseDue ?? ''}</span>
|
||||
<strong>
|
||||
{props.memberBaseDueMajor(member())} {props.dashboard!.currency}
|
||||
</strong>
|
||||
</article>
|
||||
<article class="stat-card">
|
||||
<span>{props.copy.shareOffset ?? ''}</span>
|
||||
<strong>
|
||||
{member().purchaseOffsetMajor} {props.dashboard!.currency}
|
||||
</strong>
|
||||
</article>
|
||||
<article class="stat-card">
|
||||
<span>{props.copy.finalDue ?? ''}</span>
|
||||
<strong>
|
||||
{member().netDueMajor} {props.dashboard!.currency}
|
||||
</strong>
|
||||
</article>
|
||||
<article class="stat-card">
|
||||
<span>{props.copy.paidLabel ?? ''}</span>
|
||||
<strong>
|
||||
{member().paidMajor} {props.dashboard!.currency}
|
||||
</strong>
|
||||
</article>
|
||||
<article class="stat-card">
|
||||
<span>{props.copy.remainingLabel ?? ''}</span>
|
||||
<strong>
|
||||
{member().remainingMajor} {props.dashboard!.currency}
|
||||
</strong>
|
||||
</article>
|
||||
</div>
|
||||
</article>
|
||||
)}
|
||||
</Show>
|
||||
<div class="home-grid home-grid--summary">
|
||||
<FinanceSummaryCards
|
||||
dashboard={props.dashboard}
|
||||
utilityTotalMajor={props.utilityTotalMajor}
|
||||
purchaseTotalMajor={props.purchaseTotalMajor}
|
||||
labels={{
|
||||
remaining: props.copy.remainingLabel ?? '',
|
||||
rent: props.copy.shareRent ?? '',
|
||||
utilities: props.copy.shareUtilities ?? '',
|
||||
purchases: props.copy.purchasesTitle ?? ''
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<FinanceVisuals
|
||||
dashboard={props.dashboard}
|
||||
memberVisuals={props.memberBalanceVisuals}
|
||||
purchaseChart={props.purchaseChart}
|
||||
remainingClass={props.memberRemainingClass}
|
||||
labels={{
|
||||
financeVisualsTitle: props.copy.financeVisualsTitle ?? '',
|
||||
financeVisualsBody: props.copy.financeVisualsBody ?? '',
|
||||
membersCount: props.copy.membersCount ?? '',
|
||||
purchaseInvestmentsTitle: props.copy.purchaseInvestmentsTitle ?? '',
|
||||
purchaseInvestmentsBody: props.copy.purchaseInvestmentsBody ?? '',
|
||||
purchaseInvestmentsEmpty: props.copy.purchaseInvestmentsEmpty ?? '',
|
||||
purchaseTotalLabel: props.copy.purchaseTotalLabel ?? '',
|
||||
purchaseShareLabel: props.copy.purchaseShareLabel ?? ''
|
||||
}}
|
||||
/>
|
||||
<article class="balance-item">
|
||||
<header>
|
||||
<strong>{props.copy.householdBalancesTitle ?? ''}</strong>
|
||||
</header>
|
||||
<p>{props.copy.householdBalancesBody ?? ''}</p>
|
||||
</article>
|
||||
<For each={props.dashboard.members}>
|
||||
{(member) => (
|
||||
<article class="balance-item">
|
||||
<header>
|
||||
<strong>{member.displayName}</strong>
|
||||
<span>
|
||||
{member.remainingMajor} {props.dashboard!.currency}
|
||||
</span>
|
||||
</header>
|
||||
<p>
|
||||
{props.copy.baseDue ?? ''}: {props.memberBaseDueMajor(member)}{' '}
|
||||
{props.dashboard!.currency}
|
||||
</p>
|
||||
<p>
|
||||
{props.copy.shareRent ?? ''}: {member.rentShareMajor} {props.dashboard!.currency}
|
||||
</p>
|
||||
<p>
|
||||
{props.copy.shareUtilities ?? ''}: {member.utilityShareMajor}{' '}
|
||||
{props.dashboard!.currency}
|
||||
</p>
|
||||
<p>
|
||||
{props.copy.shareOffset ?? ''}: {member.purchaseOffsetMajor}{' '}
|
||||
{props.dashboard!.currency}
|
||||
</p>
|
||||
<p>
|
||||
{props.copy.paidLabel ?? ''}: {member.paidMajor} {props.dashboard!.currency}
|
||||
</p>
|
||||
<p class={`balance-status ${props.memberRemainingClass(member)}`}>
|
||||
{props.copy.remainingLabel ?? ''}: {member.remainingMajor} {props.dashboard!.currency}
|
||||
</p>
|
||||
</article>
|
||||
)}
|
||||
</For>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
197
apps/miniapp/src/screens/home-screen.tsx
Normal file
197
apps/miniapp/src/screens/home-screen.tsx
Normal file
@@ -0,0 +1,197 @@
|
||||
import { For, Show } from 'solid-js'
|
||||
|
||||
import { FinanceSummaryCards } from '../components/finance/finance-summary-cards'
|
||||
import { FinanceVisuals } from '../components/finance/finance-visuals'
|
||||
import type { MiniAppDashboard } from '../miniapp-api'
|
||||
|
||||
type Props = {
|
||||
copy: Record<string, string | undefined>
|
||||
dashboard: MiniAppDashboard | null
|
||||
readyIsAdmin: boolean
|
||||
pendingMembersCount: number
|
||||
currentMemberLine: MiniAppDashboard['members'][number] | null
|
||||
utilityTotalMajor: string
|
||||
purchaseTotalMajor: string
|
||||
memberBalanceVisuals: {
|
||||
member: MiniAppDashboard['members'][number]
|
||||
totalMinor: bigint
|
||||
barWidthPercent: number
|
||||
segments: {
|
||||
key: string
|
||||
label: string
|
||||
amountMajor: string
|
||||
amountMinor: bigint
|
||||
widthPercent: number
|
||||
}[]
|
||||
}[]
|
||||
purchaseChart: {
|
||||
totalMajor: string
|
||||
slices: {
|
||||
key: string
|
||||
label: string
|
||||
amountMajor: string
|
||||
color: string
|
||||
percentage: number
|
||||
dasharray: string
|
||||
dashoffset: string
|
||||
}[]
|
||||
}
|
||||
memberBaseDueMajor: (member: MiniAppDashboard['members'][number]) => string
|
||||
memberRemainingClass: (member: MiniAppDashboard['members'][number]) => string
|
||||
ledgerTitle: (entry: MiniAppDashboard['ledger'][number]) => string
|
||||
ledgerPrimaryAmount: (entry: MiniAppDashboard['ledger'][number]) => string
|
||||
ledgerSecondaryAmount: (entry: MiniAppDashboard['ledger'][number]) => string | null
|
||||
}
|
||||
|
||||
export function HomeScreen(props: Props) {
|
||||
if (!props.dashboard) {
|
||||
return (
|
||||
<div class="home-grid home-grid--summary">
|
||||
<article class="stat-card">
|
||||
<span>{props.copy.remainingLabel ?? ''}</span>
|
||||
<strong>—</strong>
|
||||
</article>
|
||||
<article class="stat-card">
|
||||
<span>{props.copy.shareRent ?? ''}</span>
|
||||
<strong>—</strong>
|
||||
</article>
|
||||
<article class="stat-card">
|
||||
<span>{props.copy.shareUtilities ?? ''}</span>
|
||||
<strong>—</strong>
|
||||
</article>
|
||||
<article class="stat-card">
|
||||
<span>{props.copy.purchasesTitle ?? ''}</span>
|
||||
<strong>—</strong>
|
||||
</article>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div class="home-grid home-grid--summary">
|
||||
<FinanceSummaryCards
|
||||
dashboard={props.dashboard}
|
||||
utilityTotalMajor={props.utilityTotalMajor}
|
||||
purchaseTotalMajor={props.purchaseTotalMajor}
|
||||
labels={{
|
||||
remaining: props.copy.remainingLabel ?? '',
|
||||
rent: props.copy.shareRent ?? '',
|
||||
utilities: props.copy.shareUtilities ?? '',
|
||||
purchases: props.copy.purchasesTitle ?? ''
|
||||
}}
|
||||
/>
|
||||
<Show when={props.readyIsAdmin}>
|
||||
<article class="stat-card">
|
||||
<span>{props.copy.pendingRequests ?? ''}</span>
|
||||
<strong>{String(props.pendingMembersCount)}</strong>
|
||||
</article>
|
||||
</Show>
|
||||
|
||||
<Show
|
||||
when={props.currentMemberLine}
|
||||
fallback={
|
||||
<article class="balance-item">
|
||||
<header>
|
||||
<strong>{props.copy.overviewTitle ?? ''}</strong>
|
||||
</header>
|
||||
<p>{props.copy.overviewBody ?? ''}</p>
|
||||
</article>
|
||||
}
|
||||
>
|
||||
{(member) => (
|
||||
<article class="balance-item balance-item--accent">
|
||||
<header>
|
||||
<strong>{props.copy.yourBalanceTitle ?? ''}</strong>
|
||||
<span>
|
||||
{member().remainingMajor} {props.dashboard!.currency}
|
||||
</span>
|
||||
</header>
|
||||
<p>{props.copy.yourBalanceBody ?? ''}</p>
|
||||
<p>
|
||||
{props.copy.shareRent ?? ''}: {props.dashboard!.rentSourceAmountMajor}{' '}
|
||||
{props.dashboard!.rentSourceCurrency}
|
||||
{props.dashboard!.rentSourceCurrency !== props.dashboard!.currency
|
||||
? ` -> ${props.dashboard!.rentDisplayAmountMajor} ${props.dashboard!.currency}`
|
||||
: ''}
|
||||
</p>
|
||||
<div class="balance-breakdown">
|
||||
<article class="stat-card">
|
||||
<span>{props.copy.baseDue ?? ''}</span>
|
||||
<strong>
|
||||
{props.memberBaseDueMajor(member())} {props.dashboard!.currency}
|
||||
</strong>
|
||||
</article>
|
||||
<article class="stat-card">
|
||||
<span>{props.copy.shareOffset ?? ''}</span>
|
||||
<strong>
|
||||
{member().purchaseOffsetMajor} {props.dashboard!.currency}
|
||||
</strong>
|
||||
</article>
|
||||
<article class="stat-card">
|
||||
<span>{props.copy.finalDue ?? ''}</span>
|
||||
<strong>
|
||||
{member().netDueMajor} {props.dashboard!.currency}
|
||||
</strong>
|
||||
</article>
|
||||
<article class="stat-card">
|
||||
<span>{props.copy.paidLabel ?? ''}</span>
|
||||
<strong>
|
||||
{member().paidMajor} {props.dashboard!.currency}
|
||||
</strong>
|
||||
</article>
|
||||
<article class="stat-card">
|
||||
<span>{props.copy.remainingLabel ?? ''}</span>
|
||||
<strong>
|
||||
{member().remainingMajor} {props.dashboard!.currency}
|
||||
</strong>
|
||||
</article>
|
||||
</div>
|
||||
</article>
|
||||
)}
|
||||
</Show>
|
||||
|
||||
<FinanceVisuals
|
||||
dashboard={props.dashboard}
|
||||
memberVisuals={props.memberBalanceVisuals}
|
||||
purchaseChart={props.purchaseChart}
|
||||
remainingClass={props.memberRemainingClass}
|
||||
labels={{
|
||||
financeVisualsTitle: props.copy.financeVisualsTitle ?? '',
|
||||
financeVisualsBody: props.copy.financeVisualsBody ?? '',
|
||||
membersCount: props.copy.membersCount ?? '',
|
||||
purchaseInvestmentsTitle: props.copy.purchaseInvestmentsTitle ?? '',
|
||||
purchaseInvestmentsBody: props.copy.purchaseInvestmentsBody ?? '',
|
||||
purchaseInvestmentsEmpty: props.copy.purchaseInvestmentsEmpty ?? '',
|
||||
purchaseTotalLabel: props.copy.purchaseTotalLabel ?? '',
|
||||
purchaseShareLabel: props.copy.purchaseShareLabel ?? ''
|
||||
}}
|
||||
/>
|
||||
|
||||
<article class="balance-item balance-item--wide">
|
||||
<header>
|
||||
<strong>{props.copy.latestActivityTitle ?? ''}</strong>
|
||||
</header>
|
||||
{props.dashboard.ledger.length === 0 ? (
|
||||
<p>{props.copy.latestActivityEmpty ?? ''}</p>
|
||||
) : (
|
||||
<div class="activity-list">
|
||||
<For each={props.dashboard.ledger.slice(0, 3)}>
|
||||
{(entry) => (
|
||||
<article class="activity-row">
|
||||
<header>
|
||||
<strong>{props.ledgerTitle(entry)}</strong>
|
||||
<span>{props.ledgerPrimaryAmount(entry)}</span>
|
||||
</header>
|
||||
<Show when={props.ledgerSecondaryAmount(entry)}>
|
||||
{(secondary) => <p>{secondary()}</p>}
|
||||
</Show>
|
||||
<p>{entry.actorDisplayName ?? props.copy.ledgerActorFallback ?? ''}</p>
|
||||
</article>
|
||||
)}
|
||||
</For>
|
||||
</div>
|
||||
)}
|
||||
</article>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user