merged branches

This commit is contained in:
amirrezaghabeli
2025-08-12 09:11:26 +03:30
parent ba3becc709
commit a7e208a5de
58 changed files with 4584 additions and 2336 deletions
+26 -7
View File
@@ -1,6 +1,8 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:tm_app/core/theme/colors.dart';
import 'package:tm_app/core/utils/size_config.dart';
import 'package:tm_app/view_models/tenders_view_model.dart';
import 'package:tm_app/views/tenders/widgets/main_tenders_slider.dart';
class DesktopTendersPage extends StatelessWidget {
@@ -13,13 +15,30 @@ class DesktopTendersPage extends StatelessWidget {
backgroundColor: AppColors.backgroundColor,
body: Center(
child: SingleChildScrollView(
child: SizedBox(
width: 740,
height: 800,
child: Padding(
padding: EdgeInsets.symmetric(vertical: 24.0.h()),
child: MainTendersSlider(isDesktop: true),
),
child: Consumer<TendersViewModel>(
builder: (context, viewModel, child) {
if (viewModel.isLoading) {
return Center(
child: CircularProgressIndicator(
color: AppColors.jellyBean,
),
);
}
if (viewModel.errorMessage != null) {
return Center(child: Text(viewModel.errorMessage!));
}
return SizedBox(
width: 740,
height: 800,
child: Padding(
padding: EdgeInsets.symmetric(vertical: 24.0.h()),
child: MainTendersSlider(
tenders: viewModel.tendersResponse?.tenders ?? [],
isDesktop: true,
),
),
);
},
),
),
),
+21 -6
View File
@@ -1,10 +1,12 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:tm_app/core/utils/size_config.dart';
import 'package:tm_app/views/tenders/widgets/main_tenders_slider.dart';
import 'package:tm_app/view_models/tenders_view_model.dart';
import '../../../core/constants/strings.dart';
import '../../../core/theme/colors.dart';
import '../../shared/tender_app_bar.dart';
import '../widgets/main_tenders_slider.dart';
class MobileTendersPage extends StatelessWidget {
const MobileTendersPage({super.key});
@@ -15,11 +17,24 @@ class MobileTendersPage extends StatelessWidget {
child: Scaffold(
backgroundColor: AppColors.backgroundColor,
appBar: tenderMobileAppBar(title: AppStrings.tendersTitle),
body: SingleChildScrollView(
child: Padding(
padding: EdgeInsets.symmetric(vertical: 24.0.h()),
child: MainTendersSlider(),
),
body: Consumer<TendersViewModel>(
builder: (context, viewModel, child) {
if (viewModel.isLoading) {
return Center(
child: CircularProgressIndicator(color: AppColors.jellyBean),
);
}
if (viewModel.errorMessage != null) {
return Center(child: Text(viewModel.errorMessage!));
}
return Padding(
padding: EdgeInsets.symmetric(vertical: 24.0.h()),
child: MainTendersSlider(
tenders: viewModel.tendersResponse?.tenders ?? [],
),
);
},
),
),
);
+19 -7
View File
@@ -1,6 +1,8 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:tm_app/core/theme/colors.dart';
import 'package:tm_app/core/utils/size_config.dart';
import 'package:tm_app/view_models/tenders_view_model.dart';
import 'package:tm_app/views/tenders/widgets/main_tenders_slider.dart';
class TabletTendersPage extends StatelessWidget {
@@ -13,13 +15,23 @@ class TabletTendersPage extends StatelessWidget {
backgroundColor: AppColors.backgroundColor,
body: SingleChildScrollView(
child: Padding(
padding: EdgeInsets.only(
left: 24.0.w(),
right: 24.0.w(),
top: 128.0.h(),
),
child: MainTendersSlider(),
child: Consumer<TendersViewModel>(
builder: (context, viewModel, child) {
if (viewModel.isLoading) {
return Center(
child: CircularProgressIndicator(color: AppColors.jellyBean),
);
}
if (viewModel.errorMessage != null) {
return Center(child: Text(viewModel.errorMessage!));
}
return Padding(
padding: EdgeInsets.only(right: 24.0.w(), top: 128.0.h()),
child: MainTendersSlider(
tenders: viewModel.tendersResponse?.tenders ?? [],
),
);
},
),
),
),
@@ -1,15 +1,20 @@
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:tm_app/core/theme/colors.dart';
import 'package:tm_app/data/services/model/home/tender/tender_model.dart';
import '../../../core/constants/assets.dart';
import '../../../core/utils/size_config.dart';
import '../models/tender_model.dart';
import 'tender_card.dart';
class MainTendersSlider extends StatefulWidget {
const MainTendersSlider({super.key, this.isDesktop = false});
const MainTendersSlider({
required this.tenders,
super.key,
this.isDesktop = false,
});
final bool isDesktop;
final List<TenderModel> tenders;
@override
State<MainTendersSlider> createState() => _MainTendersSliderState();
@@ -39,7 +44,7 @@ class _MainTendersSliderState extends State<MainTendersSlider> {
curve: Curves.easeInOutCubic,
);
setState(() {
if (currentPage == sampleTenders.length) {
if (currentPage == widget.tenders.length) {
return;
}
currentPage = currentPage + 1;
@@ -62,14 +67,14 @@ class _MainTendersSliderState extends State<MainTendersSlider> {
child: PageView.builder(
controller: pageController,
scrollDirection: Axis.horizontal,
itemCount: sampleTenders.length,
itemCount: widget.tenders.length,
onPageChanged: (index) {
setState(() {
currentPage = index + 1;
});
},
itemBuilder: (context, index) {
final tender = sampleTenders[index];
final tender = widget.tenders[index];
return TenderCard(tender: tender, isDesktop: widget.isDesktop);
},
),
@@ -102,7 +107,7 @@ class _MainTendersSliderState extends State<MainTendersSlider> {
),
),
Text(
'$currentPage/${sampleTenders.length}',
'$currentPage/${widget.tenders.length}',
style: TextStyle(
fontSize: 14.0.sp(),
fontWeight: FontWeight.w500,
@@ -1,15 +1,15 @@
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:provider/provider.dart';
import 'package:tm_app/data/services/model/home/tender/tender_model.dart';
import 'package:tm_app/view_models/tenders_view_model.dart';
import 'package:tm_app/views/tenders/models/tender_model.dart';
import '../../../core/constants/assets.dart';
import '../../../core/theme/colors.dart';
import '../../../core/utils/size_config.dart';
class TenderActionButtons extends StatelessWidget {
final Tender tender;
final TenderModel tender;
final bool isDesktop;
const TenderActionButtons({
@@ -32,7 +32,7 @@ class TenderActionButtons extends StatelessWidget {
child: InkWell(
splashColor: Colors.transparent,
onTap: () {
viewModel.onDislike(tender);
viewModel.toggleDislike(tender);
},
child: Column(
children: [
@@ -42,7 +42,7 @@ class TenderActionButtons extends StatelessWidget {
fit: BoxFit.cover,
AssetsManager.dislike,
colorFilter: ColorFilter.mode(
viewModel.dislikedTenders.contains(tender)
tender.disliked ?? false
? AppColors.errorColor
: AppColors.grey50,
BlendMode.srcATop,
@@ -51,12 +51,12 @@ class TenderActionButtons extends StatelessWidget {
SizedBox(height: 8.0.h()),
if (!isDesktop)
Text(
'Like',
'Dislike',
style: TextStyle(
fontSize: 12.0.sp(),
fontWeight: FontWeight.w400,
color:
viewModel.dislikedTenders.contains(tender)
tender.disliked ?? false
? AppColors.errorColor
: AppColors.grey50,
),
@@ -72,7 +72,7 @@ class TenderActionButtons extends StatelessWidget {
child: InkWell(
splashColor: Colors.transparent,
onTap: () {
viewModel.onReject(tender);
viewModel.toggleReject(tender);
},
child: Column(
children: [
@@ -83,7 +83,7 @@ class TenderActionButtons extends StatelessWidget {
shape: BoxShape.circle,
border: Border.all(
color:
viewModel.rejectedTenders.contains(tender)
tender.rejected ?? false
? AppColors.errorColor
: AppColors.grey60,
width: 1.5.w(),
@@ -93,7 +93,7 @@ class TenderActionButtons extends StatelessWidget {
child: Icon(
Icons.close,
color:
viewModel.rejectedTenders.contains(tender)
tender.rejected ?? false
? AppColors.errorColor
: AppColors.grey60,
size: 16,
@@ -107,7 +107,7 @@ class TenderActionButtons extends StatelessWidget {
fontSize: 12.0.sp(),
fontWeight: FontWeight.w400,
color:
viewModel.rejectedTenders.contains(tender)
tender.rejected ?? false
? AppColors.errorColor
: AppColors.grey60,
),
@@ -123,7 +123,7 @@ class TenderActionButtons extends StatelessWidget {
child: InkWell(
splashColor: Colors.transparent,
onTap: () {
viewModel.onSubmit(tender);
viewModel.toggleSubmit(tender);
},
child: Column(
children: [
@@ -134,7 +134,7 @@ class TenderActionButtons extends StatelessWidget {
shape: BoxShape.circle,
border: Border.all(
color:
viewModel.submittedTenders.contains(tender)
tender.submitted ?? false
? AppColors.successColor
: AppColors.grey60,
width: 1.5.w(),
@@ -144,7 +144,7 @@ class TenderActionButtons extends StatelessWidget {
child: SvgPicture.asset(
AssetsManager.tick,
colorFilter: ColorFilter.mode(
viewModel.submittedTenders.contains(tender)
tender.submitted ?? false
? AppColors.successColor
: AppColors.grey60,
BlendMode.srcATop,
@@ -159,7 +159,7 @@ class TenderActionButtons extends StatelessWidget {
fontSize: 12.0.sp(),
fontWeight: FontWeight.w400,
color:
viewModel.submittedTenders.contains(tender)
tender.submitted ?? false
? AppColors.successColor
: AppColors.grey60,
),
@@ -175,7 +175,7 @@ class TenderActionButtons extends StatelessWidget {
child: InkWell(
splashColor: Colors.transparent,
onTap: () {
viewModel.onLike(tender);
viewModel.toggleLike(tender);
},
child: Column(
children: [
@@ -185,7 +185,7 @@ class TenderActionButtons extends StatelessWidget {
fit: BoxFit.cover,
AssetsManager.like,
colorFilter: ColorFilter.mode(
viewModel.likedTenders.contains(tender)
tender.liked ?? false
? AppColors.successColor
: AppColors.grey50,
BlendMode.srcATop,
@@ -199,7 +199,7 @@ class TenderActionButtons extends StatelessWidget {
fontSize: 12.0.sp(),
fontWeight: FontWeight.w400,
color:
viewModel.likedTenders.contains(tender)
tender.liked ?? false
? AppColors.successColor
: AppColors.grey50,
),
+10 -10
View File
@@ -2,15 +2,15 @@ import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:tm_app/core/constants/strings.dart';
import 'package:tm_app/core/routes/app_routes.dart';
import 'package:tm_app/data/services/model/home/tender/tender_model.dart';
import '../../../core/constants/assets.dart';
import '../../../core/theme/colors.dart';
import '../../../core/utils/size_config.dart';
import '../models/tender_model.dart';
import 'tender_action_buttons.dart';
class TenderCard extends StatelessWidget {
final Tender tender;
final TenderModel tender;
final bool isDesktop;
const TenderCard({required this.tender, super.key, this.isDesktop = false});
@@ -41,7 +41,7 @@ class TenderCard extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
tender.date,
tender.createdTime ?? '',
style: TextStyle(
color: AppColors.grey60,
fontSize: 12.0.sp(),
@@ -78,7 +78,7 @@ class TenderCard extends StatelessWidget {
),
),
Text(
tender.deadline,
tender.deadline ?? '',
style: TextStyle(
color: AppColors.grey80,
fontSize: 14.0.sp(),
@@ -92,7 +92,7 @@ class TenderCard extends StatelessWidget {
// Title
Text(
tender.title,
tender.title ?? '',
style: TextStyle(
color: AppColors.grey80,
fontSize: 16.0.sp(),
@@ -103,7 +103,7 @@ class TenderCard extends StatelessWidget {
// Description
Text(
tender.description,
tender.description ?? '',
style: TextStyle(
color: AppColors.grey70,
fontSize: 16.0.sp(),
@@ -115,7 +115,7 @@ class TenderCard extends StatelessWidget {
// Tender ID
Text(
tender.tenderId,
tender.tenderId ?? '',
style: TextStyle(
color: AppColors.grey,
fontSize: 14.0.sp(),
@@ -144,7 +144,7 @@ class TenderCard extends StatelessWidget {
),
),
Text(
'${tender.matchPercentage.toInt()}%',
'${tender.profileMatch?.toInt() ?? 0}%',
style: TextStyle(
color: AppColors.secondaryTextColor,
fontSize: 16.0.sp(),
@@ -165,7 +165,7 @@ class TenderCard extends StatelessWidget {
),
child: FractionallySizedBox(
alignment: Alignment.centerLeft,
widthFactor: tender.matchPercentage / 100,
widthFactor: tender.profileMatch ?? 0 / 100,
child: Container(
decoration: BoxDecoration(
color: AppColors.secondary50,
@@ -186,7 +186,7 @@ class TenderCard extends StatelessWidget {
SvgPicture.asset(AssetsManager.location),
SizedBox(width: 4.0.w()),
Text(
tender.location,
tender.location ?? '',
style: TextStyle(
color: AppColors.grey80,
fontSize: 14.0.sp(),