data sync overflow

This commit is contained in:
efrilm 2025-09-20 03:12:32 +07:00
parent f104390141
commit 04811015b6

View File

@ -1,15 +1,9 @@
// ========================================
// DATA SYNC PAGE - POST LOGIN SYNC
// lib/presentation/sync/pages/data_sync_page.dart
// ========================================
import 'dart:async'; import 'dart:async';
import 'package:enaklo_pos/core/extensions/build_context_ext.dart'; import 'package:enaklo_pos/core/extensions/build_context_ext.dart';
import 'package:enaklo_pos/presentation/home/pages/dashboard_page.dart'; import 'package:enaklo_pos/presentation/home/pages/dashboard_page.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import '../../../core/components/buttons.dart'; import '../../../core/components/buttons.dart';
import '../../../core/components/spaces.dart';
import '../../../core/constants/colors.dart'; import '../../../core/constants/colors.dart';
import '../bloc/data_sync_bloc.dart'; import '../bloc/data_sync_bloc.dart';
@ -54,6 +48,11 @@ class _DataSyncPageState extends State<DataSyncPage>
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final mediaQuery = MediaQuery.of(context);
final isLandscape = mediaQuery.orientation == Orientation.landscape;
final screenHeight = mediaQuery.size.height;
final screenWidth = mediaQuery.size.width;
return Scaffold( return Scaffold(
backgroundColor: Colors.grey.shade50, backgroundColor: Colors.grey.shade50,
body: SafeArea( body: SafeArea(
@ -77,71 +76,121 @@ class _DataSyncPageState extends State<DataSyncPage>
); );
}, },
builder: (context, state) { builder: (context, state) {
return Padding( if (isLandscape) {
padding: EdgeInsets.all(24), return _buildLandscapeLayout(state, screenWidth, screenHeight);
child: Column( } else {
children: [ return _buildPortraitLayout(state, screenHeight);
SpaceHeight(60), }
// Header
_buildHeader(),
SpaceHeight(60),
// Sync progress
Expanded(
child: state.when(
initial: () => _buildInitialState(),
syncing: (step, progress, message) =>
_buildSyncingState(step, progress, message),
completed: (stats) => _buildCompletedState(stats),
error: (message) => _buildErrorState(message),
),
),
SpaceHeight(40),
// Actions
_buildActions(state),
],
),
);
}, },
), ),
), ),
); );
} }
Widget _buildHeader() { // Portrait layout (original)
Widget _buildPortraitLayout(DataSyncState state, double screenHeight) {
return Padding(
padding: EdgeInsets.all(24),
child: Column(
children: [
SizedBox(height: screenHeight * 0.08), // Responsive spacing
// Header
_buildHeader(false),
SizedBox(height: screenHeight * 0.08),
// Sync progress
Expanded(
child: state.when(
initial: () => _buildInitialState(false),
syncing: (step, progress, message) =>
_buildSyncingState(step, progress, message, false),
completed: (stats) => _buildCompletedState(stats, false),
error: (message) => _buildErrorState(message, false),
),
),
SizedBox(height: 20),
// Actions
_buildActions(state),
],
),
);
}
// Landscape layout (side by side)
Widget _buildLandscapeLayout(
DataSyncState state, double screenWidth, double screenHeight) {
return Padding(
padding: EdgeInsets.symmetric(horizontal: 32, vertical: 16),
child: Row(
children: [
// Left side - Header and info
Expanded(
flex: 2,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
_buildHeader(true),
SizedBox(height: 20),
_buildActions(state),
],
),
),
SizedBox(width: 40),
// Right side - Sync progress
Expanded(
flex: 3,
child: Container(
height: screenHeight * 0.8,
child: state.when(
initial: () => _buildInitialState(true),
syncing: (step, progress, message) =>
_buildSyncingState(step, progress, message, true),
completed: (stats) => _buildCompletedState(stats, true),
error: (message) => _buildErrorState(message, true),
),
),
),
],
),
);
}
Widget _buildHeader(bool isLandscape) {
return Column( return Column(
children: [ children: [
Container( Container(
width: 80, width: isLandscape ? 60 : 80,
height: 80, height: isLandscape ? 60 : 80,
decoration: BoxDecoration( decoration: BoxDecoration(
color: AppColors.primary.withOpacity(0.1), color: AppColors.primary.withOpacity(0.1),
borderRadius: BorderRadius.circular(20), borderRadius: BorderRadius.circular(isLandscape ? 15 : 20),
), ),
child: Icon( child: Icon(
Icons.sync, Icons.sync,
size: 40, size: isLandscape ? 30 : 40,
color: AppColors.primary, color: AppColors.primary,
), ),
), ),
SpaceHeight(20), SizedBox(height: isLandscape ? 12 : 20),
Text( Text(
'Sinkronisasi Data', 'Sinkronisasi Data',
style: TextStyle( style: TextStyle(
fontSize: 24, fontSize: isLandscape ? 20 : 24,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: Colors.grey.shade800, color: Colors.grey.shade800,
), ),
), ),
SpaceHeight(8), SizedBox(height: isLandscape ? 4 : 8),
Text( Text(
'Mengunduh data terbaru ke perangkat', 'Mengunduh data terbaru ke perangkat',
style: TextStyle( style: TextStyle(
fontSize: 16, fontSize: isLandscape ? 14 : 16,
color: Colors.grey.shade600, color: Colors.grey.shade600,
), ),
textAlign: TextAlign.center, textAlign: TextAlign.center,
@ -150,117 +199,125 @@ class _DataSyncPageState extends State<DataSyncPage>
); );
} }
Widget _buildInitialState() { Widget _buildInitialState(bool isLandscape) {
return Column( return Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
Icon( Icon(
Icons.download_rounded, Icons.download_rounded,
size: 64, size: isLandscape ? 48 : 64,
color: Colors.grey.shade400, color: Colors.grey.shade400,
), ),
SpaceHeight(20), SizedBox(height: isLandscape ? 12 : 20),
Text( Text(
'Siap untuk sinkronisasi', 'Siap untuk sinkronisasi',
style: TextStyle( style: TextStyle(
fontSize: 18, fontSize: isLandscape ? 16 : 18,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
), ),
), ),
SpaceHeight(8), SizedBox(height: isLandscape ? 4 : 8),
Text( Text(
'Tekan tombol mulai untuk mengunduh data', 'Tekan tombol mulai untuk mengunduh data',
style: TextStyle( style: TextStyle(
fontSize: isLandscape ? 12 : 14,
color: Colors.grey.shade600, color: Colors.grey.shade600,
), ),
textAlign: TextAlign.center,
), ),
], ],
); );
} }
Widget _buildSyncingState(SyncStep step, double progress, String message) { Widget _buildSyncingState(
return Column( SyncStep step, double progress, String message, bool isLandscape) {
mainAxisAlignment: MainAxisAlignment.center, return SingleChildScrollView(
children: [ child: Column(
// Progress circle mainAxisAlignment: MainAxisAlignment.center,
Stack( children: [
alignment: Alignment.center, // Progress circle
children: [ Stack(
SizedBox( alignment: Alignment.center,
width: 120, children: [
height: 120, SizedBox(
child: AnimatedBuilder( width: isLandscape ? 100 : 120,
animation: _progressAnimation, height: isLandscape ? 100 : 120,
builder: (context, child) { child: AnimatedBuilder(
return CircularProgressIndicator(
value: _progressAnimation.value,
strokeWidth: 8,
backgroundColor: Colors.grey.shade200,
valueColor:
AlwaysStoppedAnimation<Color>(AppColors.primary),
);
},
),
),
Column(
children: [
Icon(
_getSyncIcon(step),
size: 32,
color: AppColors.primary,
),
SpaceHeight(4),
AnimatedBuilder(
animation: _progressAnimation, animation: _progressAnimation,
builder: (context, child) { builder: (context, child) {
return Text( return CircularProgressIndicator(
'${(_progressAnimation.value * 100).toInt()}%', value: _progressAnimation.value,
style: TextStyle( strokeWidth: isLandscape ? 6 : 8,
fontSize: 16, backgroundColor: Colors.grey.shade200,
fontWeight: FontWeight.bold, valueColor:
color: AppColors.primary, AlwaysStoppedAnimation<Color>(AppColors.primary),
),
); );
}, },
), ),
], ),
), Column(
], children: [
), Icon(
_getSyncIcon(step),
SpaceHeight(30), size: isLandscape ? 24 : 32,
color: AppColors.primary,
// Step indicator ),
_buildStepIndicator(step), SizedBox(height: 2),
AnimatedBuilder(
SpaceHeight(20), animation: _progressAnimation,
builder: (context, child) {
// Current message return Text(
Container( '${(_progressAnimation.value * 100).toInt()}%',
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12), style: TextStyle(
decoration: BoxDecoration( fontSize: isLandscape ? 14 : 16,
color: Colors.blue.shade50, fontWeight: FontWeight.bold,
borderRadius: BorderRadius.circular(8), color: AppColors.primary,
),
);
},
),
],
),
],
), ),
child: Text(
message, SizedBox(height: isLandscape ? 20 : 30),
style: TextStyle(
color: Colors.blue.shade700, // Step indicator
fontWeight: FontWeight.w500, _buildStepIndicator(step, isLandscape),
SizedBox(height: isLandscape ? 12 : 20),
// Current message
Container(
padding: EdgeInsets.symmetric(
horizontal: isLandscape ? 16 : 20,
vertical: isLandscape ? 8 : 12),
decoration: BoxDecoration(
color: Colors.blue.shade50,
borderRadius: BorderRadius.circular(8),
),
child: Text(
message,
style: TextStyle(
color: Colors.blue.shade700,
fontSize: isLandscape ? 12 : 14,
fontWeight: FontWeight.w500,
),
textAlign: TextAlign.center,
), ),
textAlign: TextAlign.center,
), ),
),
SpaceHeight(20), SizedBox(height: isLandscape ? 12 : 20),
// Sync details // Sync details
_buildSyncDetails(step, progress), _buildSyncDetails(step, progress, isLandscape),
], ],
),
); );
} }
Widget _buildStepIndicator(SyncStep currentStep) { Widget _buildStepIndicator(SyncStep currentStep, bool isLandscape) {
final steps = [ final steps = [
('Produk', SyncStep.products, Icons.inventory_2), ('Produk', SyncStep.products, Icons.inventory_2),
('Kategori', SyncStep.categories, Icons.category), ('Kategori', SyncStep.categories, Icons.category),
@ -268,59 +325,111 @@ class _DataSyncPageState extends State<DataSyncPage>
('Selesai', SyncStep.completed, Icons.check_circle), ('Selesai', SyncStep.completed, Icons.check_circle),
]; ];
return Row( if (isLandscape) {
mainAxisAlignment: MainAxisAlignment.center, // Vertical layout for landscape
children: steps.map((stepData) { return Column(
final (label, step, icon) = stepData; children: steps.map((stepData) {
final isActive = step == currentStep; final (label, step, icon) = stepData;
final isCompleted = step.index < currentStep.index; final isActive = step == currentStep;
final isCompleted = step.index < currentStep.index;
return Container( return Container(
margin: EdgeInsets.symmetric(horizontal: 4), margin: EdgeInsets.symmetric(vertical: 2),
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 4), padding: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
decoration: BoxDecoration( decoration: BoxDecoration(
color: isActive color: isActive
? AppColors.primary.withOpacity(0.1) ? AppColors.primary.withOpacity(0.1)
: isCompleted : isCompleted
? Colors.green.shade50 ? Colors.green.shade50
: Colors.grey.shade100, : Colors.grey.shade100,
borderRadius: BorderRadius.circular(6), borderRadius: BorderRadius.circular(6),
), ),
child: Row( child: Row(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
Icon( Icon(
isCompleted ? Icons.check : icon, isCompleted ? Icons.check : icon,
size: 14, size: 12,
color: isActive
? AppColors.primary
: isCompleted
? Colors.green.shade600
: Colors.grey.shade500,
),
SizedBox(width: 4),
Text(
label,
style: TextStyle(
fontSize: 11,
fontWeight: isActive ? FontWeight.w600 : FontWeight.normal,
color: isActive color: isActive
? AppColors.primary ? AppColors.primary
: isCompleted : isCompleted
? Colors.green.shade600 ? Colors.green.shade600
: Colors.grey.shade600, : Colors.grey.shade500,
), ),
), SizedBox(width: 4),
], Text(
), label,
); style: TextStyle(
}).toList(), fontSize: 10,
); fontWeight: isActive ? FontWeight.w600 : FontWeight.normal,
color: isActive
? AppColors.primary
: isCompleted
? Colors.green.shade600
: Colors.grey.shade600,
),
),
],
),
);
}).toList(),
);
} else {
// Horizontal layout for portrait
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: steps.map((stepData) {
final (label, step, icon) = stepData;
final isActive = step == currentStep;
final isCompleted = step.index < currentStep.index;
return Container(
margin: EdgeInsets.symmetric(horizontal: 4),
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
decoration: BoxDecoration(
color: isActive
? AppColors.primary.withOpacity(0.1)
: isCompleted
? Colors.green.shade50
: Colors.grey.shade100,
borderRadius: BorderRadius.circular(6),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(
isCompleted ? Icons.check : icon,
size: 14,
color: isActive
? AppColors.primary
: isCompleted
? Colors.green.shade600
: Colors.grey.shade500,
),
SizedBox(width: 4),
Text(
label,
style: TextStyle(
fontSize: 11,
fontWeight: isActive ? FontWeight.w600 : FontWeight.normal,
color: isActive
? AppColors.primary
: isCompleted
? Colors.green.shade600
: Colors.grey.shade600,
),
),
],
),
);
}).toList(),
);
}
} }
Widget _buildSyncDetails(SyncStep step, double progress) { Widget _buildSyncDetails(SyncStep step, double progress, bool isLandscape) {
return Container( return Container(
padding: EdgeInsets.all(16), padding: EdgeInsets.all(isLandscape ? 12 : 16),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, color: Colors.white,
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(8),
@ -334,6 +443,7 @@ class _DataSyncPageState extends State<DataSyncPage>
Text( Text(
'Status:', 'Status:',
style: TextStyle( style: TextStyle(
fontSize: isLandscape ? 12 : 14,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
color: Colors.grey.shade700, color: Colors.grey.shade700,
), ),
@ -341,19 +451,21 @@ class _DataSyncPageState extends State<DataSyncPage>
Text( Text(
_getStepLabel(step), _getStepLabel(step),
style: TextStyle( style: TextStyle(
fontSize: isLandscape ? 12 : 14,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: AppColors.primary, color: AppColors.primary,
), ),
), ),
], ],
), ),
SpaceHeight(8), SizedBox(height: isLandscape ? 6 : 8),
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
Text( Text(
'Progress:', 'Progress:',
style: TextStyle( style: TextStyle(
fontSize: isLandscape ? 12 : 14,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
color: Colors.grey.shade700, color: Colors.grey.shade700,
), ),
@ -361,6 +473,7 @@ class _DataSyncPageState extends State<DataSyncPage>
Text( Text(
'${(progress * 100).toInt()}%', '${(progress * 100).toInt()}%',
style: TextStyle( style: TextStyle(
fontSize: isLandscape ? 12 : 14,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: AppColors.primary, color: AppColors.primary,
), ),
@ -372,135 +485,141 @@ class _DataSyncPageState extends State<DataSyncPage>
); );
} }
Widget _buildCompletedState(SyncStats stats) { Widget _buildCompletedState(SyncStats stats, bool isLandscape) {
return Column( return SingleChildScrollView(
mainAxisAlignment: MainAxisAlignment.center, child: Column(
children: [ mainAxisAlignment: MainAxisAlignment.center,
// Success icon children: [
Container( // Success icon
width: 100, Container(
height: 100, width: isLandscape ? 80 : 100,
decoration: BoxDecoration( height: isLandscape ? 80 : 100,
color: Colors.green.shade50, decoration: BoxDecoration(
borderRadius: BorderRadius.circular(50), color: Colors.green.shade50,
), borderRadius: BorderRadius.circular(isLandscape ? 40 : 50),
child: Icon( ),
Icons.check_circle, child: Icon(
size: 60, Icons.check_circle,
color: Colors.green.shade600, size: isLandscape ? 48 : 60,
), color: Colors.green.shade600,
),
SpaceHeight(30),
Text(
'Sinkronisasi Berhasil!',
style: TextStyle(
fontSize: 22,
fontWeight: FontWeight.bold,
color: Colors.green.shade700,
),
),
SpaceHeight(16),
Text(
'Data berhasil diunduh ke perangkat',
style: TextStyle(
fontSize: 16,
color: Colors.grey.shade600,
),
),
SpaceHeight(30),
// Stats cards
Container(
padding: EdgeInsets.all(20),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
border: Border.all(color: Colors.grey.shade200),
),
child: Column(
children: [
Text(
'Data yang Diunduh',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
color: Colors.grey.shade700,
),
),
SpaceHeight(16),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
_buildStatItem(
'Produk',
'${stats.totalProducts}',
Icons.inventory_2,
Colors.blue,
),
_buildStatItem(
'Kategori',
'${stats.totalCategories}',
Icons.category,
Colors.green,
),
_buildStatItem(
'Variant',
'${stats.totalVariants}',
Icons.tune,
Colors.orange,
),
],
),
],
),
),
SpaceHeight(20),
Container(
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 8),
decoration: BoxDecoration(
color: Colors.grey.shade100,
borderRadius: BorderRadius.circular(6),
),
child: Text(
'Mengalihkan ke halaman utama...',
style: TextStyle(
color: Colors.grey.shade600,
fontSize: 12,
), ),
), ),
),
], SizedBox(height: isLandscape ? 20 : 30),
Text(
'Sinkronisasi Berhasil!',
style: TextStyle(
fontSize: isLandscape ? 18 : 22,
fontWeight: FontWeight.bold,
color: Colors.green.shade700,
),
),
SizedBox(height: isLandscape ? 8 : 16),
Text(
'Data berhasil diunduh ke perangkat',
style: TextStyle(
fontSize: isLandscape ? 14 : 16,
color: Colors.grey.shade600,
),
),
SizedBox(height: isLandscape ? 20 : 30),
// Stats cards
Container(
padding: EdgeInsets.all(isLandscape ? 16 : 20),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
border: Border.all(color: Colors.grey.shade200),
),
child: Column(
children: [
Text(
'Data yang Diunduh',
style: TextStyle(
fontSize: isLandscape ? 14 : 16,
fontWeight: FontWeight.w600,
color: Colors.grey.shade700,
),
),
SizedBox(height: isLandscape ? 12 : 16),
if (isLandscape)
// Vertical layout for landscape
Column(
children: [
_buildStatItem('Produk', '${stats.totalProducts}',
Icons.inventory_2, Colors.blue, isLandscape),
SizedBox(height: 8),
_buildStatItem('Kategori', '${stats.totalCategories}',
Icons.category, Colors.green, isLandscape),
SizedBox(height: 8),
_buildStatItem('Variant', '${stats.totalVariants}',
Icons.tune, Colors.orange, isLandscape),
],
)
else
// Horizontal layout for portrait
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
_buildStatItem('Produk', '${stats.totalProducts}',
Icons.inventory_2, Colors.blue, isLandscape),
_buildStatItem('Kategori', '${stats.totalCategories}',
Icons.category, Colors.green, isLandscape),
_buildStatItem('Variant', '${stats.totalVariants}',
Icons.tune, Colors.orange, isLandscape),
],
),
],
),
),
SizedBox(height: isLandscape ? 12 : 20),
Container(
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 8),
decoration: BoxDecoration(
color: Colors.grey.shade100,
borderRadius: BorderRadius.circular(6),
),
child: Text(
'Mengalihkan ke halaman utama...',
style: TextStyle(
color: Colors.grey.shade600,
fontSize: isLandscape ? 10 : 12,
),
),
),
],
),
); );
} }
Widget _buildErrorState(String message) { Widget _buildErrorState(String message, bool isLandscape) {
return Column( return Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
Icon( Icon(
Icons.error_outline, Icons.error_outline,
size: 64, size: isLandscape ? 48 : 64,
color: Colors.red.shade400, color: Colors.red.shade400,
), ),
SpaceHeight(20), SizedBox(height: isLandscape ? 12 : 20),
Text( Text(
'Sinkronisasi Gagal', 'Sinkronisasi Gagal',
style: TextStyle( style: TextStyle(
fontSize: 20, fontSize: isLandscape ? 16 : 20,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: Colors.red.shade600, color: Colors.red.shade600,
), ),
), ),
SpaceHeight(12), SizedBox(height: isLandscape ? 8 : 12),
Container( Container(
padding: EdgeInsets.all(16), padding: EdgeInsets.all(isLandscape ? 12 : 16),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.red.shade50, color: Colors.red.shade50,
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(8),
@ -508,15 +627,17 @@ class _DataSyncPageState extends State<DataSyncPage>
child: Text( child: Text(
message, message,
style: TextStyle( style: TextStyle(
fontSize: isLandscape ? 12 : 14,
color: Colors.red.shade700, color: Colors.red.shade700,
), ),
textAlign: TextAlign.center, textAlign: TextAlign.center,
), ),
), ),
SpaceHeight(20), SizedBox(height: isLandscape ? 12 : 20),
Text( Text(
'Periksa koneksi internet dan coba lagi', 'Periksa koneksi internet dan coba lagi',
style: TextStyle( style: TextStyle(
fontSize: isLandscape ? 12 : 14,
color: Colors.grey.shade600, color: Colors.grey.shade600,
), ),
textAlign: TextAlign.center, textAlign: TextAlign.center,
@ -525,40 +646,75 @@ class _DataSyncPageState extends State<DataSyncPage>
); );
} }
Widget _buildStatItem( Widget _buildStatItem(String label, String value, IconData icon, Color color,
String label, String value, IconData icon, Color color) { bool isLandscape) {
return Column( if (isLandscape) {
children: [ // Horizontal layout for landscape
Container( return Container(
padding: EdgeInsets.all(12), padding: EdgeInsets.symmetric(horizontal: 12, vertical: 8),
decoration: BoxDecoration( decoration: BoxDecoration(
color: color.withOpacity(0.1), color: color.withOpacity(0.1),
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(8),
),
child: Icon(
icon,
size: 24,
color: color,
),
), ),
SpaceHeight(8), child: Row(
Text( mainAxisSize: MainAxisSize.min,
value, children: [
style: TextStyle( Icon(icon, size: 20, color: color),
fontSize: 18, SizedBox(width: 8),
fontWeight: FontWeight.bold, Column(
color: color, crossAxisAlignment: CrossAxisAlignment.start,
), children: [
Text(
value,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: color,
),
),
Text(
label,
style: TextStyle(
fontSize: 10,
color: Colors.grey.shade600,
),
),
],
),
],
), ),
Text( );
label, } else {
style: TextStyle( // Vertical layout for portrait
fontSize: 12, return Column(
color: Colors.grey.shade600, children: [
Container(
padding: EdgeInsets.all(12),
decoration: BoxDecoration(
color: color.withOpacity(0.1),
borderRadius: BorderRadius.circular(8),
),
child: Icon(icon, size: 24, color: color),
), ),
), SizedBox(height: 8),
], Text(
); value,
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: color,
),
),
Text(
label,
style: TextStyle(
fontSize: 12,
color: Colors.grey.shade600,
),
),
],
);
}
} }
Widget _buildActions(DataSyncState state) { Widget _buildActions(DataSyncState state) {
@ -577,7 +733,7 @@ class _DataSyncPageState extends State<DataSyncPage>
), ),
completed: (stats) => Button.filled( completed: (stats) => Button.filled(
onPressed: () { onPressed: () {
Navigator.of(context).pushReplacementNamed('/home'); context.pushReplacement(DashboardPage());
}, },
label: 'Lanjutkan ke Aplikasi', label: 'Lanjutkan ke Aplikasi',
), ),
@ -586,7 +742,7 @@ class _DataSyncPageState extends State<DataSyncPage>
Expanded( Expanded(
child: Button.outlined( child: Button.outlined(
onPressed: () { onPressed: () {
Navigator.of(context).pushReplacementNamed('/home'); context.pushReplacement(DashboardPage());
}, },
label: 'Lewati', label: 'Lewati',
), ),