diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml index fdf939b63683872e0b63eacee6e9a20db9b708aa..3d96d07a9c7d0124926232c6095c874750d8bff3 100644 --- a/.idea/deploymentTargetDropDown.xml +++ b/.idea/deploymentTargetDropDown.xml @@ -3,20 +3,7 @@ <component name="deploymentTargetDropDown"> <value> <entry key="LoginActivity"> - <State> - <targetSelectedWithDropDown> - <Target> - <type value="QUICK_BOOT_TARGET" /> - <deviceKey> - <Key> - <type value="VIRTUAL_DEVICE_PATH" /> - <value value="H:\Androidstudio_AVD\avd\Pixel_3a_API_34.avd" /> - </Key> - </deviceKey> - </Target> - </targetSelectedWithDropDown> - <timeTargetWasSelectedWithDropDown value="2024-01-17T20:36:19.481840300Z" /> - </State> + <State /> </entry> <entry key="SignupActivity"> <State /> diff --git a/.idea/misc.xml b/.idea/misc.xml index 0ad17cbd33a2f389d524bc4bfef9c52e1f7ab490..8978d23db569daa721cb26dde7923f4c673d1fc9 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,4 +1,3 @@ -<?xml version="1.0" encoding="UTF-8"?> <project version="4"> <component name="ExternalStorageConfigurationManager" enabled="true" /> <component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="jbr-17" project-jdk-type="JavaSDK"> diff --git a/app/build.gradle.kts b/app/build.gradle.kts index c1c35097bba86b14fbe627d81da946b8e3b914d0..06f84324e534abab5fa67a55d422c49feb0c0aac 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -44,7 +44,13 @@ dependencies { implementation(libs.androidx.activity) implementation(libs.androidx.constraintlayout) implementation(libs.firebase.database) + implementation(libs.firebase.auth.ktx) + implementation(libs.play.services.auth) + implementation("com.google.android.libraries.places:places:3.3.0") + implementation("com.google.maps.android:android-maps-utils:0.6.0") + implementation(libs.firebase.firestore.ktx) testImplementation(libs.junit) androidTestImplementation(libs.androidx.junit) androidTestImplementation(libs.androidx.espresso.core) + } \ No newline at end of file diff --git a/app/google-services.json b/app/google-services.json index 199bde1155b8c65ace506a42c32190aeeaf6fb1e..1085d7c3845bfdf372f79c94358dc5a0392a9108 100644 --- a/app/google-services.json +++ b/app/google-services.json @@ -13,7 +13,20 @@ "package_name": "com.example.mobilecomputingapp" } }, - "oauth_client": [], + "oauth_client": [ + { + "client_id": "897141802282-sf13rp70t6m4oh0g34iojteg5uqehoop.apps.googleusercontent.com", + "client_type": 1, + "android_info": { + "package_name": "com.example.mobilecomputingapp", + "certificate_hash": "668873c25fb2c090a13af930c35e04d23f50eccc" + } + }, + { + "client_id": "897141802282-l3k6p2sku3geee2isifm25u7lgoup0dv.apps.googleusercontent.com", + "client_type": 3 + } + ], "api_key": [ { "current_key": "AIzaSyBsvQnZuQ67aJ4eGenW0aRCLUpOCp77iAw" @@ -21,7 +34,12 @@ ], "services": { "appinvite_service": { - "other_platform_oauth_client": [] + "other_platform_oauth_client": [ + { + "client_id": "897141802282-l3k6p2sku3geee2isifm25u7lgoup0dv.apps.googleusercontent.com", + "client_type": 3 + } + ] } } } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a359696db6bba021c6e2c6c44ede0ec000b611ec..33a073ce0ba17776438ed57d57658faab127c015 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -2,16 +2,38 @@ <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"> + <uses-permission android:name="android.permission.INTERNET" /> + <uses-permission android:name="android.permission.INTERNET" /> + <uses-permission android:name="android.permission.POST_NOTIFICATIONS" /> + <uses-permission android:name="android.permission.VIBRATE" /> + <application android:allowBackup="true" android:dataExtractionRules="@xml/data_extraction_rules" android:fullBackupContent="@xml/backup_rules" - android:icon="@mipmap/ic_launcher" + android:icon="@drawable/logo_wtf" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.MobileComputingApp" tools:targetApi="31"> + <activity + android:name=".ModifyPartyForm" + android:exported="false" /> + <activity + android:name=".JoinedActivity" + android:exported="false" /> + <activity + android:name=".AddPartyForm" + android:exported="false" /> + + <meta-data + android:name="com.google.android.geo.API_KEY" + android:value="AIzaSyDws8cqiJZf68mX0K54Xj3hbRvk4Ktlqic" /> + + <activity + android:name=".MapsActivity" + android:exported="false" /> <activity android:name=".LoginActivity" android:exported="true"> @@ -26,8 +48,7 @@ android:exported="false" /> <activity android:name=".MainActivity" - android:exported="false"> - </activity> + android:exported="false" /> </application> </manifest> \ No newline at end of file diff --git a/app/src/main/java/com/example/mobilecomputingapp/AddPartyForm.kt b/app/src/main/java/com/example/mobilecomputingapp/AddPartyForm.kt new file mode 100644 index 0000000000000000000000000000000000000000..8408c98d35ace8618ce566f910eda0557501a711 --- /dev/null +++ b/app/src/main/java/com/example/mobilecomputingapp/AddPartyForm.kt @@ -0,0 +1,261 @@ +package com.example.mobilecomputingapp + +import android.annotation.SuppressLint +import android.app.DatePickerDialog +import android.app.TimePickerDialog +import android.content.Context +import android.content.Intent +import android.os.Bundle +import android.util.Log +import android.view.MotionEvent +import android.widget.EditText +import android.widget.Toast +import androidx.activity.result.contract.ActivityResultContracts +import androidx.appcompat.app.AppCompatActivity +import com.example.mobilecomputingapp.databinding.ActivityAddPartyFormBinding +import com.google.android.libraries.places.api.Places +import com.google.android.libraries.places.api.model.Place +import com.google.android.libraries.places.api.model.TypeFilter +import com.google.android.libraries.places.api.net.PlacesClient +import com.google.android.libraries.places.widget.Autocomplete +import com.google.android.libraries.places.widget.model.AutocompleteActivityMode +import java.util.Arrays +import java.util.Calendar +import java.util.Locale +import com.google.firebase.database.DatabaseReference +import com.google.firebase.database.FirebaseDatabase + + +class AddPartyForm : AppCompatActivity() { + + private lateinit var binding: ActivityAddPartyFormBinding + private var placesClient: PlacesClient? = null + private lateinit var database: DatabaseReference + + private var partyLatitude: Double = 0.0 + private var partyLongitude: Double = 0.0 + + + @SuppressLint("ClickableViewAccessibility") + override fun onCreate(savedInstanceState: Bundle?) { + if (!Places.isInitialized()) { + Places.initialize(applicationContext, getString(R.string.api_key), Locale.UK) + } + + super.onCreate(savedInstanceState) + + binding = ActivityAddPartyFormBinding.inflate(layoutInflater) + setContentView(binding.getRoot()) + + database = FirebaseDatabase.getInstance().reference + + placesClient = Places.createClient(this) + + binding.address.setOnFocusChangeListener { _, hasFocus -> + if (hasFocus) { + startAutocompleteIntent() + } + } + + binding.address.setOnClickListener { + startAutocompleteIntent() + } + + val datePartyEditText: EditText = findViewById(R.id.dateparty) + datePartyEditText.setOnTouchListener { _, event -> + if (event.action == MotionEvent.ACTION_UP) { + showDatePickerDialog() + } + true + } + + val partyFromEditText: EditText = findViewById(R.id.partyfrom) + partyFromEditText.setOnTouchListener { _, event -> + if (event.action == MotionEvent.ACTION_UP) { + showTimePickerDialogFrom() + } + true + } + + val partyToEditText: EditText = findViewById(R.id.partyto) + partyToEditText.setOnTouchListener { _, event -> + if (event.action == MotionEvent.ACTION_UP) { + showTimePickerDialogTo() + } + true + } + + binding.createButton.setOnClickListener { + savePartyToFirebase() + onBackPressed() + } + + binding.addpartyformback.setOnClickListener{ + onBackPressed() + } + } + + private val startAutocomplete = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> + if (result.resultCode == RESULT_OK) { + val intent = result.data + if (intent != null) { + val place = Autocomplete.getPlaceFromIntent(intent) + fillInAddress(place) + } + } else if (result.resultCode == RESULT_CANCELED) { + Log.i("tag", "User canceled autocomplete") + } + } + + private fun startAutocompleteIntent() { + val fields = Arrays.asList( + Place.Field.ADDRESS_COMPONENTS, + Place.Field.LAT_LNG, Place.Field.VIEWPORT + ) + + val intent = Autocomplete.IntentBuilder(AutocompleteActivityMode.OVERLAY, fields) + .setTypesFilter(object : ArrayList<String?>() { + init { + add(TypeFilter.ADDRESS.toString().lowercase(Locale.getDefault())) + } + }) + .build(this) + + startAutocomplete.launch(intent) + } + + private fun showDatePickerDialog() { + val calendar = Calendar.getInstance() + val year = calendar.get(Calendar.YEAR) + val month = calendar.get(Calendar.MONTH) + val day = calendar.get(Calendar.DAY_OF_MONTH) + + val datePickerDialog = DatePickerDialog(this, { _, selectedYear, selectedMonth, selectedDay -> + val selectedDate = "$selectedDay/${selectedMonth + 1}/$selectedYear" + val datePartyEditText: EditText = findViewById(R.id.dateparty) + datePartyEditText.setText(selectedDate) + }, year, month, day) + + datePickerDialog.show() + } + + private fun showTimePickerDialogFrom() { + val calendar = Calendar.getInstance() + val currentHour = calendar.get(Calendar.HOUR_OF_DAY) + val currentMinute = calendar.get(Calendar.MINUTE) + + val timePickerDialog = TimePickerDialog( + this, + { _, hourOfDay, minute -> + // Traitement de l'heure sélectionnée + val selectedTime = String.format("%02d:%02d", hourOfDay, minute) + val partyFromEditText: EditText = findViewById(R.id.partyfrom) + partyFromEditText.setText(selectedTime) + }, + currentHour, + currentMinute, + true // Afficher le mode 24 heures + ) + + timePickerDialog.show() + } + + private fun showTimePickerDialogTo() { + val calendar = Calendar.getInstance() + val currentHour = calendar.get(Calendar.HOUR_OF_DAY) + val currentMinute = calendar.get(Calendar.MINUTE) + + val timePickerDialog = TimePickerDialog( + this, + { _, hourOfDay, minute -> + // Traitement de l'heure sélectionnée + val selectedTime = String.format("%02d:%02d", hourOfDay, minute) + val partyToEditText: EditText = findViewById(R.id.partyto) + partyToEditText.setText(selectedTime) + }, + currentHour, + currentMinute, + true // Afficher le mode 24 heures + ) + + timePickerDialog.show() + } + + private fun fillInAddress(place: Place) { + val components = place.addressComponents + val address = StringBuilder() + + if (components != null) { + for (component in components.asList()) { + val type = component.types[0] + when (type) { + "street_number" -> { + address.insert(0, component.name) + } + + "route" -> { + address.append(" ") + address.append(component.name) + } + + "postal_code" -> { + address.append(" - ").append(component.name) + } + + "postal_code_suffix" -> { + address.append("-").append(component.name) + } + + "locality" -> address.append(" - ").append(component.name) + "administrative_area_level_1" -> { + address.append(", ").append(component.name) + } + + "country" -> address.append(", ").append(component.name) + } + } + } + + partyLatitude = place.latLng?.latitude ?: 0.0 + partyLongitude = place.latLng?.longitude ?: 0.0 + + Log.d("Longitude", partyLongitude.toString()) + Log.d("Latitude", partyLatitude.toString()) + + binding.address.setText(address.toString()) + } + + private fun getUserEmail(): String? { + val sharedPreferences = getSharedPreferences("MyPreferences", Context.MODE_PRIVATE) + // Obtenez l'adresse e-mail enregistrée, si elle existe + return sharedPreferences.getString("userEmail", null) + } + + private fun savePartyToFirebase() { + val partyName = binding.partyname.text.toString() + val partyAddress = binding.address.text.toString() + val partyDate = binding.dateparty.text.toString() + val partyFrom = binding.partyfrom.text.toString() + val partyTo = binding.partyto.text.toString() + val partyDescription = binding.partydescription.text.toString() + val partylongitude = partyLongitude + val partylatitude = partyLatitude + val partyOwner = getUserEmail() + val numberMax = binding.partynumber.text.toString().toInt() + val price = binding.partyprice.text.toString().toDouble() + val paymentLink = binding.partyplink.text.toString() + + // Créez un identifiant unique pour la nouvelle fête + val partyId = database.child("parties").push().key + + // Créez un objet de fête + val party = Party(partyId, partyName, partyAddress, partyDate, partyFrom, partyTo, partyDescription, partylatitude, partylongitude, partyOwner, numberMax, price, paymentLink) + + // Enregistrez la fête dans la base de données + if (partyId != null) { + database.child("parties").child(partyId).setValue(party) + Toast.makeText(this, "Event Created !", Toast.LENGTH_SHORT).show() + } + } +} + diff --git a/app/src/main/java/com/example/mobilecomputingapp/CustomInfoWindowAdapter.kt b/app/src/main/java/com/example/mobilecomputingapp/CustomInfoWindowAdapter.kt new file mode 100644 index 0000000000000000000000000000000000000000..4c232979b2ddd65e927ab7bfa15902880db9ef88 --- /dev/null +++ b/app/src/main/java/com/example/mobilecomputingapp/CustomInfoWindowAdapter.kt @@ -0,0 +1,33 @@ +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.widget.TextView +import com.example.mobilecomputingapp.Party +import com.example.mobilecomputingapp.R +import com.google.android.gms.maps.GoogleMap +import com.google.android.gms.maps.model.Marker + +class CustomInfoWindowAdapter(private val context: Context) : GoogleMap.InfoWindowAdapter { + + override fun getInfoWindow(marker: Marker): View? { + // Retourne null pour utiliser la vue par défaut + return null + } + + override fun getInfoContents(marker: Marker): View { + // Personnalisez la vue de l'info window ici + val contentView = LayoutInflater.from(context).inflate(R.layout.custom_info_window, null) + + val titleTextView: TextView = contentView.findViewById(R.id.titleTextView) + val snippetTextView: TextView = contentView.findViewById(R.id.snippetTextView) + + // Obtenez les données de la fête à partir du tag du marqueur + val party = marker.tag as Party + + // Mettez à jour la vue avec les données de la fête + titleTextView.text = party.name + snippetTextView.text = party.address + + return contentView + } +} diff --git a/app/src/main/java/com/example/mobilecomputingapp/JoinedActivity.kt b/app/src/main/java/com/example/mobilecomputingapp/JoinedActivity.kt new file mode 100644 index 0000000000000000000000000000000000000000..15c88357776562e13afee8b2e2049f5b566a0e65 --- /dev/null +++ b/app/src/main/java/com/example/mobilecomputingapp/JoinedActivity.kt @@ -0,0 +1,324 @@ +package com.example.mobilecomputingapp + +import MyPartyAdapter +import JoinedPartyAdapter +import android.content.Context +import android.content.Intent +import android.os.Bundle +import android.util.Log +import android.view.LayoutInflater +import android.widget.Button +import android.widget.TextView +import android.widget.Toast +import androidx.appcompat.app.AlertDialog +import androidx.appcompat.app.AppCompatActivity +import androidx.appcompat.widget.Toolbar +import androidx.core.net.toUri +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import com.example.mobilecomputingapp.R.id +import com.example.mobilecomputingapp.R.id.buttonClose +import com.example.mobilecomputingapp.databinding.ActivityJoinedBinding +import com.google.firebase.auth.FirebaseAuth +import com.google.firebase.database.ChildEventListener +import com.google.firebase.database.DataSnapshot +import com.google.firebase.database.DatabaseError +import com.google.firebase.database.DatabaseReference +import com.google.firebase.database.FirebaseDatabase +import com.google.firebase.database.ValueEventListener + + +class JoinedActivity : AppCompatActivity() { + + private lateinit var binding: ActivityJoinedBinding + private lateinit var firebaseAuth: FirebaseAuth + private lateinit var databaseReferenceParties: DatabaseReference + private lateinit var joinedPartyAdapter: JoinedPartyAdapter + private lateinit var myPartiesAdapter: MyPartyAdapter + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + binding = ActivityJoinedBinding.inflate(layoutInflater) + setContentView(binding.root) + val toolbar: Toolbar = findViewById(id.toolbar) + setSupportActionBar(toolbar) + supportActionBar?.setDisplayShowTitleEnabled(false) + + firebaseAuth = FirebaseAuth.getInstance() + databaseReferenceParties = FirebaseDatabase.getInstance().reference.child("parties") + + joinedPartyAdapter = JoinedPartyAdapter(this, emptyList()) + myPartiesAdapter = MyPartyAdapter(this, emptyList()) + + + val joinedRecyclerView: RecyclerView = findViewById(id.joinedRecyclerView) + joinedRecyclerView.layoutManager = LinearLayoutManager(this) + joinedRecyclerView.adapter = joinedPartyAdapter // Utilisez joinedPartyAdapter ici + + val mypartiesRecyclerView: RecyclerView = findViewById(id.mypartiesRecyclerView) + mypartiesRecyclerView.layoutManager = LinearLayoutManager(this) + mypartiesRecyclerView.adapter = myPartiesAdapter + + + + databaseReferenceParties.addChildEventListener(object : ChildEventListener { + override fun onChildAdded(snapshot: DataSnapshot, previousChildName: String?) { + // Le code ici sera appelé lorsqu'un nouvel enfant est ajouté à la table + val valeur = snapshot.child("parties").getValue(String::class.java) + // Faites quelque chose avec la valeur... + } + + override fun onChildChanged(snapshot: DataSnapshot, previousChildName: String?) { + // Le code ici sera appelé lorsqu'un enfant existant est modifié + val valeur = snapshot.child("parties").getValue(String::class.java) + // Faites quelque chose avec la nouvelle valeur... + } + + override fun onChildRemoved(snapshot: DataSnapshot) { + // Le code ici sera appelé lorsqu'un enfant est supprimé de la table + } + + override fun onChildMoved(snapshot: DataSnapshot, previousChildName: String?) { + // Le code ici sera appelé lorsqu'un enfant change de position dans la table + } + + override fun onCancelled(error: DatabaseError) { + // Gérer les erreurs ici + } + }) + + val userEmail = getUserEmail() + Log.d("email", userEmail.toString()) + if (userEmail != null) { + // Afficher les parties auxquelles l'utilisateur actuel a adhéré + retrieveJoinedPartiesFromDatabase(userEmail) + + // Afficher les parties dont l'utilisateur actuel est le propriétaire + retrieveMyPartiesFromDatabase(userEmail) + } + + binding.backButton.setOnClickListener{ + onBackPressed() + } + } + + + private fun showToast(message: String) { + Toast.makeText(this, message, Toast.LENGTH_SHORT).show() + } + + private fun retrieveJoinedPartiesFromDatabase(userEmail: String) { + databaseReferenceParties.addValueEventListener(object : ValueEventListener { + override fun onDataChange(snapshot: DataSnapshot) { + val joinedParties = mutableListOf<Party>() + + // Parcourir les données de la base de données + for (partySnapshot in snapshot.children) { + val party = partySnapshot.getValue(Party::class.java) + + // Vérifier si l'utilisateur actuel a adhéré à la fête + if (party?.applied?.contains(userEmail) == true) { + joinedParties.add(party) + } + } + + // Mettre à jour l'adaptateur de parties rejointes + joinedPartyAdapter.updateData(joinedParties) + } + + override fun onCancelled(error: DatabaseError) { + // Gérer l'erreur, si nécessaire + } + }) + } + + private fun retrieveMyPartiesFromDatabase(userEmail: String) { + databaseReferenceParties.addValueEventListener(object : ValueEventListener { + override fun onDataChange(snapshot: DataSnapshot) { + val myParties = mutableListOf<Party>() + + // Parcourir les données de la base de données + for (partySnapshot in snapshot.children) { + val party = partySnapshot.getValue(Party::class.java) + + // Vérifier si l'utilisateur actuel est le propriétaire de la fête + if (party?.partyOwner == userEmail) { + myParties.add(party) + } + } + + // Mettre à jour l'adaptateur de mes parties + myPartiesAdapter.updateData(myParties) + } + + override fun onCancelled(error: DatabaseError) { + // Gérer l'erreur, si nécessaire + } + }) + } + + fun showJoinedPartyInfoDialog(party: Party) { + val dialogView = LayoutInflater.from(this).inflate(R.layout.joined_party_info_dialog, null) + + // Récupérez les vues à partir de la mise en page XML + val textViewPartyName: TextView = dialogView.findViewById(id.textViewPartyName) + val textViewPartyOwner: TextView = dialogView.findViewById(id.textViewPartyOwner) + val textViewPartyAddress: TextView = dialogView.findViewById(id.textViewPartyAddress) + val textViewPartyDate: TextView = dialogView.findViewById(id.textViewPartyDate) + val textViewPartyFrom: TextView = dialogView.findViewById(id.textViewPartyFrom) + val textViewPartyTo: TextView = dialogView.findViewById(id.textViewPartyTo) + val textViewPartyDescription: TextView = dialogView.findViewById(id.textViewPartyDescription) + val textViewPartyPrice: TextView = dialogView.findViewById(id.textViewPartyPrice) + val textViewPartyQty: TextView = dialogView.findViewById(id.textViewPartyquantity) + + + val buttonLeave: Button = dialogView.findViewById(id.buttonLeave) + val buttonClose: Button = dialogView.findViewById(buttonClose) + + // Configurez les valeurs des vues avec les informations de la fête + textViewPartyName.text = "${party.name}" + textViewPartyOwner.text = "Host's Email: ${party.partyOwner}" + textViewPartyAddress.text = "Event Address: ${party.address}" + textViewPartyDate.text = "Date: ${party.date}" + textViewPartyFrom.text = "From: ${party.from}" + textViewPartyTo.text = "To: ${party.to}" + textViewPartyPrice.text = "Price: ${party.price}" + textViewPartyQty.text = "Available ticket: ${party.numberMax?.minus((party.number ?: 0))}" + + textViewPartyDescription.text = "Description:\n ${party.description}" + + // Ajoutez d'autres lignes pour configurer les autres TextView avec les informations de la fête + + // Créez le dialogue + val builder = AlertDialog.Builder(this) + .setView(dialogView) + .setCancelable(true) + + val dialog = builder.create() + + // Configurez les actions des boutons Join et Close + + buttonLeave.setOnClickListener { + onLeaveButtonClicked(party) + dialog.dismiss() + } + + buttonClose.setOnClickListener { + dialog.dismiss() + } + + // Affichez la fenêtre contextuelle + dialog.show() + } + + fun showMyPartyInfoDialog(party: Party) { + val dialogView = LayoutInflater.from(this).inflate(R.layout.my_party_info_dialog, null) + + // Récupérez les vues à partir de la mise en page XML + val textViewPartyName: TextView = dialogView.findViewById(R.id.textViewPartyName) + val textViewPartyOwner: TextView = dialogView.findViewById(R.id.textViewPartyOwner) + val textViewPartyAddress: TextView = dialogView.findViewById(R.id.textViewPartyAddress) + val textViewPartyDate: TextView = dialogView.findViewById(R.id.textViewPartyDate) + val textViewPartyFrom: TextView = dialogView.findViewById(R.id.textViewPartyFrom) + val textViewPartyTo: TextView = dialogView.findViewById(R.id.textViewPartyTo) + val textViewPartyDescription: TextView = dialogView.findViewById(R.id.textViewPartyDescription) + val textViewPartyPrice: TextView = dialogView.findViewById(R.id.textViewPartyPrice) + val textViewPartyQty: TextView = dialogView.findViewById(R.id.textViewPartyquantity) + val textViewApplied: TextView = dialogView.findViewById(R.id.textViewApplied) + + val buttonModify: Button = dialogView.findViewById(R.id.buttonModify) + val buttonDelete: Button = dialogView.findViewById(R.id.buttonDelete) + val buttonClose: Button = dialogView.findViewById(R.id.buttonClose) + + // Configurez les valeurs des vues avec les informations de la fête + textViewPartyName.text = "${party.name}" + textViewPartyOwner.text = "Host's Email: ${party.partyOwner}" + textViewPartyAddress.text = "Event Address: ${party.address}" + textViewPartyDate.text = "Date: ${party.date}" + textViewPartyFrom.text = "From: ${party.from}" + textViewPartyTo.text = "To: ${party.to}" + textViewPartyPrice.text = "Price: ${party.price}" + textViewPartyQty.text = "Available ticket: ${party.numberMax?.minus((party.number ?: 0))}" + + textViewPartyDescription.text = "Description:\n ${party.description}" + + // Configurez le texte pour les personnes qui ont postulé + val appliedText = "People who applied:\n${party.applied.joinToString("\n")}" + textViewApplied.text = appliedText + + // Ajoutez d'autres lignes pour configurer les autres TextView avec les informations de la fête + + // Créez le dialogue + val builder = AlertDialog.Builder(this) + .setView(dialogView) + .setCancelable(true) + + val dialog = builder.create() + + // Configurez les actions des boutons Modify, Delete, et Close + + buttonModify.setOnClickListener { + // Ouvrez le formulaire de modification et passez les informations de la fête + val intent = Intent(this, ModifyPartyForm::class.java) + intent.putExtra("partyToModify", party) + startActivity(intent) + dialog.dismiss() + } + + buttonDelete.setOnClickListener { + // Supprimez la fête de la base de données en utilisant son ID + party.id?.let { partyId -> + val databaseReferenceParties = FirebaseDatabase.getInstance().reference.child("parties") + databaseReferenceParties.child(partyId).removeValue() + .addOnSuccessListener { + // Mettez à jour l'adaptateur après la suppression + myPartiesAdapter.removeParty(party) + Toast.makeText(this, "Event deleted successfully", Toast.LENGTH_SHORT).show() + dialog.dismiss() + } + .addOnFailureListener { + Toast.makeText(this, "Failed to delete Event", Toast.LENGTH_SHORT).show() + dialog.dismiss() + } + } + } + + buttonClose.setOnClickListener { + dialog.dismiss() + } + + // Affichez la fenêtre contextuelle + dialog.show() + } + + + private fun getUserEmail(): String? { + val sharedPreferences = getSharedPreferences("MyPreferences", Context.MODE_PRIVATE) + // Obtenez l'adresse e-mail enregistrée, si elle existe + return sharedPreferences.getString("userEmail", null) + } + + fun onLeaveButtonClicked(party: Party) { + val userEmail = getUserEmail() + + if (party.applied.contains(userEmail)) { + // Supprimez l'utilisateur actuel de la liste des participants + val updatedAppliedList = party.applied.toMutableList().apply { + remove(userEmail) + } + + // Mettez à jour la base de données avec la nouvelle liste + databaseReferenceParties.child(party.id.orEmpty()).child("applied") + .setValue(updatedAppliedList) + + // Mettez à jour le nombre de participants + val currentNumber = party.number ?: 0 + databaseReferenceParties.child(party.id.orEmpty()).child("number") + .setValue(currentNumber - 1) + + showToast("You have left the event!") + } else { + showToast("You have not joined this event.") + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/mobilecomputingapp/JoinedPartyAdapter.kt b/app/src/main/java/com/example/mobilecomputingapp/JoinedPartyAdapter.kt new file mode 100644 index 0000000000000000000000000000000000000000..49c86b19aebe865f4b29ea56b661835b059c419a --- /dev/null +++ b/app/src/main/java/com/example/mobilecomputingapp/JoinedPartyAdapter.kt @@ -0,0 +1,76 @@ +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.Button +import android.widget.TextView +import android.widget.Toast +import androidx.recyclerview.widget.RecyclerView +import com.example.mobilecomputingapp.MainActivity +import com.example.mobilecomputingapp.JoinedActivity +import com.example.mobilecomputingapp.Party +import com.example.mobilecomputingapp.R + +class JoinedPartyAdapter(private val context: Context, private var joinedpartyList: List<Party>) : + RecyclerView.Adapter<JoinedPartyAdapter.PartyViewHolder>() { + + // ViewHolder + inner class PartyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val partyName: TextView = itemView.findViewById(R.id.partyName) + val partyAddress: TextView = itemView.findViewById(R.id.partyAddress) + val partydate: TextView = itemView.findViewById(R.id.partyDate) + val partyinfo: Button = itemView.findViewById(R.id.joinedpartyinfo) + val partyleave: Button = itemView.findViewById(R.id.joinedLeave) + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PartyViewHolder { + val itemView = + LayoutInflater.from(parent.context).inflate(R.layout.joined_party_item, parent, false) + return PartyViewHolder(itemView) + } + + override fun onBindViewHolder(holder: PartyViewHolder, position: Int) { + val currentParty = joinedpartyList[position] + + // Mettez à jour les vues avec les données de la fête actuelle + holder.partyName.text = currentParty.name + holder.partyAddress.text = currentParty.address + holder.partydate.text = currentParty.date + + // Ajoutez un écouteur de clic au bouton de jointure si nécessaire + holder.partyinfo.setOnClickListener { + when (context) { + is JoinedActivity -> { + val joinedActivity = context as JoinedActivity + joinedActivity.showJoinedPartyInfoDialog(currentParty) + } + // Add more cases for other activity contexts if needed + else -> { + Toast.makeText(context, "problème d'annonce chez joined party adapter", Toast.LENGTH_SHORT).show() + } + } + } + holder.partyleave.setOnClickListener { + when (context) { + is JoinedActivity -> { + val joinedActivity = context as JoinedActivity + joinedActivity.onLeaveButtonClicked(currentParty) + } + // Add more cases for other activity contexts if needed + else -> { + Toast.makeText(context, "problème d'annonce chez joined party adapter", Toast.LENGTH_SHORT).show() + } + } + } + } + + override fun getItemCount(): Int { + return joinedpartyList.size + } + + // Fonction pour mettre à jour les données de l'adaptateur + fun updateData(newPartyList: List<Party>) { + joinedpartyList = newPartyList + notifyDataSetChanged() + } +} diff --git a/app/src/main/java/com/example/mobilecomputingapp/LoginActivity.kt b/app/src/main/java/com/example/mobilecomputingapp/LoginActivity.kt index d9b372808293eb8915e348af319b7080a9e4c57e..0a37a123d8e23ce1185b72f75a8b9b12a044597e 100644 --- a/app/src/main/java/com/example/mobilecomputingapp/LoginActivity.kt +++ b/app/src/main/java/com/example/mobilecomputingapp/LoginActivity.kt @@ -1,22 +1,31 @@ package com.example.mobilecomputingapp +import android.app.Activity +import android.content.Context import android.content.Intent import androidx.appcompat.app.AppCompatActivity import android.os.Bundle +import android.widget.ImageView import android.widget.Toast +import androidx.activity.result.contract.ActivityResultContracts import com.example.mobilecomputingapp.databinding.ActivityLoginBinding -import com.google.firebase.database.DataSnapshot -import com.google.firebase.database.DatabaseError +import com.google.android.gms.auth.api.signin.GoogleSignIn +import com.google.android.gms.auth.api.signin.GoogleSignInAccount +import com.google.android.gms.auth.api.signin.GoogleSignInClient +import com.google.android.gms.auth.api.signin.GoogleSignInOptions +import com.google.android.gms.tasks.Task +import com.google.firebase.auth.FirebaseAuth +import com.google.firebase.auth.GoogleAuthProvider import com.google.firebase.database.DatabaseReference import com.google.firebase.database.FirebaseDatabase -import com.google.firebase.database.ValueEventListener -import kotlin.math.sign class LoginActivity : AppCompatActivity() { private lateinit var binding: ActivityLoginBinding private lateinit var firebaseDatabase: FirebaseDatabase private lateinit var databaseReference: DatabaseReference + private lateinit var firebaseAuth: FirebaseAuth + private lateinit var googleSignInClient: GoogleSignInClient override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -25,52 +34,104 @@ class LoginActivity : AppCompatActivity() { firebaseDatabase = FirebaseDatabase.getInstance() databaseReference = firebaseDatabase.reference.child("users") + firebaseAuth = FirebaseAuth.getInstance() - binding.loginButton.setOnClickListener{ + binding.signupRedirect.setOnClickListener{ + startActivity(Intent(this, SignupActivity::class.java)) + finish() + } + + val gso = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN) + .requestIdToken(getString(R.string.default_web_client_id)) + .requestEmail() + .build() + + googleSignInClient = GoogleSignIn.getClient(this, gso) + + findViewById<ImageView>(R.id.googleLogIn).setOnClickListener { + signInGoogle() + } + + binding.loginButton.setOnClickListener { val loginUsername = binding.loginUsername.text.toString() val loginPassword = binding.loginPassword.text.toString() - if(loginUsername.isNotEmpty() && loginPassword.isNotEmpty()){ - loginUser(loginUsername, loginPassword) + if (loginUsername.isNotEmpty() && loginPassword.isNotEmpty()) { + firebaseAuth.signInWithEmailAndPassword(loginUsername, loginPassword) + .addOnCompleteListener { + if (it.isSuccessful) { + saveUserEmail(loginUsername) + startActivity(Intent(this, MainActivity::class.java)) + } + } +// loginUser(loginUsername, loginPassword) } else { - Toast.makeText(this@LoginActivity, "All Fields are mandatory !", Toast.LENGTH_SHORT).show() + Toast.makeText(this@LoginActivity, "All Fields are mandatory !", Toast.LENGTH_SHORT) + .show() } } + } - val id = databaseReference.push().key - val userData = UserData(id,"test1","test1") - databaseReference.child(id!!).setValue(userData) + private fun signInGoogle() { + val SignInIntent = googleSignInClient.signInIntent + launcher.launch(SignInIntent) + } - binding.signupRedirect.setOnClickListener { - startActivity(Intent(this@LoginActivity, SignupActivity::class.java)) - finish() + private val launcher = + registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> + if (result.resultCode == Activity.RESULT_OK) { + val task = GoogleSignIn.getSignedInAccountFromIntent(result.data) + handleResults(task) + } + } + + private fun handleResults(task: Task<GoogleSignInAccount>) { + if (task.isSuccessful) { + val account: GoogleSignInAccount? = task.result + if (account != null) { + updateUI(account) + } + } else { + Toast.makeText(this, task.exception.toString(), Toast.LENGTH_SHORT).show() } } - private fun loginUser(username: String, password: String){ - databaseReference.orderByChild("username").equalTo(username).addListenerForSingleValueEvent(object: ValueEventListener{ - override fun onDataChange(dataSnapshot: DataSnapshot) { - if (dataSnapshot.exists()){ - for (userSnapshot in dataSnapshot.children){ - val userData = userSnapshot.getValue(UserData::class.java) - - if(userData != null && userData.password == password){ - Toast.makeText(this@LoginActivity, "Login Successful", Toast.LENGTH_SHORT).show() - startActivity(Intent(this@LoginActivity, MainActivity::class.java)) - finish() - return - } - } - } - Toast.makeText(this@LoginActivity, "Login Failed", Toast.LENGTH_SHORT).show() + private fun updateUI(account: GoogleSignInAccount) { + val credential = GoogleAuthProvider.getCredential(account.idToken, null) + + firebaseAuth.signInWithCredential(credential).addOnCompleteListener { + if (it.isSuccessful) { + saveUserEmail(account.email ?: "") + startActivity(Intent(this, MainActivity::class.java)) + finish() + } else { + Toast.makeText(this, it.exception.toString(), Toast.LENGTH_SHORT).show() } + } + } - override fun onCancelled(databaseError: DatabaseError) { - Toast.makeText(this@LoginActivity, "Database Error: ${databaseError.message}", Toast.LENGTH_SHORT).show() + override fun onStart() { + super.onStart() - } - }) + val currentUser = firebaseAuth.currentUser + + if(currentUser != null){ + + currentUser.email?.let { saveUserEmail(it) } + + startActivity(Intent(this, MainActivity::class.java)) + finish() + } + } + + private fun saveUserEmail(userEmail: String) { + val sharedPreferences = getSharedPreferences("MyPreferences", Context.MODE_PRIVATE) + val editor = sharedPreferences.edit() + + // Enregistrez la nouvelle adresse e-mail dans les préférences partagées + editor.putString("userEmail", userEmail) + editor.apply() } } \ No newline at end of file diff --git a/app/src/main/java/com/example/mobilecomputingapp/MainActivity.kt b/app/src/main/java/com/example/mobilecomputingapp/MainActivity.kt index 2231ab2e28fa1d25c321fd58c5298a024ff99e47..00034036198b5fec4c41390821b9f236015a1153 100644 --- a/app/src/main/java/com/example/mobilecomputingapp/MainActivity.kt +++ b/app/src/main/java/com/example/mobilecomputingapp/MainActivity.kt @@ -1,20 +1,306 @@ package com.example.mobilecomputingapp +import PartyAdapter +import android.content.Context +import android.content.Intent import android.os.Bundle -import androidx.activity.enableEdgeToEdge +import android.util.Log +import android.view.LayoutInflater +import android.view.Menu +import android.view.MenuInflater +import android.view.MenuItem +import android.widget.Button +import android.widget.TextView +import android.widget.Toast +import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AppCompatActivity -import androidx.core.view.ViewCompat -import androidx.core.view.WindowInsetsCompat +import androidx.appcompat.widget.Toolbar +import androidx.core.net.toUri +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import com.example.mobilecomputingapp.R.id +import com.example.mobilecomputingapp.R.id.buttonClose +import com.example.mobilecomputingapp.databinding.ActivityMainBinding +import com.google.android.gms.maps.GoogleMap +import com.google.android.material.floatingactionbutton.FloatingActionButton +import com.google.firebase.auth.FirebaseAuth +import com.google.firebase.database.ChildEventListener +import com.google.firebase.database.DataSnapshot +import com.google.firebase.database.DatabaseError +import com.google.firebase.database.DatabaseReference +import com.google.firebase.database.FirebaseDatabase +import com.google.firebase.database.ValueEventListener +import java.text.SimpleDateFormat +import java.util.Date +import java.util.Locale + class MainActivity : AppCompatActivity() { + + private lateinit var binding: ActivityMainBinding + private lateinit var firebaseAuth: FirebaseAuth + private lateinit var databaseReferenceParties: DatabaseReference + private lateinit var partyAdapter: PartyAdapter + private lateinit var fab: FloatingActionButton + private lateinit var mapButton: FloatingActionButton + private lateinit var mMap: GoogleMap override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - enableEdgeToEdge() - setContentView(R.layout.activity_main) - ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets -> - val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()) - v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom) - insets + binding = ActivityMainBinding.inflate(layoutInflater) + setContentView(binding.root) + val toolbar: Toolbar = findViewById(id.toolbar) + setSupportActionBar(toolbar) + supportActionBar?.setDisplayShowTitleEnabled(false) + + firebaseAuth = FirebaseAuth.getInstance() + databaseReferenceParties = FirebaseDatabase.getInstance().reference.child("parties") + + val recyclerView: RecyclerView = findViewById(id.recyclerView) + recyclerView.layoutManager = LinearLayoutManager(this) + partyAdapter = PartyAdapter(this, emptyList()) + recyclerView.adapter = partyAdapter + + + databaseReferenceParties.addChildEventListener(object : ChildEventListener { + override fun onChildAdded(snapshot: DataSnapshot, previousChildName: String?) { + // Le code ici sera appelé lorsqu'un nouvel enfant est ajouté à la table + val valeur = snapshot.child("parties").getValue(String::class.java) + // Faites quelque chose avec la valeur... + } + + override fun onChildChanged(snapshot: DataSnapshot, previousChildName: String?) { + // Le code ici sera appelé lorsqu'un enfant existant est modifié + val valeur = snapshot.child("parties").getValue(String::class.java) + // Faites quelque chose avec la nouvelle valeur... + } + + override fun onChildRemoved(snapshot: DataSnapshot) { + // Le code ici sera appelé lorsqu'un enfant est supprimé de la table + val valeur = snapshot.child("parties").getValue(String::class.java) + } + + override fun onChildMoved(snapshot: DataSnapshot, previousChildName: String?) { + // Le code ici sera appelé lorsqu'un enfant change de position dans la table + } + + override fun onCancelled(error: DatabaseError) { + // Gérer les erreurs ici + } + }) + + fab = findViewById(R.id.fab) + fab.setOnClickListener { + startActivity(Intent(this, AddPartyForm::class.java)) + } + mapButton = findViewById(R.id.mapButton) + mapButton.setOnClickListener { + startActivity(Intent(this, MapsActivity::class.java)) + } + + binding.accountButton.setOnClickListener { + startActivity(Intent(this, JoinedActivity::class.java)) } + + + retrievePartiesFromDatabase() + + } + override fun onCreateOptionsMenu(menu: Menu?): Boolean { + val inflater: MenuInflater = menuInflater + inflater.inflate(R.menu.mainmenu, menu) + return true + } + override fun onOptionsItemSelected(item: MenuItem): Boolean { + when (item.itemId) { + id.signout -> { + firebaseAuth.signOut() + removeUserEmail() + startActivity(Intent(this, LoginActivity::class.java)) + finish() + } + else -> return super.onOptionsItemSelected(item) + } + return true + } + + private fun showToast(message: String) { + Toast.makeText(this, message, Toast.LENGTH_SHORT).show() + } + + private fun removeUserEmail() { + val sharedPreferences = getSharedPreferences("MyPreferences", Context.MODE_PRIVATE) + val editor = sharedPreferences.edit() + + // Supprimez la préférence de l'adresse e-mail + editor.remove("userEmail") + editor.apply() + } + + private fun retrievePartiesFromDatabase() { + // Ajouter un écouteur pour surveiller les changements dans la base de données + databaseReferenceParties.addValueEventListener(object : ValueEventListener { + override fun onDataChange(snapshot: DataSnapshot) { + val parties = mutableListOf<Party>() + + // Parcourir les données de la base de données + for (partySnapshot in snapshot.children) { + val party = partySnapshot.getValue(Party::class.java) + party?.let { parties.add(it) } + } + + // Filtrer les fêtes dont la date est inférieure à la date d'aujourd'hui + val currentDate = SimpleDateFormat("dd/M/yyyy", Locale.getDefault()).format(Date()) + val filteredParties = parties.filter { party -> + val partyDate = party.date ?: "" + partyDate.isNotEmpty() && isAfterCurrentDate(partyDate, currentDate) + } + + // Trier les fêtes restantes par date, du plus proche au plus éloigné + val sortedPartyList = filteredParties.sortedBy { party -> + calculateDistance( + 48.483334, + 9.216667, + party.latitude ?: 0.0, + party.longitude ?: 0.0 + ) + } + + // Mettre à jour l'adaptateur avec les nouvelles données triées + partyAdapter.updateData(sortedPartyList) + } + + override fun onCancelled(error: DatabaseError) { + // Gérer l'erreur, si nécessaire + } + }) + } + + // Fonction pour vérifier si la date de la fête est après la date d'aujourd'hui + private fun isAfterCurrentDate(partyDate: String, currentDate: String): Boolean { + val sdf = SimpleDateFormat("dd/mm/yyyy", Locale.getDefault()) + val date1 = sdf.parse(partyDate) + val date2 = sdf.parse(currentDate) + + return date1 != null && date2 != null && (date1.after(date2) || date1.equals(date2)) + } + + private fun calculateDistance( + lat1: Double, + lon1: Double, + lat2: Double, + lon2: Double + ): Double { + val R = 6371 // Rayon de la Terre en kilomètres + val dLat = Math.toRadians(lat2 - lat1) + val dLon = Math.toRadians(lon2 - lon1) + val a = + Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(Math.toRadians(lat1)) * + Math.cos(Math.toRadians(lat2)) * Math.sin(dLon / 2) * Math.sin(dLon / 2) + val c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)) + return R * c + } + + fun showPartyInfoDialog(party: Party) { + val dialogView = LayoutInflater.from(this).inflate(R.layout.party_info_dialog, null) + + // Récupérez les vues à partir de la mise en page XML + val textViewPartyName: TextView = dialogView.findViewById(id.textViewPartyName) + val textViewPartyOwner: TextView = dialogView.findViewById(id.textViewPartyOwner) + val textViewPartyAddress: TextView = dialogView.findViewById(id.textViewPartyAddress) + val textViewPartyDate: TextView = dialogView.findViewById(id.textViewPartyDate) + val textViewPartyFrom: TextView = dialogView.findViewById(id.textViewPartyFrom) + val textViewPartyTo: TextView = dialogView.findViewById(id.textViewPartyTo) + val textViewPartyDescription: TextView = dialogView.findViewById(id.textViewPartyDescription) + val textViewPartyPrice: TextView = dialogView.findViewById(id.textViewPartyPrice) + val textViewPartyQty: TextView = dialogView.findViewById(id.textViewPartyquantity) + + + val buttonJoin: Button = dialogView.findViewById(id.buttonJoin) + val buttonClose: Button = dialogView.findViewById(buttonClose) + + // Configurez les valeurs des vues avec les informations de la fête + textViewPartyName.text = "${party.name}" + textViewPartyOwner.text = "Host's Email: ${party.partyOwner}" + textViewPartyAddress.text = "Event Address: ${party.address}" + textViewPartyDate.text = "Date: ${party.date}" + textViewPartyFrom.text = "From: ${party.from}" + textViewPartyTo.text = "To: ${party.to}" + textViewPartyPrice.text = "Price: ${party.price}" + textViewPartyQty.text = "Available tickets: ${party.numberMax?.minus((party.number ?: 0))}" + + textViewPartyDescription.text = "Description:\n ${party.description}" + + // Ajoutez d'autres lignes pour configurer les autres TextView avec les informations de la fête + + // Créez le dialogue + val builder = AlertDialog.Builder(this) + .setView(dialogView) + .setCancelable(true) + + val dialog = builder.create() + + // Configurez les actions des boutons Join et Close + val joinButton = dialogView.findViewById<Button>(id.buttonJoin) + + joinButton.setOnClickListener { + onJoinButtonClicked(party) + dialog.dismiss() + } + + val closeButton = dialogView.findViewById<Button>(id.buttonClose) + closeButton.setOnClickListener { + dialog.dismiss() + } + + // Affichez la fenêtre contextuelle + dialog.show() + } + private fun onJoinButtonClicked(party: Party) { + val userEmail = getUserEmail() + + if (party.applied.contains(userEmail)) { + showToast("You have already joined this event.") + return + } + + val currentNumber = party.number ?: 0 + val maxNumber = party.numberMax ?: 0 + + Log.d("JoinButtonClicked", "Current Number: $currentNumber, Max Number: $maxNumber") + + if (currentNumber < maxNumber) { + if (party.paymentLink.isNullOrEmpty()) { + // Entrée gratuite + val updatedAppliedList = party.applied.toMutableList().apply { + userEmail?.let { add(it) } + } + + // Mettre à jour la base de données avec la nouvelle liste + databaseReferenceParties.child(party.id.orEmpty()).child("applied") + .setValue(updatedAppliedList) + + // Mettre à jour le nombre de participants + databaseReferenceParties.child(party.id.orEmpty()).child("number") + .setValue(currentNumber + 1) + + showToast("You have joined the event!") + + } else { + // Entrée payante + if (party.paymentLink != null && party.paymentLink!!.isNotEmpty()) { + val intent = Intent(Intent.ACTION_VIEW, party.paymentLink!!.toUri()) + startActivity(intent) + } else { + showToast("Payment link is empty.") + } + } + } else { + showToast("All tickets are already taken!") + } + } + private fun getUserEmail(): String? { + val sharedPreferences = getSharedPreferences("MyPreferences", Context.MODE_PRIVATE) + // Obtenez l'adresse e-mail enregistrée, si elle existe + return sharedPreferences.getString("userEmail", null) } } \ No newline at end of file diff --git a/app/src/main/java/com/example/mobilecomputingapp/MapsActivity.kt b/app/src/main/java/com/example/mobilecomputingapp/MapsActivity.kt new file mode 100644 index 0000000000000000000000000000000000000000..14fb9e1c51106584f457dc53d3668a3cd82b18e4 --- /dev/null +++ b/app/src/main/java/com/example/mobilecomputingapp/MapsActivity.kt @@ -0,0 +1,416 @@ +package com.example.mobilecomputingapp + +import CustomInfoWindowAdapter +import android.annotation.SuppressLint +import android.content.Context +import android.content.pm.PackageManager +import android.location.Location +import android.os.Bundle +import android.widget.Toast +import androidx.appcompat.app.AppCompatActivity +import androidx.core.app.ActivityCompat +import com.example.mobilecomputingapp.databinding.ActivityMapsBinding +import com.google.android.gms.location.FusedLocationProviderClient +import com.google.android.gms.location.LocationServices +import com.google.android.gms.maps.* +import com.google.android.gms.maps.model.LatLng +import com.google.android.gms.maps.model.MarkerOptions +import com.google.firebase.database.DataSnapshot +import com.google.firebase.database.DatabaseError +import com.google.firebase.database.FirebaseDatabase +import com.google.firebase.database.ValueEventListener +import android.content.Intent +import android.location.LocationManager +import android.os.Handler +import android.util.Log +import android.view.LayoutInflater +import android.widget.Button +import android.widget.TextView +import androidx.core.net.toUri +import com.google.android.gms.maps.model.Marker +import com.google.firebase.database.ChildEventListener +import com.google.firebase.database.DatabaseReference + + +class MapsActivity : AppCompatActivity(), OnMapReadyCallback { + + private lateinit var mMap: GoogleMap + private lateinit var binding: ActivityMapsBinding + + private lateinit var currentLocation: Location + private lateinit var fusedLocationProviderClient: FusedLocationProviderClient + private val permissionCode = 101 + private lateinit var databaseReferenceParties: DatabaseReference + private val markers = mutableListOf<Marker>() + + private val partiesList = mutableListOf<Party>() + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + binding = ActivityMapsBinding.inflate(layoutInflater) + setContentView(binding.root) + + fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this) + databaseReferenceParties = FirebaseDatabase.getInstance().reference.child("parties") + + if (markers.isEmpty()) { + markers.clear() + } + + databaseReferenceParties.addChildEventListener(object : ChildEventListener { + override fun onChildAdded(snapshot: DataSnapshot, previousChildName: String?) { + Log.d("Firebase", "onChildAdded") + val party = snapshot.getValue(Party::class.java) + party?.let { + // Ajoutez un marqueur sur la carte avec les données de la fête nouvellement ajoutée + addMarkerOnMap(it) + Log.d("Marker", "Marker added successfully") + Log.d("Marker", "Markers size: ${markers.size}") + } + } + + override fun onChildChanged(snapshot: DataSnapshot, previousChildName: String?) { + Log.d("Firebase", "onChildChanged") + val updatedParty = snapshot.getValue(Party::class.java) + updatedParty?.let { + Log.d("Firebase", "Updated Party ID: ${it.id}") + // Mettez à jour le marqueur sur la carte avec les nouvelles données de la fête modifiée + updateMarkerOnMap(it) + + // Mettez à jour le tag du marqueur avec les nouvelles données de la fête + var markerUpdated = false + for (marker in markers) { + val party = marker.tag as? Party + if (party?.id == updatedParty.id) { + marker.tag = updatedParty + markerUpdated = true + Log.d("Marker", "Marker updated successfully") + break + } + } + + if (!markerUpdated) { + Log.e("Marker", "Marker not found for party with ID: ${updatedParty?.id}") + Log.e("Marker", "Markers size: ${markers.size}") + } + } + } + + override fun onChildRemoved(snapshot: DataSnapshot) { + Log.d("Firebase", "onChildRemoved") + val removedParty = snapshot.getValue(Party::class.java) + removedParty?.let { + // Supprimez le marqueur correspondant sur la carte lorsque la fête est supprimée + removeMarkerFromMap(it) + } + } + + override fun onChildMoved(snapshot: DataSnapshot, previousChildName: String?) { + // Peut être ignoré, sauf si vous avez besoin de gérer les mouvements des enfants + } + + override fun onCancelled(error: DatabaseError) { + // Gérer les erreurs ici + } + }) + + val mapFragment = supportFragmentManager.findFragmentById(R.id.map) as SupportMapFragment + mapFragment.getMapAsync(this) + + val databaseReferenceParties = FirebaseDatabase.getInstance().getReference("parties") + databaseReferenceParties.addValueEventListener(object : ValueEventListener { + override fun onDataChange(dataSnapshot: DataSnapshot) { + partiesList.clear() + for (partySnapshot in dataSnapshot.children) { + val party = partySnapshot.getValue(Party::class.java) + party?.let { partiesList.add(it) } + } + // Ajoutez des marqueurs sur la carte avec les données récupérées + Log.d("test","onchangedata") + addMarkersOnMap() + } + + override fun onCancelled(databaseError: DatabaseError) { + // Gérez l'erreur + } + }) + binding.listButton.setOnClickListener { + startActivity(Intent(this, MainActivity::class.java)) + finish() + } + binding.fab.setOnClickListener { + startActivity(Intent(this, AddPartyForm::class.java)) + } + } + + private fun showToast(message: String) { + Toast.makeText(this, message, Toast.LENGTH_SHORT).show() + } + + private fun placeMarker(latLng: LatLng, annotation: String) { + // Coloca un marcador en la ubicación proporcionada + mMap.addMarker(MarkerOptions().position(latLng).title(annotation)) + + mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, 15f)) + } + + private fun getCurrentLocationUser() { + if (ActivityCompat.checkSelfPermission( + this, android.Manifest.permission.ACCESS_FINE_LOCATION + ) != + PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission + (this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != + PackageManager.PERMISSION_GRANTED + ) { + ActivityCompat.requestPermissions(this, + arrayOf(android.Manifest.permission.ACCESS_FINE_LOCATION), permissionCode) + return + } + + // Obtenez la dernière position connue de l'utilisateur + fusedLocationProviderClient.lastLocation.addOnSuccessListener { location -> + if (location != null) { + currentLocation = location + val userLatLng = LatLng(currentLocation.latitude, currentLocation.longitude) + + // Zoom sur la position actuelle + mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(userLatLng, 15f)) + } + } + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array<out String>, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + when (requestCode) { + permissionCode -> if (grantResults.isNotEmpty() && grantResults[0] == + PackageManager.PERMISSION_GRANTED + ) { + getCurrentLocationUser() + } + } + } + + override fun onMapReady(googleMap: GoogleMap) { + // Le map est prêt pour être utilisé + mMap = googleMap + + // Initialiser la liste des marqueurs + markers.clear() + + // Masquer les boutons d'itinéraire et de Maps + mMap.uiSettings.isMapToolbarEnabled = false + + // Configurer l'adapter pour l'info window + mMap.setInfoWindowAdapter(CustomInfoWindowAdapter(this)) + + // Gérer le clic sur l'info window + mMap.setOnInfoWindowClickListener { marker -> + val party = marker.tag as? Party + party?.let { + // Afficher la fenêtre d'informations avec les boutons "Close" et "Join" + showPartyInfoWindow(it) + } + + } + + // Vérifier si la localisation est activée + if (isLocationEnabled()) { + // Localisation activée, zoom sur la position actuelle + getCurrentLocationUser() + } else { + // Localisation désactivée, zoom sur la ville de Reutlingen + zoomToReutlingen() + } + + // Attribuer des tags aux marqueurs à partir des données de fête + Log.d("test","onmapready") + addMarkersOnMap() + } + + private fun addMarkersOnMap() { + if (::mMap.isInitialized) { + for (party in partiesList) { + val partyLocation = LatLng(party.latitude ?: 0.0, party.longitude ?: 0.0) + val marker = mMap.addMarker( + MarkerOptions() + .position(partyLocation) + .title(party.name) + ) + marker.tag = party // Attachez les données de la fête au marqueur + markers.add(marker) // Ajoutez le marqueur à la liste + } + } else { + // Attendre que mMap soit initialisé, par exemple, en plaçant une logique de réessai + Handler().postDelayed({ + Log.d("test","addmarkersonmap") + addMarkersOnMap() + }, 100) // Attendre 100 millisecondes avant de réessayer + } + } + + @SuppressLint("CutPasteId") + private fun showPartyInfoWindow(party: Party) { + val dialogView = LayoutInflater.from(this).inflate(R.layout.party_info_dialog, null) + + // Récupérez les vues à partir de la mise en page XML + val textViewPartyName: TextView = dialogView.findViewById(R.id.textViewPartyName) + val textViewPartyOwner: TextView = dialogView.findViewById(R.id.textViewPartyOwner) + val textViewPartyAddress: TextView = dialogView.findViewById(R.id.textViewPartyAddress) + val textViewPartyDate: TextView = dialogView.findViewById(R.id.textViewPartyDate) + val textViewPartyFrom: TextView = dialogView.findViewById(R.id.textViewPartyFrom) + val textViewPartyTo: TextView = dialogView.findViewById(R.id.textViewPartyTo) + val textViewPartyDescription: TextView = dialogView.findViewById(R.id.textViewPartyDescription) + val textViewPartyPrice: TextView = dialogView.findViewById(R.id.textViewPartyPrice) + val textViewPartyQty: TextView = dialogView.findViewById(R.id.textViewPartyquantity) + + + val buttonJoin: Button = dialogView.findViewById(R.id.buttonJoin) + val buttonClose: Button = dialogView.findViewById(R.id.buttonClose) + + // Configurez les valeurs des vues avec les informations de la fête + textViewPartyName.text = "${party.name}" + textViewPartyOwner.text = "Host's Email: ${party.partyOwner}" + textViewPartyAddress.text = "Event Address: ${party.address}" + textViewPartyDate.text = "Date: ${party.date}" + textViewPartyFrom.text = "From: ${party.from}" + textViewPartyTo.text = "To: ${party.to}" + textViewPartyPrice.text = "Price: ${party.price}" + textViewPartyQty.text = "Available ticket: ${party.numberMax?.minus((party.number ?: 0))}" + + textViewPartyDescription.text = "Description:\n ${party.description}" + + // Ajoutez d'autres lignes pour configurer les autres TextView avec les informations de la fête + + // Créez le dialogue + val builder = androidx.appcompat.app.AlertDialog.Builder(this) + .setView(dialogView) + .setCancelable(true) + + val dialog = builder.create() + + // Configurez les actions des boutons Join et Close + val joinButton = dialogView.findViewById<Button>(R.id.buttonJoin) + joinButton.setOnClickListener { + onJoinButtonClicked(party) + dialog.dismiss() + } + + val closeButton = dialogView.findViewById<Button>(R.id.buttonClose) + closeButton.setOnClickListener { + dialog.dismiss() + } + + // Affichez la fenêtre contextuelle + dialog.show() + } + + private fun onJoinButtonClicked(party: Party) { + val userEmail = getUserEmail() + + if (party.applied.contains(userEmail)) { + showToast("You have already joined this event.") + return + } + + val currentNumber = party.number ?: 0 + val maxNumber = party.numberMax ?: 0 + + Log.d("JoinButtonClicked", "Current Number: $currentNumber, Max Number: $maxNumber") + + if (currentNumber < maxNumber) { + if (party.paymentLink.isNullOrEmpty()) { + // Entrée gratuite + val updatedAppliedList = party.applied.toMutableList().apply { + userEmail?.let { add(it) } + } + + // Mettre à jour la base de données avec la nouvelle liste + databaseReferenceParties.child(party.id.orEmpty()).child("applied") + .setValue(updatedAppliedList) + + // Mettre à jour le nombre de participants + databaseReferenceParties.child(party.id.orEmpty()).child("number") + .setValue(currentNumber + 1) + + showToast("You have joined the event!") + + } else { + // Entrée payante + if (party.paymentLink?.isNotEmpty() == true) { + val intent = Intent(Intent.ACTION_VIEW, party.paymentLink!!.toUri()) + startActivity(intent) + } else { + showToast("Payment link is empty.") + } + } + } else { + showToast("All tickets are already taken!") + } + } + private fun getUserEmail(): String? { + val sharedPreferences = getSharedPreferences("MyPreferences", Context.MODE_PRIVATE) + // Obtenez l'adresse e-mail enregistrée, si elle existe + return sharedPreferences.getString("userEmail", null) + } + + private fun addMarkerOnMap(party: Party) { + // Vérifie si mMap est initialisé + if (::mMap.isInitialized) { + val partyLocation = LatLng(party.latitude ?: 0.0, party.longitude ?: 0.0) + val marker = mMap.addMarker( + MarkerOptions() + .position(partyLocation) + .title(party.name) + ) + marker.tag = party // Attachez les données de la fête au marqueur + markers.add(marker) // Ajoutez le marqueur à la liste + } else { + // Attendre que mMap soit initialisé, par exemple, en plaçant une logique de réessai + Handler().postDelayed({ + Log.d("test","addmarkersonmap") + addMarkersOnMap() + }, 100) // Attendre 100 millisecondes avant de réessayer + } + } + private fun updateMarkerOnMap(updatedParty: Party) { + for (marker in markers) { + val party = marker.tag as? Party + if (party?.id == updatedParty.id) { + marker.tag = updatedParty // Mettez à jour les données de la fête dans le tag du marqueur + // Mettez à jour d'autres informations du marqueur si nécessaire + } + } + } + + private fun removeMarkerFromMap(removedParty: Party) { + val markerToRemove = markers.firstOrNull { marker -> + val party = marker.tag as? Party + party?.id == removedParty.id + } + + markerToRemove?.remove() + markers.remove(markerToRemove) + } + private fun clearMarkers() { + for (marker in markers) { + marker.remove() + } + markers.clear() + } + + private fun isLocationEnabled(): Boolean { + val locationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager + return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) || + locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER) + } + + private fun zoomToReutlingen() { + val reutlingen = LatLng(48.4919, 9.2046) + mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(reutlingen, 15f)) + } +} diff --git a/app/src/main/java/com/example/mobilecomputingapp/ModifyPartyForm.kt b/app/src/main/java/com/example/mobilecomputingapp/ModifyPartyForm.kt new file mode 100644 index 0000000000000000000000000000000000000000..9dcb3166c2fee9a4466c6bbac6f16b10855f3235 --- /dev/null +++ b/app/src/main/java/com/example/mobilecomputingapp/ModifyPartyForm.kt @@ -0,0 +1,284 @@ +package com.example.mobilecomputingapp + +import android.annotation.SuppressLint +import android.app.DatePickerDialog +import android.app.TimePickerDialog +import android.content.Context +import android.os.Bundle +import android.util.Log +import android.view.MotionEvent +import android.widget.EditText +import android.widget.Toast +import android.widget.Toast.* +import androidx.activity.enableEdgeToEdge +import androidx.activity.result.contract.ActivityResultContracts +import androidx.appcompat.app.AppCompatActivity +import androidx.core.view.ViewCompat +import androidx.core.view.WindowInsetsCompat +import com.example.mobilecomputingapp.databinding.ActivityModifyPartyFormBinding +import com.google.android.libraries.places.api.Places +import com.google.android.libraries.places.api.model.Place +import com.google.android.libraries.places.api.model.TypeFilter +import com.google.android.libraries.places.api.net.PlacesClient +import com.google.android.libraries.places.widget.Autocomplete +import com.google.android.libraries.places.widget.model.AutocompleteActivityMode +import com.google.firebase.database.DatabaseReference +import com.google.firebase.database.FirebaseDatabase +import java.util.Arrays +import java.util.Calendar +import java.util.Locale + +class ModifyPartyForm : AppCompatActivity() { + + private lateinit var binding: ActivityModifyPartyFormBinding + private var placesClient: PlacesClient? = null + private lateinit var database: DatabaseReference + + private var partyLatitude: Double = 0.0 + private var partyLongitude: Double = 0.0 + + + @SuppressLint("ClickableViewAccessibility") + override fun onCreate(savedInstanceState: Bundle?) { + if (!Places.isInitialized()) { + Places.initialize(applicationContext, getString(R.string.api_key), Locale.UK) + } + + super.onCreate(savedInstanceState) + + binding = ActivityModifyPartyFormBinding.inflate(layoutInflater) + setContentView(binding.getRoot()) + + database = FirebaseDatabase.getInstance().reference + + placesClient = Places.createClient(this) + + val partyToModify: Party? = intent.getSerializableExtra("partyToModify") as? Party + + binding.address.setText(partyToModify?.address) + binding.partyname.setText(partyToModify?.name) + binding.dateparty.setText(partyToModify?.date) + binding.partynumber.setText(partyToModify?.numberMax.toString()) + binding.partyprice.setText(partyToModify?.price.toString()) + binding.partyplink.setText(partyToModify?.paymentLink) + binding.partyfrom.setText(partyToModify?.from) + binding.partyto.setText(partyToModify?.to) + binding.partydescription.setText(partyToModify?.description) + + binding.address.setOnFocusChangeListener { _, hasFocus -> + if (hasFocus) { + startAutocompleteIntent() + } + } + + binding.address.setOnClickListener { + startAutocompleteIntent() + } + + val datePartyEditText: EditText = findViewById(R.id.dateparty) + datePartyEditText.setOnTouchListener { _, event -> + if (event.action == MotionEvent.ACTION_UP) { + showDatePickerDialog() + } + true + } + + val partyFromEditText: EditText = findViewById(R.id.partyfrom) + partyFromEditText.setOnTouchListener { _, event -> + if (event.action == MotionEvent.ACTION_UP) { + showTimePickerDialogFrom() + } + true + } + + val partyToEditText: EditText = findViewById(R.id.partyto) + partyToEditText.setOnTouchListener { _, event -> + if (event.action == MotionEvent.ACTION_UP) { + showTimePickerDialogTo() + } + true + } + + binding.createButton.setOnClickListener { + savePartyToFirebase() + onBackPressed() + } + + binding.addpartyformback.setOnClickListener{ + onBackPressed() + } + } + + private val startAutocomplete = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> + if (result.resultCode == RESULT_OK) { + val intent = result.data + if (intent != null) { + val place = Autocomplete.getPlaceFromIntent(intent) + fillInAddress(place) + } + } else if (result.resultCode == RESULT_CANCELED) { + Log.i("tag", "User canceled autocomplete") + } + } + + private fun startAutocompleteIntent() { + val fields = Arrays.asList( + Place.Field.ADDRESS_COMPONENTS, + Place.Field.LAT_LNG, Place.Field.VIEWPORT + ) + + val intent = Autocomplete.IntentBuilder(AutocompleteActivityMode.OVERLAY, fields) + .setTypesFilter(object : ArrayList<String?>() { + init { + add(TypeFilter.ADDRESS.toString().lowercase(Locale.getDefault())) + } + }) + .build(this) + + startAutocomplete.launch(intent) + } + + private fun showDatePickerDialog() { + val calendar = Calendar.getInstance() + val year = calendar.get(Calendar.YEAR) + val month = calendar.get(Calendar.MONTH) + val day = calendar.get(Calendar.DAY_OF_MONTH) + + val datePickerDialog = DatePickerDialog(this, { _, selectedYear, selectedMonth, selectedDay -> + val selectedDate = "$selectedDay/${selectedMonth + 1}/$selectedYear" + val datePartyEditText: EditText = findViewById(R.id.dateparty) + datePartyEditText.setText(selectedDate) + }, year, month, day) + + datePickerDialog.show() + } + + private fun showTimePickerDialogFrom() { + val calendar = Calendar.getInstance() + val currentHour = calendar.get(Calendar.HOUR_OF_DAY) + val currentMinute = calendar.get(Calendar.MINUTE) + + val timePickerDialog = TimePickerDialog( + this, + { _, hourOfDay, minute -> + // Traitement de l'heure sélectionnée + val selectedTime = String.format("%02d:%02d", hourOfDay, minute) + val partyFromEditText: EditText = findViewById(R.id.partyfrom) + partyFromEditText.setText(selectedTime) + }, + currentHour, + currentMinute, + true // Afficher le mode 24 heures + ) + + timePickerDialog.show() + } + + private fun showTimePickerDialogTo() { + val calendar = Calendar.getInstance() + val currentHour = calendar.get(Calendar.HOUR_OF_DAY) + val currentMinute = calendar.get(Calendar.MINUTE) + + val timePickerDialog = TimePickerDialog( + this, + { _, hourOfDay, minute -> + // Traitement de l'heure sélectionnée + val selectedTime = String.format("%02d:%02d", hourOfDay, minute) + val partyToEditText: EditText = findViewById(R.id.partyto) + partyToEditText.setText(selectedTime) + }, + currentHour, + currentMinute, + true // Afficher le mode 24 heures + ) + + timePickerDialog.show() + } + + private fun fillInAddress(place: Place) { + val components = place.addressComponents + val address = StringBuilder() + + if (components != null) { + for (component in components.asList()) { + val type = component.types[0] + when (type) { + "street_number" -> { + address.insert(0, component.name) + } + + "route" -> { + address.append(" ") + address.append(component.name) + } + + "postal_code" -> { + address.append(" - ").append(component.name) + } + + "postal_code_suffix" -> { + address.append("-").append(component.name) + } + + "locality" -> address.append(" - ").append(component.name) + "administrative_area_level_1" -> { + address.append(", ").append(component.name) + } + + "country" -> address.append(", ").append(component.name) + } + } + } + + partyLatitude = place.latLng?.latitude ?: 0.0 + partyLongitude = place.latLng?.longitude ?: 0.0 + + Log.d("Longitude", partyLongitude.toString()) + Log.d("Latitude", partyLatitude.toString()) + + binding.address.setText(address.toString()) + } + + private fun getUserEmail(): String? { + val sharedPreferences = getSharedPreferences("MyPreferences", Context.MODE_PRIVATE) + // Obtenez l'adresse e-mail enregistrée, si elle existe + return sharedPreferences.getString("userEmail", null) + } + + private fun savePartyToFirebase() { + val partyToModify: Party? = intent.getSerializableExtra("partyToModify") as? Party + + // Assurez-vous que la fête à modifier existe + if (partyToModify != null) { + // Stockez la valeur initiale de paymentLink + val originalPaymentLink = partyToModify.paymentLink + + // Mettez à jour les propriétés de la fête existante avec les nouvelles valeurs + partyToModify.name = binding.partyname.text.toString() + partyToModify.address = binding.address.text.toString() + partyToModify.date = binding.dateparty.text.toString() + partyToModify.from = binding.partyfrom.text.toString() + partyToModify.to = binding.partyto.text.toString() + partyToModify.description = binding.partydescription.text.toString() + partyToModify.latitude = partyLatitude + partyToModify.longitude = partyLongitude + partyToModify.partyOwner = getUserEmail() + partyToModify.numberMax = binding.partynumber.text.toString().toInt() + partyToModify.price = binding.partyprice.text.toString().toDouble() + partyToModify.paymentLink = binding.partyplink.text.toString() + + // Mettez à jour la fête dans la base de données en utilisant son ID + val partyId = partyToModify.id + if (partyId != null) { + database.child("parties").child(partyId).setValue(partyToModify) + + // Restaurez la valeur initiale de paymentLink après la modification + partyToModify.paymentLink = originalPaymentLink + Toast.makeText(this, "Event Modified !", LENGTH_SHORT).show() + } + } + } + + +} + diff --git a/app/src/main/java/com/example/mobilecomputingapp/MyPartyAdapter.kt b/app/src/main/java/com/example/mobilecomputingapp/MyPartyAdapter.kt new file mode 100644 index 0000000000000000000000000000000000000000..022313454ec7805ce3241926b561c99dbe49e881 --- /dev/null +++ b/app/src/main/java/com/example/mobilecomputingapp/MyPartyAdapter.kt @@ -0,0 +1,97 @@ +import android.content.Context +import android.content.Intent +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.Button +import android.widget.TextView +import android.widget.Toast +import androidx.recyclerview.widget.RecyclerView +import com.example.mobilecomputingapp.JoinedActivity +import com.example.mobilecomputingapp.ModifyPartyForm +import com.example.mobilecomputingapp.Party +import com.example.mobilecomputingapp.R +import com.google.firebase.database.FirebaseDatabase + +class MyPartyAdapter(private val context: Context, var myPartyList: List<Party>) : + RecyclerView.Adapter<MyPartyAdapter.PartyViewHolder>() { + + inner class PartyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val partyName: TextView = itemView.findViewById(R.id.partyName) + val partyAddress: TextView = itemView.findViewById(R.id.partyAddress) + val partyDate: TextView = itemView.findViewById(R.id.partyDate) + val partyInfo: Button = itemView.findViewById(R.id.mypartyInfo) + val buttonModify: Button = itemView.findViewById(R.id.buttonModify) + val buttonDelete: Button = itemView.findViewById(R.id.buttonDelete) + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PartyViewHolder { + val itemView = LayoutInflater.from(parent.context) + .inflate(R.layout.my_party_item, parent, false) + return PartyViewHolder(itemView) + } + + override fun onBindViewHolder(holder: PartyViewHolder, position: Int) { + val currentParty = myPartyList[position] + + holder.partyName.text = currentParty.name + holder.partyAddress.text = currentParty.address + holder.partyDate.text = currentParty.date + + holder.partyInfo.setOnClickListener { + when (context) { + is JoinedActivity -> { + val joinedActivity = context as JoinedActivity + joinedActivity.showMyPartyInfoDialog(currentParty) + } + // Add more cases for other activity contexts if needed + else -> { + Toast.makeText( + context, + "Problème d'annonce chez my party adapter", + Toast.LENGTH_SHORT + ).show() + } + } + } + + // Add similar onClickListener for buttonModify and buttonDelete if needed + holder.buttonModify.setOnClickListener { + // Ouvrez le formulaire de modification et passez les informations de la fête + val intent = Intent(context, ModifyPartyForm::class.java) + intent.putExtra("partyToModify", currentParty) + context.startActivity(intent) + } + + holder.buttonDelete.setOnClickListener { + removeParty(currentParty) + } + } + + override fun getItemCount(): Int { + return myPartyList.size + } + + fun removeParty(party: Party) { + // Supprimer la fête de la base de données en utilisant son ID + party.id?.let { partyId -> + val databaseReferenceParties = FirebaseDatabase.getInstance().reference.child("parties") + databaseReferenceParties.child(partyId).removeValue() + .addOnSuccessListener { + // Mettez à jour l'adaptateur après la suppression + myPartyList = myPartyList.filterNot { it.id == partyId } + notifyDataSetChanged() + Toast.makeText(context, "Party deleted successfully", Toast.LENGTH_SHORT).show() + } + .addOnFailureListener { + Toast.makeText(context, "Failed to delete party", Toast.LENGTH_SHORT).show() + } + } + } + + // Fonction pour mettre à jour les données de l'adaptateur + fun updateData(newPartyList: List<Party>) { + myPartyList = newPartyList + notifyDataSetChanged() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/mobilecomputingapp/Party.kt b/app/src/main/java/com/example/mobilecomputingapp/Party.kt new file mode 100644 index 0000000000000000000000000000000000000000..1540f79588d34ec4522987448638757d87c39f5f --- /dev/null +++ b/app/src/main/java/com/example/mobilecomputingapp/Party.kt @@ -0,0 +1,21 @@ +package com.example.mobilecomputingapp + +import java.io.Serializable + +data class Party ( + val id: String? = null, + var name: String? = "", + var address: String? = "", + var date: String? = "", + var from: String? = "", + var to: String? = "", + var description: String? = "", + var latitude: Double? = 0.0, + var longitude: Double? = 0.0, + var partyOwner: String? = "", + var numberMax: Int? = 0, + var price: Double? = 0.00, + var paymentLink: String? = "", + var number: Int? = 0, + var applied: List<String> = listOf() +) : Serializable diff --git a/app/src/main/java/com/example/mobilecomputingapp/PartyAdapter.kt b/app/src/main/java/com/example/mobilecomputingapp/PartyAdapter.kt new file mode 100644 index 0000000000000000000000000000000000000000..d19cbede1c011c3854bfb9484b431ed3deaa0341 --- /dev/null +++ b/app/src/main/java/com/example/mobilecomputingapp/PartyAdapter.kt @@ -0,0 +1,63 @@ +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.Button +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.example.mobilecomputingapp.JoinedActivity +import com.example.mobilecomputingapp.MainActivity +import com.example.mobilecomputingapp.Party +import com.example.mobilecomputingapp.R + +class PartyAdapter(private val context: Context, private var partyList: List<Party>) : + RecyclerView.Adapter<PartyAdapter.PartyViewHolder>() { + + // ViewHolder + inner class PartyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val partyName: TextView = itemView.findViewById(R.id.partyName) + val partyAddress: TextView = itemView.findViewById(R.id.partyAddress) + val partydate: TextView = itemView.findViewById(R.id.partyDate) + val partyinfo: Button = itemView.findViewById(R.id.partyinfo) + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PartyViewHolder { + val itemView = + LayoutInflater.from(parent.context).inflate(R.layout.party_item, parent, false) + return PartyViewHolder(itemView) + } + + override fun onBindViewHolder(holder: PartyViewHolder, position: Int) { + val currentParty = partyList[position] + + // Mettez à jour les vues avec les données de la fête actuelle + holder.partyName.text = currentParty.name + holder.partyAddress.text = currentParty.address + holder.partydate.text = currentParty.date + + // Ajoutez un écouteur de clic au bouton de jointure si nécessaire + holder.partyinfo.setOnClickListener { + when (context) { + is MainActivity -> { + val mainActivity = context as MainActivity + mainActivity.showPartyInfoDialog(currentParty) + } + // Add more cases for other activity contexts if needed + else -> { + // Handle the case where the context is not MainActivity or JoinedActivity + } + } + } + } + + override fun getItemCount(): Int { + return partyList.size + } + + // Fonction pour mettre à jour les données de l'adaptateur + fun updateData(newPartyList: List<Party>) { + partyList = newPartyList + notifyDataSetChanged() + } +} + diff --git a/app/src/main/java/com/example/mobilecomputingapp/SignupActivity.kt b/app/src/main/java/com/example/mobilecomputingapp/SignupActivity.kt index 7760cd9a6cfc1fe52e3ca0d75db802fa36b4b07a..ae8ac810f0039ffafbbc66f2299d56edaea8fe0d 100644 --- a/app/src/main/java/com/example/mobilecomputingapp/SignupActivity.kt +++ b/app/src/main/java/com/example/mobilecomputingapp/SignupActivity.kt @@ -5,6 +5,7 @@ import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.widget.Toast import com.example.mobilecomputingapp.databinding.ActivitySignupBinding +import com.google.firebase.auth.FirebaseAuth import com.google.firebase.database.DataSnapshot import com.google.firebase.database.DatabaseError import com.google.firebase.database.DatabaseReference @@ -16,6 +17,7 @@ class SignupActivity : AppCompatActivity() { private lateinit var binding: ActivitySignupBinding private lateinit var firebaseDatabase: FirebaseDatabase private lateinit var databaseReference: DatabaseReference + private lateinit var firebaseAuth: FirebaseAuth override fun onCreate(savedInstanceState: Bundle?) { @@ -23,15 +25,28 @@ class SignupActivity : AppCompatActivity() { binding = ActivitySignupBinding.inflate(layoutInflater) setContentView(binding.root) + firebaseAuth = FirebaseAuth.getInstance() firebaseDatabase = FirebaseDatabase.getInstance() databaseReference = firebaseDatabase.reference.child("users") binding.signupButton.setOnClickListener { val signupUsername = binding.signupUsername.text.toString() val signupPassword = binding.signupPassword.text.toString() - - if(signupUsername.isNotEmpty() && signupPassword.isNotEmpty()){ - signupUser(signupUsername, signupPassword) + val signupPasswordConfirm = binding.signupPasswordConfirm.text.toString() + + if(signupUsername.isNotEmpty() && signupPassword.isNotEmpty() && signupPasswordConfirm.isNotEmpty()){ + if(signupPassword.equals(signupPasswordConfirm)){ + firebaseAuth.createUserWithEmailAndPassword(signupUsername, signupPassword).addOnCompleteListener{ + if(it.isSuccessful){ + startActivity(Intent(this, LoginActivity::class.java)) + finish() + }else{ + Toast.makeText(this@SignupActivity, it.exception.toString(), Toast.LENGTH_SHORT).show() + } + } + } else { + Toast.makeText(this@SignupActivity, "Passwords are not matching !", Toast.LENGTH_SHORT).show() + } } else { Toast.makeText(this@SignupActivity, "All Fields are mandatory !", Toast.LENGTH_SHORT).show() @@ -45,25 +60,4 @@ class SignupActivity : AppCompatActivity() { } - private fun signupUser(username: String, password: String){ - databaseReference.orderByChild("username").equalTo(username).addListenerForSingleValueEvent(object : ValueEventListener{ - override fun onDataChange(dataSnapshot: DataSnapshot) { - if(!dataSnapshot.exists()){ - val id = databaseReference.push().key - val userData = UserData(id,username,password) - databaseReference.child(id!!).setValue(userData) - Toast.makeText(this@SignupActivity, "Sign up Successful", Toast.LENGTH_SHORT).show() - startActivity(Intent(this@SignupActivity, LoginActivity::class.java)) - finish() - } else { - Toast.makeText(this@SignupActivity, "User already exists !", Toast.LENGTH_SHORT).show() - } - } - - override fun onCancelled(databaseError: DatabaseError) { - Toast.makeText(this@SignupActivity, "Database Error: ${databaseError.message}", Toast.LENGTH_SHORT).show() - - } - }) - } } \ No newline at end of file diff --git a/app/src/main/res/drawable-anydpi-v24/ic_stat_name.xml b/app/src/main/res/drawable-anydpi-v24/ic_stat_name.xml new file mode 100644 index 0000000000000000000000000000000000000000..668574055e028c69065dc730c16ad9194a64dfc8 --- /dev/null +++ b/app/src/main/res/drawable-anydpi-v24/ic_stat_name.xml @@ -0,0 +1,15 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24" + android:tint="#FFFFFF"> + <group android:scaleX="0.92" + android:scaleY="0.92" + android:translateX="0.96" + android:translateY="0.96"> + <path + android:fillColor="@android:color/white" + android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,18.5c-0.83,0 -1.5,-0.67 -1.5,-1.5h3c0,0.83 -0.67,1.5 -1.5,1.5zM17,16L7,16v-1l1,-1v-2.61C8,9.27 9.03,7.47 11,7v-0.5c0,-0.57 0.43,-1 1,-1s1,0.43 1,1L13,7c1.97,0.47 3,2.28 3,4.39L16,14l1,1v1z"/> + </group> +</vector> diff --git a/app/src/main/res/drawable-anydpi/ic_action_name.xml b/app/src/main/res/drawable-anydpi/ic_action_name.xml new file mode 100644 index 0000000000000000000000000000000000000000..a521a99677b226a26cbe64374d039bdca21b67a5 --- /dev/null +++ b/app/src/main/res/drawable-anydpi/ic_action_name.xml @@ -0,0 +1,11 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24" + android:tint="#333333" + android:alpha="0.6"> + <path + android:fillColor="@android:color/white" + android:pathData="M12,2L12,2C8.13,2 5,5.13 5,9c0,1.74 0.5,3.37 1.41,4.84c0.95,1.54 2.2,2.86 3.16,4.4c0.47,0.75 0.81,1.45 1.17,2.26C11,21.05 11.21,22 12,22h0c0.79,0 1,-0.95 1.25,-1.5c0.37,-0.81 0.7,-1.51 1.17,-2.26c0.96,-1.53 2.21,-2.85 3.16,-4.4C18.5,12.37 19,10.74 19,9C19,5.13 15.87,2 12,2zM12,11.75c-1.38,0 -2.5,-1.12 -2.5,-2.5s1.12,-2.5 2.5,-2.5s2.5,1.12 2.5,2.5S13.38,11.75 12,11.75z"/> +</vector> diff --git a/app/src/main/res/drawable-hdpi/ic_action_name.png b/app/src/main/res/drawable-hdpi/ic_action_name.png new file mode 100644 index 0000000000000000000000000000000000000000..ddd180a4c40e370e522d75c7aef3402a76687442 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_action_name.png differ diff --git a/app/src/main/res/drawable-hdpi/ic_stat_name.png b/app/src/main/res/drawable-hdpi/ic_stat_name.png new file mode 100644 index 0000000000000000000000000000000000000000..6a214eb1d8cdd8fe43d3f24d6ac0a9101f5ce938 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_stat_name.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_action_name.png b/app/src/main/res/drawable-mdpi/ic_action_name.png new file mode 100644 index 0000000000000000000000000000000000000000..2090386fccf189efc6fd9751aa1de848d4a7e88a Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_action_name.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_stat_name.png b/app/src/main/res/drawable-mdpi/ic_stat_name.png new file mode 100644 index 0000000000000000000000000000000000000000..ff3be1ba6c90faadb47b20c98280c0bde8dad72b Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_stat_name.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_action_name.png b/app/src/main/res/drawable-xhdpi/ic_action_name.png new file mode 100644 index 0000000000000000000000000000000000000000..87d86030d746d631a785aea3fd2e65b497f308cc Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_action_name.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_stat_name.png b/app/src/main/res/drawable-xhdpi/ic_stat_name.png new file mode 100644 index 0000000000000000000000000000000000000000..427a3d8f7af13008f8bd12bc7fa98d8f2b5e353f Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_stat_name.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_action_name.png b/app/src/main/res/drawable-xxhdpi/ic_action_name.png new file mode 100644 index 0000000000000000000000000000000000000000..cf7bd4403a3fbe59c68b4a05a0fac56e66bc3e1f Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_action_name.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_stat_name.png b/app/src/main/res/drawable-xxhdpi/ic_stat_name.png new file mode 100644 index 0000000000000000000000000000000000000000..75646a410e7aa30b6a203593ccf570b771b86aad Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_stat_name.png differ diff --git a/app/src/main/res/drawable/baseline_arrow_back_16.xml b/app/src/main/res/drawable/baseline_arrow_back_16.xml new file mode 100644 index 0000000000000000000000000000000000000000..2ddef35dc6f908c0c82daadd6cd03f17e53ce467 --- /dev/null +++ b/app/src/main/res/drawable/baseline_arrow_back_16.xml @@ -0,0 +1,5 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" android:autoMirrored="true" android:height="16dp" android:tint="#FFFFFF" android:viewportHeight="24" android:viewportWidth="24" android:width="16dp"> + + <path android:fillColor="@android:color/white" android:pathData="M20,11H7.83l5.59,-5.59L12,4l-8,8 8,8 1.41,-1.41L7.83,13H20v-2z"/> + +</vector> diff --git a/app/src/main/res/drawable/baseline_menu_24.xml b/app/src/main/res/drawable/baseline_menu_24.xml new file mode 100644 index 0000000000000000000000000000000000000000..45ca7a9ee08e3fa3b845b171f3f43c8e7ed11604 --- /dev/null +++ b/app/src/main/res/drawable/baseline_menu_24.xml @@ -0,0 +1,5 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#FFFFFF" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp"> + + <path android:fillColor="@android:color/white" android:pathData="M3,18h18v-2L3,16v2zM3,13h18v-2L3,11v2zM3,6v2h18L21,6L3,6z"/> + +</vector> diff --git a/app/src/main/res/drawable/edittext_border.xml b/app/src/main/res/drawable/edittext_border.xml index 7a24c32af389f546e0ccc9150dc88be131eb6cd8..225498c20d01fe783be9dfc4fbeb00fc374be4a2 100644 --- a/app/src/main/res/drawable/edittext_border.xml +++ b/app/src/main/res/drawable/edittext_border.xml @@ -2,7 +2,7 @@ <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> - <stroke android:color="@color/green" + <stroke android:color="@color/blue" android:width="2dp"/> <corners android:radius="20dp"/> diff --git a/app/src/main/res/drawable/googlelogodraw.png b/app/src/main/res/drawable/googlelogodraw.png new file mode 100644 index 0000000000000000000000000000000000000000..4efc24cc1ed81c760ef0259c9efb1a0f5fd98540 Binary files /dev/null and b/app/src/main/res/drawable/googlelogodraw.png differ diff --git a/app/src/main/res/drawable/ic_add_marker.xml b/app/src/main/res/drawable/ic_add_marker.xml new file mode 100644 index 0000000000000000000000000000000000000000..61b00b84daf77280b2bc596ba0cf59f4fc2dae0b --- /dev/null +++ b/app/src/main/res/drawable/ic_add_marker.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8"?> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0"> + <!-- Add your vector drawable content here --> +</vector> + diff --git a/app/src/main/res/drawable/icons8_event_accept_24.png b/app/src/main/res/drawable/icons8_event_accept_24.png new file mode 100644 index 0000000000000000000000000000000000000000..82564d7ab984b83139f3da03363d883611ce8b20 Binary files /dev/null and b/app/src/main/res/drawable/icons8_event_accept_24.png differ diff --git a/app/src/main/res/drawable/icons8_user_30.png b/app/src/main/res/drawable/icons8_user_30.png new file mode 100644 index 0000000000000000000000000000000000000000..5ae5b67b8aba138b5edf7373d6e7ba1a9d18dd6f Binary files /dev/null and b/app/src/main/res/drawable/icons8_user_30.png differ diff --git a/app/src/main/res/drawable/logo_wtf.jpg b/app/src/main/res/drawable/logo_wtf.jpg new file mode 100644 index 0000000000000000000000000000000000000000..734b45380a4658afd864d7e47674f681e207584e Binary files /dev/null and b/app/src/main/res/drawable/logo_wtf.jpg differ diff --git a/app/src/main/res/drawable/nobg_logo_wtf.png b/app/src/main/res/drawable/nobg_logo_wtf.png new file mode 100644 index 0000000000000000000000000000000000000000..9cbd426a913f8a4b03b9fab238fffa9aa663c2da Binary files /dev/null and b/app/src/main/res/drawable/nobg_logo_wtf.png differ diff --git a/app/src/main/res/layout/activity_add_party_form.xml b/app/src/main/res/layout/activity_add_party_form.xml new file mode 100644 index 0000000000000000000000000000000000000000..d5594e3ac5d5ff41ad4b7244612df79e8f616057 --- /dev/null +++ b/app/src/main/res/layout/activity_add_party_form.xml @@ -0,0 +1,219 @@ + +<ScrollView + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent" + tools:context=".AddPartyForm" + tools:ignore="HardcodedText"> + + <androidx.constraintlayout.widget.ConstraintLayout + android:layout_width="match_parent" + android:layout_height="wrap_content"> + + <androidx.appcompat.widget.Toolbar + android:id="@+id/toolbar" + android:layout_width="match_parent" + android:layout_height="?attr/actionBarSize" + android:layout_alignParentTop="true" + android:background="@color/blue" + android:gravity="center" + app:layout_constraintTop_toTopOf="parent" + app:titleTextColor="@color/white" + > + + <ImageView + android:id="@+id/addpartyformback" + android:layout_width="30dp" + android:layout_height="30dp" + android:layout_marginTop="8dp" + android:background="@drawable/baseline_arrow_back_16" + android:contentDescription="Google Icon" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@+id/loginButton" /> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_centerVertical="true" + android:layout_gravity="center" + android:text="Create new event" + android:textColor="@color/white" + android:textSize="20sp" /> + </androidx.appcompat.widget.Toolbar> + + + <EditText + android:id="@+id/address" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_marginStart="16dp" + android:layout_marginTop="104dp" + android:layout_marginEnd="16dp" + android:background="@drawable/edittext_border" + android:hint="Address" + android:importantForAutofill="noExcludeDescendants" + android:padding="12dp" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintHeight_percent="0.20" + app:layout_constraintHorizontal_bias="0.0" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> + + <FrameLayout + android:id="@+id/mapContainer" + android:layout_width="match_parent" + android:layout_height="0dp" + app:layout_constraintTop_toBottomOf="@+id/address" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toEndOf="parent" + android:layout_marginTop="16dp" + android:layout_marginStart="16dp" + android:layout_marginEnd="16dp"> + </FrameLayout> + + <EditText + android:layout_width="0dp" + android:layout_height="wrap_content" + android:id="@+id/partyname" + android:hint="Event Name" + android:padding="12dp" + android:background="@drawable/edittext_border" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintTop_toBottomOf="@+id/address" + android:layout_marginTop="16dp" + android:layout_marginStart="16dp" + android:layout_marginEnd="16dp" + android:importantForAutofill="noExcludeDescendants"/> + + <EditText + android:layout_width="0dp" + android:layout_height="wrap_content" + android:id="@+id/dateparty" + android:hint="Date" + android:padding="12dp" + android:background="@drawable/edittext_border" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintTop_toBottomOf="@+id/partyname" + android:layout_marginTop="16dp" + android:layout_marginStart="16dp" + android:layout_marginEnd="16dp" + android:importantForAutofill="noExcludeDescendants"/> + + <EditText + android:layout_width="0dp" + android:layout_height="wrap_content" + android:id="@+id/partynumber" + android:hint="Available guests" + android:inputType="number" + android:padding="12dp" + android:background="@drawable/edittext_border" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@+id/dateparty" + android:layout_marginTop="16dp" + android:layout_marginStart="16dp" + android:layout_marginEnd="16dp" + android:importantForAutofill="noExcludeDescendants"/> + + <EditText + android:id="@+id/partyprice" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_marginStart="16dp" + android:layout_marginTop="16dp" + android:layout_marginEnd="16dp" + android:background="@drawable/edittext_border" + android:hint="Price" + android:inputType="numberDecimal" + android:importantForAutofill="noExcludeDescendants" + android:padding="12dp" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toEndOf="@+id/partynumber" + app:layout_constraintTop_toBottomOf="@+id/dateparty" /> + + <EditText + android:layout_width="0dp" + android:layout_height="wrap_content" + android:id="@+id/partyplink" + android:hint="Link for the tickets" + android:padding="12dp" + android:background="@drawable/edittext_border" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintTop_toBottomOf="@+id/partyprice" + android:layout_marginTop="16dp" + android:layout_marginStart="16dp" + android:layout_marginEnd="16dp" + android:importantForAutofill="noExcludeDescendants" + /> + + <EditText + android:layout_width="0dp" + android:layout_height="wrap_content" + android:id="@+id/partyfrom" + android:hint="From" + android:inputType="time" + android:padding="12dp" + android:background="@drawable/edittext_border" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toEndOf="@id/partynumber" + app:layout_constraintTop_toBottomOf="@+id/partyplink" + android:layout_marginTop="16dp" + android:layout_marginStart="16dp" + android:layout_marginEnd="16dp" + android:importantForAutofill="noExcludeDescendants"/> + + <EditText + android:id="@+id/partyto" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_marginStart="16dp" + android:layout_marginTop="16dp" + android:layout_marginEnd="16dp" + android:background="@drawable/edittext_border" + android:hint="To" + android:inputType="time" + android:importantForAutofill="noExcludeDescendants" + android:padding="12dp" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toEndOf="@+id/partyfrom" + app:layout_constraintTop_toBottomOf="@+id/partyplink" /> + + <EditText + android:layout_width="0dp" + android:layout_height="0dp" + android:id="@+id/partydescription" + android:hint="Description" + android:padding="12dp" + android:background="@drawable/edittext_border" + android:inputType="textMultiLine" + android:gravity="top|start" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintTop_toBottomOf="@+id/partyfrom" + android:layout_marginTop="16dp" + android:layout_marginStart="16dp" + android:layout_marginEnd="16dp" + android:importantForAutofill="noExcludeDescendants" + app:layout_constraintHeight_percent="0.20"/> + + <Button + android:layout_width="0dp" + android:layout_height="wrap_content" + android:id="@+id/createButton" + android:text="CREATE" + android:backgroundTint="@color/blue" + android:layout_marginTop="32dp" + android:layout_marginStart="16dp" + android:layout_marginEnd="16dp" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintTop_toBottomOf="@+id/partydescription"/> + + +</androidx.constraintlayout.widget.ConstraintLayout> +</ScrollView> \ No newline at end of file diff --git a/app/src/main/res/layout/activity_joined.xml b/app/src/main/res/layout/activity_joined.xml new file mode 100644 index 0000000000000000000000000000000000000000..46950b3e66ddd9e4a717d4d3400c1b9d2ffa19b8 --- /dev/null +++ b/app/src/main/res/layout/activity_joined.xml @@ -0,0 +1,91 @@ +<?xml version="1.0" encoding="utf-8"?> +<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools" + android:id="@+id/main" + android:layout_width="match_parent" + android:layout_height="match_parent" + tools:context=".JoinedActivity"> + + <androidx.appcompat.widget.Toolbar + android:id="@+id/toolbar" + android:layout_width="match_parent" + android:layout_height="?attr/actionBarSize" + android:background="@color/blue" + app:layout_constraintTop_toTopOf="parent" + android:layout_alignParentTop="true"> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_centerVertical="true" + android:layout_gravity="center" + android:text="My Events" + android:textColor="@color/white" + android:textSize="20sp" + app:layout_constraintStart_toStartOf="parent" /> + + <!-- Account Button --> + <ImageView + android:id="@+id/backButton" + android:layout_width="30dp" + android:layout_height="30dp" + android:layout_marginTop="8dp" + android:background="@drawable/baseline_arrow_back_16" + android:contentDescription="Google Icon" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@+id/loginButton" /> + + </androidx.appcompat.widget.Toolbar> + + <TextView + android:id="@+id/joinedTitle" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="Joined Events" + app:layout_constraintTop_toBottomOf="@+id/toolbar" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toEndOf="parent" + android:textSize="20sp" + android:layout_marginTop="16dp" + android:gravity="center"/> + + <androidx.recyclerview.widget.RecyclerView + android:id="@+id/joinedRecyclerView" + android:layout_width="0dp" + android:layout_height="0dp" + app:layout_constraintTop_toBottomOf="@+id/joinedTitle" + app:layout_constraintBottom_toTopOf="@+id/mypartiestitle" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toEndOf="parent"/> + + <TextView + android:id="@+id/mypartiestitle" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="My Events" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintVertical_bias="0.5" + app:layout_constraintHorizontal_bias="0.5" + app:flow_verticalAlign="center" + android:textSize="20sp" + android:layout_marginTop="16dp" + android:layout_marginBottom="19sp" + android:gravity="center"/> + + <androidx.recyclerview.widget.RecyclerView + android:id="@+id/mypartiesRecyclerView" + android:layout_width="0dp" + android:layout_height="0dp" + app:layout_constraintTop_toBottomOf="@+id/mypartiestitle" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toEndOf="parent" + android:layout_marginTop="8dp"/> + +</androidx.constraintlayout.widget.ConstraintLayout> diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml index 34d27a32a31311ad1302e8f75d9401182ecddd31..db9cbdcef426e21b02a928881d85e4cecf5d0d63 100644 --- a/app/src/main/res/layout/activity_login.xml +++ b/app/src/main/res/layout/activity_login.xml @@ -11,7 +11,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:id="@+id/loginUsername" - android:hint="Username" + android:hint="Email" android:padding="12dp" android:background="@drawable/edittext_border" app:layout_constraintStart_toStartOf="parent" @@ -42,7 +42,7 @@ android:layout_height="wrap_content" android:id="@+id/loginButton" android:text="LOGIN" - android:backgroundTint="@color/green" + android:backgroundTint="@color/blue" android:layout_marginTop="50dp" android:layout_marginStart="16dp" android:layout_marginEnd="16dp" @@ -51,6 +51,18 @@ app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toBottomOf="@+id/loginPassword"/> + <ImageView + android:id="@+id/googleLogIn" + android:layout_width="40dp" + android:layout_height="40dp" + android:layout_marginTop="40dp" + android:background="@drawable/googlelogodraw" + android:contentDescription="Google Icon" + + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@+id/loginButton" /> + <TextView android:layout_width="0dp" android:layout_height="wrap_content" @@ -58,13 +70,22 @@ android:text="Not yet registered ? Sign up" android:textSize="18sp" android:gravity="center" - android:textColor="@color/green" - android:layout_marginTop="70dp" + android:textColor="@color/blue" + android:layout_marginTop="90dp" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toBottomOf="@+id/loginButton"/> - + <ImageView + android:id="@+id/imageView" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + app:srcCompat="@drawable/nobg_logo_wtf" + android:layout_centerVertical="true" + android:paddingBottom="500dp" + android:layout_gravity="center" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintBottom_toBottomOf="parent"/> </androidx.constraintlayout.widget.ConstraintLayout> \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 41422779c0edf1c46e8c1c9e12b9a126bcb16748..fa1ad8e57179ff9653e1d573e831e34de23e1eb3 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -7,16 +7,72 @@ android:layout_height="match_parent" tools:context=".MainActivity"> - <TextView + <androidx.appcompat.widget.Toolbar + android:id="@+id/toolbar" + android:layout_width="match_parent" + android:layout_height="?attr/actionBarSize" + android:background="@color/blue" + app:layout_constraintTop_toTopOf="parent" + android:layout_alignParentTop="true"> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_centerVertical="true" + android:layout_gravity="center" + android:text="Upcoming Events" + android:textColor="@color/white" + android:textSize="20sp" + app:layout_constraintStart_toStartOf="parent" /> + + <!-- Account Button --> + <ImageButton + android:id="@+id/accountButton" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:src="@drawable/icons8_event_accept_24" + android:backgroundTint="@color/blue" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintBottom_toBottomOf="parent" + android:layout_marginEnd="8dp" + app:showAsAction="always" + app:actionButtonStyle="@style/Widget.AppCompat.ActionButton" /> + + </androidx.appcompat.widget.Toolbar> + + <androidx.recyclerview.widget.RecyclerView + android:id="@+id/recyclerView" + android:layout_width="0dp" + android:layout_height="0dp" + app:layout_constraintTop_toBottomOf="@+id/toolbar" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toEndOf="parent"/> + + <com.google.android.material.floatingactionbutton.FloatingActionButton + android:id="@+id/mapButton" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="Welcome to the app !" - android:textSize="36sp" - android:textColor="@color/green" + android:src="@android:drawable/ic_dialog_map" + android:backgroundTint="@color/blue" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintBottom_toTopOf="@id/fab" + android:layout_margin="16dp" + android:layout_marginBottom="8dp" + app:showAsAction="always" + app:actionButtonStyle="@style/Widget.AppCompat.ActionButton" /> + + <com.google.android.material.floatingactionbutton.FloatingActionButton + android:id="@+id/fab" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:backgroundTint="@color/quantum_bluegrey500" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toTopOf="parent" - tools:ignore="HardcodedText" /> + android:layout_margin="16dp" + android:layout_marginTop="8dp" + android:src="@android:drawable/ic_input_add" + android:contentDescription="@string/fab_description" /> -</androidx.constraintlayout.widget.ConstraintLayout> \ No newline at end of file +</androidx.constraintlayout.widget.ConstraintLayout> diff --git a/app/src/main/res/layout/activity_maps.xml b/app/src/main/res/layout/activity_maps.xml new file mode 100644 index 0000000000000000000000000000000000000000..843b2ad94e517860c6acd9f019d11b46e2e3300b --- /dev/null +++ b/app/src/main/res/layout/activity_maps.xml @@ -0,0 +1,66 @@ +<?xml version="1.0" encoding="utf-8"?> +<androidx.constraintlayout.widget.ConstraintLayout + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:map="http://schemas.android.com/apk/res-auto" + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent" + tools:context=".MapsActivity"> + + <androidx.appcompat.widget.Toolbar + android:id="@+id/toolbar" + android:layout_width="match_parent" + android:layout_height="?attr/actionBarSize" + android:layout_alignParentTop="true" + android:background="@color/blue" + android:gravity="center" + app:layout_constraintTop_toTopOf="parent" + app:titleTextColor="@color/white"> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_centerVertical="true" + android:layout_gravity="center" + android:text="Want To Find" + android:textColor="@color/white" + android:textSize="20sp" /> + </androidx.appcompat.widget.Toolbar> + + <fragment + android:id="@+id/map" + android:name="com.google.android.gms.maps.SupportMapFragment" + android:layout_width="match_parent" + android:layout_height="0dp" + app:layout_constraintTop_toBottomOf="@id/toolbar" + map:layout_constraintBottom_toBottomOf="parent" /> + + <com.google.android.material.floatingactionbutton.FloatingActionButton + android:id="@+id/listButton" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + + android:layout_marginLeft="16dp" + android:layout_marginEnd="16dp" + android:layout_marginRight="16dp" + android:layout_marginBottom="12dp" + android:backgroundTint="@color/blue" + android:src="@drawable/baseline_menu_24" + app:layout_constraintBottom_toTopOf="@id/fab" + app:layout_constraintStart_toStartOf="@id/fab" + app:layout_constraintEnd_toEndOf="parent" /> + + <com.google.android.material.floatingactionbutton.FloatingActionButton + android:id="@+id/fab" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:backgroundTint="@color/quantum_bluegrey500" + android:layout_alignParentBottom="true" + android:layout_alignParentEnd="true" + android:layout_margin="16dp" + android:src="@android:drawable/ic_input_add" + android:contentDescription="@string/fab_description" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" /> +</androidx.constraintlayout.widget.ConstraintLayout> diff --git a/app/src/main/res/layout/activity_modify_party_form.xml b/app/src/main/res/layout/activity_modify_party_form.xml new file mode 100644 index 0000000000000000000000000000000000000000..62589353478b5bfe048e07ca7064e44fdb9afbe3 --- /dev/null +++ b/app/src/main/res/layout/activity_modify_party_form.xml @@ -0,0 +1,219 @@ + +<ScrollView + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent" + tools:context=".ModifyPartyForm" + tools:ignore="HardcodedText"> + + <androidx.constraintlayout.widget.ConstraintLayout + android:layout_width="match_parent" + android:layout_height="wrap_content"> + + <androidx.appcompat.widget.Toolbar + android:id="@+id/toolbar" + android:layout_width="match_parent" + android:layout_height="?attr/actionBarSize" + android:layout_alignParentTop="true" + android:background="@color/blue" + android:gravity="center" + app:layout_constraintTop_toTopOf="parent" + app:titleTextColor="@color/white" + > + + <ImageView + android:id="@+id/addpartyformback" + android:layout_width="30dp" + android:layout_height="30dp" + android:layout_marginTop="8dp" + android:background="@drawable/baseline_arrow_back_16" + android:contentDescription="Google Icon" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@+id/loginButton" /> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_centerVertical="true" + android:layout_gravity="center" + android:text="Modify event" + android:textColor="@color/white" + android:textSize="20sp" /> + </androidx.appcompat.widget.Toolbar> + + + <EditText + android:id="@+id/address" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_marginStart="16dp" + android:layout_marginTop="104dp" + android:layout_marginEnd="16dp" + android:background="@drawable/edittext_border" + android:hint="Address" + android:importantForAutofill="noExcludeDescendants" + android:padding="12dp" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintHeight_percent="0.20" + app:layout_constraintHorizontal_bias="0.0" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> + + <FrameLayout + android:id="@+id/mapContainer" + android:layout_width="match_parent" + android:layout_height="0dp" + app:layout_constraintTop_toBottomOf="@+id/address" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toEndOf="parent" + android:layout_marginTop="16dp" + android:layout_marginStart="16dp" + android:layout_marginEnd="16dp"> + </FrameLayout> + + <EditText + android:layout_width="0dp" + android:layout_height="wrap_content" + android:id="@+id/partyname" + android:hint="Event Name" + android:padding="12dp" + android:background="@drawable/edittext_border" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintTop_toBottomOf="@+id/address" + android:layout_marginTop="16dp" + android:layout_marginStart="16dp" + android:layout_marginEnd="16dp" + android:importantForAutofill="noExcludeDescendants"/> + + <EditText + android:layout_width="0dp" + android:layout_height="wrap_content" + android:id="@+id/dateparty" + android:hint="Date" + android:padding="12dp" + android:background="@drawable/edittext_border" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintTop_toBottomOf="@+id/partyname" + android:layout_marginTop="16dp" + android:layout_marginStart="16dp" + android:layout_marginEnd="16dp" + android:importantForAutofill="noExcludeDescendants"/> + + <EditText + android:layout_width="0dp" + android:layout_height="wrap_content" + android:id="@+id/partynumber" + android:hint="Available guests" + android:inputType="number" + android:padding="12dp" + android:background="@drawable/edittext_border" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@+id/dateparty" + android:layout_marginTop="16dp" + android:layout_marginStart="16dp" + android:layout_marginEnd="16dp" + android:importantForAutofill="noExcludeDescendants"/> + + <EditText + android:id="@+id/partyprice" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_marginStart="16dp" + android:layout_marginTop="16dp" + android:layout_marginEnd="16dp" + android:background="@drawable/edittext_border" + android:hint="Price" + android:inputType="numberDecimal" + android:importantForAutofill="noExcludeDescendants" + android:padding="12dp" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toEndOf="@+id/partynumber" + app:layout_constraintTop_toBottomOf="@+id/dateparty" /> + + <EditText + android:layout_width="0dp" + android:layout_height="wrap_content" + android:id="@+id/partyplink" + android:hint="Link to the Ticketing" + android:padding="12dp" + android:background="@drawable/edittext_border" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintTop_toBottomOf="@+id/partyprice" + android:layout_marginTop="16dp" + android:layout_marginStart="16dp" + android:layout_marginEnd="16dp" + android:importantForAutofill="noExcludeDescendants" + /> + + <EditText + android:layout_width="0dp" + android:layout_height="wrap_content" + android:id="@+id/partyfrom" + android:hint="From" + android:inputType="time" + android:padding="12dp" + android:background="@drawable/edittext_border" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toEndOf="@id/partynumber" + app:layout_constraintTop_toBottomOf="@+id/partyplink" + android:layout_marginTop="16dp" + android:layout_marginStart="16dp" + android:layout_marginEnd="16dp" + android:importantForAutofill="noExcludeDescendants"/> + + <EditText + android:id="@+id/partyto" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_marginStart="16dp" + android:layout_marginTop="16dp" + android:layout_marginEnd="16dp" + android:background="@drawable/edittext_border" + android:hint="To" + android:inputType="time" + android:importantForAutofill="noExcludeDescendants" + android:padding="12dp" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toEndOf="@+id/partyfrom" + app:layout_constraintTop_toBottomOf="@+id/partyplink" /> + + <EditText + android:layout_width="0dp" + android:layout_height="0dp" + android:id="@+id/partydescription" + android:hint="Description" + android:padding="12dp" + android:background="@drawable/edittext_border" + android:inputType="textMultiLine" + android:gravity="top|start" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintTop_toBottomOf="@+id/partyfrom" + android:layout_marginTop="16dp" + android:layout_marginStart="16dp" + android:layout_marginEnd="16dp" + android:importantForAutofill="noExcludeDescendants" + app:layout_constraintHeight_percent="0.20"/> + + <Button + android:layout_width="0dp" + android:layout_height="wrap_content" + android:id="@+id/createButton" + android:text="MODIFY" + android:backgroundTint="@color/blue" + android:layout_marginTop="32dp" + android:layout_marginStart="16dp" + android:layout_marginEnd="16dp" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintTop_toBottomOf="@+id/partydescription"/> + + + </androidx.constraintlayout.widget.ConstraintLayout> +</ScrollView> \ No newline at end of file diff --git a/app/src/main/res/layout/activity_signup.xml b/app/src/main/res/layout/activity_signup.xml index 9ecea81b7373cf45d2f79337a3fe1974796cba09..b7e7797808f4370ce87793c8fce9fe9c073f169e 100644 --- a/app/src/main/res/layout/activity_signup.xml +++ b/app/src/main/res/layout/activity_signup.xml @@ -6,21 +6,30 @@ android:layout_height="match_parent" tools:context=".SignupActivity" tools:ignore="HardcodedText"> + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintTop_toBottomOf="@+id/signupPassword" + android:text="The password must meet the following criteria:\n\u2022 1 Uppercase letter\n\u2022 1 Lowercase letter\n\u2022 1 Number\n\u2022 Minimum length of 6 characters." + android:layout_marginTop="95dp" /> <EditText android:layout_width="0dp" android:layout_height="wrap_content" android:id="@+id/signupUsername" - android:hint="Username" + android:hint="Email" android:padding="12dp" android:background="@drawable/edittext_border" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="parent" - android:layout_marginTop="330dp" + android:layout_marginTop="260dp" android:layout_marginStart="16dp" - android:layout_marginEnd="16dp"/> - + android:layout_marginEnd="16dp" + /> + <EditText android:layout_width="0dp" android:layout_height="wrap_content" @@ -32,25 +41,48 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toBottomOf="@+id/signupUsername" + app:layout_constraintBottom_toTopOf="@+id/signupPasswordConfirm" + android:layout_marginTop="30dp" + android:layout_marginStart="16dp" + android:layout_marginEnd="16dp" + /> + + + <EditText + + android:layout_width="0dp" + android:layout_height="wrap_content" + android:id="@+id/signupPasswordConfirm" + android:hint="Confirm Password" + android:inputType="textPassword" + android:padding="12dp" + android:background="@drawable/edittext_border" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintTop_toBottomOf="@+id/signupPassword" app:layout_constraintBottom_toTopOf="@+id/signupButton" android:layout_marginTop="30dp" android:layout_marginStart="16dp" - android:layout_marginEnd="16dp"/> - + android:layout_marginEnd="16dp" + + /> + + <Button android:layout_width="0dp" android:layout_height="wrap_content" android:id="@+id/signupButton" android:text="SIGNUP" - android:backgroundTint="@color/green" - android:layout_marginTop="50dp" + android:backgroundTint="@color/blue" + android:layout_marginTop="120dp" android:layout_marginStart="16dp" android:layout_marginEnd="16dp" app:layout_constraintBottom_toTopOf="@+id/loginRedirect" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintTop_toBottomOf="@+id/signupPassword"/> - + app:layout_constraintTop_toBottomOf="@+id/signupPasswordConfirm" + /> + <TextView android:layout_width="0dp" android:layout_height="wrap_content" @@ -58,13 +90,26 @@ android:text="Already registered? Login" android:textSize="18sp" android:gravity="center" - android:textColor="@color/green" + android:textColor="@color/blue" android:layout_marginTop="70dp" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintTop_toBottomOf="@+id/signupButton"/> + app:layout_constraintTop_toBottomOf="@+id/signupButton" + /> - + <ImageView + android:id="@+id/imageView" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_centerVertical="true" + android:layout_gravity="center" + android:paddingBottom="500dp" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintVertical_bias="1.0" + app:srcCompat="@drawable/nobg_logo_wtf" + tools:layout_editor_absoluteX="0dp" + /> </androidx.constraintlayout.widget.ConstraintLayout> \ No newline at end of file diff --git a/app/src/main/res/layout/custom_info_window.xml b/app/src/main/res/layout/custom_info_window.xml new file mode 100644 index 0000000000000000000000000000000000000000..c207e398a220cebbd094d5d0af8ecf062e445408 --- /dev/null +++ b/app/src/main/res/layout/custom_info_window.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:orientation="vertical" + android:padding="8dp"> + + <TextView + android:id="@+id/titleTextView" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textSize="16sp" + android:textStyle="bold"/> + + <TextView + android:id="@+id/snippetTextView" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textSize="14sp"/> +</LinearLayout> \ No newline at end of file diff --git a/app/src/main/res/layout/joined_party_info_dialog.xml b/app/src/main/res/layout/joined_party_info_dialog.xml new file mode 100644 index 0000000000000000000000000000000000000000..7a887e3f2d97f43f5f492d3513acdf6e449c72af --- /dev/null +++ b/app/src/main/res/layout/joined_party_info_dialog.xml @@ -0,0 +1,125 @@ +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" + android:padding="16dp"> + + <!-- Add TextView elements to display party information --> + <TextView + android:id="@+id/textViewPartyName" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="Party Name" + android:textSize="18sp" + android:textStyle="bold" + android:layout_marginBottom="4dp" /> + + <TextView + android:id="@+id/textViewPartyOwner" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="Owner Email" + android:layout_marginBottom="4dp" /> + + <TextView + android:id="@+id/textViewPartyAddress" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="Address" + android:layout_marginBottom="4dp" /> + + <TextView + android:id="@+id/textViewPartyDate" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="Party Date" + android:layout_marginBottom="4dp" /> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal"> + + <TextView + android:id="@+id/textViewPartyFrom" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:text="From" /> + + <TextView + android:id="@+id/textViewPartyTo" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:text="To" /> + + </LinearLayout> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal"> + + <TextView + android:id="@+id/textViewPartyPrice" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:text="Price" /> + + <TextView + android:id="@+id/textViewPartyquantity" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:text="Available Tickets" /> + + </LinearLayout> + + <TextView + android:id="@+id/textViewPartyDescription" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="Description" + android:layout_marginBottom="8dp" /> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal"> + + <Button + android:id="@+id/buttonClose" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:textColor="@android:color/white" + android:backgroundTint="@color/quantum_googred" + android:text="CLOSE" + android:paddingStart="16dp" + android:paddingEnd="16dp" + android:paddingTop="8dp" + android:paddingBottom="8dp" + android:layout_marginTop="8dp" + android:layout_marginEnd="4dp" + android:layout_marginStart="4dp" /> + + <Button + android:id="@+id/buttonLeave" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:textColor="@android:color/white" + android:backgroundTint="@color/blue" + android:text="LEAVE" + android:paddingStart="16dp" + android:paddingEnd="16dp" + android:paddingTop="8dp" + android:paddingBottom="8dp" + android:layout_marginTop="8dp" + android:layout_marginEnd="4dp" + android:layout_marginStart="4dp" /> + + </LinearLayout> +</LinearLayout> diff --git a/app/src/main/res/layout/joined_party_item.xml b/app/src/main/res/layout/joined_party_item.xml new file mode 100644 index 0000000000000000000000000000000000000000..f3f6231fefc73934e043362093097115bb309303 --- /dev/null +++ b/app/src/main/res/layout/joined_party_item.xml @@ -0,0 +1,66 @@ +<!-- party_item.xml --> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" + android:padding="16dp"> + + <TextView + android:id="@+id/partyName" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="Party Name" + android:textSize="18sp" + android:textStyle="bold" + android:layout_marginBottom="4dp" /> + + <TextView + android:id="@+id/partyAddress" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="Party Address" + android:layout_marginBottom="4dp" /> + + <TextView + android:id="@+id/partyDate" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="Party Date" + android:layout_marginBottom="4dp" /> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal" + android:layout_marginTop="8dp"> + + <Button + android:id="@+id/joinedpartyinfo" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:textColor="@android:color/white" + android:backgroundTint="@color/blue" + android:text="INFO" + android:paddingStart="16dp" + android:paddingEnd="16dp" + android:paddingTop="8dp" + android:paddingBottom="8dp" + android:layout_marginEnd="4dp" /> + + <Button + android:id="@+id/joinedLeave" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:textColor="@android:color/white" + android:backgroundTint="@color/quantum_googred" + android:text="LEAVE" + android:paddingStart="16dp" + android:paddingEnd="16dp" + android:paddingTop="8dp" + android:paddingBottom="8dp" + android:layout_marginStart="4dp" /> + + </LinearLayout> +</LinearLayout> diff --git a/app/src/main/res/layout/my_party_info_dialog.xml b/app/src/main/res/layout/my_party_info_dialog.xml new file mode 100644 index 0000000000000000000000000000000000000000..a362f5f0509056b93bc59eea8115283a3418fc81 --- /dev/null +++ b/app/src/main/res/layout/my_party_info_dialog.xml @@ -0,0 +1,141 @@ +<!-- res/layout/my_party_info_dialog.xml --> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" + android:padding="16dp"> + + <TextView + android:id="@+id/textViewPartyName" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="Party Name" + android:textSize="18sp" + android:textStyle="bold" + android:layout_marginBottom="4dp" /> + + <TextView + android:id="@+id/textViewPartyOwner" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="Owner Email" + android:layout_marginBottom="4dp" /> + + <TextView + android:id="@+id/textViewPartyAddress" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="Address" + android:layout_marginBottom="4dp" /> + + <TextView + android:id="@+id/textViewPartyDate" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="Party Date" + android:layout_marginBottom="4dp" /> + + <TextView + android:id="@+id/appliedTextView" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="Applied" + android:layout_marginBottom="4dp" /> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal"> + + <TextView + android:id="@+id/textViewPartyFrom" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:text="From" /> + + <TextView + android:id="@+id/textViewPartyTo" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:text="To" /> + + </LinearLayout> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal"> + + <TextView + android:id="@+id/textViewPartyPrice" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:text="Price" /> + + <TextView + android:id="@+id/textViewPartyquantity" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:text="Available Tickets" /> + + </LinearLayout> + + <TextView + android:id="@+id/textViewPartyDescription" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="Description" + android:layout_marginTop="4dp" /> + + <TextView + android:id="@+id/textViewApplied" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="People who applied:" + android:textSize="16sp" + android:textStyle="bold" + android:layout_marginTop="8dp" /> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal"> + + <Button + android:id="@+id/buttonClose" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:textColor="@android:color/white" + android:backgroundTint="@color/blue" + android:text="CLOSE" + android:layout_marginTop="8dp" + android:layout_marginRight="4dp" + android:layout_marginLeft="4dp" /> + + <Button + android:id="@+id/buttonModify" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:textColor="@android:color/white" + android:backgroundTint="@color/blue" + android:text="EDIT" + android:layout_marginTop="8dp" + android:layout_marginRight="4dp" + android:layout_marginLeft="4dp" /> + + </LinearLayout> + <Button + android:id="@+id/buttonDelete" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:textColor="@android:color/white" + android:backgroundTint="@color/quantum_googred" + android:text="DELETE" + android:layout_marginTop="8dp" /> +</LinearLayout> diff --git a/app/src/main/res/layout/my_party_item.xml b/app/src/main/res/layout/my_party_item.xml new file mode 100644 index 0000000000000000000000000000000000000000..a4b43c1c9d438e4a18844ee14baf2c33be8a23ef --- /dev/null +++ b/app/src/main/res/layout/my_party_item.xml @@ -0,0 +1,80 @@ +<!-- party_item.xml --> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" + android:padding="16dp"> + + <TextView + android:id="@+id/partyName" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="Party Name" + android:textSize="18sp" + android:textStyle="bold" + android:layout_marginBottom="4dp" /> + + <TextView + android:id="@+id/partyAddress" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="Party Address" + android:layout_marginBottom="4dp" /> + + <TextView + android:id="@+id/partyDate" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="Party Date" + android:layout_marginBottom="4dp" /> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal" + android:layout_marginTop="8dp"> + + <Button + android:id="@+id/mypartyInfo" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:textColor="@android:color/white" + android:backgroundTint="@color/blue" + android:text="INFO" + android:paddingStart="16dp" + android:paddingEnd="16dp" + android:paddingTop="8dp" + android:paddingBottom="8dp" + android:layout_marginEnd="4dp" /> + + <Button + android:id="@+id/buttonModify" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:textColor="@android:color/white" + android:backgroundTint="@color/blue" + android:text="EDIT" + android:paddingStart="16dp" + android:paddingEnd="16dp" + android:paddingTop="8dp" + android:paddingBottom="8dp" + android:layout_marginStart="4dp" /> + + </LinearLayout> + + <Button + android:id="@+id/buttonDelete" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_weight="1" + android:textColor="@android:color/white" + android:backgroundTint="@color/quantum_googred" + android:text="DELETE" + android:paddingStart="16dp" + android:paddingEnd="16dp" + android:paddingTop="8dp" + android:paddingBottom="8dp" + android:layout_marginTop="8dp" /> +</LinearLayout> diff --git a/app/src/main/res/layout/party_info_dialog.xml b/app/src/main/res/layout/party_info_dialog.xml new file mode 100644 index 0000000000000000000000000000000000000000..9bf5420c827cf22d0af4482003adb7138e284235 --- /dev/null +++ b/app/src/main/res/layout/party_info_dialog.xml @@ -0,0 +1,116 @@ +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" + android:padding="16dp"> + + <TextView + android:id="@+id/textViewPartyName" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="Party Name" + android:textSize="25sp" + android:textStyle="bold" + android:layout_marginBottom="20dp" /> + + <TextView + android:id="@+id/textViewPartyOwner" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="Owner Email" + android:layout_marginBottom="8dp" /> + + <TextView + android:id="@+id/textViewPartyAddress" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="Address" + android:layout_marginBottom="8dp" /> + + <TextView + android:id="@+id/textViewPartyDate" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="Party Date" + android:layout_marginBottom="8dp" /> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal"> + + <TextView + android:id="@+id/textViewPartyFrom" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:text="From" + android:layout_marginEnd="8dp" /> + + <TextView + android:id="@+id/textViewPartyTo" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:text="To" + android:layout_marginStart="8dp" /> + + </LinearLayout> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal"> + + <TextView + android:id="@+id/textViewPartyPrice" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:text="Price" + android:layout_marginEnd="8dp" /> + + <TextView + android:id="@+id/textViewPartyquantity" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:text="Available tickets" + android:layout_marginBottom="8dp" /> + + </LinearLayout> + + <TextView + android:id="@+id/textViewPartyDescription" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="Description" + android:layout_marginBottom="8dp" /> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal"> + + <Button + android:id="@+id/buttonClose" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:textColor="@android:color/white" + android:backgroundTint="@color/quantum_googred" + android:text="CLOSE" + android:layout_marginEnd="8dp" /> + + <Button + android:id="@+id/buttonJoin" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:textColor="@android:color/white" + android:backgroundTint="@color/blue" + android:text="JOIN" + android:layout_marginStart="4dp" /> + + </LinearLayout> +</LinearLayout> diff --git a/app/src/main/res/layout/party_item.xml b/app/src/main/res/layout/party_item.xml new file mode 100644 index 0000000000000000000000000000000000000000..be703e6d30ec397777e8720304ff693b2db3c497 --- /dev/null +++ b/app/src/main/res/layout/party_item.xml @@ -0,0 +1,44 @@ +<!-- party_item.xml --> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" + android:padding="16dp"> + + <TextView + android:id="@+id/partyName" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="Party Name" + android:textSize="18sp" + android:textStyle="bold" + android:layout_marginBottom="4dp" /> + + <TextView + android:id="@+id/partyAddress" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="Party Address" + android:layout_marginBottom="4dp" /> + + <TextView + android:id="@+id/partyDate" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="Party Date" + android:layout_marginBottom="4dp" /> + + <Button + android:id="@+id/partyinfo" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textColor="@android:color/white" + android:backgroundTint="@color/quantum_bluegrey400" + android:text="INFO" + android:paddingStart="16dp" + android:paddingEnd="16dp" + android:paddingTop="8dp" + android:paddingBottom="8dp" + android:layout_marginTop="8dp" /> +</LinearLayout> + diff --git a/app/src/main/res/menu/mainmenu.xml b/app/src/main/res/menu/mainmenu.xml new file mode 100644 index 0000000000000000000000000000000000000000..03c1dd9ecd9ab3af6f7f33e3ad7ea72597cddafa --- /dev/null +++ b/app/src/main/res/menu/mainmenu.xml @@ -0,0 +1,10 @@ +<menu xmlns:tools="http://schemas.android.com/tools" + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + > + + <item + android:id="@+id/signout" + android:title="Sign Out" + /> +</menu> \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index c8234577fdb41638e6f76ef41d919f9079abda98..9bb651b2f4564df2d3bded35cd7e8d185fc58454 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,3 +1,5 @@ <resources> <string name="app_name">MobileComputingApp</string> + <string name="api_key">AIzaSyCd0OBDtZ9sNJwywwWf47yABIZzv2P-0sQ</string> + <string name="fab_description">Descripción del botón flotante</string> </resources> \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index ba097c4a91b3ec80e57fd2f6b95858e1eb2693cc..51d83ee97a51433746a4a071ba5bf44cb3a04b6d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -11,6 +11,9 @@ activity = "1.8.0" constraintlayout = "2.1.4" googleServices = "4.4.0" firebaseDatabase = "20.3.0" +firebaseAuthKtx = "22.3.0" +playServicesAuth = "20.7.0" +firebaseFirestoreKtx = "24.10.1" [libraries] androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } @@ -23,6 +26,9 @@ androidx-activity = { group = "androidx.activity", name = "activity", version.re androidx-constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintlayout" } google-services = { group = "com.google.gms", name = "google-services", version.ref = "googleServices" } firebase-database = { group = "com.google.firebase", name = "firebase-database", version.ref = "firebaseDatabase" } +firebase-auth-ktx = { group = "com.google.firebase", name = "firebase-auth-ktx", version.ref = "firebaseAuthKtx" } +play-services-auth = { group = "com.google.android.gms", name = "play-services-auth", version.ref = "playServicesAuth" } +firebase-firestore-ktx = { group = "com.google.firebase", name = "firebase-firestore-ktx", version.ref = "firebaseFirestoreKtx" } [plugins] android-application = { id = "com.android.application", version.ref = "agp" }