marco.pms.mobileapp/lib/model/expense/add_expense_bottom_sheet.dart

320 lines
12 KiB
Dart

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:marco/helpers/widgets/my_text.dart';
void showAddExpenseBottomSheet() {
final TextEditingController amountController = TextEditingController();
final TextEditingController descriptionController = TextEditingController();
final TextEditingController supplierController = TextEditingController();
final TextEditingController transactionIdController = TextEditingController();
final TextEditingController gstController = TextEditingController();
String selectedProject = "Select Project";
String selectedCategory = "Select Expense Type";
String selectedPaymentMode = "Select Payment Mode";
String selectedLocation = "Select Location";
bool preApproved = false;
Get.bottomSheet(
StatefulBuilder(
builder: (context, setState) {
return SafeArea(
child: Padding(
padding:
const EdgeInsets.only(top: 60),
child: Material(
color: Colors.white,
borderRadius:
const BorderRadius.vertical(top: Radius.circular(20)),
child: Container(
constraints: BoxConstraints(
maxHeight: MediaQuery.of(context).size.height - 60,
),
padding: const EdgeInsets.fromLTRB(16, 12, 16, 24),
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Drag Handle
Center(
child: Container(
width: 40,
height: 4,
margin: const EdgeInsets.only(bottom: 16),
decoration: BoxDecoration(
color: Colors.grey.shade400,
borderRadius: BorderRadius.circular(2),
),
),
),
// Title
Center(
child: MyText.titleLarge(
"Add Expense",
fontWeight: 700,
),
),
const SizedBox(height: 20),
// Project
_sectionTitle(Icons.work_outline, "Project"),
const SizedBox(height: 6),
_dropdownTile(
title: selectedProject,
onTap: () {
setState(() {
selectedProject = "Project A";
});
},
),
const SizedBox(height: 16),
// Expense Type + GST
_sectionTitle(
Icons.category_outlined, "Expense Type & GST No."),
const SizedBox(height: 6),
_dropdownTile(
title: selectedCategory,
onTap: () {
setState(() {
selectedCategory = "Travel Expense";
});
},
),
const SizedBox(height: 8),
_customTextField(
controller: gstController,
hint: "Enter GST No.",
),
const SizedBox(height: 16),
// Payment Mode
_sectionTitle(Icons.payment, "Payment Mode"),
const SizedBox(height: 6),
_dropdownTile(
title: selectedPaymentMode,
onTap: () {
setState(() {
selectedPaymentMode = "UPI";
});
},
),
const SizedBox(height: 16),
// Paid By
_sectionTitle(Icons.person, "Paid By (Employee)"),
const SizedBox(height: 6),
_dropdownTile(
title: "Self (Default)",
onTap: () {},
),
const SizedBox(height: 16),
// Transaction Date
_sectionTitle(Icons.calendar_today, "Transaction Date"),
const SizedBox(height: 6),
_dropdownTile(
title: "Select Date & Time",
onTap: () async {
// Add date/time picker
},
),
const SizedBox(height: 16),
// Amount
_sectionTitle(Icons.currency_rupee, "Amount"),
const SizedBox(height: 6),
_customTextField(
controller: amountController,
hint: "Enter Amount",
keyboardType: TextInputType.number,
),
const SizedBox(height: 16),
// Supplier
_sectionTitle(Icons.store_mall_directory,
"Supplier Name / Expense Done At"),
const SizedBox(height: 6),
_customTextField(
controller: supplierController,
hint: "Enter Supplier Name",
),
const SizedBox(height: 16),
// Location
_sectionTitle(Icons.location_on_outlined, "Location"),
const SizedBox(height: 6),
_dropdownTile(
title: selectedLocation,
onTap: () {
setState(() {
selectedLocation = "Pune";
});
},
),
const SizedBox(height: 16),
// Description
_sectionTitle(Icons.description_outlined, "Description"),
const SizedBox(height: 6),
_customTextField(
controller: descriptionController,
hint: "Enter Description",
maxLines: 3,
),
const SizedBox(height: 16),
// Bill Attachment
_sectionTitle(Icons.attachment, "Bill Attachment"),
const SizedBox(height: 6),
OutlinedButton.icon(
onPressed: () {},
icon: const Icon(Icons.upload_file),
label: const Text("Upload Bill"),
style: OutlinedButton.styleFrom(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
),
),
),
const SizedBox(height: 16),
// Transaction ID
_sectionTitle(
Icons.confirmation_num_outlined, "Transaction ID"),
const SizedBox(height: 6),
_customTextField(
controller: transactionIdController,
hint: "Enter Transaction ID",
),
const SizedBox(height: 16),
// Pre-Approved Switch
Row(
children: [
Switch(
value: preApproved,
onChanged: (val) =>
setState(() => preApproved = val),
activeColor: Colors.red,
),
const SizedBox(width: 8),
const Text("Pre-Approved?"),
],
),
const SizedBox(height: 24),
// Action Buttons
Row(
children: [
Expanded(
child: OutlinedButton.icon(
onPressed: () => Get.back(),
icon: const Icon(Icons.close, size: 18),
label:
MyText.bodyMedium("Cancel", fontWeight: 600),
style: OutlinedButton.styleFrom(
side: const BorderSide(color: Colors.grey),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
),
),
),
const SizedBox(width: 12),
Expanded(
child: ElevatedButton.icon(
onPressed: () {
// Handle Save
Get.back();
},
icon: const Icon(Icons.check, size: 18),
label: MyText.bodyMedium(
"Submit",
color: Colors.white,
fontWeight: 600,
),
style: ElevatedButton.styleFrom(
backgroundColor: Colors.indigo,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
),
),
),
],
),
],
),
),
),
),
),
);
},
),
isScrollControlled: true,
);
}
/// Section Title
Widget _sectionTitle(IconData icon, String title) {
return Row(
children: [
Icon(icon, color: Colors.grey[700], size: 18),
const SizedBox(width: 8),
MyText.bodyMedium(title, fontWeight: 600),
],
);
}
/// Custom TextField
Widget _customTextField({
required TextEditingController controller,
required String hint,
int maxLines = 1,
TextInputType keyboardType = TextInputType.text,
}) {
return TextField(
controller: controller,
maxLines: maxLines,
keyboardType: keyboardType,
decoration: InputDecoration(
hintText: hint,
filled: true,
fillColor: Colors.grey.shade100,
border: OutlineInputBorder(borderRadius: BorderRadius.circular(8)),
contentPadding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
),
);
}
/// Dropdown Tile
Widget _dropdownTile({required String title, required VoidCallback onTap}) {
return GestureDetector(
onTap: onTap,
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 14),
decoration: BoxDecoration(
color: Colors.grey.shade100,
borderRadius: BorderRadius.circular(8),
border: Border.all(color: Colors.grey.shade300),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: Text(
title,
style: const TextStyle(fontSize: 14, color: Colors.black87),
overflow: TextOverflow.ellipsis,
),
),
const Icon(Icons.arrow_drop_down),
],
),
),
);
}