feat(app): scan-mode sync, confirmation-gated documents, single-pass product classification
Fixes reported from APK field testing: DO/Product scan mode was inconsistent between the camera drawer and documents screen (now one shared provider, with an orange/green color cue); unconfirmed scans leaked into history with placeholder data before the user tapped confirm (backend now gates GET /documents on a new `confirmed` column, flipped only by PUT); and Product Scan ran the GPU classifier twice, once at upload and again on review (now a single pass at upload, persisted and read directly by the editor). Also removes the unused "Hubungkan ke PO" field and fabricated PO/SO/DO placeholder values from the Product Scan flow, closes out the per-document-polling and save-recovery tasks (6.1/6.3), and splits several touched files to stay under the repo's 256-line guideline. Full detail in docs/iteration-log.md and backend/docs/iteration-log.md. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
2febe0c886
commit
ada6488592
67 files changed
+5705
-1142
No files matched your search
@@ -6,33 +6,45 @@ import '../../models/document_model.dart';
|
||||
class DocumentCard extends StatelessWidget {
|
||||
final DocumentModel doc;
|
||||
final Future<void> Function(DocumentModel) onPrint;
|
||||
final bool isUnsynced;
|
||||
|
||||
const DocumentCard({
|
||||
super.key,
|
||||
required this.doc,
|
||||
required this.onPrint,
|
||||
this.isUnsynced = false,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final isProductScan = doc.orderUntuk == 'PRODUCT SCAN';
|
||||
final isProductScan = doc.docType == 'Product';
|
||||
|
||||
// Header category text
|
||||
final categoryText = isProductScan
|
||||
? (doc.items.isNotEmpty ? doc.items.first.namaBarang : 'Product Scan')
|
||||
: (doc.namaPenerima.isNotEmpty ? doc.namaPenerima : 'Staff Toko');
|
||||
|
||||
// Category color (greenish-blue for product, orange-yellow for DO)
|
||||
final categoryColor = isProductScan ? AppConfig.primaryColor : Colors.orange.shade700;
|
||||
// Category color: Product → green (primaryColor), DO → orange (doModeColor).
|
||||
// doModeColor is the shared constant for the DO orange cue across the app
|
||||
// (camera drawer, tab switcher, and here) — was an ad-hoc inline value.
|
||||
final categoryColor = isProductScan ? AppConfig.primaryColor : AppConfig.doModeColor;
|
||||
|
||||
// Sync status badge (see docs/api-contract-map.md G6 - a document can be
|
||||
// corrected locally after its PUT sync failed; the corrected copy is
|
||||
// shown here, so the badge must reflect that it hasn't reached the
|
||||
// server yet rather than always claiming "Terkonfirmasi").
|
||||
final badgeLabel = isUnsynced ? 'Belum Tersinkron' : 'Terkonfirmasi';
|
||||
final badgeColor = isUnsynced ? Colors.deepOrange : AppConfig.successColor;
|
||||
|
||||
// Bold title
|
||||
final boldTitle = isProductScan
|
||||
? doc.noDo
|
||||
: doc.noPo;
|
||||
|
||||
// Subtitle text
|
||||
// Subtitle text. Product Scan no longer links to a PO document (field
|
||||
// removed - user request), so its subtitle is just the expiry date.
|
||||
final subtitleText = isProductScan
|
||||
? '${_formatDateString(doc.alamat.replaceAll("Product Scan: Expired ", ""))} • ${doc.noPo}'
|
||||
? _formatDateString(doc.alamat.replaceAll("Product Scan: Expired ", ""))
|
||||
: '${doc.tanggal} • ${doc.items.length} Item';
|
||||
|
||||
return Card(
|
||||
@@ -92,17 +104,17 @@ class DocumentCard extends StatelessWidget {
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
// Status badge (e.g. Approved / Terkonfirmasi)
|
||||
// Status badge (Terkonfirmasi / Belum Tersinkron)
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||||
decoration: BoxDecoration(
|
||||
color: AppConfig.successColor.withOpacity(0.1),
|
||||
color: badgeColor.withOpacity(0.1),
|
||||
borderRadius: BorderRadius.circular(AppConfig.borderRadiusSmall),
|
||||
),
|
||||
child: Text(
|
||||
'Terkonfirmasi',
|
||||
badgeLabel,
|
||||
style: AppConfig.bodySmall.copyWith(
|
||||
color: AppConfig.successColor,
|
||||
color: badgeColor,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 11,
|
||||
),
|
||||
|
||||
Reference in new issue
Block a user