import 'dart:io'; import 'package:connectivity_plus/connectivity_plus.dart'; import 'package:dotted_line/dotted_line.dart'; import 'package:dropdown_button2/dropdown_button2.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:generp/Notifiers/crmProvider/appointmentCalendarProvider.dart'; import 'package:generp/Utils/app_colors.dart'; import 'package:generp/Utils/commonServices.dart'; import 'package:generp/Utils/commonWidgets.dart'; import 'package:generp/Utils/dropdownTheme.dart'; import 'package:generp/screens/crm/LeadDetailsByMode.dart'; import 'package:intl/intl.dart'; import 'package:provider/provider.dart'; import 'package:url_launcher/url_launcher.dart'; class Appointmentcalendar extends StatefulWidget { const Appointmentcalendar({super.key}); @override State createState() => _AppointmentcalendarState(); } class _AppointmentcalendarState extends State { Map _source = {ConnectivityResult.mobile: true}; final MyConnectivity _connectivity = MyConnectivity.instance; Dropdowntheme ddtheme = Dropdowntheme(); int year = DateTime.now().year; int month = DateTime.now().month; ScrollController scrollController = ScrollController(); GlobalKey currentKey = GlobalKey(); @override void initState() { super.initState(); _connectivity.initialise(); _connectivity.myStream.listen((source) { setState(() => _source = source); }); WidgetsBinding.instance.addPostFrameCallback((timeStamp) { final provider = Provider.of( context, listen: false, ); DateTime now = DateTime.now(); final currentDate = DateTime(now.year, now.month, now.day); String formattedDate = DateFormat('yyyy-MM-dd').format(currentDate); provider.setSelectedDate(currentDate); // Initialize selected date provider.crmAppointmentCalendarAPIFunction(context, formattedDate, "All"); _scrollToSelectedDate(currentDate); }); } void _scrollToSelectedDate(DateTime selectedDate) { WidgetsBinding.instance.addPostFrameCallback((_) { if (currentKey.currentContext != null) { Scrollable.ensureVisible( currentKey.currentContext!, duration: const Duration(milliseconds: 300), curve: Curves.easeInOut, alignment: 0.5, // Center the selected date in the viewport ); } else { final daysInMonth = DateTime(year, month + 1, 0).day; final selectedDay = selectedDate.day; const itemWidth = 70.0; // Approximate width of each day item (adjust as needed) final targetOffset = (selectedDay - 1) * itemWidth; scrollController.jumpTo( targetOffset.clamp(0.0, scrollController.position.maxScrollExtent), ); } }); } @override void dispose() { _connectivity.disposeStream(); super.dispose(); } @override Widget build(BuildContext context) { String connection; switch (_source.keys.toList()[0]) { case ConnectivityResult.mobile: connection = 'Online'; break; case ConnectivityResult.wifi: connection = 'Online'; break; case ConnectivityResult.none: default: connection = 'Offline'; } return (connection == "Online") ? Platform.isAndroid ? WillPopScope( onWillPop: () => onBackPressed(context), child: SafeArea( top: false, bottom: true, child: _scaffold(context), ), ) : _scaffold(context) : NoNetwork(context); } Widget _scaffold(BuildContext context) { return Consumer( builder: (context, provider, child) { return Scaffold( resizeToAvoidBottomInset: true, appBar: appbarNew(context, "Appointment Calendar", 0xffffffff), backgroundColor: AppColors.white, body: SizedBox( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Divider( height: 2, color: Color(0xFFD2D2D2), thickness: 0.5, ), Container( padding: const EdgeInsets.symmetric( vertical: 5, horizontal: 10, ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ TextWidget(context, "Follow up Type"), DropdownButtonHideUnderline( child: Row( children: [ Expanded( child: DropdownButton2( isExpanded: true, hint: const Row( children: [ Expanded( child: Text( 'Select Followup Type', style: TextStyle(fontSize: 14), overflow: TextOverflow.ellipsis, ), ), ], ), items: ['All', 'Phone', 'Visit'] .map( (value) => DropdownMenuItem( value: value, child: Text( value, style: const TextStyle( fontSize: 14, ), overflow: TextOverflow.ellipsis, ), ), ) .toList(), value: provider.selectedFollowUpType, onChanged: (String? newValue) { if (newValue != null) { provider.selectedFollowUpType = newValue; if (provider.selectedDate != null) { final formattedDate = DateFormat( 'yyyy-MM-dd', ).format(provider.selectedDate!); provider .crmAppointmentCalendarAPIFunction( context, formattedDate, newValue, ); } } }, buttonStyleData: ddtheme.buttonStyleData, iconStyleData: ddtheme.iconStyleData, menuItemStyleData: ddtheme.menuItemStyleData, dropdownStyleData: ddtheme.dropdownStyleData, ), ), ], ), ), ], ), ), const SizedBox(height: 10), const Divider( height: 2, color: Color(0xFFD2D2D2), thickness: 0.5, ), const SizedBox(height: 16), buildCalendar(context, provider), const SizedBox(height: 16), if (provider.appointmentList.isNotEmpty) ...[ Expanded( child: Container( width: double.infinity, decoration: BoxDecoration( color: AppColors.scaffold_bg_color, ), child: ListView.builder( physics: AlwaysScrollableScrollPhysics(), shrinkWrap: true, padding: EdgeInsets.symmetric( vertical: 5, horizontal: 0, ), itemCount: provider.appointmentList.length, itemBuilder: (context, index) { return InkResponse( onTap: () async { HapticFeedback.selectionClick(); await Navigator.push( context, MaterialPageRoute( builder: (context) => LeadDetailsByMode( mode: "", pageTitleName: "Lead Details", leadId: provider .appointmentList[index] .leadId, ), settings: RouteSettings( name: 'LeadDetailsByMode', ), ), ); }, child: Container( padding: EdgeInsets.symmetric( horizontal: 10, vertical: 5, ), margin: EdgeInsets.symmetric( horizontal: 10, vertical: 5, ), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(16), ), child: Column( children: [ Row( children: [ Expanded( flex: 1, child: Container( height: 50, width: 35, child: SvgPicture.asset( "assets/svg/crm/lead_details_list_ic.svg", ), ), ), SizedBox(width: 10), Expanded( flex: 6, child: SizedBox( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( provider .appointmentList[index] .name ?? "-", maxLines: 1, overflow: TextOverflow.ellipsis, style: TextStyle( fontFamily: "JakartaMedium", fontSize: 14, color: AppColors.semi_black, ), ), Text( provider .appointmentList[index] .product ?? "-", maxLines: 1, style: TextStyle( fontFamily: "JakartaMedium", fontSize: 12, color: AppColors.grey_semi, ), ), ], ), ), ), SizedBox(width: 10), Expanded( flex: 1, child: InkResponse( onTap: () { HapticFeedback.selectionClick(); launch( 'tel://${provider.appointmentList[index].mob1}', ); }, child: SizedBox( height: 35, width: 35, child: SvgPicture.asset( "assets/svg/crm/lead_list_call_ic.svg", ), ), ), ), ], ), ], ), ), ); }, ), ), ), ] else ...[ Expanded( child: Container( decoration: BoxDecoration( color: AppColors.scaffold_bg_color, ), child: Center( child: Text("No Data Available"), ), ), ), ], ], ), ), ); }, ); } Widget buildCalendar( BuildContext context, Appointmentcalendarprovider provider, ) { final daysInMonth = DateTime(year, month + 1, 0).day; const weekdays = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']; return Column( children: [ Container( child: Row( children: [ Expanded( flex: 1, child: SizedBox( child: Row( children: [ Expanded( flex: 1, child: GestureDetector( onTap: () { setState(() { if (month == 1) { month = 12; year--; } else { month--; } // Fetch data for the first day of the new month or selected date final newDate = provider.selectedDate != null && provider.selectedDate!.month == month && provider.selectedDate!.year == year ? provider.selectedDate! : DateTime(year, month, 1); final formattedDate = DateFormat( 'yyyy-MM-dd', ).format(newDate); provider.setSelectedDate(newDate); provider.crmAppointmentCalendarAPIFunction( context, formattedDate, provider.selectedFollowUpType ?? '', ); }); }, child: SvgPicture.asset( "assets/svg/crm/calendar_left.svg", ), ), ), Expanded( flex: 2, child: Text( textAlign: TextAlign.center, '${_monthName(month)} $year', style: TextStyle(fontSize: 14), ), ), Expanded( flex: 1, child: GestureDetector( onTap: () { setState(() { if (month == 12) { month = 1; year++; } else { month++; } // Fetch data for the first day of the new month or selected date final newDate = provider.selectedDate != null && provider.selectedDate!.month == month && provider.selectedDate!.year == year ? provider.selectedDate! : DateTime(year, month, 1); final formattedDate = DateFormat( 'yyyy-MM-dd', ).format(newDate); provider.setSelectedDate(newDate); provider.crmAppointmentCalendarAPIFunction( context, formattedDate, provider.selectedFollowUpType ?? '', ); }); }, child: SvgPicture.asset( "assets/svg/crm/calendar_right.svg", ), ), ), ], ), ), ), Spacer(), ], ), ), const SizedBox(height: 8), Container( height: 70, // Increased height to accommodate weekday text child: ListView.builder( controller: scrollController, scrollDirection: Axis.horizontal, itemCount: daysInMonth, itemBuilder: (BuildContext context, int index) { final day = index + 1; final date = DateTime(year, month, day); final weekday = weekdays[date.weekday - 1]; final isToday = date.year == DateTime.now().year && date.month == DateTime.now().month && date.day == DateTime.now().day; final isSelected = provider.selectedDate == date; return InkResponse( onTap: () { HapticFeedback.selectionClick(); final formattedDate = DateFormat('yyyy-MM-dd').format(date); print(formattedDate); provider.setSelectedDate(date); provider.crmAppointmentCalendarAPIFunction( context, formattedDate, provider.selectedFollowUpType ?? '', ); _scrollToSelectedDate(date); }, child: Container( key: isSelected ? currentKey : null, padding: const EdgeInsets.symmetric(horizontal: 12), decoration: BoxDecoration( color: isSelected ? AppColors.app_blue : Colors.white, ), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text( day.toString(), style: TextStyle( fontSize: 18, fontFamily: "JakartaSemiBold", color: isSelected ? Colors.white : AppColors.semi_black, ), ), const SizedBox(height: 4), Text( weekday, style: TextStyle( fontSize: 12, fontFamily: "JakartaMedium", color: isSelected ? Colors.white : AppColors.grey_semi, ), ), ], ), ), ); }, ), ), ], ); } String _monthName(int month) { const months = [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'June', 'July', 'Aug', 'Sept', 'Oct', 'Nov', 'Dec', ]; return months[month - 1]; } }