financial screens added

master
Sneha 3 months ago
parent b07033dda7
commit 44ccc525fb

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 709 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 865 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 465 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 349 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 817 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 912 B

@ -9,8 +9,10 @@ import 'package:supplier_new/common/settings.dart';
import 'package:supplier_new/financials/financial_main_screen.dart'; import 'package:supplier_new/financials/financial_main_screen.dart';
import 'package:supplier_new/orders/all_orders.dart'; import 'package:supplier_new/orders/all_orders.dart';
import 'package:supplier_new/orders/order_requests.dart'; import 'package:supplier_new/orders/order_requests.dart';
import 'package:supplier_new/orders/search_order_appbar.dart';
import 'package:supplier_new/plans/all_plans.dart'; import 'package:supplier_new/plans/all_plans.dart';
import 'package:supplier_new/plans/plan_requests.dart'; import 'package:supplier_new/plans/plan_requests.dart';
import 'package:supplier_new/plans/search_plan_appbar.dart';
import 'package:supplier_new/resources/fleet.dart'; import 'package:supplier_new/resources/fleet.dart';
import 'package:supplier_new/set_rates/set_rates.dart'; import 'package:supplier_new/set_rates/set_rates.dart';
@ -33,12 +35,15 @@ class _DashboardScreenState extends State<DashboardScreen> {
), ),
); );
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>(); final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
final TextEditingController orderSearchController = TextEditingController();
final TextEditingController planSearchController = TextEditingController();
// Define a list of widgets for each screen // Define a list of widgets for each screen
final List<Widget> _screens = [ final List<Widget> _screens = [
HomeScreen(), HomeScreen(),
AllOrders(), AllOrders(navigationFrom: 'bottombar',),
AllPlans(), AllPlans(navigationFrom: 'bottombar',),
FleetStep1Page(), FleetStep1Page(),
FinancialMainScreen(), FinancialMainScreen(),
]; ];
@ -246,6 +251,126 @@ class _DashboardScreenState extends State<DashboardScreen> {
}); });
} }
final List<String> _screenTitles = [
'Aquick Supplier', // index 0
'Orders', // index 1
'Plans', // index 2
'Resources', // index 3
'Financials', // index 4
];
String getScreenTitle(int index) {
if (index < 0 || index >= _screenTitles.length) return '';
return _screenTitles[index];
}
PreferredSizeWidget? _buildAppBar() {
// 👉 Orders tab (index 1): Custom Search AppBar
if (_currentIndex == 1) {
return SearchOrderAppBar(
controller: orderSearchController,
onBack: () {
setState(() {
_currentIndex = 0; // go back to Home
});
},
onHelp: () {
// handle help button action
debugPrint("Help tapped");
},
);
}
if (_currentIndex == 2) {
return SearchPlanAppBar(
controller: planSearchController,
onBack: () {
setState(() {
_currentIndex = 0; // go back to Home
});
},
onHelp: () {
// handle help button action
debugPrint("Help tapped");
},
);
}
// 👉 Home tab (index 0): Main AppBar
if (_currentIndex == 0) {
return AppBar(
backgroundColor: Colors.white,
elevation: 0,
scrolledUnderElevation: 0,
titleSpacing: 0,
title: Text(
'Aquick Supplier',
style: fontTextStyle(
16, const Color(0XFF515253), FontWeight.w600),
),
iconTheme: const IconThemeData(color: Color(0XFF2A2A2A)),
actions: [
Row(
children: [
Padding(
padding: const EdgeInsets.fromLTRB(10, 10, 0, 10),
child: IconButton(
icon: Image.asset('images/calendar_appbar.png'),
onPressed: () {},
),
),
Padding(
padding: const EdgeInsets.fromLTRB(0, 10, 10, 10),
child: IconButton(
icon: Image.asset('images/notification_appbar.png'),
onPressed: () {},
),
),
],
)
],
leading: IconButton(
icon: Image.asset(
'images/profile_appbar.png',
height: 20,
width: 20,
),
onPressed: () {
_scaffoldKey.currentState?.openDrawer();
},
),
);
}
// 👉 Other tabs (index 2,3,4): Simple AppBar with Back to Home
return AppBar(
backgroundColor: Colors.white,
elevation: 0,
scrolledUnderElevation: 0,
titleSpacing: 0,
title: Text(
getScreenTitle(_currentIndex),
style: fontTextStyle(
16, const Color(0XFF515253), FontWeight.w600),
),
leading: GestureDetector(
onTap:(){
setState(() {
_currentIndex = 0; // Back Home
});
}, // 👉 use callback from parent
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Image.asset(
'images/backbutton_appbar.png',
height: 24,
width: 24,
fit: BoxFit.contain,
),
),
),
);
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -352,52 +477,8 @@ class _DashboardScreenState extends State<DashboardScreen> {
child: Scaffold( child: Scaffold(
key: _scaffoldKey, key: _scaffoldKey,
backgroundColor: Colors.white, backgroundColor: Colors.white,
appBar: _currentIndex==0?AppBar( appBar: _buildAppBar(),
backgroundColor: Colors.white,
elevation: 0,
scrolledUnderElevation: 0,
titleSpacing: 0,
title: Text('Aquick Supplier',style: fontTextStyle(16,Color(0XFF515253),FontWeight.w600),),
iconTheme: IconThemeData(color: Color(0XFF2A2A2A)),
actions: [
Row(
children: [
Padding(padding: EdgeInsets.fromLTRB(10,10,0,10),
child: IconButton(
icon: Image(
image: AssetImage('images/calendar_appbar.png')
),
onPressed: (){
},
),
),
Padding(padding: EdgeInsets.fromLTRB(0,10,10,10),
child: IconButton(
icon: Image.asset(
'images/notification_appbar.png', // Example URL image
),
onPressed: (){
},
),
)
],
)
],
leading: IconButton(
icon: Image(
image: AssetImage('images/profile_appbar.png'),
height: 20,
width: 20,
),
onPressed: (){
_scaffoldKey.currentState?.openDrawer();
},
),
):null,
drawer: Drawer( drawer: Drawer(
width: MediaQuery.of(context).size.width, width: MediaQuery.of(context).size.width,
backgroundColor: Colors.white, backgroundColor: Colors.white,
@ -730,7 +811,7 @@ class _HomeScreenState extends State<HomeScreen> {
Navigator.push( Navigator.push(
context, context,
MaterialPageRoute( MaterialPageRoute(
builder: (context) => AllOrders()), builder: (context) => AllOrders(navigationFrom: 'dashboard',)),
); );
}, },
), ),

@ -574,6 +574,22 @@ class AppSettings{
style: fontTextStyle(16, Color(0XFF2A2A2A), FontWeight.w600), style: fontTextStyle(16, Color(0XFF2A2A2A), FontWeight.w600),
), ),
iconTheme: IconThemeData(color: Color(0XFF2A2A2A)), iconTheme: IconThemeData(color: Color(0XFF2A2A2A)),
leading: GestureDetector(
onTap: () {
Navigator.pop(context);
},
child: Padding(
padding:
const EdgeInsets.fromLTRB(8, 8, 8, 8), // Add padding if needed
child: Image.asset(
'images/backbutton_appbar.png', // Replace with your image path
fit: BoxFit.contain,
color: Color(0XFF2A2A2A),
height: 24,
width: 24,
),
),
),
actions: [ actions: [
Row( Row(
children: [ children: [
@ -591,6 +607,21 @@ class AppSettings{
], ],
) )
], ],
);
}
static supplierAppBarWithActionsText(String title,context) {
title = title ?? '';
return AppBar(
backgroundColor: Colors.white,
elevation: 0,
scrolledUnderElevation: 0,
title: Text(
title,
style: fontTextStyle(16, Color(0XFF2A2A2A), FontWeight.w600),
),
iconTheme: IconThemeData(color: Color(0XFF2A2A2A)),
leading: GestureDetector( leading: GestureDetector(
onTap: () { onTap: () {
Navigator.pop(context); Navigator.pop(context);
@ -607,6 +638,15 @@ class AppSettings{
), ),
), ),
), ),
actions: [
Padding(padding: EdgeInsets.all(8),
child: TextButton(
onPressed: () async {
},
child: Text('HELP',
style: fontTextStyle(14,primaryColor,FontWeight.w600),),
),)
],
); );
} }

@ -0,0 +1,216 @@
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
class AddCreditTransactionPage extends StatefulWidget {
const AddCreditTransactionPage({super.key});
@override
State<AddCreditTransactionPage> createState() =>
_AddCreditTransactionPageState();
}
class _AddCreditTransactionPageState extends State<AddCreditTransactionPage> {
final _formKey = GlobalKey<FormState>();
String? _transactionType;
String? _creditAccount;
String? _paymentMode;
String? _paymentStatus;
DateTime? _selectedDate;
final TextEditingController _amountController =
TextEditingController(text: "₹500");
final TextEditingController _transactionIdController =
TextEditingController(text: "₹500");
final TextEditingController _detailsController = TextEditingController();
Future<void> _pickDate() async {
DateTime now = DateTime.now();
final picked = await showDatePicker(
context: context,
initialDate: now,
firstDate: DateTime(2020),
lastDate: DateTime(2100),
);
if (picked != null) {
setState(() {
_selectedDate = picked;
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
elevation: 0,
backgroundColor: Colors.white,
leading: IconButton(
icon: const Icon(Icons.arrow_back, color: Colors.black),
onPressed: () => Navigator.pop(context),
),
title: const Text(
"Add Credit Transaction",
style: TextStyle(color: Colors.black, fontWeight: FontWeight.w600),
),
actions: [
TextButton(
onPressed: () {},
child: const Text(
"HELP",
style: TextStyle(color: Colors.blue),
),
),
],
),
body: SafeArea(
child: SingleChildScrollView(
padding: const EdgeInsets.all(16),
child: Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildDropdown(
label: "Transaction Type *",
value: _transactionType,
items: ["Credit", "Debit"],
onChanged: (val) => setState(() => _transactionType = val),
),
const SizedBox(height: 12),
_buildDropdown(
label: "Credit Account Name *",
value: _creditAccount,
items: ["Credit Account", "Other Account"],
onChanged: (val) => setState(() => _creditAccount = val),
),
const SizedBox(height: 12),
_buildTextField(
controller: _amountController,
label: "Amount (in ₹) *",
keyboardType: TextInputType.number,
),
const SizedBox(height: 12),
Row(
children: [
Expanded(
child: _buildDropdown(
label: "Payment Mode *",
value: _paymentMode,
items: ["Cash", "UPI", "Bank Transfer"],
onChanged: (val) => setState(() => _paymentMode = val),
),
),
const SizedBox(width: 12),
Expanded(
child: GestureDetector(
onTap: _pickDate,
child: AbsorbPointer(
child: TextFormField(
decoration: InputDecoration(
labelText: "Date *",
hintText: "DD-MM-YYYY",
suffixIcon: const Icon(Icons.calendar_today),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
),
),
controller: TextEditingController(
text: _selectedDate == null
? ""
: DateFormat("dd-MM-yyyy")
.format(_selectedDate!),
),
),
),
),
),
],
),
const SizedBox(height: 12),
_buildTextField(
controller: _transactionIdController,
label: "Transaction ID *",
),
const SizedBox(height: 12),
_buildDropdown(
label: "Payment Status *",
value: _paymentStatus,
items: ["Pending", "Completed", "Failed"],
onChanged: (val) => setState(() => _paymentStatus = val),
),
const SizedBox(height: 12),
_buildTextField(
controller: _detailsController,
label: "Additional Details",
),
const SizedBox(height: 24),
ElevatedButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
// Handle save
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text("Transaction Saved")),
);
}
},
style: ElevatedButton.styleFrom(
backgroundColor: Colors.blue,
padding: const EdgeInsets.symmetric(vertical: 14),
minimumSize: const Size(double.infinity, 50),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
),
child: const Text("Save Transaction"),
),
],
),
),
),
),
);
}
Widget _buildDropdown({
required String label,
required String? value,
required List<String> items,
required Function(String?) onChanged,
}) {
return DropdownButtonFormField<String>(
value: value,
isExpanded: true,
decoration: InputDecoration(
labelText: label,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
),
),
items: items
.map((e) => DropdownMenuItem(
value: e,
child: Text(e),
))
.toList(),
onChanged: onChanged,
);
}
Widget _buildTextField({
required TextEditingController controller,
required String label,
TextInputType keyboardType = TextInputType.text,
}) {
return TextFormField(
controller: controller,
keyboardType: keyboardType,
decoration: InputDecoration(
labelText: label,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
),
),
);
}
}

