Update dependencies, enhance API endpoints, and refactor UI components
- Updated `pubspec.lock` to new package versions for `async`, `fake_async`, `leak_tracker`, and `vm_service`. - Modified API endpoint for unread notifications to include `event_type=PUSH`. - Refactored `CompletionOfDocumentsMobilePage` layout for improved structure. - Simplified `DetailDropDown` widget by removing unnecessary animations. - Updated `CommentBox` styling and adjusted padding for better UI consistency. - Replaced deprecated `FormCard` implementation in final completion pages with a new widget structure. - Enhanced button styles across various dialogs and pages for a cohesive design.
This commit is contained in:
@@ -15,5 +15,6 @@ class HomeApi {
|
||||
|
||||
static const String tenderApprovalStats = '/api/v1/tender-approvals/stats';
|
||||
static const String statsCompany = '/api/v1/feedback/stats/company';
|
||||
static const String checkUnreadNotifications = '/api/v1/notifications?seen=false&limit=1';
|
||||
static const String checkUnreadNotifications =
|
||||
'/api/v1/notifications?seen=false&limit=1&event_type=PUSH';
|
||||
}
|
||||
|
||||
@@ -13,14 +13,14 @@ class CompletionOfDocumentsMobilePage extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: AppColors.backgroundColor,
|
||||
appBar: appBar(
|
||||
context: context,
|
||||
title: CompletionOfDocumentsStrings.completionOfDocuments,
|
||||
),
|
||||
body: SafeArea(
|
||||
child: SingleChildScrollView(
|
||||
return SafeArea(
|
||||
child: Scaffold(
|
||||
backgroundColor: AppColors.backgroundColor,
|
||||
appBar: appBar(
|
||||
context: context,
|
||||
title: CompletionOfDocumentsStrings.completionOfDocuments,
|
||||
),
|
||||
body: SingleChildScrollView(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 16.0.w(),
|
||||
vertical: 12.0.h(),
|
||||
|
||||
@@ -16,30 +16,16 @@ class DetailDropDown extends StatefulWidget {
|
||||
class _DetailDropDownState extends State<DetailDropDown>
|
||||
with SingleTickerProviderStateMixin {
|
||||
bool isOpen = true;
|
||||
late AnimationController _animationController;
|
||||
late Animation<double> _rotationAnimation;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_animationController = AnimationController(
|
||||
duration: const Duration(milliseconds: 300),
|
||||
vsync: this,
|
||||
);
|
||||
_rotationAnimation = Tween<double>(begin: 0.0, end: 0.5).animate(
|
||||
CurvedAnimation(parent: _animationController, curve: Curves.elasticIn),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_animationController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
@@ -48,11 +34,6 @@ class _DetailDropDownState extends State<DetailDropDown>
|
||||
setState(() {
|
||||
isOpen = !isOpen;
|
||||
});
|
||||
if (isOpen) {
|
||||
_animationController.forward();
|
||||
} else {
|
||||
_animationController.reverse();
|
||||
}
|
||||
},
|
||||
child: Container(
|
||||
width: 24.0.w(),
|
||||
@@ -62,17 +43,12 @@ class _DetailDropDownState extends State<DetailDropDown>
|
||||
border: Border.all(color: AppColors.grey60),
|
||||
),
|
||||
alignment: Alignment.center,
|
||||
child: AnimatedBuilder(
|
||||
animation: _rotationAnimation,
|
||||
builder: (context, child) {
|
||||
return Icon(
|
||||
isOpen
|
||||
? CupertinoIcons.chevron_up
|
||||
: CupertinoIcons.chevron_down,
|
||||
color: AppColors.grey60,
|
||||
size: 12,
|
||||
);
|
||||
},
|
||||
child: Icon(
|
||||
isOpen
|
||||
? CupertinoIcons.chevron_up
|
||||
: CupertinoIcons.chevron_down,
|
||||
color: AppColors.grey60,
|
||||
size: 12,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -88,24 +64,20 @@ class _DetailDropDownState extends State<DetailDropDown>
|
||||
],
|
||||
),
|
||||
SizedBox(height: 12.0.h()),
|
||||
AnimatedSize(
|
||||
duration: const Duration(milliseconds: 300),
|
||||
curve: Curves.easeInOut,
|
||||
child:
|
||||
isOpen
|
||||
? Column(
|
||||
children:
|
||||
widget.items
|
||||
.map(
|
||||
(e) => Padding(
|
||||
padding: EdgeInsets.only(left: 12.0.w()),
|
||||
child: Text(e),
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
)
|
||||
: const SizedBox.shrink(),
|
||||
),
|
||||
isOpen
|
||||
? Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children:
|
||||
widget.items
|
||||
.map(
|
||||
(e) => Padding(
|
||||
padding: EdgeInsets.only(left: 12.0.w()),
|
||||
child: Text(e),
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
)
|
||||
: const SizedBox.shrink(),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
+1
-239
@@ -1,8 +1,5 @@
|
||||
import 'package:dotted_border/dotted_border.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:tm_app/core/constants/assets.dart';
|
||||
import 'package:tm_app/core/theme/colors.dart';
|
||||
import 'package:tm_app/core/utils/size_config.dart';
|
||||
import 'package:tm_app/view_models/final_completion_of_documents_view_model.dart';
|
||||
@@ -12,7 +9,7 @@ import 'package:tm_app/views/login/widgets/widgets.dart';
|
||||
import 'package:tm_app/views/shared/desktop_navigation_widget.dart';
|
||||
import 'package:tm_app/views/shared/tablet_desktop_appbar.dart';
|
||||
|
||||
import '../../shared/main_drop_down.dart';
|
||||
import '../widgets/form_card.dart';
|
||||
|
||||
class DesktopFinalCompletionOfDocumentsPage extends StatelessWidget {
|
||||
const DesktopFinalCompletionOfDocumentsPage({super.key});
|
||||
@@ -84,238 +81,3 @@ class DesktopFinalCompletionOfDocumentsPage extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class FormCard extends StatelessWidget {
|
||||
const FormCard({required this.viewModel, super.key});
|
||||
final FinalCompletionOfDocumentsViewModel viewModel;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
width: double.infinity,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 24),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
border: Border.all(color: AppColors.borderColor),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Container(
|
||||
width: double.infinity,
|
||||
height: 64.0,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 16),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
border: Border.all(color: AppColors.borderColor),
|
||||
),
|
||||
alignment: AlignmentDirectional.centerStart,
|
||||
child: Container(
|
||||
width: 118,
|
||||
height: 32,
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.yellow3,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
alignment: Alignment.center,
|
||||
child: const Text(
|
||||
'50% Completed',
|
||||
style: TextStyle(color: AppColors.yellow4),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 48.0),
|
||||
Text(
|
||||
FinalCompletionOfDocumentsStrings.numberOfServersListedTitle,
|
||||
style: TextStyle(
|
||||
fontSize: 16.0,
|
||||
fontWeight: FontWeight.w400,
|
||||
color: AppColors.grey60,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 12.0),
|
||||
Text(
|
||||
'12 servers across 2 data centers',
|
||||
style: TextStyle(
|
||||
fontSize: 16.0,
|
||||
fontWeight: FontWeight.w400,
|
||||
color: AppColors.grey80,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
Divider(color: AppColors.borderColor),
|
||||
const SizedBox(height: 24),
|
||||
Text(
|
||||
FinalCompletionOfDocumentsStrings
|
||||
.technicalTeamOrganizationChartUploadedTitle,
|
||||
style: TextStyle(
|
||||
fontSize: 16.0,
|
||||
fontWeight: FontWeight.w400,
|
||||
color: AppColors.grey60,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 12.0),
|
||||
Text(
|
||||
'PDF submitted with full team roles and structure',
|
||||
style: TextStyle(
|
||||
fontSize: 16.0,
|
||||
fontWeight: FontWeight.w400,
|
||||
color: AppColors.grey80,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
Divider(color: AppColors.borderColor),
|
||||
const SizedBox(height: 48),
|
||||
_titleDropDownRow(
|
||||
text:
|
||||
FinalCompletionOfDocumentsStrings
|
||||
.describeInfrastructureCapabilitiestitle,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
_uploadFileCard(viewModel: viewModel),
|
||||
const SizedBox(height: 40),
|
||||
_titleDropDownRow(
|
||||
text:
|
||||
FinalCompletionOfDocumentsStrings
|
||||
.uploadTechnicalTeamOrgChartTitle,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
_describeYourTeamTextField(),
|
||||
const SizedBox(height: 48),
|
||||
_titleDropDownRow(
|
||||
text:
|
||||
FinalCompletionOfDocumentsStrings
|
||||
.noCertificationInISO27001Title,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
_uploadFileCard(viewModel: viewModel),
|
||||
const SizedBox(height: 48),
|
||||
_titleDropDownRow(
|
||||
text:
|
||||
FinalCompletionOfDocumentsStrings
|
||||
.uploadCompletionCertificateTitle,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
_uploadFileCard(viewModel: viewModel),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _describeYourTeamTextField() {
|
||||
return TextFormField(
|
||||
maxLines: 5,
|
||||
decoration: InputDecoration(
|
||||
filled: true,
|
||||
fillColor: AppColors.grey0,
|
||||
hintText: FinalCompletionOfDocumentsStrings.describeYourTeamHint,
|
||||
hintStyle: TextStyle(
|
||||
fontSize: 12.0,
|
||||
fontWeight: FontWeight.w400,
|
||||
color: AppColors.grey60,
|
||||
),
|
||||
border: OutlineInputBorder(
|
||||
borderSide: const BorderSide(color: AppColors.secondaryborder2),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderSide: const BorderSide(color: AppColors.secondaryborder2),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderSide: const BorderSide(color: AppColors.secondaryborder2),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _uploadFileCard({
|
||||
required FinalCompletionOfDocumentsViewModel viewModel,
|
||||
}) {
|
||||
return InkWell(
|
||||
onTap: () => viewModel.pickFile(),
|
||||
child: Container(
|
||||
width: double.infinity,
|
||||
height: 140,
|
||||
decoration: BoxDecoration(color: AppColors.grey0),
|
||||
child: DottedBorder(
|
||||
options: const RoundedRectDottedBorderOptions(
|
||||
radius: Radius.circular(12),
|
||||
dashPattern: [4, 4],
|
||||
strokeWidth: 1,
|
||||
color: AppColors.secondaryborder,
|
||||
padding: EdgeInsets.all(16),
|
||||
),
|
||||
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
SvgPicture.asset(AssetsManager.uploadFile),
|
||||
const SizedBox(height: 12),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const Text(
|
||||
FinalCompletionOfDocumentsStrings.chooseFile,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: AppColors.mainBlue,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 4),
|
||||
Text(
|
||||
FinalCompletionOfDocumentsStrings.toUpload,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: AppColors.grey60,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
FinalCompletionOfDocumentsStrings.selectZipOrEtcTitle,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w400,
|
||||
color: AppColors.grey60,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _titleDropDownRow({required String text}) {
|
||||
return Row(
|
||||
children: [
|
||||
SvgPicture.asset(AssetsManager.dangerFill),
|
||||
const SizedBox(width: 8),
|
||||
Text(
|
||||
text,
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w400,
|
||||
color: AppColors.grey60,
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
MainDropDown(
|
||||
text: FinalCompletionOfDocumentsStrings.statusTitle,
|
||||
items: const [
|
||||
FinalCompletionOfDocumentsStrings.statusWaitingForOthers,
|
||||
FinalCompletionOfDocumentsStrings.statusToDo,
|
||||
FinalCompletionOfDocumentsStrings.statusDone,
|
||||
],
|
||||
onSelect: (String item) {},
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-249
@@ -1,19 +1,17 @@
|
||||
import 'package:dotted_border/dotted_border.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:tm_app/core/constants/assets.dart';
|
||||
import 'package:tm_app/core/theme/colors.dart';
|
||||
import 'package:tm_app/core/utils/size_config.dart';
|
||||
import 'package:tm_app/view_models/final_completion_of_documents_view_model.dart';
|
||||
import 'package:tm_app/views/final_completion_of_documents/strings/final_completion_of_documents_strings.dart';
|
||||
import 'package:tm_app/views/final_completion_of_documents/widgets/comment_box.dart';
|
||||
import 'package:tm_app/views/login/widgets/widgets.dart';
|
||||
import 'package:tm_app/views/shared/main_drop_down.dart';
|
||||
import 'package:tm_app/views/shared/tablet_desktop_appbar.dart';
|
||||
import 'package:tm_app/views/shared/tablet_navigation_widget.dart';
|
||||
import 'package:tm_app/views/shared/tender_app_bar.dart';
|
||||
|
||||
import '../widgets/form_card.dart';
|
||||
|
||||
class TabletFinalCompletionOfDocumentsPage extends StatelessWidget {
|
||||
const TabletFinalCompletionOfDocumentsPage({super.key});
|
||||
|
||||
@@ -96,248 +94,3 @@ class TabletFinalCompletionOfDocumentsPage extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class FormCard extends StatelessWidget {
|
||||
const FormCard({required this.viewModel, super.key});
|
||||
final FinalCompletionOfDocumentsViewModel viewModel;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
width: double.infinity,
|
||||
padding: EdgeInsets.symmetric(horizontal: 16.0.w(), vertical: 24.0.h()),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
border: Border.all(color: AppColors.borderColor),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
_progressCard(),
|
||||
SizedBox(height: 48.0.h()),
|
||||
_infoSection(
|
||||
title: FinalCompletionOfDocumentsStrings.numberOfServersListedTitle,
|
||||
value: '12 servers across 2 data centers',
|
||||
),
|
||||
SizedBox(height: 24.0.h()),
|
||||
Divider(color: AppColors.borderColor),
|
||||
SizedBox(height: 24.0.h()),
|
||||
_infoSection(
|
||||
title:
|
||||
FinalCompletionOfDocumentsStrings
|
||||
.technicalTeamOrganizationChartUploadedTitle,
|
||||
value: 'PDF submitted with full team roles and structure',
|
||||
),
|
||||
SizedBox(height: 24.0.h()),
|
||||
Divider(color: AppColors.borderColor),
|
||||
SizedBox(height: 48.0.h()),
|
||||
_titleDropDownRow(
|
||||
text:
|
||||
FinalCompletionOfDocumentsStrings
|
||||
.describeInfrastructureCapabilitiestitle,
|
||||
),
|
||||
SizedBox(height: 16.0.h()),
|
||||
_uploadFileCard(viewModel: viewModel),
|
||||
SizedBox(height: 40.0.h()),
|
||||
_titleDropDownRow(
|
||||
text:
|
||||
FinalCompletionOfDocumentsStrings
|
||||
.uploadTechnicalTeamOrgChartTitle,
|
||||
),
|
||||
SizedBox(height: 16.0.h()),
|
||||
_describeYourTeamTextField(),
|
||||
SizedBox(height: 48.0.h()),
|
||||
_titleDropDownRow(
|
||||
text:
|
||||
FinalCompletionOfDocumentsStrings
|
||||
.noCertificationInISO27001Title,
|
||||
),
|
||||
SizedBox(height: 16.0.h()),
|
||||
_uploadFileCard(viewModel: viewModel),
|
||||
SizedBox(height: 48.0.h()),
|
||||
_titleDropDownRow(
|
||||
text:
|
||||
FinalCompletionOfDocumentsStrings
|
||||
.uploadCompletionCertificateTitle,
|
||||
),
|
||||
SizedBox(height: 16.0.h()),
|
||||
_uploadFileCard(viewModel: viewModel),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _progressCard() {
|
||||
return Container(
|
||||
width: double.infinity,
|
||||
height: 64.0.h(),
|
||||
padding: EdgeInsets.symmetric(horizontal: 16.0.w(), vertical: 16.0.h()),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
border: Border.all(color: AppColors.borderColor),
|
||||
),
|
||||
alignment: AlignmentDirectional.centerStart,
|
||||
child: Container(
|
||||
width: 118.0.w(),
|
||||
height: 32.0.h(),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.yellow3,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
alignment: Alignment.center,
|
||||
child: Text(
|
||||
'50% Completed',
|
||||
style: TextStyle(color: AppColors.yellow4, fontSize: 14.0.sp()),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _infoSection({required String title, required String value}) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
title,
|
||||
style: TextStyle(
|
||||
fontSize: 16.0.sp(),
|
||||
fontWeight: FontWeight.w400,
|
||||
color: AppColors.grey60,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 12.0.h()),
|
||||
Text(
|
||||
value,
|
||||
style: TextStyle(
|
||||
fontSize: 16.0.sp(),
|
||||
fontWeight: FontWeight.w400,
|
||||
color: AppColors.grey80,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _describeYourTeamTextField() {
|
||||
return TextFormField(
|
||||
maxLines: 5,
|
||||
decoration: InputDecoration(
|
||||
filled: true,
|
||||
fillColor: AppColors.grey0,
|
||||
hintText: FinalCompletionOfDocumentsStrings.describeYourTeamHint,
|
||||
hintStyle: TextStyle(
|
||||
fontSize: 12.0.sp(),
|
||||
fontWeight: FontWeight.w400,
|
||||
color: AppColors.grey60,
|
||||
),
|
||||
border: OutlineInputBorder(
|
||||
borderSide: const BorderSide(color: AppColors.secondaryborder2),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderSide: const BorderSide(color: AppColors.secondaryborder2),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderSide: const BorderSide(color: AppColors.secondaryborder2),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _uploadFileCard({
|
||||
required FinalCompletionOfDocumentsViewModel viewModel,
|
||||
}) {
|
||||
return InkWell(
|
||||
onTap: () => viewModel.pickFile(),
|
||||
child: Container(
|
||||
width: double.infinity,
|
||||
height: 140.0.h(),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.grey0,
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
child: DottedBorder(
|
||||
options: RoundedRectDottedBorderOptions(
|
||||
radius: const Radius.circular(12),
|
||||
dashPattern: const [4, 4],
|
||||
strokeWidth: 1,
|
||||
color: AppColors.secondaryborder,
|
||||
padding: EdgeInsets.all(16.0.w()),
|
||||
),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
SvgPicture.asset(AssetsManager.uploadFile, height: 32.0.h()),
|
||||
SizedBox(height: 12.0.h()),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
FinalCompletionOfDocumentsStrings.chooseFile,
|
||||
style: TextStyle(
|
||||
fontSize: 14.0.sp(),
|
||||
fontWeight: FontWeight.w500,
|
||||
color: AppColors.mainBlue,
|
||||
),
|
||||
),
|
||||
SizedBox(width: 4.0.w()),
|
||||
Text(
|
||||
FinalCompletionOfDocumentsStrings.toUpload,
|
||||
style: TextStyle(
|
||||
fontSize: 14.0.sp(),
|
||||
fontWeight: FontWeight.w500,
|
||||
color: AppColors.grey60,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 8.0.h()),
|
||||
Text(
|
||||
FinalCompletionOfDocumentsStrings.selectZipOrEtcTitle,
|
||||
style: TextStyle(
|
||||
fontSize: 12.0.sp(),
|
||||
fontWeight: FontWeight.w400,
|
||||
color: AppColors.grey60,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _titleDropDownRow({required String text}) {
|
||||
return Row(
|
||||
children: [
|
||||
SvgPicture.asset(
|
||||
AssetsManager.dangerFill,
|
||||
height: 20.0.h(),
|
||||
width: 20.0.w(),
|
||||
),
|
||||
SizedBox(width: 8.0.w()),
|
||||
Expanded(
|
||||
child: Text(
|
||||
text,
|
||||
style: TextStyle(
|
||||
fontSize: 16.0.sp(),
|
||||
fontWeight: FontWeight.w400,
|
||||
color: AppColors.grey60,
|
||||
),
|
||||
),
|
||||
),
|
||||
MainDropDown(
|
||||
text: FinalCompletionOfDocumentsStrings.statusTitle,
|
||||
items: const [
|
||||
FinalCompletionOfDocumentsStrings.statusWaitingForOthers,
|
||||
FinalCompletionOfDocumentsStrings.statusToDo,
|
||||
FinalCompletionOfDocumentsStrings.statusDone,
|
||||
],
|
||||
onSelect: (String item) {},
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ class CommentBox extends StatelessWidget {
|
||||
return Container(
|
||||
height: 148,
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.yellow1,
|
||||
color: AppColors.orange10,
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
border: Border.all(color: AppColors.yellow2),
|
||||
),
|
||||
@@ -27,7 +27,13 @@ class CommentBox extends StatelessWidget {
|
||||
|
||||
child: Row(
|
||||
children: [
|
||||
SvgPicture.asset(AssetsManager.clipboardText),
|
||||
SvgPicture.asset(
|
||||
AssetsManager.clipboardText,
|
||||
colorFilter: ColorFilter.mode(
|
||||
AppColors.grey80,
|
||||
BlendMode.srcIn,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 16.0),
|
||||
Text(
|
||||
FinalCompletionOfDocumentsStrings.commentNoteTitle,
|
||||
@@ -41,8 +47,11 @@ class CommentBox extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
const Padding(
|
||||
padding: EdgeInsetsDirectional.only(start: 65, bottom: 10),
|
||||
Padding(
|
||||
padding: const EdgeInsetsDirectional.only(
|
||||
start: 65,
|
||||
bottom: 10,
|
||||
),
|
||||
child: SizedBox(
|
||||
width: 256,
|
||||
height: 78,
|
||||
@@ -53,7 +62,7 @@ class CommentBox extends StatelessWidget {
|
||||
fontSize: 14.0,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
fontWeight: FontWeight.w400,
|
||||
color: AppColors.grey,
|
||||
color: AppColors.grey70,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -0,0 +1,244 @@
|
||||
import 'package:dotted_border/dotted_border.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
|
||||
import '../../../core/constants/assets.dart' show AssetsManager;
|
||||
import '../../../core/theme/colors.dart';
|
||||
import '../../../view_models/final_completion_of_documents_view_model.dart';
|
||||
import '../../shared/main_drop_down.dart';
|
||||
import '../strings/final_completion_of_documents_strings.dart';
|
||||
|
||||
class FormCard extends StatelessWidget {
|
||||
const FormCard({required this.viewModel, super.key});
|
||||
final FinalCompletionOfDocumentsViewModel viewModel;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
width: double.infinity,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 24),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
border: Border.all(color: AppColors.borderColor),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Container(
|
||||
width: double.infinity,
|
||||
height: 64.0,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 16),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
border: Border.all(color: AppColors.borderColor),
|
||||
),
|
||||
alignment: AlignmentDirectional.centerStart,
|
||||
child: Container(
|
||||
width: 118,
|
||||
height: 32,
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.orange10,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
alignment: Alignment.center,
|
||||
child: const Text(
|
||||
'50% Completed',
|
||||
style: TextStyle(color: AppColors.yellow4),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 48.0),
|
||||
Text(
|
||||
FinalCompletionOfDocumentsStrings.numberOfServersListedTitle,
|
||||
style: TextStyle(
|
||||
fontSize: 16.0,
|
||||
fontWeight: FontWeight.w400,
|
||||
color: AppColors.grey60,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 12.0),
|
||||
Text(
|
||||
'12 servers across 2 data centers',
|
||||
style: TextStyle(
|
||||
fontSize: 16.0,
|
||||
fontWeight: FontWeight.w400,
|
||||
color: AppColors.grey80,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
Divider(color: AppColors.borderColor),
|
||||
const SizedBox(height: 24),
|
||||
Text(
|
||||
FinalCompletionOfDocumentsStrings
|
||||
.technicalTeamOrganizationChartUploadedTitle,
|
||||
style: TextStyle(
|
||||
fontSize: 16.0,
|
||||
fontWeight: FontWeight.w400,
|
||||
color: AppColors.grey60,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 12.0),
|
||||
Text(
|
||||
'PDF submitted with full team roles and structure',
|
||||
style: TextStyle(
|
||||
fontSize: 16.0,
|
||||
fontWeight: FontWeight.w400,
|
||||
color: AppColors.grey80,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
Divider(color: AppColors.borderColor),
|
||||
const SizedBox(height: 48),
|
||||
_titleDropDownRow(
|
||||
text:
|
||||
FinalCompletionOfDocumentsStrings
|
||||
.describeInfrastructureCapabilitiestitle,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
_uploadFileCard(viewModel: viewModel),
|
||||
const SizedBox(height: 40),
|
||||
_titleDropDownRow(
|
||||
text:
|
||||
FinalCompletionOfDocumentsStrings
|
||||
.uploadTechnicalTeamOrgChartTitle,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
_describeYourTeamTextField(),
|
||||
const SizedBox(height: 48),
|
||||
_titleDropDownRow(
|
||||
text:
|
||||
FinalCompletionOfDocumentsStrings
|
||||
.noCertificationInISO27001Title,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
_uploadFileCard(viewModel: viewModel),
|
||||
const SizedBox(height: 48),
|
||||
_titleDropDownRow(
|
||||
text:
|
||||
FinalCompletionOfDocumentsStrings
|
||||
.uploadCompletionCertificateTitle,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
_uploadFileCard(viewModel: viewModel),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _describeYourTeamTextField() {
|
||||
return TextFormField(
|
||||
maxLines: 5,
|
||||
decoration: InputDecoration(
|
||||
filled: true,
|
||||
fillColor: AppColors.grey0,
|
||||
hintText: FinalCompletionOfDocumentsStrings.describeYourTeamHint,
|
||||
hintStyle: TextStyle(
|
||||
fontSize: 12.0,
|
||||
fontWeight: FontWeight.w400,
|
||||
color: AppColors.grey60,
|
||||
),
|
||||
border: OutlineInputBorder(
|
||||
borderSide: const BorderSide(color: AppColors.secondaryborder2),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderSide: const BorderSide(color: AppColors.secondaryborder2),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderSide: const BorderSide(color: AppColors.secondaryborder2),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _uploadFileCard({
|
||||
required FinalCompletionOfDocumentsViewModel viewModel,
|
||||
}) {
|
||||
return InkWell(
|
||||
onTap: () => viewModel.pickFile(),
|
||||
child: Container(
|
||||
width: double.infinity,
|
||||
height: 140,
|
||||
decoration: BoxDecoration(color: AppColors.grey0),
|
||||
child: DottedBorder(
|
||||
options: const RoundedRectDottedBorderOptions(
|
||||
radius: Radius.circular(12),
|
||||
dashPattern: [4, 4],
|
||||
strokeWidth: 1,
|
||||
color: AppColors.secondaryborder,
|
||||
padding: EdgeInsets.all(16),
|
||||
),
|
||||
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
SvgPicture.asset(AssetsManager.uploadFile),
|
||||
const SizedBox(height: 12),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const Text(
|
||||
FinalCompletionOfDocumentsStrings.chooseFile,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: AppColors.mainBlue,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 4),
|
||||
Text(
|
||||
FinalCompletionOfDocumentsStrings.toUpload,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: AppColors.grey60,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
FinalCompletionOfDocumentsStrings.selectZipOrEtcTitle,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w400,
|
||||
color: AppColors.grey60,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _titleDropDownRow({required String text}) {
|
||||
return Row(
|
||||
children: [
|
||||
SvgPicture.asset(AssetsManager.dangerFill),
|
||||
const SizedBox(width: 8),
|
||||
Text(
|
||||
text,
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w400,
|
||||
color: AppColors.grey60,
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
MainDropDown(
|
||||
text: FinalCompletionOfDocumentsStrings.statusTitle,
|
||||
items: const [
|
||||
FinalCompletionOfDocumentsStrings.statusWaitingForOthers,
|
||||
FinalCompletionOfDocumentsStrings.statusToDo,
|
||||
FinalCompletionOfDocumentsStrings.statusDone,
|
||||
],
|
||||
onSelect: (String item) {},
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -124,7 +124,7 @@ class TendersListItem extends StatelessWidget {
|
||||
const Spacer(),
|
||||
BaseButton(
|
||||
text: HomeStrings.seeMoreButton,
|
||||
backgroundColor: AppColors.primary2,
|
||||
backgroundColor: AppColors.primary20,
|
||||
isEnabled: true,
|
||||
width: 100.0.w(),
|
||||
height: 40.0.h(),
|
||||
|
||||
@@ -27,7 +27,7 @@ class _SelectSubmissionBottomSheetState
|
||||
Container(
|
||||
width: double.infinity,
|
||||
// height: 272.0.h(),
|
||||
padding: EdgeInsets.fromLTRB(24.0.w(), 24.0.h(), 24.0.w(), 33.0.h()),
|
||||
padding: EdgeInsets.fromLTRB(24.0.w(), 12.0.h(), 24.0.w(), 33.0.h()),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.backgroundColor,
|
||||
borderRadius: const BorderRadius.only(
|
||||
@@ -37,6 +37,15 @@ class _SelectSubmissionBottomSheetState
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
Align(
|
||||
alignment: AlignmentDirectional.centerStart,
|
||||
child: IconButton(
|
||||
onPressed: () {
|
||||
context.pop();
|
||||
},
|
||||
icon: const Icon(Icons.close),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
CommonStrings.selectSubmission,
|
||||
style: TextStyle(
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:tm_app/core/utils/size_config.dart';
|
||||
import 'package:tm_app/views/shared/base_button.dart';
|
||||
|
||||
import '../../core/constants/common_strings.dart';
|
||||
import '../../core/constants/tender_submision_mode.dart';
|
||||
@@ -68,27 +69,39 @@ class _SelectSubmissionDialogState extends State<SelectSubmissionDialog> {
|
||||
child: Row(
|
||||
children: [
|
||||
const Spacer(),
|
||||
InkWell(
|
||||
onTap: () {
|
||||
// InkWell(
|
||||
// onTap: () {
|
||||
// context.pop();
|
||||
// },
|
||||
// child: Container(
|
||||
// width: 150,
|
||||
// height: 56.0,
|
||||
// decoration: BoxDecoration(
|
||||
// color: AppColors.red10,
|
||||
// borderRadius: BorderRadius.circular(100),
|
||||
// ),
|
||||
// alignment: Alignment.center,
|
||||
// child: Text(
|
||||
// CommonStrings.cancel,
|
||||
// style: TextStyle(
|
||||
// fontSize: 14.0.sp(),
|
||||
// fontWeight: FontWeight.w500,
|
||||
// color: AppColors.red20,
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
BaseButton(
|
||||
isEnabled: true,
|
||||
onPressed: () {
|
||||
context.pop();
|
||||
},
|
||||
child: Container(
|
||||
width: 150,
|
||||
height: 56.0,
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.red10,
|
||||
borderRadius: BorderRadius.circular(100),
|
||||
),
|
||||
alignment: Alignment.center,
|
||||
child: Text(
|
||||
CommonStrings.cancel,
|
||||
style: TextStyle(
|
||||
fontSize: 14.0.sp(),
|
||||
fontWeight: FontWeight.w500,
|
||||
color: AppColors.red20,
|
||||
),
|
||||
),
|
||||
),
|
||||
width: 150,
|
||||
height: 56.0,
|
||||
text: CommonStrings.cancel,
|
||||
backgroundColor: Colors.transparent,
|
||||
textColor: AppColors.errorColor,
|
||||
borderColor: AppColors.errorColor,
|
||||
),
|
||||
SizedBox(width: 10.0.w()),
|
||||
|
||||
|
||||
@@ -221,7 +221,7 @@ class _ActionButtons extends StatelessWidget {
|
||||
text: TendersStrings.filter,
|
||||
icon: AssetsManager.filter,
|
||||
iconColor: AppColors.textBlue,
|
||||
backgroundColor: AppColors.primary2,
|
||||
backgroundColor: AppColors.primary20,
|
||||
textColor: AppColors.textBlue,
|
||||
),
|
||||
SizedBox(width: 10.0.w()),
|
||||
@@ -253,7 +253,7 @@ class _ActionButtons extends StatelessWidget {
|
||||
text: TendersStrings.sort,
|
||||
icon: AssetsManager.sort,
|
||||
iconColor: AppColors.textBlue,
|
||||
backgroundColor: AppColors.primary2,
|
||||
backgroundColor: AppColors.primary20,
|
||||
textColor: AppColors.textBlue,
|
||||
),
|
||||
],
|
||||
@@ -322,7 +322,7 @@ class _DesktopPagination extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
SizedBox(width: 5.0.w()),
|
||||
SvgPicture.asset(AssetsManager.arrowDownSmall),
|
||||
Icon(Icons.arrow_drop_down, color: AppColors.grey80),
|
||||
SizedBox(width: 5.0.w()),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -230,7 +230,7 @@ class _TendersFilterDialogState extends State<TendersFilterDialog> {
|
||||
},
|
||||
text: TendersStrings.confirm,
|
||||
textColor: AppColors.textBlue,
|
||||
backgroundColor: AppColors.primary2,
|
||||
backgroundColor: AppColors.primary20,
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
@@ -103,7 +103,7 @@ class _TendersSortDialogState extends State<TendersSortDialog> {
|
||||
},
|
||||
text: TendersStrings.confirm,
|
||||
textColor: AppColors.textBlue,
|
||||
backgroundColor: AppColors.primary2,
|
||||
backgroundColor: AppColors.primary20,
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
+8
-8
@@ -45,10 +45,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: async
|
||||
sha256: d2872f9c19731c2e5f10444b14686eb7cc85c76274bd6c16e1816bff9a3bab63
|
||||
sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.12.0"
|
||||
version: "2.13.0"
|
||||
boolean_selector:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -269,10 +269,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: fake_async
|
||||
sha256: "6a95e56b2449df2273fd8c45a662d6947ce1ebb7aafe80e550a3f68297f3cacc"
|
||||
sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.2"
|
||||
version: "1.3.3"
|
||||
ffi:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -572,10 +572,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: leak_tracker
|
||||
sha256: c35baad643ba394b40aac41080300150a4f08fd0fd6a10378f8f7c6bc161acec
|
||||
sha256: "6bb818ecbdffe216e81182c2f0714a2e62b593f4a4f13098713ff1685dfb6ab0"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "10.0.8"
|
||||
version: "10.0.9"
|
||||
leak_tracker_flutter_testing:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -1049,10 +1049,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vm_service
|
||||
sha256: "0968250880a6c5fe7edc067ed0a13d4bae1577fe2771dcf3010d52c4a9d3ca14"
|
||||
sha256: ddfa8d30d89985b96407efce8acbdd124701f96741f2d981ca860662f1c0dc02
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "14.3.1"
|
||||
version: "15.0.0"
|
||||
watcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
||||
Reference in New Issue
Block a user