File size: 2,543 Bytes
5960fdf
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
export type PlaceItem = {
  code: string
  name: string
}

export type CreateBirthProfileRequest = {
  name: string
  birth_date: string
  birth_time?: string | null
  time_confidence: 'exact' | 'approximate' | 'unknown' | 'rectified'
  birth_place_adcode?: string | null
  birth_place?: string | null
}

export type CreateBirthProfileResponse = {
  profile_id: string
  resolved_location: { lat: number; lng: number; timezone: string }
}

export type CreateNatalChartRequest = {
  profile_id: string
  calculation_profile: {
    ephemeris: 'DE440' | 'DE441'
    zodiac: 'tropical'
    house_system: 'whole_sign' | 'equal' | 'porphyry' | 'placidus'
    orb_profile: string
    position_type: 'apparent' | 'astrometric'
    ecliptic_epoch: 'date' | 'J2000'
  }
}

export type CreateChartResponse = {
  chart_id: string
  chart_json: Record<string, unknown>
}

export type HealthResponse = {
  status: string
}

export function apiBase(): string {
  return process.env.NEXT_PUBLIC_API_BASE_URL ?? ''
}

async function apiGet<T>(path: string, init?: RequestInit): Promise<T> {
  const base = apiBase()
  const url = base ? `${base}${path}` : `/api${path}`
  const res = await fetch(url, { cache: 'no-store', ...init })
  if (!res.ok) throw new Error((await res.text()) || `http_${res.status}`)
  return (await res.json()) as T
}

async function apiPost<T>(path: string, body: unknown): Promise<T> {
  const base = apiBase()
  const url = base ? `${base}${path}` : `/api${path}`
  const res = await fetch(url, {
    method: 'POST',
    headers: { 'content-type': 'application/json' },
    body: JSON.stringify(body),
    cache: 'no-store',
  })
  if (!res.ok) throw new Error((await res.text()) || `http_${res.status}`)
  return (await res.json()) as T
}

export function getCnProvinces(): Promise<PlaceItem[]> {
  return apiGet('/places/cn/provinces')
}

export function getCnCities(provinceCode: string): Promise<PlaceItem[]> {
  return apiGet(`/places/cn/cities?province_code=${encodeURIComponent(provinceCode)}`)
}

export function getCnCounties(cityCode: string): Promise<PlaceItem[]> {
  return apiGet(`/places/cn/counties?city_code=${encodeURIComponent(cityCode)}`)
}

export function createBirthProfile(req: CreateBirthProfileRequest): Promise<CreateBirthProfileResponse> {
  return apiPost('/birth-profiles', req)
}

export function createNatalChart(req: CreateNatalChartRequest): Promise<CreateChartResponse> {
  return apiPost('/charts/natal', req)
}

export function getHealth(): Promise<HealthResponse> {
  return apiGet('/health')
}