tasq/lib/providers/ramadan_provider.dart

107 lines
3.2 KiB
Dart

import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:supabase_flutter/supabase_flutter.dart';
import '../models/app_settings.dart';
import 'supabase_provider.dart';
/// Fetches the Ramadan configuration from app_settings.
final ramadanConfigProvider = FutureProvider<RamadanConfig>((ref) async {
final client = ref.watch(supabaseClientProvider);
final data = await client
.from('app_settings')
.select()
.eq('key', 'ramadan_mode')
.maybeSingle();
if (data == null) return RamadanConfig(enabled: false, autoDetect: true);
final setting = AppSetting.fromMap(data);
return RamadanConfig.fromJson(setting.value);
});
/// Whether Ramadan mode is currently active.
/// Combines manual toggle with auto-detection via Hijri calendar approximation.
final isRamadanActiveProvider = Provider<bool>((ref) {
final config = ref.watch(ramadanConfigProvider).valueOrNull;
if (config == null) return false;
// Manual override takes priority
if (config.enabled) return true;
// Auto-detect based on approximate Hijri calendar
if (config.autoDetect) {
return isApproximateRamadan(DateTime.now());
}
return false;
});
/// Approximate Ramadan detection using a simplified Hijri calendar calculation.
/// Ramadan moves ~11 days earlier each Gregorian year.
/// This provides a reasonable approximation; for exact dates, a Hijri calendar
/// package could be used.
bool isApproximateRamadan(DateTime now) {
// Known Ramadan start dates (approximate):
// 2025: Feb 28 - Mar 30
// 2026: Feb 17 - Mar 19
// 2027: Feb 7 - Mar 8
// 2028: Jan 27 - Feb 25
final ramadanWindows = {
2025: (start: DateTime(2025, 2, 28), end: DateTime(2025, 3, 30)),
2026: (start: DateTime(2026, 2, 17), end: DateTime(2026, 3, 19)),
2027: (start: DateTime(2027, 2, 7), end: DateTime(2027, 3, 8)),
2028: (start: DateTime(2028, 1, 27), end: DateTime(2028, 2, 25)),
};
final window = ramadanWindows[now.year];
if (window != null) {
return !now.isBefore(window.start) && !now.isAfter(window.end);
}
return false;
}
final ramadanControllerProvider = Provider<RamadanController>((ref) {
final client = ref.watch(supabaseClientProvider);
return RamadanController(client);
});
class RamadanController {
RamadanController(this._client);
final SupabaseClient _client;
Future<void> setEnabled(bool enabled) async {
final current = await _client
.from('app_settings')
.select()
.eq('key', 'ramadan_mode')
.maybeSingle();
final value = current != null
? Map<String, dynamic>.from(current['value'] as Map)
: <String, dynamic>{'auto_detect': true};
value['enabled'] = enabled;
await _client.from('app_settings').upsert({
'key': 'ramadan_mode',
'value': value,
});
}
Future<void> setAutoDetect(bool autoDetect) async {
final current = await _client
.from('app_settings')
.select()
.eq('key', 'ramadan_mode')
.maybeSingle();
final value = current != null
? Map<String, dynamic>.from(current['value'] as Map)
: <String, dynamic>{'enabled': false};
value['auto_detect'] = autoDetect;
await _client.from('app_settings').upsert({
'key': 'ramadan_mode',
'value': value,
});
}
}