swipe history added
parent
f6e2ef676c
commit
c5f863b05c
@ -0,0 +1,164 @@
|
||||
import 'package:flutter/animation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:test_sa/extensions/int_extensions.dart';
|
||||
import 'package:test_sa/new_views/app_style/app_color.dart';
|
||||
|
||||
class CircularAnimationWithProgressIndicator extends StatefulWidget {
|
||||
Widget child;
|
||||
CircularAnimationWithProgressIndicator({Key key, this.child}) : super(key: key);
|
||||
@override
|
||||
_CircularAnimationWithProgressIndicatorState createState() =>
|
||||
_CircularAnimationWithProgressIndicatorState();
|
||||
}
|
||||
|
||||
class _CircularAnimationWithProgressIndicatorState
|
||||
extends State<CircularAnimationWithProgressIndicator>
|
||||
with SingleTickerProviderStateMixin {
|
||||
AnimationController _controller;
|
||||
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
// Animation controller for progress indicator
|
||||
_controller = AnimationController(
|
||||
vsync: this,
|
||||
duration: const Duration(seconds: 40), // Duration of one full rotation
|
||||
)..repeat(); // Repeat animation continuously
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_controller.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Center(
|
||||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
// Animated CircularProgressIndicator
|
||||
AnimatedBuilder(
|
||||
animation: _controller,
|
||||
builder: (context, child) {
|
||||
return Transform.rotate(
|
||||
angle: _controller.value * 2 * 3.1416, // Full rotation
|
||||
child: child,
|
||||
);
|
||||
},
|
||||
child: SizedBox(
|
||||
width: 100.toScreenHeight,
|
||||
height: 100.toScreenWidth,
|
||||
child: const CircularProgressIndicator(
|
||||
strokeWidth: 3.0,
|
||||
backgroundColor: AppColor.primary30,
|
||||
|
||||
value: null, // Infinite animation
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
// Static container in the center
|
||||
widget.child?? const SizedBox(),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class CircularAnimatedContainer extends StatefulWidget {
|
||||
Widget child;
|
||||
|
||||
CircularAnimatedContainer({Key key, @required this.child}) : super(key: key);
|
||||
@override
|
||||
_CircularAnimatedContainerState createState() => _CircularAnimatedContainerState();
|
||||
}
|
||||
|
||||
class _CircularAnimatedContainerState extends State<CircularAnimatedContainer>
|
||||
with SingleTickerProviderStateMixin {
|
||||
AnimationController _controller;
|
||||
Animation<double> _animation;
|
||||
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_controller = AnimationController(
|
||||
duration: const Duration(seconds: 2),
|
||||
vsync: this,
|
||||
)..repeat();
|
||||
|
||||
_animation = CurvedAnimation(
|
||||
parent: _controller,
|
||||
curve: Curves.easeInOut, // Applies the ease-in-out effect
|
||||
);
|
||||
// Repeats animation
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_controller.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Center(
|
||||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
widget.child,
|
||||
AnimatedBuilder(
|
||||
animation: _animation,
|
||||
builder: (context, child) {
|
||||
return CustomPaint(
|
||||
painter: CircularProgressPainter(
|
||||
progress: _animation.value),
|
||||
size: Size(100.toScreenHeight, 100.toScreenWidth),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class CircularProgressPainter extends CustomPainter {
|
||||
final double progress;
|
||||
|
||||
CircularProgressPainter({@required this.progress});
|
||||
@override
|
||||
void paint(Canvas canvas, Size size) {
|
||||
|
||||
|
||||
final Paint paint = Paint()
|
||||
..color = AppColor.primary80
|
||||
..style = PaintingStyle.stroke
|
||||
..strokeWidth = 3
|
||||
..strokeCap = StrokeCap.round;
|
||||
|
||||
final center = Offset(size.width / 2, size.height / 2);
|
||||
final radius = size.width / 2.05;
|
||||
final double startAngle = 2.5 * 3.141592653589793 * progress;
|
||||
final double sweepAngle = 2 * 3.141592653589793 * progress;
|
||||
// const double startAngle = -90 * (3.141592653589793 / 180);
|
||||
// final double sweepAngle = 2.05 * 3.141592653589793 * progress;
|
||||
|
||||
canvas.drawArc(
|
||||
Rect.fromCircle(center: center, radius: radius),
|
||||
startAngle,
|
||||
sweepAngle,
|
||||
false,
|
||||
paint,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
bool shouldRepaint(covariant CustomPainter oldDelegate) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,47 @@
|
||||
class SwipeHistory {
|
||||
final int id;
|
||||
final String swipeTypeName;
|
||||
final String userName;
|
||||
final String siteName;
|
||||
final String pointName;
|
||||
final String swipeTime;
|
||||
final bool isSuccess;
|
||||
final String errorMessage;
|
||||
|
||||
SwipeHistory({
|
||||
this.id,
|
||||
this.swipeTypeName,
|
||||
this.userName,
|
||||
this.siteName,
|
||||
this.pointName,
|
||||
this.swipeTime,
|
||||
this.isSuccess,
|
||||
this.errorMessage,
|
||||
});
|
||||
|
||||
factory SwipeHistory.fromJson(Map<String, dynamic> json) {
|
||||
return SwipeHistory(
|
||||
id: json['id'],
|
||||
swipeTypeName: json['swipeTypeName'],
|
||||
userName: json['userName'],
|
||||
siteName: json['siteName'],
|
||||
pointName: json['pointName'],
|
||||
swipeTime: json['swipeTime']!=null? DateTime.parse(json['swipeTime']).toIso8601String():'',
|
||||
isSuccess: json['isSuccess'],
|
||||
errorMessage: json['errorMessage'],
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'id': id,
|
||||
'swipeTypeName': swipeTypeName,
|
||||
'userName': userName,
|
||||
'siteName': siteName,
|
||||
'pointName': pointName,
|
||||
'swipeTime': swipeTime,
|
||||
'isSuccess': isSuccess,
|
||||
'errorMessage': errorMessage,
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,189 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:test_sa/controllers/providers/api/user_provider.dart';
|
||||
import 'package:test_sa/extensions/context_extension.dart';
|
||||
import 'package:test_sa/extensions/int_extensions.dart';
|
||||
import 'package:test_sa/extensions/string_extensions.dart';
|
||||
import 'package:test_sa/extensions/text_extensions.dart';
|
||||
import 'package:test_sa/extensions/widget_extensions.dart';
|
||||
import 'package:test_sa/new_views/app_style/app_color.dart';
|
||||
import 'package:test_sa/new_views/common_widgets/app_filled_button.dart';
|
||||
import 'package:test_sa/new_views/common_widgets/default_app_bar.dart';
|
||||
import 'package:test_sa/views/widgets/date_and_time/date_picker.dart';
|
||||
import 'package:test_sa/views/widgets/loaders/lazy_loading.dart';
|
||||
import 'package:test_sa/views/widgets/loaders/no_item_found.dart';
|
||||
|
||||
|
||||
import 'models/swipe_transaction_history.dart';
|
||||
|
||||
class SwipeHistoryView extends StatefulWidget {
|
||||
static const routeName = '/swipe_list_view';
|
||||
|
||||
const SwipeHistoryView({Key key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<SwipeHistoryView> createState() => _SwipeHistoryViewState();
|
||||
}
|
||||
|
||||
|
||||
class _SwipeHistoryViewState extends State<SwipeHistoryView> {
|
||||
DateTime dateFrom = DateTime.now();
|
||||
DateTime dateTo = DateTime.now();
|
||||
UserProvider _userProvider;
|
||||
@override
|
||||
void initState() {
|
||||
getSwipeHistory();
|
||||
super.initState();
|
||||
}
|
||||
|
||||
void getSwipeHistory () {
|
||||
_userProvider = Provider.of<UserProvider>(context,listen:false);
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
||||
await _userProvider.getSwipeTransactionHistory(userId: _userProvider.user.userID,dateFrom: dateFrom,dateTo: dateTo);
|
||||
});
|
||||
}
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: const DefaultAppBar(title: 'Swipe History',),
|
||||
body: Column(
|
||||
crossAxisAlignment:CrossAxisAlignment.start,
|
||||
children: [
|
||||
|
||||
8.height,
|
||||
Row(
|
||||
children: [
|
||||
ADatePicker(
|
||||
label: context.translation.from,
|
||||
date: dateFrom,
|
||||
from: DateTime(DateTime.now().year - 5, DateTime.now().month, DateTime.now().day),
|
||||
formatDateWithTime: true,
|
||||
onDatePicker: (selectedDate) {
|
||||
if (selectedDate != null) {
|
||||
showTimePicker(
|
||||
context: context,
|
||||
initialTime: TimeOfDay.now(),
|
||||
).then((selectedTime) {
|
||||
// Handle the selected date and time here.
|
||||
if (selectedTime != null) {
|
||||
DateTime selectedDateTime = DateTime(
|
||||
selectedDate.year,
|
||||
selectedDate.month,
|
||||
selectedDate.day,
|
||||
selectedTime.hour,
|
||||
selectedTime.minute,
|
||||
);
|
||||
if (selectedDateTime != null) {
|
||||
setState(() {
|
||||
dateFrom = selectedDateTime;
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
).expanded,
|
||||
8.width,
|
||||
ADatePicker(
|
||||
label: context.translation.to,
|
||||
date: dateTo,
|
||||
from: DateTime(DateTime.now().year - 5, DateTime.now().month, DateTime.now().day),
|
||||
formatDateWithTime: true,
|
||||
onDatePicker: (selectedDate) {
|
||||
if (selectedDate != null) {
|
||||
showTimePicker(
|
||||
context: context,
|
||||
initialTime: TimeOfDay.now(),
|
||||
).then((selectedTime) {
|
||||
// Handle the selected date and time here.
|
||||
if (selectedTime != null) {
|
||||
DateTime selectedDateTime = DateTime(
|
||||
selectedDate.year,
|
||||
selectedDate.month,
|
||||
selectedDate.day,
|
||||
selectedTime.hour,
|
||||
selectedTime.minute,
|
||||
);
|
||||
if (selectedDateTime != null) {
|
||||
setState(() {
|
||||
dateTo = selectedDateTime;
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
).expanded,
|
||||
],
|
||||
),
|
||||
12.height,
|
||||
|
||||
AppFilledButton(label: context.translation.search, maxWidth: false, onPressed: getSwipeHistory),
|
||||
8.height,
|
||||
Divider(thickness: 2,),
|
||||
|
||||
Consumer<UserProvider>(
|
||||
builder: (context, snapshot,child) {
|
||||
return SwipeHistoryList(snapshot.swipeHistory ?? [], snapshot.isLoading).expanded;
|
||||
}
|
||||
),
|
||||
|
||||
|
||||
],
|
||||
).paddingAll(20),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
class SwipeHistoryList extends StatelessWidget {
|
||||
List<SwipeHistory> list;
|
||||
bool isLoading;
|
||||
|
||||
SwipeHistoryList(this.list, this.isLoading, {Key key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return (list.isEmpty && !isLoading)
|
||||
? NoItemFound(message: context.translation.noDataFound)
|
||||
: ListView.separated(
|
||||
padding: EdgeInsets.only(top: 12.toScreenHeight),
|
||||
itemBuilder: (cxt, index) {
|
||||
if (isLoading) return const SizedBox().toRequestShimmer(cxt, isLoading);
|
||||
return SwipeHistoryCard(list[index]);
|
||||
},
|
||||
separatorBuilder: (cxt, index) => 12.height,
|
||||
itemCount: isLoading ? 6 : list.length);
|
||||
}
|
||||
}
|
||||
class SwipeHistoryCard extends StatelessWidget {
|
||||
final SwipeHistory swipeHistory;
|
||||
final bool showShadow;
|
||||
const SwipeHistoryCard(this.swipeHistory, {Key key, this.showShadow = true}) : super(key: key);
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(swipeHistory.swipeTime.toServiceRequestDetailsFormat, textAlign: TextAlign.end, style: AppTextStyles.tinyFont.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral50)),
|
||||
],
|
||||
),
|
||||
8.height,
|
||||
'${context.translation.swipeTypeName}: ${swipeHistory.swipeTypeName?.cleanupWhitespace?.capitalizeFirstOfEach}'.bodyText(context),
|
||||
'${context.translation.userName}: ${swipeHistory.userName}'.bodyText(context),
|
||||
'${context.translation.siteName}: ${swipeHistory.siteName}'.bodyText(context),
|
||||
'${context.translation.pointName}: ${swipeHistory.pointName}'.bodyText(context),
|
||||
8.height,
|
||||
],
|
||||
).toShadowContainer(context, showShadow: showShadow);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue