fix: use exact collection stats beyond row limits
This commit is contained in:
parent
69362e7a96
commit
34597b9909
2 changed files with 87 additions and 28 deletions
|
|
@ -139,26 +139,12 @@ class GarageScreenState extends State<GarageScreen> {
|
|||
|
||||
Future<void> _loadCollectionStats() async {
|
||||
try {
|
||||
final weekAgoIso = DateTime.now()
|
||||
.subtract(const Duration(days: 7))
|
||||
.toUtc()
|
||||
.toIso8601String();
|
||||
|
||||
final totalResult = await supabase
|
||||
.from('hotwheels')
|
||||
.select('id')
|
||||
.eq('collection_id', widget.collectionId);
|
||||
|
||||
final recentResult = await supabase
|
||||
.from('hotwheels')
|
||||
.select('id')
|
||||
.eq('collection_id', widget.collectionId)
|
||||
.gte('created_at', weekAgoIso);
|
||||
final stats = await CollectionService.getCollectionStats(widget.collectionId);
|
||||
|
||||
if (!mounted) return;
|
||||
setState(() {
|
||||
_totalCarsCount = totalResult.length;
|
||||
_recentCarsCount = recentResult.length;
|
||||
_totalCarsCount = stats.total;
|
||||
_recentCarsCount = stats.recent;
|
||||
});
|
||||
} catch (_) {
|
||||
if (!mounted) return;
|
||||
|
|
|
|||
|
|
@ -103,17 +103,7 @@ class CollectionService {
|
|||
|
||||
final collectionIdList = collectionIds.toList();
|
||||
|
||||
// Fetch all items for these collections in a single query and count them in memory.
|
||||
final items = await supabase
|
||||
.from('hotwheels')
|
||||
.select('id, collection_id')
|
||||
.inFilter('collection_id', collectionIdList);
|
||||
|
||||
final itemCounts = <String, int>{};
|
||||
for (final item in items) {
|
||||
final collectionId = item['collection_id'] as String;
|
||||
itemCounts[collectionId] = (itemCounts[collectionId] ?? 0) + 1;
|
||||
}
|
||||
final itemCounts = await getCollectionItemCounts(collectionIdList);
|
||||
|
||||
final memberCounts = <String, int>{};
|
||||
await Future.wait(collectionIdList.map((collectionId) async {
|
||||
|
|
@ -171,6 +161,89 @@ class CollectionService {
|
|||
return collections;
|
||||
}
|
||||
|
||||
static Future<Map<String, int>> getCollectionItemCounts(
|
||||
List<String> collectionIds) async {
|
||||
if (collectionIds.isEmpty) return <String, int>{};
|
||||
|
||||
final itemCounts = <String, int>{};
|
||||
try {
|
||||
final rows = await supabase.rpc('get_collection_counts', params: {
|
||||
'p_collection_ids': collectionIds,
|
||||
});
|
||||
|
||||
for (final row in rows as List) {
|
||||
final collectionId = row['collection_id'] as String?;
|
||||
if (collectionId == null) continue;
|
||||
itemCounts[collectionId] = (row['total_count'] as num?)?.toInt() ?? 0;
|
||||
}
|
||||
} catch (_) {}
|
||||
|
||||
final unresolvedIds = collectionIds
|
||||
.where((collectionId) => !itemCounts.containsKey(collectionId))
|
||||
.toList(growable: false);
|
||||
|
||||
if (unresolvedIds.isNotEmpty) {
|
||||
await Future.wait(unresolvedIds.map((collectionId) async {
|
||||
itemCounts[collectionId] = await _countCarsPaginated(collectionId);
|
||||
}));
|
||||
}
|
||||
|
||||
return itemCounts;
|
||||
}
|
||||
|
||||
static Future<({int total, int recent})> getCollectionStats(
|
||||
String collectionId) async {
|
||||
try {
|
||||
final rows = await supabase.rpc('get_collection_counts', params: {
|
||||
'p_collection_ids': [collectionId],
|
||||
});
|
||||
|
||||
if (rows is List && rows.isNotEmpty) {
|
||||
final first = rows.first as Map<String, dynamic>;
|
||||
return (
|
||||
total: (first['total_count'] as num?)?.toInt() ?? 0,
|
||||
recent: (first['recent_count'] as num?)?.toInt() ?? 0,
|
||||
);
|
||||
}
|
||||
} catch (_) {}
|
||||
|
||||
final weekAgoIso = DateTime.now()
|
||||
.subtract(const Duration(days: 7))
|
||||
.toUtc()
|
||||
.toIso8601String();
|
||||
final total = await _countCarsPaginated(collectionId);
|
||||
final recent = await _countCarsPaginated(collectionId, sinceIso: weekAgoIso);
|
||||
return (total: total, recent: recent);
|
||||
}
|
||||
|
||||
static Future<int> _countCarsPaginated(String collectionId,
|
||||
{String? sinceIso}) async {
|
||||
const pageSize = 1000;
|
||||
var from = 0;
|
||||
var total = 0;
|
||||
|
||||
while (true) {
|
||||
dynamic query = supabase
|
||||
.from('hotwheels')
|
||||
.select('id')
|
||||
.eq('collection_id', collectionId)
|
||||
.range(from, from + pageSize - 1);
|
||||
|
||||
if (sinceIso != null) {
|
||||
query = query.gte('created_at', sinceIso);
|
||||
}
|
||||
|
||||
final rows = await query;
|
||||
final count = (rows as List).length;
|
||||
total += count;
|
||||
|
||||
if (count < pageSize) break;
|
||||
from += pageSize;
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
/// Create a new collection. The caller is automatically added as owner.
|
||||
static Future<Collection> create({
|
||||
required String name,
|
||||
|
|
|
|||
Loading…
Reference in a new issue