【问题标题】:Advice with method please请用方法建议
【发布时间】:2020-07-23 19:14:20
【问题描述】:

在我有时间回答之前再次发布!

我一直在想这个问题!....我以为我已经破解了它,但似乎没有。所以我正在制作一个简单的预订系统,需要防止重复预订。

所以我使用 Date TicketType Place Plot 之类的变量创建了一个文档,我将这些变量结合起来并插入到 firebase 中。因此,在给定的日期和情节上,一个人可以预订类型为 Day Night,24 小时的票。我已经做到了,所以代码检查了我上面提到的创建的文档。这很有效,因为您无法预订任何同类型的机票。所以我的问题是,如果用户选择日票或夜票,我仍然可以在同一天预订 24 小时票。任何人都可以帮助我一些逻辑或示例代码如何防止这种情况发生。

一些代码

import 'dart:ui';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:flutter_form_builder/flutter_form_builder.dart';
import 'package:intl/intl.dart';
import 'package:swimfinder/Models/swimlakes.dart';
import 'package:swimfinder/common_widgets/provider_widget.dart';

class Booking extends StatefulWidget {
  @override
  _Booking createState() => _Booking();
  final String name;
  const Booking({
    Key key,
    @required this.name,
  }) : super(key: key);
}

class _Booking extends State<Booking> {
  SwimLake lake = SwimLake();

  @override
  void initState() {
    _loadCurrentUser();
    getLakeData();
    super.initState();
  }

  void _loadCurrentUser() {
    FirebaseAuth.instance.currentUser().then((FirebaseUser user) {
      setState(() {
        this.currentUser = user;
      });
    });
  }

  getLakeData() async {
    await Firestore.instance
        .collection('swimfinderlakes')
        .document(widget.name)
        .get()
        .then((result) {
      //lake.active = result.data['active'];
      lake.address = result.data['address'];
      //lake.advert = result.data['advert'];
      lake.description = result.data['description'];
      lake.email = result.data['email'];
      lake.id = result.data['id'];;
      lake.name = result.data['name'];
      lake.swimplots = result.data['swimplots'];
      lake.telephone = result.data['telephone'];
      lake.website = result.data['website'];
    });
  }

  FirebaseUser currentUser;
  var data;
  bool autoValidate = true;
  bool readOnly = false;
  bool showSegmentedControl = true;
  final GlobalKey<FormBuilderState> _fbKey = GlobalKey<FormBuilderState>();
  List<String> plots = [];

  @override
  Widget build(BuildContext context) {
    return FutureBuilder(
      future: Provider.of(context).auth.getCurrentUser(),
      builder: (context, snapshot) {
        if (snapshot.hasError) {
          return Center(child: CircularProgressIndicator());
        } else if (snapshot.connectionState == ConnectionState.done) {
          return lakebookingage(context, snapshot);
        } else {
          return Center(child: CircularProgressIndicator());
        }
      },
    );
  }

