diff --git a/assets/images/device_note.svg b/assets/images/device_note.svg
new file mode 100644
index 00000000..f0b94043
--- /dev/null
+++ b/assets/images/device_note.svg
@@ -0,0 +1,5 @@
+
diff --git a/lib/main.dart b/lib/main.dart
index 92b8684c..e57db364 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -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/home/bloc/home_bloc.dart';
import 'package:syncrow_web/pages/home/view/home_page.dart';
+import 'package:syncrow_web/pages/visitor_password/view/add_device_dialog.dart';
import 'package:syncrow_web/pages/visitor_password/view/visitor_password_dialog.dart';
import 'package:syncrow_web/services/locator.dart';
import 'package:syncrow_web/utils/color_manager.dart';
@@ -40,6 +41,7 @@ class MyApp extends StatelessWidget {
PointerDeviceKind.unknown,
},
),
+
theme: ThemeData(
textTheme: const TextTheme(
bodySmall: TextStyle(fontSize: 13, color: ColorsManager.whiteColors, fontWeight: FontWeight.bold),
@@ -53,10 +55,11 @@ class MyApp extends StatelessWidget {
fontWeight: FontWeight.bold,
),
),
+
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), // Set up color scheme
useMaterial3: true, // Enable Material 3
),
- // home: VisitorPasswordDialog()
+ // home: AddDeviceDialog()
home:isLoggedIn == 'Success' ? const HomePage() : const LoginPage(),
));
}
diff --git a/lib/pages/access_management/bloc/access_bloc.dart b/lib/pages/access_management/bloc/access_bloc.dart
index e8be33f4..aef9508c 100644
--- a/lib/pages/access_management/bloc/access_bloc.dart
+++ b/lib/pages/access_management/bloc/access_bloc.dart
@@ -171,11 +171,10 @@ class AccessBloc extends Bloc {
}
-
- DateTime timestampToDateTime(dynamic timestamp) {
- return DateTime.fromMillisecondsSinceEpoch(int.parse(timestamp) * 1000);
+ String timestampToDate(dynamic timestamp) {
+ DateTime dateTime = DateTime.fromMillisecondsSinceEpoch(int.parse(timestamp) * 1000);
+ return "${dateTime.year}/${dateTime.month.toString().padLeft(2, '0')}/${dateTime.day.toString().padLeft(2, '0')}";
}
-
}
diff --git a/lib/pages/access_management/model/password_model.dart b/lib/pages/access_management/model/password_model.dart
index 0377bfb7..acd3e13a 100644
--- a/lib/pages/access_management/model/password_model.dart
+++ b/lib/pages/access_management/model/password_model.dart
@@ -1,3 +1,5 @@
+import 'package:syncrow_web/utils/constants/const.dart';
+
class PasswordModel {
final dynamic passwordId;
final dynamic invalidTime;
@@ -6,7 +8,7 @@ class PasswordModel {
final dynamic createdTime;
final dynamic passwodName; // New field
final dynamic passwordStatus;
- final dynamic passwordType;
+ final AccessType passwordType;
final dynamic deviceUuid;
PasswordModel({
@@ -17,7 +19,7 @@ class PasswordModel {
this.createdTime,
this.passwodName, // New field
this.passwordStatus,
- this.passwordType,
+ required this.passwordType,
this.deviceUuid,
});
@@ -30,7 +32,7 @@ class PasswordModel {
createdTime: json['createdTime'],
passwodName: json['passwodName']??'No name', // New field
passwordStatus: json['passwordStatus'],
- passwordType: json['passwordType'],
+ passwordType:AccessTypeExtension.fromString(json['passwordType']) ,
deviceUuid: json['deviceUuid'],
);
}
diff --git a/lib/pages/access_management/view/access_management.dart b/lib/pages/access_management/view/access_management.dart
index d2dd72b9..265c96c0 100644
--- a/lib/pages/access_management/view/access_management.dart
+++ b/lib/pages/access_management/view/access_management.dart
@@ -3,10 +3,12 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/access_management/bloc/access_bloc.dart';
import 'package:syncrow_web/pages/access_management/bloc/access_event.dart';
import 'package:syncrow_web/pages/access_management/bloc/access_state.dart';
+import 'package:syncrow_web/pages/common/custom_table.dart';
import 'package:syncrow_web/pages/common/date_time_widget.dart';
import 'package:syncrow_web/pages/common/default_button.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/constants/const.dart';
import 'package:syncrow_web/utils/style.dart';
import 'package:syncrow_web/web_layout/web_scaffold.dart';
@@ -51,68 +53,69 @@ class AccessManagementPage extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
- height: size.height * 0.05,
- width:size.width * 0.26 ,
decoration: containerDecoration,
- child: Center(
- child: ListView.builder(
- scrollDirection: Axis.horizontal,
- itemCount: BlocProvider.of(context).tabs.length,
- itemBuilder: (context, index) {
- final isSelected = index ==
- BlocProvider.of(context).selectedIndex;
- return InkWell(
- onTap: () {
- BlocProvider.of(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(context).tabs[index],
- style: TextStyle(
- color: isSelected
- ? Colors.blue
- : Colors.black,
+ height: size.height * 0.05,
+ child: Flexible(
+ child: ListView.builder(
+ scrollDirection: Axis.horizontal,
+ itemCount: BlocProvider.of(context).tabs.length,
+ shrinkWrap: true,
+ itemBuilder: (context, index) {
+ final isSelected = index ==
+ BlocProvider.of(context).selectedIndex;
+ return InkWell(
+ onTap: () {
+ BlocProvider.of(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(context).tabs[index],
+ style: TextStyle(
+ color: isSelected
+ ? Colors.blue
+ : Colors.black,
+ ),
),
),
),
- ),
- );
- },
+ );
+ },
+ ),
),
),
- ),
const SizedBox(
height: 20,
),
Row(
children: [
Column(
+
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
- const Text('Password Name'),
+ const Text('Name'),
Container(
width: size.width * 0.15,
decoration: containerDecoration,
child: TextFormField(
controller: accessBloc.passwordName,
- style: TextStyle(color: Colors.black),
+ style: const TextStyle(color: Colors.black),
decoration: textBoxDecoration()!
.copyWith(hintText: 'Please enter'),
)),
@@ -206,7 +209,7 @@ class AccessManagementPage extends StatelessWidget {
);
},
borderRadius: 8,
- child: Text('+ Create Visitor Password ')),
+ child: const Text('+ Create Visitor Password ')),
),
const SizedBox(
width: 10,
@@ -230,120 +233,110 @@ class AccessManagementPage extends StatelessWidget {
height: 20,
),
Expanded(
- child: state is TableLoaded
- ? TableWidget(size, state,accessBloc)
- : const Center(child: CircularProgressIndicator()))
+ child: state is TableLoaded
+ ? DynamicTable(
+ size: size,
+ cellDecoration: containerDecoration,
+ headers: const [
+ 'Name',
+ 'Access Type',
+ 'Access Period',
+ 'Device Id',
+ 'Authorizer',
+ 'Authorization Date & Time',
+ 'Access Status'
+ ],
+ data: state.data.map((item) {
+ return [
+ item.passwodName.toString(),
+ item.passwordType.value,
+ ('${accessBloc.timestampToDate(item.effectiveTime)} - ${accessBloc.timestampToDate(item.invalidTime)}'),
+ item.deviceUuid.toString(),
+ '',
+ '',
+ ''
+ ];
+ }).toList(),
+ )
+ : 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(),
- ),
- ],
- ),
- ),
- ),
- ],
- ),
- ),
- ],
- ),
- ),
- );
- }
+ // 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(),
+ // ),
+ // ],
+ // ),
+ // ),
+ // ),
+ // ],
+ // ),
+ // ),
+ // ],
+ // ),
+ // ),
+ // );
+ // }
}
-Widget _buildTableHeaderCell(String title) {
- return Expanded(
- child: Container(
- decoration: const BoxDecoration(
- border: Border.symmetric(
- vertical: BorderSide(color: ColorsManager.boxDivider))),
- alignment: Alignment.centerLeft,
- child: Padding(
- padding: const EdgeInsets.all(8.0),
- child: Text(title, style: TextStyle(fontWeight: FontWeight.bold)),
- ),
- ),
- );
-}
-
-Widget _buildTableCell(String content) {
- return Expanded(
- child: Container(
- height: 80,
- padding: const EdgeInsets.all(20.0),
- decoration: BoxDecoration(
- border: Border(
- bottom: BorderSide( // <--- right side
- color: ColorsManager.boxDivider,
- width: 1.0,
- ),
- )
- ),
- alignment: Alignment.centerLeft,
- child: Text(
- content,
- style: TextStyle(color: Colors.black, fontSize: 12),
- ),
- ),
- );
-}
diff --git a/lib/pages/common/custom_table.dart b/lib/pages/common/custom_table.dart
new file mode 100644
index 00000000..25c821fb
--- /dev/null
+++ b/lib/pages/common/custom_table.dart
@@ -0,0 +1,103 @@
+import 'package:flutter/material.dart';
+import 'package:syncrow_web/utils/color_manager.dart';
+
+class DynamicTable extends StatelessWidget {
+ final List headers;
+ final List> data;
+ final BoxDecoration? headerDecoration;
+ final BoxDecoration? cellDecoration;
+ final Size size;
+
+ const DynamicTable({
+ Key? key,
+ required this.headers,
+ required this.data,
+ required this.size,
+ this.headerDecoration,
+ this.cellDecoration,
+ }) : super(key: key);
+
+ @override
+ Widget build(BuildContext context) {
+ return Container(
+
+ decoration: cellDecoration,
+ child: Padding(
+ padding: const EdgeInsets.all(10.0),
+ child: ListView(
+ scrollDirection: Axis.horizontal,
+ children: [
+ Container(
+ width:size.width,
+ child: Column(
+ children: [
+ Container(
+ decoration: headerDecoration ??
+ BoxDecoration(color: Colors.grey[200]),
+ child: Row(
+ children: headers.map((header) =>
+ _buildTableHeaderCell(header)).toList(),
+ ),
+ ),
+ Expanded(
+ child: Container(
+ color: Colors.white,
+ child: ListView(
+ shrinkWrap: true,
+ children: data.map((row) {
+ return Row(
+ children: row.map((cell) =>
+ _buildTableCell(cell.toString())).toList(),
+ );
+ }).toList(),
+ ),
+ ),
+ ),
+ ],
+ ),
+ ),
+ ],
+ ),
+ ),
+ );
+ }
+}
+Widget _buildTableHeaderCell(String title) {
+ return Expanded(
+ child: Container(
+ decoration: const BoxDecoration(
+ border: Border.symmetric(
+ vertical: BorderSide(color: ColorsManager.boxDivider))),
+ alignment: Alignment.centerLeft,
+ child: Padding(
+ padding: const EdgeInsets.all(8.0),
+ child: Text(title, style: TextStyle(fontWeight: FontWeight.bold)),
+ ),
+ ),
+ );
+}
+
+Widget _buildTableCell(String content) {
+ return Expanded(
+ child: Container(
+ height: 80,
+ padding: const EdgeInsets.all(20.0),
+ decoration: const BoxDecoration(
+ border: Border(
+ bottom: BorderSide( // <--- right side
+ color: ColorsManager.boxDivider,
+ width: 1.0,
+ ),
+ )
+ ),
+ alignment: Alignment.centerLeft,
+ child: Text(
+ content,
+ style: TextStyle(color: Colors.black, fontSize: 12),
+ ),
+ ),
+ );
+}
+
+
+
diff --git a/lib/pages/common/custom_web_textfield.dart b/lib/pages/common/custom_web_textfield.dart
index 003ca88d..0662199b 100644
--- a/lib/pages/common/custom_web_textfield.dart
+++ b/lib/pages/common/custom_web_textfield.dart
@@ -29,8 +29,7 @@ class CustomWebTextField extends StatelessWidget {
if(isRequired)
Row(
children: [
- Text(
- '* ',
+ Text('* ',
style: Theme.of(context)
.textTheme
.bodyMedium!
@@ -39,6 +38,7 @@ class CustomWebTextField extends StatelessWidget {
Text(textFieldName),
],
),
+ const SizedBox(width: 10,),
Text(
description??'', // ' The password will be sent to the visitor’s email address.',
style: Theme.of(context)
@@ -53,7 +53,17 @@ class CustomWebTextField extends StatelessWidget {
),
const SizedBox(height: 7,),
Container(
- decoration: containerDecoration,
+ height: MediaQuery.of(context).size.height*0.05,
+ decoration: containerDecoration.copyWith(
+ color: const Color(0xFFF5F6F7),
+ boxShadow: [
+ BoxShadow(
+ color: Colors.grey.withOpacity(0.3),
+ spreadRadius:2,
+ blurRadius: 3,
+ offset: Offset(1, 1), // changes position of shadow
+ ), ]
+ ),
child: TextFormField(
controller: controller,
style: const TextStyle(color: Colors.black),
diff --git a/lib/pages/visitor_password/bloc/visitor_password_bloc.dart b/lib/pages/visitor_password/bloc/visitor_password_bloc.dart
index 668d082e..c6ce5188 100644
--- a/lib/pages/visitor_password/bloc/visitor_password_bloc.dart
+++ b/lib/pages/visitor_password/bloc/visitor_password_bloc.dart
@@ -2,6 +2,8 @@ import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.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/model/device_model.dart';
+import 'package:syncrow_web/services/access_mang_api.dart';
import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/utils/snack_bar.dart';
@@ -9,15 +11,29 @@ import 'package:syncrow_web/utils/snack_bar.dart';
class VisitorPasswordBloc extends Bloc {
VisitorPasswordBloc() : super(VisitorPasswordInitial()) {
on(selectUsageFrequency);
+ on(_onFetchDevice);
+
on(selectAccessType);
on(selectTimeVisitorPassword);
on(toggleRepeat);
on(toggleDaySelection);
-
}
final TextEditingController userNameController = TextEditingController();
final TextEditingController emailController = TextEditingController();
+
+
+ final TextEditingController deviceNameController = TextEditingController();
+ final TextEditingController deviceIdController = TextEditingController();
+ final TextEditingController unitNameController = TextEditingController();
+ final TextEditingController virtualAddressController = TextEditingController();
+
+ List data=[];
+
+
+
+
+
String accessTypeSelected='Offline Password';
String usageFrequencySelected='One-Time';
@@ -136,6 +152,17 @@ class VisitorPasswordBloc extends Bloc _onFetchDevice(
+ FetchDevice event, Emitter emit) async {
+ try {
+ emit(DeviceLoaded());
+ data = await AccessMangApi().fetchDevices();
+ emit(TableLoaded(data));
+ } catch (e) {
+ emit(FailedState(e.toString()));
+ }
+ }
}
diff --git a/lib/pages/visitor_password/bloc/visitor_password_event.dart b/lib/pages/visitor_password/bloc/visitor_password_event.dart
index b0a51ca0..8195e155 100644
--- a/lib/pages/visitor_password/bloc/visitor_password_event.dart
+++ b/lib/pages/visitor_password/bloc/visitor_password_event.dart
@@ -47,3 +47,4 @@ class ToggleDaySelectionEvent extends VisitorPasswordEvent {
class ToggleRepeatEvent extends VisitorPasswordEvent {}
+class FetchDevice extends VisitorPasswordEvent {}
diff --git a/lib/pages/visitor_password/bloc/visitor_password_state.dart b/lib/pages/visitor_password/bloc/visitor_password_state.dart
index 8a5525d3..88b14ec9 100644
--- a/lib/pages/visitor_password/bloc/visitor_password_state.dart
+++ b/lib/pages/visitor_password/bloc/visitor_password_state.dart
@@ -1,6 +1,7 @@
import 'package:equatable/equatable.dart';
+import 'package:syncrow_web/pages/visitor_password/model/device_model.dart';
abstract class VisitorPasswordState extends Equatable {
const VisitorPasswordState();
@@ -42,3 +43,20 @@ class IsRepeatState extends VisitorPasswordState {
class LoadingInitialState extends VisitorPasswordState {}
class ChangeTimeState extends VisitorPasswordState {}
+class DeviceLoaded extends VisitorPasswordState {}
+class FailedState extends VisitorPasswordState {
+ final String message;
+
+ FailedState(this.message);
+
+ @override
+ List