feat(miniapp): add admin billing settings foundation

This commit is contained in:
2026-03-10 01:38:03 +04:00
parent 4797e4f200
commit 565ac277c1
26 changed files with 5061 additions and 11 deletions

View File

@@ -34,6 +34,32 @@ export interface MiniAppPendingMember {
languageCode: string | null
}
export interface MiniAppMember {
id: string
displayName: string
isAdmin: boolean
}
export interface MiniAppBillingSettings {
householdId: string
rentAmountMinor: string | null
rentCurrency: 'USD' | 'GEL'
rentDueDay: number
rentWarningDay: number
utilitiesDueDay: number
utilitiesReminderDay: number
timezone: string
}
export interface MiniAppUtilityCategory {
id: string
householdId: string
slug: string
name: string
sortOrder: number
isActive: boolean
}
export interface MiniAppDashboard {
period: string
currency: 'USD' | 'GEL'
@@ -57,6 +83,12 @@ export interface MiniAppDashboard {
}[]
}
export interface MiniAppAdminSettingsPayload {
settings: MiniAppBillingSettings
categories: readonly MiniAppUtilityCategory[]
members: readonly MiniAppMember[]
}
function apiBaseUrl(): string {
const runtimeConfigured = runtimeBotApiUrl()
if (runtimeConfigured) {
@@ -260,3 +292,142 @@ export async function updateMiniAppLocalePreference(
return payload.locale
}
export async function fetchMiniAppAdminSettings(
initData: string
): Promise<MiniAppAdminSettingsPayload> {
const response = await fetch(`${apiBaseUrl()}/api/miniapp/admin/settings`, {
method: 'POST',
headers: {
'content-type': 'application/json'
},
body: JSON.stringify({
initData
})
})
const payload = (await response.json()) as {
ok: boolean
authorized?: boolean
settings?: MiniAppBillingSettings
categories?: MiniAppUtilityCategory[]
members?: MiniAppMember[]
error?: string
}
if (
!response.ok ||
!payload.authorized ||
!payload.settings ||
!payload.categories ||
!payload.members
) {
throw new Error(payload.error ?? 'Failed to load admin settings')
}
return {
settings: payload.settings,
categories: payload.categories,
members: payload.members
}
}
export async function updateMiniAppBillingSettings(
initData: string,
input: {
rentAmountMajor?: string
rentCurrency: 'USD' | 'GEL'
rentDueDay: number
rentWarningDay: number
utilitiesDueDay: number
utilitiesReminderDay: number
timezone: string
}
): Promise<MiniAppBillingSettings> {
const response = await fetch(`${apiBaseUrl()}/api/miniapp/admin/settings/update`, {
method: 'POST',
headers: {
'content-type': 'application/json'
},
body: JSON.stringify({
initData,
...input
})
})
const payload = (await response.json()) as {
ok: boolean
authorized?: boolean
settings?: MiniAppBillingSettings
error?: string
}
if (!response.ok || !payload.authorized || !payload.settings) {
throw new Error(payload.error ?? 'Failed to update billing settings')
}
return payload.settings
}
export async function upsertMiniAppUtilityCategory(
initData: string,
input: {
slug?: string
name: string
sortOrder: number
isActive: boolean
}
): Promise<MiniAppUtilityCategory> {
const response = await fetch(`${apiBaseUrl()}/api/miniapp/admin/utility-categories/upsert`, {
method: 'POST',
headers: {
'content-type': 'application/json'
},
body: JSON.stringify({
initData,
...input
})
})
const payload = (await response.json()) as {
ok: boolean
authorized?: boolean
category?: MiniAppUtilityCategory
error?: string
}
if (!response.ok || !payload.authorized || !payload.category) {
throw new Error(payload.error ?? 'Failed to save utility category')
}
return payload.category
}
export async function promoteMiniAppMember(
initData: string,
memberId: string
): Promise<MiniAppMember> {
const response = await fetch(`${apiBaseUrl()}/api/miniapp/admin/members/promote`, {
method: 'POST',
headers: {
'content-type': 'application/json'
},
body: JSON.stringify({
initData,
memberId
})
})
const payload = (await response.json()) as {
ok: boolean
authorized?: boolean
member?: MiniAppMember
error?: string
}
if (!response.ok || !payload.authorized || !payload.member) {
throw new Error(payload.error ?? 'Failed to promote member')
}
return payload.member
}