Products

UI Widgets

Overview

Our UI Widgets offer a suite of components designed to enrich your application with insightful health information. By integrating our UI Widgets into your app, you provide your users with valuable health insights derived from their activity and wellness data.

Get started with UI Widgets


Key Features

  • Seamless Integration : UI Widgets are designed for easy integration into any mobile application, providing a smooth and cohesive user experience.

  • User Engagement : Engage users with interactive and visually appealing widgets that present health insights in an intuitive and accessible manner.

  • Data-Driven Insights : UI widgets offer valuable insights from processed health data, empowering users with the knowledge to understand and improve their well-being.

  • Cross-Platform Compatibility : With support for iOS, Android, Flutter, and React Native, our widgets ensure a wide-reaching and versatile application across various devices and platforms.

  • Customizable Presentation (Coming Soon) : Tailor the appearance and functionality of the widgets to align with your app's design and user needs, ensuring a consistent and branded experience.


How It Works

Simply use our webview component and call one of our UI Widget endpoints with the profile token provided by our SDK. Instantly, you'll receive a dynamic and interactive chart that suits your needs. Whether you want to display a Score Chart, Score Arc, or Factor List, our widgets make it easy to present valuable insights in a visually appealing way.


Available Widgets

Widgets come in two types - pages and components.


Widget Pages

Widget pages are larger, comprehensive widgets that include a variety of widget components.

Webview Placeholder

Scores Page

The Scores Page widget visually represents an overview of all scores for the current day along with a date selector for browsing historical scores.

URL

https://webview.sahha.ai/app

URL with date

https://webview.sahha.ai/app?date=2024-05-20


Widget Components

Widget components are smaller, more modular widgets that can present target data in a compact way.

You can choose from a variety of styles to present target:

  • Score Chart : Show scores values in a 7 day chart
  • Score Arc : Show score values in a sleek, semicircular gauge
  • Score Bar : Show scores values in a progressive, horizontal gauge
  • Factor List : Show scores factors in an organized list

See below for examples of each style.

Activity Score chart

The Score Chart widget provides a clear visual representation of scores over the last 7 days. Each bar corresponds to a day's score, with the most recent day displayed on the right. This intuitive layout helps you easily track and compare daily performance trends. Perfect for monitoring progress, analyzing patterns, and making data-driven decisions at a glance.

URL

https://webview.sahha.ai/score/activity/chart

URL with date

https://webview.sahha.ai/score/activity/chart?date=2024-05-20


Activity Score Arc

The Score Arc widget visually represents a score within a semi-circle arc. It dynamically displays a numeric score at the center of the arc along with its current state. This intuitive design makes it easy to quickly gauge performance or status at a glance. Ideal for dashboards, reports, and any application where you need a clear, concise visual representation of a score.

URL

https://webview.sahha.ai/score/activity/arc

URL with date

https://webview.sahha.ai/score/activity/arc?date=2024-05-20


Activity Score Bar

The Score Bar widget visually represents a score within a linear bar. It dynamically displays a numeric score at the top of the bar along with its current state. This intuitive design makes it easy to quickly gauge performance or status at a glance. Ideal for dashboards, reports, and any application where you need a clear, concise visual representation of a score.

URL

https://webview.sahha.ai/score/activity/bar

URL with date

https://webview.sahha.ai/score/activity/bar?date=2024-05-20


Activity Factors

The Factors widget offers a detailed list of factors that contributed to determining a score. Each factor is clearly listed, providing transparency and insight into the scoring process. This component is designed to help users understand the underlying reasons behind their scores, fostering trust and enabling more informed decision-making.

URL

https://webview.sahha.ai/score/activity/factors

URL with date

https://webview.sahha.ai/score/activity/factors?date=2024-05-20

Factor score as percentage

https://webview.sahha.ai/score/activity/factors?percentage=true


Integration Guide

Follow this guide to easily add UI Widgets directly into your project. Choose your platform:


iOS

You can show a webview in your UIKit or SwiftUI project.

UIKit

Use a WKWebView

If your project uses UIKit views, you will need to create and display a WKWebView .

View the WebKit - WKWebView guide.

