done landscape responsive of all screen

This commit is contained in:
Manish 2025-11-18 10:50:50 +05:30
parent c005d2574c
commit a79ab9fcab
2 changed files with 140 additions and 38 deletions

View File

@ -78,6 +78,7 @@ class _PaymentRequestBottomSheetState extends State<_PaymentRequestBottomSheet>
'name': data["projectName"], 'name': data["projectName"],
}; };
controller.selectedPayee.value = data["payee"] ?? ""; controller.selectedPayee.value = data["payee"] ?? "";
controller.isAdvancePayment.value = data["isAdvancePayment"] ?? false; controller.isAdvancePayment.value = data["isAdvancePayment"] ?? false;
@ -142,7 +143,38 @@ class _PaymentRequestBottomSheetState extends State<_PaymentRequestBottomSheet>
} else { } else {
success = await controller.submitPaymentRequest(); success = await controller.submitPaymentRequest();
} }
return Obx(() => SafeArea(
child: Form(
key: _formKey,
child: BaseBottomSheet(
title: widget.isEdit
? "Edit Payment Request"
: "Create Payment Request",
isSubmitting: controller.isSubmitting.value,
onCancel: Get.back,
submitText: "Save as Draft",
onSubmit: () async {
if (_formKey.currentState!.validate() &&
_validateSelections()) {
bool success = false;
if (widget.isEdit && widget.existingData != null) {
final requestId =
widget.existingData!['id']?.toString() ?? '';
if (requestId.isNotEmpty) {
success = await controller.submitEditedPaymentRequest(
requestId: requestId);
} else {
_showError("Invalid Payment Request ID");
return;
}
} else {
success = await controller.submitPaymentRequest();
}
if (success) {
Get.back();
widget.onUpdated?.call();
if (success) { if (success) {
Get.back(); Get.back();
widget.onUpdated?.call(); widget.onUpdated?.call();
@ -157,6 +189,23 @@ class _PaymentRequestBottomSheetState extends State<_PaymentRequestBottomSheet>
} }
} }
}, },
child: SingleChildScrollView(
padding: const EdgeInsets.only(bottom: 20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
_buildDropdown(
showAppSnackbar(
title: "Success",
message: widget.isEdit
? "Payment request updated successfully!"
: "Payment request created successfully!",
type: SnackbarType.success,
);
}
}
},
child: SingleChildScrollView( child: SingleChildScrollView(
padding: const EdgeInsets.only(bottom: 20), padding: const EdgeInsets.only(bottom: 20),
child: Column( child: Column(
@ -174,6 +223,10 @@ class _PaymentRequestBottomSheetState extends State<_PaymentRequestBottomSheet>
key: _projectDropdownKey, key: _projectDropdownKey,
), ),
_gap(), _gap(),
_buildDropdown(
key: _projectDropdownKey,
),
_gap(),
_buildDropdown( _buildDropdown(
"Expense Category", "Expense Category",
Icons.category_outlined, Icons.category_outlined,
@ -208,7 +261,7 @@ class _PaymentRequestBottomSheetState extends State<_PaymentRequestBottomSheet>
? null ? null
: "Enter valid amount"), : "Enter valid amount"),
_gap(), _gap(),
_buildPayeeField(), _buildPayeeAutocompleteField(),
_gap(), _gap(),
_buildDropdown( _buildDropdown(
"Currency", "Currency",
@ -230,6 +283,19 @@ class _PaymentRequestBottomSheetState extends State<_PaymentRequestBottomSheet>
_buildAttachmentsSection(), _buildAttachmentsSection(),
MySpacing.height(30), MySpacing.height(30),
], ],
),
key: _currencyDropdownKey,
),
_gap(),
_buildTextField("Description", Icons.description_outlined,
controller.descriptionController,
hint: "Enter description",
maxLines: 3,
validator: Validators.requiredField),
_gap(),
_buildAttachmentsSection(),
MySpacing.height(30),
],
), ),
), ),
), ),
@ -297,6 +363,7 @@ class _PaymentRequestBottomSheetState extends State<_PaymentRequestBottomSheet>
final label = entry.value; final label = entry.value;
final value = i == 0; final value = i == 0;
return Expanded( return Expanded(
child: RadioListTile<bool>( child: RadioListTile<bool>(
contentPadding: EdgeInsets.zero, contentPadding: EdgeInsets.zero,
@ -353,27 +420,67 @@ class _PaymentRequestBottomSheetState extends State<_PaymentRequestBottomSheet>
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
const SectionTitle( SectionTitle(
icon: Icons.person_outline, icon: Icons.person_outline, title: "Payee", requiredField: true),
title: "Payee", const SizedBox(height: 6),
requiredField: true, Autocomplete<String>(
optionsBuilder: (textEditingValue) {
final query = textEditingValue.text.toLowerCase();
return query.isEmpty
? const Iterable<String>.empty()
: controller.payees
.where((p) => p.toLowerCase().contains(query));
},
displayStringForOption: (option) => option,
fieldViewBuilder:
(context, fieldController, focusNode, onFieldSubmitted) {
WidgetsBinding.instance.addPostFrameCallback((_) {
if (fieldController.text != controller.selectedPayee.value) {
fieldController.text = controller.selectedPayee.value;
fieldController.selection = TextSelection.fromPosition(
TextPosition(offset: fieldController.text.length));
}
});
return TextFormField(
controller: fieldController,
focusNode: focusNode,
decoration: InputDecoration(
hintText: "Type or select payee",
filled: true,
fillColor: Colors.grey.shade100,
contentPadding:
const EdgeInsets.symmetric(horizontal: 12, vertical: 14),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide: BorderSide(color: Colors.grey.shade300),
),
),
validator: (v) =>
v == null || v.trim().isEmpty ? "Please enter payee" : null,
onChanged: (val) => controller.selectedPayee.value = val,
);
},
onSelected: (selection) => controller.selectedPayee.value = selection,
optionsViewBuilder: (context, onSelected, options) => Material(
color: Colors.white,
elevation: 4,
borderRadius: BorderRadius.circular(8),
child: ConstrainedBox(
constraints: const BoxConstraints(maxHeight: 200, minWidth: 300),
child: ListView.builder(
padding: EdgeInsets.zero,
itemCount: options.length,
itemBuilder: (_, index) => InkWell(
onTap: () => onSelected(options.elementAt(index)),
child: Container(
padding: const EdgeInsets.symmetric(
vertical: 10, horizontal: 12),
child: Text(options.elementAt(index),
style: const TextStyle(fontSize: 14)),
),
), ),
MySpacing.height(6),
GestureDetector(
onTap: _showPayeeSelector,
child: TileContainer(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: Obx(() => Text(
controller.selectedPayee.value?.name ?? "Select Payee",
style: const TextStyle(fontSize: 15),
overflow: TextOverflow.ellipsis,
)),
), ),
const Icon(Icons.arrow_drop_down, size: 22),
],
), ),
), ),
), ),

