diff --git a/assets/icons/left-arrow.svg b/assets/icons/left-arrow.svg
new file mode 100644
index 0000000..703721b
--- /dev/null
+++ b/assets/icons/left-arrow.svg
@@ -0,0 +1,4 @@
+
diff --git a/lib/core/config/app_config.dart b/lib/core/config/app_config.dart
index b23e7de..d1e38d9 100644
--- a/lib/core/config/app_config.dart
+++ b/lib/core/config/app_config.dart
@@ -8,13 +8,13 @@ class AppConfig {
// این متد بر اساس محیط فعال، URL مناسب را برمیگرداند.
static String get apiBaseUrl {
- return 'http://10.0.2.2:8081';
+ // return 'http://10.0.2.2:8081';
// return '192.168.1.103:8081';
// if (isDevelopment) {
// // Handle different platforms for local development
// if (kIsWeb) {
// For web, use localhost
- // return 'https://app.opplens.com';
+ return 'https://app.opplens.com';
// return 'http://localhost:8081';
// } else {
// For Android emulator, use 10.0.2.2 (special IP for host machine)
diff --git a/lib/core/constants/assets.dart b/lib/core/constants/assets.dart
index e0088c3..33252ae 100644
--- a/lib/core/constants/assets.dart
+++ b/lib/core/constants/assets.dart
@@ -47,6 +47,7 @@ class AssetsManager {
static const shield = 'assets/icons/shield.svg';
static const edit = 'assets/icons/edit.svg';
static const arrowRight = 'assets/icons/arrow-right.svg';
+ static const leftArrow = 'assets/icons/left-arrow.svg';
static const notification = 'assets/icons/notification.svg';
static const danger = 'assets/icons/danger.svg';
diff --git a/lib/views/detail/pages/detail_mobile_page.dart b/lib/views/detail/pages/detail_mobile_page.dart
index 3f66d3d..ced899d 100644
--- a/lib/views/detail/pages/detail_mobile_page.dart
+++ b/lib/views/detail/pages/detail_mobile_page.dart
@@ -86,50 +86,55 @@ class _TenderDetailMobilePageState extends State {
});
}
},
- child: Scaffold(
- backgroundColor: AppColors.backgroundColor,
- appBar: appBar(
- context: context,
- title: TenderDetailsStrings.tenderDetailTitle,
- ),
- body: Consumer(
- builder: (context, tenderViewModel, child) {
- if (tenderViewModel.isLoading) {
- return const Center(
- child: CircularProgressIndicator(color: AppColors.secondary50),
- );
- }
+ child: Directionality(
+ textDirection: TextDirection.rtl,
+ child: Scaffold(
+ backgroundColor: AppColors.backgroundColor,
+ appBar: appBar(
+ context: context,
+ title: TenderDetailsStrings.tenderDetailTitle,
+ ),
+ body: Consumer(
+ builder: (context, tenderViewModel, child) {
+ if (tenderViewModel.isLoading) {
+ return const Center(
+ child: CircularProgressIndicator(
+ color: AppColors.secondary50,
+ ),
+ );
+ }
- if (tenderViewModel.errorMessage != null) {
- return Center(child: Text(tenderViewModel.errorMessage!));
- }
+ if (tenderViewModel.errorMessage != null) {
+ return Center(child: Text(tenderViewModel.errorMessage!));
+ }
- final detail = tenderViewModel.tenderDetail;
- if (detail == null) {
- return const Center(
- child: Text(TenderDetailsStrings.tenderNoData),
- );
- }
+ final detail = tenderViewModel.tenderDetail;
+ if (detail == null) {
+ return const Center(
+ child: Text(TenderDetailsStrings.tenderNoData),
+ );
+ }
- return SingleChildScrollView(
- child: Padding(
- padding: EdgeInsets.symmetric(
- horizontal: 16.0.w(),
- vertical: 16.0.h(),
+ return SingleChildScrollView(
+ child: Padding(
+ padding: EdgeInsets.symmetric(
+ horizontal: 16.0.w(),
+ vertical: 16.0.h(),
+ ),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ TenderDetailHeader(isScreenBig: false, detail: detail),
+ SizedBox(height: 24.0.h()),
+ TenderDetailCard(detail: detail),
+ SizedBox(height: 24.0.h()),
+ TenderDetailActions(isScreenBig: false, detail: detail),
+ ],
+ ),
),
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- TenderDetailHeader(isScreenBig: false, detail: detail),
- SizedBox(height: 24.0.h()),
- TenderDetailCard(detail: detail),
- SizedBox(height: 24.0.h()),
- TenderDetailActions(isScreenBig: false, detail: detail),
- ],
- ),
- ),
- );
- },
+ );
+ },
+ ),
),
),
);
diff --git a/lib/views/home/pages/d_home_page.dart b/lib/views/home/pages/d_home_page.dart
index 06861c0..f81370a 100644
--- a/lib/views/home/pages/d_home_page.dart
+++ b/lib/views/home/pages/d_home_page.dart
@@ -182,7 +182,7 @@ class DesktopHomePage extends StatelessWidget {
return ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 740),
child: Align(
- alignment: Alignment.centerLeft,
+ alignment: AlignmentDirectional.centerStart,
child: Text(
isYourTenders
? HomeStrings.yourTenders
diff --git a/lib/views/home/tender_card.dart b/lib/views/home/tender_card.dart
index 2660767..ec20ef5 100644
--- a/lib/views/home/tender_card.dart
+++ b/lib/views/home/tender_card.dart
@@ -31,6 +31,7 @@ class TenderCard extends StatelessWidget {
@override
Widget build(BuildContext context) {
+ final directionality = Directionality.of(context);
return InkWell(
onTap: enableTap ? onTap : null,
child: Container(
@@ -67,7 +68,15 @@ class TenderCard extends StatelessWidget {
),
),
enableTap
- ? SvgPicture.asset(AssetsManager.arrowRight)
+ ? SvgPicture.asset(
+ directionality == TextDirection.rtl
+ ? AssetsManager.leftArrow
+ : AssetsManager.arrowRight,
+ colorFilter: ColorFilter.mode(
+ AppColors.grey50,
+ BlendMode.srcIn,
+ ),
+ )
: const SizedBox(),
],
),
diff --git a/lib/views/home/tenders_list_item.dart b/lib/views/home/tenders_list_item.dart
index a27cb60..510048c 100644
--- a/lib/views/home/tenders_list_item.dart
+++ b/lib/views/home/tenders_list_item.dart
@@ -87,9 +87,10 @@ class TendersListItem extends StatelessWidget {
width: double.infinity,
child: Text(
tender.description!,
- textAlign: TextAlign.left,
+ textAlign: TextAlign.start,
maxLines: 4,
overflow: TextOverflow.ellipsis,
+
style: TextStyle(
fontSize: 14.0.sp(),
fontWeight: FontWeight.w400,
diff --git a/lib/views/liked_tenders/pages/liked_tenders_desktop_page.dart b/lib/views/liked_tenders/pages/liked_tenders_desktop_page.dart
index b4f8387..172d724 100644
--- a/lib/views/liked_tenders/pages/liked_tenders_desktop_page.dart
+++ b/lib/views/liked_tenders/pages/liked_tenders_desktop_page.dart
@@ -56,9 +56,7 @@ class _LikedTendersDesktopPageState extends State {
backgroundColor: AppColors.backgroundColor,
endDrawer: Drawer(
backgroundColor: AppColors.backgroundColor,
- shape: const RoundedRectangleBorder(
- borderRadius: BorderRadius.horizontal(left: Radius.circular(20)),
- ),
+
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
@@ -131,59 +129,53 @@ class _LikedTendersDesktopPageState extends State {
return Column(
children: [
Expanded(
- child: RefreshIndicator(
- onRefresh: () async {
- await viewModel.getLikedTenders(reset: true);
- },
- child: ListView.builder(
- padding: EdgeInsets.symmetric(
- horizontal: 24.0.w(),
- vertical: 15.0.h(),
- ),
- itemCount: feedback.length,
- itemBuilder: (context, index) {
- final item = feedback[index];
- TenderApprovalsData? approval;
- bool hasApproval = viewModel
- .hasTenderApprovalForTender(item.tenderId!);
- if (hasApproval) {
- approval = viewModel
- .getApprovalStatusForTender(
- item.tenderId!,
- );
- } else {
- approval = null;
- }
- return Padding(
- padding: EdgeInsets.only(bottom: 20.0.h()),
- child: Dismissible(
- key: ValueKey(item.tenderId ?? index),
- direction: DismissDirection.endToStart,
- background: Container(
- alignment: Alignment.centerRight,
- padding: EdgeInsets.symmetric(
- horizontal: 20.0.w(),
- ),
- child: SvgPicture.asset(
- AssetsManager.trash,
- ),
+ child: ListView.builder(
+ padding: EdgeInsets.symmetric(
+ horizontal: 24.0.w(),
+ vertical: 15.0.h(),
+ ),
+ itemCount: feedback.length,
+ itemBuilder: (context, index) {
+ final item = feedback[index];
+ TenderApprovalsData? approval;
+ bool hasApproval = viewModel
+ .hasTenderApprovalForTender(item.tenderId!);
+ if (hasApproval) {
+ approval = viewModel.getApprovalStatusForTender(
+ item.tenderId!,
+ );
+ } else {
+ approval = null;
+ }
+ return Padding(
+ padding: EdgeInsets.only(bottom: 20.0.h()),
+ child: Dismissible(
+ key: ValueKey(item.tenderId ?? index),
+ direction: DismissDirection.endToStart,
+ background: Container(
+ alignment: Alignment.centerRight,
+ padding: EdgeInsets.symmetric(
+ horizontal: 20.0.w(),
),
- onDismissed: (_) {
- if (item.tenderId != null) {
- viewModel.removeTenderById(
- item.tenderId!,
- );
- }
- },
- child: LikedListItem(
- tender: item.tender!,
- approval: approval,
- isDesktop: true,
+ child: SvgPicture.asset(
+ AssetsManager.trash,
),
),
- );
- },
- ),
+ onDismissed: (_) {
+ if (item.tenderId != null) {
+ viewModel.removeTenderById(
+ item.tenderId!,
+ );
+ }
+ },
+ child: LikedListItem(
+ tender: item.tender!,
+ approval: approval,
+ isDesktop: true,
+ ),
+ ),
+ );
+ },
),
),
diff --git a/lib/views/profile/pages/d_profile_page.dart b/lib/views/profile/pages/d_profile_page.dart
index 0ec481d..6a0f00d 100644
--- a/lib/views/profile/pages/d_profile_page.dart
+++ b/lib/views/profile/pages/d_profile_page.dart
@@ -140,7 +140,7 @@ class _DesktopProfilePageState extends State {
SizedBox(height: 24.0.h()),
// Spacer(),
Align(
- alignment: Alignment.centerRight,
+ alignment: AlignmentDirectional.centerEnd,
child: InkWell(
onTap: () => viewModel.logout(),
borderRadius: BorderRadius.circular(100),
diff --git a/lib/views/profile/pages/t_profile_page.dart b/lib/views/profile/pages/t_profile_page.dart
index 19a5c49..9673336 100644
--- a/lib/views/profile/pages/t_profile_page.dart
+++ b/lib/views/profile/pages/t_profile_page.dart
@@ -145,7 +145,7 @@ class _TabletProfilePageState extends State {
SizedBox(height: 24.0.h()),
// Spacer(),
Align(
- alignment: Alignment.centerRight,
+ alignment: AlignmentDirectional.centerStart,
child: InkWell(
onTap: () => viewModel.logout(),
borderRadius: BorderRadius.circular(100),
diff --git a/lib/views/shared/tender_app_bar.dart b/lib/views/shared/tender_app_bar.dart
index 58cf072..13893c7 100644
--- a/lib/views/shared/tender_app_bar.dart
+++ b/lib/views/shared/tender_app_bar.dart
@@ -35,6 +35,7 @@ PreferredSizeWidget appBar({
required BuildContext context,
required String title,
}) {
+ final isRtl = Directionality.of(context) == TextDirection.rtl;
return PreferredSize(
preferredSize: const Size.fromHeight(60),
child: AppBar(
@@ -43,7 +44,7 @@ PreferredSizeWidget appBar({
titleSpacing: 0,
leading: IconButton(
icon: SvgPicture.asset(
- AssetsManager.arrowLeft,
+ isRtl ? AssetsManager.arrowRight : AssetsManager.arrowLeft,
height: 24.0.w(),
width: 24.0.w(),
),
diff --git a/lib/views/tenders/pages/t_tenders_page.dart b/lib/views/tenders/pages/t_tenders_page.dart
index f2f1846..53d03dd 100644
--- a/lib/views/tenders/pages/t_tenders_page.dart
+++ b/lib/views/tenders/pages/t_tenders_page.dart
@@ -34,30 +34,35 @@ class _TabletTendersPageState extends State {
backgroundColor: AppColors.backgroundColor,
appBar: tabletAppBar(title: TendersStrings.tendersTitle, key: key),
drawer: const TabletNavigationWidget(currentIndex: 1),
- body: SingleChildScrollView(
- child: Consumer(
- builder: (context, viewModel, child) {
- if (viewModel.isLoading) {
- return const Center(
- child: CircularProgressIndicator(color: AppColors.jellyBean),
- );
- }
- if (viewModel.errorMessage != null) {
- return Center(child: Text(viewModel.errorMessage!));
- }
- if ((viewModel.tendersResponse?.data?.tenders == null ||
- viewModel.tendersResponse!.data!.tenders!.isEmpty) &&
- viewModel.isLoading == false) {
- return const Center(child: Text(CommonStrings.noData));
- }
- return Padding(
- padding: EdgeInsets.only(right: 24.0.w(), top: 128.0.h()),
- child: MainTendersSlider(
- tenders: viewModel.tendersResponse?.data?.tenders ?? [],
- ),
+ body: Consumer(
+ builder: (context, viewModel, child) {
+ if (viewModel.isLoading) {
+ return const Center(
+ child: CircularProgressIndicator(color: AppColors.jellyBean),
);
- },
- ),
+ }
+ if (viewModel.errorMessage != null) {
+ return Center(child: Text(viewModel.errorMessage!));
+ }
+ if ((viewModel.tendersResponse?.data?.tenders == null ||
+ viewModel.tendersResponse!.data!.tenders!.isEmpty) &&
+ viewModel.isLoading == false) {
+ return const Center(child: Text(CommonStrings.noData));
+ }
+ return Expanded(
+ child: SingleChildScrollView(
+ child: Padding(
+ padding: EdgeInsetsDirectional.only(
+ end: 24.0.w(),
+ top: 128.0.h(),
+ ),
+ child: MainTendersSlider(
+ tenders: viewModel.tendersResponse?.data?.tenders ?? [],
+ ),
+ ),
+ ),
+ );
+ },
),
);
}
diff --git a/lib/views/tenders/widgets/main_tenders_slider.dart b/lib/views/tenders/widgets/main_tenders_slider.dart
index 4c3526b..1ff7aae 100644
--- a/lib/views/tenders/widgets/main_tenders_slider.dart
+++ b/lib/views/tenders/widgets/main_tenders_slider.dart
@@ -83,8 +83,11 @@ class _MainTendersSliderState extends State {
@override
Widget build(BuildContext context) {
+ bool isLtr = Directionality.of(context) == TextDirection.ltr;
return SingleChildScrollView(
- child: Stack(children: [_tendersPageView(), _nextPreviousArrows()]),
+ child: Stack(
+ children: [_tendersPageView(), _nextPreviousArrows(isLtr: isLtr)],
+ ),
);
}
@@ -127,43 +130,48 @@ class _MainTendersSliderState extends State {
);
}
- Widget _nextPreviousArrows() {
- return Positioned(
+ Widget _nextPreviousArrows({required bool isLtr}) {
+ return PositionedDirectional(
top: 607.0.h(),
bottom: 52.0.h(),
- left: 9.0.w(),
- right: 9.0.w(),
+ start: 9.0.w(),
+ end: 9.0.w(),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
- children: [_leftArrowButton(), _pageNumberText(), _rightArrowButton()],
+ children: [
+ _leftArrowButton(isLtr: isLtr),
+ _pageNumberText(),
+ _rightArrowButton(isLtr: isLtr),
+ ],
),
);
}
- Widget _leftArrowButton() {
- return Visibility(
- visible: currentPage != 1,
- child: InkWell(
- borderRadius: BorderRadius.circular(100),
- onTap: _goToPreviousPage,
- child: Container(
- width: 32.0.h(),
- height: 32.0.h(),
- decoration: BoxDecoration(
- shape: BoxShape.circle,
- border: Border.all(color: AppColors.iconColor, width: 1.5),
- ),
- alignment: Alignment.center,
- child: SvgPicture.asset(
- AssetsManager.arrowLeftSmall,
- colorFilter: ColorFilter.mode(
- AppColors.iconColor,
- BlendMode.srcATop,
+ Widget _leftArrowButton({required bool isLtr}) {
+ return currentPage != 1
+ ? InkWell(
+ borderRadius: BorderRadius.circular(100),
+ onTap: _goToPreviousPage,
+ child: Container(
+ width: 32.0.h(),
+ height: 32.0.h(),
+ decoration: BoxDecoration(
+ shape: BoxShape.circle,
+ border: Border.all(color: AppColors.iconColor, width: 1.5),
+ ),
+ alignment: Alignment.center,
+ child: SvgPicture.asset(
+ isLtr
+ ? AssetsManager.arrowLeftSmall
+ : AssetsManager.arrowRightSmall,
+ colorFilter: ColorFilter.mode(
+ AppColors.iconColor,
+ BlendMode.srcATop,
+ ),
),
),
- ),
- ),
- );
+ )
+ : SizedBox(width: 32.0.h(), height: 32.0.h());
}
Widget _pageNumberText() {
@@ -195,29 +203,30 @@ class _MainTendersSliderState extends State {
);
}
- Widget _rightArrowButton() {
- return Visibility(
- visible: currentPage != widget.tenders.length,
- child: InkWell(
- borderRadius: BorderRadius.circular(100),
- onTap: _goToNextPage,
- child: Container(
- width: 32.0.h(),
- height: 32.0.h(),
- decoration: BoxDecoration(
- shape: BoxShape.circle,
- border: Border.all(color: AppColors.iconColor, width: 1.5),
- ),
- alignment: Alignment.center,
- child: SvgPicture.asset(
- AssetsManager.arrowRightSmall,
- colorFilter: ColorFilter.mode(
- AppColors.iconColor,
- BlendMode.srcATop,
+ Widget _rightArrowButton({required bool isLtr}) {
+ return currentPage != widget.tenders.length
+ ? InkWell(
+ borderRadius: BorderRadius.circular(100),
+ onTap: _goToNextPage,
+ child: Container(
+ width: 32.0.h(),
+ height: 32.0.h(),
+ decoration: BoxDecoration(
+ shape: BoxShape.circle,
+ border: Border.all(color: AppColors.iconColor, width: 1.5),
+ ),
+ alignment: Alignment.center,
+ child: SvgPicture.asset(
+ isLtr
+ ? AssetsManager.arrowRightSmall
+ : AssetsManager.arrowLeftSmall,
+ colorFilter: ColorFilter.mode(
+ AppColors.iconColor,
+ BlendMode.srcATop,
+ ),
),
),
- ),
- ),
- );
+ )
+ : SizedBox(width: 32.0.h(), height: 32.0.h());
}
}
diff --git a/lib/views/your_tenders/pages/your_tenders_mobile_page.dart b/lib/views/your_tenders/pages/your_tenders_mobile_page.dart
index e4ca33c..12d6356 100644
--- a/lib/views/your_tenders/pages/your_tenders_mobile_page.dart
+++ b/lib/views/your_tenders/pages/your_tenders_mobile_page.dart
@@ -35,74 +35,77 @@ class _YourTendersMobilePageState extends State {
@override
Widget build(BuildContext context) {
- return Scaffold(
- backgroundColor: AppColors.backgroundColor,
- appBar: appBar(context: context, title: YourTendersStrings.yourTenders),
- body: Column(
- children: [
- const FilterButton(platformType: PlatformType.mobile),
- Expanded(
- child: Consumer(
- builder: (context, viewModel, child) {
- if (viewModel.isLoading &&
- (viewModel.data?.data?.tenders ?? []).isEmpty &&
- (viewModel.likedTendersData?.data?.feedback ?? [])
- .isEmpty) {
- return const Center(
- child: CircularProgressIndicator(
- color: AppColors.secondary50,
- ),
- );
- }
-
- if (viewModel.errorMessage != null) {
- return Center(child: Text(viewModel.errorMessage!));
- }
-
- return Column(
- children: [
- if (viewModel.selectedStatus ==
- YourTendersStrings.likeTenders &&
- viewModel.likedTendersData != null)
- Expanded(
- child: LikedDislikedTendersList(
- data: viewModel.likedTendersData!,
- status: TenderFeedback.liked.value,
- isDesktop: false,
- isMobile: true,
- ),
- )
- else if (viewModel.selectedStatus ==
- YourTendersStrings.dislikeTenders &&
- viewModel.likedTendersData != null)
- Expanded(
- child: LikedDislikedTendersList(
- data: viewModel.likedTendersData!,
- status: TenderFeedback.disliked.value,
- isDesktop: false,
- isMobile: true,
- ),
- )
- else if (viewModel.data != null)
- Expanded(
- child: TendersSubmitted(
- approvedTenders: viewModel.data!,
- isDesktop: false,
- isMobile: true,
- ),
- )
- else
- const Expanded(
- child: Center(
- child: Text(YourTendersStrings.noTenders),
- ),
+ return Directionality(
+ textDirection: TextDirection.rtl,
+ child: Scaffold(
+ backgroundColor: AppColors.backgroundColor,
+ appBar: appBar(context: context, title: YourTendersStrings.yourTenders),
+ body: Column(
+ children: [
+ const FilterButton(platformType: PlatformType.mobile),
+ Expanded(
+ child: Consumer(
+ builder: (context, viewModel, child) {
+ if (viewModel.isLoading &&
+ (viewModel.data?.data?.tenders ?? []).isEmpty &&
+ (viewModel.likedTendersData?.data?.feedback ?? [])
+ .isEmpty) {
+ return const Center(
+ child: CircularProgressIndicator(
+ color: AppColors.secondary50,
),
- ],
- );
- },
+ );
+ }
+
+ if (viewModel.errorMessage != null) {
+ return Center(child: Text(viewModel.errorMessage!));
+ }
+
+ return Column(
+ children: [
+ if (viewModel.selectedStatus ==
+ YourTendersStrings.likeTenders &&
+ viewModel.likedTendersData != null)
+ Expanded(
+ child: LikedDislikedTendersList(
+ data: viewModel.likedTendersData!,
+ status: TenderFeedback.liked.value,
+ isDesktop: false,
+ isMobile: true,
+ ),
+ )
+ else if (viewModel.selectedStatus ==
+ YourTendersStrings.dislikeTenders &&
+ viewModel.likedTendersData != null)
+ Expanded(
+ child: LikedDislikedTendersList(
+ data: viewModel.likedTendersData!,
+ status: TenderFeedback.disliked.value,
+ isDesktop: false,
+ isMobile: true,
+ ),
+ )
+ else if (viewModel.data != null)
+ Expanded(
+ child: TendersSubmitted(
+ approvedTenders: viewModel.data!,
+ isDesktop: false,
+ isMobile: true,
+ ),
+ )
+ else
+ const Expanded(
+ child: Center(
+ child: Text(YourTendersStrings.noTenders),
+ ),
+ ),
+ ],
+ );
+ },
+ ),
),
- ),
- ],
+ ],
+ ),
),
);
}