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:flutter/material.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
import 'package:image_picker/image_picker.dart';
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
/// Widget untuk dialog konfigurasi informasi toko
|
/// Widget untuk dialog konfigurasi informasi toko
|
||||||
class StoreInfoConfigDialog extends StatefulWidget {
|
class StoreInfoConfigDialog extends StatefulWidget {
|
||||||
|
@ -18,6 +20,12 @@ class _StoreInfoConfigDialogState extends State<StoreInfoConfigDialog> {
|
||||||
final TextEditingController _adminNameController = TextEditingController();
|
final TextEditingController _adminNameController = TextEditingController();
|
||||||
final TextEditingController _adminPhoneController = TextEditingController();
|
final TextEditingController _adminPhoneController = TextEditingController();
|
||||||
|
|
||||||
|
// Variabel untuk menyimpan path logo
|
||||||
|
String? _logoPath;
|
||||||
|
|
||||||
|
// Image picker instance
|
||||||
|
final ImagePicker _picker = ImagePicker();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
@ -34,6 +42,7 @@ class _StoreInfoConfigDialogState extends State<StoreInfoConfigDialog> {
|
||||||
_storeAddressController.text = prefs.getString('store_address') ?? 'Jl. Merdeka No. 123';
|
_storeAddressController.text = prefs.getString('store_address') ?? 'Jl. Merdeka No. 123';
|
||||||
_adminNameController.text = prefs.getString('admin_name') ?? 'Budi Santoso';
|
_adminNameController.text = prefs.getString('admin_name') ?? 'Budi Santoso';
|
||||||
_adminPhoneController.text = prefs.getString('admin_phone') ?? '08123456789';
|
_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('store_address', _storeAddressController.text);
|
||||||
await prefs.setString('admin_name', _adminNameController.text);
|
await prefs.setString('admin_name', _adminNameController.text);
|
||||||
await prefs.setString('admin_phone', _adminPhoneController.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) {
|
if (mounted) {
|
||||||
Navigator.of(context).pop(true); // Kembali dengan nilai true jika berhasil disimpan
|
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
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
_storeNameController.dispose();
|
_storeNameController.dispose();
|
||||||
|
@ -72,6 +112,57 @@ class _StoreInfoConfigDialogState extends State<StoreInfoConfigDialog> {
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
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(
|
TextFormField(
|
||||||
controller: _storeNameController,
|
controller: _storeNameController,
|
||||||
decoration: const InputDecoration(
|
decoration: const InputDecoration(
|
||||||
|
|
|
@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:google_fonts/google_fonts.dart';
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
/// Widget untuk menampilkan informasi toko dan admin
|
/// Widget untuk menampilkan informasi toko dan admin
|
||||||
/// Dapat di-tap untuk membuka dialog konfigurasi
|
/// Dapat di-tap untuk membuka dialog konfigurasi
|
||||||
|
@ -19,6 +20,7 @@ class _StoreInfoWidgetState extends State<StoreInfoWidget> {
|
||||||
String storeAddress = 'Jl. Merdeka No. 123';
|
String storeAddress = 'Jl. Merdeka No. 123';
|
||||||
String adminName = 'Budi Santoso';
|
String adminName = 'Budi Santoso';
|
||||||
String adminPhone = '08123456789';
|
String adminPhone = '08123456789';
|
||||||
|
String? logoPath; // Path untuk logo toko
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
|
@ -35,6 +37,7 @@ class _StoreInfoWidgetState extends State<StoreInfoWidget> {
|
||||||
storeAddress = prefs.getString('store_address') ?? 'Jl. Merdeka No. 123';
|
storeAddress = prefs.getString('store_address') ?? 'Jl. Merdeka No. 123';
|
||||||
adminName = prefs.getString('admin_name') ?? 'Budi Santoso';
|
adminName = prefs.getString('admin_name') ?? 'Budi Santoso';
|
||||||
adminPhone = prefs.getString('admin_phone') ?? '08123456789';
|
adminPhone = prefs.getString('admin_phone') ?? '08123456789';
|
||||||
|
logoPath = prefs.getString('store_logo_path'); // Memuat path logo
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,6 +61,27 @@ class _StoreInfoWidgetState extends State<StoreInfoWidget> {
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
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(
|
Text(
|
||||||
storeName,
|
storeName,
|
||||||
style: courierPrime.copyWith(
|
style: courierPrime.copyWith(
|
||||||
|
@ -67,15 +91,17 @@ class _StoreInfoWidgetState extends State<StoreInfoWidget> {
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
),
|
),
|
||||||
const SizedBox(height: 4),
|
const SizedBox(height: 4),
|
||||||
Text(storeAddress, style: courierPrime, textAlign: TextAlign.center),
|
Text(storeAddress,
|
||||||
|
style: courierPrime, textAlign: TextAlign.center),
|
||||||
const SizedBox(height: 4),
|
const SizedBox(height: 4),
|
||||||
Text('Admin: $adminName', style: courierPrime, textAlign: TextAlign.center),
|
Text('Admin: $adminName',
|
||||||
Text('Telp: $adminPhone', style: courierPrime, textAlign: TextAlign.center),
|
style: courierPrime, textAlign: TextAlign.center),
|
||||||
|
Text('Telp: $adminPhone',
|
||||||
|
style: courierPrime, textAlign: TextAlign.center),
|
||||||
const SizedBox(height: 4),
|
const SizedBox(height: 4),
|
||||||
Text('Tanggal: ${DateFormat('dd/MM/yyyy').format(DateTime.now())}',
|
Text('Tanggal: ${DateFormat('dd/MM/yyyy').format(DateTime.now())}',
|
||||||
style: courierPrime,
|
style: courierPrime, textAlign: TextAlign.center),
|
||||||
textAlign: TextAlign.center),
|
],
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in New Issue