cashumit/lib/widgets/store_info_widget.dart

159 lines
5.3 KiB
Dart

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 toko.
/// Baris tanggal dapat di-tap untuk mengatur tanggal transaksi.
class StoreInfoWidget extends StatefulWidget {
final VoidCallback onTap; // Buka dialog konfigurasi toko
final DateTime transactionDate;
final VoidCallback onChangeDate; // Buka date+time picker
const StoreInfoWidget({
super.key,
required this.onTap,
required this.transactionDate,
required this.onChangeDate,
});
@override
State<StoreInfoWidget> createState() => _StoreInfoWidgetState();
}
class _StoreInfoWidgetState extends State<StoreInfoWidget> {
String storeName = 'TOKO SEMBAKO MURAH';
String storeAddress = 'Jl. Merdeka No. 123';
String adminName = 'Budi Santoso';
String adminPhone = '08123456789';
String? logoPath;
// Cache style agar tidak dibuat ulang tiap rebuild (perbaikan performa).
static final TextStyle _courierPrime = () {
try {
return GoogleFonts.courierPrime(
textStyle: const TextStyle(fontSize: 14, height: 1.2),
);
} catch (_) {
return const TextStyle(
fontFamily: 'CourierPrime, Courier, monospace',
fontSize: 14,
height: 1.2,
);
}
}();
@override
void initState() {
super.initState();
_loadStoreInfo();
}
/// Memuat informasi toko dari shared preferences (sekali di initState,
/// bukan di build, untuk menghindari rebuild loop).
Future<void> _loadStoreInfo() async {
final prefs = await SharedPreferences.getInstance();
if (!mounted) return;
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');
});
}
/// Refresh info toko (dipanggil saat kembali dari dialog konfigurasi).
void refresh() {
_loadStoreInfo();
}
@override
Widget build(BuildContext context) {
final formattedDate =
DateFormat('dd/MM/yyyy HH:mm').format(widget.transactionDate);
return GestureDetector(
onTap: widget.onTap,
child: Container(
width: double.infinity,
padding: const EdgeInsets.all(8.0),
color: Colors.white,
child: Column(
children: [
// 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,
cacheWidth:
160, // Resolusi render lebih kecil (perbaikan performa)
errorBuilder: (context, error, stackTrace) {
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(
fontSize: 16,
fontWeight: FontWeight.bold,
),
textAlign: TextAlign.center,
),
const SizedBox(height: 4),
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),
const SizedBox(height: 4),
// Baris tanggal: tappable untuk ubah tanggal transaksi
GestureDetector(
onTap: widget.onChangeDate,
child: Container(
padding:
const EdgeInsets.symmetric(horizontal: 8, vertical: 2),
decoration: BoxDecoration(
border: Border.all(color: Colors.grey[300]!),
borderRadius: BorderRadius.circular(4),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
const Icon(Icons.calendar_today, size: 12),
const SizedBox(width: 4),
Text(
'Tanggal: $formattedDate',
style: _courierPrime.copyWith(
decoration: TextDecoration.underline,
decorationStyle: TextDecorationStyle.dotted,
),
textAlign: TextAlign.center,
),
const Icon(Icons.edit, size: 12, color: Colors.grey),
],
),
),
),
],
),
),
);
}
}