diff --git a/devtools_options.yaml b/devtools_options.yaml new file mode 100644 index 0000000..fa0b357 --- /dev/null +++ b/devtools_options.yaml @@ -0,0 +1,3 @@ +description: This file stores settings for Dart & Flutter DevTools. +documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states +extensions: diff --git a/lib/services/yahrtzeits_manager.dart b/lib/services/yahrtzeits_manager.dart index 6eadc1d..cd46a73 100644 --- a/lib/services/yahrtzeits_manager.dart +++ b/lib/services/yahrtzeits_manager.dart @@ -3,6 +3,9 @@ import 'package:flutter/services.dart'; import 'package:timezone/timezone.dart' as tz; import '../models/yahrtzeit.dart'; import '../models/yahrtzeit_date.dart'; +import 'package:kosher_dart/kosher_dart.dart' as kj; +import 'package:device_calendar/device_calendar.dart' as dc; + class YahrtzeitsManager { static final YahrtzeitsManager _instance = YahrtzeitsManager._internal(); @@ -24,18 +27,16 @@ class YahrtzeitsManager { YahrtzeitsManager._internal(); - DeviceCalendarPlugin get deviceCalendarPlugin => _deviceCalendarPlugin; + dc. DeviceCalendarPlugin get deviceCalendarPlugin => _deviceCalendarPlugin; Future syncWithCalendar() async { try { var permissionsGranted = await _deviceCalendarPlugin.hasPermissions(); print('Permissions Granted: $permissionsGranted'); - if (permissionsGranted?.isSuccess == true && - permissionsGranted?.data == false) { + if (permissionsGranted?.isSuccess == true && permissionsGranted?.data == false) { permissionsGranted = await _deviceCalendarPlugin.requestPermissions(); print('Requested Permissions: $permissionsGranted'); - if (permissionsGranted?.isSuccess == false || - permissionsGranted?.data == false) { + if (permissionsGranted?.isSuccess == false || permissionsGranted?.data == false) { print('Calendar permissions not granted'); return; } @@ -43,21 +44,19 @@ class YahrtzeitsManager { final calendarsResult = await _deviceCalendarPlugin.retrieveCalendars(); print('Calendars Result: $calendarsResult'); - if (calendarsResult?.isSuccess == true && - calendarsResult?.data!.isNotEmpty == true) { + if (calendarsResult?.isSuccess == true && calendarsResult?.data!.isNotEmpty == true) { _yahrtzeits.clear(); for (var calendar in calendarsResult!.data!) { print('Retrieving events from calendar: ${calendar.name}'); final eventsResult = await _deviceCalendarPlugin.retrieveEvents( calendar.id!, - RetrieveEventsParams( + dc.RetrieveEventsParams( startDate: tz.TZDateTime.now(tz.local).subtract(Duration(days: 365)), endDate: tz.TZDateTime.now(tz.local).add(Duration(days: 365)), ), ); - if (eventsResult?.isSuccess == true && - eventsResult?.data!.isNotEmpty == true) { + if (eventsResult?.isSuccess == true && eventsResult?.data!.isNotEmpty == true) { for (var event in eventsResult!.data!) { if (event.description?.startsWith('Yahrtzeit for') == true) { final hebrewName = _extractHebrewName(event.description!); @@ -87,118 +86,129 @@ class YahrtzeitsManager { } } - Future addYahrtzeit(Yahrtzeit yahrtzeit) async { + final nextYearGregorianDate = _getNextGregorianDate(yahrtzeit.day, yahrtzeit.month); if (!_yahrtzeits.any((y) => y.englishName == yahrtzeit.englishName && - y.hebrewName == yahrtzeit.hebrewName && - y.gregorianDate == yahrtzeit.gregorianDate)) { - _yahrtzeits.add(yahrtzeit); - await _addToCalendar(yahrtzeit); + y.hebrewName == y.hebrewName && + y.day == yahrtzeit.day && + y.month == yahrtzeit.month && + y.gregorianDate == nextYearGregorianDate)) { + final newYahrtzeit = Yahrtzeit( + englishName: yahrtzeit.englishName, + hebrewName: yahrtzeit.hebrewName, + day: yahrtzeit.day, + month: yahrtzeit.month, + year: yahrtzeit.year, + gregorianDate: nextYearGregorianDate, + ); + _yahrtzeits.add(newYahrtzeit); + await _addToCalendar(newYahrtzeit); + print('Yahrtzeit added: ${newYahrtzeit.englishName}'); } } - Future updateYahrtzeit( - Yahrtzeit oldYahrtzeit, Yahrtzeit newYahrtzeit) async { - await deleteYahrtzeit(oldYahrtzeit); - await addYahrtzeit(newYahrtzeit); - } + Future updateYahrtzeit(Yahrtzeit oldYahrtzeit, Yahrtzeit newYahrtzeit) async { + await deleteYahrtzeit(oldYahrtzeit); // מחיקת היארצייט הישן + await addYahrtzeit(newYahrtzeit); // הוספת היארצייט החדש + print('Yahrtzeit updated: ${newYahrtzeit.englishName}'); + } Future deleteYahrtzeit(Yahrtzeit yahrtzeit) async { - _yahrtzeits.removeWhere((y) => - y.englishName == yahrtzeit.englishName && - y.hebrewName == yahrtzeit.hebrewName && - y.gregorianDate == yahrtzeit.gregorianDate); - await _deleteFromCalendar(yahrtzeit); + try { + final nextYearGregorianDate = _getNextGregorianDate(yahrtzeit.day, yahrtzeit.month); + _yahrtzeits.removeWhere((y) => + y.englishName == yahrtzeit.englishName && + y.hebrewName == y.hebrewName && + y.day == yahrtzeit.day && + y.month == y.month && + y.gregorianDate == nextYearGregorianDate); + await _deleteFromCalendar(yahrtzeit); + print('Yahrtzeit deleted: ${yahrtzeit.englishName}'); + } catch (e) { + print('Error deleting yahrtzeit: $e'); + } } Future> getAllYahrtzeits() async { await syncWithCalendar(); + print('All yahrtzeits fetched: ${_yahrtzeits.length}'); return _yahrtzeits; } - Future> getUpcomingYahrtzeits({int days = 10}) async { + Future> getUpcomingYahrtzeits({int days = 1000}) async { final allYahrtzeits = await getAllYahrtzeits(); final now = tz.TZDateTime.now(tz.local); final upcomingYahrtzeits = allYahrtzeits.where((yahrtzeit) { - final yahrtzeitDate = - tz.TZDateTime.from(yahrtzeit.getGregorianDate(), tz.local); - return yahrtzeitDate.isAfter(now) && - yahrtzeitDate.isBefore(now.add(Duration(days: days))); + final yahrtzeitDate = tz.TZDateTime.from(yahrtzeit.getGregorianDate(), tz.local); + return yahrtzeitDate.isAfter(now) && yahrtzeitDate.isBefore(now.add(Duration(days: days))); }).toList(); + print('Upcoming yahrtzeits fetched: ${upcomingYahrtzeits.length}'); return upcomingYahrtzeits; } - Future _addToCalendar(Yahrtzeit yahrtzeit) async { try { var permissionsGranted = await _deviceCalendarPlugin.hasPermissions(); - print('Permissions Granted: $permissionsGranted'); - if (permissionsGranted?.isSuccess == true && - permissionsGranted?.data == false) { + if (permissionsGranted?.isSuccess == true && permissionsGranted?.data == false) { permissionsGranted = await _deviceCalendarPlugin.requestPermissions(); - print('Requested Permissions: $permissionsGranted'); - if (permissionsGranted?.isSuccess == false || - permissionsGranted?.data == false) { - print('Calendar permissions not granted'); + if (permissionsGranted?.isSuccess == false || permissionsGranted?.data == false) { return; } } final calendarsResult = await _deviceCalendarPlugin.retrieveCalendars(); - print('Calendars Result: $calendarsResult'); - if (calendarsResult?.isSuccess == true && - calendarsResult?.data!.isNotEmpty == true) { + if (calendarsResult?.isSuccess == true && calendarsResult?.data!.isNotEmpty == true) { for (var calendar in calendarsResult!.data!) { - print('Adding event to calendar: ${calendar.name}'); - final event = Event( + final gregorianDate = DateTime( + yahrtzeit.gregorianDate.year, + yahrtzeit.gregorianDate.month, + yahrtzeit.gregorianDate.day, + ); + final event = dc.Event( calendar.id!, title: yahrtzeit.englishName, - description: - 'Yahrtzeit for ${yahrtzeit.englishName} (${yahrtzeit.hebrewName})', - start: tz.TZDateTime.from(yahrtzeit.getGregorianDate(), tz.local), - end: tz.TZDateTime.from(yahrtzeit.getGregorianDate(), tz.local) - .add(Duration(hours: 1)), + description: 'Yahrtzeit for ${yahrtzeit.englishName} (${yahrtzeit.hebrewName})', + start: tz.TZDateTime.from(gregorianDate, tz.local), + end: tz.TZDateTime.from(gregorianDate, tz.local).add(Duration(hours: 1)), ); - print( - 'Event Details: ${event.title}, ${event.description}, ${event.start}, ${event.end}'); final result = await _deviceCalendarPlugin.createOrUpdateEvent(event); - print( - 'Create or Update Event Result for ${calendar.name}: ${result?.data}'); if (result?.isSuccess == false) { - print( - 'Error creating or updating event for ${calendar.name}: ${result?.data}'); + print('Error creating or updating event for ${calendar.name}: ${result?.data}'); } } - } else { - print('No calendars available or failed to retrieve calendars'); } } on PlatformException catch (e) { print('Error adding event to calendar: $e'); } } - Future _deleteFromCalendar(Yahrtzeit yahrtzeit) async { +Future _deleteFromCalendar(Yahrtzeit yahrtzeit) async { try { + var permissionsGranted = await _deviceCalendarPlugin.hasPermissions(); + if (permissionsGranted?.isSuccess == true && permissionsGranted?.data == false) { + permissionsGranted = await _deviceCalendarPlugin.requestPermissions(); + if (permissionsGranted?.isSuccess == false || permissionsGranted?.data == false) { + return; + } + } + final calendarsResult = await _deviceCalendarPlugin.retrieveCalendars(); - if (calendarsResult?.isSuccess == true && - calendarsResult?.data!.isNotEmpty == true) { + if (calendarsResult?.isSuccess == true && calendarsResult?.data!.isNotEmpty == true) { for (var calendar in calendarsResult!.data!) { final eventsResult = await _deviceCalendarPlugin.retrieveEvents( calendar.id!, - RetrieveEventsParams( - startDate: - tz.TZDateTime.now(tz.local).subtract(Duration(days: 365)), + dc.RetrieveEventsParams( + startDate: tz.TZDateTime.now(tz.local).subtract(Duration(days: 365)), endDate: tz.TZDateTime.now(tz.local).add(Duration(days: 365)), ), ); - if (eventsResult?.isSuccess == true && - eventsResult?.data!.isNotEmpty == true) { + if (eventsResult?.isSuccess == true && eventsResult?.data!.isNotEmpty == true) { for (var event in eventsResult!.data!) { - if (event.description?.startsWith( - 'Yahrtzeit for ${yahrtzeit.englishName} (${yahrtzeit.hebrewName})') == - true) { - await _deviceCalendarPlugin.deleteEvent( - calendar.id!, event.eventId!); + if (event.title == yahrtzeit.englishName) { + final result = await _deviceCalendarPlugin.deleteEvent(calendar.id!, event.eventId!); + if (result?.isSuccess == false) { + print('Error deleting event for ${calendar.name}: ${result?.data}'); + } } } } @@ -244,4 +254,19 @@ class YahrtzeitsManager { return true; } + DateTime _getNextGregorianDate(int day, int month) { + try { + final now = DateTime.now(); + final jewishDate = kj.JewishDate(); + final hebrewYear = kj.JewishDate.fromDateTime(now).getJewishYear() + 1; // Always use next Hebrew year + jewishDate.setJewishDate(hebrewYear, month, day); + final gregorianDate = jewishDate.getGregorianCalendar(); + + print('Next Year Gregorian Date: $gregorianDate'); + return gregorianDate; + } catch (e) { + print('Error converting date: $e'); + throw ArgumentError('Invalid Hebrew date provided.'); + } + } } \ No newline at end of file diff --git a/lib/views/add_yahrtzeit.dart b/lib/views/add_yahrtzeit.dart index 019c0c2..6138bd6 100644 --- a/lib/views/add_yahrtzeit.dart +++ b/lib/views/add_yahrtzeit.dart @@ -1,182 +1,10 @@ -// import 'package:flutter/material.dart'; -// import '../localizations/app_localizations.dart'; -// import '../models/yahrtzeit.dart'; -// import '../services/yahrtzeits_manager.dart'; - -// class AddYahrtzeitPage extends StatefulWidget { -// final Yahrtzeit? yahrtzeit; -// final bool isEditing; - -// AddYahrtzeitPage({this.yahrtzeit, this.isEditing = false}); - -// @override -// _AddYahrtzeitPageState createState() => _AddYahrtzeitPageState(); -// } - -// class _AddYahrtzeitPageState extends State { -// final _formKey = GlobalKey(); -// final _englishNameController = TextEditingController(); -// final _hebrewNameController = TextEditingController(); -// final _dayController = TextEditingController(); -// String? _selectedMonth; -// DateTime? _selectedDate; -// final YahrtzeitsManager manager = YahrtzeitsManager(); - -// final List hebrewMonths = [ -// 'Tishrey', 'Cheshvan', 'Kislev', 'Tevet', 'Shvat', 'Adar', -// 'Nissan', 'Iyar', 'Sivan', 'Tamuz', 'Av', 'Elul' -// ]; - -// @override -// void initState() { -// super.initState(); -// if (widget.isEditing && widget.yahrtzeit != null) { -// _englishNameController.text = widget.yahrtzeit!.englishName; -// _hebrewNameController.text = widget.yahrtzeit!.hebrewName; -// _dayController.text = widget.yahrtzeit!.day.toString(); -// _selectedMonth = hebrewMonths[widget.yahrtzeit!.month - 1]; -// _selectedDate = widget.yahrtzeit!.gregorianDate; -// } -// } - -// @override -// Widget build(BuildContext context) { -// return Scaffold( -// appBar: AppBar( -// title: Text(widget.isEditing -// ? AppLocalizations.of(context)!.translate('Edit Yahrtzeit') -// : AppLocalizations.of(context)!.translate('Add Yahrtzeit')), -// ), -// body: Padding( -// padding: const EdgeInsets.all(16.0), -// child: Form( -// key: _formKey, -// child: Column( -// children: [ -// TextFormField( -// controller: _englishNameController, -// decoration: InputDecoration( -// labelText: AppLocalizations.of(context)! -// .translate('Jewish Name')), -// validator: (value) { -// if (value == null || value.isEmpty) { -// return AppLocalizations.of(context)! -// .translate('Please enter Jewish name'); -// } -// return null; -// }, -// ), -// TextFormField( -// controller: _hebrewNameController, -// decoration: InputDecoration( -// labelText: AppLocalizations.of(context)! -// .translate('Full Name')), -// validator: (value) { -// if (value == null || value.isEmpty) { -// return AppLocalizations.of(context)! -// .translate('Please enter Full name'); -// } -// return null; -// }, -// ), -// DropdownButtonFormField( -// value: _selectedMonth, -// decoration: InputDecoration( -// labelText: AppLocalizations.of(context)! -// .translate('Select Month')), -// items: hebrewMonths.map((month) { -// return DropdownMenuItem( -// value: month, -// child: Text(month), -// ); -// }).toList(), -// onChanged: (value) { -// setState(() { -// _selectedMonth = value; -// }); -// }, -// validator: (value) { -// if (value == null || value.isEmpty) { -// return AppLocalizations.of(context)! -// .translate('Please select a month'); -// } -// return null; -// }, -// ), -// TextFormField( -// controller: _dayController, -// decoration: InputDecoration( -// labelText: AppLocalizations.of(context)! -// .translate('Select Day')), -// keyboardType: TextInputType.number, -// validator: (value) { -// if (value == null || value.isEmpty) { -// return AppLocalizations.of(context)! -// .translate('Please enter a day'); -// } -// final day = int.tryParse(value); -// if (day == null || day < 1 || day > 31) { -// return AppLocalizations.of(context)! -// .translate('Please enter a valid day'); -// } -// return null; -// }, -// ), - -// SizedBox(height: 20), -// ElevatedButton( -// onPressed: _saveYahrtzeit, -// child: Text(widget.isEditing -// ? AppLocalizations.of(context)!.translate('Update') -// : AppLocalizations.of(context)!.translate('Save')), -// ), -// ], -// ), -// ), -// ), -// ); -// } - -// Future _pickDate() async { -// DateTime? picked = await showDatePicker( -// context: context, -// initialDate: _selectedDate ?? DateTime.now(), -// firstDate: DateTime(1900), -// lastDate: DateTime(2100), -// ); -// if (picked != null && picked != _selectedDate) { -// setState(() { -// _selectedDate = picked; -// }); -// } -// } - -// void _saveYahrtzeit() async { -// if (_formKey.currentState!.validate() && _selectedDate != null) { -// final now = DateTime.now(); -// final selectedDay = int.parse(_dayController.text); -// final selectedMonth = hebrewMonths.indexOf(_selectedMonth!) + 1; -// final selectedDate = DateTime(now.year, selectedMonth, selectedDay); -// final newYahrtzeit = Yahrtzeit( -// englishName: _englishNameController.text, -// hebrewName: _hebrewNameController.text, -// day: selectedDay, -// month: selectedMonth, -// year: now.year, -// gregorianDate: _selectedDate!, -// ); -// if (widget.isEditing && widget.yahrtzeit != null) { -// await manager.updateYahrtzeit(widget.yahrtzeit!, newYahrtzeit); -// } else { -// await manager.addYahrtzeit(newYahrtzeit); -// } -// Navigator.pop(context, true); -// } -// } -// } +import 'package:cambium_project/views/manage_yahrtzeits.dart'; import 'package:flutter/material.dart'; +import '../home_page.dart'; import '../models/yahrtzeit.dart'; import '../services/yahrtzeits_manager.dart'; +import 'package:kosher_dart/kosher_dart.dart'; +import '../localizations/app_localizations.dart'; class AddYahrtzeitPage extends StatefulWidget { final Yahrtzeit? yahrtzeit; @@ -192,26 +20,36 @@ class _AddYahrtzeitPageState extends State { final _formKey = GlobalKey(); final _englishNameController = TextEditingController(); final _hebrewNameController = TextEditingController(); - final _dayController = TextEditingController(); final _groupController = TextEditingController(); - - String? _selectedMonth; + int? _selectedDay; + int? _selectedMonth; final YahrtzeitsManager manager = YahrtzeitsManager(); - final List hebrewMonths = [ - 'Tishrey', 'Cheshvan', 'Kislev', 'Tevet', 'Shvat', 'Adar', 'AdarAleph','AdarBeit', - 'Nissan', 'Iyar', 'Sivan', 'Tamuz', 'Av', 'Elul' - ]; + static const Map hebrewMonths = { + JewishDate.TISHREI: 'Tishrei', + JewishDate.CHESHVAN: 'Cheshvan', + JewishDate.KISLEV: 'Kislev', + JewishDate.TEVES: 'Teves', + JewishDate.SHEVAT: 'Shevat', + JewishDate.ADAR: 'Adar', + JewishDate.ADAR_II: 'Adar II', + JewishDate.NISSAN: 'Nissan', + JewishDate.IYAR: 'Iyar', + JewishDate.SIVAN: 'Sivan', + JewishDate.TAMMUZ: 'Tammuz', + JewishDate.AV: 'Av', + JewishDate.ELUL: 'Elul', + }; @override void initState() { super.initState(); - if (widget.isEditing && widget.yahrtzeit != null) { - _englishNameController.text = widget.yahrtzeit!.englishName; - _hebrewNameController.text = widget.yahrtzeit!.hebrewName; - _dayController.text = widget.yahrtzeit!.day.toString(); - _selectedMonth = hebrewMonths[widget.yahrtzeit!.month - 1]; - } + if (widget.isEditing && widget.yahrtzeit!= null) { + _englishNameController.text = widget.yahrtzeit!.englishName; + _hebrewNameController.text = widget.yahrtzeit!.hebrewName; + _selectedDay = widget.yahrtzeit!.day; + _selectedMonth = widget.yahrtzeit!.month; + } } @override @@ -228,7 +66,7 @@ class _AddYahrtzeitPageState extends State { children: [ TextFormField( controller: _englishNameController, - decoration: InputDecoration(labelText: 'English Name'), + decoration: InputDecoration(labelText: AppLocalizations.of(context)!.translate('english_name')), validator: (value) { if (value == null || value.isEmpty) { return 'Please enter English name'; @@ -238,7 +76,7 @@ class _AddYahrtzeitPageState extends State { ), TextFormField( controller: _hebrewNameController, - decoration: InputDecoration(labelText: 'Hebrew Name'), + decoration: InputDecoration(labelText: AppLocalizations.of(context)!.translate('hebrew_name')), validator: (value) { if (value == null || value.isEmpty) { return 'Please enter Hebrew name'; @@ -246,56 +84,21 @@ class _AddYahrtzeitPageState extends State { return null; }, ), - DropdownButtonFormField( - value: _selectedMonth, - decoration: InputDecoration(labelText: 'Select Month'), - items: hebrewMonths.map((month) { - return DropdownMenuItem( - value: month, - child: Text(month), - ); - }).toList(), - onChanged: (value) { - setState(() { - _selectedMonth = value; - }); - }, - validator: (value) { - if (value == null || value.isEmpty) { - return 'Please select a month'; - } - return null; - }, - ), - TextFormField( - controller: _dayController, - decoration: InputDecoration(labelText: 'Select Day'), - keyboardType: TextInputType.number, - validator: (value) { - if (value == null || value.isEmpty) { - return 'Please enter a day'; - } - final day = int.tryParse(value); - if (day == null || day < 1 || day > 31) { - return 'Please enter a valid day'; - } - return null; - }, + ListTile( + title: Text(AppLocalizations.of(context)!.translate('select_hebrew_date')), + trailing: Icon(Icons.calendar_today), + onTap: _pickHebrewDate, + ), - TextFormField( + TextFormField( controller: _groupController, decoration: InputDecoration(labelText: 'Group Name'), - validator: (value) { - if (value == null || value.isEmpty) { - return 'Please enter Group name'; - } - return null; - }, ), - SizedBox(height: 20), + + SizedBox(height: 20), ElevatedButton( onPressed: _saveYahrtzeit, - child: Text(widget.isEditing ? 'Update' : 'Save'), + child: Text(AppLocalizations.of(context)!.translate(widget.isEditing ? 'update' : 'save')), ), ], ), @@ -303,27 +106,123 @@ class _AddYahrtzeitPageState extends State { ), ); } + Future _pickHebrewDate() async { + showDialog( + context: context, + builder: (context) { + int? day; + int? month; + return AlertDialog( + title: Text(AppLocalizations.of(context)!.translate('select_hebrew_date')), + content: Column( + mainAxisSize: MainAxisSize.min, + children: [ + TextField( + decoration: InputDecoration(labelText: AppLocalizations.of(context)!.translate('day')), + keyboardType: TextInputType.number, + onChanged: (value) { + day = int.tryParse(value); + }, + ), + DropdownButtonFormField( + decoration: InputDecoration(labelText: AppLocalizations.of(context)!.translate('month')), + items: hebrewMonths.entries.map((entry) { + return DropdownMenuItem( + value: entry.key, + child: Text(entry.value), + ); + }).toList(), + onChanged: (value) { + month = value; + }, + ), + ], + ), + actions: [ + TextButton( + onPressed: () { + Navigator.pop(context); + }, + child: Text(AppLocalizations.of(context)!.translate('cancel')), + ), + TextButton( + onPressed: () { + if (day != null && month != null) { + setState(() { + _selectedDay = day!; + _selectedMonth = month; + }); + Navigator.pop(context); + } + }, + child: Text(AppLocalizations.of(context)!.translate('ok')), + ), + ], + ); + + }, + ); + } void _saveYahrtzeit() async { - if (_formKey.currentState!.validate()) { - final now = DateTime.now(); - final selectedDay = int.parse(_dayController.text); - final selectedMonth = hebrewMonths.indexOf(_selectedMonth!) + 1; - final selectedDate = DateTime(now.year, selectedMonth, selectedDay); - final newYahrtzeit = Yahrtzeit( - englishName: _englishNameController.text, - hebrewName: _hebrewNameController.text, - day: selectedDay, - month: selectedMonth, - year: now.year, - gregorianDate: selectedDate, - ); - if (widget.isEditing && widget.yahrtzeit != null) { - await manager.updateYahrtzeit(widget.yahrtzeit!, newYahrtzeit); - } else { - await manager.addYahrtzeit(newYahrtzeit); + if (_formKey.currentState!.validate() && _selectedDay != null && _selectedMonth != null) { + try { + print(AppLocalizations.of(context)!.translate('saving_yahrtzeit...')); + final gregorianDate = _getNextGregorianDate(_selectedDay!, _selectedMonth!); + print(AppLocalizations.of(context)!.translate('gregorian_date') + ': $gregorianDate'); + final newYahrtzeit = Yahrtzeit( + englishName: _englishNameController.text, + hebrewName: _hebrewNameController.text, + day: _selectedDay!, + month: _selectedMonth!, + year: JewishDate().getJewishYear() + 1, // Use the next Hebrew year + gregorianDate: gregorianDate, + ); + print(AppLocalizations.of(context)!.translate('new_yahrtzeit') + ': $newYahrtzeit'); + if (widget.isEditing && widget.yahrtzeit != null) { + await manager.updateYahrtzeit(widget.yahrtzeit!, newYahrtzeit); + } else { + await manager.addYahrtzeit(newYahrtzeit); + } + print(AppLocalizations.of(context)!.translate('yahrtzeit_saved_successfully')); + Navigator.pop( + context, + ); + } catch (e) { + print(AppLocalizations.of(context)!.translate('error') + ': $e'); + showDialog( + context: context, + builder: (context) => AlertDialog( + title: Text(AppLocalizations.of(context)!.translate('error')), + content: Text(AppLocalizations.of(context)!.translate('error') + ': $e'), + actions: [ + TextButton( + onPressed: () { + Navigator.pop(context); + }, + child: Text(AppLocalizations.of(context)!.translate('ok')), + ), + ], + ), + ); } - Navigator.pop(context, true); + } + } + + DateTime _getNextGregorianDate(int day, int month) { + try { + final now = DateTime.now(); + final jewishDate = JewishDate(); + final hebrewYear = JewishDate.fromDateTime(now).getJewishYear(); + jewishDate.setJewishDate(hebrewYear + 1, month, day); // Use the next Hebrew year + final gregorianDate = jewishDate.getGregorianCalendar(); + + print('Next Year Gregorian Date: $gregorianDate'); + return gregorianDate; + } catch (e) { + print('Error converting date: $e'); + throw ArgumentError('Invalid Hebrew date provided.'); } } } + diff --git a/lib/views/manage_yahrtzeits.dart b/lib/views/manage_yahrtzeits.dart index fc39789..b896f0d 100644 --- a/lib/views/manage_yahrtzeits.dart +++ b/lib/views/manage_yahrtzeits.dart @@ -12,6 +12,8 @@ class ManageYahrtzeits extends StatefulWidget { class _ManageYahrtzeitsState extends State { final YahrtzeitsManager manager = YahrtzeitsManager(); List yahrtzeits = []; + bool isLoading = true; // משתנה לבדוק אם הדאטה בטעינה + final GlobalKey _listKey = GlobalKey(); @override void initState() { @@ -20,10 +22,26 @@ class _ManageYahrtzeitsState extends State { } Future fetchYahrtzeits() async { - final fetchedYahrtzeits = await manager.getAllYahrtzeits(); - setState(() { - yahrtzeits = fetchedYahrtzeits; - }); + try { + final fetchedYahrtzeits = await manager.getAllYahrtzeits(); + setState(() { + yahrtzeits = fetchedYahrtzeits; + isLoading = false; // הגדרת המשתנה ל-false לאחר שהדאטה התקבלה + }); + + WidgetsBinding.instance.addPostFrameCallback((_) { + for (var i = 0; i < yahrtzeits.length; i++) { + if (_listKey.currentState != null && i < yahrtzeits.length) { + _listKey.currentState?.insertItem(i); + } + } + }); + } catch (e) { + print('Error fetching yahrtzeits: $e'); + setState(() { + isLoading = false; // הגדרת המשתנה ל-false גם במקרה של שגיאה + }); + } } void _editYahrtzeit(Yahrtzeit yahrtzeit) async { @@ -36,21 +54,124 @@ class _ManageYahrtzeitsState extends State { ), ), ); - if (result == true) { + if (result != null && result is Yahrtzeit) { + await manager.deleteYahrtzeit(yahrtzeit); // מחיקת הישן + await manager.addYahrtzeit(result); // הוספת החדש fetchYahrtzeits(); } } void _deleteYahrtzeit(Yahrtzeit yahrtzeit) async { - await manager.deleteYahrtzeit(yahrtzeit); - fetchYahrtzeits(); + final confirm = await showDialog( + context: context, + builder: (context) => AlertDialog( + title: + Text(AppLocalizations.of(context)!.translate('confirm_deletion')), + content: Text( + AppLocalizations.of(context)!.translate('delete_confirmation')), + actions: [ + TextButton( + onPressed: () => Navigator.of(context).pop(false), + child: Text(AppLocalizations.of(context)!.translate('cancel')), + ), + TextButton( + onPressed: () => Navigator.of(context).pop(true), + child: Text(AppLocalizations.of(context)!.translate('delete')), + ), + ], + ), + ); + + if (confirm == true) { + try { + final index = yahrtzeits.indexOf(yahrtzeit); + if (index >= 0 && index < yahrtzeits.length) { + setState(() { + yahrtzeits.removeAt(index); + _listKey.currentState?.removeItem(index, (context, animation) { + return SizeTransition( + sizeFactor: animation, + child: _buildYahrtzeitTile(yahrtzeit), + ); + }, duration: Duration(milliseconds: 300)); + }); + await manager.deleteYahrtzeit(yahrtzeit); + } + } catch (e) { + print('Error deleting yahrtzeit: $e'); + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text( + AppLocalizations.of(context)!.translate('deletion_failed')), + ), + ); + } + } } + Widget _buildYahrtzeitTile(Yahrtzeit yahrtzeit) { + return Card( + elevation: 5, + margin: EdgeInsets.symmetric(vertical: 8, horizontal: 16), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(15), + ), + child: ListTile( + contentPadding: EdgeInsets.symmetric(vertical: 10, horizontal: 16), + title: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + yahrtzeit.englishName, + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.bold, + color: Colors.black, + ), + ), + SizedBox(height: 5), + Text( + yahrtzeit.hebrewName, + style: TextStyle( + fontSize: 16, + color: Colors.grey[600], + ), + ), + ], + ), + ], + ), + trailing: Row( + mainAxisSize: MainAxisSize.min, + children: [ + IconButton( + icon: Icon(Icons.edit, color: Colors.deepPurple), + onPressed: () => _editYahrtzeit(yahrtzeit), + ), + IconButton( + icon: Icon(Icons.delete, color: Colors.red), + onPressed: () => _deleteYahrtzeit(yahrtzeit), + ), + ], + ), + ), + ); + } + + // void _deleteYahrtzeit(Yahrtzeit yahrtzeit) async { + // await manager.deleteYahrtzeit(yahrtzeit); + // fetchYahrtzeits(); + // } + @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( - title: Text(AppLocalizations.of(context)!.translate('manage_yahrzeits'), style: TextStyle(color: Colors.white)), + title: Text(AppLocalizations.of(context)!.translate('manage_yahrzeits'), + style: TextStyle(color: Colors.white)), centerTitle: true, backgroundColor: Color.fromARGB(255, 50, 4, 129), elevation: 0, @@ -61,60 +182,45 @@ class _ManageYahrtzeitsState extends State { Navigator.push( context, MaterialPageRoute(builder: (context) => AddYahrtzeitPage()), - ).then((_) => fetchYahrtzeits()); + ).then((result) { + if (result == true) { + fetchYahrtzeits(); + } + }); }, ), ], ), body: Container( color: Colors.white, - child: ListView.builder( - itemCount: yahrtzeits.length, - itemBuilder: (context, index) { - final yahrtzeit = yahrtzeits[index]; - return Card( - elevation: 5, - margin: EdgeInsets.symmetric(vertical: 8, horizontal: 16), - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(15)), - child: ListTile( - contentPadding: EdgeInsets.symmetric(vertical: 10, horizontal: 16), - title: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - yahrtzeit.englishName, - style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold, color: Colors.black), - ), - SizedBox(height: 5), - Text( - yahrtzeit.hebrewName, - style: TextStyle(fontSize: 16, color: Colors.grey[600]), - ), - ], - ), - ], + child: isLoading // בדיקה אם הדאטה עדיין בטעינה + ? Center( + child: CircularProgressIndicator( + valueColor: AlwaysStoppedAnimation(Colors.deepPurple), ), - trailing: Row( - mainAxisSize: MainAxisSize.min, - children: [ - IconButton( - icon: Icon(Icons.edit, color: Colors.deepPurple), - onPressed: () => _editYahrtzeit(yahrtzeit), - ), - IconButton( - icon: Icon(Icons.delete, color: Colors.red), - onPressed: () => _deleteYahrtzeit(yahrtzeit), + ) + : yahrtzeits.isEmpty // בדיקה אם הרשימה ריקה + ? Center( + child: Text( + AppLocalizations.of(context)! + .translate('you_have_not_added_any_yahrtzeits_yet.'), + style: TextStyle(fontSize: 18, color: Colors.grey), ), - ], - ), - ), - ); - }, - ), + ) + : AnimatedList( + key: _listKey, + initialItemCount: yahrtzeits.length, + itemBuilder: (context, index, animation) { + if (index >= yahrtzeits.length) { + return SizedBox.shrink(); + } + return FadeTransition( + opacity: animation, + child: _buildYahrtzeitTile(yahrtzeits[index]), + ); + }, + ), ), ); } -} \ No newline at end of file +} diff --git a/lib/views/upcoming_yahrtzeits.dart b/lib/views/upcoming_yahrtzeits.dart index 4cc0f0c..686f230 100644 --- a/lib/views/upcoming_yahrtzeits.dart +++ b/lib/views/upcoming_yahrtzeits.dart @@ -13,6 +13,7 @@ class UpcomingYahrtzeits extends StatefulWidget { class _UpcomingYahrtzeitsState extends State { final YahrtzeitsManager manager = YahrtzeitsManager(); List yahrtzeitDates = []; + bool isLoading = true; // משתנה חדש לבדוק אם הדאטה בטעינה @override void initState() { @@ -26,9 +27,13 @@ class _UpcomingYahrtzeitsState extends State { final upcomingDates = manager.nextMultiple(yahrtzeits); setState(() { yahrtzeitDates = upcomingDates; + isLoading = false; // הגדרת המשתנה ל-false לאחר שהדאטה התקבלה }); } catch (e) { print('Error fetching yahrtzeits: $e'); + setState(() { + isLoading = false; // הגדרת המשתנה ל-false גם במקרה של שגיאה + }); } } @@ -36,28 +41,37 @@ class _UpcomingYahrtzeitsState extends State { Widget build(BuildContext context) { return Scaffold( appBar: AppBar( - title: Text(AppLocalizations.of(context)!.translate('upcoming_yahrtzeits'), style: TextStyle(color: Colors.white)), + title: Text( + AppLocalizations.of(context)!.translate('upcoming_yahrtzeits'), + style: TextStyle(color: Colors.white)), centerTitle: true, backgroundColor: Color.fromARGB(255, 50, 4, 129), elevation: 0, ), body: Container( color: Colors.white, - child: yahrtzeitDates.isEmpty + child: isLoading // בדיקה אם הדאטה עדיין בטעינה ? Center( - child: Text( - 'No upcoming yahrtzeits found.', - style: TextStyle(color: Colors.white, fontSize: 18), + child: CircularProgressIndicator( + valueColor: AlwaysStoppedAnimation(Colors.deepPurple), ), ) - : ListView.builder( - itemCount: yahrtzeitDates.length, - itemBuilder: (context, index) { - final yahrtzeitDate = yahrtzeitDates[index]; - return YahrtzeitTile(yahrtzeitDate: yahrtzeitDate); - }, - ), + : yahrtzeitDates.isEmpty + ? Center( + child: Text( + AppLocalizations.of(context)! + .translate('no_upcoming_yahrtzeits_found.'), + style: TextStyle(fontSize: 18, color: Colors.grey), + ), + ) + : ListView.builder( + itemCount: yahrtzeitDates.length, + itemBuilder: (context, index) { + final yahrtzeitDate = yahrtzeitDates[index]; + return YahrtzeitTile(yahrtzeitDate: yahrtzeitDate); + }, + ), ), ); } -} \ No newline at end of file +} diff --git a/test/widget_test.dart b/test/widget_test.dart index a2ccb92..3819346 100644 --- a/test/widget_test.dart +++ b/test/widget_test.dart @@ -5,11 +5,10 @@ // gestures. You can also use WidgetTester to find child widgets in the widget // tree, read text, and verify that the values of widget properties are correct. +import 'package:cambium_project/main.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; -import 'package:yahrtzeit_manager/main.dart'; - void main() { testWidgets('Counter increments smoke test', (WidgetTester tester) async { // Build our app and trigger a frame.