import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import 'package:niogu_app/core/components/top_back_bar_app.dart'; import 'package:niogu_app/core/constants/app_color.dart'; import 'package:niogu_app/core/constants/app_font_size.dart'; import 'package:niogu_app/core/router/app_route.dart'; import 'package:niogu_app/core/utils/log_message.dart'; import 'package:niogu_app/core/widgets/custom_snackbar.dart'; import 'package:niogu_app/core/widgets/custom_text_form_field.dart'; import 'package:niogu_app/features/supplier/domain/entities/supplier.dart'; import 'package:niogu_app/features/supplier/presentation/providers/supplier_provider.dart'; import 'package:niogu_app/features/supplier/presentation/widgets/edit_supplier_shimmer.dart'; import 'package:niogu_app/features/supplier/presentation/widgets/supplier_activity.dart'; import 'package:sizer/sizer.dart'; class EditSupplierScreen extends ConsumerStatefulWidget { final String supplierId; const EditSupplierScreen({super.key, required this.supplierId}); @override ConsumerState createState() => _EditSupplierScreenState(); } class _EditSupplierScreenState extends ConsumerState { final GlobalKey _formKey = GlobalKey(); final TextEditingController _nameController = TextEditingController(); final TextEditingController _emailController = TextEditingController(); final TextEditingController _phoneController = TextEditingController(); List _activities = []; bool _isLoading = true; @override void initState() { super.initState(); WidgetsBinding.instance.addPostFrameCallback((_) { Future.delayed(const Duration(milliseconds: 800), () { _fetchSupplier(); }); }); } Future _fetchSupplier() async { try { final supplierRepository = ref.read(supplierRepositoryProvider); final supplier = await supplierRepository.fetchSupplierById( widget.supplierId, ); _nameController.text = supplier.name; _emailController.text = supplier.email; _phoneController.text = supplier.phoneNumber; _activities = supplier.activities; setState(() { _isLoading = false; }); } catch (e, st) { if (!mounted) return; setState(() { _isLoading = false; }); LogMessage.log.e(e.toString(), error: e, stackTrace: st); CustomSnackbar.showError(context, "Ups, terjadi kesalahan"); context.pop(); } } Future _updateSupplier() async { if (!_formKey.currentState!.validate()) return; try { await ref .read(supplierControllerProvider.notifier) .saveSupplier( UpsertSupplier( id: widget.supplierId, name: _nameController.text.trim(), email: _emailController.text.trim(), phoneNumber: _phoneController.text.trim(), ), ); if (!mounted) return; CustomSnackbar.showSuccess(context, "Pemasok berhasil diubah"); context.pop(); } catch (e, st) { LogMessage.log.e(e.toString(), error: e, stackTrace: st); CustomSnackbar.showError(context, "Ups, terjadi kesalahan"); context.pop(); } } Future _deleteSupplier() async { try { ref .read(supplierControllerProvider.notifier) .deleteSupplier(widget.supplierId); if (!mounted) return; CustomSnackbar.showSuccess(context, "Pemasok berhasil dihapus"); Navigator.pop(context); context.pop(); } catch (e, st) { LogMessage.log.e(e.toString(), error: e, stackTrace: st); CustomSnackbar.showError(context, "Ups, terjadi kesalahan"); Navigator.pop(context); context.pop(); } } @override void dispose() { // TODO: implement dispose _nameController.dispose(); _emailController.dispose(); _phoneController.dispose(); super.dispose(); } void _showDeleteConfirmation(BuildContext context) { final bool isTablet = 100.w >= 600; final supplierControllerState = ref.watch(supplierControllerProvider); showDialog( context: context, builder: (BuildContext context) { return Dialog( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(4.5.w), ), elevation: 0, backgroundColor: Colors.transparent, child: Container( padding: EdgeInsets.all(6.w), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(4.5.w), ), child: Column( mainAxisSize: MainAxisSize.min, children: [ Container( padding: EdgeInsets.all(4.w), decoration: BoxDecoration( color: Colors.red[50], shape: BoxShape.circle, ), child: Icon( Icons.warning_amber_rounded, color: Colors.red, size: 10.w, ), ), SizedBox(height: 2.h), Text( "Hapus Pemasok?", style: TextStyle( fontSize: AppFontSize.medium.sp, fontWeight: FontWeight.bold, color: Colors.black87, ), ), SizedBox(height: 1.h), Text( "Tindakan ini tidak dapat dibatalkan. Semua data profil pemasok akan dihapus dari sistem.", textAlign: TextAlign.center, style: TextStyle( fontSize: isTablet ? (AppFontSize.medium - 1.25).sp : (AppFontSize.small - 1.25).sp, color: Colors.grey[600], height: 1.5, ), ), SizedBox(height: 3.h), Row( children: [ Expanded( child: ElevatedButton( onPressed: () => Navigator.pop(context), style: ElevatedButton.styleFrom( backgroundColor: Colors.grey.shade300, padding: EdgeInsets.symmetric(vertical: 1.5.h), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(2.5.w), ), elevation: 0, ), child: Text( "Batal", style: TextStyle( color: Colors.grey[800], fontWeight: FontWeight.bold, fontSize: AppFontSize.medium.sp, ), ), ), ), SizedBox(width: 3.w), Expanded( child: ElevatedButton( onPressed: supplierControllerState.isLoading ? null : _deleteSupplier, style: ElevatedButton.styleFrom( padding: EdgeInsets.symmetric(vertical: 1.5.h), backgroundColor: Colors.red, elevation: 0, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(2.5.w), ), disabledBackgroundColor: Colors.grey.shade300, ), child: Text( "Ya, Hapus", style: TextStyle( color: Colors.white, fontWeight: FontWeight.bold, fontSize: AppFontSize.medium.sp, ), ), ), ), ], ), ], ), ), ); }, ); } @override Widget build(BuildContext context) { return LayoutBuilder( builder: (context, constraints) { final bool isTablet = 100.w >= 600; final int totalActivity = _activities.length; final int displayActivityCount = totalActivity > 3 ? 3 : totalActivity; final supplierControllerState = ref.watch(supplierControllerProvider); return SafeArea( top: false, bottom: true, right: false, left: false, child: Scaffold( backgroundColor: Colors.white, appBar: TopBackBarApp( title: "Detail Pemasok", onTap: () => context.pop(), ), body: _isLoading ? const EditSupplierShimmer() : RefreshIndicator( onRefresh: () async { await Future.delayed(const Duration(milliseconds: 800)); await _fetchSupplier(); }, color: AppColor.primaryColor, backgroundColor: Colors.white, strokeWidth: 2.5, triggerMode: RefreshIndicatorTriggerMode.onEdge, child: SingleChildScrollView( child: Form( key: _formKey, child: Column( children: [ Center( child: Container( width: 25.w, height: 25.w, decoration: BoxDecoration( color: Colors.grey[100], shape: BoxShape.circle, border: Border.all( color: Colors.grey.shade200, width: 2, ), ), child: Icon( Icons.person_rounded, size: 12.w, color: Colors.grey[400], ), ), ), Container( color: Colors.white, padding: EdgeInsets.fromLTRB(5.w, 0, 5.w, 3.h), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ CustomTextFormField( label: "Nama Pemasok", controller: _nameController, hint: "Masukkan nama", validator: (value) { if (value == null || value.isEmpty) { return "Nama pemasok belum diisi"; } return null; }, prefixIcon: Icons.person_outline, ), SizedBox(height: 2.h), CustomTextFormField( label: "Email", controller: _emailController, hint: "Masukkan email (opsional)", keyboardType: TextInputType.emailAddress, prefixIcon: Icons.email_outlined, ), SizedBox(height: 2.h), CustomTextFormField( label: "No. Handphone / WA", controller: _phoneController, hint: "Masukkan no handphone / wa (opsional)", keyboardType: TextInputType.phone, prefixIcon: Icons.phone_android_outlined, ), ], ), ), _buildSectionHeader("Aktivitas Dengan Pemasok"), _activities.isEmpty ? Container( width: double.infinity, padding: EdgeInsets.symmetric( vertical: 4.h, ), margin: EdgeInsets.symmetric( horizontal: 5.w, ), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular( 2.5.w, ), border: Border.all( color: Colors.grey.shade100, ), ), child: Column( children: [ Icon( Icons.history_rounded, color: Colors.grey[300], size: 10.w, ), SizedBox(height: 1.5.h), Text( "Belum ada riwayat aktivitas dengan pemasok", style: TextStyle( fontSize: (AppFontSize.medium - 1.25).sp, color: Colors.grey[500], ), ), ], ), ) : Column( children: [ ListView.builder( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), padding: EdgeInsets.symmetric( horizontal: 5.w, ), itemCount: displayActivityCount, itemBuilder: (context, index) { final activity = _activities[index]; return SupplierActivity( activity: activity, ); }, ), if (totalActivity > 3) Padding( padding: EdgeInsets.symmetric( horizontal: 5.w, ), child: InkWell( onTap: () { context.pushNamed( AppRoute.supplierActivityScreen, extra: { "activities": _activities, }, ); }, borderRadius: BorderRadius.circular( 2.5.w, ), child: Container( padding: EdgeInsets.symmetric( vertical: 1.5.h, ), decoration: BoxDecoration( border: Border.all( color: Colors.grey[300]!, ), borderRadius: BorderRadius.circular( 2.5.w, ), ), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Text( "Lihat ${totalActivity - 3} Aktivitas Lainnya", style: TextStyle( color: Colors.grey[600], fontWeight: FontWeight.bold, fontSize: isTablet ? (AppFontSize.medium - 1.25) .sp : (AppFontSize.small - 1.25) .sp, ), ), SizedBox(width: 2.w), Icon( Icons .keyboard_arrow_down_rounded, color: Colors.grey[600], size: 5.w, ), ], ), ), ), ), ], ), SizedBox(height: 5.h), Padding( padding: EdgeInsets.symmetric(horizontal: 5.w), child: TextButton.icon( onPressed: () => _showDeleteConfirmation(context), style: TextButton.styleFrom( foregroundColor: Colors.red[700], padding: EdgeInsets.symmetric( vertical: 1.5.h, horizontal: 4.w, ), ), icon: Icon( Icons.delete_outline_rounded, size: 5.w, ), label: Text( "Hapus Pelanggan Ini", style: TextStyle( fontWeight: FontWeight.bold, fontSize: isTablet ? (AppFontSize.medium - 1.25).sp : (AppFontSize.small - 1.25).sp, ), ), ), ), SizedBox(height: 4.h), ], ), ), ), ), bottomNavigationBar: _isLoading ? null : Container( padding: EdgeInsets.all(5.w), decoration: BoxDecoration( color: Colors.white, boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.05), blurRadius: 10, offset: const Offset(0, -5), ), ], ), child: ElevatedButton( onPressed: supplierControllerState.isLoading ? null : _updateSupplier, style: ElevatedButton.styleFrom( backgroundColor: AppColor.primaryColor, minimumSize: Size(double.infinity, 6.5.h), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(2.5.w), ), disabledBackgroundColor: Colors.grey.shade300, ), child: Text( "Perbarui Informasi Pemasok", style: TextStyle( fontWeight: FontWeight.bold, fontSize: AppFontSize.medium.sp, color: Colors.white, ), ), ), ), ), ); }, ); } Widget _buildSectionHeader(String title) { return Padding( padding: EdgeInsets.fromLTRB(5.w, 3.h, 5.w, 1.5.h), child: Row( mainAxisAlignment: MainAxisAlignment.start, children: [ Text( title, style: TextStyle( fontWeight: FontWeight.bold, fontSize: (AppFontSize.medium - 1.25).sp, ), ), ], ), ); } }