// WebViewController.swift
import UIKit
import WebKit
import Sahha
class WebViewController: UIViewController, WKUIDelegate {
var webView: WKWebView!
override func loadView() {
let webConfiguration = WKWebViewConfiguration()
webView = WKWebView(frame: .zero, configuration: webConfiguration)
webView.uiDelegate = self
view = webView
}
override func viewDidLoad() {
super.viewDidLoad()
// Use https://webview.sahha.ai/app in production
if let url = URL(string: "https://sandbox.webview.sahha.ai/app") {
var request = URLRequest(url: url)
if let authToken = Sahha.profileToken {
request.setValue(authToken, forHTTPHeaderField: "Authorization")
}
webView.load(request)
}
}
}

SwiftUI

Use a UIViewRepresentable and WKWebview

If your project uses SwiftUI views, you will need to create and display a UIViewRepresentable and WKWebview .

Step 1) Create the UIViewRepresentable

View the SwiftUI - UIViewRepresentable guide.

// WebView.swift
import SwiftUI
import WebKit
struct WebView: UIViewRepresentable {
let urlString: String
var profileToken: String?
func makeUIView(context: Context) -> WKWebView {
let webview = WKWebView()
webview.isMultipleTouchEnabled = false
return webview
}
func updateUIView(_ webView: WKWebView, context: Context) {
if let url = URL(string: urlString) {
var request = URLRequest(url: url)
// Add authorization
if let authToken = profileToken {
request.setValue(authToken, forHTTPHeaderField: "Authorization")
}
webView.load(request)
}
}
}

Step 2) Display the UIViewRepresentable in a SwiftUI view

View the WebKit - WKWebview guide.

// ContentView.swift
import SwiftUI
import Sahha
struct ContentView: View {
var body: some View {
// Use https://webview.sahha.ai/app in production
WebView(urlString: "https://sandbox.webview.sahha.ai/app", profileToken: Sahha.profileToken)
}
}

Android

Use a WebView

You will need to create and display a WebView .

View the Webkit - WebView guide.

AndroidView(
factory = {
WebView(context).apply {
val cookieManager = CookieManager.getInstance()
cookieManager.setAcceptCookie(true)
cookieManager.setAcceptThirdPartyCookies(this, true)
layoutParams = ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT
)
webViewClient = WebViewClient()
settings.apply {
javaScriptEnabled = true
domStorageEnabled = true
databaseEnabled = true
cacheMode = WebSettings.LOAD_DEFAULT
}
// Use https://webview.sahha.ai/app in production
val webViewUrl = "https://sandbox.webview.sahha.ai/app"
Sahha.profileToken?.also { token ->
loadUrl(webViewUrl, mapOf("Authorization" to token))
} ?: loadUrl(webViewUrl)
}
},
)

Flutter

Use a WebView

You will need to create and display a WebView .

View the Flutter WebView guide.

Step 1) Add webview_flutter as a dependency in your pubspec.yaml file

dependencies:
flutter:
sdk: flutter
webview_flutter: ^4.7.0

Step 2) Instantiate a WebViewController

View the Flutter WebViewController guide.

Step 3) Pass the controller to a WebViewWidget

View the Flutter WebViewWidget guide.

