feat(health): expose getCharacteristics (DOB / sexe / groupe sanguin)
Nouvelle méthode CoachHealthRoutePlugin.getCharacteristics qui lit les caractéristiques read-only depuis HealthKit : - dateOfBirth (ISO8601 date) - biologicalSex (male/female/other) - bloodType (A+/A-/B+/B-/AB+/AB-/O+/O-) Auth étendue : on demande aussi read sur dateOfBirth, biologicalSex et bloodType en plus de workoutType + workoutRoute. Utilisé côté web par la page Profil pour auto-remplir les champs sans saisie manuelle (cf. /api/profile/healthkit-suggestions). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -24,6 +24,7 @@ public class CoachHealthRoutePlugin: CAPPlugin, CAPBridgedPlugin {
|
|||||||
CAPPluginMethod(name: "isAvailable", returnType: CAPPluginReturnPromise),
|
CAPPluginMethod(name: "isAvailable", returnType: CAPPluginReturnPromise),
|
||||||
CAPPluginMethod(name: "requestAuthorization", returnType: CAPPluginReturnPromise),
|
CAPPluginMethod(name: "requestAuthorization", returnType: CAPPluginReturnPromise),
|
||||||
CAPPluginMethod(name: "getRoute", returnType: CAPPluginReturnPromise),
|
CAPPluginMethod(name: "getRoute", returnType: CAPPluginReturnPromise),
|
||||||
|
CAPPluginMethod(name: "getCharacteristics", returnType: CAPPluginReturnPromise),
|
||||||
]
|
]
|
||||||
|
|
||||||
private lazy var store = HKHealthStore()
|
private lazy var store = HKHealthStore()
|
||||||
@@ -42,10 +43,14 @@ public class CoachHealthRoutePlugin: CAPPlugin, CAPBridgedPlugin {
|
|||||||
call.resolve(["granted": false, "reason": "HealthKit unavailable"])
|
call.resolve(["granted": false, "reason": "HealthKit unavailable"])
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let types: Set<HKObjectType> = [
|
var types: Set<HKObjectType> = [
|
||||||
HKObjectType.workoutType(),
|
HKObjectType.workoutType(),
|
||||||
HKSeriesType.workoutRoute(),
|
HKSeriesType.workoutRoute(),
|
||||||
]
|
]
|
||||||
|
// Caractéristiques (DOB, sexe, groupe sanguin) — read-only depuis HK
|
||||||
|
if let dob = HKObjectType.characteristicType(forIdentifier: .dateOfBirth) { types.insert(dob) }
|
||||||
|
if let sex = HKObjectType.characteristicType(forIdentifier: .biologicalSex) { types.insert(sex) }
|
||||||
|
if let blood = HKObjectType.characteristicType(forIdentifier: .bloodType) { types.insert(blood) }
|
||||||
store.requestAuthorization(toShare: nil, read: types) { ok, err in
|
store.requestAuthorization(toShare: nil, read: types) { ok, err in
|
||||||
if let err = err {
|
if let err = err {
|
||||||
call.resolve(["granted": false, "reason": err.localizedDescription])
|
call.resolve(["granted": false, "reason": err.localizedDescription])
|
||||||
@@ -55,6 +60,43 @@ public class CoachHealthRoutePlugin: CAPPlugin, CAPBridgedPlugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@objc func getCharacteristics(_ call: CAPPluginCall) {
|
||||||
|
guard HKHealthStore.isHealthDataAvailable() else {
|
||||||
|
call.resolve(["available": false, "reason": "HealthKit unavailable"])
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var result: [String: Any] = ["available": true]
|
||||||
|
|
||||||
|
// Date de naissance
|
||||||
|
if let dob = try? store.dateOfBirthComponents() {
|
||||||
|
if let date = Calendar.current.date(from: dob) {
|
||||||
|
let fmt = ISO8601DateFormatter()
|
||||||
|
fmt.formatOptions = [.withFullDate]
|
||||||
|
result["dateOfBirth"] = fmt.string(from: date)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Sexe biologique
|
||||||
|
if let bs = try? store.biologicalSex() {
|
||||||
|
switch bs.biologicalSex {
|
||||||
|
case .male: result["biologicalSex"] = "male"
|
||||||
|
case .female: result["biologicalSex"] = "female"
|
||||||
|
case .other: result["biologicalSex"] = "other"
|
||||||
|
default: break // notSet
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Groupe sanguin
|
||||||
|
if let bt = try? store.bloodType() {
|
||||||
|
let map: [HKBloodType: String] = [
|
||||||
|
.aPositive: "A+", .aNegative: "A-",
|
||||||
|
.bPositive: "B+", .bNegative: "B-",
|
||||||
|
.abPositive: "AB+", .abNegative: "AB-",
|
||||||
|
.oPositive: "O+", .oNegative: "O-",
|
||||||
|
]
|
||||||
|
if let s = map[bt.bloodType] { result["bloodType"] = s }
|
||||||
|
}
|
||||||
|
call.resolve(result)
|
||||||
|
}
|
||||||
|
|
||||||
@objc func getRoute(_ call: CAPPluginCall) {
|
@objc func getRoute(_ call: CAPPluginCall) {
|
||||||
guard HKHealthStore.isHealthDataAvailable() else {
|
guard HKHealthStore.isHealthDataAvailable() else {
|
||||||
call.resolve(["available": false, "reason": "HealthKit unavailable", "route": []])
|
call.resolve(["available": false, "reason": "HealthKit unavailable", "route": []])
|
||||||
|
|||||||
Reference in New Issue
Block a user