mirror of
https://github.com/whekin/household-bot.git
synced 2026-03-31 12:04:02 +00:00
refactor(miniapp): extract shell states and finance visuals
This commit is contained in:
@@ -42,6 +42,9 @@ 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 {
|
||||
demoAdminSettings,
|
||||
demoCycleState,
|
||||
@@ -3760,16 +3763,16 @@ function App() {
|
||||
|
||||
<Switch>
|
||||
<Match when={session().status === 'loading'}>
|
||||
<HeroBanner
|
||||
badges={[copy().loadingBadge]}
|
||||
<LoadingState
|
||||
badge={copy().loadingBadge}
|
||||
title={copy().loadingTitle}
|
||||
body={copy().loadingBody}
|
||||
/>
|
||||
</Match>
|
||||
|
||||
<Match when={session().status === 'blocked'}>
|
||||
<HeroBanner
|
||||
badges={[copy().loadingBadge]}
|
||||
<BlockedState
|
||||
badge={copy().loadingBadge}
|
||||
title={
|
||||
blockedSession()?.reason === 'telegram_only'
|
||||
? copy().telegramOnlyTitle
|
||||
@@ -3780,24 +3783,23 @@ function App() {
|
||||
? copy().telegramOnlyBody
|
||||
: copy().unexpectedErrorBody
|
||||
}
|
||||
action={{ label: copy().reload, onClick: () => window.location.reload() }}
|
||||
reloadLabel={copy().reload}
|
||||
onReload={() => window.location.reload()}
|
||||
/>
|
||||
</Match>
|
||||
|
||||
<Match when={session().status === 'onboarding'}>
|
||||
<section class="hero-card">
|
||||
<div class="hero-card__meta">
|
||||
<span class="pill">{copy().loadingBadge}</span>
|
||||
</div>
|
||||
<h2>
|
||||
{onboardingSession()?.mode === 'pending'
|
||||
<OnboardingState
|
||||
badge={copy().loadingBadge}
|
||||
title={
|
||||
onboardingSession()?.mode === 'pending'
|
||||
? copy().pendingTitle
|
||||
: onboardingSession()?.mode === 'open_from_group'
|
||||
? copy().openFromGroupTitle
|
||||
: copy().joinTitle}
|
||||
</h2>
|
||||
<p>
|
||||
{onboardingSession()?.mode === 'pending'
|
||||
: copy().joinTitle
|
||||
}
|
||||
body={
|
||||
onboardingSession()?.mode === 'pending'
|
||||
? copy().pendingBody.replace(
|
||||
'{household}',
|
||||
onboardingSession()?.householdName ?? copy().householdFallback
|
||||
@@ -3807,29 +3809,18 @@ function App() {
|
||||
: copy().joinBody.replace(
|
||||
'{household}',
|
||||
onboardingSession()?.householdName ?? copy().householdFallback
|
||||
)}
|
||||
</p>
|
||||
<div class="nav-grid">
|
||||
{onboardingSession()?.mode === 'join_required' ? (
|
||||
<Button variant="ghost" disabled={joining()} onClick={handleJoinHousehold}>
|
||||
{joining() ? copy().joining : copy().joinAction}
|
||||
</Button>
|
||||
) : null}
|
||||
{joinDeepLink() ? (
|
||||
<a
|
||||
class="ui-button ui-button--ghost"
|
||||
href={joinDeepLink() ?? '#'}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
{copy().botLinkAction}
|
||||
</a>
|
||||
) : null}
|
||||
<Button variant="ghost" onClick={() => window.location.reload()}>
|
||||
{copy().reload}
|
||||
</Button>
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
canJoin={onboardingSession()?.mode === 'join_required'}
|
||||
joining={joining()}
|
||||
joinActionLabel={copy().joinAction}
|
||||
joiningLabel={copy().joining}
|
||||
botLinkLabel={copy().botLinkAction}
|
||||
botLink={joinDeepLink()}
|
||||
reloadLabel={copy().reload}
|
||||
onJoin={handleJoinHousehold}
|
||||
onReload={() => window.location.reload()}
|
||||
/>
|
||||
</Match>
|
||||
|
||||
<Match when={session().status === 'ready'}>
|
||||
|
||||
@@ -129,10 +129,8 @@ export function FinanceVisuals(props: Props) {
|
||||
</For>
|
||||
</svg>
|
||||
<div class="purchase-chart__center">
|
||||
<span>{props.labels.purchaseTotalLabel}</span>
|
||||
<strong>
|
||||
{props.purchaseChart.totalMajor} {props.dashboard.currency}
|
||||
</strong>
|
||||
<strong>{props.purchaseChart.totalMajor}</strong>
|
||||
<small>{props.dashboard.currency}</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="purchase-chart__legend">
|
||||
|
||||
20
apps/miniapp/src/components/session/blocked-state.tsx
Normal file
20
apps/miniapp/src/components/session/blocked-state.tsx
Normal file
@@ -0,0 +1,20 @@
|
||||
import { HeroBanner } from '../layout/hero-banner'
|
||||
|
||||
type Props = {
|
||||
badge: string
|
||||
title: string
|
||||
body: string
|
||||
reloadLabel: string
|
||||
onReload: () => void
|
||||
}
|
||||
|
||||
export function BlockedState(props: Props) {
|
||||
return (
|
||||
<HeroBanner
|
||||
badges={[props.badge]}
|
||||
title={props.title}
|
||||
body={props.body}
|
||||
action={{ label: props.reloadLabel, onClick: props.onReload }}
|
||||
/>
|
||||
)
|
||||
}
|
||||
11
apps/miniapp/src/components/session/loading-state.tsx
Normal file
11
apps/miniapp/src/components/session/loading-state.tsx
Normal file
@@ -0,0 +1,11 @@
|
||||
import { HeroBanner } from '../layout/hero-banner'
|
||||
|
||||
type Props = {
|
||||
badge: string
|
||||
title: string
|
||||
body: string
|
||||
}
|
||||
|
||||
export function LoadingState(props: Props) {
|
||||
return <HeroBanner badges={[props.badge]} title={props.title} body={props.body} />
|
||||
}
|
||||
47
apps/miniapp/src/components/session/onboarding-state.tsx
Normal file
47
apps/miniapp/src/components/session/onboarding-state.tsx
Normal file
@@ -0,0 +1,47 @@
|
||||
import { Show } from 'solid-js'
|
||||
|
||||
import { Button } from '../ui'
|
||||
|
||||
type Props = {
|
||||
badge: string
|
||||
title: string
|
||||
body: string
|
||||
joinActionLabel: string
|
||||
joiningLabel: string
|
||||
joining: boolean
|
||||
canJoin: boolean
|
||||
botLinkLabel: string
|
||||
botLink: string | null
|
||||
reloadLabel: string
|
||||
onJoin: () => void
|
||||
onReload: () => void
|
||||
}
|
||||
|
||||
export function OnboardingState(props: Props) {
|
||||
return (
|
||||
<section class="hero-card">
|
||||
<div class="hero-card__meta">
|
||||
<span class="pill">{props.badge}</span>
|
||||
</div>
|
||||
<h2>{props.title}</h2>
|
||||
<p>{props.body}</p>
|
||||
<div class="nav-grid">
|
||||
<Show when={props.canJoin}>
|
||||
<Button variant="ghost" disabled={props.joining} onClick={props.onJoin}>
|
||||
{props.joining ? props.joiningLabel : props.joinActionLabel}
|
||||
</Button>
|
||||
</Show>
|
||||
<Show when={props.botLink}>
|
||||
{(link) => (
|
||||
<a class="ui-button ui-button--ghost" href={link()} target="_blank" rel="noreferrer">
|
||||
{props.botLinkLabel}
|
||||
</a>
|
||||
)}
|
||||
</Show>
|
||||
<Button variant="ghost" onClick={props.onReload}>
|
||||
{props.reloadLabel}
|
||||
</Button>
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
@@ -493,20 +493,21 @@ button {
|
||||
inset: 0;
|
||||
display: grid;
|
||||
place-content: center;
|
||||
gap: 4px;
|
||||
gap: 2px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.purchase-chart__center span {
|
||||
color: #c6c2bb;
|
||||
font-size: 0.72rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.08em;
|
||||
}
|
||||
|
||||
.purchase-chart__center strong {
|
||||
font-family: 'Space Grotesk', 'IBM Plex Sans', sans-serif;
|
||||
font-size: clamp(1.15rem, 4vw, 1.5rem);
|
||||
font-size: clamp(1.1rem, 4vw, 1.45rem);
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.purchase-chart__center small {
|
||||
color: #c6c2bb;
|
||||
font-size: 0.72rem;
|
||||
letter-spacing: 0.08em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.purchase-chart__legend {
|
||||
|
||||
Reference in New Issue
Block a user