import 'package:flutter/material.dart'; import 'package:print_bluetooth_thermal/print_bluetooth_thermal.dart'; import '../services/printer_service.dart'; import '../utils/colors.dart'; class PrinterScreen extends StatefulWidget { final bool embedded; const PrinterScreen({super.key, this.embedded = false}); @override State createState() => _PrinterScreenState(); } class _PrinterScreenState extends State { List _devices = []; bool _loading = false; bool _scanning = false; bool _connecting = false; @override void initState() { super.initState(); _loadDevices(); } Future _loadDevices() async { setState(() => _loading = true); try { final enabled = await printerService.isBluetoothEnabled(); if (!enabled) { if (mounted) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('Bluetooth belum aktif. Nyalakan Bluetooth di HP.'), backgroundColor: kDanger, ), ); } } _devices = await printerService.getPairedDevices(); } catch (e) { if (mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('Gagal memuat printer: $e')), ); } } finally { if (mounted) setState(() => _loading = false); } } Future _scan() async { setState(() => _scanning = true); try { _devices = await printerService.getPairedDevices(); } catch (e) { if (mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('Gagal scan: $e')), ); } } finally { if (mounted) setState(() => _scanning = false); } } Future _connect(BluetoothInfo device) async { setState(() => _connecting = true); final ok = await printerService.connect(device.macAdress); if (mounted) { setState(() => _connecting = false); ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(ok ? 'Terhubung ke ${device.name}' : 'Gagal hubungkan ${device.name}'), backgroundColor: ok ? kSuccess : kDanger, ), ); if (ok) setState(() {}); } } Future _disconnect() async { await printerService.disconnect(); if (mounted) setState(() {}); } @override Widget build(BuildContext context) { final body = _buildBody(context); if (widget.embedded) return body; return Scaffold( appBar: AppBar( title: const Text('Printer Bluetooth'), ), body: SingleChildScrollView( padding: const EdgeInsets.all(12), child: body, ), ); } Widget _buildBody(BuildContext context) { final connected = printerService.isConnected; final connectedMac = printerService.connectedMac; return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Card( child: Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ const Icon(Icons.print_outlined, color: kAccent), const SizedBox(width: 8), Text( 'Printer Bluetooth', style: TextStyle( fontSize: 16, fontWeight: FontWeight.w700, color: kText), ), ], ), const SizedBox(height: 12), Container( width: double.infinity, padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: connected ? kSuccess.withValues(alpha: 0.12) : kSurface, borderRadius: BorderRadius.circular(8), border: Border.all( color: connected ? kSuccess : kBorder, ), ), child: Row( children: [ Icon( connected ? Icons.bluetooth_connected : Icons.bluetooth, color: connected ? kSuccess : kMuted, ), const SizedBox(width: 10), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( connected ? 'Terhubung' : 'Tidak terhubung', style: TextStyle( fontWeight: FontWeight.w600, color: connected ? kSuccess : kMuted, ), ), if (connected && connectedMac != null) Text( connectedMac, style: const TextStyle( fontSize: 12, color: kMuted), ), ], ), ), if (connected) TextButton( onPressed: _connecting ? null : _disconnect, child: const Text('Putus'), ), ], ), ), const SizedBox(height: 14), Row( children: [ Expanded( child: OutlinedButton.icon( onPressed: _scanning ? null : _scan, icon: _scanning ? const SizedBox( height: 16, width: 16, child: CircularProgressIndicator( strokeWidth: 2, color: kAccent), ) : const Icon(Icons.refresh), label: Text(_scanning ? 'Scanning...' : 'Scan Ulang'), ), ), ], ), ], ), ), ), const SizedBox(height: 12), Text( 'Perangkat Tersedia', style: TextStyle(fontSize: 16, fontWeight: FontWeight.w700, color: kText), ), const SizedBox(height: 10), if (_loading) const Center( child: Padding( padding: EdgeInsets.symmetric(vertical: 40), child: CircularProgressIndicator(color: kAccent), )) else if (_devices.isEmpty) const Center( child: Padding( padding: EdgeInsets.symmetric(vertical: 40), child: Column( children: [ Icon(Icons.print_disabled_outlined, size: 48, color: kMuted), SizedBox(height: 8), Text('Tidak ada printer terpasang', style: TextStyle(color: kMuted)), SizedBox(height: 4), Text('Pasangkan printer di pengaturan Bluetooth HP', style: TextStyle(color: kMuted, fontSize: 12)), ], ), ), ) else ListView.separated( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), itemCount: _devices.length, separatorBuilder: (_, __) => const SizedBox(height: 8), itemBuilder: (context, i) { final d = _devices[i]; final isThis = connected && connectedMac == d.macAdress; return Card( child: ListTile( leading: CircleAvatar( backgroundColor: isThis ? kSuccess.withValues(alpha: 0.15) : kAccent.withValues(alpha: 0.15), child: Icon( isThis ? Icons.bluetooth_connected : Icons.print_outlined, color: isThis ? kSuccess : kAccent, ), ), title: Text(d.name.isNotEmpty ? d.name : 'Printer', style: const TextStyle(fontWeight: FontWeight.w600)), subtitle: Text(d.macAdress, style: const TextStyle(fontSize: 12, color: kMuted)), trailing: _connecting ? const SizedBox( height: 18, width: 18, child: CircularProgressIndicator( strokeWidth: 2, color: kAccent), ) : isThis ? const Chip( label: Text('Aktif', style: TextStyle(fontSize: 11)), backgroundColor: kSuccess, labelPadding: EdgeInsets.zero, ) : TextButton( onPressed: () => _connect(d), child: const Text('Hubungkan'), ), ), ); }, ), ], ); } }