import 'package:flutter/material.dart'; import 'package:posyandu/services/artikel_service.dart'; import 'package:share_plus/share_plus.dart'; import 'dart:async'; class ArtikelDetailScreen extends StatefulWidget { final int artikelId; final ArtikelModel? initialData; const ArtikelDetailScreen({ Key? key, required this.artikelId, this.initialData, }) : super(key: key); @override _ArtikelDetailScreenState createState() => _ArtikelDetailScreenState(); } class _ArtikelDetailScreenState extends State { final ArtikelService _artikelService = ArtikelService(); late Future _artikelFuture; bool _isLoading = true; String? _error; // Flag untuk selalu menggunakan data initial final bool _useInitialDataOnly = false; @override void initState() { super.initState(); _loadArtikelDetail(); } void _loadArtikelDetail() { // Jika ada initial data, prioritaskan initial data if (widget.initialData != null) { _artikelFuture = Future.value(widget.initialData!); return; } // Jika tidak ada initial data tapi flag aktif, buat dummy if (_useInitialDataOnly) { _artikelFuture = Future.value(_createDummyDetail(widget.artikelId)); return; } // Jika masih bisa ambil dari API, coba dengan timeout 5 detik _artikelFuture = _artikelService.getArtikelDetail(widget.artikelId) .timeout( Duration(seconds: 5), onTimeout: () { print('Timeout saat mengambil detail artikel'); throw TimeoutException('Waktu habis saat mengambil detail artikel'); }, ); } // Fungsi lokal untuk membuat model dummy sebagai fallback ArtikelModel _createDummyDetail(int id) { return ArtikelModel( id: id, judul: 'Artikel Tidak Tersedia', isiArtikel: 'Maaf, artikel yang Anda cari tidak dapat diakses saat ini. Silakan coba lagi nanti.', tanggal: DateTime.now(), gambarUrl: null, ); } String _formatDate(DateTime date) { final months = [ '', 'Januari', 'Februari', 'Maret', 'April', 'Mei', 'Juni', 'Juli', 'Agustus', 'September', 'Oktober', 'November', 'Desember' ]; return '${date.day} ${months[date.month]} ${date.year}'; } @override Widget build(BuildContext context) { return Scaffold( body: FutureBuilder( future: _artikelFuture, builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting && widget.initialData == null) { return Center( child: CircularProgressIndicator( color: Colors.teal.shade700, ), ); } else if (snapshot.hasError) { // Jika error tapi ada initial data, gunakan initial data if (widget.initialData != null) { return _buildArtikelDetailBody(widget.initialData!); } return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( Icons.error_outline, color: Colors.red, size: 48, ), SizedBox(height: 16), Text( 'Gagal memuat artikel', style: TextStyle( fontWeight: FontWeight.bold, fontSize: 18, ), ), SizedBox(height: 8), Text('${snapshot.error}'), SizedBox(height: 16), ElevatedButton( onPressed: () { setState(() { _loadArtikelDetail(); }); }, child: Text('Coba Lagi'), style: ElevatedButton.styleFrom( backgroundColor: Colors.teal.shade700, foregroundColor: Colors.white, ), ), ], ), ); } else if (!snapshot.hasData) { // Jika tidak ada data tapi ada initial data, gunakan initial data if (widget.initialData != null) { return _buildArtikelDetailBody(widget.initialData!); } return Center( child: Text('Artikel tidak ditemukan'), ); } return _buildArtikelDetailBody(snapshot.data!); }, ), ); } Widget _buildArtikelDetailBody(ArtikelModel artikel) { final screenSize = MediaQuery.of(context).size; final gambarUrl = artikel.gambarUrl; return CustomScrollView( slivers: [ // Artikel header with image SliverAppBar( expandedHeight: screenSize.height * 0.3, pinned: true, backgroundColor: Colors.teal.shade700, leading: IconButton( icon: Container( padding: EdgeInsets.all(8), decoration: BoxDecoration( color: Colors.black26, shape: BoxShape.circle, ), child: Icon(Icons.arrow_back), ), onPressed: () => Navigator.pop(context), ), actions: [ IconButton( icon: Container( padding: EdgeInsets.all(8), decoration: BoxDecoration( color: Colors.black26, shape: BoxShape.circle, ), child: Icon(Icons.share), ), onPressed: () { Share.share( 'Baca artikel "${artikel.judul}" di aplikasi Posyandu', subject: artikel.judul, ); }, ), ], flexibleSpace: FlexibleSpaceBar( background: Stack( fit: StackFit.expand, children: [ // Image or placeholder gambarUrl != null ? Image.network( gambarUrl, fit: BoxFit.cover, errorBuilder: (context, error, stackTrace) { return Image.network( 'https://img.freepik.com/free-photo/stethoscope-copy-space-medical-stilllife_23-2148854308.jpg', fit: BoxFit.cover, ); }, ) : Image.network( 'https://img.freepik.com/free-photo/stethoscope-copy-space-medical-stilllife_23-2148854308.jpg', fit: BoxFit.cover, ), // Gradient overlay Container( decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ Colors.transparent, Colors.black.withOpacity(0.7), ], ), ), ), ], ), ), ), // Content SliverToBoxAdapter( child: Padding( padding: EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Title Text( artikel.judul, style: TextStyle( fontSize: 24, fontWeight: FontWeight.bold, color: Colors.grey.shade800, ), ), SizedBox(height: 8), // Date Row( children: [ Icon( Icons.calendar_today, size: 16, color: Colors.grey.shade600, ), SizedBox(width: 4), Text( _formatDate(artikel.tanggal), style: TextStyle( color: Colors.grey.shade600, fontSize: 14, ), ), ], ), SizedBox(height: 24), // Content Text( artikel.isiArtikel, style: TextStyle( fontSize: 16, height: 1.6, color: Colors.grey.shade800, ), ), SizedBox(height: 32), // Footer Container( padding: EdgeInsets.all(16), decoration: BoxDecoration( color: Colors.grey.shade100, borderRadius: BorderRadius.circular(12), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Bagikan Artikel', style: TextStyle( fontWeight: FontWeight.bold, fontSize: 16, ), ), SizedBox(height: 8), Text( 'Informasi kesehatan ini penting untuk dibagikan kepada keluarga dan teman Anda.', style: TextStyle( color: Colors.grey.shade700, fontSize: 14, ), ), SizedBox(height: 16), Row( mainAxisAlignment: MainAxisAlignment.center, children: [ ElevatedButton.icon( onPressed: () { Share.share( 'Baca artikel: ${artikel.judul}\n\nBaca selengkapnya di aplikasi Posyandu.', ); }, icon: Icon(Icons.share), label: Text('Bagikan'), style: ElevatedButton.styleFrom( backgroundColor: Colors.teal.shade700, foregroundColor: Colors.white, padding: EdgeInsets.symmetric(horizontal: 24, vertical: 12), ), ), ], ), ], ), ), SizedBox(height: 50), ], ), ), ), ], ); } }