Files
pulse-mobile/PulseHealth/Services/HealthAPIService.swift
Cosmo c015824b36 feat: полноценное Pulse приложение с TabBar
- Auth: переключено на Pulse API (api.digital-home.site) вместо health
- TabBar: Главная, Задачи, Привычки, Здоровье, Финансы
- Models: TaskModels, HabitModels, FinanceModels, обновлённые AuthModels
- Services: APIService (Pulse API), HealthAPIService (health отдельно)
- Dashboard: обзор дня с задачами, привычками, readiness, балансом
- Tasks: список, фильтр, создание, выполнение, удаление
- Habits: список с прогресс-баром, отметка выполнения, стрики
- Health: бывший DashboardView, HealthKit sync через health API key
- Finance: баланс, список транзакций, добавление расхода/дохода
- Health данные через x-api-key вместо JWT токена health сервиса
2026-03-25 11:49:52 +00:00

61 lines
2.9 KiB
Swift

import Foundation
class HealthAPIService {
static let shared = HealthAPIService()
let baseURL = "https://health.digital-home.site"
private func makeRequest(_ path: String, token: String? = nil, apiKey: String? = nil) -> URLRequest {
var req = URLRequest(url: URL(string: "\(baseURL)\(path)")!)
req.setValue("application/json", forHTTPHeaderField: "Content-Type")
req.timeoutInterval = 15
if let t = token { req.setValue("Bearer \(t)", forHTTPHeaderField: "Authorization") }
if let k = apiKey { req.setValue(k, forHTTPHeaderField: "x-api-key") }
return req
}
func getLatest(apiKey: String) async throws -> LatestHealthResponse {
let req = makeRequest("/api/health/latest", apiKey: apiKey)
let (data, response) = try await URLSession.shared.data(for: req)
guard let http = response as? HTTPURLResponse, http.statusCode == 200 else {
throw APIError.networkError("Latest недоступен")
}
return try JSONDecoder().decode(LatestHealthResponse.self, from: data)
}
func getReadiness(apiKey: String) async throws -> ReadinessResponse {
let req = makeRequest("/api/health/readiness", apiKey: apiKey)
let (data, response) = try await URLSession.shared.data(for: req)
guard let http = response as? HTTPURLResponse, http.statusCode == 200 else {
throw APIError.networkError("Readiness недоступен")
}
return try JSONDecoder().decode(ReadinessResponse.self, from: data)
}
func getHeatmap(apiKey: String, days: Int = 7) async throws -> [HeatmapEntry] {
let req = makeRequest("/api/health/heatmap?days=\(days)", apiKey: apiKey)
let (data, response) = try await URLSession.shared.data(for: req)
guard let http = response as? HTTPURLResponse, http.statusCode == 200 else {
throw APIError.networkError("Heatmap недоступен")
}
if let entries = try? JSONDecoder().decode([HeatmapEntry].self, from: data) {
return entries
}
let wrapped = try JSONDecoder().decode(HeatmapResponse.self, from: data)
return wrapped.data
}
func sendHealthData(apiKey: String, payload: Data) async throws {
let url = URL(string: "\(baseURL)/api/health?key=\(apiKey)")!
var req = URLRequest(url: url)
req.httpMethod = "POST"
req.setValue("application/json", forHTTPHeaderField: "Content-Type")
req.httpBody = payload
req.timeoutInterval = 30
let (_, response) = try await URLSession.shared.data(for: req)
guard let http = response as? HTTPURLResponse, (200...299).contains(http.statusCode) else {
let code = (response as? HTTPURLResponse)?.statusCode ?? 0
throw APIError.serverError(code, "Ошибка отправки health данных")
}
}
}