@ -0,0 +1,151 @@
import 'package:flutter/material.dart';
class AddTransactionScreen extends StatefulWidget {
@override
_AddTransactionScreenState createState() => _AddTransactionScreenState();
}
class _AddTransactionScreenState extends State<AddTransactionScreen> {
final _formKey = GlobalKey<FormState>();
String? transactionType;
String? accountName;
String? paymentMode;
String? paymentStatus;
TextEditingController amountController = TextEditingController(text: "₹500");
TextEditingController transactionIdController = TextEditingController(text: "₹500");
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)),
)
],
),
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(),
),
],
),
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),
),
padding: EdgeInsets.symmetric(vertical: 14),
),
onPressed: () {
if (_formKey.currentState!.validate()) {
// Handle save
}
},
child: Text("Save", style: TextStyle(color: Colors.white, fontSize: 16)),
),
)
],
),
),
),
),
);
}
Widget buildDropdown(String label, List<String> items, String? value, Function(String?) onChanged) {
return DropdownButtonFormField<String>(
decoration: InputDecoration(
labelText: label,
border: OutlineInputBorder(borderRadius: BorderRadius.circular(8)),
contentPadding: EdgeInsets.symmetric(horizontal: 12, vertical: 12),
),
value: value,
items: items.map((e) => DropdownMenuItem(value: e, child: Text(e))).toList(),
onChanged: onChanged,
);
}
Widget buildTextField(String label, TextEditingController controller) {
return TextFormField(
controller: controller,
decoration: InputDecoration(
labelText: label,
border: OutlineInputBorder(borderRadius: BorderRadius.circular(8)),
contentPadding: EdgeInsets.symmetric(horizontal: 12, vertical: 12),
),
);
}
Widget buildDatePicker() {
return TextFormField(
controller: dateController,
readOnly: true,
decoration: InputDecoration(
labelText: "Date *",
suffixIcon: Icon(Icons.calendar_today),
border: OutlineInputBorder(borderRadius: BorderRadius.circular(8)),
contentPadding: EdgeInsets.symmetric(horizontal: 12, vertical: 12),
),
onTap: () async {
DateTime? picked = await showDatePicker(
context: context,
initialDate: DateTime.now(),
firstDate: DateTime(2000),
lastDate: DateTime(2100),
);
if (picked != null) {
setState(() {
dateController.text = "${picked.day}-${picked.month}-${picked.year}";
});
}
},
);
}
}

@ -0,0 +1,296 @@
import 'package:flutter/material.dart';
import 'package:supplier_new/financials/add_transaction_for_credit_account.dart';
class BuildingTransactionsDetails extends StatefulWidget {
const BuildingTransactionsDetails({super.key});
@override
State<BuildingTransactionsDetails> createState() => _BuildingTransactionsDetailsState();
}
class _BuildingTransactionsDetailsState extends State<BuildingTransactionsDetails> {
@override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: SizedBox(
width: 52, // default is 56
height: 52, // make it bigger
child: FloatingActionButton(
shape: const CircleBorder(), // ensures perfect round shape
backgroundColor: Colors.black,
onPressed: (){
Navigator.push(
context,
MaterialPageRoute(
builder: (_) => AddCreditTransactionPage(),
),
);
},
child:Image.asset(
"images/plus.png", // your custom image
width: 20,
height: 20,
color: Colors.white, // optional: apply tint
),
),
),
body: SafeArea(
child: Column(
children: [
// Header
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
"Green Valley Apartments",
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.w600,
),
),
const SizedBox(height: 4),
Text(
"Gachibowli",
style: TextStyle(
fontSize: 14,
color: Colors.grey.shade600,
),
),
],
),
TextButton(
onPressed: () {},
child: const Text(
"HELP",
style: TextStyle(color: Colors.blue),
),
)
],
),
),
// Statement button
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
OutlinedButton.icon(
style: OutlinedButton.styleFrom(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
),
),
onPressed: () {},
icon: const Icon(Icons.download),
label: const Text("Statement"),
),
],
),
),
// Orders and balances
Padding(
padding: const EdgeInsets.all(16),
child: Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.grey.shade100,
borderRadius: BorderRadius.circular(12),
),
child: Column(
children: [
// Total orders
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Text(
"Total Orders",
style: TextStyle(fontSize: 16),
),
Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: const [
Text(
"45",
style: TextStyle(
fontSize: 22, fontWeight: FontWeight.bold),
),
Text(
"12 complete",
style:
TextStyle(fontSize: 13, color: Colors.grey),
)
],
)
],
),
const SizedBox(height: 16),
// Balances
Row(
children: [
Expanded(
child: Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: const [
Text("Receivable Balance"),
SizedBox(height: 4),
Text(
"₹24,000",
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.red),
),
SizedBox(height: 2),
Text(
"40.61% of total credit",
style: TextStyle(
fontSize: 12, color: Colors.grey),
)
],
),
),
),
const SizedBox(width: 12),
Expanded(
child: Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: const [
Text("Advance Balance"),
SizedBox(height: 4),
Text(
"₹24,000",
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.green),
),
SizedBox(height: 2),
Text(
"60.41% of total credit",
style: TextStyle(
fontSize: 12, color: Colors.grey),
)
],
),
),
),
],
),
],
),
),
),
// Buttons
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Row(
children: [
Expanded(
child: ElevatedButton(
onPressed: () {},
style: ElevatedButton.styleFrom(
backgroundColor: Colors.blue,
padding: const EdgeInsets.symmetric(vertical: 14),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
),
child: const Text("Add Transaction"),
),
),
const SizedBox(width: 12),
Expanded(
child: OutlinedButton(
onPressed: () {},
style: OutlinedButton.styleFrom(
padding: const EdgeInsets.symmetric(vertical: 14),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
),
child: const Text("Request Top up"),
),
),
],
),
),
const SizedBox(height: 12),
// History label
const Padding(
padding: EdgeInsets.symmetric(horizontal: 16),
child: Align(
alignment: Alignment.centerLeft,
child: Text(
"HISTORY",
style: TextStyle(fontWeight: FontWeight.w600, fontSize: 15),
),
),
),
const SizedBox(height: 8),
// History list
Expanded(
child: ListView(
padding: const EdgeInsets.symmetric(horizontal: 16),
children: [
_historyItem(
"Transaction Description", "21 August", "+ ₹2,580", true),
_historyItem(
"Transaction Description", "19 August", "- ₹748", false),
_historyItem(
"Transaction Description", "16 August", "- ₹10,000", false),
_historyItem(
"Transaction Description", "12 August", "- ₹500", false),
],
),
),
],
),
),
);
}
Widget _historyItem(
String title, String date, String amount, bool isCredit) {
return ListTile(
contentPadding: EdgeInsets.zero,
leading: CircleAvatar(
backgroundColor: Colors.blue.shade100,
child: const Icon(Icons.swap_horiz, color: Colors.blue),
),
title: Text(title),
subtitle: Text(date),
trailing: Text(
amount,
style: TextStyle(
fontWeight: FontWeight.bold,
color: isCredit ? Colors.green : Colors.red,
),
),
);
}
}

@ -0,0 +1,143 @@
import 'package:flutter/material.dart';
import 'package:dropdown_button2/dropdown_button2.dart';
class CreateCreditAccountScreen extends StatefulWidget {
@override
_CreateCreditAccountScreenState createState() => _CreateCreditAccountScreenState();
}
class _CreateCreditAccountScreenState extends State<CreateCreditAccountScreen> {
String? selectedCustomer;
String paymentTerm = 'Net 30';
final creditLimitController = TextEditingController(text: '₹500');
final openingBalanceController = TextEditingController(text: '₹500');
final List<Map<String, String>> customers = [
{'name': 'Ramakrishna', 'date': '20 August'},
{'name': 'Mallesham Water Supplies', 'date': '21 August'},
{'name': 'My Home Bhooja', 'date': '21 August'},
];
final List<String> paymentTerms = ['Net 15', 'Net 30', 'Net 45'];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Create Credit Account'),
actions: [
TextButton(
onPressed: () {},
child: Text('HELP', style: TextStyle(color: Colors.blue)),
)
],
backgroundColor: Colors.white,
foregroundColor: Colors.black,
elevation: 1,
),
body: Padding(
padding: const EdgeInsets.all(16),
child: ListView(
children: [
Text('SELECT CUSTOMER', style: TextStyle(fontWeight: FontWeight.bold)),
const SizedBox(height: 10),
...customers.map((customer) {
return GestureDetector(
onTap: () {
setState(() {
selectedCustomer = customer['name'];
});
},
child: Container(
margin: const EdgeInsets.only(bottom: 10),
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
border: Border.all(
color: selectedCustomer == customer['name'] ? Colors.black : Colors.grey.shade300,
width: 1.5,
),
borderRadius: BorderRadius.circular(8),
color: Colors.white,
),
child: Row(
children: [
CircleAvatar(child: Icon(Icons.person)),
const SizedBox(width: 10),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(customer['name']!, style: TextStyle(fontSize: 16)),
Text(customer['date']!, style: TextStyle(color: Colors.grey)),
],
)
],
),
),
);
}),
const SizedBox(height: 20),
Text('ENTER DETAILS', style: TextStyle(fontWeight: FontWeight.bold)),
const SizedBox(height: 10),
TextField(
controller: creditLimitController,
keyboardType: TextInputType.number,
decoration: InputDecoration(
labelText: 'Credit Limit (in ₹) *',
border: OutlineInputBorder(),
),
),
const SizedBox(height: 15),
DropdownButtonFormField2<String>(
decoration: InputDecoration(
labelText: 'Payment Terms *',
border: OutlineInputBorder(),
),
value: paymentTerm,
items: paymentTerms.map((term) {
return DropdownMenuItem<String>(
value: term,
child: Text(term),
);
}).toList(),
onChanged: (value) {
setState(() {
paymentTerm = value!;
});
},
),
const SizedBox(height: 15),
TextField(
controller: openingBalanceController,
keyboardType: TextInputType.number,
decoration: InputDecoration(
labelText: 'Opening Balance (in ₹) *',
border: OutlineInputBorder(),
),
),
const SizedBox(height: 10),
Row(
children: [
Icon(Icons.info_outline, color: Colors.orange, size: 18),
const SizedBox(width: 8),
Expanded(
child: Text(
'Creating an Account will send the customer a notification about the details and a request to add balance to start the water delivery plan.',
style: TextStyle(color: Colors.black87, fontSize: 13),
),
)
],
),
const SizedBox(height: 20),
ElevatedButton(
onPressed: () {
// Add your submission logic here
},
style: ElevatedButton.styleFrom(
backgroundColor: Color(0xFF9375E8),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(30)),
minimumSize: Size(double.infinity, 50),
),
child: Text('Create Account'),
)
],
),
),
);
}
}