View File

@ -50,6 +50,7 @@ class _AdvancePaymentScreenState extends State<AdvancePaymentScreen>
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
backgroundColor: const Color(0xFFF5F5F5),
backgroundColor: const Color(0xFFF5F5F5), backgroundColor: const Color(0xFFF5F5F5),
appBar: _buildAppBar(), appBar: _buildAppBar(),
body: SafeArea( body: SafeArea(
@ -58,7 +59,9 @@ class _AdvancePaymentScreenState extends State<AdvancePaymentScreen>
final bool isLandscape = final bool isLandscape =
constraints.maxWidth > constraints.maxHeight; constraints.maxWidth > constraints.maxHeight;
return RefreshIndicator( return GestureDetector(
onTap: () => FocusScope.of(context).unfocus(),
child: RefreshIndicator(
onRefresh: () async { onRefresh: () async {
final emp = controller.selectedEmployee.value; final emp = controller.selectedEmployee.value;
if (emp != null) { if (emp != null) {
@ -69,14 +72,6 @@ class _AdvancePaymentScreenState extends State<AdvancePaymentScreen>
backgroundColor: contentTheme.primary, backgroundColor: contentTheme.primary,
strokeWidth: 2.5, strokeWidth: 2.5,
displacement: 60, displacement: 60,
child: GestureDetector(
behavior: HitTestBehavior.translucent,
onTap: () {
FocusScopeNode currentFocus = FocusScope.of(context);
if (!currentFocus.hasPrimaryFocus) {
currentFocus.unfocus();
}
},
// ---------------- PORTRAIT (UNCHANGED) ---------------- // ---------------- PORTRAIT (UNCHANGED) ----------------
child: !isLandscape child: !isLandscape