proviscommerce_ai_flutter_sdk 0.0.1 copy "proviscommerce_ai_flutter_sdk: ^0.0.1" to clipboard
proviscommerce_ai_flutter_sdk: ^0.0.1 copied to clipboard

A Flutter plugin for integrating the Provis AI chatbot into your applications.

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:proviscommerce_ai_flutter_sdk/proviscommerce_ai_flutter_sdk.dart';
import 'package:geolocator/geolocator.dart';
import 'package:geocoding/geocoding.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'PCAIChatbot SDK Demo',
      theme: ThemeData(primarySwatch: Colors.blue, useMaterial3: true),
      home: const ChatbotDemo(),
    );
  }
}

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

  @override
  State<ChatbotDemo> createState() => _ChatbotDemoState();
}

class _ChatbotDemoState extends State<ChatbotDemo> {
  bool _isInitialized = false;
  String _status = 'Not initialized';

  final String _apiKey =
      'a28ebe289010fc85c188cf7b3462c1c51f2d0375401f699cb0f0c801b317663a';

  @override
  void initState() {
    super.initState();
    _initializeSDK();
    _updateUserLocation();
  }

  Future<void> _initializeSDK() async {
    setState(() => _status = 'Initializing...');

    try {
      final result = await PCAIChatbot.instance.init(apiKey: _apiKey);

      if (result.success) {
        setState(() {
          _isInitialized = true;
          _status = 'SDK initialized successfully';
        });
      } else {
        setState(() {
          _isInitialized = false;
          _status = 'Failed to initialize: ${result.error}';
        });
      }
    } catch (e) {
      setState(() {
        _isInitialized = false;
        _status = 'Error: $e';
      });
    }
  }

  Map<String, dynamic> _locationInfo = {};
  final Map<String, dynamic> _userInfo = {
    "userId": 1,
    "name": "John Doe",
    "productId": "SKU12345",
    "productName": "Wireless Headphones",
    "price": 99.99,
    "cart": {"itemsCount": 2, "totalAmount": 149.99},
    "language": "en",
    "currency": "USD",
  };