@ -1,5 +1,8 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:supplier_new/common/settings.dart'; import 'package:supplier_new/common/settings.dart';
import 'package:supplier_new/financials/add_transactions.dart';
import 'package:supplier_new/financials/building_transactions_details.dart';
import 'package:supplier_new/financials/create_credit_accounts.dart';
class FinancialMainScreen extends StatefulWidget { class FinancialMainScreen extends StatefulWidget {
@ -55,6 +58,9 @@ class _FinancialMainScreenState extends State<FinancialMainScreen>
void initState() { void initState() {
super.initState(); super.initState();
_tabController = TabController(length: 2, vsync: this); _tabController = TabController(length: 2, vsync: this);
_tabController.addListener(() {
setState(() {}); // rebuilds FAB visibility when tab changes
});
} }
@override @override
@ -63,6 +69,50 @@ class _FinancialMainScreenState extends State<FinancialMainScreen>
super.dispose(); super.dispose();
} }
Widget fab(){
final index = _tabController.index;
if (index == 0) {
return SizedBox(
width: 52,
height: 52,
child: FloatingActionButton(
shape: const CircleBorder(),
backgroundColor: Colors.black,
onPressed: _onFabPressed,
child: Image.asset(
"images/plus.png",
width: 20,
height: 20,
color: Colors.white,
),
),
);
} else {
return Container();
}
}
void _onFabPressed() {
final index = _tabController.index;
if (index == 0) {
// Tab 1 Navigate to Create Account
Navigator.push(
context,
MaterialPageRoute(
builder: (_) => AddTransactionScreen(),
),
);
} else if (index == 1) {
// Tab 2 Navigate to Transactions
/*Navigator.push(
context,
MaterialPageRoute(builder: (_) => const TransactionsPage()),
);*/
}
}
Widget Transactions(){ Widget Transactions(){
return Container( return Container(
@ -134,10 +184,345 @@ class _FinancialMainScreenState extends State<FinancialMainScreen>
} }
Widget CreditAccounts(){ Widget CreditAccounts(){
return Container( return SingleChildScrollView(
color: Color(0XFFFFFFFF), child: Padding(
child:Center( padding: const EdgeInsets.all(16),
child: Text("Credit Accounts Coming Soon..."), child: Column(
children: [
// Account Summary
Align(
alignment: Alignment.centerRight, // aligns button to the right
child: OutlinedButton(
style: OutlinedButton.styleFrom(
foregroundColor: Color(0xFFFFFFFF),
backgroundColor: Color(0xFF000000),
side: BorderSide(color: Color(0xFF000000)),
padding: EdgeInsets.symmetric(vertical: 10, horizontal: 16), // padding around content
),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (_) => CreateCreditAccountScreen(),
),
);
},
child: Row(
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),
),
],
),
),
),
Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
const Expanded(
child: Text(
"Account Summary",
style: TextStyle(
fontSize: 16, fontWeight: FontWeight.w600),
),
),
Column(
children: const [
Text(
"05",
style: TextStyle(
fontSize: 28,
fontWeight: FontWeight.bold,
color: Colors.blue),
),
SizedBox(height: 2),
Text(
"4 active, 1 overdue",
style: TextStyle(
fontSize: 12,
color: Colors.grey,
),
),
],
),
],
),
const SizedBox(height: 16),
Row(
children: [
Expanded(
child: Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12),
color: const Color(0xfffafafa),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: const [
Text(
"Receivable Balance",
style: TextStyle(
fontSize: 12, color: Colors.black54),
),
SizedBox(height: 4),
Text(
"₹24,000",
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: Colors.red),
),
Text(
"40.6% of total credit",
style: TextStyle(
fontSize: 11, color: Colors.grey),
),
],
),
),
),
const SizedBox(width: 12),
Expanded(
child: Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12),
color: const Color(0xfffafafa),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: const [
Text(
"Advance Balance",
style: TextStyle(
fontSize: 12, color: Colors.black54),
),
SizedBox(height: 4),
Text(
"₹24,000",
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: Colors.green),
),
Text(
"60.4% of total credit",
style: TextStyle(
fontSize: 11, color: Colors.grey),
),
],
),
),
),
],
),
],
),
),
const SizedBox(height: 20),
// Search Bar
Container(
padding:
const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
),
child: Row(
children: [
const Icon(Icons.search, color: Colors.grey),
const SizedBox(width: 8),
const Expanded(
child: TextField(
decoration: InputDecoration(
hintText: "Search",
border: InputBorder.none,
),
),
),
IconButton(
onPressed: () {},
icon: const Icon(Icons.sort, color: Colors.grey),
),
],
),
),
const SizedBox(height: 20),
// Accounts List
_accountTile(
name: "SVG Towers",
status: "active",
orders: "48 orders",
balance: "₹10,000",
credit: "₹10,000",
lastPayment: "₹5,000 | 12 Aug",
balanceColor: Colors.red,
creditColor: Colors.green,
),
_accountTile(
name: "Canvas Creations",
status: "active",
orders: "32 orders",
balance: "₹7,500",
credit: "₹7,500",
lastPayment: "₹3,000 | 5 Aug",
balanceColor: Colors.red,
creditColor: Colors.green,
),
_accountTile(
name: "Digital Designs",
status: "inactive",
orders: "15 orders",
balance: "₹2,000",
credit: "₹2,000",
lastPayment: "₹1,000 | 1 Aug",
balanceColor: Colors.red,
creditColor: Colors.green,
),
],
),
),
);
}
Widget _accountTile({
required String name,
required String status,
required String orders,
required String balance,
required String credit,
required String lastPayment,
required Color balanceColor,
required Color creditColor,
}) {
return GestureDetector(
onTap: (){
Navigator.push(
context,
MaterialPageRoute(
builder: (_) => BuildingTransactionsDetails(),
),
);
},
child: Container(
margin: const EdgeInsets.only(bottom: 12),
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Name + Status
Row(
children: [
Expanded(
child: Text(
name,
style: const TextStyle(
fontSize: 16, fontWeight: FontWeight.bold),
),
),
Container(
padding:
const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
decoration: BoxDecoration(
color: status == "active"
? Colors.green.withOpacity(0.1)
: Colors.red.withOpacity(0.1),
borderRadius: BorderRadius.circular(12),
),
child: Text(
status,
style: TextStyle(
color:
status == "active" ? Colors.green : Colors.redAccent,
fontSize: 12,
fontWeight: FontWeight.w500,
),
),
)
],
),
const SizedBox(height: 4),
Text(
orders,
style: const TextStyle(color: Colors.grey, fontSize: 12),
),
const SizedBox(height: 12),
// Balance - Credit - Last Payment
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text("Available Balance",
style: TextStyle(
fontSize: 12, color: Colors.black54)),
const SizedBox(height: 4),
Text(
balance,
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.bold,
color: balanceColor),
),
],
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text("Available Credit",
style: TextStyle(
fontSize: 12, color: Colors.black54)),
const SizedBox(height: 4),
Text(
credit,
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.bold,
color: creditColor),
),
],
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text("Last Payment",
style: TextStyle(
fontSize: 12, color: Colors.black54)),
const SizedBox(height: 4),
Text(
lastPayment,
style: const TextStyle(
fontSize: 12, fontWeight: FontWeight.w500),
),
],
),
],
)
],
),
), ),
); );
} }
@ -148,28 +533,8 @@ class _FinancialMainScreenState extends State<FinancialMainScreen>
appBar:AppBar( appBar:AppBar(
elevation: 0, elevation: 0,
backgroundColor: Colors.white, backgroundColor: Colors.white,
title: Text(
'Financials',
style: fontTextStyle(14, Color(0XFF2A2A2A), FontWeight.w500),
),
iconTheme: IconThemeData(color: Color(0XFF2A2A2A)),
leading: GestureDetector(
onTap: () {
Navigator.pop(context);
},
child: Padding(
padding: const EdgeInsets.fromLTRB(
8, 8, 8, 8), // Add padding if needed
child: Image.asset(
'images/backbutton_appbar.png',
height: 24,
width: 24,// Replace with your image path
fit: BoxFit.contain, // Adjust the fit
),
),
),
bottom: PreferredSize( bottom: PreferredSize(
preferredSize: const Size.fromHeight(50.0), preferredSize: const Size.fromHeight(0.0),
child: Container( child: Container(
height: 38, height: 38,
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
@ -218,10 +583,9 @@ class _FinancialMainScreenState extends State<FinancialMainScreen>
CreditAccounts() CreditAccounts()
], ],
), ),
floatingActionButton: FloatingActionButton(
onPressed: () {},
child: const Icon(Icons.add), floatingActionButton:_tabController.index == 0 ? fab() : null,
),
); );
} }

