50 lines
1.6 KiB
TypeScript
50 lines
1.6 KiB
TypeScript
import { fetchApi } from '@/api/client'
|
|
|
|
export type Household = { id: number; name: string; slug: string }
|
|
|
|
function isHousehold(value: unknown): value is Household {
|
|
return (
|
|
typeof value === 'object' && value !== null &&
|
|
typeof (value as { id: unknown }).id === 'number' &&
|
|
typeof (value as { name: unknown }).name === 'string' &&
|
|
typeof (value as { slug: unknown }).slug === 'string'
|
|
)
|
|
}
|
|
|
|
async function safeJson<T>(resp: Response): Promise<T | null> {
|
|
try {
|
|
const d = await resp.json()
|
|
return d as T
|
|
} catch (_e) {
|
|
return null
|
|
}
|
|
}
|
|
|
|
export async function acceptInvitation(token: string): Promise<Household> {
|
|
const resp = await fetchApi('/api/v1/invitations/accept', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ token }),
|
|
})
|
|
if (!resp.ok) throw new Error(`${resp.status} ${resp.statusText || 'HTTP error'}`)
|
|
const data = await safeJson<{ household?: unknown }>(resp)
|
|
let h: unknown
|
|
if (data && typeof data === 'object' && 'household' in data) {
|
|
h = (data as { household?: unknown }).household
|
|
} else {
|
|
h = undefined
|
|
}
|
|
if (!isHousehold(h)) {
|
|
throw new Error('Invalid invitation accept response')
|
|
}
|
|
return { id: h.id, name: h.name, slug: h.slug }
|
|
}
|
|
|
|
export async function sendInvitation(email: string): Promise<void> {
|
|
const resp = await fetchApi('/api/v1/invitations', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ email }),
|
|
})
|
|
if (!resp.ok && resp.status !== 204) throw new Error(`${resp.status} ${resp.statusText || 'HTTP error'}`)
|
|
}
|