import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'dart:convert'; import 'package:siro_admin/constant/links.dart'; import 'package:siro_admin/controller/functions/crud.dart'; import 'package:siro_admin/views/widgets/snackbar.dart'; import '../../print.dart'; class PackageUpdateScreen extends StatelessWidget { PackageUpdateScreen({super.key}); final PackageController packageController = Get.put(PackageController()); @override Widget build(BuildContext context) { final cs = Theme.of(context).colorScheme; return Scaffold( backgroundColor: cs.surface, body: Column( children: [ Container( padding: const EdgeInsets.fromLTRB(16, 50, 16, 16), child: Row( children: [ GestureDetector( onTap: () => Get.back(), child: Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( color: cs.surfaceContainerHighest, borderRadius: BorderRadius.circular(10), border: Border.all(color: cs.outline), ), child: Icon(Icons.arrow_back_ios_new_rounded, color: cs.onSurfaceVariant, size: 16), ), ), const SizedBox(width: 12), Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( color: cs.primary.withValues(alpha: 0.12), borderRadius: BorderRadius.circular(10), border: Border.all(color: cs.primary.withValues(alpha: 0.25)), ), child: Icon(Icons.system_update_rounded, color: cs.primary, size: 16), ), const SizedBox(width: 10), Text('تحديث التطبيق', style: TextStyle( color: cs.onSurface, fontSize: 17, fontWeight: FontWeight.bold)), const Spacer(), GestureDetector( onTap: () => packageController.fetchPackages(), child: Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( color: cs.surfaceContainerHighest, borderRadius: BorderRadius.circular(10), border: Border.all(color: cs.outline), ), child: Icon(Icons.refresh_rounded, color: cs.onSurfaceVariant, size: 16), ), ), ], ), ), Container(height: 1, color: cs.outline), Expanded( child: GetBuilder( builder: (controller) { if (controller.isLoading.value) { return Center( child: CircularProgressIndicator(color: cs.primary, strokeWidth: 2), ); } if (controller.packages.isEmpty) { return _buildEmptyState(cs); } return ListView.separated( padding: const EdgeInsets.fromLTRB(16, 16, 16, 40), itemCount: controller.packages.length, separatorBuilder: (_, __) => const SizedBox(height: 10), itemBuilder: (context, index) { final package = controller.packages[index]; return _buildPackageCard(context, package, controller, cs); }, ); }, ), ), ], ), ); } Widget _buildPackageCard( BuildContext context, dynamic package, PackageController controller, ColorScheme cs) { final platform = package['platform']?.toString() ?? ''; final isAndroid = platform.toLowerCase().contains('android'); final isIOS = platform.toLowerCase().contains('ios'); final Color platformColor = isAndroid ? const Color(0xFF4CAF50) : isIOS ? cs.tertiary : cs.tertiary; final IconData platformIcon = isAndroid ? Icons.android_rounded : isIOS ? Icons.apple_rounded : Icons.devices_rounded; return Material( color: Colors.transparent, child: InkWell( onTap: () => _showUpdateDialog(context, package, controller, cs), borderRadius: BorderRadius.circular(16), splashColor: cs.primary.withValues(alpha: 0.06), highlightColor: Colors.transparent, child: Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: cs.surfaceContainerHighest, borderRadius: BorderRadius.circular(16), border: Border.all(color: cs.outline), ), child: Row( children: [ Container( width: 48, height: 48, decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [ platformColor.withValues(alpha: 0.20), platformColor.withValues(alpha: 0.06), ], ), borderRadius: BorderRadius.circular(13), border: Border.all(color: platformColor.withValues(alpha: 0.25)), ), child: Icon(platformIcon, color: platformColor, size: 22), ), const SizedBox(width: 14), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( package['appName']?.toString() ?? '—', style: TextStyle( color: cs.onSurface, fontSize: 14, fontWeight: FontWeight.w600, ), ), const SizedBox(height: 4), Row( children: [ _buildTag(platform, platformColor), const SizedBox(width: 6), _buildVersionBadge( package['version']?.toString() ?? '?', cs), ], ), ], ), ), Container( padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 7), decoration: BoxDecoration( color: cs.primary.withValues(alpha: 0.10), borderRadius: BorderRadius.circular(10), border: Border.all(color: cs.primary.withValues(alpha: 0.25)), ), child: Row( mainAxisSize: MainAxisSize.min, children: [ Icon(Icons.edit_rounded, color: cs.primary, size: 13), const SizedBox(width: 5), Text( 'تعديل', style: TextStyle( color: cs.primary, fontSize: 11, fontWeight: FontWeight.w600, ), ), ], ), ), ], ), ), ), ); } Widget _buildTag(String label, Color color) { return Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 3), decoration: BoxDecoration( color: color.withValues(alpha: 0.10), borderRadius: BorderRadius.circular(6), ), child: Text( label, style: TextStyle( color: color, fontSize: 10, fontWeight: FontWeight.w600, ), ), ); } Widget _buildVersionBadge(String version, ColorScheme cs) { return Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 3), decoration: BoxDecoration( color: cs.surfaceContainerHighest, borderRadius: BorderRadius.circular(6), ), child: Text( 'v$version', style: TextStyle( color: cs.onSurfaceVariant, fontSize: 10, fontWeight: FontWeight.w500, fontFamily: 'monospace', ), ), ); } Widget _buildEmptyState(ColorScheme cs) { return Center( child: Column( mainAxisSize: MainAxisSize.min, children: [ Container( padding: const EdgeInsets.all(20), decoration: BoxDecoration( color: cs.surfaceContainerHighest, shape: BoxShape.circle, border: Border.all(color: cs.outline), ), child: Icon(Icons.inventory_2_outlined, color: cs.onSurfaceVariant, size: 32), ), const SizedBox(height: 16), Text('لا توجد حزم متاحة', style: TextStyle( color: cs.onSurface, fontSize: 15, fontWeight: FontWeight.w600)), const SizedBox(height: 6), Text('اسحب للأسفل لإعادة التحميل', style: TextStyle(color: cs.onSurfaceVariant, fontSize: 12)), ], ), ); } void _showUpdateDialog( BuildContext context, dynamic package, PackageController controller, ColorScheme cs) { controller.versionController.clear(); Get.dialog( Dialog( backgroundColor: Colors.transparent, child: Container( decoration: BoxDecoration( color: cs.surfaceContainerHighest, borderRadius: BorderRadius.circular(24), border: Border.all(color: cs.outline), boxShadow: const [ BoxShadow( color: Colors.black54, blurRadius: 30, offset: Offset(0, 12), ), ], ), padding: const EdgeInsets.all(24), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Container( padding: const EdgeInsets.all(10), decoration: BoxDecoration( color: cs.primary.withValues(alpha: 0.12), borderRadius: BorderRadius.circular(12), border: Border.all(color: cs.primary.withValues(alpha: 0.25)), ), child: Icon(Icons.system_update_rounded, color: cs.primary, size: 20), ), const SizedBox(width: 12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'تحديث الإصدار', style: TextStyle( color: cs.onSurface, fontSize: 16, fontWeight: FontWeight.w700, ), ), Text( package['appName']?.toString() ?? '', style: TextStyle( color: cs.onSurfaceVariant, fontSize: 11), ), ], ), ), ], ), const SizedBox(height: 20), Container(height: 1, color: cs.outline), const SizedBox(height: 20), Row( children: [ _buildInfoChip(Icons.devices_rounded, package['platform']?.toString() ?? '', cs.tertiary), const SizedBox(width: 8), _buildInfoChip(Icons.tag_rounded, 'الحالي: ${package['version']}', cs.tertiary), ], ), const SizedBox(height: 18), Text( 'الإصدار الجديد', style: TextStyle( color: cs.onSurfaceVariant, fontSize: 11, fontWeight: FontWeight.w600, letterSpacing: 0.8, ), ), const SizedBox(height: 8), Container( decoration: BoxDecoration( color: cs.surface, borderRadius: BorderRadius.circular(12), border: Border.all(color: cs.outline), ), child: TextField( controller: controller.versionController, keyboardType: const TextInputType.numberWithOptions(decimal: true), style: TextStyle( color: cs.onSurface, fontSize: 15, fontFamily: 'monospace', fontWeight: FontWeight.w600, ), decoration: InputDecoration( hintText: package['version'].toString(), hintStyle: TextStyle( color: cs.onSurfaceVariant, fontFamily: 'monospace', ), prefixIcon: Icon(Icons.tag_rounded, color: cs.primary, size: 18), border: InputBorder.none, contentPadding: const EdgeInsets.symmetric( horizontal: 14, vertical: 14), ), ), ), const SizedBox(height: 24), Row( children: [ Expanded( child: TextButton( onPressed: () => Get.back(), style: TextButton.styleFrom( padding: const EdgeInsets.symmetric(vertical: 12), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), side: BorderSide(color: cs.outline), ), ), child: Text( 'إلغاء', style: TextStyle(color: cs.onSurfaceVariant, fontSize: 13), ), ), ), const SizedBox(width: 12), Expanded( child: Obx(() => ElevatedButton.icon( icon: controller.isLoading.value ? SizedBox( width: 14, height: 14, child: CircularProgressIndicator( color: cs.onPrimary, strokeWidth: 2, ), ) : const Icon(Icons.check_rounded, size: 16), label: Text( controller.isLoading.value ? 'جاري...' : 'تحديث', style: const TextStyle(fontSize: 13), ), style: ElevatedButton.styleFrom( backgroundColor: cs.primary, foregroundColor: cs.surface, padding: const EdgeInsets.symmetric(vertical: 12), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), elevation: 0, ), onPressed: controller.isLoading.value ? null : () async { await controller.updatePackages( package['id'].toString(), controller.versionController.text, ); }, )), ), ], ), ], ), ), ), ); } Widget _buildInfoChip(IconData icon, String label, Color color) { return Container( padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6), decoration: BoxDecoration( color: color.withValues(alpha: 0.08), borderRadius: BorderRadius.circular(8), border: Border.all(color: color.withValues(alpha: 0.2)), ), child: Row( mainAxisSize: MainAxisSize.min, children: [ Icon(icon, color: color, size: 13), const SizedBox(width: 5), Text( label, style: TextStyle( color: color, fontSize: 11, fontWeight: FontWeight.w600, ), ), ], ), ); } } class PackageController extends GetxController { List packages = []; var isLoading = false.obs; final versionController = TextEditingController(); final formKey = GlobalKey(); @override void onInit() { super.onInit(); fetchPackages(); } fetchPackages() async { isLoading.value = true; var response = await CRUD().get(link: AppLink.getPackages, payload: {}); if (response is String && (response == 'failure' || response == 'token_expired')) { isLoading.value = false; return; } try { var jsonData = response is String ? jsonDecode(response) : response; packages = jsonData['message'] ?? []; Log.print('✅ Decoded packages: ${packages.length} items'); update(); } catch (e) { Log.print('❌ Error parsing packages: $e'); } isLoading.value = false; } updatePackages(String id, String version) async { if (version.trim().isEmpty) { mySnackbarWarning('يرجى إدخال رقم الإصدار'); return; } isLoading.value = true; var response = await CRUD().post( link: AppLink.updatePackages, payload: {"id": id, "version": version}, ); Log.print('response: $response'); isLoading.value = false; if (response != 'failure') { Get.back(); mySnackbarSuccess('تم تحديث الإصدار بنجاح'); fetchPackages(); } else { mySnackbarError('فشل التحديث، يرجى المحاولة مجدداً'); } } }