diff --git a/assets/dome.json b/assets/dome.json
deleted file mode 100644
index 91186608..00000000
--- a/assets/dome.json
+++ /dev/null
@@ -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"
- }
-]
diff --git a/assets/images/empty_table.svg b/assets/images/empty_table.svg
new file mode 100644
index 00000000..24ac359d
--- /dev/null
+++ b/assets/images/empty_table.svg
@@ -0,0 +1,23 @@
+
diff --git a/assets/images/time_icon.svg b/assets/images/time_icon.svg
new file mode 100644
index 00000000..a8f06677
--- /dev/null
+++ b/assets/images/time_icon.svg
@@ -0,0 +1,4 @@
+
diff --git a/lib/main.dart b/lib/main.dart
index bf63e062..464406cc 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/bloc/visitor_password_bloc.dart';
import 'package:syncrow_web/services/locator.dart';
import 'package:syncrow_web/utils/color_manager.dart';
@@ -28,6 +29,9 @@ class MyApp extends StatelessWidget {
return MultiBlocProvider(
providers: [
BlocProvider(create: (context) => HomeBloc()),
+ BlocProvider(
+ create: (context) => VisitorPasswordBloc(),
+ )
],
child: MaterialApp(
debugShowCheckedModeBanner: false, // Hide debug banner
@@ -39,6 +43,7 @@ class MyApp extends StatelessWidget {
PointerDeviceKind.unknown,
},
),
+
theme: ThemeData(
textTheme: const TextTheme(
bodySmall: TextStyle(
@@ -55,12 +60,10 @@ class MyApp extends StatelessWidget {
fontWeight: FontWeight.bold,
),
),
-
colorScheme: ColorScheme.fromSeed(
seedColor: Colors.deepPurple), // Set up color scheme
useMaterial3: true, // Enable Material 3
),
- // 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 7c57bfa4..47f865ef 100644
--- a/lib/pages/access_management/bloc/access_bloc.dart
+++ b/lib/pages/access_management/bloc/access_bloc.dart
@@ -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/services/access_mang_api.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';
class AccessBloc extends Bloc {
AccessBloc() : super((AccessInitial())) {
on(_onFetchTableData);
- on(selectFilterTap);
+ // on(selectFilterTap);
on(selectTime);
on(_filterData);
on(resetSearch);
+ on(onTabChanged);
}
- String startTime = 'Start Time';
- String endTime = 'End Time';
+ String startTime = 'Start Date';
+ String endTime = 'End Date';
int? effectiveTimeTimeStamp;
int? expirationTimeTimeStamp;
TextEditingController passwordName= TextEditingController();
- List filteredData = []; // To store filtered data
+ List filteredData = [];
List data=[];
Future _onFetchTableData(
@@ -29,14 +31,25 @@ class AccessBloc extends Bloc {
try {
emit(AccessLoaded());
data = await AccessMangApi().fetchVisitorPassword();
- emit(TableLoaded(data));
+ filteredData= data;
+ updateTabsCount();
+ emit(TableLoaded(data));
} catch (e) {
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;
-
final List tabs = [
'All',
'To Be Effective (0)',
@@ -49,9 +62,8 @@ class AccessBloc extends Bloc {
try {
emit(AccessLoaded());
selectedIndex= event.selectedIndex;
- emit(AccessInitial());
+ emit(AccessInitial());
emit(TableLoaded(data));
-
} catch (e) {
emit(FailedState( e.toString()));
return;
@@ -60,6 +72,8 @@ class AccessBloc extends Bloc {
Future selectTime(SelectTime event, Emitter emit) async {
+ emit(AccessLoaded());
+
final DateTime? picked = await showDatePicker(
context: event.context,
initialDate: DateTime.now(),
@@ -120,27 +134,23 @@ class AccessBloc extends Bloc {
}
}
}
- emit(AccessInitial());
- emit(TableLoaded(data));
+ emit(ChangeTimeState());
}
+
Future _filterData(FilterDataEvent event, Emitter emit) async {
emit(AccessLoaded());
try {
- // Filter the data based on the provided criteria
filteredData = data.where((item) {
bool matchesCriteria = true;
- // Check if the password name should be used for filtering
if (event.passwordName != null && event.passwordName!.isNotEmpty) {
- final bool matchesName = item.passwodName != null &&
- item.passwodName.contains(event.passwordName!);
+ final bool matchesName = item.passwordName != null &&
+ item.passwordName.contains(event.passwordName);
if (!matchesName) {
matchesCriteria = false;
}
}
- // Check if the time range should be used for filtering
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? invalidTime = int.tryParse(item.invalidTime.toString());
if (effectiveTime == null || invalidTime == null) {
@@ -153,22 +163,30 @@ class AccessBloc extends Bloc {
}
}
}
+ 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;
}).toList();
- print('Filtered data: $filteredData');
emit(TableLoaded(filteredData));
} catch (e) {
- print('Error occurred during filtering: $e');
+ emit(FailedState(e.toString()));
}
}
- // ResetSearch
+
resetSearch(ResetSearch event, Emitter emit) async{
emit(AccessLoaded());
startTime = 'Start Time';
endTime = 'End Time';
passwordName.clear();
+ selectedIndex=0;
+ effectiveTimeTimeStamp=null;
+ expirationTimeTimeStamp=null;
add(FetchTableData());
-
}
String timestampToDate(dynamic timestamp) {
@@ -176,5 +194,36 @@ class AccessBloc extends Bloc {
return "${dateTime.year}/${dateTime.month.toString().padLeft(2, '0')}/${dateTime.day.toString().padLeft(2, '0')}";
}
+ Future onTabChanged(TabChangedEvent event, Emitter 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()));
+ }
+ }
}
diff --git a/lib/pages/access_management/bloc/access_event.dart b/lib/pages/access_management/bloc/access_event.dart
index 3a64a11a..f2f631b4 100644
--- a/lib/pages/access_management/bloc/access_event.dart
+++ b/lib/pages/access_management/bloc/access_event.dart
@@ -31,10 +31,16 @@ class FilterDataEvent extends AccessEvent {
final String? passwordName;
final int? startTime;
final int? endTime;
+ final int selectedTabIndex; // Add this field
const FilterDataEvent({
this.passwordName,
this.startTime,
this.endTime,
+ required this.selectedTabIndex, // Initialize this field
+
});
}
+
+
+
diff --git a/lib/pages/access_management/model/password_model.dart b/lib/pages/access_management/model/password_model.dart
index acd3e13a..584e9b7e 100644
--- a/lib/pages/access_management/model/password_model.dart
+++ b/lib/pages/access_management/model/password_model.dart
@@ -6,8 +6,8 @@ class PasswordModel {
final dynamic effectiveTime;
final dynamic passwordCreated;
final dynamic createdTime;
- final dynamic passwodName; // New field
- final dynamic passwordStatus;
+ final dynamic passwordName; // New field
+ final AccessStatus passwordStatus;
final AccessType passwordType;
final dynamic deviceUuid;
@@ -17,8 +17,8 @@ class PasswordModel {
this.effectiveTime,
this.passwordCreated,
this.createdTime,
- this.passwodName, // New field
- this.passwordStatus,
+ this.passwordName, // New field
+ required this.passwordStatus,
required this.passwordType,
this.deviceUuid,
});
@@ -30,9 +30,9 @@ class PasswordModel {
effectiveTime: json['effectiveTime'],
passwordCreated: json['passwordCreated'],
createdTime: json['createdTime'],
- passwodName: json['passwodName']??'No name', // New field
- passwordStatus: json['passwordStatus'],
- passwordType:AccessTypeExtension.fromString(json['passwordType']) ,
+ passwordName: json['passwordName']??'No name', // New field
+ passwordStatus:AccessStatusExtension.fromString(json['passwordStatus']),
+ passwordType:AccessTypeExtension.fromString(json['passwordType']),
deviceUuid: json['deviceUuid'],
);
}
@@ -44,13 +44,11 @@ class PasswordModel {
'effectiveTime': effectiveTime,
'passwordCreated': passwordCreated,
'createdTime': createdTime,
- 'passwodName': passwodName, // New field
+ 'passwodName': passwordName, // New field
'passwordStatus': passwordStatus,
'passwordType': passwordType,
'deviceUuid': deviceUuid,
};
}
- List parsePasswordList(List jsonList) {
- return jsonList.map((json) => PasswordModel.fromJson(json)).toList();
- }
+
}
diff --git a/lib/pages/access_management/view/access_management.dart b/lib/pages/access_management/view/access_management.dart
index de8dc102..4c7023bb 100644
--- a/lib/pages/access_management/view/access_management.dart
+++ b/lib/pages/access_management/view/access_management.dart
@@ -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/visitor_password/view/visitor_password_dialog.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/style.dart';
import 'package:syncrow_web/web_layout/web_scaffold.dart';
@@ -41,270 +42,278 @@ class AccessManagementPage extends StatelessWidget {
create: (BuildContext context) =>
AccessBloc()..add(FetchTableData()),
child: BlocConsumer(
- listener: (context, state) {
- if (state is FailedState) {
- // CustomSnackBar.displaySnackBar(
- // state.errorMessage
- // );
- }
- }, builder: (context, state) {
- final accessBloc = BlocProvider.of(context);
- return Container(
- padding: EdgeInsets.all(30),
- height: size.height,
- width: size.width,
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- FilterWidget(
- size: size,
- tabs: accessBloc.tabs,
- selectedIndex: accessBloc.selectedIndex,
- onTabChanged: (index) {
- accessBloc.add(TabChangedEvent(index));
- },
- ),
- const SizedBox(
- height: 20,
- ),
- Row(
- children: [
- Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- mainAxisAlignment: MainAxisAlignment.start,
- children: [
- const Text('Name'),
- Container(
- width: size.width * 0.15,
- decoration: containerDecoration,
- child: TextFormField(
- controller: accessBloc.passwordName,
- style: const TextStyle(color: Colors.black),
- decoration: textBoxDecoration()!
- .copyWith(hintText: 'Please enter'),
- )),
- ],
- ),
- const SizedBox(
- width: 15,
- ),
- DateTimeWebWidget(
- isRequired: false,
- title: 'Access Time',
- size: size,
- endTime: () {
- accessBloc.add(
- SelectTime(context: context, isStart: false));
- },
- startTime: () {
- accessBloc.add(
- SelectTime(context: context, isStart: true));
- },
- firstString:
- BlocProvider.of(context).startTime,
- secondString:
- BlocProvider.of(context).endTime,
- ),
- const SizedBox(
- width: 15,
- ),
- SizedBox(
- width: size.width * 0.06,
+ listener: (context, state) {},
+ builder: (context, state) {
+ final accessBloc = BlocProvider.of(context);
+ final filteredData = accessBloc.filteredData;
+ return state is AccessLoaded
+ ? const Center(child: CircularProgressIndicator())
+ : Container(
+ padding: EdgeInsets.all(30),
+ height: size.height,
+ width: size.width,
child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
children: [
- Text(''),
- Container(
- decoration: containerDecoration,
- child: DefaultButton(
- onPressed: () {
- accessBloc.add(FilterDataEvent(
- passwordName:
- accessBloc.passwordName.text,
- startTime: accessBloc
- .effectiveTimeTimeStamp,
- endTime: accessBloc
- .expirationTimeTimeStamp));
- },
- borderRadius: 9,
- child: const Text('Search'))),
- ],
- ),
- ),
- const SizedBox(
- width: 10,
- ),
- SizedBox(
- width: size.width * 0.06,
- child: Column(
- children: [
- Text(''),
Container(
decoration: containerDecoration,
- child: DefaultButton(
- onPressed: () {
- accessBloc.add(ResetSearch());
- },
- backgroundColor: ColorsManager.whiteColors,
- borderRadius: 9,
- child: Text(
- 'Reset',
- style: Theme.of(context)
- .textTheme
- .bodySmall!
- .copyWith(color: 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(
+ mainAxisSize: MainAxisSize.min,
+ crossAxisAlignment: CrossAxisAlignment.end,
+ textBaseline: TextBaseline.ideographic,
+ children: [
+ Column(
+ crossAxisAlignment:
+ CrossAxisAlignment.start,
+ mainAxisAlignment:
+ MainAxisAlignment.spaceBetween,
+ children: [
+ Text(
+ 'Name',
+ style: Theme.of(context)
+ .textTheme
+ .bodySmall!
+ .copyWith(
+ color: Colors.black,
+ fontSize: 13),
+ ),
+ const SizedBox(
+ height: 5,
+ ),
+ Container(
+ height: 43,
+ width: size.width * 0.15,
+ decoration: containerDecoration,
+ child: TextFormField(
+ controller: accessBloc.passwordName,
+ style: const TextStyle(
+ color: Colors.black),
+ decoration: textBoxDecoration()!
+ .copyWith(
+ hintText: 'Please enter'),
+ )),
+ ],
+ ),
+ const SizedBox(
+ width: 15,
+ ),
+ DateTimeWebWidget(
+ icon: Assets.calendarIcon,
+ isRequired: false,
+ title: 'Access Time',
+ size: size,
+ endTime: () {
+ accessBloc.add(SelectTime(
+ context: context, isStart: false));
+ },
+ startTime: () {
+ accessBloc.add(SelectTime(
+ context: context, isStart: true));
+ },
+ firstString:
+ BlocProvider.of(context)
+ .startTime,
+ secondString:
+ BlocProvider.of(context)
+ .endTime,
+ ),
+ const SizedBox(
+ width: 15,
+ ),
+ SizedBox(
+ height: 45,
+ width: size.width * 0.06,
+ child: Container(
+ decoration: containerDecoration,
+ child: DefaultButton(
+ onPressed: () {
+ accessBloc.add(FilterDataEvent(
+ selectedTabIndex: BlocProvider
+ .of(
+ context)
+ .selectedIndex, // Pass the selected tab index
+ passwordName: accessBloc
+ .passwordName.text
+ .toLowerCase(),
+ startTime: accessBloc
+ .effectiveTimeTimeStamp,
+ endTime: accessBloc
+ .expirationTimeTimeStamp));
+ },
+ borderRadius: 9,
+ child: const Text('Search'))),
+ ),
+ const SizedBox(
+ width: 10,
+ ),
+ SizedBox(
+ height: 45,
+ width: size.width * 0.06,
+ child: Container(
+ decoration: containerDecoration,
+ child: DefaultButton(
+ onPressed: () {
+ accessBloc.add(ResetSearch());
+ },
+ backgroundColor:
+ ColorsManager.whiteColors,
+ borderRadius: 9,
+ child: Text(
+ 'Reset',
+ style: Theme.of(context)
+ .textTheme
+ .bodySmall!
+ .copyWith(color: Colors.black),
+ ),
+ ),
+ ),
+ ),
+ ],
+ ),
+ const SizedBox(
+ height: 20,
+ ),
+ Wrap(
+ children: [
+ Container(
+ width: size.width * 0.15,
+ decoration: containerDecoration,
+ child: DefaultButton(
+ onPressed: () {
+ showDialog(
+ context: context,
+ barrierDismissible: false,
+ builder: (BuildContext context) {
+ return const VisitorPasswordDialog();
+ },
+ ).then((v) {
+ if (v != null) {
+ accessBloc.add(FetchTableData());
+ }
+ });
+ },
+ borderRadius: 8,
+ child: const Text(
+ '+ Create Visitor Password ')),
+ ),
+ const SizedBox(
+ width: 10,
+ ),
+ Container(
+ width: size.width * 0.12,
+ decoration: containerDecoration,
+ child: DefaultButton(
+ borderRadius: 8,
+ backgroundColor:
+ ColorsManager.whiteColors,
+ child: Text(
+ 'Admin Password',
+ style: Theme.of(context)
+ .textTheme
+ .bodySmall!
+ .copyWith(color: Colors.black),
+ )))
+ ],
+ ),
+ const SizedBox(
+ height: 20,
+ ),
+ Expanded(
+ child: DynamicTable(
+ isEmpty: filteredData.isEmpty,
+ withCheckBox: false,
+ size: size,
+ cellDecoration: containerDecoration,
+ headers: const [
+ 'Name',
+ 'Access Type',
+ 'Access Period',
+ 'Accessible Device',
+ 'Authorizer',
+ 'Authorization Date & Time',
+ 'Access Status'
+ ],
+ data: filteredData.map((item) {
+ return [
+ item.passwordName.toString(),
+ item.passwordType.value,
+ ('${accessBloc.timestampToDate(item.effectiveTime)} - ${accessBloc.timestampToDate(item.invalidTime)}'),
+ item.deviceUuid.toString(),
+ '',
+ '',
+ item.passwordStatus.value
+ ];
+ }).toList(),
+ )
+ // : const Center(child: CircularProgressIndicator()),
+ )
],
),
- ),
- ],
- ),
- const SizedBox(
- height: 20,
- ),
- Wrap(
- children: [
- Container(
- width: size.width * 0.15,
- decoration: containerDecoration,
- child: DefaultButton(
- onPressed: () {
- showDialog(
- context: context,
- barrierDismissible: false,
- builder: (BuildContext context) {
- return const VisitorPasswordDialog();
- },
- );
- },
- borderRadius: 8,
- child:
- const Text('+ Create Visitor Password ')),
- ),
- const SizedBox(
- width: 10,
- ),
- Container(
- width: size.width * 0.12,
- decoration: containerDecoration,
- child: DefaultButton(
- borderRadius: 8,
- backgroundColor: ColorsManager.whiteColors,
- child: Text(
- 'Admin Password',
- style: Theme.of(context)
- .textTheme
- .bodySmall!
- .copyWith(color: Colors.black),
- )))
- ],
- ),
- const SizedBox(
- height: 20,
- ),
- Expanded(
- child: state is TableLoaded
- ? DynamicTable(
- withCheckBox: false,
- 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(),
- // ),
- // ],
- // ),
- // ),
- // ),
- // ],
- // ),
- // ),
- // ],
- // ),
- // ),
- // );
- // }
}
diff --git a/lib/pages/auth/bloc/auth_bloc.dart b/lib/pages/auth/bloc/auth_bloc.dart
index 120de89a..514e158b 100644
--- a/lib/pages/auth/bloc/auth_bloc.dart
+++ b/lib/pages/auth/bloc/auth_bloc.dart
@@ -84,6 +84,9 @@ class AuthBloc extends Bloc {
} else if (response == "You entered wrong otp") {
forgetValidate = 'Wrong one time password.';
emit(AuthInitialState());
+ }else if (response == "OTP expired") {
+ forgetValidate = 'One time password has been expired.';
+ emit(AuthInitialState());
}
} catch (failure) {
// forgetValidate='Invalid Credentials!';
@@ -91,7 +94,7 @@ class AuthBloc extends Bloc {
// emit(FailureForgetState(error: failure.toString()));
}
}
-
+//925207
String? validateCode(String? value) {
if (value == null || value.isEmpty) {
return 'Code is required';
diff --git a/lib/pages/auth/view/login_mobile_page.dart b/lib/pages/auth/view/login_mobile_page.dart
index d2787f04..f86ec301 100644
--- a/lib/pages/auth/view/login_mobile_page.dart
+++ b/lib/pages/auth/view/login_mobile_page.dart
@@ -146,7 +146,6 @@ class LoginMobilePage extends StatelessWidget {
textAlign: TextAlign.center,
),
),
-
isDense: true,
style: const TextStyle(color: Colors.black),
items:loginBloc.regionList!.map((RegionModel region) {
@@ -156,7 +155,6 @@ class LoginMobilePage extends StatelessWidget {
);
}).toList(),
onChanged: (String? value) {
- print(value);
},
),
)
diff --git a/lib/pages/auth/view/login_web_page.dart b/lib/pages/auth/view/login_web_page.dart
index 77c7afba..893c3a86 100644
--- a/lib/pages/auth/view/login_web_page.dart
+++ b/lib/pages/auth/view/login_web_page.dart
@@ -166,8 +166,7 @@ class _LoginWebPageState extends State {
return DropdownMenuItem(
value: region.id,
child: SizedBox(
- width: size.width*0.06,
-
+ width: size.width*0.08,
child: Text(region.name)),
);
}).toList(),
diff --git a/lib/pages/common/custom_dialog.dart b/lib/pages/common/custom_dialog.dart
new file mode 100644
index 00000000..3b667811
--- /dev/null
+++ b/lib/pages/common/custom_dialog.dart
@@ -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 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: [
+ 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),
+ ),
+ ),
+ ],
+ );
+ },
+ );
+}
diff --git a/lib/pages/common/custom_table.dart b/lib/pages/common/custom_table.dart
index 93ae29ce..6b84a76e 100644
--- a/lib/pages/common/custom_table.dart
+++ b/lib/pages/common/custom_table.dart
@@ -1,5 +1,7 @@
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/constants/assets.dart';
class DynamicTable extends StatefulWidget {
final List headers;
@@ -8,20 +10,24 @@ class DynamicTable extends StatefulWidget {
final BoxDecoration? cellDecoration;
final Size size;
final bool withCheckBox;
+ final bool isEmpty;
final void Function(bool?)? selectAll;
final void Function(int, bool?)? onRowCheckboxChanged;
+ final List? initialSelectedIds;
const DynamicTable({
- Key? key,
+ super.key,
required this.headers,
required this.data,
required this.size,
+ required this.isEmpty,
required this.withCheckBox,
this.headerDecoration,
this.cellDecoration,
this.selectAll,
this.onRowCheckboxChanged,
- }) : super(key: key);
+ this.initialSelectedIds,
+ });
@override
_DynamicTableState createState() => _DynamicTableState();
@@ -34,7 +40,11 @@ class _DynamicTableState extends State {
@override
void initState() {
super.initState();
- _selected = List.filled(widget.data.length, false);
+ _selected = List.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) {
@@ -62,7 +72,7 @@ class _DynamicTableState extends State {
return Container(
decoration: widget.cellDecoration,
child: Padding(
- padding: const EdgeInsets.all(10.0),
+ padding: const EdgeInsets.all(2.0),
child: ListView(
scrollDirection: Axis.horizontal,
children: [
@@ -82,27 +92,60 @@ class _DynamicTableState extends State {
],
),
),
- Expanded(
- child: Container(
- color: Colors.white,
- child: ListView.builder(
- shrinkWrap: true,
- itemCount: widget.data.length,
- itemBuilder: (context, index) {
- final row = widget.data[index];
- return Row(
+ widget.isEmpty
+ ? Expanded(
+ child: Column(
+ mainAxisAlignment: MainAxisAlignment.center,
children: [
- if (widget.withCheckBox) _buildRowCheckbox(index),
- ...row
- .map((cell) =>
- _buildTableCell(cell.toString()))
- .toList(),
+ 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(
+ color: Colors.white,
+ child: ListView.builder(
+ shrinkWrap: true,
+ itemCount: widget.data.length,
+ itemBuilder: (context, index) {
+ final row = widget.data[index];
+ return Row(
+ children: [
+ if (widget.withCheckBox)
+ _buildRowCheckbox(
+ index, widget.size.height * 0.10),
+ ...row
+ .map((cell) => _buildTableCell(
+ cell.toString(),
+ widget.size.height * 0.10))
+ .toList(),
+ ],
+ );
+ },
+ ),
+ ),
+ ),
],
),
),
@@ -113,8 +156,11 @@ class _DynamicTableState extends State {
}
Widget _buildSelectAllCheckbox() {
- return SizedBox(
- width: 50,
+ return Container(
+ padding: const EdgeInsets.all(8.0),
+ decoration: const BoxDecoration(
+ border: Border.symmetric(
+ vertical: BorderSide(color: ColorsManager.boxDivider))),
child: Checkbox(
value: _selectAll,
onChanged: _toggleSelectAll,
@@ -122,16 +168,26 @@ class _DynamicTableState extends State {
);
}
- Widget _buildRowCheckbox(int index) {
- return SizedBox(
- width: 50,
- child: Checkbox(
- value: _selected[index],
- onChanged: (bool? value) {
- _toggleRowSelection(index, value);
- },
- ),
- );
+ Widget _buildRowCheckbox(int index, size) {
+ return Container(
+ 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(
+ value: _selected[index],
+ onChanged: (bool? value) {
+ _toggleRowSelection(index, value);
+ },
+ ),
+ ));
}
Widget _buildTableHeaderCell(String title) {
@@ -146,17 +202,18 @@ class _DynamicTableState extends State {
child: Text(title,
style: const TextStyle(
fontWeight: FontWeight.w400,
- color: ColorsManager.lightGreyColor)),
+ fontSize: 13,
+ color: Color(0xFF999999))),
),
),
);
}
- Widget _buildTableCell(String content) {
+ Widget _buildTableCell(String content, size) {
return Expanded(
child: Container(
- height: 80,
- padding: const EdgeInsets.all(15.0),
+ height: size,
+ padding: const EdgeInsets.all(5.0),
decoration: const BoxDecoration(
border: Border(
bottom: BorderSide(
@@ -167,7 +224,8 @@ class _DynamicTableState extends State {
alignment: Alignment.centerLeft,
child: Text(
content,
- style: const TextStyle(color: Colors.black, fontSize: 12),
+ style: const TextStyle(
+ color: Colors.black, fontSize: 10, fontWeight: FontWeight.w400),
),
),
);
diff --git a/lib/pages/common/date_time_widget.dart b/lib/pages/common/date_time_widget.dart
index ace2cf8d..d8fbfe51 100644
--- a/lib/pages/common/date_time_widget.dart
+++ b/lib/pages/common/date_time_widget.dart
@@ -1,5 +1,6 @@
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/constants/assets.dart';
import 'package:syncrow_web/utils/style.dart';
@@ -13,6 +14,7 @@ class DateTimeWebWidget extends StatelessWidget {
required this.endTime,
required this.firstString,
required this.secondString,
+ required this.icon,
});
final Size size;
@@ -20,6 +22,7 @@ class DateTimeWebWidget extends StatelessWidget {
final bool isRequired;
final String firstString;
final String secondString;
+ final String icon;
final Function()? startTime;
final Function()? endTime;
@@ -39,35 +42,52 @@ class DateTimeWebWidget extends StatelessWidget {
.bodyMedium!
.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(
- width: size.width * 0.25,
- padding: EdgeInsets.all(10),
- decoration: containerDecoration,
- child: Column(
- children: [
- Row(
- mainAxisAlignment:
- MainAxisAlignment.spaceBetween,
- children: [
- InkWell(
- onTap: startTime,
- child: Text(firstString)
- ),
- const Icon(Icons.arrow_right_alt),
- InkWell(
- onTap:endTime,
- child: Text(secondString)),
- SvgPicture.asset(
- Assets.calendarIcon,
- ),
- ],
- ),
- ],
- )),
+ height:size.height * 0.055 ,
+ padding: EdgeInsets.only(top: 10,bottom: 10,right: 30,left: 10),
+ decoration: containerDecoration,
+ child: FittedBox(
+ child: Column(
+ children: [
+ Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ InkWell(
+ onTap: startTime,
+ 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),
+ SizedBox(width: 30,),
+
+ InkWell(
+ onTap:endTime,
+ 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(
+ icon,
+ ),
+ ],
+ ),
+ ],
+ )),
+ ),
],
);
}
diff --git a/lib/pages/common/hour_picker_dialog.dart b/lib/pages/common/hour_picker_dialog.dart
new file mode 100644
index 00000000..718f1ebf
--- /dev/null
+++ b/lib/pages/common/hour_picker_dialog.dart
@@ -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 {
+ 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(
+ 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(
+ 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 showHourPicker({
+ required BuildContext context,
+ required TimeOfDay initialTime,
+}) {
+ return showDialog(
+ context: context,
+ builder: (context) => HourPickerDialog(initialTime: initialTime),
+ );
+}
diff --git a/lib/pages/common/info_dialog.dart b/lib/pages/common/info_dialog.dart
index 4465ced6..cfd2cbd4 100644
--- a/lib/pages/common/info_dialog.dart
+++ b/lib/pages/common/info_dialog.dart
@@ -66,7 +66,7 @@ class InfoDialog extends StatelessWidget {
onPressed: () {
Navigator.of(context).pop();
},
- child: Text('OK'),
+ child: const Text('OK'),
),
],
);
diff --git a/lib/pages/common/text_field/custom_web_textfield.dart b/lib/pages/common/text_field/custom_web_textfield.dart
index 4ec0aa81..363a1994 100644
--- a/lib/pages/common/text_field/custom_web_textfield.dart
+++ b/lib/pages/common/text_field/custom_web_textfield.dart
@@ -33,23 +33,23 @@ class CustomWebTextField extends StatelessWidget {
children: [
Text('* ',
style: Theme.of(context)
- .textTheme
- .bodyMedium!
+ .textTheme.bodyMedium!
.copyWith(color: Colors.red),
),
- Text(textFieldName),
+ Text(textFieldName, style: Theme.of(context).textTheme.bodySmall!.copyWith(
+ color: Colors.black,fontSize: 13),),
],
),
const SizedBox(width: 10,),
- Text(
- description??'', // ' The password will be sent to the visitor’s email address.',
- style: Theme.of(context)
- .textTheme
- .bodySmall!
- .copyWith(
- fontSize: 9,
- fontWeight: FontWeight.w400,
- color: ColorsManager.textGray),
+ Expanded(
+ child: Text(
+ description??'',
+ style: Theme.of(context)
+ .textTheme.bodySmall!
+ .copyWith(fontSize: 9,
+ fontWeight: FontWeight.w400,
+ color: ColorsManager.textGray),
+ ),
),
],
),
@@ -62,21 +62,19 @@ class CustomWebTextField extends StatelessWidget {
color: Colors.grey.withOpacity(0.3),
spreadRadius:2,
blurRadius: 3,
- offset: Offset(1, 1), // changes position of shadow
+ offset: const Offset(1, 1), // changes position of shadow
),
]
),
- child: Container(
- child: TextFormField(
- validator: validator,
- controller: controller,
- style: const TextStyle(color: Colors.black),
- decoration: textBoxDecoration()!
- .copyWith(
- errorStyle: const TextStyle(height: 0), // Hide the error text space
+ child: TextFormField(
+ validator: validator,
+ controller: controller,
+ style: const TextStyle(color: Colors.black),
+ decoration: textBoxDecoration()!
+ .copyWith(
+ errorStyle: const TextStyle(height: 0), // Hide the error text space
- hintText: 'Please enter'),
- ),
+ hintText: 'Please enter'),
),
),
],
diff --git a/lib/pages/home/bloc/home_bloc.dart b/lib/pages/home/bloc/home_bloc.dart
index 2b0b5035..58d452ae 100644
--- a/lib/pages/home/bloc/home_bloc.dart
+++ b/lib/pages/home/bloc/home_bloc.dart
@@ -65,7 +65,7 @@ class HomeBloc extends Bloc {
color: null,
),
HomeItemModel(
- title: 'Space\nManagement',
+ title: 'Space Management',
icon: Assets.spaseManagementIcon,
active: true,
onPress: (context) {},
diff --git a/lib/pages/home/view/home_card.dart b/lib/pages/home/view/home_card.dart
index 287bb4f4..ce152c1c 100644
--- a/lib/pages/home/view/home_card.dart
+++ b/lib/pages/home/view/home_card.dart
@@ -37,14 +37,16 @@ class HomeCard extends StatelessWidget {
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
- FittedBox(
- fit: BoxFit.scaleDown,
- child: Text(
- name,
- style: const TextStyle(
- fontSize: 20,
- color: Colors.white,
- fontWeight: FontWeight.bold,
+ Flexible(
+ child: FittedBox(
+ fit: BoxFit.scaleDown,
+ child: Text(
+ name,
+ style: const TextStyle(
+ fontSize: 20,
+ color: Colors.white,
+ fontWeight: FontWeight.bold,
+ ),
),
),
),
diff --git a/lib/pages/home/view/home_page_web.dart b/lib/pages/home/view/home_page_web.dart
index 0124acad..39a79a57 100644
--- a/lib/pages/home/view/home_page_web.dart
+++ b/lib/pages/home/view/home_page_web.dart
@@ -2,13 +2,11 @@ import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.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_state.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/web_layout/web_scaffold.dart';
-import '../bloc/home_state.dart';
-
class HomeWebPage extends StatelessWidget {
HomeWebPage({super.key});
@override
diff --git a/lib/pages/visitor_password/bloc/visitor_password_bloc.dart b/lib/pages/visitor_password/bloc/visitor_password_bloc.dart
index d9f49e56..2a3e486f 100644
--- a/lib/pages/visitor_password/bloc/visitor_password_bloc.dart
+++ b/lib/pages/visitor_password/bloc/visitor_password_bloc.dart
@@ -1,18 +1,18 @@
import 'dart:math';
-
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.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_state.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/services/access_mang_api.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';
- List selectedDevices = [];
-// Define the BLoC
class VisitorPasswordBloc
extends Bloc {
VisitorPasswordBloc() : super(VisitorPasswordInitial()) {
@@ -24,13 +24,12 @@ class VisitorPasswordBloc
on(toggleDaySelection);
on(selectDevice);
on(_onUpdateFilteredDevices);
-
on(postOnlineOneTimePassword);
on(postOnlineMultipleTimePassword);
-
on(postOfflineMultipleTimePassword);
on(postOfflineOneTimePassword);
-
+ on(selectTimeOfLinePassword);
+ on(changeTime);
}
final TextEditingController userNameController = TextEditingController();
final TextEditingController emailController = TextEditingController();
@@ -38,14 +37,14 @@ class VisitorPasswordBloc
final TextEditingController deviceNameController = TextEditingController();
final TextEditingController deviceIdController = TextEditingController();
final TextEditingController unitNameController = TextEditingController();
- final TextEditingController virtualAddressController = TextEditingController();
-
-
+ final TextEditingController virtualAddressController =
+ TextEditingController();
+ List selectedDevices = [];
List data = [];
List selectedDeviceIds = [];
-
-
+ String effectiveTime = 'Start Time';
+ String expirationTime = 'End Time';
final forgetFormKey = GlobalKey();
@@ -58,18 +57,11 @@ class VisitorPasswordBloc
int? effectiveTimeTimeStamp;
int? expirationTimeTimeStamp;
- int? repeatEffectiveTimeTimeStamp;
- int? repeatExpirationTimeTimeStamp;
+ DateTime? startTime = DateTime.now();
+ DateTime? endTime;
- String startTime = 'Start Time';
- String endTime = 'End Time';
-
-
- String repeatStartTime = 'Start Time';
- String repeatEndTime = 'End Time';
-
- // DateTime? repeatStartTime=DateTime.now();
- // DateTime? repeatEndTime;
+ String startTimeAccess = 'Start Time';
+ String endTimeAccess = 'End Time';
selectAccessType(
SelectPasswordType event, Emitter emit) {
@@ -84,14 +76,16 @@ class VisitorPasswordBloc
}
Future selectTimeVisitorPassword(
- SelectTimeVisitorPassword event,
- Emitter emit) async {
+ SelectTimeVisitorPassword event,
+ Emitter emit,
+ ) async {
final DateTime? picked = await showDatePicker(
context: event.context,
initialDate: DateTime.now(),
firstDate: DateTime(2015, 8),
lastDate: DateTime(3101),
);
+
if (picked != null) {
final TimeOfDay? timePicked = await showTimePicker(
context: event.context,
@@ -113,6 +107,7 @@ class VisitorPasswordBloc
);
},
);
+
if (timePicked != null) {
final selectedDateTime = DateTime(
picked.year,
@@ -121,49 +116,35 @@ class VisitorPasswordBloc
timePicked.hour,
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
- {startTime = selectedDateTime.toString().split('.').first;}
- effectiveTimeTimeStamp = selectedTimestamp;
- emit(ChangeTimeState());
+ final selectedTimestamp =
+ selectedDateTime.millisecondsSinceEpoch ~/ 1000;
+
+ 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 {
if (effectiveTimeTimeStamp != null &&
selectedTimestamp < effectiveTimeTimeStamp!) {
- CustomSnackBar.displaySnackBar('Expiration Time cannot be earlier than Effective Time.');
- } else {
- if(event.isRepeat==true)
- {repeatEndTime = selectedDateTime.toString().split('.').first;}
- else
- {endTime = selectedDateTime.toString().split('.').first;}
- expirationTimeTimeStamp = selectedTimestamp;
- emit(ChangeTimeState());
-
+ CustomSnackBar.displaySnackBar(
+ 'Expiration Time cannot be earlier than Effective Time.',
+ );
+ return;
}
- emit(ChangeTimeState());
-
- emit(VisitorPasswordInitial());
+ expirationTimeTimeStamp = selectedTimestamp;
+ endTimeAccess = selectedDateTime.toString().split('.').first;
}
+ emit(ChangeTimeState());
+ emit(VisitorPasswordInitial());
}
}
-
- // emit(AccessInitial());
- // emit(TableLoaded(data));
}
bool toggleRepeat(
@@ -211,67 +192,99 @@ class VisitorPasswordBloc
}
//online password
-
- Future postOnlineOneTimePassword(
- OnlineOneTimePasswordEvent event,
+ Future postOnlineOneTimePassword(OnlineOneTimePasswordEvent event,
Emitter emit) async {
try {
- print('selectedDevices$selectedDevices');
- // emit(DeviceLoaded());
- await AccessMangApi().postOnlineOneTime(
+ emit(LoadingInitialState());
+ generate7DigitNumber();
+ bool res = await AccessMangApi().postOnlineOneTime(
email: event.email,
+ password: passwordController,
devicesUuid: selectedDevices,
- passwordName: event.passwordName);
- // emit(TableLoaded(data));
+ passwordName: event.passwordName,
+ effectiveTime: effectiveTimeTimeStamp.toString(),
+ invalidTime: expirationTimeTimeStamp.toString());
+ if (res == true) {
+ emit(SuccessState());
+ } else {
+ throw Exception('Failed to create password');
+ }
+ emit(TableLoaded(data));
} catch (e) {
emit(FailedState(e.toString()));
+ Navigator.pop(event.context!);
+ stateDialog(
+ context: event.context!,
+ message: e.toString(),
+ title: 'Something Wrong');
}
}
+
Future postOnlineMultipleTimePassword(
OnlineMultipleTimePasswordEvent event,
Emitter emit) async {
try {
- generate7DigitNumber();
- // emit(DeviceLoaded());
- await AccessMangApi().postOnlineMultipleTime(
- scheduleList:[
- // if (repeat)
- // Schedule(
- // effectiveTime: getTimeOnly(repeatStartTime),
- // invalidTime: getTimeOnly(repeatEndTime).toString(),
- // workingDay: selectedDays,
- // ),
- ] ,
+ emit(LoadingInitialState());
+
+ await generate7DigitNumber();
+ bool res = await AccessMangApi().postOnlineMultipleTime(
+ scheduleList: [
+ if (repeat)
+ Schedule(
+ effectiveTime: getTimeFromDateTimeString(expirationTime),
+ invalidTime:
+ getTimeFromDateTimeString(effectiveTime).toString(),
+ workingDay: selectedDays,
+ ),
+ ],
password: passwordController,
- invalidTime:event.invalidTime ,
- effectiveTime:event.effectiveTime ,
+ invalidTime: expirationTimeTimeStamp.toString(),
+ effectiveTime: effectiveTimeTimeStamp.toString(),
email: event.email,
devicesUuid: selectedDevices,
- passwordName: event.passwordName
- );
- // emit(TableLoaded(data));
+ passwordName: event.passwordName);
+ if (res == true) {
+ emit(SuccessState());
+ }else {
+ throw Exception('Failed to create password');
+ }
+ emit(TableLoaded(data));
+
} catch (e) {
emit(FailedState(e.toString()));
+ Navigator.pop(event.context!);
+ stateDialog(
+ context: event.context!,
+ message: e.toString(),
+ title: 'Something Wrong');
}
}
-
//offline password
- Future postOfflineOneTimePassword(
- OfflineOneTimePasswordEvent event,
+ Future postOfflineOneTimePassword(OfflineOneTimePasswordEvent event,
Emitter emit) async {
try {
- generate7DigitNumber();
- // emit(DeviceLoaded());
- await AccessMangApi().postOffLineOneTime(
+ emit(LoadingInitialState());
+ await generate7DigitNumber();
+ bool res = await AccessMangApi().postOffLineOneTime(
email: event.email,
devicesUuid: selectedDevices,
- passwordName: event.passwordName
- );
- // emit(TableLoaded(data));
+ passwordName: event.passwordName);
+ if (res == true) {
+ emit(SuccessState());
+ }else {
+ throw Exception('Failed to create password');
+ }
+ emit(TableLoaded(data));
+
} catch (e) {
emit(FailedState(e.toString()));
+ Navigator.pop(event.context!);
+ stateDialog(
+ context: event.context!,
+ message: e.toString(),
+ title: 'Something Wrong');
}
}
@@ -279,22 +292,31 @@ class VisitorPasswordBloc
OfflineMultipleTimePasswordEvent event,
Emitter emit) async {
try {
- generate7DigitNumber();
- // emit(DeviceLoaded());
- await AccessMangApi().postOffLineMultipleTime(
- email: event.email,
- devicesUuid: selectedDevices,
- passwordName: event.passwordName,
- invalidTime:event.invalidTime ,
- effectiveTime:event.effectiveTime
+ emit(LoadingInitialState());
+ await generate7DigitNumber();
+ bool res = await AccessMangApi().postOffLineMultipleTime(
+ email: event.email,
+ devicesUuid: selectedDevices,
+ passwordName: event.passwordName,
+ invalidTime: expirationTimeTimeStamp.toString(),
+ effectiveTime: effectiveTimeTimeStamp.toString(),
);
- // emit(TableLoaded(data));
+ if (res == true) {
+ emit(SuccessState());
+ }else {
+ throw Exception('Failed to create password');
+ }
+ emit(TableLoaded(data));
+
} catch (e) {
emit(FailedState(e.toString()));
- }
+ Navigator.pop(event.context!);
+ stateDialog(
+ context: event.context!,
+ message: e.toString(),
+ title: 'Something Wrong'); }
}
-
void selectDevice(
SelectDeviceEvent event, Emitter emit) {
if (selectedDeviceIds.contains(event.deviceId)) {
@@ -302,8 +324,6 @@ class VisitorPasswordBloc
} else {
selectedDeviceIds.add(event.deviceId);
}
- selectedDevices=selectedDeviceIds;
- print(selectedDevices);
}
String? validate(String? value) {
@@ -313,49 +333,165 @@ class VisitorPasswordBloc
return null;
}
-
Future generate7DigitNumber() async {
- emit(LoadingInitialState());
- passwordController='';
+ passwordController = '';
Random random = Random();
int min = 1000000;
int max = 9999999;
passwordController = (min + random.nextInt(max - min + 1)).toString();
- emit(GeneratePasswordState());
return passwordController;
}
+
String getTimeOnly(DateTime? dateTime) {
if (dateTime == null) return '';
return DateFormat('HH:mm').format(dateTime);
}
-
void filterDevices() {
final deviceName = deviceNameController.text.toLowerCase();
final deviceId = deviceIdController.text.toLowerCase();
final unitName = unitNameController.text.toLowerCase();
-
final filteredData = data.where((device) {
final matchesDeviceName = device.name.toLowerCase().contains(deviceName);
final matchesDeviceId = device.uuid.toLowerCase().contains(deviceId);
// final matchesUnitName = device.unitName.toLowerCase().contains(unitName); // Assuming unitName is a property of the device
-
- return matchesDeviceName && matchesDeviceId ;
+ return matchesDeviceName && matchesDeviceId;
}).toList();
- // emit(TableLoaded(filteredData));
-
- add(UpdateFilteredDevicesEvent(filteredData));
+ add(UpdateFilteredDevicesEvent(filteredData));
}
+
@override
- Stream mapEventToState(VisitorPasswordEvent event) async* {
+ Stream mapEventToState(
+ VisitorPasswordEvent event) async* {
if (event is FetchDevice) {
- // Fetching logic...
} else if (event is UpdateFilteredDevicesEvent) {
yield TableLoaded(event.filteredData);
}
}
- void _onUpdateFilteredDevices(UpdateFilteredDevicesEvent event, Emitter emit) {
+ void _onUpdateFilteredDevices(
+ UpdateFilteredDevicesEvent event, Emitter emit) {
emit(TableLoaded(event.filteredData));
}
+
+ addDeviceToList(context) {
+ selectedDevices = selectedDeviceIds;
+ Navigator.of(context).pop(selectedDevices);
+ }
+
+ Future selectTimeOfLinePassword(
+ SelectTimeEvent event, Emitter 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 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 stateDialog({
+ BuildContext? context,
+ String? message,
+ String? title,
+ dynamic actions,
+ }) {
+ return showCustomDialog(
+ context: context!,
+ message: message!,
+ iconPath: Assets.deviceNoteIcon,
+ title: title,
+ dialogHeight: 150,
+ actions: actions ??
+ [
+ TextButton(
+ onPressed: () {
+ Navigator.of(context).pop();
+ },
+ child: const Text('OK'),
+ ),
+ ],
+ );
+ }
}
diff --git a/lib/pages/visitor_password/bloc/visitor_password_event.dart b/lib/pages/visitor_password/bloc/visitor_password_event.dart
index 9990ad9a..9526bf54 100644
--- a/lib/pages/visitor_password/bloc/visitor_password_event.dart
+++ b/lib/pages/visitor_password/bloc/visitor_password_event.dart
@@ -51,14 +51,16 @@ class ToggleDaySelectionEvent extends VisitorPasswordEvent {
class ToggleRepeatEvent extends VisitorPasswordEvent {}
class GeneratePasswordEvent extends VisitorPasswordEvent {}
-class FetchDevice extends VisitorPasswordEvent {}
+class FetchDevice extends VisitorPasswordEvent {
+}
//online password
class OnlineOneTimePasswordEvent extends VisitorPasswordEvent {
final String? email;
final String? passwordName;
+ final BuildContext? context;
- const OnlineOneTimePasswordEvent({this.email,this.passwordName});
+ const OnlineOneTimePasswordEvent({this.email,this.passwordName,this.context});
@override
List