didvan-app/lib/views/monthly/monthly_list_state.dart

240 lines
6.9 KiB
Dart

import 'dart:convert';
import 'package:didvan/constants/assets.dart';
import 'package:didvan/models/category.dart';
import 'package:didvan/models/enums.dart';
import 'package:didvan/models/monthly/monthly_model.dart';
import 'package:didvan/providers/core.dart';
import 'package:didvan/services/network/request.dart';
import 'package:didvan/services/network/request_helper.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
class MonthlyListState extends CoreProvier {
List<MonthlyItem> monthlyItems = [];
List<MonthlyItem> _allMonthlyItems = [];
String searchQuery = '';
String? startDate;
String? endDate;
final List<CategoryData> selectedCats = [];
List<CategoryData> categories = [];
bool filtering = false;
void initCategories() {
categories = [
CategoryData(
id: 1,
label: 'اقتصادی',
asset: Assets.economicCategoryIcon,
),
CategoryData(
id: 2,
label: 'سیاسی',
asset: Assets.politicalCategoryIcon,
),
CategoryData(
id: 3,
label: 'فناوری',
asset: Assets.techCategoryIcon,
),
CategoryData(
id: 4,
label: 'کسب و کار',
asset: Assets.businessCategoryIcon,
),
CategoryData(
id: 5,
label: 'زیست‌محیطی',
asset: Assets.enviromentalCategoryIcon,
),
CategoryData(
id: 6,
label: 'اجتماعی',
asset: Assets.socialCategoryIcon,
),
];
}
bool get searching => searchQuery.isNotEmpty;
Future<void> fetchMonthlyList() async {
appState = AppState.busy;
notifyListeners();
try {
final url = '${RequestHelper.baseUrl}/monthly';
debugPrint('Fetching monthly list from: $url');
final response = await http.get(
Uri.parse(url),
headers: {
'Authorization': 'Bearer ${RequestService.token}',
'accept': '*/*',
'Content-Type': 'application/json; charset=UTF-8',
},
).timeout(const Duration(seconds: 30));
debugPrint('Response status code: ${response.statusCode}');
if (response.statusCode == 200) {
final jsonData = json.decode(response.body);
debugPrint('Decoded JSON: $jsonData');
final List<dynamic> resultList = jsonData['result'] as List;
debugPrint('Found ${resultList.length} items');
_allMonthlyItems =
resultList.map((item) => MonthlyItem.fromJson(item)).toList();
monthlyItems = _applyFilters(_allMonthlyItems);
debugPrint(
'Successfully parsed ${monthlyItems.length} monthly items after filters');
appState = AppState.idle;
} else {
debugPrint('Request failed with status code: ${response.statusCode}');
appState = AppState.failed;
}
} catch (e, stackTrace) {
debugPrint('Error fetching monthly list: $e');
debugPrint('Stack trace: $stackTrace');
appState = AppState.failed;
}
notifyListeners();
}
void search(String query) {
searchQuery = query;
var filtered = _allMonthlyItems;
if (query.isNotEmpty) {
filtered = filtered
.where((item) =>
item.title.toLowerCase().contains(query.toLowerCase()) ||
item.description.toLowerCase().contains(query.toLowerCase()))
.toList();
}
monthlyItems = _applyFilters(filtered);
notifyListeners();
}
Future<void> toggleLike(int id) async {
try {
final url = '${RequestHelper.baseUrl}/monthly/$id/like';
debugPrint('Toggling like for monthly item: $url');
final index = monthlyItems.indexWhere((item) => item.id == id);
if (index != -1) {
monthlyItems[index].isLiked = !monthlyItems[index].isLiked;
notifyListeners();
}
final response = await http.post(
Uri.parse(url),
headers: {
'Authorization': 'Bearer ${RequestService.token}',
'accept': '*/*',
'Content-Type': 'application/json; charset=UTF-8',
},
).timeout(const Duration(seconds: 30));
if (response.statusCode == 200) {
debugPrint('Like toggled successfully');
} else {
debugPrint('Failed to toggle like: ${response.statusCode}');
if (index != -1) {
monthlyItems[index].isLiked = !monthlyItems[index].isLiked;
notifyListeners();
}
}
} catch (e) {
debugPrint('Error toggling like: $e');
final index = monthlyItems.indexWhere((item) => item.id == id);
if (index != -1) {
monthlyItems[index].isLiked = !monthlyItems[index].isLiked;
notifyListeners();
}
}
}
Future<void> toggleBookmark(int id) async {
try {
final url = '${RequestHelper.baseUrl}/monthly/$id/mark';
debugPrint('Toggling bookmark for monthly item: $url');
final index = monthlyItems.indexWhere((item) => item.id == id);
if (index != -1) {
monthlyItems[index].isBookmarked = !monthlyItems[index].isBookmarked;
notifyListeners();
}
final response = await http.post(
Uri.parse(url),
headers: {
'Authorization': 'Bearer ${RequestService.token}',
'accept': '*/*',
'Content-Type': 'application/json; charset=UTF-8',
},
).timeout(const Duration(seconds: 30));
if (response.statusCode == 200) {
debugPrint('Bookmark toggled successfully');
} else {
debugPrint('Failed to toggle bookmark: ${response.statusCode}');
if (index != -1) {
monthlyItems[index].isBookmarked = !monthlyItems[index].isBookmarked;
notifyListeners();
}
}
} catch (e) {
debugPrint('Error toggling bookmark: $e');
final index = monthlyItems.indexWhere((item) => item.id == id);
if (index != -1) {
monthlyItems[index].isBookmarked = !monthlyItems[index].isBookmarked;
notifyListeners();
}
}
}
void resetFilters([bool notify = true]) {
startDate = null;
endDate = null;
selectedCats.clear();
filtering = false;
if (notify) {
fetchMonthlyList();
}
}
List<MonthlyItem> _applyFilters(List<MonthlyItem> items) {
var filtered = items;
if (startDate != null || endDate != null) {
filtered = filtered.where((item) {
final itemDate = DateTime.parse(item.publishedAt);
if (startDate != null) {
final start = DateTime.parse(startDate!);
if (itemDate.isBefore(start)) return false;
}
if (endDate != null) {
final end = DateTime.parse(endDate!).add(const Duration(days: 1));
if (itemDate.isAfter(end)) return false;
}
return true;
}).toList();
}
if (selectedCats.isNotEmpty) {
filtered = filtered.where((item) {
return item.tags
.any((tag) => selectedCats.any((cat) => cat.id == tag.id));
}).toList();
}
return filtered;
}
}