import 'package:flutter/material.dart';
import 'package:sahha_flutter/sahha_flutter.dart';
import 'package:webview_flutter/webview_flutter.dart';
// Import for Android features
import 'package:webview_flutter_android/webview_flutter_android.dart';
// Import for iOS features
import 'package:webview_flutter_wkwebview/webview_flutter_wkwebview.dart';
class WebView extends StatefulWidget {
const WebView({Key? key}) : super(key: key);
WebState createState() => WebState();
}
class WebState extends State<WebView> {
late final WebViewController _controller;
void initState() {
super.initState();
// #docregion platform_features
late final PlatformWebViewControllerCreationParams params;
if (WebViewPlatform.instance is WebKitWebViewPlatform) {
params = WebKitWebViewControllerCreationParams(
allowsInlineMediaPlayback: true,
mediaTypesRequiringUserAction: const <PlaybackMediaTypes>{},
);
} else {
params = const PlatformWebViewControllerCreationParams();
}
final WebViewController controller =
WebViewController.fromPlatformCreationParams(params);
controller
..setJavaScriptMode(JavaScriptMode.unrestricted)
..setBackgroundColor(const Color(0x00000000))
..setNavigationDelegate(
NavigationDelegate(
onProgress: (int progress) {
debugPrint('WebView is loading (progress : $progress%)');
},
onPageStarted: (String url) {
debugPrint('Page started loading: $url');
},
onPageFinished: (String url) {
debugPrint('Page finished loading: $url');
},
onWebResourceError: (WebResourceError error) {
debugPrint('''
Page resource error:
code: ${error.errorCode}
description: ${error.description}
errorType: ${error.errorType}
isForMainFrame: ${error.isForMainFrame}
''');
},
onNavigationRequest: (NavigationRequest request) {
if (request.url.startsWith('https://www.youtube.com/')) {
debugPrint('blocking navigation to ${request.url}');
return NavigationDecision.prevent;
}
debugPrint('allowing navigation to ${request.url}');
return NavigationDecision.navigate;
},
onHttpError: (HttpResponseError error) {
debugPrint('Error occurred on page: ${error.response?.statusCode}');
},
onUrlChange: (UrlChange change) {
debugPrint('url change to ${change.url}');
},
onHttpAuthRequest: (HttpAuthRequest request) {
debugPrint('auth request $request');
},
),
)
// #docregion platform_features
if (controller.platform is AndroidWebViewController) {
AndroidWebViewController.enableDebugging(true);
(controller.platform as AndroidWebViewController)
.setMediaPlaybackRequiresUserGesture(false);
}
// #enddocregion platform_features
_controller = controller;
SahhaFlutter.getProfileToken().then((value) {
debugPrint(value);
if (value != null) {
controller.loadRequest(
// Use https://webview.sahha.ai/app in production
Uri.parse("https://sandbox.webview.sahha.ai/app"),
headers: {"Authorization": value},
);
} else {
controller.loadRequest(
// Use https://webview.sahha.ai/app in production
Uri.parse("https://sandbox.webview.sahha.ai/app"),
);
}
}).catchError((error, stackTrace) {
debugPrint(error.toString());
});
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Webview Example')),
body: WebViewWidget(controller: _controller),
);
}
}

React Native

Use a WebView

You will need to create and display a WebView .

View the React Native WebView guide.

Step 1) Install react-native-webview via npm

npm install react-native-webview

Step 2) Instantiate a WebViewController

import React, { Component } from 'react';
import { WebView } from 'react-native-webview';
import Sahha from 'sahha-react-native';
const MyWebComponent = () => {
const [profileToken, setProfileToken] = useState<string>('');
useEffect(() => {
Sahha.getProfileToken((error: string, token?: string) => {
if (error) {
console.error(`Error: ${error}`);
} else if (token) {
console.log(`Profile Token: ${token}`);
setProfileToken(token);
} else {
console.log(`Profile Token: null`);
}
});
}, []);
// Use https://webview.sahha.ai/app in production
return <WebView source={{
uri: "https://sandbox.webview.sahha.ai/app",
headers: {
'Authorization': profileToken,
},
}} style={{ flex: 1 }} />;
}

Web

Use an HTML iFrame

You will need to create and display an HTML iFrame .

View the HTML iFrame guide.

Route prefix required

When embedding webviews inside of an iFrame, all route names must be prefixed with /web .

For example, to use the sleep chart widget, the URL should be: https://webview.sahha.ai/web/score/sleep/chart

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Sahha UI Widget Example</title>
<script>
// You will need to authenticate your user profile via the Sahha SDK or API
// Once you receive a profile token, set it here
const profileToken = 'PROFILE_TOKEN'; // Replace 'PROFILE_TOKEN' with the real profile token
// Origin for the webview
// Use 'https://webview.sahha.ai' for your production app
const origin = 'https://sandbox.webview.sahha.ai';
// The source URL for the iFrame
// This should be the full URL of the Sahha widget you want to render inside the iFrame.
// The URL must use the same `origin` as defined above to ensure proper communication between the parent page and the iFrame.
const source = origin + '/web/app'; // Example widget path: "/web/app"
// Event listener for message event
window.addEventListener('message', (event) => {
if (event.origin !== origin) return;
if (event.data.loaded) {
event.source?.postMessage(profileToken, origin);
}
});
// Create and inject the iFrame into your HTML page
document.addEventListener('DOMContentLoaded', () => {
const iframe = document.createElement('iframe');
iframe.src = source;
iframe.title = 'Sahha Webview';
iframe.style.width = '100%';
iframe.style.height = '1000px';
iframe.style.border = 'none';
document.body.appendChild(iframe);
});
</script>
</head>
<body></body>
</html>
Previous
Data Logs