fixed select item and add more than one services in appointment
parent
dce3638761
commit
1e22570a1c
@ -0,0 +1,224 @@
|
||||
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:mc_common_app/generated/locale_keys.g.dart';
|
||||
import 'package:mc_common_app/models/services_models/item_model.dart';
|
||||
import 'package:mc_common_app/theme/colors.dart';
|
||||
import 'package:mc_common_app/view_models/service_view_model.dart';
|
||||
import 'package:mc_common_app/widgets/dropdown/dropdow_field.dart';
|
||||
import 'package:mc_common_app/widgets/bottom_sheet.dart';
|
||||
import 'package:car_provider_app/views/appoinments/widget/select_items_sheet.dart';
|
||||
import 'package:car_provider_app/views/branch_management/schedule/widgets/chips_picker_item.dart';
|
||||
import 'package:mc_common_app/models/appointments_models/selected_appointment_service_model.dart';
|
||||
import 'package:car_provider_app/views/branch_management/schedule/widgets/chips_picker_item.dart';
|
||||
|
||||
|
||||
class AddAppointmentServiceBottomSheet extends StatefulWidget {
|
||||
final int branchId;
|
||||
final SelectedAppointmentServiceModel? initialService;
|
||||
|
||||
const AddAppointmentServiceBottomSheet({
|
||||
super.key,
|
||||
required this.branchId,
|
||||
this.initialService,
|
||||
});
|
||||
|
||||
@override
|
||||
State<AddAppointmentServiceBottomSheet> createState() =>
|
||||
_AddAppointmentServiceBottomSheetState();
|
||||
}
|
||||
|
||||
class _AddAppointmentServiceBottomSheetState
|
||||
extends State<AddAppointmentServiceBottomSheet> {
|
||||
DropValue? category;
|
||||
DropValue? service;
|
||||
List<ItemData> selectedItems = [];
|
||||
bool isLoadingServices = false;
|
||||
String? loadError;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
category = widget.initialService?.category;
|
||||
service = widget.initialService?.service;
|
||||
selectedItems = List.of(widget.initialService?.items ?? []);
|
||||
if (category != null) {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
if (mounted) _loadServices(category!.id);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _loadServices(int categoryId) async {
|
||||
setState(() {
|
||||
isLoadingServices = true;
|
||||
loadError = null;
|
||||
});
|
||||
try {
|
||||
await context.read<ServiceVM>().fetchProviderServices(
|
||||
widget.branchId.toString(),
|
||||
categoryId.toString(),
|
||||
);
|
||||
} catch (e) {
|
||||
if (mounted) loadError = e.toString();
|
||||
} finally {
|
||||
if (mounted) setState(() => isLoadingServices = false);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _openItemsSheet() async {
|
||||
if (service == null) return;
|
||||
final serviceId = service!.id;
|
||||
final pickedItems = selectedItems
|
||||
.map((item) => PickerItem(id: item.id ?? 0, title: item.name ?? ''))
|
||||
.toList();
|
||||
|
||||
showMyBottomSheet(
|
||||
context,
|
||||
child: SelectItemsSheet(
|
||||
serviceId: serviceId,
|
||||
list: pickedItems,
|
||||
onSelectItems: (items) {
|
||||
if (!mounted) return;
|
||||
setState(() => selectedItems = List.of(items));
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _confirm() {
|
||||
if (category == null || service == null || selectedItems.isEmpty) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text(LocaleKeys.pleaseSelectItems.tr())),
|
||||
);
|
||||
return;
|
||||
}
|
||||
Navigator.of(context).pop(
|
||||
SelectedAppointmentServiceModel(
|
||||
category: category!,
|
||||
service: service!,
|
||||
items: List.of(selectedItems),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SizedBox(
|
||||
height: MediaQuery.of(context).size.height * 0.85,
|
||||
child: SafeArea(
|
||||
top: false,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(20),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Center(
|
||||
child: Container(
|
||||
width: 60,
|
||||
height: 6,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.grey.shade300,
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
Text(
|
||||
LocaleKeys.selectServiceDetails.tr(),
|
||||
style: const TextStyle(fontSize: 22, fontWeight: FontWeight.bold),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
child: Consumer<ServiceVM>(
|
||||
builder: (context, serviceVm, _) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
DropdownField(
|
||||
(value) {
|
||||
setState(() {
|
||||
category = value;
|
||||
service = null;
|
||||
selectedItems.clear();
|
||||
});
|
||||
_loadServices(value.id);
|
||||
},
|
||||
dropdownValue: category,
|
||||
list: serviceVm.categoryDropList,
|
||||
hint: LocaleKeys.selectServiceCategory.tr(),
|
||||
isSelectAble: !isLoadingServices,
|
||||
),
|
||||
if (category != null) ...[
|
||||
const SizedBox(height: 16),
|
||||
if (isLoadingServices)
|
||||
const Center(child: CircularProgressIndicator())
|
||||
else if (loadError != null)
|
||||
TextButton(
|
||||
onPressed: () => _loadServices(category!.id),
|
||||
child: const Text('Retry loading services'),
|
||||
)
|
||||
else
|
||||
DropdownField(
|
||||
(value) {
|
||||
setState(() {
|
||||
service = value;
|
||||
selectedItems.clear();
|
||||
});
|
||||
},
|
||||
dropdownValue: service,
|
||||
list: serviceVm.servicesDropList,
|
||||
hint: LocaleKeys.defineServices.tr(),
|
||||
),
|
||||
],
|
||||
if (service != null) ...[
|
||||
const SizedBox(height: 16),
|
||||
ChipsPickerItem(
|
||||
isNeedLabelOnTop: true,
|
||||
hint: LocaleKeys.selectItems.tr(),
|
||||
itemsList: selectedItems.map((item) {
|
||||
return PickerItem(
|
||||
id: item.id ?? 0,
|
||||
title: item.name ?? "",
|
||||
);
|
||||
}).toList(),
|
||||
onClick: () {
|
||||
_openItemsSheet();
|
||||
},
|
||||
),
|
||||
...selectedItems.map(
|
||||
(item) => ListTile(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
title: Text(item.name ?? ''),
|
||||
trailing: Text('${item.price ?? '0'} SAR'),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
child: ElevatedButton(
|
||||
onPressed: isLoadingServices ? null : _confirm,
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: MyColors.darkPrimaryColor,
|
||||
foregroundColor: Colors.white,
|
||||
minimumSize: const Size.fromHeight(50),
|
||||
),
|
||||
child: Text(LocaleKeys.next.tr()),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue