TIFNGK_E41221954/lib/screens/kader/detail_history_page.dart

396 lines
9.6 KiB
Dart

import 'dart:io';
import 'package:flutter/material.dart';
import 'package:sijentik/models/report_model.dart';
import 'package:sijentik/component/app_theme.dart';
class DetailHistoryPage extends StatelessWidget {
final Report report;
const DetailHistoryPage({super.key, required this.report});
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: AppColors.background,
appBar: AppBar(
backgroundColor: AppColors.button,
elevation: 4,
leading: IconButton(
icon: const Icon(Icons.arrow_back, color: Colors.white),
onPressed: () {
Navigator.pop(context);
},
),
title: const Text(
'Detail Riwayat Laporan',
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 18),
),
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(bottom: Radius.circular(16)),
),
flexibleSpace: Container(
decoration: const BoxDecoration(
gradient: LinearGradient(
colors: [AppColors.button, AppColors.primaryDark],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
borderRadius:
BorderRadius.vertical(bottom: Radius.circular(16)),
),
),
),
body: SingleChildScrollView(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// HEADER
Card(
child: Padding(
padding: const EdgeInsets.all(16),
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Text(
'ID: ${report.id}',
style: AppTextStyles.pageTitle.copyWith(
fontSize: 18,
color: AppColors.button,
),
),
Container(
padding: const EdgeInsets.symmetric(
horizontal: 12, vertical: 6),
decoration: BoxDecoration(
color:
report.statusColor.withOpacity(0.1),
borderRadius:
BorderRadius.circular(20),
),
child: Text(
report.status,
style:
AppTextStyles.smallText.copyWith(
color: report.statusColor,
fontWeight: FontWeight.w600,
),
),
),
],
),
),
),
const SizedBox(height: 20),
// INFORMASI UTAMA
_buildInfoSection(
title: 'Informasi Utama',
children: [
_buildInfoRow(
icon: Icons.calendar_today,
label: 'Tanggal Laporan',
value: report.date,
labelFontSize: 14,
),
_buildInfoRow(
icon: Icons.location_on,
label: 'Alamat',
value: report.address,
labelFontSize: 14,
),
],
),
const SizedBox(height: 20),
// DETAIL TEMUAN
_buildInfoSection(
title: 'Detail Temuan',
children: [
_buildInfoRow(
icon: Icons.description,
label: 'Judul Laporan',
value: report.judul,
),
_buildInfoRow(
icon: Icons.search,
label: 'Temuan',
value: report.finding,
),
],
),
const SizedBox(height: 20),
// FOTO
_buildInfoSection(
title: 'Foto Laporan',
children: [
_buildImageSection(
imageUrl: report.imageUrl,
images: report.images,
),
],
),
const SizedBox(height: 20),
// LOKASI
_buildInfoSection(
title: 'Lokasi Pemeriksaan',
children: [
_buildLocationSection(
latitude: report.latitude,
longitude: report.longitude,
),
],
),
const SizedBox(height: 20),
// CATATAN PETUGAS
_buildInfoSection(
title: 'Catatan Petugas',
children: [
Text(
report.notes ?? "Tidak ada catatan",
style: AppTextStyles.bodyMedium,
),
],
),
],
),
),
);
}
// INFO SECTION
Widget _buildInfoSection({
required String title,
required List<Widget> children,
}) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
title,
style: AppTextStyles.pageTitle.copyWith(
fontSize: 16,
color: AppColors.button,
),
),
const SizedBox(height: 8),
Card(
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(children: children),
),
),
],
);
}
// INFO ROW
Widget _buildInfoRow({
required IconData icon,
required String label,
required dynamic value,
double labelFontSize = 12,
double valueFontSize = 14,
FontWeight labelFontWeight = FontWeight.w600,
FontWeight valueFontWeight = FontWeight.w600,
}) {
final String displayValue = value is DateTime
? '${value.day}/${value.month}/${value.year}'
: value.toString();
return Padding(
padding: const EdgeInsets.only(bottom: 12),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Icon(icon, size: 20, color: AppColors.textGrey),
const SizedBox(width: 12),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
label,
style: AppTextStyles.labelSmall.copyWith(
fontSize: labelFontSize,
fontWeight: labelFontWeight,
),
),
const SizedBox(height: 4),
Text(
displayValue,
style: AppTextStyles.bodyMedium.copyWith(
fontSize: valueFontSize,
fontWeight: valueFontWeight,
),
),
],
),
),
],
),
);
}
// IMAGE SECTION
Widget _buildImageSection({
List<String>? images,
String? imageUrl,
}) {
if (images != null && images.isNotEmpty) {
return SizedBox(
height: 150,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: images.length,
itemBuilder: (context, index) {
return Container(
margin: const EdgeInsets.only(right: 8),
width: 150,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12),
border: Border.all(color: AppColors.grey300),
),
child: ClipRRect(
borderRadius: BorderRadius.circular(12),
child: _buildImage(images[index]),
),
);
},
),
);
}
if (imageUrl != null && imageUrl.isNotEmpty) {
return ClipRRect(
borderRadius: BorderRadius.circular(12),
child: _buildImage(imageUrl, height: 200),
);
}
return Text(
'Tidak ada foto laporan',
style: AppTextStyles.smallText,
);
}
// IMAGE BUILDER
Widget _buildImage(String path, {double height = 150}) {
return path.startsWith('http')
? Image.network(
path,
height: height,
width: double.infinity,
fit: BoxFit.cover,
errorBuilder: (_, __, ___) => _imageError(),
)
: Image.file(
File(path),
height: height,
width: double.infinity,
fit: BoxFit.cover,
errorBuilder: (_, __, ___) => _imageError(),
);
}
// IMAGE ERROR
Widget _imageError() {
return Container(
color: AppColors.grey100,
child: const Center(
child: Icon(
Icons.broken_image,
size: 40,
color: Colors.grey,
),
),
);
}
// LOCATION
Widget _buildLocationSection({
double? latitude,
double? longitude,
}) {
if (latitude == null || longitude == null) {
return Text(
'Lokasi tidak tersedia',
style: AppTextStyles.smallText,
);
}
return Column(
children: [
_buildInfoRow(
icon: Icons.location_on,
label: 'Latitude',
value: latitude.toStringAsFixed(6),
),
_buildInfoRow(
icon: Icons.location_on,
label: 'Longitude',
value: longitude.toStringAsFixed(6),
),
],
);
}
}