feat: Remove store logo functionality and update printing services
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>master
parent
c2e6f6b945
commit
64e36aa691
|
@ -0,0 +1,36 @@
|
|||
# Printing Status Card Implementation
|
||||
|
||||
I've successfully implemented a floating card with animations that shows the printing status when the user presses the print button.
|
||||
|
||||
## Features
|
||||
|
||||
1. **Animated Appearance/Disappearance**:
|
||||
- Smooth scale and fade animations when showing/hiding
|
||||
- Elastic entrance animation for a polished feel
|
||||
|
||||
2. **Visual Design**:
|
||||
- Beautiful gradient background (purple to blue)
|
||||
- Clear icon and text indicators
|
||||
- Indeterminate progress bar
|
||||
- Rounded corners and shadow for depth
|
||||
|
||||
3. **Functionality**:
|
||||
- Automatically appears when printing starts
|
||||
- Automatically disappears when printing completes
|
||||
- Manual dismiss option with the close button
|
||||
|
||||
## Files Modified
|
||||
|
||||
1. Created new widget: `lib/widgets/printing_status_card.dart`
|
||||
2. Modified: `lib/screens/receipt_screen.dart` to integrate the widget
|
||||
|
||||
## How It Works
|
||||
|
||||
When the user presses the "Cetak Struk" button in the speed dial:
|
||||
1. The `_isPrinting` state is set to `true`
|
||||
2. The `PrintingStatusCard` becomes visible with animations
|
||||
3. The printing process begins
|
||||
4. When printing completes (success or failure), `_isPrinting` is set to `false`
|
||||
5. The card smoothly animates out of view
|
||||
|
||||
The card also allows manual dismissal by the user if needed.
|
Binary file not shown.
Before Width: | Height: | Size: 91 B |
|
@ -2,7 +2,6 @@ import 'package:cashumit/screens/config_screen.dart';
|
|||
import 'package:cashumit/screens/transaction_screen.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:cashumit/screens/receipt_screen.dart';
|
||||
import 'package:cashumit/utils/store_logo_utils.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:cashumit/providers/receipt_provider.dart';
|
||||
|
||||
|
@ -10,9 +9,6 @@ void main() async {
|
|||
// Ensure WidgetsFlutterBinding is initialized for async operations
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
// Initialize the store logo from asset
|
||||
await copyAndSaveStoreLogoFromAsset('assets/images/store_logo.png');
|
||||
|
||||
runApp(
|
||||
MultiProvider(
|
||||
providers: [
|
||||
|
|
|
@ -30,13 +30,11 @@ class EscPosPrintService {
|
|||
final storeAddress = prefs.getString('store_address') ?? 'Jl. Merdeka No. 123';
|
||||
final adminName = prefs.getString('admin_name') ?? 'Budi Santoso';
|
||||
final adminPhone = prefs.getString('admin_phone') ?? '08123456789';
|
||||
final logoPath = prefs.getString('store_logo_path'); // Load logo path
|
||||
|
||||
print('Nama toko: $storeName');
|
||||
print('Alamat toko: $storeAddress');
|
||||
print('Nama admin: $adminName');
|
||||
print('Telepon admin: $adminPhone');
|
||||
print('Logo path: $logoPath');
|
||||
|
||||
// Format tanggal
|
||||
final dateFormatter = DateFormat('dd/MM/yyyy HH:mm');
|
||||
|
@ -64,93 +62,14 @@ class EscPosPrintService {
|
|||
// Mulai dengan inisialisasi printer
|
||||
List<int> bytes = [];
|
||||
|
||||
// Tambahkan logo jika ada path-nya
|
||||
if (logoPath != null && logoPath.isNotEmpty) {
|
||||
try {
|
||||
// Membaca file gambar dari path lokal dengan timeout
|
||||
final file = File(logoPath);
|
||||
bool fileExists = false;
|
||||
try {
|
||||
fileExists = await file.exists();
|
||||
} catch (e) {
|
||||
print('Error saat memeriksa keberadaan file logo: $e');
|
||||
}
|
||||
|
||||
if (fileExists) {
|
||||
// Baca file dengan timeout
|
||||
Uint8List imageBytes;
|
||||
try {
|
||||
imageBytes = await file.readAsBytes();
|
||||
} catch (e) {
|
||||
print('Gagal membaca file logo: $e');
|
||||
throw Exception('Gagal membaca file logo');
|
||||
}
|
||||
|
||||
// Decode gambar dengan penanganan error menggunakan isolate
|
||||
Uint8List? processedImageBytes;
|
||||
try {
|
||||
processedImageBytes = await compute(processImageInIsolate, ImageProcessParams(imageBytes, 200));
|
||||
} catch (e) {
|
||||
print('Gagal mendecode gambar: $e');
|
||||
}
|
||||
|
||||
if (processedImageBytes != null) {
|
||||
// Decode the processed image bytes back to an image object for printing
|
||||
final img.Image? image = img.decodeImage(processedImageBytes);
|
||||
if (image != null) {
|
||||
bytes += generator.image(image);
|
||||
} else {
|
||||
// Jika gagal decode gambar, gunakan teks sebagai fallback
|
||||
bytes += generator.text(storeName,
|
||||
styles: PosStyles(
|
||||
bold: true,
|
||||
height: PosTextSize.size1,
|
||||
width: PosTextSize.size1,
|
||||
align: PosAlign.center,
|
||||
));
|
||||
}
|
||||
} else {
|
||||
// Jika gagal decode gambar, gunakan teks sebagai fallback
|
||||
bytes += generator.text(storeName,
|
||||
styles: PosStyles(
|
||||
bold: true,
|
||||
height: PosTextSize.size1,
|
||||
width: PosTextSize.size1,
|
||||
align: PosAlign.center,
|
||||
));
|
||||
}
|
||||
} else {
|
||||
print('File logo tidak ditemukan: $logoPath');
|
||||
// Jika file tidak ditemukan, gunakan teks sebagai fallback
|
||||
bytes += generator.text(storeName,
|
||||
styles: PosStyles(
|
||||
bold: true,
|
||||
height: PosTextSize.size1,
|
||||
width: PosTextSize.size1,
|
||||
align: PosAlign.center,
|
||||
));
|
||||
}
|
||||
} catch (e) {
|
||||
print('Gagal memuat logo: $e');
|
||||
// Jika gagal memuat logo, gunakan teks sebagai fallback
|
||||
bytes += generator.text(storeName,
|
||||
styles: PosStyles(
|
||||
bold: true,
|
||||
height: PosTextSize.size1,
|
||||
width: PosTextSize.size1,
|
||||
align: PosAlign.center,
|
||||
));
|
||||
}
|
||||
} else {
|
||||
// Jika tidak ada logo, gunakan nama toko sebagai header
|
||||
bytes += generator.text(storeName,
|
||||
styles: PosStyles(
|
||||
bold: true,
|
||||
height: PosTextSize.size1,
|
||||
width: PosTextSize.size1,
|
||||
align: PosAlign.center,
|
||||
));
|
||||
}
|
||||
// Tambahkan nama toko sebagai header
|
||||
bytes += generator.text(storeName,
|
||||
styles: PosStyles(
|
||||
bold: true,
|
||||
height: PosTextSize.size1,
|
||||
width: PosTextSize.size1,
|
||||
align: PosAlign.center,
|
||||
));
|
||||
|
||||
try {
|
||||
bytes += generator.text(storeAddress,
|
||||
|
|
|
@ -17,25 +17,6 @@ class StrukTextGenerator {
|
|||
return char * width;
|
||||
}
|
||||
|
||||
/// Fungsi untuk membuat representasi ASCII sederhana dari logo
|
||||
static String createAsciiLogo(String storeName, int width) {
|
||||
final buffer = StringBuffer();
|
||||
|
||||
// Membuat logo ASCII sederhana dengan nama toko
|
||||
final int nameLength = storeName.length;
|
||||
final int boxWidth = nameLength + 4;
|
||||
final String horizontalLine = '=' * boxWidth;
|
||||
final String emptyLine = '|${' ' * (boxWidth - 2)}|';
|
||||
|
||||
buffer.writeln(centerText(horizontalLine, width));
|
||||
buffer.writeln(centerText(emptyLine, width));
|
||||
buffer.writeln(centerText('| $storeName |', width));
|
||||
buffer.writeln(centerText(emptyLine, width));
|
||||
buffer.writeln(centerText(horizontalLine, width));
|
||||
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
/// Menghasilkan struk dalam format teks berdasarkan data transaksi
|
||||
static Future<String> generateStrukText({
|
||||
required List<ReceiptItem> items,
|
||||
|
@ -55,13 +36,11 @@ class StrukTextGenerator {
|
|||
final storeAddress = prefs.getString('store_address') ?? 'Jl. Merdeka No. 123';
|
||||
final adminName = prefs.getString('admin_name') ?? 'Budi Santoso';
|
||||
final adminPhone = prefs.getString('admin_phone') ?? '08123456789';
|
||||
final logoPath = prefs.getString('store_logo_path'); // Load logo path
|
||||
|
||||
print('Nama toko: $storeName');
|
||||
print('Alamat toko: $storeAddress');
|
||||
print('Nama admin: $adminName');
|
||||
print('Telepon admin: $adminPhone');
|
||||
print('Logo path: $logoPath');
|
||||
|
||||
// Format tanggal
|
||||
final dateFormatter = DateFormat('dd/MM/yyyy');
|
||||
|
@ -77,9 +56,8 @@ class StrukTextGenerator {
|
|||
// Bangun struk dalam format teks
|
||||
final buffer = StringBuffer();
|
||||
|
||||
// Header toko dengan logo ASCII - menggunakan lebar 32 karakter untuk kompatibilitas printer termal
|
||||
buffer.write(createAsciiLogo(storeName, 32));
|
||||
buffer.writeln('');
|
||||
// Header toko - menggunakan lebar 32 karakter untuk kompatibilitas printer termal
|
||||
buffer.writeln(centerText(storeName, 32));
|
||||
buffer.writeln(centerText(storeAddress, 32));
|
||||
buffer.writeln(centerText('Admin: $adminName', 32));
|
||||
buffer.writeln(centerText('Telp: $adminPhone', 32));
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
import 'dart:io';
|
||||
import 'dart:typed_data';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart' show instantiateImageCodec;
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
|
||||
/// Utility to validate image files
|
||||
class ImageValidator {
|
||||
/// Validate if a file is a valid image by trying to decode it
|
||||
static Future<bool> validateImageFile(String filePath) async {
|
||||
try {
|
||||
final file = File(filePath);
|
||||
if (!await file.exists()) {
|
||||
print('File does not exist: $filePath');
|
||||
return false;
|
||||
}
|
||||
|
||||
final bytes = await file.readAsBytes();
|
||||
print('File size: ${bytes.length} bytes');
|
||||
|
||||
if (bytes.isEmpty) {
|
||||
print('File is empty: $filePath');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Try to decode as image
|
||||
final codec = await instantiateImageCodec(bytes);
|
||||
final frameInfo = await codec.getNextFrame();
|
||||
final image = frameInfo.image;
|
||||
|
||||
print('Image dimensions: ${image.width}x${image.height}');
|
||||
await image.dispose();
|
||||
await codec.dispose();
|
||||
|
||||
return true;
|
||||
} catch (e) {
|
||||
print('Failed to validate image file $filePath: $e');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// Validate images in the documents directory
|
||||
static Future<void> validateStoredImages() async {
|
||||
try {
|
||||
final dir = await getApplicationDocumentsDirectory();
|
||||
final logoDir = Directory('${dir.path}/logos');
|
||||
|
||||
if (!await logoDir.exists()) {
|
||||
print('Logo directory does not exist');
|
||||
return;
|
||||
}
|
||||
|
||||
final files = logoDir.listSync();
|
||||
print('Found ${files.length} files in logo directory');
|
||||
|
||||
for (final file in files) {
|
||||
if (file is File) {
|
||||
print('Validating ${file.path}...');
|
||||
final isValid = await validateImageFile(file.path);
|
||||
print('Validation result: $isValid');
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
print('Error validating stored images: $e');
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'dart:io';
|
||||
import 'package:flutter/services.dart' show rootBundle;
|
||||
|
||||
/// Fungsi untuk menyimpan path logo toko ke shared preferences
|
||||
Future<void> saveStoreLogoPath(String logoPath) async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setString('store_logo_path', logoPath);
|
||||
}
|
||||
|
||||
/// Fungsi untuk menghapus path logo toko dari shared preferences
|
||||
Future<void> removeStoreLogoPath() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.remove('store_logo_path');
|
||||
}
|
||||
|
||||
/// Fungsi untuk mengambil path logo toko dari shared preferences
|
||||
Future<String?> getStoreLogoPath() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
return prefs.getString('store_logo_path');
|
||||
}
|
||||
|
||||
/// Fungsi untuk menyalin logo dari asset ke direktori dokumen aplikasi
|
||||
/// dan menyimpan path-nya ke shared preferences
|
||||
Future<void> copyAndSaveStoreLogoFromAsset(String assetPath) async {
|
||||
try {
|
||||
// Dapatkan direktori dokumen aplikasi
|
||||
final dir = await getApplicationDocumentsDirectory();
|
||||
final logoDir = Directory('${dir.path}/logos');
|
||||
|
||||
// Buat direktori jika belum ada
|
||||
if (!await logoDir.exists()) {
|
||||
await logoDir.create(recursive: true);
|
||||
}
|
||||
|
||||
// Path file logo di direktori dokumen
|
||||
final logoFile = File('${logoDir.path}/store_logo.png');
|
||||
|
||||
// Baca data dari asset
|
||||
final data = await rootBundle.load(assetPath);
|
||||
|
||||
// Tulis data ke file di direktori dokumen
|
||||
await logoFile.writeAsBytes(data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes));
|
||||
|
||||
// Simpan path ke shared preferences
|
||||
await saveStoreLogoPath(logoFile.path);
|
||||
} catch (e) {
|
||||
print('Error copying logo from asset: $e');
|
||||
// Jika gagal, hapus path yang mungkin tersimpan
|
||||
await removeStoreLogoPath();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,158 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
class PrintingStatusCard extends StatefulWidget {
|
||||
final bool isVisible;
|
||||
final VoidCallback? onDismiss;
|
||||
|
||||
const PrintingStatusCard({
|
||||
Key? key,
|
||||
required this.isVisible,
|
||||
this.onDismiss,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<PrintingStatusCard> createState() => _PrintingStatusCardState();
|
||||
}
|
||||
|
||||
class _PrintingStatusCardState extends State<PrintingStatusCard>
|
||||
with SingleTickerProviderStateMixin {
|
||||
late AnimationController _controller;
|
||||
late Animation<double> _scaleAnimation;
|
||||
late Animation<double> _fadeAnimation;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_controller = AnimationController(
|
||||
duration: const Duration(milliseconds: 300),
|
||||
vsync: this,
|
||||
);
|
||||
|
||||
_scaleAnimation = Tween<double>(
|
||||
begin: 0.0,
|
||||
end: 1.0,
|
||||
).animate(CurvedAnimation(
|
||||
parent: _controller,
|
||||
curve: Curves.elasticOut,
|
||||
));
|
||||
|
||||
_fadeAnimation = Tween<double>(
|
||||
begin: 0.0,
|
||||
end: 1.0,
|
||||
).animate(CurvedAnimation(
|
||||
parent: _controller,
|
||||
curve: Curves.easeInOut,
|
||||
));
|
||||
|
||||
// Start animation when widget is visible
|
||||
if (widget.isVisible) {
|
||||
_controller.forward();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void didUpdateWidget(covariant PrintingStatusCard oldWidget) {
|
||||
super.didUpdateWidget(oldWidget);
|
||||
if (widget.isVisible && !oldWidget.isVisible) {
|
||||
_controller.forward();
|
||||
} else if (!widget.isVisible && oldWidget.isVisible) {
|
||||
_controller.reverse();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_controller.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AnimatedBuilder(
|
||||
animation: _controller,
|
||||
builder: (context, child) {
|
||||
return Positioned(
|
||||
top: 100,
|
||||
left: MediaQuery.of(context).size.width * 0.1,
|
||||
right: MediaQuery.of(context).size.width * 0.1,
|
||||
child: IgnorePointer(
|
||||
ignoring: !widget.isVisible,
|
||||
child: Opacity(
|
||||
opacity: _fadeAnimation.value,
|
||||
child: Transform.scale(
|
||||
scale: _scaleAnimation.value,
|
||||
child: Card(
|
||||
elevation: 12,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
),
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(20),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
gradient: const LinearGradient(
|
||||
begin: Alignment.topLeft,
|
||||
end: Alignment.bottomRight,
|
||||
colors: [
|
||||
Color(0xFF6A11CB),
|
||||
Color(0xFF2575FC),
|
||||
],
|
||||
),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const SizedBox(width: 8),
|
||||
const Icon(
|
||||
Icons.print,
|
||||
color: Colors.white,
|
||||
size: 36,
|
||||
),
|
||||
const SizedBox(width: 16),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const Text(
|
||||
'Mencetak Struk',
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
const Text(
|
||||
'Mohon tunggu...',
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
color: Colors.white70,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
LinearProgressIndicator(
|
||||
backgroundColor: Colors.white30,
|
||||
color: Colors.white,
|
||||
minHeight: 6,
|
||||
value: null,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
icon: const Icon(Icons.close, color: Colors.white70),
|
||||
onPressed: widget.onDismiss,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,7 +1,5 @@
|
|||
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 {
|
||||
|
@ -19,10 +17,6 @@ class _StoreInfoConfigDialogState extends State<StoreInfoConfigDialog> {
|
|||
final TextEditingController _storeAddressController = TextEditingController();
|
||||
final TextEditingController _adminNameController = TextEditingController();
|
||||
final TextEditingController _adminPhoneController = TextEditingController();
|
||||
|
||||
// Variabel untuk logo
|
||||
String? _logoPath;
|
||||
final ImagePicker _picker = ImagePicker();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
|
@ -40,7 +34,6 @@ 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'); // Load logo path
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -53,12 +46,6 @@ 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);
|
||||
// Save logo path
|
||||
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
|
||||
|
@ -66,17 +53,6 @@ class _StoreInfoConfigDialogState extends State<StoreInfoConfigDialog> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Memilih logo dari galeri
|
||||
Future<void> _pickImage() async {
|
||||
final XFile? image = await _picker.pickImage(source: ImageSource.gallery);
|
||||
|
||||
if (image != null && mounted) {
|
||||
setState(() {
|
||||
_logoPath = image.path;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_storeNameController.dispose();
|
||||
|
@ -96,28 +72,6 @@ class _StoreInfoConfigDialogState extends State<StoreInfoConfigDialog> {
|
|||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
// Display selected logo or a placeholder
|
||||
GestureDetector(
|
||||
onTap: _pickImage,
|
||||
child: Container(
|
||||
height: 100,
|
||||
width: 100,
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(color: Colors.grey),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: _logoPath != null
|
||||
? ClipRRect(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
child: Image.file(File(_logoPath!), fit: BoxFit.cover),
|
||||
)
|
||||
: const Icon(Icons.add_a_photo, size: 40, color: Colors.grey),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
const Text('Ketuk untuk memilih logo toko', style: TextStyle(fontSize: 12)),
|
||||
const SizedBox(height: 16),
|
||||
|
||||
TextFormField(
|
||||
controller: _storeNameController,
|
||||
decoration: const InputDecoration(
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'dart:io';
|
||||
import 'package:intl/intl.dart';
|
||||
|
||||
/// Widget untuk menampilkan informasi toko dan admin
|
||||
|
@ -20,7 +19,6 @@ class _StoreInfoWidgetState extends State<StoreInfoWidget> {
|
|||
String storeAddress = 'Jl. Merdeka No. 123';
|
||||
String adminName = 'Budi Santoso';
|
||||
String adminPhone = '08123456789';
|
||||
String? _logoPath; // Path to the store logo
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
|
@ -37,7 +35,6 @@ class _StoreInfoWidgetState extends State<StoreInfoWidget> {
|
|||
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'); // Load logo path
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -61,17 +58,6 @@ class _StoreInfoWidgetState extends State<StoreInfoWidget> {
|
|||
color: Colors.white,
|
||||
child: Column(
|
||||
children: [
|
||||
// Display store logo if available
|
||||
if (_logoPath != null && _logoPath!.isNotEmpty)
|
||||
Container(
|
||||
margin: const EdgeInsets.only(bottom: 8.0),
|
||||
child: Image.file(
|
||||
File(_logoPath!),
|
||||
height: 60,
|
||||
width: 60,
|
||||
fit: BoxFit.contain,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
storeName,
|
||||
style: courierPrime.copyWith(
|
||||
|
|
Loading…
Reference in New Issue