reading test receipt text detected OK
This commit is contained in:
@@ -1,130 +0,0 @@
|
||||
/// Domain models for catalog items shown in lists and detail screens.
|
||||
library;
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// High-level grouping used for filters, icons, and accent colors.
|
||||
enum ItemCategory {
|
||||
design,
|
||||
development,
|
||||
productivity,
|
||||
lifestyle,
|
||||
}
|
||||
|
||||
extension ItemCategoryX on ItemCategory {
|
||||
String get label => switch (this) {
|
||||
ItemCategory.design => 'Design',
|
||||
ItemCategory.development => 'Development',
|
||||
ItemCategory.productivity => 'Productivity',
|
||||
ItemCategory.lifestyle => 'Lifestyle',
|
||||
};
|
||||
|
||||
IconData get icon => switch (this) {
|
||||
ItemCategory.design => Icons.palette_outlined,
|
||||
ItemCategory.development => Icons.code,
|
||||
ItemCategory.productivity => Icons.bolt_outlined,
|
||||
ItemCategory.lifestyle => Icons.spa_outlined,
|
||||
};
|
||||
|
||||
/// Stable accent used by [Hero] tiles so the animation has a colored target.
|
||||
Color get accent => switch (this) {
|
||||
ItemCategory.design => const Color(0xFF7C3AED),
|
||||
ItemCategory.development => const Color(0xFF0F766E),
|
||||
ItemCategory.productivity => const Color(0xFFC2410C),
|
||||
ItemCategory.lifestyle => const Color(0xFF0369A1),
|
||||
};
|
||||
|
||||
static ItemCategory fromName(String name) {
|
||||
return ItemCategory.values.firstWhere(
|
||||
(category) => category.name == name,
|
||||
orElse: () => ItemCategory.productivity,
|
||||
);
|
||||
}
|
||||
|
||||
static ItemCategory fromIndex(int index) {
|
||||
return ItemCategory.values[index.abs() % ItemCategory.values.length];
|
||||
}
|
||||
}
|
||||
|
||||
/// A catalog entry displayed on Home / Search and opened on the detail route.
|
||||
class Item {
|
||||
const Item({
|
||||
required this.id,
|
||||
required this.title,
|
||||
required this.subtitle,
|
||||
required this.description,
|
||||
required this.category,
|
||||
required this.createdAt,
|
||||
});
|
||||
|
||||
final String id;
|
||||
final String title;
|
||||
final String subtitle;
|
||||
final String description;
|
||||
final ItemCategory category;
|
||||
final DateTime createdAt;
|
||||
|
||||
/// Tag used by the list-to-detail [Hero] animation.
|
||||
String get heroTag => 'item-hero-$id';
|
||||
|
||||
Item copyWith({
|
||||
String? id,
|
||||
String? title,
|
||||
String? subtitle,
|
||||
String? description,
|
||||
ItemCategory? category,
|
||||
DateTime? createdAt,
|
||||
}) {
|
||||
return Item(
|
||||
id: id ?? this.id,
|
||||
title: title ?? this.title,
|
||||
subtitle: subtitle ?? this.subtitle,
|
||||
description: description ?? this.description,
|
||||
category: category ?? this.category,
|
||||
createdAt: createdAt ?? this.createdAt,
|
||||
);
|
||||
}
|
||||
|
||||
/// Maps a JSONPlaceholder `/posts` payload (or any similar JSON object).
|
||||
factory Item.fromJson(Map<String, dynamic> json) {
|
||||
final id = json['id']?.toString() ?? '0';
|
||||
final title = (json['title'] as String? ?? 'Untitled').trim();
|
||||
final body = (json['body'] as String? ?? '').trim();
|
||||
final numericId = int.tryParse(id) ?? 0;
|
||||
|
||||
return Item(
|
||||
id: 'remote-$id',
|
||||
title: _titleCase(title),
|
||||
subtitle: _firstSentence(body),
|
||||
description: body.replaceAll('\n', ' '),
|
||||
category: ItemCategoryX.fromIndex(numericId),
|
||||
createdAt: DateTime(2026, 1, 1).add(Duration(days: numericId)),
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'id': id,
|
||||
'title': title,
|
||||
'subtitle': subtitle,
|
||||
'description': description,
|
||||
'category': category.name,
|
||||
'createdAt': createdAt.toIso8601String(),
|
||||
};
|
||||
}
|
||||
|
||||
static String _titleCase(String value) {
|
||||
if (value.isEmpty) return value;
|
||||
return value[0].toUpperCase() + value.substring(1);
|
||||
}
|
||||
|
||||
static String _firstSentence(String value) {
|
||||
if (value.isEmpty) return 'No summary available.';
|
||||
final cleaned = value.replaceAll('\n', ' ');
|
||||
final period = cleaned.indexOf('.');
|
||||
if (period <= 0) {
|
||||
return cleaned.length > 80 ? '${cleaned.substring(0, 77)}…' : cleaned;
|
||||
}
|
||||
return cleaned.substring(0, period + 1);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user