Add a small curated catalog of Iberian horticultural species and let a variety be linked to it from the edit sheet. - assets/catalog/species.json: 14 species with botanical family and ES/EN common names (wikidata_qid/gbif_key deferred to the varilla enrichment). - SpeciesRepository: idempotent seedBundled (is_bundled rows, keyed by scientific name) + search by scientific/common name with a locale-best label. Seeded on startup from DI. - VarietyRepository.linkSpecies: sets species_id and prefills category from the species' family when empty (never overwrites an existing category). VarietyDetail now carries the scientific name. - Edit sheet gains a live species-search field; the detail view shows the scientific name (italic). i18n strings added (ES/EN). Tests: catalog parse, idempotent seeding, search by scientific/common name, linkSpecies prefill semantics, and a widget test for the autocomplete → link → scientific-name-shown flow. Full suite: 32 passing, 0 skipped.
71 lines
1.8 KiB
Dart
71 lines
1.8 KiB
Dart
import 'dart:async';
|
|
|
|
import 'package:commons_core/commons_core.dart';
|
|
import 'package:equatable/equatable.dart';
|
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
|
|
|
import '../data/variety_repository.dart';
|
|
|
|
class VarietyDetailState extends Equatable {
|
|
const VarietyDetailState({
|
|
this.detail,
|
|
this.loading = true,
|
|
this.deleted = false,
|
|
});
|
|
|
|
final VarietyDetail? detail;
|
|
final bool loading;
|
|
final bool deleted;
|
|
|
|
@override
|
|
List<Object?> get props => [detail, loading, deleted];
|
|
}
|
|
|
|
/// Streams one variety's detail and edits it through the repository.
|
|
class VarietyDetailCubit extends Cubit<VarietyDetailState> {
|
|
VarietyDetailCubit(this._repo, this.varietyId)
|
|
: super(const VarietyDetailState()) {
|
|
_sub = _repo
|
|
.watchVariety(varietyId)
|
|
.listen(
|
|
(d) => emit(
|
|
VarietyDetailState(
|
|
detail: d,
|
|
loading: false,
|
|
deleted: state.deleted,
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
final VarietyRepository _repo;
|
|
final String varietyId;
|
|
late final StreamSubscription<VarietyDetail?> _sub;
|
|
|
|
Future<void> updateFields({String? label, String? category, String? notes}) =>
|
|
_repo.updateVariety(
|
|
id: varietyId,
|
|
label: label,
|
|
category: category,
|
|
notes: notes,
|
|
);
|
|
|
|
Future<void> addLot({int? year, Quantity? quantity}) =>
|
|
_repo.addLot(varietyId: varietyId, harvestYear: year, quantity: quantity);
|
|
|
|
Future<void> linkSpecies(String speciesId) =>
|
|
_repo.linkSpecies(varietyId, speciesId);
|
|
|
|
Future<void> deleteVariety() async {
|
|
await _repo.softDeleteVariety(varietyId);
|
|
emit(
|
|
VarietyDetailState(detail: state.detail, loading: false, deleted: true),
|
|
);
|
|
}
|
|
|
|
@override
|
|
Future<void> close() async {
|
|
await _sub.cancel();
|
|
return super.close();
|
|
}
|
|
}
|