medibound_integration 0.0.45 copy "medibound_integration: ^0.0.45" to clipboard
medibound_integration: ^0.0.45 copied to clipboard

All of medibound's integrations in one package

example/lib/main.dart

import 'dart:async';
import 'dart:io' show HttpServer;
import 'package:flutter/foundation.dart' show kIsWeb;
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_web_auth_2/flutter_web_auth_2.dart';
import 'package:medibound_integration/medibound_integration.dart';

const _html = '''
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Epic Authentication</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <style>
    html, body { margin: 0; padding: 0; }
    main {
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      min-height: 100vh;
      font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif;
    }
    #icon { font-size: 96pt; }
    #text { padding: 2em; max-width: 260px; text-align: center; }
    #button a {
      display: inline-block;
      padding: 12px 24px;
      color: white;
      border-radius: 6px;
      background-color: #0066cc;
      text-decoration: none;
      font-size: 16px;
      font-weight: 600;
    }
    #button a:active { background-color: #0052a3; }
  </style>
</head>
<body>
  <main>
    <div id="icon">🏥</div>
    <div id="text">Press the button below to complete Epic authentication.</div>
    <div id="button"><a href="CALLBACK_URL_HERE">Complete Authentication</a></div>
  </main>
</body>
</html>
''';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  final _integration = EpicIntegration(
    clientId: 'your-client-id', // Replace with your Epic client ID
    clientSecret: 'your-client-secret', // Replace with your Epic client secret
    redirectUri: kIsWeb 
      ? '${Uri.base.origin}/callback' 
      : 'http://localhost:43823/callback',
    epicBaseUrl: 'https://fhir.epic.com/interconnect-fhir-oauth/api/FHIR/R4',
  );

  String _status = 'Not connected';
  bool _isLoading = false;
  HttpServer? _server;

  @override
  void initState() {
    super.initState();
    if (!kIsWeb) {
      _startServer();
    }
  }

  @override
  void dispose() {
    _server?.close();
    super.dispose();
  }

  Future<void> _startServer() async {
    _server = await HttpServer.bind('127.0.0.1', 43823);
    _server?.listen((req) async {
      if (req.uri.path == '/callback') {
        req.response.headers.add('Content-Type', 'text/html');
        req.response.write(
          _html.replaceFirst(
            'CALLBACK_URL_HERE',
            'medibound://success?code=${Uri.encodeComponent(req.uri.queryParameters['code'] ?? '')}',
          ),
        );
        await req.response.close();
      }
    });
  }

  Future<void> _linkWithEpic() async {
    setState(() {
      _isLoading = true;
      _status = 'Connecting...';
    });

    try {
      final tokens = await _integration.launchOAuth(
        callbackUrlScheme: kIsWeb ? Uri.base.origin : 'medibound',
        preferEphemeral: false,
      );

      setState(() {
        _status = 'Connected successfully!\nAccess Token: ${tokens['access_token']?.substring(0, 10)}...';
      });
    } on PlatformException catch (e) {
      setState(() {
        _status = 'Connection failed: ${e.message}';
      });
    } catch (e) {
      setState(() {
        _status = 'Connection failed: $e';
      });
    } finally {
      setState(() {
        _isLoading = false;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Epic Integration Test',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Epic Integration Test'),
          backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        ),
        body: Center(
          child: Padding(
            padding: const EdgeInsets.all(16.0),
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                const Text(
                  'Test Epic Integration',
                  style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
                ),
                const SizedBox(height: 32),
                ElevatedButton.icon(
                  onPressed: _isLoading ? null : _linkWithEpic,
                  icon: _isLoading
                      ? const SizedBox(
                          width: 20,
                          height: 20,
                          child: CircularProgressIndicator(strokeWidth: 2),
                        )
                      : const Icon(Icons.link),
                  label: Text(_isLoading ? 'Connecting...' : 'Link with Epic'),
                  style: ElevatedButton.styleFrom(
                    padding: const EdgeInsets.symmetric(
                      horizontal: 32,
                      vertical: 16,
                    ),
                  ),
                ),
                const SizedBox(height: 32),
                Container(
                  padding: const EdgeInsets.all(16),
                  decoration: BoxDecoration(
                    color: Colors.grey[200],
                    borderRadius: BorderRadius.circular(8),
                  ),
                  child: Text(
                    _status,
                    textAlign: TextAlign.center,
                    style: const TextStyle(fontSize: 16),
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}