MIF_E31231313/Android/flutter_app/lib/screens/loading_screen.dart

178 lines
5.4 KiB
Dart

import 'package:flutter/material.dart';
import '../app_design.dart';
import '../app_state.dart';
import '../models/api_result_model.dart';
import '../services/api_service.dart';
import 'result_screen.dart';
class LoadingScreen extends StatefulWidget {
const LoadingScreen({super.key, required this.payload});
final Map<String, dynamic> payload;
@override
State<LoadingScreen> createState() => _LoadingScreenState();
}
class _LoadingScreenState extends State<LoadingScreen> {
final ApiService _apiService = ApiService();
late Future<ApiResultModel> _future;
@override
void initState() {
super.initState();
_future = _apiService.postHasil(widget.payload);
}
void _retry() {
setState(() => _future = _apiService.postHasil(widget.payload));
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: FutureBuilder<ApiResultModel>(
future: _future,
builder: (context, snapshot) {
if (snapshot.hasError) {
return ErrorState(
message:
'S-Gizi belum berhasil menghitung data. Periksa koneksi atau server API, lalu coba lagi.',
onRetry: _retry,
);
}
if (snapshot.hasData) {
WidgetsBinding.instance.addPostFrameCallback((_) {
final childId = widget.payload['child_id'];
final tanggalUkur = widget.payload['tanggal_ukur'];
if (childId is int && tanggalUkur is String) {
SgiziAppState.instance.updateChildMeasurementSnapshot(
childId: childId,
latestStatus: snapshot.data!.statusGabungan,
latestMeasurementAt: tanggalUkur,
);
}
if (!mounted) return;
Navigator.of(context).pushReplacement(
fadeRoute(ResultScreen(result: snapshot.data!)),
);
});
}
return const _LoadingContent();
},
),
);
}
}
class _LoadingContent extends StatefulWidget {
const _LoadingContent();
@override
State<_LoadingContent> createState() => _LoadingContentState();
}
class _LoadingContentState extends State<_LoadingContent>
with SingleTickerProviderStateMixin {
late final AnimationController _controller;
@override
void initState() {
super.initState();
_controller = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 1600),
)..repeat();
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return SafeArea(
child: Center(
child: Padding(
padding: const EdgeInsets.all(32),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
RotationTransition(
turns: Tween<double>(begin: 0, end: 1).animate(_controller),
child: Container(
width: 112,
height: 112,
decoration: BoxDecoration(
color: const Color(0xFFEFF8F7),
shape: BoxShape.circle,
border: Border.all(
color: const Color(0xFFE2F1EF),
width: 8,
),
),
child: const Icon(
Icons.auto_awesome_rounded,
color: SgColors.primary,
size: 38,
),
),
),
const SizedBox(height: 32),
const Text(
'Sedang menghitung status gizi...',
style: AppTypography.h1,
textAlign: TextAlign.center,
),
const SizedBox(height: 16),
const Text(
'Mohon tunggu sebentar, sistem S-Gizi sedang menganalisis data pertumbuhan si Kecil berdasarkan standar kesehatan.',
style: AppTypography.body,
textAlign: TextAlign.center,
),
const SizedBox(height: 40),
ClipRRect(
borderRadius: BorderRadius.circular(99),
child: AnimatedBuilder(
animation: _controller,
builder: (context, _) {
final value = 0.18 + (_controller.value * 0.72);
return LinearProgressIndicator(
value: value,
minHeight: 8,
backgroundColor: const Color(0xFFEFF4F2),
valueColor: const AlwaysStoppedAnimation(
SgColors.primary,
),
);
},
),
),
const SizedBox(height: 12),
AnimatedBuilder(
animation: _controller,
builder: (context, _) {
final percent = (20 + (_controller.value * 70)).round();
return Text(
'MEMPROSES DATA $percent%',
style: AppTypography.caption.copyWith(
letterSpacing: 1.2,
fontWeight: FontWeight.w800,
),
);
},
),
],
),
),
),
);
}
}