Flutter预订服务插件flutter_booking的使用
Flutter预订服务插件flutter_booking的使用
预订日历
想要在你的应用中实现在线预订功能吗?那么你无需再寻找其他解决方案了!
仅需四行代码,你就可以获得一个实时跟踪预订情况的在线预订系统。它会计算日历中可能发生的冲突,并以不同的颜色展示这些冲突。
你可以通过多种可选参数自定义你的预订日历。
使用方法
更多详细信息可以查看示例代码:
Widget build(BuildContext context) {
return BookingCalendar(
key: key,
/// 这些是必需的参数
getBookingStream: getBookingStream,
uploadBooking: uploadBooking,
convertStreamResultToDateTimeRanges: convertStreamResultToDateTimeRanges,
/// 这些是可选的自定义参数
bookingButtonColor: bookingButtonColor,
bookingButtonText: bookingButtonText,
bookingExplanation: bookingExplanation,
bookingGridChildAspectRatio: bookingGridChildAspectRatio,
bookingGridCrossAxisCount: bookingGridCrossAxisCount,
formatDateTime: formatDateTime,
convertStreamResultToDateTimeRanges:
convertStreamResultToDateTimeRanges,
availableSlotColor: availableSlotColor,
availableSlotText: availableSlotText,
bookedSlotColor: bookedSlotColor,
bookedSlotText: bookedSlotText,
selectedSlotColor: selectedSlotColor,
selectedSlotText: selectedSlotText,
gridScrollPhysics: gridScrollPhysics,
loadingWidget: loadingWidget,
errorWidget: errorWidget,
uploadingWidget: uploadingWidget,
pauseSlotColor: pauseSlotColor,
pauseSlotText: pauseSlotText,
hideBreakTime: hideBreakTime,
locale: locale,
disabledDays: disabledDays,
startingDayOfWeek: startingDayOfWeek,
);
}
Firebase 示例
在成功将 Firebase 集成到你的应用之后,请参考以下步骤:如何在 Flutter 中设置 Firebase
在这个例子中,我们将使用 Firebase Firestore 来预订体育场地。
存储在 Firebase 中的模型
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:json_annotation/json_annotation.dart';
import 'package:sport.bp/util/app_util.dart';
part 'sport_booking.g.dart';
@JsonSerializable(explicitToJson: true)
class SportBooking {
/// 假设 JSON 中存在这些值。
final String? userId;
final String? userName;
final String? placeId;
final String? serviceName;
final int? serviceDuration;
final int? servicePrice;
// 因为我们存储的是时间戳,所以需要一个 DateTime 的转换器
/* static DateTime timeStampToDateTime(Timestamp timestamp) {
return DateTime.parse(timestamp.toDate().toString());
}
static Timestamp dateTimeToTimeStamp(DateTime? dateTime) {
return Timestamp.fromDate(dateTime ?? DateTime.now()); // 转换为时间戳
}*/
@JsonKey(fromJson: AppUtil.timeStampToDateTime, toJson: AppUtil.dateTimeToTimeStamp)
final DateTime? bookingStart;
@JsonKey(fromJson: AppUtil.timeStampToDateTime, toJson: AppUtil.dateTimeToTimeStamp)
final DateTime? bookingEnd;
final String? email;
final String? phoneNumber;
final String? placeAddress;
SportBooking(
{this.email,
this.phoneNumber,
this.placeAddress,
this.bookingStart,
this.bookingEnd,
this.placeId,
this.userId,
this.userName,
this.serviceName,
this.serviceDuration,
this.servicePrice});
/// 将生成的 [_$SportBookingFromJson] 函数连接到 `fromJson` 工厂。
factory SportBooking.fromJson(Map<String, dynamic> json) => _$SportBookingFromJson(json);
/// 将生成的 [_$SportBookingToJson] 函数连接到 `toJson` 方法。
Map<String, dynamic> toJson() => _$SportBookingToJson(this);
}
Firebase 中的数据结构
在 Firebase 初始化后,我们可以访问 Firestore 集合。
CollectionReference bookings = FirebaseFirestore.instance.collection('bookings');
/// 获取集合中的数据引用,并通过 Firestore 的 [withConverter] 序列化数据。
CollectionReference<SportBooking> getBookingStream({required String placeId}) {
return bookings.doc(placeId).collection('bookings').withConverter<SportBooking>(
fromFirestore: (snapshots, _) => SportBooking.fromJson(snapshots.data()!),
toFirestore: (snapshots, _) => snapshots.toJson(),
);
}
/// 通过之前的方法从 Firestore 获取数据流
/// 注意,这些查询过滤器适用于我的数据结构,你需要根据自己的需求调整。
Stream<dynamic>? getBookingStreamFirebase(
{required DateTime end, required DateTime start}) {
return ApiRepository
.getBookingStream(placeId: 'YOUR_DOC_ID')
.where('bookingStart', isGreaterThanOrEqualTo: start)
.where('bookingStart', isLessThanOrEqualTo: end)
.snapshots(),
}
/// 在从 Firestore 获取数据后,我们需要将预订列表转换为 DateTimeRange 列表:
List<DateTimeRange> convertStreamResultFirebase(
{required dynamic streamResult}) {
/// 这里你可以解析流结果并将其转换为 [List<DateTimeRange>]。
/// 注意,这是动态的,因此你需要知道结果中可用的属性,在我们的例子中,[SportBooking] 有 bookingStart 和 bookingEnd 属性。
List<DateTimeRange> converted = [];
for (var i = 0; i < streamResult.size; i++) {
final item = streamResult.docs[i].data();
converted.add(DateTimeRange(start: (item.bookingStart!), end: (item.bookingEnd!)));
}
return converted;
}
/// 向 Firestore 上传数据
Future<dynamic> uploadBookingFirebase(
{required BookingService newBooking}) async {
await bookings
.doc('your id, or autogenerate')
.collection('bookings')
.add(newBooking.toJson())
.then((value) => print("Booking Added"))
.catchError((error) => print("Failed to add booking: $error"));
}
/** 在完成所有辅助函数后,你可以将它们传递给你的 BookingCalendar */
BookingCalendar(
bookingService: mockBookingService,
convertStreamResultToDateTimeRanges: convertStreamResultFirebase,
getBookingStream: getBookingStreamFirebase,
uploadBooking: uploadBookingFirebase,
uploadingWidget: const CircularProgressIndicator(),
// ... 其他自定义属性
),
更多关于Flutter预订服务插件flutter_booking的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter预订服务插件flutter_booking的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
flutter_booking
是一个用于在 Flutter 应用中实现预订服务的插件。它可以帮助你轻松地集成预订功能,如选择日期、时间、服务类型等。以下是如何使用 flutter_booking
插件的基本步骤:
1. 添加依赖
首先,你需要在 pubspec.yaml
文件中添加 flutter_booking
插件的依赖。
dependencies:
flutter:
sdk: flutter
flutter_booking: ^1.0.0 # 请使用最新版本
然后运行 flutter pub get
来获取依赖。
2. 导入插件
在你的 Dart 文件中导入 flutter_booking
插件。
import 'package:flutter_booking/flutter_booking.dart';
3. 使用 BookingWidget
flutter_booking
插件提供了一个 BookingWidget
,你可以将其添加到你的应用中。这个组件允许用户选择日期、时间、服务类型等。
class BookingPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('预订服务'),
),
body: BookingWidget(
onBookingComplete: (BookingDetails details) {
// 处理预订完成后的逻辑
print('预订成功: $details');
},
availableServices: [
Service(name: '按摩', duration: Duration(hours: 1)),
Service(name: '理发', duration: Duration(minutes: 30)),
Service(name: '美甲', duration: Duration(minutes: 45)),
],
availableDates: [
DateTime.now(),
DateTime.now().add(Duration(days: 1)),
DateTime.now().add(Duration(days: 2)),
],
availableTimes: [
TimeOfDay(hour: 9, minute: 0),
TimeOfDay(hour: 10, minute: 0),
TimeOfDay(hour: 11, minute: 0),
],
),
);
}
}
4. 处理预订完成后的逻辑
当用户完成预订后,onBookingComplete
回调会被触发。你可以在这里处理预订完成后的逻辑,例如将预订信息保存到数据库或显示确认信息。
onBookingComplete: (BookingDetails details) {
// 处理预订完成后的逻辑
print('预订成功: $details');
// 例如,显示一个确认对话框
showDialog(
context: context,
builder: (context) => AlertDialog(
title: Text('预订成功'),
content: Text('您已成功预订 ${details.service.name} 于 ${details.date} ${details.time}。'),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: Text('确定'),
),
],
),
);
},
5. 自定义 Service
和 BookingDetails
你可以自定义 Service
和 BookingDetails
类来满足你的需求。例如,你可以添加更多的字段来存储服务的价格、描述等信息。
class Service {
final String name;
final Duration duration;
final double price;
Service({
required this.name,
required this.duration,
this.price = 0.0,
});
}
class BookingDetails {
final Service service;
final DateTime date;
final TimeOfDay time;
BookingDetails({
required this.service,
required this.date,
required this.time,
});
@override
String toString() {
return 'BookingDetails(service: $service, date: $date, time: $time)';
}
}
6. 运行应用
现在你可以运行你的 Flutter 应用,并在应用中使用 flutter_booking
插件来实现预订服务功能。
7. 进一步定制
根据你的需求,你可以进一步定制 BookingWidget
的外观和行为。例如,你可以自定义日期选择器、时间选择器、服务选择器等。
8. 处理异常
在实际应用中,你可能需要处理一些异常情况,例如用户未选择日期或时间、服务不可用等。你可以在 onBookingComplete
回调中添加相应的逻辑来处理这些情况。
9. 集成后端服务
如果你的应用需要将预订信息保存到服务器,你可以在 onBookingComplete
回调中调用 API 将预订信息发送到后端。
onBookingComplete: (BookingDetails details) async {
// 调用 API 保存预订信息
final response = await http.post(
Uri.parse('https://your-api-endpoint.com/bookings'),
body: {
'service': details.service.name,
'date': details.date.toIso8601String(),
'time': details.time.format(context),
},
);
if (response.statusCode == 200) {
// 预订成功
showDialog(
context: context,
builder: (context) => AlertDialog(
title: Text('预订成功'),
content: Text('您已成功预订 ${details.service.name} 于 ${details.date} ${details.time}。'),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: Text('确定'),
),
],
),
);
} else {
// 预订失败
showDialog(
context: context,
builder: (context) => AlertDialog(
title: Text('预订失败'),
content: Text('预订失败,请稍后重试。'),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: Text('确定'),
),
],
),
);
}
},