feat: Menambahkan fitur upload logo toko pada konfigurasi toko
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>master
							parent
							
								
									64e36aa691
								
							
						
					
					
						commit
						b255d0a137
					
				| 
						 | 
				
			
			@ -1,5 +1,7 @@
 | 
			
		|||
import 'package:flutter/material.dart';
 | 
			
		||||
import 'package:shared_preferences/shared_preferences.dart';
 | 
			
		||||
import 'package:image_picker/image_picker.dart';
 | 
			
		||||
import 'dart:io';
 | 
			
		||||
 | 
			
		||||
/// Widget untuk dialog konfigurasi informasi toko
 | 
			
		||||
class StoreInfoConfigDialog extends StatefulWidget {
 | 
			
		||||
| 
						 | 
				
			
			@ -17,6 +19,12 @@ class _StoreInfoConfigDialogState extends State<StoreInfoConfigDialog> {
 | 
			
		|||
  final TextEditingController _storeAddressController = TextEditingController();
 | 
			
		||||
  final TextEditingController _adminNameController = TextEditingController();
 | 
			
		||||
  final TextEditingController _adminPhoneController = TextEditingController();
 | 
			
		||||
  
 | 
			
		||||
  // Variabel untuk menyimpan path logo
 | 
			
		||||
  String? _logoPath;
 | 
			
		||||
  
 | 
			
		||||
  // Image picker instance
 | 
			
		||||
  final ImagePicker _picker = ImagePicker();
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  void initState() {
 | 
			
		||||
| 
						 | 
				
			
			@ -34,6 +42,7 @@ class _StoreInfoConfigDialogState extends State<StoreInfoConfigDialog> {
 | 
			
		|||
      _storeAddressController.text = prefs.getString('store_address') ?? 'Jl. Merdeka No. 123';
 | 
			
		||||
      _adminNameController.text = prefs.getString('admin_name') ?? 'Budi Santoso';
 | 
			
		||||
      _adminPhoneController.text = prefs.getString('admin_phone') ?? '08123456789';
 | 
			
		||||
      _logoPath = prefs.getString('store_logo_path'); // Memuat path logo
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -46,6 +55,12 @@ class _StoreInfoConfigDialogState extends State<StoreInfoConfigDialog> {
 | 
			
		|||
      await prefs.setString('store_address', _storeAddressController.text);
 | 
			
		||||
      await prefs.setString('admin_name', _adminNameController.text);
 | 
			
		||||
      await prefs.setString('admin_phone', _adminPhoneController.text);
 | 
			
		||||
      // Menyimpan path logo
 | 
			
		||||
      if (_logoPath != null) {
 | 
			
		||||
        await prefs.setString('store_logo_path', _logoPath!);
 | 
			
		||||
      } else {
 | 
			
		||||
        await prefs.remove('store_logo_path');
 | 
			
		||||
      }
 | 
			
		||||
      
 | 
			
		||||
      if (mounted) {
 | 
			
		||||
        Navigator.of(context).pop(true); // Kembali dengan nilai true jika berhasil disimpan
 | 
			
		||||
| 
						 | 
				
			
			@ -53,6 +68,31 @@ class _StoreInfoConfigDialogState extends State<StoreInfoConfigDialog> {
 | 
			
		|||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /// Fungsi untuk memilih gambar dari gallery
 | 
			
		||||
  Future<void> _pickImage() async {
 | 
			
		||||
    try {
 | 
			
		||||
      final XFile? image = await _picker.pickImage(source: ImageSource.gallery);
 | 
			
		||||
      if (image != null) {
 | 
			
		||||
        setState(() {
 | 
			
		||||
          _logoPath = image.path;
 | 
			
		||||
        });
 | 
			
		||||
      }
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
      if (mounted) {
 | 
			
		||||
        ScaffoldMessenger.of(context).showSnackBar(
 | 
			
		||||
          SnackBar(content: Text('Gagal memilih gambar: $e')),
 | 
			
		||||
        );
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /// Fungsi untuk menghapus logo
 | 
			
		||||
  void _removeLogo() {
 | 
			
		||||
    setState(() {
 | 
			
		||||
      _logoPath = null;
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  void dispose() {
 | 
			
		||||
    _storeNameController.dispose();
 | 
			
		||||
| 
						 | 
				
			
			@ -72,6 +112,57 @@ class _StoreInfoConfigDialogState extends State<StoreInfoConfigDialog> {
 | 
			
		|||
          child: Column(
 | 
			
		||||
            mainAxisSize: MainAxisSize.min,
 | 
			
		||||
            children: [
 | 
			
		||||
              // Preview logo
 | 
			
		||||
              if (_logoPath != null)
 | 
			
		||||
                Column(
 | 
			
		||||
                  children: [
 | 
			
		||||
                    Container(
 | 
			
		||||
                      height: 100,
 | 
			
		||||
                      width: 100,
 | 
			
		||||
                      decoration: BoxDecoration(
 | 
			
		||||
                        border: Border.all(color: Colors.grey),
 | 
			
		||||
                        borderRadius: BorderRadius.circular(8),
 | 
			
		||||
                      ),
 | 
			
		||||
                      child: ClipRRect(
 | 
			
		||||
                        borderRadius: BorderRadius.circular(8),
 | 
			
		||||
                        child: Image.file(
 | 
			
		||||
                          File(_logoPath!),
 | 
			
		||||
                          fit: BoxFit.contain,
 | 
			
		||||
                          errorBuilder: (context, error, stackTrace) {
 | 
			
		||||
                            return const Icon(Icons.error);
 | 
			
		||||
                          },
 | 
			
		||||
                        ),
 | 
			
		||||
                      ),
 | 
			
		||||
                    ),
 | 
			
		||||
                    const SizedBox(height: 8),
 | 
			
		||||
                    Row(
 | 
			
		||||
                      mainAxisAlignment: MainAxisAlignment.center,
 | 
			
		||||
                      children: [
 | 
			
		||||
                        TextButton(
 | 
			
		||||
                          onPressed: _pickImage,
 | 
			
		||||
                          child: const Text('Ganti Logo'),
 | 
			
		||||
                        ),
 | 
			
		||||
                        TextButton(
 | 
			
		||||
                          onPressed: _removeLogo,
 | 
			
		||||
                          child: const Text('Hapus Logo'),
 | 
			
		||||
                        ),
 | 
			
		||||
                      ],
 | 
			
		||||
                    ),
 | 
			
		||||
                    const SizedBox(height: 16),
 | 
			
		||||
                  ],
 | 
			
		||||
                )
 | 
			
		||||
              else
 | 
			
		||||
                Column(
 | 
			
		||||
                  children: [
 | 
			
		||||
                    // Tombol untuk memilih logo jika belum ada
 | 
			
		||||
                    ElevatedButton.icon(
 | 
			
		||||
                      onPressed: _pickImage,
 | 
			
		||||
                      icon: const Icon(Icons.add_photo_alternate),
 | 
			
		||||
                      label: const Text('Pilih Logo Toko'),
 | 
			
		||||
                    ),
 | 
			
		||||
                    const SizedBox(height: 16),
 | 
			
		||||
                  ],
 | 
			
		||||
                ),
 | 
			
		||||
              TextFormField(
 | 
			
		||||
                controller: _storeNameController,
 | 
			
		||||
                decoration: const InputDecoration(
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
 | 
			
		|||
import 'package:google_fonts/google_fonts.dart';
 | 
			
		||||
import 'package:shared_preferences/shared_preferences.dart';
 | 
			
		||||
import 'package:intl/intl.dart';
 | 
			
		||||
import 'dart:io';
 | 
			
		||||
 | 
			
		||||
/// Widget untuk menampilkan informasi toko dan admin
 | 
			
		||||
/// Dapat di-tap untuk membuka dialog konfigurasi
 | 
			
		||||
| 
						 | 
				
			
			@ -19,6 +20,7 @@ class _StoreInfoWidgetState extends State<StoreInfoWidget> {
 | 
			
		|||
  String storeAddress = 'Jl. Merdeka No. 123';
 | 
			
		||||
  String adminName = 'Budi Santoso';
 | 
			
		||||
  String adminPhone = '08123456789';
 | 
			
		||||
  String? logoPath; // Path untuk logo toko
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  void initState() {
 | 
			
		||||
| 
						 | 
				
			
			@ -29,12 +31,13 @@ class _StoreInfoWidgetState extends State<StoreInfoWidget> {
 | 
			
		|||
  /// Memuat informasi toko dari shared preferences
 | 
			
		||||
  Future<void> _loadStoreInfo() async {
 | 
			
		||||
    final prefs = await SharedPreferences.getInstance();
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    setState(() {
 | 
			
		||||
      storeName = prefs.getString('store_name') ?? 'TOKO SEMBAKO MURAH';
 | 
			
		||||
      storeAddress = prefs.getString('store_address') ?? 'Jl. Merdeka No. 123';
 | 
			
		||||
      adminName = prefs.getString('admin_name') ?? 'Budi Santoso';
 | 
			
		||||
      adminPhone = prefs.getString('admin_phone') ?? '08123456789';
 | 
			
		||||
      logoPath = prefs.getString('store_logo_path'); // Memuat path logo
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -42,7 +45,7 @@ class _StoreInfoWidgetState extends State<StoreInfoWidget> {
 | 
			
		|||
  Widget build(BuildContext context) {
 | 
			
		||||
    // Load data every time the widget is built to ensure it's up-to-date
 | 
			
		||||
    _loadStoreInfo();
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    final courierPrime = GoogleFonts.courierPrime(
 | 
			
		||||
      textStyle: const TextStyle(
 | 
			
		||||
        fontSize: 14,
 | 
			
		||||
| 
						 | 
				
			
			@ -58,6 +61,27 @@ class _StoreInfoWidgetState extends State<StoreInfoWidget> {
 | 
			
		|||
        color: Colors.white,
 | 
			
		||||
        child: Column(
 | 
			
		||||
          children: [
 | 
			
		||||
            // Menampilkan logo jika tersedia
 | 
			
		||||
            if (logoPath != null)
 | 
			
		||||
              Container(
 | 
			
		||||
                height: 80,
 | 
			
		||||
                width: 80,
 | 
			
		||||
                margin: const EdgeInsets.only(bottom: 8),
 | 
			
		||||
                child: Image.file(
 | 
			
		||||
                  File(logoPath!),
 | 
			
		||||
                  fit: BoxFit.contain,
 | 
			
		||||
                  errorBuilder: (context, error, stackTrace) {
 | 
			
		||||
                    // Jika gagal memuat gambar, tampilkan placeholder
 | 
			
		||||
                    return Container(
 | 
			
		||||
                      decoration: BoxDecoration(
 | 
			
		||||
                        border: Border.all(color: Colors.grey),
 | 
			
		||||
                        borderRadius: BorderRadius.circular(4),
 | 
			
		||||
                      ),
 | 
			
		||||
                      child: const Icon(Icons.image_not_supported, size: 40),
 | 
			
		||||
                    );
 | 
			
		||||
                  },
 | 
			
		||||
                ),
 | 
			
		||||
              ),
 | 
			
		||||
            Text(
 | 
			
		||||
              storeName,
 | 
			
		||||
              style: courierPrime.copyWith(
 | 
			
		||||
| 
						 | 
				
			
			@ -67,15 +91,17 @@ class _StoreInfoWidgetState extends State<StoreInfoWidget> {
 | 
			
		|||
              textAlign: TextAlign.center,
 | 
			
		||||
            ),
 | 
			
		||||
            const SizedBox(height: 4),
 | 
			
		||||
            Text(storeAddress, style: courierPrime, textAlign: TextAlign.center),
 | 
			
		||||
            Text(storeAddress,
 | 
			
		||||
                style: courierPrime, textAlign: TextAlign.center),
 | 
			
		||||
            const SizedBox(height: 4),
 | 
			
		||||
            Text('Admin: $adminName', style: courierPrime, textAlign: TextAlign.center),
 | 
			
		||||
	    Text('Telp: $adminPhone', style: courierPrime, textAlign: TextAlign.center),
 | 
			
		||||
            Text('Admin: $adminName',
 | 
			
		||||
                style: courierPrime, textAlign: TextAlign.center),
 | 
			
		||||
            Text('Telp: $adminPhone',
 | 
			
		||||
                style: courierPrime, textAlign: TextAlign.center),
 | 
			
		||||
            const SizedBox(height: 4),
 | 
			
		||||
            Text('Tanggal: ${DateFormat('dd/MM/yyyy').format(DateTime.now())}', 
 | 
			
		||||
                style: courierPrime, 
 | 
			
		||||
                textAlign: TextAlign.center),
 | 
			
		||||
	    ],
 | 
			
		||||
            Text('Tanggal: ${DateFormat('dd/MM/yyyy').format(DateTime.now())}',
 | 
			
		||||
                style: courierPrime, textAlign: TextAlign.center),
 | 
			
		||||
          ],
 | 
			
		||||
        ),
 | 
			
		||||
      ),
 | 
			
		||||
    );
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue