mirror of
https://github.com/whekin/household-bot.git
synced 2026-03-31 10:24:02 +00:00
refactor(miniapp): remove placeholder shell cards
This commit is contained in:
@@ -107,6 +107,14 @@ function joinDeepLink(): string | null {
|
||||
return `https://t.me/${context.botUsername}?start=join_${encodeURIComponent(context.joinToken)}`
|
||||
}
|
||||
|
||||
function dashboardMemberCount(dashboard: MiniAppDashboard | null): string {
|
||||
return dashboard ? String(dashboard.members.length) : '—'
|
||||
}
|
||||
|
||||
function dashboardLedgerCount(dashboard: MiniAppDashboard | null): string {
|
||||
return dashboard ? String(dashboard.ledger.length) : '—'
|
||||
}
|
||||
|
||||
function App() {
|
||||
const [locale, setLocale] = createSignal<Locale>('en')
|
||||
const [session, setSession] = createSignal<SessionState>({
|
||||
@@ -479,6 +487,12 @@ function App() {
|
||||
case 'house':
|
||||
return readySession()?.member.isAdmin ? (
|
||||
<div class="balance-list">
|
||||
<article class="balance-item">
|
||||
<header>
|
||||
<strong>{copy().householdSettingsTitle}</strong>
|
||||
</header>
|
||||
<p>{copy().householdSettingsBody}</p>
|
||||
</article>
|
||||
<article class="balance-item">
|
||||
<header>
|
||||
<strong>{copy().householdLanguage}</strong>
|
||||
@@ -544,22 +558,75 @@ function App() {
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
copy().houseEmpty
|
||||
<div class="balance-list">
|
||||
<article class="balance-item">
|
||||
<header>
|
||||
<strong>{copy().residentHouseTitle}</strong>
|
||||
</header>
|
||||
<p>{copy().residentHouseBody}</p>
|
||||
</article>
|
||||
</div>
|
||||
)
|
||||
default:
|
||||
return (
|
||||
<ShowDashboard
|
||||
dashboard={dashboard()}
|
||||
fallback={<p>{copy().summaryBody}</p>}
|
||||
render={(data) => (
|
||||
<>
|
||||
<p>
|
||||
{copy().totalDue}: {data.totalDueMajor} {data.currency}
|
||||
</p>
|
||||
<p>{copy().summaryBody}</p>
|
||||
</>
|
||||
)}
|
||||
/>
|
||||
<div class="home-grid">
|
||||
<article class="stat-card">
|
||||
<span>{copy().totalDue}</span>
|
||||
<strong>
|
||||
{dashboard() ? `${dashboard()!.totalDueMajor} ${dashboard()!.currency}` : '—'}
|
||||
</strong>
|
||||
</article>
|
||||
<article class="stat-card">
|
||||
<span>{copy().membersCount}</span>
|
||||
<strong>{dashboardMemberCount(dashboard())}</strong>
|
||||
</article>
|
||||
<article class="stat-card">
|
||||
<span>{copy().ledgerEntries}</span>
|
||||
<strong>{dashboardLedgerCount(dashboard())}</strong>
|
||||
</article>
|
||||
{readySession()?.member.isAdmin ? (
|
||||
<article class="stat-card">
|
||||
<span>{copy().pendingRequests}</span>
|
||||
<strong>{String(pendingMembers().length)}</strong>
|
||||
</article>
|
||||
) : null}
|
||||
|
||||
<article class="balance-item">
|
||||
<header>
|
||||
<strong>{copy().overviewTitle}</strong>
|
||||
</header>
|
||||
<p>{copy().overviewBody}</p>
|
||||
</article>
|
||||
|
||||
<article class="balance-item">
|
||||
<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="ledger-list">
|
||||
{data.ledger.slice(0, 3).map((entry) => (
|
||||
<article class="ledger-item">
|
||||
<header>
|
||||
<strong>{entry.title}</strong>
|
||||
<span>
|
||||
{entry.amountMajor} {data.currency}
|
||||
</span>
|
||||
</header>
|
||||
<p>{entry.actorDisplayName ?? 'Household'}</p>
|
||||
</article>
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
/>
|
||||
</article>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -601,7 +668,7 @@ function App() {
|
||||
<Switch>
|
||||
<Match when={session().status === 'loading'}>
|
||||
<section class="hero-card">
|
||||
<span class="pill">{copy().navHint}</span>
|
||||
<span class="pill">{copy().loadingBadge}</span>
|
||||
<h2>{copy().loadingTitle}</h2>
|
||||
<p>{copy().loadingBody}</p>
|
||||
</section>
|
||||
@@ -609,7 +676,7 @@ function App() {
|
||||
|
||||
<Match when={session().status === 'blocked'}>
|
||||
<section class="hero-card">
|
||||
<span class="pill">{copy().navHint}</span>
|
||||
<span class="pill">{copy().loadingBadge}</span>
|
||||
<h2>
|
||||
{blockedSession()?.reason === 'telegram_only'
|
||||
? copy().telegramOnlyTitle
|
||||
@@ -628,7 +695,7 @@ function App() {
|
||||
|
||||
<Match when={session().status === 'onboarding'}>
|
||||
<section class="hero-card">
|
||||
<span class="pill">{copy().navHint}</span>
|
||||
<span class="pill">{copy().loadingBadge}</span>
|
||||
<h2>
|
||||
{onboardingSession()?.mode === 'pending'
|
||||
? copy().pendingTitle
|
||||
@@ -681,7 +748,7 @@ function App() {
|
||||
<section class="hero-card">
|
||||
<div class="hero-card__meta">
|
||||
<span class="pill">
|
||||
{readySession()?.mode === 'demo' ? copy().demoBadge : copy().navHint}
|
||||
{readySession()?.mode === 'demo' ? copy().demoBadge : copy().liveBadge}
|
||||
</span>
|
||||
<span class="pill pill--muted">
|
||||
{readySession()?.member.isAdmin ? copy().adminTag : copy().residentTag}
|
||||
@@ -692,7 +759,7 @@ function App() {
|
||||
{copy().welcome},{' '}
|
||||
{readySession()?.telegramUser.firstName ?? readySession()?.member.displayName}
|
||||
</h2>
|
||||
<p>{copy().sectionBody}</p>
|
||||
<p>{copy().overviewBody}</p>
|
||||
</section>
|
||||
|
||||
<nav class="nav-grid">
|
||||
@@ -716,25 +783,10 @@ function App() {
|
||||
|
||||
<section class="content-grid">
|
||||
<article class="panel panel--wide">
|
||||
<p class="eyebrow">{copy().summaryTitle}</p>
|
||||
<p class="eyebrow">{copy().overviewTitle}</p>
|
||||
<h3>{readySession()?.member.displayName}</h3>
|
||||
<div>{renderPanel()}</div>
|
||||
</article>
|
||||
|
||||
<article class="panel">
|
||||
<p class="eyebrow">{copy().cardAccess}</p>
|
||||
<p>{copy().cardAccessBody}</p>
|
||||
</article>
|
||||
|
||||
<article class="panel">
|
||||
<p class="eyebrow">{copy().cardLocale}</p>
|
||||
<p>{copy().cardLocaleBody}</p>
|
||||
</article>
|
||||
|
||||
<article class="panel">
|
||||
<p class="eyebrow">{copy().cardNext}</p>
|
||||
<p>{copy().cardNextBody}</p>
|
||||
</article>
|
||||
</section>
|
||||
</Match>
|
||||
</Switch>
|
||||
|
||||
@@ -6,7 +6,9 @@ export const dictionary = {
|
||||
appSubtitle: 'Shared home dashboard',
|
||||
loadingTitle: 'Checking your household access',
|
||||
loadingBody: 'Validating Telegram session and membership…',
|
||||
loadingBadge: 'Secure session',
|
||||
demoBadge: 'Demo mode',
|
||||
liveBadge: 'Live household',
|
||||
joinTitle: 'Welcome to your household',
|
||||
joinBody:
|
||||
'You are not a member of {household} yet. Send a join request and wait for admin approval.',
|
||||
@@ -33,28 +35,28 @@ export const dictionary = {
|
||||
balances: 'Balances',
|
||||
ledger: 'Ledger',
|
||||
house: 'House',
|
||||
navHint: 'Shell v1',
|
||||
welcome: 'Welcome back',
|
||||
adminTag: 'Admin',
|
||||
residentTag: 'Resident',
|
||||
summaryTitle: 'Current shell',
|
||||
summaryBody:
|
||||
'Balances, ledger, and house wiki will land in the next tickets. This shell focuses on verified access, navigation, and mobile layout.',
|
||||
overviewTitle: 'Current cycle',
|
||||
overviewBody:
|
||||
'Use the sections below to review balances, ledger entries, and household access.',
|
||||
totalDue: 'Total due',
|
||||
membersCount: 'Members',
|
||||
ledgerEntries: 'Ledger entries',
|
||||
pendingRequests: 'Pending requests',
|
||||
shareRent: 'Rent',
|
||||
shareUtilities: 'Utilities',
|
||||
shareOffset: 'Shared buys',
|
||||
ledgerTitle: 'Included ledger',
|
||||
emptyDashboard: 'No billing cycle is ready yet.',
|
||||
cardAccess: 'Access',
|
||||
cardAccessBody: 'Telegram identity verified and matched to a household member.',
|
||||
cardLocale: 'Locale',
|
||||
cardLocaleBody: 'Switch RU/EN immediately without reloading the shell.',
|
||||
cardNext: 'Next up',
|
||||
cardNextBody: 'Balances, ledger, and house pages will plug into this navigation.',
|
||||
sectionTitle: 'Ready for the next features',
|
||||
sectionBody:
|
||||
'This layout is intentionally narrow and mobile-first so it behaves well inside the Telegram webview.',
|
||||
latestActivityTitle: 'Latest activity',
|
||||
latestActivityEmpty: 'Recent utility and purchase entries will appear here.',
|
||||
householdSettingsTitle: 'Household settings',
|
||||
householdSettingsBody: 'Control household defaults and approve roommates who requested access.',
|
||||
residentHouseTitle: 'Household access',
|
||||
residentHouseBody:
|
||||
'Your admins manage household settings and approvals here. You can still switch your own language above.',
|
||||
pendingMembersTitle: 'Pending members',
|
||||
pendingMembersBody:
|
||||
'Approve roommates here after they request access from the group join flow.',
|
||||
@@ -64,14 +66,16 @@ export const dictionary = {
|
||||
pendingMemberHandle: '@{username}',
|
||||
balancesEmpty: 'Balances will appear here once the dashboard API lands.',
|
||||
ledgerEmpty: 'Ledger entries will appear here after the finance view is connected.',
|
||||
houseEmpty: 'House rules, Wi-Fi info, and practical notes will live here.'
|
||||
houseEmpty: 'Household details will appear here.'
|
||||
},
|
||||
ru: {
|
||||
appTitle: 'Kojori House',
|
||||
appSubtitle: 'Панель общего дома',
|
||||
loadingTitle: 'Проверяем доступ к дому',
|
||||
loadingBody: 'Проверяем Telegram-сессию и членство…',
|
||||
loadingBadge: 'Защищённая сессия',
|
||||
demoBadge: 'Демо режим',
|
||||
liveBadge: 'Живой household',
|
||||
joinTitle: 'Добро пожаловать домой',
|
||||
joinBody:
|
||||
'Ты пока не участник {household}. Отправь заявку на вступление и дождись подтверждения админа.',
|
||||
@@ -98,28 +102,27 @@ export const dictionary = {
|
||||
balances: 'Баланс',
|
||||
ledger: 'Леджер',
|
||||
house: 'Дом',
|
||||
navHint: 'Shell v1',
|
||||
welcome: 'С возвращением',
|
||||
adminTag: 'Админ',
|
||||
residentTag: 'Житель',
|
||||
summaryTitle: 'Текущая оболочка',
|
||||
summaryBody:
|
||||
'Баланс, леджер и вики дома появятся в следующих тикетах. Сейчас приоритет — проверенный доступ, навигация и мобильный layout.',
|
||||
overviewTitle: 'Текущий цикл',
|
||||
overviewBody: 'Ниже можно посмотреть балансы, записи леджера и доступ к household.',
|
||||
totalDue: 'Итого к оплате',
|
||||
membersCount: 'Участники',
|
||||
ledgerEntries: 'Записи леджера',
|
||||
pendingRequests: 'Ожидают подтверждения',
|
||||
shareRent: 'Аренда',
|
||||
shareUtilities: 'Коммуналка',
|
||||
shareOffset: 'Общие покупки',
|
||||
ledgerTitle: 'Вошедшие операции',
|
||||
emptyDashboard: 'Пока нет готового billing cycle.',
|
||||
cardAccess: 'Доступ',
|
||||
cardAccessBody: 'Telegram-личность подтверждена и сопоставлена с участником household.',
|
||||
cardLocale: 'Локаль',
|
||||
cardLocaleBody: 'RU/EN переключаются сразу, без перезагрузки.',
|
||||
cardNext: 'Дальше',
|
||||
cardNextBody: 'Баланс, леджер и страницы дома подключатся к этой навигации.',
|
||||
sectionTitle: 'Основа готова для следующих функций',
|
||||
sectionBody:
|
||||
'Этот layout специально сделан узким и mobile-first, чтобы хорошо жить внутри Telegram webview.',
|
||||
latestActivityTitle: 'Последняя активность',
|
||||
latestActivityEmpty: 'Здесь появятся последние коммунальные платежи и покупки.',
|
||||
householdSettingsTitle: 'Настройки household',
|
||||
householdSettingsBody: 'Здесь можно менять язык household и подтверждать новых соседей.',
|
||||
residentHouseTitle: 'Доступ к household',
|
||||
residentHouseBody:
|
||||
'Настройки household и подтверждение заявок управляются админами. Свой язык можно менять переключателем выше.',
|
||||
pendingMembersTitle: 'Ожидающие участники',
|
||||
pendingMembersBody:
|
||||
'Подтверждай соседей здесь после того, как они отправят заявку через кнопку подключения.',
|
||||
@@ -129,6 +132,6 @@ export const dictionary = {
|
||||
pendingMemberHandle: '@{username}',
|
||||
balancesEmpty: 'Баланс появится здесь, когда подключим dashboard API.',
|
||||
ledgerEmpty: 'Записи леджера появятся здесь после подключения finance view.',
|
||||
houseEmpty: 'Правила дома, Wi-Fi и полезные инструкции будут здесь.'
|
||||
houseEmpty: 'Детали household появятся здесь.'
|
||||
}
|
||||
} satisfies Record<Locale, Record<string, string>>
|
||||
|
||||
@@ -228,13 +228,15 @@ button {
|
||||
}
|
||||
|
||||
.balance-list,
|
||||
.ledger-list {
|
||||
.ledger-list,
|
||||
.home-grid {
|
||||
display: grid;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.balance-item,
|
||||
.ledger-item {
|
||||
.ledger-item,
|
||||
.stat-card {
|
||||
border: 1px solid rgb(255 255 255 / 0.08);
|
||||
border-radius: 18px;
|
||||
padding: 14px;
|
||||
@@ -260,6 +262,27 @@ button {
|
||||
margin-top: 6px;
|
||||
}
|
||||
|
||||
.home-grid {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.stat-card {
|
||||
display: grid;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.stat-card span {
|
||||
color: #c6c2bb;
|
||||
font-size: 0.82rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.08em;
|
||||
}
|
||||
|
||||
.stat-card strong {
|
||||
font-family: 'Space Grotesk', 'IBM Plex Sans', sans-serif;
|
||||
font-size: clamp(1.2rem, 4vw, 1.7rem);
|
||||
}
|
||||
|
||||
.panel--wide {
|
||||
min-height: 170px;
|
||||
}
|
||||
@@ -275,6 +298,10 @@ button {
|
||||
grid-template-columns: 1.3fr 1fr 1fr;
|
||||
}
|
||||
|
||||
.home-grid {
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.panel--wide {
|
||||
grid-column: 1 / -1;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user