121 lines
3.9 KiB
Dart
121 lines
3.9 KiB
Dart
// lib/core/widgets/data_handler.dart
|
|
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
|
import 'package:smpn1_lengkong/core/constants/app_colors.dart';
|
|
|
|
class DataHandler extends StatelessWidget {
|
|
final AsyncSnapshot snapshot;
|
|
final Widget child;
|
|
final VoidCallback onRetry;
|
|
final Future<void> Function() onRefresh;
|
|
final String? emptyMessage;
|
|
|
|
const DataHandler({
|
|
super.key,
|
|
required this.snapshot,
|
|
required this.child,
|
|
required this.onRetry,
|
|
required this.onRefresh,
|
|
this.emptyMessage,
|
|
});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
// 1. KONDISI LOADING: Muncul saat halaman pertama kali dibuka
|
|
if (snapshot.connectionState == ConnectionState.waiting) {
|
|
return const Center(
|
|
child: CircularProgressIndicator(color: AppColors.primaryBlue),
|
|
);
|
|
}
|
|
|
|
// 2. KONDISI ERROR: Muncul jika gagal koneksi/timeout saat inisialisasi
|
|
if (snapshot.hasError) {
|
|
return RefreshIndicator(
|
|
onRefresh: onRefresh,
|
|
color: AppColors.primaryBlue,
|
|
child: SingleChildScrollView(
|
|
physics: const AlwaysScrollableScrollPhysics(),
|
|
child: Container(
|
|
height: 0.7.sh, // Mengambil 70% tinggi layar
|
|
padding: EdgeInsets.all(24.w),
|
|
alignment: Alignment.center,
|
|
child: Column(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: [
|
|
Icon(
|
|
Icons.wifi_off_rounded,
|
|
size: 80.sp,
|
|
color: Colors.grey[400],
|
|
),
|
|
SizedBox(height: 16.h),
|
|
Text(
|
|
"Koneksi Bermasalah",
|
|
style: TextStyle(
|
|
fontSize: 18.sp,
|
|
fontWeight: FontWeight.bold,
|
|
color: AppColors.textPrimary,
|
|
),
|
|
),
|
|
SizedBox(height: 8.h),
|
|
Text(
|
|
"Gagal mengambil data dari server. Periksa internet Anda atau tarik layar untuk mencoba lagi.",
|
|
textAlign: TextAlign.center,
|
|
style: TextStyle(
|
|
color: AppColors.textSecondary,
|
|
fontSize: 14.sp,
|
|
),
|
|
),
|
|
SizedBox(height: 24.h),
|
|
ElevatedButton.icon(
|
|
onPressed: onRetry,
|
|
icon: const Icon(Icons.refresh_rounded),
|
|
label: const Text("Coba Lagi"),
|
|
style: ElevatedButton.styleFrom(
|
|
backgroundColor: AppColors.primaryBlue,
|
|
foregroundColor: Colors.white,
|
|
padding: EdgeInsets.symmetric(
|
|
horizontal: 24.w,
|
|
vertical: 12.h,
|
|
),
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(10.r),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
// 3. KONDISI KOSONG: Jika data berhasil diambil tapi list-nya kosong
|
|
final data = snapshot.data;
|
|
if (data is List && data.isEmpty) {
|
|
return RefreshIndicator(
|
|
onRefresh: onRefresh,
|
|
child: SingleChildScrollView(
|
|
physics: const AlwaysScrollableScrollPhysics(),
|
|
child: Container(
|
|
height: 0.7.sh,
|
|
alignment: Alignment.center,
|
|
child: Text(
|
|
emptyMessage ?? "Data tidak ditemukan",
|
|
style: TextStyle(color: Colors.grey, fontSize: 14.sp),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
// 4. KONDISI SUKSES: Menampilkan konten asli dengan RefreshIndicator
|
|
return RefreshIndicator(
|
|
onRefresh: onRefresh,
|
|
color: AppColors.primaryBlue,
|
|
backgroundColor: Colors.white,
|
|
child: child,
|
|
);
|
|
}
|
|
}
|