320 lines
12 KiB
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),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|