|
|
|
@ -1,9 +1,11 @@
|
|
|
|
import 'package:flutter/cupertino.dart';
|
|
|
|
import 'package:flutter/cupertino.dart';
|
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
|
|
|
|
import 'package:flutter_svg/flutter_svg.dart';
|
|
|
|
import 'package:provider/provider.dart';
|
|
|
|
import 'package:provider/provider.dart';
|
|
|
|
import 'package:test_sa/controllers/providers/api/user_provider.dart';
|
|
|
|
import 'package:test_sa/controllers/providers/api/user_provider.dart';
|
|
|
|
import 'package:test_sa/extensions/context_extension.dart';
|
|
|
|
import 'package:test_sa/extensions/context_extension.dart';
|
|
|
|
import 'package:test_sa/extensions/int_extensions.dart';
|
|
|
|
import 'package:test_sa/extensions/int_extensions.dart';
|
|
|
|
|
|
|
|
import 'package:test_sa/extensions/string_extensions.dart';
|
|
|
|
import 'package:test_sa/extensions/text_extensions.dart';
|
|
|
|
import 'package:test_sa/extensions/text_extensions.dart';
|
|
|
|
import 'package:test_sa/extensions/widget_extensions.dart';
|
|
|
|
import 'package:test_sa/extensions/widget_extensions.dart';
|
|
|
|
import 'package:test_sa/helper/utils.dart';
|
|
|
|
import 'package:test_sa/helper/utils.dart';
|
|
|
|
@ -12,16 +14,18 @@ import 'package:test_sa/models/enums/work_order_next_step.dart';
|
|
|
|
import 'package:test_sa/models/helper_data_models/workorder/work_order_helper_models.dart';
|
|
|
|
import 'package:test_sa/models/helper_data_models/workorder/work_order_helper_models.dart';
|
|
|
|
import 'package:test_sa/modules/cm_module/cm_detail_provider.dart';
|
|
|
|
import 'package:test_sa/modules/cm_module/cm_detail_provider.dart';
|
|
|
|
import 'package:test_sa/modules/cm_module/views/components/bottom_sheets/service_request_bottomsheet.dart';
|
|
|
|
import 'package:test_sa/modules/cm_module/views/components/bottom_sheets/service_request_bottomsheet.dart';
|
|
|
|
import 'package:test_sa/modules/cx_module/chat/chat_page.dart';
|
|
|
|
|
|
|
|
import 'package:test_sa/modules/cx_module/chat/chat_provider.dart';
|
|
|
|
import 'package:test_sa/modules/cx_module/chat/chat_provider.dart';
|
|
|
|
import 'package:test_sa/modules/cx_module/chat/chat_widget.dart';
|
|
|
|
import 'package:test_sa/modules/cx_module/chat/chat_widget.dart';
|
|
|
|
import 'package:test_sa/modules/cx_module/survey/survey_page.dart';
|
|
|
|
import 'package:test_sa/modules/export_module/provider/export_provider.dart';
|
|
|
|
import 'package:test_sa/modules/loan_module/pages/create_loan_request_page.dart';
|
|
|
|
import 'package:test_sa/modules/loan_module/pages/create_loan_request_page.dart';
|
|
|
|
import 'package:test_sa/modules/loan_module/pages/loan_equipment_detail_page.dart';
|
|
|
|
import 'package:test_sa/modules/loan_module/pages/loan_equipment_detail_page.dart';
|
|
|
|
import 'package:test_sa/modules/loan_module/provider/loan_provider.dart';
|
|
|
|
import 'package:test_sa/modules/loan_module/provider/loan_provider.dart';
|
|
|
|
import 'package:test_sa/new_views/app_style/app_color.dart';
|
|
|
|
import 'package:test_sa/new_views/app_style/app_color.dart';
|
|
|
|
|
|
|
|
import 'package:test_sa/new_views/common_widgets/app_filled_button.dart';
|
|
|
|
import 'package:test_sa/new_views/common_widgets/default_app_bar.dart';
|
|
|
|
import 'package:test_sa/new_views/common_widgets/default_app_bar.dart';
|
|
|
|
import 'package:test_sa/views/widgets/loaders/no_data_found.dart';
|
|
|
|
import 'package:open_file/open_file.dart';
|
|
|
|
|
|
|
|
import 'package:share_plus/share_plus.dart';
|
|
|
|
|
|
|
|
import 'dart:developer';
|
|
|
|
import 'views/components/history_log_view.dart';
|
|
|
|
import 'views/components/history_log_view.dart';
|
|
|
|
import 'views/components/service_request_detail_view.dart';
|
|
|
|
import 'views/components/service_request_detail_view.dart';
|
|
|
|
|
|
|
|
|
|
|
|
@ -142,11 +146,11 @@ class _CMDetailPageState extends State<CMDetailPage> {
|
|
|
|
return Container(
|
|
|
|
return Container(
|
|
|
|
padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 6),
|
|
|
|
padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 6),
|
|
|
|
margin: const EdgeInsets.only(left: 2),
|
|
|
|
margin: const EdgeInsets.only(left: 2),
|
|
|
|
decoration: BoxDecoration(color: AppColor.background(context) ,border: Border.all(color: AppColor.border2Color(context)), borderRadius: BorderRadius.circular(16)),
|
|
|
|
decoration: BoxDecoration(color: AppColor.background(context), border: Border.all(color: AppColor.border2Color(context)), borderRadius: BorderRadius.circular(16)),
|
|
|
|
child: Row(
|
|
|
|
child: Row(
|
|
|
|
mainAxisSize: MainAxisSize.min,
|
|
|
|
mainAxisSize: MainAxisSize.min,
|
|
|
|
children: [
|
|
|
|
children: [
|
|
|
|
Icon(Icons.add, size: 20, color:AppColor.textStyleColor(context)),
|
|
|
|
Icon(Icons.add, size: 20, color: AppColor.textStyleColor(context)),
|
|
|
|
Text(
|
|
|
|
Text(
|
|
|
|
"Loan",
|
|
|
|
"Loan",
|
|
|
|
style: AppTextStyles.bodyText2.copyWith(color: AppColor.textStyleColor(context)),
|
|
|
|
style: AppTextStyles.bodyText2.copyWith(color: AppColor.textStyleColor(context)),
|
|
|
|
@ -170,6 +174,11 @@ class _CMDetailPageState extends State<CMDetailPage> {
|
|
|
|
return const SizedBox();
|
|
|
|
return const SizedBox();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}),
|
|
|
|
}),
|
|
|
|
|
|
|
|
// Print Button
|
|
|
|
|
|
|
|
IconButton(
|
|
|
|
|
|
|
|
icon: const Icon(Icons.print),
|
|
|
|
|
|
|
|
onPressed: _handlePrint,
|
|
|
|
|
|
|
|
),
|
|
|
|
IconButton(
|
|
|
|
IconButton(
|
|
|
|
icon: const Icon(Icons.home),
|
|
|
|
icon: const Icon(Icons.home),
|
|
|
|
onPressed: () {
|
|
|
|
onPressed: () {
|
|
|
|
@ -187,10 +196,14 @@ class _CMDetailPageState extends State<CMDetailPage> {
|
|
|
|
children: <Widget>[
|
|
|
|
children: <Widget>[
|
|
|
|
Container(
|
|
|
|
Container(
|
|
|
|
margin: EdgeInsets.only(left: 16.toScreenWidth, right: 16.toScreenWidth, top: 12.toScreenHeight),
|
|
|
|
margin: EdgeInsets.only(left: 16.toScreenWidth, right: 16.toScreenWidth, top: 12.toScreenHeight),
|
|
|
|
decoration: BoxDecoration(color: context.isDark ? AppColor.neutral50 : AppColor.white10, borderRadius: BorderRadius.circular(10)),
|
|
|
|
decoration: BoxDecoration(
|
|
|
|
|
|
|
|
color: AppColor.tabBarBackground(context),
|
|
|
|
|
|
|
|
border: Border.all(color: AppColor.tabBarBorder(context)),
|
|
|
|
|
|
|
|
borderRadius: BorderRadius.circular(20),
|
|
|
|
|
|
|
|
),
|
|
|
|
child: TabBar(
|
|
|
|
child: TabBar(
|
|
|
|
//controller: _tabController,
|
|
|
|
//controller: _tabController,
|
|
|
|
padding: EdgeInsets.symmetric(vertical: 4.toScreenHeight, horizontal: 4.toScreenWidth),
|
|
|
|
padding: EdgeInsets.symmetric(vertical: 6.toScreenHeight, horizontal: 6.toScreenWidth),
|
|
|
|
labelColor: context.isDark ? AppColor.neutral30 : AppColor.black20,
|
|
|
|
labelColor: context.isDark ? AppColor.neutral30 : AppColor.black20,
|
|
|
|
unselectedLabelColor: context.isDark ? AppColor.neutral30 : AppColor.black20,
|
|
|
|
unselectedLabelColor: context.isDark ? AppColor.neutral30 : AppColor.black20,
|
|
|
|
unselectedLabelStyle: AppTextStyles.bodyText,
|
|
|
|
unselectedLabelStyle: AppTextStyles.bodyText,
|
|
|
|
@ -198,7 +211,11 @@ class _CMDetailPageState extends State<CMDetailPage> {
|
|
|
|
indicatorPadding: EdgeInsets.zero,
|
|
|
|
indicatorPadding: EdgeInsets.zero,
|
|
|
|
indicatorSize: TabBarIndicatorSize.tab,
|
|
|
|
indicatorSize: TabBarIndicatorSize.tab,
|
|
|
|
dividerColor: Colors.transparent,
|
|
|
|
dividerColor: Colors.transparent,
|
|
|
|
indicator: BoxDecoration(color: context.isDark ? AppColor.neutral60 : AppColor.neutral110, borderRadius: BorderRadius.circular(7)),
|
|
|
|
overlayColor: WidgetStateProperty.all(Colors.transparent),
|
|
|
|
|
|
|
|
indicator: BoxDecoration(
|
|
|
|
|
|
|
|
color: AppColor.background(context),
|
|
|
|
|
|
|
|
borderRadius: BorderRadius.circular(15),
|
|
|
|
|
|
|
|
boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.03), blurRadius: 5, offset: const Offset(0, 0), spreadRadius: 0)]),
|
|
|
|
onTap: (index) {
|
|
|
|
onTap: (index) {
|
|
|
|
// setState(() {});
|
|
|
|
// setState(() {});
|
|
|
|
},
|
|
|
|
},
|
|
|
|
@ -237,4 +254,138 @@ class _CMDetailPageState extends State<CMDetailPage> {
|
|
|
|
|
|
|
|
|
|
|
|
cProvider.getUserAutoLoginTokenSilent(moduleId, widget.requestId, title, myEmployeeId, receiver);
|
|
|
|
cProvider.getUserAutoLoginTokenSilent(moduleId, widget.requestId, title, myEmployeeId, receiver);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Show success dialog after file is downloaded - using same implementation as export module
|
|
|
|
|
|
|
|
Future<void> _showSuccessDialog(String filePath) async {
|
|
|
|
|
|
|
|
if (!mounted) return;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return showDialog(
|
|
|
|
|
|
|
|
context: context,
|
|
|
|
|
|
|
|
barrierDismissible: false,
|
|
|
|
|
|
|
|
builder: (BuildContext dialogContext) {
|
|
|
|
|
|
|
|
return Dialog(
|
|
|
|
|
|
|
|
backgroundColor: AppColor.background(context),
|
|
|
|
|
|
|
|
shape: RoundedRectangleBorder(
|
|
|
|
|
|
|
|
borderRadius: BorderRadius.circular(16),
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
child: Padding(
|
|
|
|
|
|
|
|
padding: const EdgeInsets.all(24.0),
|
|
|
|
|
|
|
|
child: Column(
|
|
|
|
|
|
|
|
mainAxisSize: MainAxisSize.min,
|
|
|
|
|
|
|
|
children: [
|
|
|
|
|
|
|
|
SvgPicture.asset(
|
|
|
|
|
|
|
|
'assets/images/done.svg',
|
|
|
|
|
|
|
|
width: 80,
|
|
|
|
|
|
|
|
height: 80,
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
const SizedBox(height: 24),
|
|
|
|
|
|
|
|
Text(
|
|
|
|
|
|
|
|
'Print Successful',
|
|
|
|
|
|
|
|
style: TextStyle(
|
|
|
|
|
|
|
|
fontSize: 20,
|
|
|
|
|
|
|
|
fontWeight: FontWeight.bold,
|
|
|
|
|
|
|
|
color: AppColor.headingTextColor(context),
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
textAlign: TextAlign.center,
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
const SizedBox(height: 12),
|
|
|
|
|
|
|
|
Text(
|
|
|
|
|
|
|
|
'Your PDF has been generated successfully',
|
|
|
|
|
|
|
|
style: TextStyle(
|
|
|
|
|
|
|
|
fontSize: 14,
|
|
|
|
|
|
|
|
color: AppColor.lightTextColor(context),
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
textAlign: TextAlign.center,
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
const SizedBox(height: 32),
|
|
|
|
|
|
|
|
Row(
|
|
|
|
|
|
|
|
children: [
|
|
|
|
|
|
|
|
Expanded(
|
|
|
|
|
|
|
|
child: AppFilledButton(
|
|
|
|
|
|
|
|
onPressed: () async {
|
|
|
|
|
|
|
|
Navigator.of(dialogContext).pop();
|
|
|
|
|
|
|
|
log('📂 Opening printed file...');
|
|
|
|
|
|
|
|
final result = await OpenFile.open(filePath);
|
|
|
|
|
|
|
|
if (result.type != ResultType.done) {
|
|
|
|
|
|
|
|
log('⚠️ Could not open file: ${result.message}');
|
|
|
|
|
|
|
|
'No app found to open this file type. File saved to: $filePath'.showToast;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
label: 'Open',
|
|
|
|
|
|
|
|
buttonColor: AppColor.primary10,
|
|
|
|
|
|
|
|
showIcon: true,
|
|
|
|
|
|
|
|
icon: const Icon(Icons.folder_open, color: Colors.white),
|
|
|
|
|
|
|
|
height: 48,
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
const SizedBox(width: 12),
|
|
|
|
|
|
|
|
Expanded(
|
|
|
|
|
|
|
|
child: AppFilledButton(
|
|
|
|
|
|
|
|
onPressed: () async {
|
|
|
|
|
|
|
|
Navigator.of(dialogContext).pop();
|
|
|
|
|
|
|
|
log('📤 Sharing printed file...');
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
final xFile = XFile(filePath);
|
|
|
|
|
|
|
|
await Share.shareXFiles(
|
|
|
|
|
|
|
|
[xFile],
|
|
|
|
|
|
|
|
text: 'Printed file',
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
log('✅ File shared successfully');
|
|
|
|
|
|
|
|
} catch (e) {
|
|
|
|
|
|
|
|
log('❌ Error sharing file: $e');
|
|
|
|
|
|
|
|
'Failed to share file: $e'.showToast;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
label: 'Share',
|
|
|
|
|
|
|
|
buttonColor: AppColor.green40,
|
|
|
|
|
|
|
|
textColor: AppColor.green60,
|
|
|
|
|
|
|
|
showIcon: true,
|
|
|
|
|
|
|
|
icon: Icon(Icons.share, color: AppColor.green60),
|
|
|
|
|
|
|
|
height: 48,
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
],
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
],
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Handle print button press
|
|
|
|
|
|
|
|
Future<void> _handlePrint() async {
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
final exportProvider = Provider.of<ExportApiProvider>(context, listen: false);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
final filePath = await exportProvider.printWorkOrder(
|
|
|
|
|
|
|
|
widget.requestId,
|
|
|
|
|
|
|
|
widget.moduleId,
|
|
|
|
|
|
|
|
context,
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (filePath != null) {
|
|
|
|
|
|
|
|
await _showSuccessDialog(filePath);
|
|
|
|
|
|
|
|
} else if (exportProvider.errorMessage != null) {
|
|
|
|
|
|
|
|
if (mounted) {
|
|
|
|
|
|
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
|
|
|
|
|
|
SnackBar(
|
|
|
|
|
|
|
|
content: Text(exportProvider.errorMessage!),
|
|
|
|
|
|
|
|
backgroundColor: AppColor.red60,
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
|
|
if (mounted) {
|
|
|
|
|
|
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
|
|
|
|
|
|
SnackBar(
|
|
|
|
|
|
|
|
content: Text('Print failed: $error'),
|
|
|
|
|
|
|
|
backgroundColor: AppColor.red60,
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|