import 'package:flutter/material.dart'; import 'package:novyronst/common/const/const_color.dart'; import 'package:novyronst/common/const/const_string.dart'; import 'package:novyronst/pages/widgets/cut_corner_clipper.dart'; import 'package:novyronst/pages/widgets/ny_tag_widget.dart'; import 'package:novyronst/tools/widgets/novy_com_widget.dart'; class HomeRemainingSections extends StatelessWidget { const HomeRemainingSections({super.key}); static const List<_DramaItem> _rankingItems = [ _DramaItem( title: 'Star Of The Ocean', category: 'Period Drama', palette: [Color(0xFF6E4968), Color(0xFFE5A3B8)], ), _DramaItem( title: 'Not Your Bride', category: 'Period Drama', palette: [Color(0xFF262431), Color(0xFFE0A15F)], ), _DramaItem( title: 'Not Your Bride', category: 'Period Drama', palette: [Color(0xFF261B16), Color(0xFFD9C2A2)], ), _DramaItem( title: 'Not Your Bride', category: 'Period Drama', palette: [Color(0xFF223E36), Color(0xFFFFC568)], ), ]; static const _ActorInfo _actor = _ActorInfo( name: 'Cheng Zi', tags: 'Romantic Lead | Revenge Drama | Lead Actor', bornYear: '2002', height: '168cm', nationality: 'China', ); static const List<_DramaItem> _seriesItems = [ _DramaItem( title: 'Cities Of Smoke Starlight', category: 'Satisfying', palette: [Color(0xFF33241D), Color(0xFFD8A65B)], ), _DramaItem( title: 'Cities Of Smoke Starlight', category: 'Satisfying', palette: [Color(0xFF25354C), Color(0xFFC88B57)], ), _DramaItem( title: 'Cities Of Smoke Starlight', category: 'Satisfying', palette: [Color(0xFF3E2B2C), Color(0xFFE2B36B)], ), _DramaItem( title: 'Cities Of Smoke Starlight', category: 'Satisfying', palette: [Color(0xFF443A2C), Color(0xFFC48645)], ), _DramaItem( title: 'Cities Of Smoke Starlight', category: 'Satisfying', palette: [Color(0xFF314559), Color(0xFFE5AA65)], ), _DramaItem( title: 'Cities Of Smoke Starlight', category: 'Satisfying', palette: [Color(0xFF2C2637), Color(0xFFD39458)], ), ]; static const List _categoryTitles = [ 'Counterattack Life', 'Reborn And Returned', 'God Of War Returns', ]; @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.fromLTRB(16, 10, 16, 92), child: Column( children: [ const _RankingSection(items: _rankingItems), const SizedBox(height: 18), const _ActorSection(actor: _actor, items: _seriesItems), const SizedBox(height: 18), ..._categoryTitles.map((title) { return Padding( padding: const EdgeInsets.only(bottom: 18), child: _DramaShelfSection(title: title, items: _seriesItems), ); }), ], ), ); } } class _RankingSection extends StatelessWidget { const _RankingSection({required this.items}); final List<_DramaItem> items; @override Widget build(BuildContext context) { return Container( padding: const EdgeInsets.all(5), decoration: BoxDecoration( color: Colors.white, border: Border.all(color: Colors.black, width: 2), ), child: Column( children: [ SizedBox( height: 230, child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Expanded(flex: 6, child: _TopRankingPoster(item: items.first)), const SizedBox(width: 8), Expanded( flex: 5, child: Column( children: List.generate(3, (index) { return Expanded( child: _RankingListItem( rank: index + 2, item: items[index + 1], ), ); }), ), ), ], ), ), const SizedBox(height: 5), const _GreenActionButton(text: 'View more rankings'), ], ), ); } } class _TopRankingPoster extends StatelessWidget { const _TopRankingPoster({required this.item}); final _DramaItem item; @override Widget build(BuildContext context) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Expanded( child: Stack( children: [ Positioned.fill( child: _PosterBlock(item: item, showLargeTitle: true), ), Positioned( top: 4, left: 5, child: NovyText( '1', color: ConstColor.btGreen, fontSize: 36, fontFamily: ConstFont.montBlack, shadow: const Shadow( offset: Offset(1.5, 1.5), color: Colors.black, ), ), ), ], ), ), const SizedBox(height: 8), NovyText( item.title, color: Colors.black, fontSize: 14, fontFamily: ConstFont.montMedium, ), const SizedBox(height: 5), NyTagWidget(text: item.category), ], ); } } class _RankingListItem extends StatelessWidget { const _RankingListItem({required this.rank, required this.item}); final int rank; final _DramaItem item; @override Widget build(BuildContext context) { final Color rankColor = rank == 4 ? const Color(0xFFBBBBBB) : ConstColor.btGreen; return Row( children: [ SizedBox(width: 42, height: 64, child: _PosterBlock(item: item)), const SizedBox(width: 6), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.center, children: [ NovyText( '$rank', color: rankColor, fontSize: 19, fontFamily: ConstFont.montBlack, lineHeight: 1, ), const SizedBox(height: 3), NovyText( item.title, color: Colors.black, fontSize: 11, fontFamily: ConstFont.montBold, maxLines: 1, ), const SizedBox(height: 4), NyTagWidget(text: item.category), ], ), ), ], ); } } class _ActorSection extends StatelessWidget { const _ActorSection({required this.actor, required this.items}); final _ActorInfo actor; final List<_DramaItem> items; @override Widget build(BuildContext context) { return CutCornerClipper( cutCorner: CutCorner.topLeft, cutSize: 66, child: Stack( children: [ Padding( padding: const EdgeInsets.fromLTRB(10, 18, 10, 10), child: Column( children: [ const _CornerEyes(), const SizedBox(height: 4), _OutlinedTitle('Read This Series Of Short Plays', fontSize: 19), const SizedBox(height: 26), const _ActorAvatar(), const SizedBox(height: 10), NovyText( actor.name, color: Colors.black, fontSize: 22, fontFamily: ConstFont.montBlack, ), const SizedBox(height: 10), NovyText( actor.tags, color: const Color(0xFF888888), fontSize: 13, fontFamily: ConstFont.montRegular, ), const SizedBox(height: 12), _ActorStats(actor: actor), const SizedBox(height: 8), _SectionHeader(title: 'Series'), const SizedBox(height: 8), _SeriesGrid(items: items, showTags: false), const SizedBox(height: 12), const _PagerDots(), ], ), ), ], ), ); } } class _DramaShelfSection extends StatelessWidget { const _DramaShelfSection({required this.title, required this.items}); final String title; final List<_DramaItem> items; @override Widget build(BuildContext context) { return CutCornerClipper( cutSize: 40, child: Padding( padding: const EdgeInsets.fromLTRB(8, 14, 8, 8), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const _GripBars(), const SizedBox(height: 8), _OutlinedTitle(title, fontSize: 19), const SizedBox(height: 12), Row( children: List.generate(3, (index) { return Expanded( child: Padding( padding: EdgeInsets.only(right: index == 2 ? 0 : 8), child: _SeriesCard(item: items[index], showTag: true), ), ); }), ), const SizedBox(height: 8), const _GreenActionButton(text: 'Click to watch'), ], ), ), ); } } class _SeriesGrid extends StatelessWidget { const _SeriesGrid({required this.items, required this.showTags}); final List<_DramaItem> items; final bool showTags; @override Widget build(BuildContext context) { return GridView.builder( padding: EdgeInsets.zero, itemCount: items.length, shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 3, crossAxisSpacing: 9, mainAxisSpacing: 10, childAspectRatio: 0.47, ), itemBuilder: (context, index) { return _SeriesCard(item: items[index], showTag: showTags); }, ); } } class _SeriesCard extends StatelessWidget { const _SeriesCard({required this.item, required this.showTag}); final _DramaItem item; final bool showTag; @override Widget build(BuildContext context) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ AspectRatio( aspectRatio: 0.68, child: _PosterBlock(item: item, showLargeTitle: true), ), const SizedBox(height: 7), NovyText( item.title, color: Colors.black, fontSize: 14, lineHeight: 1.05, fontFamily: ConstFont.montMedium, maxLines: 2, ), if (showTag) ...[ const SizedBox(height: 7), NyTagWidget(text: item.category), ], ], ); } } class _PosterBlock extends StatelessWidget { const _PosterBlock({required this.item, this.showLargeTitle = false}); final _DramaItem item; final bool showLargeTitle; @override Widget build(BuildContext context) { return Container( decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: item.palette, ), ), child: Stack( children: [ Positioned( top: 12, left: 10, right: 10, child: Container( height: showLargeTitle ? 74 : 28, decoration: BoxDecoration( color: Colors.white.withValues(alpha: 0.2), borderRadius: BorderRadius.circular(80), ), ), ), Positioned( left: 7, right: 7, bottom: 10, child: NovyText( showLargeTitle ? 'CITIES\nOF SMOKE\nSTARLIGHT' : item.title, color: Colors.white, fontSize: showLargeTitle ? 17 : 8, lineHeight: 0.95, textAlign: TextAlign.center, fontFamily: ConstFont.montBlack, maxLines: showLargeTitle ? 3 : 2, shadow: const Shadow(offset: Offset(1, 1), color: Colors.black54), ), ), ], ), ); } } class _ActorAvatar extends StatelessWidget { const _ActorAvatar(); @override Widget build(BuildContext context) { return Container( width: 116, height: 116, decoration: const BoxDecoration( shape: BoxShape.circle, gradient: LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [Color(0xFFFFA6D9), Color(0xFFFFE6F5)], ), ), child: Center( child: Container( width: 58, height: 58, decoration: BoxDecoration( color: Colors.white.withValues(alpha: 0.55), borderRadius: BorderRadius.circular(18), ), child: const Icon(Icons.person, size: 44, color: Color(0xFF8E2A55)), ), ), ); } } class _ActorStats extends StatelessWidget { const _ActorStats({required this.actor}); final _ActorInfo actor; @override Widget build(BuildContext context) { final List> stats = [ [actor.bornYear, 'Born Year'], [actor.height, 'Height'], [actor.nationality, 'Nationality'], ]; return Container( height: 68, decoration: BoxDecoration( color: const Color(0xFFF4F4F4), border: Border.all(color: const Color(0xFFD8D8D8)), ), child: Row( children: List.generate(stats.length, (index) { return Expanded( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ NovyText( stats[index][0], color: Colors.black, fontSize: 18, fontFamily: ConstFont.montMedium, ), const SizedBox(height: 7), NovyText( stats[index][1], color: const Color(0xFF777777), fontSize: 13, fontFamily: ConstFont.montRegular, ), ], ), ); }), ), ); } } class _SectionHeader extends StatelessWidget { const _SectionHeader({required this.title}); final String title; @override Widget build(BuildContext context) { return Align( alignment: Alignment.centerLeft, child: NovyText( title, color: Colors.black, fontSize: 19, fontFamily: ConstFont.montBlack, ), ); } } class _OutlinedTitle extends StatelessWidget { const _OutlinedTitle(this.text, {required this.fontSize}); final String text; final double fontSize; @override Widget build(BuildContext context) { return Stack( children: [ Text( text, maxLines: 2, style: TextStyle( fontSize: fontSize, height: 1.05, fontFamily: ConstFont.montBlack, foreground: Paint() ..style = PaintingStyle.stroke ..strokeWidth = 3.5 ..color = Colors.black, ), ), Text( text, maxLines: 2, style: TextStyle( color: Colors.white, fontSize: fontSize, height: 1.05, fontFamily: ConstFont.montBlack, ), ), ], ); } } class _GreenActionButton extends StatelessWidget { const _GreenActionButton({required this.text}); final String text; @override Widget build(BuildContext context) { return ClipPath( clipper: const EqualCutCornerClipper( cutSize: 18, corner: CutCorner.bottomLeft, ), child: Container( height: 34, decoration: BoxDecoration( color: ConstColor.btGreen, border: Border.all(color: Colors.black, width: 2), ), child: Stack( children: [ const Positioned(left: 22, top: 6, child: _GripBars()), const Positioned(right: 10, bottom: 4, child: _GripBars()), Center( child: NovyText( text, color: Colors.black, fontSize: 14, fontFamily: ConstFont.montBlack, ), ), ], ), ), ); } } class _CornerEyes extends StatelessWidget { const _CornerEyes(); @override Widget build(BuildContext context) { return SizedBox( height: 18, child: Stack( clipBehavior: Clip.none, children: [ Positioned( left: -3, top: -38, child: Transform.rotate( angle: 0.68, child: Container( width: 34, height: 84, color: ConstColor.btGreen, ), ), ), const Positioned(left: 18, top: -12, child: _EyeDot()), const Positioned(left: 38, top: -18, child: _EyeDot()), ], ), ); } } class _EyeDot extends StatelessWidget { const _EyeDot(); @override Widget build(BuildContext context) { return Container( width: 22, height: 26, decoration: const BoxDecoration( color: Colors.white, shape: BoxShape.circle, ), child: Align( alignment: Alignment.topRight, child: Container( width: 10, height: 10, margin: const EdgeInsets.only(top: 2, right: 2), decoration: const BoxDecoration( color: Colors.black, shape: BoxShape.circle, ), ), ), ); } } class _PagerDots extends StatelessWidget { const _PagerDots(); @override Widget build(BuildContext context) { return Row( mainAxisAlignment: MainAxisAlignment.center, children: List.generate(7, (index) { return Container( width: index == 1 ? 26 : 7, height: 7, margin: const EdgeInsets.symmetric(horizontal: 3), color: index == 1 ? ConstColor.btGreen : const Color(0xFFD9D9D9), ); }), ); } } class _GripBars extends StatelessWidget { const _GripBars(); @override Widget build(BuildContext context) { return Row( mainAxisSize: MainAxisSize.min, children: List.generate(4, (index) { return Container( width: 3, height: 8, margin: const EdgeInsets.only(right: 2), color: Colors.black, ); }), ); } } class _DramaItem { const _DramaItem({ required this.title, required this.category, required this.palette, }); final String title; final String category; final List palette; } class _ActorInfo { const _ActorInfo({ required this.name, required this.tags, required this.bornYear, required this.height, required this.nationality, }); final String name; final String tags; final String bornYear; final String height; final String nationality; }