Introduction
In today's fast-paced world, managing events and bookings through mobile applications has become increasingly essential. An Event Booking App allows users to browse upcoming events, book tickets, select seats, and manage their bookings seamlessly. In this tutorial, you will learn how to create a complete Event Booking App using Flutter for the frontend and Back4App as the backend service.
By the end of this tutorial, you will have built a functional app that:
Displays a list of events with details.
Allows users to view event schedules and venue information.
Enables ticket booking with seat selection.
Processes payments securely (integration with a payment gateway).
Manages user profiles, including booking history and preferences.
Let's get started!
Prerequisites
To complete this tutorial, you will need:
Flutter SDK installed on your local machine. Follow the official Flutter installation guide.
Basic knowledge of Dart and Flutter. If you're new to Flutter, consider going through Flutter's introductory tutorial.
A Back4App account. Sign up for a free account at Back4App.
Back4App Flutter SDK integrated into your project. You can learn how to set it up by following the Back4App Flutter Guide.
A code editor like Visual Studio Code or Android Studio.
Node.js and npm installed for running Back4App cloud functions. Install them from the official Node.js website.
Step 1 – Setting Up the Back4App Backend
In this step, you will set up your Back4App project, create the necessary classes (tables), and configure the backend to store event data, ticket information, and user profiles.
1.1. Create a New Back4App Application
Log in to your Back4App account.
Click on "Create new App".
Enter an App Name (e.g., "EventBookingApp") and select your App Icon.
Click "Create".
1.2. Configure Application Keys
Navigate to your app's Dashboard.
Click on "App Settings" > "Security & Keys".
Note down the Application ID and Client Key. You will need these to initialize the Parse SDK in your Flutter app.
1.3. Define the Data Models
You need to create the following classes in Back4App:
Event: Stores event details.
Venue: Stores venue information.
Ticket: Manages ticket availability and bookings.
User: Manages user profiles (default class).
Create the Event Class
In the left sidebar, click on "Database" to open the Data Browser.
Click on "Create a class".
Select "Custom", enter "Event" as the class name, and click "Create class".
Add the following columns to the Event class:
name (String)
description (String)
date (Date)
image (File)
venue (Pointer to Venue)
price (Number)
Create the Venue Class
Repeat the steps to create a new class named "Venue".
Add the following columns:
name (String)
address (String)
capacity (Number)
seatingChart (File)
Create the Ticket Class
Create a new class named "Ticket".
Add the following columns:
event (Pointer to Event)
user (Pointer to User)
seatNumber (String)
price (Number)
isBooked (Boolean)
1.4. Enable User Authentication
In the left sidebar, click on "Server Settings" > "General Settings".
Under "Authentication", ensure that "Enable Class Level Permissions" is checked.
Configure the User class permissions to allow users to sign up and log in.
1.5. Set Up Cloud Functions (Optional for Payment Processing)
For payment integration, you might need to write cloud functions. This step will depend on the payment gateway you choose (e.g., Stripe, PayPal). Refer to Back4App's documentation on Cloud Code Functions.
Step 2 – Initializing the Flutter Project
In this step, you will set up the Flutter project and integrate the Back4App Parse SDK.
2.1. Create a New Flutter Project
Open your terminal and run:
Text
1flutter create event_booking_app
Navigate to the project directory:
Text
1cd event_booking_app
2.2. Add Dependencies
Open pubspec.yaml and add the following dependencies:
YAML
1dependencies:2 flutter:3 sdk: flutter4 cupertino_icons: ^1.0.25 parse_server_sdk_flutter: ^4.0.16 provider: ^6.0.07 # Add any additional packages you need, e.g., http, image_picker, etc.
Run flutter pub get to install the packages.
2.3. Initialize Parse SDK
In lib/main.dart, import the necessary packages and initialize Parse:
Dart
1import 'package:flutter/material.dart';2import 'package:parse_server_sdk_flutter/parse_server_sdk.dart';34void main() async {5 WidgetsFlutterBinding.ensureInitialized();67 const keyApplicationId = 'YOUR_BACK4APP_APPLICATION_ID';8 const keyClientKey = 'YOUR_BACK4APP_CLIENT_KEY';9 const keyParseServerUrl = 'https://parseapi.back4app.com';1011 await Parse().initialize(12 keyApplicationId,13 keyParseServerUrl,14 clientKey: keyClientKey,15 debug: true,16 autoSendSessionId: true,17 );1819 runApp(MyApp());20}2122class MyApp extends StatelessWidget {23 // Build your app's UI here24}
Replace 'YOUR_BACK4APP_APPLICATION_ID' and 'YOUR_BACK4APP_CLIENT_KEY' with your actual keys from Back4App.
Step 3 – Implementing User Authentication
Users need to sign up and log in to book events and manage their profiles.
3.1. Create Authentication Screens
Create two new Dart files in lib/:
login_screen.dart
signup_screen.dart
login_screen.dart
Dart
1import 'package:flutter/material.dart';2import 'package:parse_server_sdk_flutter/parse_server_sdk.dart';34class LoginScreen extends StatefulWidget {5 @override6 _LoginScreenState createState() => _LoginScreenState();7}89class _LoginScreenState extends State<LoginScreen> {10 final TextEditingController usernameController = TextEditingController();11 final TextEditingController passwordController = TextEditingController();1213 void doUserLogin() async {14 final username = usernameController.text.trim();15 final password = passwordController.text.trim();1617 final user = ParseUser(username, password, null);18 var response = await user.login();1920 if (response.success) {21 // Navigate to Home Screen22 Navigator.pushReplacementNamed(context, '/home');23 } else {24 // Show error message25 _showError(response.error!.message);26 }27 }2829 void _showError(String message) {30 // Implement a method to show error messages31 }3233 @override34 Widget build(BuildContext context) {35 // Build your login UI here36 }37}
signup_screen.dart
Dart
1import 'package:flutter/material.dart';2import 'package:parse_server_sdk_flutter/parse_server_sdk.dart';34class SignUpScreen extends StatefulWidget {5 @override6 _SignUpScreenState createState() => _SignUpScreenState();7}89class _SignUpScreenState extends State<SignUpScreen> {10 final TextEditingController usernameController = TextEditingController();11 final TextEditingController passwordController = TextEditingController();1213 void doUserRegistration() async {14 final username = usernameController.text.trim();15 final password = passwordController.text.trim();1617 final user = ParseUser(username, password, null);18 var response = await user.signUp();1920 if (response.success) {21 // Navigate to Home Screen22 Navigator.pushReplacementNamed(context, '/home');23 } else {24 // Show error message25 _showError(response.error!.message);26 }27 }2829 void _showError(String message) {30 // Implement a method to show error messages31 }3233 @override34 Widget build(BuildContext context) {35 // Build your sign-up UI here36 }37}
3.2. Update main.dart with Routes
Dart
1class MyApp extends StatelessWidget {2 @override3 Widget build(BuildContext context) {4 return MaterialApp(5 title: 'Event Booking App',6 initialRoute: '/login',7 routes: {8 '/login': (context) => LoginScreen(),9 '/signup': (context) => SignUpScreen(),10 '/home': (context) => HomeScreen(),11 // Add other routes as needed12 },13 );14 }15}
3.3. Implement Home Screen
Create a home_screen.dart file where authenticated users are redirected.
Dart
1import 'package:flutter/material.dart';23class HomeScreen extends StatelessWidget {4 @override5 Widget build(BuildContext context) {6 // Build your home screen UI here7 }8}
Step 4 – Displaying Events
Fetch events from Back4App and display them in a list.
4.1. Create Event Model
Create a Dart class event.dart in lib/models/.
Dart
1import 'package:parse_server_sdk_flutter/parse_server_sdk.dart';23class Event extends ParseObject implements ParseCloneable {4 Event() : super(_keyTableName);5 Event.clone() : this();67 static const String _keyTableName = 'Event';8 static const String keyName = 'name';9 static const String keyDescription = 'description';10 static const String keyDate = 'date';11 static const String keyImage = 'image';12 static const String keyVenue = 'venue';13 static const String keyPrice = 'price';1415 @override16 clone(Map<String, dynamic> map) => Event.clone()..fromJson(map);1718 String? get name => get<String>(keyName);19 String? get description => get<String>(keyDescription);20 DateTime? get date => get<DateTime>(keyDate);21 ParseFileBase? get image => get<ParseFileBase>(keyImage);22 ParseObject? get venue => get<ParseObject>(keyVenue);23 double? get price => get<double>(keyPrice);24}
4.2. Fetch Events in Home Screen
In home_screen.dart, fetch events and display them.
Dart
1import 'package:flutter/material.dart';2import 'models/event.dart';3import 'package:parse_server_sdk_flutter/parse_server_sdk.dart';45class HomeScreen extends StatefulWidget {6 @override7 _HomeScreenState createState() => _HomeScreenState();8}910class _HomeScreenState extends State<HomeScreen> {11 Future<List<Event>> getEvents() async {12 QueryBuilder<Event> queryEvents = QueryBuilder<Event>(Event())13 ..orderByDescending('date');14 final ParseResponse apiResponse = await queryEvents.query();1516 if (apiResponse.success && apiResponse.results != null) {17 return apiResponse.results as List<Event>;18 } else {19 return [];20 }21 }2223 @override24 Widget build(BuildContext context) {25 return Scaffold(26 appBar: AppBar(27 title: Text('Events'),28 ),29 body: FutureBuilder<List<Event>>(30 future: getEvents(),31 builder: (context, snapshot) {32 if (snapshot.hasData) {33 List<Event> events = snapshot.data!;34 return ListView.builder(35 itemCount: events.length,36 itemBuilder: (context, index) {37 Event event = events[index];38 return ListTile(39 title: Text(event.name ?? 'No Title'),40 subtitle: Text(event.date?.toLocal().toString() ?? ''),41 onTap: () {42 // Navigate to Event Details43 Navigator.push(44 context,45 MaterialPageRoute(46 builder: (context) => EventDetailsScreen(event: event),47 ),48 );49 },50 );51 },52 );53 } else if (snapshot.hasError) {54 return Center(child: Text('Error loading events'));55 } else {56 return Center(child: CircularProgressIndicator());57 }58 },59 ),60 );61 }62}
4.3. Create Event Details Screen
Create event_details_screen.dart.
Dart
1import 'package:flutter/material.dart';2import 'models/event.dart';34class EventDetailsScreen extends StatelessWidget {5 final Event event;67 EventDetailsScreen({required this.event});89 void _bookTicket(BuildContext context) {10 // Implement ticket booking logic11 Navigator.push(12 context,13 MaterialPageRoute(14 builder: (context) => SeatSelectionScreen(event: event),15 ),16 );17 }1819 @override20 Widget build(BuildContext context) {21 // Build UI to display event details22 return Scaffold(23 appBar: AppBar(24 title: Text(event.name ?? 'Event Details'),25 ),26 body: Column(27 children: [28 // Display event image, description, date, venue, etc.29 Text(event.description ?? ''),30 ElevatedButton(31 onPressed: () => _bookTicket(context),32 child: Text('Book Ticket'),33 ),34 ],35 ),36 );37 }38}
Step 5 – Implementing Seat Selection
Allow users to select seats before booking.
5.1. Create Seat Selection Screen
Create seat_selection_screen.dart.
Dart
1import 'package:flutter/material.dart';2import 'models/event.dart';34class SeatSelectionScreen extends StatelessWidget {5 final Event event;67 SeatSelectionScreen({required this.event});89 // Mock data for seats10 final List<String> seats = List.generate(100, (index) => 'Seat ${index + 1}');1112 @override13 Widget build(BuildContext context) {14 // Build UI for seat selection15 return Scaffold(16 appBar: AppBar(17 title: Text('Select Seats'),18 ),19 body: GridView.builder(20 gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(21 crossAxisCount: 5,22 ),23 itemCount: seats.length,24 itemBuilder: (context, index) {25 String seat = seats[index];26 return GestureDetector(27 onTap: () {28 // Handle seat selection29 // Navigate to Payment Screen30 Navigator.push(31 context,32 MaterialPageRoute(33 builder: (context) => PaymentScreen(event: event, seat: seat),34 ),35 );36 },37 child: Card(38 child: Center(child: Text(seat)),39 ),40 );41 },42 ),43 );44 }45}
Step 6 – Processing Payments
Integrate a payment gateway to process ticket payments securely.
6.1. Choose a Payment Gateway
For this tutorial, we will assume the use of Stripe.
6.2. Set Up Stripe Account and Obtain API Keys
Sign up for a Stripe account.
Obtain your Publishable Key and Secret Key.
6.3. Add Stripe Dependency
Add stripe_payment package to your pubspec.yaml:
YAML
1dependencies:2 stripe_payment: ^1.0.9
Run flutter pub get.
6.4. Implement Payment Screen
Create payment_screen.dart.
Dart
1import 'package:flutter/material.dart';2import 'package:stripe_payment/stripe_payment.dart';3import 'models/event.dart';45class PaymentScreen extends StatefulWidget {6 final Event event;7 final String seat;89 PaymentScreen({required this.event, required this.seat});1011 @override12 _PaymentScreenState createState() => _PaymentScreenState();13}1415class _PaymentScreenState extends State<PaymentScreen> {16 void initState() {17 super.initState();18 StripePayment.setOptions(19 StripeOptions(20 publishableKey: 'YOUR_STRIPE_PUBLISHABLE_KEY',21 // Optionally set other options22 ),23 );24 }2526 void _startPayment() async {27 // Implement payment logic28 // Create Payment Method29 PaymentMethod paymentMethod = await StripePayment.paymentRequestWithCardForm(30 CardFormPaymentRequest(),31 );3233 // Process the payment using a cloud function or your server34 // For simplicity, we'll assume payment is successful3536 _saveTicket();37 }3839 void _saveTicket() async {40 // Save ticket information to Back4App41 final ticket = ParseObject('Ticket')42 ..set('event', widget.event)43 ..set('user', await ParseUser.currentUser())44 ..set('seatNumber', widget.seat)45 ..set('price', widget.event.price)46 ..set('isBooked', true);4748 await ticket.save();4950 // Navigate to confirmation screen or display success message51 }5253 @override54 Widget build(BuildContext context) {55 // Build payment UI56 return Scaffold(57 appBar: AppBar(58 title: Text('Payment'),59 ),60 body: Center(61 child: ElevatedButton(62 onPressed: _startPayment,63 child: Text('Pay \$${widget.event.price}'),64 ),65 ),66 );67 }68}
Note: Payment processing requires secure handling of sensitive data. In a production app, you should process payments securely using your own server or cloud functions.
Step 7 – Managing User Profiles
Allow users to view and manage their bookings and preferences.
7.1. Create Profile Screen
Create profile_screen.dart.
Dart
1import 'package:flutter/material.dart';2import 'package:parse_server_sdk_flutter/parse_server_sdk.dart';34class ProfileScreen extends StatelessWidget {5 Future<List<ParseObject>> getUserTickets() async {6 final user = await ParseUser.currentUser();7 QueryBuilder<ParseObject> queryTickets = QueryBuilder<ParseObject>(ParseObject('Ticket'))8 ..whereEqualTo('user', user)9 ..includeObject(['event']);1011 final ParseResponse apiResponse = await queryTickets.query();1213 if (apiResponse.success && apiResponse.results != null) {14 return apiResponse.results as List<ParseObject>;15 } else {16 return [];17 }18 }1920 @override21 Widget build(BuildContext context) {22 // Build profile UI23 return Scaffold(24 appBar: AppBar(25 title: Text('My Profile'),26 ),27 body: FutureBuilder<List<ParseObject>>(28 future: getUserTickets(),29 builder: (context, snapshot) {30 if (snapshot.hasData) {31 List<ParseObject> tickets = snapshot.data!;32 return ListView.builder(33 itemCount: tickets.length,34 itemBuilder: (context, index) {35 ParseObject ticket = tickets[index];36 ParseObject event = ticket.get('event');37 return ListTile(38 title: Text(event.get<String>('name') ?? 'No Event Name'),39 subtitle: Text('Seat: ${ticket.get<String>('seatNumber')}'),40 );41 },42 );43 } else if (snapshot.hasError) {44 return Center(child: Text('Error loading tickets'));45 } else {46 return Center(child: CircularProgressIndicator());47 }48 },49 ),50 );51 }52}
7.2. Add Navigation to Profile Screen
In your home_screen.dart or main navigation drawer, add a link to the Profile Screen.
Dart
1IconButton(2 icon: Icon(Icons.person),3 onPressed: () {4 Navigator.push(5 context,6 MaterialPageRoute(builder: (context) => ProfileScreen()),7 );8 },9),
Step 8 – Testing the App
Run your app using:
Text
1flutter run
Test the following functionalities:
Sign up and log in.
View the list of events.
View event details.
Select seats and proceed to payment.
Process a payment (test mode if possible).
View bookings in the profile.
Conclusion
Congratulations! You have built a complete Event Booking App using Flutter and Back4App. This app allows users to browse events, book tickets with seat selection, process payments, and manage their profiles and bookings.
From here, you can enhance your app by:
Adding push notifications for event reminders.
Implementing search and filtering for events.
Enhancing the UI/UX with better design and animations.
Securing payment processing with server-side validation.
For more information on Flutter and Back4App features, check out:
Back4App Documentation
By integrating Flutter with Back4App, you leverage a powerful combination to build scalable, feature-rich mobile applications efficiently.