import 'package:flutter/material.dart'; import 'package:wisata_app/models/destination.dart'; class DestinationCardModern extends StatefulWidget { final Destination destination; final VoidCallback onTap; const DestinationCardModern({ super.key, required this.destination, required this.onTap, }); @override State createState() => _DestinationCardModernState(); } class _DestinationCardModernState extends State with SingleTickerProviderStateMixin { late AnimationController _controller; late Animation _scaleAnimation; @override void initState() { super.initState(); _controller = AnimationController( duration: const Duration(milliseconds: 300), vsync: this, ); _scaleAnimation = Tween(begin: 1.0, end: 0.95).animate( CurvedAnimation(parent: _controller, curve: Curves.easeInOut), ); } @override void dispose() { _controller.dispose(); super.dispose(); } void _onTapDown(TapDownDetails details) { _controller.forward(); } void _onTapUp(TapUpDetails details) { _controller.reverse(); widget.onTap(); } void _onTapCancel() { _controller.reverse(); } Color _getCategoryColor(String kategori) { switch (kategori.toLowerCase()) { case 'gunung': return const Color(0xFF6B7280); case 'danau': return const Color(0xFF2563EB); case 'pantai': return const Color(0xFF0EA5E9); case 'air terjun': return const Color(0xFF14B8C4); default: return const Color(0xFF0F4C81); } } String _getCategoryLabel(String kategori) { switch (kategori.toLowerCase()) { case 'gunung': return 'Gunung'; case 'danau': return 'Danau'; case 'pantai': return 'Pantai'; case 'air terjun': return 'Air Terjun'; default: return 'Wisata'; } } @override Widget build(BuildContext context) { return GestureDetector( onTapDown: _onTapDown, onTapUp: _onTapUp, onTapCancel: _onTapCancel, child: ScaleTransition( scale: _scaleAnimation, child: Card( elevation: 4, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(16), ), child: Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(16), color: Colors.white, ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Image Section with Gradient Overlay Expanded( flex: 2, child: Stack( children: [ // Background Image Container( width: double.infinity, decoration: BoxDecoration( borderRadius: const BorderRadius.only( topLeft: Radius.circular(16), topRight: Radius.circular(16), ), gradient: LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [ const Color(0xFF0F4C81).withValues(alpha: 0.7), const Color(0xFF14B8C4).withValues(alpha: 0.5), ], ), ), child: ClipRRect( borderRadius: const BorderRadius.only( topLeft: Radius.circular(16), topRight: Radius.circular(16), ), 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(12), child: Column( mainAxisSize: MainAxisSize.min, children: [ const Icon( Icons.broken_image_rounded, color: Colors.white, size: 42, ), const SizedBox(height: 8), Text( 'Gambar gagal dimuat\n${widget.destination.imagePath}', textAlign: TextAlign.center, maxLines: 3, overflow: TextOverflow.ellipsis, style: const TextStyle( color: Colors.white, fontSize: 11, fontWeight: FontWeight.w800, ), ), ], ), ), ), ); }, ), ), ), // Gradient Overlay untuk readability Container( width: double.infinity, decoration: BoxDecoration( borderRadius: const BorderRadius.only( topLeft: Radius.circular(16), topRight: Radius.circular(16), ), gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ Colors.transparent, Colors.black.withValues(alpha: 0.3), ], ), ), ), // Rating Badge Positioned( top: 10, right: 10, child: Container( padding: const EdgeInsets.symmetric( horizontal: 8, vertical: 4, ), decoration: BoxDecoration( color: const Color(0xFFE28D42).withValues(alpha: 0.95), borderRadius: BorderRadius.circular(8), ), child: Row( mainAxisSize: MainAxisSize.min, children: [ const Icon( Icons.star, color: Colors.white, size: 14, ), const SizedBox(width: 3), Text( '${widget.destination.rating.toStringAsFixed(1)} ⭐', style: const TextStyle( color: Colors.white, fontWeight: FontWeight.bold, fontSize: 11, ), ), ], ), ), ), // Category Badge Positioned( top: 10, left: 10, child: Container( padding: const EdgeInsets.symmetric( horizontal: 8, vertical: 4, ), decoration: BoxDecoration( color: _getCategoryColor(widget.destination.kategori) .withValues(alpha: 0.95), borderRadius: BorderRadius.circular(8), ), child: Text( _getCategoryLabel(widget.destination.kategori), style: const TextStyle( color: Colors.white, fontWeight: FontWeight.w600, fontSize: 11, ), ), ), ), ], ), ), // Content Section Expanded( flex: 1, child: Padding( padding: const EdgeInsets.fromLTRB(12, 10, 12, 10), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Nama Wisata Text( widget.destination.nama, maxLines: 1, overflow: TextOverflow.ellipsis, style: const TextStyle( fontSize: 14, fontWeight: FontWeight.bold, color: Color(0xFF0F4C81), ), ), const SizedBox(height: 8), // Lokasi Row( children: [ const Icon( Icons.location_on, size: 12, color: Color(0xFF8B6F47), ), const SizedBox(width: 4), Expanded( child: Text( widget.destination.lokasi, maxLines: 1, overflow: TextOverflow.ellipsis, style: const TextStyle( fontSize: 11, color: Color(0xFF4B6475), ), ), ), ], ), ], ), ), ), ], ), ), ), ), ); } }