import 'package:flutter/material.dart'; import 'package:mysql_client/mysql_client.dart'; import 'package:video_player/video_player.dart'; import 'package:better_player_plus/better_player_plus.dart'; import 'generated/l10n.dart'; class HistoricalRecord extends StatefulWidget { final String email; // 接收來自上個頁面的 email HistoricalRecord({required this.email}); @override _HistoricalRecordState createState() => _HistoricalRecordState(); } class _HistoricalRecordState extends State { List> _results = []; int _totalRecords = 0; // 儲存總比數 @override void initState() { super.initState(); _fetchData(); // 連資料庫 } void _fetchData() async { print('connect'); final conn = await MySQLConnection.createConnection( host: '203.64.84.154', port: 33061, userName: 'root', password: 'Topic@2024', databaseName: 'care', ); await conn.connect(); try { var userNameResult = await conn.execute( 'SELECT homeUserName FROM HomeLogin WHERE homeEmail = :email', {'email': widget.email}, ); if (userNameResult.rows.isNotEmpty) { String homeUserName = userNameResult.rows.first.colByName("homeUserName").toString(); print('homeUserName: $homeUserName'); // 先計算該長者的跌倒紀錄總筆數 var countResult = await conn.execute( 'SELECT COUNT(*) AS total FROM HomeElderFall WHERE homeUserName = :homeUserName', {'homeUserName': homeUserName}, ); if (countResult.rows.isNotEmpty) { _totalRecords = int.parse(countResult.rows.first.colByName("total").toString()); } // 查詢對應 homeUserName 的跌倒資料,並按時間降序排列 var fallResult = await conn.execute( 'SELECT HomeElderFall.* FROM HomeElderFall WHERE homeUserName = :homeUserName ORDER BY hfTime DESC', {'homeUserName': homeUserName}, ); if (fallResult.rows.isEmpty) { print('No data found in users table.'); } else { setState(() { _results = fallResult.rows .map((row) => { '跌倒編號': row.colAt(0), '跌倒時間': row.colAt(1), '跌倒原因': row.colAt(2), '跌倒地點': row.colAt(6), }) .toList(); }); } } else { setState(() { _results = []; }); print('No data found.'); } } catch (e) { print('Error: $e'); } finally { await conn.close(); } } @override Widget build(BuildContext context) { return Scaffold( body: Column( children: [ Container( height: 100, color: Color(0xFFF5E3C3), width: double.infinity, padding: EdgeInsets.all(10.0), child: Center( child: Text( S.of(context).fall_record, style: TextStyle(fontSize: 24, height: 5), ), ), ), Expanded( child: _results.isEmpty ? Center( child: Text( S.of(context).fall_record_empty, // 當沒有資料時顯示的訊息 style: TextStyle(fontSize: 20, color: Colors.grey), ), ) : ListView.builder( padding: EdgeInsets.symmetric(vertical: 5), // 調整列表視圖的 padding itemCount: _results.length, itemBuilder: (context, index) { int displayIndex = _totalRecords - index; // 計算倒序編號 return Padding( padding: const EdgeInsets.symmetric( vertical: 4.0, horizontal: 16.0), child:Card( elevation: 4, // 卡片陰影效果 shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10.0), // 圓角卡片 ), child: Container( decoration: BoxDecoration( border: Border( left: BorderSide(color: Color(0xFFFFCC99), width: 5.0), // 左邊框 top: BorderSide(color: Color(0xFFFFCC99), width: 5.0), // 上邊框 ), borderRadius: BorderRadius.circular(10.0), // 圓角 ), child: ListTile( title: Text( S.of(context).fall_id(displayIndex), // 使用倒序顯示編號 style: TextStyle( fontWeight: FontWeight.bold, fontSize: 18, ), ), subtitle: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( S.of(context).fall_detail( _results[index]['跌倒時間'], _results[index]['跌倒原因'], _results[index]['跌倒地點'], ), style: TextStyle(fontSize: 16, color: Colors.black), // 統一字體樣式 ), ], ), onTap: () { // 點擊時導向詳細資料頁面,並傳遞資料 Navigator.push( context, MaterialPageRoute( builder: (context) => FallDetailPage(fallDetail: _results[index]), ), ); }, ), ), ), ); }, ), ), SizedBox(height: 60), ], ), ); } } // 新增詳細資料頁面 class FallDetailPage extends StatefulWidget { final Map fallDetail; FallDetailPage({required this.fallDetail}); @override State createState() => _FallDetailPageState(); } class _FallDetailPageState extends State { late BetterPlayerController _betterPlayerController; String fhvideoId = ''; @override void initState() { super.initState(); BetterPlayerConfiguration betterPlayerConfiguration = const BetterPlayerConfiguration( aspectRatio: 16 / 9, fit: BoxFit.contain, ); _betterPlayerController = BetterPlayerController(betterPlayerConfiguration); _fetchData(); // 連資料庫、取得影片連結 } void dispose() { super.dispose(); _betterPlayerController.dispose(); } void _fetchData() async { final conn = await MySQLConnection.createConnection( host: '203.64.84.154', port: 33061, userName: 'root', password: 'Topic@2024', databaseName: 'care', ); await conn.connect(); try { var userNameResult = await conn.execute(// 使用傳遞過來的 hfId來找hfvideoId 'SELECT hfvideoId FROM HomeFallVideo WHERE hfallId = :fallId', {'fallId': widget.fallDetail['跌倒編號']}, ); if (userNameResult.rows.isNotEmpty) { fhvideoId = userNameResult.rows.first.colByName( "hfvideoId").toString(); BetterPlayerDataSource dataSource = BetterPlayerDataSource( BetterPlayerDataSourceType.network, "https://streamer.comprehensiveguardian.software/stream/${fhvideoId}/playlist.m3u8", videoFormat: BetterPlayerVideoFormat.hls, ); _betterPlayerController.setupDataSource(dataSource); setState(() {}); // 重新繪製畫面 } } catch (e) { print('Error: $e'); } finally { await conn.close(); } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(S.of(context).fall_detail_title), ), body: Padding( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(S.of(context).fall_detail_time(widget.fallDetail['跌倒時間']), style: TextStyle(fontSize: 18)), SizedBox(height: 10), Text(S.of(context).fall_detail_reason(widget.fallDetail['跌倒原因']), style: TextStyle(fontSize: 18)), SizedBox(height: 10), Text(S.of(context).fall_detail_location(widget.fallDetail['跌倒地點']), style: TextStyle(fontSize: 18)), if (fhvideoId != '') AspectRatio( aspectRatio: 16 / 9, child: BetterPlayer(controller: _betterPlayerController), ), ], ), ), ); } }