import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import 'package:image_picker/image_picker.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/utils/image_service.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/profile/domain/entities/profile.dart'; import 'package:niogu_app/features/profile/presentation/providers/profile_provider.dart'; import 'package:sizer/sizer.dart'; class BusinessInfoScreen extends ConsumerStatefulWidget { final BusinessInfo businessInfo; const BusinessInfoScreen({super.key, required this.businessInfo}); @override ConsumerState createState() => _BusinessInfoScreenState(); } class _BusinessInfoScreenState extends ConsumerState { final _formKey = GlobalKey(); late final String businessCode; final _nameController = TextEditingController(); final _emailController = TextEditingController(); final _phoneController = TextEditingController(); final _categoryController = TextEditingController(); final ImagePicker _picker = ImagePicker(); final List _logoPathTemps = []; String? _logoPath; @override void initState() { // TODO: implement initState super.initState(); final businessInfo = widget.businessInfo; businessCode = businessInfo.businessCode; _logoPath = businessInfo.logoPath; _nameController.text = businessInfo.businessName; _emailController.text = businessInfo.businessEmail; _phoneController.text = businessInfo.businessPhoneNumber; _categoryController.text = businessInfo.businessType; } @override void dispose() { // TODO: implement dispose _nameController.dispose(); _emailController.dispose(); _phoneController.dispose(); _categoryController.dispose(); super.dispose(); } Future _showPickerOptions() async { final bool isTablet = 100.w >= 600; showModalBottomSheet( context: context, backgroundColor: Colors.white, shape: RoundedRectangleBorder( borderRadius: BorderRadius.vertical(top: Radius.circular(2.5.w)), ), constraints: const BoxConstraints(maxWidth: double.infinity), builder: (BuildContext context) { return SafeArea( child: Container( width: 100.w, padding: EdgeInsets.symmetric(vertical: 2.h, horizontal: 5.w), clipBehavior: Clip.hardEdge, decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.vertical(top: Radius.circular(6.w)), ), child: Column( mainAxisSize: MainAxisSize.min, children: [ ListTile( leading: Icon(Icons.photo_library, size: 6.w), title: Text( 'Galeri', style: TextStyle( fontSize: isTablet ? AppFontSize.medium.sp : AppFontSize.small.sp, ), ), onTap: () async { await _getImage(ImageSource.gallery); context.pop(); }, ), SizedBox(height: 2.h), ListTile( leading: Icon(Icons.photo_camera, size: 6.w), title: Text( 'Kamera', style: TextStyle( fontSize: isTablet ? AppFontSize.medium.sp : AppFontSize.small.sp, ), ), onTap: () async { await _getImage(ImageSource.camera); context.pop(); }, ), ], ), ), ); }, ); } Future _getImage(ImageSource ImageSource) async { try { final XFile? pickedFile = await _picker.pickImage( source: ImageSource, imageQuality: 70, ); if (pickedFile != null) { File tempFile = File(pickedFile.path); String? logoPath = await ImageService.saveImageToLocalDirectory( tempFile, "logo_images", ); if (logoPath != null) { _logoPathTemps.add(logoPath); setState(() { _logoPath = logoPath; }); } } } catch (e, st) { LogMessage.log.e(e.toString(), error: e, stackTrace: st); CustomSnackbar.showWarning(context, "Akses ditolak"); } } Future _cleanUpImages() async { for (final image in _logoPathTemps) { if (image != null) { await ImageService.deleteLocalImage(image); } } } Future _updateBusinessInfo() async { if (!_formKey.currentState!.validate()) return; try { await ref .read(profileControllerProvider.notifier) .updateBusinessInfo( BusinessInfo( logoPath: _logoPath, businessCode: businessCode, businessName: _nameController.text.trim(), businessEmail: _emailController.text.trim(), businessPhoneNumber: _phoneController.text.trim(), businessType: _categoryController.text.trim(), ), ); if (!mounted) return; for (final path in _logoPathTemps) { if (path != null && _logoPath != null && path != _logoPath) { await ImageService.deleteLocalImage(path); } } CustomSnackbar.showSuccess(context, "Informasi usaha berhasil diubah"); context.pop(); } catch (e, st) { LogMessage.log.e(e.toString(), error: e, stackTrace: st); CustomSnackbar.showError(context, "Ups, terjadi kesalahan"); } } @override Widget build(BuildContext context) { return LayoutBuilder( builder: (context, constraints) { final bool isTablet = 100.w >= 600; final File imageFile = File(_logoPath ?? "image not found"); final bool imageFileExists = imageFile.existsSync(); final profileControllerState = ref.watch(profileControllerProvider); return PopScope( canPop: false, onPopInvokedWithResult: (didPop, result) async { if (didPop) return; await _cleanUpImages(); context.pop(); }, child: SafeArea( child: Scaffold( backgroundColor: const Color(0xFFF9FAFB), appBar: TopBackBarApp( title: "Informasi Usaha", onTap: () async { await _cleanUpImages(); context.pop(); }, ), body: SingleChildScrollView( padding: EdgeInsets.all(5.w), child: Form( key: _formKey, child: Column( children: [ Center( child: Column( children: [ Stack( clipBehavior: Clip.none, children: [ Container( width: 25.w, height: 25.w, decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(4.w), border: Border.all( color: Colors.grey.shade200, ), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.02), blurRadius: 10, ), ], ), child: imageFileExists ? ClipRRect( borderRadius: BorderRadius.circular( 2.5.w, ), child: Image.file( imageFile, fit: BoxFit.cover, width: double.infinity, height: double.infinity, errorBuilder: (context, error, stackTrace) { return Icon( Icons.error, color: Colors.grey[400], size: 10.w, ); }, ), ) : IconButton( onPressed: _showPickerOptions, icon: Icon( Icons.add_a_photo_outlined, color: Colors.grey[400], size: 8.w, ), ), ), if (_logoPath != null) Positioned( top: 1.w, right: 1.w, child: Material( color: Colors.transparent, type: MaterialType.transparency, child: InkWell( onTap: () { setState(() { _logoPath = null; }); }, child: Container( padding: EdgeInsets.all(1.w), decoration: BoxDecoration( color: Colors.red[50], shape: BoxShape.circle, border: Border.all( color: Colors.red.withOpacity( 0.2, ), ), boxShadow: [ BoxShadow( color: Colors.black.withOpacity( 0.1, ), blurRadius: 2, offset: Offset(0, 1), ), ], ), child: Icon( Icons.remove, color: Colors.red, size: 4.w, ), ), ), ), ), ], ), SizedBox(height: 1.5.h), Text( "Logo Usaha", style: TextStyle( fontSize: isTablet ? AppFontSize.medium.sp : AppFontSize.small.sp, color: Colors.grey, ), ), ], ), ), SizedBox(height: 4.h), CustomTextFormField( label: "ID Usaha", controller: TextEditingController(text: businessCode), readOnly: true, prefixIcon: Icons.badge_outlined, suffixIcon: Icons.copy_rounded, suffixPressed: () { Clipboard.setData(ClipboardData(text: businessCode)); CustomSnackbar.showSuccess( context, "ID Usaha berhasil disalin", ); }, ), SizedBox(height: 2.h), CustomTextFormField( label: "Nama Usaha", hint: "Masukkan nama bisnis Anda", controller: _nameController, prefixIcon: Icons.storefront_outlined, validator: (value) { if (value == null || value.isEmpty) { return "Nama usaha belum diisi"; } return null; }, ), SizedBox(height: 2.h), CustomTextFormField( label: "Email Usaha", hint: "bisnis@email.com", controller: _emailController, prefixIcon: Icons.email_outlined, keyboardType: TextInputType.emailAddress, ), SizedBox(height: 2.h), CustomTextFormField( label: "No HP / WhatsApp Usaha", hint: "0812xxxx", controller: _phoneController, prefixIcon: Icons.phone_android, keyboardType: TextInputType.phone, ), SizedBox(height: 2.h), CustomTextFormField( label: "Kategori Usaha", hint: "Contoh: F&B, Retail, Pertanian", controller: _categoryController, prefixIcon: Icons.category_outlined, ), SizedBox(height: 5.h), ElevatedButton( onPressed: profileControllerState.isLoading ? null : _updateBusinessInfo, style: ElevatedButton.styleFrom( backgroundColor: AppColor.primaryColor, minimumSize: Size(double.infinity, 7.h), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(3.w), ), disabledBackgroundColor: Colors.grey.shade300, ), child: Text( "Simpan Perubahan", style: TextStyle( color: Colors.white, fontWeight: FontWeight.bold, fontSize: AppFontSize.medium.sp, ), ), ), ], ), ), ), ), ), ); }, ); } }