mirror of
https://github.com/SyncrowIOT/web.git
synced 2025-07-10 07:07:19 +00:00
merge dev to devices view
This commit is contained in:
@ -1,96 +0,0 @@
|
|||||||
[
|
|
||||||
{
|
|
||||||
"accessUser": "Ali Doe",
|
|
||||||
"accessType": "Admin",
|
|
||||||
"startTime": "2023-08-01",
|
|
||||||
"endTime": "2023-08-02",
|
|
||||||
"accessibleDevice": "Smart Door",
|
|
||||||
"authorizationSource": "System",
|
|
||||||
"authorizer": "Jane Smith",
|
|
||||||
"authorizationTime": "2023-08-01 10:00 AM",
|
|
||||||
"accessStatus": "Granted",
|
|
||||||
"actions": "View"
|
|
||||||
}, {
|
|
||||||
"accessUser": "oamr Doe",
|
|
||||||
"accessType": "Admin",
|
|
||||||
"startTime": "2023-08-01",
|
|
||||||
"endTime": "2023-08-05",
|
|
||||||
"accessibleDevice": "Smart Door",
|
|
||||||
"authorizationSource": "System",
|
|
||||||
"authorizer": "Jane Smith",
|
|
||||||
"authorizationTime": "2023-08-01 10:00 AM",
|
|
||||||
"accessStatus": "Granted",
|
|
||||||
"actions": "View"
|
|
||||||
}, {
|
|
||||||
"accessUser": "John Doe",
|
|
||||||
"accessType": "Admin",
|
|
||||||
"startTime": "2023-08-01",
|
|
||||||
"endTime": "2023-08-10",
|
|
||||||
"accessibleDevice": "Smart Door",
|
|
||||||
"authorizationSource": "System",
|
|
||||||
"authorizer": "Jane Smith",
|
|
||||||
"authorizationTime": "2023-08-01 10:00 AM",
|
|
||||||
"accessStatus": "Granted",
|
|
||||||
"actions": "View"
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
"accessUser": "John Doe",
|
|
||||||
"accessType": "Admin",
|
|
||||||
"startTime": "2023-08-01",
|
|
||||||
"endTime": "2023-10-10",
|
|
||||||
"accessibleDevice": "Smart Door",
|
|
||||||
"authorizationSource": "System",
|
|
||||||
"authorizer": "Jane Smith",
|
|
||||||
"authorizationTime": "2023-08-01 10:00 AM",
|
|
||||||
"accessStatus": "Granted",
|
|
||||||
"actions": "View"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"accessUser": "John Doe",
|
|
||||||
"accessType": "Admin",
|
|
||||||
"startTime": "2023-03-01",
|
|
||||||
"endTime": "2023-05-10",
|
|
||||||
"accessibleDevice": "Smart Door",
|
|
||||||
"authorizationSource": "System",
|
|
||||||
"authorizer": "Jane Smith",
|
|
||||||
"authorizationTime": "2023-08-01 10:00 AM",
|
|
||||||
"accessStatus": "Granted",
|
|
||||||
"actions": "View"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"accessUser": "John Doe",
|
|
||||||
"accessType": "Admin",
|
|
||||||
"startTime": "2023-07-01",
|
|
||||||
"endTime": "2023-08-10",
|
|
||||||
"accessibleDevice": "Smart Door",
|
|
||||||
"authorizationSource": "System",
|
|
||||||
"authorizer": "Jane Smith",
|
|
||||||
"authorizationTime": "2023-08-01 10:00 AM",
|
|
||||||
"accessStatus": "Granted",
|
|
||||||
"actions": "View"
|
|
||||||
}, {
|
|
||||||
"accessUser": "John Doe",
|
|
||||||
"accessType": "Admin",
|
|
||||||
"startTime": "2023-01-01",
|
|
||||||
"endTime": "2023-09-05",
|
|
||||||
"accessibleDevice": "Smart Door",
|
|
||||||
"authorizationSource": "System",
|
|
||||||
"authorizer": "Jane Smith",
|
|
||||||
"authorizationTime": "2023-08-01 10:00 AM",
|
|
||||||
"accessStatus": "Granted",
|
|
||||||
"actions": "View"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"accessUser": "Alice Johnson",
|
|
||||||
"accessType": "User",
|
|
||||||
"startTime": "2023-08-01",
|
|
||||||
"endTime": "2023-08-10",
|
|
||||||
"accessibleDevice": "Smart Lock",
|
|
||||||
"authorizationSource": "Admin",
|
|
||||||
"authorizer": "John Doe",
|
|
||||||
"authorizationTime": "2023-08-02 11:00 AM",
|
|
||||||
"accessStatus": "Pending",
|
|
||||||
"actions": "Approve"
|
|
||||||
}
|
|
||||||
]
|
|
23
assets/images/empty_table.svg
Normal file
23
assets/images/empty_table.svg
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<svg width="100" height="88" viewBox="0 0 100 88" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g opacity="0.7">
|
||||||
|
<path d="M99.9982 31V87.5508H23.9567C22.6831 87.5508 21.6528 86.5186 21.6528 85.2469V23.2094C21.6528 21.9358 22.6831 20.9055 23.9567 20.9055H51.8961C52.5057 20.9055 53.0912 21.1469 53.5238 21.5795L59.9664 28.0221C60.399 28.4547 60.9845 28.6961 61.596 28.6961H97.6943C98.966 28.6963 99.9982 29.7285 99.9982 31Z" fill="#756F6F"/>
|
||||||
|
<path d="M63.2924 39.9286C66.3941 39.9286 68.9086 37.4142 68.9086 34.3124C68.9086 31.2107 66.3941 28.6963 63.2924 28.6963C60.1907 28.6963 57.6763 31.2107 57.6763 34.3124C57.6763 37.4142 60.1907 39.9286 63.2924 39.9286Z" fill="#5B5555"/>
|
||||||
|
<path d="M42.6767 47.5693C43.6907 48.5814 42.9745 50.3158 41.54 50.3158H23.8057C23.0794 50.3158 22.361 50.2795 21.6528 50.2111V23.2094C21.6528 21.9358 22.6831 20.9055 23.9567 20.9055H43.9786C44.9122 23.3219 45.4253 25.9498 45.4253 28.6963C45.4253 34.6661 43.0048 40.0704 39.0933 43.9838L42.6767 47.5693Z" fill="#5B5555"/>
|
||||||
|
<path d="M99.9997 31.0001V87.551H92.3498V31.0001C92.3498 29.7284 91.3195 28.6962 90.0459 28.6962H97.6956C98.9675 28.6964 99.9997 29.7286 99.9997 31.0001Z" fill="#5B5555"/>
|
||||||
|
<path d="M76.5031 58.662L99.9992 87.5516H22.7485C22.0552 87.5516 21.3989 87.2393 20.9614 86.7014L0.520807 61.5688C-0.7034 60.0636 0.367684 57.8118 2.3079 57.8118H74.7158C75.4094 57.8118 76.0658 58.1241 76.5031 58.662Z" fill="#64B9FC"/>
|
||||||
|
<path d="M99.9988 87.5508H90.0915L66.5968 58.6618C66.1581 58.1245 65.5022 57.8107 64.8101 57.8107H74.7154C75.4096 57.8107 76.0654 58.1245 76.5021 58.6618L99.9988 87.5508Z" fill="#31A7FB"/>
|
||||||
|
<path d="M82.504 80.7751H62.1786C61.5502 80.7751 60.9581 80.4815 60.5774 79.9815L55.3685 73.1373C54.8644 72.475 55.3368 71.522 56.169 71.522H76.4944C77.1228 71.522 77.7149 71.8156 78.0956 72.3156L83.3045 79.1599C83.8086 79.822 83.3364 80.7751 82.504 80.7751Z" fill="#F8F3F1"/>
|
||||||
|
<path d="M82.5047 80.7746H75.9655C76.7985 80.7746 77.2713 79.8229 76.7663 79.159L71.5571 72.3161C71.1768 71.8151 70.5852 71.5214 69.9575 71.5214H76.4948C77.1244 71.5214 77.716 71.8151 78.0963 72.3161L83.3054 79.159C83.8084 79.823 83.3377 80.7746 82.5047 80.7746Z" fill="#EFE2DD"/>
|
||||||
|
<path d="M49.999 82.2837H40.7663C39.9329 82.2837 39.2573 81.6081 39.2573 80.7748C39.2573 79.9414 39.9329 79.2658 40.7663 79.2658H49.999C50.8324 79.2658 51.508 79.9414 51.508 80.7748C51.508 81.6081 50.8324 82.2837 49.999 82.2837Z" fill="#F8F3F1"/>
|
||||||
|
<path d="M46.6315 77.2784H42.7126C41.8792 77.2784 41.2036 76.6029 41.2036 75.7695C41.2036 74.9361 41.8792 74.2605 42.7126 74.2605H46.6315C47.4649 74.2605 48.1405 74.9361 48.1405 75.7695C48.1407 76.6029 47.4651 77.2784 46.6315 77.2784Z" fill="#F8F3F1"/>
|
||||||
|
<path d="M45.4271 21.6202C45.4271 9.68008 35.7477 0.000671387 23.8077 0.000671387C11.8787 0.000671387 2.18799 9.69141 2.18799 21.6204C2.18818 33.5605 11.8674 43.2397 23.8075 43.2397H41.5417C42.9755 43.2397 43.6937 41.5062 42.6798 40.4923L39.0949 36.9074C43.0074 32.9953 45.4271 27.5903 45.4271 21.6202Z" fill="#31A7FB"/>
|
||||||
|
<path d="M42.6806 40.4929C43.6946 41.507 42.9784 43.2394 41.5438 43.2394H34.2521C35.6847 43.2394 36.4031 41.507 35.3888 40.4929L33.1658 38.2687C32.4264 37.5289 32.3795 36.348 33.0537 35.5482C36.2251 31.7865 38.1372 26.9256 38.1372 21.6198C38.1372 10.9238 30.3688 2.04051 20.1655 0.308107C21.1528 0.138772 22.1626 0.0379915 23.1901 0.00889019C35.2808 -0.331732 45.2247 9.15764 45.4258 21.2515C45.5276 27.3669 43.0886 32.9154 39.097 36.9072L42.6806 40.4929Z" fill="#1C96F9"/>
|
||||||
|
<path d="M28.074 21.6202L32.0957 17.5986C33.2744 16.4199 33.2744 14.509 32.0957 13.3304C30.9172 12.1517 29.0061 12.1517 27.8276 13.3304L23.8059 17.3521L19.7845 13.3303C18.606 12.1516 16.6949 12.1516 15.5163 13.3303C14.3376 14.5088 14.3376 16.4197 15.5163 17.5984L19.538 21.62L15.5163 25.6417C14.3376 26.8204 14.3376 28.7313 15.5163 29.9098C16.1056 30.4992 16.8781 30.7938 17.6505 30.7938C18.423 30.7938 19.1952 30.4991 19.7847 29.9098L23.8063 25.8882L27.828 29.9098C28.4174 30.4992 29.1895 30.7938 29.9621 30.7938C30.7344 30.7938 31.5068 30.4991 32.0963 29.9098C33.275 28.7313 33.275 26.8204 32.0963 25.6417L28.074 21.6202Z" fill="#F8F3F1"/>
|
||||||
|
<path d="M63.2939 35.1746C66.3956 35.1746 68.9101 32.6601 68.9101 29.5584C68.9101 26.4567 66.3956 23.9423 63.2939 23.9423C60.1922 23.9423 57.6777 26.4567 57.6777 29.5584C57.6777 32.6601 60.1922 35.1746 63.2939 35.1746Z" fill="#BCEA73"/>
|
||||||
|
<path d="M68.9087 29.5576C68.9087 32.6605 66.3935 35.1758 63.2931 35.1758C62.2537 35.1758 61.2785 34.8933 60.4443 34.398C62.649 33.8898 64.2916 31.9162 64.2916 29.5576C64.2916 27.2016 62.6515 25.2255 60.4469 24.7173C61.281 24.2245 62.2537 23.9423 63.2931 23.9423C66.3937 23.9421 68.9087 26.4573 68.9087 29.5576Z" fill="#99D53B"/>
|
||||||
|
<path d="M82.9628 22.8247C85.4105 22.8247 87.3947 20.8404 87.3947 18.3927C87.3947 15.945 85.4105 13.9607 82.9628 13.9607C80.515 13.9607 78.5308 15.945 78.5308 18.3927C78.5308 20.8404 80.515 22.8247 82.9628 22.8247Z" fill="#BCEA73"/>
|
||||||
|
<path d="M87.3925 18.3923C87.3925 20.8409 85.4078 22.8257 82.9611 22.8257C82.1408 22.8257 81.3713 22.6028 80.7129 22.212C82.4527 21.811 83.7488 20.2534 83.7488 18.3923C83.7488 16.5329 82.4547 14.9736 80.7148 14.5724C81.373 14.1835 82.1406 13.9607 82.9609 13.9607C85.4078 13.9607 87.3925 15.9456 87.3925 18.3923Z" fill="#99D53B"/>
|
||||||
|
<path d="M72.8344 10.292L73.6508 9.4756C74.2403 8.88615 74.2403 7.93089 73.6508 7.34144C73.0616 6.75219 72.1061 6.75219 71.5167 7.34144L70.7003 8.15784L69.8839 7.34144C69.2946 6.75199 68.3392 6.75199 67.7497 7.34144C67.1603 7.93069 67.1603 8.88615 67.7497 9.4756L68.5661 10.292L67.7497 11.1084C67.1603 11.6978 67.1603 12.6531 67.7497 13.2426C68.0444 13.5373 68.4306 13.6845 68.8167 13.6845C69.2028 13.6845 69.5891 13.5371 69.8837 13.2426L70.7001 12.4262L71.5165 13.2426C71.8112 13.5373 72.1973 13.6845 72.5835 13.6845C72.9696 13.6845 73.3559 13.5371 73.6504 13.2426C74.2399 12.6533 74.2399 11.6978 73.6504 11.1084L72.8344 10.292Z" fill="#64B9FC"/>
|
||||||
|
<path d="M11.2994 44.5503C10.7102 43.961 9.75473 43.961 9.16528 44.5503L7.74381 45.9718L6.32234 44.5503C5.73309 43.961 4.77763 43.961 4.18818 44.5503C3.59873 45.1395 3.59873 46.095 4.18818 46.6844L5.60965 48.1059L4.18818 49.5274C3.59873 50.1166 3.59873 51.0721 4.18818 51.6615C4.4829 51.9563 4.86903 52.1035 5.25516 52.1035C5.64129 52.1035 6.02762 51.9561 6.32214 51.6615L7.74362 50.2401L9.16509 51.6615C9.45981 51.9563 9.84594 52.1035 10.2321 52.1035C10.6182 52.1035 11.0045 51.9561 11.2991 51.6615C11.8885 51.0723 11.8885 50.1168 11.2991 49.5274L9.87758 48.1059L11.2991 46.6844C11.8887 46.095 11.8887 45.1395 11.2994 44.5503Z" fill="#A8E7EF"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 6.4 KiB |
4
assets/images/time_icon.svg
Normal file
4
assets/images/time_icon.svg
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<svg width="10" height="10" viewBox="0 0 10 10" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M5.00005 0C2.24302 0 0 2.24297 0 4.99995C0 7.75712 2.24302 10.0002 5.00005 10.0002C7.75703 10.0002 10 7.75708 10 4.99995C10 2.24297 7.75703 0 5.00005 0ZM5.00005 9.28343C2.63824 9.28343 0.716757 7.36186 0.716757 4.99995C0.716757 2.63819 2.63824 0.716757 5.00005 0.716757C7.36181 0.716757 9.28324 2.63819 9.28324 4.99995C9.28324 7.36186 7.36181 9.28343 5.00005 9.28343Z" fill="#999999"/>
|
||||||
|
<path d="M7.57087 4.91629H5.22115V2.34782C5.22115 2.1499 5.06074 1.98944 4.86277 1.98944C4.66485 1.98944 4.50439 2.1499 4.50439 2.34782V5.27467C4.50439 5.47259 4.66485 5.63305 4.86277 5.63305H7.57087C7.76884 5.63305 7.92925 5.47259 7.92925 5.27467C7.92925 5.07675 7.76879 4.91629 7.57087 4.91629Z" fill="#999999"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 813 B |
@ -5,6 +5,7 @@ import 'package:syncrow_web/pages/auth/bloc/auth_bloc.dart';
|
|||||||
import 'package:syncrow_web/pages/auth/view/login_page.dart';
|
import 'package:syncrow_web/pages/auth/view/login_page.dart';
|
||||||
import 'package:syncrow_web/pages/home/bloc/home_bloc.dart';
|
import 'package:syncrow_web/pages/home/bloc/home_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/home/view/home_page.dart';
|
import 'package:syncrow_web/pages/home/view/home_page.dart';
|
||||||
|
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_bloc.dart';
|
||||||
import 'package:syncrow_web/services/locator.dart';
|
import 'package:syncrow_web/services/locator.dart';
|
||||||
import 'package:syncrow_web/utils/color_manager.dart';
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
|
|
||||||
@ -28,6 +29,9 @@ class MyApp extends StatelessWidget {
|
|||||||
return MultiBlocProvider(
|
return MultiBlocProvider(
|
||||||
providers: [
|
providers: [
|
||||||
BlocProvider(create: (context) => HomeBloc()),
|
BlocProvider(create: (context) => HomeBloc()),
|
||||||
|
BlocProvider<VisitorPasswordBloc>(
|
||||||
|
create: (context) => VisitorPasswordBloc(),
|
||||||
|
)
|
||||||
],
|
],
|
||||||
child: MaterialApp(
|
child: MaterialApp(
|
||||||
debugShowCheckedModeBanner: false, // Hide debug banner
|
debugShowCheckedModeBanner: false, // Hide debug banner
|
||||||
@ -39,6 +43,7 @@ class MyApp extends StatelessWidget {
|
|||||||
PointerDeviceKind.unknown,
|
PointerDeviceKind.unknown,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
||||||
theme: ThemeData(
|
theme: ThemeData(
|
||||||
textTheme: const TextTheme(
|
textTheme: const TextTheme(
|
||||||
bodySmall: TextStyle(
|
bodySmall: TextStyle(
|
||||||
@ -55,12 +60,10 @@ class MyApp extends StatelessWidget {
|
|||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
colorScheme: ColorScheme.fromSeed(
|
colorScheme: ColorScheme.fromSeed(
|
||||||
seedColor: Colors.deepPurple), // Set up color scheme
|
seedColor: Colors.deepPurple), // Set up color scheme
|
||||||
useMaterial3: true, // Enable Material 3
|
useMaterial3: true, // Enable Material 3
|
||||||
),
|
),
|
||||||
// home: AddDeviceDialog()
|
|
||||||
home: isLoggedIn == 'Success' ? const HomePage() : const LoginPage(),
|
home: isLoggedIn == 'Success' ? const HomePage() : const LoginPage(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -5,23 +5,25 @@ import 'package:syncrow_web/pages/access_management/bloc/access_state.dart';
|
|||||||
import 'package:syncrow_web/pages/access_management/model/password_model.dart';
|
import 'package:syncrow_web/pages/access_management/model/password_model.dart';
|
||||||
import 'package:syncrow_web/services/access_mang_api.dart';
|
import 'package:syncrow_web/services/access_mang_api.dart';
|
||||||
import 'package:syncrow_web/utils/color_manager.dart';
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
|
import 'package:syncrow_web/utils/constants/const.dart';
|
||||||
import 'package:syncrow_web/utils/snack_bar.dart';
|
import 'package:syncrow_web/utils/snack_bar.dart';
|
||||||
|
|
||||||
class AccessBloc extends Bloc<AccessEvent, AccessState> {
|
class AccessBloc extends Bloc<AccessEvent, AccessState> {
|
||||||
AccessBloc() : super((AccessInitial())) {
|
AccessBloc() : super((AccessInitial())) {
|
||||||
on<FetchTableData>(_onFetchTableData);
|
on<FetchTableData>(_onFetchTableData);
|
||||||
on<TabChangedEvent>(selectFilterTap);
|
// on<TabChangedEvent>(selectFilterTap);
|
||||||
on<SelectTime>(selectTime);
|
on<SelectTime>(selectTime);
|
||||||
on<FilterDataEvent>(_filterData);
|
on<FilterDataEvent>(_filterData);
|
||||||
on<ResetSearch>(resetSearch);
|
on<ResetSearch>(resetSearch);
|
||||||
|
on<TabChangedEvent>(onTabChanged);
|
||||||
}
|
}
|
||||||
String startTime = 'Start Time';
|
String startTime = 'Start Date';
|
||||||
String endTime = 'End Time';
|
String endTime = 'End Date';
|
||||||
|
|
||||||
int? effectiveTimeTimeStamp;
|
int? effectiveTimeTimeStamp;
|
||||||
int? expirationTimeTimeStamp;
|
int? expirationTimeTimeStamp;
|
||||||
TextEditingController passwordName= TextEditingController();
|
TextEditingController passwordName= TextEditingController();
|
||||||
List<PasswordModel> filteredData = []; // To store filtered data
|
List<PasswordModel> filteredData = [];
|
||||||
List<PasswordModel> data=[];
|
List<PasswordModel> data=[];
|
||||||
|
|
||||||
Future<void> _onFetchTableData(
|
Future<void> _onFetchTableData(
|
||||||
@ -29,14 +31,25 @@ class AccessBloc extends Bloc<AccessEvent, AccessState> {
|
|||||||
try {
|
try {
|
||||||
emit(AccessLoaded());
|
emit(AccessLoaded());
|
||||||
data = await AccessMangApi().fetchVisitorPassword();
|
data = await AccessMangApi().fetchVisitorPassword();
|
||||||
|
filteredData= data;
|
||||||
|
updateTabsCount();
|
||||||
emit(TableLoaded(data));
|
emit(TableLoaded(data));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
emit(FailedState(e.toString()));
|
emit(FailedState(e.toString()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
void updateTabsCount() {
|
||||||
|
int toBeEffectiveCount = data.where((item) => item.passwordStatus.value== 'To Be Effective').length;
|
||||||
|
int effectiveCount = data.where((item) => item.passwordStatus.value == 'Effective').length;
|
||||||
|
int expiredCount = data.where((item) => item.passwordStatus.value == 'Expired').length;
|
||||||
|
tabs[1] = 'To Be Effective ($toBeEffectiveCount)';
|
||||||
|
tabs[2] = 'Effective ($effectiveCount)';
|
||||||
|
tabs[3] = 'Expired ($expiredCount)';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int selectedIndex = 0;
|
int selectedIndex = 0;
|
||||||
|
|
||||||
final List<String> tabs = [
|
final List<String> tabs = [
|
||||||
'All',
|
'All',
|
||||||
'To Be Effective (0)',
|
'To Be Effective (0)',
|
||||||
@ -51,7 +64,6 @@ class AccessBloc extends Bloc<AccessEvent, AccessState> {
|
|||||||
selectedIndex= event.selectedIndex;
|
selectedIndex= event.selectedIndex;
|
||||||
emit(AccessInitial());
|
emit(AccessInitial());
|
||||||
emit(TableLoaded(data));
|
emit(TableLoaded(data));
|
||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
emit(FailedState( e.toString()));
|
emit(FailedState( e.toString()));
|
||||||
return;
|
return;
|
||||||
@ -60,6 +72,8 @@ class AccessBloc extends Bloc<AccessEvent, AccessState> {
|
|||||||
|
|
||||||
|
|
||||||
Future<void> selectTime(SelectTime event, Emitter<AccessState> emit) async {
|
Future<void> selectTime(SelectTime event, Emitter<AccessState> emit) async {
|
||||||
|
emit(AccessLoaded());
|
||||||
|
|
||||||
final DateTime? picked = await showDatePicker(
|
final DateTime? picked = await showDatePicker(
|
||||||
context: event.context,
|
context: event.context,
|
||||||
initialDate: DateTime.now(),
|
initialDate: DateTime.now(),
|
||||||
@ -120,27 +134,23 @@ class AccessBloc extends Bloc<AccessEvent, AccessState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
emit(AccessInitial());
|
emit(ChangeTimeState());
|
||||||
emit(TableLoaded(data));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Future<void> _filterData(FilterDataEvent event, Emitter<AccessState> emit) async {
|
Future<void> _filterData(FilterDataEvent event, Emitter<AccessState> emit) async {
|
||||||
emit(AccessLoaded());
|
emit(AccessLoaded());
|
||||||
try {
|
try {
|
||||||
// Filter the data based on the provided criteria
|
|
||||||
filteredData = data.where((item) {
|
filteredData = data.where((item) {
|
||||||
bool matchesCriteria = true;
|
bool matchesCriteria = true;
|
||||||
// Check if the password name should be used for filtering
|
|
||||||
if (event.passwordName != null && event.passwordName!.isNotEmpty) {
|
if (event.passwordName != null && event.passwordName!.isNotEmpty) {
|
||||||
final bool matchesName = item.passwodName != null &&
|
final bool matchesName = item.passwordName != null &&
|
||||||
item.passwodName.contains(event.passwordName!);
|
item.passwordName.contains(event.passwordName);
|
||||||
if (!matchesName) {
|
if (!matchesName) {
|
||||||
matchesCriteria = false;
|
matchesCriteria = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Check if the time range should be used for filtering
|
|
||||||
if (event.startTime != null && event.endTime != null) {
|
if (event.startTime != null && event.endTime != null) {
|
||||||
// Ensure effectiveTime and invalidTime are treated as integers
|
|
||||||
final int? effectiveTime = int.tryParse(item.effectiveTime.toString());
|
final int? effectiveTime = int.tryParse(item.effectiveTime.toString());
|
||||||
final int? invalidTime = int.tryParse(item.invalidTime.toString());
|
final int? invalidTime = int.tryParse(item.invalidTime.toString());
|
||||||
if (effectiveTime == null || invalidTime == null) {
|
if (effectiveTime == null || invalidTime == null) {
|
||||||
@ -153,22 +163,30 @@ class AccessBloc extends Bloc<AccessEvent, AccessState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (event.selectedTabIndex == 1 && item.passwordStatus.value != 'To Be Effective') {
|
||||||
|
matchesCriteria = false;
|
||||||
|
} else if (event.selectedTabIndex == 2 && item.passwordStatus.value != 'Effective') {
|
||||||
|
matchesCriteria = false;
|
||||||
|
} else if (event.selectedTabIndex == 3 && item.passwordStatus.value != 'Expired') {
|
||||||
|
matchesCriteria = false;
|
||||||
|
}
|
||||||
return matchesCriteria;
|
return matchesCriteria;
|
||||||
}).toList();
|
}).toList();
|
||||||
print('Filtered data: $filteredData');
|
|
||||||
emit(TableLoaded(filteredData));
|
emit(TableLoaded(filteredData));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print('Error occurred during filtering: $e');
|
emit(FailedState(e.toString()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ResetSearch
|
|
||||||
resetSearch(ResetSearch event, Emitter<AccessState> emit) async{
|
resetSearch(ResetSearch event, Emitter<AccessState> emit) async{
|
||||||
emit(AccessLoaded());
|
emit(AccessLoaded());
|
||||||
startTime = 'Start Time';
|
startTime = 'Start Time';
|
||||||
endTime = 'End Time';
|
endTime = 'End Time';
|
||||||
passwordName.clear();
|
passwordName.clear();
|
||||||
|
selectedIndex=0;
|
||||||
|
effectiveTimeTimeStamp=null;
|
||||||
|
expirationTimeTimeStamp=null;
|
||||||
add(FetchTableData());
|
add(FetchTableData());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String timestampToDate(dynamic timestamp) {
|
String timestampToDate(dynamic timestamp) {
|
||||||
@ -176,5 +194,36 @@ class AccessBloc extends Bloc<AccessEvent, AccessState> {
|
|||||||
return "${dateTime.year}/${dateTime.month.toString().padLeft(2, '0')}/${dateTime.day.toString().padLeft(2, '0')}";
|
return "${dateTime.year}/${dateTime.month.toString().padLeft(2, '0')}/${dateTime.day.toString().padLeft(2, '0')}";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> onTabChanged(TabChangedEvent event, Emitter<AccessState> emit) async {
|
||||||
|
try {
|
||||||
|
emit(AccessLoaded());
|
||||||
|
selectedIndex = event.selectedIndex;
|
||||||
|
switch (selectedIndex) {
|
||||||
|
case 0: // All
|
||||||
|
filteredData = data;
|
||||||
|
break;
|
||||||
|
case 1: // To Be Effective
|
||||||
|
filteredData = data.where((item) => item.passwordStatus.value == "To Be Effective").toList();
|
||||||
|
break;
|
||||||
|
case 2: // Effective
|
||||||
|
filteredData = data.where((item) => item.passwordStatus.value == "Effective").toList();
|
||||||
|
break;
|
||||||
|
case 3: // Expired
|
||||||
|
filteredData = data.where((item) => item.passwordStatus.value == "Expired").toList();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
filteredData = data;
|
||||||
|
}
|
||||||
|
add(FilterDataEvent(
|
||||||
|
selectedTabIndex: selectedIndex,
|
||||||
|
passwordName: passwordName.text.toLowerCase(),
|
||||||
|
startTime: effectiveTimeTimeStamp,
|
||||||
|
endTime: expirationTimeTimeStamp
|
||||||
|
));
|
||||||
|
emit(TableLoaded(filteredData));
|
||||||
|
} catch (e) {
|
||||||
|
emit(FailedState(e.toString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -31,10 +31,16 @@ class FilterDataEvent extends AccessEvent {
|
|||||||
final String? passwordName;
|
final String? passwordName;
|
||||||
final int? startTime;
|
final int? startTime;
|
||||||
final int? endTime;
|
final int? endTime;
|
||||||
|
final int selectedTabIndex; // Add this field
|
||||||
|
|
||||||
const FilterDataEvent({
|
const FilterDataEvent({
|
||||||
this.passwordName,
|
this.passwordName,
|
||||||
this.startTime,
|
this.startTime,
|
||||||
this.endTime,
|
this.endTime,
|
||||||
|
required this.selectedTabIndex, // Initialize this field
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -6,8 +6,8 @@ class PasswordModel {
|
|||||||
final dynamic effectiveTime;
|
final dynamic effectiveTime;
|
||||||
final dynamic passwordCreated;
|
final dynamic passwordCreated;
|
||||||
final dynamic createdTime;
|
final dynamic createdTime;
|
||||||
final dynamic passwodName; // New field
|
final dynamic passwordName; // New field
|
||||||
final dynamic passwordStatus;
|
final AccessStatus passwordStatus;
|
||||||
final AccessType passwordType;
|
final AccessType passwordType;
|
||||||
final dynamic deviceUuid;
|
final dynamic deviceUuid;
|
||||||
|
|
||||||
@ -17,8 +17,8 @@ class PasswordModel {
|
|||||||
this.effectiveTime,
|
this.effectiveTime,
|
||||||
this.passwordCreated,
|
this.passwordCreated,
|
||||||
this.createdTime,
|
this.createdTime,
|
||||||
this.passwodName, // New field
|
this.passwordName, // New field
|
||||||
this.passwordStatus,
|
required this.passwordStatus,
|
||||||
required this.passwordType,
|
required this.passwordType,
|
||||||
this.deviceUuid,
|
this.deviceUuid,
|
||||||
});
|
});
|
||||||
@ -30,9 +30,9 @@ class PasswordModel {
|
|||||||
effectiveTime: json['effectiveTime'],
|
effectiveTime: json['effectiveTime'],
|
||||||
passwordCreated: json['passwordCreated'],
|
passwordCreated: json['passwordCreated'],
|
||||||
createdTime: json['createdTime'],
|
createdTime: json['createdTime'],
|
||||||
passwodName: json['passwodName']??'No name', // New field
|
passwordName: json['passwordName']??'No name', // New field
|
||||||
passwordStatus: json['passwordStatus'],
|
passwordStatus:AccessStatusExtension.fromString(json['passwordStatus']),
|
||||||
passwordType:AccessTypeExtension.fromString(json['passwordType']) ,
|
passwordType:AccessTypeExtension.fromString(json['passwordType']),
|
||||||
deviceUuid: json['deviceUuid'],
|
deviceUuid: json['deviceUuid'],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -44,13 +44,11 @@ class PasswordModel {
|
|||||||
'effectiveTime': effectiveTime,
|
'effectiveTime': effectiveTime,
|
||||||
'passwordCreated': passwordCreated,
|
'passwordCreated': passwordCreated,
|
||||||
'createdTime': createdTime,
|
'createdTime': createdTime,
|
||||||
'passwodName': passwodName, // New field
|
'passwodName': passwordName, // New field
|
||||||
'passwordStatus': passwordStatus,
|
'passwordStatus': passwordStatus,
|
||||||
'passwordType': passwordType,
|
'passwordType': passwordType,
|
||||||
'deviceUuid': deviceUuid,
|
'deviceUuid': deviceUuid,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
List<PasswordModel> parsePasswordList(List<dynamic> jsonList) {
|
|
||||||
return jsonList.map((json) => PasswordModel.fromJson(json)).toList();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ import 'package:syncrow_web/pages/common/buttons/default_button.dart';
|
|||||||
import 'package:syncrow_web/pages/common/filter/filter_widget.dart';
|
import 'package:syncrow_web/pages/common/filter/filter_widget.dart';
|
||||||
import 'package:syncrow_web/pages/visitor_password/view/visitor_password_dialog.dart';
|
import 'package:syncrow_web/pages/visitor_password/view/visitor_password_dialog.dart';
|
||||||
import 'package:syncrow_web/utils/color_manager.dart';
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
|
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||||
import 'package:syncrow_web/utils/constants/const.dart';
|
import 'package:syncrow_web/utils/constants/const.dart';
|
||||||
import 'package:syncrow_web/utils/style.dart';
|
import 'package:syncrow_web/utils/style.dart';
|
||||||
import 'package:syncrow_web/web_layout/web_scaffold.dart';
|
import 'package:syncrow_web/web_layout/web_scaffold.dart';
|
||||||
@ -41,47 +42,119 @@ class AccessManagementPage extends StatelessWidget {
|
|||||||
create: (BuildContext context) =>
|
create: (BuildContext context) =>
|
||||||
AccessBloc()..add(FetchTableData()),
|
AccessBloc()..add(FetchTableData()),
|
||||||
child: BlocConsumer<AccessBloc, AccessState>(
|
child: BlocConsumer<AccessBloc, AccessState>(
|
||||||
listener: (context, state) {
|
listener: (context, state) {},
|
||||||
if (state is FailedState) {
|
builder: (context, state) {
|
||||||
// CustomSnackBar.displaySnackBar(
|
|
||||||
// state.errorMessage
|
|
||||||
// );
|
|
||||||
}
|
|
||||||
}, builder: (context, state) {
|
|
||||||
final accessBloc = BlocProvider.of<AccessBloc>(context);
|
final accessBloc = BlocProvider.of<AccessBloc>(context);
|
||||||
return Container(
|
final filteredData = accessBloc.filteredData;
|
||||||
|
return state is AccessLoaded
|
||||||
|
? const Center(child: CircularProgressIndicator())
|
||||||
|
: Container(
|
||||||
padding: EdgeInsets.all(30),
|
padding: EdgeInsets.all(30),
|
||||||
height: size.height,
|
height: size.height,
|
||||||
width: size.width,
|
width: size.width,
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
FilterWidget(
|
Container(
|
||||||
size: size,
|
decoration: containerDecoration,
|
||||||
tabs: accessBloc.tabs,
|
height: size.height * 0.05,
|
||||||
selectedIndex: accessBloc.selectedIndex,
|
child: Flexible(
|
||||||
onTabChanged: (index) {
|
child: ListView.builder(
|
||||||
accessBloc.add(TabChangedEvent(index));
|
scrollDirection: Axis.horizontal,
|
||||||
|
itemCount:
|
||||||
|
BlocProvider.of<AccessBloc>(context)
|
||||||
|
.tabs
|
||||||
|
.length,
|
||||||
|
shrinkWrap: true,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
final isSelected = index ==
|
||||||
|
BlocProvider.of<AccessBloc>(context)
|
||||||
|
.selectedIndex;
|
||||||
|
return InkWell(
|
||||||
|
onTap: () {
|
||||||
|
BlocProvider.of<AccessBloc>(context)
|
||||||
|
.add(TabChangedEvent(index));
|
||||||
},
|
},
|
||||||
|
child: Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: ColorsManager.boxColor,
|
||||||
|
border: Border.all(
|
||||||
|
color: isSelected
|
||||||
|
? Colors.blue
|
||||||
|
: Colors.transparent,
|
||||||
|
width: 2.0,
|
||||||
|
),
|
||||||
|
borderRadius: index == 0
|
||||||
|
? const BorderRadius.only(
|
||||||
|
topLeft:
|
||||||
|
Radius.circular(10),
|
||||||
|
bottomLeft:
|
||||||
|
Radius.circular(10))
|
||||||
|
: index == 3
|
||||||
|
? const BorderRadius.only(
|
||||||
|
topRight:
|
||||||
|
Radius.circular(10),
|
||||||
|
bottomRight:
|
||||||
|
Radius.circular(10))
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
padding: const EdgeInsets.only(
|
||||||
|
left: 10, right: 10),
|
||||||
|
child: Center(
|
||||||
|
child: Text(
|
||||||
|
BlocProvider.of<AccessBloc>(
|
||||||
|
context)
|
||||||
|
.tabs[index],
|
||||||
|
style: TextStyle(
|
||||||
|
color: isSelected
|
||||||
|
? Colors.blue
|
||||||
|
: Colors.black,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
height: 20,
|
height: 20,
|
||||||
),
|
),
|
||||||
Row(
|
Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
|
textBaseline: TextBaseline.ideographic,
|
||||||
children: [
|
children: [
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment:
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
CrossAxisAlignment.start,
|
||||||
|
mainAxisAlignment:
|
||||||
|
MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
const Text('Name'),
|
Text(
|
||||||
|
'Name',
|
||||||
|
style: Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.bodySmall!
|
||||||
|
.copyWith(
|
||||||
|
color: Colors.black,
|
||||||
|
fontSize: 13),
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 5,
|
||||||
|
),
|
||||||
Container(
|
Container(
|
||||||
|
height: 43,
|
||||||
width: size.width * 0.15,
|
width: size.width * 0.15,
|
||||||
decoration: containerDecoration,
|
decoration: containerDecoration,
|
||||||
child: TextFormField(
|
child: TextFormField(
|
||||||
controller: accessBloc.passwordName,
|
controller: accessBloc.passwordName,
|
||||||
style: const TextStyle(color: Colors.black),
|
style: const TextStyle(
|
||||||
|
color: Colors.black),
|
||||||
decoration: textBoxDecoration()!
|
decoration: textBoxDecoration()!
|
||||||
.copyWith(hintText: 'Please enter'),
|
.copyWith(
|
||||||
|
hintText: 'Please enter'),
|
||||||
)),
|
)),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@ -89,37 +162,43 @@ class AccessManagementPage extends StatelessWidget {
|
|||||||
width: 15,
|
width: 15,
|
||||||
),
|
),
|
||||||
DateTimeWebWidget(
|
DateTimeWebWidget(
|
||||||
|
icon: Assets.calendarIcon,
|
||||||
isRequired: false,
|
isRequired: false,
|
||||||
title: 'Access Time',
|
title: 'Access Time',
|
||||||
size: size,
|
size: size,
|
||||||
endTime: () {
|
endTime: () {
|
||||||
accessBloc.add(
|
accessBloc.add(SelectTime(
|
||||||
SelectTime(context: context, isStart: false));
|
context: context, isStart: false));
|
||||||
},
|
},
|
||||||
startTime: () {
|
startTime: () {
|
||||||
accessBloc.add(
|
accessBloc.add(SelectTime(
|
||||||
SelectTime(context: context, isStart: true));
|
context: context, isStart: true));
|
||||||
},
|
},
|
||||||
firstString:
|
firstString:
|
||||||
BlocProvider.of<AccessBloc>(context).startTime,
|
BlocProvider.of<AccessBloc>(context)
|
||||||
|
.startTime,
|
||||||
secondString:
|
secondString:
|
||||||
BlocProvider.of<AccessBloc>(context).endTime,
|
BlocProvider.of<AccessBloc>(context)
|
||||||
|
.endTime,
|
||||||
),
|
),
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
width: 15,
|
width: 15,
|
||||||
),
|
),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
|
height: 45,
|
||||||
width: size.width * 0.06,
|
width: size.width * 0.06,
|
||||||
child: Column(
|
child: Container(
|
||||||
children: [
|
|
||||||
Text(''),
|
|
||||||
Container(
|
|
||||||
decoration: containerDecoration,
|
decoration: containerDecoration,
|
||||||
child: DefaultButton(
|
child: DefaultButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
accessBloc.add(FilterDataEvent(
|
accessBloc.add(FilterDataEvent(
|
||||||
passwordName:
|
selectedTabIndex: BlocProvider
|
||||||
accessBloc.passwordName.text,
|
.of<AccessBloc>(
|
||||||
|
context)
|
||||||
|
.selectedIndex, // Pass the selected tab index
|
||||||
|
passwordName: accessBloc
|
||||||
|
.passwordName.text
|
||||||
|
.toLowerCase(),
|
||||||
startTime: accessBloc
|
startTime: accessBloc
|
||||||
.effectiveTimeTimeStamp,
|
.effectiveTimeTimeStamp,
|
||||||
endTime: accessBloc
|
endTime: accessBloc
|
||||||
@ -127,24 +206,21 @@ class AccessManagementPage extends StatelessWidget {
|
|||||||
},
|
},
|
||||||
borderRadius: 9,
|
borderRadius: 9,
|
||||||
child: const Text('Search'))),
|
child: const Text('Search'))),
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
width: 10,
|
width: 10,
|
||||||
),
|
),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
|
height: 45,
|
||||||
width: size.width * 0.06,
|
width: size.width * 0.06,
|
||||||
child: Column(
|
child: Container(
|
||||||
children: [
|
|
||||||
Text(''),
|
|
||||||
Container(
|
|
||||||
decoration: containerDecoration,
|
decoration: containerDecoration,
|
||||||
child: DefaultButton(
|
child: DefaultButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
accessBloc.add(ResetSearch());
|
accessBloc.add(ResetSearch());
|
||||||
},
|
},
|
||||||
backgroundColor: ColorsManager.whiteColors,
|
backgroundColor:
|
||||||
|
ColorsManager.whiteColors,
|
||||||
borderRadius: 9,
|
borderRadius: 9,
|
||||||
child: Text(
|
child: Text(
|
||||||
'Reset',
|
'Reset',
|
||||||
@ -155,8 +231,6 @@ class AccessManagementPage extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@ -176,11 +250,15 @@ class AccessManagementPage extends StatelessWidget {
|
|||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
return const VisitorPasswordDialog();
|
return const VisitorPasswordDialog();
|
||||||
},
|
},
|
||||||
);
|
).then((v) {
|
||||||
|
if (v != null) {
|
||||||
|
accessBloc.add(FetchTableData());
|
||||||
|
}
|
||||||
|
});
|
||||||
},
|
},
|
||||||
borderRadius: 8,
|
borderRadius: 8,
|
||||||
child:
|
child: const Text(
|
||||||
const Text('+ Create Visitor Password ')),
|
'+ Create Visitor Password ')),
|
||||||
),
|
),
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
width: 10,
|
width: 10,
|
||||||
@ -190,7 +268,8 @@ class AccessManagementPage extends StatelessWidget {
|
|||||||
decoration: containerDecoration,
|
decoration: containerDecoration,
|
||||||
child: DefaultButton(
|
child: DefaultButton(
|
||||||
borderRadius: 8,
|
borderRadius: 8,
|
||||||
backgroundColor: ColorsManager.whiteColors,
|
backgroundColor:
|
||||||
|
ColorsManager.whiteColors,
|
||||||
child: Text(
|
child: Text(
|
||||||
'Admin Password',
|
'Admin Password',
|
||||||
style: Theme.of(context)
|
style: Theme.of(context)
|
||||||
@ -204,8 +283,8 @@ class AccessManagementPage extends StatelessWidget {
|
|||||||
height: 20,
|
height: 20,
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: state is TableLoaded
|
child: DynamicTable(
|
||||||
? DynamicTable(
|
isEmpty: filteredData.isEmpty,
|
||||||
withCheckBox: false,
|
withCheckBox: false,
|
||||||
size: size,
|
size: size,
|
||||||
cellDecoration: containerDecoration,
|
cellDecoration: containerDecoration,
|
||||||
@ -213,98 +292,28 @@ class AccessManagementPage extends StatelessWidget {
|
|||||||
'Name',
|
'Name',
|
||||||
'Access Type',
|
'Access Type',
|
||||||
'Access Period',
|
'Access Period',
|
||||||
'Device Id',
|
'Accessible Device',
|
||||||
'Authorizer',
|
'Authorizer',
|
||||||
'Authorization Date & Time',
|
'Authorization Date & Time',
|
||||||
'Access Status'
|
'Access Status'
|
||||||
],
|
],
|
||||||
data: state.data.map((item) {
|
data: filteredData.map((item) {
|
||||||
return [
|
return [
|
||||||
item.passwodName.toString(),
|
item.passwordName.toString(),
|
||||||
item.passwordType.value,
|
item.passwordType.value,
|
||||||
('${accessBloc.timestampToDate(item.effectiveTime)} - ${accessBloc.timestampToDate(item.invalidTime)}'),
|
('${accessBloc.timestampToDate(item.effectiveTime)} - ${accessBloc.timestampToDate(item.invalidTime)}'),
|
||||||
item.deviceUuid.toString(),
|
item.deviceUuid.toString(),
|
||||||
'',
|
'',
|
||||||
'',
|
'',
|
||||||
''
|
item.passwordStatus.value
|
||||||
];
|
];
|
||||||
}).toList(),
|
}).toList(),
|
||||||
)
|
)
|
||||||
: const Center(child: CircularProgressIndicator()),
|
// : const Center(child: CircularProgressIndicator()),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
})));
|
})));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Container TableWidget(Size size, TableLoaded state,AccessBloc accessBloc) {
|
|
||||||
// return Container(
|
|
||||||
// decoration: containerDecoration,
|
|
||||||
// width: size.width,
|
|
||||||
// child: Padding(
|
|
||||||
// padding: const EdgeInsets.all(10.0),
|
|
||||||
// child: ListView(
|
|
||||||
// scrollDirection: Axis.horizontal,
|
|
||||||
// children: [
|
|
||||||
// Container(
|
|
||||||
// width: size.width,
|
|
||||||
// height: size.height,
|
|
||||||
// child: Column(
|
|
||||||
// children: [
|
|
||||||
// Container(
|
|
||||||
// color: ColorsManager.boxColor,
|
|
||||||
// child: Row(
|
|
||||||
// children: [
|
|
||||||
// _buildTableHeaderCell('Password name'),
|
|
||||||
// _buildTableHeaderCell(' Password Type'),
|
|
||||||
// _buildTableHeaderCell('Start Time'),
|
|
||||||
// _buildTableHeaderCell('End Time'),
|
|
||||||
// _buildTableHeaderCell('Device Id'),
|
|
||||||
// // _buildTableHeaderCell('Authorization Source'),
|
|
||||||
// // _buildTableHeaderCell('Authorizer'),
|
|
||||||
// _buildTableHeaderCell('Password Created'),
|
|
||||||
// // _buildTableHeaderCell('Access Status'),
|
|
||||||
// _buildTableHeaderCell('Password Status'),
|
|
||||||
// ],
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// Expanded(
|
|
||||||
// child: Container(
|
|
||||||
// width: size.width,
|
|
||||||
// color: ColorsManager.whiteColors,
|
|
||||||
// child: ListView(
|
|
||||||
// shrinkWrap: true,
|
|
||||||
// children: [
|
|
||||||
// Column(
|
|
||||||
// children: state.data.map((item) {
|
|
||||||
// return Row(
|
|
||||||
// children: [
|
|
||||||
// _buildTableCell(item.passwodName),
|
|
||||||
// _buildTableCell(item.passwordType),
|
|
||||||
//
|
|
||||||
// _buildTableCell(accessBloc.timestampToDateTime(item.effectiveTime).toString()),
|
|
||||||
// _buildTableCell(accessBloc.timestampToDateTime(item.invalidTime).toString()),
|
|
||||||
// _buildTableCell(item.deviceUuid.toString()),
|
|
||||||
// // _buildTableCell(item.authorizationSource),
|
|
||||||
// // _buildTableCell(item.authorizer),
|
|
||||||
// _buildTableCell(item.passwordCreated!=null?accessBloc.timestampToDateTime(item.passwordCreated).toString():'no data'),
|
|
||||||
// // _buildTableCell(item.accessStatus),
|
|
||||||
// _buildTableCell(item.passwordStatus.toString()),
|
|
||||||
// ],
|
|
||||||
// );
|
|
||||||
// }).toList(),
|
|
||||||
// ),
|
|
||||||
// ],
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ],
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ],
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
@ -84,6 +84,9 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
|
|||||||
} else if (response == "You entered wrong otp") {
|
} else if (response == "You entered wrong otp") {
|
||||||
forgetValidate = 'Wrong one time password.';
|
forgetValidate = 'Wrong one time password.';
|
||||||
emit(AuthInitialState());
|
emit(AuthInitialState());
|
||||||
|
}else if (response == "OTP expired") {
|
||||||
|
forgetValidate = 'One time password has been expired.';
|
||||||
|
emit(AuthInitialState());
|
||||||
}
|
}
|
||||||
} catch (failure) {
|
} catch (failure) {
|
||||||
// forgetValidate='Invalid Credentials!';
|
// forgetValidate='Invalid Credentials!';
|
||||||
@ -91,7 +94,7 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
|
|||||||
// emit(FailureForgetState(error: failure.toString()));
|
// emit(FailureForgetState(error: failure.toString()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//925207
|
||||||
String? validateCode(String? value) {
|
String? validateCode(String? value) {
|
||||||
if (value == null || value.isEmpty) {
|
if (value == null || value.isEmpty) {
|
||||||
return 'Code is required';
|
return 'Code is required';
|
||||||
|
@ -146,7 +146,6 @@ class LoginMobilePage extends StatelessWidget {
|
|||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
isDense: true,
|
isDense: true,
|
||||||
style: const TextStyle(color: Colors.black),
|
style: const TextStyle(color: Colors.black),
|
||||||
items:loginBloc.regionList!.map((RegionModel region) {
|
items:loginBloc.regionList!.map((RegionModel region) {
|
||||||
@ -156,7 +155,6 @@ class LoginMobilePage extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}).toList(),
|
}).toList(),
|
||||||
onChanged: (String? value) {
|
onChanged: (String? value) {
|
||||||
print(value);
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
@ -166,8 +166,7 @@ class _LoginWebPageState extends State<LoginWebPage> {
|
|||||||
return DropdownMenuItem<String>(
|
return DropdownMenuItem<String>(
|
||||||
value: region.id,
|
value: region.id,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
width: size.width*0.06,
|
width: size.width*0.08,
|
||||||
|
|
||||||
child: Text(region.name)),
|
child: Text(region.name)),
|
||||||
);
|
);
|
||||||
}).toList(),
|
}).toList(),
|
||||||
|
75
lib/pages/common/custom_dialog.dart
Normal file
75
lib/pages/common/custom_dialog.dart
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
|
|
||||||
|
Future<void> showCustomDialog({
|
||||||
|
required BuildContext context,
|
||||||
|
required String message,
|
||||||
|
String? title,
|
||||||
|
String? iconPath,
|
||||||
|
double? dialogHeight,
|
||||||
|
double? iconHeight,
|
||||||
|
double? iconWidth,
|
||||||
|
VoidCallback? onOkPressed,
|
||||||
|
bool barrierDismissible = false, required actions,
|
||||||
|
}) {
|
||||||
|
return showDialog(
|
||||||
|
context: context,
|
||||||
|
barrierDismissible: barrierDismissible,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
final size = MediaQuery.of(context).size;
|
||||||
|
return AlertDialog(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
content: SizedBox(
|
||||||
|
height: dialogHeight ?? size.height * 0.15,
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
if (iconPath != null)
|
||||||
|
SvgPicture.asset(
|
||||||
|
iconPath,
|
||||||
|
height: iconHeight ?? 35,
|
||||||
|
width: iconWidth ?? 35,
|
||||||
|
),
|
||||||
|
if (title != null)
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 8.0),
|
||||||
|
child: Text(
|
||||||
|
title,
|
||||||
|
style: Theme.of(context).textTheme.headlineLarge!.copyWith(
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
color: Colors.black),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 8.0),
|
||||||
|
child: Text(
|
||||||
|
message,
|
||||||
|
style: Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.bodyMedium!
|
||||||
|
.copyWith(color: Colors.black),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
actionsAlignment: MainAxisAlignment.center,
|
||||||
|
actions: <Widget>[
|
||||||
|
TextButton(
|
||||||
|
onPressed: onOkPressed ?? () => Navigator.of(context).pop(),
|
||||||
|
child: Text(
|
||||||
|
'OK',
|
||||||
|
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
color: ColorsManager.blackColor,
|
||||||
|
fontSize: 16),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
@ -1,5 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
import 'package:syncrow_web/utils/color_manager.dart';
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
|
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||||
|
|
||||||
class DynamicTable extends StatefulWidget {
|
class DynamicTable extends StatefulWidget {
|
||||||
final List<String> headers;
|
final List<String> headers;
|
||||||
@ -8,20 +10,24 @@ class DynamicTable extends StatefulWidget {
|
|||||||
final BoxDecoration? cellDecoration;
|
final BoxDecoration? cellDecoration;
|
||||||
final Size size;
|
final Size size;
|
||||||
final bool withCheckBox;
|
final bool withCheckBox;
|
||||||
|
final bool isEmpty;
|
||||||
final void Function(bool?)? selectAll;
|
final void Function(bool?)? selectAll;
|
||||||
final void Function(int, bool?)? onRowCheckboxChanged;
|
final void Function(int, bool?)? onRowCheckboxChanged;
|
||||||
|
final List<String>? initialSelectedIds;
|
||||||
|
|
||||||
const DynamicTable({
|
const DynamicTable({
|
||||||
Key? key,
|
super.key,
|
||||||
required this.headers,
|
required this.headers,
|
||||||
required this.data,
|
required this.data,
|
||||||
required this.size,
|
required this.size,
|
||||||
|
required this.isEmpty,
|
||||||
required this.withCheckBox,
|
required this.withCheckBox,
|
||||||
this.headerDecoration,
|
this.headerDecoration,
|
||||||
this.cellDecoration,
|
this.cellDecoration,
|
||||||
this.selectAll,
|
this.selectAll,
|
||||||
this.onRowCheckboxChanged,
|
this.onRowCheckboxChanged,
|
||||||
}) : super(key: key);
|
this.initialSelectedIds,
|
||||||
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_DynamicTableState createState() => _DynamicTableState();
|
_DynamicTableState createState() => _DynamicTableState();
|
||||||
@ -34,7 +40,11 @@ class _DynamicTableState extends State<DynamicTable> {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
_selected = List<bool>.filled(widget.data.length, false);
|
_selected = List<bool>.generate(widget.data.length, (index) {
|
||||||
|
return widget.initialSelectedIds != null &&
|
||||||
|
widget.initialSelectedIds!.contains(widget.data[index][1]);
|
||||||
|
});
|
||||||
|
_selectAll = _selected.every((element) => element == true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _toggleSelectAll(bool? value) {
|
void _toggleSelectAll(bool? value) {
|
||||||
@ -62,7 +72,7 @@ class _DynamicTableState extends State<DynamicTable> {
|
|||||||
return Container(
|
return Container(
|
||||||
decoration: widget.cellDecoration,
|
decoration: widget.cellDecoration,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(10.0),
|
padding: const EdgeInsets.all(2.0),
|
||||||
child: ListView(
|
child: ListView(
|
||||||
scrollDirection: Axis.horizontal,
|
scrollDirection: Axis.horizontal,
|
||||||
children: [
|
children: [
|
||||||
@ -82,7 +92,37 @@ class _DynamicTableState extends State<DynamicTable> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Expanded(
|
widget.isEmpty
|
||||||
|
? Expanded(
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Column(
|
||||||
|
children: [
|
||||||
|
SvgPicture.asset(Assets.emptyTable),
|
||||||
|
const SizedBox(
|
||||||
|
height: 15,
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
'No Passwords',
|
||||||
|
style: Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.bodySmall!
|
||||||
|
.copyWith(
|
||||||
|
color: ColorsManager.grayColor),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: Expanded(
|
||||||
child: Container(
|
child: Container(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
child: ListView.builder(
|
child: ListView.builder(
|
||||||
@ -92,10 +132,13 @@ class _DynamicTableState extends State<DynamicTable> {
|
|||||||
final row = widget.data[index];
|
final row = widget.data[index];
|
||||||
return Row(
|
return Row(
|
||||||
children: [
|
children: [
|
||||||
if (widget.withCheckBox) _buildRowCheckbox(index),
|
if (widget.withCheckBox)
|
||||||
|
_buildRowCheckbox(
|
||||||
|
index, widget.size.height * 0.10),
|
||||||
...row
|
...row
|
||||||
.map((cell) =>
|
.map((cell) => _buildTableCell(
|
||||||
_buildTableCell(cell.toString()))
|
cell.toString(),
|
||||||
|
widget.size.height * 0.10))
|
||||||
.toList(),
|
.toList(),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
@ -113,8 +156,11 @@ class _DynamicTableState extends State<DynamicTable> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildSelectAllCheckbox() {
|
Widget _buildSelectAllCheckbox() {
|
||||||
return SizedBox(
|
return Container(
|
||||||
width: 50,
|
padding: const EdgeInsets.all(8.0),
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
border: Border.symmetric(
|
||||||
|
vertical: BorderSide(color: ColorsManager.boxDivider))),
|
||||||
child: Checkbox(
|
child: Checkbox(
|
||||||
value: _selectAll,
|
value: _selectAll,
|
||||||
onChanged: _toggleSelectAll,
|
onChanged: _toggleSelectAll,
|
||||||
@ -122,16 +168,26 @@ class _DynamicTableState extends State<DynamicTable> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildRowCheckbox(int index) {
|
Widget _buildRowCheckbox(int index, size) {
|
||||||
return SizedBox(
|
return Container(
|
||||||
width: 50,
|
padding: const EdgeInsets.all(8.0),
|
||||||
|
height: size,
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
border: Border(
|
||||||
|
bottom: BorderSide(
|
||||||
|
color: ColorsManager.boxDivider,
|
||||||
|
width: 1.0,
|
||||||
|
),
|
||||||
|
)),
|
||||||
|
alignment: Alignment.centerLeft,
|
||||||
|
child: Center(
|
||||||
child: Checkbox(
|
child: Checkbox(
|
||||||
value: _selected[index],
|
value: _selected[index],
|
||||||
onChanged: (bool? value) {
|
onChanged: (bool? value) {
|
||||||
_toggleRowSelection(index, value);
|
_toggleRowSelection(index, value);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildTableHeaderCell(String title) {
|
Widget _buildTableHeaderCell(String title) {
|
||||||
@ -146,17 +202,18 @@ class _DynamicTableState extends State<DynamicTable> {
|
|||||||
child: Text(title,
|
child: Text(title,
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
fontWeight: FontWeight.w400,
|
fontWeight: FontWeight.w400,
|
||||||
color: ColorsManager.lightGreyColor)),
|
fontSize: 13,
|
||||||
|
color: Color(0xFF999999))),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildTableCell(String content) {
|
Widget _buildTableCell(String content, size) {
|
||||||
return Expanded(
|
return Expanded(
|
||||||
child: Container(
|
child: Container(
|
||||||
height: 80,
|
height: size,
|
||||||
padding: const EdgeInsets.all(15.0),
|
padding: const EdgeInsets.all(5.0),
|
||||||
decoration: const BoxDecoration(
|
decoration: const BoxDecoration(
|
||||||
border: Border(
|
border: Border(
|
||||||
bottom: BorderSide(
|
bottom: BorderSide(
|
||||||
@ -167,7 +224,8 @@ class _DynamicTableState extends State<DynamicTable> {
|
|||||||
alignment: Alignment.centerLeft,
|
alignment: Alignment.centerLeft,
|
||||||
child: Text(
|
child: Text(
|
||||||
content,
|
content,
|
||||||
style: const TextStyle(color: Colors.black, fontSize: 12),
|
style: const TextStyle(
|
||||||
|
color: Colors.black, fontSize: 10, fontWeight: FontWeight.w400),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_svg/flutter_svg.dart';
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
import 'package:syncrow_web/utils/constants/assets.dart';
|
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||||
import 'package:syncrow_web/utils/style.dart';
|
import 'package:syncrow_web/utils/style.dart';
|
||||||
|
|
||||||
@ -13,6 +14,7 @@ class DateTimeWebWidget extends StatelessWidget {
|
|||||||
required this.endTime,
|
required this.endTime,
|
||||||
required this.firstString,
|
required this.firstString,
|
||||||
required this.secondString,
|
required this.secondString,
|
||||||
|
required this.icon,
|
||||||
});
|
});
|
||||||
|
|
||||||
final Size size;
|
final Size size;
|
||||||
@ -20,6 +22,7 @@ class DateTimeWebWidget extends StatelessWidget {
|
|||||||
final bool isRequired;
|
final bool isRequired;
|
||||||
final String firstString;
|
final String firstString;
|
||||||
final String secondString;
|
final String secondString;
|
||||||
|
final String icon;
|
||||||
final Function()? startTime;
|
final Function()? startTime;
|
||||||
final Function()? endTime;
|
final Function()? endTime;
|
||||||
|
|
||||||
@ -39,35 +42,52 @@ class DateTimeWebWidget extends StatelessWidget {
|
|||||||
.bodyMedium!
|
.bodyMedium!
|
||||||
.copyWith(color: Colors.red),
|
.copyWith(color: Colors.red),
|
||||||
),
|
),
|
||||||
Text(title??''),
|
Text(title??'' ,
|
||||||
|
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||||
|
color: Colors.black,fontSize: 13),),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
SizedBox(height: 8,),
|
const SizedBox(height: 8,),
|
||||||
Container(
|
Container(
|
||||||
width: size.width * 0.25,
|
height:size.height * 0.055 ,
|
||||||
padding: EdgeInsets.all(10),
|
padding: EdgeInsets.only(top: 10,bottom: 10,right: 30,left: 10),
|
||||||
decoration: containerDecoration,
|
decoration: containerDecoration,
|
||||||
|
child: FittedBox(
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment:
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
children: [
|
||||||
InkWell(
|
InkWell(
|
||||||
onTap: startTime,
|
onTap: startTime,
|
||||||
child: Text(firstString)
|
child: FittedBox(
|
||||||
|
child: Text(firstString,
|
||||||
|
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||||
|
color: ColorsManager.grayColor,fontSize: 12,fontWeight: FontWeight.w400),),
|
||||||
|
)
|
||||||
),
|
),
|
||||||
|
SizedBox(width: 30,),
|
||||||
const Icon(Icons.arrow_right_alt),
|
const Icon(Icons.arrow_right_alt),
|
||||||
|
SizedBox(width: 30,),
|
||||||
|
|
||||||
InkWell(
|
InkWell(
|
||||||
onTap:endTime,
|
onTap:endTime,
|
||||||
child: Text(secondString)),
|
child: FittedBox(
|
||||||
|
child: Text(secondString,
|
||||||
|
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||||
|
color: ColorsManager.grayColor,fontSize: 12,fontWeight: FontWeight.w400),
|
||||||
|
),
|
||||||
|
)),
|
||||||
|
SizedBox(width: 30,),
|
||||||
|
|
||||||
SvgPicture.asset(
|
SvgPicture.asset(
|
||||||
Assets.calendarIcon,
|
icon,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
)),
|
)),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
92
lib/pages/common/hour_picker_dialog.dart
Normal file
92
lib/pages/common/hour_picker_dialog.dart
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class HourPickerDialog extends StatefulWidget {
|
||||||
|
final TimeOfDay initialTime;
|
||||||
|
const HourPickerDialog({super.key, required this.initialTime});
|
||||||
|
|
||||||
|
@override
|
||||||
|
_HourPickerDialogState createState() => _HourPickerDialogState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _HourPickerDialogState extends State<HourPickerDialog> {
|
||||||
|
late int _selectedHour;
|
||||||
|
bool _isPm = false;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_selectedHour = widget.initialTime.hour > 12 ? widget.initialTime.hour - 12 : widget.initialTime.hour;
|
||||||
|
_isPm = widget.initialTime.period == DayPeriod.pm;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return AlertDialog(
|
||||||
|
title: const Text('Select Hour'),
|
||||||
|
content: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
DropdownButton<int>(
|
||||||
|
value: _selectedHour,
|
||||||
|
items: List.generate(12, (index) {
|
||||||
|
int displayHour = index + 1;
|
||||||
|
return DropdownMenuItem(
|
||||||
|
value: displayHour,
|
||||||
|
child: Text(displayHour.toString()),
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
onChanged: (value) {
|
||||||
|
setState(() {
|
||||||
|
_selectedHour = value!;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
SizedBox(width: 16.0),
|
||||||
|
DropdownButton<bool>(
|
||||||
|
value: _isPm,
|
||||||
|
items: const [
|
||||||
|
DropdownMenuItem(
|
||||||
|
value: false,
|
||||||
|
child: Text('AM'),
|
||||||
|
),
|
||||||
|
DropdownMenuItem(
|
||||||
|
value: true,
|
||||||
|
child: Text('PM'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
onChanged: (value) {
|
||||||
|
setState(() {
|
||||||
|
_isPm = value!;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => Navigator.of(context).pop(null),
|
||||||
|
child: const Text('Cancel'),
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
onPressed: () {
|
||||||
|
int hour = _isPm ? _selectedHour + 12 : _selectedHour;
|
||||||
|
Navigator.of(context).pop(TimeOfDay(hour: hour, minute: 0));
|
||||||
|
},
|
||||||
|
child: const Text('OK'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<TimeOfDay?> showHourPicker({
|
||||||
|
required BuildContext context,
|
||||||
|
required TimeOfDay initialTime,
|
||||||
|
}) {
|
||||||
|
return showDialog<TimeOfDay>(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => HourPickerDialog(initialTime: initialTime),
|
||||||
|
);
|
||||||
|
}
|
@ -66,7 +66,7 @@ class InfoDialog extends StatelessWidget {
|
|||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
},
|
},
|
||||||
child: Text('OK'),
|
child: const Text('OK'),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
@ -33,24 +33,24 @@ class CustomWebTextField extends StatelessWidget {
|
|||||||
children: [
|
children: [
|
||||||
Text('* ',
|
Text('* ',
|
||||||
style: Theme.of(context)
|
style: Theme.of(context)
|
||||||
.textTheme
|
.textTheme.bodyMedium!
|
||||||
.bodyMedium!
|
|
||||||
.copyWith(color: Colors.red),
|
.copyWith(color: Colors.red),
|
||||||
),
|
),
|
||||||
Text(textFieldName),
|
Text(textFieldName, style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||||
|
color: Colors.black,fontSize: 13),),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(width: 10,),
|
const SizedBox(width: 10,),
|
||||||
Text(
|
Expanded(
|
||||||
description??'', // ' The password will be sent to the visitor’s email address.',
|
child: Text(
|
||||||
|
description??'',
|
||||||
style: Theme.of(context)
|
style: Theme.of(context)
|
||||||
.textTheme
|
.textTheme.bodySmall!
|
||||||
.bodySmall!
|
.copyWith(fontSize: 9,
|
||||||
.copyWith(
|
|
||||||
fontSize: 9,
|
|
||||||
fontWeight: FontWeight.w400,
|
fontWeight: FontWeight.w400,
|
||||||
color: ColorsManager.textGray),
|
color: ColorsManager.textGray),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 7,),
|
const SizedBox(height: 7,),
|
||||||
@ -62,11 +62,10 @@ class CustomWebTextField extends StatelessWidget {
|
|||||||
color: Colors.grey.withOpacity(0.3),
|
color: Colors.grey.withOpacity(0.3),
|
||||||
spreadRadius:2,
|
spreadRadius:2,
|
||||||
blurRadius: 3,
|
blurRadius: 3,
|
||||||
offset: Offset(1, 1), // changes position of shadow
|
offset: const Offset(1, 1), // changes position of shadow
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
child: Container(
|
|
||||||
child: TextFormField(
|
child: TextFormField(
|
||||||
validator: validator,
|
validator: validator,
|
||||||
controller: controller,
|
controller: controller,
|
||||||
@ -78,7 +77,6 @@ class CustomWebTextField extends StatelessWidget {
|
|||||||
hintText: 'Please enter'),
|
hintText: 'Please enter'),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -65,7 +65,7 @@ class HomeBloc extends Bloc<HomeEvent, HomeState> {
|
|||||||
color: null,
|
color: null,
|
||||||
),
|
),
|
||||||
HomeItemModel(
|
HomeItemModel(
|
||||||
title: 'Space\nManagement',
|
title: 'Space Management',
|
||||||
icon: Assets.spaseManagementIcon,
|
icon: Assets.spaseManagementIcon,
|
||||||
active: true,
|
active: true,
|
||||||
onPress: (context) {},
|
onPress: (context) {},
|
||||||
|
@ -37,7 +37,8 @@ class HomeCard extends StatelessWidget {
|
|||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
FittedBox(
|
Flexible(
|
||||||
|
child: FittedBox(
|
||||||
fit: BoxFit.scaleDown,
|
fit: BoxFit.scaleDown,
|
||||||
child: Text(
|
child: Text(
|
||||||
name,
|
name,
|
||||||
@ -48,6 +49,7 @@ class HomeCard extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -2,13 +2,11 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:flutter_svg/svg.dart';
|
import 'package:flutter_svg/svg.dart';
|
||||||
import 'package:syncrow_web/pages/home/bloc/home_bloc.dart';
|
import 'package:syncrow_web/pages/home/bloc/home_bloc.dart';
|
||||||
|
import 'package:syncrow_web/pages/home/bloc/home_state.dart';
|
||||||
import 'package:syncrow_web/pages/home/view/home_card.dart';
|
import 'package:syncrow_web/pages/home/view/home_card.dart';
|
||||||
import 'package:syncrow_web/utils/color_manager.dart';
|
|
||||||
import 'package:syncrow_web/utils/constants/assets.dart';
|
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||||
import 'package:syncrow_web/web_layout/web_scaffold.dart';
|
import 'package:syncrow_web/web_layout/web_scaffold.dart';
|
||||||
|
|
||||||
import '../bloc/home_state.dart';
|
|
||||||
|
|
||||||
class HomeWebPage extends StatelessWidget {
|
class HomeWebPage extends StatelessWidget {
|
||||||
HomeWebPage({super.key});
|
HomeWebPage({super.key});
|
||||||
@override
|
@override
|
||||||
|
@ -1,18 +1,18 @@
|
|||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
|
import 'package:syncrow_web/pages/common/custom_dialog.dart';
|
||||||
|
import 'package:syncrow_web/pages/common/hour_picker_dialog.dart';
|
||||||
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_event.dart';
|
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_event.dart';
|
||||||
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_state.dart';
|
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_state.dart';
|
||||||
import 'package:syncrow_web/pages/visitor_password/model/device_model.dart';
|
import 'package:syncrow_web/pages/visitor_password/model/device_model.dart';
|
||||||
import 'package:syncrow_web/pages/visitor_password/model/schedule_model.dart';
|
import 'package:syncrow_web/pages/visitor_password/model/schedule_model.dart';
|
||||||
import 'package:syncrow_web/services/access_mang_api.dart';
|
import 'package:syncrow_web/services/access_mang_api.dart';
|
||||||
import 'package:syncrow_web/utils/color_manager.dart';
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
|
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||||
import 'package:syncrow_web/utils/snack_bar.dart';
|
import 'package:syncrow_web/utils/snack_bar.dart';
|
||||||
List<String> selectedDevices = [];
|
|
||||||
|
|
||||||
// Define the BLoC
|
|
||||||
class VisitorPasswordBloc
|
class VisitorPasswordBloc
|
||||||
extends Bloc<VisitorPasswordEvent, VisitorPasswordState> {
|
extends Bloc<VisitorPasswordEvent, VisitorPasswordState> {
|
||||||
VisitorPasswordBloc() : super(VisitorPasswordInitial()) {
|
VisitorPasswordBloc() : super(VisitorPasswordInitial()) {
|
||||||
@ -24,13 +24,12 @@ class VisitorPasswordBloc
|
|||||||
on<ToggleDaySelectionEvent>(toggleDaySelection);
|
on<ToggleDaySelectionEvent>(toggleDaySelection);
|
||||||
on<SelectDeviceEvent>(selectDevice);
|
on<SelectDeviceEvent>(selectDevice);
|
||||||
on<UpdateFilteredDevicesEvent>(_onUpdateFilteredDevices);
|
on<UpdateFilteredDevicesEvent>(_onUpdateFilteredDevices);
|
||||||
|
|
||||||
on<OnlineOneTimePasswordEvent>(postOnlineOneTimePassword);
|
on<OnlineOneTimePasswordEvent>(postOnlineOneTimePassword);
|
||||||
on<OnlineMultipleTimePasswordEvent>(postOnlineMultipleTimePassword);
|
on<OnlineMultipleTimePasswordEvent>(postOnlineMultipleTimePassword);
|
||||||
|
|
||||||
on<OfflineMultipleTimePasswordEvent>(postOfflineMultipleTimePassword);
|
on<OfflineMultipleTimePasswordEvent>(postOfflineMultipleTimePassword);
|
||||||
on<OfflineOneTimePasswordEvent>(postOfflineOneTimePassword);
|
on<OfflineOneTimePasswordEvent>(postOfflineOneTimePassword);
|
||||||
|
on<SelectTimeEvent>(selectTimeOfLinePassword);
|
||||||
|
on<ChangeTimeEvent>(changeTime);
|
||||||
}
|
}
|
||||||
final TextEditingController userNameController = TextEditingController();
|
final TextEditingController userNameController = TextEditingController();
|
||||||
final TextEditingController emailController = TextEditingController();
|
final TextEditingController emailController = TextEditingController();
|
||||||
@ -38,14 +37,14 @@ class VisitorPasswordBloc
|
|||||||
final TextEditingController deviceNameController = TextEditingController();
|
final TextEditingController deviceNameController = TextEditingController();
|
||||||
final TextEditingController deviceIdController = TextEditingController();
|
final TextEditingController deviceIdController = TextEditingController();
|
||||||
final TextEditingController unitNameController = TextEditingController();
|
final TextEditingController unitNameController = TextEditingController();
|
||||||
final TextEditingController virtualAddressController = TextEditingController();
|
final TextEditingController virtualAddressController =
|
||||||
|
TextEditingController();
|
||||||
|
List<String> selectedDevices = [];
|
||||||
|
|
||||||
List<DeviceModel> data = [];
|
List<DeviceModel> data = [];
|
||||||
List<String> selectedDeviceIds = [];
|
List<String> selectedDeviceIds = [];
|
||||||
|
String effectiveTime = 'Start Time';
|
||||||
|
String expirationTime = 'End Time';
|
||||||
|
|
||||||
final forgetFormKey = GlobalKey<FormState>();
|
final forgetFormKey = GlobalKey<FormState>();
|
||||||
|
|
||||||
@ -58,18 +57,11 @@ class VisitorPasswordBloc
|
|||||||
int? effectiveTimeTimeStamp;
|
int? effectiveTimeTimeStamp;
|
||||||
int? expirationTimeTimeStamp;
|
int? expirationTimeTimeStamp;
|
||||||
|
|
||||||
int? repeatEffectiveTimeTimeStamp;
|
DateTime? startTime = DateTime.now();
|
||||||
int? repeatExpirationTimeTimeStamp;
|
DateTime? endTime;
|
||||||
|
|
||||||
String startTime = 'Start Time';
|
String startTimeAccess = 'Start Time';
|
||||||
String endTime = 'End Time';
|
String endTimeAccess = 'End Time';
|
||||||
|
|
||||||
|
|
||||||
String repeatStartTime = 'Start Time';
|
|
||||||
String repeatEndTime = 'End Time';
|
|
||||||
|
|
||||||
// DateTime? repeatStartTime=DateTime.now();
|
|
||||||
// DateTime? repeatEndTime;
|
|
||||||
|
|
||||||
selectAccessType(
|
selectAccessType(
|
||||||
SelectPasswordType event, Emitter<VisitorPasswordState> emit) {
|
SelectPasswordType event, Emitter<VisitorPasswordState> emit) {
|
||||||
@ -85,13 +77,15 @@ class VisitorPasswordBloc
|
|||||||
|
|
||||||
Future<void> selectTimeVisitorPassword(
|
Future<void> selectTimeVisitorPassword(
|
||||||
SelectTimeVisitorPassword event,
|
SelectTimeVisitorPassword event,
|
||||||
Emitter<VisitorPasswordState> emit) async {
|
Emitter<VisitorPasswordState> emit,
|
||||||
|
) async {
|
||||||
final DateTime? picked = await showDatePicker(
|
final DateTime? picked = await showDatePicker(
|
||||||
context: event.context,
|
context: event.context,
|
||||||
initialDate: DateTime.now(),
|
initialDate: DateTime.now(),
|
||||||
firstDate: DateTime(2015, 8),
|
firstDate: DateTime(2015, 8),
|
||||||
lastDate: DateTime(3101),
|
lastDate: DateTime(3101),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (picked != null) {
|
if (picked != null) {
|
||||||
final TimeOfDay? timePicked = await showTimePicker(
|
final TimeOfDay? timePicked = await showTimePicker(
|
||||||
context: event.context,
|
context: event.context,
|
||||||
@ -113,6 +107,7 @@ class VisitorPasswordBloc
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
if (timePicked != null) {
|
if (timePicked != null) {
|
||||||
final selectedDateTime = DateTime(
|
final selectedDateTime = DateTime(
|
||||||
picked.year,
|
picked.year,
|
||||||
@ -121,51 +116,37 @@ class VisitorPasswordBloc
|
|||||||
timePicked.hour,
|
timePicked.hour,
|
||||||
timePicked.minute,
|
timePicked.minute,
|
||||||
);
|
);
|
||||||
final selectedTimestamp = DateTime(
|
|
||||||
selectedDateTime.year,
|
|
||||||
selectedDateTime.month,
|
|
||||||
selectedDateTime.day,
|
|
||||||
selectedDateTime.hour,
|
|
||||||
selectedDateTime.minute,
|
|
||||||
).millisecondsSinceEpoch ~/
|
|
||||||
1000; // Divide by 1000 to remove milliseconds
|
|
||||||
if (event.isStart) {
|
|
||||||
if (expirationTimeTimeStamp != null && selectedTimestamp >expirationTimeTimeStamp!) {
|
|
||||||
CustomSnackBar.displaySnackBar('Effective Time cannot be later than Expiration Time.');
|
|
||||||
} else {
|
|
||||||
if(event.isRepeat==true)
|
|
||||||
{repeatStartTime = selectedDateTime.toString().split('.').first;}
|
|
||||||
|
|
||||||
else // Remove seconds and milliseconds
|
final selectedTimestamp =
|
||||||
{startTime = selectedDateTime.toString().split('.').first;}
|
selectedDateTime.millisecondsSinceEpoch ~/ 1000;
|
||||||
effectiveTimeTimeStamp = selectedTimestamp;
|
|
||||||
emit(ChangeTimeState());
|
if (event.isStart) {
|
||||||
|
if (expirationTimeTimeStamp != null &&
|
||||||
|
selectedTimestamp > expirationTimeTimeStamp!) {
|
||||||
|
CustomSnackBar.displaySnackBar(
|
||||||
|
'Effective Time cannot be later than Expiration Time.',
|
||||||
|
);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
emit(ChangeTimeState());
|
effectiveTimeTimeStamp = selectedTimestamp;
|
||||||
|
startTimeAccess = selectedDateTime.toString().split('.').first;
|
||||||
} else {
|
} else {
|
||||||
if (effectiveTimeTimeStamp != null &&
|
if (effectiveTimeTimeStamp != null &&
|
||||||
selectedTimestamp < effectiveTimeTimeStamp!) {
|
selectedTimestamp < effectiveTimeTimeStamp!) {
|
||||||
CustomSnackBar.displaySnackBar('Expiration Time cannot be earlier than Effective Time.');
|
CustomSnackBar.displaySnackBar(
|
||||||
} else {
|
'Expiration Time cannot be earlier than Effective Time.',
|
||||||
if(event.isRepeat==true)
|
);
|
||||||
{repeatEndTime = selectedDateTime.toString().split('.').first;}
|
return;
|
||||||
else
|
}
|
||||||
{endTime = selectedDateTime.toString().split('.').first;}
|
|
||||||
expirationTimeTimeStamp = selectedTimestamp;
|
expirationTimeTimeStamp = selectedTimestamp;
|
||||||
emit(ChangeTimeState());
|
endTimeAccess = selectedDateTime.toString().split('.').first;
|
||||||
|
|
||||||
}
|
}
|
||||||
emit(ChangeTimeState());
|
emit(ChangeTimeState());
|
||||||
|
|
||||||
emit(VisitorPasswordInitial());
|
emit(VisitorPasswordInitial());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// emit(AccessInitial());
|
|
||||||
// emit(TableLoaded(data));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool toggleRepeat(
|
bool toggleRepeat(
|
||||||
ToggleRepeatEvent event, Emitter<VisitorPasswordState> emit) {
|
ToggleRepeatEvent event, Emitter<VisitorPasswordState> emit) {
|
||||||
emit(LoadingInitialState());
|
emit(LoadingInitialState());
|
||||||
@ -211,67 +192,99 @@ class VisitorPasswordBloc
|
|||||||
}
|
}
|
||||||
|
|
||||||
//online password
|
//online password
|
||||||
|
Future<void> postOnlineOneTimePassword(OnlineOneTimePasswordEvent event,
|
||||||
Future<void> postOnlineOneTimePassword(
|
|
||||||
OnlineOneTimePasswordEvent event,
|
|
||||||
Emitter<VisitorPasswordState> emit) async {
|
Emitter<VisitorPasswordState> emit) async {
|
||||||
try {
|
try {
|
||||||
print('selectedDevices$selectedDevices');
|
emit(LoadingInitialState());
|
||||||
// emit(DeviceLoaded());
|
generate7DigitNumber();
|
||||||
await AccessMangApi().postOnlineOneTime(
|
bool res = await AccessMangApi().postOnlineOneTime(
|
||||||
email: event.email,
|
email: event.email,
|
||||||
|
password: passwordController,
|
||||||
devicesUuid: selectedDevices,
|
devicesUuid: selectedDevices,
|
||||||
passwordName: event.passwordName);
|
passwordName: event.passwordName,
|
||||||
// emit(TableLoaded(data));
|
effectiveTime: effectiveTimeTimeStamp.toString(),
|
||||||
|
invalidTime: expirationTimeTimeStamp.toString());
|
||||||
|
if (res == true) {
|
||||||
|
emit(SuccessState());
|
||||||
|
} else {
|
||||||
|
throw Exception('Failed to create password');
|
||||||
|
}
|
||||||
|
emit(TableLoaded(data));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
emit(FailedState(e.toString()));
|
emit(FailedState(e.toString()));
|
||||||
|
Navigator.pop(event.context!);
|
||||||
|
stateDialog(
|
||||||
|
context: event.context!,
|
||||||
|
message: e.toString(),
|
||||||
|
title: 'Something Wrong');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Future<void> postOnlineMultipleTimePassword(
|
Future<void> postOnlineMultipleTimePassword(
|
||||||
OnlineMultipleTimePasswordEvent event,
|
OnlineMultipleTimePasswordEvent event,
|
||||||
Emitter<VisitorPasswordState> emit) async {
|
Emitter<VisitorPasswordState> emit) async {
|
||||||
try {
|
try {
|
||||||
generate7DigitNumber();
|
emit(LoadingInitialState());
|
||||||
// emit(DeviceLoaded());
|
|
||||||
await AccessMangApi().postOnlineMultipleTime(
|
await generate7DigitNumber();
|
||||||
scheduleList:[
|
bool res = await AccessMangApi().postOnlineMultipleTime(
|
||||||
// if (repeat)
|
scheduleList: [
|
||||||
// Schedule(
|
if (repeat)
|
||||||
// effectiveTime: getTimeOnly(repeatStartTime),
|
Schedule(
|
||||||
// invalidTime: getTimeOnly(repeatEndTime).toString(),
|
effectiveTime: getTimeFromDateTimeString(expirationTime),
|
||||||
// workingDay: selectedDays,
|
invalidTime:
|
||||||
// ),
|
getTimeFromDateTimeString(effectiveTime).toString(),
|
||||||
] ,
|
workingDay: selectedDays,
|
||||||
|
),
|
||||||
|
],
|
||||||
password: passwordController,
|
password: passwordController,
|
||||||
invalidTime:event.invalidTime ,
|
invalidTime: expirationTimeTimeStamp.toString(),
|
||||||
effectiveTime:event.effectiveTime ,
|
effectiveTime: effectiveTimeTimeStamp.toString(),
|
||||||
email: event.email,
|
email: event.email,
|
||||||
devicesUuid: selectedDevices,
|
devicesUuid: selectedDevices,
|
||||||
passwordName: event.passwordName
|
passwordName: event.passwordName);
|
||||||
);
|
if (res == true) {
|
||||||
// emit(TableLoaded(data));
|
emit(SuccessState());
|
||||||
|
}else {
|
||||||
|
throw Exception('Failed to create password');
|
||||||
|
}
|
||||||
|
emit(TableLoaded(data));
|
||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
emit(FailedState(e.toString()));
|
emit(FailedState(e.toString()));
|
||||||
|
Navigator.pop(event.context!);
|
||||||
|
stateDialog(
|
||||||
|
context: event.context!,
|
||||||
|
message: e.toString(),
|
||||||
|
title: 'Something Wrong');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//offline password
|
//offline password
|
||||||
Future<void> postOfflineOneTimePassword(
|
Future<void> postOfflineOneTimePassword(OfflineOneTimePasswordEvent event,
|
||||||
OfflineOneTimePasswordEvent event,
|
|
||||||
Emitter<VisitorPasswordState> emit) async {
|
Emitter<VisitorPasswordState> emit) async {
|
||||||
try {
|
try {
|
||||||
generate7DigitNumber();
|
emit(LoadingInitialState());
|
||||||
// emit(DeviceLoaded());
|
await generate7DigitNumber();
|
||||||
await AccessMangApi().postOffLineOneTime(
|
bool res = await AccessMangApi().postOffLineOneTime(
|
||||||
email: event.email,
|
email: event.email,
|
||||||
devicesUuid: selectedDevices,
|
devicesUuid: selectedDevices,
|
||||||
passwordName: event.passwordName
|
passwordName: event.passwordName);
|
||||||
);
|
if (res == true) {
|
||||||
// emit(TableLoaded(data));
|
emit(SuccessState());
|
||||||
|
}else {
|
||||||
|
throw Exception('Failed to create password');
|
||||||
|
}
|
||||||
|
emit(TableLoaded(data));
|
||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
emit(FailedState(e.toString()));
|
emit(FailedState(e.toString()));
|
||||||
|
Navigator.pop(event.context!);
|
||||||
|
stateDialog(
|
||||||
|
context: event.context!,
|
||||||
|
message: e.toString(),
|
||||||
|
title: 'Something Wrong');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -279,21 +292,30 @@ class VisitorPasswordBloc
|
|||||||
OfflineMultipleTimePasswordEvent event,
|
OfflineMultipleTimePasswordEvent event,
|
||||||
Emitter<VisitorPasswordState> emit) async {
|
Emitter<VisitorPasswordState> emit) async {
|
||||||
try {
|
try {
|
||||||
generate7DigitNumber();
|
emit(LoadingInitialState());
|
||||||
// emit(DeviceLoaded());
|
await generate7DigitNumber();
|
||||||
await AccessMangApi().postOffLineMultipleTime(
|
bool res = await AccessMangApi().postOffLineMultipleTime(
|
||||||
email: event.email,
|
email: event.email,
|
||||||
devicesUuid: selectedDevices,
|
devicesUuid: selectedDevices,
|
||||||
passwordName: event.passwordName,
|
passwordName: event.passwordName,
|
||||||
invalidTime:event.invalidTime ,
|
invalidTime: expirationTimeTimeStamp.toString(),
|
||||||
effectiveTime:event.effectiveTime
|
effectiveTime: effectiveTimeTimeStamp.toString(),
|
||||||
);
|
);
|
||||||
// emit(TableLoaded(data));
|
if (res == true) {
|
||||||
|
emit(SuccessState());
|
||||||
|
}else {
|
||||||
|
throw Exception('Failed to create password');
|
||||||
|
}
|
||||||
|
emit(TableLoaded(data));
|
||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
emit(FailedState(e.toString()));
|
emit(FailedState(e.toString()));
|
||||||
|
Navigator.pop(event.context!);
|
||||||
|
stateDialog(
|
||||||
|
context: event.context!,
|
||||||
|
message: e.toString(),
|
||||||
|
title: 'Something Wrong'); }
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void selectDevice(
|
void selectDevice(
|
||||||
SelectDeviceEvent event, Emitter<VisitorPasswordState> emit) {
|
SelectDeviceEvent event, Emitter<VisitorPasswordState> emit) {
|
||||||
@ -302,8 +324,6 @@ class VisitorPasswordBloc
|
|||||||
} else {
|
} else {
|
||||||
selectedDeviceIds.add(event.deviceId);
|
selectedDeviceIds.add(event.deviceId);
|
||||||
}
|
}
|
||||||
selectedDevices=selectedDeviceIds;
|
|
||||||
print(selectedDevices);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String? validate(String? value) {
|
String? validate(String? value) {
|
||||||
@ -313,49 +333,165 @@ class VisitorPasswordBloc
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Future generate7DigitNumber() async {
|
Future generate7DigitNumber() async {
|
||||||
emit(LoadingInitialState());
|
passwordController = '';
|
||||||
passwordController='';
|
|
||||||
Random random = Random();
|
Random random = Random();
|
||||||
int min = 1000000;
|
int min = 1000000;
|
||||||
int max = 9999999;
|
int max = 9999999;
|
||||||
passwordController = (min + random.nextInt(max - min + 1)).toString();
|
passwordController = (min + random.nextInt(max - min + 1)).toString();
|
||||||
emit(GeneratePasswordState());
|
|
||||||
return passwordController;
|
return passwordController;
|
||||||
}
|
}
|
||||||
|
|
||||||
String getTimeOnly(DateTime? dateTime) {
|
String getTimeOnly(DateTime? dateTime) {
|
||||||
if (dateTime == null) return '';
|
if (dateTime == null) return '';
|
||||||
return DateFormat('HH:mm').format(dateTime);
|
return DateFormat('HH:mm').format(dateTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void filterDevices() {
|
void filterDevices() {
|
||||||
final deviceName = deviceNameController.text.toLowerCase();
|
final deviceName = deviceNameController.text.toLowerCase();
|
||||||
final deviceId = deviceIdController.text.toLowerCase();
|
final deviceId = deviceIdController.text.toLowerCase();
|
||||||
final unitName = unitNameController.text.toLowerCase();
|
final unitName = unitNameController.text.toLowerCase();
|
||||||
|
|
||||||
final filteredData = data.where((device) {
|
final filteredData = data.where((device) {
|
||||||
final matchesDeviceName = device.name.toLowerCase().contains(deviceName);
|
final matchesDeviceName = device.name.toLowerCase().contains(deviceName);
|
||||||
final matchesDeviceId = device.uuid.toLowerCase().contains(deviceId);
|
final matchesDeviceId = device.uuid.toLowerCase().contains(deviceId);
|
||||||
// final matchesUnitName = device.unitName.toLowerCase().contains(unitName); // Assuming unitName is a property of the device
|
// final matchesUnitName = device.unitName.toLowerCase().contains(unitName); // Assuming unitName is a property of the device
|
||||||
|
return matchesDeviceName && matchesDeviceId;
|
||||||
return matchesDeviceName && matchesDeviceId ;
|
|
||||||
}).toList();
|
}).toList();
|
||||||
// emit(TableLoaded(filteredData));
|
|
||||||
|
|
||||||
add(UpdateFilteredDevicesEvent(filteredData));
|
add(UpdateFilteredDevicesEvent(filteredData));
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Stream<VisitorPasswordState> mapEventToState(VisitorPasswordEvent event) async* {
|
Stream<VisitorPasswordState> mapEventToState(
|
||||||
|
VisitorPasswordEvent event) async* {
|
||||||
if (event is FetchDevice) {
|
if (event is FetchDevice) {
|
||||||
// Fetching logic...
|
|
||||||
} else if (event is UpdateFilteredDevicesEvent) {
|
} else if (event is UpdateFilteredDevicesEvent) {
|
||||||
yield TableLoaded(event.filteredData);
|
yield TableLoaded(event.filteredData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _onUpdateFilteredDevices(UpdateFilteredDevicesEvent event, Emitter<VisitorPasswordState> emit) {
|
void _onUpdateFilteredDevices(
|
||||||
|
UpdateFilteredDevicesEvent event, Emitter<VisitorPasswordState> emit) {
|
||||||
emit(TableLoaded(event.filteredData));
|
emit(TableLoaded(event.filteredData));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addDeviceToList(context) {
|
||||||
|
selectedDevices = selectedDeviceIds;
|
||||||
|
Navigator.of(context).pop(selectedDevices);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> selectTimeOfLinePassword(
|
||||||
|
SelectTimeEvent event, Emitter<VisitorPasswordState> emit) async {
|
||||||
|
emit(ChangeTimeState());
|
||||||
|
final DateTime? picked = await showDatePicker(
|
||||||
|
context: event.context,
|
||||||
|
initialDate: DateTime.now(),
|
||||||
|
firstDate: DateTime.now(),
|
||||||
|
lastDate: DateTime(3101),
|
||||||
|
);
|
||||||
|
if (picked != null) {
|
||||||
|
final TimeOfDay? timePicked = await showHourPicker(
|
||||||
|
context: event.context,
|
||||||
|
initialTime: TimeOfDay.now(),
|
||||||
|
);
|
||||||
|
if (timePicked != null) {
|
||||||
|
final selectedDateTime = DateTime(
|
||||||
|
picked.year,
|
||||||
|
picked.month,
|
||||||
|
picked.day,
|
||||||
|
timePicked.hour,
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
final selectedTimestamp = DateTime(
|
||||||
|
selectedDateTime.year,
|
||||||
|
selectedDateTime.month,
|
||||||
|
selectedDateTime.day,
|
||||||
|
selectedDateTime.hour,
|
||||||
|
selectedDateTime.minute,
|
||||||
|
).millisecondsSinceEpoch ~/
|
||||||
|
1000; // Divide by 1000 to remove milliseconds
|
||||||
|
if (event.isEffective) {
|
||||||
|
if (expirationTimeTimeStamp != null &&
|
||||||
|
selectedTimestamp > expirationTimeTimeStamp!) {
|
||||||
|
CustomSnackBar.displaySnackBar(
|
||||||
|
'Effective Time cannot be later than Expiration Time.');
|
||||||
|
} else {
|
||||||
|
effectiveTime = selectedDateTime
|
||||||
|
.toString()
|
||||||
|
.split('.')
|
||||||
|
.first; // Remove seconds and milliseconds
|
||||||
|
effectiveTimeTimeStamp = selectedTimestamp;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (effectiveTimeTimeStamp != null &&
|
||||||
|
selectedTimestamp < effectiveTimeTimeStamp!) {
|
||||||
|
CustomSnackBar.displaySnackBar(
|
||||||
|
'Expiration Time cannot be earlier than Effective Time.');
|
||||||
|
} else {
|
||||||
|
expirationTime = selectedDateTime
|
||||||
|
.toString()
|
||||||
|
.split('.')
|
||||||
|
.first; // Remove seconds and milliseconds
|
||||||
|
expirationTimeTimeStamp = selectedTimestamp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
emit(TimeSelectedState());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
changeTime(ChangeTimeEvent event, Emitter<VisitorPasswordState> emit) {
|
||||||
|
if (event.isStartEndTime == true) {
|
||||||
|
startTime = event.val;
|
||||||
|
} else {
|
||||||
|
endTime = event.val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DateTime? convertStringToDateTime(String dateTimeString) {
|
||||||
|
try {
|
||||||
|
final DateFormat inputFormat = DateFormat('yyyy-MM-dd HH:mm:ss');
|
||||||
|
DateTime dateTime = inputFormat.parse(dateTimeString);
|
||||||
|
return dateTime;
|
||||||
|
} catch (e) {
|
||||||
|
print("Error parsing date: $e");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String getTimeFromDateTimeString(String dateTimeString) {
|
||||||
|
DateTime? dateTime = convertStringToDateTime(dateTimeString);
|
||||||
|
if (dateTime == null) return '';
|
||||||
|
return DateFormat('HH:mm').format(dateTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
String? validateEmail(String? value) {
|
||||||
|
if (!RegExp(r'^[^@]+@[^@]+\.[^@]+').hasMatch(value!)) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> stateDialog({
|
||||||
|
BuildContext? context,
|
||||||
|
String? message,
|
||||||
|
String? title,
|
||||||
|
dynamic actions,
|
||||||
|
}) {
|
||||||
|
return showCustomDialog(
|
||||||
|
context: context!,
|
||||||
|
message: message!,
|
||||||
|
iconPath: Assets.deviceNoteIcon,
|
||||||
|
title: title,
|
||||||
|
dialogHeight: 150,
|
||||||
|
actions: actions ??
|
||||||
|
<Widget>[
|
||||||
|
TextButton(
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
child: const Text('OK'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -51,14 +51,16 @@ class ToggleDaySelectionEvent extends VisitorPasswordEvent {
|
|||||||
class ToggleRepeatEvent extends VisitorPasswordEvent {}
|
class ToggleRepeatEvent extends VisitorPasswordEvent {}
|
||||||
class GeneratePasswordEvent extends VisitorPasswordEvent {}
|
class GeneratePasswordEvent extends VisitorPasswordEvent {}
|
||||||
|
|
||||||
class FetchDevice extends VisitorPasswordEvent {}
|
class FetchDevice extends VisitorPasswordEvent {
|
||||||
|
}
|
||||||
|
|
||||||
//online password
|
//online password
|
||||||
class OnlineOneTimePasswordEvent extends VisitorPasswordEvent {
|
class OnlineOneTimePasswordEvent extends VisitorPasswordEvent {
|
||||||
final String? email;
|
final String? email;
|
||||||
final String? passwordName;
|
final String? passwordName;
|
||||||
|
final BuildContext? context;
|
||||||
|
|
||||||
const OnlineOneTimePasswordEvent({this.email,this.passwordName});
|
const OnlineOneTimePasswordEvent({this.email,this.passwordName,this.context});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [email!,passwordName!,];
|
List<Object> get props => [email!,passwordName!,];
|
||||||
@ -68,18 +70,20 @@ class OnlineMultipleTimePasswordEvent extends VisitorPasswordEvent {
|
|||||||
final String? passwordName;
|
final String? passwordName;
|
||||||
final String? invalidTime;
|
final String? invalidTime;
|
||||||
final String? effectiveTime;
|
final String? effectiveTime;
|
||||||
const OnlineMultipleTimePasswordEvent({this.email,this.passwordName,this.invalidTime,this.effectiveTime});
|
final BuildContext? context;
|
||||||
|
const OnlineMultipleTimePasswordEvent({this.email,this.passwordName,this.invalidTime,this.effectiveTime,this.context});
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [email!,passwordName!,invalidTime!,effectiveTime!];
|
List<Object> get props => [email!,passwordName!,invalidTime!,effectiveTime!,context!];
|
||||||
}
|
}
|
||||||
|
|
||||||
//offline password
|
//offline password
|
||||||
class OfflineOneTimePasswordEvent extends VisitorPasswordEvent {
|
class OfflineOneTimePasswordEvent extends VisitorPasswordEvent {
|
||||||
|
final BuildContext? context;
|
||||||
final String? email;
|
final String? email;
|
||||||
final String? passwordName;
|
final String? passwordName;
|
||||||
const OfflineOneTimePasswordEvent({this.email,this.passwordName});
|
const OfflineOneTimePasswordEvent({this.email,this.passwordName,this.context});
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [email!,passwordName!,];
|
List<Object> get props => [email!,passwordName!,context!,];
|
||||||
}
|
}
|
||||||
|
|
||||||
class OfflineMultipleTimePasswordEvent extends VisitorPasswordEvent {
|
class OfflineMultipleTimePasswordEvent extends VisitorPasswordEvent {
|
||||||
@ -87,11 +91,12 @@ class OfflineMultipleTimePasswordEvent extends VisitorPasswordEvent {
|
|||||||
final String? passwordName;
|
final String? passwordName;
|
||||||
final String? invalidTime;
|
final String? invalidTime;
|
||||||
final String? effectiveTime;
|
final String? effectiveTime;
|
||||||
|
final BuildContext? context;
|
||||||
|
|
||||||
const OfflineMultipleTimePasswordEvent({this.email,this.passwordName,this.invalidTime,this.effectiveTime});
|
const OfflineMultipleTimePasswordEvent({this.context,this.email,this.passwordName,this.invalidTime,this.effectiveTime});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [email!,passwordName!,invalidTime!,effectiveTime!];
|
List<Object> get props => [email!,passwordName!,invalidTime!,effectiveTime!,context!];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -115,4 +120,18 @@ class UpdateFilteredDevicesEvent extends VisitorPasswordEvent {
|
|||||||
final List<DeviceModel> filteredData;
|
final List<DeviceModel> filteredData;
|
||||||
|
|
||||||
UpdateFilteredDevicesEvent(this.filteredData);
|
UpdateFilteredDevicesEvent(this.filteredData);
|
||||||
|
}class SelectTimeEvent extends VisitorPasswordEvent {
|
||||||
|
final BuildContext context;
|
||||||
|
final bool isEffective;
|
||||||
|
const SelectTimeEvent({required this.context,required this.isEffective});
|
||||||
|
@override
|
||||||
|
List<Object> get props => [context,isEffective];
|
||||||
|
}
|
||||||
|
class ChangeTimeEvent extends VisitorPasswordEvent {
|
||||||
|
final dynamic val;
|
||||||
|
final bool isStartEndTime;
|
||||||
|
|
||||||
|
const ChangeTimeEvent({required this.val,required this.isStartEndTime});
|
||||||
|
@override
|
||||||
|
List<Object> get props => [val,isStartEndTime];
|
||||||
}
|
}
|
@ -41,8 +41,9 @@ class IsRepeatState extends VisitorPasswordState {
|
|||||||
|
|
||||||
class LoadingInitialState extends VisitorPasswordState {}
|
class LoadingInitialState extends VisitorPasswordState {}
|
||||||
class ChangeTimeState extends VisitorPasswordState {}
|
class ChangeTimeState extends VisitorPasswordState {}
|
||||||
|
class TimeSelectedState extends VisitorPasswordState {}
|
||||||
class DeviceLoaded extends VisitorPasswordState {}
|
class DeviceLoaded extends VisitorPasswordState {}
|
||||||
class GeneratePasswordState extends VisitorPasswordState {}
|
class SuccessState extends VisitorPasswordState {}
|
||||||
|
|
||||||
class FailedState extends VisitorPasswordState {
|
class FailedState extends VisitorPasswordState {
|
||||||
final String message;
|
final String message;
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:flutter_svg/flutter_svg.dart';
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
import 'package:syncrow_web/pages/common/buttons/search_reset_buttons.dart';
|
|
||||||
import 'package:syncrow_web/pages/common/custom_table.dart';
|
import 'package:syncrow_web/pages/common/custom_table.dart';
|
||||||
import 'package:syncrow_web/pages/common/text_field/custom_web_textfield.dart';
|
import 'package:syncrow_web/pages/common/text_field/custom_web_textfield.dart';
|
||||||
import 'package:syncrow_web/pages/common/buttons/default_button.dart';
|
import 'package:syncrow_web/pages/common/buttons/default_button.dart';
|
||||||
@ -14,7 +13,8 @@ import 'package:syncrow_web/utils/constants/const.dart';
|
|||||||
import 'package:syncrow_web/utils/style.dart';
|
import 'package:syncrow_web/utils/style.dart';
|
||||||
|
|
||||||
class AddDeviceDialog extends StatelessWidget {
|
class AddDeviceDialog extends StatelessWidget {
|
||||||
const AddDeviceDialog({super.key});
|
final List<String>? selectedDeviceIds;
|
||||||
|
const AddDeviceDialog({super.key, this.selectedDeviceIds});
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
Size size = MediaQuery.of(context).size;
|
Size size = MediaQuery.of(context).size;
|
||||||
@ -23,9 +23,23 @@ class AddDeviceDialog extends StatelessWidget {
|
|||||||
child: BlocBuilder<VisitorPasswordBloc, VisitorPasswordState>(
|
child: BlocBuilder<VisitorPasswordBloc, VisitorPasswordState>(
|
||||||
builder: (BuildContext context, VisitorPasswordState state) {
|
builder: (BuildContext context, VisitorPasswordState state) {
|
||||||
final visitorBloc = BlocProvider.of<VisitorPasswordBloc>(context);
|
final visitorBloc = BlocProvider.of<VisitorPasswordBloc>(context);
|
||||||
|
if (state is TableLoaded) {
|
||||||
|
for (var device in selectedDeviceIds!) {
|
||||||
|
if (selectedDeviceIds!.contains(device)) {
|
||||||
|
visitorBloc.add(SelectDeviceEvent(device));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return AlertDialog(
|
return AlertDialog(
|
||||||
backgroundColor: Colors.white,
|
backgroundColor: Colors.white,
|
||||||
title: const Text('Add Accessible Device'),
|
title: Text(
|
||||||
|
'Add Accessible Device',
|
||||||
|
style: Theme.of(context).textTheme.headlineLarge!.copyWith(
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
fontSize: 24,
|
||||||
|
color: Colors.black),
|
||||||
|
),
|
||||||
content: Container(
|
content: Container(
|
||||||
height: MediaQuery.of(context).size.height / 1.7,
|
height: MediaQuery.of(context).size.height / 1.7,
|
||||||
width: MediaQuery.of(context).size.width / 2,
|
width: MediaQuery.of(context).size.width / 2,
|
||||||
@ -49,21 +63,34 @@ class AddDeviceDialog extends StatelessWidget {
|
|||||||
width: 15,
|
width: 15,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(
|
const SizedBox(
|
||||||
width: 10,
|
width: 10,
|
||||||
),
|
),
|
||||||
Text('Only online accessible devices can be added'),
|
Text(
|
||||||
|
'Only online accessible devices can be added',
|
||||||
|
style: Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.bodySmall!
|
||||||
|
.copyWith(
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
fontSize: 12,
|
||||||
|
color: ColorsManager.grayColor),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
)),
|
)),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
height: 20,
|
height: 20,
|
||||||
),
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 20,
|
||||||
|
),
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
|
textBaseline: TextBaseline.alphabetic,
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
flex: 2,
|
flex: 4,
|
||||||
child: CustomWebTextField(
|
child: CustomWebTextField(
|
||||||
controller: visitorBloc.deviceNameController,
|
controller: visitorBloc.deviceNameController,
|
||||||
isRequired: true,
|
isRequired: true,
|
||||||
@ -73,7 +100,7 @@ class AddDeviceDialog extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
const SizedBox(width: 10),
|
const SizedBox(width: 10),
|
||||||
Expanded(
|
Expanded(
|
||||||
flex: 2,
|
flex: 4,
|
||||||
child: CustomWebTextField(
|
child: CustomWebTextField(
|
||||||
controller: visitorBloc.deviceIdController,
|
controller: visitorBloc.deviceIdController,
|
||||||
isRequired: true,
|
isRequired: true,
|
||||||
@ -83,7 +110,7 @@ class AddDeviceDialog extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
const SizedBox(width: 10),
|
const SizedBox(width: 10),
|
||||||
Expanded(
|
Expanded(
|
||||||
flex: 2,
|
flex: 4,
|
||||||
child: CustomWebTextField(
|
child: CustomWebTextField(
|
||||||
controller: visitorBloc.unitNameController,
|
controller: visitorBloc.unitNameController,
|
||||||
isRequired: true,
|
isRequired: true,
|
||||||
@ -92,24 +119,58 @@ class AddDeviceDialog extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 10),
|
const SizedBox(width: 10),
|
||||||
SearchResetButtons(
|
Expanded(
|
||||||
onSearch: () {
|
flex: 2,
|
||||||
|
child: Container(
|
||||||
|
child: SizedBox(
|
||||||
|
width: size.width * 0.06,
|
||||||
|
child: Center(
|
||||||
|
child: DefaultButton(
|
||||||
|
onPressed: () {
|
||||||
visitorBloc.filterDevices();
|
visitorBloc.filterDevices();
|
||||||
},
|
},
|
||||||
onReset: () {
|
borderRadius: 9,
|
||||||
|
child: const Text('Search'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 10),
|
||||||
|
Expanded(
|
||||||
|
flex: 2,
|
||||||
|
child: Container(
|
||||||
|
width: size.width * 0.06,
|
||||||
|
child: DefaultButton(
|
||||||
|
backgroundColor: ColorsManager.whiteColors,
|
||||||
|
borderRadius: 9,
|
||||||
|
child: Text(
|
||||||
|
'Reset',
|
||||||
|
style: Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.bodySmall!
|
||||||
|
.copyWith(color: Colors.black),
|
||||||
|
),
|
||||||
|
onPressed: () {
|
||||||
visitorBloc.deviceNameController.clear();
|
visitorBloc.deviceNameController.clear();
|
||||||
visitorBloc.deviceIdController.clear();
|
visitorBloc.deviceIdController.clear();
|
||||||
visitorBloc.unitNameController.clear();
|
visitorBloc.unitNameController.clear();
|
||||||
visitorBloc.add(FetchDevice());
|
visitorBloc.add(
|
||||||
|
FetchDevice()); // Reset to original list
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
Expanded(
|
Expanded(
|
||||||
|
flex: 3,
|
||||||
child: state is TableLoaded
|
child: state is TableLoaded
|
||||||
? DynamicTable(
|
? DynamicTable(
|
||||||
|
initialSelectedIds: selectedDeviceIds,
|
||||||
cellDecoration: containerDecoration,
|
cellDecoration: containerDecoration,
|
||||||
|
isEmpty: visitorBloc.data.isEmpty,
|
||||||
selectAll: (p0) {
|
selectAll: (p0) {
|
||||||
visitorBloc.selectedDeviceIds.clear();
|
visitorBloc.selectedDeviceIds.clear();
|
||||||
for (var item in state.data) {
|
for (var item in state.data) {
|
||||||
@ -167,7 +228,7 @@ class AddDeviceDialog extends StatelessWidget {
|
|||||||
width: size.width * 0.2,
|
width: size.width * 0.2,
|
||||||
child: DefaultButton(
|
child: DefaultButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.of(context).pop(); // Close the dialog
|
visitorBloc.addDeviceToList(context);
|
||||||
},
|
},
|
||||||
borderRadius: 8,
|
borderRadius: 8,
|
||||||
child: Text('Ok'),
|
child: Text('Ok'),
|
||||||
|
@ -5,6 +5,7 @@ import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_bloc.da
|
|||||||
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_event.dart';
|
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_event.dart';
|
||||||
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_state.dart';
|
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_state.dart';
|
||||||
import 'package:syncrow_web/utils/color_manager.dart';
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
|
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||||
|
|
||||||
class RepeatWidget extends StatelessWidget {
|
class RepeatWidget extends StatelessWidget {
|
||||||
const RepeatWidget({
|
const RepeatWidget({
|
||||||
@ -14,34 +15,36 @@ class RepeatWidget extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
Size size = MediaQuery.of(context).size;
|
Size size = MediaQuery.of(context).size;
|
||||||
|
|
||||||
return BlocBuilder<VisitorPasswordBloc, VisitorPasswordState>(
|
return BlocBuilder<VisitorPasswordBloc, VisitorPasswordState>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
final smartDoorBloc = BlocProvider.of<VisitorPasswordBloc>(context);
|
final visitorBloc = BlocProvider.of<VisitorPasswordBloc>(context);
|
||||||
return Column(
|
return Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Container(
|
// Wrap the Row in a SingleChildScrollView to handle overflow
|
||||||
width: size.width * 0.8,
|
SingleChildScrollView(
|
||||||
height: size.height * 0.06, // Adjust height as needed
|
|
||||||
child: ListView(
|
|
||||||
scrollDirection: Axis.horizontal,
|
scrollDirection: Axis.horizontal,
|
||||||
children: smartDoorBloc.days.map((day) {
|
child: Row(
|
||||||
|
children: visitorBloc.days.map((day) {
|
||||||
return Container(
|
return Container(
|
||||||
width: size.width* 0.09,
|
width: 70, // Adjust width as needed
|
||||||
|
margin: EdgeInsets.all(5),
|
||||||
child: CheckboxListTile(
|
child: CheckboxListTile(
|
||||||
|
contentPadding: EdgeInsets.zero,
|
||||||
title: Text(
|
title: Text(
|
||||||
day['day']!,
|
day['day']!,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 18,
|
fontSize: 10,
|
||||||
color: smartDoorBloc.selectedDays.contains(day['key'])
|
color: visitorBloc.selectedDays.contains(day['key'])
|
||||||
? Colors.black
|
? Colors.black
|
||||||
: ColorsManager.grayColor,
|
: ColorsManager.blackColor,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
value: smartDoorBloc.selectedDays.contains(day['key']),
|
value: visitorBloc.selectedDays.contains(day['key']),
|
||||||
onChanged: (bool? value) {
|
onChanged: (bool? value) {
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
smartDoorBloc.add(ToggleDaySelectionEvent(key: day['key']!));
|
visitorBloc.add(ToggleDaySelectionEvent(key: day['key']!));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -52,30 +55,32 @@ class RepeatWidget extends StatelessWidget {
|
|||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.all(8.0),
|
padding: const EdgeInsets.all(8.0),
|
||||||
child: DateTimeWebWidget(
|
child: DateTimeWebWidget(
|
||||||
|
icon: Assets.timeIcon,
|
||||||
isRequired: false,
|
isRequired: false,
|
||||||
title: '',
|
title: '',
|
||||||
size: size,
|
size: size,
|
||||||
endTime: () {
|
endTime: () {
|
||||||
smartDoorBloc.add(SelectTimeVisitorPassword(
|
visitorBloc.add(SelectTimeEvent(
|
||||||
isRepeat: true,
|
context: context,
|
||||||
context: context, isStart: false
|
isEffective: false));
|
||||||
));
|
Future.delayed(const Duration(milliseconds: 500), () {
|
||||||
|
visitorBloc.add(ChangeTimeEvent(val: visitorBloc.endTime, isStartEndTime: true));
|
||||||
|
});
|
||||||
},
|
},
|
||||||
startTime: () {
|
startTime: () {
|
||||||
smartDoorBloc.add(SelectTimeVisitorPassword(
|
Future.delayed(const Duration(milliseconds: 500), () {
|
||||||
isRepeat: true,
|
visitorBloc.add(ChangeTimeEvent(val: visitorBloc.endTime, isStartEndTime: true));
|
||||||
context: context, isStart: true
|
});
|
||||||
));
|
visitorBloc.add(SelectTimeEvent(context: context, isEffective: true));
|
||||||
},
|
},
|
||||||
firstString: smartDoorBloc.repeatStartTime.toString(),
|
firstString: visitorBloc.effectiveTime,
|
||||||
secondString: smartDoorBloc.repeatEndTime.toString(),
|
secondString: visitorBloc.expirationTime,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
const SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
|
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
});
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,17 @@
|
|||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/common/text_field/custom_web_textfield.dart';
|
import 'package:flutter_svg/svg.dart';
|
||||||
import 'package:syncrow_web/pages/common/date_time_widget.dart';
|
|
||||||
import 'package:syncrow_web/pages/common/buttons/default_button.dart';
|
import 'package:syncrow_web/pages/common/buttons/default_button.dart';
|
||||||
import 'package:syncrow_web/pages/common/info_dialog.dart';
|
import 'package:syncrow_web/pages/common/date_time_widget.dart';
|
||||||
|
import 'package:syncrow_web/pages/common/text_field/custom_web_textfield.dart';
|
||||||
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_bloc.dart';
|
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_event.dart';
|
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_event.dart';
|
||||||
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_state.dart';
|
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_state.dart';
|
||||||
import 'package:syncrow_web/pages/visitor_password/view/add_device_dialog.dart';
|
import 'package:syncrow_web/pages/visitor_password/view/add_device_dialog.dart';
|
||||||
import 'package:syncrow_web/pages/visitor_password/view/repeat_widget.dart';
|
import 'package:syncrow_web/pages/visitor_password/view/repeat_widget.dart';
|
||||||
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
|
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||||
import 'package:syncrow_web/utils/style.dart';
|
import 'package:syncrow_web/utils/style.dart';
|
||||||
|
|
||||||
class VisitorPasswordDialog extends StatelessWidget {
|
class VisitorPasswordDialog extends StatelessWidget {
|
||||||
@ -18,20 +20,50 @@ class VisitorPasswordDialog extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
Size size = MediaQuery.of(context).size;
|
Size size = MediaQuery.of(context).size;
|
||||||
|
var text = Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.bodySmall!
|
||||||
|
.copyWith(color: Colors.black, fontSize: 13);
|
||||||
return BlocProvider(
|
return BlocProvider(
|
||||||
create: (context) => VisitorPasswordBloc(),
|
create: (context) => VisitorPasswordBloc(),
|
||||||
|
child: BlocListener<VisitorPasswordBloc, VisitorPasswordState>(
|
||||||
|
listener: (context, state) {
|
||||||
|
final visitorBloc = BlocProvider.of<VisitorPasswordBloc>(context);
|
||||||
|
if (state is SuccessState) {
|
||||||
|
visitorBloc.stateDialog(
|
||||||
|
context: context,
|
||||||
|
message: 'Password Created Successfully',
|
||||||
|
title: 'Send Success',
|
||||||
|
);
|
||||||
|
} else if (state is FailedState) {
|
||||||
|
visitorBloc.stateDialog(
|
||||||
|
context: context,
|
||||||
|
message: state.message,
|
||||||
|
title: 'Something Wrong',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
child: BlocBuilder<VisitorPasswordBloc, VisitorPasswordState>(
|
child: BlocBuilder<VisitorPasswordBloc, VisitorPasswordState>(
|
||||||
builder: (BuildContext context, VisitorPasswordState state) {
|
builder: (BuildContext context, VisitorPasswordState state) {
|
||||||
final visitorBloc = BlocProvider.of<VisitorPasswordBloc>(context);
|
final visitorBloc = BlocProvider.of<VisitorPasswordBloc>(context);
|
||||||
bool isRepeat = state is IsRepeatState ? state.repeat : visitorBloc.repeat;
|
bool isRepeat =
|
||||||
|
state is IsRepeatState ? state.repeat : visitorBloc.repeat;
|
||||||
return AlertDialog(
|
return AlertDialog(
|
||||||
backgroundColor: Colors.white,
|
backgroundColor: Colors.white,
|
||||||
title: const Text('Create visitor password'),
|
title: Text(
|
||||||
content: SingleChildScrollView(
|
'Create visitor password',
|
||||||
|
style: Theme.of(context).textTheme.headlineLarge!.copyWith(
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
fontSize: 24,
|
||||||
|
color: Colors.black),
|
||||||
|
),
|
||||||
|
content: state is LoadingInitialState
|
||||||
|
? const Center(child: CircularProgressIndicator())
|
||||||
|
: SingleChildScrollView(
|
||||||
child: Form(
|
child: Form(
|
||||||
key: visitorBloc.forgetFormKey,
|
key: visitorBloc.forgetFormKey,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(10.0),
|
padding: const EdgeInsets.all(5.0),
|
||||||
child: ListBody(
|
child: ListBody(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Container(
|
Container(
|
||||||
@ -41,7 +73,8 @@ class VisitorPasswordDialog extends StatelessWidget {
|
|||||||
flex: 2,
|
flex: 2,
|
||||||
child: CustomWebTextField(
|
child: CustomWebTextField(
|
||||||
validator: visitorBloc.validate,
|
validator: visitorBloc.validate,
|
||||||
controller: visitorBloc.userNameController,
|
controller:
|
||||||
|
visitorBloc.userNameController,
|
||||||
isRequired: true,
|
isRequired: true,
|
||||||
textFieldName: 'Name',
|
textFieldName: 'Name',
|
||||||
description: '',
|
description: '',
|
||||||
@ -51,18 +84,21 @@ class VisitorPasswordDialog extends StatelessWidget {
|
|||||||
Expanded(
|
Expanded(
|
||||||
flex: 2,
|
flex: 2,
|
||||||
child: CustomWebTextField(
|
child: CustomWebTextField(
|
||||||
validator: visitorBloc.validate,
|
validator: visitorBloc.validateEmail,
|
||||||
controller: visitorBloc.emailController,
|
controller: visitorBloc.emailController,
|
||||||
isRequired: true,
|
isRequired: true,
|
||||||
textFieldName: 'Email Address',
|
textFieldName: 'Email Address',
|
||||||
description: 'The password will be sent to the visitor’s email address.',
|
description:
|
||||||
|
'The password will be sent to the visitor’s email address.',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const Spacer(),
|
const Spacer(),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 20,),
|
const SizedBox(
|
||||||
|
height: 15,
|
||||||
|
),
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
@ -75,72 +111,100 @@ class VisitorPasswordDialog extends StatelessWidget {
|
|||||||
.bodyMedium!
|
.bodyMedium!
|
||||||
.copyWith(color: Colors.red),
|
.copyWith(color: Colors.red),
|
||||||
),
|
),
|
||||||
const Text('Access Type'),
|
Text('Access Type', style: text),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
Row(
|
Row(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
SizedBox(
|
Flexible(
|
||||||
width: size.width * 0.15,
|
|
||||||
child: RadioListTile<String>(
|
child: RadioListTile<String>(
|
||||||
title: const Text('Online Password'),
|
contentPadding: EdgeInsets.zero,
|
||||||
|
title: Text(
|
||||||
|
'Online Password',
|
||||||
|
style: text,
|
||||||
|
),
|
||||||
value: 'Online Password',
|
value: 'Online Password',
|
||||||
groupValue: (state is PasswordTypeSelected)
|
groupValue: (state
|
||||||
|
is PasswordTypeSelected)
|
||||||
? state.selectedType
|
? state.selectedType
|
||||||
: visitorBloc.accessTypeSelected,
|
: visitorBloc.accessTypeSelected,
|
||||||
onChanged: (String? value) {
|
onChanged: (String? value) {
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
print(value);
|
context
|
||||||
context.read<VisitorPasswordBloc>().add(SelectPasswordType(value));
|
.read<VisitorPasswordBloc>()
|
||||||
|
.add(SelectPasswordType(
|
||||||
|
value));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
Flexible(
|
||||||
SizedBox(
|
|
||||||
width: size.width * 0.15,
|
|
||||||
child: RadioListTile<String>(
|
child: RadioListTile<String>(
|
||||||
title: const Text('Offline Password'),
|
contentPadding: EdgeInsets.zero,
|
||||||
|
title: Text('Offline Password',
|
||||||
|
style: text),
|
||||||
value: 'Offline Password',
|
value: 'Offline Password',
|
||||||
groupValue: (state is PasswordTypeSelected)
|
groupValue: (state
|
||||||
|
is PasswordTypeSelected)
|
||||||
? state.selectedType
|
? state.selectedType
|
||||||
: visitorBloc.accessTypeSelected,
|
: visitorBloc.accessTypeSelected,
|
||||||
onChanged: (String? value) {
|
onChanged: (String? value) {
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
print(value);
|
context
|
||||||
|
.read<VisitorPasswordBloc>()
|
||||||
context.read<VisitorPasswordBloc>().add(SelectPasswordType(value));
|
.add(SelectPasswordType(
|
||||||
|
value));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
Flexible(
|
||||||
SizedBox(
|
|
||||||
width: size.width * 0.15,
|
|
||||||
child: RadioListTile<String>(
|
child: RadioListTile<String>(
|
||||||
title: const Text('Dynamic Password'),
|
contentPadding: EdgeInsets.zero,
|
||||||
|
title: Text(
|
||||||
|
'Dynamic Password',
|
||||||
|
style: text,
|
||||||
|
),
|
||||||
value: 'Dynamic Password',
|
value: 'Dynamic Password',
|
||||||
groupValue: (state is PasswordTypeSelected)
|
groupValue: (state
|
||||||
|
is PasswordTypeSelected)
|
||||||
? state.selectedType
|
? state.selectedType
|
||||||
: visitorBloc.accessTypeSelected,
|
: visitorBloc.accessTypeSelected,
|
||||||
onChanged: (String? value) {
|
onChanged: (String? value) {
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
context.read<VisitorPasswordBloc>().add(SelectPasswordType(value));
|
context
|
||||||
visitorBloc.usageFrequencySelected='';
|
.read<VisitorPasswordBloc>()
|
||||||
|
.add(SelectPasswordType(
|
||||||
|
value));
|
||||||
|
visitorBloc
|
||||||
|
.usageFrequencySelected = '';
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const Text('Only currently online devices can be selected. It is recommended to use when the device network is stable, and the system randomly generates a digital password'),
|
Text(
|
||||||
const SizedBox(height: 20,)
|
'Only currently online devices can be selected. It is recommended to use when the device network is stable, and the system randomly generates a digital password',
|
||||||
|
style: Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.bodySmall!
|
||||||
|
.copyWith(
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
color: ColorsManager.grayColor,
|
||||||
|
fontSize: 9),
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 20,
|
||||||
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
visitorBloc.accessTypeSelected=='Dynamic Password' ?
|
visitorBloc.accessTypeSelected ==
|
||||||
SizedBox():
|
'Dynamic Password'
|
||||||
Column(
|
? const SizedBox()
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
: Column(
|
||||||
|
crossAxisAlignment:
|
||||||
|
CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
@ -151,70 +215,108 @@ class VisitorPasswordDialog extends StatelessWidget {
|
|||||||
.bodyMedium!
|
.bodyMedium!
|
||||||
.copyWith(color: Colors.red),
|
.copyWith(color: Colors.red),
|
||||||
),
|
),
|
||||||
const Text('Usage Frequency'),
|
Text(
|
||||||
|
'Usage Frequency',
|
||||||
|
style: text,
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
Row(
|
Row(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
SizedBox(
|
Flexible(
|
||||||
width: 200,
|
|
||||||
child: RadioListTile<String>(
|
child: RadioListTile<String>(
|
||||||
title: const Text('One-Time'),
|
contentPadding: EdgeInsets.zero,
|
||||||
|
title: Text(
|
||||||
|
'One-Time',
|
||||||
|
style: text,
|
||||||
|
),
|
||||||
value: 'One-Time',
|
value: 'One-Time',
|
||||||
groupValue: (state is UsageFrequencySelected)
|
groupValue: (state
|
||||||
|
is UsageFrequencySelected)
|
||||||
? state.selectedFrequency
|
? state.selectedFrequency
|
||||||
: visitorBloc.usageFrequencySelected,
|
: visitorBloc
|
||||||
|
.usageFrequencySelected,
|
||||||
onChanged: (String? value) {
|
onChanged: (String? value) {
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
print(value);
|
context
|
||||||
|
.read<
|
||||||
context.read<VisitorPasswordBloc>().add(SelectUsageFrequency(value));
|
VisitorPasswordBloc>()
|
||||||
|
.add(
|
||||||
|
SelectUsageFrequency(
|
||||||
|
value));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(
|
Flexible(
|
||||||
width: 200,
|
|
||||||
child: RadioListTile<String>(
|
child: RadioListTile<String>(
|
||||||
title: const Text('Periodic'),
|
contentPadding: EdgeInsets.zero,
|
||||||
|
title: Text('Periodic',
|
||||||
|
style: text),
|
||||||
value: 'Periodic',
|
value: 'Periodic',
|
||||||
groupValue: (state is UsageFrequencySelected)
|
groupValue: (state
|
||||||
|
is UsageFrequencySelected)
|
||||||
? state.selectedFrequency
|
? state.selectedFrequency
|
||||||
: visitorBloc.usageFrequencySelected,
|
: visitorBloc
|
||||||
|
.usageFrequencySelected,
|
||||||
onChanged: (String? value) {
|
onChanged: (String? value) {
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
context.read<VisitorPasswordBloc>().add(SelectUsageFrequency(value));
|
context
|
||||||
|
.read<
|
||||||
|
VisitorPasswordBloc>()
|
||||||
|
.add(
|
||||||
|
SelectUsageFrequency(
|
||||||
|
value));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
Text(
|
||||||
const Text('Within the validity period, each device can be unlocked only once.')
|
'Within the validity period, each device can be unlocked only once.',
|
||||||
|
style: Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.bodySmall!
|
||||||
|
.copyWith(
|
||||||
|
color:
|
||||||
|
ColorsManager.grayColor,
|
||||||
|
fontSize: 9),
|
||||||
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 20,),
|
const SizedBox(
|
||||||
if((visitorBloc.usageFrequencySelected!='One-Time'||visitorBloc.accessTypeSelected!='Offline Password')&&(visitorBloc.usageFrequencySelected!=''))
|
height: 20,
|
||||||
|
),
|
||||||
|
if ((visitorBloc.usageFrequencySelected !=
|
||||||
|
'One-Time' ||
|
||||||
|
visitorBloc.accessTypeSelected !=
|
||||||
|
'Offline Password') &&
|
||||||
|
(visitorBloc.usageFrequencySelected != ''))
|
||||||
DateTimeWebWidget(
|
DateTimeWebWidget(
|
||||||
|
|
||||||
isRequired: true,
|
isRequired: true,
|
||||||
title: 'Access Period',
|
title: 'Access Period',
|
||||||
size: size,
|
size: size,
|
||||||
endTime: () {
|
endTime: () {
|
||||||
visitorBloc.add(SelectTimeVisitorPassword(
|
visitorBloc.add(SelectTimeVisitorPassword(
|
||||||
context: context, isStart: false,isRepeat:false));
|
context: context,
|
||||||
|
isStart: false,
|
||||||
|
isRepeat: false));
|
||||||
},
|
},
|
||||||
startTime: () {
|
startTime: () {
|
||||||
visitorBloc.add(SelectTimeVisitorPassword(
|
visitorBloc.add(SelectTimeVisitorPassword(
|
||||||
context: context, isStart: true,isRepeat:false));
|
context: context,
|
||||||
|
isStart: true,
|
||||||
|
isRepeat: false));
|
||||||
},
|
},
|
||||||
firstString: visitorBloc.startTime,
|
firstString:
|
||||||
secondString: visitorBloc.endTime,
|
visitorBloc.startTimeAccess.toString(),
|
||||||
|
secondString:
|
||||||
|
visitorBloc.endTimeAccess.toString(),
|
||||||
|
icon: Assets.calendarIcon),
|
||||||
|
const SizedBox(
|
||||||
|
height: 20,
|
||||||
),
|
),
|
||||||
|
|
||||||
const SizedBox(height: 20,),
|
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
@ -227,51 +329,92 @@ class VisitorPasswordDialog extends StatelessWidget {
|
|||||||
.bodyMedium!
|
.bodyMedium!
|
||||||
.copyWith(color: Colors.red),
|
.copyWith(color: Colors.red),
|
||||||
),
|
),
|
||||||
const Text('Access Devices'),
|
Text(
|
||||||
|
'Access Devices',
|
||||||
|
style: text,
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const Text('Within the validity period, each device can be unlocked only once.'),
|
Text(
|
||||||
const SizedBox(height: 20,),
|
'Within the validity period, each device can be unlocked only once.',
|
||||||
if(visitorBloc.usageFrequencySelected=='Periodic'&&visitorBloc.accessTypeSelected=='Online Password')
|
style: Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.bodySmall!
|
||||||
|
.copyWith(
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
color: ColorsManager.grayColor,
|
||||||
|
fontSize: 9),
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 20,
|
||||||
|
),
|
||||||
|
if (visitorBloc.usageFrequencySelected ==
|
||||||
|
'Periodic' &&
|
||||||
|
visitorBloc.accessTypeSelected ==
|
||||||
|
'Online Password')
|
||||||
SizedBox(
|
SizedBox(
|
||||||
width: 100,
|
width: 100,
|
||||||
child: ListTile(
|
child: Column(
|
||||||
contentPadding: EdgeInsets.zero,
|
children: [
|
||||||
leading: const Text('Repeat'),
|
Text('Repeat', style: text),
|
||||||
trailing: Transform.scale(
|
Transform.scale(
|
||||||
scale: .8,
|
scale: .8,
|
||||||
child: CupertinoSwitch(
|
child: CupertinoSwitch(
|
||||||
value: visitorBloc.repeat,
|
value: visitorBloc.repeat,
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
visitorBloc.add(ToggleRepeatEvent());
|
visitorBloc
|
||||||
|
.add(ToggleRepeatEvent());
|
||||||
},
|
},
|
||||||
applyTheme: true,
|
applyTheme: true,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if(visitorBloc.usageFrequencySelected=='Periodic'&&visitorBloc.accessTypeSelected=='Online Password')
|
if (visitorBloc.usageFrequencySelected ==
|
||||||
isRepeat ? const RepeatWidget() : const SizedBox(),
|
'Periodic' &&
|
||||||
|
visitorBloc.accessTypeSelected ==
|
||||||
|
'Online Password')
|
||||||
|
isRepeat
|
||||||
|
? const RepeatWidget()
|
||||||
|
: const SizedBox(),
|
||||||
Container(
|
Container(
|
||||||
decoration: containerDecoration,
|
decoration: containerDecoration,
|
||||||
width: size.width * 0.1,
|
width: size.width / 9,
|
||||||
child: DefaultButton(
|
child: DefaultButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
showDialog(
|
showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
barrierDismissible: false,
|
barrierDismissible: false,
|
||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
return const AddDeviceDialog();
|
return AddDeviceDialog(
|
||||||
},
|
selectedDeviceIds:
|
||||||
|
visitorBloc.selectedDevices,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
).then((listDevice) {
|
||||||
|
if (listDevice != null) {
|
||||||
|
visitorBloc.selectedDevices =
|
||||||
|
listDevice;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
borderRadius: 8,
|
borderRadius: 8,
|
||||||
child: Text('+ Add Device'),
|
child: Text(
|
||||||
|
'+ Add Device',
|
||||||
|
style: Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.bodySmall!
|
||||||
|
.copyWith(
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
color:
|
||||||
|
ColorsManager.whiteColors,
|
||||||
|
fontSize: 12),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -285,12 +428,15 @@ class VisitorPasswordDialog extends StatelessWidget {
|
|||||||
child: DefaultButton(
|
child: DefaultButton(
|
||||||
borderRadius: 8,
|
borderRadius: 8,
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.of(context).pop(); // Close the dialog
|
Navigator.of(context).pop(true);
|
||||||
},
|
},
|
||||||
backgroundColor: Colors.white,
|
backgroundColor: Colors.white,
|
||||||
child: Text(
|
child: Text(
|
||||||
'Cancel',
|
'Cancel',
|
||||||
style: Theme.of(context).textTheme.bodyMedium!,
|
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
color: ColorsManager.blackColor,
|
||||||
|
fontSize: 16),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -299,89 +445,198 @@ class VisitorPasswordDialog extends StatelessWidget {
|
|||||||
width: size.width * 0.2,
|
width: size.width * 0.2,
|
||||||
child: DefaultButton(
|
child: DefaultButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
if(visitorBloc.forgetFormKey.currentState!.validate()){
|
if (visitorBloc.forgetFormKey.currentState!.validate()) {
|
||||||
showDialog(
|
if (visitorBloc.selectedDevices.isNotEmpty) {
|
||||||
|
if (visitorBloc.effectiveTimeTimeStamp != null &&
|
||||||
|
visitorBloc.expirationTimeTimeStamp != null) {
|
||||||
|
setPasswordFunction(context, size, visitorBloc);
|
||||||
|
} else {
|
||||||
|
visitorBloc.stateDialog(
|
||||||
context: context,
|
context: context,
|
||||||
barrierDismissible: false,
|
message:
|
||||||
builder: (BuildContext context) {
|
'Please select Access Period to continue',
|
||||||
return InfoDialog(
|
title: 'Access Period');
|
||||||
size: size,
|
}
|
||||||
title: 'Set Password',
|
} else {
|
||||||
content: 'This action will update all of the selected\n door locks passwords in the property.\n\nAre you sure you want to continue?',
|
visitorBloc.stateDialog(
|
||||||
|
context: context,
|
||||||
actions: [
|
message: 'Please select devices to continue',
|
||||||
Container(
|
title: 'Select Devices');
|
||||||
decoration: containerDecoration,
|
}
|
||||||
width: size.width * 0.1,
|
}
|
||||||
child: DefaultButton(
|
|
||||||
borderRadius: 8,
|
|
||||||
onPressed: () {
|
|
||||||
Navigator.of(context).pop(); // Close the dialog
|
|
||||||
},
|
},
|
||||||
backgroundColor: Colors.white,
|
borderRadius: 8,
|
||||||
child: Text(
|
child: Text(
|
||||||
'Cancel',
|
|
||||||
style: Theme.of(context).textTheme.bodyMedium!,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Container(
|
|
||||||
decoration: containerDecoration,
|
|
||||||
width: size.width * 0.1,
|
|
||||||
child: DefaultButton(
|
|
||||||
borderRadius: 8,
|
|
||||||
onPressed: () {
|
|
||||||
if(visitorBloc.usageFrequencySelected=='One-Time'&&visitorBloc.accessTypeSelected=='Online Password'){
|
|
||||||
visitorBloc.add(OnlineOneTimePasswordEvent(
|
|
||||||
passwordName:visitorBloc.userNameController.text ,
|
|
||||||
email: visitorBloc.emailController.text
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else if(visitorBloc.usageFrequencySelected=='Periodic'&&visitorBloc.accessTypeSelected=='Online Password') {
|
|
||||||
visitorBloc.add(OnlineMultipleTimePasswordEvent(
|
|
||||||
passwordName:visitorBloc.userNameController.text ,
|
|
||||||
email: visitorBloc.emailController.text,
|
|
||||||
effectiveTime:visitorBloc.effectiveTimeTimeStamp.toString() ,
|
|
||||||
invalidTime:visitorBloc.expirationTimeTimeStamp.toString()
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else if(visitorBloc.usageFrequencySelected=='One-Time'&&visitorBloc.accessTypeSelected=='Offline Password') {
|
|
||||||
visitorBloc.add(OfflineOneTimePasswordEvent(
|
|
||||||
passwordName:visitorBloc.userNameController.text ,
|
|
||||||
email: visitorBloc.emailController.text,
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else if(visitorBloc.usageFrequencySelected=='Periodic'&&visitorBloc.accessTypeSelected=='Offline Password') {
|
|
||||||
visitorBloc.add(OfflineMultipleTimePasswordEvent(
|
|
||||||
passwordName:visitorBloc.userNameController.text ,
|
|
||||||
email: visitorBloc.emailController.text,
|
|
||||||
effectiveTime:visitorBloc.effectiveTimeTimeStamp.toString() ,
|
|
||||||
invalidTime:visitorBloc.expirationTimeTimeStamp.toString()
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
child: const Text(
|
|
||||||
'Ok',
|
'Ok',
|
||||||
|
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
color: ColorsManager.whiteColors,
|
||||||
|
fontSize: 16),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
borderRadius: 8,
|
|
||||||
child: Text('Ok'),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> setPasswordFunction(
|
||||||
|
BuildContext context,
|
||||||
|
Size size,
|
||||||
|
VisitorPasswordBloc visitorBloc,
|
||||||
|
) {
|
||||||
|
return showDialog<void>(
|
||||||
|
context: context,
|
||||||
|
barrierDismissible: false,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return BlocBuilder<VisitorPasswordBloc, VisitorPasswordState>(
|
||||||
|
builder: (context, state) {
|
||||||
|
if (state is LoadingInitialState) {
|
||||||
|
// Show loading indicator while loading
|
||||||
|
return AlertDialog(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
content: SizedBox(
|
||||||
|
height: size.height * 0.25,
|
||||||
|
child: Center(
|
||||||
|
child:
|
||||||
|
CircularProgressIndicator(), // Display a loading spinner
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return AlertDialog(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
content: SizedBox(
|
||||||
|
height: size.height * 0.25,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
SizedBox(
|
||||||
|
child: SvgPicture.asset(
|
||||||
|
Assets.deviceNoteIcon,
|
||||||
|
height: 35,
|
||||||
|
width: 35,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
'Set Password',
|
||||||
|
style: Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.headlineLarge!
|
||||||
|
.copyWith(
|
||||||
|
fontSize: 30,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
color: Colors.black,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(width: 15),
|
||||||
|
Text(
|
||||||
|
'This action will update all of the selected\n door locks passwords in the property.\n\nAre you sure you want to continue?',
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
|
||||||
|
color: ColorsManager.grayColor,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
fontSize: 18,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
actionsAlignment: MainAxisAlignment.center,
|
||||||
|
actions: <Widget>[
|
||||||
|
Container(
|
||||||
|
decoration: containerDecoration,
|
||||||
|
width: size.width * 0.1,
|
||||||
|
child: DefaultButton(
|
||||||
|
borderRadius: 8,
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
backgroundColor: Colors.white,
|
||||||
|
child: Text(
|
||||||
|
'Cancel',
|
||||||
|
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
color: ColorsManager.blackColor,
|
||||||
|
fontSize: 16,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
decoration: containerDecoration,
|
||||||
|
width: size.width * 0.1,
|
||||||
|
child: DefaultButton(
|
||||||
|
borderRadius: 8,
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
if (visitorBloc.usageFrequencySelected == 'One-Time' &&
|
||||||
|
visitorBloc.accessTypeSelected ==
|
||||||
|
'Online Password') {
|
||||||
|
visitorBloc.add(OnlineOneTimePasswordEvent(
|
||||||
|
context: context,
|
||||||
|
passwordName: visitorBloc.userNameController.text,
|
||||||
|
email: visitorBloc.emailController.text,
|
||||||
|
));
|
||||||
|
} else if (visitorBloc.usageFrequencySelected ==
|
||||||
|
'Periodic' &&
|
||||||
|
visitorBloc.accessTypeSelected ==
|
||||||
|
'Online Password') {
|
||||||
|
visitorBloc.add(OnlineMultipleTimePasswordEvent(
|
||||||
|
passwordName: visitorBloc.userNameController.text,
|
||||||
|
email: visitorBloc.emailController.text,
|
||||||
|
effectiveTime:
|
||||||
|
visitorBloc.effectiveTimeTimeStamp.toString(),
|
||||||
|
invalidTime:
|
||||||
|
visitorBloc.expirationTimeTimeStamp.toString(),
|
||||||
|
));
|
||||||
|
} else if (visitorBloc.usageFrequencySelected ==
|
||||||
|
'One-Time' &&
|
||||||
|
visitorBloc.accessTypeSelected ==
|
||||||
|
'Offline Password') {
|
||||||
|
visitorBloc.add(OfflineOneTimePasswordEvent(
|
||||||
|
context: context,
|
||||||
|
passwordName: visitorBloc.userNameController.text,
|
||||||
|
email: visitorBloc.emailController.text,
|
||||||
|
));
|
||||||
|
} else if (visitorBloc.usageFrequencySelected ==
|
||||||
|
'Periodic' &&
|
||||||
|
visitorBloc.accessTypeSelected ==
|
||||||
|
'Offline Password') {
|
||||||
|
visitorBloc.add(OfflineMultipleTimePasswordEvent(
|
||||||
|
passwordName: visitorBloc.userNameController.text,
|
||||||
|
email: visitorBloc.emailController.text,
|
||||||
|
effectiveTime:
|
||||||
|
visitorBloc.effectiveTimeTimeStamp.toString(),
|
||||||
|
invalidTime:
|
||||||
|
visitorBloc.expirationTimeTimeStamp.toString(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: Text(
|
||||||
|
'Ok',
|
||||||
|
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
color: ColorsManager.whiteColors,
|
||||||
|
fontSize: 16,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
import 'package:dio/dio.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:syncrow_web/pages/access_management/model/password_model.dart';
|
import 'package:syncrow_web/pages/access_management/model/password_model.dart';
|
||||||
|
import 'package:syncrow_web/pages/visitor_password/model/device_model.dart';
|
||||||
import 'package:syncrow_web/pages/visitor_password/model/schedule_model.dart';
|
import 'package:syncrow_web/pages/visitor_password/model/schedule_model.dart';
|
||||||
import 'package:syncrow_web/services/api/http_service.dart';
|
import 'package:syncrow_web/services/api/http_service.dart';
|
||||||
import 'package:syncrow_web/utils/constants/api_const.dart';
|
import 'package:syncrow_web/utils/constants/api_const.dart';
|
||||||
|
|
||||||
import '../pages/visitor_password/model/device_model.dart';
|
|
||||||
|
|
||||||
class AccessMangApi{
|
class AccessMangApi{
|
||||||
|
|
||||||
Future<List<PasswordModel>> fetchVisitorPassword() async {
|
Future<List<PasswordModel>> fetchVisitorPassword() async {
|
||||||
@ -16,7 +16,6 @@ class AccessMangApi{
|
|||||||
showServerMessage: true,
|
showServerMessage: true,
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
List<dynamic> jsonData = json;
|
List<dynamic> jsonData = json;
|
||||||
print('Password List: $json');
|
|
||||||
List<PasswordModel> passwordList = jsonData.map((jsonItem) {
|
List<PasswordModel> passwordList = jsonData.map((jsonItem) {
|
||||||
return PasswordModel.fromJson(jsonItem);
|
return PasswordModel.fromJson(jsonItem);
|
||||||
}).toList();
|
}).toList();
|
||||||
@ -37,7 +36,6 @@ class AccessMangApi{
|
|||||||
showServerMessage: true,
|
showServerMessage: true,
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
List<dynamic> jsonData = json;
|
List<dynamic> jsonData = json;
|
||||||
print('fetchDevices List: $json');
|
|
||||||
List<DeviceModel> passwordList = jsonData.map((jsonItem) {
|
List<DeviceModel> passwordList = jsonData.map((jsonItem) {
|
||||||
return DeviceModel.fromJson(jsonItem);
|
return DeviceModel.fromJson(jsonItem);
|
||||||
}).toList();
|
}).toList();
|
||||||
@ -51,34 +49,38 @@ class AccessMangApi{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future postOnlineOneTime({String? email,String? passwordName,List<String>? devicesUuid}) async {
|
Future<bool> postOnlineOneTime({
|
||||||
|
String? email,
|
||||||
|
String? passwordName,
|
||||||
|
String? password,
|
||||||
|
String? effectiveTime,
|
||||||
|
String? invalidTime,
|
||||||
|
List<String>? devicesUuid}) async {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
print('postOfflineOneTime List: ${
|
|
||||||
{
|
|
||||||
"email": email,
|
|
||||||
"passwordName": passwordName,
|
|
||||||
"devicesUuid": devicesUuid
|
|
||||||
}
|
|
||||||
}');
|
|
||||||
|
|
||||||
final response = await HTTPService().post(
|
final response = await HTTPService().post(
|
||||||
path: ApiEndpoints.sendOnlineOneTime,
|
path: ApiEndpoints.sendOnlineOneTime,
|
||||||
body: jsonEncode({
|
body: jsonEncode({
|
||||||
"email": email,
|
"email": email,
|
||||||
"passwordName": passwordName,
|
"passwordName": passwordName,
|
||||||
"devicesUuid": devicesUuid
|
"password": password,
|
||||||
|
"devicesUuid": devicesUuid,
|
||||||
|
"effectiveTime":effectiveTime ,
|
||||||
|
"invalidTime": invalidTime
|
||||||
}),
|
}),
|
||||||
showServerMessage: true,
|
showServerMessage: true,
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
List<dynamic> jsonData = json;
|
if(json['statusCode'].toString()=='201'){
|
||||||
print('postOfflineOneTime List: $json');
|
return true;
|
||||||
|
}else{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
return response;
|
return response;
|
||||||
} catch (e) {
|
} on DioException catch (e) {
|
||||||
debugPrint('Error fetching $e');
|
debugPrint('Error: ${e.message}');
|
||||||
return [];
|
debugPrint('Error fetching ${e.response!.statusMessage}');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,25 +101,26 @@ class AccessMangApi{
|
|||||||
"effectiveTime": effectiveTime,
|
"effectiveTime": effectiveTime,
|
||||||
"invalidTime": invalidTime,
|
"invalidTime": invalidTime,
|
||||||
};
|
};
|
||||||
print('createPassword =${scheduleList![0].workingDay}');
|
|
||||||
if (scheduleList != null) {
|
if (scheduleList != null) {
|
||||||
body["scheduleList"] = scheduleList.map((schedule) => schedule.toJson()).toList();
|
body["scheduleList"] = scheduleList.map((schedule) => schedule.toJson()).toList();
|
||||||
}
|
}
|
||||||
print('createPassword =$body');
|
|
||||||
|
|
||||||
final response = await HTTPService().post(
|
final response = await HTTPService().post(
|
||||||
path: ApiEndpoints.sendOnlineMultipleTime,
|
path: ApiEndpoints.sendOnlineMultipleTime,
|
||||||
body: jsonEncode(body),
|
body: jsonEncode(body),
|
||||||
showServerMessage: true,
|
showServerMessage: true,
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
List<dynamic> jsonData = json;
|
if(json['data']['successOperations'][0]['success'].toString()=='true'){
|
||||||
print('postOfflineOneTime List: $json');
|
return true;
|
||||||
|
}else{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
return response;
|
return response;
|
||||||
} catch (e) {
|
} on DioException catch (e){
|
||||||
debugPrint('Error fetching $e');
|
debugPrint('Error fetching ${e.type.name}');
|
||||||
return [];
|
debugPrint('Error fetching ${e.response!.statusMessage}');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,15 +128,6 @@ class AccessMangApi{
|
|||||||
|
|
||||||
Future postOffLineOneTime({String? email,String? passwordName,List<String>? devicesUuid}) async {
|
Future postOffLineOneTime({String? email,String? passwordName,List<String>? devicesUuid}) async {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
print('postOfflineOneTime List: ${
|
|
||||||
{
|
|
||||||
"email": email,
|
|
||||||
"passwordName": passwordName,
|
|
||||||
"devicesUuid": devicesUuid
|
|
||||||
}
|
|
||||||
}');
|
|
||||||
|
|
||||||
final response = await HTTPService().post(
|
final response = await HTTPService().post(
|
||||||
path: ApiEndpoints.sendOffLineOneTime,
|
path: ApiEndpoints.sendOffLineOneTime,
|
||||||
body: jsonEncode({
|
body: jsonEncode({
|
||||||
@ -143,9 +137,13 @@ class AccessMangApi{
|
|||||||
}),
|
}),
|
||||||
showServerMessage: true,
|
showServerMessage: true,
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
List<dynamic> jsonData = json;
|
if (json['data']['successOperations'][0]['success'].toString() ==
|
||||||
print('postOfflineOneTime List: $json');
|
'true') {
|
||||||
},
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
);
|
);
|
||||||
return response;
|
return response;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -163,15 +161,6 @@ class AccessMangApi{
|
|||||||
|
|
||||||
}) async {
|
}) async {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
print('postOfflineOneTime List: ${
|
|
||||||
{
|
|
||||||
"email": email,
|
|
||||||
"passwordName": passwordName,
|
|
||||||
"devicesUuid": devicesUuid
|
|
||||||
}
|
|
||||||
}');
|
|
||||||
|
|
||||||
final response = await HTTPService().post(
|
final response = await HTTPService().post(
|
||||||
path: ApiEndpoints.sendOffLineOneTime,
|
path: ApiEndpoints.sendOffLineOneTime,
|
||||||
body: jsonEncode({
|
body: jsonEncode({
|
||||||
@ -183,9 +172,13 @@ class AccessMangApi{
|
|||||||
}),
|
}),
|
||||||
showServerMessage: true,
|
showServerMessage: true,
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
List<dynamic> jsonData = json;
|
if (json['data']['successOperations'][0]['success'].toString() ==
|
||||||
print('postOfflineOneTime List: $json');
|
'true') {
|
||||||
},
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
);
|
);
|
||||||
return response;
|
return response;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import 'dart:convert';
|
|
||||||
|
|
||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
@ -8,9 +7,7 @@ import 'package:syncrow_web/services/api/http_service.dart';
|
|||||||
import 'package:syncrow_web/utils/constants/api_const.dart';
|
import 'package:syncrow_web/utils/constants/api_const.dart';
|
||||||
|
|
||||||
class AuthenticationAPI {
|
class AuthenticationAPI {
|
||||||
|
|
||||||
static Future<Token> loginWithEmail({required var model}) async {
|
static Future<Token> loginWithEmail({required var model}) async {
|
||||||
print('model=$model');
|
|
||||||
final response = await HTTPService().post(
|
final response = await HTTPService().post(
|
||||||
path: ApiEndpoints.login,
|
path: ApiEndpoints.login,
|
||||||
body: model.toJson(),
|
body: model.toJson(),
|
||||||
@ -46,19 +43,15 @@ class AuthenticationAPI {
|
|||||||
},
|
},
|
||||||
showServerMessage: true,
|
showServerMessage: true,
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
print('object==$json');
|
|
||||||
return 30;
|
return 30;
|
||||||
}
|
}
|
||||||
|
|
||||||
);
|
);
|
||||||
return 30;
|
return 30;
|
||||||
} on DioException catch (e) {
|
} on DioException catch (e) {
|
||||||
if (e.response != null) {
|
if (e.response != null) {
|
||||||
if (e.response!.statusCode == 400) {
|
if (e.response!.statusCode == 400) {
|
||||||
// Handle 400 Bad Request
|
|
||||||
final errorData = e.response!.data;
|
final errorData = e.response!.data;
|
||||||
String errorMessage = errorData['message'];
|
String errorMessage = errorData['message'];
|
||||||
debugPrint('Unexpected Error: $errorMessage');
|
|
||||||
if(errorMessage=='User not found'){
|
if(errorMessage=='User not found'){
|
||||||
return 1;
|
return 1;
|
||||||
}else{
|
}else{
|
||||||
@ -87,8 +80,6 @@ class AuthenticationAPI {
|
|||||||
body: {"email": email, "type": "PASSWORD", "otpCode": otpCode},
|
body: {"email": email, "type": "PASSWORD", "otpCode": otpCode},
|
||||||
showServerMessage: true,
|
showServerMessage: true,
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
print('json=$json');
|
|
||||||
|
|
||||||
if (json['message'] == 'Otp Verified Successfully') {
|
if (json['message'] == 'Otp Verified Successfully') {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
@ -99,12 +90,9 @@ class AuthenticationAPI {
|
|||||||
}on DioException catch (e){
|
}on DioException catch (e){
|
||||||
if (e.response != null) {
|
if (e.response != null) {
|
||||||
if (e.response!.statusCode == 400) {
|
if (e.response!.statusCode == 400) {
|
||||||
// Handle 400 Bad Request
|
|
||||||
final errorData = e.response!.data;
|
final errorData = e.response!.data;
|
||||||
String errorMessage = errorData['message'];
|
String errorMessage = errorData['message'];
|
||||||
debugPrint('Unexpected Error: $errorMessage');
|
|
||||||
return errorMessage;
|
return errorMessage;
|
||||||
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
debugPrint('Error: ${e.message}');
|
debugPrint('Error: ${e.message}');
|
||||||
|
@ -26,7 +26,7 @@ abstract class ColorsManager {
|
|||||||
static const Color blackColor = Color(0xFF000000);
|
static const Color blackColor = Color(0xFF000000);
|
||||||
static const Color lightGreen = Color(0xFF00FF0A);
|
static const Color lightGreen = Color(0xFF00FF0A);
|
||||||
static const Color grayColor = Color(0xFF999999);
|
static const Color grayColor = Color(0xFF999999);
|
||||||
static const Color red = Colors.red;
|
static const Color red = Color(0xFFFF0000);
|
||||||
static const Color graysColor = Color(0xffEBEBEB);
|
static const Color graysColor = Color(0xffEBEBEB);
|
||||||
static const Color textGray = Color(0xffD5D5D5);
|
static const Color textGray = Color(0xffD5D5D5);
|
||||||
static const Color btnColor = Color(0xFF00008B);
|
static const Color btnColor = Color(0xFF00008B);
|
||||||
|
@ -25,4 +25,6 @@ class Assets {
|
|||||||
static const String assetIcon = "assets/images/asset_icon.svg";
|
static const String assetIcon = "assets/images/asset_icon.svg";
|
||||||
static const String calendarIcon = "assets/images/calendar_icon.svg";
|
static const String calendarIcon = "assets/images/calendar_icon.svg";
|
||||||
static const String deviceNoteIcon = "assets/images/device_note.svg";
|
static const String deviceNoteIcon = "assets/images/device_note.svg";
|
||||||
|
static const String timeIcon = "assets/images/time_icon.svg";
|
||||||
|
static const String emptyTable = "assets/images/empty_table.svg";
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
enum AccessType {
|
enum AccessType {
|
||||||
onlineOnetime,
|
onlineOnetime,
|
||||||
onlineMultiple,
|
onlineMultiple,
|
||||||
@ -43,8 +41,6 @@ extension AccessTypeExtension on AccessType {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
enum DeviseStatus {
|
enum DeviseStatus {
|
||||||
online,
|
online,
|
||||||
offline,
|
offline,
|
||||||
@ -74,6 +70,40 @@ extension OnlineTypeExtension on DeviseStatus {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
enum AccessStatus {
|
||||||
|
expired ,
|
||||||
|
effective ,
|
||||||
|
toBeEffective,
|
||||||
|
}
|
||||||
|
|
||||||
|
extension AccessStatusExtension on AccessStatus {
|
||||||
|
String get value {
|
||||||
|
switch (this) {
|
||||||
|
case AccessStatus.expired:
|
||||||
|
return "Expired";
|
||||||
|
case AccessStatus.effective:
|
||||||
|
return "Effective" ;
|
||||||
|
case AccessStatus.toBeEffective:
|
||||||
|
return "To be effective";
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static AccessStatus fromString(String value) {
|
||||||
|
switch (value) {
|
||||||
|
case "EXPIRED" :
|
||||||
|
return AccessStatus.expired;
|
||||||
|
case "EFFECTIVE" :
|
||||||
|
return AccessStatus.effective;
|
||||||
|
case "TO_BE_EFFECTIVE":
|
||||||
|
return AccessStatus.toBeEffective;
|
||||||
|
default:
|
||||||
|
throw ArgumentError("Invalid access type: $value");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -3,14 +3,12 @@ import 'package:flutter_svg/svg.dart';
|
|||||||
import 'package:syncrow_web/utils/constants/assets.dart';
|
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||||
import 'package:syncrow_web/web_layout/web_app_bar.dart';
|
import 'package:syncrow_web/web_layout/web_app_bar.dart';
|
||||||
import 'menu_sidebar.dart';
|
import 'menu_sidebar.dart';
|
||||||
|
|
||||||
class WebScaffold extends StatelessWidget {
|
class WebScaffold extends StatelessWidget {
|
||||||
final bool enableMenuSideba;
|
final bool enableMenuSideba;
|
||||||
final Widget? appBarTitle;
|
final Widget? appBarTitle;
|
||||||
final List<Widget>? appBarBody;
|
final List<Widget>? appBarBody;
|
||||||
final Widget? scaffoldBody;
|
final Widget? scaffoldBody;
|
||||||
const WebScaffold({super.key,this.appBarTitle,this.appBarBody,this.scaffoldBody,this.enableMenuSideba=true});
|
const WebScaffold({super.key,this.appBarTitle,this.appBarBody,this.scaffoldBody,this.enableMenuSideba=true});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
|
Reference in New Issue
Block a user