From 50c1e9be84acc486c35fc70f9d861a70c5c68d8f Mon Sep 17 00:00:00 2001 From: Mohammad Salameh Date: Wed, 24 Apr 2024 00:18:00 +0300 Subject: [PATCH] Added Unlocking Records page --- .../view/widgets/smart_door/door_grid.dart | 3 +- .../smart_door/unlocking_records_view.dart | 318 ++++++++++++++++++ 2 files changed, 320 insertions(+), 1 deletion(-) create mode 100644 lib/features/devices/view/widgets/smart_door/unlocking_records_view.dart diff --git a/lib/features/devices/view/widgets/smart_door/door_grid.dart b/lib/features/devices/view/widgets/smart_door/door_grid.dart index f739291..70fe7b8 100644 --- a/lib/features/devices/view/widgets/smart_door/door_grid.dart +++ b/lib/features/devices/view/widgets/smart_door/door_grid.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; +import 'package:syncrow_app/features/devices/view/widgets/smart_door/unlocking_records_view.dart'; import 'package:syncrow_app/features/shared_widgets/default_container.dart'; import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart'; import 'package:syncrow_app/generated/assets.dart'; @@ -67,7 +68,7 @@ List> doorLockButtons = [ { 'title': 'Unlocking Records', 'image': Assets.doorlockAssetsUnlockingRecords, - 'page': null, + 'page': const UnlockingRecordsView(), }, { 'title': 'Memebers Managment', diff --git a/lib/features/devices/view/widgets/smart_door/unlocking_records_view.dart b/lib/features/devices/view/widgets/smart_door/unlocking_records_view.dart new file mode 100644 index 0000000..0548563 --- /dev/null +++ b/lib/features/devices/view/widgets/smart_door/unlocking_records_view.dart @@ -0,0 +1,318 @@ +// ignore_for_file: constant_identifier_names + +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/widgets.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:syncrow_app/features/shared_widgets/defaukt_scaffold.dart'; +import 'package:syncrow_app/features/shared_widgets/default_container.dart'; +import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart'; +import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart'; +import 'package:syncrow_app/generated/assets.dart'; +import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; + +class UnlockingRecordsView extends StatelessWidget { + const UnlockingRecordsView({super.key}); + + @override + Widget build(BuildContext context) { + List>> sortedRecords = + sortRecordsByDate(unlockingRecords); + return DefaultScaffold( + title: 'Unlocking Records', + child: SingleChildScrollView( + child: Column( + children: [ + for (var records in sortedRecords) + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.symmetric(vertical: 10), + child: BodyMedium( + fontWeight: FontWeight.bold, + fontColor: Colors.grey, + text: + '${records[0]['day']} ${formatDate(DateTime.parse(records[0]['date'].toString()))}'), + ), + DefaultContainer( + padding: const EdgeInsets.symmetric( + horizontal: 20, vertical: 10), + child: Column( + children: [ + for (int i = 0; i < records.length; i++) + Column( + children: [ + Row( + children: [ + SizedBox.square( + dimension: 30, + child: records[i]['method'] == + UnlockingMethod.Fingerprint + ? SvgPicture.asset(Assets + .unlockingMethodsIconsFingerprint) + : records[i]['method'] == + UnlockingMethod.Remote + ? SvgPicture.asset(Assets + .unlockingMethodsIconsRemote) + : SvgPicture.asset(Assets + .unlockingMethodsIconsFace), + ), + const SizedBox( + width: 13, + ), + Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + BodyMedium( + text: records[i]['title'], + ), + BodySmall( + fontColor: Colors.grey, + text: formatTime( + records[i]['time'], + ), + ), + ], + ) + ], + ), + i != records.length - 1 + ? Padding( + padding: const EdgeInsets.only( + top: 10, + bottom: 10, + right: 15, + left: 40), + child: Container( + height: 1, + color: ColorsManager.greyColor, + ), + ) + : const SizedBox.shrink(), + ], + ), + ], + )) + ], + ), + ], + ), + ), + ); + } + + String formatDate(DateTime date) { + return '${date.year}/${date.month.toString().padLeft(2, '0')}/${date.day.toString().padLeft(2, '0')}'; + } + + //time from 1200 to 12:00 + String formatTime(int time) { + return '${(time / 100).floor()}:${(time % 100).toString().padLeft(2, '0')}'; + } + + /// Sorts the given [records] by date and returns a nested list of records grouped by date. + /// + /// The [records] parameter is a list of maps, where each map represents a record with a 'date' key. + /// The records are sorted in ascending order based on the 'date' value. + /// The returned nested list contains sublists, where each sublist represents records for a specific date. + /// + /// Example usage: + /// ```dart + /// List> records = [ + /// {'date': '2022-01-01', 'data': 'Record 1'}, + /// {'date': '2022-01-02', 'data': 'Record 2'}, + /// {'date': '2022-01-01', 'data': 'Record 3'}, + /// ]; + /// + /// List>> sortedRecords = sortRecordsByDate(records); + /// print(sortedRecords); + /// ``` + /// This Dart function, sortRecordsByDate, takes a list of records as input, + /// where each record is a map with string keys and dynamic values. The + /// function's purpose is to sort these records by date and return a list of + /// lists, where each sublist contains records for a specific date. +// The function begins by initializing two empty lists: sortedRecords and dates. +// The sortedRecords list will eventually hold the sorted records, while the +//dates list will hold all unique dates present in the records. + +// The first for loop iterates over each record in the input list. For each +//record, it parses the 'date' field into a DateTime object and checks if this +//date is already in the dates list. If the date is not already in the list, it +// is added. This way, the dates list ends up holding all unique dates present +//in the records. + +// Next, the dates list is sorted in ascending order using the sort method with +// a comparator function that compares two DateTime objects. + +// The second for loop iterates over each unique date. For each date, it +//initializes an empty list recordsForDate to hold all records for that date. +// It then iterates over each record in the input list again. If a record's +//ate matches the current date (i.e., their comparison result is 0), the record +// is added to recordsForDate. After all records have been checked, r +//ecordsForDate is added to sortedRecords. + +// Finally, the function returns sortedRecords, which is a list of lists of +//records, where each sublist contains all records for a specific date, and the +//sublists are sorted in ascending order of date. + List>> sortRecordsByDate( + List> records) { + List>> sortedRecords = []; + List dates = []; + for (var record in records) { + if (!dates.contains(DateTime.parse(record['date'].toString()))) { + dates.add(DateTime.parse(record['date'].toString())); + } + } + dates.sort((a, b) => a.compareTo(b)); + for (var date in dates) { + List> recordsForDate = []; + for (var record in records) { + if (DateTime.parse(record['date'].toString()).compareTo(date) == 0) { + recordsForDate.add(record); + } + } + sortedRecords.add(recordsForDate); + } + return sortedRecords; + } +} + +enum UnlockingMethod { + Fingerprint, + Password, + Card, + Face, + Remote, +} + +List> unlockingRecords = [ + { + 'title': "XXX Fingerprint", + 'time': 1200, + 'date': 20240305, + 'day': 'Tuesday', + 'method': UnlockingMethod.Fingerprint, + }, + { + 'title': "XXX Face", + 'time': 1200, + 'date': 20240305, + 'day': 'Tuesday', + 'method': UnlockingMethod.Face, + }, + { + 'title': "XXX Remote", + 'time': 1200, + 'date': 20240305, + 'day': 'Tuesday', + 'method': UnlockingMethod.Remote, + }, + { + 'title': "XXX Face", + 'time': 1200, + 'date': 20240405, + 'day': 'Wednesday', + 'method': UnlockingMethod.Face, + }, + { + 'title': "XXX Fingerprint", + 'time': 1200, + 'date': 20240405, + 'day': 'Wednesday', + 'method': UnlockingMethod.Fingerprint, + }, + { + 'title': "XXX Fingerprint", + 'time': 1200, + 'date': 20240405, + 'day': 'Wednesday', + 'method': UnlockingMethod.Fingerprint, + }, + { + 'title': "XXX Remote", + 'time': 1500, + 'date': 20240505, + 'day': 'Thursday', + 'method': UnlockingMethod.Remote, + }, + { + 'title': "XXX Face", + 'time': 1200, + 'date': 20240505, + 'day': 'Thursday', + 'method': UnlockingMethod.Face, + }, + { + 'title': "XXX Fingerprint", + 'time': 1200, + 'date': 20240505, + 'day': 'Thursday', + 'method': UnlockingMethod.Fingerprint, + }, + { + 'title': "XXX Fingerprint", + 'time': 1200, + 'date': 20240505, + 'day': 'Thursday', + 'method': UnlockingMethod.Fingerprint, + }, + { + 'title': "XXX Remote", + 'time': 1500, + 'date': 20240505, + 'day': 'Thursday', + 'method': UnlockingMethod.Remote, + }, + { + 'title': "XXX Face", + 'time': 1200, + 'date': 20240605, + 'day': 'Friday', + 'method': UnlockingMethod.Face, + }, + { + 'title': "XXX Fingerprint", + 'time': 1200, + 'date': 20240605, + 'day': 'Friday', + 'method': UnlockingMethod.Fingerprint, + }, + { + 'title': "XXX Fingerprint", + 'time': 1200, + 'date': 20240605, + 'day': 'Friday', + 'method': UnlockingMethod.Fingerprint, + }, + { + 'title': "XXX Remote", + 'time': 1500, + 'date': 20240705, + 'day': 'Saturday', + 'method': UnlockingMethod.Remote, + }, + { + 'title': "XXX Face", + 'time': 1200, + 'date': 20240705, + 'day': 'Saturday', + 'method': UnlockingMethod.Face, + }, + { + 'title': "XXX Fingerprint", + 'time': 1200, + 'date': 20240705, + 'day': 'Saturday', + 'method': UnlockingMethod.Fingerprint, + }, + { + 'title': "XXX Fingerprint", + 'time': 1200, + 'date': 20240705, + 'day': 'Saturday', + 'method': UnlockingMethod.Fingerprint, + } +];