@ -1,32 +1,81 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:supplier_new/common/settings.dart';
import 'package:supplier_new/orders/edit_order_requests.dart'; import 'package:supplier_new/orders/edit_order_requests.dart';
class AcceptOrderRequests extends StatefulWidget { class AcceptOrderRequests extends StatefulWidget {
var order; var order;
AcceptOrderRequests({this.order}); var status;
AcceptOrderRequests({this.order,this.status});
@override @override
State<AcceptOrderRequests> createState() => _AcceptOrderRequestsState(); State<AcceptOrderRequests> createState() => _AcceptOrderRequestsState();
} }
class _AcceptOrderRequestsState extends State<AcceptOrderRequests> { class _AcceptOrderRequestsState extends State<AcceptOrderRequests> {
double advancePayable=0.0;
double advance=0.0;
double amountToPayAfterDelivery=0.0;
double totalFare=0.0;
@override
void initState() {
// TODO: implement initState
super.initState();
advance=150;
advancePayable = advance;
totalFare=advance+double.parse(widget.order.quoted_amount);
amountToPayAfterDelivery = totalFare - advancePayable;
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
backgroundColor: Colors.white, backgroundColor: Colors.white,
extendBodyBehindAppBar: true,
appBar: AppBar( appBar: AppBar(
backgroundColor: Colors.white, backgroundColor: Colors.transparent,
elevation: 0, elevation: 0,
leading: IconButton( scrolledUnderElevation: 0,
icon: const Icon(Icons.arrow_back, color: Colors.black), title: Text(
onPressed: () => Navigator.pop(context), '',
style: fontTextStyle(16, Color(0XFF2A2A2A), FontWeight.w600),
), ),
iconTheme: IconThemeData(color: Color(0XFF2A2A2A)),
actions: [ actions: [
IconButton( Row(
icon: const Icon(Icons.help_outline, color: Colors.black), children: [
onPressed: () {}, Padding(
), padding: EdgeInsets.fromLTRB(0, 10, 10, 10),
child: IconButton(
icon: Image.asset(
'images/help_appbar.png',
height: 20,
width: 20,
color: Color(0XFFFFFFFF),
),
onPressed: () {},
),
)
],
)
], ],
leading: GestureDetector(
onTap: () {
Navigator.pop(context);
},
child: Padding(
padding:
const EdgeInsets.fromLTRB(8, 8, 8, 8), // Add padding if needed
child: Image.asset(
'images/backbutton_appbar.png', // Replace with your image path
fit: BoxFit.contain,
color: Color(0XFFFFFFFF),
height: 24,
width: 24,
),
),
),
), ),
body: SingleChildScrollView( body: SingleChildScrollView(
@ -35,125 +84,170 @@ class _AcceptOrderRequestsState extends State<AcceptOrderRequests> {
children: [ children: [
/// 🔹 Top Card with Image /// 🔹 Top Card with Image
Stack( Stack(
clipBehavior: Clip.none,
children: [ children: [
/// 🔹 Background Image
ClipRRect( ClipRRect(
borderRadius: BorderRadius.circular(12), borderRadius: const BorderRadius.only(
bottomLeft: Radius.circular(0),
bottomRight: Radius.circular(0),
),
child: Image.asset( child: Image.asset(
"images/building.png", // replace with network image "images/building.png",
height: 180, height: 220,
width: double.infinity, width: double.infinity,
fit: BoxFit.cover, fit: BoxFit.cover,
), ),
), ),
/// Status Chip /// 🔹 Floating Info Card (half on image, half below)
Positioned( Positioned(
top: 12, bottom: -40, // pulls the card out by 40px
left: 12, left: 12,
right: 12,
child: Container( child: Container(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), padding: const EdgeInsets.all(12),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.blue.withOpacity(0.1), color: Colors.white,
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(12),
boxShadow: [
BoxShadow(
color: Colors.black12,
blurRadius: 6,
offset: Offset(0, 3),
),
],
), ),
child: const Text( child: Row(
"New", crossAxisAlignment: CrossAxisAlignment.center,
style: TextStyle( children: [
color: Colors.blue, Column(
fontWeight: FontWeight.w600, crossAxisAlignment: CrossAxisAlignment.start,
fontSize: 12, children: [
), Container(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
decoration: BoxDecoration(
color: Color(0XFFFFFFFF),
borderRadius: BorderRadius.circular(4),
border: Border.all(
color: widget.status.statusColor,
width: 0.5,
),
),
child: Text(
widget.status.status,
style: fontTextStyle(12, widget.status.statusColor, FontWeight.w500)
),
),
Text(
widget.order.building_name,
style: fontTextStyle(20, const Color(0XFF2D2E30), FontWeight.w600),
),
SizedBox(height: 4),
Text(
widget.order.displayAddress,
style: fontTextStyle(12, const Color(0XFF939495), FontWeight.w400),
),
],
),
const Spacer(),
Text(
widget.order.distanceInKm.toString()+'Km',
style: fontTextStyle(12, const Color(0XFF939495), FontWeight.w400),
),
],
), ),
), ),
), ),
], ],
), ),
SizedBox(height:MediaQuery.of(context).size.height * .08,),
/// Title + Location + Distance /// 🔹 Order Details
Padding( Padding(
padding: const EdgeInsets.all(12), padding: EdgeInsets.fromLTRB(16,0,16,0),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: const [ children: [
Text( Text(
"Club Kohinoor", "ORDER DETAILS",
style: TextStyle( style: fontTextStyle(10, const Color(0XFF2D2E30), FontWeight.w600),
fontSize: 18,
fontWeight: FontWeight.w600,
),
), ),
SizedBox(height: 4), SizedBox(height:MediaQuery.of(context).size.height * .011,),
Text( _detailTwoRow(
"Banjara Hills, Hyderabad • 5.5 Km", "Tanker Price", "${AppSettings.formDouble(widget.order.quoted_amount) ?? ''}","images/financialsBottomIcon.png",
style: TextStyle( "", "",""
fontSize: 13,
color: Colors.grey,
),
), ),
SizedBox(height:MediaQuery.of(context).size.height * .02,),
_detailTwoRow(
"Water Type", "${widget.order.type_of_water}","images/water.png",
"Date of Delivery", "${widget.order.time}","images/calendar_appbar.png",
),
SizedBox(height:MediaQuery.of(context).size.height * .02,),
_detailTwoRow(
"Capacity", "${widget.order.capacity}","images/capacity.png",
"Time of Delivery", "${widget.order.averageTime}","images/time.png",
),
SizedBox(height:MediaQuery.of(context).size.height * .02,),
_detailTwoRow(
"Quantity", "${widget.order.quantity}","images/quantity.png",
"Booking Charges", advance.toString(),"images/advance.png",
),
], ],
), ),
), ),
SizedBox(height:MediaQuery.of(context).size.height * .008,),
const Divider(), /// 🔹 Additional Details
/// 🔹 Order Details
Padding( Padding(
padding: const EdgeInsets.all(12), padding: EdgeInsets.fromLTRB(16,0,16,16),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
const Text( Text(
"ORDER DETAILS", "ADDITIONAL DETAILS",
style: TextStyle( style: fontTextStyle(10, const Color(0XFF2D2E30), FontWeight.w600),
fontSize: 14, ),
fontWeight: FontWeight.w600, SizedBox(height:MediaQuery.of(context).size.height * .011,),
), Text(
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, "
"sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. "
"Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut "
"aliquip ex ea commodo consequat.",
style: fontTextStyle(12, const Color(0XFF646566), FontWeight.w400),
), ),
const SizedBox(height: 12),
_detailRow("Tanker Price", "${widget.order.quoted_amount}"),
_detailRow("Water Type", " ${widget.order.type_of_water}"),
_detailRow("Date of Delivery", "${widget.order.time}"),
_detailRow("Capacity", "${widget.order.capacity}"),
_detailRow("Time of Delivery", "${widget.order.averageTime}"),
_detailRow("Quantity", "${widget.order.quantity}"),
_detailRow("Advance", "10%"),
], ],
), )
),
const Divider(),
/// 🔹 Additional Details
const Padding(
padding: EdgeInsets.all(12),
child: Text(
"ADDITIONAL DETAILS\n\nLorem ipsum dolor sit amet, consectetur adipiscing elit, "
"sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. "
"Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut "
"aliquip ex ea commodo consequat.",
style: TextStyle(fontSize: 13, color: Colors.black87, height: 1.4),
),
), ),
const Divider(),
/// 🔹 Payment Summary /// 🔹 Payment Summary
Padding( Padding(
padding: const EdgeInsets.all(12), padding: EdgeInsets.fromLTRB(16,0,16,16),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
const Text( Text(
"PAYMENT SUMMARY", "PAYMENT SUMMARY",
style: TextStyle( style: fontTextStyle(10, const Color(0XFF2D2E30), FontWeight.w600),
fontSize: 14,
fontWeight: FontWeight.w600,
),
), ),
const SizedBox(height: 12), SizedBox(height:MediaQuery.of(context).size.height * .011,),
_detailRow("Tanker Price", "₹ 1,500"), _detailRow("Tanker Price", "${AppSettings.formDouble(widget.order.quoted_amount) ?? ''}"),
_detailRow("Advance", "10%"), SizedBox(height:MediaQuery.of(context).size.height * .004,),
_detailRow("Booking Charges", ""+advance.toString()),
SizedBox(height:MediaQuery.of(context).size.height * .004,),
_detailRow("Total Amount", ""+totalFare.toString()),
SizedBox(height:MediaQuery.of(context).size.height * .004,),
Divider(color: Color(0XFF646566),
thickness: 0.3,),
SizedBox(height:MediaQuery.of(context).size.height * .004,),
_detailRow("Booking Charges Payable",'${AppSettings.formDouble(advancePayable.toString()) ?? ''}'
),
SizedBox(height:MediaQuery.of(context).size.height * .004,),
_detailRow("Amount to Pay (After Delivery)", '${AppSettings.formDouble(amountToPayAfterDelivery.toString()) ?? ''}'
),
], ],
), ),
), ),
@ -167,50 +261,101 @@ class _AcceptOrderRequestsState extends State<AcceptOrderRequests> {
bottomNavigationBar: Container( bottomNavigationBar: Container(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, color: Color(0XFFFFFFFF),
border: Border(top: BorderSide(color: Colors.grey.shade300)), border: Border(top: BorderSide(color: Color(0XFFF5F6F6))),
), ),
child: Row( child: Row(
children: [ children: [
Expanded( Expanded(
child: OutlinedButton( child: OutlinedButton(
style: OutlinedButton.styleFrom(
foregroundColor: Color(0XFF000000),
backgroundColor: Color(0xFFF1F1F1),
side: BorderSide(color: Color(0xFFF1F1F1)),
padding: EdgeInsets.symmetric(vertical: 10), // uniform height
),
onPressed: () { onPressed: () {
Navigator.push( Navigator.push(
context, context,
MaterialPageRoute( MaterialPageRoute(
builder: (_) => EditOrderRequests(order: widget.order,advance:"10%" ,), builder: (_) => EditOrderRequests(
order: widget.order,
advance: advance.toString(),
status: widget.status,
),
), ),
); );
}, },
child: const Text("Edit Order"), child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image.asset('images/edit.png', height: 20, width: 20),
SizedBox(width: 4),
Text(
"Edit Order",
style: fontTextStyle(14, const Color(0XFF000000), FontWeight.w400),
),
],
),
), ),
), ),
const SizedBox(width: 8),
SizedBox(width: 8),
Expanded( Expanded(
child: OutlinedButton( child: OutlinedButton(
style: OutlinedButton.styleFrom( style: OutlinedButton.styleFrom(
foregroundColor: Colors.red, foregroundColor: Color(0XFFE2483D),
side: const BorderSide(color: Colors.red), backgroundColor: Colors.white,
side: BorderSide(color: Color(0XFFE2483D)),
padding: EdgeInsets.symmetric(vertical: 10),
), ),
onPressed: () {}, onPressed: () {},
child: const Text("Reject"), child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image.asset('images/cross.png', height: 20, width: 20),
SizedBox(width: 4),
Text(
"Reject",
style: fontTextStyle(14, const Color(0XFF000000), FontWeight.w400),
),
],
),
), ),
), ),
const SizedBox(width: 8),
SizedBox(width: 8),
Expanded( Expanded(
child: ElevatedButton( child: ElevatedButton(
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
backgroundColor: Colors.green, backgroundColor: Color(0XFF0A9E04),
foregroundColor: Colors.white, foregroundColor: Color(0XFFFFFFFF),
padding: EdgeInsets.symmetric(vertical: 10),
),
onPressed: () {
},
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image.asset('images/rite.png', height: 20, width: 20),
SizedBox(width: 4),
Text(
"Accept",
style: fontTextStyle(14, const Color(0XFFFFFFFF), FontWeight.w400),
),
],
), ),
onPressed: () {},
child: const Text("Accept"),
), ),
), ),
], ],
), )
), ),
); );
} }
@ -218,17 +363,74 @@ class _AcceptOrderRequestsState extends State<AcceptOrderRequests> {
/// 🔹 Helper widget for rows /// 🔹 Helper widget for rows
Widget _detailRow(String title, String value) { Widget _detailRow(String title, String value) {
return Padding( return Padding(
padding: const EdgeInsets.symmetric(vertical: 6), padding: const EdgeInsets.symmetric(vertical: 0),
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
Text(title, Text(title,
style: const TextStyle(fontSize: 13, color: Colors.grey)), style: fontTextStyle(12, const Color(0XFF646566), FontWeight.w400),),
Text(value, Text(value,
style: const TextStyle( style: fontTextStyle(12, const Color(0XFF2D2E30), FontWeight.w500),),
fontSize: 13, fontWeight: FontWeight.w600)),
], ],
), ),
); );
} }
Widget _detailTwoRow(
String title1,
String value1,
String path1,
String title2,
String value2,
String path2, {
EdgeInsetsGeometry padding = const EdgeInsets.symmetric(vertical: 6),
}) {
final titleStyle = fontTextStyle(12, Color(0XFF646566), FontWeight.w400);
final valueStyle = fontTextStyle(12, Color(0XFF343637), FontWeight.w500);
Widget _col(String t, String v, String path) {
return Expanded(
child: Padding(
padding: const EdgeInsets.only(right: 8.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
if (path.isNotEmpty)
Image.asset(
path,
fit: BoxFit.contain,
height: 20,
width: 20,
color: const Color(0XFFC3C4C4),
),
if (path.isNotEmpty) const SizedBox(width: 6),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(t, style: titleStyle, maxLines: 1, overflow: TextOverflow.ellipsis),
Text(v, style: valueStyle, maxLines: 1, overflow: TextOverflow.ellipsis),
],
),
)
],
),
),
);
}
return Padding(
padding: padding,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
_col(title1, value1, path1),
_col(title2, value2, path2),
],
),
);
}
} }

