import 'dart:math' as math; import 'package:flutter/material.dart'; import 'package:lottie/lottie.dart'; import 'package:youtube_player_flutter/youtube_player_flutter.dart'; class VideoItem { const VideoItem({required this.title, required this.url}); final String title; final String url; } class VideoScreen extends StatelessWidget { const VideoScreen({super.key}); static const Color _teal = Color(0xFF2F9E94); static const Color _accentPink = Color(0xFFFF55A7); static const List library = [ VideoItem(title: 'Como escovar da maneira certa', url: 'https://www.youtube.com/watch?v=uH8dBWkD__0'), ]; @override Widget build(BuildContext context) { final size = MediaQuery.sizeOf(context); return Scaffold( appBar: AppBar( backgroundColor: _teal, foregroundColor: Colors.white, elevation: 0, title: const Text( 'Vídeos Educativos', style: TextStyle(fontWeight: FontWeight.w900), ), ), body: Stack( clipBehavior: Clip.none, children: [ Positioned.fill( child: Container( decoration: const BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ Color(0xFFFFE6F1), Color(0xFFFFC9DF), ], ), ), ), ), Positioned( left: -size.width * 0.40, bottom: -size.width * 0.45, child: IgnorePointer( child: SizedBox( width: size.width * 1.05, height: size.width * 1.05, child: Transform.rotate( angle: 35 * math.pi / 180, child: Opacity( opacity: 0.95, child: Lottie.asset( 'lottie/Liquid waves.json', fit: BoxFit.cover, repeat: true, ), ), ), ), ), ), SafeArea( child: Align( alignment: Alignment.topCenter, child: ConstrainedBox( constraints: const BoxConstraints(maxWidth: 560), child: Padding( padding: const EdgeInsets.fromLTRB(16, 16, 16, 16), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Container( padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 10), decoration: BoxDecoration( color: Colors.white.withValues(alpha: 0.65), borderRadius: BorderRadius.circular(14), border: Border.all(color: Colors.black.withValues(alpha: 0.08)), ), child: const Row( children: [ Icon(Icons.play_circle_fill_rounded, color: _accentPink), SizedBox(width: 10), Expanded( child: Text( 'Vídeos Educativos', style: TextStyle( fontWeight: FontWeight.w900, color: _accentPink, ), ), ), ], ), ), const SizedBox(height: 14), Expanded( child: GridView.count( crossAxisCount: 2, mainAxisSpacing: 12, crossAxisSpacing: 12, childAspectRatio: 0.92, children: library.map((item) { final videoId = YoutubePlayer.convertUrlToId(item.url); final thumb = videoId == null ? null : 'https://img.youtube.com/vi/$videoId/0.jpg'; return _VideoCard( title: item.title, thumbnailUrl: thumb, onTap: () { Navigator.of(context).push( MaterialPageRoute( builder: (_) => VideoPlayerScreen(url: item.url, title: item.title), ), ); }, ); }).toList(), ), ), ], ), ), ), ), ), ], ), ); } } class _VideoCard extends StatelessWidget { const _VideoCard({required this.title, required this.thumbnailUrl, required this.onTap}); final String title; final String? thumbnailUrl; final VoidCallback onTap; @override Widget build(BuildContext context) { return Material( color: Colors.white.withValues(alpha: 0.80), borderRadius: BorderRadius.circular(16), child: InkWell( borderRadius: BorderRadius.circular(16), onTap: onTap, child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Expanded( child: ClipRRect( borderRadius: const BorderRadius.vertical(top: Radius.circular(16)), child: Stack( fit: StackFit.expand, children: [ if (thumbnailUrl != null) Image.network( thumbnailUrl!, fit: BoxFit.cover, ) else Container(color: Colors.black.withValues(alpha: 0.06)), Container( decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ Colors.black.withValues(alpha: 0.10), Colors.black.withValues(alpha: 0.42), ], ), ), ), const Align( alignment: Alignment.center, child: Icon(Icons.play_circle_fill_rounded, size: 54, color: Colors.white), ), ], ), ), ), Padding( padding: const EdgeInsets.fromLTRB(12, 10, 12, 12), child: Text( title, maxLines: 2, overflow: TextOverflow.ellipsis, style: const TextStyle( fontWeight: FontWeight.w900, color: Color(0xFF2F9E94), ), ), ), ], ), ), ); } } class VideoPlayerScreen extends StatefulWidget { const VideoPlayerScreen({super.key, required this.url, required this.title}); final String url; final String title; @override State createState() => _VideoPlayerScreenState(); } class _VideoPlayerScreenState extends State { static const Color _teal = Color(0xFF2F9E94); static const Color _bg = Color(0xFFFFE6F1); late final YoutubePlayerController _controller; @override void initState() { super.initState(); final id = YoutubePlayer.convertUrlToId(widget.url); _controller = YoutubePlayerController( initialVideoId: id ?? '', flags: const YoutubePlayerFlags( autoPlay: true, mute: false, enableCaption: true, ), ); } @override void dispose() { _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { final hasVideo = _controller.initialVideoId.isNotEmpty; return Scaffold( appBar: AppBar( backgroundColor: _teal, foregroundColor: Colors.white, elevation: 0, title: Text( widget.title, style: const TextStyle(fontWeight: FontWeight.w900), ), ), body: Container( color: _bg, child: SafeArea( child: ListView( padding: const EdgeInsets.fromLTRB(16, 16, 16, 16), children: [ ClipRRect( borderRadius: BorderRadius.circular(16), child: AspectRatio( aspectRatio: 16 / 9, child: hasVideo ? YoutubePlayer( controller: _controller, showVideoProgressIndicator: true, progressIndicatorColor: Colors.white, ) : Container( color: Colors.black.withValues(alpha: 0.10), child: const Center( child: Text( 'Link de vídeo inválido', style: TextStyle(fontWeight: FontWeight.w800), ), ), ), ), ), const SizedBox(height: 14), Text( widget.title, style: const TextStyle( fontSize: 18, fontWeight: FontWeight.w900, color: Color(0xFFFF55A7), ), ), const SizedBox(height: 6), Text( 'Assista ao vídeo e aprenda mais sobre saúde bucal.', style: TextStyle( color: Colors.black.withValues(alpha: 0.70), fontWeight: FontWeight.w600, ), ), ], ), ), ), ); } }