delete likes in liked screen
This commit is contained in:
@@ -119,8 +119,10 @@ List<SingleChildWidget> get viewModels {
|
||||
),
|
||||
ChangeNotifierProvider(
|
||||
create:
|
||||
(context) =>
|
||||
LikedTendersViewModel(likedTendersRepository: context.read()),
|
||||
(context) => LikedTendersViewModel(
|
||||
likedTendersRepository: context.read(),
|
||||
tendersRepository: context.read(),
|
||||
),
|
||||
),
|
||||
ChangeNotifierProvider(
|
||||
create:
|
||||
|
||||
@@ -3,13 +3,14 @@ import 'package:tm_app/data/services/liked_tenders_service.dart';
|
||||
import 'package:tm_app/data/services/model/liked_tenders_response/liked_tenders_response.dart';
|
||||
|
||||
class LikedTendersRepository {
|
||||
final LikedTendersService likedTendersService;
|
||||
LikedTendersRepository({required this.likedTendersService});
|
||||
final LikedTendersService _likedTendersService;
|
||||
LikedTendersRepository({required LikedTendersService likedTendersService})
|
||||
: _likedTendersService = likedTendersService;
|
||||
|
||||
Future<Result<LikedTendersResponse>> getLikedTenders({
|
||||
int offset = 0,
|
||||
int limit = 20,
|
||||
}) {
|
||||
return likedTendersService.getLikedTenders(offset: offset, limit: limit);
|
||||
return _likedTendersService.getLikedTenders(offset: offset, limit: limit);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,20 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:tm_app/core/utils/result.dart';
|
||||
import 'package:tm_app/data/repositories/liked_tenders_repository.dart';
|
||||
import 'package:tm_app/data/repositories/tenders_repository.dart';
|
||||
import 'package:tm_app/data/services/model/liked_tender_feedback/liked_tender_feedback.dart';
|
||||
import 'package:tm_app/data/services/model/liked_tenders_response/liked_tenders_response.dart';
|
||||
|
||||
import '../data/services/model/feedback_response/feedback_response.dart';
|
||||
|
||||
class LikedTendersViewModel with ChangeNotifier {
|
||||
final LikedTendersRepository likedTendersRepository;
|
||||
LikedTendersViewModel({required this.likedTendersRepository}) {
|
||||
getLikedTenders(reset: true);
|
||||
}
|
||||
final LikedTendersRepository _likedTendersRepository;
|
||||
final TendersRepository _tendersRepository;
|
||||
LikedTendersViewModel({
|
||||
required LikedTendersRepository likedTendersRepository,
|
||||
required TendersRepository tendersRepository,
|
||||
}) : _likedTendersRepository = likedTendersRepository,
|
||||
_tendersRepository = tendersRepository;
|
||||
|
||||
bool isLoading = false;
|
||||
bool isLoadingMore = false;
|
||||
@@ -21,71 +27,70 @@ class LikedTendersViewModel with ChangeNotifier {
|
||||
|
||||
int currentPage = 1;
|
||||
|
||||
Future<void> getLikedTenders({bool reset = false}) async {
|
||||
if (!reset && (isLoadingMore || !hasMore)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (reset) {
|
||||
_offset = (currentPage - 1) * _limit;
|
||||
hasMore = true;
|
||||
|
||||
data = null;
|
||||
isLoading = true;
|
||||
notifyListeners();
|
||||
} else {
|
||||
if (_offset == 0) {
|
||||
isLoading = true;
|
||||
} else {
|
||||
isLoadingMore = true;
|
||||
Future<void> getLikedTenders({bool reset = false}) async {
|
||||
if (!reset && (isLoadingMore || !hasMore)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (reset) {
|
||||
_offset = (currentPage - 1) * _limit;
|
||||
hasMore = true;
|
||||
|
||||
data = null;
|
||||
isLoading = true;
|
||||
notifyListeners();
|
||||
} else {
|
||||
if (_offset == 0) {
|
||||
isLoading = true;
|
||||
} else {
|
||||
isLoadingMore = true;
|
||||
}
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
errorMessage = null;
|
||||
|
||||
final result = await _likedTendersRepository.getLikedTenders(
|
||||
offset: _offset,
|
||||
limit: _limit,
|
||||
);
|
||||
|
||||
switch (result) {
|
||||
case Ok<LikedTendersResponse>():
|
||||
final incoming = result.value;
|
||||
final incomingList = incoming.data?.feedback ?? [];
|
||||
|
||||
if (reset) {
|
||||
data = incoming;
|
||||
} else {
|
||||
final existingList = data?.data?.feedback ?? [];
|
||||
final combined = List<LikedTenderFeedback>.of(existingList)
|
||||
..addAll(incomingList);
|
||||
|
||||
data = data?.copyWith(
|
||||
data: data?.data?.copyWith(
|
||||
feedback: combined,
|
||||
meta: incoming.data?.meta ?? data!.data!.meta,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
hasMore = incomingList.length == _limit;
|
||||
_offset += _limit;
|
||||
|
||||
errorMessage = null;
|
||||
break;
|
||||
|
||||
case Error<LikedTendersResponse>():
|
||||
errorMessage = result.error.toString();
|
||||
break;
|
||||
}
|
||||
|
||||
isLoading = false;
|
||||
isLoadingMore = false;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
errorMessage = null;
|
||||
|
||||
final result = await likedTendersRepository.getLikedTenders(
|
||||
offset: _offset,
|
||||
limit: _limit,
|
||||
);
|
||||
|
||||
switch (result) {
|
||||
case Ok<LikedTendersResponse>():
|
||||
final incoming = result.value;
|
||||
final incomingList = incoming.data?.feedback ?? [];
|
||||
|
||||
if (reset) {
|
||||
data = incoming;
|
||||
} else {
|
||||
final existingList = data?.data?.feedback ?? [];
|
||||
final combined = List<LikedTenderFeedback>.of(existingList)
|
||||
..addAll(incomingList);
|
||||
|
||||
data = data?.copyWith(
|
||||
data: data?.data?.copyWith(
|
||||
feedback: combined,
|
||||
meta: incoming.data?.meta ?? data!.data!.meta,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
hasMore = incomingList.length == _limit;
|
||||
_offset += _limit;
|
||||
|
||||
errorMessage = null;
|
||||
break;
|
||||
|
||||
case Error<LikedTendersResponse>():
|
||||
errorMessage = result.error.toString();
|
||||
break;
|
||||
}
|
||||
|
||||
isLoading = false;
|
||||
isLoadingMore = false;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
|
||||
Future<void> loadMoreIfNeeded() async {
|
||||
if (isLoadingMore || !hasMore) {
|
||||
return;
|
||||
@@ -100,24 +105,49 @@ Future<void> getLikedTenders({bool reset = false}) async {
|
||||
await getLikedTenders(reset: true);
|
||||
}
|
||||
|
||||
void removeTenderById(String id) {
|
||||
void removeTenderById(String id) async {
|
||||
final current = data;
|
||||
final list = current?.data?.feedback;
|
||||
if (current == null || list == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Store original list to restore if error occurs
|
||||
final originalList = List<LikedTenderFeedback>.of(list);
|
||||
final updatedList = List<LikedTenderFeedback>.of(list)
|
||||
..removeWhere((e) => e.id == id);
|
||||
|
||||
final updatedMeta = current.data?.meta?.copyWith(total: updatedList.length);
|
||||
..removeWhere((e) => e.tenderId == id);
|
||||
|
||||
// Temporarily update UI
|
||||
data = current.copyWith(
|
||||
data: current.data?.copyWith(
|
||||
feedback: updatedList,
|
||||
meta: updatedMeta,
|
||||
),
|
||||
data: current.data?.copyWith(feedback: updatedList),
|
||||
);
|
||||
notifyListeners();
|
||||
|
||||
final result = await _tendersRepository.toggleFeedback(
|
||||
tenderId: id,
|
||||
feedbackType: 'like',
|
||||
);
|
||||
|
||||
switch (result) {
|
||||
case Ok<FeedbackResponse>():
|
||||
final updatedMeta = current.data?.meta?.copyWith(
|
||||
total: updatedList.length,
|
||||
);
|
||||
data = current.copyWith(
|
||||
data: current.data?.copyWith(
|
||||
feedback: updatedList,
|
||||
meta: updatedMeta,
|
||||
),
|
||||
);
|
||||
break;
|
||||
case Error<FeedbackResponse>():
|
||||
// Restore original list if error occurs
|
||||
data = current.copyWith(
|
||||
data: current.data?.copyWith(feedback: originalList),
|
||||
);
|
||||
errorMessage = result.error.toString();
|
||||
break;
|
||||
}
|
||||
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
@@ -152,7 +152,9 @@ class MobileHomePage extends StatelessWidget {
|
||||
textColor: AppColors.grey80,
|
||||
enableTap: true,
|
||||
onTap: () {
|
||||
LikedTendersRouteData().push(context);
|
||||
LikedTendersRouteData().push(context).then((value) {
|
||||
homeViewModel.init();
|
||||
});
|
||||
},
|
||||
),
|
||||
],
|
||||
|
||||
@@ -61,7 +61,9 @@ class _LikedTendersDesktopPageState extends State<LikedTendersDesktopPage> {
|
||||
final feedback = viewModel.data?.data?.feedback ?? [];
|
||||
|
||||
if (feedback.isEmpty) {
|
||||
return const Center(child: Text('Nothing to show'));
|
||||
return const Center(
|
||||
child: Text('You haven’t liked any tenders yet.'),
|
||||
);
|
||||
}
|
||||
|
||||
final currentPage = viewModel.currentPage;
|
||||
@@ -140,8 +142,11 @@ class _LikedTendersDesktopPageState extends State<LikedTendersDesktopPage> {
|
||||
final pageNumber = index + 1;
|
||||
return ListTile(
|
||||
title: Text('Page $pageNumber'),
|
||||
onTap: () =>
|
||||
Navigator.pop(context, pageNumber),
|
||||
onTap:
|
||||
() => Navigator.pop(
|
||||
context,
|
||||
pageNumber,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
|
||||
@@ -71,10 +71,13 @@ class _LikedTendersMobilePageState extends State<LikedTendersMobilePage> {
|
||||
final feedback = viewModel.data?.data?.feedback ?? [];
|
||||
|
||||
if (feedback.isEmpty) {
|
||||
return const Center(child: Text('Nothing to show'));
|
||||
return const Center(
|
||||
child: Text('You haven’t liked any tenders yet.'),
|
||||
);
|
||||
}
|
||||
|
||||
final itemCount = feedback.length + (viewModel.isLoadingMore ? 1 : 0);
|
||||
final itemCount =
|
||||
feedback.length + (viewModel.isLoadingMore ? 1 : 0);
|
||||
|
||||
return RefreshIndicator(
|
||||
onRefresh: () async {
|
||||
@@ -93,16 +96,18 @@ class _LikedTendersMobilePageState extends State<LikedTendersMobilePage> {
|
||||
return Padding(
|
||||
padding: EdgeInsets.only(bottom: 20.0.h()),
|
||||
child: Dismissible(
|
||||
key: ValueKey(item.id ?? index),
|
||||
key: ValueKey(item.tenderId ?? index),
|
||||
direction: DismissDirection.endToStart,
|
||||
background: Container(
|
||||
alignment: Alignment.centerRight,
|
||||
padding: EdgeInsets.symmetric(horizontal: 20.0.w()),
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 20.0.w(),
|
||||
),
|
||||
child: SvgPicture.asset(AssetsManager.trash),
|
||||
),
|
||||
onDismissed: (_) {
|
||||
if (item.id != null) {
|
||||
viewModel.removeTenderById(item.id!);
|
||||
if (item.tenderId != null) {
|
||||
viewModel.removeTenderById(item.tenderId!);
|
||||
}
|
||||
},
|
||||
child: LikedListItem(tender: item.tender!),
|
||||
|
||||
@@ -1,13 +1,31 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:tm_app/core/utils/size_config.dart';
|
||||
import 'package:tm_app/views/shared/responsive_builder.dart';
|
||||
import 'package:tm_app/view_models/liked_tenders_view_model.dart';
|
||||
import 'package:tm_app/views/liked_tenders/pages/liked_tenders_desktop_page.dart';
|
||||
import 'package:tm_app/views/liked_tenders/pages/liked_tenders_mobile_page.dart';
|
||||
import 'package:tm_app/views/liked_tenders/pages/liked_tenders_tablet_page.dart';
|
||||
import 'package:tm_app/views/shared/responsive_builder.dart';
|
||||
|
||||
class LikedTendersScreen extends StatelessWidget {
|
||||
class LikedTendersScreen extends StatefulWidget {
|
||||
const LikedTendersScreen({super.key});
|
||||
|
||||
@override
|
||||
State<LikedTendersScreen> createState() => _LikedTendersScreenState();
|
||||
}
|
||||
|
||||
class _LikedTendersScreenState extends State<LikedTendersScreen> {
|
||||
late final LikedTendersViewModel viewModel;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
viewModel = context.read<LikedTendersViewModel>();
|
||||
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
|
||||
viewModel.getLikedTenders(reset: true);
|
||||
});
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
SizeConfig.init(context);
|
||||
|
||||
@@ -68,7 +68,9 @@ class _LikedTendersTabletPageState extends State<LikedTendersTabletPage> {
|
||||
final feedback = viewModel.data?.data?.feedback ?? [];
|
||||
|
||||
if (feedback.isEmpty) {
|
||||
return const Center(child: Text('Nothing to show'));
|
||||
return const Center(
|
||||
child: Text('You haven’t liked any tenders yet.'),
|
||||
);
|
||||
}
|
||||
|
||||
final currentPage = viewModel.currentPage;
|
||||
|
||||
Reference in New Issue
Block a user