|
|
|
@ -618,26 +618,9 @@ class SwipeGeneralUtils {
|
|
|
|
),
|
|
|
|
),
|
|
|
|
backgroundColor: AppColor.bottomSheetColor(context),
|
|
|
|
backgroundColor: AppColor.bottomSheetColor(context),
|
|
|
|
clipBehavior: Clip.antiAliasWithSaveLayer,
|
|
|
|
clipBehavior: Clip.antiAliasWithSaveLayer,
|
|
|
|
builder: (BuildContext context) => Padding(
|
|
|
|
builder: (BuildContext context) => _SwipeTypeBottomSheetContent(
|
|
|
|
padding: EdgeInsets.only(
|
|
|
|
userProvider: _userProvider,
|
|
|
|
bottom: MediaQuery.of(context).viewInsets.bottom + MediaQuery.of(context).padding.bottom,
|
|
|
|
isNfcSupported: isNfcSupported,
|
|
|
|
),
|
|
|
|
|
|
|
|
child: Column(
|
|
|
|
|
|
|
|
mainAxisSize: MainAxisSize.min,
|
|
|
|
|
|
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
|
|
|
|
|
|
children: [
|
|
|
|
|
|
|
|
context.translation.markAttendance.heading4(context).custom(color: context.isDark ? AppColor.white50 : AppColor.white936),
|
|
|
|
|
|
|
|
8.height,
|
|
|
|
|
|
|
|
context.translation.selectMethodToMarkAttendance.bodyText2(context).custom(color: AppColor.lightTextColor(context)),
|
|
|
|
|
|
|
|
12.height,
|
|
|
|
|
|
|
|
GridView(
|
|
|
|
|
|
|
|
padding: const EdgeInsets.all(0),
|
|
|
|
|
|
|
|
shrinkWrap: true,
|
|
|
|
|
|
|
|
physics: const NeverScrollableScrollPhysics(),
|
|
|
|
|
|
|
|
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3, childAspectRatio: 1, crossAxisSpacing: 12, mainAxisSpacing: 12),
|
|
|
|
|
|
|
|
children: availableAttendanceMethodList(context: context, userProvider: _userProvider, isNfcSupported: isNfcSupported)),
|
|
|
|
|
|
|
|
],
|
|
|
|
|
|
|
|
).paddingAll(16),
|
|
|
|
|
|
|
|
),
|
|
|
|
),
|
|
|
|
);
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -764,3 +747,167 @@ class SwipeGeneralUtils {
|
|
|
|
return await WiFiForIoTPlugin.disconnect();
|
|
|
|
return await WiFiForIoTPlugin.disconnect();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class _SwipeTypeBottomSheetContent extends StatefulWidget {
|
|
|
|
|
|
|
|
final UserProvider userProvider;
|
|
|
|
|
|
|
|
final bool isNfcSupported;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const _SwipeTypeBottomSheetContent({
|
|
|
|
|
|
|
|
required this.userProvider,
|
|
|
|
|
|
|
|
required this.isNfcSupported,
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@override
|
|
|
|
|
|
|
|
State<_SwipeTypeBottomSheetContent> createState() => _SwipeTypeBottomSheetContentState();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class _SwipeTypeBottomSheetContentState extends State<_SwipeTypeBottomSheetContent> with SingleTickerProviderStateMixin {
|
|
|
|
|
|
|
|
late AnimationController _animationController;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@override
|
|
|
|
|
|
|
|
void initState() {
|
|
|
|
|
|
|
|
super.initState();
|
|
|
|
|
|
|
|
_animationController = AnimationController(
|
|
|
|
|
|
|
|
duration: const Duration(milliseconds: 1200),
|
|
|
|
|
|
|
|
vsync: this,
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
_animationController.forward();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@override
|
|
|
|
|
|
|
|
void dispose() {
|
|
|
|
|
|
|
|
_animationController.dispose();
|
|
|
|
|
|
|
|
super.dispose();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
List<_SwipeTypeItem> _getAvailableSwipeMethods() {
|
|
|
|
|
|
|
|
List<_SwipeTypeItem> availableMethods = [];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (widget.userProvider.user!.enableNFC!) {
|
|
|
|
|
|
|
|
availableMethods.add(_SwipeTypeItem(
|
|
|
|
|
|
|
|
type: SwipeTypeEnum.NFC,
|
|
|
|
|
|
|
|
icon: 'nfc_icon',
|
|
|
|
|
|
|
|
isEnabled: widget.isNfcSupported,
|
|
|
|
|
|
|
|
));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (widget.userProvider.user!.enableQR!) {
|
|
|
|
|
|
|
|
availableMethods.add(_SwipeTypeItem(
|
|
|
|
|
|
|
|
type: SwipeTypeEnum.QR,
|
|
|
|
|
|
|
|
icon: 'qr',
|
|
|
|
|
|
|
|
isEnabled: widget.userProvider.user!.enableQR!,
|
|
|
|
|
|
|
|
));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (kDebugMode) {
|
|
|
|
|
|
|
|
widget.userProvider.user!.enableWifi = true;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (widget.userProvider.user!.enableWifi!) {
|
|
|
|
|
|
|
|
availableMethods.add(_SwipeTypeItem(
|
|
|
|
|
|
|
|
type: SwipeTypeEnum.Wifi,
|
|
|
|
|
|
|
|
icon: 'wifi_icon',
|
|
|
|
|
|
|
|
isEnabled: widget.userProvider.user!.enableWifi!,
|
|
|
|
|
|
|
|
));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return availableMethods;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@override
|
|
|
|
|
|
|
|
Widget build(BuildContext context) {
|
|
|
|
|
|
|
|
final availableMethods = _getAvailableSwipeMethods();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return Padding(
|
|
|
|
|
|
|
|
padding: EdgeInsets.only(
|
|
|
|
|
|
|
|
bottom: MediaQuery.of(context).viewInsets.bottom + MediaQuery.of(context).padding.bottom,
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
child: Column(
|
|
|
|
|
|
|
|
mainAxisSize: MainAxisSize.min,
|
|
|
|
|
|
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
|
|
|
|
|
|
children: [
|
|
|
|
|
|
|
|
context.translation.markAttendance.heading5(context).custom(color: AppColor.headingTextColor(context)),
|
|
|
|
|
|
|
|
8.height,
|
|
|
|
|
|
|
|
context.translation.selectMethodToMarkAttendance.bodyText2(context).custom(color: AppColor.lightTextColor(context)),
|
|
|
|
|
|
|
|
12.height,
|
|
|
|
|
|
|
|
GridView.builder(
|
|
|
|
|
|
|
|
padding: const EdgeInsets.all(0),
|
|
|
|
|
|
|
|
shrinkWrap: true,
|
|
|
|
|
|
|
|
physics: const NeverScrollableScrollPhysics(),
|
|
|
|
|
|
|
|
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
|
|
|
|
|
|
|
|
crossAxisCount: 3,
|
|
|
|
|
|
|
|
childAspectRatio: 1,
|
|
|
|
|
|
|
|
crossAxisSpacing: 12,
|
|
|
|
|
|
|
|
mainAxisSpacing: 12,
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
itemCount: availableMethods.length,
|
|
|
|
|
|
|
|
itemBuilder: (context, index) {
|
|
|
|
|
|
|
|
// Calculate staggered animation delay
|
|
|
|
|
|
|
|
final delay = index * 0.08;
|
|
|
|
|
|
|
|
final animation = Tween<double>(begin: 0.0, end: 1.0).animate(
|
|
|
|
|
|
|
|
CurvedAnimation(
|
|
|
|
|
|
|
|
parent: _animationController,
|
|
|
|
|
|
|
|
curve: Interval(
|
|
|
|
|
|
|
|
delay.clamp(0.0, 0.8),
|
|
|
|
|
|
|
|
(delay + 0.3).clamp(0.0, 1.0),
|
|
|
|
|
|
|
|
curve: Curves.easeOut,
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
final slideAnimation = Tween<Offset>(
|
|
|
|
|
|
|
|
begin: const Offset(0.0, 0.3),
|
|
|
|
|
|
|
|
end: Offset.zero,
|
|
|
|
|
|
|
|
).animate(
|
|
|
|
|
|
|
|
CurvedAnimation(
|
|
|
|
|
|
|
|
parent: _animationController,
|
|
|
|
|
|
|
|
curve: Interval(
|
|
|
|
|
|
|
|
delay.clamp(0.0, 0.8),
|
|
|
|
|
|
|
|
(delay + 0.3).clamp(0.0, 1.0),
|
|
|
|
|
|
|
|
curve: Curves.easeOutCubic,
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
final item = availableMethods[index];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return FadeTransition(
|
|
|
|
|
|
|
|
opacity: animation,
|
|
|
|
|
|
|
|
child: SlideTransition(
|
|
|
|
|
|
|
|
position: slideAnimation,
|
|
|
|
|
|
|
|
child: SwipeGeneralUtils.instance.attendanceTypeCard(
|
|
|
|
|
|
|
|
item.type.name,
|
|
|
|
|
|
|
|
item.icon,
|
|
|
|
|
|
|
|
item.isEnabled,
|
|
|
|
|
|
|
|
() {
|
|
|
|
|
|
|
|
Navigator.pop(context);
|
|
|
|
|
|
|
|
SwipeGeneralUtils.instance.handleSwipe(
|
|
|
|
|
|
|
|
swipeType: item.type,
|
|
|
|
|
|
|
|
isEnable: item.isEnabled,
|
|
|
|
|
|
|
|
context: navigatorKey.currentState!.overlay!.context,
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
context,
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
],
|
|
|
|
|
|
|
|
).paddingAll(16),
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class _SwipeTypeItem {
|
|
|
|
|
|
|
|
final SwipeTypeEnum type;
|
|
|
|
|
|
|
|
final String icon;
|
|
|
|
|
|
|
|
final bool isEnabled;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
_SwipeTypeItem({
|
|
|
|
|
|
|
|
required this.type,
|
|
|
|
|
|
|
|
required this.icon,
|
|
|
|
|
|
|
|
required this.isEnabled,
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|