financial changes

master
gitadmin 2 months ago
parent 07d1f7210e
commit c664967fa2

@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:supplier_new/common/settings.dart';
class AddCreditTransactionPage extends StatefulWidget {
const AddCreditTransactionPage({super.key});
@ -49,9 +50,9 @@ class _AddCreditTransactionPageState extends State<AddCreditTransactionPage> {
icon: const Icon(Icons.arrow_back, color: Colors.black),
onPressed: () => Navigator.pop(context),
),
title: const Text(
title: Text(
"Add Credit Transaction",
style: TextStyle(color: Colors.black, fontWeight: FontWeight.w600),
style: fontTextStyle(14,Color(0XFF2A2A2A),FontWeight.w400),
),
actions: [
TextButton(

@ -1,8 +1,12 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:supplier_new/common/settings.dart'; // for fontTextStyle
class AddTransactionScreen extends StatefulWidget {
const AddTransactionScreen({super.key});
@override
_AddTransactionScreenState createState() => _AddTransactionScreenState();
State<AddTransactionScreen> createState() => _AddTransactionScreenState();
}
class _AddTransactionScreenState extends State<AddTransactionScreen> {
@ -13,85 +17,215 @@ class _AddTransactionScreenState extends State<AddTransactionScreen> {
String? paymentMode;
String? paymentStatus;
TextEditingController amountController = TextEditingController(text: "₹500");
TextEditingController transactionIdController = TextEditingController(text: "₹500");
TextEditingController dateController = TextEditingController();
final TextEditingController amountController = TextEditingController();
final TextEditingController transactionIdController = TextEditingController();
final TextEditingController dateController = TextEditingController();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.white,
elevation: 0,
leading: Icon(Icons.arrow_back, color: Colors.black),
title: Text(
"Add Transaction",
style: TextStyle(color: Colors.black, fontWeight: FontWeight.w600),
),
actions: [
TextButton(
onPressed: () {},
child: Text("HELP", style: TextStyle(color: Colors.purple)),
)
],
return AnnotatedRegion<SystemUiOverlayStyle>(
value: SystemUiOverlayStyle.dark.copyWith(
statusBarColor: Colors.white,
systemNavigationBarColor: Colors.white,
systemNavigationBarIconBrightness: Brightness.dark,
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Form(
key: _formKey,
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
buildDropdown("Transaction Type *", ["Credit", "Debit"], transactionType, (val) {
setState(() => transactionType = val);
}),
SizedBox(height: 16),
buildDropdown("Account Name *", ["Name1", "Name2"], accountName, (val) {
setState(() => accountName = val);
}),
SizedBox(height: 16),
buildTextField("Amount (in ₹) *", amountController),
SizedBox(height: 16),
Row(
children: [
Expanded(
child: buildDropdown("Payment Mode *", ["Cash", "Card", "UPI"], paymentMode, (val) {
setState(() => paymentMode = val);
}),
),
SizedBox(width: 12),
Expanded(
child: buildDatePicker(),
),
],
child: Theme(
data: Theme.of(context).copyWith(
scaffoldBackgroundColor: Colors.white,
canvasColor: Colors.white,
dialogBackgroundColor: Colors.white,
dropdownMenuTheme: const DropdownMenuThemeData(
menuStyle: MenuStyle(
backgroundColor: WidgetStatePropertyAll(Colors.white),
),
),
inputDecorationTheme: InputDecorationTheme(
filled: true,
fillColor: Colors.white,
labelStyle:
fontTextStyle(12, const Color(0xFF6B7280), FontWeight.w800),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide: const BorderSide(color: Color(0xFFE5E7EB)),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide: const BorderSide(color: Color(0xFFE5E7EB)),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide:
const BorderSide(color: Color(0xFF8270DB), width: 1.5),
),
contentPadding:
const EdgeInsets.symmetric(horizontal: 12, vertical: 12),
),
appBarTheme: const AppBarTheme(
backgroundColor: Colors.white,
elevation: 0,
surfaceTintColor: Colors.white,
foregroundColor: Color(0xFF2A2A2A),
systemOverlayStyle: SystemUiOverlayStyle.dark,
),
),
child: Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
leading: IconButton(
onPressed: () => Navigator.pop(context),
tooltip: 'Back',
icon: Image.asset(
'images/backbutton_appbar.png',
width: 24,
height: 24,
color: const Color(0XFF2A2A2A),
),
),
title: Text(
"Add Transaction",
style:
fontTextStyle(16, const Color(0xFF2A2A2A), FontWeight.w600),
),
actions: [
TextButton(
onPressed: () {},
child: Text(
"HELP",
style: fontTextStyle(
12, const Color(0xFF8270DB), FontWeight.w600),
),
SizedBox(height: 16),
buildTextField("Transaction ID *", transactionIdController),
SizedBox(height: 16),
buildDropdown("Payment Status *", ["Pending", "Completed", "Failed"], paymentStatus, (val) {
setState(() => paymentStatus = val);
}),
SizedBox(height: 24),
SizedBox(
width: double.infinity,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: Color(0xFF8270DB),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
],
),
body: SafeArea(
child: Container(
color: Colors.white,
padding: const EdgeInsets.all(16),
child: Form(
key: _formKey,
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
fieldLabel("Transaction Type", requiredMark: true),
buildDropdownHint(
hint: "Select type",
items: const ["Credit", "Debit"],
value: transactionType,
onChanged: (val) =>
setState(() => transactionType = val),
hintStyle: fontTextStyle(
14, const Color(0xFF939495), FontWeight.w400),
),
const SizedBox(height: 16),
fieldLabel("Account Name", requiredMark: true),
buildDropdownHint(
hint: " name",
items: const ["Name1", "Name2"],
value: accountName,
onChanged: (val) => setState(() => accountName = val),
hintStyle: fontTextStyle(
14, const Color(0xFF939495), FontWeight.w400),
),
const SizedBox(height: 16),
fieldLabel("Amount (in ₹)", requiredMark: true),
buildTextField(
hint: "Enter amount",
controller: amountController,
keyboardType: const TextInputType.numberWithOptions(
decimal: true),
validator: (v) =>
(v == null || v
.trim()
.isEmpty)
? "Amount is required"
: null,
hintStyle: fontTextStyle(
14, const Color(0xFF939495), FontWeight.w400),
),
const SizedBox(height: 16),
Row(
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
fieldLabel("Payment Status",
requiredMark: true),
buildDropdownHint(
hint: "Select status",
items: const [
"Pending",
"Completed",
"Failed"
],
value: paymentStatus,
onChanged: (val) =>
setState(() => paymentStatus = val),
hintStyle: fontTextStyle(
14,
const Color(0xFF939495),
FontWeight.w400), // styled
),
],
),
),
const SizedBox(width: 12),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
fieldLabel("Date", requiredMark: true),
buildDatePicker(hint: "DD-MM-YYYY"),
],
),
),
],
),
const SizedBox(height: 16),
fieldLabel("Transaction ID", requiredMark: true),
buildTextField(
hint: "Transaction ID *",
controller: transactionIdController,
validator: (v) =>
(v == null || v
.trim()
.isEmpty)
? "Transaction ID is required"
: null,
),
const SizedBox(height: 16),
fieldLabel("Payment Status", requiredMark: true),
buildDropdownHint(
hint: "Select status",
items: const ["Pending", "Completed", "Failed"],
value: paymentStatus,
onChanged: (val) => setState(() => paymentStatus = val),
),
const SizedBox(height: 24),
SizedBox(
width: double.infinity,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xFF8270DB),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12)),
padding: const EdgeInsets.symmetric(vertical: 14),
foregroundColor: Colors.white,
),
onPressed: () {
if (_formKey.currentState!.validate()) {
// TODO: Save handler
}
},
child: const Text("Save",
style: TextStyle(fontSize: 16)),
),
),
padding: EdgeInsets.symmetric(vertical: 14),
),
onPressed: () {
if (_formKey.currentState!.validate()) {
// Handle save
}
},
child: Text("Save", style: TextStyle(color: Colors.white, fontSize: 16)),
],
),
)
],
),
),
),
),
),
@ -99,50 +233,183 @@ class _AddTransactionScreenState extends State<AddTransactionScreen> {
);
}
Widget buildDropdown(String label, List<String> items, String? value, Function(String?) onChanged) {
Widget buildDropdownHint({
required String hint,
required List<String> items,
required String? value,
required Function(String?) onChanged,
TextStyle? hintStyle,
EdgeInsetsGeometry? contentPadding,
bool centerHint = false,
}) {
return DropdownButtonFormField<String>(
value: value,
// must be null to show the hint
isExpanded: true,
isDense: true,
decoration: InputDecoration(
labelText: label,
border: OutlineInputBorder(borderRadius: BorderRadius.circular(8)),
contentPadding: EdgeInsets.symmetric(horizontal: 12, vertical: 12),
// don't set hintText here; use the `hint:` widget below
contentPadding: contentPadding ??
const EdgeInsets.symmetric(horizontal: 12, vertical: 12),
),
hint: Align(
alignment: centerHint ? Alignment.center : Alignment.centerLeft,
child: Text(
hint,
textAlign: centerHint ? TextAlign.center : TextAlign.start,
style: hintStyle ??
fontTextStyle(
14,
const Color(0xFF939495),
FontWeight.w400),
),
),
items:
items.map((e) => DropdownMenuItem(value: e, child: Text(e))).toList(),
onChanged: onChanged,
dropdownColor: Colors.white,
validator: (v) => (v == null || v.isEmpty) ? "Required" : null,
);
}
Widget fieldLabel(String text, {bool requiredMark = false}) {
return Padding(
padding: const EdgeInsets.only(bottom: 8),
child: Row(
children: [
Text(
text,
style: fontTextStyle(12, Color(0xFF515253), FontWeight.w500),
),
if (requiredMark) ...[
const SizedBox(width: 2),
Text("*",
style: fontTextStyle(
12, const Color(0xFFD32F2F), FontWeight.w800)),
],
],
),
);
}
Widget buildDropdown({
required String label,
required List<String> items,
required String? value,
required Function(String?) onChanged,
}) {
return DropdownButtonFormField<String>(
value: value,
items: items.map((e) => DropdownMenuItem(value: e, child: Text(e))).toList(),
decoration: InputDecoration(labelText: label),
isExpanded: true,
items:
items.map((e) => DropdownMenuItem(value: e, child: Text(e))).toList(),
onChanged: onChanged,
dropdownColor: Colors.white,
validator: (v) => (v == null || v.isEmpty) ? "Required" : null,
);
}
Widget buildTextField(String label, TextEditingController controller) {
Widget buildTextField({
required String hint,
required TextEditingController controller,
TextInputType? keyboardType,
String? Function(String?)? validator,
// Optional style overrides
TextStyle? textStyle,
TextStyle? hintStyle,
EdgeInsetsGeometry? contentPadding,
Widget? prefixIcon,
Widget? suffixIcon,
bool obscureText = false,
int? maxLines = 1,
int? minLines,
int? maxLength,
}) {
return TextFormField(
controller: controller,
keyboardType: keyboardType,
validator: validator,
obscureText: obscureText,
maxLines: maxLines,
minLines: minLines,
maxLength: maxLength,
// Text input styling
style: textStyle ??
fontTextStyle(14, const Color(0xFF101214), FontWeight.w500),
cursorColor: const Color(0xFF8270DB),
decoration: InputDecoration(
labelText: label,
border: OutlineInputBorder(borderRadius: BorderRadius.circular(8)),
contentPadding: EdgeInsets.symmetric(horizontal: 12, vertical: 12),
hintText: hint,
hintStyle: hintStyle ??
fontTextStyle(13, const Color(0xFF6B7280), FontWeight.w500),
contentPadding: contentPadding ??
const EdgeInsets.symmetric(horizontal: 12, vertical: 12),
prefixIcon: prefixIcon,
suffixIcon: suffixIcon,
// Border/fill are already controlled by your Theme.inputDecorationTheme
// but you could override here if needed.
),
);
}
Widget buildDatePicker() {
Widget buildDatePicker({
required String hint,
TextStyle? hintStyle, // NEW
EdgeInsetsGeometry? contentPadding, // optional
TextAlign textAlign = TextAlign.start, // optional (for centering)
}) {
return TextFormField(
controller: dateController,
readOnly: true,
textAlign: textAlign,
decoration: InputDecoration(
labelText: "Date *",
suffixIcon: Icon(Icons.calendar_today),
border: OutlineInputBorder(borderRadius: BorderRadius.circular(8)),
contentPadding: EdgeInsets.symmetric(horizontal: 12, vertical: 12),
hintText: hint,
hintStyle: hintStyle ??
fontTextStyle(
14,
const Color(0xFF939495),
FontWeight.w400),
contentPadding: contentPadding ??
const EdgeInsets.symmetric(horizontal: 12, vertical: 12),
suffixIcon: const Icon(Icons.calendar_today),
),
validator: (v) =>
(v == null || v
.trim()
.isEmpty) ? "Date is required" : null,
onTap: () async {
DateTime? picked = await showDatePicker(
final picked = await showDatePicker(
context: context,
initialDate: DateTime.now(),
firstDate: DateTime(2000),
lastDate: DateTime(2100),
builder: (context, child) {
return Theme(
data: Theme.of(context).copyWith(
dialogBackgroundColor: Colors.white,
colorScheme: Theme
.of(context)
.colorScheme
.copyWith(
primary: const Color(0xFF8270DB),
surface: Colors.white,
onSurface: const Color(0xFF101214),
),
),
child: child!,
);
},
);
if (picked != null) {
setState(() {
dateController.text = "${picked.day}-${picked.month}-${picked.year}";
dateController.text =
"${picked.day.toString().padLeft(2, '0')}-"
"${picked.month.toString().padLeft(2, '0')}-"
"${picked.year}";
});
}
},

@ -12,6 +12,16 @@ class FinancialMainScreen extends StatefulWidget {
State<FinancialMainScreen> createState() => _FinancialMainScreenState();
}
Color _amountColor(Map<String, dynamic> txn) {
if ((txn["status"] ?? "").toString().toLowerCase() == "failed") {
return const Color(0xFF9F9F9F); // gray
}
final amt = (txn["amount"] ?? "").toString().trim();
if (amt.startsWith('+')) return const Color(0xFF0A9E04); // green
if (amt.startsWith('-')) return const Color(0xFFE2483D); // red
return const Color(0xFF2D2E30); // default/dark text
}
class _FinancialMainScreenState extends State<FinancialMainScreen>
with SingleTickerProviderStateMixin {
late TabController _tabController;
@ -69,7 +79,7 @@ class _FinancialMainScreenState extends State<FinancialMainScreen>
super.dispose();
}
Widget fab(){
Widget fab() {
final index = _tabController.index;
if (index == 0) {
@ -114,10 +124,10 @@ class _FinancialMainScreenState extends State<FinancialMainScreen>
}
Widget Transactions(){
Widget Transactions() {
return Container(
color: Color(0XFFFFFFFF),
child:Column(
child: Column(
children: [
// Filters row
SingleChildScrollView(
@ -133,57 +143,74 @@ class _FinancialMainScreenState extends State<FinancialMainScreen>
),
),
const Divider(height: 1),
// Transactions list
Expanded(
child: ListView.builder(
padding: EdgeInsets.zero,
itemCount: transactions.length,
itemBuilder: (context, index) {
final txn = transactions[index];
return ListTile(
dense: true, //
minVerticalPadding: 0,
visualDensity: const VisualDensity(vertical: 0, horizontal: 0), // tighter
contentPadding: const EdgeInsets.symmetric(horizontal: 12, vertical: 0), // no extra top/bottom
horizontalTitleGap: 8,
minLeadingWidth: 40,
leading: const CircleAvatar(
radius: 18,
backgroundColor: Colors.blue,
child: Icon(Icons.person, color: Colors.white),
child: Icon(Icons.person, color: Colors.white, size: 18),
),
title: Text(
txn["name"].toString(),
style: fontTextStyle(14, Color(0xFF2D2E30), FontWeight.w500)
.copyWith(height: 1.1), // tighter line height
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
title: Text(txn["name"].toString()),
subtitle: Text(txn["date"].toString()),
subtitle: Text(
txn["date"].toString(),
style: fontTextStyle(12, Color(0xFF939495), FontWeight.w400)
.copyWith(height: 1.0), // tighter line height
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
trailing: Column(
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
txn["amount"].toString(),
style: TextStyle(
color: txn["color"] as Color,
fontWeight: FontWeight.bold,
),
style: fontTextStyle(12, _amountColor(txn), FontWeight.w600),
),
if (txn["status"] == "failed")
const Row(
if ((txn["status"] ?? "").toString().toLowerCase() == "failed")
Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(Icons.error, color: Colors.red, size: 14),
SizedBox(width: 4),
const Icon(Icons.error, color: Color(0xFF9F9F9F), size: 14), // gray
const SizedBox(width: 4),
Text(
"Failed",
style: TextStyle(
color: Colors.red, fontSize: 12),
style: fontTextStyle(10, const Color(0xFF9F9F9F), FontWeight.w400),
),
],
),
],
),
);
},
),
),
)
],
),
);
}
Widget CreditAccounts(){
Widget CreditAccounts() {
return SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(16),
@ -198,7 +225,8 @@ class _FinancialMainScreenState extends State<FinancialMainScreen>
foregroundColor: Color(0xFFFFFFFF),
backgroundColor: Color(0xFF000000),
side: BorderSide(color: Color(0xFF000000)),
padding: EdgeInsets.symmetric(vertical: 10, horizontal: 16), // padding around content
padding: EdgeInsets.symmetric(
vertical: 10, horizontal: 16), // padding around content
),
onPressed: () {
Navigator.push(
@ -209,13 +237,15 @@ class _FinancialMainScreenState extends State<FinancialMainScreen>
);
},
child: Row(
mainAxisSize: MainAxisSize.min, // shrink button to fit content
mainAxisSize: MainAxisSize.min,
// shrink button to fit content
children: [
Image.asset('images/plus.png', height: 20, width: 20),
SizedBox(width: 4),
Text(
"Create Account",
style: fontTextStyle(14, const Color(0xFFFFFFFF), FontWeight.w400),
style: fontTextStyle(
14, const Color(0xFFFFFFFF), FontWeight.w400),
),
],
),
@ -413,7 +443,7 @@ class _FinancialMainScreenState extends State<FinancialMainScreen>
required Color creditColor,
}) {
return GestureDetector(
onTap: (){
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
@ -477,13 +507,11 @@ class _FinancialMainScreenState extends State<FinancialMainScreen>
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text("Available Balance",
style: TextStyle(
fontSize: 12, color: Colors.black54)),
style: TextStyle(fontSize: 12, color: Colors.black54)),
const SizedBox(height: 4),
Text(
balance,
style: TextStyle(
fontSize: 14,
style: TextStyle(fontSize: 14,
fontWeight: FontWeight.bold,
color: balanceColor),
),
@ -498,8 +526,7 @@ class _FinancialMainScreenState extends State<FinancialMainScreen>
const SizedBox(height: 4),
Text(
credit,
style: TextStyle(
fontSize: 14,
style: TextStyle(fontSize: 14,
fontWeight: FontWeight.bold,
color: creditColor),
),
@ -509,13 +536,12 @@ class _FinancialMainScreenState extends State<FinancialMainScreen>
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text("Last Payment",
style: TextStyle(
fontSize: 12, color: Colors.black54)),
style: TextStyle(fontSize: 12, color: Colors.black54)),
const SizedBox(height: 4),
Text(
lastPayment,
style: const TextStyle(
fontSize: 12, fontWeight: FontWeight.w500),
style: fontTextStyle(
12, Color(0XFFF1F1F1), FontWeight.w500),
),
],
),
@ -530,7 +556,7 @@ class _FinancialMainScreenState extends State<FinancialMainScreen>
@override
Widget build(BuildContext context) {
return Scaffold(
appBar:AppBar(
appBar: AppBar(
elevation: 0,
backgroundColor: Colors.white,
bottom: PreferredSize(
@ -543,26 +569,27 @@ class _FinancialMainScreenState extends State<FinancialMainScreen>
builder: (context, _) {
return TabBar(
controller: _tabController,
indicatorColor: Colors.transparent, // remove underline
indicatorColor: Colors.transparent,
// remove underline
dividerColor: Colors.transparent,
isScrollable: false,
overlayColor: MaterialStateProperty.all(Colors.transparent),// equal width
overlayColor: MaterialStateProperty.all(Colors.transparent),
// equal width
tabs: List.generate(2, (index) {
final labels = ['Transactions', 'Credit Accounts'];
final isSelected = _tabController.index == index;
return Container(
decoration: BoxDecoration(
color: isSelected ? const Color(0XFFF1F1F1) : Colors.transparent,
color: isSelected ? const Color(0XFFF1F1F1) : Colors
.transparent,
borderRadius: BorderRadius.circular(27),
),
alignment: Alignment.center,
child: Text(
labels[index],
style: fontTextStyle(
12,
const Color(0XFF101214),
FontWeight.w600,
12, Color(0XFF000000), FontWeight.w600,
),
),
);
@ -585,7 +612,7 @@ class _FinancialMainScreenState extends State<FinancialMainScreen>
),
floatingActionButton:_tabController.index == 0 ? fab() : null,
floatingActionButton: _tabController.index == 0 ? fab() : null,
);
}
@ -593,9 +620,35 @@ class _FinancialMainScreenState extends State<FinancialMainScreen>
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 4),
child: FilterChip(
label: Text(text),
onSelected: (val) {},
label: Row(
mainAxisSize: MainAxisSize.min,
children: [
Text(
text,
style: const TextStyle(
fontSize: 12,
fontWeight: FontWeight.w500,
color: Colors.black,
),
),
const SizedBox(width: 4),
const Icon(
Icons.keyboard_arrow_down, // Down arrow
size: 18,
color: Colors.black,
),
],
),
backgroundColor: Colors.white,
selectedColor: const Color(0XFFF1F1F1),
side: const BorderSide(color: Color(0XFF444444)),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16),
),
onSelected: (val) {
},
),
);
}
}

@ -471,8 +471,8 @@ class _ResourcesFleetScreenState extends State<ResourcesFleetScreen> {
),
floatingActionButton: FloatingActionButton(
onPressed: () async{
// openTankerSimpleSheet(context);
final result = await Navigator.push(
openTankerSimpleSheet(context);
/*final result = await Navigator.push(
context,
MaterialPageRoute(
builder: (context) => FleetStep1Page(),
@ -482,7 +482,7 @@ class _ResourcesFleetScreenState extends State<ResourcesFleetScreen> {
// If result indicates API reload
if (result == true) {
_fetchTankers();
}
}*/
},
backgroundColor: const Color(0xFF000000),

Loading…
Cancel
Save