diff --git a/assets/images/grid.svg b/assets/images/grid.svg
new file mode 100644
index 00000000..f3e41133
--- /dev/null
+++ b/assets/images/grid.svg
@@ -0,0 +1,18 @@
+
diff --git a/devtools_options.yaml b/devtools_options.yaml
index fa0b357c..6ee932ce 100644
--- a/devtools_options.yaml
+++ b/devtools_options.yaml
@@ -1,3 +1,4 @@
description: This file stores settings for Dart & Flutter DevTools.
documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states
extensions:
+ - provider: true
diff --git a/lib/main.dart b/lib/main.dart
index 6a7fd37d..90c643cc 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -2,28 +2,34 @@ import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
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:go_router/go_router.dart';
import 'package:syncrow_web/services/locator.dart';
+import 'package:syncrow_web/utils/app_routes.dart';
import 'package:syncrow_web/utils/color_manager.dart';
+import 'package:syncrow_web/utils/constants/routes_const.dart';
Future main() async {
WidgetsFlutterBinding.ensureInitialized();
- initialSetup(); // Perform initial setup, e.g., dependency injection
+ initialSetup();
String checkToken = await AuthBloc.getTokenAndValidate();
+ GoRouter router = GoRouter(
+ initialLocation: checkToken == 'Success' ? RoutesConst.home : RoutesConst.auth,
+ routes: AppRoutes.getRoutes(),
+ );
runApp(MyApp(
- isLoggedIn: checkToken,
+ router: router,
));
}
class MyApp extends StatelessWidget {
- final dynamic isLoggedIn;
+ final GoRouter router;
const MyApp({
super.key,
- required this.isLoggedIn,
+ required this.router,
});
+
@override
Widget build(BuildContext context) {
return MultiBlocProvider(
@@ -33,7 +39,7 @@ class MyApp extends StatelessWidget {
create: (context) => VisitorPasswordBloc(),
)
],
- child: MaterialApp(
+ child: MaterialApp.router(
debugShowCheckedModeBanner: false, // Hide debug banner
scrollBehavior: const MaterialScrollBehavior().copyWith(
dragDevices: {
@@ -48,9 +54,7 @@ class MyApp extends StatelessWidget {
fontFamily: 'Aftika',
textTheme: const TextTheme(
bodySmall: TextStyle(
- fontSize: 13,
- color: ColorsManager.whiteColors,
- fontWeight: FontWeight.bold),
+ fontSize: 13, color: ColorsManager.whiteColors, fontWeight: FontWeight.bold),
bodyMedium: TextStyle(color: Colors.black87, fontSize: 14),
bodyLarge: TextStyle(fontSize: 16, color: Colors.white),
headlineSmall: TextStyle(color: Colors.black87, fontSize: 18),
@@ -61,47 +65,10 @@ class MyApp extends StatelessWidget {
fontWeight: FontWeight.bold,
),
),
- colorScheme: ColorScheme.fromSeed(
- seedColor: ColorsManager.blueColor,
- primary: ColorsManager.blueColor, // Checked state color
- onSurface: Colors.grey.shade400, // Unchecked state color
- ),
- switchTheme: SwitchThemeData(
- thumbColor: MaterialStateProperty.resolveWith((states) {
- if (states.contains(MaterialState.selected)) {
- return ColorsManager
- .blueColor; // Color of the switch knob when selected
- }
- return ColorsManager
- .whiteColors; // Color of the switch knob when not selected
- }),
- trackColor: MaterialStateProperty.resolveWith((states) {
- if (states.contains(MaterialState.selected)) {
- return ColorsManager.blueColor
- .withOpacity(0.5); // Track color when selected
- }
- return ColorsManager
- .whiteColors; // Track color when not selected
- }),
- ),
- checkboxTheme: CheckboxThemeData(
- fillColor: MaterialStateProperty.resolveWith((states) {
- if (states.contains(MaterialState.selected)) {
- return ColorsManager.blueColor; // Checked state color
- }
- return Colors.grey.shade200; // Unchecked state color
- }),
- checkColor: MaterialStateProperty.all(
- Colors.white), // The color of the checkmark
- side:
- BorderSide(color: ColorsManager.whiteColors), // Border color
- shape: RoundedRectangleBorder(
- borderRadius: BorderRadius.circular(4), // Border radius
- ),
- ),
- useMaterial3: true, // Enable Material 3
),
- home: isLoggedIn == 'Success' ? const HomePage() : const LoginPage(),
+ routeInformationProvider: router.routeInformationProvider,
+ routerDelegate: router.routerDelegate,
+ routeInformationParser: router.routeInformationParser,
));
}
}
diff --git a/lib/pages/access_management/bloc/access_bloc.dart b/lib/pages/access_management/bloc/access_bloc.dart
index d5b42bd1..473d19bd 100644
--- a/lib/pages/access_management/bloc/access_bloc.dart
+++ b/lib/pages/access_management/bloc/access_bloc.dart
@@ -5,7 +5,7 @@ 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/constants/app_enum.dart';
import 'package:syncrow_web/utils/snack_bar.dart';
class AccessBloc extends Bloc {
@@ -26,8 +26,7 @@ class AccessBloc extends Bloc {
List filteredData = [];
List data = [];
- Future _onFetchTableData(
- FetchTableData event, Emitter emit) async {
+ Future _onFetchTableData(FetchTableData event, Emitter emit) async {
try {
emit(AccessLoaded());
data = await AccessMangApi().fetchVisitorPassword();
@@ -40,28 +39,19 @@ class AccessBloc extends Bloc {
}
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;
+ 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)',
- 'Effective (0)',
- 'Expired'
- ];
+ final List tabs = ['All', 'To Be Effective (0)', 'Effective (0)', 'Expired'];
- Future selectFilterTap(
- TabChangedEvent event, Emitter emit) async {
+ Future selectFilterTap(TabChangedEvent event, Emitter emit) async {
try {
emit(AccessLoaded());
selectedIndex = event.selectedIndex;
@@ -75,7 +65,6 @@ class AccessBloc extends Bloc {
Future selectTime(SelectTime event, Emitter emit) async {
emit(AccessLoaded());
-
final DateTime? picked = await showDatePicker(
context: event.context,
initialDate: DateTime.now(),
@@ -83,111 +72,112 @@ class AccessBloc extends Bloc {
lastDate: DateTime(2101),
);
if (picked != null) {
- final TimeOfDay? timePicked = await showTimePicker(
- context: event.context,
- initialTime: TimeOfDay.now(),
- builder: (context, child) {
- return Theme(
- data: ThemeData.light().copyWith(
- colorScheme: const ColorScheme.light(
- primary: ColorsManager.primaryColor,
- onSurface: Colors.black,
- ),
- buttonTheme: const ButtonThemeData(
- colorScheme: ColorScheme.light(
- primary: Colors.green,
- ),
- ),
- ),
- child: child!,
- );
- },
+ final selectedDateTime = DateTime(
+ picked.year,
+ picked.month,
+ picked.day,
);
- if (timePicked != null) {
- final selectedDateTime = DateTime(
- picked.year,
- picked.month,
- picked.day,
- 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 {
- startTime = selectedDateTime
- .toString()
- .split('.')
- .first; // Remove seconds and milliseconds
- effectiveTimeTimeStamp = selectedTimestamp;
- }
+ 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 (effectiveTimeTimeStamp != null &&
- selectedTimestamp < effectiveTimeTimeStamp!) {
- CustomSnackBar.displaySnackBar(
- 'Expiration Time cannot be earlier than Effective Time.');
- } else {
- endTime = selectedDateTime
- .toString()
- .split('.')
- .first; // Remove seconds and milliseconds
- expirationTimeTimeStamp = selectedTimestamp;
- }
+ startTime =
+ 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 {
+ endTime = selectedDateTime.toString().split('.').first; // Remove seconds and milliseconds
+ expirationTimeTimeStamp = selectedTimestamp;
}
}
}
emit(ChangeTimeState());
}
- Future _filterData(
- FilterDataEvent event, Emitter emit) async {
+ Future _filterData(FilterDataEvent event, Emitter emit) async {
emit(AccessLoaded());
try {
filteredData = data.where((item) {
bool matchesCriteria = true;
+
+ // Convert timestamp to DateTime and extract date component
+ DateTime effectiveDate =
+ DateTime.fromMillisecondsSinceEpoch(int.parse(item.effectiveTime.toString()) * 1000)
+ .toUtc()
+ .toLocal();
+ DateTime invalidDate =
+ DateTime.fromMillisecondsSinceEpoch(int.parse(item.invalidTime.toString()) * 1000)
+ .toUtc()
+ .toLocal();
+ DateTime effectiveDateOnly =
+ DateTime(effectiveDate.year, effectiveDate.month, effectiveDate.day);
+ DateTime invalidDateOnly = DateTime(invalidDate.year, invalidDate.month, invalidDate.day);
+
+ // Filter by password name
if (event.passwordName != null && event.passwordName!.isNotEmpty) {
- final bool matchesName = item.passwordName != null &&
- item.passwordName.contains(event.passwordName);
+ final bool matchesName =
+ item.passwordName != null && item.passwordName.contains(event.passwordName);
if (!matchesName) {
matchesCriteria = false;
}
}
- if (event.startTime != null && event.endTime != null) {
- final int? effectiveTime =
- int.tryParse(item.effectiveTime.toString());
- final int? invalidTime = int.tryParse(item.invalidTime.toString());
- if (effectiveTime == null || invalidTime == null) {
+
+ // Filter by start date only
+ if (event.startTime != null && event.endTime == null) {
+ DateTime startDateOnly =
+ DateTime.fromMillisecondsSinceEpoch(event.startTime! * 1000).toUtc().toLocal();
+ startDateOnly = DateTime(startDateOnly.year, startDateOnly.month, startDateOnly.day);
+ if (effectiveDateOnly.isBefore(startDateOnly)) {
matchesCriteria = false;
- } else {
- final bool matchesStartTime = effectiveTime >= event.startTime!;
- final bool matchesEndTime = invalidTime <= event.endTime!;
- if (!matchesStartTime || !matchesEndTime) {
- matchesCriteria = false;
- }
}
}
- if (event.selectedTabIndex == 1 &&
- item.passwordStatus.value != 'To Be Effective') {
+
+ // Filter by end date only
+ if (event.endTime != null && event.startTime == null) {
+ DateTime endDateOnly =
+ DateTime.fromMillisecondsSinceEpoch(event.endTime! * 1000).toUtc().toLocal();
+ endDateOnly = DateTime(endDateOnly.year, endDateOnly.month, endDateOnly.day);
+ if (invalidDateOnly.isAfter(endDateOnly)) {
+ matchesCriteria = false;
+ }
+ }
+
+ // Filter by both start date and end date
+ if (event.startTime != null && event.endTime != null) {
+ DateTime startDateOnly =
+ DateTime.fromMillisecondsSinceEpoch(event.startTime! * 1000).toUtc().toLocal();
+ DateTime endDateOnly =
+ DateTime.fromMillisecondsSinceEpoch(event.endTime! * 1000).toUtc().toLocal();
+ startDateOnly = DateTime(startDateOnly.year, startDateOnly.month, startDateOnly.day);
+ endDateOnly = DateTime(endDateOnly.year, endDateOnly.month, endDateOnly.day);
+ if (effectiveDateOnly.isBefore(startDateOnly) || invalidDateOnly.isAfter(endDateOnly)) {
+ matchesCriteria = false;
+ }
+ }
+
+ // Filter by selected tab index
+ if (event.selectedTabIndex == 1 && item.passwordStatus.value != 'To be effective') {
matchesCriteria = false;
- } else if (event.selectedTabIndex == 2 &&
- item.passwordStatus.value != 'Effective') {
+ } else if (event.selectedTabIndex == 2 && item.passwordStatus.value != 'Effective') {
matchesCriteria = false;
- } else if (event.selectedTabIndex == 3 &&
- item.passwordStatus.value != 'Expired') {
+ } else if (event.selectedTabIndex == 3 && item.passwordStatus.value != 'Expired') {
matchesCriteria = false;
}
+
return matchesCriteria;
}).toList();
+
emit(TableLoaded(filteredData));
} catch (e) {
emit(FailedState(e.toString()));
@@ -206,13 +196,11 @@ class AccessBloc extends Bloc {
}
String timestampToDate(dynamic timestamp) {
- DateTime dateTime =
- DateTime.fromMillisecondsSinceEpoch(int.parse(timestamp) * 1000);
+ DateTime dateTime = DateTime.fromMillisecondsSinceEpoch(int.parse(timestamp) * 1000);
return "${dateTime.year}/${dateTime.month.toString().padLeft(2, '0')}/${dateTime.day.toString().padLeft(2, '0')}";
}
- Future onTabChanged(
- TabChangedEvent event, Emitter emit) async {
+ Future onTabChanged(TabChangedEvent event, Emitter emit) async {
try {
emit(AccessLoaded());
selectedIndex = event.selectedIndex;
@@ -221,19 +209,14 @@ class AccessBloc extends Bloc {
filteredData = data;
break;
case 1: // To Be Effective
- filteredData = data
- .where((item) => item.passwordStatus.value == "To Be Effective")
- .toList();
+ filteredData =
+ data.where((item) => item.passwordStatus.value == "To Be Effective").toList();
break;
case 2: // Effective
- filteredData = data
- .where((item) => item.passwordStatus.value == "Effective")
- .toList();
+ filteredData = data.where((item) => item.passwordStatus.value == "Effective").toList();
break;
case 3: // Expired
- filteredData = data
- .where((item) => item.passwordStatus.value == "Expired")
- .toList();
+ filteredData = data.where((item) => item.passwordStatus.value == "Expired").toList();
break;
default:
filteredData = data;
diff --git a/lib/pages/access_management/model/password_model.dart b/lib/pages/access_management/model/password_model.dart
index e79528fc..8436ef56 100644
--- a/lib/pages/access_management/model/password_model.dart
+++ b/lib/pages/access_management/model/password_model.dart
@@ -1,4 +1,4 @@
-import 'package:syncrow_web/utils/constants/const.dart';
+import 'package:syncrow_web/utils/constants/app_enum.dart';
class PasswordModel {
final dynamic passwordId;
diff --git a/lib/pages/access_management/view/access_management.dart b/lib/pages/access_management/view/access_management.dart
index 09912ba5..a63b02a3 100644
--- a/lib/pages/access_management/view/access_management.dart
+++ b/lib/pages/access_management/view/access_management.dart
@@ -1,293 +1,287 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:flutter_svg/flutter_svg.dart';
+import 'package:go_router/go_router.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/buttons/default_button.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/buttons/default_button.dart';
+import 'package:syncrow_web/pages/common/text_field/custom_web_textfield.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/constants/app_enum.dart';
+import 'package:syncrow_web/utils/constants/routes_const.dart';
import 'package:syncrow_web/utils/style.dart';
import 'package:syncrow_web/web_layout/web_scaffold.dart';
class AccessManagementPage extends StatelessWidget {
const AccessManagementPage({super.key});
-
@override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
return WebScaffold(
- enableMenuSideba: false,
- appBarTitle: Row(
- children: [
- Text(
- 'Access Management',
- style: Theme.of(context).textTheme.headlineLarge,
- )
- ],
- ),
- appBarBody: [
- Text(
- 'Physical Access',
- style: Theme.of(context)
- .textTheme
- .headlineMedium!
- .copyWith(color: Colors.white),
+ enableMenuSideba: false,
+ appBarTitle: Row(
+ children: [
+ Text(
+ 'Access Management',
+ style: Theme.of(context).textTheme.headlineLarge,
+ )
+ ],
),
- ],
- scaffoldBody: BlocProvider(
- create: (BuildContext context) => AccessBloc()..add(FetchTableData()),
- child: BlocConsumer(
- listener: (context, state) {},
- builder: (context, state) {
- final accessBloc = BlocProvider.of(context);
- final filteredData = accessBloc.filteredData;
-
- return state is AccessLoaded
- ? const Center(child: CircularProgressIndicator())
- : CustomScrollView(
- slivers: [
- SliverToBoxAdapter(
- child: Padding(
- padding: const EdgeInsets.all(30),
+ appBarBody: [
+ Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ Text(
+ 'Physical Access',
+ style: Theme.of(context).textTheme.headlineMedium!.copyWith(color: Colors.white),
+ ),
+ Row(
+ children: [
+ InkWell(
+ onTap: () {
+ context.go(RoutesConst.home);
+ },
+ child: SvgPicture.asset(
+ height: 20,
+ width: 20,
+ Assets.grid,
+ ),
+ ),
+ const SizedBox(
+ width: 10,
+ )
+ ],
+ ),
+ ],
+ ),
+ ],
+ scaffoldBody: BlocProvider(
+ create: (BuildContext context) => AccessBloc()..add(FetchTableData()),
+ child: BlocConsumer(
+ 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: [
- _buildTabSelector(context, accessBloc, size),
- const SizedBox(height: 20),
- _buildSearchFilters(context, accessBloc, size),
- const SizedBox(height: 20),
- _buildActionButtons(context, accessBloc, size),
- const SizedBox(height: 20),
+ Container(
+ decoration: containerDecoration,
+ 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: [
+ Container(
+ width: size.width * 0.15,
+ child: CustomWebTextField(
+ controller: accessBloc.passwordName,
+ isRequired: true,
+ textFieldName: 'Name',
+ description: '',
+ ),
+ ),
+ 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(
+ 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(
+ 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()),
+ )
],
),
- ),
- ),
- SliverFillRemaining(
- 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(),
- ),
- ),
- ],
- );
- },
- ),
- ),
- );
- }
-
- Widget _buildTabSelector(
- BuildContext context, AccessBloc accessBloc, Size size) {
- return Container(
- decoration: containerDecoration,
- height: size.height * 0.05,
- child: Flexible(
- child: ListView.builder(
- scrollDirection: Axis.horizontal,
- itemCount: accessBloc.tabs.length,
- shrinkWrap: true,
- itemBuilder: (context, index) {
- final isSelected = index == accessBloc.selectedIndex;
- return InkWell(
- onTap: () {
- accessBloc.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 == accessBloc.tabs.length - 1
- ? const BorderRadius.only(
- topRight: Radius.circular(10),
- bottomRight: Radius.circular(10))
- : null,
- ),
- padding: const EdgeInsets.only(left: 10, right: 10),
- child: Center(
- child: Text(
- accessBloc.tabs[index],
- style: TextStyle(
- color: isSelected ? Colors.blue : Colors.black,
- ),
- ),
- ),
- ),
- );
- },
- ),
- ),
- );
- }
-
- Widget _buildSearchFilters(
- BuildContext context, AccessBloc accessBloc, Size size) {
- return 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: accessBloc.startTime,
- secondString: accessBloc.endTime,
- ),
- const SizedBox(width: 15),
- SizedBox(
- height: 45,
- width: size.width * 0.06,
- child: Container(
- decoration: containerDecoration,
- child: DefaultButton(
- onPressed: () {
- accessBloc.add(FilterDataEvent(
- selectedTabIndex:
- accessBloc.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),
- ),
- ),
- ),
- ),
- ],
- );
- }
-
- Widget _buildActionButtons(
- BuildContext context, AccessBloc accessBloc, Size size) {
- return 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),
- ),
- ),
- )
- ],
- );
+ );
+ })));
}
}
diff --git a/lib/pages/auth/view/login_web_page.dart b/lib/pages/auth/view/login_web_page.dart
index cce4f1a8..7e9123ee 100644
--- a/lib/pages/auth/view/login_web_page.dart
+++ b/lib/pages/auth/view/login_web_page.dart
@@ -1,9 +1,8 @@
-import 'package:flutter/cupertino.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
-import 'package:flutter/widgets.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/svg.dart';
+import 'package:go_router/go_router.dart';
import 'package:syncrow_web/pages/auth/bloc/auth_bloc.dart';
import 'package:syncrow_web/pages/auth/bloc/auth_event.dart';
import 'package:syncrow_web/pages/auth/bloc/auth_state.dart';
@@ -13,7 +12,7 @@ import 'package:syncrow_web/pages/common/buttons/default_button.dart';
import 'package:syncrow_web/pages/common/first_layer.dart';
import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/utils/constants/assets.dart';
-import 'package:syncrow_web/pages/home/view/home_page.dart';
+import 'package:syncrow_web/utils/constants/routes_const.dart';
import 'package:syncrow_web/utils/style.dart';
class LoginWebPage extends StatefulWidget {
@@ -32,13 +31,8 @@ class _LoginWebPageState extends State {
child: BlocConsumer(
listener: (context, state) {
if (state is LoginSuccess) {
- // Navigate to home screen after successful login
- Navigator.pushReplacement(
- context,
- MaterialPageRoute(builder: (context) => HomePage()),
- );
+ context.go(RoutesConst.home);
} else if (state is LoginFailure) {
- // Show error message
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(state.error),
@@ -60,8 +54,7 @@ class _LoginWebPageState extends State {
late ScrollController _scrollController;
_scrollController = ScrollController();
void _scrollToCenter() {
- final double middlePosition =
- _scrollController.position.maxScrollExtent / 2;
+ final double middlePosition = _scrollController.position.maxScrollExtent / 2;
_scrollController.animateTo(
middlePosition,
duration: const Duration(seconds: 1),
@@ -105,11 +98,9 @@ class _LoginWebPageState extends State {
child: Container(
decoration: BoxDecoration(
color: Colors.white.withOpacity(0.1),
- borderRadius: const BorderRadius.all(
- Radius.circular(30)),
+ borderRadius: const BorderRadius.all(Radius.circular(30)),
border: Border.all(
- color: ColorsManager.graysColor
- .withOpacity(0.2))),
+ color: ColorsManager.graysColor.withOpacity(0.2))),
child: Form(
key: loginBloc.loginFormKey,
child: Padding(
@@ -117,22 +108,16 @@ class _LoginWebPageState extends State {
horizontal: size.width * 0.02,
vertical: size.width * 0.003),
child: Column(
- mainAxisAlignment:
- MainAxisAlignment.spaceEvenly,
- crossAxisAlignment:
- CrossAxisAlignment.start,
+ mainAxisAlignment: MainAxisAlignment.spaceEvenly,
+ crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(height: 40),
Text('Login',
- style: Theme.of(context)
- .textTheme
- .headlineLarge),
+ style: Theme.of(context).textTheme.headlineLarge),
SizedBox(height: size.height * 0.03),
Column(
- crossAxisAlignment:
- CrossAxisAlignment.start,
- mainAxisAlignment:
- MainAxisAlignment.start,
+ crossAxisAlignment: CrossAxisAlignment.start,
+ mainAxisAlignment: MainAxisAlignment.start,
children: [
Text(
"Country/Region",
@@ -140,81 +125,57 @@ class _LoginWebPageState extends State {
.textTheme
.bodySmall!
.copyWith(
- fontSize: 14,
- fontWeight:
- FontWeight.w400),
+ fontSize: 14, fontWeight: FontWeight.w400),
),
const SizedBox(
height: 10,
),
SizedBox(
- child: DropdownButtonFormField<
- String>(
+ child: DropdownButtonFormField(
padding: EdgeInsets.zero,
- value: loginBloc.regionList!
- .any((region) =>
- region.id ==
- loginBloc
- .regionUuid)
+ value: loginBloc.regionList!.any((region) =>
+ region.id == loginBloc.regionUuid)
? loginBloc.regionUuid
: null,
- validator:
- loginBloc.validateRegion,
+ validator: loginBloc.validateRegion,
icon: const Icon(
- Icons
- .keyboard_arrow_down_outlined,
+ Icons.keyboard_arrow_down_outlined,
),
- decoration: textBoxDecoration()!
- .copyWith(
- errorStyle: const TextStyle(
- height: 0),
+ decoration: textBoxDecoration()!.copyWith(
+ errorStyle: const TextStyle(height: 0),
hintText: null,
),
hint: SizedBox(
width: size.width * 0.12,
child: Align(
- alignment:
- Alignment.centerLeft,
+ alignment: Alignment.centerLeft,
child: Text(
'Select your region/country',
- textAlign:
- TextAlign.center,
+ textAlign: TextAlign.center,
style: Theme.of(context)
.textTheme
.bodySmall!
.copyWith(
- color:
- ColorsManager
- .grayColor,
- fontWeight:
- FontWeight
- .w400),
- overflow:
- TextOverflow.ellipsis,
+ color: ColorsManager.grayColor,
+ fontWeight: FontWeight.w400),
+ overflow: TextOverflow.ellipsis,
),
),
),
isDense: true,
- style: const TextStyle(
- color: Colors.black),
- items: loginBloc.regionList!
- .map((RegionModel region) {
- return DropdownMenuItem<
- String>(
+ style: const TextStyle(color: Colors.black),
+ items:
+ loginBloc.regionList!.map((RegionModel region) {
+ return DropdownMenuItem(
value: region.id,
child: SizedBox(
- width:
- size.width * 0.08,
- child:
- Text(region.name)),
+ width: size.width * 0.08,
+ child: Text(region.name)),
);
}).toList(),
onChanged: (String? value) {
- loginBloc
- .add(CheckEnableEvent());
- loginBloc.add(
- SelectRegionEvent(
- val: value!));
+ loginBloc.add(CheckEnableEvent());
+ loginBloc.add(SelectRegionEvent(val: value!));
},
),
)
@@ -222,10 +183,8 @@ class _LoginWebPageState extends State {
),
const SizedBox(height: 20.0),
Column(
- crossAxisAlignment:
- CrossAxisAlignment.start,
- mainAxisAlignment:
- MainAxisAlignment.start,
+ crossAxisAlignment: CrossAxisAlignment.start,
+ mainAxisAlignment: MainAxisAlignment.start,
children: [
Text(
"Email",
@@ -233,9 +192,7 @@ class _LoginWebPageState extends State {
.textTheme
.bodySmall!
.copyWith(
- fontSize: 14,
- fontWeight:
- FontWeight.w400),
+ fontSize: 14, fontWeight: FontWeight.w400),
),
const SizedBox(
height: 10,
@@ -243,43 +200,30 @@ class _LoginWebPageState extends State {
SizedBox(
child: TextFormField(
onChanged: (value) {
- loginBloc
- .add(CheckEnableEvent());
+ loginBloc.add(CheckEnableEvent());
// print(loginBloc.checkEnable());
},
- validator: loginBloc
- .loginValidateEmail,
- controller: loginBloc
- .loginEmailController,
- decoration: textBoxDecoration()!
- .copyWith(
- errorStyle: const TextStyle(
- height:
- 0), // Hide the error text space
- hintText:
- 'Enter your email address',
- hintStyle: Theme.of(
- context)
- .textTheme
- .bodySmall!
- .copyWith(
- color: ColorsManager
- .grayColor,
- fontWeight:
- FontWeight
- .w400)),
- style: const TextStyle(
- color: Colors.black),
+ validator: loginBloc.loginValidateEmail,
+ controller: loginBloc.loginEmailController,
+ decoration: textBoxDecoration()!.copyWith(
+ errorStyle: const TextStyle(
+ height: 0), // Hide the error text space
+ hintText: 'Enter your email address',
+ hintStyle: Theme.of(context)
+ .textTheme
+ .bodySmall!
+ .copyWith(
+ color: ColorsManager.grayColor,
+ fontWeight: FontWeight.w400)),
+ style: const TextStyle(color: Colors.black),
),
),
],
),
const SizedBox(height: 20.0),
Column(
- crossAxisAlignment:
- CrossAxisAlignment.start,
- mainAxisAlignment:
- MainAxisAlignment.start,
+ crossAxisAlignment: CrossAxisAlignment.start,
+ mainAxisAlignment: MainAxisAlignment.start,
children: [
Text(
"Password",
@@ -287,9 +231,7 @@ class _LoginWebPageState extends State {
.textTheme
.bodySmall!
.copyWith(
- fontSize: 14,
- fontWeight:
- FontWeight.w400),
+ fontSize: 14, fontWeight: FontWeight.w400),
),
const SizedBox(
height: 10,
@@ -297,54 +239,39 @@ class _LoginWebPageState extends State {
SizedBox(
child: TextFormField(
onChanged: (value) {
- loginBloc
- .add(CheckEnableEvent());
+ loginBloc.add(CheckEnableEvent());
},
- validator:
- loginBloc.validatePassword,
- obscureText:
- loginBloc.obscureText,
- keyboardType: TextInputType
- .visiblePassword,
- controller: loginBloc
- .loginPasswordController,
- decoration: textBoxDecoration()!
- .copyWith(
- hintText:
- 'At least 8 characters',
+ validator: loginBloc.validatePassword,
+ obscureText: loginBloc.obscureText,
+ keyboardType: TextInputType.visiblePassword,
+ controller: loginBloc.loginPasswordController,
+ decoration: textBoxDecoration()!.copyWith(
+ hintText: 'At least 8 characters',
hintStyle: Theme.of(context)
.textTheme
.bodySmall!
.copyWith(
- color: ColorsManager
- .grayColor,
- fontWeight:
- FontWeight.w400),
+ color: ColorsManager.grayColor,
+ fontWeight: FontWeight.w400),
suffixIcon: IconButton(
onPressed: () {
- loginBloc.add(
- PasswordVisibleEvent(
- newValue: loginBloc
- .obscureText));
+ loginBloc.add(PasswordVisibleEvent(
+ newValue: loginBloc.obscureText));
},
icon: SizedBox(
child: SvgPicture.asset(
loginBloc.obscureText
- ? Assets
- .visiblePassword
- : Assets
- .invisiblePassword,
+ ? Assets.visiblePassword
+ : Assets.invisiblePassword,
height: 15,
width: 15,
),
),
),
errorStyle: const TextStyle(
- height:
- 0), // Hide the error text space
+ height: 0), // Hide the error text space
),
- style: const TextStyle(
- color: Colors.black),
+ style: const TextStyle(color: Colors.black),
),
),
],
@@ -354,13 +281,11 @@ class _LoginWebPageState extends State {
),
SizedBox(
child: Row(
- mainAxisAlignment:
- MainAxisAlignment.end,
+ mainAxisAlignment: MainAxisAlignment.end,
children: [
InkWell(
onTap: () {
- Navigator.of(context)
- .push(MaterialPageRoute(
+ Navigator.of(context).push(MaterialPageRoute(
builder: (context) =>
const ForgetPasswordPage(),
));
@@ -373,8 +298,7 @@ class _LoginWebPageState extends State {
.copyWith(
color: Colors.black,
fontSize: 14,
- fontWeight:
- FontWeight.w400),
+ fontWeight: FontWeight.w400),
),
),
],
@@ -386,18 +310,16 @@ class _LoginWebPageState extends State {
Row(
children: [
Transform.scale(
- scale:
- 1.2, // Adjust the scale as needed
+ scale: 1.2, // Adjust the scale as needed
child: Checkbox(
- fillColor: MaterialStateProperty
- .all(Colors.white),
+ fillColor:
+ MaterialStateProperty.all(Colors.white),
activeColor: Colors.white,
value: loginBloc.isChecked,
checkColor: Colors.black,
shape: const CircleBorder(),
onChanged: (bool? newValue) {
- loginBloc.add(CheckBoxEvent(
- newValue: newValue));
+ loginBloc.add(CheckBoxEvent(newValue: newValue));
},
),
),
@@ -406,45 +328,36 @@ class _LoginWebPageState extends State {
child: RichText(
text: TextSpan(
text: 'Agree to ',
- style: const TextStyle(
- color: Colors.white),
+ style: const TextStyle(color: Colors.white),
children: [
TextSpan(
- text:
- '(Terms of Service)',
+ text: '(Terms of Service)',
style: const TextStyle(
color: Colors.black,
),
- recognizer:
- TapGestureRecognizer()
- ..onTap = () {
- loginBloc.launchURL(
- 'https://example.com/terms');
- },
+ recognizer: TapGestureRecognizer()
+ ..onTap = () {
+ loginBloc.launchURL(
+ 'https://example.com/terms');
+ },
),
TextSpan(
- text:
- ' (Legal Statement)',
- style: const TextStyle(
- color: Colors.black),
- recognizer:
- TapGestureRecognizer()
- ..onTap = () {
- loginBloc.launchURL(
- 'https://example.com/legal');
- },
+ text: ' (Legal Statement)',
+ style: const TextStyle(color: Colors.black),
+ recognizer: TapGestureRecognizer()
+ ..onTap = () {
+ loginBloc.launchURL(
+ 'https://example.com/legal');
+ },
),
TextSpan(
- text:
- ' (Privacy Statement)',
- style: const TextStyle(
- color: Colors.black),
- recognizer:
- TapGestureRecognizer()
- ..onTap = () {
- loginBloc.launchURL(
- 'https://example.com/privacy');
- },
+ text: ' (Privacy Statement)',
+ style: const TextStyle(color: Colors.black),
+ recognizer: TapGestureRecognizer()
+ ..onTap = () {
+ loginBloc.launchURL(
+ 'https://example.com/privacy');
+ },
),
],
),
@@ -454,49 +367,35 @@ class _LoginWebPageState extends State {
),
const SizedBox(height: 20.0),
Row(
- crossAxisAlignment:
- CrossAxisAlignment.center,
- mainAxisAlignment:
- MainAxisAlignment.center,
+ crossAxisAlignment: CrossAxisAlignment.center,
+ mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(
width: size.width * 0.2,
child: DefaultButton(
- enabled:
- loginBloc.checkValidate,
+ enabled: loginBloc.checkValidate,
child: Text('Sign in',
style: Theme.of(context)
.textTheme
.labelLarge!
.copyWith(
fontSize: 14,
- color: loginBloc
- .checkValidate
- ? ColorsManager
- .whiteColors
- : ColorsManager
- .whiteColors
- .withOpacity(
- 0.2),
+ color: loginBloc.checkValidate
+ ? ColorsManager.whiteColors
+ : ColorsManager.whiteColors
+ .withOpacity(0.2),
)),
onPressed: () {
- if (loginBloc.loginFormKey
- .currentState!
+ if (loginBloc.loginFormKey.currentState!
.validate()) {
- loginBloc
- .add(LoginButtonPressed(
- regionUuid:
- loginBloc.regionUuid,
- username: loginBloc
- .loginEmailController
- .text,
- password: loginBloc
- .loginPasswordController
- .text,
+ loginBloc.add(LoginButtonPressed(
+ regionUuid: loginBloc.regionUuid,
+ username: loginBloc.loginEmailController.text,
+ password:
+ loginBloc.loginPasswordController.text,
));
} else {
- loginBloc.add(
- ChangeValidateEvent());
+ loginBloc.add(ChangeValidateEvent());
}
},
),
@@ -505,10 +404,8 @@ class _LoginWebPageState extends State {
),
const SizedBox(height: 15.0),
Row(
- crossAxisAlignment:
- CrossAxisAlignment.center,
- mainAxisAlignment:
- MainAxisAlignment.center,
+ crossAxisAlignment: CrossAxisAlignment.center,
+ mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(
child: Text(
@@ -533,8 +430,7 @@ class _LoginWebPageState extends State {
),
),
),
- if (state is AuthLoading)
- const Center(child: CircularProgressIndicator())
+ if (state is AuthLoading) const Center(child: CircularProgressIndicator())
],
);
}
diff --git a/lib/pages/common/custom_dialog.dart b/lib/pages/common/custom_dialog.dart
index 363d6900..e75c1e90 100644
--- a/lib/pages/common/custom_dialog.dart
+++ b/lib/pages/common/custom_dialog.dart
@@ -7,6 +7,7 @@ Future showCustomDialog({
required String message,
String? title,
String? iconPath,
+ Widget? widget,
double? dialogHeight,
double? iconHeight,
double? iconWidth,
@@ -54,6 +55,8 @@ Future showCustomDialog({
textAlign: TextAlign.center,
),
),
+ if(widget!=null)
+ Expanded(child:widget)
],
),
),
diff --git a/lib/pages/common/custom_table.dart b/lib/pages/common/custom_table.dart
index fd64608a..fdeff6b6 100644
--- a/lib/pages/common/custom_table.dart
+++ b/lib/pages/common/custom_table.dart
@@ -14,7 +14,6 @@ class DynamicTable extends StatefulWidget {
final void Function(bool?)? selectAll;
final void Function(int, bool, dynamic)? onRowSelected;
final List? initialSelectedIds;
-
const DynamicTable({
super.key,
required this.headers,
@@ -66,14 +65,11 @@ class _DynamicTableState extends State {
child: Column(
children: [
Container(
- decoration: widget.headerDecoration ??
- BoxDecoration(color: Colors.grey[200]),
+ decoration: widget.headerDecoration ?? BoxDecoration(color: Colors.grey[200]),
child: Row(
children: [
if (widget.withCheckBox) _buildSelectAllCheckbox(),
- ...widget.headers
- .map((header) => _buildTableHeaderCell(header))
- .toList(),
+ ...widget.headers.map((header) => _buildTableHeaderCell(header)).toList(),
],
),
),
@@ -97,8 +93,7 @@ class _DynamicTableState extends State {
style: Theme.of(context)
.textTheme
.bodySmall!
- .copyWith(
- color: ColorsManager.grayColor),
+ .copyWith(color: ColorsManager.grayColor),
)
],
),
@@ -118,12 +113,10 @@ class _DynamicTableState extends State {
return Row(
children: [
if (widget.withCheckBox)
- _buildRowCheckbox(
- index, widget.size.height * 0.10),
+ _buildRowCheckbox(index, widget.size.height * 0.10),
...row
- .map((cell) => _buildTableCell(
- cell.toString(),
- widget.size.height * 0.10))
+ .map((cell) =>
+ _buildTableCell(cell.toString(), widget.size.height * 0.10))
.toList(),
],
);
@@ -211,6 +204,27 @@ class _DynamicTableState extends State {
batteryLevel = double.tryParse(content.replaceAll('%', '').trim());
}
+ Color? statusColor;
+ switch (content) {
+ case 'Effective':
+ statusColor = ColorsManager.textGreen;
+ break;
+ case 'Expired':
+ statusColor = ColorsManager.red;
+ break;
+ case 'To be effective':
+ statusColor = ColorsManager.yaGreen;
+ break;
+ case 'Online':
+ statusColor = ColorsManager.green;
+ break;
+ case 'Offline':
+ statusColor = ColorsManager.red;
+ break;
+ default:
+ statusColor = Colors.black; // Default color
+ }
+
return Expanded(
child: Container(
height: size,
@@ -227,16 +241,11 @@ class _DynamicTableState extends State {
child: Text(
content,
style: TextStyle(
- color: batteryLevel != null && batteryLevel < 20
- ? ColorsManager.red // Red color for low battery
- : content == 'Online'
- ? ColorsManager.green // Green color for Online
- : content == 'Offline'
- ? ColorsManager.red // Red color for Offline
- : Colors.black,
- fontSize: 12,
- fontWeight: FontWeight.w400,
- ),
+ color: batteryLevel != null && batteryLevel < 20
+ ? ColorsManager.red
+ : statusColor, // Use the passed color or default to 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 233ac772..0b8fa0da 100644
--- a/lib/pages/common/date_time_widget.dart
+++ b/lib/pages/common/date_time_widget.dart
@@ -36,10 +36,7 @@ class DateTimeWebWidget extends StatelessWidget {
if (isRequired)
Text(
'* ',
- style: Theme.of(context)
- .textTheme
- .bodyMedium!
- .copyWith(color: Colors.red),
+ style: Theme.of(context).textTheme.bodyMedium!.copyWith(color: Colors.red),
),
Text(
title,
@@ -55,8 +52,7 @@ class DateTimeWebWidget extends StatelessWidget {
),
Container(
height: size.height * 0.055,
- padding:
- const EdgeInsets.only(top: 10, bottom: 10, right: 30, left: 10),
+ padding: const EdgeInsets.only(top: 10, bottom: 10, right: 30, left: 10),
decoration: containerDecoration,
child: FittedBox(
child: Column(
@@ -69,13 +65,10 @@ class DateTimeWebWidget extends StatelessWidget {
child: FittedBox(
child: Text(
firstString,
- style: Theme.of(context)
- .textTheme
- .bodySmall!
- .copyWith(
- color: ColorsManager.grayColor,
- fontSize: 12,
- fontWeight: FontWeight.w400),
+ style: Theme.of(context).textTheme.bodySmall!.copyWith(
+ color: ColorsManager.grayColor,
+ fontSize: 12,
+ fontWeight: FontWeight.w400),
),
)),
const SizedBox(
@@ -90,13 +83,10 @@ class DateTimeWebWidget extends StatelessWidget {
child: FittedBox(
child: Text(
secondString,
- style: Theme.of(context)
- .textTheme
- .bodySmall!
- .copyWith(
- color: ColorsManager.grayColor,
- fontSize: 12,
- fontWeight: FontWeight.w400),
+ style: Theme.of(context).textTheme.bodySmall!.copyWith(
+ color: ColorsManager.grayColor,
+ fontSize: 12,
+ fontWeight: FontWeight.w400),
),
)),
const SizedBox(
diff --git a/lib/pages/home/bloc/home_bloc.dart b/lib/pages/home/bloc/home_bloc.dart
index 7d0034a5..42a63592 100644
--- a/lib/pages/home/bloc/home_bloc.dart
+++ b/lib/pages/home/bloc/home_bloc.dart
@@ -1,17 +1,15 @@
-import 'package:flutter/cupertino.dart';
-import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
+import 'package:go_router/go_router.dart';
import 'package:graphview/GraphView.dart';
-import 'package:syncrow_web/pages/access_management/view/access_management.dart';
import 'package:syncrow_web/pages/auth/model/user_model.dart';
-import 'package:syncrow_web/pages/device_managment/all_devices/view/device_managment_page.dart';
import 'package:syncrow_web/pages/home/bloc/home_event.dart';
import 'package:syncrow_web/pages/home/bloc/home_state.dart';
import 'package:syncrow_web/pages/home/home_model/home_item_model.dart';
import 'package:syncrow_web/services/home_api.dart';
import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/utils/constants/assets.dart';
+import 'package:syncrow_web/utils/constants/routes_const.dart';
class HomeBloc extends Bloc {
final Graph graph = Graph()..isTree = true;
@@ -43,8 +41,7 @@ class HomeBloc extends Bloc {
Future fetchUserInfo() async {
try {
- var uuid =
- await const FlutterSecureStorage().read(key: UserModel.userUuidKey);
+ var uuid = await const FlutterSecureStorage().read(key: UserModel.userUuidKey);
user = await HomeApi().fetchUserInfo(uuid);
emit(HomeUserInfoLoaded(user!)); // Emit state after fetching user info
} catch (e) {
@@ -58,9 +55,7 @@ class HomeBloc extends Bloc {
icon: Assets.accessIcon,
active: true,
onPress: (context) {
- Navigator.of(context).push(
- MaterialPageRoute(builder: (context) => AccessManagementPage()),
- );
+ context.go(RoutesConst.accessManagementPage);
},
color: null,
),
@@ -76,9 +71,7 @@ class HomeBloc extends Bloc {
icon: Assets.devicesIcon,
active: true,
onPress: (context) {
- Navigator.of(context).push(
- MaterialPageRoute(builder: (context) => const DeviceManagementPage()),
- );
+ context.go(RoutesConst.deviceManagementPage);
},
color: ColorsManager.primaryColor,
),
diff --git a/lib/pages/home/view/home_card.dart b/lib/pages/home/view/home_card.dart
index c1805a20..d2e71608 100644
--- a/lib/pages/home/view/home_card.dart
+++ b/lib/pages/home/view/home_card.dart
@@ -24,13 +24,19 @@ class HomeCard extends StatelessWidget {
child: Container(
padding: const EdgeInsets.only(left: 10, right: 10, bottom: 10),
decoration: BoxDecoration(
- color:
- // evenNumbers && active
- // ? ColorsManager.blueColor.withOpacity(0.8)
- // :
- (active
- ? ColorsManager.blueColor
- : ColorsManager.blueColor.withOpacity(0.2)),
+ color: index == 0 && active
+ ? ColorsManager.blue1.withOpacity(0.9)
+ : index == 1 && active
+ ? ColorsManager.blue2.withOpacity(0.9)
+ : index == 2 && active
+ ? ColorsManager.blue3
+ : index == 4 && active == false
+ ? ColorsManager.blue4.withOpacity(0.2)
+ : index == 7 && active == false
+ ? ColorsManager.blue4.withOpacity(0.2)
+ : ColorsManager.blueColor.withOpacity(0.2),
+ // (active ?ColorsManager.blueColor
+ // : ColorsManager.blueColor.withOpacity(0.2)),
borderRadius: BorderRadius.circular(30),
),
child: Column(
diff --git a/lib/pages/home/view/home_page.dart b/lib/pages/home/view/home_page.dart
index 75937cf2..c1e36729 100644
--- a/lib/pages/home/view/home_page.dart
+++ b/lib/pages/home/view/home_page.dart
@@ -8,7 +8,6 @@ class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
- return ResponsiveLayout(
- desktopBody: HomeWebPage(), mobileBody: HomeMobilePage());
+ return ResponsiveLayout(desktopBody: HomeWebPage(), mobileBody: HomeMobilePage());
}
}
diff --git a/lib/pages/home/view/home_page_web.dart b/lib/pages/home/view/home_page_web.dart
index aa779796..2a578fc9 100644
--- a/lib/pages/home/view/home_page_web.dart
+++ b/lib/pages/home/view/home_page_web.dart
@@ -12,7 +12,11 @@ class HomeWebPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
- return WebScaffold(
+ return PopScope(
+ canPop: false,
+ onPopInvoked: (didPop) => false,
+ child:
+ WebScaffold(
enableMenuSideba: false,
appBarTitle: Row(
children: [
@@ -76,6 +80,6 @@ class HomeWebPage extends StatelessWidget {
);
},
),
- ));
+ )));
}
}
diff --git a/lib/pages/space_management/spaseManagementIcon.dart b/lib/pages/space_management/spaseManagementIcon.dart
new file mode 100644
index 00000000..510b90b9
--- /dev/null
+++ b/lib/pages/space_management/spaseManagementIcon.dart
@@ -0,0 +1,16 @@
+
+
+
+import 'package:flutter/cupertino.dart';
+import 'package:flutter/material.dart';
+
+class SpaseManagementicon extends StatelessWidget {
+ const SpaseManagementicon({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ body: Container(),
+ );
+ }
+}
diff --git a/lib/pages/visitor_password/bloc/visitor_password_bloc.dart b/lib/pages/visitor_password/bloc/visitor_password_bloc.dart
index 6b1c60ee..2b64d606 100644
--- a/lib/pages/visitor_password/bloc/visitor_password_bloc.dart
+++ b/lib/pages/visitor_password/bloc/visitor_password_bloc.dart
@@ -1,4 +1,5 @@
import 'dart:math';
+import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:intl/intl.dart';
@@ -7,14 +8,14 @@ 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/failed_operation.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';
-class VisitorPasswordBloc
- extends Bloc {
+class VisitorPasswordBloc extends Bloc {
VisitorPasswordBloc() : super(VisitorPasswordInitial()) {
on(selectUsageFrequency);
on(_onFetchDevice);
@@ -37,8 +38,7 @@ 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 = [];
@@ -62,15 +62,13 @@ class VisitorPasswordBloc
String startTimeAccess = 'Start Time';
String endTimeAccess = 'End Time';
-
- selectAccessType(
- SelectPasswordType event, Emitter emit) {
+ PasswordStatus? passwordStatus;
+ selectAccessType(SelectPasswordType event, Emitter emit) {
accessTypeSelected = event.type;
emit(PasswordTypeSelected(event.type));
}
- selectUsageFrequency(
- SelectUsageFrequency event, Emitter emit) {
+ selectUsageFrequency(SelectUsageFrequency event, Emitter emit) {
usageFrequencySelected = event.usageType;
emit(UsageFrequencySelected(event.usageType));
}
@@ -117,12 +115,10 @@ class VisitorPasswordBloc
timePicked.minute,
);
- final selectedTimestamp =
- selectedDateTime.millisecondsSinceEpoch ~/ 1000;
+ final selectedTimestamp = selectedDateTime.millisecondsSinceEpoch ~/ 1000;
if (event.isStart) {
- if (expirationTimeTimeStamp != null &&
- selectedTimestamp > expirationTimeTimeStamp!) {
+ if (expirationTimeTimeStamp != null && selectedTimestamp > expirationTimeTimeStamp!) {
CustomSnackBar.displaySnackBar(
'Effective Time cannot be later than Expiration Time.',
);
@@ -131,8 +127,7 @@ class VisitorPasswordBloc
effectiveTimeTimeStamp = selectedTimestamp;
startTimeAccess = selectedDateTime.toString().split('.').first;
} else {
- if (effectiveTimeTimeStamp != null &&
- selectedTimestamp < effectiveTimeTimeStamp!) {
+ if (effectiveTimeTimeStamp != null && selectedTimestamp < effectiveTimeTimeStamp!) {
CustomSnackBar.displaySnackBar(
'Expiration Time cannot be earlier than Effective Time.',
);
@@ -147,8 +142,7 @@ class VisitorPasswordBloc
}
}
- bool toggleRepeat(
- ToggleRepeatEvent event, Emitter emit) {
+ bool toggleRepeat(ToggleRepeatEvent event, Emitter emit) {
emit(LoadingInitialState());
repeat = !repeat;
emit(IsRepeatState(repeat: repeat));
@@ -180,8 +174,7 @@ class VisitorPasswordBloc
emit(ChangeTimeState());
}
- Future _onFetchDevice(
- FetchDevice event, Emitter emit) async {
+ Future _onFetchDevice(FetchDevice event, Emitter emit) async {
try {
emit(DeviceLoaded());
data = await AccessMangApi().fetchDevices();
@@ -192,48 +185,43 @@ class VisitorPasswordBloc
}
//online password
- Future postOnlineOneTimePassword(OnlineOneTimePasswordEvent event,
- Emitter emit) async {
+ Future postOnlineOneTimePassword(
+ OnlineOneTimePasswordEvent event, Emitter emit) async {
try {
emit(LoadingInitialState());
generate7DigitNumber();
- bool res = await AccessMangApi().postOnlineOneTime(
+ var res = await AccessMangApi().postOnlineOneTime(
email: event.email,
password: passwordController,
devicesUuid: selectedDevices,
passwordName: event.passwordName,
effectiveTime: effectiveTimeTimeStamp.toString(),
invalidTime: expirationTimeTimeStamp.toString());
- if (res == true) {
+ if (res['statusCode'] == 201) {
+ passwordStatus = PasswordStatus.fromJson(res['data']);
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');
+ } on DioException catch (e) {
+ final errorData = e.response!.data;
+ String errorMessage = errorData['message'];
+ print('errorMessage==$errorData');
+ emit(FailedState(errorMessage.toString()));
}
}
Future postOnlineMultipleTimePassword(
- OnlineMultipleTimePasswordEvent event,
- Emitter emit) async {
+ OnlineMultipleTimePasswordEvent event, Emitter emit) async {
try {
emit(LoadingInitialState());
await generate7DigitNumber();
- bool res = await AccessMangApi().postOnlineMultipleTime(
+ var res = await AccessMangApi().postOnlineMultipleTime(
scheduleList: [
if (repeat)
Schedule(
effectiveTime: getTimeFromDateTimeString(expirationTime),
- invalidTime:
- getTimeFromDateTimeString(effectiveTime).toString(),
+ invalidTime: getTimeFromDateTimeString(effectiveTime).toString(),
workingDay: selectedDays,
),
],
@@ -243,79 +231,66 @@ class VisitorPasswordBloc
email: event.email,
devicesUuid: selectedDevices,
passwordName: event.passwordName);
- if (res == true) {
+ if (res['statusCode'] == 201) {
+ passwordStatus = PasswordStatus.fromJson(res['data']);
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');
+ } on DioException catch (e) {
+ final errorData = e.response!.data;
+ String errorMessage = errorData['message'];
+ print('errorMessage==$errorData');
+ emit(FailedState(errorMessage.toString()));
}
}
//offline password
- Future postOfflineOneTimePassword(OfflineOneTimePasswordEvent event,
- Emitter emit) async {
+ Future postOfflineOneTimePassword(
+ OfflineOneTimePasswordEvent event, Emitter emit) async {
try {
emit(LoadingInitialState());
await generate7DigitNumber();
- bool res = await AccessMangApi().postOffLineOneTime(
- email: event.email,
- devicesUuid: selectedDevices,
- passwordName: event.passwordName);
- if (res == true) {
+ var res = await AccessMangApi().postOffLineOneTime(
+ email: event.email, devicesUuid: selectedDevices, passwordName: event.passwordName);
+ if (res['statusCode'] == 201) {
+ passwordStatus = PasswordStatus.fromJson(res['data']);
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');
+ } on DioException catch (e) {
+ final errorData = e.response!.data;
+ String errorMessage = errorData['message'];
+ print('errorMessage==$errorData');
+ emit(FailedState(errorMessage.toString()));
}
}
Future postOfflineMultipleTimePassword(
- OfflineMultipleTimePasswordEvent event,
- Emitter emit) async {
+ OfflineMultipleTimePasswordEvent event, Emitter emit) async {
try {
emit(LoadingInitialState());
await generate7DigitNumber();
- bool res = await AccessMangApi().postOffLineMultipleTime(
+ var res = await AccessMangApi().postOffLineMultipleTime(
email: event.email,
devicesUuid: selectedDevices,
passwordName: event.passwordName,
invalidTime: expirationTimeTimeStamp.toString(),
effectiveTime: effectiveTimeTimeStamp.toString(),
);
- if (res == true) {
+ if (res['statusCode'] == 201) {
+ passwordStatus = PasswordStatus.fromJson(res['data']);
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');
+ } on DioException catch (e) {
+ final errorData = e.response!.data;
+ String errorMessage = errorData['message'];
+ print('errorMessage==$errorData');
+ emit(FailedState(errorMessage.toString()));
}
}
- void selectDevice(
- SelectDeviceEvent event, Emitter emit) {
+ void selectDevice(SelectDeviceEvent event, Emitter emit) {
if (selectedDeviceIds.contains(event.deviceId)) {
selectedDeviceIds.remove(event.deviceId);
} else {
@@ -358,8 +333,7 @@ class VisitorPasswordBloc
}
@override
- Stream mapEventToState(
- VisitorPasswordEvent event) async* {
+ Stream mapEventToState(VisitorPasswordEvent event) async* {
if (event is FetchDevice) {
} else if (event is UpdateFilteredDevicesEvent) {
yield TableLoaded(event.filteredData);
@@ -407,27 +381,20 @@ class VisitorPasswordBloc
).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.');
+ 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
+ effectiveTime =
+ selectedDateTime.toString().split('.').first; // Remove seconds and milliseconds
effectiveTimeTimeStamp = selectedTimestamp;
}
} else {
- if (effectiveTimeTimeStamp != null &&
- selectedTimestamp < effectiveTimeTimeStamp!) {
+ 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
+ expirationTime =
+ selectedDateTime.toString().split('.').first; // Remove seconds and milliseconds
expirationTimeTimeStamp = selectedTimestamp;
}
}
@@ -468,23 +435,26 @@ class VisitorPasswordBloc
return null;
}
- Future stateDialog({
+ Future stateDialog({
BuildContext? context,
String? message,
String? title,
dynamic actions,
+ Widget? widgeta,
}) {
return showCustomDialog(
+ barrierDismissible: false,
context: context!,
message: message!,
iconPath: Assets.deviceNoteIcon,
title: title,
- dialogHeight: 150,
+ widget: widgeta,
+ dialogHeight: MediaQuery.of(context).size.height * 0.3,
actions: actions ??
[
TextButton(
onPressed: () {
- Navigator.of(context).pop();
+ Navigator.of(context).pop(true);
},
child: const Text('OK'),
),
diff --git a/lib/pages/visitor_password/model/device_model.dart b/lib/pages/visitor_password/model/device_model.dart
index 6446634b..6d1c714d 100644
--- a/lib/pages/visitor_password/model/device_model.dart
+++ b/lib/pages/visitor_password/model/device_model.dart
@@ -1,6 +1,6 @@
import 'package:syncrow_web/utils/constants/assets.dart';
-import 'package:syncrow_web/utils/constants/const.dart';
import 'package:syncrow_web/utils/enum/device_types.dart';
+import 'package:syncrow_web/utils/constants/app_enum.dart';
class DeviceModel {
dynamic productUuid;
@@ -54,8 +54,7 @@ class DeviceModel {
if (type == DeviceType.LightBulb) {
tempIcon = Assets.lightBulb;
- } else if (type == DeviceType.CeilingSensor ||
- type == DeviceType.WallSensor) {
+ } else if (type == DeviceType.CeilingSensor || type == DeviceType.WallSensor) {
tempIcon = Assets.sensors;
} else if (type == DeviceType.AC) {
tempIcon = Assets.ac;
diff --git a/lib/pages/visitor_password/model/failed_operation.dart b/lib/pages/visitor_password/model/failed_operation.dart
new file mode 100644
index 00000000..223f9ac5
--- /dev/null
+++ b/lib/pages/visitor_password/model/failed_operation.dart
@@ -0,0 +1,124 @@
+class FailedOperation {
+ final bool success;
+ final dynamic deviceUuid;
+ final dynamic error;
+
+ FailedOperation({
+ required this.success,
+ required this.deviceUuid,
+ required this.error,
+ });
+
+ factory FailedOperation.fromJson(Map json) {
+ return FailedOperation(
+ success: json['success'],
+ deviceUuid: json['deviceUuid'],
+ error: json['error'],
+ );
+ }
+
+ Map toJson() {
+ return {
+ 'success': success,
+ 'deviceUuid': deviceUuid,
+ 'error': error,
+ };
+ }
+}
+
+
+
+class SuccessOperation {
+ final bool success;
+ // final Result result;
+ final String deviceUuid;
+
+ SuccessOperation({
+ required this.success,
+ // required this.result,
+ required this.deviceUuid,
+ });
+
+ factory SuccessOperation.fromJson(Map json) {
+ return SuccessOperation(
+ success: json['success'],
+ // result: Result.fromJson(json['result']),
+ deviceUuid: json['deviceUuid'],
+ );
+ }
+
+ Map toJson() {
+ return {
+ 'success': success,
+ // 'result': result.toJson(),
+ 'deviceUuid': deviceUuid,
+ };
+ }
+}
+
+// class Result {
+// final dynamic effectiveTime;
+// final dynamic invalidTime;
+// final dynamic offlineTempPassword;
+// final dynamic offlineTempPasswordId;
+// final dynamic offlineTempPasswordName;
+//
+// Result({
+// required this.effectiveTime,
+// required this.invalidTime,
+// required this.offlineTempPassword,
+// required this.offlineTempPasswordId,
+// required this.offlineTempPasswordName,
+// });
+//
+// factory Result.fromJson(Map json) {
+// return Result(
+// effectiveTime: json['effective_time'],
+// invalidTime: json['invalid_time'],
+// offlineTempPassword: json['offline_temp_password'].toString(),
+// offlineTempPasswordId: json['offline_temp_password_id'],
+// offlineTempPasswordName: json['offline_temp_password_name'],
+// );
+// }
+//
+// Map toJson() {
+// return {
+// 'effective_time': effectiveTime,
+// 'invalid_time': invalidTime,
+// 'offline_temp_password': offlineTempPassword,
+// 'offline_temp_password_id': offlineTempPasswordId,
+// 'offline_temp_password_name': offlineTempPasswordName,
+// };
+// }
+// }
+
+
+
+class PasswordStatus {
+ final List successOperations;
+ final List failedOperations;
+
+ PasswordStatus({
+ required this.successOperations,
+ required this.failedOperations,
+ });
+
+ factory PasswordStatus.fromJson(Map json) {
+ return PasswordStatus(
+ successOperations: (json['successOperations'] as List)
+ .map((i) => SuccessOperation.fromJson(i))
+ .toList(),
+ failedOperations: (json['failedOperations'] as List)
+ .map((i) => FailedOperation.fromJson(i))
+ .toList(),
+ );
+ }
+
+ Map toJson() {
+ return {
+ 'successOperations': successOperations.map((e) => e.toJson()).toList(),
+ 'failedOperations': failedOperations.map((e) => e.toJson()).toList(),
+ };
+ }
+}
+
diff --git a/lib/pages/visitor_password/view/add_device_dialog.dart b/lib/pages/visitor_password/view/add_device_dialog.dart
index c7d558b8..85262ff1 100644
--- a/lib/pages/visitor_password/view/add_device_dialog.dart
+++ b/lib/pages/visitor_password/view/add_device_dialog.dart
@@ -9,7 +9,7 @@ import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_event.d
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/constants/assets.dart';
-import 'package:syncrow_web/utils/constants/const.dart';
+import 'package:syncrow_web/utils/constants/app_enum.dart';
import 'package:syncrow_web/utils/style.dart';
class AddDeviceDialog extends StatelessWidget {
diff --git a/lib/pages/visitor_password/view/visitor_password_dialog.dart b/lib/pages/visitor_password/view/visitor_password_dialog.dart
index d7999177..20238252 100644
--- a/lib/pages/visitor_password/view/visitor_password_dialog.dart
+++ b/lib/pages/visitor_password/view/visitor_password_dialog.dart
@@ -20,21 +20,75 @@ class VisitorPasswordDialog extends StatelessWidget {
@override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
- var text = Theme.of(context)
- .textTheme
- .bodySmall!
- .copyWith(color: Colors.black, fontSize: 13);
+ var text = Theme.of(context).textTheme.bodySmall!.copyWith(color: Colors.black, fontSize: 13);
return BlocProvider(
create: (context) => VisitorPasswordBloc(),
child: BlocListener(
listener: (context, state) {
final visitorBloc = BlocProvider.of(context);
if (state is SuccessState) {
- visitorBloc.stateDialog(
- context: context,
- message: 'Password Created Successfully',
- title: 'Send Success',
- );
+ visitorBloc
+ .stateDialog(
+ context: context,
+ message: 'Password Created Successfully',
+ title: 'Send Success',
+ widgeta: Column(
+ children: [
+ if (visitorBloc.passwordStatus!.failedOperations.isNotEmpty)
+ Column(
+ children: [
+ const Text('Failed Devises'),
+ SizedBox(
+ width: 200,
+ height: 50,
+ child: ListView.builder(
+ scrollDirection: Axis.horizontal,
+ shrinkWrap: true,
+ itemCount: visitorBloc.passwordStatus!.failedOperations.length,
+ itemBuilder: (context, index) {
+ return Container(
+ margin: EdgeInsets.all(5),
+ decoration: containerDecoration,
+ height: 45,
+ child: Center(
+ child: Text(visitorBloc
+ .passwordStatus!.failedOperations[index].deviceUuid)),
+ );
+ },
+ ),
+ ),
+ ],
+ ),
+ if (visitorBloc.passwordStatus!.successOperations.isNotEmpty)
+ Column(
+ children: [
+ const Text('Success Devises'),
+ SizedBox(
+ width: 200,
+ height: 50,
+ child: ListView.builder(
+ scrollDirection: Axis.horizontal,
+ shrinkWrap: true,
+ itemCount: visitorBloc.passwordStatus!.successOperations.length,
+ itemBuilder: (context, index) {
+ return Container(
+ margin: EdgeInsets.all(5),
+ decoration: containerDecoration,
+ height: 45,
+ child: Center(
+ child: Text(visitorBloc.passwordStatus!
+ .successOperations[index].deviceUuid)),
+ );
+ },
+ ),
+ ),
+ ],
+ ),
+ ],
+ ))
+ .then((v) {
+ Navigator.of(context).pop();
+ });
} else if (state is FailedState) {
visitorBloc.stateDialog(
context: context,
@@ -46,16 +100,15 @@ class VisitorPasswordDialog extends StatelessWidget {
child: BlocBuilder(
builder: (BuildContext context, VisitorPasswordState state) {
final visitorBloc = BlocProvider.of(context);
- bool isRepeat =
- state is IsRepeatState ? state.repeat : visitorBloc.repeat;
+ bool isRepeat = state is IsRepeatState ? state.repeat : visitorBloc.repeat;
return AlertDialog(
backgroundColor: Colors.white,
title: Text(
'Create visitor password',
- style: Theme.of(context).textTheme.headlineLarge!.copyWith(
- fontWeight: FontWeight.w400,
- fontSize: 24,
- color: Colors.black),
+ style: Theme.of(context)
+ .textTheme
+ .headlineLarge!
+ .copyWith(fontWeight: FontWeight.w400, fontSize: 24, color: Colors.black),
),
content: state is LoadingInitialState
? const Center(child: CircularProgressIndicator())
@@ -73,8 +126,7 @@ class VisitorPasswordDialog extends StatelessWidget {
flex: 2,
child: CustomWebTextField(
validator: visitorBloc.validate,
- controller:
- visitorBloc.userNameController,
+ controller: visitorBloc.userNameController,
isRequired: true,
textFieldName: 'Name',
description: '',
@@ -116,95 +168,111 @@ class VisitorPasswordDialog extends StatelessWidget {
),
Row(
children: [
- Flexible(
- child: RadioListTile(
- contentPadding: EdgeInsets.zero,
- title: Text(
- 'Online Password',
- style: text,
- ),
- value: 'Online Password',
- groupValue: (state
- is PasswordTypeSelected)
- ? state.selectedType
- : visitorBloc.accessTypeSelected,
- onChanged: (String? value) {
- if (value != null) {
- context
- .read()
- .add(SelectPasswordType(
- value));
- }
- },
- ),
- ),
- Flexible(
- child: RadioListTile(
- contentPadding: EdgeInsets.zero,
- title: Text('Offline Password',
- style: text),
- value: 'Offline Password',
- groupValue: (state
- is PasswordTypeSelected)
- ? state.selectedType
- : visitorBloc.accessTypeSelected,
- onChanged: (String? value) {
- if (value != null) {
- context
- .read()
- .add(SelectPasswordType(
- value));
- }
- },
- ),
- ),
- Flexible(
- child: RadioListTile(
- contentPadding: EdgeInsets.zero,
- title: Text(
- 'Dynamic Password',
- style: text,
- ),
- value: 'Dynamic Password',
- groupValue: (state
- is PasswordTypeSelected)
- ? state.selectedType
- : visitorBloc.accessTypeSelected,
- onChanged: (String? value) {
- if (value != null) {
- context
- .read()
- .add(SelectPasswordType(
- value));
- visitorBloc
- .usageFrequencySelected = '';
- }
- },
- ),
+ Expanded(
+ flex: 2,
+ child: Row(
+ children: [
+ SizedBox(
+ width: size.width * 0.12,
+ child: RadioListTile(
+ contentPadding: EdgeInsets.zero,
+ title: Text(
+ 'Online Password',
+ style: text,
+ ),
+ value: 'Online Password',
+ groupValue: (state is PasswordTypeSelected)
+ ? state.selectedType
+ : visitorBloc.accessTypeSelected,
+ onChanged: (String? value) {
+ if (value != null) {
+ context
+ .read()
+ .add(SelectPasswordType(value));
+ }
+ },
+ ),
+ ),
+ SizedBox(
+ width: size.width * 0.12,
+ child: RadioListTile(
+ contentPadding: EdgeInsets.zero,
+ title: Text('Offline Password', style: text),
+ value: 'Offline Password',
+ groupValue: (state is PasswordTypeSelected)
+ ? state.selectedType
+ : visitorBloc.accessTypeSelected,
+ onChanged: (String? value) {
+ if (value != null) {
+ context
+ .read()
+ .add(SelectPasswordType(value));
+ }
+ },
+ ),
+ ),
+ SizedBox(
+ width: size.width * 0.12,
+ child: RadioListTile(
+ contentPadding: EdgeInsets.zero,
+ title: Text(
+ 'Dynamic Password',
+ style: text,
+ ),
+ value: 'Dynamic Password',
+ groupValue: (state is PasswordTypeSelected)
+ ? state.selectedType
+ : visitorBloc.accessTypeSelected,
+ onChanged: (String? value) {
+ if (value != null) {
+ context
+ .read()
+ .add(SelectPasswordType(value));
+ visitorBloc.usageFrequencySelected = '';
+ }
+ },
+ ),
+ ),
+ ],
+ )),
+ const Spacer(
+ flex: 2,
),
],
),
- 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',
- style: Theme.of(context)
- .textTheme
- .bodySmall!
- .copyWith(
- fontWeight: FontWeight.w400,
- color: ColorsManager.grayColor,
- fontSize: 9),
- ),
+ if (visitorBloc.accessTypeSelected == 'Online Password')
+ 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',
+ style: Theme.of(context).textTheme.bodySmall!.copyWith(
+ fontWeight: FontWeight.w400,
+ color: ColorsManager.grayColor,
+ fontSize: 9),
+ ),
+ if (visitorBloc.accessTypeSelected == 'Offline Password')
+ Text(
+ 'Unaffected by the online status of the device, you can select online or offline device, and the system randomly generates a digital password',
+ style: Theme.of(context).textTheme.bodySmall!.copyWith(
+ fontWeight: FontWeight.w400,
+ color: ColorsManager.grayColor,
+ fontSize: 9),
+ ),
+ if (visitorBloc.accessTypeSelected == 'Dynamic Password')
+ Text(
+ 'Quick and short-acting password, only valid within 5 minutes after creation, 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 == 'Dynamic Password'
? const SizedBox()
: Column(
- crossAxisAlignment:
- CrossAxisAlignment.start,
+ crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
@@ -223,7 +291,8 @@ class VisitorPasswordDialog extends StatelessWidget {
),
Row(
children: [
- Flexible(
+ SizedBox(
+ width: size.width * 0.12,
child: RadioListTile(
contentPadding: EdgeInsets.zero,
title: Text(
@@ -231,88 +300,113 @@ class VisitorPasswordDialog extends StatelessWidget {
style: text,
),
value: 'One-Time',
- groupValue: (state
- is UsageFrequencySelected)
+ groupValue: (state is UsageFrequencySelected)
? state.selectedFrequency
- : visitorBloc
- .usageFrequencySelected,
+ : visitorBloc.usageFrequencySelected,
onChanged: (String? value) {
if (value != null) {
context
- .read<
- VisitorPasswordBloc>()
- .add(
- SelectUsageFrequency(
- value));
+ .read()
+ .add(SelectUsageFrequency(value));
}
},
),
),
- Flexible(
+ SizedBox(
+ width: size.width * 0.12,
child: RadioListTile(
contentPadding: EdgeInsets.zero,
- title: Text('Periodic',
- style: text),
+ title: Text('Periodic', style: text),
value: 'Periodic',
- groupValue: (state
- is UsageFrequencySelected)
+ groupValue: (state is UsageFrequencySelected)
? state.selectedFrequency
- : visitorBloc
- .usageFrequencySelected,
+ : visitorBloc.usageFrequencySelected,
onChanged: (String? value) {
if (value != null) {
context
- .read<
- VisitorPasswordBloc>()
- .add(
- SelectUsageFrequency(
- value));
+ .read()
+ .add(SelectUsageFrequency(value));
}
},
),
),
],
),
- Text(
- 'Within the validity period, each device can be unlocked only once.',
- style: Theme.of(context)
- .textTheme
- .bodySmall!
- .copyWith(
- color:
- ColorsManager.grayColor,
- fontSize: 9),
- )
+
+ //One-Time
+ if (visitorBloc.usageFrequencySelected == 'One-Time' &&
+ visitorBloc.accessTypeSelected == 'Online Password')
+ Text(
+ 'Within the validity period, each device can be unlocked only once.',
+ style: Theme.of(context).textTheme.bodySmall!.copyWith(
+ color: ColorsManager.grayColor, fontSize: 9),
+ ),
+ if (visitorBloc.usageFrequencySelected == 'One-Time' &&
+ visitorBloc.accessTypeSelected == 'Offline Password')
+ Text(
+ 'Within the validity period, there is no limit to the number of times each device can be unlocked.',
+ style: Theme.of(context).textTheme.bodySmall!.copyWith(
+ color: ColorsManager.grayColor, fontSize: 9),
+ ),
+
+ // Periodic
+ if (visitorBloc.usageFrequencySelected == 'Periodic' &&
+ visitorBloc.accessTypeSelected == 'Offline Password')
+ Text(
+ 'Within the validity period, there is no limit to the number of times each device can be unlocked, and it should be used at least once within 24 hours after the entry into force.',
+ style: Theme.of(context).textTheme.bodySmall!.copyWith(
+ color: ColorsManager.grayColor, fontSize: 9),
+ ),
+
+ if (visitorBloc.usageFrequencySelected == 'Periodic' &&
+ visitorBloc.accessTypeSelected == 'Online Password')
+ Text(
+ 'Within the validity period, there is no limit to the number of times each device can be unlocked.',
+ style: Theme.of(context).textTheme.bodySmall!.copyWith(
+ color: ColorsManager.grayColor, fontSize: 9),
+ ),
],
),
const SizedBox(
height: 20,
),
- if ((visitorBloc.usageFrequencySelected !=
- 'One-Time' ||
- visitorBloc.accessTypeSelected !=
- 'Offline Password') &&
+ if ((visitorBloc.usageFrequencySelected != 'One-Time' ||
+ visitorBloc.accessTypeSelected != 'Offline Password') &&
(visitorBloc.usageFrequencySelected != ''))
DateTimeWebWidget(
isRequired: true,
title: 'Access Period',
size: size,
endTime: () {
- visitorBloc.add(SelectTimeVisitorPassword(
- context: context,
- isStart: false,
- isRepeat: false));
+ if (visitorBloc.usageFrequencySelected == 'Periodic' &&
+ visitorBloc.accessTypeSelected == 'Offline Password') {
+ visitorBloc.add(
+ SelectTimeEvent(context: context, isEffective: false));
+ } else {
+ visitorBloc.add(SelectTimeVisitorPassword(
+ context: context, isStart: false, isRepeat: false));
+ }
},
startTime: () {
- visitorBloc.add(SelectTimeVisitorPassword(
- context: context,
- isStart: true,
- isRepeat: false));
+ if (visitorBloc.usageFrequencySelected == 'Periodic' &&
+ visitorBloc.accessTypeSelected == 'Offline Password') {
+ visitorBloc.add(
+ SelectTimeEvent(context: context, isEffective: true));
+ } else {
+ visitorBloc.add(SelectTimeVisitorPassword(
+ context: context, isStart: true, isRepeat: false));
+ }
},
- firstString:
- visitorBloc.startTimeAccess.toString(),
- secondString:
- visitorBloc.endTimeAccess.toString(),
+ firstString: (visitorBloc.usageFrequencySelected ==
+ 'Periodic' &&
+ visitorBloc.accessTypeSelected == 'Offline Password')
+ ? visitorBloc.effectiveTime
+ : visitorBloc.startTimeAccess.toString(),
+ secondString: (visitorBloc.usageFrequencySelected ==
+ 'Periodic' &&
+ visitorBloc.accessTypeSelected == 'Offline Password')
+ ? visitorBloc.expirationTime
+ : visitorBloc.endTimeAccess.toString(),
icon: Assets.calendarIcon),
const SizedBox(
height: 20,
@@ -337,21 +431,16 @@ class VisitorPasswordDialog extends StatelessWidget {
),
Text(
'Within the validity period, each device can be unlocked only once.',
- style: Theme.of(context)
- .textTheme
- .bodySmall!
- .copyWith(
- fontWeight: FontWeight.w400,
- color: ColorsManager.grayColor,
- fontSize: 9),
+ 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')
+ if (visitorBloc.usageFrequencySelected == 'Periodic' &&
+ visitorBloc.accessTypeSelected == 'Online Password')
SizedBox(
width: 100,
child: Column(
@@ -362,8 +451,7 @@ class VisitorPasswordDialog extends StatelessWidget {
child: CupertinoSwitch(
value: visitorBloc.repeat,
onChanged: (value) {
- visitorBloc
- .add(ToggleRepeatEvent());
+ visitorBloc.add(ToggleRepeatEvent());
},
applyTheme: true,
),
@@ -371,13 +459,9 @@ class VisitorPasswordDialog extends StatelessWidget {
],
),
),
- if (visitorBloc.usageFrequencySelected ==
- 'Periodic' &&
- visitorBloc.accessTypeSelected ==
- 'Online Password')
- isRepeat
- ? const RepeatWidget()
- : const SizedBox(),
+ if (visitorBloc.usageFrequencySelected == 'Periodic' &&
+ visitorBloc.accessTypeSelected == 'Online Password')
+ isRepeat ? const RepeatWidget() : const SizedBox(),
Container(
decoration: containerDecoration,
width: size.width / 9,
@@ -388,28 +472,22 @@ class VisitorPasswordDialog extends StatelessWidget {
barrierDismissible: false,
builder: (BuildContext context) {
return AddDeviceDialog(
- selectedDeviceIds:
- visitorBloc.selectedDevices,
+ selectedDeviceIds: visitorBloc.selectedDevices,
);
},
).then((listDevice) {
if (listDevice != null) {
- visitorBloc.selectedDevices =
- listDevice;
+ visitorBloc.selectedDevices = listDevice;
}
});
},
borderRadius: 8,
child: Text(
'+ Add Device',
- style: Theme.of(context)
- .textTheme
- .bodySmall!
- .copyWith(
- fontWeight: FontWeight.w400,
- color:
- ColorsManager.whiteColors,
- fontSize: 12),
+ style: Theme.of(context).textTheme.bodySmall!.copyWith(
+ fontWeight: FontWeight.w400,
+ color: ColorsManager.whiteColors,
+ fontSize: 12),
),
),
),
@@ -447,15 +525,36 @@ class VisitorPasswordDialog extends StatelessWidget {
onPressed: () {
if (visitorBloc.forgetFormKey.currentState!.validate()) {
if (visitorBloc.selectedDevices.isNotEmpty) {
- if (visitorBloc.effectiveTimeTimeStamp != null &&
- visitorBloc.expirationTimeTimeStamp != null) {
+ if (visitorBloc.usageFrequencySelected == 'One-Time' &&
+ visitorBloc.accessTypeSelected == 'Offline Password') {
+ setPasswordFunction(context, size, visitorBloc);
+ } else if (visitorBloc.accessTypeSelected == 'Dynamic Password') {
+ print('objectobjectobjectobject');
setPasswordFunction(context, size, visitorBloc);
} else {
- visitorBloc.stateDialog(
- context: context,
- message:
- 'Please select Access Period to continue',
- title: 'Access Period');
+ if (visitorBloc.effectiveTimeTimeStamp != null &&
+ visitorBloc.expirationTimeTimeStamp != null) {
+ if (isRepeat == true) {
+ if (visitorBloc.expirationTime != 'End Time' &&
+ visitorBloc.effectiveTime != 'Start Time' &&
+ visitorBloc.selectedDays.isNotEmpty) {
+ setPasswordFunction(context, size, visitorBloc);
+ } else {
+ visitorBloc.stateDialog(
+ context: context,
+ message:
+ 'Please select days and fill start time and end time to continue',
+ title: 'Access Period');
+ }
+ } else {
+ setPasswordFunction(context, size, visitorBloc);
+ }
+ } else {
+ visitorBloc.stateDialog(
+ context: context,
+ message: 'Please select Access Period to continue',
+ title: 'Access Period');
+ }
}
} else {
visitorBloc.stateDialog(
@@ -465,6 +564,57 @@ class VisitorPasswordDialog extends StatelessWidget {
}
}
},
+
+ // onPressed: () {
+ // if (visitorBloc.forgetFormKey.currentState!.validate()) {
+ // if (visitorBloc.selectedDevices.isNotEmpty) {
+ // switch (visitorBloc.usageFrequencySelected) {
+ // case 'One-Time':
+ // if (visitorBloc.accessTypeSelected == 'Offline Password') {
+ // setPasswordFunction(context, size, visitorBloc);
+ // } else {
+ // visitorBloc.stateDialog(
+ // context: context,
+ // message: 'Invalid combination of Access Type and Usage Frequency.',
+ // title: 'Error',
+ // );
+ // }
+ // break;
+ // default:
+ // if (visitorBloc.effectiveTimeTimeStamp != null && visitorBloc.expirationTimeTimeStamp != null) {
+ // if (isRepeat) {
+ // if (visitorBloc.expirationTime != 'End Time' &&
+ // visitorBloc.effectiveTime != 'Start Time' &&
+ // visitorBloc.selectedDays.isNotEmpty) {
+ // setPasswordFunction(context, size, visitorBloc);
+ // } else {
+ // visitorBloc.stateDialog(
+ // context: context,
+ // message: 'Please select days and fill start time and end time to continue',
+ // title: 'Access Period',
+ // );
+ // }
+ // } else {
+ // setPasswordFunction(context, size, visitorBloc);
+ // }
+ // } else {
+ // visitorBloc.stateDialog(
+ // context: context,
+ // message: 'Please select Access Period to continue',
+ // title: 'Access Period',
+ // );
+ // }
+ // break;
+ // }
+ // } else {
+ // visitorBloc.stateDialog(
+ // context: context,
+ // message: 'Please select devices to continue',
+ // title: 'Select Devices',
+ // );
+ // }
+ // }
+ // },
borderRadius: 8,
child: Text(
'Ok',
@@ -501,8 +651,7 @@ class VisitorPasswordDialog extends StatelessWidget {
content: SizedBox(
height: size.height * 0.25,
child: Center(
- child:
- CircularProgressIndicator(), // Display a loading spinner
+ child: CircularProgressIndicator(), // Display a loading spinner
),
),
);
@@ -526,10 +675,7 @@ class VisitorPasswordDialog extends StatelessWidget {
),
Text(
'Set Password',
- style: Theme.of(context)
- .textTheme
- .headlineLarge!
- .copyWith(
+ style: Theme.of(context).textTheme.headlineLarge!.copyWith(
fontSize: 30,
fontWeight: FontWeight.w400,
color: Colors.black,
@@ -578,47 +724,39 @@ class VisitorPasswordDialog extends StatelessWidget {
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(),
- ));
+ if (visitorBloc.accessTypeSelected == 'Dynamic Password') {
+ } else {
+ 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(
diff --git a/lib/services/access_mang_api.dart b/lib/services/access_mang_api.dart
index 84c82586..c93466d4 100644
--- a/lib/services/access_mang_api.dart
+++ b/lib/services/access_mang_api.dart
@@ -1,5 +1,4 @@
import 'dart:convert';
-import 'package:dio/dio.dart';
import 'package:flutter/cupertino.dart';
import 'package:syncrow_web/pages/access_management/model/password_model.dart';
import 'package:syncrow_web/pages/visitor_password/model/device_model.dart';
@@ -48,39 +47,29 @@ class AccessMangApi {
}
}
- Future postOnlineOneTime(
+ Future postOnlineOneTime(
{String? email,
String? passwordName,
String? password,
String? effectiveTime,
String? invalidTime,
List? devicesUuid}) async {
- try {
- final response = await HTTPService().post(
- path: ApiEndpoints.sendOnlineOneTime,
- body: jsonEncode({
- "email": email,
- "passwordName": passwordName,
- "password": password,
- "devicesUuid": devicesUuid,
- "effectiveTime": effectiveTime,
- "invalidTime": invalidTime
- }),
- showServerMessage: true,
- expectedResponseModel: (json) {
- if (json['statusCode'].toString() == '201') {
- return true;
- } else {
- return false;
- }
- },
- );
- return response;
- } on DioException catch (e) {
- debugPrint('Error: ${e.message}');
- debugPrint('Error fetching ${e.response!.statusMessage}');
- return false;
- }
+ final response = await HTTPService().post(
+ path: ApiEndpoints.sendOnlineOneTime,
+ body: jsonEncode({
+ "email": email,
+ "passwordName": passwordName,
+ "password": password,
+ "devicesUuid": devicesUuid,
+ "effectiveTime": effectiveTime,
+ "invalidTime": invalidTime
+ }),
+ showServerMessage: true,
+ expectedResponseModel: (json) {
+ return json;
+ },
+ );
+ return response;
}
Future postOnlineMultipleTime(
@@ -91,66 +80,41 @@ class AccessMangApi {
String? passwordName,
List? scheduleList,
List? devicesUuid}) async {
- try {
- Map body = {
- "email": email,
- "devicesUuid": devicesUuid,
- "passwordName": passwordName,
- "password": password,
- "effectiveTime": effectiveTime,
- "invalidTime": invalidTime,
- };
- if (scheduleList != null) {
- body["scheduleList"] =
- scheduleList.map((schedule) => schedule.toJson()).toList();
- }
- final response = await HTTPService().post(
- path: ApiEndpoints.sendOnlineMultipleTime,
- body: jsonEncode(body),
- showServerMessage: true,
- expectedResponseModel: (json) {
- if (json['data']['successOperations'][0]['success'].toString() ==
- 'true') {
- return true;
- } else {
- return false;
- }
- },
- );
- return response;
- } on DioException catch (e) {
- debugPrint('Error fetching ${e.type.name}');
- debugPrint('Error fetching ${e.response!.statusMessage}');
- return false;
+ Map body = {
+ "email": email,
+ "devicesUuid": devicesUuid,
+ "passwordName": passwordName,
+ "password": password,
+ "effectiveTime": effectiveTime,
+ "invalidTime": invalidTime,
+ };
+ if (scheduleList != null) {
+ body["scheduleList"] = scheduleList.map((schedule) => schedule.toJson()).toList();
}
+ final response = await HTTPService().post(
+ path: ApiEndpoints.sendOnlineMultipleTime,
+ body: jsonEncode(body),
+ showServerMessage: true,
+ expectedResponseModel: (json) {
+ return json;
+ },
+ );
+ return response;
}
// OffLine One Time Password
Future postOffLineOneTime(
{String? email, String? passwordName, List? devicesUuid}) async {
- try {
- final response = await HTTPService().post(
- path: ApiEndpoints.sendOffLineOneTime,
- body: jsonEncode({
- "email": email,
- "passwordName": passwordName,
- "devicesUuid": devicesUuid
- }),
- showServerMessage: true,
- expectedResponseModel: (json) {
- if (json['data']['successOperations'][0]['success'].toString() ==
- 'true') {
- return true;
- } else {
- return false;
- }
- });
- return response;
- } catch (e) {
- debugPrint('Error fetching $e');
- return [];
- }
+ final response = await HTTPService().post(
+ path: ApiEndpoints.sendOffLineOneTime,
+ body: jsonEncode({"email": email, "passwordName": passwordName, "devicesUuid": devicesUuid}),
+ showServerMessage: true,
+ expectedResponseModel: (json) {
+ return json;
+ },
+ );
+ return response;
}
Future postOffLineMultipleTime(
@@ -159,29 +123,27 @@ class AccessMangApi {
String? effectiveTime,
String? invalidTime,
List? devicesUuid}) async {
- try {
- final response = await HTTPService().post(
- path: ApiEndpoints.sendOffLineOneTime,
- body: jsonEncode({
- "email": email,
- "devicesUuid": devicesUuid,
- "passwordName": passwordName,
- "effectiveTime": effectiveTime,
- "invalidTime": invalidTime
- }),
- showServerMessage: true,
- expectedResponseModel: (json) {
- if (json['data']['successOperations'][0]['success'].toString() ==
- 'true') {
- return true;
- } else {
- return false;
- }
- });
- return response;
- } catch (e) {
- debugPrint('Error fetching $e');
- return [];
- }
+ print(jsonEncode({
+ "email": email,
+ "devicesUuid": devicesUuid,
+ "passwordName": passwordName,
+ "effectiveTime": effectiveTime,
+ "invalidTime": invalidTime,
+ }));
+ final response = await HTTPService().post(
+ path: ApiEndpoints.sendOffLineMultipleTime,
+ body: jsonEncode({
+ "email": email,
+ "devicesUuid": devicesUuid,
+ "passwordName": passwordName,
+ "effectiveTime": effectiveTime,
+ "invalidTime": invalidTime,
+ }),
+ showServerMessage: true,
+ expectedResponseModel: (json) {
+ return json;
+ },
+ );
+ return response;
}
}
diff --git a/lib/services/auth_api.dart b/lib/services/auth_api.dart
index 55d12717..6573f3ad 100644
--- a/lib/services/auth_api.dart
+++ b/lib/services/auth_api.dart
@@ -29,17 +29,17 @@ class AuthenticationAPI {
return response;
}
- static Future sendOtp(
- {required String email, required String regionUuid}) async {
+ static Future sendOtp({required String email, required String regionUuid}) async {
try {
final response = await HTTPService().post(
path: ApiEndpoints.sendOtp,
body: {"email": email, "type": "PASSWORD", "regionUuid": regionUuid},
showServerMessage: true,
expectedResponseModel: (json) {
- return 30;
+ return json['data']['cooldown'];
});
- return 30;
+
+ return response;
} on DioException catch (e) {
if (e.response != null) {
if (e.response!.statusCode == 400) {
@@ -52,8 +52,7 @@ class AuthenticationAPI {
return cooldown;
}
} else {
- debugPrint(
- 'Error: ${e.response!.statusCode} - ${e.response!.statusMessage}');
+ debugPrint('Error: ${e.response!.statusCode} - ${e.response!.statusMessage}');
return 1;
}
} else {
@@ -66,8 +65,7 @@ class AuthenticationAPI {
}
}
- static Future verifyOtp(
- {required String email, required String otpCode}) async {
+ static Future verifyOtp({required String email, required String otpCode}) async {
try {
final response = await HTTPService().post(
path: ApiEndpoints.verifyOtp,
@@ -99,9 +97,7 @@ class AuthenticationAPI {
path: ApiEndpoints.getRegion,
showServerMessage: true,
expectedResponseModel: (json) {
- return (json as List)
- .map((zone) => RegionModel.fromJson(zone))
- .toList();
+ return (json as List).map((zone) => RegionModel.fromJson(zone)).toList();
});
return response;
}
diff --git a/lib/utils/app_routes.dart b/lib/utils/app_routes.dart
new file mode 100644
index 00000000..a730341b
--- /dev/null
+++ b/lib/utils/app_routes.dart
@@ -0,0 +1,34 @@
+import 'package:go_router/go_router.dart';
+import 'package:syncrow_web/pages/access_management/view/access_management.dart';
+import 'package:syncrow_web/pages/auth/view/login_page.dart';
+import 'package:syncrow_web/pages/device_managment/all_devices/view/device_managment_page.dart';
+import 'package:syncrow_web/pages/home/view/home_page.dart';
+import 'package:syncrow_web/pages/visitor_password/view/visitor_password_dialog.dart';
+import 'package:syncrow_web/utils/constants/routes_const.dart';
+
+class AppRoutes {
+ static List getRoutes() {
+ return [
+ GoRoute(
+ path: RoutesConst.auth,
+ builder: (context, state) => const LoginPage(),
+ ),
+ GoRoute(
+ path: RoutesConst.home,
+ builder: (context, state) => const HomePage(),
+ ),
+ GoRoute(
+ path: RoutesConst.visitorPassword,
+ builder: (context, state) => const VisitorPasswordDialog(),
+ ),
+ GoRoute(
+ path: RoutesConst.accessManagementPage,
+ builder: (context, state) => const AccessManagementPage(),
+ ),
+ GoRoute(
+ path: RoutesConst.deviceManagementPage,
+ builder: (context, state) => const DeviceManagementPage(),
+ ),
+ ];
+ }
+}
diff --git a/lib/utils/color_manager.dart b/lib/utils/color_manager.dart
index fa1d7394..b62889d0 100644
--- a/lib/utils/color_manager.dart
+++ b/lib/utils/color_manager.dart
@@ -36,4 +36,11 @@ abstract class ColorsManager {
static const Color blueColor = Color(0xFF0036E6);
static const Color boxColor = Color(0xFFF5F6F7);
static const Color boxDivider = Color(0xFFE0E0E0);
+ static const Color blue1 = Color(0xFF0036E6);
+ static const Color blue2 = Color(0xFF0026A2);
+ static const Color blue3 = Color(0xFF00165E);
+ static const Color blue4 = Color(0xFF001E7E);
+ static const Color textGreen = Color(0xFF008905);
+ static const Color yaGreen = Color(0xFFFFBF44);
}
+//0036E6
\ No newline at end of file
diff --git a/lib/utils/constants/const.dart b/lib/utils/constants/app_enum.dart
similarity index 100%
rename from lib/utils/constants/const.dart
rename to lib/utils/constants/app_enum.dart
diff --git a/lib/utils/constants/assets.dart b/lib/utils/constants/assets.dart
index 5a4f97f8..49cefd2d 100644
--- a/lib/utils/constants/assets.dart
+++ b/lib/utils/constants/assets.dart
@@ -13,12 +13,10 @@ class Assets {
static const String rightLine = "assets/images/right_line.png";
static const String google = "assets/images/google.svg";
static const String facebook = "assets/images/facebook.svg";
- static const String invisiblePassword =
- "assets/images/Password_invisible.svg";
+ static const String invisiblePassword = "assets/images/Password_invisible.svg";
static const String visiblePassword = "assets/images/Password_visible.svg";
static const String accessIcon = "assets/images/access_icon.svg";
- static const String spaseManagementIcon =
- "assets/images/spase_management_icon.svg";
+ static const String spaseManagementIcon = "assets/images/spase_management_icon.svg";
static const String devicesIcon = "assets/images/devices_icon.svg";
static const String moveinIcon = "assets/images/movein_icon.svg";
static const String constructionIcon = "assets/images/construction_icon.svg";
@@ -31,15 +29,13 @@ class Assets {
static const String emptyTable = "assets/images/empty_table.svg";
// General assets
- static const String motionlessDetection =
- "assets/icons/motionless_detection.svg";
+ static const String motionlessDetection = "assets/icons/motionless_detection.svg";
static const String acHeating = "assets/icons/ac_heating.svg";
static const String acPowerOff = "assets/icons/ac_power_off.svg";
static const String acFanMiddle = "assets/icons/ac_fan_middle.svg";
static const String switchAlarmSound = "assets/icons/switch_alarm_sound.svg";
static const String resetOff = "assets/icons/reset_off.svg";
- static const String sensitivityOperationIcon =
- "assets/icons/sesitivity_operation_icon.svg";
+ static const String sensitivityOperationIcon = "assets/icons/sesitivity_operation_icon.svg";
static const String motionDetection = "assets/icons/motion_detection.svg";
static const String freezing = "assets/icons/freezing.svg";
static const String indicator = "assets/icons/indicator.svg";
@@ -60,8 +56,7 @@ class Assets {
static const String celsiusDegrees = "assets/icons/celsius_degrees.svg";
static const String masterState = "assets/icons/master_state.svg";
static const String acPower = "assets/icons/ac_power.svg";
- static const String farDetectionFunction =
- "assets/icons/far_detection_function.svg";
+ static const String farDetectionFunction = "assets/icons/far_detection_function.svg";
static const String nobodyTime = "assets/icons/nobody_time.svg";
// Automation functions
@@ -69,47 +64,33 @@ class Assets {
"assets/icons/automation_functions/temp_password_unlock.svg";
static const String doorlockNormalOpen =
"assets/icons/automation_functions/doorlock_normal_open.svg";
- static const String doorbell =
- "assets/icons/automation_functions/doorbell.svg";
+ static const String doorbell = "assets/icons/automation_functions/doorbell.svg";
static const String remoteUnlockViaApp =
"assets/icons/automation_functions/remote_unlock_via_app.svg";
- static const String doubleLock =
- "assets/icons/automation_functions/double_lock.svg";
- static const String selfTestResult =
- "assets/icons/automation_functions/self_test_result.svg";
- static const String lockAlarm =
- "assets/icons/automation_functions/lock_alarm.svg";
- static const String presenceState =
- "assets/icons/automation_functions/presence_state.svg";
- static const String currentTemp =
- "assets/icons/automation_functions/current_temp.svg";
- static const String presence =
- "assets/icons/automation_functions/presence.svg";
+ static const String doubleLock = "assets/icons/automation_functions/double_lock.svg";
+ static const String selfTestResult = "assets/icons/automation_functions/self_test_result.svg";
+ static const String lockAlarm = "assets/icons/automation_functions/lock_alarm.svg";
+ static const String presenceState = "assets/icons/automation_functions/presence_state.svg";
+ static const String currentTemp = "assets/icons/automation_functions/current_temp.svg";
+ static const String presence = "assets/icons/automation_functions/presence.svg";
static const String residualElectricity =
"assets/icons/automation_functions/residual_electricity.svg";
- static const String hijackAlarm =
- "assets/icons/automation_functions/hijack_alarm.svg";
- static const String passwordUnlock =
- "assets/icons/automation_functions/password_unlock.svg";
+ static const String hijackAlarm = "assets/icons/automation_functions/hijack_alarm.svg";
+ static const String passwordUnlock = "assets/icons/automation_functions/password_unlock.svg";
static const String remoteUnlockRequest =
"assets/icons/automation_functions/remote_unlock_req.svg";
- static const String cardUnlock =
- "assets/icons/automation_functions/card_unlock.svg";
+ static const String cardUnlock = "assets/icons/automation_functions/card_unlock.svg";
static const String motion = "assets/icons/automation_functions/motion.svg";
static const String fingerprintUnlock =
"assets/icons/automation_functions/fingerprint_unlock.svg";
// Presence Sensor Assets
static const String sensorMotionIcon = "assets/icons/sensor_motion_ic.svg";
- static const String sensorPresenceIcon =
- "assets/icons/sensor_presence_ic.svg";
+ static const String sensorPresenceIcon = "assets/icons/sensor_presence_ic.svg";
static const String sensorVacantIcon = "assets/icons/sensor_vacant_ic.svg";
- static const String illuminanceRecordIcon =
- "assets/icons/illuminance_record_ic.svg";
- static const String presenceRecordIcon =
- "assets/icons/presence_record_ic.svg";
- static const String helpDescriptionIcon =
- "assets/icons/help_description_ic.svg";
+ static const String illuminanceRecordIcon = "assets/icons/illuminance_record_ic.svg";
+ static const String presenceRecordIcon = "assets/icons/presence_record_ic.svg";
+ static const String helpDescriptionIcon = "assets/icons/help_description_ic.svg";
static const String lightPulp = "assets/icons/light_pulb.svg";
static const String acDevice = "assets/icons/ac_device.svg";
@@ -142,4 +123,5 @@ class Assets {
static const String dyi = 'assets/icons/dyi.svg';
static const String office = 'assets/icons/office.svg';
static const String parlour = 'assets/icons/parlour.svg';
+ static const String grid = "assets/images/grid.svg";
}
diff --git a/lib/utils/constants/routes_const.dart b/lib/utils/constants/routes_const.dart
new file mode 100644
index 00000000..99145609
--- /dev/null
+++ b/lib/utils/constants/routes_const.dart
@@ -0,0 +1,7 @@
+class RoutesConst {
+ static const String auth = '/login';
+ static const String home = '/';
+ static const String visitorPassword = '/visitor-password';
+ static const String accessManagementPage = '/access-management-page';
+ static const String deviceManagementPage = '/device-management-page';
+}
diff --git a/lib/utils/navigation_service.dart b/lib/utils/navigation_service.dart
index c0b12167..c9d654e6 100644
--- a/lib/utils/navigation_service.dart
+++ b/lib/utils/navigation_service.dart
@@ -5,3 +5,6 @@ class NavigationService {
static GlobalKey? snackbarKey =
GlobalKey();
}
+
+
+
diff --git a/pubspec.lock b/pubspec.lock
index 629c9fa0..9a9cd6a8 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -216,6 +216,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "7.7.0"
+ go_router:
+ dependency: "direct main"
+ description:
+ name: go_router
+ sha256: "2ddb88e9ad56ae15ee144ed10e33886777eb5ca2509a914850a5faa7b52ff459"
+ url: "https://pub.dev"
+ source: hosted
+ version: "14.2.7"
graphview:
dependency: "direct main"
description:
@@ -260,18 +268,18 @@ packages:
dependency: transitive
description:
name: leak_tracker
- sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05"
+ sha256: "7f0df31977cb2c0b88585095d168e689669a2cc9b97c309665e3386f3e9d341a"
url: "https://pub.dev"
source: hosted
- version: "10.0.5"
+ version: "10.0.4"
leak_tracker_flutter_testing:
dependency: transitive
description:
name: leak_tracker_flutter_testing
- sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806"
+ sha256: "06e98f569d004c1315b991ded39924b21af84cf14cc94791b8aea337d25b57f8"
url: "https://pub.dev"
source: hosted
- version: "3.0.5"
+ version: "3.0.3"
leak_tracker_testing:
dependency: transitive
description:
@@ -288,6 +296,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.0.0"
+ logging:
+ dependency: transitive
+ description:
+ name: logging
+ sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.2.0"
matcher:
dependency: transitive
description:
@@ -300,18 +316,18 @@ packages:
dependency: transitive
description:
name: material_color_utilities
- sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec
+ sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a"
url: "https://pub.dev"
source: hosted
- version: "0.11.1"
+ version: "0.8.0"
meta:
dependency: transitive
description:
name: meta
- sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7
+ sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136"
url: "https://pub.dev"
source: hosted
- version: "1.15.0"
+ version: "1.12.0"
nested:
dependency: transitive
description:
@@ -521,10 +537,10 @@ packages:
dependency: transitive
description:
name: test_api
- sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb"
+ sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f"
url: "https://pub.dev"
source: hosted
- version: "0.7.2"
+ version: "0.7.0"
typed_data:
dependency: transitive
description:
@@ -569,10 +585,10 @@ packages:
dependency: transitive
description:
name: vm_service
- sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d"
+ sha256: "3923c89304b715fb1eb6423f017651664a03bf5f4b29983627c4da791f74a4ec"
url: "https://pub.dev"
source: hosted
- version: "14.2.5"
+ version: "14.2.1"
web:
dependency: transitive
description:
diff --git a/pubspec.yaml b/pubspec.yaml
index 776d9f0c..a8e96a9b 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -44,7 +44,9 @@ dependencies:
flutter_secure_storage: ^9.2.2
shared_preferences: ^2.3.0
data_table_2: ^2.5.15
+ go_router:
intl: ^0.19.0
+
dev_dependencies:
flutter_test:
sdk: flutter