fix final3
This commit is contained in:
parent
c92c80a7c6
commit
1a34474c37
|
|
@ -36,6 +36,10 @@ class _DashboardScreenState extends State<DashboardScreen> with RouteAware {
|
||||||
_controller.loadDashboard(showLoading: false);
|
_controller.loadDashboard(showLoading: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> _refreshDashboard() {
|
||||||
|
return _controller.loadDashboard(showLoading: false);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final topPadding = MediaQuery.of(context).padding.top;
|
final topPadding = MediaQuery.of(context).padding.top;
|
||||||
|
|
@ -69,6 +73,25 @@ class _DashboardScreenState extends State<DashboardScreen> with RouteAware {
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
children: [
|
children: [
|
||||||
|
Container(
|
||||||
|
width: 40,
|
||||||
|
height: 40,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white.withValues(alpha: 0.3),
|
||||||
|
borderRadius: BorderRadius.circular(10),
|
||||||
|
),
|
||||||
|
child: IconButton(
|
||||||
|
tooltip: 'Refresh',
|
||||||
|
icon: const Icon(
|
||||||
|
Icons.refresh,
|
||||||
|
color: Colors.white,
|
||||||
|
size: 20,
|
||||||
|
),
|
||||||
|
onPressed: _refreshDashboard,
|
||||||
|
padding: EdgeInsets.zero,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 10),
|
||||||
Stack(
|
Stack(
|
||||||
children: [
|
children: [
|
||||||
Container(
|
Container(
|
||||||
|
|
@ -188,7 +211,11 @@ class _DashboardScreenState extends State<DashboardScreen> with RouteAware {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
body: SingleChildScrollView(
|
body: RefreshIndicator(
|
||||||
|
onRefresh: _refreshDashboard,
|
||||||
|
color: AppColors.primaryBrown,
|
||||||
|
child: SingleChildScrollView(
|
||||||
|
physics: const AlwaysScrollableScrollPhysics(),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
Padding(
|
Padding(
|
||||||
|
|
@ -208,10 +235,12 @@ class _DashboardScreenState extends State<DashboardScreen> with RouteAware {
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment:
|
||||||
|
MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment:
|
||||||
|
CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
'Penggunaan Bahan',
|
'Penggunaan Bahan',
|
||||||
|
|
@ -318,7 +347,8 @@ class _DashboardScreenState extends State<DashboardScreen> with RouteAware {
|
||||||
style: AppTextStyles.bodySmall
|
style: AppTextStyles.bodySmall
|
||||||
.copyWith(
|
.copyWith(
|
||||||
color:
|
color:
|
||||||
AppColors.textTertiary,
|
AppColors
|
||||||
|
.textTertiary,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
@ -357,7 +387,9 @@ class _DashboardScreenState extends State<DashboardScreen> with RouteAware {
|
||||||
Expanded(
|
Expanded(
|
||||||
child: ElevatedButton.icon(
|
child: ElevatedButton.icon(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.of(context).pushNamed('/prediction');
|
Navigator.of(
|
||||||
|
context,
|
||||||
|
).pushNamed('/prediction');
|
||||||
},
|
},
|
||||||
icon: const Icon(Icons.trending_up, size: 20),
|
icon: const Icon(Icons.trending_up, size: 20),
|
||||||
label: const Text(
|
label: const Text(
|
||||||
|
|
@ -384,7 +416,9 @@ class _DashboardScreenState extends State<DashboardScreen> with RouteAware {
|
||||||
Expanded(
|
Expanded(
|
||||||
child: ElevatedButton.icon(
|
child: ElevatedButton.icon(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.of(context).pushNamed('/transaction');
|
Navigator.of(
|
||||||
|
context,
|
||||||
|
).pushNamed('/transaction');
|
||||||
},
|
},
|
||||||
icon: const Icon(Icons.check_circle, size: 20),
|
icon: const Icon(Icons.check_circle, size: 20),
|
||||||
label: const Text(
|
label: const Text(
|
||||||
|
|
@ -416,6 +450,7 @@ class _DashboardScreenState extends State<DashboardScreen> with RouteAware {
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
bottomNavigationBar: BottomNavigationBar(
|
bottomNavigationBar: BottomNavigationBar(
|
||||||
currentIndex: _controller.selectedIndex,
|
currentIndex: _controller.selectedIndex,
|
||||||
onTap: (index) {
|
onTap: (index) {
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,10 @@ class _PredictionScreenState extends State<PredictionScreen> {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(error)));
|
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(error)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> _refreshRecipes() {
|
||||||
|
return _loadRecipes();
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> _submitProduction() async {
|
Future<void> _submitProduction() async {
|
||||||
if (_controller.isSubmitting) return;
|
if (_controller.isSubmitting) return;
|
||||||
final result = await _controller.submitProduction();
|
final result = await _controller.submitProduction();
|
||||||
|
|
@ -203,6 +207,24 @@ class _PredictionScreenState extends State<PredictionScreen> {
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
Container(
|
||||||
|
width: 40,
|
||||||
|
height: 40,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white.withOpacity(0.3),
|
||||||
|
borderRadius: BorderRadius.circular(10),
|
||||||
|
),
|
||||||
|
child: IconButton(
|
||||||
|
tooltip: 'Refresh',
|
||||||
|
icon: const Icon(
|
||||||
|
Icons.refresh,
|
||||||
|
color: Colors.white,
|
||||||
|
size: 20,
|
||||||
|
),
|
||||||
|
onPressed: _refreshRecipes,
|
||||||
|
padding: EdgeInsets.zero,
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 12),
|
const SizedBox(height: 12),
|
||||||
|
|
@ -267,7 +289,10 @@ class _PredictionScreenState extends State<PredictionScreen> {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
body:
|
body: RefreshIndicator(
|
||||||
|
onRefresh: _refreshRecipes,
|
||||||
|
color: const Color(0xFFA89080),
|
||||||
|
child:
|
||||||
_controller.isLoading
|
_controller.isLoading
|
||||||
? Center(
|
? Center(
|
||||||
child: Column(
|
child: Column(
|
||||||
|
|
@ -300,6 +325,7 @@ class _PredictionScreenState extends State<PredictionScreen> {
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
: SingleChildScrollView(
|
: SingleChildScrollView(
|
||||||
|
physics: const AlwaysScrollableScrollPhysics(),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
Padding(
|
Padding(
|
||||||
|
|
@ -321,7 +347,8 @@ class _PredictionScreenState extends State<PredictionScreen> {
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment:
|
||||||
|
CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
const Text(
|
const Text(
|
||||||
'Rencana Produksi',
|
'Rencana Produksi',
|
||||||
|
|
@ -351,13 +378,13 @@ class _PredictionScreenState extends State<PredictionScreen> {
|
||||||
color: const Color(0xFFE5E7EB),
|
color: const Color(0xFFE5E7EB),
|
||||||
width: 1,
|
width: 1,
|
||||||
),
|
),
|
||||||
borderRadius: BorderRadius.circular(
|
borderRadius:
|
||||||
10,
|
BorderRadius.circular(10),
|
||||||
),
|
|
||||||
),
|
),
|
||||||
child: DropdownButtonHideUnderline(
|
child: DropdownButtonHideUnderline(
|
||||||
child: DropdownButton<String>(
|
child: DropdownButton<String>(
|
||||||
value: _controller.selectedRecipe,
|
value:
|
||||||
|
_controller.selectedRecipe,
|
||||||
hint: const Padding(
|
hint: const Padding(
|
||||||
padding: EdgeInsets.symmetric(
|
padding: EdgeInsets.symmetric(
|
||||||
horizontal: 12,
|
horizontal: 12,
|
||||||
|
|
@ -406,7 +433,8 @@ class _PredictionScreenState extends State<PredictionScreen> {
|
||||||
)
|
)
|
||||||
.toList(),
|
.toList(),
|
||||||
onChanged:
|
onChanged:
|
||||||
_controller.setSelectedRecipe,
|
_controller
|
||||||
|
.setSelectedRecipe,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
@ -430,7 +458,8 @@ class _PredictionScreenState extends State<PredictionScreen> {
|
||||||
controller: _productionController,
|
controller: _productionController,
|
||||||
keyboardType: TextInputType.number,
|
keyboardType: TextInputType.number,
|
||||||
onChanged:
|
onChanged:
|
||||||
_controller.setProductionQuantity,
|
_controller
|
||||||
|
.setProductionQuantity,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
hintText: '0',
|
hintText: '0',
|
||||||
hintStyle: const TextStyle(
|
hintStyle: const TextStyle(
|
||||||
|
|
@ -515,7 +544,8 @@ class _PredictionScreenState extends State<PredictionScreen> {
|
||||||
color: Color(0xFFE5E7EB),
|
color: Color(0xFFE5E7EB),
|
||||||
width: 1,
|
width: 1,
|
||||||
),
|
),
|
||||||
padding: const EdgeInsets.symmetric(
|
padding:
|
||||||
|
const EdgeInsets.symmetric(
|
||||||
horizontal: 20,
|
horizontal: 20,
|
||||||
),
|
),
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
|
|
@ -651,7 +681,9 @@ class _PredictionScreenState extends State<PredictionScreen> {
|
||||||
borderRadius: BorderRadius.circular(12),
|
borderRadius: BorderRadius.circular(12),
|
||||||
boxShadow: [
|
boxShadow: [
|
||||||
BoxShadow(
|
BoxShadow(
|
||||||
color: Colors.black.withOpacity(0.05),
|
color: Colors.black.withOpacity(
|
||||||
|
0.05,
|
||||||
|
),
|
||||||
blurRadius: 10,
|
blurRadius: 10,
|
||||||
offset: const Offset(0, 2),
|
offset: const Offset(0, 2),
|
||||||
),
|
),
|
||||||
|
|
@ -672,7 +704,9 @@ class _PredictionScreenState extends State<PredictionScreen> {
|
||||||
borderRadius: BorderRadius.circular(12),
|
borderRadius: BorderRadius.circular(12),
|
||||||
boxShadow: [
|
boxShadow: [
|
||||||
BoxShadow(
|
BoxShadow(
|
||||||
color: Colors.black.withOpacity(0.05),
|
color: Colors.black.withOpacity(
|
||||||
|
0.05,
|
||||||
|
),
|
||||||
blurRadius: 10,
|
blurRadius: 10,
|
||||||
offset: const Offset(0, 2),
|
offset: const Offset(0, 2),
|
||||||
),
|
),
|
||||||
|
|
@ -686,14 +720,16 @@ class _PredictionScreenState extends State<PredictionScreen> {
|
||||||
final isLast =
|
final isLast =
|
||||||
entry.key ==
|
entry.key ==
|
||||||
displayIngredients.length - 1;
|
displayIngredients.length - 1;
|
||||||
final ingredient = entry.value.key;
|
final ingredient =
|
||||||
|
entry.value.key;
|
||||||
final details = entry.value.value;
|
final details = entry.value.value;
|
||||||
final isSelected = _controller
|
final isSelected = _controller
|
||||||
.isIngredientSelected(
|
.isIngredientSelected(
|
||||||
ingredient,
|
ingredient,
|
||||||
);
|
);
|
||||||
final unit =
|
final unit =
|
||||||
(details['unit'] as String?) ??
|
(details['unit']
|
||||||
|
as String?) ??
|
||||||
_controller.getIngredientUnit(
|
_controller.getIngredientUnit(
|
||||||
ingredient,
|
ingredient,
|
||||||
);
|
);
|
||||||
|
|
@ -721,7 +757,8 @@ class _PredictionScreenState extends State<PredictionScreen> {
|
||||||
ingredient,
|
ingredient,
|
||||||
);
|
);
|
||||||
final isSufficient =
|
final isSufficient =
|
||||||
stockKg >= requiredInStockUnit;
|
stockKg >=
|
||||||
|
requiredInStockUnit;
|
||||||
final statusColor =
|
final statusColor =
|
||||||
isSelected
|
isSelected
|
||||||
? (isSufficient
|
? (isSufficient
|
||||||
|
|
@ -742,7 +779,8 @@ class _PredictionScreenState extends State<PredictionScreen> {
|
||||||
return Column(
|
return Column(
|
||||||
children: [
|
children: [
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.all(
|
padding:
|
||||||
|
const EdgeInsets.all(
|
||||||
14,
|
14,
|
||||||
),
|
),
|
||||||
child: Column(
|
child: Column(
|
||||||
|
|
@ -754,7 +792,9 @@ class _PredictionScreenState extends State<PredictionScreen> {
|
||||||
children: [
|
children: [
|
||||||
Checkbox(
|
Checkbox(
|
||||||
value: isSelected,
|
value: isSelected,
|
||||||
onChanged: (value) {
|
onChanged: (
|
||||||
|
value,
|
||||||
|
) {
|
||||||
_controller
|
_controller
|
||||||
.setIngredientSelection(
|
.setIngredientSelection(
|
||||||
ingredient,
|
ingredient,
|
||||||
|
|
@ -939,7 +979,9 @@ class _PredictionScreenState extends State<PredictionScreen> {
|
||||||
borderRadius: BorderRadius.circular(12),
|
borderRadius: BorderRadius.circular(12),
|
||||||
boxShadow: [
|
boxShadow: [
|
||||||
BoxShadow(
|
BoxShadow(
|
||||||
color: Colors.black.withOpacity(0.05),
|
color: Colors.black.withOpacity(
|
||||||
|
0.05,
|
||||||
|
),
|
||||||
blurRadius: 10,
|
blurRadius: 10,
|
||||||
offset: const Offset(0, 2),
|
offset: const Offset(0, 2),
|
||||||
),
|
),
|
||||||
|
|
@ -984,7 +1026,9 @@ class _PredictionScreenState extends State<PredictionScreen> {
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight:
|
fontWeight:
|
||||||
FontWeight.w700,
|
FontWeight.w700,
|
||||||
color: Color(0xFFDC2626),
|
color: Color(
|
||||||
|
0xFFDC2626,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
@ -1014,7 +1058,9 @@ class _PredictionScreenState extends State<PredictionScreen> {
|
||||||
>(Colors.white),
|
>(Colors.white),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
: const Icon(Icons.check_circle),
|
: const Icon(
|
||||||
|
Icons.check_circle,
|
||||||
|
),
|
||||||
label: Text(
|
label: Text(
|
||||||
_controller.isSubmitting
|
_controller.isSubmitting
|
||||||
? 'Memproses...'
|
? 'Memproses...'
|
||||||
|
|
@ -1184,6 +1230,7 @@ class _PredictionScreenState extends State<PredictionScreen> {
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
bottomNavigationBar: BottomNavigationBar(
|
bottomNavigationBar: BottomNavigationBar(
|
||||||
currentIndex: 3,
|
currentIndex: 3,
|
||||||
type: BottomNavigationBarType.fixed,
|
type: BottomNavigationBarType.fixed,
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,10 @@ class _ProductListScreenState extends State<ProductListScreen> with RouteAware {
|
||||||
_controller.loadProducts();
|
_controller.loadProducts();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> _refreshProducts() {
|
||||||
|
return _controller.loadProducts();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return AnimatedBuilder(
|
return AnimatedBuilder(
|
||||||
|
|
@ -111,6 +115,25 @@ class _ProductListScreenState extends State<ProductListScreen> with RouteAware {
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
const Spacer(),
|
||||||
|
Container(
|
||||||
|
width: 40,
|
||||||
|
height: 40,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white.withValues(alpha: 0.3),
|
||||||
|
borderRadius: BorderRadius.circular(10),
|
||||||
|
),
|
||||||
|
child: IconButton(
|
||||||
|
tooltip: 'Refresh',
|
||||||
|
icon: const Icon(
|
||||||
|
Icons.refresh,
|
||||||
|
color: Colors.white,
|
||||||
|
size: 20,
|
||||||
|
),
|
||||||
|
onPressed: _refreshProducts,
|
||||||
|
padding: EdgeInsets.zero,
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
@ -155,7 +178,7 @@ class _ProductListScreenState extends State<ProductListScreen> with RouteAware {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
body: RefreshIndicator(
|
body: RefreshIndicator(
|
||||||
onRefresh: _controller.loadProducts,
|
onRefresh: _refreshProducts,
|
||||||
color: AppColors.primaryBrown,
|
color: AppColors.primaryBrown,
|
||||||
child:
|
child:
|
||||||
_controller.isLoading
|
_controller.isLoading
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,10 @@ class _ReportScreenState extends State<ReportScreen> {
|
||||||
_controller.startAutoRefresh();
|
_controller.startAutoRefresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> _refreshReports() {
|
||||||
|
return _controller.loadReports();
|
||||||
|
}
|
||||||
|
|
||||||
double _sectionMaxHeight() {
|
double _sectionMaxHeight() {
|
||||||
final height = MediaQuery.of(context).size.height * 0.35;
|
final height = MediaQuery.of(context).size.height * 0.35;
|
||||||
if (height < 220) return 220;
|
if (height < 220) return 220;
|
||||||
|
|
@ -82,6 +86,13 @@ class _ReportScreenState extends State<ReportScreen> {
|
||||||
'Laporan & Analitik',
|
'Laporan & Analitik',
|
||||||
style: AppTextStyles.headlineLarge.copyWith(color: Colors.white),
|
style: AppTextStyles.headlineLarge.copyWith(color: Colors.white),
|
||||||
),
|
),
|
||||||
|
actions: [
|
||||||
|
IconButton(
|
||||||
|
tooltip: 'Refresh',
|
||||||
|
icon: const Icon(Icons.refresh, color: Colors.white),
|
||||||
|
onPressed: _refreshReports,
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
body: AnimatedBuilder(
|
body: AnimatedBuilder(
|
||||||
animation: _controller,
|
animation: _controller,
|
||||||
|
|
@ -98,7 +109,7 @@ class _ReportScreenState extends State<ReportScreen> {
|
||||||
final List<double> demandTrend = _controller.demandTrend;
|
final List<double> demandTrend = _controller.demandTrend;
|
||||||
|
|
||||||
return RefreshIndicator(
|
return RefreshIndicator(
|
||||||
onRefresh: () => _controller.loadReports(),
|
onRefresh: _refreshReports,
|
||||||
child: SingleChildScrollView(
|
child: SingleChildScrollView(
|
||||||
physics: const AlwaysScrollableScrollPhysics(),
|
physics: const AlwaysScrollableScrollPhysics(),
|
||||||
padding: const EdgeInsets.all(16),
|
padding: const EdgeInsets.all(16),
|
||||||
|
|
|
||||||
|
|
@ -125,8 +125,19 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
||||||
'Pengaturan',
|
'Pengaturan',
|
||||||
style: AppTextStyles.headlineLarge.copyWith(color: Colors.white),
|
style: AppTextStyles.headlineLarge.copyWith(color: Colors.white),
|
||||||
),
|
),
|
||||||
|
actions: [
|
||||||
|
IconButton(
|
||||||
|
tooltip: 'Refresh',
|
||||||
|
icon: const Icon(Icons.refresh, color: Colors.white),
|
||||||
|
onPressed: _loadAccount,
|
||||||
),
|
),
|
||||||
body: SingleChildScrollView(
|
],
|
||||||
|
),
|
||||||
|
body: RefreshIndicator(
|
||||||
|
onRefresh: _loadAccount,
|
||||||
|
color: AppColors.primaryBrown,
|
||||||
|
child: SingleChildScrollView(
|
||||||
|
physics: const AlwaysScrollableScrollPhysics(),
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(16.0),
|
padding: const EdgeInsets.all(16.0),
|
||||||
child: Column(
|
child: Column(
|
||||||
|
|
@ -167,6 +178,7 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
bottomNavigationBar: BottomNavigationBar(
|
bottomNavigationBar: BottomNavigationBar(
|
||||||
currentIndex: _controller.selectedIndex,
|
currentIndex: _controller.selectedIndex,
|
||||||
onTap: (index) {
|
onTap: (index) {
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,20 @@ class _TransactionScreenState extends State<TransactionScreen> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> _refreshProducts() async {
|
||||||
|
try {
|
||||||
|
await _controller.loadProducts();
|
||||||
|
} catch (_) {
|
||||||
|
if (!mounted) return;
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
SnackBar(
|
||||||
|
content: const Text('Gagal memuat data produk'),
|
||||||
|
backgroundColor: AppColors.statusError,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> _submitAllTransactions() async {
|
Future<void> _submitAllTransactions() async {
|
||||||
final result = await _controller.submitAllTransactions();
|
final result = await _controller.submitAllTransactions();
|
||||||
|
|
||||||
|
|
@ -504,8 +518,19 @@ class _TransactionScreenState extends State<TransactionScreen> {
|
||||||
icon: const Icon(Icons.arrow_back, color: Colors.white),
|
icon: const Icon(Icons.arrow_back, color: Colors.white),
|
||||||
onPressed: () => Navigator.pop(context),
|
onPressed: () => Navigator.pop(context),
|
||||||
),
|
),
|
||||||
|
actions: [
|
||||||
|
IconButton(
|
||||||
|
tooltip: 'Refresh',
|
||||||
|
icon: const Icon(Icons.refresh, color: Colors.white),
|
||||||
|
onPressed: _refreshProducts,
|
||||||
),
|
),
|
||||||
body: SingleChildScrollView(
|
],
|
||||||
|
),
|
||||||
|
body: RefreshIndicator(
|
||||||
|
onRefresh: _refreshProducts,
|
||||||
|
color: AppColors.primaryBrown,
|
||||||
|
child: SingleChildScrollView(
|
||||||
|
physics: const AlwaysScrollableScrollPhysics(),
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(16.0),
|
padding: const EdgeInsets.all(16.0),
|
||||||
child: Column(
|
child: Column(
|
||||||
|
|
@ -585,7 +610,9 @@ class _TransactionScreenState extends State<TransactionScreen> {
|
||||||
label: const Text('Tambah ke Keranjang'),
|
label: const Text('Tambah ke Keranjang'),
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: AppColors.primaryBrown,
|
backgroundColor: AppColors.primaryBrown,
|
||||||
padding: const EdgeInsets.symmetric(vertical: 12),
|
padding: const EdgeInsets.symmetric(
|
||||||
|
vertical: 12,
|
||||||
|
),
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.circular(10),
|
borderRadius: BorderRadius.circular(10),
|
||||||
),
|
),
|
||||||
|
|
@ -600,8 +627,12 @@ class _TransactionScreenState extends State<TransactionScreen> {
|
||||||
icon: const Icon(Icons.add_circle_outline),
|
icon: const Icon(Icons.add_circle_outline),
|
||||||
label: const Text('Tambah Produk Baru'),
|
label: const Text('Tambah Produk Baru'),
|
||||||
style: OutlinedButton.styleFrom(
|
style: OutlinedButton.styleFrom(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 12),
|
padding: const EdgeInsets.symmetric(
|
||||||
side: BorderSide(color: AppColors.secondaryBlue),
|
vertical: 12,
|
||||||
|
),
|
||||||
|
side: BorderSide(
|
||||||
|
color: AppColors.secondaryBlue,
|
||||||
|
),
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.circular(10),
|
borderRadius: BorderRadius.circular(10),
|
||||||
),
|
),
|
||||||
|
|
@ -657,7 +688,9 @@ class _TransactionScreenState extends State<TransactionScreen> {
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: AppColors.bgLight,
|
color: AppColors.bgLight,
|
||||||
borderRadius: BorderRadius.circular(10),
|
borderRadius: BorderRadius.circular(10),
|
||||||
border: Border.all(color: AppColors.grey300),
|
border: Border.all(
|
||||||
|
color: AppColors.grey300,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
|
|
@ -672,16 +705,19 @@ class _TransactionScreenState extends State<TransactionScreen> {
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
item.productName,
|
item.productName,
|
||||||
style: AppTextStyles.labelLarge
|
style: AppTextStyles
|
||||||
|
.labelLarge
|
||||||
.copyWith(
|
.copyWith(
|
||||||
color:
|
color:
|
||||||
AppColors.textPrimary,
|
AppColors
|
||||||
|
.textPrimary,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 4),
|
const SizedBox(height: 4),
|
||||||
Text(
|
Text(
|
||||||
'Rp ${item.unitPrice} / unit',
|
'Rp ${item.unitPrice} / unit',
|
||||||
style: AppTextStyles.labelSmall
|
style: AppTextStyles
|
||||||
|
.labelSmall
|
||||||
.copyWith(
|
.copyWith(
|
||||||
color:
|
color:
|
||||||
AppColors
|
AppColors
|
||||||
|
|
@ -695,7 +731,8 @@ class _TransactionScreenState extends State<TransactionScreen> {
|
||||||
'Rp ${item.totalPrice}',
|
'Rp ${item.totalPrice}',
|
||||||
style: AppTextStyles.labelLarge
|
style: AppTextStyles.labelLarge
|
||||||
.copyWith(
|
.copyWith(
|
||||||
color: AppColors.statusSuccess,
|
color:
|
||||||
|
AppColors.statusSuccess,
|
||||||
fontWeight: FontWeight.w700,
|
fontWeight: FontWeight.w700,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
@ -719,9 +756,12 @@ class _TransactionScreenState extends State<TransactionScreen> {
|
||||||
width: 32,
|
width: 32,
|
||||||
height: 32,
|
height: 32,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: AppColors.primaryBrown,
|
color:
|
||||||
|
AppColors.primaryBrown,
|
||||||
borderRadius:
|
borderRadius:
|
||||||
BorderRadius.circular(6),
|
BorderRadius.circular(
|
||||||
|
6,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
child: const Icon(
|
child: const Icon(
|
||||||
Icons.remove,
|
Icons.remove,
|
||||||
|
|
@ -737,7 +777,8 @@ class _TransactionScreenState extends State<TransactionScreen> {
|
||||||
.copyWith(
|
.copyWith(
|
||||||
color:
|
color:
|
||||||
AppColors.textPrimary,
|
AppColors.textPrimary,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight:
|
||||||
|
FontWeight.w600,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 12),
|
const SizedBox(width: 12),
|
||||||
|
|
@ -752,9 +793,12 @@ class _TransactionScreenState extends State<TransactionScreen> {
|
||||||
width: 32,
|
width: 32,
|
||||||
height: 32,
|
height: 32,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: AppColors.primaryBrown,
|
color:
|
||||||
|
AppColors.primaryBrown,
|
||||||
borderRadius:
|
borderRadius:
|
||||||
BorderRadius.circular(6),
|
BorderRadius.circular(
|
||||||
|
6,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
child: const Icon(
|
child: const Icon(
|
||||||
Icons.add,
|
Icons.add,
|
||||||
|
|
@ -767,9 +811,8 @@ class _TransactionScreenState extends State<TransactionScreen> {
|
||||||
),
|
),
|
||||||
GestureDetector(
|
GestureDetector(
|
||||||
onTap:
|
onTap:
|
||||||
() => _controller.removeFromCart(
|
() => _controller
|
||||||
index,
|
.removeFromCart(index),
|
||||||
),
|
|
||||||
child: Container(
|
child: Container(
|
||||||
width: 32,
|
width: 32,
|
||||||
height: 32,
|
height: 32,
|
||||||
|
|
@ -827,7 +870,8 @@ class _TransactionScreenState extends State<TransactionScreen> {
|
||||||
final picked = await showDatePicker(
|
final picked = await showDatePicker(
|
||||||
context: context,
|
context: context,
|
||||||
initialDate:
|
initialDate:
|
||||||
_controller.selectedDate ?? DateTime.now(),
|
_controller.selectedDate ??
|
||||||
|
DateTime.now(),
|
||||||
firstDate: DateTime(2020),
|
firstDate: DateTime(2020),
|
||||||
lastDate: DateTime.now(),
|
lastDate: DateTime.now(),
|
||||||
);
|
);
|
||||||
|
|
@ -1001,6 +1045,7 @@ class _TransactionScreenState extends State<TransactionScreen> {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
bottomNavigationBar: BottomNavigationBar(
|
bottomNavigationBar: BottomNavigationBar(
|
||||||
currentIndex: _controller.selectedIndex,
|
currentIndex: _controller.selectedIndex,
|
||||||
onTap: (index) {
|
onTap: (index) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue