import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import '../../../../core/theme/app_colors.dart'; import '../../../../core/widgets/riotz_scaffold.dart'; import '../../../music/domain/models/track_model.dart'; import '../providers/admin_providers.dart'; import '../../domain/models/admin_user_model.dart'; import '../../domain/models/admin_post_model.dart'; class AdminScreen extends ConsumerWidget { const AdminScreen({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { final dataAsync = ref.watch(adminPanelDataProvider); ref.listen(adminControllerProvider, (_, next) { next.whenOrNull( data: (_) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( backgroundColor: AppColors.success, content: Text('SYSTEM OVERRIDE SUCCESSFUL.', style: TextStyle(color: AppColors.black, fontWeight: FontWeight.bold)), ), ); }, error: (error, _) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( backgroundColor: AppColors.bloodRed, content: Text('ERROR: ${error.toString().toUpperCase()}'), ), ); }, ); }); return RiotzScaffold( appBar: AppBar( title: const Text('RIOTZ // TERMINAL'), leading: IconButton( icon: const Icon(Icons.arrow_back_ios_new, size: 20), onPressed: () => context.pop(), ), ), body: dataAsync.when( loading: () => const Center(child: CircularProgressIndicator(color: AppColors.neonRed)), error: (error, _) => Center(child: Text('TERMINAL OFFLINE: $error')), data: (data) => RefreshIndicator( onRefresh: () async => ref.invalidate(adminPanelDataProvider), color: AppColors.neonRed, child: ListView( padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 24), children: [ _SectionHeader(title: 'USER MODERATION', count: data.users.length), const SizedBox(height: 16), ...data.users.map((user) => _AdminUserCard(user: user)), const SizedBox(height: 48), _SectionHeader(title: 'TRACK MODERATION', count: data.tracks.length), const SizedBox(height: 16), ...data.tracks.map((track) => _AdminTrackCard(track: track)), const SizedBox(height: 48), _SectionHeader(title: 'POST MODERATION', count: data.posts.length), const SizedBox(height: 16), ...data.posts.map((post) => _AdminPostCard(post: post)), const SizedBox(height: 40), ], ), ), ), ); } } class _SectionHeader extends StatelessWidget { const _SectionHeader({required this.title, required this.count}); final String title; final int count; @override Widget build(BuildContext context) { final theme = Theme.of(context); return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(title, style: theme.textTheme.labelLarge?.copyWith(letterSpacing: 2, color: AppColors.neonRed)), const Divider(color: AppColors.neonRed, thickness: 2), ], ); } } class _AdminUserCard extends ConsumerWidget { const _AdminUserCard({required this.user}); final AdminUserModel user; @override Widget build(BuildContext context, WidgetRef ref) { final theme = Theme.of(context); return Container( margin: const EdgeInsets.only(bottom: 12), decoration: BoxDecoration( color: AppColors.surface, border: Border.all(color: user.banned ? AppColors.bloodRed : AppColors.border), ), child: ListTile( leading: CircleAvatar( backgroundColor: AppColors.surfaceLight, backgroundImage: user.avatarUrl.isNotEmpty ? NetworkImage(user.avatarUrl) : null, child: user.avatarUrl.isEmpty ? const Icon(Icons.person, color: AppColors.grey) : null, ), title: Text(user.username.toUpperCase(), style: theme.textTheme.labelLarge), subtitle: Text(user.banned ? 'STATUS: BANNED' : (user.featured ? 'STATUS: FEATURED ARTIST' : 'STATUS: ACTIVE'), style: TextStyle(color: user.banned ? AppColors.neonRed : (user.featured ? AppColors.success : AppColors.grey), fontSize: 10, fontWeight: FontWeight.bold)), trailing: PopupMenuButton( icon: const Icon(Icons.more_vert, color: AppColors.white), color: AppColors.surfaceLight, onSelected: (value) { if (value == 'ban') { ref.read(adminControllerProvider.notifier).setUserBanned(userId: user.userId, banned: !user.banned); } else if (value == 'feature') { ref.read(adminControllerProvider.notifier).setUserFeatured(userId: user.userId, featured: !user.featured); } }, itemBuilder: (context) => [ PopupMenuItem( value: 'ban', child: Text(user.banned ? 'UNBAN USER' : 'BAN USER', style: const TextStyle(color: AppColors.neonRed)), ), PopupMenuItem( value: 'feature', child: Text(user.featured ? 'UNFEATURE ARTIST' : 'FEATURE ARTIST'), ), ], ), ), ); } } class _AdminTrackCard extends ConsumerWidget { const _AdminTrackCard({required this.track}); final TrackModel track; @override Widget build(BuildContext context, WidgetRef ref) { final theme = Theme.of(context); return Container( margin: const EdgeInsets.only(bottom: 12), decoration: BoxDecoration( color: AppColors.surface, border: Border.all(color: track.featured ? AppColors.success : AppColors.border), ), child: ListTile( leading: Icon(Icons.music_note, color: track.featured ? AppColors.success : AppColors.white), title: Text(track.title.toUpperCase(), style: theme.textTheme.labelLarge), subtitle: Text('BY: ${track.username.toUpperCase()}', style: const TextStyle(fontSize: 10, color: AppColors.grey)), trailing: Switch( value: track.featured, activeThumbColor: AppColors.success, onChanged: (val) { ref.read(adminControllerProvider.notifier).setTrackFeatured(trackId: track.id, featured: val); }, ), ), ); } } class _AdminPostCard extends ConsumerWidget { const _AdminPostCard({required this.post}); final AdminPostModel post; @override Widget build(BuildContext context, WidgetRef ref) { final theme = Theme.of(context); return Container( margin: const EdgeInsets.only(bottom: 16), decoration: BoxDecoration( color: AppColors.surface, border: Border.all(color: post.featured ? AppColors.neonRed : AppColors.border), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ ListTile( title: Text(post.username.toUpperCase(), style: theme.textTheme.labelLarge), subtitle: Text('ID: ${post.id.substring(0, 8)}...', style: const TextStyle(fontSize: 10)), trailing: IconButton( icon: const Icon(Icons.delete_forever, color: AppColors.neonRed), onPressed: () => _confirmDelete(context, ref), ), ), if (post.imageUrl.isNotEmpty) Image.network(post.imageUrl, height: 120, width: double.infinity, fit: BoxFit.cover), Padding( padding: const EdgeInsets.all(12), child: Row( children: [ const Text('FEATURE CONTENT', style: TextStyle(fontSize: 10, fontWeight: FontWeight.bold)), const Spacer(), Switch( value: post.featured, activeThumbColor: AppColors.neonRed, onChanged: (val) { ref.read(adminControllerProvider.notifier).setPostFeatured(postId: post.id, featured: val); }, ), ], ), ), ], ), ); } void _confirmDelete(BuildContext context, WidgetRef ref) { showDialog( context: context, builder: (context) => AlertDialog( backgroundColor: AppColors.surface, shape: const RoundedRectangleBorder(borderRadius: BorderRadius.zero), title: const Text('ERASE DATA?'), content: const Text('THIS WILL REMOVE THE CONTENT FROM THE NETWORK PERMANENTLY.'), actions: [ TextButton(onPressed: () => Navigator.pop(context), child: const Text('CANCEL')), TextButton( onPressed: () { ref.read(adminControllerProvider.notifier).deletePost(post.id); Navigator.pop(context); }, child: const Text('DELETE', style: TextStyle(color: AppColors.neonRed)), ), ], ), ); } }