import 'dart:io'; import 'package:flutter/material.dart'; import 'package:gifunavi/model/destination.dart'; import 'package:gifunavi/utils/database_helper.dart'; import 'package:get/get.dart'; import 'package:path_provider/path_provider.dart'; import 'package:path/path.dart' as path; class HistoryPage extends StatefulWidget { const HistoryPage({super.key}); @override State createState() => _HistoryPageState(); } class _HistoryPageState extends State { DatabaseHelper db = DatabaseHelper.instance; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("pass_history".tr), ), body: FutureBuilder>( future: db.getDestinations(), builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { return const Center(child: CircularProgressIndicator()); } else if (snapshot.hasError) { return Center(child: Text('Error: ${snapshot.error}')); } else if (!snapshot.hasData || snapshot.data!.isEmpty) { return Center(child: Text("no_checkin_yet".tr)); } final dests = snapshot.data!; return ListView.builder( itemCount: dests.length, itemBuilder: (context, index) { return Padding( padding: const EdgeInsets.all(8.0), child: CustomWidget( title: dests[index].name ?? 'No Name', subtitle: "${dests[index].sub_loc_id ?? 'N/A'} : ${dests[index].name ?? 'N/A'}", image1Path: dests[index].checkin_image, image2Path: dests[index].buypoint_image, ), ); }, ); }, ), ); } } /* class _HistoryPageState_old extends State { DatabaseHelper db = DatabaseHelper.instance; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("pass_history".tr), ), body: SingleChildScrollView( child: Column( children: [ FutureBuilder( // 要検討:スナップショットのエラーハンドリングが行われていますが、具体的なエラーメッセージを表示するようにすることをお勧めします。 // future: db.getDestinations(), builder: (BuildContext context, AsyncSnapshot> snapshot) { if (snapshot.connectionState == ConnectionState.done) { if (snapshot.hasError) { return Center( child: Text( '${snapshot.error} occurred', style: const TextStyle(fontSize: 18), ), ); } else if (snapshot.hasData) { final dests = snapshot.data; if (dests!.isNotEmpty) { debugPrint("----- 通過履歴表示 -----"); return SizedBox( width: MediaQuery.of(context).size.width, height: MediaQuery.of(context).size.height, child: ListView.builder( itemCount: dests.length, itemBuilder: (ctx, index) { //print("--- photo ${dests[index].checkin_image!} ----"); return Padding( padding: const EdgeInsets.all(8.0), child: CustomWidget( // 要検討:画像のサイズがハードコードされています。画像のサイズを動的に設定できるようにすることを検討してください。 title: dests[index].name!, subtitle: "${dests[index].sub_loc_id} : ${dests[index].name}", image1: dests[index].checkin_image != null ? Image.file( File(dests[index].checkin_image!)) : null, image2: dests[index].buypoint_image != null ? Image.file(File( dests[index].buypoint_image!)) : null, ), ); })); } else { return Center(child: Text("no_checkin_yet".tr)); } } } else if (snapshot.connectionState == ConnectionState.waiting) { return const Center( child: CircularProgressIndicator(), ); } return Container(); }), ], ), ), ); } } */ class CustomWidget extends StatelessWidget { final String? image1Path; final String? image2Path; final String title; final String subtitle; const CustomWidget({ super.key, this.image1Path, this.image2Path, required this.title, required this.subtitle, }); Widget _buildImage(String? path) { if (path == null) return const SizedBox.shrink(); return FutureBuilder( future: _getFullImagePath(path), builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.done && snapshot.hasData) { return Image.file( File(snapshot.data!), width: 50, height: 100, fit: BoxFit.cover, errorBuilder: (context, error, stackTrace) { print('Error loading image: $error'); return const Icon(Icons.error); }, ); } else if (snapshot.hasError) { print('Error loading image path: ${snapshot.error}'); return const Icon(Icons.error); } else { return const CircularProgressIndicator(); } }, ); } Future _getFullImagePath(String imagePath) async { final appDir = await getApplicationDocumentsDirectory(); final fileName = path.basename(imagePath); final fullPath = path.join(appDir.path, fileName); debugPrint("Full image path: $fullPath"); return fullPath; } @override Widget build(BuildContext context) { return Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ SizedBox( width: 104, child: Row( children: [ _buildImage(image1Path), if (image1Path != null && image2Path != null) const SizedBox(width: 2), _buildImage(image2Path), ], ), ), const SizedBox(width: 10), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( title, style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold), maxLines: null, ), Text( subtitle, style: const TextStyle(fontSize: 16), maxLines: null, ), ], ), ), ], ); } } /* class CustomWidget_old extends StatelessWidget { final Image? image1; final Image? image2; final String title; final String subtitle; const CustomWidget({ super.key, this.image1, this.image2, required this.title, required this.subtitle, }); @override Widget build(BuildContext context) { return Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ SizedBox( width: 104, // 50 (width of each image) + 2 (space between images) + 2*1 (padding on both sides) child: Row( children: [ if (image1 != null) SizedBox( width: 50, height: 100, child: image1, ), if (image1 != null && image2 != null) const SizedBox(width: 2), if (image2 != null) SizedBox( width: 50, height: 100, child: image2, ), ], ), ), const SizedBox(width: 10), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( title, style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold), maxLines: null, // Allows the text to wrap onto an unlimited number of lines ), Text( subtitle, style: const TextStyle(fontSize: 16), maxLines: null, // Allows the text to wrap onto an unlimited number of lines ), ], ), ), ], ); } } */