Skip to content

Commit

Permalink
Abstracted scan status card
Browse files Browse the repository at this point in the history
Added additional enums to TicketStatus and a separate widget for ticket scan status cards.
  • Loading branch information
TomCranitch committed May 12, 2018
1 parent 3fe566a commit 0c5b6a9
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 22 deletions.
46 changes: 25 additions & 21 deletions lib/pages/scan_barcode_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import 'package:barcode_scan/barcode_scan.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import '../utils/ticket_status_enum.dart';
import '../utils/colours.dart';
import '../widgets/scanned_ticket_card.dart';

class ScanBarcodePage extends StatefulWidget {

Expand All @@ -19,7 +20,8 @@ class ScanBarcodePage extends StatefulWidget {

class ScanBarcodePageState extends State<ScanBarcodePage>{

List<List> scannedTickets = []; //[Name, Status, Pass]
// TODO: make scanned tickets collection in firestore, but only show messages from current device when scanning (i.e. it will appear the same to the user but there will be a log of all scans)
List<Map<String, dynamic>> scannedTickets = []; //[Name, Status, Pass]

///Validates the ticket with [qrContent] against the database
///
Expand All @@ -32,31 +34,41 @@ class ScanBarcodePageState extends State<ScanBarcodePage>{
List<String> qrContentArray = qrContent.split(",");
if(qrContentArray[0] != widget._eventId) {
this.setState(() {
scannedTickets.add(["Ticket Lookup Failed", "This ticket is for a different event", TicketStatus.Unverified]);

scannedTickets.add({"TicketStatus": TicketStatus.DifferentEvent});
});
return; // ignore: return_without_value
return;
}
Firestore.instance.document("events/" + qrContentArray[0] + "/attendees/" + qrContentArray[1]).get().then((DocumentSnapshot attendeeSnapshot) {
if(attendeeSnapshot.data == null) {
this.setState(() {
scannedTickets.add({"TicketStatus": TicketStatus.UnknownUser});
});
return;
}
Firestore.instance.document("users/" + qrContentArray[1]).get().then((DocumentSnapshot userSnapshot) {
String name = userSnapshot.data["FirstName"] + " " + userSnapshot.data["LastName"];
this.setState(() {
if(qrContentArray[2] == attendeeSnapshot.data["EntryCode"] && attendeeSnapshot.data["Entered"] == false){
scannedTickets.add([name, "Ticket Verified", TicketStatus.Verified]);
scannedTickets.add({"Name": name, "TicketStatus": TicketStatus.Verified});
Firestore.instance.document("events/" + qrContentArray[0] + "/attendees/" + qrContentArray[1]).updateData({"Entered": true});
// TODO: set Entered to true
} else if(qrContentArray[2] == attendeeSnapshot.data["EntryCode"] && attendeeSnapshot.data["Entered"] == true){
scannedTickets.add([name, "Ticket Verification Failed: Guest has already entered", TicketStatus.Unverified]);
scannedTickets.add({"Name": name, "TicketStatus": TicketStatus.AlreadyScanned});
} else {
scannedTickets.add([name, "Ticket Verification Failed: Invalid Ticket", TicketStatus.Unverified]);
scannedTickets.add({"Name": name, "TicketStatus": TicketStatus.InvalidEntryCode});
}
});
}).catchError((Error error) {
this.setState(() {
this.setState(() => scannedTickets.add(["Ticket Lookup Failed", "The user doesn't exist or cannot attend this event", TicketStatus.Unverified]));
scannedTickets.add({"TicketStatus": TicketStatus.UnknownUser});
});
print(error);
});
}).catchError((Error error) {
print("Catching error...");
this.setState(() {
scannedTickets.add({"TicketStatus": TicketStatus.UnknownUser});
});
});

}
Expand All @@ -79,15 +91,7 @@ class ScanBarcodePageState extends State<ScanBarcodePage>{
itemCount: scannedTickets.length,
itemBuilder: (BuildContext context, int index) {
index = scannedTickets.length - index - 1;
return new Card(
child: new ListTile(
leading: scannedTickets[index][2] == TicketStatus.Verified
? const Icon(Icons.check, color: Colors.greenAccent,) : const Icon(Icons.clear, color: Colors.white),
title: new Text(scannedTickets[index][0]),
subtitle: new Text(scannedTickets[index][1]),
),
color: scannedTickets[index][2] == TicketStatus.Verified ? Colors.white : scannedTickets[index][2] == TicketStatus.ScanFailed ? AppColours.warning : AppColours.error,
);
return new ScannedTicketCard(scannedTickets[index]);
}
),
)
Expand All @@ -104,15 +108,15 @@ class ScanBarcodePageState extends State<ScanBarcodePage>{
} on PlatformException catch (e) {
if (e.code == BarcodeScanner.CameraAccessDenied) {
setState(() {
this.scannedTickets.add(['Scan Failed', 'Unable to access the camera.', TicketStatus.ScanFailed]);
this.scannedTickets.add({"TicketStatus": TicketStatus.UnableToAccessCamera});
});
} else {
setState(() => this.scannedTickets.add(['Scan Failed', 'Unknown error: $e', TicketStatus.ScanFailed]));
setState(() => this.scannedTickets.add({"TicketStatus": TicketStatus.ScanFailed, "ErrorMessage": e}));
}
} on FormatException{
setState(() => this.scannedTickets.add(['Scan Failed', 'Exited scanning before scanning a ticket', TicketStatus.ScanFailed]));
setState(() => this.scannedTickets.add({"TicketStatus": TicketStatus.ExitedScan}));
} catch (e) {
setState(() => this.scannedTickets.add(['Scan Failed', 'Unknown error: $e', TicketStatus.ScanFailed]));
setState(() => this.scannedTickets.add({"TicketStatus": TicketStatus.ScanFailed, "ErrorMessage": e}));
}
}

Expand Down
4 changes: 3 additions & 1 deletion lib/utils/ticket_status_enum.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
enum TicketStatus {
Verified, Unverified, ScanFailed
Verified,
AlreadyScanned, UnknownUser, InvalidEntryCode, DifferentEvent,
ExitedScan, ScanFailed, UnableToAccessCamera
}
65 changes: 65 additions & 0 deletions lib/widgets/scanned_ticket_card.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import 'package:flutter/material.dart';
import '../utils/ticket_status_enum.dart';
import '../utils/colours.dart';

class ScannedTicketCard extends StatelessWidget {
final Map<String, dynamic> ticketScan;

ScannedTicketCard(this.ticketScan);

final Map<TicketStatus, String> errorCardTitles = <TicketStatus, String> {
TicketStatus.DifferentEvent: "Different Event",
TicketStatus.UnknownUser: "Unkown Guest",
TicketStatus.UnableToAccessCamera: "Unable to Access Camera",
TicketStatus.ExitedScan: "Exited Scan",
TicketStatus.ScanFailed: "Unknown Scan Error"
};

final Map<TicketStatus, String> errorCardDescriptions = <TicketStatus, String> {
TicketStatus.AlreadyScanned: "This guest has already entered",
TicketStatus.DifferentEvent: "This ticket is for a different event",
TicketStatus.UnknownUser: "The scanned ticket does not belong to a guest going to this event",
TicketStatus.InvalidEntryCode: "The scanned ticket belongs to a guest going to this event, but the security information was not valid",
TicketStatus.UnableToAccessCamera: "Ensure that the camera permissions have been enabled",
TicketStatus.ExitedScan: "The scan was exited before a ticket was shown",
TicketStatus.ScanFailed: ""
};

@override
Widget build(BuildContext context) {
String cardTitle;
String cardDescription;
bool ticketVerified = false;
bool scanError = false;

if (ticketScan["TicketStatus"] == TicketStatus.Verified) {
cardTitle = ticketScan["Name"];
cardDescription = "Entry verified";
ticketVerified = true;
} else if (ticketScan["TicketStatus"] == TicketStatus.AlreadyScanned || ticketScan["TicketStatus"] == TicketStatus.InvalidEntryCode) {
cardTitle = ticketScan["Name"];
cardDescription = errorCardDescriptions[ticketScan["TicketStatus"]];
} else {
cardTitle = errorCardTitles[ticketScan["TicketStatus"]];
cardDescription = errorCardDescriptions[ticketScan["TicketStatus"]];
}

if(ticketScan["TicketStatus"] == TicketStatus.UnableToAccessCamera || ticketScan["TicketStatus"] == TicketStatus.ExitedScan || ticketScan["TicketStatus"] == TicketStatus.ScanFailed) {
scanError = true;
}


return new Card(
child: new ListTile(
leading: ticketVerified
? const Icon(Icons.check, color: Colors.greenAccent,) : const Icon(Icons.clear, color: Colors.white),
title: new Text(cardTitle),
subtitle: new Text(cardDescription),
),
color: ticketVerified ? Colors.white
: scanError ? AppColours.warning
: AppColours.error,
);
}

}

0 comments on commit 0c5b6a9

Please sign in to comment.