Velar/Frontend/lib/main_pages/HomePage/Components/Voice/confirm.dart

422 lines
15 KiB
Dart

// ignore_for_file: use_build_context_synchronously, deprecated_member_use
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:http/http.dart' as http;
import 'package:monarch/other_pages/reponsive.dart';
import 'package:monarch/other_pages/colors.dart';
import 'package:monarch/other_pages/enviroment.dart';
import 'package:shared_preferences/shared_preferences.dart';
class ConfirmTransactionPage extends StatefulWidget {
final Map<String, dynamic> data;
const ConfirmTransactionPage({super.key, required this.data});
@override
State<ConfirmTransactionPage> createState() => _ConfirmTransactionPageState();
}
class _ConfirmTransactionPageState extends State<ConfirmTransactionPage>
with SingleTickerProviderStateMixin {
late AnimationController _controller;
late Animation<Offset> _slideAnimation;
late Animation<double> _fadeAnimation;
@override
void initState() {
super.initState();
_controller = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 600),
);
_slideAnimation = Tween<Offset>(
begin: const Offset(0, 0.2),
end: Offset.zero,
).animate(CurvedAnimation(parent: _controller, curve: Curves.easeOutCubic));
_fadeAnimation = CurvedAnimation(
parent: _controller,
curve: Curves.easeInOut,
);
_controller.forward();
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
Future<void> _saveTransaction(BuildContext context) async {
const String saveUrl = '${Environment.baseUrl}/api/transaction/add';
try {
final prefs = await SharedPreferences.getInstance();
final userId = prefs.getString('userId');
if (userId == null) {
throw Exception('User ID not found. Please log in again.');
}
final response = await http.post(
Uri.parse(saveUrl),
headers: {'Content-Type': 'application/json'},
body: jsonEncode({
'userId': userId,
'description': widget.data['description'] ?? '',
'amount': double.tryParse(widget.data['amount'].toString()) ?? 0.0,
'category': widget.data['category'] ?? 'Uncategorized',
'date': widget.data['date'] ?? DateTime.now().toIso8601String(),
}),
);
if (response.statusCode == 200) {
_showCustomSnackBar(
context: context,
message: '✅ Transaction saved successfully!',
icon: Icons.check_circle,
backgroundColor: const Color(0xFF4CAF50),
iconColor: Colors.white,
);
Navigator.popUntil(context, (route) => route.isFirst);
} else {
throw Exception('Save failed: ${response.statusCode} ${response.body}');
}
} catch (e) {
_showCustomSnackBar(
context: context,
message: 'Error saving transaction: ${e.toString()}',
icon: Icons.error_outline,
backgroundColor: const Color(0xFFFF6B6B),
iconColor: Colors.white,
);
}
}
void _showCustomSnackBar({
required String message,
required IconData icon,
required Color backgroundColor,
required Color iconColor,
Duration duration = const Duration(seconds: 3),
required BuildContext context,
}) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Row(
children: [
Icon(icon, color: iconColor, size: context.responsiveText(20)),
SizedBox(width: context.responsiveWidth(8)),
Expanded(
child: Text(
message,
style: GoogleFonts.inter(
fontWeight: FontWeight.w600,
color: Colors.white,
fontSize: context.responsiveText(14),
),
),
),
],
),
backgroundColor: backgroundColor,
behavior: SnackBarBehavior.floating,
margin: EdgeInsets.all(context.responsiveWidth(12)),
duration: duration,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(context.responsiveWidth(12)),
),
),
);
}
Widget _buildDetailItem({
required IconData icon,
required String label,
required String value,
bool isAmount = false,
}) {
return Row(
children: [
Container(
width: context.responsiveWidth(40),
height: context.responsiveWidth(40),
decoration: BoxDecoration(
color: accentColor.withOpacity(0.08),
borderRadius: BorderRadius.circular(context.responsiveWidth(10)),
),
child: Icon(
icon,
color: accentColor,
size: context.responsiveText(20),
),
),
SizedBox(width: context.responsiveWidth(14)),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
label,
style: GoogleFonts.inter(
color: primaryColor.withOpacity(0.6),
fontSize: context.responsiveText(12),
fontWeight: FontWeight.w500,
),
),
SizedBox(height: context.responsiveHeight(2)),
Text(
value,
style: GoogleFonts.inter(
color: isAmount ? Colors.green : primaryColor,
fontSize: context.responsiveText(16),
fontWeight: FontWeight.w700,
),
),
],
),
),
],
);
}
@override
Widget build(BuildContext context) {
final amount = widget.data['amount'];
final description = widget.data['description'];
final category = widget.data['category'];
final date =
widget.data['date'] != null
? DateTime.parse(widget.data['date']).toLocal()
: DateTime.now();
return Scaffold(
backgroundColor: backgroundColor,
appBar: AppBar(
backgroundColor: Colors.transparent,
elevation: 0,
leading: Container(
margin: EdgeInsets.all(context.responsiveWidth(6)),
decoration: BoxDecoration(
color: cardColor,
borderRadius: BorderRadius.circular(context.responsiveWidth(12)),
),
child: IconButton(
icon: Icon(Icons.arrow_back, color: primaryColor),
onPressed: () => Navigator.pop(context),
),
),
title: Text(
'Confirm Transaction',
style: GoogleFonts.inter(
color: primaryColor,
fontSize: context.responsiveText(18),
fontWeight: FontWeight.w700,
),
),
centerTitle: true,
),
body: SafeArea(
child: SlideTransition(
position: _slideAnimation,
child: FadeTransition(
opacity: _fadeAnimation,
child: Padding(
padding: EdgeInsets.all(context.responsiveWidth(20)),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Header
Container(
padding: EdgeInsets.all(context.responsiveWidth(18)),
decoration: BoxDecoration(
color: cardColor,
borderRadius: BorderRadius.circular(
context.responsiveWidth(18),
),
boxShadow: [
BoxShadow(
color: accentColor.withOpacity(0.08),
blurRadius: 18,
offset: const Offset(0, 6),
),
],
),
child: Row(
children: [
Container(
padding: EdgeInsets.all(context.responsiveWidth(10)),
decoration: BoxDecoration(
color: Colors.green.withOpacity(0.1),
borderRadius: BorderRadius.circular(
context.responsiveWidth(10),
),
),
child: Icon(
Icons.check_circle_outline,
color: Colors.green,
size: context.responsiveText(22),
),
),
SizedBox(width: context.responsiveWidth(14)),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Review Transaction",
style: GoogleFonts.inter(
fontSize: context.responsiveText(16),
fontWeight: FontWeight.w700,
color: primaryColor,
),
),
Text(
"Please confirm the details below",
style: GoogleFonts.inter(
fontSize: context.responsiveText(13),
fontWeight: FontWeight.w500,
color: primaryColor.withOpacity(0.6),
),
),
],
),
],
),
),
SizedBox(height: context.responsiveHeight(24)),
// Details Card
Container(
padding: EdgeInsets.all(context.responsiveWidth(20)),
decoration: BoxDecoration(
color: backgroundColor,
borderRadius: BorderRadius.circular(
context.responsiveWidth(18),
),
border: Border.all(
color: primaryColor.withOpacity(0.08),
width: 1,
),
),
child: Column(
children: [
_buildDetailItem(
icon: Icons.description_outlined,
label: "Description",
value: description?.toString() ?? "No description",
),
SizedBox(height: context.responsiveHeight(16)),
_buildDetailItem(
icon: Icons.payments_outlined,
label: "Amount",
value: "₹$amount",
isAmount: true,
),
SizedBox(height: context.responsiveHeight(16)),
_buildDetailItem(
icon: Icons.category_outlined,
label: "Category",
value: category?.toString() ?? "Uncategorized",
),
SizedBox(height: context.responsiveHeight(16)),
_buildDetailItem(
icon: Icons.calendar_today_outlined,
label: "Date",
value: "${date.day}/${date.month}/${date.year}",
),
],
),
),
const Spacer(),
// Buttons
Column(
children: [
// Confirm
GestureDetector(
onTapDown: (_) => _controller.forward(),
onTapUp: (_) => _saveTransaction(context),
child: AnimatedScale(
scale: 1,
duration: const Duration(milliseconds: 150),
child: Container(
width: double.infinity,
padding: EdgeInsets.symmetric(
vertical: context.responsiveHeight(14),
),
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Colors.green, Colors.green.shade700],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
borderRadius: BorderRadius.circular(
context.responsiveWidth(14),
),
boxShadow: [
BoxShadow(
color: Colors.green.withOpacity(0.3),
blurRadius: 10,
offset: const Offset(0, 4),
),
],
),
child: Center(
child: Text(
"Confirm & Save Transaction",
style: GoogleFonts.inter(
fontSize: context.responsiveText(15),
fontWeight: FontWeight.w700,
color: Colors.white,
),
),
),
),
),
),
SizedBox(height: context.responsiveHeight(14)),
// Cancel
OutlinedButton(
onPressed: () => Navigator.pop(context),
style: OutlinedButton.styleFrom(
minimumSize: Size(
double.infinity,
context.responsiveHeight(48),
),
side: BorderSide(
color: primaryColor.withOpacity(0.3),
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(
context.responsiveWidth(12),
),
),
),
child: Text(
"Edit or Cancel",
style: GoogleFonts.inter(
fontSize: context.responsiveText(14),
fontWeight: FontWeight.w600,
color: primaryColor.withOpacity(0.8),
),
),
),
],
),
],
),
),
),
),
),
);
}
}