import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/extensions/int_extensions.dart'; import 'package:test_sa/extensions/text_extensions.dart'; import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/modules/copilot/model/copilot_message_model.dart'; import 'package:test_sa/new_views/app_style/app_color.dart'; import 'package:test_sa/new_views/common_widgets/app_filled_button.dart'; import 'package:test_sa/new_views/common_widgets/default_app_bar.dart'; import 'package:test_sa/new_views/common_widgets/app_text_form_field.dart'; import 'package:test_sa/views/widgets/item_views/info_header_widget.dart'; import 'package:test_sa/views/widgets/item_views/info_text_widget.dart'; import '../controller/copilot_provider.dart'; import 'copilot_chat_page.dart' show CopilotChatPage; class CopilotHistoryPage extends StatefulWidget { static const String routeName = "/copilot-history"; const CopilotHistoryPage({Key? key}) : super(key: key); @override State createState() => _CopilotHistoryPageState(); } class _CopilotHistoryPageState extends State { String _searchQuery = ''; @override void initState() { super.initState(); WidgetsBinding.instance.addPostFrameCallback((_) { context.read().loadHistory(); }); } void _openConversation(String threadId) { Navigator.push( context, CupertinoPageRoute( builder: (_) => const CopilotChatPage( isNewConversation: false, ), ), ).then( (_) => context.read().loadHistory(), ); context.read().loadConversation(threadId); } void _startNewConversation() { context.read().startNewConversation(); Navigator.push( context, CupertinoPageRoute( builder: (_) => const CopilotChatPage( isNewConversation: true, ), ), ).then( (_) => context.read().loadHistory(), ); } List _filteredHistory( List history, ) { final query = _searchQuery.trim().toLowerCase(); if (query.isEmpty) { return history; } return history.where((item) { return item.firstHumanMessage.toLowerCase().contains(query); }).toList(); } @override Widget build(BuildContext context) { return Scaffold( appBar: DefaultAppBar( title: "Copilot History", actions: [ IconButton( icon: const Icon(Icons.chat_bubble), onPressed: _startNewConversation, ), ], ), body: Consumer( builder: (context, provider, _) { if (provider.historyLoading) { return const Center( child: CircularProgressIndicator(), ); } if (provider.history.isEmpty) { return Column( mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.center, children: [ const Icon( Icons.chat_bubble_outline, size: 56, color: AppColor.neutral120, ), 16.height, Text( "No conversations yet", style: AppTextStyles.heading6.copyWith( color: AppColor.neutral120, ), ), 24.height, AppFilledButton( label: "Start a new conversation", maxWidth: true, buttonColor: AppColor.primary10, onPressed: _startNewConversation, ).paddingOnly( start: 48, end: 48, ), ], ).center; } final filteredHistory = _filteredHistory(provider.history); return Column( children: [ 8.height, _buildSearchBar(context), 8.height, if (filteredHistory.isEmpty) Expanded( child: Column( mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.center, children: [ const Icon( Icons.search_off, size: 48, color: AppColor.neutral120, ), 12.height, Text( "No conversations found", style: AppTextStyles.heading6.copyWith( color: AppColor.neutral120, ), ), ], ).center, ) else Expanded( child: ListView.separated( padding: const EdgeInsets.symmetric( horizontal: 16, ), itemCount: filteredHistory.length, separatorBuilder: (context, index) => 12.height, itemBuilder: (context, index) { final item = filteredHistory[index]; return messageHistoryCard( item: item, provider: provider, ); }, ), ), ], ); }, ), ); } Widget _buildSearchBar(BuildContext context) { return AppTextFormField( labelText: "", hintText: context.translation.search, showBorder: false, showShadow: false, // backgroundColor: AppColor.fieldBgColor(context), prefixIcon: Icon( Icons.search, color: context.isDark ? AppColor.neutral10 : AppColor.neutral20, size: 19, ), textInputType: TextInputType.text, contentPadding: EdgeInsets.zero, hintStyle: AppTextStyles.bodyText.copyWith( color: context.isDark ? AppColor.neutral10 : AppColor.neutral20, ), style: AppTextStyles.bodyText.copyWith( color: AppColor.textStyleColor(context), ), onChange: (value) { setState(() { _searchQuery = value; }); }, ) .toShadowContainer( context, showShadow: false, ) .paddingOnly(start: 16, end: 16); } Widget messageHistoryCard({ required CopilotHistoryItem item, required CopilotProvider provider, }) { return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Icon( Icons.chat_bubble, color: AppColor.icon2Color(context), ), 16.width, Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ InfoHeaderWidget( item.firstHumanMessage, ), 4.height, InfoTextLabelWidget( label: _formatDate(item.updatedAt), ), ], ), ], ), "delete_icon" .toSvgAsset( height: 20, width: 20, ) .onPress( () => provider.deleteHistory(item.threadId), ), ], ) .toShadowContainer( context, showShadow: false, ) .onPress(() { _openConversation(item.threadId); }); } String _formatDate(DateTime date) { return "${date.day.toString().padLeft(2, '0')}/" "${date.month.toString().padLeft(2, '0')}/" "${date.year} " "${date.hour.toString().padLeft(2, '0')}:" "${date.minute.toString().padLeft(2, '0')}"; } }