Reputation: 1
The database that I'm using is Supabase and the IDs of "Guest" and "passenger_manifest" tables are both identities. In my QRPage.dart
code below, I'm trying to use _deleteData
to delete the information that was inputted from GuestRegistration.dart
and it doesn't delete it when I press the back button. It shows the ID in the debug console, but it doesn't delete the row.
QRPage.dart code:
import 'package:flutter/material.dart';
import 'package:namer_app/Passenger_Widgets/GuestRegistration.dart';
import 'package:qr_flutter/qr_flutter.dart';
import 'package:supabase_flutter/supabase_flutter.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: HomePage(
firstNameController: TextEditingController(),
surnameController: TextEditingController(),
professionController: TextEditingController(),
),
);
}
}
class HomePage extends StatefulWidget {
final int? id;
final int? guest_id;
final String? origin;
final String? destination;
final TextEditingController firstNameController;
final TextEditingController surnameController;
final TextEditingController professionController;
const HomePage({
super.key,
this.id,
this.guest_id,
this.origin,
this.destination,
required this.firstNameController,
required this.surnameController,
required this.professionController,
});
@override
HomePageState createState() => HomePageState();
}
class HomePageState extends State<HomePage> {
final SupabaseClient _supabase = Supabase.instance.client;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('E-Ticket'),
backgroundColor: const Color(0xFF7ADFC1),
leading: IconButton(
icon: const Icon(Icons.arrow_back),
onPressed: () {
_showExitConfirmationDialog();
},
),
),
body: Container(
decoration: const BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [Color(0xFF7ADFC1), Color(0xFF21A5D1)],
),
),
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
width: 350,
height: 550,
padding: const EdgeInsets.all(20),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(35),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
QrImageView(
data: widget.destination ?? '',
version: QrVersions.auto,
size: 300.0,
),
const SizedBox(height: 20),
Text(
'${widget.firstNameController.text} ${widget.surnameController.text}',
style: const TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
Text(
widget.professionController.text,
style: const TextStyle(
fontSize: 16,
color: Colors.grey,
),
),
const SizedBox(height: 20),
Text(
'${widget.origin ?? ''} - ${widget.destination ?? ''}',
style: const TextStyle(
fontSize: 16,
),
),
const SizedBox(height: 10),
const Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'Total Fee:',
style: TextStyle(
fontSize: 25,
),
),
Text(
'₱0.00',
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
),
),
],
),
],
),
),
const SizedBox(height: 20),
ElevatedButton(
onPressed: () {
showConfirmationDialog(context);
},
child: const Text('Complete Transaction'),
),
],
),
),
),
);
}
void _showExitConfirmationDialog() {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: const Text('Are you sure?'),
content: const Text('Do you want to go back? This will delete the input data.'),
actions: [
TextButton(
child: const Text('No'),
onPressed: () {
Navigator.of(context).pop();
},
),
TextButton(
child: const Text('Yes'),
onPressed: () async {
await _deleteData();
Navigator.of(context).pop();
Navigator.pop(context);
},
),
],
);
},
);
}
Future<void> _deleteData() async {
try {
if (widget.id == null) {
print('Error: No ID to delete.');
return;
}
await _supabase.from('passenger_manifest').delete().eq('id', widget.id!);
await _supabase.from('Guest').delete().eq('id', widget.guest_id!);
print('Data deleted successfully.');
} catch (error) {
print('Error deleting data: $error');
}
}
void showConfirmationDialog(BuildContext context) {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: const Text('Are you sure?'),
content: const Text('Do you want to complete the transaction?'),
actions: [
TextButton(
child: const Text('No'),
onPressed: () {
Navigator.of(context).pop();
},
),
TextButton(
child: const Text('Yes'),
onPressed: () {
Navigator.of(context).pop();
},
),
],
);
},
);
}
}
and this is my GuestRegistration.dart code:
import 'package:flutter/material.dart';
import 'package:namer_app/Passenger_Widgets/CustomTextBoxes.dart';
import 'package:namer_app/Passenger_Widgets/DropBoxes.dart';
import 'package:namer_app/Passenger_Widgets/UserEmailRegistration.dart';
import 'package:philippines_rpcmb/philippines_rpcmb.dart';
import 'package:supabase_flutter/supabase_flutter.dart';
import 'QRPage.dart';
void main() async {
await Supabase.initialize(
url: 'https://bdhoonwrqbdvkhatpxdv.supabase.co',
anonKey:
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImJkaG9vbndycWJkdmtoYXRweGR2Iiwicm9sZSI6ImFub24iLCJpYXQiOjE3MjMwMDY4NTIsImV4cCI6MjAzODU4Mjg1Mn0.TOHOu-NNXVwNLOWauZFvzDTPYmhKZJOXD6WEmVPP1cQ',
);
runApp(MaterialApp(
title: 'Guest Registration',
home: PrfGuestRegistration(),
debugShowCheckedModeBanner: false,
));
}
class PrfGuestRegistration extends StatefulWidget {
const PrfGuestRegistration({super.key});
@override
State<PrfGuestRegistration> createState() => _PrfGuestRegistrationState();
}
class _PrfGuestRegistrationState extends State<PrfGuestRegistration> {
Region? region;
Province? province;
Municipality? municipality;
String? barangay;
String? selectedGender;
String? selectedOrigin;
String? selectedDestination;
int? _id;
int? _guest_id;
final usernameController = TextEditingController();
final passwordController = TextEditingController();
final firstNameController = TextEditingController();
final middleInitialController = TextEditingController();
final surnameController = TextEditingController();
final contactController = TextEditingController();
final professionController = TextEditingController();
final ageController = TextEditingController();
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
List<String> _errors = [];
void _validatePassword(String value) {
setState(() {
_errors.clear();
if (!value.contains(RegExp(r'[a-z]'))) {
_errors.add("Must contain lowercase.");
}
if (!value.contains(RegExp(r'[A-Z]'))) {
_errors.add("Must contain uppercase.");
}
if (value.length < 8) {
_errors.add("At least 8 characters.");
}
if (!value.contains(RegExp(r'[0-9]'))) {
_errors.add("At least one number.");
}
if (!value.contains(RegExp(r'[!@#$%^&*(),.?":{}|<>]'))) {
_errors.add("At least one special character.");
}
});
}
String? _validateRequired(String? value) {
if (value == null || value.isEmpty) {
return 'This field is required';
}
return null;
}
void _submitForm() async {
final form = _formKey.currentState;
if (form!.validate()) {
if (selectedOrigin == selectedDestination) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text("Origin and destination cannot be the same. Please choose a different destination."),
),
);
return;
}
final data = {
'first_name': firstNameController.text,
'middle_name': middleInitialController.text,
'last_name': surnameController.text,
'address': municipality?.name,
'contact_number': contactController.text,
'profession': professionController.text,
'age': ageController.text,
'gender': selectedGender,
'origin': selectedOrigin,
'destination': selectedDestination,
};
try {
final response = await Supabase.instance.client.from('passenger_manifest').insert([data]).select('id').single();
if (response.containsKey('error')) {
print('Error inserting data: ${response['error']}');
} else {
final id = response['id'];
print('Registration successful, ID: $id');
}
} catch (e) {
print('Error inserting data: $e');
}
}
if (form!.validate()) {
final data = {
'first_name': firstNameController.text,
'middle_initial': middleInitialController.text,
'last_name': surnameController.text,
'contact_num': contactController.text,
'profession': professionController.text,
'age': ageController.text,
'gender': selectedGender,
'region': region!.regionName,
'province': province?.name,
'municipality': municipality?.name,
'barangay': barangay,
'origin': selectedOrigin,
'destination': selectedDestination,
};
try {
final response = await Supabase.instance.client.from('Guest').insert([data]).select('guest_id').single();
if (response.containsKey('error')) {
print('Error inserting data: ${response['error']}');
} else {
final guest_id = response['guest_id'];
print('Registration successful, ID: $guest_id');
}
} catch (e) {
print('Error inserting data: $e');
}
}
}
void handleGenderSelected(String? gender) {
setState(() {
selectedGender = gender;
});
}
void handleOriginSelected(String? origin) {
setState(() {
selectedOrigin = origin;
});
}
void handleDestinationSelected(String? destination) {
setState(() {
selectedDestination = destination;
});
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Color(0xFF4FCAD2),
title: Center(
child: const Text(
"Guest Registration",
style: TextStyle(
color: Color(0xFF33385F),
fontWeight: FontWeight.bold,
fontFamily: 'EBGaramond',
),
),
),
actions: [
Padding(
padding: const EdgeInsets.only(right: 10.0),
child: Image.asset(
'images/prf_logo.png',
width: 40,
height: 40,
),
),
],
),
body: Form(
key: _formKey,
child: ListView(
children: [
Column(
children: [
SizedBox(height: 40),
FirstMiddleTextBox(
firstNameController: firstNameController,
middleController: middleInitialController,
validator: _validateRequired,
),
SurnameTextBox(
textController: surnameController,
validator: _validateRequired,
),
LocationDropdowns(
isEnabled: true,
onRegionChanged: (selectedRegion) {
setState(() {
region = selectedRegion;
province = null;
municipality = null;
barangay = null;
});
},
onProvinceChanged: (selectedProvince) {
setState(() {
province = selectedProvince;
municipality = null;
barangay = null;
});
},
onMunicipalityChanged: (selectedMunicipality) {
setState(() {
municipality = selectedMunicipality;
barangay = null;
});
},
onBarangayChanged: (selectedBarangay) {
setState(() {
barangay = selectedBarangay;
});
},
region: region,
province: province,
municipality: municipality,
barangay: barangay,
),
ContactNumTextBox(
textController: contactController,
validator: _validateRequired,
),
ProfessionAgeTextBox(
professionController: professionController,
professionValidator: _validateRequired,
ageController: ageController,
ageValidator: _validateRequired,
),
OriginAgeBox(
onGenderChanged: handleGenderSelected,
onOriginChanged: handleOriginSelected,
),
DesitinationDropBox(
onDestinationChanged: handleDestinationSelected,
),
SizedBox(height: 20),
SubmitButton(onPressed: _submitForm,
firstNameController: firstNameController,
surnameController: surnameController,
professionController: professionController,
origin: selectedOrigin,
destination: selectedDestination,
id: _id,
guest_id: _guest_id,),
SizedBox(height: 20),
],
),
],
),
));
}
}
class ProfessionAgeTextBox extends StatefulWidget {
final TextEditingController professionController;
final TextEditingController ageController;
final FormFieldValidator<String>? professionValidator;
final FormFieldValidator<String>? ageValidator;
const ProfessionAgeTextBox(
{super.key,
required this.professionController,
required this.ageController,
required this.professionValidator,
required this.ageValidator});
@override
State<ProfessionAgeTextBox> createState() => _ProfessionAgeTextBoxState();
}
class _ProfessionAgeTextBoxState extends State<ProfessionAgeTextBox> {
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.fromLTRB(40, 0, 0, 8),
child: Row(
children: [
URCustomTexboxes(
validator: widget.professionValidator,
myKeyboardType: TextInputType.text,
textController: widget.professionController,
hintText: 'Enter profession',
labelText: 'Profession',
containerWidth: 190,
),
SizedBox(width: 10),
URCustomTexboxes(
textController: widget.ageController,
validator: widget.ageValidator,
isRequired: true,
restrictToDigits: true,
myKeyboardType: TextInputType.number,
hintText: 'Enter age',
labelText: 'Age',
containerWidth: 80,
),
],
),
);
}
}
class SurnameTextBox extends StatefulWidget {
final TextEditingController textController;
final FormFieldValidator<String>? validator;
const SurnameTextBox(
{super.key, required this.textController, required this.validator});
@override
State<SurnameTextBox> createState() => _SurnameTextBoxState();
}
class _SurnameTextBoxState extends State<SurnameTextBox> {
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.fromLTRB(5, 0, 5, 8),
child: URCustomTexboxes(
validator: widget.validator,
isRequired: true,
restrictToStrings: true,
myKeyboardType: TextInputType.text,
textController: widget.textController,
hintText: 'Enter surname',
labelText: 'Surname',
containerWidth: 280,
),
);
}
}
class OriginAgeBox extends StatefulWidget {
final Function(String?) onOriginChanged;
final Function(String?) onGenderChanged;
const OriginAgeBox({
super.key,
required this.onOriginChanged,
required this.onGenderChanged,
});
@override
State<OriginAgeBox> createState() => _OriginAgeBoxState();
}
class _OriginAgeBoxState extends State<OriginAgeBox> {
List<DropdownMenuItem<String>> get genderItems {
List<DropdownMenuItem<String>> menuItems = [
DropdownMenuItem(child: Text("Male"), value: "Male"),
DropdownMenuItem(child: Text("Female"), value: "Female"),
];
return menuItems;
}
List<DropdownMenuItem<String>> get ferryStations {
List<DropdownMenuItem<String>> menuItems = [
DropdownMenuItem(child: Text("Pinagbuhatan"), value: "Pinagbuhatan"),
DropdownMenuItem(child: Text("Kalawaan"), value: "Kalawaan"),
DropdownMenuItem(child: Text("San Joaquin"), value: "San Joaquin"),
DropdownMenuItem(child: Text("Guadalupe"), value: "Guadalupe"),
DropdownMenuItem(child: Text("Hulo"), value: "Hulo"),
DropdownMenuItem(child: Text("Valenzuela"), value: "Valenzuela"),
DropdownMenuItem(child: Text("Lambingan"), value: "Lambingan"),
DropdownMenuItem(child: Text("Sta.Ana"), value: "Sta.Ana"),
DropdownMenuItem(child: Text("PUP"), value: "PUP"),
DropdownMenuItem(child: Text("Quinta"), value: "Quinta"),
DropdownMenuItem(child: Text("Lawton"), value: "Lawton"),
DropdownMenuItem(child: Text("Escolta"), value: "Escolta"),
];
return menuItems;
}
String selectedGender = "";
String selectedOrigin = "";
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.fromLTRB(40, 0, 0, 8),
child: Row(
children: [
Padding(
padding: const EdgeInsets.fromLTRB(0, 0, 0, 9),
child: Container(
height: 68,
width: 176,
child: DropdownButtonFormField(
isDense: true,
decoration: InputDecoration(
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
width: 2,
color: Color(0xFF33385F),
),
),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
width: 2,
color: Color(0xFF33385F),
),
),
contentPadding:
EdgeInsets.symmetric(vertical: 15, horizontal: 10),
),
hint: Text("Select origin"),
style: TextStyle(
color: Colors.black,
fontSize: 9,
),
onChanged: (String? newValue) {
setState(() {
selectedOrigin = newValue!;
});
widget.onOriginChanged(newValue);
},
items: ferryStations)),
),
SizedBox(width: 10),
Padding(
padding: const EdgeInsets.fromLTRB(0, 0, 0, 9),
child: Container(
height: 68,
width: 95,
child: DropdownButtonFormField(
isDense: true,
decoration: InputDecoration(
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
width: 2,
color: Color(0xFF33385F),
),
),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
width: 2,
color: Color(0xFF33385F),
),
),
contentPadding:
EdgeInsets.symmetric(vertical: 15, horizontal: 6),
),
hint: Text("Select gender"),
style: TextStyle(
color: Colors.black,
fontSize: 9,
),
onChanged: (String? newValue) {
setState(() {
selectedGender = newValue!;
});
widget.onGenderChanged(newValue);
},
items: genderItems,
)),
),
],
),
);
}
}
class DesitinationDropBox extends StatefulWidget {
final Function(String?) onDestinationChanged;
const DesitinationDropBox({super.key, required this.onDestinationChanged});
@override
State<DesitinationDropBox> createState() => _DesitinationDropBoxState();
}
class _DesitinationDropBoxState extends State<DesitinationDropBox> {
List<DropdownMenuItem<String>> get ferryStations {
List<DropdownMenuItem<String>> menuItems = [
DropdownMenuItem(child: Text("Pinagbuhatan"), value: "Pinagbuhatan"),
DropdownMenuItem(child: Text("Kalawaan"), value: "Kalawaan"),
DropdownMenuItem(child: Text("San Joaquin"), value: "San Joaquin"),
DropdownMenuItem(child: Text("Guadalupe"), value: "Guadalupe"),
DropdownMenuItem(child: Text("Hulo"), value: "Hulo"),
DropdownMenuItem(child: Text("Valenzuela"), value: "Valenzuela"),
DropdownMenuItem(child: Text("Lambingan"), value: "Lambingan"),
DropdownMenuItem(child: Text("Sta.Ana"), value: "Sta.Ana"),
DropdownMenuItem(child: Text("PUP"), value: "PUP"),
DropdownMenuItem(child: Text("Quinta"), value: "Quinta"),
DropdownMenuItem(child: Text("Lawton"), value: "Lawton"),
DropdownMenuItem(child: Text("Escolta"), value: "Escolta"),
];
return menuItems;
}
String selectedDestination = "";
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.fromLTRB(0, 0, 0, 9),
child: Container(
height: 68,
width: 282,
child: DropdownButtonFormField(
isDense: true,
decoration: InputDecoration(
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
width: 2,
color: Color(0xFF33385F),
),
),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
width: 2,
color: Color(0xFF33385F),
),
),
contentPadding: EdgeInsets.symmetric(vertical: 15, horizontal: 5),
),
hint: Text("Select destination"),
style: TextStyle(
color: Colors.black,
fontSize: 9,
),
onChanged: (String? newValue) {
setState(() {
selectedDestination = newValue!;
});
widget.onDestinationChanged(newValue);
},
items: ferryStations,
),
),
);
}
}
class SubmitButton extends StatelessWidget {
final VoidCallback onPressed;
final String? origin;
final String? destination;
final TextEditingController firstNameController;
final TextEditingController surnameController;
final TextEditingController professionController;
final int? id;
final int? guest_id;
const SubmitButton({
super.key,
required this.onPressed,
this.origin,
this.destination,
required this.firstNameController,
required this.surnameController,
required this.professionController,
this.id,
this.guest_id,
});
@override
Widget build(BuildContext context) {
return Container(
width: 280,
height: 50,
child: ElevatedButton(
onPressed: () {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: const Text("Confirm Your Selection"),
content: Text(
"Are you sure you want to proceed with the following selections?\n\nOrigin: $origin\nDestination: $destination"),
actions: [
TextButton(
onPressed: () {
Navigator.of(context).pop();
},
child: const Text("Cancel"),
),
TextButton(
onPressed: () {
Navigator.of(context).pop();
if (origin != destination) {
onPressed();
if (origin != null && destination != null) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => HomePage(
id: id,
guest_id: guest_id,
origin: origin,
destination: destination,
firstNameController: firstNameController,
surnameController: surnameController,
professionController: professionController,
),
),
);
}
} else {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text("Origin and destination cannot be the same. Please choose a different destination."),
),
);
}
},
child: const Text("Proceed"),
),
],
);
},
);
},
child: const Text("SUBMIT"),
style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xFF4FCAD2),
textStyle: const TextStyle(
color: Color(0xFF33385F),
fontWeight: FontWeight.bold,
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5),
),
),
),
);
}
}
I tried storing the IDs on the registration and passing the IDs from GuestRegistration.dart
to QRPage.dart
.
Upvotes: 0
Views: 33