@ -6,8 +6,11 @@ import 'package:supplier_new/orders/search_order_appbar.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
class AllOrders extends StatefulWidget { class AllOrders extends StatefulWidget {
const AllOrders({super.key}); final String navigationFrom;
AllOrders({
super.key,
required this.navigationFrom,
});
@override @override
State<AllOrders> createState() => _AllOrdersState(); State<AllOrders> createState() => _AllOrdersState();
} }
@ -82,14 +85,15 @@ class _AllOrdersState extends State<AllOrders> {
} }
return Scaffold( return Scaffold(
backgroundColor: Color(0XFFF2F2F2), backgroundColor: Color(0XFFF2F2F2),
appBar: SearchOrderAppBar( appBar: widget.navigationFrom.toString().toLowerCase()=='dashboard'?
SearchOrderAppBar(
controller: searchController, controller: searchController,
onBack: () => Navigator.pop(context), onBack: () => Navigator.pop(context),
onHelp: () { onHelp: () {
// Show help dialog or navigate // Show help dialog or navigate
print("Help tapped"); print("Help tapped");
}, },
), ):null,
body: SingleChildScrollView( body: SingleChildScrollView(
child: child:
Padding( Padding(

@ -1,9 +1,11 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:supplier_new/common/settings.dart';
class EditOrderRequests extends StatefulWidget { class EditOrderRequests extends StatefulWidget {
var order; var order;
String? advance; String? advance;
EditOrderRequests({this.order,this.advance}); var status;
EditOrderRequests({this.order,this.advance,this.status});
@override @override
State<EditOrderRequests> createState() => _EditOrderRequestsState(); State<EditOrderRequests> createState() => _EditOrderRequestsState();
@ -30,11 +32,11 @@ class _EditOrderRequestsState extends State<EditOrderRequests> {
advanceController.text='${widget.advance}'; advanceController.text='${widget.advance}';
// Update summary in real-time as user types // Update summary in real-time as user types
tankerPriceController.addListener(() => setState(() {})); tankerPriceController.addListener(() => setState(() {}));
capacityController.addListener(() => setState(() {})); /*capacityController.addListener(() => setState(() {}));
quantityController.addListener(() => setState(() {})); quantityController.addListener(() => setState(() {}));
dateController.addListener(() => setState(() {})); dateController.addListener(() => setState(() {}));
timeController.addListener(() => setState(() {})); timeController.addListener(() => setState(() {}));
waterTypeController.addListener(() => setState(() {})); waterTypeController.addListener(() => setState(() {}));*/
advanceController.addListener(() => setState(() {})); advanceController.addListener(() => setState(() {}));
} }
@ -43,25 +45,42 @@ class _EditOrderRequestsState extends State<EditOrderRequests> {
int tankerPrice = int.tryParse(tankerPriceController.text) ?? 0; int tankerPrice = int.tryParse(tankerPriceController.text) ?? 0;
int updatedQuantity=int.tryParse(quantityController.text) ?? 0; int updatedQuantity=int.tryParse(quantityController.text) ?? 0;
String updatedCapacity=capacityController.text ?? ''; String updatedCapacity=capacityController.text ?? '';
int totalPrice = tankerPrice * updatedQuantity; // Parse booking/advance as a double to accept "150.0" then convert to int (round)
double advancePercent = double bookingChargesDouble = double.tryParse(advanceController.text.trim()) ?? 0.0;
double.tryParse(advanceController.text.replaceAll('%', '')) ?? 0; int bookingCharges = bookingChargesDouble.round(); // or .toInt() / .floor() as you prefer
int advancePayable = (totalPrice * (advancePercent / 100)).round();
int totalPrice = (tankerPrice * updatedQuantity) + bookingCharges;
int advancePayable = bookingCharges; //
int amountToPayAfterDelivery=totalPrice-bookingCharges;
return Scaffold( return Scaffold(
backgroundColor: Colors.white, backgroundColor: Colors.white,
appBar: AppBar( appBar: AppBar(
backgroundColor: Colors.white, backgroundColor: Colors.white,
elevation: 0, elevation: 0,
leading: IconButton( scrolledUnderElevation: 0,
icon: const Icon(Icons.close, color: Colors.black), title: Text(
onPressed: () => Navigator.pop(context), 'Edit Order',
style: fontTextStyle(16, Color(0XFF2A2A2A), FontWeight.w600),
), ),
title: const Text( leading: GestureDetector(
"Edit Order", onTap: () {
style: TextStyle(color: Colors.black, fontWeight: FontWeight.w600), Navigator.pop(context);
},
child: Padding(
padding:
const EdgeInsets.fromLTRB(16, 8, 8, 8), // Add padding if needed
child: Image.asset(
'images/cross.png', // Replace with your image path
fit: BoxFit.contain,
color: Color(0XFF2A2A2A),
height: 24,
width: 24,
),
),
), ),
centerTitle: true, iconTheme: IconThemeData(color: Color(0XFF2A2A2A)),
), ),
body: SingleChildScrollView( body: SingleChildScrollView(
padding: const EdgeInsets.all(16), padding: const EdgeInsets.all(16),
@ -69,92 +88,146 @@ class _EditOrderRequestsState extends State<EditOrderRequests> {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
// 🔹 Club Info Card // 🔹 Club Info Card
Container( Material(
padding: const EdgeInsets.all(12), elevation: 4, // shadow depth
decoration: BoxDecoration( borderRadius: BorderRadius.circular(12),
border: Border.all(color: Colors.grey.shade300), child: Container(
borderRadius: BorderRadius.circular(12), padding: const EdgeInsets.all(12),
), decoration: BoxDecoration(
child: Row( borderRadius: BorderRadius.circular(12),
children: [ color: Colors.white, // Material needs a background color
Expanded( border: Border.all(color: Color(0XFFC9C2F0),width: 0.5),
child: Column( ),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: const [ children: [
Chip( Container(
label: Text("New", padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
style: TextStyle( decoration: BoxDecoration(
color: Colors.blue, color: Color(0XFFFFFFFF),
fontSize: 12, borderRadius: BorderRadius.circular(4),
fontWeight: FontWeight.w600)), border: Border.all(
backgroundColor: Color(0xFFEAF3FF), color: widget.status.statusColor,
padding: EdgeInsets.symmetric(horizontal: 4), width: 0.5,
),
),
child: Text(
widget.status.status,
style: fontTextStyle(12, widget.status.statusColor, FontWeight.w500)
),
), ),
Text("Club Kohinoor",
style: TextStyle(
fontSize: 18, fontWeight: FontWeight.w600)),
SizedBox(height: 4), SizedBox(height: 4),
Text("Banjara Hills, Hyderabad", Text(
style: TextStyle(color: Colors.grey, fontSize: 13)), widget.order.building_name,
style: fontTextStyle(20, const Color(0XFF2D2E30), FontWeight.w600),
),
Text(
widget.order.displayAddress,
style: fontTextStyle(12, const Color(0XFF939495), FontWeight.w400),
),
], ],
), ),
), const Spacer(),
const Text("5.5 Km", style: TextStyle(color: Colors.black54)), Text(
], widget.order.distanceInKm.toString()+'Km',
style: fontTextStyle(12, const Color(0XFF939495), FontWeight.w400),
),
],
),
), ),
), ),
const SizedBox(height: 20),
const Text("ORDER DETAILS", SizedBox(height:MediaQuery.of(context).size.height * .06,),
style: TextStyle(fontWeight: FontWeight.w600, fontSize: 14)), Text("ORDER DETAILS",
style: fontTextStyle(12, const Color(0XFF2D2E30), FontWeight.w600),),
const SizedBox(height: 12), const SizedBox(height: 12),
// 🔹 Two in a row // 🔹 Two in a row
_twoFields(tankerPriceController, "Tanker Price", null, null), _twoFields(tankerPriceController, "Tanker Price",'images/price.png',false, null, null,null,null),
_twoFields(capacityController, "Capacity", quantityController, "Quantity"), _twoFields(capacityController, "Capacity",'images/capacity.png',true,quantityController, "Quantity",'images/quantity.png',true),
_twoFields(waterTypeController, "Water Type",advanceController, "Advance"), _twoFields(waterTypeController, "Water Type",'images/water.png',true,advanceController, "Booking Charges",'images/advance.png',false),
_twoFields(dateController, "Date",timeController, "Time Of Delivery"), _twoFields(dateController, "Date",'images/calendar_appbar.png',true,timeController, "Time Of Delivery",'images/time.png',true),
const SizedBox(height: 20), const SizedBox(height: 20),
const Text("UPDATED PAYMENT SUMMARY", Text("UPDATED PAYMENT SUMMARY",
style: TextStyle(fontWeight: FontWeight.w600, fontSize: 14)), style: fontTextStyle(12,Color(0XFF2D2E30),FontWeight.w600),),
const SizedBox(height: 12), const SizedBox(height: 12),
_summaryRow("Tanker Price", "$tankerPrice"), _summaryRow("Tanker Price", "$tankerPrice"),
_summaryRow("Quantity", " $updatedQuantity"), _summaryRow("Quantity", " $updatedQuantity"),
_summaryRow("Capacity", "$updatedCapacity"), _summaryRow("Capacity", "$updatedCapacity"),
_summaryRow("Booking Charges", "$bookingCharges"),
_summaryRow("Total Price", "$totalPrice"), _summaryRow("Total Price", "$totalPrice"),
const Divider(), const Divider(),
_summaryRow("Advance", advanceController.text),
_summaryRow("Advance Payable", "$advancePayable"), _summaryRow("Booking Charges Payable", "$advancePayable"),
_summaryRow("Amount to Pay (After Delivery)", "$amountToPayAfterDelivery"),
], ],
), ),
), ),
bottomNavigationBar: Container( bottomNavigationBar: Container(
padding: const EdgeInsets.all(12), padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, color: Color(0XFFFFFFFF),
border: Border(top: BorderSide(color: Colors.grey.shade300)), border: Border(top: BorderSide(color: Color(0XFFF5F6F6))),
), ),
child: Row( child: Row(
children: [ children: [
Expanded( Expanded(
child: OutlinedButton( child: OutlinedButton(
onPressed: () => Navigator.pop(context), style: OutlinedButton.styleFrom(
child: const Text("Cancel"), foregroundColor: Color(0XFF000000),
backgroundColor: Color(0xFFFFFFFF),
side: BorderSide(color: Color(0xFF939495)),
padding: EdgeInsets.symmetric(vertical: 10),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(24), // <-- radius here
),
),
onPressed: () {
Navigator.pop(context);
},
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"Cancel",
style: fontTextStyle(14, const Color(0XFF000000), FontWeight.w400),
),
],
),
), ),
), ),
const SizedBox(width: 8), const SizedBox(width: 8),
Expanded( Expanded(
child: ElevatedButton( child: OutlinedButton(
style: ElevatedButton.styleFrom( style: OutlinedButton.styleFrom(
backgroundColor: Colors.deepPurple, foregroundColor: Color(0XFFFFFFFF),
foregroundColor: Colors.white, backgroundColor: Color(0xFF8270DB),
side: BorderSide(color: Color(0xFF8270DB)),
padding: EdgeInsets.symmetric(vertical: 10),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(24), // <-- radius here
),
), ),
onPressed: () { onPressed: () {
// 🔹 Collect updated values
print("Tanker Price: ${tankerPriceController.text}");
print("Water Type: ${waterTypeController.text}");
// Save logic here
}, },
child: const Text("Send ➤"), child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"Send",
style: fontTextStyle(14, const Color(0XFFFFFFFF), FontWeight.w400),
),
SizedBox(width: 12),
Image.asset('images/send.png', height: 20, width: 20),
],
),
), ),
), ),
], ],
@ -164,36 +237,72 @@ class _EditOrderRequestsState extends State<EditOrderRequests> {
} }
/// 🔹 Two fields side by side /// 🔹 Two fields side by side
Widget _twoFields(TextEditingController? controller1, String? label1, Widget _twoFields(TextEditingController? controller1, String? label1,String? path1, bool? readOnly1,
TextEditingController? controller2, String? label2) { TextEditingController? controller2, String? label2,String? path2,bool? readOnly2) {
return Row( return Row(
children: [ children: [
Expanded( Expanded(
child: _textField(controller1, label1), child: _textField(controller1, label1,path1,readOnly1!),
), ),
const SizedBox(width: 10), const SizedBox(width: 10),
if (controller2 != null) if (controller2 != null)
Expanded( Expanded(
child: _textField(controller2, label2), child: _textField(controller2, label2,path2,readOnly2!),
), ),
], ],
); );
} }
/// 🔹 Custom text field /// 🔹 Custom text field
Widget _textField(TextEditingController? controller, String? label) { Widget _textField(TextEditingController? controller, String? label,String? path,bool readOnly) {
return Container( return Container(
margin: const EdgeInsets.only(bottom: 12), margin: const EdgeInsets.only(bottom: 12),
child: TextField( child: TextField(
controller: controller, controller: controller,
cursorColor: primaryColor,
readOnly: readOnly,
decoration: InputDecoration( decoration: InputDecoration(
labelText: label, counterText: '',
filled: false,
fillColor: Colors.white,
prefixIcon: Padding(
padding: const EdgeInsets.symmetric(horizontal: 6.0, vertical: 6.0),
child: SizedBox(
width: 18,
height: 18,
child: Image.asset(
path!,
fit: BoxFit.contain,
color: Color(0XFFC3C4C4),
),
),
),
prefixIconConstraints: BoxConstraints(
minWidth: 24,
minHeight: 24,
),
border: OutlineInputBorder( border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10), borderRadius: BorderRadius.circular(4.0),
borderSide: BorderSide(color: Color(0XFFC3C4C4),
width: 1,)),
focusedBorder: !readOnly?OutlineInputBorder(
borderRadius: BorderRadius.circular(4.0),
borderSide: BorderSide(color: Color(0XFF8270DB),width: 1,),
):OutlineInputBorder(
borderRadius: BorderRadius.circular(4.0),
borderSide: BorderSide(color: Color(0XFFC3C4C4),width: 1,),
), ),
contentPadding:
const EdgeInsets.symmetric(horizontal: 12, vertical: 10), enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(4.0),
borderSide: BorderSide(color: Color(0XFFC3C4C4)),
),
labelText: label,
labelStyle:fontTextStyle(12,Color(0XFF646566),FontWeight.w400),
/* TextStyle(color: greyColor, fontWeight: FontWeight.bold //<-- SEE HERE
),*/
), ),
style:fontTextStyle(12,Color(0XFF343637),FontWeight.w500),
), ),
); );
} }
@ -205,12 +314,12 @@ class _EditOrderRequestsState extends State<EditOrderRequests> {
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
Text(title, style: const TextStyle(color: Colors.black54)), Text(title, style: fontTextStyle(12,Color(0XFF646566),FontWeight.w400),),
Text(value, Text(value,
style: const TextStyle( style: fontTextStyle(12,Color(0XFF2D2E30),FontWeight.w500),),
fontWeight: FontWeight.w600, color: Colors.black)),
], ],
), ),
); );
} }
} }

