Appearance
Part 2: Folder Structure and Models
Linkbox separates concerns well: core, data, features, providers, sync. We will apply the same for an expense app.
Suggested Folder Structure
text
lib/
core/
network/
providers/
services/
utils/
data/
local/
entities/
isar_instance.dart
remote/
expense_remote_data_source.dart
repositories/
expense_repository.dart
sync/
sync_service.dart
sync_state_manager.dart
features/
expenses/
models/
providers/
ui/
screens/
widgets/
main.dartExpense Local Entity (Isar)
dart
import 'package:isar/isar.dart';
part 'expense_local.g.dart';
@collection
class ExpenseLocal {
Id isarId = Isar.autoIncrement;
@Index(unique: true, replace: true)
late String id;
@Index()
late String userId;
@Index()
late DateTime spentAt;
late String category;
late double amount;
String note = '';
@Index()
DateTime updatedAt = DateTime.now().toUtc();
bool isDeleted = false;
bool isSynced = false;
DateTime? lastSyncedAt;
static ExpenseLocal create({
required String id,
required String userId,
required DateTime spentAt,
required String category,
required double amount,
String? note,
}) {
return ExpenseLocal()
..id = id
..userId = userId
..spentAt = spentAt
..category = category
..amount = amount
..note = note ?? '';
}
}Sync Queue Entity
dart
@collection
class SyncTaskLocal {
Id isarId = Isar.autoIncrement;
@Index()
late String entityId;
late String entityType; // expense
late String operation; // upsert | delete
late String payloadJson;
@Index()
DateTime createdAt = DateTime.now().toUtc();
int retryCount = 0;
}