|
|
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
|
|
import 'package:supplier_new/common/settings.dart';
|
|
|
|
|
|
|
|
|
|
|
|
class SetRatesScreen extends StatefulWidget {
|
|
|
|
|
|
const SetRatesScreen({super.key});
|
|
|
|
|
|
|
|
|
|
|
|
@override
|
|
|
|
|
|
State<SetRatesScreen> createState() => _SetRatesScreenState();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
class _SetRatesScreenState extends State<SetRatesScreen>
|
|
|
|
|
|
with SingleTickerProviderStateMixin {
|
|
|
|
|
|
late TabController _tabController;
|
|
|
|
|
|
|
|
|
|
|
|
final Map<String, TextEditingController> controllers = {};
|
|
|
|
|
|
// Define categories + tankers
|
|
|
|
|
|
final Map<String, List<String>> tankerGroups = {};
|
|
|
|
|
|
final Map<String, TextEditingController> deliveryControllers = {};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*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
|
|
|
|
|
|
void initState() {
|
|
|
|
|
|
super.initState();
|
|
|
|
|
|
_tabController = TabController(length: 3, vsync: this);
|
|
|
|
|
|
|
|
|
|
|
|
// Group data by category and initialize controllers for WaterCharges
|
|
|
|
|
|
for (final item in data) {
|
|
|
|
|
|
final category = item['category'] as String;
|
|
|
|
|
|
final size = item['size'] as String;
|
|
|
|
|
|
final price = item['price']?.toString() ?? ""; // default to empty if null
|
|
|
|
|
|
|
|
|
|
|
|
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) {
|
|
|
|
|
|
return Padding(
|
|
|
|
|
|
padding: const EdgeInsets.symmetric(vertical: 8),
|
|
|
|
|
|
child: TextField(
|
|
|
|
|
|
controller: controller,
|
|
|
|
|
|
cursorColor: primaryColor,
|
|
|
|
|
|
readOnly: false,
|
|
|
|
|
|
keyboardType: TextInputType.number,
|
|
|
|
|
|
decoration: InputDecoration(
|
|
|
|
|
|
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),
|
|
|
|
|
|
));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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),
|
|
|
|
|
|
),
|
|
|
|
|
|
),
|
|
|
|
|
|
)
|
|
|
|
|
|
],
|
|
|
|
|
|
),
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Widget DeliveryFee() {
|
|
|
|
|
|
// Extract unique capacities
|
|
|
|
|
|
final capacities = data.map((item) => item['size'] as String).toSet().toList();
|
|
|
|
|
|
|
|
|
|
|
|
return SingleChildScrollView(
|
|
|
|
|
|
padding: const EdgeInsets.all(16),
|
|
|
|
|
|
child: Column(
|
|
|
|
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
|
|
|
|
children: [
|
|
|
|
|
|
Text(
|
|
|
|
|
|
"ADDITIONAL RATES",
|
|
|
|
|
|
style: fontTextStyle(10, const Color(0xFF2D2E30), FontWeight.w600),
|
|
|
|
|
|
),
|
|
|
|
|
|
SizedBox(height: MediaQuery.of(context).size.height * .004),
|
|
|
|
|
|
Text(
|
|
|
|
|
|
"Add your price per Kilometer for every tanker capacity",
|
|
|
|
|
|
style: fontTextStyle(12, const Color(0xFF939495), FontWeight.w400),
|
|
|
|
|
|
),
|
|
|
|
|
|
SizedBox(height: MediaQuery.of(context).size.height * .020),
|
|
|
|
|
|
|
|
|
|
|
|
// 🔹 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),
|
|
|
|
|
|
),
|
|
|
|
|
|
SizedBox(height: MediaQuery.of(context).size.height * .024),
|
|
|
|
|
|
labelText('Tanker with pump*'),
|
|
|
|
|
|
SizedBox(height: MediaQuery.of(context).size.height * .004),
|
|
|
|
|
|
buildTextField("+ ₹50 ", pumpFeeController),
|
|
|
|
|
|
SizedBox(height: MediaQuery.of(context).size.height * .024),
|
|
|
|
|
|
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: () {
|
|
|
|
|
|
// Handle save logic
|
|
|
|
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
|
|
|
|
const SnackBar(content: Text("Rates saved successfully")),
|
|
|
|
|
|
);
|
|
|
|
|
|
},
|
|
|
|
|
|
child: Text(
|
|
|
|
|
|
"Save",
|
|
|
|
|
|
style: fontTextStyle(14, const Color(0XFFFFFFFF), FontWeight.w600),
|
|
|
|
|
|
),
|
|
|
|
|
|
),
|
|
|
|
|
|
)
|
|
|
|
|
|
]),
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@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),
|
|
|
|
|
|
),
|
|
|
|
|
|
),
|
|
|
|
|
|
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 24),
|
|
|
|
|
|
child: Column(
|
|
|
|
|
|
children: [
|
|
|
|
|
|
SizedBox(height: MediaQuery.of(context).size.height * .096),
|
|
|
|
|
|
const CircleAvatar(radius: 50, backgroundColor: Color(0XFFC9C2F0)),
|
|
|
|
|
|
SizedBox(height: MediaQuery.of(context).size.height * .016),
|
|
|
|
|
|
Text(
|
|
|
|
|
|
"What’s today’s water price?",
|
|
|
|
|
|
style: fontTextStyle(20, Color(0XFF343637), FontWeight.w600),
|
|
|
|
|
|
),
|
|
|
|
|
|
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,
|
|
|
|
|
|
),
|
|
|
|
|
|
],
|
|
|
|
|
|
),
|
|
|
|
|
|
),
|
|
|
|
|
|
const SizedBox(height: 20),
|
|
|
|
|
|
Container(
|
|
|
|
|
|
height: 30,
|
|
|
|
|
|
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
|
|
|
|
|
child: AnimatedBuilder(
|
|
|
|
|
|
animation: _tabController,
|
|
|
|
|
|
builder: (context, _) {
|
|
|
|
|
|
return TabBar(
|
|
|
|
|
|
controller: _tabController,
|
|
|
|
|
|
indicatorColor: Colors.transparent, // remove underline
|
|
|
|
|
|
dividerColor: Colors.transparent,
|
|
|
|
|
|
isScrollable: false,
|
|
|
|
|
|
overlayColor: MaterialStateProperty.all(Colors.transparent),// equal width
|
|
|
|
|
|
tabs: List.generate(3, (index) {
|
|
|
|
|
|
final labels = ['Water Type', 'Delivery Fee','Pump'];
|
|
|
|
|
|
final isSelected = _tabController.index == index;
|
|
|
|
|
|
|
|
|
|
|
|
return Container(
|
|
|
|
|
|
decoration: BoxDecoration(
|
|
|
|
|
|
color: isSelected ? const Color(0XFFF1F1F1) : Colors.transparent,
|
|
|
|
|
|
borderRadius: BorderRadius.circular(27),
|
|
|
|
|
|
),
|
|
|
|
|
|
alignment: Alignment.center,
|
|
|
|
|
|
child: Text(
|
|
|
|
|
|
labels[index],
|
|
|
|
|
|
style: isSelected ?fontTextStyle(
|
|
|
|
|
|
12,
|
|
|
|
|
|
const Color(0XFF101214),
|
|
|
|
|
|
FontWeight.w600,
|
|
|
|
|
|
):fontTextStyle(
|
|
|
|
|
|
12,
|
|
|
|
|
|
const Color(0XFF646464),
|
|
|
|
|
|
FontWeight.w600,
|
|
|
|
|
|
),
|
|
|
|
|
|
),
|
|
|
|
|
|
);
|
|
|
|
|
|
}),
|
|
|
|
|
|
);
|
|
|
|
|
|
},
|
|
|
|
|
|
),
|
|
|
|
|
|
),
|
|
|
|
|
|
Expanded(
|
|
|
|
|
|
child: TabBarView(
|
|
|
|
|
|
controller: _tabController,
|
|
|
|
|
|
children: [
|
|
|
|
|
|
// Water Type Tab
|
|
|
|
|
|
WaterCharges(),
|
|
|
|
|
|
// Delivery Fee Tab
|
|
|
|
|
|
DeliveryFee(),
|
|
|
|
|
|
// Pump Tab
|
|
|
|
|
|
PumpFee()
|
|
|
|
|
|
],
|
|
|
|
|
|
),
|
|
|
|
|
|
),
|
|
|
|
|
|
],
|
|
|
|
|
|
),
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|