feat: add quick payment action and improve copy button UX

Mini App Home Screen:
- Add 'Record Payment' button to utilities and rent period cards
- Pre-fill payment amount with member's share (rentShare/utilityShare)
- Modal dialog with amount input and currency display
- Toast notifications for copy and payment success/failure feedback

Copy Button Improvements:
- Increase spacing between icon and text (4px → 8px)
- Add hover background and padding for better touch target
- Green background highlight when copied (in addition to icon color change)
- Toast notification appears when copying any value

Backend:
- Add /api/miniapp/payments/add endpoint for quick payments
- Payment notifications sent to 'reminders' topic in Telegram
- Include member name, payment type, amount, and period in notification

Files:
- New: apps/miniapp/src/components/ui/toast.tsx
- Modified: apps/miniapp/src/routes/home.tsx, apps/miniapp/src/index.css,
  apps/miniapp/src/theme.css, apps/miniapp/src/i18n.ts,
  apps/bot/src/miniapp-billing.ts, apps/bot/src/server.ts

Quality Gates:  format, lint, typecheck, build, test

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
2026-03-14 08:51:53 +04:00
parent 771d64aa4e
commit 488a488137
45 changed files with 2236 additions and 101 deletions

View File

@@ -69,6 +69,16 @@ export interface MiniAppBillingSettings {
utilitiesDueDay: number
utilitiesReminderDay: number
timezone: string
rentPaymentDestinations: readonly MiniAppRentPaymentDestination[] | null
}
export interface MiniAppRentPaymentDestination {
label: string
recipientName: string | null
bankName: string | null
account: string
note: string | null
link: string | null
}
export interface MiniAppAssistantConfig {
@@ -96,9 +106,12 @@ export interface MiniAppDashboard {
period: string
currency: 'USD' | 'GEL'
timezone: string
rentWarningDay: number
rentDueDay: number
utilitiesReminderDay: number
utilitiesDueDay: number
paymentBalanceAdjustmentPolicy: 'utilities' | 'rent' | 'separate'
rentPaymentDestinations: readonly MiniAppRentPaymentDestination[] | null
totalDueMajor: string
totalPaidMajor: string
totalRemainingMajor: string
@@ -466,6 +479,7 @@ export async function updateMiniAppBillingSettings(
utilitiesDueDay: number
utilitiesReminderDay: number
timezone: string
rentPaymentDestinations?: readonly MiniAppRentPaymentDestination[] | null
assistantContext?: string
assistantTone?: string
}
@@ -883,6 +897,36 @@ export async function addMiniAppUtilityBill(
return payload.cycleState
}
export async function submitMiniAppUtilityBill(
initData: string,
input: {
billName: string
amountMajor: string
currency: 'USD' | 'GEL'
}
): Promise<void> {
const response = await fetch(`${apiBaseUrl()}/api/miniapp/utility-bills/add`, {
method: 'POST',
headers: {
'content-type': 'application/json'
},
body: JSON.stringify({
initData,
...input
})
})
const payload = (await response.json()) as {
ok: boolean
authorized?: boolean
error?: string
}
if (!response.ok || !payload.authorized) {
throw new Error(payload.error ?? 'Failed to submit utility bill')
}
}
export async function updateMiniAppUtilityBill(
initData: string,
input: {