  Widget lakebookingage(context, snapshot) {
    return FutureBuilder(
        future: getLakeData(),
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.done) {
            plots = lake.swimplots.split(',');
            return MaterialApp(
                home: Scaffold(
                    appBar: AppBar(
                      title: Text(
                        lake.name,
                        style: TextStyle(
                          fontSize: 18.0,
                          fontWeight: FontWeight.w700,
                          color: Colors.white,
                        ),
                      ),
                      backgroundColor: Color.fromRGBO(70, 109, 69, 1.0),
                      automaticallyImplyLeading: false,
                      leading: IconButton(
                        icon: Icon(
                          Icons.keyboard_backspace,
                        ),
                        onPressed: () => Navigator.pop(context),
                      ),
                    ),
                    body: Stack(children: <Widget>[
                      Container(
                        constraints: BoxConstraints.expand(),
                        decoration: BoxDecoration(
                          image: DecorationImage(
                            image: NetworkImage(lake.mainimage),
                            fit: BoxFit.cover,
                          ),
                        ),
                        child: ClipRRect(
                          child: BackdropFilter(
                            filter: ImageFilter.blur(sigmaX: 1, sigmaY: 1),
                            child: Container(
                              alignment: Alignment.center,
                              color: Colors.white.withOpacity(0.6),
                            ),
                          ),
                        ),
                      ),
                      Center(
                        child: FormBuilder(
                          key: _fbKey,
                          initialValue: {
                            'bookedondata': DateTime.now(),
                            'emailaddr': currentUser.email,
                            'lake': lake.name,
                            'mainimage': lake.mainimage,
                            'dismissed': false,
                            'reviewed': false,
                            'uid': currentUser.uid,

                            //'accept_terms': false,
                          },
                          autovalidate: true,
                          child: Padding(
                            padding: const EdgeInsets.all(10.0),
                            child: Column(
                              children: <Widget>[
                                Container(height: 20),
                                FormBuilderDateTimePicker(
                                  attribute: "bookedfordate",
                                  firstDate: DateTime.now(),
                                  resetIcon: null,
                                  inputType: InputType.date,
                                  validators: [
                                    FormBuilderValidators.required()
                                  ],
                                  format: DateFormat("dd-MM-yyyy"),
                                  decoration: InputDecoration(
                                    labelText: "Reservation Date",
                                    labelStyle: TextStyle(
                                      color: Colors.black,
                                      fontSize: 15,
                                      fontWeight: FontWeight.w900,
                                    ),
                                  ),
                                ),
                                Container(height: 20),
                                FormBuilderDropdown(
                                  attribute: "tickettype",
                                  decoration: InputDecoration(
                                    labelText: "Ticket Type",
                                    labelStyle: TextStyle(
                                      color: Colors.black,
                                      fontSize: 20,
                                      fontWeight: FontWeight.w900,
                                    ),
                                  ),
                                  // initialValue: 'Male',
                                  hint: Text('Day/Night/24Hour'),
                                  validators: [
                                    FormBuilderValidators.required()
                                  ],
                                  items: ['Day', 'Night', '24Hour']
                                      .map((ticket) => DropdownMenuItem(
                                          value: ticket,
                                          child: Text("$ticket")))
                                      .toList(),
                                ),
                                Container(height: 20),
                                FormBuilderDropdown(
                                  attribute: "swimplot",
                                  decoration: InputDecoration(
                                    labelText: "Select Swim",
                                    labelStyle: TextStyle(
                                      color: Colors.black,
                                      fontSize: 20,
                                      fontWeight: FontWeight.w900,
                                    ),
                                  ),
                                  // initialValue: 'Male',
                                  hint:
                                      Text('Which pitch do you wish to choose'),
                                  validators: [
                                    FormBuilderValidators.required()
                                  ],
                                  items: plots
                                      .map((ticket) => DropdownMenuItem(
                                          value: ticket,
                                          child: Text("$ticket")))
                                      .toList(),
                                ),
                                Container(height: 20),
                                RaisedButton.icon(
                                  icon: Icon(
                                    Icons.search,
                                    color: Colors.white,
                                    size: 30,
                                  ),
                                  label: Text("Book",
                                      textAlign: TextAlign.center,
                                      style: TextStyle(
                                        color: Colors.white,
                                        fontSize: 20,
                                      )),
                                  onPressed: () {
                                    _bookswim();
                                  },
                                  shape: RoundedRectangleBorder(
                                      borderRadius: BorderRadius.all(
                                          Radius.circular(10.0))),
                                  color: Color.fromRGBO(70, 109, 69, 1.0),
                                ),
                              ],
                            ),
                          ),
                        ),
                      ),
                    ])));
          } else {
            return CircularProgressIndicator();
          }
        });
  }





  

  void getDocument() {
    Firestore.instance
        .collection('bookings')
        .where("bookedfordate", isEqualTo: DateTime.now())
        .limit(1)
        .getDocuments()
        .then(
      (value) {
        if (value.documents.length > 0) {
          //return _myClassFromSnapshot(value.documents[0]);
        } else {
          //return _bookswim
          return null;
        }
      },
    );
  }

  void _bookswim() {
    //getDocument();
    _fbKey.currentState.save();
    if (_fbKey.currentState.validate()) {
      String combine = ((DateFormat('yyyyMMdd')
              .format(_fbKey.currentState.value['bookedfordate'])) +
          (_fbKey.currentState.value['swimplot']) +
          (_fbKey.currentState.value['tickettype']) +
          (widget.name.replaceAll(RegExp(' '), '')));

      Firestore.instance
          .collection("bookings")
          .document(combine)
          .get()
          .then((doc) {
        if (!doc.exists) {
          Firestore.instance.collection('bookings').document(combine).setData({
            'bookedfordate': _fbKey.currentState.value['bookedfordate'],
            'emailaddr': _fbKey.currentState.value['emailaddr'],
            'lake': _fbKey.currentState.value['lake'],
            'mainimage': _fbKey.currentState.value['mainimage'],
            'dismissed': _fbKey.currentState.value['dismissed'],
            'reviewed': _fbKey.currentState.value['reviewed'],
            'uid': _fbKey.currentState.value['uid'],
            'bookedondata': _fbKey.currentState.value['bookedondata'],
            'tickettype': _fbKey.currentState.value['tickettype'],
            'swimplot': _fbKey.currentState.value['swimplot']
          });
          _showDialog();
        } else {
          _showMyDialog();
        }
      });
    }
  }

  Future<void> _showMyDialog() async {
    return showDialog<void>(
      context: context,
      barrierDismissible: false,
      builder: (BuildContext context) {
        return AlertDialog(
          title: Text('SwimFinder'),
          content: SingleChildScrollView(
            child: ListBody(
              children: <Widget>[
                Text('Sorry this Swim in already booked!'),
              ],
            ),
          ),
          actions: <Widget>[
            FlatButton(
              child: Text('close'),
              onPressed: () {
                Navigator.of(context).pop();
              },
            ),
          ],
        );
      },
    );
  }

  void _showDialog() {
    showDialog(
      context: context,
      builder: (BuildContext context) {
        return AlertDialog(
          title: new Text("SwimFinder",
              style: TextStyle(
                color: Color.fromRGBO(70, 109, 69, 1.0),
                fontSize: 20,
              )),
          content: new Text("Thank you for your booking!",
              style: TextStyle(
                color: Color.fromRGBO(70, 109, 69, 1.0),
                fontSize: 20,
              )),
          actions: <Widget>[
            new FlatButton(
              child: new Text("Close"),
              onPressed: () {
                Navigator.popUntil(context, ModalRoute.withName('/'));
              },
            ),
          ],
        );
      },
    );
  }
}

