godcrm/god_frame/lib/features/documents/providers/documents_provider.dart
GOD CRM Release f89e074dd1
Some checks failed
CI / Lint / Typecheck / Test / Build (push) Has been cancelled
CI / PostgreSQL Integration Tests (push) Has been cancelled
GOD CRM — public scrubbed snapshot
Governed substrate for autonomous agents: scoped identity (passports),
audited actions, MCP workspace. Infra IPs and secrets redacted for public release.
2026-08-10 04:01:45 +03:00

99 lines
3.6 KiB
Dart

import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../data/documents_repository.dart';
/// Documents list provider with auto-refresh.
final documentsProvider = FutureProvider.autoDispose<List<Document>>((ref) async {
final repo = ref.watch(documentsRepositoryProvider);
return repo.getDocuments();
});
/// Single document provider.
final documentProvider = FutureProvider.autoDispose.family<Document, int>((ref, id) async {
final repo = ref.watch(documentsRepositoryProvider);
return repo.getDocument(id);
});
/// Document atoms provider.
final documentAtomsProvider = FutureProvider.autoDispose.family<List<DocumentAtom>, int>((ref, docId) async {
final repo = ref.watch(documentsRepositoryProvider);
return repo.getDocumentAtoms(docId);
});
/// Document content provider — loads from doc_* content table via API.
/// First fetches the document to get its table_id, then loads content.
final documentContentProvider = FutureProvider.autoDispose.family<DocumentContent?, int>((ref, docId) async {
final repo = ref.watch(documentsRepositoryProvider);
// Get document first to extract table_id from _registry
try {
final doc = await ref.watch(documentProvider(docId).future);
return repo.getDocumentContent(docId, tableId: doc.tableId);
} catch (_) {
return repo.getDocumentContent(docId);
}
});
/// Search query state.
final documentsSearchProvider = StateProvider<String>((ref) => '');
/// Status filter state.
final documentsStatusFilterProvider = StateProvider<String?>((ref) => null);
/// Type filter state.
final documentsTypeFilterProvider = StateProvider<String?>((ref) => null);
/// Space filter state.
final documentsSpaceFilterProvider = StateProvider<int?>((ref) => null);
/// Filtered documents based on search and filters.
final filteredDocumentsProvider = FutureProvider.autoDispose<List<Document>>((ref) async {
final search = ref.watch(documentsSearchProvider);
final statusFilter = ref.watch(documentsStatusFilterProvider);
final typeFilter = ref.watch(documentsTypeFilterProvider);
final spaceFilter = ref.watch(documentsSpaceFilterProvider);
final repo = ref.watch(documentsRepositoryProvider);
var docs = await repo.getDocuments(search: search.isNotEmpty ? search : null);
// Apply status filter
if (statusFilter != null) {
docs = docs.where((d) =>
d.status?.toLowerCase() == statusFilter.toLowerCase()).toList();
}
// Apply type filter (matches type or category)
if (typeFilter != null) {
docs = docs.where((d) =>
d.type?.toLowerCase() == typeFilter.toLowerCase() ||
d.category?.toLowerCase() == typeFilter.toLowerCase()).toList();
}
// Apply space filter
if (spaceFilter != null) {
docs = docs.where((d) => d.spaceId == spaceFilter).toList();
}
return docs;
});
/// Available statuses derived from loaded documents.
final documentStatusesProvider = FutureProvider.autoDispose<List<String>>((ref) async {
final repo = ref.watch(documentsRepositoryProvider);
final docs = await repo.getDocuments();
final statuses = <String>{};
for (final d in docs) {
if (d.status != null && d.status!.isNotEmpty) statuses.add(d.status!);
}
return statuses.toList()..sort();
});
/// Available types derived from loaded documents (type + category).
final documentTypesProvider = FutureProvider.autoDispose<List<String>>((ref) async {
final repo = ref.watch(documentsRepositoryProvider);
final docs = await repo.getDocuments();
final types = <String>{};
for (final d in docs) {
if (d.type != null && d.type!.isNotEmpty) types.add(d.type!);
if (d.category != null && d.category!.isNotEmpty) types.add(d.category!);
}
return types.toList()..sort();
});