Files
jamshalat-diary/lib/core/widgets/ayat_today_card.dart
2026-03-18 00:07:10 +07:00

215 lines
6.3 KiB
Dart

import 'package:flutter/material.dart';
import '../../app/icons/app_icons.dart';
import '../../app/theme/app_colors.dart';
import '../../data/services/muslim_api_service.dart';
import 'arabic_text.dart';
import 'ayat_share_sheet.dart';
class AyatTodayCard extends StatefulWidget {
const AyatTodayCard({
super.key,
required this.headerText,
required this.headerStyle,
});
final String headerText;
final TextStyle headerStyle;
@override
State<AyatTodayCard> createState() => _AyatTodayCardState();
}
class _AyatTodayCardState extends State<AyatTodayCard> {
Map<String, dynamic>? _dailyAyat;
Map<String, dynamic>? _activeAyat;
bool _isLoading = true;
bool _isRandomizing = false;
bool _showingRandomAyat = false;
@override
void initState() {
super.initState();
_loadDailyAyat();
}
Future<void> _loadDailyAyat() async {
final ayat = await MuslimApiService.instance.getDailyAyat();
if (!mounted) return;
setState(() {
_dailyAyat = ayat;
_activeAyat = ayat;
_showingRandomAyat = false;
_isLoading = false;
});
}
Future<void> _showRandomAyat() async {
if (_isRandomizing || _activeAyat == null) return;
setState(() => _isRandomizing = true);
final randomAyat = await MuslimApiService.instance.getRandomAyat(
excludeSurahNumber: _asInt(_activeAyat?['nomorSurah']),
excludeAyahNumber: _asInt(_activeAyat?['nomorAyat']),
);
if (!mounted) return;
setState(() {
_isRandomizing = false;
if (randomAyat != null) {
_activeAyat = randomAyat;
_showingRandomAyat = true;
}
});
}
void _restoreDailyAyat() {
if (_dailyAyat == null) return;
setState(() {
_activeAyat = _dailyAyat;
_showingRandomAyat = false;
});
}
int _asInt(dynamic value) {
if (value is int) return value;
if (value is num) return value.toInt();
if (value is String) return int.tryParse(value) ?? 0;
return 0;
}
@override
Widget build(BuildContext context) {
final isDark = Theme.of(context).brightness == Brightness.dark;
final backgroundColor = isDark
? AppColors.primary.withValues(alpha: 0.08)
: const Color(0xFFF5F9F0);
if (_isLoading) {
return Container(
width: double.infinity,
padding: const EdgeInsets.all(20),
decoration: BoxDecoration(
color: backgroundColor,
borderRadius: BorderRadius.circular(16),
),
child: const Center(child: CircularProgressIndicator()),
);
}
final data = _activeAyat;
if (data == null) return const SizedBox.shrink();
final secondaryColor =
isDark ? AppColors.textSecondaryDark : AppColors.textSecondaryLight;
return Container(
width: double.infinity,
padding: const EdgeInsets.all(20),
decoration: BoxDecoration(
color: backgroundColor,
borderRadius: BorderRadius.circular(16),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: Text(widget.headerText, style: widget.headerStyle)),
IconButton(
icon: AppIcon(
glyph: AppIcons.share,
size: 18,
color: secondaryColor,
),
tooltip: 'Bagikan ayat',
onPressed: () => showAyatShareSheet(context, data),
),
],
),
const SizedBox(height: 16),
Align(
alignment: Alignment.centerRight,
child: ArabicText(
data['teksArab'] ?? '',
baseFontSize: 24,
fontWeight: FontWeight.w400,
height: 1.8,
textAlign: TextAlign.right,
),
),
const SizedBox(height: 16),
Text(
'"${data['teksIndonesia'] ?? ''}"',
style: TextStyle(
fontSize: 14,
fontStyle: FontStyle.italic,
height: 1.5,
color: isDark ? Colors.white : Colors.black87,
),
),
const SizedBox(height: 12),
Text(
'QS. ${data['surahName']}: ${data['nomorAyat']}',
style: const TextStyle(
fontSize: 13,
fontWeight: FontWeight.w600,
color: AppColors.primary,
),
),
const SizedBox(height: 12),
Wrap(
spacing: 8,
runSpacing: 8,
children: [
TextButton.icon(
onPressed: _isRandomizing ? null : _showRandomAyat,
style: TextButton.styleFrom(
foregroundColor: AppColors.primary,
backgroundColor: AppColors.primary.withValues(
alpha: isDark ? 0.16 : 0.12,
),
padding:
const EdgeInsets.symmetric(horizontal: 14, vertical: 10),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(999),
),
),
icon: _isRandomizing
? const SizedBox(
width: 16,
height: 16,
child: CircularProgressIndicator(
strokeWidth: 2,
valueColor: AlwaysStoppedAnimation(AppColors.primary),
),
)
: const AppIcon(
glyph: AppIcons.shuffle,
size: 16,
color: AppColors.primary,
),
label: Text(_showingRandomAyat ? 'Acak Lagi' : 'Ayat Lain'),
),
if (_showingRandomAyat)
TextButton(
onPressed: _restoreDailyAyat,
style: TextButton.styleFrom(
foregroundColor: secondaryColor,
padding: const EdgeInsets.symmetric(
horizontal: 10,
vertical: 10,
),
),
child: const Text('Kembali ke Hari Ini'),
),
],
),
],
),
);
}
}