import 'package:flutter/material.dart'; import 'package:skywood/global/client/play_client.dart'; import 'package:skywood/main/lib_file.dart'; import 'package:skywood/pages/home/players/page/drama_detail_page.dart'; import 'package:skywood/utils/models/drama/skywood_category.dart'; import 'package:skywood/utils/models/drama/skywood_drama.dart'; import 'package:skywood/utils/tools/sky_time_tool.dart'; import 'package:skywood/utils/tools/widgets/sky_common_widget.dart'; class CatePage extends StatefulWidget { const CatePage({super.key}); @override State createState() => _CatePageState(); } class _CatePageState extends State { final List _categories = []; final List _dramas = []; int _selectedIndex = 0; int? _loadingCategoryId; bool _loadingCategories = true; bool _loadingDramas = false; @override void initState() { super.initState(); _loadCategories(); } Future _loadCategories() async { List categories = []; try { categories = await PlayClient.getCategoriesList(); } catch (_) { if (!mounted) return; } setState(() { _categories ..clear() ..addAll(categories); _loadingCategories = false; }); if (categories.isNotEmpty) { _loadCategoryDetail(categories.first.id); } } Future _loadCategoryDetail(int categoryId) async { _loadingCategoryId = categoryId; setState(() { _loadingDramas = true; _dramas.clear(); }); List dramas = []; try { dramas = await PlayClient.getCategoriesDetail(categoryId: categoryId); } catch (_) { if (!mounted || _loadingCategoryId != categoryId) return; } if (!mounted || _loadingCategoryId != categoryId) return; setState(() { _dramas.addAll(dramas); _loadingDramas = false; }); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.white, body: SafeArea( bottom: false, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ _buildHeader(), Expanded( child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ _buildCategoryList(), Expanded(child: _buildDramaList()), ], ), ), ], ), ), ); } Widget _buildHeader() { return SizedBox( height: 49.h, child: Stack( children: [ Positioned( left: 13.w, top: 16.h, child: HelpImg.asset( ConstImg.back, width: 24.w, height: 24.w, ).addInkWell(onTap: () => HelpNav.back()), ), Positioned( left: 94.w, top: 22.h, child: SkyText( text: 'Explore Genres', color: CommonColor.black, fontSize: 14, fontWeight: FontWeight.w800, ), ), ], ), ); } Widget _buildCategoryList() { return Container( width: 86.w, height: double.infinity, padding: EdgeInsets.only(top: 12.h, bottom: 18.h), decoration: BoxDecoration( color: const Color(0xFFF2FFF0), borderRadius: BorderRadius.only(topRight: Radius.circular(8.r)), ), child: _loadingCategories ? const SizedBox.shrink() : ListView.builder( padding: EdgeInsets.zero, itemCount: _categories.length, itemBuilder: (context, index) { return _buildCategoryItem(index); }, ), ); } Widget _buildCategoryItem(int index) { final category = _categories[index]; final selected = index == _selectedIndex; return GestureDetector( behavior: HitTestBehavior.opaque, onTap: () { if (selected) return; setState(() { _selectedIndex = index; }); _loadCategoryDetail(category.id); }, child: SizedBox( height: 47.h, child: Stack( alignment: Alignment.center, children: [ if (selected) Positioned( left: 0, top: 0, bottom: 0, child: HelpImg.asset( ConstImg.cateSelLeft, width: 20.w, height: 50.h, fit: BoxFit.fill, ), ), if (selected) Positioned( right: 0, top: 0, bottom: 0, child: HelpImg.asset( ConstImg.cateSelRight, width: 20.w, height: 50.h, fit: BoxFit.fill, ), ), Padding( padding: EdgeInsets.symmetric(horizontal: 12.w), child: SkyText( text: category.name, color: selected ? CommonColor.primacyColor : Colors.black.withAlpha(100), fontSize: 11, fontWeight: selected ? FontWeight.w700 : FontWeight.w500, textAlign: TextAlign.center, maxLines: 2, lineHeight: 1.05, ), ), ], ), ), ); } Widget _buildDramaList() { if (_loadingDramas) { return const Center( child: CircularProgressIndicator(color: CommonColor.primacyColor), ); } if (_dramas.isEmpty) { return Center( child: SkyText( text: 'No Data', color: Colors.black.withAlpha(100), fontSize: 13, ), ); } return ListView.separated( padding: EdgeInsets.only(left: 8.w, right: 10.w, bottom: 24.h), itemCount: _dramas.length, separatorBuilder: (context, index) => SizedBox(height: 10.h), itemBuilder: (context, index) { return _DramaItem(drama: _dramas[index]); }, ); } } class _DramaItem extends StatelessWidget { const _DramaItem({required this.drama}); final SkywoodDrama drama; @override Widget build(BuildContext context) { return SizedBox( height: 80.h, child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ HelpImg.networkRadius( drama.imageUrl, width: 64.w, height: 80.h, fit: BoxFit.cover, borderRadius: BorderRadius.circular(4.r), ), SizedBox(width: 8.w), Expanded( child: Padding( padding: EdgeInsets.only(top: 2.h), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ SkyText( text: drama.name, color: CommonColor.black, fontSize: 11, fontWeight: FontWeight.w700, maxLines: 2, lineHeight: 1.08, ), SizedBox(height: 7.h), SkyText( text: drama.description, color: Colors.black.withAlpha(92), fontSize: 9, maxLines: 2, lineHeight: 1.2, ), const Spacer(), Row( children: [ _TipView(icon: ConstImg.star, text: '10.0'), SizedBox(width: 12.w), _TipView( icon: ConstImg.look, text: SkyTimeTool.formatNum(drama.watchTotal), ), ], ), ], ), ), ), ], ), ).addInkWell(onTap: () => HelpNav.to(DramaDetailPage(dramaBean: drama))); } } class _TipView extends StatelessWidget { const _TipView({required this.icon, required this.text}); final String icon; final String text; @override Widget build(BuildContext context) { return Row( mainAxisSize: MainAxisSize.min, children: [ HelpImg.asset(icon, width: 8.w, height: 8.w), SizedBox(width: 2.w), SkyText(text: text, color: Colors.black.withAlpha(110), fontSize: 8), ], ); } }