import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../../core/models/comment_model.dart'; import '../../../core/network/providers.dart'; class CommentsNotifier extends StateNotifier>> { final Ref _ref; final String novelId; final String? chapterId; int _page = 1; bool _hasMore = true; CommentsNotifier(this._ref, {required this.novelId, this.chapterId}) : super(const AsyncValue.loading()) { fetch(); } bool get hasMore => _hasMore; Future fetch({bool reset = false}) async { if (reset) { _page = 1; _hasMore = true; state = const AsyncValue.loading(); } try { final client = _ref.read(apiClientProvider); final queryParams = { 'page': _page.toString(), 'limit': '20', if (chapterId != null) 'chapterId': chapterId, }; final res = await client.dio.get('/api/truyen/$novelId/comments', queryParameters: queryParams); final data = res.data as Map; final newItems = (data['comments'] as List) .map((e) => CommentModel.fromJson(e as Map)) .toList(); final totalPages = data['totalPages'] as int? ?? 1; _hasMore = _page < totalPages; final existing = reset ? [] : (state.valueOrNull ?? []); state = AsyncValue.data([...existing, ...newItems]); } catch (e, st) { state = AsyncValue.error(e, st); } } Future loadMore() async { if (!_hasMore) return; _page++; await fetch(); } Future post(String content) async { final client = _ref.read(apiClientProvider); final res = await client.dio.post('/api/truyen/$novelId/comments', data: { 'content': content, if (chapterId != null) 'chapterId': chapterId, }); final newComment = CommentModel.fromJson(res.data as Map); state = AsyncValue.data([newComment, ...(state.valueOrNull ?? [])]); } } // Provider family params: "novelId" or "novelId:chapterId" final commentsProvider = StateNotifierProvider.family>, String>((ref, key) { final parts = key.split(':'); return CommentsNotifier( ref, novelId: parts[0], chapterId: parts.length > 1 ? parts[1] : null, ); });