diff --git a/assets/images/asset_image_upload/side_bottom.svg b/assets/images/asset_image_upload/side_bottom.svg
new file mode 100644
index 00000000..7d9ec605
--- /dev/null
+++ b/assets/images/asset_image_upload/side_bottom.svg
@@ -0,0 +1,13 @@
+
diff --git a/assets/images/asset_image_upload/side_left.svg b/assets/images/asset_image_upload/side_left.svg
new file mode 100644
index 00000000..bdf7e6d9
--- /dev/null
+++ b/assets/images/asset_image_upload/side_left.svg
@@ -0,0 +1,13 @@
+
diff --git a/assets/images/asset_image_upload/side_right.svg b/assets/images/asset_image_upload/side_right.svg
new file mode 100644
index 00000000..f8db13a1
--- /dev/null
+++ b/assets/images/asset_image_upload/side_right.svg
@@ -0,0 +1,13 @@
+
diff --git a/assets/images/asset_image_upload/side_top.svg b/assets/images/asset_image_upload/side_top.svg
new file mode 100644
index 00000000..52841a4e
--- /dev/null
+++ b/assets/images/asset_image_upload/side_top.svg
@@ -0,0 +1,13 @@
+
diff --git a/lib/controllers/api_routes/api_manager.dart b/lib/controllers/api_routes/api_manager.dart
index ea8fcf06..f0c7ab42 100644
--- a/lib/controllers/api_routes/api_manager.dart
+++ b/lib/controllers/api_routes/api_manager.dart
@@ -19,9 +19,9 @@ import 'package:test_sa/new_views/pages/login_page.dart';
class _CachedResponse {
final http.Response response;
final DateTime timestamp;
-
+
_CachedResponse(this.response, this.timestamp);
-
+
bool isValid(Duration cacheDuration) {
return DateTime.now().difference(timestamp) < cacheDuration;
}
@@ -41,26 +41,26 @@ class ApiManager {
User? user;
AssetGroup? assetGroup;
-
+
// OPTIMIZATION: HTTP Connection Pooling - Reuse connections instead of creating new ones
// This improves performance by 100-200ms on subsequent API calls
static final http.Client _httpClient = http.Client();
-
+
// OPTIMIZATION: Response Caching - Cache lookup/static data to reduce network calls
// This reduces API calls by 60% for frequently accessed but rarely changing data
static final Map _cache = {};
static const Duration _defaultCacheDuration = Duration(hours: 1);
-
+
/// Clear all cached responses (call on logout or when needed)
void clearCache() {
_cache.clear();
}
-
+
/// Clear specific cache entry
void clearCacheEntry(String url) {
_cache.remove(_generateCacheKey(url));
}
-
+
/// Generate cache key from URL and user context
String _generateCacheKey(String url) {
// Include user and asset group in cache key to avoid cross-user pollution
@@ -68,7 +68,7 @@ class ApiManager {
}
/// GET request with optional caching support
- ///
+ ///
/// [url] - API endpoint URL
/// [headers] - Optional additional headers
/// [enableToastMessage] - Show toast message from API response
@@ -86,12 +86,12 @@ class ApiManager {
headers ??= {};
headers.addAll(_headers);
Uri url0 = Uri.parse(url);
-
+
// OPTIMIZATION: Check cache first if enabled
if (useCache && !forceRefresh) {
final cacheKey = _generateCacheKey(url);
final cachedResponse = _cache[cacheKey];
-
+
if (cachedResponse != null && cachedResponse.isValid(cacheDuration ?? _defaultCacheDuration)) {
if (kDebugMode) {
print('📦 Cache HIT: $url');
@@ -99,10 +99,10 @@ class ApiManager {
return cachedResponse.response;
}
}
-
+
// OPTIMIZATION: Use persistent HTTP client for connection pooling
http.Response response = await _httpClient.get(url0, headers: headers);
-
+
// OPTIMIZATION: Cache the response if caching is enabled
if (useCache && response.statusCode >= 200 && response.statusCode < 300) {
final cacheKey = _generateCacheKey(url);
@@ -310,7 +310,7 @@ class ApiManager {
Uri url0 = Uri.parse(url);
// print(headers);
// log(json.encode(body));
-
+
// OPTIMIZATION: Use persistent HTTP client for connection pooling
var request = http.Request('PUT', url0);
request.body = json.encode(body);
@@ -377,10 +377,9 @@ class ApiManager {
}
Future multiPart(String url, {Map? headers, required Map body, required List> files}) async {
- Map headers0 = const {
- 'Content-Type': 'multipart/form-data',
- };
+ Map headers0 = _headers;
+ headers0["Content-Type"] = 'multipart/form-data';
headers ??= {};
headers.addAll(headers0);
@@ -463,7 +462,7 @@ class ApiManager {
Navigator.pop(context);
Navigator.of(context).pushNamedAndRemoveUntil(LoginPage.routeName, (routes) => true);
}
-
+
/// Dispose HTTP client (call when app is closing if needed)
/// Note: In most cases, keep client alive for app lifetime for best performance
void dispose() {
diff --git a/lib/controllers/api_routes/urls.dart b/lib/controllers/api_routes/urls.dart
index 501df4b8..b7088f02 100644
--- a/lib/controllers/api_routes/urls.dart
+++ b/lib/controllers/api_routes/urls.dart
@@ -1,11 +1,11 @@
class URLs {
URLs._();
- static const String appReleaseBuildNumber = "44";
+ static const String appReleaseBuildNumber = "47";
- // static const host1 = "https://atomsm.hmg.com"; // production url
+ static const host1 = "https://atomsm.hmg.com"; // production url
// static const host1 = "https://atomsmdev.hmg.com"; // local DEV url
- static const host1 = "https://atomsmuat.hmg.com"; // local UAT url
+ // static const host1 = "https://atomsmuat.hmg.com"; // local UAT url
// static final String _baseUrl = "$_host/mobile"; // host local UAT
static final String _baseUrl = "$_host/v2/mobile"; // new V2 apis
@@ -66,6 +66,7 @@ class URLs {
static get getFaultDescription => "$_baseUrl/Asset/GetDefectForModelDefinition"; // get
static get getAssetById => "$_baseUrl/Asset/GetAssetById?assetId="; // get
static get getAssetColumnsMetadata => "$_baseUrl/Asset/columns/metadata"; // get asset export columns metadata
+ static get saveAssetImages => "$_baseUrl/Asset/SaveAssetImages"; // get
static get getModels => "$_baseUrl/ModelDefinition/GetModelDefinitionAsset"; // get ?client=2
static get getAllRequestsAndCount => "$_baseUrl/CallRequest/GetAllRequestsAndCount"; // get
static get updateUserContactInformation => "$_baseUrl/Account/UpdateContactInfo"; // get
diff --git a/lib/controllers/providers/api/all_requests_provider.dart b/lib/controllers/providers/api/all_requests_provider.dart
index a3eeb0d0..0a93116b 100644
--- a/lib/controllers/providers/api/all_requests_provider.dart
+++ b/lib/controllers/providers/api/all_requests_provider.dart
@@ -742,6 +742,7 @@ class AllRequestsProvider extends ChangeNotifier {
List? statusTransaction,
List? priority,
List? displayData,
+ bool? isAscending,
}) async {
if (isMultiFilterLoading == true) return -2;
if (_allRequestsAndCount == null || pagination) {
@@ -758,6 +759,7 @@ class AllRequestsProvider extends ChangeNotifier {
body["pageNumber"] = pageNum++;
body["pageSize"] = pageItemNumber;
}
+ if (isAscending != null) body["isAscending"] = isAscending;
response = await ApiManager.instance.post(URLs.getAllRequestsAndCount, body: body);
stateCode = response.statusCode;
diff --git a/lib/controllers/providers/api/devices_provider.dart b/lib/controllers/providers/api/devices_provider.dart
index 218ebf80..66c95d7b 100644
--- a/lib/controllers/providers/api/devices_provider.dart
+++ b/lib/controllers/providers/api/devices_provider.dart
@@ -9,6 +9,7 @@ import 'package:test_sa/controllers/api_routes/http_status_manger.dart';
import 'package:test_sa/controllers/api_routes/urls.dart';
import 'package:test_sa/models/device/asset_by_id_model.dart';
import 'package:test_sa/models/device/asset_search.dart';
+import 'package:test_sa/models/generic_attachment_model.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/models/user.dart';
import 'package:test_sa/modules/asset_delivery_module/models/technical_inpection_asset_model.dart';
@@ -152,9 +153,7 @@ class AssetProvider extends ChangeNotifier {
print(error);
throw (HttpStatusManger.getStatusMessage(status: -1, subtitle: appLocalizations));
}
- _stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
- // client's request was successfully received
Map assetData = json.decode(response.body)["data"];
_assetById = AssetByIdModel.fromJson(assetData);
return _assetById!;
@@ -230,4 +229,32 @@ class AssetProvider extends ChangeNotifier {
return [];
}
}
+
+ Future uploadAssetImages(int assetId, TrainingImageData trainingImageData) async {
+ late Response response;
+ try {
+ List> files = [];
+ files.add(MultipartFile.fromPath("LeftImage", trainingImageData.leftImage!.name!));
+ files.add(MultipartFile.fromPath("RightImage", trainingImageData.rightImage!.name!));
+ files.add(MultipartFile.fromPath("UpImage", trainingImageData.upImage!.name!));
+ files.add(MultipartFile.fromPath("DownImage", trainingImageData.downImage!.name!));
+
+ for (var i = 0; i < (trainingImageData.additionalImages?.length ?? 0); i++) {
+ files.add(
+ MultipartFile.fromPath('AdditionalImage', trainingImageData.additionalImages![i].name!),
+ );
+ }
+ response = await ApiManager.instance.multiPart(URLs.saveAssetImages + "?AssetId=$assetId", body: {}, files: files);
+ if (response.statusCode >= 200 && response.statusCode < 300) {
+ // client's request was successfully received
+ // Map assetData = json.decode(response.body)["data"];
+ // _assetById = AssetByIdModel.fromJson(assetData);
+ // return _assetById!;
+ return true;
+ }
+ return false;
+ } catch (error) {
+ return false;
+ }
+ }
}
diff --git a/lib/dashboard_latest/dashboard_provider.dart b/lib/dashboard_latest/dashboard_provider.dart
index 77896468..c50e9039 100644
--- a/lib/dashboard_latest/dashboard_provider.dart
+++ b/lib/dashboard_latest/dashboard_provider.dart
@@ -348,6 +348,7 @@ class DashBoardProvider extends ChangeNotifier {
statusTransaction: statusTransaction,
priority: priority,
displayData: displayData,
+ isAscending: isAscending,
);
}
diff --git a/lib/dashboard_latest/dashboard_view.dart b/lib/dashboard_latest/dashboard_view.dart
index ca986cc1..6de6e88b 100644
--- a/lib/dashboard_latest/dashboard_view.dart
+++ b/lib/dashboard_latest/dashboard_view.dart
@@ -12,6 +12,7 @@ import 'package:test_sa/controllers/providers/api/user_provider.dart';
import 'package:test_sa/controllers/providers/settings/setting_provider.dart';
import 'package:test_sa/dashboard_latest/dashboard_provider.dart';
import 'package:test_sa/dashboard_latest/widgets/app_bar_widget.dart';
+import 'package:test_sa/extensions/enum_extensions.dart';
import 'package:test_sa/dashboard_latest/widgets/progress_fragment.dart';
import 'package:test_sa/dashboard_latest/widgets/request_category_fragment_housekeeper.dart';
import 'package:test_sa/dashboard_latest/widgets/requests_fragment.dart';
@@ -103,15 +104,86 @@ class _DashboardViewState extends State {
void handleScroll() async {
_scrollController = ScrollController();
_scrollController.addListener(() async {
- if (_scrollController.position.pixels == _scrollController.position.maxScrollExtent && !_dashBoardProvider.isDetailLoading) {
- _dashBoardProvider.pageNum = _dashBoardProvider.pageNum + 1;
- if (_dashBoardProvider.currentListIndex == null) {
- } else {
- _dashBoardProvider.getRequestDetail(
+ if (_scrollController.position.pixels == _scrollController.position.maxScrollExtent) {
+ final allRequestsProvider = Provider.of(context, listen: false);
+
+ // Check which scenario is active and call appropriate pagination API
+ if (_dashBoardProvider.listIndex.isEmpty) {
+ // No category selected - paginate AllRequests
+ if (!allRequestsProvider.isAllLoading && allRequestsProvider.nextPage) {
+ allRequestsProvider.getAllRequests(context);
+ }
+ } else if (_dashBoardProvider.listIndex.length == 1 && _dashBoardProvider.isUnassignedTab(_dashBoardProvider.listIndex[0])) {
+ // Only UnAssigned tab selected - paginate with getRequestDetail
+ if (!_dashBoardProvider.isDetailLoading && _dashBoardProvider.nextPage) {
+ _dashBoardProvider.pageNum = _dashBoardProvider.pageNum + 1;
+ _dashBoardProvider.getRequestDetail(
usersType: user.type!,
showLoader: false,
- status: _dashBoardProvider.tabs[_dashBoardProvider.currentListIndex!].tag,
- tabId: _dashBoardProvider.tabs[_dashBoardProvider.currentListIndex!].id);
+ status: _dashBoardProvider.tabs[_dashBoardProvider.listIndex[0]].tag,
+ tabId: _dashBoardProvider.tabs[_dashBoardProvider.listIndex[0]].id,
+ );
+ }
+ } else {
+ // Multi-select categories - paginate with getDashboardMultifilterRequests
+ if (!allRequestsProvider.isMultiFilterLoading && allRequestsProvider.nextPage) {
+ // Build filter arrays based on selected tabs
+ List statusTransaction = [];
+ List priority = [];
+ List displayData = [];
+
+ for (int index in _dashBoardProvider.listIndex) {
+ if (index >= 0 && index < _dashBoardProvider.tabs.length) {
+ CategoryTabs tab = _dashBoardProvider.tabs[index];
+
+ // High Priority
+ if (tab.isHighPriority) {
+ if (!priority.contains(1)) priority.add(1);
+ }
+
+ // Overdue
+ if (tab.isOverDue) {
+ if (!displayData.contains(1)) displayData.add(1);
+ }
+
+ // Status categories
+ if (!tab.isHighPriority && !tab.isOverDue && tab.requestType != RequestTypeEnum.unassigned) {
+ switch (tab.requestType) {
+ case RequestTypeEnum.open:
+ if (!statusTransaction.contains(1)) statusTransaction.add(1);
+ break;
+ case RequestTypeEnum.inProgress:
+ if (!statusTransaction.contains(2)) statusTransaction.add(2);
+ break;
+ case RequestTypeEnum.completed:
+ if (!statusTransaction.contains(4)) statusTransaction.add(4);
+ break;
+ case RequestTypeEnum.closed:
+ if (!statusTransaction.contains(4)) statusTransaction.add(4);
+ break;
+ case RequestTypeEnum.canceled:
+ if (!statusTransaction.contains(5)) statusTransaction.add(5);
+ break;
+ case RequestTypeEnum.pendingAcknowledgment:
+ if (!statusTransaction.contains(3)) statusTransaction.add(3);
+ break;
+ case RequestTypeEnum.unassigned:
+ case RequestTypeEnum.highPriority:
+ case RequestTypeEnum.overdue:
+ break;
+ }
+ }
+ }
+ }
+
+ allRequestsProvider.getDashboardMultifilterRequests(
+ context,
+ pagination: false,
+ statusTransaction: statusTransaction,
+ priority: priority,
+ displayData: displayData,
+ );
+ }
}
}
});
diff --git a/lib/dashboard_latest/widgets/app_bar_widget.dart b/lib/dashboard_latest/widgets/app_bar_widget.dart
index 78ffe1a0..a87ec4cb 100644
--- a/lib/dashboard_latest/widgets/app_bar_widget.dart
+++ b/lib/dashboard_latest/widgets/app_bar_widget.dart
@@ -223,7 +223,7 @@ class _AppBarWidgetState extends State with TickerProviderStateMix
[],
builder: (_, MenuController controller, Widget? child) {
return Container(
- padding: const EdgeInsets.all(10),
+ padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 10),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
color: AppColor.assetGroupBackground(context),
@@ -234,10 +234,13 @@ class _AppBarWidgetState extends State with TickerProviderStateMix
),
child: Row(
mainAxisSize: MainAxisSize.min,
- spacing: 16,
+ spacing: 8,
children: [
- Text(settingProvider.assetGroup?.name ?? "", style: AppTextStyles.bodyText2.copyWith(color: AppColor.headingTextColor(context))),
- Icon(Icons.keyboard_arrow_down, color: AppColor.headingTextColor(context)),
+ Text(
+ settingProvider.assetGroup?.name ?? "",
+ style: AppTextStyles.bodyText2.copyWith(color: AppColor.headingTextColor(context)),
+ ),
+ Icon(Icons.keyboard_arrow_down, color: AppColor.headingTextColor(context), size: 20),
],
),
).onPress(() {
@@ -252,7 +255,7 @@ class _AppBarWidgetState extends State with TickerProviderStateMix
}),
),
),
- 16.width,
+ 8.width,
SlideTransition(
position: _rightSlideAnimation,
child: FadeTransition(
@@ -260,10 +263,15 @@ class _AppBarWidgetState extends State with TickerProviderStateMix
child: Row(
children: [
if (context.settingProvider.isUserFlowMedical) ...[
- ("dashboard/chat").toSvgAsset(height: 24, width: 24, color: AppColor.icon2Color(context)).paddingOnly(top: 0, end: 0).onPress(() {
- Navigator.of(context).push(CupertinoPageRoute(builder: (_) => UnReadChatList()));
- }),
- 16.width,
+ IconButton(
+ icon: ("dashboard/chat").toSvgAsset(height: 24, width: 24, color: AppColor.icon2Color(context)),
+ padding: EdgeInsets.zero,
+ visualDensity: VisualDensity.compact,
+ tooltip: "Notifications",
+ onPressed: () {
+ Navigator.of(context).push(CupertinoPageRoute(builder: (_) => UnReadChatList()));
+ },
+ ),
],
// Notification icon with unread count badge
Consumer(
@@ -285,7 +293,7 @@ class _AppBarWidgetState extends State with TickerProviderStateMix
),
),
],
- ).paddingOnly(start: 16, end: 16);
+ ).paddingOnly(start: 16, end: 08);
}),
);
}
diff --git a/lib/dashboard_latest/widgets/request_category_fragment.dart b/lib/dashboard_latest/widgets/request_category_fragment.dart
index c452d306..c6f80cad 100644
--- a/lib/dashboard_latest/widgets/request_category_fragment.dart
+++ b/lib/dashboard_latest/widgets/request_category_fragment.dart
@@ -83,8 +83,8 @@ class _RequestCategoryFragmentState extends State with
Provider.of(context, listen: false).reset();
if (dashboardProvider.listIndex.isEmpty) {
- // No category selected - do nothing or could reload default
- return;
+ // No category selected - reload default data with sorting
+ Provider.of(context, listen: false).getAllRequests(context, isAscending: isAscending);
} else if (dashboardProvider.listIndex.length == 1 && dashboardProvider.isUnassignedTab(dashboardProvider.listIndex[0])) {
// UnAssigned only - check by requestType, not by index
int index = dashboardProvider.listIndex[0];
@@ -117,8 +117,6 @@ class _RequestCategoryFragmentState extends State with
final bool isHouseKeeper = user?.type == UsersTypes.houseKeeper;
return Column(mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [
-
-
// !isNurse && dashboardProvider.tabs.isNotEmpty && dashboardProvider.tabs[dashboardProvider.currentListIndex].tag == 0
// ? Column(
// crossAxisAlignment: CrossAxisAlignment.start,
@@ -193,46 +191,50 @@ class _RequestCategoryFragmentState extends State with
// ).paddingOnly(start: 14, end: 12)
// :
-
- isHouseKeeper
- ? Row(
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
- children: [
- 'All Tasks'.addTranslation.heading4(context),
- 'add_icon'.toSvgAsset(width: 24, height: 24,).onPress(() {
- Navigator.of(context).pushNamed('/cleaner_search');
- }),
- ],
- ).paddingOnly(start: 16, end: 16) :
- Row(
- spacing: 16,
- children: [
- Text(context.translation.allWorkOrder, style: AppTextStyles.heading4.copyWith(color: AppColor.headingTextColor(context))).expanded,
- // todo commenting this code, for FM
- // if (!isFMSEngineer)
- // 'search'.toSvgAsset(width: 24, height: 24, color: AppColor.headingTextColor(context)).onPress(() {
- // Navigator.of(context).pushNamed('/cleaner_search');
- // }),
-
- if (dashboardProvider.listIndex.isNotEmpty)
- Text(
- 'Clear Filters',
- style: AppTextStyles.bodyText2.copyWith(color: AppColor.red30),
- ).onPress(() {
- dashboardProvider.resetRequestDataList();
- dashboardProvider.currentListIndex = null;
- Provider.of(context, listen: false)
- ..reset()
- ..getAllRequests(context);
- }),
- Transform.flip(
- flipY: isAscending,
- child: 'dashboard/sort_descending'.toSvgAsset(width: 24, height: 24, color: AppColor.headingTextColor(context)).onPress(() {
- _toggleSort(dashboardProvider, user?.type);
- }),
- )
- ],
- ).paddingOnly(start: 16, end: 16),
+ isHouseKeeper
+ ? Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ 'All Tasks'.addTranslation.heading4(context),
+ 'add_icon'
+ .toSvgAsset(
+ width: 24,
+ height: 24,
+ )
+ .onPress(() {
+ Navigator.of(context).pushNamed('/cleaner_search');
+ }),
+ ],
+ ).paddingOnly(start: 16, end: 16)
+ : Row(
+ spacing: 16,
+ children: [
+ Text(context.translation.allWorkOrder, style: AppTextStyles.heading4.copyWith(color: AppColor.headingTextColor(context))).expanded,
+ // todo commenting this code, for FM
+ // if (!isFMSEngineer)
+ // 'search'.toSvgAsset(width: 24, height: 24, color: AppColor.headingTextColor(context)).onPress(() {
+ // Navigator.of(context).pushNamed('/cleaner_search');
+ // }),
+
+ if (dashboardProvider.listIndex.isNotEmpty)
+ Text(
+ 'Clear Filters',
+ style: AppTextStyles.bodyText2.copyWith(color: AppColor.red30),
+ ).onPress(() {
+ dashboardProvider.resetRequestDataList();
+ dashboardProvider.currentListIndex = null;
+ Provider.of(context, listen: false)
+ ..reset()
+ ..getAllRequests(context);
+ }),
+ Transform.flip(
+ flipY: isAscending,
+ child: 'dashboard/sort_descending'.toSvgAsset(width: 24, height: 24, color: AppColor.headingTextColor(context)).onPress(() {
+ _toggleSort(dashboardProvider, user?.type);
+ }),
+ )
+ ],
+ ).paddingOnly(start: 16, end: 16),
),
),
diff --git a/lib/extensions/context_extension.dart b/lib/extensions/context_extension.dart
index 41f93d7f..8b2a4b23 100644
--- a/lib/extensions/context_extension.dart
+++ b/lib/extensions/context_extension.dart
@@ -1,3 +1,4 @@
+import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:localization/localization.dart';
import 'package:provider/provider.dart';
@@ -5,6 +6,8 @@ import 'package:test_sa/controllers/providers/api/user_provider.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/new_views/swipe_module/dialoge/confirm_dialog.dart';
import 'package:test_sa/new_views/swipe_module/dialoge/info_dialog.dart';
+import 'package:test_sa/views/full_screen_image_viewer.dart';
+import 'package:test_sa/views/widgets/dialogs/confirm_dialog.dart';
import '../controllers/providers/settings/setting_provider.dart';
import '../l10n/app_localizations.dart';
@@ -24,6 +27,15 @@ extension BuildContextExtension on BuildContext {
UserProvider get userProvider => Provider.of(this, listen: false);
+ void fullScreenImageViewer(Widget child) {
+ Navigator.of(this).push(
+ CupertinoPageRoute(
+ fullscreenDialog: true,
+ builder: (_) => FullScreenImageViewer(child),
+ ),
+ );
+ }
+
bool isTablet() {
final mediaQueryData = MediaQuery.of(this);
final double screenWidth = mediaQueryData.size.width;
@@ -49,6 +61,7 @@ extension BuildContextExtension on BuildContext {
isScrollControlled: true,
isDismissible: true,
backgroundColor: Colors.transparent,
- builder: (context) => SingleChildScrollView(padding: const EdgeInsets.all(0), child: childWidget.bottomSafeArea).bottomSheetContainerNew(context, title: title,showCancelButton: showCancelButton),
+ builder: (context) =>
+ SingleChildScrollView(padding: const EdgeInsets.all(0), child: childWidget.bottomSafeArea).bottomSheetContainerNew(context, title: title, showCancelButton: showCancelButton),
);
}
diff --git a/lib/extensions/widget_extensions.dart b/lib/extensions/widget_extensions.dart
index 2dc5cf00..5273a12a 100644
--- a/lib/extensions/widget_extensions.dart
+++ b/lib/extensions/widget_extensions.dart
@@ -120,12 +120,13 @@ extension WidgetExtensions on Widget {
double padding = 12,
EdgeInsets? paddingObject,
EdgeInsets? margin,
+ double? width,
}) =>
withShadow
? Container(
padding: paddingObject ?? EdgeInsets.all(padding),
margin: margin,
- width: double.infinity,
+ width: width ?? double.infinity,
decoration: ShapeDecoration(
color: backgroundColor ?? AppColor.background(context),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(borderRadius), side: BorderSide(color: borderColor ?? AppColor.borderColor(context))),
diff --git a/lib/helper/utils.dart b/lib/helper/utils.dart
index 0d706f4e..53496f1f 100644
--- a/lib/helper/utils.dart
+++ b/lib/helper/utils.dart
@@ -13,7 +13,7 @@ import 'package:nfc_manager/nfc_manager_ios.dart' show MiFareIos, Iso15693Ios;
import 'package:shared_preferences/shared_preferences.dart';
import 'package:test_sa/new_views/common_widgets/app_lazy_loading.dart';
import 'package:test_sa/views/widgets/dialogs/confirm_dialog.dart';
-import 'package:test_sa/views/widgets/dialogs/loading_dialog.dart';
+import 'package:test_sa/views/widgets/dialogs/loading_with_text_dialog.dart';
// ignore_for_file: avoid_annotating_with_dynamic
@@ -103,7 +103,7 @@ class Utils {
_isLoadingVisible = false;
}
- static void showUploadingDialog(BuildContext context) {
+ static void showLoadingWithTextDialog(BuildContext context, {String? message}) {
WidgetsBinding.instance.addPostFrameCallback((_) {
_isLoadingVisible = true;
@@ -111,7 +111,7 @@ class Utils {
context: context,
barrierColor: Colors.black.withOpacity(0.5),
useRootNavigator: false,
- builder: (BuildContext context) => const UploadingDialog(),
+ builder: (BuildContext context) => LoadingWithTextDialog(message: message),
).then((value) {
_isLoadingVisible = false;
});
diff --git a/lib/models/device/asset.dart b/lib/models/device/asset.dart
index 1e41dc31..91c86dc9 100644
--- a/lib/models/device/asset.dart
+++ b/lib/models/device/asset.dart
@@ -65,6 +65,7 @@ class Asset {
this.comment,
this.tagCode,
this.assetPhoto,
+ this.hasTrainingImageData,
});
Asset.fromJson(dynamic json) {
@@ -122,6 +123,7 @@ class Asset {
comment = json['comment'];
tagCode = json['tagCode'];
assetPhoto = json['assetPhoto'];
+ hasTrainingImageData = json['hasTrainingImageData'];
}
num? id; // Now nullable
@@ -177,6 +179,7 @@ class Asset {
String? comment; // Now nullable
String? tagCode; // Now nullable
String? assetPhoto;
+ bool? hasTrainingImageData;
Asset copyWith({
num? id,
@@ -232,6 +235,7 @@ class Asset {
String? comment,
String? tagCode,
String? assetPhoto,
+ bool? hasTrainingImageData,
}) =>
Asset(
id: id ?? this.id,
@@ -287,6 +291,7 @@ class Asset {
comment: comment ?? this.comment,
tagCode: tagCode ?? this.tagCode,
assetPhoto: assetPhoto ?? this.assetPhoto,
+ hasTrainingImageData: hasTrainingImageData ?? this.hasTrainingImageData,
);
Map toJson() {
@@ -381,6 +386,7 @@ class Asset {
map['comment'] = comment;
map['tagCode'] = tagCode;
map['assetPhoto'] = assetPhoto;
+ map['hasTrainingImageData'] = hasTrainingImageData;
return map;
}
}
diff --git a/lib/models/device/asset_by_id_model.dart b/lib/models/device/asset_by_id_model.dart
index c631b767..ab177b23 100644
--- a/lib/models/device/asset_by_id_model.dart
+++ b/lib/models/device/asset_by_id_model.dart
@@ -1,4 +1,5 @@
import 'package:test_sa/models/device/technical_guidance_book.dart';
+import 'package:test_sa/models/generic_attachment_model.dart';
import 'package:test_sa/models/lookup.dart';
class AssetByIdModel {
@@ -13,12 +14,12 @@ class AssetByIdModel {
AssetInfo? oldAsset;
AssetReplace? isParent;
AssetInfo? parentAsset;
- AssetReplace? assetType;
+ Lookup? assetType;
DemoRequest? demoRequest;
String? missionCritical;
Site? site;
- AssetReplace? building;
- AssetReplace? floor;
+ Lookup? building;
+ Lookup? floor;
Department? department;
Lookup? room;
num? testsDay;
@@ -54,14 +55,17 @@ class AssetByIdModel {
String? comment;
bool? isEnabled;
String? tagCode;
- List? assetAttachments;
+ List? assetAttachments;
String? retirementTypeName;
String? retirementStatusName;
String? retirementDate;
AssetGroup? assetGroup;
String? assetPhoto;
+ String? modelPhoto;
String? nextPMDate;
String? lastPMDate;
+ bool? hasTrainingImageData;
+ TrainingImageData? trainingImageData;
AssetByIdModel(
{this.multiAssets,
@@ -122,10 +126,15 @@ class AssetByIdModel {
this.retirementDate,
this.assetGroup,
this.assetPhoto,
+ this.modelPhoto,
this.nextPMDate,
- this.lastPMDate});
+ this.lastPMDate,
+ this.trainingImageData,
+ this.hasTrainingImageData});
AssetByIdModel.fromJson(Map json) {
+ print("assetModel!.fromJson:${json['hasTrainingImageData']}");
+
if (json['multiAssets'] != null) {
multiAssets = [];
json['multiAssets'].forEach((v) {
@@ -142,12 +151,12 @@ class AssetByIdModel {
oldAsset = json['oldAsset'] != null ? AssetInfo.fromJson(json['oldAsset']) : null;
isParent = json['isParent'] != null ? AssetReplace.fromJson(json['isParent']) : null;
parentAsset = json['parentAsset'] != null ? AssetInfo.fromJson(json['parentAsset']) : null;
- assetType = json['assetType'] != null ? AssetReplace.fromJson(json['assetType']) : null;
+ assetType = json['assetType'] != null ? Lookup.fromJson(json['assetType']) : null;
demoRequest = json['demoRequest'] != null ? DemoRequest.fromJson(json['demoRequest']) : null;
missionCritical = json['missionCritical'];
site = json['site'] != null ? Site.fromJson(json['site']) : null;
- building = json['building'] != null ? AssetReplace.fromJson(json['building']) : null;
- floor = json['floor'] != null ? AssetReplace.fromJson(json['floor']) : null;
+ building = json['building'] != null ? Lookup.fromJson(json['building']) : null;
+ floor = json['floor'] != null ? Lookup.fromJson(json['floor']) : null;
department = json['department'] != null ? Department.fromJson(json['department']) : null;
room = json['room'] != null ? Lookup.fromJson(json['room']) : null;
testsDay = json['testsDay'];
@@ -189,9 +198,9 @@ class AssetByIdModel {
isEnabled = json['isEnabled'];
tagCode = json['tagCode'];
if (json['assetAttachments'] != null) {
- assetAttachments = [];
+ assetAttachments = [];
json['assetAttachments'].forEach((v) {
- assetAttachments!.add(v);
+ assetAttachments!.add(AssetAttachment.fromJson(v));
});
}
retirementTypeName = json['retirementTypeName'];
@@ -199,8 +208,11 @@ class AssetByIdModel {
retirementDate = json['retirementDate'];
assetGroup = json['assetGroup'] != null ? AssetGroup.fromJson(json['assetGroup']) : null;
assetPhoto = json['assetPhoto'];
+ modelPhoto = json['modelPhoto'];
nextPMDate = json['nextPMDate'];
lastPMDate = json['lastPMDate'];
+ hasTrainingImageData = json['hasTrainingImageData'];
+ trainingImageData = json['trainingImageData'] != null ? TrainingImageData.fromJson(json['trainingImageData']) : null;
}
Map toJson() {
@@ -295,8 +307,11 @@ class AssetByIdModel {
data['assetGroup'] = assetGroup?.toJson();
}
data['assetPhoto'] = assetPhoto;
+ data['modelPhoto'] = modelPhoto;
data['nextPMDate'] = nextPMDate;
data['lastPMDate'] = lastPMDate;
+ data['hasTrainingImageData'] = hasTrainingImageData;
+ data['trainingImageData'] = trainingImageData?.toJson();
return data;
}
}
@@ -323,6 +338,31 @@ class MultiAssets {
}
}
+class AssetAttachment {
+ int? id;
+ String? attachmentName;
+ String? attachmentURL;
+ String? originalName;
+
+ AssetAttachment({this.id, this.attachmentName, this.attachmentURL, this.originalName});
+
+ AssetAttachment.fromJson(Map json) {
+ id = json['id'];
+ attachmentName = json['attachmentName'];
+ attachmentURL = json['attachmentURL'];
+ originalName = json['originalName'];
+ }
+
+ Map toJson() {
+ final Map data = {};
+ data['id'] = id;
+ data['attachmentName'] = attachmentName;
+ data['attachmentURL'] = attachmentURL;
+ data['originalName'] = originalName;
+ return data;
+ }
+}
+
class ModelDefinition {
int? id;
String? assetName;
@@ -546,18 +586,50 @@ class Floors {
class Departments {
int? id;
String? name;
+ List? rooms;
Departments({this.id, this.name});
Departments.fromJson(Map json) {
id = json['id'];
name = json['name'];
+ if (json['departments'] != null) {
+ rooms = [];
+ json['rooms'].forEach((v) {
+ rooms!.add(Rooms.fromJson(v));
+ });
+ }
+ }
+
+ Map toJson() {
+ final Map data = {};
+ data['id'] = id;
+ data['name'] = name;
+ if (rooms != null) {
+ data['rooms'] = rooms!.map((v) => v.toJson()).toList();
+ }
+ return data;
+ }
+}
+
+class Rooms {
+ int? id;
+ String? name;
+ int? value;
+
+ Rooms({this.id, this.name, this.value});
+
+ Rooms.fromJson(Map json) {
+ id = json['id'];
+ name = json['name'];
+ value = json['value'];
}
Map toJson() {
final Map data = {};
data['id'] = id;
data['name'] = name;
+ data['value'] = value;
return data;
}
}
@@ -567,14 +639,16 @@ class Department {
String? departmentName;
String? departmentCode;
String? ntCode;
+ num? operationalHours;
- Department({this.id, this.departmentName, this.departmentCode, this.ntCode});
+ Department({this.id, this.departmentName, this.departmentCode, this.ntCode, this.operationalHours});
Department.fromJson(Map json) {
id = json['id'];
departmentName = json['departmentName'];
departmentCode = json['departmentCode'];
ntCode = json['ntCode'];
+ operationalHours = json['operationalHours'];
}
Map toJson() {
@@ -583,6 +657,7 @@ class Department {
data['departmentName'] = departmentName;
data['departmentCode'] = departmentCode;
data['ntCode'] = ntCode;
+ data['operationalHours'] = operationalHours;
return data;
}
}
@@ -725,3 +800,37 @@ class DemoRequest {
return data;
}
}
+
+class TrainingImageData {
+ GenericAttachmentModel? leftImage;
+ GenericAttachmentModel? rightImage;
+ GenericAttachmentModel? upImage;
+ GenericAttachmentModel? downImage;
+ List? additionalImages;
+
+ TrainingImageData({this.leftImage, this.rightImage, this.upImage, this.downImage, this.additionalImages = const []});
+
+ TrainingImageData.fromJson(Map json) {
+ leftImage = json['leftImage'] == null ? null : GenericAttachmentModel.fromJson(json['leftImage'], convertToLink: true);
+ rightImage = json['rightImage'] == null ? null : GenericAttachmentModel.fromJson(json['rightImage'], convertToLink: true);
+ upImage = json['upImage'] == null ? null : GenericAttachmentModel.fromJson(json['upImage'], convertToLink: true);
+ downImage = json['downImage'] == null ? null : GenericAttachmentModel.fromJson(json['downImage'], convertToLink: true);
+ additionalImages = [];
+ if (json['additionalImages'] != null) {
+ json['additionalImages'].forEach((v) {
+ additionalImages!.add(GenericAttachmentModel.fromJson(v, convertToLink: true));
+ });
+ }
+ }
+
+ Map toJson() {
+ final Map data = {};
+ data['leftImage'] = leftImage?.toJson();
+ data['rightImage'] = rightImage?.toJson();
+ data['upImage'] = upImage?.toJson();
+ data['downImage'] = downImage?.toJson();
+ data['additionalImages'] = additionalImages?.map((v) => v.toJson()).toList() ?? [];
+
+ return data;
+ }
+}
diff --git a/lib/models/generic_attachment_model.dart b/lib/models/generic_attachment_model.dart
index dde1d74d..6ba126e1 100644
--- a/lib/models/generic_attachment_model.dart
+++ b/lib/models/generic_attachment_model.dart
@@ -1,9 +1,10 @@
import 'dart:io';
+import 'package:test_sa/controllers/api_routes/urls.dart';
import 'package:test_sa/models/lookup.dart';
class GenericAttachmentModel {
- GenericAttachmentModel({this.id, this.name, this.originalName, this.createdBy,this.documentTypeId});
+ GenericAttachmentModel({this.id, this.name, this.originalName, this.createdBy, this.documentTypeId});
int? id;
String? name;
@@ -11,11 +12,14 @@ class GenericAttachmentModel {
String? originalName;
Lookup? documentTypeId;
- GenericAttachmentModel.fromJson(Map json) {
+ GenericAttachmentModel.fromJson(Map json, {bool convertToLink = false}) {
id = json['id'];
- name = json['name'];
+ name = json['name'] ?? json['imageName'];
createdBy = json['createdBy'];
- originalName = json['originalName'];
+ originalName = json['originalName'] ?? json['imageOriginalName'];
+ if (convertToLink) {
+ name = URLs.getFileUrl(name);
+ }
}
Map toJson() {
diff --git a/lib/models/new_models/work_order_detail_model.dart b/lib/models/new_models/work_order_detail_model.dart
index 1936113a..984edca5 100644
--- a/lib/models/new_models/work_order_detail_model.dart
+++ b/lib/models/new_models/work_order_detail_model.dart
@@ -304,17 +304,20 @@ class WorkOrderAsset {
required this.id,
required this.assetNumber,
required this.assetSerialNo,
+ required this.hasTrainingImageData,
});
int? id;
String? assetNumber;
String? assetSerialNo;
+ bool? hasTrainingImageData;
factory WorkOrderAsset.fromJson(Map json) {
return WorkOrderAsset(
id: json["id"],
assetNumber: json["assetNumber"],
assetSerialNo: json["assetSerialNo"],
+ hasTrainingImageData: json["hasTrainingImageData"],
);
}
@@ -322,6 +325,7 @@ class WorkOrderAsset {
"id": id,
"assetNumber": assetNumber,
"assetSerialNo": assetSerialNo,
+ "hasTrainingImageData": hasTrainingImageData,
};
}
diff --git a/lib/modules/asset_inventory_module/pages/asset_inventory_detail_view.dart b/lib/modules/asset_inventory_module/pages/asset_inventory_detail_view.dart
index 1f0b0481..48688b2f 100644
--- a/lib/modules/asset_inventory_module/pages/asset_inventory_detail_view.dart
+++ b/lib/modules/asset_inventory_module/pages/asset_inventory_detail_view.dart
@@ -69,7 +69,7 @@ class _AssetInventoryDetailViewState extends State {
InfoTextWidget(label: 'Start Date'.addTranslation, value: sessionModel.startDate?.toServiceRequestDetailsFormat ?? '-'),
InfoTextWidget(label: 'End Date'.addTranslation, value: sessionModel.endDate?.toServiceRequestDetailsFormat ?? '-'),
],
- ).toShadowContainer(context, padding: 16, borderRadius: 20);
+ ).toShadowContainer(context, borderRadius: 20);
}
Widget siteListCard(BuildContext context, SessionModel sessionModel) {
@@ -84,7 +84,7 @@ class _AssetInventoryDetailViewState extends State {
sites: sites,
),
],
- ).toShadowContainer(context, padding: 16, borderRadius: 20);
+ ).toShadowContainer(context, borderRadius: 20);
}
}
diff --git a/lib/modules/cleaner_module/pages/one_time_task_preview_screen.dart b/lib/modules/cleaner_module/pages/one_time_task_preview_screen.dart
index 0e44bcda..19ef67fb 100644
--- a/lib/modules/cleaner_module/pages/one_time_task_preview_screen.dart
+++ b/lib/modules/cleaner_module/pages/one_time_task_preview_screen.dart
@@ -262,33 +262,15 @@ class OneTimeTaskPreviewScreen extends StatelessWidget {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
- InfoHeader16Widget(
- 'Captured Images',
- ),
- 16.height,
+ InfoHeader16Widget('Captured Images'),
+ 12.height,
Wrap(
spacing: 8,
runSpacing: 8,
children: taskData.imageRooms!.map((imageString) {
return GestureDetector(
onTap: () {
- // Show full screen image
- Navigator.of(context).push(
- MaterialPageRoute(
- builder: (_) => Scaffold(
- backgroundColor: Colors.black,
- appBar: AppBar(
- backgroundColor: Colors.black,
- iconTheme: const IconThemeData(color: Colors.white),
- ),
- body: Center(
- child: InteractiveViewer(
- child: _buildImage(imageString),
- ),
- ),
- ),
- ),
- );
+ context.fullScreenImageViewer(_buildImage(imageString));
},
child: Container(
width: 100,
@@ -349,12 +331,12 @@ class OneTimeTaskPreviewScreen extends StatelessWidget {
SizedBox(
width: 100,
child: InfoTextLabelWidget(
- label:'$label:',
+ label: '$label:',
),
),
Expanded(
child: InfoTextLabelWidget(
- label: value,
+ label: value,
),
),
],
diff --git a/lib/modules/cleaner_module/pages/one_time_task_view.dart b/lib/modules/cleaner_module/pages/one_time_task_view.dart
index 5a94f7e6..25ac466d 100644
--- a/lib/modules/cleaner_module/pages/one_time_task_view.dart
+++ b/lib/modules/cleaner_module/pages/one_time_task_view.dart
@@ -159,7 +159,7 @@ class _OneTimeTaskViewState extends State {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildTaskInfoCard(context),
- 16.height,
+ 12.height,
CleanerChecklistWidget(
isClosed: isClosed,
checklistItems: _convertInstructionsToChecklist(),
@@ -276,9 +276,9 @@ class _OneTimeTaskViewState extends State {
),
],
],
- ).paddingOnly(start: 16, end: 16, top: 16, bottom: 16),
+ ),
],
- ).toShadowContainer(context, padding: 0);
+ ).toShadowContainer(context);
}
List _convertInstructionsToChecklist() {
diff --git a/lib/modules/cleaner_module/widgets/cleaner_checklist_widget.dart b/lib/modules/cleaner_module/widgets/cleaner_checklist_widget.dart
index 3f69efa1..f6b0a1a0 100644
--- a/lib/modules/cleaner_module/widgets/cleaner_checklist_widget.dart
+++ b/lib/modules/cleaner_module/widgets/cleaner_checklist_widget.dart
@@ -37,18 +37,17 @@ class _CleanerChecklistWidgetState extends State {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
+ spacing: 12,
children: [
InfoHeader16Widget('Checklist'),
- 16.height,
ListView.separated(
shrinkWrap: true,
padding: EdgeInsets.zero,
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (cxt, index) => _buildChecklistItem(context, widget.checklistItems[index]),
- separatorBuilder: (cxt, index) => const Divider(height: 1, color: AppColor.neutral30, thickness: 1).paddingOnly(top: 16, bottom: 16),
+ separatorBuilder: (cxt, index) => const Divider().defaultStyle(context),
itemCount: widget.checklistItems.length)
- .toShadowContainer(context, padding: 16),
- 16.height,
+ .toShadowContainer(context),
_buildImageCaptureWidget(context),
],
);
@@ -70,7 +69,7 @@ class _CleanerChecklistWidgetState extends State {
child: Checkbox(
value: item.isChecked,
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
- side: BorderSide(color: Colors.black.withValues(alpha: .05)),
+ side: BorderSide(color: AppColor.loadingColor(context), width: 1.0),
visualDensity: const VisualDensity(horizontal: -4.0, vertical: -4.0),
activeColor: AppColor.primary10,
onChanged: (bool? value) {},
@@ -181,12 +180,7 @@ class _CleanerChecklistWidgetState extends State {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
- Row(
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
- children: [
- InfoHeader16Widget('Captured Image'),
- ],
- ),
+ InfoHeader16Widget('Captured Image'),
8.height,
_buildImageWidget(context),
],
@@ -277,24 +271,7 @@ class _CleanerChecklistWidgetState extends State {
maxImages: 2,
// Enforce max 2 images
onImageTap: (index, imageUrl) {
- // Handle image tap - show in full screen
- Navigator.of(context).push(
- MaterialPageRoute(
- builder: (_) => Scaffold(
- backgroundColor: Colors.black,
- body: SafeArea(
- child: Stack(
- children: [
- InteractiveViewer(
- child: _buildImageForViewing(imageUrl),
- ).center,
- const ABackButton(),
- ],
- ),
- ),
- ),
- ),
- );
+ context.fullScreenImageViewer(_buildImageForViewing(imageUrl));
},
onDelete: (index) {
// Handle image delete
diff --git a/lib/modules/cleaner_module/widgets/multi_image_picker.dart b/lib/modules/cleaner_module/widgets/multi_image_picker.dart
index 002acbe4..d970c2d3 100644
--- a/lib/modules/cleaner_module/widgets/multi_image_picker.dart
+++ b/lib/modules/cleaner_module/widgets/multi_image_picker.dart
@@ -48,8 +48,7 @@ class MultiImagePicker extends StatelessWidget {
),
// Add image button (only show if under max limit)
- if (enabled && imageUrls.length < maxImages)
- _buildAddImageButton(context),
+ if (enabled && imageUrls.length < maxImages) _buildAddImageButton(context),
],
),
],
@@ -77,7 +76,9 @@ class MultiImagePicker extends StatelessWidget {
if (onImageTap != null) {
onImageTap!(index, imageUrl);
} else {
- _showFullImage(context, imageUrl);
+ context.fullScreenImageViewer(
+ _getImageWidget(imageUrl),
+ );
}
}),
if (enabled)
@@ -193,26 +194,4 @@ class MultiImagePicker extends StatelessWidget {
}
}
}
-
- void _showFullImage(BuildContext context, String imageUrl) {
- Navigator.of(context).push(
- MaterialPageRoute(
- builder: (_) => Scaffold(
- backgroundColor: Colors.black,
- body: SafeArea(
- child: Stack(
- children: [
- Center(
- child: InteractiveViewer(
- child: _getImageWidget(imageUrl),
- ),
- ),
- const ABackButton(),
- ],
- ),
- ),
- ),
- ),
- );
- }
}
diff --git a/lib/modules/cm_module/cm_detail_page.dart b/lib/modules/cm_module/cm_detail_page.dart
index afa9ea03..7dd2ba42 100644
--- a/lib/modules/cm_module/cm_detail_page.dart
+++ b/lib/modules/cm_module/cm_detail_page.dart
@@ -121,7 +121,10 @@ class _CMDetailPageState extends State {
}),
if (isNurse)
IconButton(
- icon: 'qr'.toSvgAsset(height: 24, width: 24,color: AppColor.icon2Color(context)),
+ icon: 'qr'.toSvgAsset(height: 24, width: 24, color: AppColor.icon2Color(context)),
+ padding: EdgeInsets.zero,
+ visualDensity: VisualDensity.compact,
+ tooltip: "QR Code",
onPressed: () {
ServiceRequestBottomSheet.getQRCodeBottomSheet(context: context);
},
@@ -173,11 +176,16 @@ class _CMDetailPageState extends State {
IconButton(
icon: "download".toSvgAsset(height: 24, width: 24, color: AppColor.icon2Color(context)),
padding: EdgeInsets.zero,
+ visualDensity: VisualDensity.compact,
tooltip: "Export",
onPressed: _handlePrint,
),
IconButton(
icon: const Icon(Icons.home),
+ padding: EdgeInsets.zero,
+ iconSize: 20,
+ visualDensity: VisualDensity.compact,
+ tooltip:"Home",
onPressed: () {
// stopTimer();
Navigator.pop(context);
diff --git a/lib/modules/cm_module/views/components/activities_list_view.dart b/lib/modules/cm_module/views/components/activities_list_view.dart
index d3880a44..a543651f 100644
--- a/lib/modules/cm_module/views/components/activities_list_view.dart
+++ b/lib/modules/cm_module/views/components/activities_list_view.dart
@@ -175,7 +175,7 @@ class _ActivitiesListViewState extends State {
FilesList(images: activity.activitySparePart!.acitiySparePartAttachments!.map((toElement) => URLs.getFileUrl(toElement.name!)!).toList()),
],
],
- ).toShadowContainer(context, padding: 12, showShadow: false).onPress(() {
+ ).toShadowContainer(context, showShadow: false).onPress(() {
if (showActionButtons) return;
if (requestDetailProvider.isReadOnlyRequest) {
editSparePartRequest(context: context, requestDetailProvider: requestDetailProvider, activity: activity);
@@ -272,7 +272,7 @@ class _ActivitiesListViewState extends State {
// // ),
// ]
],
- ).toShadowContainer(context, padding: 12, showShadow: false).onPress(() {
+ ).toShadowContainer(context, showShadow: false).onPress(() {
if (showActionButtons) return;
if (requestDetailProvider.isReadOnlyRequest) {
editMaintenanceRequest(context: context, requestDetailProvider: requestDetailProvider, activity: activity);
diff --git a/lib/modules/cm_module/views/components/history_log_view.dart b/lib/modules/cm_module/views/components/history_log_view.dart
index e549f02f..b3fef162 100644
--- a/lib/modules/cm_module/views/components/history_log_view.dart
+++ b/lib/modules/cm_module/views/components/history_log_view.dart
@@ -120,20 +120,7 @@ class HistoryLogView extends StatelessWidget {
padding: EdgeInsets.symmetric(vertical: 12.toScreenWidth),
child: InteractiveViewer(child: Image.network(URLs.getFileUrl(object.photoVerfication ?? '')!, height: 143.toScreenHeight)),
).onPress(() async {
- Navigator.of(context).push(
- MaterialPageRoute(
- builder: (_) => Scaffold(
- body: SafeArea(
- child: Stack(
- children: [
- InteractiveViewer(child: Image.network(URLs.getFileUrl(object.photoVerfication ?? '')!)).center,
- const ABackButton(),
- ],
- ),
- ),
- ),
- ),
- );
+ context.fullScreenImageViewer(Image.network(URLs.getFileUrl(object.photoVerfication ?? '')!));
}),
],
title.bodyText(context).custom(color: AppColor.textColor(context)),
@@ -142,7 +129,7 @@ class HistoryLogView extends StatelessWidget {
),
),
],
- ).toShadowContainer(context, padding: 16).paddingOnly(bottom: 16);
+ ).toShadowContainer(context).paddingOnly(bottom: 16);
}
Widget statusCard(BuildContext context, String status) {
diff --git a/lib/modules/cm_module/views/components/initial_visit_card.dart b/lib/modules/cm_module/views/components/initial_visit_card.dart
index 424351a5..ecd93663 100644
--- a/lib/modules/cm_module/views/components/initial_visit_card.dart
+++ b/lib/modules/cm_module/views/components/initial_visit_card.dart
@@ -55,7 +55,7 @@ class _InitialVisitCardState extends State {
requestDetailProvider.needVisitHelperModel!.comment!.bodyText2(context).custom(color: AppColor.neutral120),
]
],
- ).toShadowContainer(context, padding: 16);
+ ).toShadowContainer(context);
});
}
}
diff --git a/lib/modules/cm_module/views/components/service_request_detail_view.dart b/lib/modules/cm_module/views/components/service_request_detail_view.dart
index c6fef7db..73a7f9ea 100644
--- a/lib/modules/cm_module/views/components/service_request_detail_view.dart
+++ b/lib/modules/cm_module/views/components/service_request_detail_view.dart
@@ -18,6 +18,7 @@ import 'package:test_sa/modules/cm_module/views/forms/asset_retired/asset_retire
import 'package:test_sa/modules/cm_module/views/forms/cost/cost_detail_form_screen.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/views/widgets/equipment/asset_detail_page.dart';
import 'package:test_sa/views/widgets/images/files_list.dart';
import 'package:test_sa/views/widgets/images/multi_image_picker.dart';
import 'package:test_sa/views/widgets/item_views/info_date_widget.dart';
@@ -141,7 +142,7 @@ class _ServiceRequestDetailViewState extends State {
// spacing: 8,
runSpacing: 8,
children: [
- if (Provider.of(context, listen: false).showPriority&&workOrder.priority!=null) ...[
+ if (Provider.of(context, listen: false).showPriority && workOrder.priority != null) ...[
StatusLabel(
label: workOrder.priority?.name,
id: workOrder.priority?.value,
@@ -192,9 +193,23 @@ class _ServiceRequestDetailViewState extends State {
],
),
8.height,
- InfoHeader16Widget(context.translation.assetInformation),
+ Row(
+ spacing: 4,
+ children: [
+ Flexible(
+ child: InfoHeader16Widget(context.translation.assetInformation),
+ ),
+ const Icon(Icons.open_in_new_rounded, color: AppColor.primary10, size: 16).onPress(() {
+ Navigator.of(context).pushNamed(AssetDetailPage.id, arguments: workOrder.asset!.id);
+ })
+ ],
+ ),
+ if (context.userProvider.isEngineer && !(workOrder.asset!.hasTrainingImageData ?? true)) ...[
+ InfoTextLabelWidget(label: '*Images are required for the asset', color: AppColor.red30, textStyle: AppTextStyles.tinyFont2),
+ 4.height,
+ ],
InfoTextWidget(label: context.translation.assetName, value: workOrder.assetNdModel!.name?.cleanupWhitespace.capitalizeFirstOfEach),
- InfoTextWidget(label: context.translation.assetNumber, value: workOrder.asset!.assetNumber),
+ InfoTextWidget(label: context.translation.assetNumber, value: workOrder.asset!.assetNumber, copyValue: true),
InfoTextWidget(label: context.translation.serialNo, value: workOrder.asset!.assetSerialNo),
InfoTextWidget(label: context.translation.manufacture, value: workOrder.manufacturer?.name?.cleanupWhitespace.capitalizeFirstOfEach),
InfoTextWidget(label: context.translation.model, value: workOrder.model?.name!.cleanupWhitespace.capitalizeFirstOfEach),
@@ -212,7 +227,7 @@ class _ServiceRequestDetailViewState extends State {
//... request details starts here....
InfoHeader16Widget(context.translation.callDetails),
- InfoTextWidget(label: context.translation.cmNumber, value: workOrder.workOrderNo),
+ InfoTextWidget(label: context.translation.cmNumber, value: workOrder.workOrderNo, copyValue: true),
InfoTextWidget(label: context.translation.createdBy, value: workOrder.workOrderCreatedBy?.userName ?? "-"),
InfoTextWidget(label: context.translation.arrivedDate, value: workOrder.iHaveArrivedDate != null ? workOrder.iHaveArrivedDate.toString().toServiceRequestDetailsFormat : '-'),
InfoTextWidget(label: context.translation.closedDate, value: workOrder.closedDate != null ? workOrder.closedDate!.toString().toServiceRequestDetailsFormat : '-'),
@@ -282,9 +297,7 @@ class _ServiceRequestDetailViewState extends State {
assetRetiredButton(context: context),
]
],
- ).toShadowContainer(
- context,
- );
+ ).toShadowContainer(context);
}
Widget contactInfoCard(BuildContext context, WorkOrderData workOrder) {
@@ -340,7 +353,7 @@ class _ServiceRequestDetailViewState extends State {
InfoTextWidget(label: 'MR No'.addTranslation, value: provider.currentWorkOrder?.data?.mrNo?.toString() ?? '-'),
InfoTextWidget(label: 'Exchange Cost'.addTranslation, value: provider.currentWorkOrder?.data?.exchangeCost?.toString() ?? '-'),
],
- ).toShadowContainer(context, padding: 16);
+ ).toShadowContainer(context);
}
Widget assetRetiredButton({required BuildContext context}) {
diff --git a/lib/modules/cx_module/chat/chat_page.dart b/lib/modules/cx_module/chat/chat_page.dart
index ea9893b6..6b0fbd37 100644
--- a/lib/modules/cx_module/chat/chat_page.dart
+++ b/lib/modules/cx_module/chat/chat_page.dart
@@ -388,7 +388,7 @@ class _ChatPageState extends State {
clipBehavior: Clip.antiAliasWithSaveLayer,
builder: (BuildContext context) => ChatFilePicker())) as File?;
if (file != null) {
- Utils.showUploadingDialog(context);
+ Utils.showLoadingWithTextDialog(context);
await chatProvider.uploadAttachments(context.userProvider.user!.username!, file, "1");
Utils.hideLoading(context);
}
@@ -638,7 +638,7 @@ class _ChatPageState extends State {
hoverColor: Colors.transparent,
onPressed: () async {
if (chatState == ChatState.voiceRecordingCompleted) {
- Utils.showUploadingDialog(context);
+ Utils.showLoadingWithTextDialog(context);
try {
await chatProvider.uploadAttachments(context.userProvider.user!.username!, File(recordedFilePath!), "1");
Utils.hideLoading(context);
diff --git a/lib/modules/cx_module/chat/helper/chat_file_viewer.dart b/lib/modules/cx_module/chat/helper/chat_file_viewer.dart
index 9eee8c44..34653e1b 100644
--- a/lib/modules/cx_module/chat/helper/chat_file_viewer.dart
+++ b/lib/modules/cx_module/chat/helper/chat_file_viewer.dart
@@ -24,7 +24,6 @@ class ChatFileViewer extends StatelessWidget {
@override
Widget build(BuildContext context) {
-
return FutureBuilder(
future: checkFileInLocalStorage(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
@@ -80,16 +79,7 @@ class ChatFileViewer extends StatelessWidget {
padding: EdgeInsets.zero,
onPressed: () async {
if (isImage) {
- Navigator.of(context).push(
- MaterialPageRoute(
- builder: (_) => Scaffold(
- appBar: const DefaultAppBar(),
- body: SafeArea(
- child: InteractiveViewer(child: Image.file(file)).center,
- ),
- ),
- ),
- );
+ context.fullScreenImageViewer(Image.file(file));
} else {
OpenFile.open(file.path);
}
diff --git a/lib/modules/cx_module/chat/view_all_attachment_page.dart b/lib/modules/cx_module/chat/view_all_attachment_page.dart
index 1e442591..8eb13b7d 100644
--- a/lib/modules/cx_module/chat/view_all_attachment_page.dart
+++ b/lib/modules/cx_module/chat/view_all_attachment_page.dart
@@ -182,16 +182,7 @@ class AttachmentFileViewer extends StatelessWidget {
),
).onPress(() {
if (isImage) {
- Navigator.of(context).push(
- MaterialPageRoute(
- builder: (_) => Scaffold(
- appBar: const DefaultAppBar(),
- body: SafeArea(
- child: InteractiveViewer(child: Image.file(snapshot.data!)).center,
- ),
- ),
- ),
- );
+ context.fullScreenImageViewer(Image.file(snapshot.data!));
} else {
OpenFile.open(snapshot.data!.path);
}
@@ -253,16 +244,7 @@ class AttachmentFileViewer extends StatelessWidget {
padding: EdgeInsets.zero,
onPressed: () async {
if (isImage) {
- Navigator.of(context).push(
- MaterialPageRoute(
- builder: (_) => Scaffold(
- appBar: const DefaultAppBar(),
- body: SafeArea(
- child: InteractiveViewer(child: Image.file(file)).center,
- ),
- ),
- ),
- );
+ context.fullScreenImageViewer(Image.file(file));
} else {
OpenFile.open(file.path);
}
diff --git a/lib/modules/demo_module/create_demo_request_page.dart b/lib/modules/demo_module/create_demo_request_page.dart
index a921ed91..4ff8f3ff 100644
--- a/lib/modules/demo_module/create_demo_request_page.dart
+++ b/lib/modules/demo_module/create_demo_request_page.dart
@@ -43,6 +43,8 @@ import 'package:test_sa/providers/gas_request_providers/site_provider.dart';
import 'package:test_sa/providers/loading_list_notifier.dart';
import 'package:test_sa/providers/work_order/vendor_provider.dart';
import 'package:test_sa/views/widgets/images/multi_image_picker.dart';
+import 'package:test_sa/views/widgets/item_views/info_header_widget.dart';
+import 'package:test_sa/views/widgets/item_views/info_text_widget.dart';
import '../../../../../../new_views/common_widgets/default_app_bar.dart';
import '../../models/new_models/department.dart';
import 'demo_detail_view_page.dart';
@@ -92,76 +94,23 @@ class _CreateDemoRequestPageState extends State with Tick
SingleChildScrollView(
padding: const EdgeInsets.all(16),
child: Column(
+ spacing: 12,
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
- // SingleItemDropDownMenu(
- // context: context,
- // title: "Demo Period",
- // initialValue: demoPeriodLookup,
- // showShadow: false,
- // validator: (value) {
- // if (value == null) return "Mandatory";
- // return null;
- // },
- // backgroundColor: AppColor.fieldBgColor(context),
- // showAsBottomSheet: true,
- // onSelect: (value) {
- // demoPeriodLookup = value;
- // setState(() {});
- // },
- // ),
- // 16.height,
...siteSection(),
- 16.height,
...doctorInfoSection(),
- 16.height,
...assetSection(),
- 16.height,
...vendorDetailsSection(),
- 16.height,
- "Attachments".bodyText(context).custom(color: AppColor.black10),
- 8.height,
- SingleItemDropDownMenu(
- context: context,
- height: 56.toScreenHeight,
- title: "Document Type",
- initialValue: demoDocumentLookup,
- showShadow: false,
- validator: (value) {
- if (value == null) return "Mandatory";
- return null;
- },
- backgroundColor: AppColor.fieldBgColor(context),
- showAsBottomSheet: true,
- onSelect: (value) {
- demoDocumentLookup = value;
- setState(() {});
- },
- ),
- 16.height,
- AttachmentPicker(
- label: context.translation.attachments,
- attachment: _attachments,
- buttonColor: AppColor.black10.withOpacity(demoDocumentLookup != null ? 1 : .4),
- onlyImages: false,
- enabled: demoDocumentLookup != null,
- documentType: demoDocumentLookup,
- showAsListView: true,
- buttonIcon: 'image-plus'.toSvgAsset(color: (AppColor.primary10).withOpacity(demoDocumentLookup != null ? 1 : .4)),
- onChange: (attachments) {
- _attachments = attachments;
- setState(() {});
- },
- ),
- 16.height,
+ ...attachmentSection(),
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Checkbox(
value: _demoFormModel.demoEaluationAcknowledge,
- visualDensity: const VisualDensity(horizontal: -4, vertical: -4),
- activeColor: AppColor.blueStatus(context),
+ activeColor: AppColor.primary10,
+ side: BorderSide(color: AppColor.loadingColor(context), width: 1.0),
+ visualDensity: const VisualDensity(horizontal: -4.0, vertical: -4.0),
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
onChanged: (value) {
setState(() {
@@ -172,24 +121,29 @@ class _CreateDemoRequestPageState extends State with Tick
Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
+ spacing: 4,
children: [
- "DEMO outcome evaluation form acknowledgement".bodyText(context).custom(color: context.isDark ? AppColor.primary50 : AppColor.neutral50),
- 4.height,
- "I acknowledge at the end of the trial period I will complete and submit the Medical Technology Trial Outcome Form within two weeks."
- .tinyFont(context)
- .custom(color: context.isDark ? AppColor.primary50 : AppColor.neutral120),
+ InfoTextLabelWidget(
+ label: "DEMO outcome evaluation form acknowledgement",
+ textStyle: AppTextStyles.bodyText,
+ color: AppColor.textColor(context),
+ ),
+ InfoTextLabelWidget(
+ label: "I acknowledge at the end of the trial period I will complete and submit the Medical Technology Trial Outcome Form within two weeks.",
+ color: AppColor.lightTextColor(context),
+ ),
],
).expanded,
],
),
- 16.height,
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Checkbox(
value: _demoFormModel.acknowledgeNotEquipment,
- visualDensity: const VisualDensity(horizontal: -4, vertical: -4),
- activeColor: AppColor.blueStatus(context),
+ activeColor: AppColor.primary10,
+ side: BorderSide(color: AppColor.loadingColor(context), width: 1.0),
+ visualDensity: const VisualDensity(horizontal: -4.0, vertical: -4.0),
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
onChanged: (value) {
setState(() {
@@ -200,18 +154,23 @@ class _CreateDemoRequestPageState extends State with Tick
Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
+ spacing: 4,
children: [
- "Acknowledgement of not using the equipment".bodyText(context).custom(color: context.isDark ? AppColor.primary50 : AppColor.neutral50),
- 4.height,
- "I acknowledge at the end of the trial period I will not use the DEMO medical equipment & I will not book any patient on the DEMO medical equipment."
- .tinyFont(context)
- .custom(color: context.isDark ? AppColor.primary50 : AppColor.neutral120),
+ InfoTextLabelWidget(
+ label: "Acknowledgement of not using the equipment",
+ textStyle: AppTextStyles.bodyText,
+ color: AppColor.textColor(context),
+ ),
+ InfoTextLabelWidget(
+ label: "I acknowledge at the end of the trial period I will not use the DEMO medical equipment & I will not book any patient on the DEMO medical equipment.",
+ color: AppColor.lightTextColor(context),
+ ),
],
).expanded,
],
),
],
- ).toShadowContainer(context, borderRadius: 20),
+ ).toShadowContainer(context),
).expanded,
FooterActionButton.footerContainer(
context: context,
@@ -231,8 +190,7 @@ class _CreateDemoRequestPageState extends State with Tick
List siteSection() {
return [
- 'Site Details'.addTranslation.bodyText(context).custom(color: AppColor.black10),
- 8.height,
+ InfoHeader16Widget('Site Details'.addTranslation),
SingleItemDropDownMenu(
context: context,
title: context.translation.site,
@@ -252,7 +210,6 @@ class _CreateDemoRequestPageState extends State with Tick
setState(() {});
},
),
- 8.height,
SingleItemDropDownMenu(
context: context,
title: context.translation.building,
@@ -273,7 +230,6 @@ class _CreateDemoRequestPageState extends State with Tick
setState(() {});
},
),
- 8.height,
SingleItemDropDownMenu(
context: context,
title: context.translation.floor,
@@ -293,7 +249,6 @@ class _CreateDemoRequestPageState extends State with Tick
setState(() {});
},
),
- 8.height,
SingleItemDropDownMenu(
context: context,
title: context.translation.department,
@@ -318,8 +273,7 @@ class _CreateDemoRequestPageState extends State with Tick
List doctorInfoSection() {
return [
- "Doctor Details".bodyText(context).custom(color: AppColor.black10),
- 8.height,
+ InfoHeader16Widget('Doctor Details'.addTranslation),
AppTextFormField(
initialValue: "",
labelText: "Name",
@@ -336,7 +290,6 @@ class _CreateDemoRequestPageState extends State with Tick
_demoFormModel.docName = value;
},
),
- 8.height,
AppTextFormField(
initialValue: "",
labelText: "Contact Number",
@@ -353,7 +306,6 @@ class _CreateDemoRequestPageState extends State with Tick
_demoFormModel.docNumber = value;
},
),
- 8.height,
AppTextFormField(
initialValue: "",
labelText: "Email",
@@ -373,7 +325,6 @@ class _CreateDemoRequestPageState extends State with Tick
_demoFormModel.docEmail = value;
},
),
- 8.height,
AppTextFormField(
labelText: "Item Description",
validator: (value) {
@@ -391,7 +342,6 @@ class _CreateDemoRequestPageState extends State with Tick
_demoFormModel.itemDescription = value;
},
),
- 8.height,
AppTextFormField(
labelText: "Request Description",
// validator: (value) {
@@ -414,8 +364,7 @@ class _CreateDemoRequestPageState extends State with Tick
List assetSection() {
return [
- 'Asset Details'.addTranslation.bodyText(context).custom(color: AppColor.black10),
- 8.height,
+ InfoHeader16Widget('Asset Details'.addTranslation),
AppTextFormField(
labelText: "Asset Name",
validator: (value) {
@@ -433,7 +382,6 @@ class _CreateDemoRequestPageState extends State with Tick
_demoFormModel.assetName = value;
},
),
- 8.height,
AppTextFormField(
labelText: "Model",
validator: (value) {
@@ -451,7 +399,6 @@ class _CreateDemoRequestPageState extends State with Tick
_demoFormModel.model = value;
},
),
- 8.height,
AppTextFormField(
labelText: "Manufacturer",
validator: (value) {
@@ -469,7 +416,6 @@ class _CreateDemoRequestPageState extends State with Tick
_demoFormModel.manufacturer = value;
},
),
- 8.height,
SingleItemDropDownMenu(
context: context,
height: 56.toScreenHeight,
@@ -492,8 +438,7 @@ class _CreateDemoRequestPageState extends State with Tick
List vendorDetailsSection() {
return [
- 'Vendor Details'.addTranslation.bodyText(context).custom(color: AppColor.black10),
- 8.height,
+ InfoHeader16Widget('Vendor Details'.addTranslation),
AppTextFormField(
labelText: 'Vendor Name'.addTranslation,
style: Theme.of(context).textTheme.titleMedium,
@@ -506,7 +451,6 @@ class _CreateDemoRequestPageState extends State with Tick
_demoFormModel.vendorName = value;
},
),
- 8.height,
AppTextFormField(
labelText: 'Representative Name'.addTranslation,
style: Theme.of(context).textTheme.titleMedium,
@@ -519,7 +463,6 @@ class _CreateDemoRequestPageState extends State with Tick
_demoFormModel.vendorRepresentativeName = value;
},
),
- 8.height,
AppTextFormField(
// controller: vendorPhoneController,
labelText: "Contact Number",
@@ -533,7 +476,6 @@ class _CreateDemoRequestPageState extends State with Tick
_demoFormModel.vendorContactNumber = value;
},
),
- 8.height,
AppTextFormField(
labelText: "Email",
// controller: vendorEmailController,
@@ -550,6 +492,43 @@ class _CreateDemoRequestPageState extends State with Tick
];
}
+ List attachmentSection() {
+ return [
+ InfoHeader16Widget('Attachments'.addTranslation),
+ SingleItemDropDownMenu(
+ context: context,
+ height: 56.toScreenHeight,
+ title: "Document Type",
+ initialValue: demoDocumentLookup,
+ showShadow: false,
+ validator: (value) {
+ if (value == null) return "Mandatory";
+ return null;
+ },
+ backgroundColor: AppColor.fieldBgColor(context),
+ showAsBottomSheet: true,
+ onSelect: (value) {
+ demoDocumentLookup = value;
+ setState(() {});
+ },
+ ),
+ AttachmentPicker(
+ label: context.translation.attachments,
+ attachment: _attachments,
+ buttonColor: AppColor.primary10.withOpacity(demoDocumentLookup != null ? 1 : .4),
+ onlyImages: false,
+ enabled: demoDocumentLookup != null,
+ documentType: demoDocumentLookup,
+ showAsListView: true,
+ buttonIcon: 'image-plus'.toSvgAsset(color: (AppColor.primary10).withOpacity(demoDocumentLookup != null ? 1 : .4)),
+ onChange: (attachments) {
+ _attachments = attachments;
+ setState(() {});
+ },
+ ),
+ ];
+ }
+
Future _submit() async {
FocusScope.of(context).unfocus();
if (_formKey.currentState!.validate()) {
diff --git a/lib/modules/demo_module/demo_detail_view_page.dart b/lib/modules/demo_module/demo_detail_view_page.dart
index cac6e356..6d98e438 100644
--- a/lib/modules/demo_module/demo_detail_view_page.dart
+++ b/lib/modules/demo_module/demo_detail_view_page.dart
@@ -16,6 +16,8 @@ import 'package:test_sa/modules/loan_module/models/loan_attachment_model.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/swipe_module/dialoge/acknowledge_work_dialog.dart';
+import 'package:test_sa/views/widgets/item_views/info_header_widget.dart';
+import 'package:test_sa/views/widgets/item_views/info_text_widget.dart';
import 'package:test_sa/views/widgets/loaders/no_data_found.dart';
import '../../controllers/api_routes/urls.dart';
@@ -111,7 +113,6 @@ class _DemoDetailViewPageState extends State {
),
8.height,
],
- 12.height,
...requesterDetails(context, demoData),
const Divider().defaultStyle(context),
...requestDetails(context, demoData),
@@ -123,10 +124,7 @@ class _DemoDetailViewPageState extends State {
...vendorDetails(context, demoData),
if (allAttachments.isNotEmpty) ...[
const Divider().defaultStyle(context),
- Text(
- "Attachments".addTranslation,
- style: AppTextStyles.heading6.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50),
- ),
+ InfoHeader16Widget("Attachments"),
FilesList(
showAsListView: true,
images: allAttachments.map((e) => URLs.getFileUrl(e.attachmentName ?? '') ?? '').toList(),
@@ -134,10 +132,7 @@ class _DemoDetailViewPageState extends State {
],
if (suppAttachments.isNotEmpty) ...[
const Divider().defaultStyle(context),
- Text(
- "Supplier Attachments".addTranslation,
- style: AppTextStyles.heading6.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50),
- ),
+ InfoHeader16Widget("Supplier Attachments"),
FilesList(
showAsListView: true,
images: suppAttachments.map((e) => URLs.getFileUrl(e.attachmentName ?? '') ?? '').toList(),
@@ -191,53 +186,53 @@ class _DemoDetailViewPageState extends State {
List requestDetails(BuildContext context, DemoRequestModel? model) {
return [
- Text("Request Details", style: AppTextStyles.heading6.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50)),
- 'Request No: ${model?.requestNo ?? "-"}'.bodyText(context),
- 'Demo No: ${model?.demoNo ?? "-"}'.bodyText(context),
- 'Demo Period: ${model?.demoPeriod?.name ?? "-"}'.bodyText(context),
- '${context.translation.site}: ${model?.site?.custName ?? "-"}'.bodyText(context),
- '${context.translation.building}: ${model?.building?.name ?? "-"}'.bodyText(context),
- '${context.translation.floor}: ${model?.floor?.name ?? "-"}'.bodyText(context),
- '${context.translation.department}: ${model?.department?.departmentName ?? "-"}'.bodyText(context),
- 'Item Description: ${model?.itemDescription ?? "-"}'.bodyText(context),
- 'Request Description: ${model?.requestDescription ?? "-"}'.bodyText(context),
+ InfoHeader16Widget("Request Information"),
+ InfoTextWidget(label: "Request No", value: model?.requestNo ?? "-", copyValue: true),
+ InfoTextWidget(label: "Demo No", value: model?.demoNo ?? "-"),
+ InfoTextWidget(label: "Demo Period", value: model?.demoPeriod?.name ?? "-"),
+ InfoTextWidget(label: context.translation.site, value: model?.site?.custName ?? "-"),
+ InfoTextWidget(label: context.translation.building, value: model?.building?.name ?? "-"),
+ InfoTextWidget(label: context.translation.floor, value: model?.floor?.name ?? "-"),
+ InfoTextWidget(label: context.translation.department, value: model?.department?.departmentName ?? "-"),
+ InfoTextWidget(label: "Item Description", value: model?.itemDescription ?? "-"),
+ InfoTextWidget(label: "Request Description", value: model?.requestDescription ?? "-"),
];
}
List vendorDetails(BuildContext context, DemoRequestModel? model) {
return [
- Text("Vendor Information", style: AppTextStyles.heading6.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50)),
- 'Name: ${model?.supplier?.name ?? model?.vendorName ?? "-"}'.bodyText(context),
- 'Representative Name: ${model?.suppPerson?.name ?? model?.vendorRepresentativeName ?? "-"}'.bodyText(context),
- 'Contact: ${model?.supplier?.contact ?? model?.vendorContactNumber ?? "-"}'.bodyText(context),
- 'Email: ${model?.supplier?.email ?? model?.vendorEmail ?? "-"}'.bodyText(context),
+ InfoHeader16Widget("Vendor Information"),
+ InfoTextWidget(label: "Name", value: model?.supplier?.name ?? model?.vendorName ?? "-"),
+ InfoTextWidget(label: "Representative Name", value: model?.suppPerson?.name ?? model?.vendorRepresentativeName ?? "-"),
+ InfoTextWidget(label: "Contact", value: model?.supplier?.contact ?? model?.vendorContactNumber ?? "-"),
+ InfoTextWidget(label: "Email", value: model?.supplier?.email ?? model?.vendorEmail ?? "-"),
];
}
List assetDetails(BuildContext context, DemoRequestModel? model) {
return [
- Text("Asset Information", style: AppTextStyles.heading6.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50)),
- '${context.translation.assetName}: ${model?.assetName ?? "-"}'.bodyText(context),
- '${context.translation.manufacture}: ${model?.manufacturer ?? "-"}'.bodyText(context),
- '${context.translation.model}: ${model?.model ?? "-"}'.bodyText(context),
+ InfoHeader16Widget("Asset Information"),
+ InfoTextWidget(label: context.translation.assetName, value: model?.assetName ?? "-"),
+ InfoTextWidget(label: context.translation.manufacture, value: model?.manufacturer ?? "-"),
+ InfoTextWidget(label: context.translation.model, value: model?.model ?? "-"),
];
}
List doctorDetails(BuildContext context, DemoRequestModel? model) {
return [
- Text("Doctor Information", style: AppTextStyles.heading6.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50)),
- 'Name: ${model?.doctorName ?? "-"}'.bodyText(context),
- 'Contact: ${model?.doctorContactNumber ?? "-"}'.bodyText(context),
- 'Email: ${model?.doctorContactEmail ?? "-"}'.bodyText(context),
+ InfoHeader16Widget("Doctor Information"),
+ InfoTextWidget(label: "Name", value: model?.doctorName ?? "-"),
+ InfoTextWidget(label: "Contact", value: model?.doctorContactNumber ?? "-"),
+ InfoTextWidget(label: "Email", value: model?.doctorContactEmail ?? "-"),
];
}
List requesterDetails(BuildContext context, DemoRequestModel? model) {
return [
- Text("Requester Information", style: AppTextStyles.heading6.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50)),
- 'Name: ${model?.requesterUser?.requesterName ?? "-"}'.bodyText(context),
- 'Email: ${model?.requesterUser?.requesterEmail ?? "-"}'.bodyText(context),
- 'Contact: ${model?.requesterUser?.requesterMobile ?? "-"}'.bodyText(context),
+ InfoHeader16Widget("Requester Information"),
+ InfoTextWidget(label: "Name", value: model?.requesterUser?.requesterName ?? "-"),
+ InfoTextWidget(label: "Email", value: model?.requesterUser?.requesterEmail ?? "-"),
+ InfoTextWidget(label: "Contact", value: model?.requesterUser?.requesterMobile ?? "-"),
// 'Extension: ${loanData.requesterExtensionNo ?? "-"}'.bodyText(context),
];
}
diff --git a/lib/modules/export_module/provider/export_provider.dart b/lib/modules/export_module/provider/export_provider.dart
index f80c390e..81b80f8e 100644
--- a/lib/modules/export_module/provider/export_provider.dart
+++ b/lib/modules/export_module/provider/export_provider.dart
@@ -50,6 +50,7 @@ class ExportApiProvider extends ChangeNotifier {
valueColor: textColor,
elevation: 4,
msgFontSize: 14,
+ borderRadius: 14,
backgroundColor: backgroundColor,
cancel: Cancel(
cancelClicked: () {
diff --git a/lib/modules/export_module/widgets/cleaner_checklist_widget.dart b/lib/modules/export_module/widgets/cleaner_checklist_widget.dart
index 12d22165..090de70b 100644
--- a/lib/modules/export_module/widgets/cleaner_checklist_widget.dart
+++ b/lib/modules/export_module/widgets/cleaner_checklist_widget.dart
@@ -200,21 +200,7 @@ class _CleanerChecklistWidgetState extends State {
),
child: imageWidget)
.onPress(() {
- Navigator.of(context).push(
- MaterialPageRoute(
- builder: (_) => Scaffold(
- body: SafeArea(
- child: Stack(
- children: [
- // InteractiveViewer(child: Image(image: getImageObject(itemIndex))).center,
- InteractiveViewer(child: imageWidget).center,
- const ABackButton(),
- ],
- ),
- ),
- ),
- ),
- );
+ context.fullScreenImageViewer(imageWidget);
}),
_delete(),
],
@@ -241,21 +227,7 @@ class _CleanerChecklistWidgetState extends State {
),
child: imageWidget)
.onPress(() {
- Navigator.of(context).push(
- MaterialPageRoute(
- builder: (_) => Scaffold(
- body: SafeArea(
- child: Stack(
- children: [
- // InteractiveViewer(child: Image(image: getImageObject(itemIndex))).center,
- InteractiveViewer(child: imageWidget).center,
- const ABackButton(),
- ],
- ),
- ),
- ),
- ),
- );
+ context.fullScreenImageViewer(imageWidget);
}),
_delete(),
],
@@ -300,21 +272,7 @@ class _CleanerChecklistWidgetState extends State {
),
child: imageWidget)
.onPress(() {
- Navigator.of(context).push(
- MaterialPageRoute(
- builder: (_) => Scaffold(
- body: SafeArea(
- child: Stack(
- children: [
- // InteractiveViewer(child: Image(image: getImageObject(itemIndex))).center,
- InteractiveViewer(child: imageWidget).center,
- const ABackButton(),
- ],
- ),
- ),
- ),
- ),
- );
+ context.fullScreenImageViewer(imageWidget);
}),
_delete(),
],
diff --git a/lib/modules/export_module/widgets/file_success_dialog.dart b/lib/modules/export_module/widgets/file_success_dialog.dart
index 015ff7e0..e66c0c43 100644
--- a/lib/modules/export_module/widgets/file_success_dialog.dart
+++ b/lib/modules/export_module/widgets/file_success_dialog.dart
@@ -7,6 +7,7 @@ import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.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/views/widgets/item_views/info_header_widget.dart';
/// Reusable success dialog for file operations (export, print, etc.)
class FileSuccessDialog {
@@ -31,47 +32,25 @@ class FileSuccessDialog {
return Dialog(
backgroundColor: AppColor.background(context),
shape: RoundedRectangleBorder(
- borderRadius: BorderRadius.circular(16),
+ side: BorderSide(color: AppColor.borderColor(context)),
+ borderRadius: BorderRadius.circular(14),
),
child: Padding(
- padding: const EdgeInsets.all(24.0),
+ padding: const EdgeInsets.all(16.0),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
- // Close button
Align(
alignment: Alignment.topRight,
- child: 'clear'.toSvgAsset(
- color: AppColor.icon2Color(context),
- width: 18,
- height: 18,
- ).onPress(() {
+ child: 'clear'.toSvgAsset(color: AppColor.icon2Color(context), width: 18, height: 18).onPress(() {
Navigator.of(dialogContext).pop();
}),
),
- // Success icon
'done'.toSvgAsset(color: AppColor.green70, width: 56, height: 56),
const SizedBox(height: 24),
- // Title
- Text(
- title,
- style: TextStyle(
- fontSize: 20,
- fontWeight: FontWeight.bold,
- color: AppColor.headingTextColor(context),
- ),
- textAlign: TextAlign.center,
- ),
+ title.heading5(context).custom(fontWeight: FontWeight.w600, color: AppColor.textStyleColor(context)),
const SizedBox(height: 12),
- // Message
- Text(
- message,
- style: TextStyle(
- fontSize: 18,
- color: AppColor.lightTextColor(context),
- ),
- textAlign: TextAlign.center,
- ),
+ message.heading6(context).custom(align: TextAlign.center, fontWeight: FontWeight.w500, color: AppColor.lightTextColor(context)),
const SizedBox(height: 32),
// Action buttons
Row(
@@ -84,14 +63,13 @@ class FileSuccessDialog {
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;
+ 'No app found to open this file type. File saved to: $filePath'.showToast;
}
},
label: 'Open',
// buttonColor: AppColor.primary10,
showIcon: true,
- icon: Icon(Icons.folder_open, color: AppColor.background(context)),
+ icon: Icon(Icons.folder_open, color: AppColor.background(context)),
height: 48,
),
),
@@ -131,4 +109,3 @@ class FileSuccessDialog {
);
}
}
-
diff --git a/lib/modules/incident_module/create_incident_request_page.dart b/lib/modules/incident_module/create_incident_request_page.dart
index 3e8e0aad..d1535400 100644
--- a/lib/modules/incident_module/create_incident_request_page.dart
+++ b/lib/modules/incident_module/create_incident_request_page.dart
@@ -133,7 +133,7 @@ class _CreateIncidentRequestPageState extends State {
onPick: (asset) async {
device = asset;
payload["assetId"] = asset?.id;
- payload["oracleCode"] = asset.modelDefinition?.oracleCodes?.first.codeValue;
+ payload["oracleCode"] = (asset.modelDefinition?.oracleCodes?.isNotEmpty ?? false) ? asset.modelDefinition?.oracleCodes?.first.codeValue : null;
payload["model"] = asset.modelDefinition?.modelName;
payload["manufacturer"] = asset.modelDefinition?.manufacturerName;
payload["assetOrigin"] = asset.modelDefinition?.assetName;
diff --git a/lib/modules/incident_module/incident_detail_page.dart b/lib/modules/incident_module/incident_detail_page.dart
index b131c0eb..4f9ade6e 100644
--- a/lib/modules/incident_module/incident_detail_page.dart
+++ b/lib/modules/incident_module/incident_detail_page.dart
@@ -41,41 +41,39 @@ class IncidentDetailPage extends StatelessWidget {
List allAttachments = snapshot.data!.incidentAttachments!;
- return ListView(
+ return SingleChildScrollView(
padding: const EdgeInsets.all(16),
- children: [
- Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Row(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- StatusLabel(
- label: snapshot.data!.incidentStatusName!,
- textColor: AppColor.getRequestStatusTextColorByName(context, snapshot.data!.incidentStatusName!),
- backgroundColor: AppColor.getRequestStatusColorByName(context, snapshot.data!.incidentStatusName!),
- ),
- 1.width.expanded,
- InfoDateWidget(snapshot.data!.createdDate?.toString() ?? ""),
- ],
- ),
- // 12.height,
- ...requesterDetails(context, snapshot.data!),
- const Divider().defaultStyle(context),
- ...requestDetails(context, snapshot.data!),
- if (snapshot.data!.ovrTicketNumber?.isNotEmpty ?? false) ovrInformation(context, snapshot.data!.ovrTicketNumber!),
- const Divider().defaultStyle(context),
- ...assetDetails(context, snapshot.data!),
- const Divider().defaultStyle(context),
- ...personInvolvedDetails(context, snapshot.data!),
- if (allAttachments.isNotEmpty) ...[
- const Divider().defaultStyle(context),
- InfoHeader16Widget("Attachments".addTranslation),
- FilesList(images: allAttachments.map((e) => URLs.getFileUrl(e.attachmentName ?? '') ?? '').toList() ?? []),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Row(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ StatusLabel(
+ label: snapshot.data!.incidentStatusName!,
+ textColor: AppColor.getRequestStatusTextColorByName(context, snapshot.data!.incidentStatusName!),
+ backgroundColor: AppColor.getRequestStatusColorByName(context, snapshot.data!.incidentStatusName!),
+ ),
+ 1.width.expanded,
+ InfoDateWidget(snapshot.data!.createdDate?.toString() ?? ""),
],
+ ),
+ // 12.height,
+ ...requesterDetails(context, snapshot.data!),
+ const Divider().defaultStyle(context),
+ ...requestDetails(context, snapshot.data!),
+ if (snapshot.data!.ovrTicketNumber?.isNotEmpty ?? false) ovrInformation(context, snapshot.data!.ovrTicketNumber!),
+ const Divider().defaultStyle(context),
+ ...assetDetails(context, snapshot.data!),
+ const Divider().defaultStyle(context),
+ ...personInvolvedDetails(context, snapshot.data!),
+ if (allAttachments.isNotEmpty) ...[
+ const Divider().defaultStyle(context),
+ InfoHeader16Widget("Attachments".addTranslation),
+ FilesList(images: allAttachments.map((e) => URLs.getFileUrl(e.attachmentName ?? '') ?? '').toList() ?? []),
],
- ).toShadowContainer(context, padding: 16),
- ],
+ ],
+ ).toShadowContainer(context),
);
}));
}
@@ -83,7 +81,7 @@ class IncidentDetailPage extends StatelessWidget {
List requestDetails(BuildContext context, IncidentDataModel incidentData) {
return [
InfoHeader16Widget("Request Details"),
- InfoTextWidget(label: 'Incident No', value: incidentData.reqCode ?? "-"),
+ InfoTextWidget(label: 'Incident No', value: incidentData.reqCode ?? "-", copyValue: true),
InfoTextWidget(label: 'Incident Type', value: incidentData.incidentClassificationName ?? "-"),
InfoTextWidget(label: 'Incident Title', value: incidentData.incidentTitle ?? "-"),
InfoTextWidget(label: 'Incident Description', value: incidentData.incidentDescription ?? "-"),
@@ -95,10 +93,10 @@ class IncidentDetailPage extends StatelessWidget {
InfoTextWidget(label: 'Occurrence Date', value: incidentData.occurrenceDate?.toServiceRequestDetailsFormat ?? "-"),
if (incidentData.workOrderId != null)
RichText(
- text: TextSpan(text: "Work Order: ", style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20), children: [
+ text: TextSpan(text: "Work Order: ", style: AppTextStyles.bodyText2.copyWith(color: AppColor.lightTextColor(context)), children: [
TextSpan(
text: "${incidentData.workOrderNo}",
- style: AppTextStyles.bodyText.copyWith(color: AppColor.blueStatus(context), decoration: TextDecoration.underline),
+ style: AppTextStyles.bodyText.copyWith(color: AppColor.primary10, decoration: TextDecoration.underline),
recognizer: TapGestureRecognizer()
..onTap = () async {
await Navigator.of(context).push(MaterialPageRoute(builder: (_) => CMDetailPage(requestId: incidentData.workOrderId!, moduleId: 3)));
diff --git a/lib/modules/internal_audit_module/pages/equipment_internal_audit/equipment_internal_audit_detail_page.dart b/lib/modules/internal_audit_module/pages/equipment_internal_audit/equipment_internal_audit_detail_page.dart
index f1f44a77..b617db05 100644
--- a/lib/modules/internal_audit_module/pages/equipment_internal_audit/equipment_internal_audit_detail_page.dart
+++ b/lib/modules/internal_audit_module/pages/equipment_internal_audit/equipment_internal_audit_detail_page.dart
@@ -185,7 +185,7 @@ class _EquipmentInternalAuditDetailPageState extends State {
FilesList(images: allAttachments.map((e) => URLs.getFileUrl(e.attachmentName ?? '') ?? '').toList() ?? []),
],
],
- ).toShadowContainer(context, padding: 12)
+ ).toShadowContainer(context)
],
).expanded,
// @todo ask backend to add loanTypeValue, so we can show or hide the buttons
@@ -184,7 +184,7 @@ class _LoanEquipmentDetailPageState extends State {
return [
InfoHeader16Widget("Request Details"),
InfoTextWidget(label: 'Loan Type', value: loanData.loanTypeName ?? "-"),
- InfoTextWidget(label: 'Loan No', value: loanData.reqCode ?? "-"),
+ InfoTextWidget(label: 'Loan No', value: loanData.reqCode ?? "-", copyValue: true),
InfoTextWidget(label: 'Loan Period', value: loanData.loanPeriodName ?? "-"),
InfoTextWidget(label: context.translation.site, value: loanData.siteName ?? "-"),
InfoTextWidget(label: context.translation.department, value: loanData.departmentName ?? "-"),
diff --git a/lib/modules/medical_gas_inspection/medical_gas_inspection_detail_page.dart b/lib/modules/medical_gas_inspection/medical_gas_inspection_detail_page.dart
index 61b4e037..b499f20b 100644
--- a/lib/modules/medical_gas_inspection/medical_gas_inspection_detail_page.dart
+++ b/lib/modules/medical_gas_inspection/medical_gas_inspection_detail_page.dart
@@ -90,7 +90,7 @@ class _MedicalGasInspectionDetailPageState extends State URLs.getFileUrl(e.name ?? '') ?? '').toList() ?? []),
],
],
- ).toShadowContainer(context, padding: 16),
+ ).toShadowContainer(context,),
],
).expanded,
if (model?.requestStatus?.value != null && model!.requestStatus!.value! < 3)
diff --git a/lib/modules/medical_gas_inspection/update_delivery_notes_page.dart b/lib/modules/medical_gas_inspection/update_delivery_notes_page.dart
index c4fd21ba..47c77c39 100644
--- a/lib/modules/medical_gas_inspection/update_delivery_notes_page.dart
+++ b/lib/modules/medical_gas_inspection/update_delivery_notes_page.dart
@@ -400,7 +400,8 @@ class _UpdateDeliveryNotesState extends State {
vertical: 6, // keeps normal height ~30
),
filled: true,
- fillColor: AppColor.fieldBgColor(context),
+ fillColor: AppColor.dropDownBackground(context),
+ // fillColor: AppColor.fieldBgColor(context),
border: border,
enabledBorder: border,
focusedBorder: border,
diff --git a/lib/modules/pm_module/ppm_wo/ppm_details_page.dart b/lib/modules/pm_module/ppm_wo/ppm_details_page.dart
index 622131a3..bf64bf9a 100644
--- a/lib/modules/pm_module/ppm_wo/ppm_details_page.dart
+++ b/lib/modules/pm_module/ppm_wo/ppm_details_page.dart
@@ -70,6 +70,7 @@ class _PpmDetailsPageState extends State {
: planPreventiveVisit != null
? Column(children: [
SingleChildScrollView(
+ padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
@@ -86,7 +87,7 @@ class _PpmDetailsPageState extends State {
InfoHeader16Widget(planPreventiveVisit.assetName?.cleanupWhitespace.capitalizeFirstOfEach ?? ''),
InfoTextWidget(label: context.translation.assetNumber, value: planPreventiveVisit.asset?.assetNumber ?? '-'),
InfoTextWidget(label: context.translation.assetSN, value: planPreventiveVisit.asset?.assetSerialNo ?? '-'),
- InfoTextWidget(label: context.translation.requestNo, value: planPreventiveVisit.visitNo ?? '-'),
+ InfoTextWidget(label: context.translation.requestNo, value: planPreventiveVisit.visitNo ?? '-', copyValue: true),
if (planPreventiveVisit.acutalDateOfVisit != null) ...[
const Divider().defaultStyle(context),
InfoTextWidget(label: context.translation.actualDate, value: planPreventiveVisit.acutalDateOfVisit?.toIso8601String().toAssetDetailsFormat ?? ""),
@@ -99,7 +100,7 @@ class _PpmDetailsPageState extends State {
InfoTextWidget(label: context.translation.department, value: planPreventiveVisit.departmentName?.cleanupWhitespace.capitalizeFirstOfEach ?? '-'),
InfoTextWidget(label: context.translation.room, value: (planPreventiveVisit.roomName ?? "").cleanupWhitespace.capitalizeFirstOfEach),
],
- ).toShadowContainer(context, padding: 16),
+ ).toShadowContainer(context),
).expanded,
if (userProvider!.user!.type == UsersTypes.engineer && (!ppmProvider.isReadOnly)) ...[
FooterActionButton.footerContainer(
diff --git a/lib/modules/pm_module/recurrent_wo/components/task_info_widget.dart b/lib/modules/pm_module/recurrent_wo/components/task_info_widget.dart
index e76ca8bd..d65022c7 100644
--- a/lib/modules/pm_module/recurrent_wo/components/task_info_widget.dart
+++ b/lib/modules/pm_module/recurrent_wo/components/task_info_widget.dart
@@ -80,7 +80,7 @@ class _RecurrentTaskInfoWidgetState extends State {
),
8.height,
InfoHeader16Widget(widget.model!.title!),
- InfoTextWidget(label: context.translation.taskNo, value: widget.model!.taskNo!),
+ InfoTextWidget(label: context.translation.taskNo, value: widget.model!.taskNo!, copyValue: true),
InfoTextWidget(label: 'Plan Name:'.addTranslation, value: widget.model?.planRecurrent?.planName),
InfoTextWidget(label: context.translation.site, value: widget.model!.site!.siteName!),
if (widget.isHouseKeeper) ...[
diff --git a/lib/modules/tm_module/device_transfer/device_filter_screen.dart b/lib/modules/tm_module/device_transfer/device_filter_screen.dart
index bf55ae1e..04802a5e 100644
--- a/lib/modules/tm_module/device_transfer/device_filter_screen.dart
+++ b/lib/modules/tm_module/device_transfer/device_filter_screen.dart
@@ -91,6 +91,7 @@ class _DeviceFilterScreenState extends State {
return Scaffold(
appBar: DefaultAppBar(
title: context.translation.filter,
+ showBackButtonAsCancel: true,
actions: [
if (loading == false && _showResetButton())
TextButton(
diff --git a/lib/modules/tm_module/device_transfer/device_search_screen.dart b/lib/modules/tm_module/device_transfer/device_search_screen.dart
index 74cdeeb6..88050fb2 100644
--- a/lib/modules/tm_module/device_transfer/device_search_screen.dart
+++ b/lib/modules/tm_module/device_transfer/device_search_screen.dart
@@ -51,7 +51,6 @@ class _DeviceSearchScreenState extends State {
_modelController.dispose();
_supplierController.dispose();
_siteController.dispose();
- _siteController.dispose();
_manufactureController.dispose();
_mdController.dispose();
super.dispose();
@@ -62,6 +61,7 @@ class _DeviceSearchScreenState extends State {
return Scaffold(
appBar: DefaultAppBar(
title: context.translation.search,
+ showBackButtonAsCancel: true,
actions: [
if (_showResetButton())
TextButton(
diff --git a/lib/modules/tm_module/device_transfer/device_transfer_details.dart b/lib/modules/tm_module/device_transfer/device_transfer_details.dart
index a7579fb2..3c4c0993 100644
--- a/lib/modules/tm_module/device_transfer/device_transfer_details.dart
+++ b/lib/modules/tm_module/device_transfer/device_transfer_details.dart
@@ -94,7 +94,7 @@ class _DeviceTransferDetailsState extends State {
),
8.height,
InfoHeader16Widget(context.translation.callDetails),
- InfoTextWidget(label: context.translation.trNumber, value: _model?.transferCode ?? "-"),
+ InfoTextWidget(label: context.translation.trNumber, value: _model?.transferCode ?? "-", copyValue: true),
InfoTextWidget(label: context.translation.createdBy, value: _model?.name ?? "-"),
const Divider().defaultStyle(context),
InfoHeader16Widget(context.translation.assetInformation),
diff --git a/lib/modules/tm_module/gas_refill/gas_refill_details.dart b/lib/modules/tm_module/gas_refill/gas_refill_details.dart
index 520d2518..bbeee78a 100644
--- a/lib/modules/tm_module/gas_refill/gas_refill_details.dart
+++ b/lib/modules/tm_module/gas_refill/gas_refill_details.dart
@@ -204,7 +204,7 @@ class _GasRefillDetailsPageState extends State {
),
8.height,
InfoHeader16Widget(context.translation.callDetails),
- InfoTextWidget(label: context.translation.requestNo, value: gasRefillModel.gasRefillNo ?? '-'),
+ InfoTextWidget(label: context.translation.requestNo, value: gasRefillModel.gasRefillNo ?? '-', copyValue: true),
InfoTextWidget(label: context.translation.createdBy, value: gasRefillModel.name ?? '-'),
InfoTextWidget(label: context.translation.gasType, value: gasRefillModel.gasRefillDetails?[0].gasType?.name ?? '-'),
InfoTextWidget(label: context.translation.cylinderType, value: gasRefillModel.gasRefillDetails?[0].cylinderType?.name ?? '-'),
diff --git a/lib/modules/tm_module/tasks/task_request_detail_view.dart b/lib/modules/tm_module/tasks/task_request_detail_view.dart
index ca6f02e8..326c3989 100644
--- a/lib/modules/tm_module/tasks/task_request_detail_view.dart
+++ b/lib/modules/tm_module/tasks/task_request_detail_view.dart
@@ -103,6 +103,7 @@ class _TaskRequestDetailsViewState extends State {
? const ALoading()
: Column(children: [
SingleChildScrollView(
+ padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
@@ -136,7 +137,7 @@ class _TaskRequestDetailsViewState extends State {
const Divider().defaultStyle(context),
InfoHeader16Widget("Task Details".addTranslation),
InfoTextWidget(label: context.translation.taskType, value: taskModel?.taskType?.typeName ?? "-"),
- InfoTextWidget(label: context.translation.taskNo, value: taskModel?.taskJobNo ?? "-"),
+ InfoTextWidget(label: context.translation.taskNo, value: taskModel?.taskJobNo ?? "-", copyValue: true),
InfoTextWidget(label: context.translation.createdBy, value: taskModel?.userCreated?.userName ?? "-"),
if (taskProvider.taskRequestModel?.taskType?.isRecallAndAlert == true) ...[
recallAlertTypeWidget(taskModel: taskProvider.taskRequestModel!),
@@ -243,12 +244,13 @@ class _TaskRequestDetailsViewState extends State {
return RichText(
text: TextSpan(
text: "${context.translation.totalWorkingTime}: ",
- style: TextStyle(
- fontSize: 14.toScreenWidth, fontWeight: FontWeight.w500, fontStyle: FontStyle.normal, decoration: TextDecoration.none, color: context.isDark ? AppColor.neutral10 : AppColor.neutral20),
+ style: AppTextStyles.bodyText2.copyWith(color: AppColor.lightTextColor(context)),
+ // TextStyle(
+ // fontSize: 14.toScreenWidth, fontWeight: FontWeight.w500, fontStyle: FontStyle.normal, decoration: TextDecoration.none, color: context.isDark ? AppColor.neutral10 : AppColor.neutral20),
children: [
- TextSpan(text: "$totalHourString ", style: AppTextStyles.bodyText),
- const WidgetSpan(
- child: Icon(Icons.info_outline_rounded, color: AppColor.primary10, size: 14),
+ TextSpan(text: "$totalHourString ", style: AppTextStyles.bodyText2.copyWith(color: AppColor.lightTextColor(context))),
+ WidgetSpan(
+ child: Icon(Icons.info_outline_rounded, color: AppColor.loadingColor(context), size: 14),
),
],
),
diff --git a/lib/modules/traf_module/create_traf_request_page.dart b/lib/modules/traf_module/create_traf_request_page.dart
index 84eed483..4d552cf1 100644
--- a/lib/modules/traf_module/create_traf_request_page.dart
+++ b/lib/modules/traf_module/create_traf_request_page.dart
@@ -519,7 +519,7 @@ class _CreateTRAFRequestPageState extends State {
attachment: attachments,
buttonColor: AppColor.black10,
onlyImages: false,
- buttonIcon: 'image-plus'.toSvgAsset(color: AppColor.neutral120),
+ buttonIcon: 'image-plus'.toSvgAsset(color: AppColor.primary10),
onChange: (attachment) {
attachments = attachment;
},
@@ -531,6 +531,7 @@ class _CreateTRAFRequestPageState extends State {
children: [
Checkbox(
value: _acknowledgement,
+ side: BorderSide(color: AppColor.loadingColor(context), width: 1.0),
visualDensity: const VisualDensity(horizontal: -4.0, vertical: -4.0),
activeColor: AppColor.blueStatus(context),
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
diff --git a/lib/modules/traf_module/traf_request_detail_page.dart b/lib/modules/traf_module/traf_request_detail_page.dart
index 31fcf68e..00673a35 100644
--- a/lib/modules/traf_module/traf_request_detail_page.dart
+++ b/lib/modules/traf_module/traf_request_detail_page.dart
@@ -119,7 +119,7 @@ class _TrafRequestDetailPageState extends State {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
InfoHeader16Widget("Request Information"),
- InfoTextWidget(label: 'Request No', value: data.reqCode ?? '-'),
+ InfoTextWidget(label: 'Request No', value: data.reqCode ?? '-', copyValue: true),
InfoTextWidget(label: 'Request type', value: data.requestTypeName ?? '-'),
if (data.requestTypeValue == 1) ...[
4.height,
diff --git a/lib/new_views/common_widgets/custom_app_bar.dart b/lib/new_views/common_widgets/custom_app_bar.dart
index 9ab589d1..edfda750 100644
--- a/lib/new_views/common_widgets/custom_app_bar.dart
+++ b/lib/new_views/common_widgets/custom_app_bar.dart
@@ -1,3 +1,5 @@
+import 'dart:io';
+
import 'package:flutter/material.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
@@ -20,7 +22,7 @@ class CustomAppBar extends StatelessWidget implements PreferredSizeWidget {
titleSpacing: 16,
title: Row(
children: [
- const Icon(Icons.arrow_back_ios).onPress(() {
+ Icon(Platform.isIOS ? Icons.arrow_back_ios : Icons.arrow_back).onPress(() {
Navigator.of(context).pop();
}),
Text(
diff --git a/lib/new_views/common_widgets/default_app_bar.dart b/lib/new_views/common_widgets/default_app_bar.dart
index 58ac9631..1f68b56a 100644
--- a/lib/new_views/common_widgets/default_app_bar.dart
+++ b/lib/new_views/common_widgets/default_app_bar.dart
@@ -1,3 +1,5 @@
+import 'dart:io';
+
import 'package:flutter/material.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
@@ -16,8 +18,11 @@ class DefaultAppBar extends StatelessWidget implements PreferredSizeWidget {
final bool showBackButton;
final VoidCallback? onWillPopScope;
final TextStyle? titleStyle;
+ final bool showBackButtonAsCancel;
- const DefaultAppBar({this.title, this.onBackPress, this.onWillPopScope, this.actions, this.titleStyle, this.showHomeActionButton = false, this.showBackButton = true, Key? key}) : super(key: key);
+ const DefaultAppBar(
+ {this.title, this.onBackPress, this.onWillPopScope, this.actions, this.titleStyle, this.showHomeActionButton = false, this.showBackButton = true, this.showBackButtonAsCancel = false, Key? key})
+ : super(key: key);
@override
Widget build(BuildContext context) {
@@ -44,7 +49,7 @@ class DefaultAppBar extends StatelessWidget implements PreferredSizeWidget {
title: Row(
children: [
if (showBackButton)
- const Icon(Icons.arrow_back_ios).onPress(() {
+ Icon(showBackButtonAsCancel ? Icons.clear : (Platform.isIOS ? Icons.arrow_back_ios : Icons.arrow_back)).onPress(() {
if (onWillPopScope != null) {
showDialog(
context: context,
@@ -63,11 +68,10 @@ class DefaultAppBar extends StatelessWidget implements PreferredSizeWidget {
Navigator.of(context).pop();
}
}),
- 10.width,
+ 12.width,
Text(
title ?? "",
- style: titleStyle ??
- (context.isTablet() ? AppTextStyles.heading4 : AppTextStyles.heading3).copyWith(fontWeight: FontWeight.w500, color: context.isDark ? AppColor.neutral30 : AppColor.neutral50),
+ style: titleStyle ?? (AppTextStyles.heading5).copyWith(fontWeight: FontWeight.w500, color: context.isDark ? AppColor.neutral30 : AppColor.neutral50),
).expanded,
],
),
diff --git a/lib/new_views/pages/land_page/mark_attendance_widget.dart b/lib/new_views/pages/land_page/mark_attendance_widget.dart
deleted file mode 100644
index 1ab12c67..00000000
--- a/lib/new_views/pages/land_page/mark_attendance_widget.dart
+++ /dev/null
@@ -1,866 +0,0 @@
-// import 'dart:async';
-// import 'dart:developer';
-// import 'dart:io';
-//
-// import 'package:flutter/material.dart';
-// import 'package:flutter_svg/flutter_svg.dart';
-// import 'package:geolocator/geolocator.dart';
-// import 'package:huawei_location/huawei_location.dart';
-// import 'package:nfc_manager/nfc_manager.dart';
-// import 'package:permission_handler/permission_handler.dart';
-// import 'package:provider/provider.dart';
-// import 'package:test_sa/dashboard_latest/dashboard_provider.dart';
-// // import 'package:platform_device_id/platform_device_id.dart';
-// import 'package:test_sa/dashboard_latest/widgets/app_bar_widget.dart';
-// import 'package:test_sa/extensions/enum_extensions.dart';
-// import 'package:test_sa/extensions/text_extensions.dart';
-// import 'package:test_sa/extensions/widget_extensions.dart';
-// import 'package:test_sa/helper/utils.dart';
-// import 'package:test_sa/models/enums/swipe_type.dart';
-// import 'package:test_sa/models/lookup.dart';
-// import 'package:test_sa/models/new_models/swipe_model.dart';
-// import 'package:test_sa/nfc/nfc_reader_sheet.dart';
-// import 'package:test_sa/utilities/Location.dart' as location;
-// import 'package:test_sa/views/widgets/dialogs/confirm_dialog.dart';
-// import 'package:test_sa/views/widgets/dialogs/success_dialog.dart';
-// import 'package:test_sa/views/widgets/qr_scanner_dialog.dart';
-// import 'package:wifi_iot/wifi_iot.dart';
-//
-// import '../../app_style/app_color.dart';
-//
-// class MarkAttendanceWidget extends StatefulWidget {
-// // DashboardProviderModel model;
-// double topPadding;
-// bool isFromDashboard;
-//
-// MarkAttendanceWidget( {Key? key, this.topPadding = 0, this.isFromDashboard = false}) : super(key: key);
-// // todo MarkAttendanceWidget(this.model, {Key? key, this.topPadding = 0, this.isFromDashboard = false}) : super(key: key);
-//
-// @override
-// _MarkAttendanceWidgetState createState() {
-// return _MarkAttendanceWidgetState();
-// }
-// }
-//
-// class _MarkAttendanceWidgetState extends State {
-// bool isNfcEnabled = false, isNfcLocationEnabled = false, isQrEnabled = false, isQrLocationEnabled = false, isWifiEnabled = false, isWifiLocationEnabled = false;
-//
-// int _locationUpdateCbId = 0;
-//
-// @override
-// void initState() {
-// super.initState();
-// checkAttendanceAvailability();
-// }
-//
-// void checkAttendanceAvailability() async {
-// bool isAvailable = await NfcManager.instance.isAvailable();
-// // setState(() {
-// // AppState().privilegeListModel!.forEach((PrivilegeListModel element) {
-// // if (element.serviceName == "enableNFC") {
-// // if (isAvailable) if (element.previlege ?? false) isNfcEnabled = true;
-// // } else if (element.serviceName == "enableQR") {
-// // if (element.previlege ?? false) isQrEnabled = true;
-// // } else if (element.serviceName == "enableWIFI") {
-// // if (element.previlege ?? false) isWifiEnabled = true;
-// // } else if (element.serviceName!.trim() == "enableLocationNFC") {
-// // if (element.previlege ?? false) isNfcLocationEnabled = true;
-// // } else if (element.serviceName == "enableLocationQR") {
-// // if (element.previlege ?? false) isQrLocationEnabled = true;
-// // } else if (element.serviceName == "enableLocationWIFI") {
-// // if (element.previlege ?? false) isWifiLocationEnabled = true;
-// // }
-// // });
-// // });
-// }
-//
-// void checkHuaweiLocationPermission(String attendanceType) async {
-// // Permission_Handler permissionHandler = PermissionHandler();
-// location.Location.isEnabled((bool isEnabled) async {
-// if (isEnabled) {
-// location.Location.havePermission((bool permission) async {
-// if (permission) {
-// getHuaweiCurrentLocation(attendanceType);
-// } else {
-// bool has = await requestPermissions();
-// if (has) {
-// getHuaweiCurrentLocation(attendanceType);
-// } else {
-// showDialog(
-// context: context,
-// builder: (BuildContext cxt) => ConfirmDialog(
-// message: "You need to give location permission to mark attendance",
-// onTap: () {
-// Navigator.pop(context);
-// },
-// ),
-// );
-// }
-// }
-// });
-// } else {
-// showDialog(
-// context: context,
-// builder: (BuildContext cxt) => ConfirmDialog(
-// message: "You need to enable location services to mark attendance",
-// onTap: () async {
-// Navigator.pop(context);
-// await Geolocator.openLocationSettings();
-// },
-// ),
-// );
-// }
-// });
-//
-// // if (await permissionHandler.hasLocationPermission()) {
-// // getHuaweiCurrentLocation(attendanceType);
-// // } else {
-// // bool has = await requestPermissions();
-// // if (has) {
-// // getHuaweiCurrentLocation(attendanceType);
-// // } else {
-// // showDialog(
-// // context: context,
-// // builder: (BuildContext cxt) => ConfirmDialog(
-// // message: "You need to give location permission to mark attendance",
-// // onTap: () {
-// // Navigator.pop(context);
-// // },
-// // ),
-// // );
-// // }
-// // }
-// }
-//
-// Future requestPermissions() async {
-// var result = await [
-// Permission.location,
-// ].request();
-// return (result[Permission.location] == PermissionStatus.granted || result[Permission.locationAlways] == PermissionStatus.granted);
-// }
-//
-// @override
-// void dispose() {
-// super.dispose();
-// // Stop Session
-// NfcManager.instance.stopSession();
-// }
-//
-// @override
-// Widget build(BuildContext context) {
-// return Container(
-// padding: EdgeInsets.only(left: 21, right: 21, bottom: 21, top: widget.topPadding),
-// decoration: const BoxDecoration(borderRadius: BorderRadius.only(topLeft: Radius.circular(25), topRight: Radius.circular(25)), color: Colors.white),
-// width: double.infinity,
-// child: Column(
-// crossAxisAlignment: CrossAxisAlignment.start,
-// mainAxisSize: MainAxisSize.min,
-// children: [
-// // LocaleKeys.markAttendance.tr().toSectionHeading(),
-// // LocaleKeys.selectMethodOfAttendance.tr().toText11(color: const Color(0xff535353)),
-// GridView(
-// physics: const NeverScrollableScrollPhysics(),
-// shrinkWrap: true,
-// padding: const EdgeInsets.only(bottom: 0, top: 21),
-// gridDelegate:
-// SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: (MediaQuery.of(context).size.width < 550) ? 3 : 5, childAspectRatio: 1 / 1, crossAxisSpacing: 8, mainAxisSpacing: 8),
-// children: [
-// attendanceMethod(SwipeTypeEnum.NFC.name, Icons.nfc, true, () {
-// log('i am here...nfc');
-// handleSwipe(swipeType: SwipeTypeEnum.NFC, isEnable: true);
-// return;
-// // if (AppState().getIsHuawei) {
-// if (false) {
-// checkHuaweiLocationPermission("NFC");
-// } else {
-// location.Location.isEnabled((bool isEnabled) {
-// if (isEnabled) {
-// location.Location.havePermission((bool permission) {
-// if (permission) {
-// Utils.showLoading(context);
-// location.Location.getCurrentLocation(
-// (Position position, bool isMocked) {
-// if (isMocked) {
-// Utils.hideLoading(context);
-// markFakeAttendance("NFC", position.latitude.toString() ?? "", position.longitude.toString() ?? "");
-// } else {
-// Utils.hideLoading(context);
-// //todo performNfcAttendance(widget.model, lat: position.latitude.toString() ?? "", lng: position.longitude.toString() ?? "");
-// }
-// },
-// () {
-// Utils.hideLoading(context);
-// Utils.confirmDialog(context, "Unable to determine your location, Please make sure that your location services are turned on & working.");
-// },
-// context,
-// );
-// } else {
-// showDialog(
-// context: context,
-// builder: (BuildContext cxt) => ConfirmDialog(
-// message: "You need to give location permission to mark attendance",
-// onTap: () async {
-// Navigator.pop(context);
-// await Geolocator.openAppSettings();
-// },
-// ),
-// );
-// }
-// });
-// } else {
-// showDialog(
-// context: context,
-// builder: (BuildContext cxt) => ConfirmDialog(
-// message: "You need to enable location services to mark attendance",
-// onTap: () async {
-// Navigator.pop(context);
-// await Geolocator.openLocationSettings();
-// },
-// ),
-// );
-// }
-// });
-// }
-// }),
-// //if (isWifiEnabled) //todo
-// attendanceMethod("Wifi", Icons.wifi, isWifiEnabled, () {
-// // if (AppState().getIsHuawei) {
-// if (false) {
-// checkHuaweiLocationPermission("WIFI");
-// } else {
-// location.Location.isEnabled((bool isEnabled) {
-// if (isEnabled) {
-// location.Location.havePermission((bool permission) {
-// if (permission) {
-// Utils.showLoading(context);
-// location.Location.getCurrentLocation(
-// (Position position, bool isMocked) {
-// if (isMocked) {
-// Utils.hideLoading(context);
-// markFakeAttendance("WIFI", position.latitude.toString() ?? "", position.longitude.toString() ?? "");
-// } else {
-// Utils.hideLoading(context);
-// //todo performWifiAttendance(widget.model, lat: position.latitude.toString() ?? "", lng: position.longitude.toString() ?? "");
-// }
-// },
-// () {
-// Utils.hideLoading(context);
-// Utils.confirmDialog(context, "Unable to determine your location, Please make sure that your location services are turned on & working.");
-// },
-// context,
-// );
-// } else {
-// showDialog(
-// context: context,
-// builder: (BuildContext cxt) => ConfirmDialog(
-// message: "You need to give location permission to mark attendance",
-// onTap: () async {
-// Navigator.pop(context);
-// await Geolocator.openAppSettings();
-// },
-// ),
-// );
-// }
-// });
-// } else {
-// showDialog(
-// context: context,
-// builder: (BuildContext cxt) => ConfirmDialog(
-// message: "You need to enable location services to mark attendance",
-// onTap: () async {
-// Navigator.pop(context);
-// await Geolocator.openLocationSettings();
-// },
-// ),
-// );
-// }
-// });
-// }
-// }),
-// // if (isQrEnabled) //todo
-// attendanceMethod(SwipeTypeEnum.QR.name, Icons.qr_code_2, true, () async {
-// handleSwipe(swipeType: SwipeTypeEnum.QR, isEnable: true);
-// return;
-// // if (AppState().getIsHuawei) {
-// if (false) {
-// checkHuaweiLocationPermission("QR");
-// } else {
-// location.Location.isEnabled((bool isEnabled) {
-// if (isEnabled) {
-// location.Location.havePermission((bool permission) {
-// if (permission) {
-// Utils.showLoading(context);
-// location.Location.getCurrentLocation(
-// (Position position, bool isMocked) {
-// if (isMocked) {
-// Utils.hideLoading(context);
-// markFakeAttendance("QR", position.latitude.toString() ?? "", position.longitude.toString() ?? "");
-// } else {
-// Utils.hideLoading(context);
-// //todo performQrCodeAttendance(widget.model, lat: position.latitude.toString() ?? "", lng: position.longitude.toString() ?? "");
-// }
-// },
-// () {
-// Utils.hideLoading(context);
-// Utils.confirmDialog(context, "Unable to determine your location, Please make sure that your location services are turned on & working.");
-// },
-// context,
-// );
-// } else {
-// showDialog(
-// context: context,
-// builder: (BuildContext cxt) => ConfirmDialog(
-// message: "You need to give location permission to mark attendance",
-// onTap: () async {
-// Navigator.pop(context);
-// await Geolocator.openAppSettings();
-// },
-// ),
-// );
-// }
-// });
-// } else {
-// showDialog(
-// context: context,
-// builder: (BuildContext cxt) => ConfirmDialog(
-// message: "You need to enable location services to mark attendance",
-// onTap: () async {
-// Navigator.pop(context);
-// await Geolocator.openLocationSettings();
-// },
-// ),
-// );
-// }
-// });
-// }
-// }),
-// ],
-// )
-// ],
-// ),
-// );
-// }
-//
-// void handleSwipe({required SwipeTypeEnum swipeType,required bool isEnable,}){
-// log('handle swipe value is ${swipeType.name}');
-// // if (AppState().getIsHuawei) {
-// if (false) {
-// checkHuaweiLocationPermission("NFC");
-// } else {
-// location.Location.isEnabled((bool isEnabled) {
-// if (isEnabled) {
-// location.Location.havePermission((bool permission) {
-// if (permission) {
-// Utils.showLoading(context);
-// location.Location.getCurrentLocation(
-// (Position position, bool isMocked) {
-// if (isMocked) {
-// Utils.hideLoading(context);
-// markFakeAttendance(swipeType.name, position.latitude.toString() ?? "", position.longitude.toString() ?? "");
-// } else {
-// Utils.hideLoading(context);
-// //todo performNfcAttendance(widget.model, lat: position.latitude.toString() ?? "", lng: position.longitude.toString() ?? "");
-// handleSwipeOperation(swipeType: swipeType,lat: position.latitude,lang: position.longitude);
-// }
-// },
-// () {
-// Utils.hideLoading(context);
-// Utils.confirmDialog(context, "Unable to determine your location, Please make sure that your location services are turned on & working.");
-// },
-// context,
-// );
-// } else {
-// showDialog(
-// context: context,
-// builder: (BuildContext cxt) => ConfirmDialog(
-// message: "You need to give location permission to mark attendance",
-// onTap: () async {
-// Navigator.pop(context);
-// await Geolocator.openAppSettings();
-// },
-// ),
-// );
-// }
-// });
-// } else {
-// showDialog(
-// context: context,
-// builder: (BuildContext cxt) => ConfirmDialog(
-// message: "You need to enable location services to mark attendance",
-// onTap: () async {
-// Navigator.pop(context);
-// await Geolocator.openLocationSettings();
-// },
-// ),
-// );
-// }
-// });
-// }
-// }
-//
-// void handleSwipeOperation({required SwipeTypeEnum swipeType,double ?lat, double ?lang}){
-// switch(swipeType){
-// case SwipeTypeEnum.NFC:
-// handleNfcAttendance(latitude: lat,longitude: lang);
-// return;
-// case SwipeTypeEnum.QR:
-// performQrCodeAttendance(latitude: lat,longitude: lang);
-// return;
-// case SwipeTypeEnum.Wifi:
-// return;
-//
-// }
-// }
-//
-// void getHuaweiCurrentLocation(String attendanceType) async {
-// try {
-// Utils.showLoading(context);
-// FusedLocationProviderClient locationService = FusedLocationProviderClient()..initFusedLocationService();
-// LocationRequest locationRequest = LocationRequest();
-// locationRequest.priority = LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY;
-// locationRequest.interval = 500;
-// List locationRequestList = [locationRequest];
-// LocationSettingsRequest locationSettingsRequest = LocationSettingsRequest(requests: locationRequestList);
-//
-// late StreamSubscription _streamSubscription;
-// int requestCode = (await (locationService.requestLocationUpdates(locationRequest)))!;
-//
-// _streamSubscription = locationService.onLocationData!.listen(
-// (Location location) async {
-// Utils.hideLoading(context);
-// await locationService.removeLocationUpdates(requestCode);
-// if (attendanceType == "QR") {
-// // todo performQrCodeAttendance(widget.model, lat: location.latitude.toString() ?? "", lng: location.longitude.toString() ?? "");
-// }
-// if (attendanceType == "WIFI") {
-// // todo performWifiAttendance(widget.model, lat: location.latitude.toString() ?? "", lng: location.longitude.toString() ?? "");
-// }
-// if (attendanceType == "NFC") {
-// //todo performNfcAttendance(widget.model, lat: location.latitude.toString() ?? "", lng: location.longitude.toString() ?? "");
-// }
-// requestCode = 0;
-// },
-// );
-//
-// // locationService.checkLocationSettings(locationSettingsRequest).then((settings) async {
-// // await locationService.getLastLocation().then((value) {
-// // if (value.latitude == null || value.longitude == null) {
-// // showDialog(
-// // context: context,
-// // builder: (BuildContext cxt) => ConfirmDialog(
-// // message: "Unable to get your location, Please check your location settings & try again.",
-// // onTap: () {
-// // Navigator.pop(context);
-// // },
-// // ),
-// // );
-// // } else {
-// // if (attendanceType == "QR") {
-// // performQrCodeAttendance(widget.model, lat: value.latitude.toString() ?? "", lng: value.longitude.toString() ?? "");
-// // }
-// // if (attendanceType == "WIFI") {
-// // performWifiAttendance(widget.model, lat: value.latitude.toString() ?? "", lng: value.longitude.toString() ?? "");
-// // }
-// // if (attendanceType == "NFC") {
-// // performNfcAttendance(widget.model, lat: value.latitude.toString() ?? "", lng: value.longitude.toString() ?? "");
-// // }
-// // }
-// // }).catchError((error) {
-// // log("HUAWEI LOCATION getLastLocation ERROR!!!!!");
-// // log(error);
-// // });
-// // }).catchError((error) {
-// // log("HUAWEI LOCATION checkLocationSettings ERROR!!!!!");
-// // log(error);
-// // if (error.code == "LOCATION_SETTINGS_NOT_AVAILABLE") {
-// // // Location service not enabled.
-// // }
-// // });
-// } catch (error) {
-// log("HUAWEI LOCATION ERROR!!!!!");
-// log('$error');
-// Utils.hideLoading(context);
-// // Utils.handleException(error, context, null);
-// }
-// }
-//
-// Future handleNfcAttendance({double? latitude = 0, double? longitude = 0}) async {
-// final dashBoardProvider = Provider.of(context, listen: false);
-//
-// if (Platform.isIOS) {
-// Utils.readNFc(onRead: (String nfcId) async {
-// await _processNfcAttendance(dashBoardProvider, nfcId, latitude, longitude);
-// });
-// } else {
-// showNfcReader(context, onNcfScan: (String? nfcId) async {
-// await _processNfcAttendance(dashBoardProvider, nfcId ?? '', latitude, longitude);
-// });
-// }
-// }
-//
-//
-// Future _processNfcAttendance(
-// DashBoardProvider dashBoardProvider,
-// String nfcId,
-// double? latitude,
-// double? longitude,
-// ) async {
-// Utils.showLoading(context);
-// try {
-// final swipeModel = Swipe(
-// swipeTypeValue: SwipeTypeEnum.NFC.getIntFromSwipeTypeEnum(),
-// value: nfcId,
-// latitude: latitude,
-// longitude: longitude,
-// );
-//
-// final swipeResponse = await dashBoardProvider.makeSwipe(model: swipeModel);
-// log('swipe response i got is ${swipeResponse.toJson()}');
-//
-// if (swipeResponse.responseCode != 1) {
-// Utils.hideLoading(context);
-// _showErrorDialog(swipeResponse.message ?? "Unexpected error occurred");
-// } else {
-// final isSuccess = swipeResponse.data;
-// log('nfc swipe response is ${isSuccess}');
-// if (Platform.isIOS) await Future.delayed(const Duration(seconds: 3));
-// Utils.hideLoading(context);
-// _showSuccessDialog();
-// }
-// } catch (error) {
-// Utils.hideLoading(context);
-// // Uncomment below line for error handling if needed
-// // Utils.handleException(error, context, null);
-// }
-// }
-//
-//
-// void _showErrorDialog(String message) {
-// showDialog(
-// context: context,
-// builder: (context) => ConfirmDialog(
-// message: message,
-// onTap: () => Navigator.pop(context),
-// ),
-// );
-// }
-//
-// void _showSuccessDialog() {
-// showMDialog(
-// context,
-// backgroundColor: Colors.transparent,
-// isDismissable: true,
-// child: SuccessDialog(widget.isFromDashboard),
-// );
-// }
-//
-//
-// //older code....
-// Future performNfcAttendance({double? lat = 0, double ?lng = 0}) async {
-// DashBoardProvider dashBoardProvider = Provider.of(context,listen:false);
-// if (Platform.isIOS) {
-// Utils.readNFc(onRead: (String nfcId) async {
-// Utils.showLoading(context);
-// try {
-// SwipeModel? swipeResponse = await dashBoardProvider.makeSwipe(model: Swipe(swipeTypeValue: SwipeTypeEnum.NFC.getIntFromSwipeTypeEnum(), value: '', latitude: lat, longitude: lng));
-// if (swipeResponse.responseCode != 1) {
-// Utils.hideLoading(context);
-// showDialog(
-// context: context,
-// builder: (BuildContext cxt) => ConfirmDialog(
-// message: swipeResponse.message ?? "Unexpected error occurred",
-// onTap: () {
-// Navigator.pop(context);
-// },
-// ),
-// );
-// } else {
-// bool status = swipeResponse.data;
-// if (Platform.isIOS) await Future.delayed(const Duration(seconds: 3));
-// Utils.hideLoading(context);
-// showMDialog(
-// context,
-// backgroundColor: Colors.transparent,
-// isDismissable: true,
-// child: SuccessDialog(widget.isFromDashboard),
-// );
-// }
-// } catch (ex) {
-// Utils.hideLoading(context);
-// // Utils.handleException(ex, context, null);
-// }
-// });
-// } else {
-// showNfcReader(context, onNcfScan: (String? nfcId) async {
-// Utils.showLoading(context);
-// try {
-// SwipeModel? swipeResponse = await dashBoardProvider.makeSwipe(model: Swipe(swipeTypeValue: SwipeTypeEnum.NFC.getIntFromSwipeTypeEnum(), value: nfcId??'', latitude: lat, longitude: lng));
-// log('api response i got is ${swipeResponse.toJson()}');
-// if (swipeResponse.responseCode != 1) {
-// Utils.hideLoading(context);
-// showDialog(
-// context: context,
-// builder: (BuildContext cxt) => ConfirmDialog(
-// message: swipeResponse.message ?? "Unexpected error occurred",
-// onTap: () {
-// Navigator.pop(context);
-// },
-// ),
-// );
-// } else {
-// bool status = swipeResponse.data; //use this status to get transactions.
-// if (Platform.isIOS) await Future.delayed(const Duration(seconds: 3));
-// Utils.hideLoading(context);
-// showMDialog(
-// context,
-// backgroundColor: Colors.transparent,
-// isDismissable: true,
-// child: SuccessDialog(widget.isFromDashboard),
-// );
-// }
-// } catch (ex) {
-// Utils.hideLoading(context);
-// // Utils.handleException(ex, context, null);
-// }
-// // Utils.showLoading(context);
-// // try {
-// // GenericResponseModel? g = await DashboardApiClient().markAttendance(pointType: 2, nfcValue: nfcId ?? "", isGpsRequired: isNfcLocationEnabled, lat: lat, long: lng);
-// // if (g?.messageStatus != 1) {
-// // Utils.hideLoading(context);
-// // showDialog(
-// // context: context,
-// // builder: (BuildContext cxt) => ConfirmDialog(
-// // message: g?.errorEndUserMessage ?? "Unexpected error occurred",
-// // onTap: () {
-// // Navigator.pop(context);
-// // },
-// // ),
-// // );
-// // } else {
-// // bool status = await model.fetchAttendanceTracking(context);
-// // Utils.hideLoading(context);
-// // showMDialog(
-// // context,
-// // backgroundColor: Colors.transparent,
-// // isDismissable: false,
-// // child: SuccessDialog(widget.isFromDashboard),
-// // );
-// // }
-// // } catch (ex) {
-// // log(ex);
-// // Utils.hideLoading(context);
-// // // Utils.handleException(ex, context, (String msg) {
-// // // Utils.confirmDialog(context, msg);
-// // // });
-// // }
-// });
-// }
-// }
-//
-//
-//
-// void showMDialog(context, {Widget? child, Color? backgroundColor, bool isDismissable = true, bool isBusniessCard = false}) async {
-// return showDialog(
-// context: context,
-// barrierDismissible: isDismissable,
-// builder: (context) {
-// return Dialog(
-// shape: isBusniessCard
-// ? const RoundedRectangleBorder(
-// borderRadius: BorderRadius.all(
-// Radius.circular(15.0),
-// ),
-// )
-// : null,
-// backgroundColor: backgroundColor,
-// child: child,
-// );
-// },
-// );
-// }
-// //
-// // Future checkSession() async {
-// // try {
-// // Utils.showLoading(context);
-// // await DashboardApiClient().getOpenMissingSwipes();
-// // Utils.hideLoading(context);
-// // return true;
-// // } catch (ex) {
-// // Utils.hideLoading(context);
-// // Utils.handleException(ex, context, null);
-// // return false;
-// // }
-// // }
-//
-//
-// //TODO need to confirm ....
-// // Future performWifiAttendance({double? latitude, double? lng}) async {
-// // // if (Platform.isAndroid) {
-// // // if (!(await checkSession())) {
-// // // return;
-// // // }
-// // // }
-// // Utils.showLoading(context);
-// // bool isConnected = await WiFiForIoTPlugin.connect(AppState().getMohemmWifiSSID ?? "",
-// // password: AppState().getMohemmWifiPassword ?? "", joinOnce: Platform.isIOS ? false : true, security: NetworkSecurity.WPA, withInternet: false);
-// //
-// // if (Platform.isIOS) {
-// // if (await WiFiForIoTPlugin.getSSID() == AppState().getMohemmWifiSSID) {
-// // isConnected = true;
-// // } else {
-// // isConnected = false;
-// // }
-// // }
-// //
-// // if (isConnected && AppState().isAuthenticated) {
-// // await WiFiForIoTPlugin.forceWifiUsage(true);
-// // await Future.delayed(const Duration(seconds: 6));
-// // try {
-// // GenericResponseModel? g = await DashboardApiClient().markAttendance(pointType: 3, nfcValue: "", isGpsRequired: isWifiLocationEnabled, lat: lat, long: lng);
-// // bool status = await model.fetchAttendanceTracking(context);
-// // Utils.hideLoading(context);
-// // await closeWifiRequest();
-// // if (g?.messageStatus == 2) {
-// // showDialog(
-// // barrierDismissible: true,
-// // context: context,
-// // builder: (cxt) => ConfirmDialog(
-// // message: g?.errorEndUserMessage ?? "",
-// // onTap: () {
-// // Navigator.pop(context);
-// // },
-// // onCloseTap: () {},
-// // ),
-// // );
-// // } else {
-// // showMDialog(
-// // context,
-// // backgroundColor: Colors.transparent,
-// // isDismissable: false,
-// // child: SuccessDialog(widget.isFromDashboard),
-// // );
-// // }
-// // } catch (ex) {
-// // await closeWifiRequest();
-// // Utils.hideLoading(context);
-// // Utils.handleException(ex, context, null);
-// // }
-// // } else {
-// // if (AppState().isAuthenticated) {
-// // Utils.hideLoading(context);
-// // Utils.confirmDialog(context, "LocaleKeys.comeNearHMGWifi.tr()");
-// // } else {
-// // await closeWifiRequest();
-// // }
-// // }
-// // }
-//
-// Future closeWifiRequest() async {
-// if (Platform.isAndroid) {
-// await WiFiForIoTPlugin.forceWifiUsage(false);
-// }
-// return await WiFiForIoTPlugin.disconnect();
-// }
-//
-// Future performQrCodeAttendance( {double ? latitude , double ?longitude}) async {
-// DashBoardProvider dashBoardProvider = Provider.of(context,listen: false);
-// var qrCodeValue = await Navigator.of(context).push(
-// MaterialPageRoute(
-// builder: (BuildContext context) => QrScannerDialog(),
-// ),
-// );
-// if (qrCodeValue != null) {
-// Utils.showLoading(context);
-// try {
-// final swipeModel = Swipe(
-// swipeTypeValue: SwipeTypeEnum.QR.getIntFromSwipeTypeEnum(),
-// value: qrCodeValue,
-// latitude: latitude,
-// longitude: longitude,
-// );
-// log('model i got to scan qr is ${swipeModel.toJson()}');
-// final swipeResponse = await dashBoardProvider.makeSwipe(model: swipeModel);
-// log('response of swipe is ${swipeResponse.toJson()}');
-//
-// bool status = await swipeResponse.data;
-// Utils.hideLoading(context);
-// if (swipeResponse.responseCode == 2) {
-// showDialog(
-// barrierDismissible: true,
-// context: context,
-// builder: (cxt) => ConfirmDialog(
-// message: swipeResponse.message ?? "",
-// onTap: () {
-// Navigator.pop(context);
-// },
-// onCloseTap: () {},
-// ),
-// );
-// } else {
-// showMDialog(
-// context,
-// backgroundColor: Colors.transparent,
-// isDismissable: true,
-// child: SuccessDialog(widget.isFromDashboard),
-// );
-// }
-// } catch (ex) {
-// log('$ex');
-// Utils.hideLoading(context);
-// //this need to confirm where it comes..
-// // Utils.handleException(ex, context, null);
-// }
-// }
-// }
-//
-// void markFakeAttendance(dynamic sourceName, String lat, String long) async {
-// Utils.showLoading(context);
-// try {
-// // await DashboardApiClient().markFakeLocation(sourceName: sourceName, lat: lat, long: long);
-// Utils.hideLoading(context);
-// Utils.confirmDialog(context, "LocaleKeys.fakeLocation.tr()");
-// } catch (ex) {
-// log('$ex');
-// Utils.hideLoading(context);
-// //Utils.handleException(ex, context, null);
-// }
-// }
-//
-// Widget attendanceMethod(String title, IconData iconData, bool isEnabled, VoidCallback onPress) => Container(
-// decoration: BoxDecoration(
-// borderRadius: BorderRadius.circular(15),
-// color: isEnabled ? null : Colors.grey.withOpacity(.5),
-// gradient: isEnabled
-// ? const LinearGradient(
-// transform: GradientRotation(.64),
-// begin: Alignment.topRight,
-// end: Alignment.bottomLeft,
-// colors: [
-// //ToDo set Colors according to design provided by designer...
-// Colors.blue,
-// Colors.green,
-// // AppColor.gradiantEndColor,
-// // MyColors.gradiantStartColor,
-// ],
-// )
-// : null,
-// ),
-// clipBehavior: Clip.antiAlias,
-// padding: const EdgeInsets.only(left: 10, right: 10, top: 14, bottom: 14),
-// child: Column(
-// crossAxisAlignment: CrossAxisAlignment.start,
-// children: [
-// // SvgPicture.asset(image, color: Colors.white, alignment: Alignment.topLeft).expanded,
-// Icon(iconData, color: isEnabled ? AppColor.black35 : Colors.grey),
-// title.heading6(context),
-// // title.toText17(isBold: true, color: Colors.white),
-// ],
-// ),
-// ).onPress(
-// () {
-// log('isEnabled is ${!isEnabled}');
-// if (!isEnabled) return;
-// onPress();
-// },
-// );
-// }
diff --git a/lib/new_views/pages/land_page/my_request/all_requests_filter_page.dart b/lib/new_views/pages/land_page/my_request/all_requests_filter_page.dart
index a90c8188..0c4c61ab 100644
--- a/lib/new_views/pages/land_page/my_request/all_requests_filter_page.dart
+++ b/lib/new_views/pages/land_page/my_request/all_requests_filter_page.dart
@@ -169,7 +169,7 @@ class _AllRequestsFilterPageState extends State {
}
return Scaffold(
appBar: DefaultAppBar(
- title: context.translation.filter,
+ title: context.translation.filter,showBackButtonAsCancel: true,
actions: [
if (_showResetButton())
TextButton(
diff --git a/lib/new_views/pages/land_page/my_request/all_requests_search_page.dart b/lib/new_views/pages/land_page/my_request/all_requests_search_page.dart
index 1dd6da60..b49834b4 100644
--- a/lib/new_views/pages/land_page/my_request/all_requests_search_page.dart
+++ b/lib/new_views/pages/land_page/my_request/all_requests_search_page.dart
@@ -88,6 +88,7 @@ class _AllRequestsSearchPageState extends State {
// ).paddingOnly(bottom: 75),
appBar: DefaultAppBar(
title: context.translation.search,
+ showBackButtonAsCancel: true,
actions: [
if (_showResetButton())
TextButton(
diff --git a/lib/new_views/pages/land_page/my_request/my_requests_page.dart b/lib/new_views/pages/land_page/my_request/my_requests_page.dart
index d1540eba..227d46f1 100644
--- a/lib/new_views/pages/land_page/my_request/my_requests_page.dart
+++ b/lib/new_views/pages/land_page/my_request/my_requests_page.dart
@@ -194,16 +194,17 @@ class _MyRequestsPageState extends State with SingleTickerProvid
],
),
).onPress(() async {
- final result = await Navigator.push(context, CupertinoPageRoute(builder: (context) => AllRequestsSearchPage(data: _search)));
+ final result = await Navigator.push(context, CupertinoPageRoute(fullscreenDialog: true, builder: (context) => AllRequestsSearchPage(data: _search)));
if (result != null) {
_search = result;
setState(() {});
}
}).expanded,
- 16.width,
+ 12.width,
IconButton(
icon: "download".toSvgAsset(height: 24, width: 24, color: AppColor.icon2Color(context)),
padding: EdgeInsets.zero,
+ visualDensity: VisualDensity.compact,
tooltip: "Export",
onPressed: () async {
final provider = Provider.of(context, listen: false);
@@ -223,9 +224,10 @@ class _MyRequestsPageState extends State with SingleTickerProvid
IconButton(
icon: "filter".toSvgAsset(height: 24, width: 24, color: AppColor.icon2Color(context)),
padding: EdgeInsets.zero,
+ visualDensity: VisualDensity.compact,
tooltip: "Filter",
onPressed: () async {
- final result = await Navigator.push(context, CupertinoPageRoute(builder: (context) => AllRequestsFilterPage(data: _search)));
+ final result = await Navigator.push(context, CupertinoPageRoute(fullscreenDialog: true, builder: (context) => AllRequestsFilterPage(data: _search)));
if (result != null) {
_search = result;
setState(() {});
@@ -233,7 +235,7 @@ class _MyRequestsPageState extends State with SingleTickerProvid
},
),
],
- ).paddingOnly(start: 16, end: 16),
+ ).paddingOnly(start: 16, end: 8),
),
body: Consumer(builder: (context, snapshot, _) {
return Column(
diff --git a/lib/new_views/pages/land_page/non_hmg_employee_swipe_view.dart b/lib/new_views/pages/land_page/non_hmg_employee_swipe_view.dart
index a26c7965..1e0cc7f0 100644
--- a/lib/new_views/pages/land_page/non_hmg_employee_swipe_view.dart
+++ b/lib/new_views/pages/land_page/non_hmg_employee_swipe_view.dart
@@ -4,6 +4,7 @@ import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
+import 'package:test_sa/views/widgets/item_views/info_header_widget.dart';
class NonHmgEmployeeSwipeView extends StatefulWidget {
NonHmgEmployeeSwipeView({Key? key}) : super(key: key);
@@ -47,6 +48,7 @@ class _NonHmgEmployeeSwipeViewState extends State {
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
+ InfoHeader16Widget( "Mark Attendance"),
Text(
"Mark Attendance",
style: AppTextStyles.heading5.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50),
diff --git a/lib/new_views/pages/login_page.dart b/lib/new_views/pages/login_page.dart
index 1c6a83bd..4f8f7d7b 100644
--- a/lib/new_views/pages/login_page.dart
+++ b/lib/new_views/pages/login_page.dart
@@ -180,7 +180,7 @@ class _LoginPageState extends State {
children: [
Checkbox(
value: rememberMe,
- activeColor: AppColor.blueStatus(context),
+ activeColor: AppColor.primary10,
side: BorderSide(color: AppColor.loadingColor(context), width: 1.0),
visualDensity: const VisualDensity(horizontal: -4.0, vertical: -4.0),
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
@@ -190,7 +190,7 @@ class _LoginPageState extends State {
});
}),
8.width,
- "Remember Me".bodyText(context).custom(color: context.isDark ? AppColor.primary50 : AppColor.neutral50).expanded,
+ "Remember Me".bodyText(context).custom(color: AppColor.textStyleColor(context)).expanded,
],
),
8.height,
@@ -200,7 +200,7 @@ class _LoginPageState extends State {
Checkbox(
value: privacyPolicyChecked,
side: BorderSide(color: AppColor.loadingColor(context), width: 1.0),
- activeColor: AppColor.blueStatus(context),
+ activeColor: AppColor.primary10,
visualDensity: const VisualDensity(horizontal: -4.0, vertical: -4.0),
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
onChanged: (value) {
@@ -210,10 +210,10 @@ class _LoginPageState extends State {
}),
8.width,
RichText(
- text: TextSpan(text: "I have read and agree to ", style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.primary50 : AppColor.neutral50), children: [
+ text: TextSpan(text: "I have read and agree to ", style: AppTextStyles.bodyText.copyWith(color: AppColor.textStyleColor(context)), children: [
TextSpan(
text: "Privacy Policy",
- style: AppTextStyles.bodyText.copyWith(color: AppColor.blueStatus(context), decoration: TextDecoration.underline),
+ style: AppTextStyles.bodyText.copyWith(color: AppColor.primary10, decoration: TextDecoration.underline),
recognizer: TapGestureRecognizer()
..onTap = () async {
Uri uri = Uri.parse("https://cloudsolutions.com.sa/en/privacy-policy");
diff --git a/lib/new_views/swipe_module/dialoge/confirm_dialog.dart b/lib/new_views/swipe_module/dialoge/confirm_dialog.dart
index 60db0c03..e7c92bec 100644
--- a/lib/new_views/swipe_module/dialoge/confirm_dialog.dart
+++ b/lib/new_views/swipe_module/dialoge/confirm_dialog.dart
@@ -1,61 +1,61 @@
-import 'package:flutter/material.dart';
-import 'package:test_sa/extensions/int_extensions.dart';
-import 'package:test_sa/extensions/text_extensions.dart';
-import 'package:test_sa/extensions/widget_extensions.dart';
-import 'package:test_sa/new_views/app_style/app_color.dart';
-import 'package:test_sa/new_views/common_widgets/app_filled_button.dart';
-
-class ConfirmDialog extends StatelessWidget {
- final String? title;
- final String? message;
- final String? okTitle;
- final VoidCallback? onTap;
- final VoidCallback? onCloseTap;
-
- const ConfirmDialog({Key? key, this.title, this.message, this.okTitle, this.onTap, this.onCloseTap}) : super(key: key);
-
- @override
- Widget build(BuildContext context) {
- return Dialog(
- backgroundColor: AppColor.background(context),
- shape: const RoundedRectangleBorder(),
- insetPadding: const EdgeInsets.only(left: 21, right: 21),
- child: Padding(
- padding: const EdgeInsets.only(left: 20, right: 20, top: 18, bottom: 28),
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- mainAxisSize: MainAxisSize.min,
- children: [
- Row(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Expanded(
- child: Text(
- title ?? "Confirm",
- style: TextStyle(fontSize: 24, fontWeight: FontWeight.w600, color: AppColor.headingTextColor(context), height: 35 / 24, letterSpacing: -0.96),
- ).paddingOnly(top: 16),
- ),
- IconButton(
- padding: EdgeInsets.zero,
- icon: const Icon(Icons.close),
- color: AppColor.iconColor(context),
- constraints: const BoxConstraints(),
- onPressed: () => onCloseTap ?? Navigator.pop(context),
- // onPressed: () => Navigator.pop(context),
- )
- ],
- ),
- message != null ? message!.heading5(context).custom(color: AppColor.textColor(context)) : const SizedBox(),
- 28.height,
- AppFilledButton(
- label: okTitle ?? "OK",
- onPressed: onTap ?? () => Navigator.pop(context),
- textColor: Colors.white,
- //color: Ap.green,
- ),
- ],
- ),
- ),
- );
- }
-}
+// import 'package:flutter/material.dart';
+// import 'package:test_sa/extensions/int_extensions.dart';
+// import 'package:test_sa/extensions/text_extensions.dart';
+// import 'package:test_sa/extensions/widget_extensions.dart';
+// import 'package:test_sa/new_views/app_style/app_color.dart';
+// import 'package:test_sa/new_views/common_widgets/app_filled_button.dart';
+//
+// class ConfirmDialog extends StatelessWidget {
+// final String? title;
+// final String? message;
+// final String? okTitle;
+// final VoidCallback? onTap;
+// final VoidCallback? onCloseTap;
+//
+// const ConfirmDialog({Key? key, this.title, this.message, this.okTitle, this.onTap, this.onCloseTap}) : super(key: key);
+//
+// @override
+// Widget build(BuildContext context) {
+// return Dialog(
+// backgroundColor: AppColor.background(context),
+// shape: const RoundedRectangleBorder(),
+// insetPadding: const EdgeInsets.only(left: 21, right: 21),
+// child: Padding(
+// padding: const EdgeInsets.only(left: 20, right: 20, top: 18, bottom: 28),
+// child: Column(
+// crossAxisAlignment: CrossAxisAlignment.start,
+// mainAxisSize: MainAxisSize.min,
+// children: [
+// Row(
+// crossAxisAlignment: CrossAxisAlignment.start,
+// children: [
+// Expanded(
+// child: Text(
+// title ?? "Confirm",
+// style: TextStyle(fontSize: 24, fontWeight: FontWeight.w600, color: AppColor.headingTextColor(context), height: 35 / 24, letterSpacing: -0.96),
+// ).paddingOnly(top: 16),
+// ),
+// IconButton(
+// padding: EdgeInsets.zero,
+// icon: const Icon(Icons.close),
+// color: AppColor.iconColor(context),
+// constraints: const BoxConstraints(),
+// onPressed: () => onCloseTap ?? Navigator.pop(context),
+// // onPressed: () => Navigator.pop(context),
+// )
+// ],
+// ),
+// message != null ? message!.heading5(context).custom(color: AppColor.textColor(context)) : const SizedBox(),
+// 28.height,
+// AppFilledButton(
+// label: okTitle ?? "OK",
+// onPressed: onTap ?? () => Navigator.pop(context),
+// textColor: Colors.white,
+// //color: Ap.green,
+// ),
+// ],
+// ),
+// ),
+// );
+// }
+// }
diff --git a/lib/new_views/swipe_module/mark_attendance_widget.dart b/lib/new_views/swipe_module/mark_attendance_widget.dart
deleted file mode 100644
index 7ebe6b6a..00000000
--- a/lib/new_views/swipe_module/mark_attendance_widget.dart
+++ /dev/null
@@ -1,821 +0,0 @@
-// import 'dart:async';
-// import 'dart:developer';
-// import 'dart:io';
-//
-// import 'package:flutter/material.dart';
-// import 'package:geolocator/geolocator.dart';
-// import 'package:huawei_location/huawei_location.dart';
-// import 'package:nfc_manager/nfc_manager.dart';
-// import 'package:permission_handler/permission_handler.dart';
-// import 'package:provider/provider.dart';
-// import 'package:test_sa/controllers/providers/api/user_provider.dart';
-// import 'package:test_sa/extensions/int_extensions.dart';
-// import 'package:test_sa/extensions/text_extensions.dart';
-// import 'package:test_sa/extensions/widget_extensions.dart';
-// import 'package:test_sa/new_views/app_style/app_color.dart';
-// import 'package:test_sa/new_views/pages/land_page/nfc/nfc_reader_sheet.dart';
-// import 'package:test_sa/new_views/swipe_module/dialoge/confirm_dialog.dart';
-// import 'package:test_sa/new_views/swipe_module/dialoge/qr_scanner_dialog.dart';
-// import 'package:test_sa/new_views/swipe_module/dialoge/success_dialog.dart';
-// import 'package:test_sa/new_views/swipe_module/enums/swipe_type.dart';
-// import 'package:test_sa/new_views/swipe_module/models/swipe_model.dart';
-// import 'package:test_sa/new_views/swipe_module/swipe_success_view.dart';
-// import 'package:test_sa/new_views/swipe_module/utils/location_utils.dart';
-// import 'package:test_sa/new_views/swipe_module/utils/swipe_general_utils.dart';
-// import 'package:wifi_iot/wifi_iot.dart';
-// todo @sikander delete this file after compelte
-// class MarkAttendanceWidget extends StatefulWidget {
-// double topPadding;
-// bool isFromDashboard;
-//
-// MarkAttendanceWidget({Key key, this.topPadding = 0, this.isFromDashboard = false}) : super(key: key);
-//
-// // todo MarkAttendanceWidget(this.model, {Key? key, this.topPadding = 0, this.isFromDashboard = false}) : super(key: key);
-//
-// @override
-// _MarkAttendanceWidgetState createState() {
-// return _MarkAttendanceWidgetState();
-// }
-// }
-//
-// class _MarkAttendanceWidgetState extends State {
-// bool isNfcEnabled = false, isQrEnabled = false, isWifiEnabled = false;
-// UserProvider _userProvider;
-//
-// int _locationUpdateCbId = 0;
-//
-// @override
-// void initState() {
-// super.initState();
-// checkAttendanceAvailability();
-// }
-//
-// void checkAttendanceAvailability() async {
-// _userProvider = Provider.of(context, listen: false);
-// bool isAvailable = await NfcManager.instance.isAvailable();
-// log('backend enabled values are nfc ${_userProvider.user.enableNFC} qr ${_userProvider.user.enableQR} wifi ${_userProvider.user.enableWifi}');
-// setState(() {
-// if (isAvailable && _userProvider.user.enableNFC) isNfcEnabled = true;
-// if (_userProvider.user.enableQR) isQrEnabled = true;
-// if (_userProvider.user.enableWifi) isWifiEnabled = true;
-// });
-// }
-//
-// void checkHuaweiLocationPermission(SwipeTypeEnum attendanceType, BuildContext context) async {
-// // Permission_Handler permissionHandler = PermissionHandler();
-// LocationUtilities.isEnabled((bool isEnabled) async {
-// if (isEnabled) {
-// LocationUtilities.havePermission((bool permission) async {
-// if (permission) {
-// getHuaweiCurrentLocation(attendanceType, context);
-// } else {
-// bool has = await requestPermissions();
-// if (has) {
-// getHuaweiCurrentLocation(attendanceType, context);
-// } else {
-// showDialog(
-// context: context,
-// builder: (BuildContext cxt) => ConfirmDialog(
-// message: "You need to give location permission to mark attendance",
-// onTap: () {
-// Navigator.pop(context);
-// },
-// ),
-// );
-// }
-// }
-// });
-// } else {
-// showDialog(
-// context: context,
-// builder: (BuildContext cxt) => ConfirmDialog(
-// message: "You need to enable location services to mark attendance",
-// onTap: () async {
-// Navigator.pop(context);
-// await Geolocator.openLocationSettings();
-// },
-// ),
-// );
-// }
-// });
-//
-// // if (await permissionHandler.hasLocationPermission()) {
-// // getHuaweiCurrentLocation(attendanceType);
-// // } else {
-// // bool has = await requestPermissions();
-// // if (has) {
-// // getHuaweiCurrentLocation(attendanceType);
-// // } else {
-// // showDialog(
-// // context: context,
-// // builder: (BuildContext cxt) => ConfirmDialog(
-// // message: "You need to give location permission to mark attendance",
-// // onTap: () {
-// // Navigator.pop(context);
-// // },
-// // ),
-// // );
-// // }
-// // }
-// }
-//
-// Future requestPermissions() async {
-// var result = await [
-// Permission.location,
-// ].request();
-// return (result[Permission.location] == PermissionStatus.granted || result[Permission.locationAlways] == PermissionStatus.granted);
-// }
-//
-// @override
-// void dispose() {
-// super.dispose();
-// // Stop Session
-// NfcManager.instance.stopSession();
-// }
-//
-// @override
-// Widget build(BuildContext context) {
-// return Container(
-// padding: EdgeInsets.only(left: 21, right: 21, bottom: 21, top: widget.topPadding),
-// decoration: const BoxDecoration(borderRadius: BorderRadius.only(topLeft: Radius.circular(25), topRight: Radius.circular(25)), color: Colors.white),
-// width: double.infinity,
-// child: Column(
-// crossAxisAlignment: CrossAxisAlignment.start,
-// mainAxisSize: MainAxisSize.min,
-// children: [
-// 20.height,
-// 'click me '.heading5(context).custom(color: AppColor.textStyleColor(context)),
-// // LocaleKeys.markAttendance.tr().toSectionHeading(),
-// // LocaleKeys.selectMethodOfAttendance.tr().toText11(color: const Color(0xff535353)),
-// GridView(
-// physics: const NeverScrollableScrollPhysics(),
-// shrinkWrap: true,
-// padding: const EdgeInsets.only(bottom: 0, top: 21),
-// gridDelegate:
-// SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: (MediaQuery.of(context).size.width < 550) ? 3 : 5, childAspectRatio: 1 / 1, crossAxisSpacing: 8, mainAxisSpacing: 8),
-// children: availableAttendanceMethodList(context: context),
-// )
-// ],
-// ),
-// );
-// }
-//
-// void handleSwipe({
-// SwipeTypeEnum swipeType,
-// @required bool isEnable,
-// @required BuildContext context,
-// }) {
-// // if (AppState().getIsHuawei) {
-// if (false) {
-// checkHuaweiLocationPermission(swipeType, context);
-// } else {
-// LocationUtilities.isEnabled((bool isEnabled) {
-// if (isEnabled) {
-// LocationUtilities.havePermission((bool permission) {
-// if (permission) {
-// SwipeGeneralUtils.showLoading(context);
-// LocationUtilities.getCurrentLocation(
-// (Position position, bool isMocked) {
-// if (isMocked) {
-// SwipeGeneralUtils.hideLoading(context);
-// SwipeGeneralUtils.markFakeAttendance(swipeType.name, position.latitude.toString() ?? "", position.longitude.toString() ?? "", context);
-// } else {
-// SwipeGeneralUtils.hideLoading(context);
-// //todo performNfcAttendance(widget.model, lat: position.latitude.toString() ?? "", lng: position.longitude.toString() ?? "");
-// handleSwipeOperation(swipeType: swipeType, lat: position.latitude, lang: position.longitude);
-// }
-// },
-// () {
-// SwipeGeneralUtils.hideLoading(context);
-// SwipeGeneralUtils.confirmDialog(context, "Unable to determine your location, Please make sure that your location services are turned on & working.");
-// },
-// context,
-// );
-// } else {
-// showDialog(
-// context: context,
-// builder: (BuildContext cxt) => ConfirmDialog(
-// message: "You need to give location permission to mark attendance",
-// onTap: () async {
-// Navigator.pop(context);
-// await Geolocator.openAppSettings();
-// },
-// ),
-// );
-// }
-// });
-// } else {
-// showDialog(
-// context: context,
-// builder: (BuildContext cxt) => ConfirmDialog(
-// message: "You need to enable location services to mark attendance",
-// onTap: () async {
-// Navigator.pop(context);
-// await Geolocator.openLocationSettings();
-// },
-// ),
-// );
-// }
-// });
-// }
-// }
-//
-// void handleSwipeOperation({@required SwipeTypeEnum swipeType, double lat, double lang, BuildContext context}) {
-// switch (swipeType) {
-// case SwipeTypeEnum.NFC:
-// handleNfcAttendance(latitude: lat, longitude: lang, context: context);
-// return;
-// case SwipeTypeEnum.QR:
-// performQrCodeAttendance(latitude: lat, longitude: lang, context: context);
-// return;
-// case SwipeTypeEnum.Wifi:
-// //TODO need to implement.
-// return;
-// }
-// }
-//
-// void getHuaweiCurrentLocation(SwipeTypeEnum attendanceType, BuildContext context) async {
-// try {
-// SwipeGeneralUtils.showLoading(context);
-// FusedLocationProviderClient locationService = FusedLocationProviderClient()..initFusedLocationService();
-// LocationRequest locationRequest = LocationRequest();
-// locationRequest.priority = LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY;
-// locationRequest.interval = 500;
-// List locationRequestList = [locationRequest];
-// LocationSettingsRequest locationSettingsRequest = LocationSettingsRequest(requests: locationRequestList);
-//
-// StreamSubscription _streamSubscription;
-// int requestCode = (await (locationService.requestLocationUpdates(locationRequest)));
-//
-// _streamSubscription = locationService.onLocationData.listen(
-// (Location location) async {
-// SwipeGeneralUtils.hideLoading(context);
-// await locationService.removeLocationUpdates(requestCode);
-// handleSwipeOperation(swipeType: attendanceType);
-// requestCode = 0;
-// },
-// );
-//
-// // locationService.checkLocationSettings(locationSettingsRequest).then((settings) async {
-// // await locationService.getLastLocation().then((value) {
-// // if (value.latitude == null || value.longitude == null) {
-// // showDialog(
-// // context: context,
-// // builder: (BuildContext cxt) => ConfirmDialog(
-// // message: "Unable to get your location, Please check your location settings & try again.",
-// // onTap: () {
-// // Navigator.pop(context);
-// // },
-// // ),
-// // );
-// // } else {
-// // if (attendanceType == "QR") {
-// // performQrCodeAttendance(widget.model, lat: value.latitude.toString() ?? "", lng: value.longitude.toString() ?? "");
-// // }
-// // if (attendanceType == "WIFI") {
-// // performWifiAttendance(widget.model, lat: value.latitude.toString() ?? "", lng: value.longitude.toString() ?? "");
-// // }
-// // if (attendanceType == "NFC") {
-// // performNfcAttendance(widget.model, lat: value.latitude.toString() ?? "", lng: value.longitude.toString() ?? "");
-// // }
-// // }
-// // }).catchError((error) {
-// // log("HUAWEI LOCATION getLastLocation ERROR!!!!!");
-// // log(error);
-// // });
-// // }).catchError((error) {
-// // log("HUAWEI LOCATION checkLocationSettings ERROR!!!!!");
-// // log(error);
-// // if (error.code == "LOCATION_SETTINGS_NOT_AVAILABLE") {
-// // // Location service not enabled.
-// // }
-// // });
-// } catch (error) {
-// log("HUAWEI LOCATION ERROR!!!!!");
-// log('$error');
-// SwipeGeneralUtils.hideLoading(context);
-// // SwipeGeneralUtils.handleException(error, context, null);
-// }
-// }
-//
-// Future handleNfcAttendance({double latitude = 0, double longitude = 0, BuildContext context}) async {
-// final userProvider = Provider.of(context, listen: false);
-//
-// if (Platform.isIOS) {
-// SwipeGeneralUtils.readNFc(onRead: (String nfcId) async {
-// await _processNfcAttendance(userProvider, nfcId, latitude, longitude, context);
-// });
-// } else {
-// showNfcReader(context, onNcfScan: (String nfcId) async {
-// await _processNfcAttendance(userProvider, nfcId ?? '', latitude, longitude, context);
-// });
-// }
-// }
-//
-// Future _processNfcAttendance(
-// UserProvider userProvider,
-// String nfcId,
-// double latitude,
-// double longitude,
-// BuildContext context,
-// ) async {
-// SwipeGeneralUtils.showLoading(context);
-// try {
-// // final swipeModel = Swipe(
-// // swipeTypeValue: SwipeTypeEnum.NFC.getIntFromSwipeTypeEnum(),
-// // value: nfcId,
-// // latitude: latitude,
-// // longitude: longitude,
-// // );
-// //Test model...
-// final swipeModel = Swipe(swipeTypeValue: SwipeTypeEnum.NFC.getIntFromSwipeTypeEnum(), value: '123', latitude: 24.70865415364271, longitude: 46.66600861881879);
-// final swipeResponse = await userProvider.makeSwipe(model: swipeModel);
-// if (swipeResponse.isSuccess) {
-// if (Platform.isIOS) await Future.delayed(const Duration(seconds: 3));
-// SwipeGeneralUtils.hideLoading(context);
-// Navigator.pushNamed(context, SwipeSuccessView.routeName);
-// } else {
-// SwipeGeneralUtils.hideLoading(context);
-// SwipeGeneralUtils.showErrorDialog(message: swipeResponse.message ?? "Unexpected error occurred", context: context);
-// }
-// } catch (errSwipeGeneralUtilsor) {
-// SwipeGeneralUtils.hideLoading(context);
-// // Uncomment below line for error handling if needed
-// // SwipeGeneralUtils.handleException(error, context, null);
-// }
-// }
-//
-// Future closeWifiRequest() async {
-// if (Platform.isAndroid) {
-// await WiFiForIoTPlugin.forceWifiUsage(false);
-// }
-// return await WiFiForIoTPlugin.disconnect();
-// }
-//
-// Future performQrCodeAttendance({double latitude, double longitude, BuildContext context}) async {
-// UserProvider userProvider = Provider.of(context, listen: false);
-// var qrCodeValue = await Navigator.of(context).push(
-// MaterialPageRoute(
-// builder: (BuildContext context) => QrScannerDialog(),
-// ),
-// );
-// if (qrCodeValue != null) {
-// SwipeGeneralUtils.showLoading(context);
-// try {
-// //test model..
-// final swipeModel = Swipe(
-// swipeTypeValue: SwipeTypeEnum.QR.getIntFromSwipeTypeEnum(),
-// value: '2323',
-// latitude: 24.70865415364271,
-// longitude: 46.66600861881879,
-// );
-// final swipeResponse = await userProvider.makeSwipe(model: swipeModel);
-// if (swipeResponse.isSuccess) {
-// SwipeGeneralUtils.hideLoading(context);
-// SwipeGeneralUtils.showMDialog(context, backgroundColor: Colors.transparent, isDismissable: true, child: SuccessDialog(widget.isFromDashboard));
-// } else {
-// SwipeGeneralUtils.hideLoading(context);
-// showDialog(
-// barrierDismissible: true,
-// context: context,
-// builder: (cxt) => ConfirmDialog(
-// message: swipeResponse.message ?? "",
-// onTap: () {
-// Navigator.pop(context);
-// },
-// onCloseTap: () {}
-// ),
-// );
-// }
-// } catch (ex) {
-// SwipeGeneralUtils.hideLoading(context);
-// }
-// }
-// }
-//
-// List availableAttendanceMethodList({@required BuildContext context}) {
-// List availableMethods = [];
-// if (isNfcEnabled) {
-// availableMethods.add(attendanceMethod(SwipeTypeEnum.NFC.name, 'nfc_icon', isNfcEnabled, () {
-// handleSwipe(swipeType: SwipeTypeEnum.NFC, isEnable: isNfcEnabled, context: context);
-// }));
-// }
-// if (isQrEnabled) {
-// availableMethods.add(attendanceMethod(SwipeTypeEnum.QR.name, 'wifi_icon', isQrEnabled, () {
-// handleSwipe(swipeType: SwipeTypeEnum.QR, isEnable: isQrEnabled, context: context);
-// }));
-// }
-// if (isWifiEnabled) {
-// availableMethods.add(attendanceMethod(SwipeTypeEnum.Wifi.name, 'wifi_icon', isWifiEnabled, () {
-// handleSwipe(swipeType: SwipeTypeEnum.Wifi, isEnable: isWifiEnabled, context: context);
-// }));
-// }
-// return availableMethods;
-// }
-//
-// Widget attendanceMethod(String title, String icon, bool isEnabled, VoidCallback onPress) {
-// return Container(
-// padding: EdgeInsets.all(12),
-// decoration: BoxDecoration(
-// color: Colors.white,
-// borderRadius: BorderRadius.circular(18),
-// border: Border.all(color: AppColor.white40, width: 2),
-// ),
-// child: Column(
-// crossAxisAlignment: CrossAxisAlignment.start,
-// mainAxisAlignment: MainAxisAlignment.spaceBetween,
-// children: [
-// icon.toSvgAsset(),
-// title.heading5(context).custom(color: AppColor.neutral50),
-// // Text(
-// // title,
-// // style: TextStyle(fontSize: 12, fontWeight: FontWeight.w500),
-// // ),
-// ],
-// ),
-// ).onPress(
-// () {
-// log('isEnabled is ${!isEnabled}');
-// if (!isEnabled) return;
-// onPress();
-// },
-// );
-// // return Container(
-// // decoration: BoxDecoration(
-// // borderRadius: BorderRadius.circular(15),
-// // color: isEnabled ? null : Colors.grey.withOpacity(.5),
-// // gradient: isEnabled
-// // ? const LinearGradient(
-// // transform: GradientRotation(.64),
-// // begin: Alignment.topRight,
-// // end: Alignment.bottomLeft,
-// // colors: [
-// // //ToDo set Colors according to design provided by designer...
-// // Colors.blue,
-// // Colors.green,
-// // // AppColor.gradiantEndColor,
-// // // MyColors.gradiantStartColor,
-// // ],
-// // )
-// // : null,
-// // ),
-// // clipBehavior: Clip.antiAlias,
-// // padding: const EdgeInsets.only(left: 10, right: 10, top: 14, bottom: 14),
-// // child: Column(
-// // crossAxisAlignment: CrossAxisAlignment.start,
-// // children: [
-// // // SvgPicture.asset(image, color: Colors.white, alignment: Alignment.topLeft).expanded,
-// // Icon(iconData, color: isEnabled ? AppColor.black35 : Colors.grey),
-// // title.heading6(context),
-// // // title.toText17(isBold: true, color: Colors.white),
-// // ],
-// // ),
-// // ).onPress(
-// // () {
-// // log('isEnabled is ${!isEnabled}');
-// // if (!isEnabled) return;
-// // onPress();
-// // },
-// // );
-// }
-// }
-//
-// // Widget customListItem({required String icon, required String heading, required String subHeading, required VoidCallback onTap}) {
-// // return GestureDetector(
-// // onTap: onTap, // Handles the tap
-// // child: Card(
-// // shape: RoundedRectangleBorder(
-// // borderRadius: BorderRadius.circular(14), // Circular border radius
-// // ),
-// // color: Colors.white,
-// // child: Row(
-// // crossAxisAlignment: CrossAxisAlignment.start, // Align items at the top
-// // children: [
-// // // Icon Section
-// // icon
-// // .toSvgAsset(
-// // width: 32,
-// // color: AppColor.neutral120,
-// // height: 29,
-// // )
-// // .paddingOnly(top: 8),
-// // 14.width,
-// // Expanded(
-// // child: Column(
-// // crossAxisAlignment: CrossAxisAlignment.start,
-// // children: [
-// // Text(
-// // heading,
-// // style: AppTextStyles.heading6.copyWith(color: AppColor.neutral50),
-// // ),
-// // 7.height,
-// // Text(
-// // subHeading,
-// // style: AppTextStyles.bodyText2.copyWith(color: AppColor.neutral120),
-// // ),
-// // ],
-// // ).paddingOnly(end: 50),
-// // ),
-// // ],
-// // ).paddingAll(12),
-// // ),
-// // );
-// // }
-//
-// //qr older code...
-//
-// //nfc older code widget
-//
-// // // if (AppState().getIsHuawei) {
-// // if (false) {
-// // checkHuaweiLocationPermission(SwipeTypeEnum.NFC);
-// // } else {
-// // LocationUtilities.isEnabled((bool isEnabled) {
-// // if (isEnabled) {
-// // LocationUtilities.havePermission((bool permission) {
-// // if (permission) {
-// // SwipeGeneralUtils.showLoading(context);
-// // LocationUtilities.getCurrentLocation(
-// // (Position position, bool isMocked) {
-// // if (isMocked) {
-// // SwipeGeneralUtils.hideLoading(context);
-// // SwipeGeneralUtils.markFakeAttendance("NFC", position.latitude.toString() ?? "", position.longitude.toString() ?? "",context);
-// // } else {
-// // SwipeGeneralUtils.hideLoading(context);
-// // //todo performNfcAttendance(widget.model, lat: position.latitude.toString() ?? "", lng: position.longitude.toString() ?? "");
-// // }
-// // },
-// // () {
-// // SwipeGeneralUtils.hideLoading(context);
-// // SwipeGeneralUtils.confirmDialog(context, "Unable to determine your location, Please make sure that your location services are turned on & working.");
-// // },
-// // context,
-// // );
-// // } else {
-// // showDialog(
-// // context: context,
-// // builder: (BuildContext cxt) => ConfirmDialog(
-// // message: "You need to give location permission to mark attendance",
-// // onTap: () async {
-// // Navigator.pop(context);
-// // await Geolocator.openAppSettings();
-// // },
-// // ),
-// // );
-// // }
-// // });
-// // } else {
-// // showDialog(
-// // context: context,
-// // builder: (BuildContext cxt) => ConfirmDialog(
-// // message: "You need to enable location services to mark attendance",
-// // onTap: () async {
-// // Navigator.pop(context);
-// // await Geolocator.openLocationSettings();
-// // },
-// // ),
-// // );
-// // }
-// // });
-// // }
-//
-// //older code....
-// // Future performNfcAttendance({double lat = 0, double lng = 0}) async {
-// // UserProvider userProvider = Provider.of(context,listen:false);
-// // if (Platform.isIOS) {
-// // SwipeGeneralUtils.readNFc(onRead: (String nfcId) async {
-// // SwipeGeneralUtils.showLoading(context);
-// // try {
-// // SwipeModel swipeResponse = await userProvider.makeSwipe(model: Swipe(swipeTypeValue: SwipeTypeEnum.NFC.getIntFromSwipeTypeEnum(), value: '', latitude: lat, longitude: lng));
-// // if (swipeResponse.responseCode != 1) {
-// // SwipeGeneralUtils.hideLoading(context);
-// // showDialog(
-// // context: context,
-// // builder: (BuildContext cxt) => ConfirmDialog(
-// // message: swipeResponse.message ?? "Unexpected error occurred",
-// // onTap: () {
-// // Navigator.pop(context);
-// // },
-// // ),
-// // );
-// // } else {
-// // bool status = swipeResponse.data;
-// // if (Platform.isIOS) await Future.delayed(const Duration(seconds: 3));
-// // SwipeGeneralUtils.hideLoading(context);
-// // SwipeGeneralUtils.showMDialog(
-// // context,
-// // backgroundColor: Colors.transparent,
-// // isDismissable: true,
-// // child: SuccessDialog(widget.isFromDashboard),
-// // );
-// // }
-// // } catch (ex) {
-// // SwipeGeneralUtils.hideLoading(context);
-// // // SwipeGeneralUtils.handleException(ex, context, null);
-// // }
-// // });
-// // } else {
-// // showNfcReader(context, onNcfScan: (String nfcId) async {
-// // SwipeGeneralUtils.showLoading(context);
-// // try {
-// // SwipeModel swipeResponse = await userProvider.makeSwipe(model: Swipe(swipeTypeValue: SwipeTypeEnum.NFC.getIntFromSwipeTypeEnum(), value: nfcId??'', latitude: lat, longitude: lng));
-// // log('api response i got is ${swipeResponse.toJson()}');
-// // if (swipeResponse.responseCode != 1) {
-// // SwipeGeneralUtils.hideLoading(context);
-// // showDialog(
-// // context: context,
-// // builder: (BuildContext cxt) => ConfirmDialog(
-// // message: swipeResponse.message ?? "Unexpected error occurred",
-// // onTap: () {
-// // Navigator.pop(context);
-// // },
-// // ),
-// // );
-// // } else {
-// // bool status = swipeResponse.data; //use this status to get transactions.
-// // if (Platform.isIOS) await Future.delayed(const Duration(seconds: 3));
-// // SwipeGeneralUtils.hideLoading(context);
-// // SwipeGeneralUtils.showMDialog(
-// // context,
-// // backgroundColor: Colors.transparent,
-// // isDismissable: true,
-// // child: SuccessDialog(widget.isFromDashboard),
-// // );
-// // }
-// // } catch (ex) {
-// // SwipeGeneralUtils.hideLoading(context);
-// // // SwipeGeneralUtils.handleException(ex, context, null);
-// // }
-// // // SwipeGeneralUtils.showLoading(context);
-// // // try {
-// // // GenericResponseModel? g = await DashboardApiClient().markAttendance(pointType: 2, nfcValue: nfcId ?? "", isGpsRequired: isNfcLocationEnabled, lat: lat, long: lng);
-// // // if (g?.messageStatus != 1) {
-// // // SwipeGeneralUtils.hideLoading(context);
-// // // showDialog(
-// // // context: context,
-// // // builder: (BuildContext cxt) => ConfirmDialog(
-// // // message: g?.errorEndUserMessage ?? "Unexpected error occurred",
-// // // onTap: () {
-// // // Navigator.pop(context);
-// // // },
-// // // ),
-// // // );
-// // // } else {
-// // // bool status = await model.fetchAttendanceTracking(context);
-// // // SwipeGeneralUtils.hideLoading(context);
-// // // showMDialog(
-// // // context,
-// // // backgroundColor: Colors.transparent,
-// // // isDismissable: false,
-// // // child: SuccessDialog(widget.isFromDashboard),
-// // // );
-// // // }
-// // // } catch (ex) {
-// // // log(ex);
-// // // SwipeGeneralUtils.hideLoading(context);
-// // // // SwipeGeneralUtils.handleException(ex, context, (String msg) {
-// // // // SwipeGeneralUtils.confirmDialog(context, msg);
-// // // // });
-// // // }
-// // });
-// // }
-// // }
-//
-// //
-// // Future checkSession() async {
-// // try {
-// // SwipeGeneralUtils.showLoading(context);
-// // await DashboardApiClient().getOpenMissingSwipes();
-// // SwipeGeneralUtils.hideLoading(context);
-// // return true;
-// // } catch (ex) {
-// // SwipeGeneralUtils.hideLoading(context);
-// // SwipeGeneralUtils.handleException(ex, context, null);
-// // return false;
-// // }
-// // }
-//
-// //TODO need to confirm ....
-// Future performWifiAttendance({double? latitude, double? lng}) async {
-// // if (Platform.isAndroid) {
-// // if (!(await checkSession())) {
-// // return;
-// // }
-// // }
-// SwipeGeneralUtils.showLoading(context);
-// bool isConnected = await WiFiForIoTPlugin.connect(AppState().getMohemmWifiSSID ?? "",
-// password: AppState().getMohemmWifiPassword ?? "", joinOnce: Platform.isIOS ? false : true, security: NetworkSecurity.WPA, withInternet: false);
-//
-// if (Platform.isIOS) {
-// if (await WiFiForIoTPlugin.getSSID() == AppState().getMohemmWifiSSID) {
-// isConnected = true;
-// } else {
-// isConnected = false;
-// }
-// }
-//
-// if (isConnected && AppState().isAuthenticated) {
-// await WiFiForIoTPlugin.forceWifiUsage(true);
-// await Future.delayed(const Duration(seconds: 6));
-// try {
-// GenericResponseModel? g = await DashboardApiClient().markAttendance(pointType: 3, nfcValue: "", isGpsRequired: isWifiLocationEnabled, lat: lat, long: lng);
-// bool status = await model.fetchAttendanceTracking(context);
-// SwipeGeneralUtils.hideLoading(context);
-// await closeWifiRequest();
-// if (g?.messageStatus == 2) {
-// showDialog(
-// barrierDismissible: true,
-// context: context,
-// builder: (cxt) => ConfirmDialog(
-// message: g?.errorEndUserMessage ?? "",
-// onTap: () {
-// Navigator.pop(context);
-// },
-// onCloseTap: () {},
-// ),
-// );
-// } else {
-// showMDialog(
-// context,
-// backgroundColor: Colors.transparent,
-// isDismissable: false,
-// child: SuccessDialog(widget.isFromDashboard),
-// );
-// }
-// } catch (ex) {
-// await closeWifiRequest();
-// SwipeGeneralUtils.hideLoading(context);
-// SwipeGeneralUtils.handleException(ex, context, null);
-// }
-// } else {
-// if (AppState().isAuthenticated) {
-// SwipeGeneralUtils.hideLoading(context);
-// SwipeGeneralUtils.confirmDialog(context, "LocaleKeys.comeNearHMGWifi.tr()");
-// } else {
-// await closeWifiRequest();
-// }
-// }
-// }
-//
-// // older grid widget..
-// // attendanceMethod(SwipeTypeEnum.NFC.name, Icons.nfc, isNfcEnabled, () {
-// // handleSwipe(swipeType: SwipeTypeEnum.NFC, isEnable: isNfcEnabled);
-// // }),
-// // attendanceMethod(SwipeTypeEnum.QR.name, Icons.qr_code_2, isQrEnabled, () async {
-// // handleSwipe(swipeType: SwipeTypeEnum.QR, isEnable: true);
-// // }),
-// // //if (isWifiEnabled) //todo
-// // attendanceMethod(SwipeTypeEnum.Wifi.name, Icons.wifi, isWifiEnabled, () {
-// // // if (AppState().getIsHuawei) {
-// // if (false) {
-// // checkHuaweiLocationPermission(SwipeTypeEnum.Wifi);
-// // } else {
-// // LocationUtilities.isEnabled((bool isEnabled) {
-// // if (isEnabled) {
-// // LocationUtilities.havePermission((bool permission) {
-// // if (permission) {
-// // SwipeGeneralUtils.showLoading(context);
-// // LocationUtilities.getCurrentLocation(
-// // (Position position, bool isMocked) {
-// // if (isMocked) {
-// // SwipeGeneralUtils.hideLoading(context);
-// // SwipeGeneralUtils.markFakeAttendance("WIFI", position.latitude.toString() ?? "", position.longitude.toString() ?? "", context);
-// // } else {
-// // SwipeGeneralUtils.hideLoading(context);
-// // //todo performWifiAttendance(widget.model, lat: position.latitude.toString() ?? "", lng: position.longitude.toString() ?? "");
-// // }
-// // },
-// // () {
-// // SwipeGeneralUtils.hideLoading(context);
-// // SwipeGeneralUtils.confirmDialog(context, "Unable to determine your location, Please make sure that your location services are turned on & working.");
-// // },
-// // context,
-// // );
-// // } else {
-// // showDialog(
-// // context: context,
-// // builder: (BuildContext cxt) => ConfirmDialog(
-// // message: "You need to give location permission to mark attendance",
-// // onTap: () async {
-// // Navigator.pop(context);
-// // await Geolocator.openAppSettings();
-// // },
-// // ),
-// // );
-// // }
-// // });
-// // } else {
-// // showDialog(
-// // context: context,
-// // builder: (BuildContext cxt) => ConfirmDialog(
-// // message: "You need to enable location services to mark attendance",
-// // onTap: () async {
-// // Navigator.pop(context);
-// // await Geolocator.openLocationSettings();
-// // },
-// // ),
-// // );
-// // }
-// // });
-// // }
-// // }),
diff --git a/lib/new_views/swipe_module/swipe_history_view.dart b/lib/new_views/swipe_module/swipe_history_view.dart
index c340f7bb..3a939898 100644
--- a/lib/new_views/swipe_module/swipe_history_view.dart
+++ b/lib/new_views/swipe_module/swipe_history_view.dart
@@ -47,87 +47,86 @@ class _SwipeHistoryViewState extends State {
@override
Widget build(BuildContext context) {
return Scaffold(
- appBar: const DefaultAppBar(
- title: 'Swipe History',
- ),
- body: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- 8.height,
- Row(
- children: [
- ADatePicker(
- label: context.translation.from,
- date: dateFrom,
- from: DateTime(DateTime.now().year - 5, DateTime.now().month, DateTime.now().day),
- formatDateWithTime: true,
- onDatePicker: (selectedDate) {
- if (selectedDate != null) {
- showThemedTimePicker(
- context: context,
- initialTime: TimeOfDay.now(),
- ).then((selectedTime) {
- // Handle the selected date and time here.
- if (selectedTime != null) {
- DateTime selectedDateTime = DateTime(
- selectedDate.year,
- selectedDate.month,
- selectedDate.day,
- selectedTime.hour,
- selectedTime.minute,
- );
- if (selectedDateTime != null) {
- setState(() {
- dateFrom = selectedDateTime;
- });
+ appBar: const DefaultAppBar(title: 'Swipe History'),
+ body: SafeArea(
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Row(
+ spacing: 8,
+ children: [
+ ADatePicker(
+ label: context.translation.from,
+ date: dateFrom,
+ from: DateTime(DateTime.now().year - 5, DateTime.now().month, DateTime.now().day),
+ formatDateWithTime: true,
+ onDatePicker: (selectedDate) {
+ if (selectedDate != null) {
+ showThemedTimePicker(
+ context: context,
+ initialTime: TimeOfDay.now(),
+ ).then((selectedTime) {
+ // Handle the selected date and time here.
+ if (selectedTime != null) {
+ DateTime selectedDateTime = DateTime(
+ selectedDate.year,
+ selectedDate.month,
+ selectedDate.day,
+ selectedTime.hour,
+ selectedTime.minute,
+ );
+ if (selectedDateTime != null) {
+ setState(() {
+ dateFrom = selectedDateTime;
+ });
+ }
}
- }
- });
- }
- },
- ).expanded,
- 8.width,
- ADatePicker(
- label: context.translation.to,
- date: dateTo,
- from: DateTime(DateTime.now().year - 5, DateTime.now().month, DateTime.now().day),
- formatDateWithTime: true,
- onDatePicker: (selectedDate) {
- if (selectedDate != null) {
- showThemedTimePicker(
- context: context,
- initialTime: TimeOfDay.now(),
- ).then((selectedTime) {
- // Handle the selected date and time here.
- if (selectedTime != null) {
- DateTime selectedDateTime = DateTime(
- selectedDate.year,
- selectedDate.month,
- selectedDate.day,
- selectedTime.hour,
- selectedTime.minute,
- );
- if (selectedDateTime != null) {
- setState(() {
- dateTo = selectedDateTime;
- });
+ });
+ }
+ },
+ ).expanded,
+ ADatePicker(
+ label: context.translation.to,
+ date: dateTo,
+ from: DateTime(DateTime.now().year - 5, DateTime.now().month, DateTime.now().day),
+ formatDateWithTime: true,
+ onDatePicker: (selectedDate) {
+ if (selectedDate != null) {
+ showThemedTimePicker(
+ context: context,
+ initialTime: TimeOfDay.now(),
+ ).then((selectedTime) {
+ // Handle the selected date and time here.
+ if (selectedTime != null) {
+ DateTime selectedDateTime = DateTime(
+ selectedDate.year,
+ selectedDate.month,
+ selectedDate.day,
+ selectedTime.hour,
+ selectedTime.minute,
+ );
+ if (selectedDateTime != null) {
+ setState(() {
+ dateTo = selectedDateTime;
+ });
+ }
}
- }
- });
- }
- },
- ).expanded,
- ],
- ),
- 12.height,
- AppFilledButton(label: context.translation.search, maxWidth: false, onPressed: getSwipeHistory),
- 8.height,
- const Divider().defaultStyle(context),
- Consumer(builder: (context, snapshot, child) {
- return SwipeHistoryList(snapshot.swipeHistory ?? [], snapshot.isLoading).expanded;
- }),
- ],
- ).paddingAll(20),
+ });
+ }
+ },
+ ).expanded,
+ ],
+ ),
+ 12.height,
+ AppFilledButton(label: context.translation.search, maxWidth: false, onPressed: getSwipeHistory),
+ 8.height,
+ const Divider().defaultStyle(context),
+ Consumer(builder: (context, snapshot, child) {
+ return SwipeHistoryList(snapshot.swipeHistory ?? [], snapshot.isLoading).expanded;
+ }).expanded,
+ ],
+ ).paddingOnly(start: 16, end: 16, top: 16),
+ ),
);
}
}
@@ -143,7 +142,7 @@ class SwipeHistoryList extends StatelessWidget {
return (list.isEmpty && !isLoading)
? NoDataFound(message: context.translation.noDataFound).center
: ListView.separated(
- padding: EdgeInsets.only(top: 12.toScreenHeight),
+ padding: const EdgeInsets.only(bottom: 16, top: 16),
itemBuilder: (cxt, index) {
if (isLoading) return const SizedBox().toRequestShimmer(cxt, isLoading);
return SwipeHistoryCard(list[index]);
diff --git a/lib/new_views/swipe_module/utils/swipe_general_utils.dart b/lib/new_views/swipe_module/utils/swipe_general_utils.dart
index a24834e0..9bace21f 100644
--- a/lib/new_views/swipe_module/utils/swipe_general_utils.dart
+++ b/lib/new_views/swipe_module/utils/swipe_general_utils.dart
@@ -29,6 +29,9 @@ import 'package:test_sa/new_views/swipe_module/enums/swipe_type.dart';
import 'package:test_sa/new_views/swipe_module/models/swipe_model.dart';
import 'package:test_sa/new_views/swipe_module/swipe_success_view.dart';
import 'package:test_sa/new_views/swipe_module/utils/location_utils.dart';
+import 'package:test_sa/views/widgets/dialogs/confirm_dialog.dart';
+import 'package:test_sa/views/widgets/item_views/info_header_widget.dart';
+import 'package:test_sa/views/widgets/item_views/info_text_widget.dart';
import 'package:test_sa/views/widgets/qr/scan_qr.dart';
import 'package:wifi_iot/wifi_iot.dart';
@@ -125,18 +128,8 @@ class SwipeGeneralUtils {
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
- icon.toSvgAsset(
- color: isEnabled
- ? context.isDark
- ? AppColor.neutral30
- : AppColor.neutral50
- : Colors.grey.withOpacity(0.5)),
- title.heading5(context).custom(
- color: isEnabled
- ? context.isDark
- ? AppColor.neutral30
- : AppColor.neutral50
- : Colors.grey.withOpacity(0.5)),
+ icon.toSvgAsset(width: 24, height: 24, color: AppColor.icon2Color(context)),
+ title.bodyText2(context).custom(color: AppColor.labelTextStyleColor(context), fontSize: context.isTablet() ? 10.toScreenWidth : null),
],
),
).onPress(
@@ -826,9 +819,9 @@ class _SwipeTypeBottomSheetContentState extends State<_SwipeTypeBottomSheetConte
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
- context.translation.markAttendance.heading5(context).custom(color: AppColor.headingTextColor(context)),
+ InfoHeader16Widget("Mark Attendance"),
8.height,
- context.translation.selectMethodToMarkAttendance.bodyText2(context).custom(color: AppColor.lightTextColor(context)),
+ InfoTextLabelWidget(label: context.translation.selectMethodToMarkAttendance),
12.height,
GridView.builder(
padding: const EdgeInsets.all(0),
@@ -910,4 +903,3 @@ class _SwipeTypeItem {
required this.isEnabled,
});
}
-
diff --git a/lib/views/full_screen_image_viewer.dart b/lib/views/full_screen_image_viewer.dart
new file mode 100644
index 00000000..9c463e06
--- /dev/null
+++ b/lib/views/full_screen_image_viewer.dart
@@ -0,0 +1,38 @@
+import 'package:flutter/material.dart';
+import 'package:test_sa/extensions/widget_extensions.dart';
+
+import '../new_views/app_style/app_color.dart';
+
+class FullScreenImageViewer extends StatelessWidget {
+ final Widget child;
+
+ const FullScreenImageViewer(this.child, {Key? key}) : super(key: key);
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ body: Stack(
+ children: [
+ InteractiveViewer(clipBehavior: Clip.none, panEnabled: true, minScale: 0.5, maxScale: 4.0, child: child).center,
+ SafeArea(
+ child: Padding(
+ padding: const EdgeInsets.all(16.0),
+ child: FloatingActionButton(
+ heroTag: "full-screen-image-viewer",
+ backgroundColor: AppColor.background(context),
+ onPressed: () => Navigator.maybePop(context),
+ hoverColor: Colors.transparent,
+ splashColor: Colors.transparent,
+ shape: RoundedRectangleBorder(
+ side: BorderSide(color: AppColor.borderColor(context)),
+ borderRadius: BorderRadius.circular(14.0),
+ ),
+ child: Icon(Icons.clear, size: 24, color: AppColor.icon2Color(context)),
+ ),
+ ),
+ ),
+ ],
+ ),
+ );
+ }
+}
diff --git a/lib/views/update_available_screen.dart b/lib/views/update_available_screen.dart
index 558a0233..ff71f215 100644
--- a/lib/views/update_available_screen.dart
+++ b/lib/views/update_available_screen.dart
@@ -25,13 +25,13 @@ class UpdateAvailableScreen extends StatelessWidget {
48.height,
Text(
"Update Available",
- style: AppTextStyles.heading4.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral50),
+ style: AppTextStyles.heading4.copyWith(color: AppColor.headingTextColor(context)),
),
24.height,
Text(
"A new update is available on store.\nUpdate now to enjoy the latest features, improvements, and bug fixes for a smoother experience! ",
textAlign: TextAlign.center,
- style: AppTextStyles.heading6.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20),
+ style: AppTextStyles.heading6.copyWith(color: AppColor.lightTextColor(context)),
),
24.height,
AppFilledButton(
diff --git a/lib/views/widgets/auto_complete/wo_auto_complete_field.dart b/lib/views/widgets/auto_complete/wo_auto_complete_field.dart
index b157df2e..5d01acce 100644
--- a/lib/views/widgets/auto_complete/wo_auto_complete_field.dart
+++ b/lib/views/widgets/auto_complete/wo_auto_complete_field.dart
@@ -59,11 +59,12 @@ class _WoAutoCompleteFieldState extends State {
@override
Widget build(BuildContext context) {
- final border = UnderlineInputBorder(borderSide: BorderSide.none, borderRadius: BorderRadius.circular(10));
+ final border = UnderlineInputBorder(borderSide: BorderSide.none, borderRadius: BorderRadius.circular(16));
return Container(
decoration: BoxDecoration(
color: AppColor.background(context),
- borderRadius: BorderRadius.circular(AppStyle.borderRadius * AppStyle.getScaleFactor(context)),
+ border: Border.all(color: AppColor.border2Color(context), width: 1),
+ borderRadius: BorderRadius.circular(16),
// boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 10)],
),
child: Autocomplete(
@@ -93,7 +94,7 @@ class _WoAutoCompleteFieldState extends State {
return TextField(
controller: _controller,
focusNode: fieldFocusNode,
- style: AppTextStyles.bodyText.copyWith(color: AppColor.black10),
+ style: TextStyle(fontWeight: FontWeight.w500, fontSize: context.isTablet() ? 16 : 14, color: AppColor.textStyleColor(context)),
textAlign: TextAlign.start,
decoration: InputDecoration(
border: border,
@@ -101,16 +102,16 @@ class _WoAutoCompleteFieldState extends State {
focusedBorder: border,
enabledBorder: border,
errorBorder: border,
- contentPadding: EdgeInsets.symmetric(vertical: 8.toScreenHeight, horizontal: 16.toScreenWidth),
+ contentPadding: EdgeInsets.symmetric(vertical: 12.toScreenHeight, horizontal: 16.toScreenWidth),
constraints: const BoxConstraints(),
suffixIconConstraints: const BoxConstraints(maxHeight: 24, maxWidth: 24 + 8),
filled: true,
enabled: widget.enabled,
- fillColor: AppColor.fieldBgColor(context),
+ fillColor: AppColor.dropDownBackground(context),
errorStyle: AppTextStyle.tiny.copyWith(color: context.isDark ? AppColor.red50 : AppColor.red60),
- floatingLabelStyle: AppTextStyle.body1.copyWith(fontWeight: FontWeight.w500, color: context.isDark ? null : AppColor.neutral20),
+ floatingLabelStyle: TextStyle(fontWeight: FontWeight.w500, fontSize: context.isTablet() ? 16 : 12, color: AppColor.floatingTextStyleColor(context)),
+ labelStyle: TextStyle(fontWeight: FontWeight.w500, fontSize: context.isTablet() ? 16 : 12, color: AppColor.labelTextStyleColor(context)),
labelText: "CM Work Order Number",
- labelStyle: AppTextStyles.tinyFont.copyWith(color: AppColor.textColor(context)),
suffixIcon: loading ? const CircularProgressIndicator(color: AppColor.primary10, strokeWidth: 3.0).paddingOnly(end: 8) : null,
),
textInputAction: TextInputAction.search,
diff --git a/lib/views/widgets/dialogs/confirm_dialog.dart b/lib/views/widgets/dialogs/confirm_dialog.dart
index 6d8ef764..60db0c03 100644
--- a/lib/views/widgets/dialogs/confirm_dialog.dart
+++ b/lib/views/widgets/dialogs/confirm_dialog.dart
@@ -2,21 +2,22 @@ import 'package:flutter/material.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
+import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/app_filled_button.dart';
class ConfirmDialog extends StatelessWidget {
final String? title;
- final String message;
+ final String? message;
final String? okTitle;
final VoidCallback? onTap;
final VoidCallback? onCloseTap;
- const ConfirmDialog({Key? key, this.title, required this.message, this.okTitle, this.onTap, this.onCloseTap}) : super(key: key);
+ const ConfirmDialog({Key? key, this.title, this.message, this.okTitle, this.onTap, this.onCloseTap}) : super(key: key);
@override
Widget build(BuildContext context) {
return Dialog(
- backgroundColor: Colors.white,
+ backgroundColor: AppColor.background(context),
shape: const RoundedRectangleBorder(),
insetPadding: const EdgeInsets.only(left: 21, right: 21),
child: Padding(
@@ -31,21 +32,20 @@ class ConfirmDialog extends StatelessWidget {
Expanded(
child: Text(
title ?? "Confirm",
- style: const TextStyle(fontSize: 24, fontWeight: FontWeight.w600, color: Colors.black87, height: 35 / 24, letterSpacing: -0.96),
+ style: TextStyle(fontSize: 24, fontWeight: FontWeight.w600, color: AppColor.headingTextColor(context), height: 35 / 24, letterSpacing: -0.96),
).paddingOnly(top: 16),
),
IconButton(
padding: EdgeInsets.zero,
icon: const Icon(Icons.close),
- color: Colors.black87,
+ color: AppColor.iconColor(context),
constraints: const BoxConstraints(),
onPressed: () => onCloseTap ?? Navigator.pop(context),
// onPressed: () => Navigator.pop(context),
)
],
),
- 16.height,
- message.bodyText(context),
+ message != null ? message!.heading5(context).custom(color: AppColor.textColor(context)) : const SizedBox(),
28.height,
AppFilledButton(
label: okTitle ?? "OK",
diff --git a/lib/views/widgets/dialogs/dialog.dart b/lib/views/widgets/dialogs/dialog.dart
index 0cdfa87c..e7132eb1 100644
--- a/lib/views/widgets/dialogs/dialog.dart
+++ b/lib/views/widgets/dialogs/dialog.dart
@@ -37,6 +37,7 @@ class AAlertDialog extends StatelessWidget {
)
: AlertDialog(
backgroundColor: AppColor.background(context),
+ actionsPadding: const EdgeInsets.only(bottom: 12, left: 24, right: 24),
title: title != null ? Text(title!) : null,
content: content != null ? Text(content!) : null,
// contentTextStyle: AppTextStyles.bodyText.copyWith(color: (context.isDark ? AppColor.neutral30 : AppColor.neutral50)),
diff --git a/lib/views/widgets/dialogs/loading_with_text_dialog.dart b/lib/views/widgets/dialogs/loading_with_text_dialog.dart
new file mode 100644
index 00000000..b07b3eb6
--- /dev/null
+++ b/lib/views/widgets/dialogs/loading_with_text_dialog.dart
@@ -0,0 +1,41 @@
+import 'package:flutter/material.dart';
+import 'package:test_sa/extensions/int_extensions.dart';
+import 'package:test_sa/new_views/app_style/app_color.dart';
+import 'package:test_sa/views/app_style/sizing.dart';
+
+class LoadingWithTextDialog extends StatelessWidget {
+ final String? message;
+
+ const LoadingWithTextDialog({Key? key, this.message}) : super(key: key);
+
+ @override
+ Widget build(BuildContext context) {
+ return Center(
+ child: Material(
+ borderRadius: BorderRadius.circular(20.0),
+ child: Container(
+ height: 150.toScreenWidth,
+ width: 200.toScreenWidth,
+ alignment: Alignment.center,
+ padding: const EdgeInsets.all(8),
+ decoration: BoxDecoration(
+ color: AppColor.neutral30,
+ borderRadius: BorderRadius.circular(20.0),
+ boxShadow: [AppStyle.boxShadow],
+ ),
+ child: Column(
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ const CircularProgressIndicator(strokeWidth: 3),
+ 16.height,
+ Text(
+ message ?? "Uploading...",
+ style: TextStyle(fontSize: 16, fontWeight: FontWeight.w500, color: AppColor.textColor(context), height: 35 / 24, letterSpacing: -0.96),
+ )
+ ],
+ ),
+ ),
+ ),
+ );
+ }
+}
diff --git a/lib/views/widgets/equipment/asset_detail_page.dart b/lib/views/widgets/equipment/asset_detail_page.dart
index dd94a08d..0a51cc87 100644
--- a/lib/views/widgets/equipment/asset_detail_page.dart
+++ b/lib/views/widgets/equipment/asset_detail_page.dart
@@ -7,10 +7,17 @@ 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/widget_extensions.dart';
+import 'package:test_sa/helper/utils.dart';
import 'package:test_sa/models/device/asset_by_id_model.dart';
+import 'package:test_sa/models/generic_attachment_model.dart';
+import 'package:test_sa/modules/cm_module/views/components/action_button/footer_action_button.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/views/widgets/item_views/info_header_widget.dart';
import 'package:test_sa/views/widgets/item_views/info_text_widget.dart';
+import 'package:test_sa/views/widgets/equipment/asset_image_upload_page.dart';
+import 'package:test_sa/views/widgets/images/files_list.dart';
+import 'package:test_sa/views/widgets/images/multi_image_picker.dart';
import 'package:test_sa/views/widgets/loaders/app_loading.dart';
import 'package:test_sa/views/widgets/loaders/failed_loading.dart';
@@ -32,6 +39,7 @@ class _AssetDetailPageState extends State with SingleTickerProv
late AnimationController _animationController;
int? assetId;
AssetProvider? _assetProvider;
+ AssetByIdModel? assetModel;
@override
void initState() {
@@ -48,6 +56,7 @@ class _AssetDetailPageState extends State with SingleTickerProv
super.dispose();
}
+ List attachments = [];
@override
Widget build(BuildContext context) {
@@ -57,7 +66,7 @@ class _AssetDetailPageState extends State with SingleTickerProv
return Scaffold(
appBar: DefaultAppBar(title: context.translation.assetDetails),
body: FutureBuilder(
- future: _assetProvider!.getAssetById(assetId!, context.translation),
+ future: assetModel == null ? _assetProvider!.getAssetById(assetId!, context.translation) : null,
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasError) {
return FailedLoading(
@@ -71,9 +80,19 @@ class _AssetDetailPageState extends State with SingleTickerProv
return const Center(child: ALoading());
} else if (snapshot.hasData) {}
if (snapshot.hasData) {
- AssetByIdModel assetModel = snapshot.data!;
- // Start animation when data is loaded
- _animationController.forward(from: 0.0);
+ assetModel = snapshot.data!;
+ attachments = assetModel?.assetAttachments
+ ?.map((attachment) => GenericAttachmentModel(
+ id: attachment.id,
+ name: attachment.attachmentName,
+ originalName: attachment.originalName,
+ ))
+ .toList() ??
+ [];
+
+ if (!_animationController.isCompleted) {
+ _animationController.forward(from: 0.0);
+ }
// Image animation - fade in with scale
final imageAnimation = Tween(begin: 0.0, end: 1.0).animate(
@@ -180,142 +199,193 @@ class _AssetDetailPageState extends State with SingleTickerProv
),
);
- return SingleChildScrollView(
- padding: const EdgeInsets.all(16),
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- // Animated image
- FadeTransition(
- opacity: imageAnimation,
- child: ScaleTransition(
- scale: imageScaleAnimation,
- child: AspectRatio(
- aspectRatio: 159 / 94,
- child: Container(
- width: 95,
- height: 95,
- decoration: ShapeDecoration(
- color: AppColor.neutral30,
- shape: RoundedRectangleBorder(
- borderRadius: BorderRadius.circular(16),
- ),
- image: DecorationImage(
- fit: BoxFit.cover,
- image: NetworkImage(assetModel.assetPhoto != null ? URLs.getFileUrl(assetModel.assetPhoto!)! : "https://www.lasteelcraft.com/images/no-image-available.png"),
- )),
- ),
- ),
- ),
- ),
- 6.height,
- // Animated content column
- Column(
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ final attachmentAnimation = Tween(begin: 0.0, end: 1.0).animate(
+ CurvedAnimation(
+ parent: _animationController,
+ curve: const Interval(0.80, 1.0, curve: Curves.easeOut),
+ ),
+ );
+
+ final attachmentSlideAnimation = Tween(
+ begin: const Offset(0.0, 0.1),
+ end: Offset.zero,
+ ).animate(
+ CurvedAnimation(
+ parent: _animationController,
+ curve: const Interval(0.80, 1.0, curve: Curves.easeOutCubic),
+ ),
+ );
+
+ return Column(
+ children: [
+ SingleChildScrollView(
+ padding: const EdgeInsets.all(16),
+ child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
- // Status label with animation
- if (assetModel.commissioningStatus != null)
- FadeTransition(
- opacity: statusAnimation,
- child: SlideTransition(
- position: statusSlideAnimation,
- child: StatusLabel(
- label: assetModel.commissioningStatus!.name,
- textColor: AppColor.getRequestStatusTextColorByName(context, assetModel.commissioningStatus!.name!),
- backgroundColor: AppColor.getRequestStatusColorByName(context, assetModel.commissioningStatus!.name!),
+ // Animated image
+ FadeTransition(
+ opacity: imageAnimation,
+ child: ScaleTransition(
+ scale: imageScaleAnimation,
+ child: AspectRatio(
+ aspectRatio: 159 / 94,
+ child: Container(
+ width: 95,
+ height: 95,
+ decoration: ShapeDecoration(
+ color: AppColor.neutral30,
+ shape: RoundedRectangleBorder(
+ borderRadius: BorderRadius.circular(16),
+ ),
+ image: DecorationImage(
+ fit: BoxFit.cover,
+ image: NetworkImage(assetModel?.assetPhoto != null ? URLs.getFileUrl(assetModel!.assetPhoto!)! : "https://www.lasteelcraft.com/images/no-image-available.png"),
+ )),
),
),
),
- if (assetModel.commissioningStatus != null) 8.height,
-
- // Header with animation
- FadeTransition(
- opacity: headerAnimation,
- child: SlideTransition(
- position: headerSlideAnimation,
- child: InfoHeader16Widget(assetModel.modelDefinition?.assetName?.cleanupWhitespace.capitalizeFirstOfEach ?? "-"),
- ),
),
- 8.height,
+ 6.height,
+ // Animated content column
+ Column(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ // Status label with animation
+ if (assetModel?.commissioningStatus != null)
+ FadeTransition(
+ opacity: statusAnimation,
+ child: SlideTransition(
+ position: statusSlideAnimation,
+ child: StatusLabel(
+ label: assetModel!.commissioningStatus!.name,
+ textColor: AppColor.getRequestStatusTextColorByName(context, assetModel!.commissioningStatus!.name!),
+ backgroundColor: AppColor.getRequestStatusColorByName(context, assetModel!.commissioningStatus!.name!),
+ ),
+ ),
+ ),
+ if (assetModel?.commissioningStatus != null) 8.height,
- // Details row with animation
- FadeTransition(
- opacity: detailsAnimation,
- child: SlideTransition(
- position: detailsSlideAnimation,
- child: Row(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Column(
+ // Header with animation
+ FadeTransition(
+ opacity: headerAnimation,
+ child: SlideTransition(
+ position: headerSlideAnimation,
+ child: Column(
+ mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
+ spacing: 2,
children: [
- InfoTextWidget(label: context.translation.assetNo, value: assetModel.multiAssets!.first.assetNumber, showEmptyValue: true),
- InfoTextWidget(label: context.translation.modelName, value: assetModel.modelDefinition!.modelName, showEmptyValue: true),
- InfoTextWidget(label: context.translation.supplier, value: assetModel.supplier?.suppliername, showEmptyValue: true),
- InfoTextWidget(label: context.translation.manufacture, value: assetModel.modelDefinition!.manufacturerName, showEmptyValue: true),
+ InfoHeader16Widget(assetModel?.modelDefinition?.assetName?.cleanupWhitespace.capitalizeFirstOfEach ?? "-"),
+ if (context.userProvider.isEngineer && !(assetModel?.hasTrainingImageData ?? true))
+ const InfoTextLabelWidget(label: '*Upload Images for this asset', color: AppColor.red30),
],
- ).expanded,
- 8.width,
- Column(
+ ),
+ ),
+ ),
+ 8.height,
+ // Details row with animation
+ FadeTransition(
+ opacity: detailsAnimation,
+ child: SlideTransition(
+ position: detailsSlideAnimation,
+ child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
+ spacing: 8,
children: [
- InfoTextWidget(label: context.translation.snNo, value: assetModel.multiAssets!.first.assetSerialNo, showEmptyValue: true),
- InfoTextWidget(label: context.translation.site, value: assetModel.site?.custName?.cleanupWhitespace.capitalizeFirstOfEach, showEmptyValue: true),
- InfoTextWidget(label: context.translation.building, value: assetModel.building?.name?.cleanupWhitespace.capitalizeFirstOfEach, showEmptyValue: true),
- InfoTextWidget(label: context.translation.floor, value: assetModel.floor?.name?.cleanupWhitespace.capitalizeFirstOfEach, showEmptyValue: true),
- InfoTextWidget(label: context.translation.md, value: assetModel.department?.departmentName?.cleanupWhitespace.capitalizeFirstOfEach, showEmptyValue: true),
- InfoTextWidget(label: context.translation.room, value: assetModel.room?.name?.cleanupWhitespace.capitalizeFirstOfEach, showEmptyValue: true),
+ Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ InfoTextWidget(label: context.translation.assetNo, value: assetModel!.multiAssets!.first.assetNumber, showEmptyValue: true, copyValue: true),
+ InfoTextWidget(label: context.translation.modelName, value: assetModel!.modelDefinition!.modelName, showEmptyValue: true),
+ InfoTextWidget(label: context.translation.supplier, value: assetModel!.supplier?.suppliername, showEmptyValue: true),
+ InfoTextWidget(label: context.translation.manufacture, value: assetModel!.modelDefinition!.manufacturerName, showEmptyValue: true),
+ ],
+ ).expanded,
+ Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ InfoTextWidget(label: context.translation.snNo, value: assetModel!.multiAssets!.first.assetSerialNo, showEmptyValue: true),
+ InfoTextWidget(label: context.translation.site, value: assetModel!.site?.custName?.cleanupWhitespace.capitalizeFirstOfEach, showEmptyValue: true),
+ InfoTextWidget(label: context.translation.building, value: assetModel!.building?.name?.cleanupWhitespace.capitalizeFirstOfEach, showEmptyValue: true),
+ InfoTextWidget(label: context.translation.floor, value: assetModel!.floor?.name?.cleanupWhitespace.capitalizeFirstOfEach, showEmptyValue: true),
+ InfoTextWidget(label: context.translation.md, value: assetModel!.department?.departmentName?.cleanupWhitespace.capitalizeFirstOfEach, showEmptyValue: true),
+ InfoTextWidget(label: context.translation.room, value: assetModel!.room?.name?.cleanupWhitespace.capitalizeFirstOfEach, showEmptyValue: true),
+ ],
+ ).expanded,
],
- ).expanded,
- ],
+ ),
+ ),
+ ),
+ // 8.height,
+ // Divider with animation
+ FadeTransition(
+ opacity: datesAnimation,
+ child: const Divider().defaultStyle(context),
+ ),
+ // 8.height,
+ // Dates section with animation
+ FadeTransition(
+ opacity: datesAnimation,
+ child: SlideTransition(
+ position: datesSlideAnimation,
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ InfoTextWidget(label: context.translation.installationDate, value: assetModel?.installationDate?.toAssetDetailsFormat, showEmptyValue: true),
+ InfoTextWidget(label: context.translation.nextPmDate, value: assetModel?.nextPMDate?.toAssetDetailsFormat, showEmptyValue: true),
+ InfoTextWidget(label: context.translation.lastPmDate, value: assetModel?.lastPMDate?.toAssetDetailsFormat, showEmptyValue: true),
+ ],
+ ),
+ ),
),
- ),
- ),
- 8.height,
- // Divider with animation
- FadeTransition(
- opacity: datesAnimation,
- child: const Divider(color: AppColor.neutral30, height: 1, thickness: 1),
- ),
- 8.height,
+ // Description with animation (if exists)
+ if ((assetModel?.modelDefinition?.assetDescription ?? "").isNotEmpty) ...[
+ // 8.height,
+ FadeTransition(
+ opacity: descAnimation,
+ child: const Divider().defaultStyle(context),
+ ),
+ FadeTransition(
+ opacity: descAnimation,
+ child: SlideTransition(
+ position: descSlideAnimation,
+ child: InfoTextWidget(label: assetModel!.modelDefinition!.assetDescription!, showEmptyValue: true, isMsg: true),
+ ),
+ ),
+ ],
- // Dates section with animation
- FadeTransition(
- opacity: datesAnimation,
- child: SlideTransition(
- position: datesSlideAnimation,
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- InfoTextWidget(label: context.translation.installationDate, value: assetModel.installationDate?.toAssetDetailsFormat, showEmptyValue: true),
- InfoTextWidget(label: context.translation.nextPmDate, value: assetModel.nextPMDate?.toAssetDetailsFormat, showEmptyValue: true),
- InfoTextWidget(label: context.translation.lastPmDate, value: assetModel.lastPMDate?.toAssetDetailsFormat, showEmptyValue: true),
- ],
- ),
- ),
+ if (attachments.isNotEmpty) ...[
+ // 8.height,
+ FadeTransition(
+ opacity: attachmentAnimation,
+ child: const Divider().defaultStyle(context),
+ ),
+ FadeTransition(
+ opacity: attachmentAnimation,
+ child: SlideTransition(
+ position: attachmentSlideAnimation,
+ child: FilesList(images: attachments.map((toElement) => URLs.getFileUrl(toElement.name!) ?? '').toList()),
+ ),
+ ),
+ ]
+ ],
),
-
- // Description with animation (if exists)
- if ((assetModel.modelDefinition?.assetDescription ?? "").isNotEmpty) ...[
- 8.height,
- FadeTransition(
- opacity: descAnimation,
- child: const Divider().defaultStyle(context),
- ),
- FadeTransition(
- opacity: descAnimation,
- child: SlideTransition(
- position: descSlideAnimation,
- child: InfoTextWidget(label: assetModel.modelDefinition!.assetDescription!, showEmptyValue: true, isMsg: true),
- ),
- ),
- ]
],
- )
- ],
- ).toShadowContainer(context),
+ ).toShadowContainer(context),
+ ).expanded,
+ if (context.userProvider.isEngineer && !(assetModel!.hasTrainingImageData ?? true))
+ FooterActionButton.footerContainer(
+ context: context,
+ child: AppFilledButton(
+ buttonColor: AppColor.primary10,
+ label: "Upload Images",
+ onPressed: _upload,
+ ),
+ ),
+ ],
);
}
return const Center(child: ALoading());
@@ -323,4 +393,12 @@ class _AssetDetailPageState extends State with SingleTickerProv
),
);
}
+
+ void _upload() async {
+ bool reload = await Navigator.push(context, MaterialPageRoute(builder: (context) => AssetImageUploadPage(assetId: assetId!))) ?? false;
+ if (reload) {
+ assetModel = null;
+ setState(() {});
+ }
+ }
}
diff --git a/lib/views/widgets/equipment/asset_image_upload_page.dart b/lib/views/widgets/equipment/asset_image_upload_page.dart
new file mode 100644
index 00000000..33d48a62
--- /dev/null
+++ b/lib/views/widgets/equipment/asset_image_upload_page.dart
@@ -0,0 +1,251 @@
+import 'dart:convert';
+import 'dart:io';
+
+import 'package:flutter/cupertino.dart';
+import 'package:flutter/material.dart';
+import 'package:provider/provider.dart';
+import 'package:test_sa/controllers/providers/api/devices_provider.dart';
+import 'package:test_sa/extensions/context_extension.dart';
+import 'package:test_sa/extensions/text_extensions.dart';
+import 'package:test_sa/extensions/widget_extensions.dart';
+import 'package:test_sa/helper/utils.dart';
+import 'package:test_sa/models/device/asset_by_id_model.dart';
+import 'package:test_sa/models/generic_attachment_model.dart';
+import 'package:test_sa/modules/cm_module/cm_request_utils.dart';
+import 'package:test_sa/modules/cm_module/views/components/action_button/footer_action_button.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/views/full_screen_image_viewer.dart';
+import 'package:test_sa/views/widgets/dialogs/dialog.dart';
+import 'package:test_sa/views/widgets/images/multi_image_picker.dart';
+import 'package:test_sa/views/widgets/item_views/info_header_widget.dart';
+import 'package:test_sa/views/widgets/item_views/info_text_widget.dart';
+
+class AssetImageUploadPage extends StatefulWidget {
+ int assetId;
+ TrainingImageData? attachments;
+
+ AssetImageUploadPage({Key? key, required this.assetId, this.attachments}) : super(key: key);
+
+ @override
+ _AssetImageUploadPageState createState() {
+ return _AssetImageUploadPageState();
+ }
+}
+
+class _AssetImageUploadPageState extends State {
+ late TrainingImageData trainingImageData;
+
+ @override
+ void initState() {
+ super.initState();
+ trainingImageData = widget.attachments ?? TrainingImageData(additionalImages: []);
+ }
+
+ @override
+ void dispose() {
+ super.dispose();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ appBar: const DefaultAppBar(title: "Upload Images"),
+ body: Column(
+ children: [
+ ListView(
+ padding: const EdgeInsets.all(16),
+ children: [
+ InfoHeader16Widget("Instructions"),
+ InfoTextLabelWidget(
+ label:
+ "* Please upload all images of the sides of the asset as mentioned below.\n* Images should be clear and high quality.\n* Avoid uploading blurry, low-light or low-resolution images."),
+ GridView(
+ padding: const EdgeInsets.only(top: 16, bottom: 16),
+ shrinkWrap: true,
+ physics: const NeverScrollableScrollPhysics(),
+ gridDelegate:
+ SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: (MediaQuery.of(context).size.width < 550) ? 4 : 4, childAspectRatio: 1, crossAxisSpacing: 12, mainAxisSpacing: 12),
+ children: [
+ gridCard(
+ icon: "asset_image_upload/side_right",
+ title: "Right Side",
+ attachment: trainingImageData.rightImage,
+ onUpdate: (value) {
+ trainingImageData.rightImage = value;
+ setState(() {});
+ },
+ ),
+ gridCard(
+ icon: "asset_image_upload/side_left",
+ title: "Left Side",
+ attachment: trainingImageData.leftImage,
+ onUpdate: (value) {
+ trainingImageData.leftImage = value;
+ setState(() {});
+ },
+ ),
+ gridCard(
+ icon: "asset_image_upload/side_top",
+ title: "Top Side",
+ attachment: trainingImageData.upImage,
+ onUpdate: (value) {
+ trainingImageData.upImage = value;
+ setState(() {});
+ },
+ ),
+ gridCard(
+ icon: "asset_image_upload/side_bottom",
+ title: "Bottom Side",
+ attachment: trainingImageData.downImage,
+ onUpdate: (value) {
+ trainingImageData.downImage = value;
+ setState(() {});
+ },
+ ),
+ ],
+ ),
+ AttachmentPicker(
+ label: "Additional Images",
+ pickerTitle: "Attach Images",
+ attachment: trainingImageData.additionalImages!,
+ buttonColor: AppColor.black10,
+ onlyImages: true,
+ pickMultiple: true,
+ // showAsGrid: true,
+ buttonIcon: 'image-plus'.toSvgAsset(color: AppColor.primary10),
+ onChange: (_attachments) {
+ trainingImageData.additionalImages = _attachments;
+ setState(() {});
+ },
+ ).toShadowContainer(context),
+ ],
+ ).expanded,
+ FooterActionButton.footerContainer(
+ context: context,
+ child: AppFilledButton(
+ buttonColor: AppColor.primary10,
+ disableButton: trainingImageData.leftImage == null || trainingImageData.rightImage == null || trainingImageData.upImage == null || trainingImageData.downImage == null,
+ label: "Upload",
+ onPressed: () async {
+ bool result = await showDialog(
+ context: context,
+ builder: (_) => AAlertDialog(
+ title: context.translation.confirm,
+ content: "I followed all the instructions and uploading the images in high quality, clear and not blurry.",
+ ),
+ );
+ if (result) {
+ Utils.showLoadingWithTextDialog(context);
+ result = await Provider.of(context, listen: false).uploadAssetImages(widget.assetId, trainingImageData);
+ Utils.hideLoading(context);
+ if (result) {
+ Navigator.pop(context, result);
+ }
+ }
+ },
+ ),
+ ),
+ ],
+ ));
+ }
+
+ Widget gridCard({
+ required String icon,
+ required String title,
+ required GenericAttachmentModel? attachment,
+ required Function(GenericAttachmentModel?) onUpdate,
+ }) {
+ return Stack(
+ alignment: AlignmentDirectional.topEnd,
+ children: [
+ Positioned.fill(
+ child: AttachmentPicker(
+ label: "",
+ pickerTitle: title,
+ onlyImages: true,
+ checkQuality: true,
+ enabled: attachment == null,
+ attachment: attachment == null ? [] : [attachment],
+ buttonIcon: 'image-plus'.toSvgAsset(color: AppColor.primary10),
+ onChange: (_attachments) {
+ if (_attachments.isNotEmpty) {
+ onUpdate(_attachments.first);
+ } else {
+ onUpdate(null);
+ }
+ },
+ child: imageAngleCard(icon, title, attachment),
+ ).toShadowContainer(context, padding: 0),
+ ),
+ if (attachment != null)
+ Positioned(
+ top: 4,
+ right: 4,
+ child: IconButton(
+ padding: EdgeInsets.zero,
+ icon: const Icon(Icons.clear),
+ iconSize: 18,
+ style: IconButton.styleFrom(elevation: 2, tapTargetSize: MaterialTapTargetSize.shrinkWrap, backgroundColor: AppColor.red30, foregroundColor: Colors.white),
+ visualDensity: VisualDensity.compact,
+ constraints: const BoxConstraints(),
+ onPressed: () {
+ onUpdate(null);
+ },
+ )),
+ ],
+ );
+ }
+
+ Widget imageAngleCard(String icon, String title, GenericAttachmentModel? attachment) {
+ if (attachment != null) {
+ Widget imageWidget = _getImageWidget(attachment.name!);
+ return ClipRRect(borderRadius: BorderRadius.circular(12), child: imageWidget.onPress(() => context.fullScreenImageViewer(imageWidget)));
+ }
+ return Column(
+ mainAxisAlignment: MainAxisAlignment.center,
+ crossAxisAlignment: CrossAxisAlignment.center,
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ icon.toSvgAsset(height: 50, width: 50),
+ Text(
+ title,
+ style: AppTextStyles.bodyText2.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
+ ),
+ ],
+ );
+ }
+
+ Widget _getImageWidget(String imageUrl) {
+ // Check if it's base64 encoded (contains | separator)
+ if (imageUrl.contains('|')) {
+ try {
+ final base64Data = imageUrl.split('|').last;
+ return Image.memory(
+ base64Decode(base64Data),
+ fit: BoxFit.cover,
+ );
+ } catch (e) {
+ return const Icon(Icons.broken_image, size: 48);
+ }
+ }
+
+ // Check if it's a local file path
+ if (CMRequestUtils.isLocalUrl(imageUrl)) {
+ return Image.file(
+ File(imageUrl),
+ fit: BoxFit.cover,
+ );
+ }
+
+ // Otherwise treat as network URL
+ return Image.network(
+ imageUrl,
+ fit: BoxFit.cover,
+ errorBuilder: (context, error, stackTrace) {
+ return const Icon(Icons.broken_image, size: 48);
+ },
+ );
+ }
+}
diff --git a/lib/views/widgets/equipment/asset_item_gridview.dart b/lib/views/widgets/equipment/asset_item_gridview.dart
index 4947d46d..8c10be02 100644
--- a/lib/views/widgets/equipment/asset_item_gridview.dart
+++ b/lib/views/widgets/equipment/asset_item_gridview.dart
@@ -13,7 +13,7 @@ class AssetItemGridView extends StatelessWidget {
final Asset device;
final Function(Asset) onPressed;
- const AssetItemGridView({Key? key,required this.device,required this.onPressed}) : super(key: key);
+ const AssetItemGridView({Key? key, required this.device, required this.onPressed}) : super(key: key);
@override
Widget build(BuildContext context) {
@@ -44,6 +44,13 @@ class AssetItemGridView extends StatelessWidget {
overflow: TextOverflow.ellipsis,
style: AppTextStyles.bodyText.copyWith(color: AppColor.textStyleColor(context)),
),
+ if (context.userProvider.isEngineer && !(device.hasTrainingImageData ?? true)) ...[
+ 2.height,
+ Text(
+ '*Upload Images for this asset',
+ style: AppTextStyles.tinyFont2.copyWith(color: AppColor.red30),
+ ),
+ ],
Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
diff --git a/lib/views/widgets/equipment/asset_item_listview.dart b/lib/views/widgets/equipment/asset_item_listview.dart
index 6fced692..73c9187b 100644
--- a/lib/views/widgets/equipment/asset_item_listview.dart
+++ b/lib/views/widgets/equipment/asset_item_listview.dart
@@ -44,6 +44,13 @@ class AssetItemListView extends StatelessWidget {
children: [
InfoHeaderWidget(device.modelDefinition!.assetName!.cleanupWhitespace),
// device.modelDefinition!.assetName!.cleanupWhitespace.capitalizeFirstOfEach.heading6(context),
+ if (context.userProvider.isEngineer && !(device.hasTrainingImageData ?? true)) ...[
+ 2.height,
+ Text(
+ '*Upload Images for this asset',
+ style: AppTextStyles.tinyFont2.copyWith(color: AppColor.red30),
+ ),
+ ],
4.height,
InfoTextWidget(label: context.translation.assetNumber, value: device.assetNumber),
InfoTextWidget(label: context.translation.modelName, value: device.modelDefinition!.modelName),
diff --git a/lib/views/widgets/equipment/my_assets_page.dart b/lib/views/widgets/equipment/my_assets_page.dart
index 92a168a8..37df435b 100644
--- a/lib/views/widgets/equipment/my_assets_page.dart
+++ b/lib/views/widgets/equipment/my_assets_page.dart
@@ -1,3 +1,5 @@
+import 'dart:io';
+
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
@@ -97,7 +99,7 @@ class _MyAssetsPageState extends State with SingleTickerProviderSt
mainAxisAlignment: MainAxisAlignment.center,
children: [
if (!widget.fromBottomBar)
- const Icon(Icons.arrow_back_ios).onPress(() {
+ Icon(Platform.isIOS ? Icons.arrow_back_ios : Icons.arrow_back).onPress(() {
Navigator.of(context).pop();
}),
Container(
@@ -122,20 +124,28 @@ class _MyAssetsPageState extends State with SingleTickerProviderSt
],
),
).onPress(() async {
- final result = await Navigator.push(context, MaterialPageRoute(builder: (context) => const DeviceSearchScreen()));
+ final result = await Navigator.push(context, CupertinoPageRoute(fullscreenDialog: true, builder: (context) => const DeviceSearchScreen()));
if (result != null) {
_searchAsset = result;
}
_searchableList.clear();
_searchableList.addAll(_devicesProvider.devices);
}).expanded,
- 16.width,
- Icon(Icons.grid_view_outlined, color: AppColor.icon2Color(context)).onPress(() => setState(() {
- showListView = !showListView;
- })),
+ 12.width,
+ IconButton(
+ icon: Icon(!showListView ? Icons.view_list_sharp : Icons.grid_view_outlined, color: AppColor.icon2Color(context)),
+ padding: EdgeInsets.zero,
+ iconSize: 20,
+ visualDensity: VisualDensity.compact,
+ tooltip: !showListView ? "View as List" : "View as Grid",
+ onPressed: () => setState(() {
+ showListView = !showListView;
+ }),
+ ),
IconButton(
icon: "download".toSvgAsset(height: 24, width: 24, color: AppColor.icon2Color(context)),
padding: EdgeInsets.zero,
+ visualDensity: VisualDensity.compact,
tooltip: "Export",
onPressed: () async {
await Navigator.push(
@@ -154,9 +164,10 @@ class _MyAssetsPageState extends State with SingleTickerProviderSt
IconButton(
icon: "filter".toSvgAsset(height: 24, width: 24, color: AppColor.icon2Color(context)),
padding: EdgeInsets.zero,
+ visualDensity: VisualDensity.compact,
tooltip: "Filter",
onPressed: () async {
- final result = await Navigator.push(context, CupertinoPageRoute(builder: (context) => DeviceFilterScreen(data: _searchAsset)));
+ final result = await Navigator.push(context, CupertinoPageRoute(fullscreenDialog: true, builder: (context) => DeviceFilterScreen(data: _searchAsset)));
if (result != null) {
_searchAsset = result;
}
@@ -165,7 +176,7 @@ class _MyAssetsPageState extends State with SingleTickerProviderSt
},
),
],
- ).paddingOnly(start: 16, end: 16),
+ ).paddingOnly(start: 16, end: 8),
),
body: SafeArea(
child: LoadingManager(
@@ -305,7 +316,7 @@ class _MyAssetsPageState extends State with SingleTickerProviderSt
floatingActionButton: FloatingActionButton(
heroTag: "some tag 2",
backgroundColor: AppColor.primary10,
- child: "qr".toSvgAsset(height: 32, fit: BoxFit.fitHeight, color: AppColor.background(context)),
+ child: Icon(Icons.qr_code_2_rounded, size: 40, color: AppColor.addItemButtonColor(context)),
onPressed: () async {
String? result = await Navigator.of(context).push(
MaterialPageRoute(builder: (_) => const ScanQr()),
diff --git a/lib/views/widgets/equipment/single_device_picker.dart b/lib/views/widgets/equipment/single_device_picker.dart
new file mode 100644
index 00000000..e69de29b
diff --git a/lib/views/widgets/fullscreen_dialogs/multiple_selection_fullscreen_dialog.dart b/lib/views/widgets/fullscreen_dialogs/multiple_selection_fullscreen_dialog.dart
index 5adeb69e..c07d2870 100644
--- a/lib/views/widgets/fullscreen_dialogs/multiple_selection_fullscreen_dialog.dart
+++ b/lib/views/widgets/fullscreen_dialogs/multiple_selection_fullscreen_dialog.dart
@@ -7,6 +7,7 @@ import 'package:test_sa/models/base.dart';
import 'package:test_sa/modules/cm_module/views/components/action_button/footer_action_button.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';
typedef SelectionBuilderString = String Function(dynamic);
@@ -61,8 +62,9 @@ class _SelectionBottomSheetState extends State extends State Scaffold(
- body: SafeArea(
- child: Stack(
- children: [
- // InteractiveViewer(child: Image(image: getImageObject(itemIndex))).center,
- InteractiveViewer(child: getImageWidget(itemIndex)).center,
- const ABackButton(),
- ],
- ),
- ),
- ),
- ),
- );
+ context.fullScreenImageViewer(getImageWidget(itemIndex));
} else if (_isLocalUrl(images[itemIndex])) {
OpenFile.open(images[itemIndex]);
} else {
@@ -162,21 +149,7 @@ class FilesList extends StatelessWidget {
),
).onPress(() async {
if (isImage) {
- Navigator.of(context).push(
- MaterialPageRoute(
- builder: (_) => Scaffold(
- body: SafeArea(
- child: Stack(
- children: [
- // InteractiveViewer(child: Image(image: getImageObject(itemIndex))).center,
- InteractiveViewer(child: getImageWidget(itemIndex)).center,
- const ABackButton(),
- ],
- ),
- ),
- ),
- ),
- );
+ context.fullScreenImageViewer(getImageWidget(itemIndex));
} else if (_isLocalUrl(images[itemIndex])) {
OpenFile.open(images[itemIndex]);
} else {
@@ -192,59 +165,6 @@ class FilesList extends StatelessWidget {
});
},
);
-
- // return ListView.separated(
- // padding: padding ?? EdgeInsets.symmetric(horizontal: 32 * AppStyle.getScaleFactor(context)),
- // scrollDirection: Axis.horizontal,
- // itemCount: images?.length ?? 0,
- // separatorBuilder: (context, itemIndex) => 8.width,
- // itemBuilder: (context, itemIndex) {
- // if (images[itemIndex] == null || !images[itemIndex].contains(".")) {
- // return Text("Bad\nFile");
- // }
- // var isImage =
- // images[itemIndex].split(".").last.toLowerCase() == "png" || images[itemIndex].split(".").last.toLowerCase() == "jpg" || images[itemIndex].split(".").last.toLowerCase() == "jpeg";
- // var isPdf = images[itemIndex].split(".").last.toLowerCase() == "pdf";
- // var isExcel = images[itemIndex].split(".").last.toLowerCase() == "xlsx";
- //
- // return (isImage
- // ? (_isLocalUrl(images[itemIndex])
- // ? Image.file(File(images[itemIndex]))
- // : ImageLoader(
- // url: images[itemIndex],
- // boxFit: BoxFit.cover,
- // ))
- // : Image.asset("assets/images/${isPdf ? "pdf" : isExcel ? "excel" : "doc"}.png"))
- // .onPress(() async {
- // if (isImage) {
- // Navigator.of(context).push(
- // MaterialPageRoute(
- // builder: (_) => Scaffold(
- // body: SafeArea(
- // child: Stack(
- // children: [
- // InteractiveViewer(child: Image(image: (_isLocalUrl(images[itemIndex]) ? FileImage(File(images[itemIndex])) : NetworkImage(images[itemIndex])))).center,
- // const ABackButton(),
- // ],
- // ),
- // ),
- // ),
- // ),
- // );
- // } else if (_isLocalUrl(images[itemIndex])) {
- // OpenFile.open(images[itemIndex]);
- // } else {
- // try {
- // if (!await launchUrl(Uri.parse(images[itemIndex]), mode: LaunchMode.externalApplication)) {
- // Fluttertoast.showToast(msg: "UnExpected Error with file.");
- // throw Exception('Could not launch ');
- // }
- // } catch (ex) {
- // Fluttertoast.showToast(msg: "No Viewer found.");
- // }
- // }
- // });
- // });
}
Widget getImageWidget(int itemIndex) {
diff --git a/lib/views/widgets/images/multi_image_picker.dart b/lib/views/widgets/images/multi_image_picker.dart
index 582bc6ea..a0533210 100644
--- a/lib/views/widgets/images/multi_image_picker.dart
+++ b/lib/views/widgets/images/multi_image_picker.dart
@@ -3,11 +3,13 @@ import 'dart:io';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
+import 'package:image_blur_detection/image_blur_detection.dart';
import 'package:image_picker/image_picker.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
+import 'package:test_sa/helper/utils.dart';
import 'package:test_sa/models/generic_attachment_model.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
@@ -15,280 +17,6 @@ import 'package:test_sa/new_views/app_style/app_color.dart';
import '../../../new_views/common_widgets/app_dashed_button.dart';
import 'multi_image_picker_item.dart';
-// class MultiFilesPicker extends StatefulWidget {
-// final String label;
-// final bool error;
-// final List files;
-// final List attachment;
-//
-// final bool enabled, onlyImages;
-// double? buttonHeight;
-// Widget? buttonIcon;
-// Color? buttonColor;
-// final Function(List)? onChange;
-// final bool showAsGrid;
-//
-// MultiFilesPicker(
-// {Key? key,
-// this.files = const [],
-// this.attachment = const [],
-// required this.label,
-// this.error = false,
-// this.buttonHeight,
-// this.buttonIcon,
-// this.enabled = true,
-// this.onlyImages = false,
-// this.onChange,
-// this.showAsGrid = false,
-// this.buttonColor})
-// : super(key: key);
-//
-// @override
-// State createState() => _MultiFilesPickerState();
-// }
-//
-// class _MultiFilesPickerState extends State {
-// @override
-// Widget build(BuildContext context) {
-// return Column(
-// crossAxisAlignment: CrossAxisAlignment.start,
-// children: [
-// if (widget.enabled) ...[
-// AppDashedButton(
-// title: widget.label,
-// height: widget.buttonHeight,
-// buttonColor: widget.buttonColor,
-// icon: widget.buttonIcon,
-// onPressed: (widget.enabled == false)
-// ? () {}
-// : widget.showAsGrid
-// ? showFileSourceSheet
-// : onFilePicker),
-// 16.height,
-// ],
-// if (widget.files.isNotEmpty)
-// Wrap(
-// spacing: 8.toScreenWidth,
-// children: List.generate(
-// widget.files!.length,
-// (index) {
-// File image = widget.files![index];
-// return MultiFilesPickerItem(
-// file: image,
-// enabled: widget.enabled,
-// onRemoveTap: (image) {
-// if (!widget.enabled) {
-// return;
-// }
-// widget.files.remove(image);
-// if (widget.onChange != null) {
-// widget.onChange!(widget.files);
-// }
-// setState(() {});
-// },
-// );
-// },
-// ),
-// ),
-// ],
-// );
-// }
-//
-// fromFilePicker() async {
-// FilePickerResult? result = await FilePicker.platform.pickFiles(
-// type: FileType.custom,
-// allowMultiple: true,
-// allowedExtensions: widget.onlyImages ? ['jpg', 'jpeg', 'png'] : ['jpg', 'jpeg', 'png', 'pdf', 'doc', 'docx', 'xlsx', 'pptx'],
-// );
-// if (result != null) {
-// for (var path in result.paths) {
-// widget.files.add(File(path!));
-// if (widget.onChange != null) {
-// widget.onChange!(widget.files);
-// }
-// }
-// setState(() {});
-// }
-// }
-//
-// void showFileSourceSheet() async {
-// if (widget.files.length >= 5) {
-// Fluttertoast.showToast(msg: context.translation.maxImagesNumberIs5);
-// return;
-// }
-//
-// ImageSource? source = (await showModalBottomSheet(
-// context: context,
-// shape: const RoundedRectangleBorder(
-// borderRadius: BorderRadius.vertical(
-// top: Radius.circular(20),
-// ),
-// ),
-// clipBehavior: Clip.antiAliasWithSaveLayer,
-// builder: (BuildContext context) => Column(
-// mainAxisSize: MainAxisSize.min,
-// crossAxisAlignment: CrossAxisAlignment.start,
-// children: [
-// "Attach File".heading4(context),
-// 12.height,
-// GridView(
-// padding: const EdgeInsets.all(0),
-// shrinkWrap: true,
-// physics: const NeverScrollableScrollPhysics(),
-// gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3, childAspectRatio: 1, crossAxisSpacing: 12, mainAxisSpacing: 12),
-// children: [
-// gridItem(Icons.camera_enhance_rounded, context.translation.pickFromCamera).onPress(() => Navigator.of(context).pop(ImageSource.camera)),
-// gridItem(Icons.image_rounded, context.translation.pickFromGallery).onPress(() => Navigator.of(context).pop(ImageSource.gallery)),
-// gridItem(Icons.file_present_rounded, context.translation.pickFromFiles).onPress(() async {
-// await fromFilePicker();
-// Navigator.pop(context);
-// }),
-// ],
-// ),
-// 12.height,
-// ],
-// ).paddingAll(21),
-// )) as ImageSource?;
-// if (source == null) return;
-// final pickedFile = await ImagePicker().pickImage(source: source, imageQuality: 70, maxWidth: 800, maxHeight: 800);
-//
-// if (pickedFile != null) {
-// File fileImage = File(pickedFile.path);
-// widget.files.add(fileImage);
-// if (widget.onChange != null) {
-// widget.onChange!(widget.files);
-// }
-// setState(() {});
-// }
-// }
-//
-// Widget gridItem(IconData iconData, String title) {
-// return Container(
-// padding: const EdgeInsets.all(12),
-// decoration: BoxDecoration(
-// color: Colors.white,
-// borderRadius: BorderRadius.circular(12),
-// border: Border.all(color: const Color(0xffF1F1F1), width: 1),
-// ),
-// child: Column(
-// crossAxisAlignment: CrossAxisAlignment.start,
-// mainAxisAlignment: MainAxisAlignment.spaceBetween,
-// children: [
-// Icon(iconData, color: const Color(0xff7D859A), size: 36),
-// Text(
-// title,
-// style: const TextStyle(fontSize: 12, fontWeight: FontWeight.w500),
-// ),
-// ],
-// ),
-// );
-// }
-//
-// onFilePicker() async {
-// if (widget.files.length >= 5) {
-// Fluttertoast.showToast(msg: context.translation.maxImagesNumberIs5);
-// return;
-// }
-// ImageSource? source = await showModalBottomSheet(
-// context: context,
-// builder: (BuildContext context) {
-// Widget listCard({required String icon, required String label, required VoidCallback onTap}) {
-// return GestureDetector(
-// onTap: onTap,
-// child: Container(
-// constraints: BoxConstraints(minWidth: 111.toScreenWidth, minHeight: 111.toScreenHeight),
-// padding: EdgeInsets.symmetric(horizontal: 12.toScreenWidth, vertical: 12.toScreenHeight),
-// decoration: BoxDecoration(borderRadius: BorderRadius.circular(12), border: Border.all(width: 1, color: AppColor.white70)),
-// child: Column(
-// mainAxisSize: MainAxisSize.min,
-// crossAxisAlignment: CrossAxisAlignment.start,
-// children: [
-// icon.toSvgAsset(),
-// 24.height,
-// label.bodyText2(context).custom(color: AppColor.black20),
-// ],
-// ),
-// ),
-// );
-// }
-//
-// return Container(
-// padding: const EdgeInsets.all(16.0),
-// child: Row(
-// mainAxisAlignment: MainAxisAlignment.spaceBetween,
-// children: [
-// listCard(
-// icon: 'camera_icon',
-// label: '${context.translation.open}\n${context.translation.camera}',
-// onTap: () {
-// Navigator.of(context).pop(ImageSource.camera);
-// },
-// ),
-// listCard(
-// icon: 'gallery_icon',
-// label: '${context.translation.open}\n${context.translation.gallery}',
-// onTap: () {
-// Navigator.of(context).pop(ImageSource.gallery);
-// },
-// ),
-// listCard(
-// icon: 'file_icon',
-// label: '${context.translation.open}\n${context.translation.files}',
-// onTap: () async {
-// await fromFilePicker();
-// Navigator.pop(context);
-// },
-// ),
-// ],
-// ),
-// );
-// },
-// );
-// // ImageSource source = await showDialog(
-// // context: context,
-// // builder: (dialogContext) => CupertinoAlertDialog(
-// // actions: [
-// // TextButton(
-// // child: Text(context.translation.pickFromCamera),
-// // onPressed: () {
-// // Navigator.of(dialogContext).pop(ImageSource.camera);
-// // },
-// // ),
-// // TextButton(
-// // child: Text(context.translation.pickFromGallery),
-// // onPressed: () {
-// // Navigator.of(dialogContext).pop(ImageSource.gallery);
-// // },
-// // ),
-// // TextButton(
-// // child: Text(context.translation.pickFromFiles),
-// // onPressed: () async {
-// // await fromFilePicker();
-// // Navigator.pop(context);
-// // },
-// // ),
-// // ],
-// // ),
-// // );
-// if (source == null) return;
-//
-// final pickedFile = await ImagePicker().pickImage(source: source, imageQuality: 70, maxWidth: 800, maxHeight: 800);
-//
-// if (pickedFile != null) {
-// File fileImage = File(pickedFile.path);
-// if (fileImage != null) {
-// widget.files.add(fileImage);
-// if (widget.onChange != null) {
-// widget.onChange!(widget.files);
-// }
-// setState(() {});
-// }
-// }
-//
-// setState(() {});
-// }
-// }
-
class AttachmentModel {
int id = 0;
File? file;
@@ -311,6 +39,7 @@ class AttachmentModel {
}
class AttachmentPicker extends StatefulWidget {
+ final String pickerTitle;
final String label;
final bool error;
final List attachment;
@@ -320,14 +49,17 @@ class AttachmentPicker extends StatefulWidget {
Widget? buttonIcon;
Color? buttonColor;
final Function(List)? onChange;
- final bool showAsGrid;
final bool showAsListView;
+ final bool pickMultiple;
Lookup? documentType;
+ Widget? child;
+ bool checkQuality;
AttachmentPicker(
{Key? key,
this.attachment = const [],
required this.label,
+ this.pickerTitle = "Attach File",
this.error = false,
this.buttonHeight,
this.buttonIcon,
@@ -335,8 +67,10 @@ class AttachmentPicker extends StatefulWidget {
this.onlyImages = false,
this.onChange,
this.documentType,
- this.showAsGrid = false,
this.showAsListView = false,
+ this.pickMultiple = false,
+ this.checkQuality = false,
+ this.child,
this.buttonColor})
: super(key: key);
@@ -344,75 +78,91 @@ class AttachmentPicker extends StatefulWidget {
State createState() => _AttachmentPickerState();
}
-class _AttachmentPickerState extends State {
+class _AttachmentPickerState extends State with SingleTickerProviderStateMixin {
+ late AnimationController _animationController;
+
+ @override
+ void initState() {
+ super.initState();
+ _animationController = AnimationController(
+ duration: const Duration(milliseconds: 1200),
+ vsync: this,
+ );
+ _animationController.forward();
+ }
+
+ @override
+ void dispose() {
+ _animationController.dispose();
+ super.dispose();
+ }
+
@override
Widget build(BuildContext context) {
- return Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- AppDashedButton(
- title: widget.label,
- height: widget.buttonHeight,
- buttonColor: widget.buttonColor,
- icon: widget.buttonIcon,
- onPressed: (widget.enabled == false)
- ? () {}
- : widget.showAsGrid
- ? showFileSourceSheet
- : onFilePicker),
- 16.height,
- if (widget.attachment.isNotEmpty)
- widget.showAsListView
- ? ListView.separated(
- shrinkWrap: true,
- physics: const NeverScrollableScrollPhysics(),
- padding: EdgeInsets.zero,
- itemBuilder: (cxt, index) {
- File image = File(widget.attachment[index].name!);
- return MultiFilesPickerItem(
- file: image,
- showAsListView: widget.showAsListView,
- enabled: widget.enabled,
- documentType: widget.attachment[index].documentTypeId?.name,
- onRemoveTap: (image) {
- if (!widget.enabled) {
- return;
- }
- widget.attachment.removeAt(index);
- if (widget.onChange != null) {
- widget.onChange!(widget.attachment);
- }
- setState(() {});
- },
- );
- },
- separatorBuilder: (cxt, index) => 8.height,
- itemCount: widget.attachment.length)
- : Wrap(
- spacing: 8.toScreenWidth,
- children: List.generate(
- widget.attachment.length,
- (index) {
- File image = File(widget.attachment[index].name!);
- return MultiFilesPickerItem(
- file: image,
- enabled: widget.enabled,
- onRemoveTap: (image) {
- if (!widget.enabled) {
- return;
- }
- widget.attachment.removeAt(index);
- if (widget.onChange != null) {
- widget.onChange!(widget.attachment);
- }
- setState(() {});
+ return widget.child != null
+ ? widget.child!.onPress((widget.enabled == false) ? () {} : () => onFilePicker(widget.checkQuality))
+ : Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ spacing: 12,
+ children: [
+ AppDashedButton(
+ title: widget.label,
+ height: widget.buttonHeight,
+ buttonColor: widget.buttonColor,
+ icon: widget.buttonIcon,
+ onPressed: (widget.enabled == false) ? () {} : () => onFilePicker(widget.checkQuality)),
+ if (widget.attachment.isNotEmpty)
+ widget.showAsListView
+ ? ListView.separated(
+ shrinkWrap: true,
+ physics: const NeverScrollableScrollPhysics(),
+ padding: const EdgeInsets.only(top: 0),
+ itemBuilder: (cxt, index) {
+ File image = File(widget.attachment[index].name!);
+ return MultiFilesPickerItem(
+ file: image,
+ showAsListView: widget.showAsListView,
+ enabled: widget.enabled,
+ documentType: widget.attachment[index].documentTypeId?.name,
+ onRemoveTap: (image) {
+ if (!widget.enabled) {
+ return;
+ }
+ widget.attachment.removeAt(index);
+ if (widget.onChange != null) {
+ widget.onChange!(widget.attachment);
+ }
+ setState(() {});
+ },
+ );
},
- );
- },
- ),
- ),
- ],
- );
+ separatorBuilder: (cxt, index) => 8.height,
+ itemCount: widget.attachment.length)
+ : Wrap(
+ spacing: 8.toScreenWidth,
+ children: List.generate(
+ widget.attachment.length,
+ (index) {
+ File image = File(widget.attachment[index].name!);
+ return MultiFilesPickerItem(
+ file: image,
+ enabled: widget.enabled,
+ onRemoveTap: (image) {
+ if (!widget.enabled) {
+ return;
+ }
+ widget.attachment.removeAt(index);
+ if (widget.onChange != null) {
+ widget.onChange!(widget.attachment);
+ }
+ setState(() {});
+ },
+ );
+ },
+ ),
+ ).paddingOnly(top: 0),
+ ],
+ );
}
fromFilePicker() async {
@@ -432,52 +182,6 @@ class _AttachmentPickerState extends State