mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-08 04:32:42 +00:00
Surface shipped data sources in onboarding and tell the truth
Rewrite the source step to list the live integrations (Apple Health, WHOOP, Oura, Polar, Nightscout, Fitbit) alongside Withings and manual entry, each linking to where it is connected; drop the stale Apple Health coming-soon badge. Add an import affordance for existing history. Reword the goals and source copy so it no longer promises automatic dashboard or reminder configuration that does not happen yet. Add a calibration line to the done screen setting the expectation that some insights sharpen over the first weeks, and lead the success screen forward with connect-a-device and log-first-measurement actions. Generalize the dashboard checklist data-source item so any connected integration satisfies it, not Withings alone.
This commit is contained in:
1 parent
46f9dfa47f
commit
1ddc8a0c47
11 files changed
+295
-168
No files matched your search
+21
-12
@@ -3648,7 +3648,7 @@
|
||||
},
|
||||
"goals": {
|
||||
"title": "Was möchtest du erfassen?",
|
||||
"body": "Wähle die Bereiche, die dir wichtig sind. Dashboard und Erinnerungen richten sich danach.",
|
||||
"body": "Wähle die Bereiche, die dir wichtig sind – das hilft dir zu entscheiden, was du verfolgen und als Nächstes einrichten willst.",
|
||||
"helpHint": "Ein bis drei Schwerpunkte funktionieren erfahrungsgemäß am besten – mehr geht aber jederzeit.",
|
||||
"options": {
|
||||
"weightManagement": "Gewicht im Griff",
|
||||
@@ -3661,7 +3661,7 @@
|
||||
},
|
||||
"source": {
|
||||
"title": "Quelle verbinden",
|
||||
"body": "Werte automatisch übernehmen oder weiter manuell eintragen – deine Entscheidung.",
|
||||
"body": "Werte automatisch übernehmen oder weiter manuell eintragen. Hier wird nichts für dich eingerichtet – jede Karte zeigt nur, wo du sie verbindest.",
|
||||
"recommended": "Empfohlen",
|
||||
"manual": {
|
||||
"title": "Manuelle Eingabe",
|
||||
@@ -3672,12 +3672,17 @@
|
||||
"body": "Waagen, Blutdruckmesser und Tracker von Withings synchronisieren automatisch.",
|
||||
"cta": "Withings verbinden"
|
||||
},
|
||||
"appleHealth": {
|
||||
"title": "Apple Health",
|
||||
"body": "iPhone- und Apple-Watch-Daten werden über die HealthLog-iOS-App eingelesen.",
|
||||
"badge": "Mit v1.5 (iOS)",
|
||||
"disabledHint": "Verfügbar, sobald die iOS-App ausgeliefert ist."
|
||||
}
|
||||
"more": {
|
||||
"title": "Weitere Quellen",
|
||||
"body": "Verbinde eine davon in den Einstellungen, wann immer du bereit bist.",
|
||||
"appleHealth": "Apple Health",
|
||||
"whoop": "WHOOP",
|
||||
"oura": "Oura",
|
||||
"polar": "Polar",
|
||||
"nightscout": "Nightscout",
|
||||
"fitbit": "Fitbit"
|
||||
},
|
||||
"import": "Bestehende Daten importieren"
|
||||
},
|
||||
"baseline": {
|
||||
"title": "Kurz zu dir",
|
||||
@@ -3697,7 +3702,11 @@
|
||||
"done": {
|
||||
"title": "Alles bereit",
|
||||
"body": "Willkommen an Bord. Dein Dashboard wartet.",
|
||||
"returnCta": "Zum Dashboard"
|
||||
"returnCta": "Zum Dashboard",
|
||||
"learning": "Manche Einblicke – Glukose, Schlafrhythmus, Blutdrucktrends, Zyklus – schärfen sich in den ersten ein bis zwei Wochen, sobald sich deine Daten ansammeln. Leere Kacheln heißen jetzt nur, dass wir deine Basislinie noch lernen.",
|
||||
"connectCta": "Gerät verbinden",
|
||||
"logCta": "Ersten Wert eintragen",
|
||||
"importCta": "Bestehende Daten importieren"
|
||||
},
|
||||
"welcomeBack": {
|
||||
"title": "Willkommen zurück",
|
||||
@@ -3742,9 +3751,9 @@
|
||||
"medicationTitle": "Medikament hinzufügen",
|
||||
"medicationDescription": "Verfolge die Therapietreue und erhalte Erinnerungen genau dann, wenn du sie brauchst.",
|
||||
"medicationCta": "Medikament hinzufügen",
|
||||
"withingsTitle": "Withings verbinden (optional)",
|
||||
"withingsDescription": "Synchronisiere Gewicht, Blutdruck und Puls automatisch aus deinen Withings-Geräten.",
|
||||
"withingsCta": "Verbinden",
|
||||
"dataSourceTitle": "Datenquelle verbinden (optional)",
|
||||
"dataSourceDescription": "Gewicht, Blutdruck, Schlaf und mehr automatisch aus Withings, WHOOP, Oura, Polar, Nightscout, Fitbit oder Apple Health.",
|
||||
"dataSourceCta": "Verbinden",
|
||||
"notificationsTitle": "Benachrichtigungen einrichten",
|
||||
"notificationsDescription": "Wähle, wie HealthLog dich erinnert — Telegram, ntfy oder Web Push.",
|
||||
"notificationsCta": "Benachrichtigungen öffnen"
|
||||
|
||||
+21
-12
@@ -3648,7 +3648,7 @@
|
||||
},
|
||||
"goals": {
|
||||
"title": "What would you like to track?",
|
||||
"body": "Pick the areas you care about. Your dashboard and the default reminders follow your choice.",
|
||||
"body": "Pick the areas you care about — it helps you decide what to track and set up next.",
|
||||
"helpHint": "One to three priorities tend to work best — you can always add more later.",
|
||||
"options": {
|
||||
"weightManagement": "Weight management",
|
||||
@@ -3661,7 +3661,7 @@
|
||||
},
|
||||
"source": {
|
||||
"title": "Connect a source",
|
||||
"body": "Bring in measurements automatically, or stay on manual entry — your call.",
|
||||
"body": "Bring in measurements automatically, or stay on manual entry. Nothing here is configured for you — each card just shows where to connect it.",
|
||||
"recommended": "Recommended",
|
||||
"manual": {
|
||||
"title": "Manual entry",
|
||||
@@ -3672,12 +3672,17 @@
|
||||
"body": "Scales, blood-pressure cuffs and trackers from Withings sync automatically.",
|
||||
"cta": "Connect Withings"
|
||||
},
|
||||
"appleHealth": {
|
||||
"title": "Apple Health",
|
||||
"body": "iPhone and Apple Watch data flow in via the HealthLog iOS app.",
|
||||
"badge": "Coming with v1.5 (iOS)",
|
||||
"disabledHint": "Available once the iOS app ships."
|
||||
}
|
||||
"more": {
|
||||
"title": "More sources",
|
||||
"body": "Connect any of these in Settings whenever you're ready.",
|
||||
"appleHealth": "Apple Health",
|
||||
"whoop": "WHOOP",
|
||||
"oura": "Oura",
|
||||
"polar": "Polar",
|
||||
"nightscout": "Nightscout",
|
||||
"fitbit": "Fitbit"
|
||||
},
|
||||
"import": "Import existing history"
|
||||
},
|
||||
"baseline": {
|
||||
"title": "A bit about you",
|
||||
@@ -3697,7 +3702,11 @@
|
||||
"done": {
|
||||
"title": "You're all set",
|
||||
"body": "Welcome aboard. Your dashboard is ready.",
|
||||
"returnCta": "Open dashboard"
|
||||
"returnCta": "Open dashboard",
|
||||
"learning": "Some insights — glucose, sleep rhythm, blood-pressure trends, cycle — sharpen over the first week or two as your data builds up. Empty tiles now just mean we're still learning your baseline.",
|
||||
"connectCta": "Connect a device",
|
||||
"logCta": "Log your first measurement",
|
||||
"importCta": "Import existing history"
|
||||
},
|
||||
"welcomeBack": {
|
||||
"title": "Welcome back",
|
||||
@@ -3742,9 +3751,9 @@
|
||||
"medicationTitle": "Add a medication",
|
||||
"medicationDescription": "Track adherence and get reminders right when you need them.",
|
||||
"medicationCta": "Add medication",
|
||||
"withingsTitle": "Connect Withings (optional)",
|
||||
"withingsDescription": "Auto-sync weight, BP and pulse from your Withings devices.",
|
||||
"withingsCta": "Connect",
|
||||
"dataSourceTitle": "Connect a data source (optional)",
|
||||
"dataSourceDescription": "Auto-sync weight, BP, sleep and more from Withings, WHOOP, Oura, Polar, Nightscout, Fitbit or Apple Health.",
|
||||
"dataSourceCta": "Connect",
|
||||
"notificationsTitle": "Configure notifications",
|
||||
"notificationsDescription": "Choose how HealthLog should remind you — Telegram, ntfy or Web Push.",
|
||||
"notificationsCta": "Open notifications"
|
||||
|
||||
+21
-12
@@ -3648,7 +3648,7 @@
|
||||
},
|
||||
"goals": {
|
||||
"title": "¿Qué te gustaría registrar?",
|
||||
"body": "Elige las áreas que te interesan. El panel y los recordatorios se ajustarán a tu elección.",
|
||||
"body": "Elige las áreas que te interesan: te ayuda a decidir qué seguir y qué configurar a continuación.",
|
||||
"helpHint": "Una a tres prioridades suelen funcionar mejor — siempre podrás añadir más más adelante.",
|
||||
"options": {
|
||||
"weightManagement": "Control del peso",
|
||||
@@ -3661,7 +3661,7 @@
|
||||
},
|
||||
"source": {
|
||||
"title": "Conectar una fuente",
|
||||
"body": "Importa las mediciones automáticamente o sigue con la entrada manual, tú decides.",
|
||||
"body": "Importa las mediciones automáticamente o sigue con la entrada manual. Aquí no se configura nada por ti: cada tarjeta solo muestra dónde conectarla.",
|
||||
"recommended": "Recomendado",
|
||||
"manual": {
|
||||
"title": "Entrada manual",
|
||||
@@ -3672,12 +3672,17 @@
|
||||
"body": "Las básculas, los tensiómetros y los trackers de Withings se sincronizan automáticamente.",
|
||||
"cta": "Conectar Withings"
|
||||
},
|
||||
"appleHealth": {
|
||||
"title": "Apple Health",
|
||||
"body": "Los datos del iPhone y el Apple Watch llegan a través de la app de HealthLog para iOS.",
|
||||
"badge": "Con la v1.5 (iOS)",
|
||||
"disabledHint": "Disponible cuando se publique la app de iOS."
|
||||
}
|
||||
"more": {
|
||||
"title": "Más fuentes",
|
||||
"body": "Conecta cualquiera de ellas en Ajustes cuando quieras.",
|
||||
"appleHealth": "Apple Health",
|
||||
"whoop": "WHOOP",
|
||||
"oura": "Oura",
|
||||
"polar": "Polar",
|
||||
"nightscout": "Nightscout",
|
||||
"fitbit": "Fitbit"
|
||||
},
|
||||
"import": "Importar historial existente"
|
||||
},
|
||||
"baseline": {
|
||||
"title": "Cuéntanos sobre ti",
|
||||
@@ -3697,7 +3702,11 @@
|
||||
"done": {
|
||||
"title": "Todo listo",
|
||||
"body": "Bienvenido a bordo. Tu panel ya está preparado.",
|
||||
"returnCta": "Abrir el panel"
|
||||
"returnCta": "Abrir el panel",
|
||||
"learning": "Algunas conclusiones —glucosa, ritmo de sueño, tendencias de presión arterial, ciclo— se afinan durante la primera semana o dos a medida que se acumulan tus datos. Las casillas vacías ahora solo significan que aún estamos aprendiendo tu línea base.",
|
||||
"connectCta": "Conectar un dispositivo",
|
||||
"logCta": "Registra tu primera medición",
|
||||
"importCta": "Importar historial existente"
|
||||
},
|
||||
"welcomeBack": {
|
||||
"title": "Bienvenido de nuevo",
|
||||
@@ -3742,9 +3751,9 @@
|
||||
"medicationTitle": "Añadir medicamento",
|
||||
"medicationDescription": "Sigue el cumplimiento y recibe recordatorios justo cuando los necesites.",
|
||||
"medicationCta": "Añadir medicamento",
|
||||
"withingsTitle": "Conectar Withings (opcional)",
|
||||
"withingsDescription": "Sincroniza peso, tensión arterial y pulso automáticamente desde tus dispositivos Withings.",
|
||||
"withingsCta": "Conectar",
|
||||
"dataSourceTitle": "Conectar una fuente de datos (opcional)",
|
||||
"dataSourceDescription": "Sincroniza peso, presión, sueño y más desde Withings, WHOOP, Oura, Polar, Nightscout, Fitbit o Apple Health.",
|
||||
"dataSourceCta": "Conectar",
|
||||
"notificationsTitle": "Configurar notificaciones",
|
||||
"notificationsDescription": "Elige cómo te recuerda HealthLog — Telegram, ntfy o Web Push.",
|
||||
"notificationsCta": "Abrir notificaciones"
|
||||
|
||||
+21
-12
@@ -3648,7 +3648,7 @@
|
||||
},
|
||||
"goals": {
|
||||
"title": "Que souhaitez-vous suivre ?",
|
||||
"body": "Sélectionnez les domaines qui comptent pour vous. Le tableau de bord et les rappels s'y adapteront.",
|
||||
"body": "Sélectionnez les domaines qui comptent pour vous : cela vous aide à décider quoi suivre et configurer ensuite.",
|
||||
"helpHint": "Un à trois axes prioritaires fonctionnent généralement le mieux, mais vous pourrez en ajouter plus tard.",
|
||||
"options": {
|
||||
"weightManagement": "Gestion du poids",
|
||||
@@ -3661,7 +3661,7 @@
|
||||
},
|
||||
"source": {
|
||||
"title": "Connecter une source",
|
||||
"body": "Importez les mesures automatiquement ou conservez la saisie manuelle, c'est vous qui décidez.",
|
||||
"body": "Importez les mesures automatiquement ou conservez la saisie manuelle. Rien n'est configuré à votre place : chaque carte indique simplement où la connecter.",
|
||||
"recommended": "Recommandé",
|
||||
"manual": {
|
||||
"title": "Saisie manuelle",
|
||||
@@ -3672,12 +3672,17 @@
|
||||
"body": "Balances, tensiomètres et trackers Withings se synchronisent automatiquement.",
|
||||
"cta": "Connecter Withings"
|
||||
},
|
||||
"appleHealth": {
|
||||
"title": "Apple Health",
|
||||
"body": "Les données de l'iPhone et de l'Apple Watch arrivent via l'application iOS HealthLog.",
|
||||
"badge": "Avec la v1.5 (iOS)",
|
||||
"disabledHint": "Disponible dès la sortie de l'application iOS."
|
||||
}
|
||||
"more": {
|
||||
"title": "Autres sources",
|
||||
"body": "Connectez l'une d'elles dans les Réglages quand vous le souhaitez.",
|
||||
"appleHealth": "Apple Health",
|
||||
"whoop": "WHOOP",
|
||||
"oura": "Oura",
|
||||
"polar": "Polar",
|
||||
"nightscout": "Nightscout",
|
||||
"fitbit": "Fitbit"
|
||||
},
|
||||
"import": "Importer un historique existant"
|
||||
},
|
||||
"baseline": {
|
||||
"title": "Quelques informations",
|
||||
@@ -3697,7 +3702,11 @@
|
||||
"done": {
|
||||
"title": "Tout est prêt",
|
||||
"body": "Bienvenue à bord. Votre tableau de bord vous attend.",
|
||||
"returnCta": "Ouvrir le tableau de bord"
|
||||
"returnCta": "Ouvrir le tableau de bord",
|
||||
"learning": "Certaines analyses — glycémie, rythme de sommeil, tendances de tension, cycle — s'affinent au cours de la première semaine ou deux à mesure que vos données s'accumulent. Des tuiles vides signifient simplement que nous apprenons encore votre référence.",
|
||||
"connectCta": "Connecter un appareil",
|
||||
"logCta": "Enregistrez votre première mesure",
|
||||
"importCta": "Importer un historique existant"
|
||||
},
|
||||
"welcomeBack": {
|
||||
"title": "Bon retour",
|
||||
@@ -3742,9 +3751,9 @@
|
||||
"medicationTitle": "Ajouter un médicament",
|
||||
"medicationDescription": "Suis l’observance et reçois des rappels au moment où tu en as besoin.",
|
||||
"medicationCta": "Ajouter un médicament",
|
||||
"withingsTitle": "Connecter Withings (optionnel)",
|
||||
"withingsDescription": "Synchronise automatiquement poids, tension et pouls depuis tes appareils Withings.",
|
||||
"withingsCta": "Connecter",
|
||||
"dataSourceTitle": "Connecter une source de données (facultatif)",
|
||||
"dataSourceDescription": "Synchronisez poids, tension, sommeil et plus depuis Withings, WHOOP, Oura, Polar, Nightscout, Fitbit ou Apple Health.",
|
||||
"dataSourceCta": "Connecter",
|
||||
"notificationsTitle": "Configurer les notifications",
|
||||
"notificationsDescription": "Choisis comment HealthLog te prévient — Telegram, ntfy ou Web Push.",
|
||||
"notificationsCta": "Ouvrir les notifications"
|
||||
|
||||
+21
-12
@@ -3648,7 +3648,7 @@
|
||||
},
|
||||
"goals": {
|
||||
"title": "Cosa vuoi monitorare?",
|
||||
"body": "Scegli gli ambiti che ti interessano. Dashboard e promemoria si adatteranno alle tue scelte.",
|
||||
"body": "Scegli gli ambiti che ti interessano: ti aiuta a decidere cosa monitorare e configurare in seguito.",
|
||||
"helpHint": "Da una a tre priorità funzionano di solito meglio — potrai aggiungerne altre in qualsiasi momento.",
|
||||
"options": {
|
||||
"weightManagement": "Gestione del peso",
|
||||
@@ -3661,7 +3661,7 @@
|
||||
},
|
||||
"source": {
|
||||
"title": "Connetti una sorgente",
|
||||
"body": "Importa le misurazioni in automatico oppure resta sull'inserimento manuale, decidi tu.",
|
||||
"body": "Importa le misurazioni in automatico oppure resta sull'inserimento manuale. Qui non viene configurato nulla al posto tuo: ogni scheda mostra solo dove collegarla.",
|
||||
"recommended": "Consigliato",
|
||||
"manual": {
|
||||
"title": "Inserimento manuale",
|
||||
@@ -3672,12 +3672,17 @@
|
||||
"body": "Bilance, misuratori di pressione e tracker Withings si sincronizzano automaticamente.",
|
||||
"cta": "Connetti Withings"
|
||||
},
|
||||
"appleHealth": {
|
||||
"title": "Apple Health",
|
||||
"body": "I dati di iPhone e Apple Watch arrivano tramite l'app HealthLog per iOS.",
|
||||
"badge": "Con la v1.5 (iOS)",
|
||||
"disabledHint": "Disponibile al rilascio dell'app iOS."
|
||||
}
|
||||
"more": {
|
||||
"title": "Altre fonti",
|
||||
"body": "Collega una di queste nelle Impostazioni quando vuoi.",
|
||||
"appleHealth": "Apple Health",
|
||||
"whoop": "WHOOP",
|
||||
"oura": "Oura",
|
||||
"polar": "Polar",
|
||||
"nightscout": "Nightscout",
|
||||
"fitbit": "Fitbit"
|
||||
},
|
||||
"import": "Importa la cronologia esistente"
|
||||
},
|
||||
"baseline": {
|
||||
"title": "Qualcosa su di te",
|
||||
@@ -3697,7 +3702,11 @@
|
||||
"done": {
|
||||
"title": "Tutto pronto",
|
||||
"body": "Benvenuto a bordo. La tua dashboard è pronta.",
|
||||
"returnCta": "Apri la dashboard"
|
||||
"returnCta": "Apri la dashboard",
|
||||
"learning": "Alcune analisi — glicemia, ritmo del sonno, tendenze della pressione, ciclo — si affinano nella prima settimana o due man mano che i tuoi dati si accumulano. Le caselle vuote ora indicano solo che stiamo ancora imparando il tuo riferimento.",
|
||||
"connectCta": "Collega un dispositivo",
|
||||
"logCta": "Registra la tua prima misurazione",
|
||||
"importCta": "Importa la cronologia esistente"
|
||||
},
|
||||
"welcomeBack": {
|
||||
"title": "Bentornato",
|
||||
@@ -3742,9 +3751,9 @@
|
||||
"medicationTitle": "Aggiungi un farmaco",
|
||||
"medicationDescription": "Monitora l’aderenza e ricevi promemoria proprio quando ti servono.",
|
||||
"medicationCta": "Aggiungi farmaco",
|
||||
"withingsTitle": "Collega Withings (opzionale)",
|
||||
"withingsDescription": "Sincronizza peso, pressione e pulsazioni automaticamente dai tuoi dispositivi Withings.",
|
||||
"withingsCta": "Collega",
|
||||
"dataSourceTitle": "Collega una fonte di dati (opzionale)",
|
||||
"dataSourceDescription": "Sincronizza peso, pressione, sonno e altro da Withings, WHOOP, Oura, Polar, Nightscout, Fitbit o Apple Health.",
|
||||
"dataSourceCta": "Collega",
|
||||
"notificationsTitle": "Configura le notifiche",
|
||||
"notificationsDescription": "Scegli come HealthLog ti ricorda — Telegram, ntfy o Web Push.",
|
||||
"notificationsCta": "Apri notifiche"
|
||||
|
||||
+21
-12
@@ -3648,7 +3648,7 @@
|
||||
},
|
||||
"goals": {
|
||||
"title": "Co chcesz śledzić?",
|
||||
"body": "Wybierz obszary, które są dla Ciebie ważne. Pulpit i przypomnienia dostosują się do Twojego wyboru.",
|
||||
"body": "Wybierz obszary, które są dla Ciebie ważne — to pomaga zdecydować, co śledzić i co skonfigurować w następnej kolejności.",
|
||||
"helpHint": "Od jednego do trzech priorytetów zwykle sprawdza się najlepiej — możesz dodać kolejne w dowolnej chwili.",
|
||||
"options": {
|
||||
"weightManagement": "Kontrola wagi",
|
||||
@@ -3661,7 +3661,7 @@
|
||||
},
|
||||
"source": {
|
||||
"title": "Połącz źródło",
|
||||
"body": "Pobieraj pomiary automatycznie lub zostań przy wpisywaniu ręcznym — Twój wybór.",
|
||||
"body": "Pobieraj pomiary automatycznie lub zostań przy wpisywaniu ręcznym. Nic nie jest tu konfigurowane za Ciebie — każda karta pokazuje tylko, gdzie to połączyć.",
|
||||
"recommended": "Polecane",
|
||||
"manual": {
|
||||
"title": "Wpis ręczny",
|
||||
@@ -3672,12 +3672,17 @@
|
||||
"body": "Wagi, ciśnieniomierze i trackery Withings synchronizują się automatycznie.",
|
||||
"cta": "Połącz Withings"
|
||||
},
|
||||
"appleHealth": {
|
||||
"title": "Apple Health",
|
||||
"body": "Dane z iPhone'a i Apple Watch trafiają tu poprzez aplikację HealthLog na iOS.",
|
||||
"badge": "Wraz z v1.5 (iOS)",
|
||||
"disabledHint": "Dostępne po wydaniu aplikacji iOS."
|
||||
}
|
||||
"more": {
|
||||
"title": "Więcej źródeł",
|
||||
"body": "Połącz dowolne z nich w Ustawieniach, gdy zechcesz.",
|
||||
"appleHealth": "Apple Health",
|
||||
"whoop": "WHOOP",
|
||||
"oura": "Oura",
|
||||
"polar": "Polar",
|
||||
"nightscout": "Nightscout",
|
||||
"fitbit": "Fitbit"
|
||||
},
|
||||
"import": "Importuj istniejącą historię"
|
||||
},
|
||||
"baseline": {
|
||||
"title": "Kilka słów o Tobie",
|
||||
@@ -3697,7 +3702,11 @@
|
||||
"done": {
|
||||
"title": "Wszystko gotowe",
|
||||
"body": "Witaj na pokładzie. Pulpit czeka na Ciebie.",
|
||||
"returnCta": "Otwórz pulpit"
|
||||
"returnCta": "Otwórz pulpit",
|
||||
"learning": "Niektóre wnioski — glukoza, rytm snu, trendy ciśnienia, cykl — wyostrzają się w ciągu pierwszego tygodnia lub dwóch, w miarę gromadzenia danych. Puste kafelki oznaczają teraz tylko, że wciąż poznajemy Twój punkt odniesienia.",
|
||||
"connectCta": "Połącz urządzenie",
|
||||
"logCta": "Zapisz pierwszy pomiar",
|
||||
"importCta": "Importuj istniejącą historię"
|
||||
},
|
||||
"welcomeBack": {
|
||||
"title": "Witaj ponownie",
|
||||
@@ -3742,9 +3751,9 @@
|
||||
"medicationTitle": "Dodaj lek",
|
||||
"medicationDescription": "Śledź przestrzeganie i otrzymuj przypomnienia dokładnie wtedy, kiedy ich potrzebujesz.",
|
||||
"medicationCta": "Dodaj lek",
|
||||
"withingsTitle": "Połącz Withings (opcjonalnie)",
|
||||
"withingsDescription": "Automatycznie synchronizuj wagę, ciśnienie i tętno z urządzeń Withings.",
|
||||
"withingsCta": "Połącz",
|
||||
"dataSourceTitle": "Połącz źródło danych (opcjonalnie)",
|
||||
"dataSourceDescription": "Automatycznie synchronizuj wagę, ciśnienie, sen i więcej z Withings, WHOOP, Oura, Polar, Nightscout, Fitbit lub Apple Health.",
|
||||
"dataSourceCta": "Połącz",
|
||||
"notificationsTitle": "Skonfiguruj powiadomienia",
|
||||
"notificationsDescription": "Wybierz, jak HealthLog ma ci przypominać — Telegram, ntfy lub Web Push.",
|
||||
"notificationsCta": "Otwórz powiadomienia"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import Link from "next/link";
|
||||
import { CheckCircle2 } from "lucide-react";
|
||||
import { CheckCircle2, FileUp, PlusCircle, Plug } from "lucide-react";
|
||||
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { useTranslations } from "@/lib/i18n/context";
|
||||
@@ -46,11 +46,42 @@ export function DoneScreen() {
|
||||
<p className="text-muted-foreground mx-auto max-w-md text-base leading-relaxed">
|
||||
{t("onboarding.done.body")}
|
||||
</p>
|
||||
<p className="text-muted-foreground mx-auto max-w-md text-sm leading-relaxed">
|
||||
{t("onboarding.done.learning")}
|
||||
</p>
|
||||
</header>
|
||||
|
||||
<Button asChild size="lg">
|
||||
<Link href="/">{t("onboarding.done.returnCta")}</Link>
|
||||
</Button>
|
||||
<div className="flex w-full max-w-xs flex-col gap-2">
|
||||
<Button asChild size="lg">
|
||||
<Link
|
||||
href="/settings/integrations"
|
||||
className="inline-flex items-center gap-2"
|
||||
>
|
||||
<Plug className="size-4" />
|
||||
{t("onboarding.done.connectCta")}
|
||||
</Link>
|
||||
</Button>
|
||||
<Button asChild size="lg" variant="outline">
|
||||
<Link
|
||||
href="/measurements"
|
||||
className="inline-flex items-center gap-2"
|
||||
>
|
||||
<PlusCircle className="size-4" />
|
||||
{t("onboarding.done.logCta")}
|
||||
</Link>
|
||||
</Button>
|
||||
<Button asChild variant="ghost">
|
||||
<Link href="/">{t("onboarding.done.returnCta")}</Link>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<Link
|
||||
href="/settings/export"
|
||||
className="text-muted-foreground hover:text-foreground inline-flex items-center gap-1.5 text-sm underline-offset-4 hover:underline"
|
||||
>
|
||||
<FileUp className="size-3.5" />
|
||||
{t("onboarding.done.importCta")}
|
||||
</Link>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
@@ -6,8 +6,9 @@ import { useRouter } from "next/navigation";
|
||||
import { useQueryClient } from "@tanstack/react-query";
|
||||
import { toast } from "sonner";
|
||||
import {
|
||||
Apple,
|
||||
ClipboardCheck,
|
||||
FileUp,
|
||||
Plug,
|
||||
Watch,
|
||||
Wifi,
|
||||
type LucideIcon,
|
||||
@@ -19,29 +20,31 @@ import { cn } from "@/lib/utils";
|
||||
import { apiPost } from "@/lib/api/api-fetch";
|
||||
|
||||
/**
|
||||
* v1.4.25 W14b-Content — onboarding step 2 (source).
|
||||
* Onboarding step 2 (source).
|
||||
*
|
||||
* Four-card grid presenting the data sources HealthLog supports today
|
||||
* plus the announce-only Apple Health card so users land on v1.5 with
|
||||
* the right expectation.
|
||||
*
|
||||
* Cards:
|
||||
* 1. Manual entry (enabled, recommended)
|
||||
* Presents the data sources HealthLog ships today. The headline cards
|
||||
* cover the two paths most people start on:
|
||||
* 1. Manual entry (enabled, recommended — works on any device)
|
||||
* 2. Withings (enabled — opens OAuth `/api/withings/connect` in a new
|
||||
* tab; the popup hands control back via the existing callback)
|
||||
* 3. Apple Health (DISABLED — "Coming with v1.5 iOS app")
|
||||
* 4. Garmin — omitted entirely. Not on the v1.5 roadmap so showing
|
||||
* a disabled card adds noise without conveying a real promise.
|
||||
* tab; the callback flips the connection server-side)
|
||||
*
|
||||
* Below them a calm "more sources" row lists the remaining shipped
|
||||
* integrations (Apple Health, WHOOP, Oura, Polar, Nightscout, Fitbit),
|
||||
* each linking to Settings → Integrations where it is actually
|
||||
* connected. We don't try to run six OAuth flows inside the wizard;
|
||||
* the row sets the expectation and hands off. A discreet import link
|
||||
* points at the Apple Health export.zip path — the cold-start escape
|
||||
* hatch for users with existing history.
|
||||
*
|
||||
* Garmin is omitted: not shipped, so a card would over-claim.
|
||||
*
|
||||
* Selection is non-binding — Manual is the implicit default and the
|
||||
* Next CTA always advances. The Withings card opens the OAuth flow in
|
||||
* a new tab; the user returns to this step to click Next when they're
|
||||
* back (callback handler flips the connection server-side, no client
|
||||
* polling needed for the wizard contract).
|
||||
* Next CTA always advances. Nothing here is auto-configured; the step
|
||||
* only signposts where each source is connected.
|
||||
*/
|
||||
|
||||
interface SourceCard {
|
||||
slug: "manual" | "withings" | "apple-health";
|
||||
slug: "manual" | "withings";
|
||||
Icon: LucideIcon;
|
||||
titleKey: string;
|
||||
bodyKey: string;
|
||||
@@ -49,14 +52,11 @@ interface SourceCard {
|
||||
* One of:
|
||||
* - "enabled-select": tap selects the card (Manual)
|
||||
* - "enabled-oauth": tap opens OAuth in a new tab (Withings)
|
||||
* - "disabled": semi-transparent, badge, no-op (Apple Health)
|
||||
*/
|
||||
state: "enabled-select" | "enabled-oauth" | "disabled";
|
||||
state: "enabled-select" | "enabled-oauth";
|
||||
/** External href for `enabled-oauth`. */
|
||||
href?: string;
|
||||
/** Optional badge under the title (e.g. "Coming with v1.5"). */
|
||||
badgeKey?: string;
|
||||
/** Optional recommended badge ("Most popular"). */
|
||||
/** Optional recommended badge. */
|
||||
recommendedKey?: string;
|
||||
}
|
||||
|
||||
@@ -77,14 +77,19 @@ const SOURCE_CARDS: ReadonlyArray<SourceCard> = [
|
||||
state: "enabled-oauth",
|
||||
href: "/api/withings/connect",
|
||||
},
|
||||
{
|
||||
slug: "apple-health",
|
||||
Icon: Apple,
|
||||
titleKey: "onboarding.source.appleHealth.title",
|
||||
bodyKey: "onboarding.source.appleHealth.body",
|
||||
state: "disabled",
|
||||
badgeKey: "onboarding.source.appleHealth.badge",
|
||||
},
|
||||
];
|
||||
|
||||
/**
|
||||
* The remaining shipped integrations. Listed compactly so the step
|
||||
* stays calm — the full connect flow for each lives in Settings.
|
||||
*/
|
||||
const MORE_SOURCES: ReadonlyArray<{ slug: string; labelKey: string }> = [
|
||||
{ slug: "apple-health", labelKey: "onboarding.source.more.appleHealth" },
|
||||
{ slug: "whoop", labelKey: "onboarding.source.more.whoop" },
|
||||
{ slug: "oura", labelKey: "onboarding.source.more.oura" },
|
||||
{ slug: "polar", labelKey: "onboarding.source.more.polar" },
|
||||
{ slug: "nightscout", labelKey: "onboarding.source.more.nightscout" },
|
||||
{ slug: "fitbit", labelKey: "onboarding.source.more.fitbit" },
|
||||
];
|
||||
|
||||
export function SourceCardGrid() {
|
||||
@@ -140,13 +145,58 @@ export function SourceCardGrid() {
|
||||
recommendedLabel={
|
||||
card.recommendedKey ? t(card.recommendedKey) : null
|
||||
}
|
||||
badgeLabel={card.badgeKey ? t(card.badgeKey) : null}
|
||||
withingsCtaLabel={t("onboarding.source.withings.cta")}
|
||||
disabledHintLabel={t("onboarding.source.appleHealth.disabledHint")}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="space-y-3 rounded-lg border border-dashed border-border p-4">
|
||||
<div className="flex items-start gap-3">
|
||||
<span
|
||||
aria-hidden="true"
|
||||
className="bg-muted text-muted-foreground flex size-9 shrink-0 items-center justify-center rounded-md"
|
||||
>
|
||||
<Plug className="size-4" />
|
||||
</span>
|
||||
<div className="min-w-0 flex-1 space-y-1">
|
||||
<h2 className="text-base font-semibold tracking-tight">
|
||||
{t("onboarding.source.more.title")}
|
||||
</h2>
|
||||
<p className="text-muted-foreground text-sm leading-relaxed">
|
||||
{t("onboarding.source.more.body")}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<ul className="flex flex-wrap gap-2" data-testid="source-more-list">
|
||||
{MORE_SOURCES.map((item) => (
|
||||
<li key={item.slug}>
|
||||
<Button
|
||||
asChild
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="min-h-9"
|
||||
>
|
||||
<Link
|
||||
href="/settings/integrations"
|
||||
data-testid={`source-more-${item.slug}`}
|
||||
>
|
||||
{t(item.labelKey)}
|
||||
</Link>
|
||||
</Button>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<Link
|
||||
href="/settings/export"
|
||||
className="text-muted-foreground hover:text-foreground inline-flex items-center gap-1.5 text-sm underline-offset-4 hover:underline"
|
||||
data-testid="source-import-link"
|
||||
>
|
||||
<FileUp className="size-3.5" />
|
||||
{t("onboarding.source.import")}
|
||||
</Link>
|
||||
|
||||
<div className="flex items-center justify-between gap-2 pt-2">
|
||||
<Button asChild variant="ghost" className="min-h-11 min-w-11">
|
||||
<Link href="/onboarding/1">{t("onboarding.shell.back")}</Link>
|
||||
@@ -182,9 +232,7 @@ interface SourceCardItemProps {
|
||||
titleLabel: string;
|
||||
bodyLabel: string;
|
||||
recommendedLabel: string | null;
|
||||
badgeLabel: string | null;
|
||||
withingsCtaLabel: string;
|
||||
disabledHintLabel: string;
|
||||
}
|
||||
|
||||
function SourceCardItem({
|
||||
@@ -194,9 +242,7 @@ function SourceCardItem({
|
||||
titleLabel,
|
||||
bodyLabel,
|
||||
recommendedLabel,
|
||||
badgeLabel,
|
||||
withingsCtaLabel,
|
||||
disabledHintLabel,
|
||||
}: SourceCardItemProps) {
|
||||
const Icon = card.Icon;
|
||||
|
||||
@@ -211,7 +257,7 @@ function SourceCardItem({
|
||||
aria-hidden="true"
|
||||
className={cn(
|
||||
"flex size-10 shrink-0 items-center justify-center rounded-md",
|
||||
selected && card.state !== "disabled"
|
||||
selected
|
||||
? "bg-primary text-primary-foreground"
|
||||
: "bg-muted text-muted-foreground",
|
||||
)}
|
||||
@@ -220,14 +266,7 @@ function SourceCardItem({
|
||||
</span>
|
||||
<div className="min-w-0 flex-1">
|
||||
<h2 className="text-base font-semibold tracking-tight">{titleLabel}</h2>
|
||||
{badgeLabel ? (
|
||||
<span
|
||||
className="bg-muted text-foreground mt-1 inline-flex items-center rounded-full px-2 py-0.5 text-[10px] font-medium uppercase tracking-wide"
|
||||
data-testid={`source-badge-${card.slug}`}
|
||||
>
|
||||
{badgeLabel}
|
||||
</span>
|
||||
) : recommendedLabel ? (
|
||||
{recommendedLabel ? (
|
||||
<span className="bg-primary/10 text-primary mt-1 inline-flex items-center rounded-full px-2 py-0.5 text-[10px] font-medium uppercase tracking-wide">
|
||||
{recommendedLabel}
|
||||
</span>
|
||||
@@ -240,22 +279,6 @@ function SourceCardItem({
|
||||
<p className="text-muted-foreground text-sm leading-relaxed">{bodyLabel}</p>
|
||||
);
|
||||
|
||||
if (card.state === "disabled") {
|
||||
return (
|
||||
<div
|
||||
aria-disabled="true"
|
||||
className={cn(baseClasses, "cursor-not-allowed opacity-60")}
|
||||
data-testid={`source-card-${card.slug}`}
|
||||
>
|
||||
{headerRow}
|
||||
{body}
|
||||
<p className="text-muted-foreground text-xs italic">
|
||||
{disabledHintLabel}
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (card.state === "enabled-oauth") {
|
||||
return (
|
||||
<div
|
||||
|
||||
@@ -37,7 +37,7 @@ const ITEM_ICONS: Record<ChecklistItemId, LucideIcon> = {
|
||||
profile: User2,
|
||||
measurement: Activity,
|
||||
medication: Pill,
|
||||
withings: Wifi,
|
||||
dataSource: Wifi,
|
||||
notifications: Bell,
|
||||
};
|
||||
|
||||
@@ -60,10 +60,10 @@ const ITEM_LABEL_KEYS: Record<
|
||||
description: "gettingStarted.items.medicationDescription",
|
||||
cta: "gettingStarted.items.medicationCta",
|
||||
},
|
||||
withings: {
|
||||
title: "gettingStarted.items.withingsTitle",
|
||||
description: "gettingStarted.items.withingsDescription",
|
||||
cta: "gettingStarted.items.withingsCta",
|
||||
dataSource: {
|
||||
title: "gettingStarted.items.dataSourceTitle",
|
||||
description: "gettingStarted.items.dataSourceDescription",
|
||||
cta: "gettingStarted.items.dataSourceCta",
|
||||
},
|
||||
notifications: {
|
||||
title: "gettingStarted.items.notificationsTitle",
|
||||
@@ -72,8 +72,8 @@ const ITEM_LABEL_KEYS: Record<
|
||||
},
|
||||
};
|
||||
|
||||
interface WithingsStatus {
|
||||
connected?: boolean;
|
||||
interface IntegrationsStatus {
|
||||
integrations?: Array<{ connected?: boolean; enabled?: boolean }>;
|
||||
}
|
||||
|
||||
interface NotificationChannel {
|
||||
@@ -227,10 +227,13 @@ export function GettingStartedChecklist() {
|
||||
// for established users. See docs/audit/v15-performance.md.
|
||||
const onboardingPending = !!user && user.onboardingCompletedAt == null;
|
||||
|
||||
const { data: withingsData } = useQuery<WithingsStatus>({
|
||||
queryKey: ["withings", "status"],
|
||||
// v1.17.0 — any connected data source satisfies the step, so we read
|
||||
// the consolidated integrations envelope (Withings / WHOOP / Fitbit /
|
||||
// moodLog) rather than the Withings-only status route.
|
||||
const { data: integrationsData } = useQuery<IntegrationsStatus>({
|
||||
queryKey: queryKeys.integrationsStatus(),
|
||||
queryFn: async () => {
|
||||
return apiGet("/api/withings/status");
|
||||
return apiGet("/api/integrations/status");
|
||||
},
|
||||
enabled: onboardingPending,
|
||||
});
|
||||
@@ -244,7 +247,10 @@ export function GettingStartedChecklist() {
|
||||
});
|
||||
|
||||
const medicationCount = medsData?.length ?? 0;
|
||||
const withingsConnected = withingsData?.connected === true;
|
||||
const dataSourceConnected = (integrationsData?.integrations ?? []).some(
|
||||
(integration) =>
|
||||
integration?.connected === true || integration?.enabled === true,
|
||||
);
|
||||
const notificationsConfigured = (notificationsData?.channels ?? []).some(
|
||||
(channel) => channel?.enabled === true,
|
||||
);
|
||||
@@ -259,7 +265,7 @@ export function GettingStartedChecklist() {
|
||||
},
|
||||
measurementCount,
|
||||
medicationCount,
|
||||
withingsConnected,
|
||||
dataSourceConnected,
|
||||
notificationsConfigured,
|
||||
dismissedIds,
|
||||
}),
|
||||
@@ -269,7 +275,7 @@ export function GettingStartedChecklist() {
|
||||
user?.gender,
|
||||
measurementCount,
|
||||
medicationCount,
|
||||
withingsConnected,
|
||||
dataSourceConnected,
|
||||
notificationsConfigured,
|
||||
dismissedIds,
|
||||
],
|
||||
|
||||
@@ -21,7 +21,7 @@ function inputs(overrides: Partial<Parameters<typeof buildChecklist>[0]> = {}) {
|
||||
profile: completeProfile,
|
||||
measurementCount: 0,
|
||||
medicationCount: 0,
|
||||
withingsConnected: false,
|
||||
dataSourceConnected: false,
|
||||
notificationsConfigured: false,
|
||||
dismissedIds: new Set<ChecklistItemId>(),
|
||||
...overrides,
|
||||
@@ -49,7 +49,7 @@ describe("buildChecklist", () => {
|
||||
"profile",
|
||||
"measurement",
|
||||
"medication",
|
||||
"withings",
|
||||
"dataSource",
|
||||
"notifications",
|
||||
]);
|
||||
});
|
||||
@@ -64,12 +64,21 @@ describe("buildChecklist", () => {
|
||||
expect(items.find((i) => i.id === "measurement")?.done).toBe(true);
|
||||
});
|
||||
|
||||
it("flags medication and withings independently", () => {
|
||||
it("flags medication and dataSource independently", () => {
|
||||
const items = buildChecklist(
|
||||
inputs({ medicationCount: 2, withingsConnected: true }),
|
||||
inputs({ medicationCount: 2, dataSourceConnected: true }),
|
||||
);
|
||||
expect(items.find((i) => i.id === "medication")?.done).toBe(true);
|
||||
expect(items.find((i) => i.id === "withings")?.done).toBe(true);
|
||||
expect(items.find((i) => i.id === "dataSource")?.done).toBe(true);
|
||||
});
|
||||
|
||||
it("dataSource is satisfied by any connected source", () => {
|
||||
// The predicate is source-agnostic — a single boolean stands in for
|
||||
// Withings, WHOOP, Oura, Polar, Nightscout, Fitbit or Apple Health.
|
||||
const off = buildChecklist(inputs({ dataSourceConnected: false }));
|
||||
expect(off.find((i) => i.id === "dataSource")?.done).toBe(false);
|
||||
const on = buildChecklist(inputs({ dataSourceConnected: true }));
|
||||
expect(on.find((i) => i.id === "dataSource")?.done).toBe(true);
|
||||
});
|
||||
|
||||
it("propagates per-item dismissal", () => {
|
||||
@@ -86,7 +95,7 @@ describe("buildChecklist", () => {
|
||||
expect(hrefs.profile).toBe("/settings/account");
|
||||
expect(hrefs.measurement).toBe("/measurements");
|
||||
expect(hrefs.medication).toBe("/medications");
|
||||
expect(hrefs.withings).toBe("/settings/integrations");
|
||||
expect(hrefs.dataSource).toBe("/settings/integrations");
|
||||
expect(hrefs.notifications).toBe("/settings/notifications");
|
||||
});
|
||||
});
|
||||
@@ -94,10 +103,10 @@ describe("buildChecklist", () => {
|
||||
describe("visibleChecklist + checklistProgress", () => {
|
||||
it("hides per-item dismissed rows from the visible list", () => {
|
||||
const items = buildChecklist(
|
||||
inputs({ dismissedIds: new Set<ChecklistItemId>(["withings"]) }),
|
||||
inputs({ dismissedIds: new Set<ChecklistItemId>(["dataSource"]) }),
|
||||
);
|
||||
const visible = visibleChecklist(items);
|
||||
expect(visible.map((i) => i.id)).not.toContain("withings");
|
||||
expect(visible.map((i) => i.id)).not.toContain("dataSource");
|
||||
});
|
||||
|
||||
it("counts done items inside the visible subset", () => {
|
||||
@@ -106,7 +115,7 @@ describe("visibleChecklist + checklistProgress", () => {
|
||||
measurementCount: 3,
|
||||
medicationCount: 1,
|
||||
// dismiss the only one not done so percent jumps to 100
|
||||
dismissedIds: new Set<ChecklistItemId>(["withings", "notifications"]),
|
||||
dismissedIds: new Set<ChecklistItemId>(["dataSource", "notifications"]),
|
||||
}),
|
||||
);
|
||||
const progress = checklistProgress(items);
|
||||
@@ -121,7 +130,7 @@ describe("visibleChecklist + checklistProgress", () => {
|
||||
profile: { heightCm: null, dateOfBirth: null, gender: null },
|
||||
measurementCount: 0,
|
||||
medicationCount: 0,
|
||||
withingsConnected: false,
|
||||
dataSourceConnected: false,
|
||||
notificationsConfigured: false,
|
||||
dismissedIds: new Set(),
|
||||
});
|
||||
@@ -185,7 +194,7 @@ describe("shouldShowChecklist", () => {
|
||||
inputs({
|
||||
measurementCount: 3,
|
||||
medicationCount: 1,
|
||||
withingsConnected: true,
|
||||
dataSourceConnected: true,
|
||||
notificationsConfigured: true,
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -10,7 +10,7 @@ export const CHECKLIST_ITEM_IDS = [
|
||||
"profile",
|
||||
"measurement",
|
||||
"medication",
|
||||
"withings",
|
||||
"dataSource",
|
||||
"notifications",
|
||||
] as const;
|
||||
|
||||
@@ -41,8 +41,12 @@ export interface ChecklistInputs {
|
||||
measurementCount: number;
|
||||
/** Number of medications the user has created. */
|
||||
medicationCount: number;
|
||||
/** True iff Withings OAuth is connected (status.connected). */
|
||||
withingsConnected: boolean;
|
||||
/**
|
||||
* True iff at least one data source is connected — Withings, WHOOP,
|
||||
* Oura, Polar, Nightscout, Fitbit, or Apple Health. Any one satisfies
|
||||
* the "connect a data source" step.
|
||||
*/
|
||||
dataSourceConnected: boolean;
|
||||
/**
|
||||
* True iff the user has set up at least one notification channel
|
||||
* (Telegram, ntfy, or Web Push).
|
||||
@@ -54,7 +58,7 @@ export interface ChecklistInputs {
|
||||
|
||||
/**
|
||||
* Compute the ordered checklist for the dashboard hero. Stable order:
|
||||
* profile → measurement → medication → withings → notifications. Each
|
||||
* profile → measurement → medication → dataSource → notifications. Each
|
||||
* item carries the deep-link the row's CTA should navigate to.
|
||||
*/
|
||||
export function buildChecklist(inputs: ChecklistInputs): ChecklistItem[] {
|
||||
@@ -79,10 +83,10 @@ export function buildChecklist(inputs: ChecklistInputs): ChecklistItem[] {
|
||||
dismissed: inputs.dismissedIds.has("medication"),
|
||||
},
|
||||
{
|
||||
id: "withings",
|
||||
done: inputs.withingsConnected,
|
||||
id: "dataSource",
|
||||
done: inputs.dataSourceConnected,
|
||||
href: "/settings/integrations",
|
||||
dismissed: inputs.dismissedIds.has("withings"),
|
||||
dismissed: inputs.dismissedIds.has("dataSource"),
|
||||
},
|
||||
{
|
||||
id: "notifications",
|
||||
|
||||
Reference in new issue
Block a user