import 'dart:io'; import 'dart:ui'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:intl/intl.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:hugeicons/hugeicons.dart'; import '../../core/hijri_date.dart'; import '../../core/sacred_tokens.dart'; import '../../providers.dart'; import '../../data/local/models.dart'; import '../admin/admin_screen.dart'; import 'unsplash_background.dart'; /// A highly polished, dedicated screen displayed specifically on Fridays /// when transitioning towards Dzuhur (Jumat) prayer. class JumatScreen extends ConsumerWidget { const JumatScreen({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { final clock = ref.watch(clockProvider).valueOrNull ?? DateTime.now(); final schedule = ref.watch(todayScheduleProvider); final settings = ref.watch(settingsProvider); final screenData = ref.watch(screenStateProvider); final size = MediaQuery.of(context).size; final s = size.width / 1920; final fs = s * ref.watch(textScaleProvider); final timeStr = DateFormat('HH:mm').format(clock); final secStr = DateFormat(':ss').format(clock); final dateGregorian = DateFormat('EEEE, d MMMM yyyy', 'en').format(clock); final dateHijri = ref.watch(hijriDateProvider).valueOrNull ?? HijriDateFormatter.format(clock); final durToKhutbah = screenData.timeUntilNext ?? const Duration(minutes: 0); final minToKhutbah = durToKhutbah.inMinutes; return Container( color: SacredColors.background, child: Stack( children: [ // ── Underlay: Branded local image or Unsplash ── if (settings.brandedBgImage != null && settings.brandedBgImage!.isNotEmpty) Positioned.fill( child: Image.file( File(settings.brandedBgImage!), fit: BoxFit.cover, color: Colors.black.withValues(alpha: 0.55), colorBlendMode: BlendMode.darken, ), ) else const UnsplashBackground(), // ── Background darkness gradient ── Positioned.fill( child: Container( decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.bottomCenter, end: Alignment.topCenter, colors: [ SacredColors.background.withValues(alpha: 0.8), Colors.transparent, SacredColors.background.withValues(alpha: 0.9), ], stops: const [0.0, 0.4, 1.0], ), ), ), ), // ── Header Shell ── Positioned( top: 48 * s, left: 64 * s, right: 64 * s, child: _buildHeader(context, settings, s), ), // ── Main Content Canvas ── Positioned.fill( top: 140 * s, bottom: 240 * s, left: 64 * s, right: 64 * s, child: Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ // ── Left Column: Clock & Primary Focus ── Expanded( flex: 2, child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.start, children: [ // Pill Container( padding: EdgeInsets.symmetric(horizontal: 24 * s, vertical: 8 * s), decoration: BoxDecoration( color: SacredColors.secondary.withValues(alpha: 0.1), borderRadius: BorderRadius.circular(SacredRadii.full), border: Border.all(color: SacredColors.secondary.withValues(alpha: 0.2)), ), child: Row( mainAxisSize: MainAxisSize.min, children: [ _PulsingDot(color: SacredColors.secondary, size: 12 * s), SizedBox(width: 12 * s), Text( 'PERSIAPAN JUMAT', style: GoogleFonts.plusJakartaSans( fontSize: 16 * s, fontWeight: FontWeight.w700, color: SacredColors.secondary, letterSpacing: 3 * s, ), ), ], ), ), SizedBox(height: 16 * s), // Massive Clock Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( timeStr, style: GoogleFonts.plusJakartaSans( fontSize: 192 * s, fontWeight: FontWeight.w800, color: SacredColors.primary, letterSpacing: -5 * s, height: 1.0, ), ), Padding( padding: EdgeInsets.only(top: 24 * s), child: Text( secStr, style: GoogleFonts.plusJakartaSans( fontSize: 48 * s, fontWeight: FontWeight.w700, color: SacredColors.primary.withValues(alpha: 0.7), ), ), ), ], ), SizedBox(height: 16 * s), // Dates Text( dateGregorian, style: GoogleFonts.plusJakartaSans( fontSize: 36 * s, fontWeight: FontWeight.w700, color: SacredColors.onSurface, ), ), SizedBox(height: 4 * s), Text( dateHijri, style: GoogleFonts.manrope( fontSize: 24 * s, fontWeight: FontWeight.w500, color: SacredColors.secondary.withValues(alpha: 0.9), ), ), ], ), ), // ── Right Column: Khutbah Info Card ── Expanded( flex: 1, child: Container( padding: EdgeInsets.all(40 * s), decoration: BoxDecoration( color: SacredColors.surfaceContainerHigh.withValues(alpha: 0.6), borderRadius: BorderRadius.circular(SacredRadii.xl), border: Border.all(color: Colors.white.withValues(alpha: 0.05)), ), child: ClipRRect( borderRadius: BorderRadius.circular(SacredRadii.xl), child: BackdropFilter( filter: ImageFilter.blur(sigmaX: 20, sigmaY: 20), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( 'NEXT EVENT', style: GoogleFonts.manrope( fontSize: 14 * s, fontWeight: FontWeight.w600, color: SacredColors.onSurfaceVariant, letterSpacing: 3 * s, ), ), HugeIcon(icon: HugeIcons.strokeRoundedSparkles, color: SacredColors.secondary, size: 24 * s), ], ), SizedBox(height: 16 * s), Text( 'MENUJU KHUTBAH', style: GoogleFonts.plusJakartaSans( fontSize: 42 * s, fontWeight: FontWeight.w800, color: SacredColors.onSurface, height: 1.1, ), ), SizedBox(height: 32 * s), // Khatib Info _buildInfoTile( s, icon: Icons.person_pin, color: SacredColors.primary, label: 'KHATIB HARI INI', value: settings.khatibName.isEmpty ? 'Belum Diatur' : settings.khatibName ), SizedBox(height: 24 * s), // Countdown Info _buildInfoTile( s, icon: Icons.timer, color: SacredColors.secondary, label: 'KHUTBAH DIMULAI DALAM', value: minToKhutbah > 0 ? '~ $minToKhutbah Menit' : 'Sebentar Lagi' ), ], ), ), ), ), ), ], ), ), // ── Bottom Navigation Shell (Prayer Times) ── if (schedule != null) Positioned( left: 64 * s, right: 64 * s, bottom: 64 * s, child: _buildPrayerTimesRow(s, schedule), ), // ── Footer Marquee Shell ── Positioned( left: 0, right: 0, bottom: 0, child: _buildMarquee(s, fs, settings), ), ], ), ); } Widget _buildHeader(BuildContext context, AppSettings settings, double s) { return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ // Mosque Name GestureDetector( onTap: () => Navigator.of(context).push(MaterialPageRoute(builder: (_) => const AdminScreen())), child: Text( settings.masjidName, style: GoogleFonts.plusJakartaSans( fontSize: 32 * s, fontWeight: FontWeight.w800, color: SacredColors.primary, ), ), ), // Mosque Address Row( children: [ HugeIcon(icon: HugeIcons.strokeRoundedMosque01, color: SacredColors.primary, size: 24 * s), SizedBox(width: 8 * s), Text( settings.masjidAddress, style: GoogleFonts.manrope( fontSize: 18 * s, fontWeight: FontWeight.w500, color: SacredColors.onSurfaceVariant, ), ), ], ), ], ); } Widget _buildInfoTile(double s, {required IconData icon, required Color color, required String label, required String value}) { return Container( padding: EdgeInsets.all(20 * s), decoration: BoxDecoration( color: SacredColors.surfaceContainerHighest.withValues(alpha: 0.4), borderRadius: BorderRadius.circular(SacredRadii.xl), ), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( padding: EdgeInsets.all(12 * s), decoration: BoxDecoration( color: color.withValues(alpha: 0.2), borderRadius: BorderRadius.circular(SacredRadii.md), ), child: Icon(icon, color: color, size: 24 * s), ), SizedBox(width: 16 * s), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( label, style: GoogleFonts.manrope( fontSize: 12 * s, fontWeight: FontWeight.w700, color: SacredColors.onSurfaceVariant, letterSpacing: 2 * s, ), ), SizedBox(height: 4 * s), Text( value, style: GoogleFonts.plusJakartaSans( fontSize: 22 * s, fontWeight: FontWeight.w700, color: SacredColors.onSurface, ), ), ], ), ), ], ), ); } Widget _buildPrayerTimesRow(double s, DailyPrayerSchedule schedule) { return Container( padding: EdgeInsets.symmetric(horizontal: 16 * s, vertical: 16 * s), decoration: BoxDecoration( color: SacredColors.surfaceContainerLow, borderRadius: BorderRadius.circular(SacredRadii.xl), boxShadow: [ BoxShadow( color: SacredColors.primary.withValues(alpha: 0.1), blurRadius: 40 * s, spreadRadius: 0, ), ], ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ _buildTimeItem(s, 'Fajr', schedule.subuh, Icons.brightness_3, false), _buildTimeItem(s, 'Terbit', schedule.terbit, Icons.wb_twilight, false), _buildTimeItem(s, 'JUMAT', schedule.dzuhur, Icons.wb_sunny, true), _buildTimeItem(s, 'Asr', schedule.ashar, Icons.sunny_snowing, false), _buildTimeItem(s, 'Maghrib', schedule.maghrib, Icons.wb_cloudy, false), _buildTimeItem(s, 'Isha', schedule.isya, Icons.bedtime, false), ], ), ); } Widget _buildTimeItem(double s, String name, String time, IconData icon, bool isJumat) { if (isJumat) { return Container( padding: EdgeInsets.symmetric(horizontal: 48 * s, vertical: 12 * s), decoration: BoxDecoration( color: SacredColors.primary.withValues(alpha: 0.15), border: Border.all(color: SacredColors.primary.withValues(alpha: 0.3)), borderRadius: BorderRadius.circular(SacredRadii.xl), ), child: Column( children: [ Icon(icon, color: SacredColors.primary, size: 28 * s), SizedBox(height: 8 * s), Text(name, style: GoogleFonts.manrope(fontSize: 18 * s, fontWeight: FontWeight.w800, color: SacredColors.primary)), SizedBox(height: 4 * s), Text(time, style: GoogleFonts.plusJakartaSans(fontSize: 16 * s, fontWeight: FontWeight.w700, color: SacredColors.primary)), ], ), ); } return Padding( padding: EdgeInsets.symmetric(horizontal: 24 * s, vertical: 8 * s), child: Column( children: [ Icon(icon, color: SacredColors.onSurface.withValues(alpha: 0.6), size: 24 * s), SizedBox(height: 8 * s), Text(name, style: GoogleFonts.manrope(fontSize: 16 * s, fontWeight: FontWeight.w500, color: SacredColors.onSurface.withValues(alpha: 0.6))), SizedBox(height: 4 * s), Text(time, style: GoogleFonts.plusJakartaSans(fontSize: 16 * s, fontWeight: FontWeight.w700, color: SacredColors.onSurface)), ], ), ); } Widget _buildMarquee(double s, double fs, AppSettings settings) { // Quick custom simplified marquee or fallback to settings.runningTexts final texts = settings.runningTexts.isEmpty ? ["JUMAT MUBARAK: Luruskan dan rapatkan shaf. Harap non-aktifkan alat komunikasi."] : settings.runningTexts; return Container( width: double.infinity, height: 44 * s, decoration: BoxDecoration( color: Colors.black.withValues(alpha: 0.4), ), child: ClipRect( child: _JumatMarquee( texts: texts, s: s, ), ), ); } } class _PulsingDot extends StatefulWidget { final Color color; final double size; const _PulsingDot({required this.color, required this.size}); @override State<_PulsingDot> createState() => _PulsingDotState(); } class _PulsingDotState extends State<_PulsingDot> with SingleTickerProviderStateMixin { late AnimationController _ctrl; @override void initState() { super.initState(); _ctrl = AnimationController(vsync: this, duration: const Duration(milliseconds: 1200))..repeat(); } @override void dispose() { _ctrl.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return SizedBox( width: widget.size, height: widget.size, child: Stack( children: [ FadeTransition( opacity: Tween(begin: 0.75, end: 0.0).animate(_ctrl), child: ScaleTransition( scale: Tween(begin: 1.0, end: 2.0).animate(_ctrl), child: Container(decoration: BoxDecoration(shape: BoxShape.circle, color: widget.color)), ), ), Center(child: Container(width: widget.size, height: widget.size, decoration: BoxDecoration(shape: BoxShape.circle, color: widget.color))), ], ), ); } } class _JumatMarquee extends StatefulWidget { final List texts; final double s; const _JumatMarquee({required this.texts, required this.s}); @override State<_JumatMarquee> createState() => _JumatMarqueeState(); } class _JumatMarqueeState extends State<_JumatMarquee> with TickerProviderStateMixin { late AnimationController _ctrl; @override void initState() { super.initState(); _ctrl = AnimationController(vsync: this, duration: const Duration(seconds: 30))..repeat(); } @override void dispose() { _ctrl.dispose(); super.dispose(); } @override Widget build(BuildContext context) { final joined = widget.texts.join(" • "); final style = GoogleFonts.manrope( fontSize: 16 * widget.s, fontWeight: FontWeight.w600, color: SacredColors.secondary, letterSpacing: 2 * widget.s, ); return LayoutBuilder( builder: (context, constraints) { return Stack( children: [ AnimatedBuilder( animation: _ctrl, builder: (ctx, child) { // Ensure endless scroll mathematically return Positioned( left: -(_ctrl.value * constraints.maxWidth), top: 0, bottom: 0, child: Row( children: [ Container(alignment: Alignment.centerLeft, width: constraints.maxWidth, child: Text(joined, style: style, maxLines: 1)), Container(alignment: Alignment.centerLeft, width: constraints.maxWidth, child: Text(joined, style: style, maxLines: 1)), ], ), ); }, ), ], ); } ); } }