mirror of
https://github.com/SyncrowIOT/web.git
synced 2025-07-10 07:07:19 +00:00
create visitor password
This commit is contained in:
5
assets/images/device_note.svg
Normal file
5
assets/images/device_note.svg
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M5.64844 2.51953H6.35149V6.7031H5.64844V2.51953Z" fill="#FFC800"/>
|
||||||
|
<path d="M5.64844 8.82422H6.35149V9.52734H5.64844V8.82422Z" fill="#FFC800"/>
|
||||||
|
<path d="M10.2427 1.75734C9.10945 0.624141 7.60266 0 6 0C4.39734 0 2.89055 0.624141 1.75734 1.75734C0.624141 2.89055 0 4.39734 0 6C0 7.60266 0.624141 9.10945 1.75734 10.2427C2.89055 11.3759 4.39734 12 6 12C7.60266 12 9.10945 11.3759 10.2427 10.2427C11.3759 9.10945 12 7.60266 12 6C12 4.39734 11.3759 2.89055 10.2427 1.75734ZM7.05469 10.2305H4.94531V8.12109H7.05469V10.2305ZM7.05469 7.40625H4.94531V1.81641H7.05469V7.40625Z" fill="#FFC800"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 697 B |
@ -5,6 +5,7 @@ import 'package:syncrow_web/pages/auth/bloc/auth_bloc.dart';
|
|||||||
import 'package:syncrow_web/pages/auth/view/login_page.dart';
|
import 'package:syncrow_web/pages/auth/view/login_page.dart';
|
||||||
import 'package:syncrow_web/pages/home/bloc/home_bloc.dart';
|
import 'package:syncrow_web/pages/home/bloc/home_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/home/view/home_page.dart';
|
import 'package:syncrow_web/pages/home/view/home_page.dart';
|
||||||
|
import 'package:syncrow_web/pages/visitor_password/view/add_device_dialog.dart';
|
||||||
import 'package:syncrow_web/pages/visitor_password/view/visitor_password_dialog.dart';
|
import 'package:syncrow_web/pages/visitor_password/view/visitor_password_dialog.dart';
|
||||||
import 'package:syncrow_web/services/locator.dart';
|
import 'package:syncrow_web/services/locator.dart';
|
||||||
import 'package:syncrow_web/utils/color_manager.dart';
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
@ -40,6 +41,7 @@ class MyApp extends StatelessWidget {
|
|||||||
PointerDeviceKind.unknown,
|
PointerDeviceKind.unknown,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
||||||
theme: ThemeData(
|
theme: ThemeData(
|
||||||
textTheme: const TextTheme(
|
textTheme: const TextTheme(
|
||||||
bodySmall: TextStyle(fontSize: 13, color: ColorsManager.whiteColors, fontWeight: FontWeight.bold),
|
bodySmall: TextStyle(fontSize: 13, color: ColorsManager.whiteColors, fontWeight: FontWeight.bold),
|
||||||
@ -53,10 +55,11 @@ class MyApp extends StatelessWidget {
|
|||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), // Set up color scheme
|
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), // Set up color scheme
|
||||||
useMaterial3: true, // Enable Material 3
|
useMaterial3: true, // Enable Material 3
|
||||||
),
|
),
|
||||||
// home: VisitorPasswordDialog()
|
// home: AddDeviceDialog()
|
||||||
home:isLoggedIn == 'Success' ? const HomePage() : const LoginPage(),
|
home:isLoggedIn == 'Success' ? const HomePage() : const LoginPage(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -171,11 +171,10 @@ class AccessBloc extends Bloc<AccessEvent, AccessState> {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String timestampToDate(dynamic timestamp) {
|
||||||
DateTime timestampToDateTime(dynamic timestamp) {
|
DateTime dateTime = DateTime.fromMillisecondsSinceEpoch(int.parse(timestamp) * 1000);
|
||||||
return DateTime.fromMillisecondsSinceEpoch(int.parse(timestamp) * 1000);
|
return "${dateTime.year}/${dateTime.month.toString().padLeft(2, '0')}/${dateTime.day.toString().padLeft(2, '0')}";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import 'package:syncrow_web/utils/constants/const.dart';
|
||||||
|
|
||||||
class PasswordModel {
|
class PasswordModel {
|
||||||
final dynamic passwordId;
|
final dynamic passwordId;
|
||||||
final dynamic invalidTime;
|
final dynamic invalidTime;
|
||||||
@ -6,7 +8,7 @@ class PasswordModel {
|
|||||||
final dynamic createdTime;
|
final dynamic createdTime;
|
||||||
final dynamic passwodName; // New field
|
final dynamic passwodName; // New field
|
||||||
final dynamic passwordStatus;
|
final dynamic passwordStatus;
|
||||||
final dynamic passwordType;
|
final AccessType passwordType;
|
||||||
final dynamic deviceUuid;
|
final dynamic deviceUuid;
|
||||||
|
|
||||||
PasswordModel({
|
PasswordModel({
|
||||||
@ -17,7 +19,7 @@ class PasswordModel {
|
|||||||
this.createdTime,
|
this.createdTime,
|
||||||
this.passwodName, // New field
|
this.passwodName, // New field
|
||||||
this.passwordStatus,
|
this.passwordStatus,
|
||||||
this.passwordType,
|
required this.passwordType,
|
||||||
this.deviceUuid,
|
this.deviceUuid,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -30,7 +32,7 @@ class PasswordModel {
|
|||||||
createdTime: json['createdTime'],
|
createdTime: json['createdTime'],
|
||||||
passwodName: json['passwodName']??'No name', // New field
|
passwodName: json['passwodName']??'No name', // New field
|
||||||
passwordStatus: json['passwordStatus'],
|
passwordStatus: json['passwordStatus'],
|
||||||
passwordType: json['passwordType'],
|
passwordType:AccessTypeExtension.fromString(json['passwordType']) ,
|
||||||
deviceUuid: json['deviceUuid'],
|
deviceUuid: json['deviceUuid'],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -3,10 +3,12 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
|||||||
import 'package:syncrow_web/pages/access_management/bloc/access_bloc.dart';
|
import 'package:syncrow_web/pages/access_management/bloc/access_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/access_management/bloc/access_event.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/access_management/bloc/access_state.dart';
|
||||||
|
import 'package:syncrow_web/pages/common/custom_table.dart';
|
||||||
import 'package:syncrow_web/pages/common/date_time_widget.dart';
|
import 'package:syncrow_web/pages/common/date_time_widget.dart';
|
||||||
import 'package:syncrow_web/pages/common/default_button.dart';
|
import 'package:syncrow_web/pages/common/default_button.dart';
|
||||||
import 'package:syncrow_web/pages/visitor_password/view/visitor_password_dialog.dart';
|
import 'package:syncrow_web/pages/visitor_password/view/visitor_password_dialog.dart';
|
||||||
import 'package:syncrow_web/utils/color_manager.dart';
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
|
import 'package:syncrow_web/utils/constants/const.dart';
|
||||||
import 'package:syncrow_web/utils/style.dart';
|
import 'package:syncrow_web/utils/style.dart';
|
||||||
import 'package:syncrow_web/web_layout/web_scaffold.dart';
|
import 'package:syncrow_web/web_layout/web_scaffold.dart';
|
||||||
|
|
||||||
@ -51,68 +53,69 @@ class AccessManagementPage extends StatelessWidget {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Container(
|
Container(
|
||||||
height: size.height * 0.05,
|
|
||||||
width:size.width * 0.26 ,
|
|
||||||
decoration: containerDecoration,
|
decoration: containerDecoration,
|
||||||
child: Center(
|
height: size.height * 0.05,
|
||||||
child: ListView.builder(
|
child: Flexible(
|
||||||
scrollDirection: Axis.horizontal,
|
child: ListView.builder(
|
||||||
itemCount: BlocProvider.of<AccessBloc>(context).tabs.length,
|
scrollDirection: Axis.horizontal,
|
||||||
itemBuilder: (context, index) {
|
itemCount: BlocProvider.of<AccessBloc>(context).tabs.length,
|
||||||
final isSelected = index ==
|
shrinkWrap: true,
|
||||||
BlocProvider.of<AccessBloc>(context).selectedIndex;
|
itemBuilder: (context, index) {
|
||||||
return InkWell(
|
final isSelected = index ==
|
||||||
onTap: () {
|
BlocProvider.of<AccessBloc>(context).selectedIndex;
|
||||||
BlocProvider.of<AccessBloc>(context).add(TabChangedEvent(index));
|
return InkWell(
|
||||||
},
|
onTap: () {
|
||||||
child: Container(
|
BlocProvider.of<AccessBloc>(context).add(TabChangedEvent(index));
|
||||||
decoration: BoxDecoration(
|
},
|
||||||
color: ColorsManager.boxColor,
|
child: Container(
|
||||||
border: Border.all(
|
decoration: BoxDecoration(
|
||||||
color: isSelected ? Colors.blue : Colors.transparent,
|
color: ColorsManager.boxColor,
|
||||||
width: 2.0,),
|
border: Border.all(
|
||||||
borderRadius: index == 0
|
color: isSelected ? Colors.blue : Colors.transparent,
|
||||||
? const BorderRadius.only(
|
width: 2.0,),
|
||||||
topLeft: Radius.circular(10),
|
borderRadius: index == 0
|
||||||
bottomLeft: Radius.circular(10))
|
? const BorderRadius.only(
|
||||||
: index == 3
|
topLeft: Radius.circular(10),
|
||||||
? const BorderRadius.only(
|
bottomLeft: Radius.circular(10))
|
||||||
topRight: Radius.circular(10),
|
: index == 3
|
||||||
bottomRight: Radius.circular(10))
|
? const BorderRadius.only(
|
||||||
: null),
|
topRight: Radius.circular(10),
|
||||||
padding: const EdgeInsets.only(left: 10,right: 10),
|
bottomRight: Radius.circular(10))
|
||||||
child: Center(
|
: null),
|
||||||
child: Text(
|
padding: const EdgeInsets.only(left: 10,right: 10),
|
||||||
BlocProvider.of<AccessBloc>(context).tabs[index],
|
child: Center(
|
||||||
style: TextStyle(
|
child: Text(
|
||||||
color: isSelected
|
BlocProvider.of<AccessBloc>(context).tabs[index],
|
||||||
? Colors.blue
|
style: TextStyle(
|
||||||
: Colors.black,
|
color: isSelected
|
||||||
|
? Colors.blue
|
||||||
|
: Colors.black,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
);
|
||||||
);
|
},
|
||||||
},
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
height: 20,
|
height: 20,
|
||||||
),
|
),
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
Column(
|
Column(
|
||||||
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
const Text('Password Name'),
|
const Text('Name'),
|
||||||
Container(
|
Container(
|
||||||
width: size.width * 0.15,
|
width: size.width * 0.15,
|
||||||
decoration: containerDecoration,
|
decoration: containerDecoration,
|
||||||
child: TextFormField(
|
child: TextFormField(
|
||||||
controller: accessBloc.passwordName,
|
controller: accessBloc.passwordName,
|
||||||
style: TextStyle(color: Colors.black),
|
style: const TextStyle(color: Colors.black),
|
||||||
decoration: textBoxDecoration()!
|
decoration: textBoxDecoration()!
|
||||||
.copyWith(hintText: 'Please enter'),
|
.copyWith(hintText: 'Please enter'),
|
||||||
)),
|
)),
|
||||||
@ -206,7 +209,7 @@ class AccessManagementPage extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
borderRadius: 8,
|
borderRadius: 8,
|
||||||
child: Text('+ Create Visitor Password ')),
|
child: const Text('+ Create Visitor Password ')),
|
||||||
),
|
),
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
width: 10,
|
width: 10,
|
||||||
@ -230,120 +233,110 @@ class AccessManagementPage extends StatelessWidget {
|
|||||||
height: 20,
|
height: 20,
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: state is TableLoaded
|
child: state is TableLoaded
|
||||||
? TableWidget(size, state,accessBloc)
|
? DynamicTable(
|
||||||
: const Center(child: CircularProgressIndicator()))
|
size: size,
|
||||||
|
cellDecoration: containerDecoration,
|
||||||
|
headers: const [
|
||||||
|
'Name',
|
||||||
|
'Access Type',
|
||||||
|
'Access Period',
|
||||||
|
'Device Id',
|
||||||
|
'Authorizer',
|
||||||
|
'Authorization Date & Time',
|
||||||
|
'Access Status'
|
||||||
|
],
|
||||||
|
data: state.data.map((item) {
|
||||||
|
return [
|
||||||
|
item.passwodName.toString(),
|
||||||
|
item.passwordType.value,
|
||||||
|
('${accessBloc.timestampToDate(item.effectiveTime)} - ${accessBloc.timestampToDate(item.invalidTime)}'),
|
||||||
|
item.deviceUuid.toString(),
|
||||||
|
'',
|
||||||
|
'',
|
||||||
|
''
|
||||||
|
];
|
||||||
|
}).toList(),
|
||||||
|
)
|
||||||
|
: const Center(child: CircularProgressIndicator()),
|
||||||
|
)
|
||||||
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
})));
|
})));
|
||||||
}
|
}
|
||||||
|
|
||||||
Container TableWidget(Size size, TableLoaded state,AccessBloc accessBloc) {
|
|
||||||
return Container(
|
|
||||||
decoration: containerDecoration,
|
|
||||||
width: size.width,
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.all(10.0),
|
|
||||||
child: ListView(
|
|
||||||
scrollDirection: Axis.horizontal,
|
|
||||||
children: [
|
|
||||||
Container(
|
|
||||||
width: size.width,
|
|
||||||
height: size.height,
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
Container(
|
|
||||||
color: ColorsManager.boxColor,
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
_buildTableHeaderCell('Password name'),
|
|
||||||
_buildTableHeaderCell(' Password Type'),
|
|
||||||
_buildTableHeaderCell('Start Time'),
|
|
||||||
_buildTableHeaderCell('End Time'),
|
|
||||||
_buildTableHeaderCell('Device Id'),
|
|
||||||
// _buildTableHeaderCell('Authorization Source'),
|
|
||||||
// _buildTableHeaderCell('Authorizer'),
|
|
||||||
_buildTableHeaderCell('Password Created'),
|
|
||||||
// _buildTableHeaderCell('Access Status'),
|
|
||||||
_buildTableHeaderCell('Password Status'),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
child: Container(
|
|
||||||
width: size.width,
|
|
||||||
color: ColorsManager.whiteColors,
|
|
||||||
child: ListView(
|
|
||||||
shrinkWrap: true,
|
|
||||||
children: [
|
|
||||||
Column(
|
|
||||||
children: state.data.map((item) {
|
|
||||||
return Row(
|
|
||||||
children: [
|
|
||||||
_buildTableCell(item.passwodName),
|
|
||||||
_buildTableCell(item.passwordType),
|
|
||||||
|
|
||||||
_buildTableCell(accessBloc.timestampToDateTime(item.effectiveTime).toString()),
|
// Container TableWidget(Size size, TableLoaded state,AccessBloc accessBloc) {
|
||||||
_buildTableCell(accessBloc.timestampToDateTime(item.invalidTime).toString()),
|
// return Container(
|
||||||
_buildTableCell(item.deviceUuid.toString()),
|
// decoration: containerDecoration,
|
||||||
// _buildTableCell(item.authorizationSource),
|
// width: size.width,
|
||||||
// _buildTableCell(item.authorizer),
|
// child: Padding(
|
||||||
_buildTableCell(item.passwordCreated!=null?accessBloc.timestampToDateTime(item.passwordCreated).toString():'no data'),
|
// padding: const EdgeInsets.all(10.0),
|
||||||
// _buildTableCell(item.accessStatus),
|
// child: ListView(
|
||||||
_buildTableCell(item.passwordStatus.toString()),
|
// scrollDirection: Axis.horizontal,
|
||||||
],
|
// children: [
|
||||||
);
|
// Container(
|
||||||
}).toList(),
|
// width: size.width,
|
||||||
),
|
// height: size.height,
|
||||||
],
|
// child: Column(
|
||||||
),
|
// children: [
|
||||||
),
|
// Container(
|
||||||
),
|
// color: ColorsManager.boxColor,
|
||||||
],
|
// child: Row(
|
||||||
),
|
// children: [
|
||||||
),
|
// _buildTableHeaderCell('Password name'),
|
||||||
],
|
// _buildTableHeaderCell(' Password Type'),
|
||||||
),
|
// _buildTableHeaderCell('Start Time'),
|
||||||
),
|
// _buildTableHeaderCell('End Time'),
|
||||||
);
|
// _buildTableHeaderCell('Device Id'),
|
||||||
}
|
// // _buildTableHeaderCell('Authorization Source'),
|
||||||
|
// // _buildTableHeaderCell('Authorizer'),
|
||||||
|
// _buildTableHeaderCell('Password Created'),
|
||||||
|
// // _buildTableHeaderCell('Access Status'),
|
||||||
|
// _buildTableHeaderCell('Password Status'),
|
||||||
|
// ],
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// Expanded(
|
||||||
|
// child: Container(
|
||||||
|
// width: size.width,
|
||||||
|
// color: ColorsManager.whiteColors,
|
||||||
|
// child: ListView(
|
||||||
|
// shrinkWrap: true,
|
||||||
|
// children: [
|
||||||
|
// Column(
|
||||||
|
// children: state.data.map((item) {
|
||||||
|
// return Row(
|
||||||
|
// children: [
|
||||||
|
// _buildTableCell(item.passwodName),
|
||||||
|
// _buildTableCell(item.passwordType),
|
||||||
|
//
|
||||||
|
// _buildTableCell(accessBloc.timestampToDateTime(item.effectiveTime).toString()),
|
||||||
|
// _buildTableCell(accessBloc.timestampToDateTime(item.invalidTime).toString()),
|
||||||
|
// _buildTableCell(item.deviceUuid.toString()),
|
||||||
|
// // _buildTableCell(item.authorizationSource),
|
||||||
|
// // _buildTableCell(item.authorizer),
|
||||||
|
// _buildTableCell(item.passwordCreated!=null?accessBloc.timestampToDateTime(item.passwordCreated).toString():'no data'),
|
||||||
|
// // _buildTableCell(item.accessStatus),
|
||||||
|
// _buildTableCell(item.passwordStatus.toString()),
|
||||||
|
// ],
|
||||||
|
// );
|
||||||
|
// }).toList(),
|
||||||
|
// ),
|
||||||
|
// ],
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ],
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ],
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// );
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Widget _buildTableHeaderCell(String title) {
|
|
||||||
return Expanded(
|
|
||||||
child: Container(
|
|
||||||
decoration: const BoxDecoration(
|
|
||||||
border: Border.symmetric(
|
|
||||||
vertical: BorderSide(color: ColorsManager.boxDivider))),
|
|
||||||
alignment: Alignment.centerLeft,
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.all(8.0),
|
|
||||||
child: Text(title, style: TextStyle(fontWeight: FontWeight.bold)),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _buildTableCell(String content) {
|
|
||||||
return Expanded(
|
|
||||||
child: Container(
|
|
||||||
height: 80,
|
|
||||||
padding: const EdgeInsets.all(20.0),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
border: Border(
|
|
||||||
bottom: BorderSide( // <--- right side
|
|
||||||
color: ColorsManager.boxDivider,
|
|
||||||
width: 1.0,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
),
|
|
||||||
alignment: Alignment.centerLeft,
|
|
||||||
child: Text(
|
|
||||||
content,
|
|
||||||
style: TextStyle(color: Colors.black, fontSize: 12),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
103
lib/pages/common/custom_table.dart
Normal file
103
lib/pages/common/custom_table.dart
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
|
|
||||||
|
class DynamicTable extends StatelessWidget {
|
||||||
|
final List<String> headers;
|
||||||
|
final List<List<dynamic>> data;
|
||||||
|
final BoxDecoration? headerDecoration;
|
||||||
|
final BoxDecoration? cellDecoration;
|
||||||
|
final Size size;
|
||||||
|
|
||||||
|
const DynamicTable({
|
||||||
|
Key? key,
|
||||||
|
required this.headers,
|
||||||
|
required this.data,
|
||||||
|
required this.size,
|
||||||
|
this.headerDecoration,
|
||||||
|
this.cellDecoration,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
|
||||||
|
decoration: cellDecoration,
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(10.0),
|
||||||
|
child: ListView(
|
||||||
|
scrollDirection: Axis.horizontal,
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
width:size.width,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
decoration: headerDecoration ??
|
||||||
|
BoxDecoration(color: Colors.grey[200]),
|
||||||
|
child: Row(
|
||||||
|
children: headers.map((header) =>
|
||||||
|
_buildTableHeaderCell(header)).toList(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Container(
|
||||||
|
color: Colors.white,
|
||||||
|
child: ListView(
|
||||||
|
shrinkWrap: true,
|
||||||
|
children: data.map((row) {
|
||||||
|
return Row(
|
||||||
|
children: row.map((cell) =>
|
||||||
|
_buildTableCell(cell.toString())).toList(),
|
||||||
|
);
|
||||||
|
}).toList(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Widget _buildTableHeaderCell(String title) {
|
||||||
|
return Expanded(
|
||||||
|
child: Container(
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
border: Border.symmetric(
|
||||||
|
vertical: BorderSide(color: ColorsManager.boxDivider))),
|
||||||
|
alignment: Alignment.centerLeft,
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(8.0),
|
||||||
|
child: Text(title, style: TextStyle(fontWeight: FontWeight.bold)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildTableCell(String content) {
|
||||||
|
return Expanded(
|
||||||
|
child: Container(
|
||||||
|
height: 80,
|
||||||
|
padding: const EdgeInsets.all(20.0),
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
border: Border(
|
||||||
|
bottom: BorderSide( // <--- right side
|
||||||
|
color: ColorsManager.boxDivider,
|
||||||
|
width: 1.0,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
),
|
||||||
|
alignment: Alignment.centerLeft,
|
||||||
|
child: Text(
|
||||||
|
content,
|
||||||
|
style: TextStyle(color: Colors.black, fontSize: 12),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -29,8 +29,7 @@ class CustomWebTextField extends StatelessWidget {
|
|||||||
if(isRequired)
|
if(isRequired)
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text('* ',
|
||||||
'* ',
|
|
||||||
style: Theme.of(context)
|
style: Theme.of(context)
|
||||||
.textTheme
|
.textTheme
|
||||||
.bodyMedium!
|
.bodyMedium!
|
||||||
@ -39,6 +38,7 @@ class CustomWebTextField extends StatelessWidget {
|
|||||||
Text(textFieldName),
|
Text(textFieldName),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
const SizedBox(width: 10,),
|
||||||
Text(
|
Text(
|
||||||
description??'', // ' The password will be sent to the visitor’s email address.',
|
description??'', // ' The password will be sent to the visitor’s email address.',
|
||||||
style: Theme.of(context)
|
style: Theme.of(context)
|
||||||
@ -53,7 +53,17 @@ class CustomWebTextField extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
const SizedBox(height: 7,),
|
const SizedBox(height: 7,),
|
||||||
Container(
|
Container(
|
||||||
decoration: containerDecoration,
|
height: MediaQuery.of(context).size.height*0.05,
|
||||||
|
decoration: containerDecoration.copyWith(
|
||||||
|
color: const Color(0xFFF5F6F7),
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: Colors.grey.withOpacity(0.3),
|
||||||
|
spreadRadius:2,
|
||||||
|
blurRadius: 3,
|
||||||
|
offset: Offset(1, 1), // changes position of shadow
|
||||||
|
), ]
|
||||||
|
),
|
||||||
child: TextFormField(
|
child: TextFormField(
|
||||||
controller: controller,
|
controller: controller,
|
||||||
style: const TextStyle(color: Colors.black),
|
style: const TextStyle(color: Colors.black),
|
||||||
|
@ -2,6 +2,8 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_event.dart';
|
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_event.dart';
|
||||||
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_state.dart';
|
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_state.dart';
|
||||||
|
import 'package:syncrow_web/pages/visitor_password/model/device_model.dart';
|
||||||
|
import 'package:syncrow_web/services/access_mang_api.dart';
|
||||||
import 'package:syncrow_web/utils/color_manager.dart';
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
import 'package:syncrow_web/utils/snack_bar.dart';
|
import 'package:syncrow_web/utils/snack_bar.dart';
|
||||||
|
|
||||||
@ -9,15 +11,29 @@ import 'package:syncrow_web/utils/snack_bar.dart';
|
|||||||
class VisitorPasswordBloc extends Bloc<VisitorPasswordEvent, VisitorPasswordState> {
|
class VisitorPasswordBloc extends Bloc<VisitorPasswordEvent, VisitorPasswordState> {
|
||||||
VisitorPasswordBloc() : super(VisitorPasswordInitial()) {
|
VisitorPasswordBloc() : super(VisitorPasswordInitial()) {
|
||||||
on<SelectUsageFrequency>(selectUsageFrequency);
|
on<SelectUsageFrequency>(selectUsageFrequency);
|
||||||
|
on<FetchDevice>(_onFetchDevice);
|
||||||
|
|
||||||
on<SelectPasswordType>(selectAccessType);
|
on<SelectPasswordType>(selectAccessType);
|
||||||
on<SelectTimeVisitorPassword>(selectTimeVisitorPassword);
|
on<SelectTimeVisitorPassword>(selectTimeVisitorPassword);
|
||||||
on<ToggleRepeatEvent>(toggleRepeat);
|
on<ToggleRepeatEvent>(toggleRepeat);
|
||||||
on<ToggleDaySelectionEvent>(toggleDaySelection);
|
on<ToggleDaySelectionEvent>(toggleDaySelection);
|
||||||
|
|
||||||
}
|
}
|
||||||
final TextEditingController userNameController = TextEditingController();
|
final TextEditingController userNameController = TextEditingController();
|
||||||
final TextEditingController emailController = TextEditingController();
|
final TextEditingController emailController = TextEditingController();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
final TextEditingController deviceNameController = TextEditingController();
|
||||||
|
final TextEditingController deviceIdController = TextEditingController();
|
||||||
|
final TextEditingController unitNameController = TextEditingController();
|
||||||
|
final TextEditingController virtualAddressController = TextEditingController();
|
||||||
|
|
||||||
|
List<DeviceModel> data=[];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
String accessTypeSelected='Offline Password';
|
String accessTypeSelected='Offline Password';
|
||||||
String usageFrequencySelected='One-Time';
|
String usageFrequencySelected='One-Time';
|
||||||
|
|
||||||
@ -136,6 +152,17 @@ class VisitorPasswordBloc extends Bloc<VisitorPasswordEvent, VisitorPasswordStat
|
|||||||
}
|
}
|
||||||
emit(ChangeTimeState());
|
emit(ChangeTimeState());
|
||||||
}
|
}
|
||||||
|
//Add Accessible Device
|
||||||
|
|
||||||
|
Future<void> _onFetchDevice(
|
||||||
|
FetchDevice event, Emitter<VisitorPasswordState> emit) async {
|
||||||
|
try {
|
||||||
|
emit(DeviceLoaded());
|
||||||
|
data = await AccessMangApi().fetchDevices();
|
||||||
|
emit(TableLoaded(data));
|
||||||
|
} catch (e) {
|
||||||
|
emit(FailedState(e.toString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -47,3 +47,4 @@ class ToggleDaySelectionEvent extends VisitorPasswordEvent {
|
|||||||
|
|
||||||
|
|
||||||
class ToggleRepeatEvent extends VisitorPasswordEvent {}
|
class ToggleRepeatEvent extends VisitorPasswordEvent {}
|
||||||
|
class FetchDevice extends VisitorPasswordEvent {}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
|
|
||||||
|
|
||||||
import 'package:equatable/equatable.dart';
|
import 'package:equatable/equatable.dart';
|
||||||
|
import 'package:syncrow_web/pages/visitor_password/model/device_model.dart';
|
||||||
|
|
||||||
abstract class VisitorPasswordState extends Equatable {
|
abstract class VisitorPasswordState extends Equatable {
|
||||||
const VisitorPasswordState();
|
const VisitorPasswordState();
|
||||||
@ -42,3 +43,20 @@ class IsRepeatState extends VisitorPasswordState {
|
|||||||
|
|
||||||
class LoadingInitialState extends VisitorPasswordState {}
|
class LoadingInitialState extends VisitorPasswordState {}
|
||||||
class ChangeTimeState extends VisitorPasswordState {}
|
class ChangeTimeState extends VisitorPasswordState {}
|
||||||
|
class DeviceLoaded extends VisitorPasswordState {}
|
||||||
|
class FailedState extends VisitorPasswordState {
|
||||||
|
final String message;
|
||||||
|
|
||||||
|
FailedState(this.message);
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [message];
|
||||||
|
}
|
||||||
|
class TableLoaded extends VisitorPasswordState {
|
||||||
|
final List<DeviceModel> data;
|
||||||
|
|
||||||
|
const TableLoaded(this.data);
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [data];
|
||||||
|
}
|
99
lib/pages/visitor_password/model/device_model.dart
Normal file
99
lib/pages/visitor_password/model/device_model.dart
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
|
||||||
|
|
||||||
|
class DeviceModel {
|
||||||
|
dynamic productUuid;
|
||||||
|
dynamic productType;
|
||||||
|
dynamic activeTime;
|
||||||
|
dynamic category;
|
||||||
|
dynamic categoryName;
|
||||||
|
dynamic createTime;
|
||||||
|
dynamic gatewayId;
|
||||||
|
dynamic icon;
|
||||||
|
dynamic ip;
|
||||||
|
dynamic lat;
|
||||||
|
dynamic localKey;
|
||||||
|
dynamic lon;
|
||||||
|
dynamic model;
|
||||||
|
dynamic name;
|
||||||
|
dynamic online;
|
||||||
|
dynamic ownerId;
|
||||||
|
dynamic sub;
|
||||||
|
dynamic timeZone;
|
||||||
|
dynamic updateTime;
|
||||||
|
dynamic uuid;
|
||||||
|
|
||||||
|
DeviceModel({
|
||||||
|
required this.productUuid,
|
||||||
|
required this.productType,
|
||||||
|
required this.activeTime,
|
||||||
|
required this.category,
|
||||||
|
required this.categoryName,
|
||||||
|
required this.createTime,
|
||||||
|
required this.gatewayId,
|
||||||
|
required this.icon,
|
||||||
|
required this.ip,
|
||||||
|
required this.lat,
|
||||||
|
required this.localKey,
|
||||||
|
required this.lon,
|
||||||
|
required this.model,
|
||||||
|
required this.name,
|
||||||
|
required this.online,
|
||||||
|
required this.ownerId,
|
||||||
|
required this.sub,
|
||||||
|
required this.timeZone,
|
||||||
|
required this.updateTime,
|
||||||
|
required this.uuid,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Deserialize from JSON
|
||||||
|
factory DeviceModel.fromJson(Map<String, dynamic> json) {
|
||||||
|
return DeviceModel(
|
||||||
|
productUuid: json['productUuid'] ,
|
||||||
|
productType: json['productType'],
|
||||||
|
activeTime: json['activeTime'],
|
||||||
|
category: json['category'] ,
|
||||||
|
categoryName: json['categoryName'] ,
|
||||||
|
createTime: json['createTime'] ,
|
||||||
|
gatewayId: json['gatewayId'],
|
||||||
|
icon: json['icon'],
|
||||||
|
ip: json['ip'] ,
|
||||||
|
lat: json['lat'] ,
|
||||||
|
localKey: json['localKey'] ,
|
||||||
|
lon: json['lon'] ,
|
||||||
|
model: json['model'] ,
|
||||||
|
name: json['name'],
|
||||||
|
online: json['online'],
|
||||||
|
ownerId: json['ownerId'] ,
|
||||||
|
sub: json['sub'],
|
||||||
|
timeZone: json['timeZone'],
|
||||||
|
updateTime: json['updateTime'] ,
|
||||||
|
uuid: json['uuid'],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Serialize to JSON
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
return {
|
||||||
|
'productUuid': productUuid,
|
||||||
|
'productType': productType,
|
||||||
|
'activeTime': activeTime,
|
||||||
|
'category': category,
|
||||||
|
'categoryName': categoryName,
|
||||||
|
'createTime': createTime,
|
||||||
|
'gatewayId': gatewayId,
|
||||||
|
'icon': icon,
|
||||||
|
'ip': ip,
|
||||||
|
'lat': lat,
|
||||||
|
'localKey': localKey,
|
||||||
|
'lon': lon,
|
||||||
|
'model': model,
|
||||||
|
'name': name,
|
||||||
|
'online': online,
|
||||||
|
'ownerId': ownerId,
|
||||||
|
'sub': sub,
|
||||||
|
'timeZone': timeZone,
|
||||||
|
'updateTime': updateTime,
|
||||||
|
'uuid': uuid,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
210
lib/pages/visitor_password/view/add_device_dialog.dart
Normal file
210
lib/pages/visitor_password/view/add_device_dialog.dart
Normal file
@ -0,0 +1,210 @@
|
|||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
|
import 'package:syncrow_web/pages/common/custom_web_textfield.dart';
|
||||||
|
import 'package:syncrow_web/pages/common/default_button.dart';
|
||||||
|
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_bloc.dart';
|
||||||
|
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_event.dart';
|
||||||
|
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_state.dart';
|
||||||
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
|
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||||
|
import 'package:syncrow_web/utils/style.dart';
|
||||||
|
import '../../common/custom_table.dart';
|
||||||
|
|
||||||
|
|
||||||
|
class AddDeviceDialog extends StatelessWidget {
|
||||||
|
const AddDeviceDialog({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
Size size = MediaQuery.of(context).size;
|
||||||
|
return BlocProvider(
|
||||||
|
create: (context) => VisitorPasswordBloc()..add(FetchDevice()),
|
||||||
|
child: BlocBuilder<VisitorPasswordBloc, VisitorPasswordState>(
|
||||||
|
builder: (BuildContext context, VisitorPasswordState state) {
|
||||||
|
final visitorBloc = BlocProvider.of<VisitorPasswordBloc>(context);
|
||||||
|
return AlertDialog(
|
||||||
|
backgroundColor: Colors.white,
|
||||||
|
title: const Text('Add Accessible Device'),
|
||||||
|
content: Container(
|
||||||
|
height: MediaQuery.of(context).size.height/1.7,
|
||||||
|
width: MediaQuery.of(context).size.width/2,
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(10.0),
|
||||||
|
child: Column(
|
||||||
|
children: <Widget>[
|
||||||
|
Container(
|
||||||
|
width: size.width,
|
||||||
|
padding: EdgeInsets.all(15),
|
||||||
|
decoration:containerDecoration.copyWith(
|
||||||
|
color: ColorsManager.worningColor,
|
||||||
|
border: Border.all(color: Color(0xffFFD22F)),
|
||||||
|
boxShadow: []
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
SizedBox(
|
||||||
|
child: SvgPicture.asset(
|
||||||
|
Assets.deviceNoteIcon,
|
||||||
|
height: 15,
|
||||||
|
width: 15,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(width: 10,),
|
||||||
|
Text('Only online accessible devices can be added'),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
),
|
||||||
|
SizedBox(height: 20,),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
flex: 2,
|
||||||
|
child: CustomWebTextField(
|
||||||
|
controller: visitorBloc.deviceNameController,
|
||||||
|
isRequired: true,
|
||||||
|
textFieldName: 'Device Name',
|
||||||
|
description: '',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 10),
|
||||||
|
Expanded(
|
||||||
|
flex: 2,
|
||||||
|
child: CustomWebTextField(
|
||||||
|
controller: visitorBloc.deviceNameController,
|
||||||
|
isRequired: true,
|
||||||
|
textFieldName: 'Device ID',
|
||||||
|
description: '',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 10),
|
||||||
|
Expanded(
|
||||||
|
flex: 2,
|
||||||
|
child: CustomWebTextField(
|
||||||
|
controller: visitorBloc.unitNameController,
|
||||||
|
isRequired: true,
|
||||||
|
textFieldName: 'Unit Name',
|
||||||
|
description: '',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
const SizedBox(width: 10),
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
const SizedBox(height: 25),
|
||||||
|
Center(
|
||||||
|
child: Container(
|
||||||
|
height: 43,
|
||||||
|
width: 100,
|
||||||
|
decoration: containerDecoration,
|
||||||
|
child: Center(
|
||||||
|
child: DefaultButton(
|
||||||
|
onPressed: () {
|
||||||
|
// Your search function here
|
||||||
|
},
|
||||||
|
borderRadius: 9,
|
||||||
|
child: const Text('Search'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(width: 10),
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
const SizedBox(height: 25),
|
||||||
|
|
||||||
|
Center(
|
||||||
|
child: Container(
|
||||||
|
height: 43,
|
||||||
|
width: 100,
|
||||||
|
decoration: containerDecoration,
|
||||||
|
child: Center(
|
||||||
|
child: DefaultButton(
|
||||||
|
backgroundColor: ColorsManager.whiteColors,
|
||||||
|
borderRadius: 9,
|
||||||
|
child: Text(
|
||||||
|
'Reset',
|
||||||
|
style: Theme.of(context).textTheme.bodySmall!.copyWith(color: Colors.black),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
],
|
||||||
|
),
|
||||||
|
|
||||||
|
],
|
||||||
|
),
|
||||||
|
SizedBox(height: 20),
|
||||||
|
Container(
|
||||||
|
child: Expanded(
|
||||||
|
child: state is TableLoaded
|
||||||
|
? Container(
|
||||||
|
decoration: containerDecoration,
|
||||||
|
child: DynamicTable(
|
||||||
|
size: size*0.5,
|
||||||
|
headers: ['Device Name', 'Device ID', 'Access Type', 'Unit Name', 'Status'],
|
||||||
|
data: state.data.map((item) {
|
||||||
|
return [
|
||||||
|
item.name.toString(),
|
||||||
|
item.uuid.toString(),
|
||||||
|
item.productType.toString(),
|
||||||
|
'',
|
||||||
|
item.online.toString(),
|
||||||
|
// item.categoryName.toString(),
|
||||||
|
// accessBloc.timestampToDateTime(item.effectiveTime).toString(),
|
||||||
|
// accessBloc.timestampToDateTime(item.invalidTime).toString(),
|
||||||
|
// item.deviceUuid.toString(),
|
||||||
|
// item.passwordCreated != null ? accessBloc.timestampToDateTime(item.passwordCreated).toString() : 'no data',
|
||||||
|
// item.passwordStatus.toString(),
|
||||||
|
];
|
||||||
|
}).toList(),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
// TableWidget(size: size, headers: ['Device Name', 'Device ID', 'Access Type', 'Unit Name', 'Status', 'Virtual Address',], data: [], bloc: bloc)
|
||||||
|
: const Center(child: CircularProgressIndicator())),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
actionsAlignment: MainAxisAlignment.center,
|
||||||
|
actions: <Widget>[
|
||||||
|
Container(
|
||||||
|
decoration: containerDecoration,
|
||||||
|
width: size.width * 0.2,
|
||||||
|
child: DefaultButton(
|
||||||
|
borderRadius: 8,
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context).pop(); // Close the dialog
|
||||||
|
},
|
||||||
|
backgroundColor: Colors.white,
|
||||||
|
child: Text(
|
||||||
|
'Cancel',
|
||||||
|
style: Theme.of(context).textTheme.bodyMedium!,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
decoration: containerDecoration,
|
||||||
|
width: size.width * 0.2,
|
||||||
|
child: const DefaultButton(
|
||||||
|
borderRadius: 8,
|
||||||
|
child: Text('Ok'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
); }
|
||||||
|
}
|
@ -7,8 +7,8 @@ import 'package:syncrow_web/pages/common/default_button.dart';
|
|||||||
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_bloc.dart';
|
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_event.dart';
|
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_event.dart';
|
||||||
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_state.dart';
|
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_state.dart';
|
||||||
|
import 'package:syncrow_web/pages/visitor_password/view/add_device_dialog.dart';
|
||||||
import 'package:syncrow_web/pages/visitor_password/view/repeat_widget.dart';
|
import 'package:syncrow_web/pages/visitor_password/view/repeat_widget.dart';
|
||||||
import 'package:syncrow_web/utils/snack_bar.dart';
|
|
||||||
import 'package:syncrow_web/utils/style.dart';
|
import 'package:syncrow_web/utils/style.dart';
|
||||||
|
|
||||||
class VisitorPasswordDialog extends StatelessWidget {
|
class VisitorPasswordDialog extends StatelessWidget {
|
||||||
@ -24,216 +24,242 @@ class VisitorPasswordDialog extends StatelessWidget {
|
|||||||
final visitorBloc = BlocProvider.of<VisitorPasswordBloc>(context);
|
final visitorBloc = BlocProvider.of<VisitorPasswordBloc>(context);
|
||||||
bool isRepeat = state is IsRepeatState ? state.repeat : visitorBloc.repeat;
|
bool isRepeat = state is IsRepeatState ? state.repeat : visitorBloc.repeat;
|
||||||
return AlertDialog(
|
return AlertDialog(
|
||||||
|
backgroundColor: Colors.white,
|
||||||
title: const Text('Create visitor password'),
|
title: const Text('Create visitor password'),
|
||||||
content: SingleChildScrollView(
|
content: SingleChildScrollView(
|
||||||
child: ListBody(
|
child: Padding(
|
||||||
children: <Widget>[
|
padding: const EdgeInsets.all(10.0),
|
||||||
Row(
|
child: ListBody(
|
||||||
children: [
|
children: <Widget>[
|
||||||
Expanded(
|
Container(
|
||||||
flex: 2,
|
child: Row(
|
||||||
child: CustomWebTextField(
|
|
||||||
controller: visitorBloc.userNameController,
|
|
||||||
isRequired: true,
|
|
||||||
textFieldName: 'User Name',
|
|
||||||
description: '',
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const Spacer(),
|
|
||||||
Expanded(
|
|
||||||
flex: 2,
|
|
||||||
child: CustomWebTextField(
|
|
||||||
controller: visitorBloc.emailController,
|
|
||||||
isRequired: true,
|
|
||||||
textFieldName: 'Email Address',
|
|
||||||
description: 'The password will be sent to the visitor’s email address.',
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
SizedBox(height: size.height * 0.02), // Add spacing
|
|
||||||
Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Row(
|
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Expanded(
|
||||||
'* ',
|
flex: 2,
|
||||||
style: Theme.of(context)
|
child: CustomWebTextField(
|
||||||
.textTheme
|
controller: visitorBloc.userNameController,
|
||||||
.bodyMedium!
|
isRequired: true,
|
||||||
.copyWith(color: Colors.red),
|
textFieldName: 'Name',
|
||||||
|
description: '',
|
||||||
|
),
|
||||||
),
|
),
|
||||||
const Text('Access Type'),
|
const Spacer(),
|
||||||
|
Expanded(
|
||||||
|
flex: 2,
|
||||||
|
child: CustomWebTextField(
|
||||||
|
controller: visitorBloc.emailController,
|
||||||
|
isRequired: true,
|
||||||
|
textFieldName: 'Email Address',
|
||||||
|
description: 'The password will be sent to the visitor’s email address.',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Spacer(),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
Row(
|
),
|
||||||
children: <Widget>[
|
SizedBox(height: 20,),
|
||||||
SizedBox(
|
Column(
|
||||||
width: size.width * 0.15,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
child: RadioListTile<String>(
|
children: [
|
||||||
title: const Text('Offline Password'),
|
Row(
|
||||||
value: 'Offline Password',
|
children: [
|
||||||
groupValue: (state is PasswordTypeSelected)
|
Text(
|
||||||
? state.selectedType
|
'* ',
|
||||||
: visitorBloc.accessTypeSelected,
|
style: Theme.of(context)
|
||||||
onChanged: (String? value) {
|
.textTheme
|
||||||
if (value != null) {
|
.bodyMedium!
|
||||||
context.read<VisitorPasswordBloc>().add(SelectPasswordType(value));
|
.copyWith(color: Colors.red),
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
),
|
const Text('Access Type'),
|
||||||
SizedBox(
|
],
|
||||||
width: size.width * 0.15,
|
),
|
||||||
child: RadioListTile<String>(
|
Row(
|
||||||
title: const Text('Online Password'),
|
children: <Widget>[
|
||||||
value: 'Online Password',
|
SizedBox(
|
||||||
groupValue: (state is PasswordTypeSelected)
|
width: size.width * 0.15,
|
||||||
? state.selectedType
|
child: RadioListTile<String>(
|
||||||
: visitorBloc.accessTypeSelected,
|
title: const Text('Offline Password'),
|
||||||
onChanged: (String? value) {
|
value: 'Offline Password',
|
||||||
if (value != null) {
|
groupValue: (state is PasswordTypeSelected)
|
||||||
context.read<VisitorPasswordBloc>().add(SelectPasswordType(value));
|
? state.selectedType
|
||||||
}
|
: visitorBloc.accessTypeSelected,
|
||||||
},
|
onChanged: (String? value) {
|
||||||
|
if (value != null) {
|
||||||
|
context.read<VisitorPasswordBloc>().add(SelectPasswordType(value));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
SizedBox(
|
||||||
SizedBox(
|
width: size.width * 0.15,
|
||||||
width: size.width * 0.15,
|
child: RadioListTile<String>(
|
||||||
child: RadioListTile<String>(
|
title: const Text('Online Password'),
|
||||||
title: const Text('Dynamic Password'),
|
value: 'Online Password',
|
||||||
value: 'Dynamic Password',
|
groupValue: (state is PasswordTypeSelected)
|
||||||
groupValue: (state is PasswordTypeSelected)
|
? state.selectedType
|
||||||
? state.selectedType
|
: visitorBloc.accessTypeSelected,
|
||||||
: visitorBloc.accessTypeSelected,
|
onChanged: (String? value) {
|
||||||
onChanged: (String? value) {
|
if (value != null) {
|
||||||
if (value != null) {
|
context.read<VisitorPasswordBloc>().add(SelectPasswordType(value));
|
||||||
context.read<VisitorPasswordBloc>().add(SelectPasswordType(value));
|
}
|
||||||
}
|
},
|
||||||
},
|
),
|
||||||
),
|
),
|
||||||
),
|
SizedBox(
|
||||||
],
|
width: size.width * 0.15,
|
||||||
),
|
child: RadioListTile<String>(
|
||||||
],
|
title: const Text('Dynamic Password'),
|
||||||
),
|
value: 'Dynamic Password',
|
||||||
visitorBloc.accessTypeSelected=='Dynamic Password' ?
|
groupValue: (state is PasswordTypeSelected)
|
||||||
SizedBox():
|
? state.selectedType
|
||||||
Column(
|
: visitorBloc.accessTypeSelected,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
onChanged: (String? value) {
|
||||||
children: [
|
if (value != null) {
|
||||||
Row(
|
context.read<VisitorPasswordBloc>().add(SelectPasswordType(value));
|
||||||
children: [
|
}
|
||||||
Text(
|
},
|
||||||
'* ',
|
),
|
||||||
style: Theme.of(context)
|
|
||||||
.textTheme
|
|
||||||
.bodyMedium!
|
|
||||||
.copyWith(color: Colors.red),
|
|
||||||
),
|
|
||||||
const Text('Usage Frequency'),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
Row(
|
|
||||||
children: <Widget>[
|
|
||||||
SizedBox(
|
|
||||||
width: 200,
|
|
||||||
child: RadioListTile<String>(
|
|
||||||
title: const Text('One-Time'),
|
|
||||||
value: 'One-Time',
|
|
||||||
groupValue: (state is UsageFrequencySelected)
|
|
||||||
? state.selectedFrequency
|
|
||||||
: visitorBloc.usageFrequencySelected,
|
|
||||||
onChanged: (String? value) {
|
|
||||||
if (value != null) {
|
|
||||||
context.read<VisitorPasswordBloc>().add(SelectUsageFrequency(value));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
SizedBox(
|
),
|
||||||
width: 200,
|
const Text('Only currently online devices can be selected. It is recommended to use when the device network is stable, and the system randomly generates a digital password'),
|
||||||
child: RadioListTile<String>(
|
SizedBox(height: 20,)
|
||||||
title: const Text('Periodic'),
|
],
|
||||||
value: 'Periodic',
|
),
|
||||||
groupValue: (state is UsageFrequencySelected)
|
visitorBloc.accessTypeSelected=='Dynamic Password' ?
|
||||||
? state.selectedFrequency
|
SizedBox():
|
||||||
: visitorBloc.usageFrequencySelected,
|
Column(
|
||||||
onChanged: (String? value) {
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
if (value != null) {
|
children: [
|
||||||
context.read<VisitorPasswordBloc>().add(SelectUsageFrequency(value));
|
Row(
|
||||||
}
|
children: [
|
||||||
},
|
Text(
|
||||||
|
'* ',
|
||||||
|
style: Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.bodyMedium!
|
||||||
|
.copyWith(color: Colors.red),
|
||||||
),
|
),
|
||||||
),
|
const Text('Usage Frequency'),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
],
|
Row(
|
||||||
),
|
children: <Widget>[
|
||||||
visitorBloc.accessTypeSelected=='Dynamic Password' ?
|
SizedBox(
|
||||||
SizedBox():
|
width: 200,
|
||||||
|
child: RadioListTile<String>(
|
||||||
|
title: const Text('One-Time'),
|
||||||
|
value: 'One-Time',
|
||||||
|
groupValue: (state is UsageFrequencySelected)
|
||||||
|
? state.selectedFrequency
|
||||||
|
: visitorBloc.usageFrequencySelected,
|
||||||
|
onChanged: (String? value) {
|
||||||
|
if (value != null) {
|
||||||
|
context.read<VisitorPasswordBloc>().add(SelectUsageFrequency(value));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
width: 200,
|
||||||
|
child: RadioListTile<String>(
|
||||||
|
title: const Text('Periodic'),
|
||||||
|
value: 'Periodic',
|
||||||
|
groupValue: (state is UsageFrequencySelected)
|
||||||
|
? state.selectedFrequency
|
||||||
|
: visitorBloc.usageFrequencySelected,
|
||||||
|
onChanged: (String? value) {
|
||||||
|
if (value != null) {
|
||||||
|
context.read<VisitorPasswordBloc>().add(SelectUsageFrequency(value));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
|
||||||
DateTimeWebWidget(
|
Text('Within the validity period, each device can be unlocked only once.')
|
||||||
isRequired: true,
|
],
|
||||||
title: 'Access Period',
|
),
|
||||||
size: size,
|
|
||||||
endTime: () {
|
const SizedBox(height: 20,),
|
||||||
visitorBloc.add(SelectTimeVisitorPassword(context: context, isStart: false));
|
|
||||||
},
|
visitorBloc.accessTypeSelected=='Dynamic Password' ?
|
||||||
startTime: () {
|
SizedBox():
|
||||||
visitorBloc.add(SelectTimeVisitorPassword(context: context, isStart: true));
|
DateTimeWebWidget(
|
||||||
},
|
isRequired: true,
|
||||||
firstString: visitorBloc.startTime,
|
title: 'Access Period',
|
||||||
secondString: visitorBloc.endTime,
|
size: size,
|
||||||
),
|
endTime: () {
|
||||||
Column(
|
visitorBloc.add(SelectTimeVisitorPassword(context: context, isStart: false));
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
},
|
||||||
children: [
|
startTime: () {
|
||||||
Row(
|
visitorBloc.add(SelectTimeVisitorPassword(context: context, isStart: true));
|
||||||
children: [
|
},
|
||||||
Text(
|
firstString: visitorBloc.startTime,
|
||||||
'* ',
|
secondString: visitorBloc.endTime,
|
||||||
style: Theme.of(context)
|
),
|
||||||
.textTheme
|
const SizedBox(height: 20,),
|
||||||
.bodyMedium!
|
|
||||||
.copyWith(color: Colors.red),
|
Column(
|
||||||
),
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
const Text('Access Devices'),
|
children: [
|
||||||
],
|
Row(
|
||||||
),
|
children: [
|
||||||
const Text('Within the validity period, each device can be unlocked only once.'),
|
Text(
|
||||||
visitorBloc.usageFrequencySelected=='Periodic'&&visitorBloc.accessTypeSelected=='Offline Password'?
|
'* ',
|
||||||
SizedBox(
|
style: Theme.of(context)
|
||||||
width: 100,
|
.textTheme
|
||||||
child: ListTile(
|
.bodyMedium!
|
||||||
contentPadding: EdgeInsets.zero,
|
.copyWith(color: Colors.red),
|
||||||
leading: const Text('Repeat'),
|
),
|
||||||
trailing: Transform.scale(
|
const Text('Access Devices'),
|
||||||
scale: .8,
|
],
|
||||||
child: CupertinoSwitch(
|
),
|
||||||
value: visitorBloc.repeat,
|
const Text('Within the validity period, each device can be unlocked only once.'),
|
||||||
onChanged: (value) {
|
const SizedBox(height: 20,),
|
||||||
visitorBloc.add(ToggleRepeatEvent());
|
visitorBloc.usageFrequencySelected=='Periodic'&&visitorBloc.accessTypeSelected=='Offline Password'?
|
||||||
},
|
SizedBox(
|
||||||
applyTheme: true,
|
width: 100,
|
||||||
|
child: ListTile(
|
||||||
|
contentPadding: EdgeInsets.zero,
|
||||||
|
leading: const Text('Repeat'),
|
||||||
|
trailing: Transform.scale(
|
||||||
|
scale: .8,
|
||||||
|
child: CupertinoSwitch(
|
||||||
|
value: visitorBloc.repeat,
|
||||||
|
onChanged: (value) {
|
||||||
|
visitorBloc.add(ToggleRepeatEvent());
|
||||||
|
},
|
||||||
|
applyTheme: true,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
):const SizedBox(),
|
||||||
):const SizedBox(),
|
isRepeat ? const RepeatWidget() : const SizedBox(),
|
||||||
isRepeat ? const RepeatWidget() : const SizedBox(),
|
Container(
|
||||||
Container(
|
decoration: containerDecoration,
|
||||||
decoration: containerDecoration,
|
width: size.width * 0.1,
|
||||||
width: size.width * 0.2,
|
child: DefaultButton(
|
||||||
child: const DefaultButton(
|
onPressed: () {
|
||||||
borderRadius: 8,
|
showDialog(
|
||||||
child: Text('+ Add Device'),
|
context: context,
|
||||||
),
|
barrierDismissible: false,
|
||||||
),
|
builder: (BuildContext context) {
|
||||||
],
|
return const AddDeviceDialog();
|
||||||
),
|
|
||||||
|
|
||||||
],
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
borderRadius: 8,
|
||||||
|
child: Text('+ Add Device'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
actionsAlignment: MainAxisAlignment.center,
|
actionsAlignment: MainAxisAlignment.center,
|
||||||
|
@ -6,6 +6,8 @@ import 'package:syncrow_web/pages/access_management/model/password_model.dart';
|
|||||||
import 'package:syncrow_web/services/api/http_service.dart';
|
import 'package:syncrow_web/services/api/http_service.dart';
|
||||||
import 'package:syncrow_web/utils/constants/api_const.dart';
|
import 'package:syncrow_web/utils/constants/api_const.dart';
|
||||||
|
|
||||||
|
import '../pages/visitor_password/model/device_model.dart';
|
||||||
|
|
||||||
class AccessMangApi{
|
class AccessMangApi{
|
||||||
|
|
||||||
|
|
||||||
@ -31,6 +33,27 @@ class AccessMangApi{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future fetchDevices() async {
|
||||||
|
try {
|
||||||
|
final response = await HTTPService().get(
|
||||||
|
path: ApiEndpoints.getDevices,
|
||||||
|
showServerMessage: true,
|
||||||
|
expectedResponseModel: (json) {
|
||||||
|
List<dynamic> jsonData = json;
|
||||||
|
print('fetchDevices List: $json');
|
||||||
|
List<DeviceModel> passwordList = jsonData.map((jsonItem) {
|
||||||
|
return DeviceModel.fromJson(jsonItem);
|
||||||
|
}).toList();
|
||||||
|
return passwordList;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
return response;
|
||||||
|
} catch (e) {
|
||||||
|
debugPrint('Error fetching $e');
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -46,8 +46,10 @@ class AuthenticationAPI {
|
|||||||
},
|
},
|
||||||
showServerMessage: true,
|
showServerMessage: true,
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
|
print('object==$json');
|
||||||
return 30;
|
return 30;
|
||||||
}
|
}
|
||||||
|
|
||||||
);
|
);
|
||||||
return 30;
|
return 30;
|
||||||
} on DioException catch (e) {
|
} on DioException catch (e) {
|
||||||
|
@ -18,6 +18,7 @@ abstract class ColorsManager {
|
|||||||
static const Color dozeColor = Color(0xFFFEC258);
|
static const Color dozeColor = Color(0xFFFEC258);
|
||||||
static const Color relaxColor = Color(0xFFFBD288);
|
static const Color relaxColor = Color(0xFFFBD288);
|
||||||
static const Color readingColor = Color(0xFFF7D69C);
|
static const Color readingColor = Color(0xFFF7D69C);
|
||||||
|
static const Color worningColor = Color(0xFFFFF3C8);
|
||||||
static const Color energizingColor = Color(0xFFEDEDED);
|
static const Color energizingColor = Color(0xFFEDEDED);
|
||||||
static const Color dividerColor = Color(0xFFEBEBEB);
|
static const Color dividerColor = Color(0xFFEBEBEB);
|
||||||
static const Color slidingBlueColor = Color(0x99023DFE);
|
static const Color slidingBlueColor = Color(0x99023DFE);
|
||||||
|
@ -10,5 +10,6 @@ abstract class ApiEndpoints {
|
|||||||
static const String verifyOtp = '$baseUrl/authentication/user/verify-otp';
|
static const String verifyOtp = '$baseUrl/authentication/user/verify-otp';
|
||||||
static const String getRegion = '$baseUrl/region';
|
static const String getRegion = '$baseUrl/region';
|
||||||
static const String visitorPassword = '$baseUrl/visitor-password';
|
static const String visitorPassword = '$baseUrl/visitor-password';
|
||||||
|
static const String getDevices = '$baseUrl/visitor-password/devices';
|
||||||
static const String getUser = '$baseUrl/user/{userUuid}';
|
static const String getUser = '$baseUrl/user/{userUuid}';
|
||||||
}
|
}
|
||||||
|
@ -24,4 +24,5 @@ class Assets {
|
|||||||
static const String integrationsIcon = "assets/images/Integrations_icon.svg";
|
static const String integrationsIcon = "assets/images/Integrations_icon.svg";
|
||||||
static const String assetIcon = "assets/images/asset_icon.svg";
|
static const String assetIcon = "assets/images/asset_icon.svg";
|
||||||
static const String calendarIcon = "assets/images/calendar_icon.svg";
|
static const String calendarIcon = "assets/images/calendar_icon.svg";
|
||||||
|
static const String deviceNoteIcon = "assets/images/device_note.svg";
|
||||||
}
|
}
|
||||||
|
44
lib/utils/constants/const.dart
Normal file
44
lib/utils/constants/const.dart
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
enum AccessType {
|
||||||
|
onlineOnetime,
|
||||||
|
onlineMultiple,
|
||||||
|
offlineOnetime,
|
||||||
|
offlineMultiple,
|
||||||
|
}
|
||||||
|
|
||||||
|
extension AccessTypeExtension on AccessType {
|
||||||
|
String get value {
|
||||||
|
switch (this) {
|
||||||
|
case AccessType.onlineOnetime:
|
||||||
|
return "Online Password";
|
||||||
|
case AccessType.onlineMultiple:
|
||||||
|
return "online Multiple Password";
|
||||||
|
case AccessType.offlineOnetime:
|
||||||
|
return "Offline Onetime Password";
|
||||||
|
case AccessType.offlineMultiple:
|
||||||
|
return "Offline Multiple Password";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static AccessType fromString(String value) {
|
||||||
|
switch (value) {
|
||||||
|
case "ONLINE_ONETIME":
|
||||||
|
return AccessType.onlineOnetime;
|
||||||
|
case "ONLINE_MULTIPLE":
|
||||||
|
return AccessType.onlineMultiple;
|
||||||
|
case "OFFLINE_ONETIME":
|
||||||
|
return AccessType.offlineOnetime;
|
||||||
|
case "OFFLINE_MULTIPLE":
|
||||||
|
return AccessType.offlineMultiple;
|
||||||
|
default:
|
||||||
|
throw ArgumentError("Invalid access type: $value");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -6,7 +6,7 @@ InputDecoration? textBoxDecoration({bool suffixIcon = false}) => InputDecoration
|
|||||||
suffixIcon:suffixIcon? const Icon(Icons.search):null,
|
suffixIcon:suffixIcon? const Icon(Icons.search):null,
|
||||||
hintText: 'Search',
|
hintText: 'Search',
|
||||||
filled: true, // Enable background filling
|
filled: true, // Enable background filling
|
||||||
fillColor: Colors.grey.shade200, // Set the background color
|
fillColor: const Color(0xffF5F6F7), // Set the background color
|
||||||
border: OutlineInputBorder(
|
border: OutlineInputBorder(
|
||||||
borderRadius: BorderRadius.circular(8), // Add border radius
|
borderRadius: BorderRadius.circular(8), // Add border radius
|
||||||
borderSide: BorderSide.none, // Remove the underline
|
borderSide: BorderSide.none, // Remove the underline
|
||||||
@ -30,16 +30,17 @@ InputDecoration? textBoxDecoration({bool suffixIcon = false}) => InputDecoration
|
|||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
BoxDecoration containerDecoration = BoxDecoration(
|
||||||
Decoration containerDecoration = BoxDecoration(
|
|
||||||
boxShadow: [
|
boxShadow: [
|
||||||
BoxShadow(
|
BoxShadow(
|
||||||
color: Colors.grey.withOpacity(0.5),
|
color: Colors.grey.withOpacity(0.5),
|
||||||
spreadRadius: 5,
|
spreadRadius: 5,
|
||||||
blurRadius: 8,
|
blurRadius: 8,
|
||||||
offset: Offset(0,
|
offset: const Offset(0,
|
||||||
3), // changes position of shadow
|
3), // changes position of shadow
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
color: ColorsManager.boxColor,
|
color: ColorsManager.boxColor,
|
||||||
borderRadius: BorderRadius.all(Radius.circular(10)));
|
borderRadius: const BorderRadius.all(Radius.circular(10)));
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user