Files
pfm-ocr/lib/features/documents/pending_document_card.dart
T
fhanyuh caf8e98378 chore: normalize line endings (CRLF -> LF)
No content changes: git diff --ignore-all-space over these files is empty.
The churn came from editing on Windows against a repo checked out with LF.
2026-08-27 10:40:49 +07:00

176 lines
7.1 KiB
Dart

import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import '../../config/app_config.dart';
import 'pending_documents_provider.dart';
class PendingDocumentCard extends ConsumerWidget {
final PendingDocument doc;
final VoidCallback onReload;
const PendingDocumentCard({
super.key,
required this.doc,
required this.onReload,
});
@override
Widget build(BuildContext context, WidgetRef ref) {
Color statusColor;
String statusText;
IconData statusIcon;
switch (doc.status) {
case PendingDocumentStatus.uploading:
case PendingDocumentStatus.processing:
statusColor = Colors.orange;
statusText = 'Sedang memproses dokumen...';
statusIcon = Icons.cloud_upload;
break;
case PendingDocumentStatus.success:
statusColor = AppConfig.successColor;
statusText = 'Ketuk untuk dikonfirmasi';
statusIcon = Icons.check_circle;
break;
case PendingDocumentStatus.error:
statusColor = AppConfig.errorColor;
statusText = 'Gagal Memproses';
statusIcon = Icons.error;
break;
case PendingDocumentStatus.syncFailed:
statusColor = Colors.deepOrange;
statusText = 'Belum tersinkron ke server';
statusIcon = Icons.sync_problem;
break;
}
return Card(
elevation: 0,
margin: const EdgeInsets.only(bottom: AppConfig.spaceMedium),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(AppConfig.borderRadiusMedium),
side: BorderSide(color: statusColor.withOpacity(0.5)),
),
child: InkWell(
onTap: () {
if (doc.status == PendingDocumentStatus.success) {
final routePath = doc.scanMode == 'Product' ? '/product-editor' : '/editor';
context.push(routePath, extra: doc.id).then((_) {
onReload();
});
} else if (doc.status == PendingDocumentStatus.error) {
showModalBottomSheet(
context: context,
builder: (ctx) => SafeArea(
child: Wrap(
children: [
ListTile(
leading: const Icon(Icons.refresh),
title: const Text('Coba Unggah Ulang'),
onTap: () {
Navigator.pop(ctx);
ref.read(pendingDocumentsProvider.notifier).retryUpload(doc.id);
},
),
ListTile(
leading: const Icon(Icons.delete, color: AppConfig.errorColor),
title: const Text('Hapus Dokumen', style: TextStyle(color: AppConfig.errorColor)),
onTap: () {
Navigator.pop(ctx);
ref.read(pendingDocumentsProvider.notifier).removeDocument(doc.id);
},
),
],
),
),
);
} else if (doc.status == PendingDocumentStatus.syncFailed) {
showModalBottomSheet(
context: context,
builder: (ctx) => SafeArea(
child: Wrap(
children: [
ListTile(
leading: const Icon(Icons.sync),
title: const Text('Coba Sinkron Ulang'),
onTap: () {
Navigator.pop(ctx);
ref.read(pendingDocumentsProvider.notifier).retrySync(doc.id);
},
),
ListTile(
leading: const Icon(Icons.delete, color: AppConfig.errorColor),
title: const Text('Hapus Dokumen', style: TextStyle(color: AppConfig.errorColor)),
onTap: () {
Navigator.pop(ctx);
ref.read(pendingDocumentsProvider.notifier).removeDocument(doc.id);
},
),
],
),
),
);
}
},
borderRadius: BorderRadius.circular(AppConfig.borderRadiusMedium),
child: Padding(
padding: AppConfig.paddingLarge,
child: Row(
children: [
ClipRRect(
borderRadius: BorderRadius.circular(AppConfig.borderRadiusSmall),
child: Image.file(
File(doc.imagePath),
width: 60,
height: 60,
fit: BoxFit.cover,
errorBuilder: (context, error, stackTrace) => Container(
width: 60,
height: 60,
color: Colors.grey.shade200,
child: const Icon(Icons.image, color: Colors.grey),
),
),
),
const SizedBox(width: AppConfig.spaceLarge),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Icon(statusIcon, size: 16, color: statusColor),
const SizedBox(width: AppConfig.spaceXS),
Expanded(
child: Text(
statusText,
style: AppConfig.bodyMedium.copyWith(color: statusColor, fontWeight: FontWeight.bold),
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
),
],
),
const SizedBox(height: AppConfig.spaceSmall),
if (doc.status == PendingDocumentStatus.uploading || doc.status == PendingDocumentStatus.processing)
const LinearProgressIndicator(),
if (doc.status == PendingDocumentStatus.success)
Text('Ketuk untuk mereview dan konfirmasi data', style: AppConfig.bodySmall),
if (doc.status == PendingDocumentStatus.error)
Text(doc.errorMessage ?? 'Kesalahan tidak diketahui', style: AppConfig.bodySmall.copyWith(color: AppConfig.errorColor), maxLines: 1, overflow: TextOverflow.ellipsis),
if (doc.status == PendingDocumentStatus.syncFailed)
Text(doc.errorMessage ?? 'Ketuk untuk coba sinkron ulang', style: AppConfig.bodySmall.copyWith(color: Colors.deepOrange), maxLines: 1, overflow: TextOverflow.ellipsis),
],
),
),
if (doc.status == PendingDocumentStatus.success)
const Icon(Icons.chevron_right, color: AppConfig.primaryColor),
],
),
),
),
);
}
}