@ -31,7 +31,7 @@ class _OrderRequestsPageState extends State<OrderRequestsPage> {
final data = (jsonDecode(response)['data'] as List) final data = (jsonDecode(response)['data'] as List)
.map((e) => OrderRequestsModel.fromJson(e)) .map((e) => OrderRequestsModel.fromJson(e))
.toList(); .toList();
if (!mounted) return;
setState(() { setState(() {
orderRequestsList = data; orderRequestsList = data;
isLoading = false; isLoading = false;
@ -58,8 +58,8 @@ class _OrderRequestsPageState extends State<OrderRequestsPage> {
if (difference.inHours < 2) { if (difference.inHours < 2) {
status = "New"; status = "New";
color = const Color(0XFF1D7AFC); // Blue color = const Color(0XFF1D7AFC); // Blue
} else if (difference.inHours < 48) { } else if (difference.inHours < 240) {
int remaining = 48 - difference.inHours; int remaining = 240 - difference.inHours;
status = "Expires in ${remaining}h"; status = "Expires in ${remaining}h";
if (difference.inHours < 6) { if (difference.inHours < 6) {
color = const Color(0XFFE56910); // Less urgent color = const Color(0XFFE56910); // Less urgent
@ -124,7 +124,7 @@ class _OrderRequestsPageState extends State<OrderRequestsPage> {
Navigator.push( Navigator.push(
context, context,
MaterialPageRoute( MaterialPageRoute(
builder: (_) => AcceptOrderRequests(order: order), builder: (_) => AcceptOrderRequests(order: order,status:cardModel),
), ),
); );
}, },

@ -15,6 +15,7 @@ class OrderRequestsModel {
double lat=0; double lat=0;
double lng=0; double lng=0;
double distanceInMeters=0; double distanceInMeters=0;
double distanceInKm=0.0;
OrderRequestsModel(); OrderRequestsModel();
@ -36,12 +37,13 @@ class OrderRequestsModel {
if (parts.length >= 2) { if (parts.length >= 2) {
rtvm.displayAddress = parts[parts.length -4]; // "Banjara Hills" rtvm.displayAddress = parts[parts.length -4]; // "Banjara Hills"
} }
/* rtvm.distanceInMeters = double.parse((Geolocator.distanceBetween( rtvm.distanceInMeters = double.parse((Geolocator.distanceBetween(
rtvm.lat, rtvm.lat,
rtvm.lng, rtvm.lng,
AppSettings.supplierLatitude, AppSettings.supplierLatitude,
AppSettings.supplierLongitude AppSettings.supplierLongitude
) / 1000).toStringAsFixed(2));*/ ) / 1000).toStringAsFixed(2));
rtvm.distanceInKm = double.parse(( rtvm.distanceInMeters / 1000).toStringAsFixed(1));
return rtvm; return rtvm;
} }

@ -20,17 +20,14 @@ class SearchOrderAppBar extends StatelessWidget implements PreferredSizeWidget {
scrolledUnderElevation: 0, scrolledUnderElevation: 0,
elevation: 0, elevation: 0,
leading: GestureDetector( leading: GestureDetector(
onTap: () { onTap: onBack, // 👉 Controlled by parent
Navigator.pop(context);
},
child: Padding( child: Padding(
padding: const EdgeInsets.fromLTRB( padding: const EdgeInsets.all(8.0),
8, 8, 8, 8), // Add padding if needed
child: Image.asset( child: Image.asset(
'images/backbutton_appbar.png', 'images/backbutton_appbar.png',
height: 24, height: 24,
width: 24,// Replace with your image path width: 24,
fit: BoxFit.contain, // Adjust the fit fit: BoxFit.contain,
), ),
), ),
), ),
@ -40,18 +37,22 @@ class SearchOrderAppBar extends StatelessWidget implements PreferredSizeWidget {
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, color: Colors.white,
borderRadius: BorderRadius.circular(22), borderRadius: BorderRadius.circular(22),
border: Border.all(color: Color(0XFF939495)), border: Border.all(color: const Color(0XFF939495)),
), ),
child: TextField( child: TextField(
controller: controller, controller: controller,
decoration: InputDecoration( decoration: InputDecoration(
hintText: "Search order", hintText: "Search order",
hintStyle: fontTextStyle(16, Color(0XFF646566), FontWeight.w400), hintStyle: fontTextStyle(
16,
const Color(0XFF646566),
FontWeight.w400,
),
prefixIcon: SizedBox( prefixIcon: SizedBox(
height: 20, height: 20,
width: 20, width: 20,
child: Padding( child: Padding(
padding: const EdgeInsets.all(8.0), // adjust spacing padding: const EdgeInsets.all(8.0),
child: Image.asset( child: Image.asset(
'images/search.png', 'images/search.png',
fit: BoxFit.contain, fit: BoxFit.contain,
@ -60,29 +61,30 @@ class SearchOrderAppBar extends StatelessWidget implements PreferredSizeWidget {
), ),
border: InputBorder.none, border: InputBorder.none,
contentPadding: const EdgeInsets.symmetric(vertical: 0), contentPadding: const EdgeInsets.symmetric(vertical: 0),
), ),
style: fontTextStyle(16,Color(0XFF2A2A2A),FontWeight.w400), style: fontTextStyle(
16,
const Color(0XFF2A2A2A),
FontWeight.w400,
),
onSubmitted: (value) {
debugPrint("Search Orders: $value");
},
), ),
), ),
actions: [
actions: [ Padding(
Padding(padding: EdgeInsets.all(8), padding: const EdgeInsets.all(8.0),
child: child: GestureDetector(
GestureDetector( onTap: onHelp, // 👉 Controlled by parent
onTap: () {
},
child: Padding(
padding: const EdgeInsets.fromLTRB(
8, 8, 8, 8), // Add padding if needed
child: Image.asset( child: Image.asset(
'images/help_appbar.png', 'images/help_appbar.png',
height: 24, height: 24,
width: 24,// Replace with your image path width: 24,
fit: BoxFit.contain, // Adjust the fit fit: BoxFit.contain,
), ),
), ),
),) ),
], ],
); );
} }

@ -5,7 +5,11 @@ import 'package:supplier_new/plans/plans_model.dart';
import 'package:supplier_new/plans/search_plan_appbar.dart'; import 'package:supplier_new/plans/search_plan_appbar.dart';
class AllPlans extends StatefulWidget { class AllPlans extends StatefulWidget {
const AllPlans({super.key}); final String navigationFrom;
AllPlans({
super.key,
required this.navigationFrom,
});
@override @override
State<AllPlans> createState() => _AllPlansState(); State<AllPlans> createState() => _AllPlansState();
@ -57,13 +61,13 @@ class _AllPlansState extends State<AllPlans> {
return Scaffold( return Scaffold(
backgroundColor: const Color(0XFFFFFFFF), backgroundColor: const Color(0XFFFFFFFF),
appBar: SearchPlanAppBar( appBar: widget.navigationFrom.toString().toLowerCase()=='dashboard'?SearchPlanAppBar(
controller: searchController, controller: searchController,
onBack: () => Navigator.pop(context), onBack: () => Navigator.pop(context),
onHelp: () { onHelp: () {
print("Help tapped"); print("Help tapped");
}, },
), ):null,
body: SingleChildScrollView( body: SingleChildScrollView(
child: Column( child: Column(
children: [ children: [

@ -20,17 +20,14 @@ class SearchPlanAppBar extends StatelessWidget implements PreferredSizeWidget {
scrolledUnderElevation: 0, scrolledUnderElevation: 0,
elevation: 0, elevation: 0,
leading: GestureDetector( leading: GestureDetector(
onTap: () { onTap: onBack, // 👉 use callback from parent
Navigator.pop(context);
},
child: Padding( child: Padding(
padding: const EdgeInsets.fromLTRB( padding: const EdgeInsets.all(8.0),
8, 8, 8, 8), // Add padding if needed
child: Image.asset( child: Image.asset(
'images/backbutton_appbar.png', 'images/backbutton_appbar.png',
height: 24, height: 24,
width: 24,// Replace with your image path width: 24,
fit: BoxFit.contain, // Adjust the fit fit: BoxFit.contain,
), ),
), ),
), ),
@ -40,18 +37,18 @@ class SearchPlanAppBar extends StatelessWidget implements PreferredSizeWidget {
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, color: Colors.white,
borderRadius: BorderRadius.circular(22), borderRadius: BorderRadius.circular(22),
border: Border.all(color: Color(0XFF939495)), border: Border.all(color: const Color(0XFF939495)),
), ),
child: TextField( child: TextField(
controller: controller, controller: controller,
decoration: InputDecoration( decoration: InputDecoration(
hintText: "Search Plan", hintText: "Search Plan",
hintStyle: fontTextStyle(16, Color(0XFF646566), FontWeight.w400), hintStyle: fontTextStyle(16, const Color(0XFF646566), FontWeight.w400),
prefixIcon: SizedBox( prefixIcon: SizedBox(
height: 20, height: 20,
width: 20, width: 20,
child: Padding( child: Padding(
padding: const EdgeInsets.all(8.0), // adjust spacing padding: const EdgeInsets.all(8.0),
child: Image.asset( child: Image.asset(
'images/search.png', 'images/search.png',
fit: BoxFit.contain, fit: BoxFit.contain,
@ -60,29 +57,26 @@ class SearchPlanAppBar extends StatelessWidget implements PreferredSizeWidget {
), ),
border: InputBorder.none, border: InputBorder.none,
contentPadding: const EdgeInsets.symmetric(vertical: 0), contentPadding: const EdgeInsets.symmetric(vertical: 0),
), ),
style: fontTextStyle(16,Color(0XFF2A2A2A),FontWeight.w400), style: fontTextStyle(16, const Color(0XFF2A2A2A), FontWeight.w400),
onSubmitted: (value) {
debugPrint("Search Plan: $value");
},
), ),
), ),
actions: [
actions: [ Padding(
Padding(padding: EdgeInsets.all(8), padding: const EdgeInsets.all(8.0),
child: child: GestureDetector(
GestureDetector( onTap: onHelp, // 👉 use callback from parent
onTap: () {
},
child: Padding(
padding: const EdgeInsets.fromLTRB(
8, 8, 8, 8), // Add padding if needed
child: Image.asset( child: Image.asset(
'images/help_appbar.png', 'images/help_appbar.png',
height: 24, height: 24,
width: 24,// Replace with your image path width: 24,
fit: BoxFit.contain, // Adjust the fit fit: BoxFit.contain,
), ),
), ),
),) ),
], ],
); );
} }

@ -1,4 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:supplier_new/common/settings.dart';
class SetRatesScreen extends StatefulWidget { class SetRatesScreen extends StatefulWidget {
const SetRatesScreen({super.key}); const SetRatesScreen({super.key});
@ -11,158 +12,381 @@ class _SetRatesScreenState extends State<SetRatesScreen>
with SingleTickerProviderStateMixin { with SingleTickerProviderStateMixin {
late TabController _tabController; late TabController _tabController;
final TextEditingController drinking5000 = TextEditingController(); final Map<String, TextEditingController> controllers = {};
final TextEditingController drinking10000 = TextEditingController(); // Define categories + tankers
final TextEditingController drinking15000 = TextEditingController(); final Map<String, List<String>> tankerGroups = {};
final TextEditingController bore5000 = TextEditingController(); final Map<String, TextEditingController> deliveryControllers = {};
final TextEditingController bore10000 = TextEditingController();
final TextEditingController bore15000 = TextEditingController();
/*delivery fee controllers*/
final TextEditingController pumpFeeController = TextEditingController();
final List<Map<String, dynamic>> data = [
{"category": "DRINKING WATER", "size": "5,000L", "price": "12"},
{"category": "DRINKING WATER", "size": "15,000L", "price": "18"},
{"category": "DRINKING WATER", "size": "20,000L", "price": "20"},
{"category": "BORE WATER", "size": "5,000L", "price": "10"},
{"category": "BORE WATER", "size": "10,000L", "price": "14"},
{"category": "BORE WATER", "size": "15,000L", "price": "16"},
{"category": "BORE WATER", "size": "25,000L", "price": null},
];
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_tabController = TabController(length: 3, vsync: this); _tabController = TabController(length: 3, vsync: this);
// Prefill values
drinking5000.text = "₹500"; // Group data by category and initialize controllers for WaterCharges
drinking10000.text = "₹500"; for (final item in data) {
drinking15000.text = "₹500"; final category = item['category'] as String;
bore5000.text = "₹500"; final size = item['size'] as String;
bore10000.text = "₹500"; final price = item['price']?.toString() ?? ""; // default to empty if null
bore15000.text = "₹500";
if (!tankerGroups.containsKey(category)) {
tankerGroups[category] = [];
}
tankerGroups[category]!.add(size);
// Pre-fill controller with price or empty
controllers.putIfAbsent("$category-$size", () => TextEditingController(text: price));
}
// Initialize controllers for unique capacities for DeliveryFee
final capacities = data.map((item) => item['size'] as String).toSet();
for (final cap in capacities) {
// Take first price for this capacity, default to empty if null
final price = data.firstWhere(
(d) => d['size'] == cap,
orElse: () => {'price': ''},
)['price']?.toString() ?? "";
deliveryControllers.putIfAbsent(cap, () => TextEditingController(text: price));
}
}
@override
void dispose() {
// Dispose all controllers
for (final controller in controllers.values) {
controller.dispose();
}
for (final controller in deliveryControllers.values) {
controller.dispose();
}
super.dispose();
} }
Widget buildTextField(String label, TextEditingController controller) { Widget buildTextField(String label, TextEditingController controller) {
return Padding( return Padding(
padding: const EdgeInsets.symmetric(vertical: 8), padding: const EdgeInsets.symmetric(vertical: 8),
child: TextField( child: TextField(
controller: controller, controller: controller,
decoration: InputDecoration( cursorColor: primaryColor,
labelText: label, readOnly: false,
labelStyle: const TextStyle(fontSize: 14, color: Colors.black87), keyboardType: TextInputType.number,
border: OutlineInputBorder( decoration: InputDecoration(
borderRadius: BorderRadius.circular(8), counterText: '',
filled: false,
fillColor: Colors.white,
prefixIconConstraints: BoxConstraints(
minWidth: 24,
minHeight: 24,
),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(4.0),
borderSide: BorderSide(
color: Color(0XFFC3C4C4),
width: 1,
)),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(4.0),
borderSide: BorderSide(
color: Color(0XFF8270DB),
width: 1,
),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(4.0),
borderSide: BorderSide(color: Color(0XFFC3C4C4)),
),
hintText: label,
hintStyle: fontTextStyle(14, Color(0XFF939495), FontWeight.w400),
/* TextStyle(color: greyColor, fontWeight: FontWeight.bold //<-- SEE HERE
),*/
), ),
), style: fontTextStyle(14, Color(0XFF515253), FontWeight.w500),
keyboardType: TextInputType.number, ));
}
Widget labelText(String label) {
return Text(
label,
style: fontTextStyle(12, const Color(0XFF515253), FontWeight.w500),
);
}
Widget WaterCharges() {
return SingleChildScrollView(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
for (final entry in tankerGroups.entries) ...[
Text(
entry.key,
style: fontTextStyle(10, Color(0XFF2D2E30), FontWeight.w600),
),
const SizedBox(height: 8),
for (final size in entry.value)
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
labelText("$size (in ₹)*"),
const SizedBox(height: 4),
buildTextField("₹500", controllers["${entry.key}-$size"]!),
const SizedBox(height: 12),
],
),
const SizedBox(height: 10),
],
SizedBox(
width: double.infinity,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: Color(0XFF8270DB),
foregroundColor: Color(0XFFFFFFFF),
padding: EdgeInsets.symmetric(vertical: 10),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(24), // <-- set your radius here
),
),
onPressed: () {
final Map<String, Map<String, String>> grouped = {};
tankerGroups.forEach((category, sizes) {
grouped[category] = {};
for (final size in sizes) {
grouped[category]![size] =
controllers["$category-$size"]!.text;
}
});
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text("Rates saved successfully")),
);
print(grouped); // Debug: print entered rates
},
child: Text(
"Save",
style: fontTextStyle(14, const Color(0XFFFFFFFF), FontWeight.w600),
),
),
)
],
), ),
); );
} }
@override
Widget build(BuildContext context) { Widget DeliveryFee() {
return SafeArea( // Extract unique capacities
child: Scaffold( final capacities = data.map((item) => item['size'] as String).toSet().toList();
appBar: AppBar(
title: const Text( return SingleChildScrollView(
"Set Rates", padding: const EdgeInsets.all(16),
style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600), child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"ADDITIONAL RATES",
style: fontTextStyle(10, const Color(0xFF2D2E30), FontWeight.w600),
), ),
centerTitle: true, SizedBox(height: MediaQuery.of(context).size.height * .004),
actions: [ Text(
TextButton( "Add your price per Kilometer for every tanker capacity",
onPressed: () {}, style: fontTextStyle(12, const Color(0xFF939495), FontWeight.w400),
child: const Text( ),
"HELP", SizedBox(height: MediaQuery.of(context).size.height * .020),
style: TextStyle(color: Colors.blue, fontSize: 14),
), // 🔹 Dynamic textfields
) for (final cap in capacities) ...[
labelText('$cap tanker (per KM)*'),
SizedBox(height: MediaQuery.of(context).size.height * .004),
buildTextField("+ ₹12", deliveryControllers[cap]!),
const SizedBox(height: 12),
], ],
const SizedBox(height: 10),
SizedBox(
width: double.infinity,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: Color(0XFF8270DB),
foregroundColor: Color(0XFFFFFFFF),
padding: EdgeInsets.symmetric(vertical: 10),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(24), // <-- set your radius here
),
),
onPressed: () {
final Map<String, String> fees = {};
deliveryControllers.forEach((cap, controller) {
fees[cap] = controller.text;
});
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text("Rates saved successfully")),
);
print(fees);
},
child: Text(
"Save",
style: fontTextStyle(14, const Color(0XFFFFFFFF), FontWeight.w600),
),
),
)
],
),
);
}
Widget PumpFee() {
return SingleChildScrollView(
padding: const EdgeInsets.all(16),
child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
Text(
"TANKER TYPE",
style: fontTextStyle(10, Color(0XFF2D2E30), FontWeight.w600),
),
SizedBox(height: MediaQuery.of(context).size.height * .004),
Text(
"Add your price addition for tankers with pump",
style: fontTextStyle(12, Color(0XFF939495), FontWeight.w400),
), ),
body: Column( SizedBox(height: MediaQuery.of(context).size.height * .024),
children: [ labelText('Tanker with pump*'),
const SizedBox(height: 16), SizedBox(height: MediaQuery.of(context).size.height * .004),
const CircleAvatar( buildTextField("+ ₹50 ", pumpFeeController),
radius: 40, SizedBox(height: MediaQuery.of(context).size.height * .024),
backgroundColor: Color(0xFFE0E0E0), SizedBox(
child: Icon(Icons.water_drop_outlined, width: double.infinity,
size: 40, color: Colors.deepPurple), child: ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: Color(0XFF8270DB),
foregroundColor: Color(0XFFFFFFFF),
padding: EdgeInsets.symmetric(vertical: 10),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(24), // <-- set your radius here
),
), ),
const SizedBox(height: 16), onPressed: () {
const Text( // Handle save logic
"Whats todays water price?", ScaffoldMessenger.of(context).showSnackBar(
style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600), const SnackBar(content: Text("Rates saved successfully")),
);
},
child: Text(
"Save",
style: fontTextStyle(14, const Color(0XFFFFFFFF), FontWeight.w600),
), ),
const SizedBox(height: 4), ),
const Text( )
"Set your daily rate so customers know what to expect", ]),
style: TextStyle(fontSize: 13, color: Colors.black54), );
textAlign: TextAlign.center, }
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Color(0XFFFFFFFF),
appBar: AppSettings.supplierAppBarWithActionsText('Set Rates', context),
body: Column(
children: [
Container(
width: double.infinity,
decoration: const BoxDecoration(
color: Color(0XFFF3F1FB),
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(24),
bottomRight: Radius.circular(24),
),
), ),
const SizedBox(height: 20), padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 24),
TabBar( child: Column(
controller: _tabController, children: [
labelColor: Colors.black, SizedBox(height: MediaQuery.of(context).size.height * .096),
unselectedLabelColor: Colors.grey, const CircleAvatar(radius: 50, backgroundColor: Color(0XFFC9C2F0)),
indicatorColor: Colors.deepPurple, SizedBox(height: MediaQuery.of(context).size.height * .016),
tabs: const [ Text(
Tab(text: "Water Type"), "Whats todays water price?",
Tab(text: "Delivery Fee"), style: fontTextStyle(20, Color(0XFF343637), FontWeight.w600),
Tab(text: "Pump"), ),
SizedBox(height: MediaQuery.of(context).size.height * .008),
Text(
"Set your daily rate so customers know what to expect",
style: fontTextStyle(12, Color(0XFF343637), FontWeight.w400),
textAlign: TextAlign.center,
),
], ],
), ),
Expanded( ),
child: TabBarView( const SizedBox(height: 20),
controller: _tabController, Container(
children: [ height: 30,
// Water Type Tab margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
SingleChildScrollView( child: AnimatedBuilder(
padding: const EdgeInsets.all(16), animation: _tabController,
child: Column( builder: (context, _) {
crossAxisAlignment: CrossAxisAlignment.start, return TabBar(
children: [ controller: _tabController,
const Text( indicatorColor: Colors.transparent, // remove underline
"DRINKING WATER", dividerColor: Colors.transparent,
style: TextStyle( isScrollable: false,
fontWeight: FontWeight.bold, fontSize: 14), overlayColor: MaterialStateProperty.all(Colors.transparent),// equal width
), tabs: List.generate(3, (index) {
buildTextField("5,000L (in ₹)", drinking5000), final labels = ['Water Type', 'Delivery Fee','Pump'];
buildTextField("10,000L (in ₹)", drinking10000), final isSelected = _tabController.index == index;
buildTextField("15,000L (in ₹)", drinking15000),
const SizedBox(height: 20), return Container(
const Text( decoration: BoxDecoration(
"BORE WATER", color: isSelected ? const Color(0XFFF1F1F1) : Colors.transparent,
style: TextStyle( borderRadius: BorderRadius.circular(27),
fontWeight: FontWeight.bold, fontSize: 14), ),
alignment: Alignment.center,
child: Text(
labels[index],
style: isSelected ?fontTextStyle(
12,
const Color(0XFF101214),
FontWeight.w600,
):fontTextStyle(
12,
const Color(0XFF646464),
FontWeight.w600,
), ),
buildTextField("5,000L (in ₹)", bore5000), ),
buildTextField("10,000L (in ₹)", bore10000), );
buildTextField("15,000L (in ₹)", bore15000), }),
const SizedBox(height: 30), );
SizedBox( },
width: double.infinity,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: Colors.deepPurple,
padding: const EdgeInsets.symmetric(vertical: 14),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10)),
),
onPressed: () {
// Handle save logic
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text("Rates saved successfully")),
);
},
child: const Text(
"Save",
style:
TextStyle(fontSize: 16, color: Colors.white),
),
),
)
],
),
),
// Delivery Fee Tab
const Center(child: Text("Delivery Fee Settings")),
// Pump Tab
const Center(child: Text("Pump Settings")),
],
),
), ),
], ),
), Expanded(
child: TabBarView(
controller: _tabController,
children: [
// Water Type Tab
WaterCharges(),
// Delivery Fee Tab
DeliveryFee(),
// Pump Tab
PumpFee()
],
),
),
],
), ),
); );
} }

@ -113,6 +113,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.8" version: "1.0.8"
dropdown_button2:
dependency: "direct main"
description:
name: dropdown_button2
sha256: b0fe8d49a030315e9eef6c7ac84ca964250155a6224d491c1365061bc974a9e1
url: "https://pub.dev"
source: hosted
version: "2.3.9"
fake_async: fake_async:
dependency: transitive dependency: transitive
description: description:

@ -32,6 +32,7 @@ dependencies:
geocoding: ^3.0.0 geocoding: ^3.0.0
provider: ^6.0.5 provider: ^6.0.5
google_maps_place_picker_mb: ^3.0.2 google_maps_place_picker_mb: ^3.0.2
dropdown_button2: ^2.0.0
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:

Loading…
Cancel
Save