159 lines
5.3 KiB
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),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|