因此,如果用户选择 24 小时票,则在某次游泳和某个情节中使用 1 天。在此之后 Day 和 Night 票应该告诉用户不可用。日票和夜票可以在同一天预订,因为这是 24 小时,但可以为 2 个不同的用户。

我希望我的代码更有意义

【问题讨论】:

  • 请不要再问一个封闭的问题。对您现有的封闭式问题进行编辑。如果您的修改解决了原始问题,它将重新打开。
  • 它不是没有意义的代码,你的话,我显然无法理解这个想法
  • 好的,想象一下有一家有 5 间客房的酒店。客房仅可预订白天、夜间或 24 小时。从我的代码中,您可以看到如果我预订白天,我不能再次预订白天,晚上和 24 小时也一样。但是,如果用户先预订白天或晚上,仍然可以预订 24 小时......我希望这是有道理的
  • @neuromancer 你有什么建议吗?
  • 给定一天中的 24 小时,定义您认为白天和黑夜的一天中的什么时间

标签: firebase flutter dart


【解决方案1】:

鉴于您对我在 Google Groups Flutter 上的问题的回答,即:

我不清楚什么是双重预订,即。你试图阻止什么。请确认或更正以下各项:

  1. 你相当于一个“房间”是一个“游泳场”?是的!
  2. 可以在任何给定日期为“白天”、“夜晚”或“24 小时”预订“游泳场地”吗?是的!
  3. 这些“时间段”只能由一个用户在任何一天预订,即。没有两个或更多用户共享一个时隙?正确!
  4. 如果预订“24 小时”,那么“游泳区”是否不适用于“白天”或“夜间”预订?正确!
  5. 如果预订“白天”,那么“游泳区”仍然可以用于“夜间”,但不能用于“24 小时”,如果预订“夜间”,类似情况?正确!
  6. 如果用户 A 在同一天预订了“晚上”,用户 B 可以预订“白天”吗?正确!

我使用 Firebase RTDB 而不是 Firestore,因此您需要将以下内容“翻译”成 Firestore 文档结构 - 您的问题是关于逻辑的,希望我的答案能够解决这个问题。

我将在数据库中创建一个“预订”节点/记录,其复合键为'swim plot id' + 'date'。该记录将只包含三个属性,一个用于每个可能的时隙,即。

'24hrs': 'userid of person booking it'
'day': 'userid of person booking it' 
'night': 'userid of person booking it' 

其他数据,如用户电子邮件、图像等不应在预订记录上,恕我直言,但应根据需要使用用户 ID、游泳图 ID 等从其他节点/文档中读取。

尝试预订时,逻辑如下:

您阅读数据库寻找swimPlotId + date

如果记录不存在,则根据相应的时间槽属性创建一个填写用户 ID 的记录。另外两个将保持空白/空。告诉用户预订成功。

如果记录存在则

如果 24hrs 属性存在/有用户 ID(并且不是他的用户 ID)- 告诉用户不能进行预订。

如果他想 24 小时预订,并且无论白天还是晚上都存在/有用户 ID(而且这不是他的用户 ID)- 告诉用户不能进行预订。

如果他想预订一天但它不存在/没有用户 ID - 用他的用户 ID 值的一天属性更新记录 - 告诉用户预订已完成。

如果他想预订夜间但它不存在/没有用户 ID - 用他的用户 ID 值的夜间属性更新记录 - 告诉用户预订已完成。

我认为这涵盖了它。

ps。鉴于您的 24 小时并非全部在一个日期,您将需要为您的密钥创建一些人为的“日期”以确保它被正确识别,或者您可以使用早上 7 点所在的日期并控制“重叠”任何引用“日期”的代码 - 可能会在一个地方编写一个控制重叠的小方法,并在引用日期时调用该方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多