  Future<void> _updateUserLocation() async {
    try {
      bool serviceEnabled = await Geolocator.isLocationServiceEnabled();
      if (!serviceEnabled) {
        _locationInfo = {'error': 'Location services are disabled.'};
        return;
      }

      LocationPermission permission = await Geolocator.checkPermission();
      if (permission == LocationPermission.denied) {
        permission = await Geolocator.requestPermission();
        if (permission == LocationPermission.denied) {
          _locationInfo = {'error': 'Location permission denied.'};
          return;
        }
      }

      if (permission == LocationPermission.deniedForever) {
        _locationInfo = {'error': 'Location permission permanently denied.'};
        return;
      }

      Position position = await Geolocator.getCurrentPosition(
        locationSettings:LocationSettings(
          accuracy: LocationAccuracy.high,
        ),
      );

      List<Placemark> placemarks = await placemarkFromCoordinates(
        position.latitude,
        position.longitude,
      );
      Placemark place = placemarks.first;

      _locationInfo = {
        'latitude': position.latitude,
        'longitude': position.longitude,
        'accuracy': position.accuracy,
        'altitude': position.altitude,
        'speed': position.speed,
        'timestamp': position.timestamp.toIso8601String(),
        'address': {
          'street': place.street,
          'locality': place.locality,
          'subLocality': place.subLocality,
          'administrativeArea': place.administrativeArea,
          'subAdministrativeArea': place.subAdministrativeArea,
          'postalCode': place.postalCode,
          'country': place.country,
        },
      };
      setState(() {});
    } catch (e) {
      _locationInfo = {'error': e.toString()};
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('PCAIChatbot SDK Demo'),
        backgroundColor: Colors.blue[600],
        foregroundColor: Colors.white,
      ),
      body: Padding(
        padding: const EdgeInsets.all(24.0),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            // Welcome Section
            const Icon(Icons.chat_bubble_outline, size: 80, color: Colors.blue),
            const SizedBox(height: 24),
            const Text(
              'Welcome to ProvisCommerce AI',
              style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
              textAlign: TextAlign.center,
            ),
            const SizedBox(height: 12),
            const Text(
              'Your AI assistant is ready to help!\nClick the chat button below to get started.',
              style: TextStyle(fontSize: 16, color: Colors.grey),
              textAlign: TextAlign.center,
            ),
            const SizedBox(height: 32),

            // Status Indicator
            Container(
              padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
              decoration: BoxDecoration(
                color: _isInitialized ? Colors.green[50] : Colors.orange[50],
                borderRadius: BorderRadius.circular(20),
                border: Border.all(
                  color: _isInitialized
                      ? Colors.green[200]!
                      : Colors.orange[200]!,
                ),
              ),
              child: Row(
                mainAxisSize: MainAxisSize.min,
                children: [
                  Icon(
                    _isInitialized ? Icons.check_circle : Icons.hourglass_empty,
                    size: 16,
                    color: _isInitialized
                        ? Colors.green[600]
                        : Colors.orange[600],
                  ),
                  const SizedBox(width: 8),
                  Text(
                    _status,
                    style: TextStyle(
                      color: _isInitialized
                          ? Colors.green[600]
                          : Colors.orange[600],
                      fontWeight: FontWeight.w500,
                    ),
                  ),
                ],
              ),
            ),
            const SizedBox(height: 48),

            // Chat Button
            ElevatedButton(
              onPressed: _isInitialized
                  ? () {
                      Navigator.of(context).push(
                        MaterialPageRoute(
                          builder: (_) =>  FullScreenChatbotView(userInfo: _userInfo,locationInfo: _locationInfo,),
                          fullscreenDialog: true,
                        ),
                      );
                    }
                  : null,
              style: ElevatedButton.styleFrom(
                backgroundColor: Colors.blue[600],
                foregroundColor: Colors.white,
                padding: const EdgeInsets.symmetric(
                  horizontal: 32,
                  vertical: 16,
                ),
                shape: RoundedRectangleBorder(
                  borderRadius: BorderRadius.circular(25),
                ),
                elevation: 4,
              ),
              child: const Row(
                mainAxisSize: MainAxisSize.min,
                children: [
                  Icon(Icons.chat, size: 24),
                  SizedBox(width: 12),
                  Text(
                    'Open Chat',
                    style: TextStyle(fontSize: 18, fontWeight: FontWeight.w600),
                  ),
                ],
              ),
            ),
          ],
        ),
      ),
      floatingActionButton: PCAIChatbotFab(
        screenName: "product_details",
        locationInfo: _locationInfo,
        userInfo: _userInfo,
      ),
    );
  }
}

class FullScreenChatbotView extends StatefulWidget {
  final Map<String, dynamic>? locationInfo;
  final Map<String, dynamic>? userInfo;
  const FullScreenChatbotView({super.key,this.locationInfo,this.userInfo});

  @override
  State<FullScreenChatbotView> createState() => _FullScreenChatbotViewState();
}

class _FullScreenChatbotViewState extends State<FullScreenChatbotView> {
  @override
  void initState() {
    super.initState();
    _updateStatusBarColor();
  }

  void _updateStatusBarColor() {
    // Get the primary color from chatbot settings, default to blue if not available
    Color statusBarColor = Colors.blue[600]!;

    // Try to get the actual primary color from the chatbot settings
    final chatSettings = PCAIChatbot.instance.chatSettings;
    if (chatSettings?.theme.primaryColor != null) {
      try {
        statusBarColor = Color(
          int.parse(chatSettings!.theme.primaryColor.replaceAll('#', '0xFF')),
        );
      } catch (_) {
        // Keep default color if parsing fails
      }
    }

    SystemChrome.setSystemUIOverlayStyle(
      SystemUiOverlayStyle(
        statusBarColor: statusBarColor,
        statusBarIconBrightness: Brightness.light,
        statusBarBrightness: Brightness.dark,
      ),
    );
  }

  @override
  void dispose() {
    // Reset status bar to default when leaving the screen
    SystemChrome.setSystemUIOverlayStyle(
      const SystemUiOverlayStyle(
        statusBarColor: Colors.transparent,
        statusBarIconBrightness: Brightness.dark,
        statusBarBrightness: Brightness.light,
      ),
    );
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: PCAIChatbot.instance.loadView(
          onClose: () => Navigator.of(context).pop(),
          userInfo: widget.userInfo,
          locationInfo: widget.locationInfo
        ),
      ),
    );
  }
}