import 'package:flutter/material.dart'; import 'package:wisata_app/models/destination.dart'; import '../screens/ar_page.dart'; import '../screens/video_page.dart'; class DestinationDetailPage extends StatefulWidget { const DestinationDetailPage({ super.key, required this.destination, }); final Destination destination; @override State createState() => _DestinationDetailPageState(); } class _DestinationDetailPageState extends State { late final ScrollController _scrollController; @override void initState() { super.initState(); _scrollController = ScrollController(); } @override void dispose() { _scrollController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( body: CustomScrollView( controller: _scrollController, slivers: [ // App Bar with Hero Image SliverAppBar( expandedHeight: 300, floating: false, pinned: true, elevation: 0, leading: GestureDetector( onTap: () => Navigator.pop(context), child: Container( margin: const EdgeInsets.all(8), decoration: BoxDecoration( color: Colors.white.withValues(alpha: 0.95), shape: BoxShape.circle, boxShadow: [ BoxShadow( color: Colors.black.withValues(alpha: 0.2), blurRadius: 8, offset: const Offset(0, 2), ), ], ), child: const Icon( Icons.arrow_back, color: Color(0xFF0F4C81), ), ), ), flexibleSpace: FlexibleSpaceBar( background: Stack( children: [ Positioned.fill( child: Image.network( widget.destination.imagePath, fit: BoxFit.cover, errorBuilder: (context, error, stackTrace) { debugPrint( 'Gagal memuat gambar wisata: ${widget.destination.imagePath} | $error', ); return DecoratedBox( decoration: const BoxDecoration( gradient: LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [ Color(0xFF0F4C81), Color(0xFF14B8C4), ], ), ), child: Center( child: Padding( padding: const EdgeInsets.all(20), child: Column( mainAxisSize: MainAxisSize.min, children: [ const Icon( Icons.broken_image_rounded, color: Colors.white, size: 72, ), const SizedBox(height: 12), Text( 'Gambar gagal dimuat\n${widget.destination.imagePath}', textAlign: TextAlign.center, style: const TextStyle( color: Colors.white, fontWeight: FontWeight.w800, ), ), ], ), ), ), ); }, ), ), // Gradient overlay Container( decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ Colors.transparent, Colors.black.withValues(alpha: 0.5), ], ), ), ), ], ), ), bottom: PreferredSize( preferredSize: const Size.fromHeight(0), child: Container( color: Colors.white, height: 32, child: Container(), ), ), ), // Content SliverToBoxAdapter( child: Container( color: Colors.white, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Header Info Padding( padding: const EdgeInsets.fromLTRB(20, 0, 20, 24), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Title dan Rating Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( widget.destination.nama, style: const TextStyle( fontSize: 28, fontWeight: FontWeight.bold, color: Color(0xFF2C3E50), ), ), const SizedBox(height: 8), Container( padding: const EdgeInsets.symmetric( horizontal: 12, vertical: 6, ), decoration: BoxDecoration( color: _getCategoryColor( widget.destination.kategori, ).withValues(alpha: 0.15), borderRadius: BorderRadius.circular(8), ), child: Text( _getCategoryLabel( widget.destination.kategori, ), style: TextStyle( fontSize: 12, fontWeight: FontWeight.bold, color: _getCategoryColor( widget.destination.kategori, ), ), ), ), ], ), ), Column( children: [ Container( padding: const EdgeInsets.symmetric( horizontal: 12, vertical: 8, ), decoration: BoxDecoration( color: const Color(0xFFE28D42) .withValues(alpha: 0.15), borderRadius: BorderRadius.circular(12), ), child: Row( children: [ const Icon( Icons.star, color: Color(0xFFE28D42), size: 20, ), const SizedBox(width: 4), Text( '${widget.destination.rating.toStringAsFixed(1)} ⭐', style: const TextStyle( fontSize: 16, fontWeight: FontWeight.bold, color: Color(0xFFE28D42), ), ), ], ), ), ], ), ], ), const SizedBox(height: 16), // Lokasi Row( children: [ Icon( Icons.location_on, color: const Color(0xFF0F4C81), size: 20, ), const SizedBox(width: 8), Expanded( child: Text( widget.destination.lokasi, style: TextStyle( fontSize: 14, color: Colors.grey[700], fontWeight: FontWeight.w500, ), ), ), ], ), ], ), ), // Divider Container( height: 1, color: Colors.grey[200], ), // Deskripsi Lengkap Padding( padding: const EdgeInsets.all(20), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( 'Tentang Tempat Ini', style: TextStyle( fontSize: 18, fontWeight: FontWeight.bold, color: Color(0xFF2C3E50), ), ), const SizedBox(height: 12), Text( widget.destination.deskripsiLengkap, style: TextStyle( fontSize: 14, color: Colors.grey[700], height: 1.6, ), textAlign: TextAlign.justify, ), ], ), ), // Divider Container( height: 1, color: Colors.grey[200], ), // Info Wisata Padding( padding: const EdgeInsets.all(20), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( 'Informasi Wisata', style: TextStyle( fontSize: 18, fontWeight: FontWeight.bold, color: Color(0xFF2C3E50), ), ), const SizedBox(height: 16), _buildInfoRow( icon: Icons.category, label: 'Kategori', value: _getCategoryLabel( widget.destination.kategori, ), ), const SizedBox(height: 12), _buildInfoRow( icon: Icons.location_on, label: 'Lokasi', value: widget.destination.lokasi, ), const SizedBox(height: 12), _buildInfoRow( icon: Icons.star, label: 'Rating', value: '${widget.destination.rating.toStringAsFixed(1)} ⭐', ), const SizedBox(height: 12), _buildInfoRow( icon: Icons.height, label: 'Ketinggian', value: widget.destination.ketinggian, ), const SizedBox(height: 12), _buildInfoRow( icon: Icons.confirmation_number, label: 'Tiket & Parkir', value: widget.destination.tiketParkir, ), const SizedBox(height: 12), _buildInfoRow( icon: Icons.access_time, label: 'Jam Operasional', value: widget.destination.jamOperasional, ), ], ), ), // Divider Container( height: 1, color: Colors.grey[200], ), // Media wisata Padding( padding: const EdgeInsets.all(20), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( widget.destination.isVideo ? 'Lihat Video Wisata' : 'Lihat Model 3D', style: TextStyle( fontSize: 18, fontWeight: FontWeight.bold, color: Color(0xFF2C3E50), ), ), const SizedBox(height: 12), Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: const Color(0xFF0F4C81).withValues(alpha: 0.1), borderRadius: BorderRadius.circular(12), border: Border.all( color: const Color(0xFF0F4C81) .withValues(alpha: 0.3), width: 1, ), ), child: Row( children: [ Icon( widget.destination.isVideo ? Icons.play_circle_fill : Icons.view_in_ar, color: const Color(0xFF0F4C81), size: 24, ), const SizedBox(width: 12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( widget.destination.isVideo ? 'Video Wisata Tersedia' : 'Model 3D Tersedia', style: TextStyle( fontSize: 14, fontWeight: FontWeight.bold, color: Color(0xFF2C3E50), ), ), const SizedBox(height: 4), Text( widget.destination.isVideo ? widget.destination.videoPath : widget.destination.modelPath, style: TextStyle( fontSize: 12, color: Colors.grey[600], ), maxLines: 1, overflow: TextOverflow.ellipsis, ), ], ), ), ], ), ), ], ), ), const SizedBox(height: 20), ], ), ), ), ], ), bottomNavigationBar: Container( color: Colors.white, padding: EdgeInsets.fromLTRB( 20, 16, 20, 16 + MediaQuery.of(context).padding.bottom, ), child: SizedBox( width: double.infinity, child: ElevatedButton.icon( onPressed: () { if (widget.destination.isVideo) { Navigator.push( context, MaterialPageRoute( builder: (_) => VideoPage( title: widget.destination.nama, videoPath: widget.destination.videoPath, ), ), ); return; } Navigator.push( context, MaterialPageRoute( builder: (_) => ARPage( namaWisata: widget.destination.nama, modelPath: widget.destination.modelPath, ), ), ); }, icon: Icon( widget.destination.isVideo ? Icons.play_circle_fill : Icons.view_in_ar, ), label: Text( widget.destination.isVideo ? 'Lihat Video Wisata' : 'Lihat AR', ), style: ElevatedButton.styleFrom( backgroundColor: const Color(0xFF0F4C81), foregroundColor: Colors.white, padding: const EdgeInsets.symmetric(vertical: 12), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), elevation: 4, ), ), ), ), ); } Widget _buildInfoRow({ required IconData icon, required String label, required String value, }) { return Row( children: [ Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( color: const Color(0xFF0F4C81).withValues(alpha: 0.1), borderRadius: BorderRadius.circular(8), ), child: Icon( icon, color: const Color(0xFF0F4C81), size: 20, ), ), const SizedBox(width: 12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( label, style: TextStyle( fontSize: 12, color: Colors.grey[600], ), ), const SizedBox(height: 2), Text( value, style: const TextStyle( fontSize: 14, fontWeight: FontWeight.bold, color: Color(0xFF2C3E50), ), ), ], ), ), ], ); } Color _getCategoryColor(String kategori) { switch (kategori.toLowerCase()) { case 'gunung': return const Color(0xFF8B7355); case 'pantai': return const Color(0xFF4ECDC4); case 'danau': return const Color(0xFF2196F3); case 'air terjun': return const Color(0xFF4A90E2); default: return const Color(0xFF0F4C81); } } String _getCategoryLabel(String kategori) { switch (kategori.toLowerCase()) { case 'gunung': return 'Gunung'; case 'pantai': return 'Pantai'; case 'danau': return 'Danau'; case 'air terjun': return 'Air Terjun'; default: return kategori; } } }