From f1b71f467c22dc7f1c46d7317293f296b0696d36 Mon Sep 17 00:00:00 2001 From: joemacd Date: Fri, 6 Dec 2024 17:57:16 -0500 Subject: [PATCH] hide nav bar for news fragment when open --- PennMobile/build.gradle | 1 + PennMobile/src/main/AndroidManifest.xml | 3 + .../Subletting/SubletteeFragment.kt | 257 ++++++++++++++++-- .../adapters/SublettingPagerAdapter.kt | 2 +- .../res/layout/fragment_sublettee_view.xml | 121 ++++++--- 5 files changed, 330 insertions(+), 54 deletions(-) diff --git a/PennMobile/build.gradle b/PennMobile/build.gradle index 06db062e..7f2fdb34 100644 --- a/PennMobile/build.gradle +++ b/PennMobile/build.gradle @@ -89,6 +89,7 @@ dependencies { } implementation 'com.google.android.gms:play-services-location:21.0.1' implementation 'com.google.android.gms:play-services-maps:18.2.0' + implementation 'com.google.android.libraries.places:places:2.6.0' implementation 'com.google.android.material:material:1.6.1' implementation 'com.google.firebase:firebase-analytics' implementation 'com.google.firebase:firebase-crashlytics-ktx:18.6.0' diff --git a/PennMobile/src/main/AndroidManifest.xml b/PennMobile/src/main/AndroidManifest.xml index c510c0cf..6076e276 100644 --- a/PennMobile/src/main/AndroidManifest.xml +++ b/PennMobile/src/main/AndroidManifest.xml @@ -65,6 +65,9 @@ + + + + // Default addresses to display when input is empty + private val defaultAddresses = listOf( + "3600 Chestnut St, Philadelphia, PA", + "3700 Walnut St, Philadelphia, PA", + "3800 Spruce St, Philadelphia, PA" + ) + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -30,39 +72,210 @@ class SubletteeFragment : Fragment() { mActivity = activity as MainActivity mActivity.closeKeyboard() - val bundle = Bundle() - //edit this later for firebase - /* bundle.putString(FirebaseAnalytics.Param.ITEM_ID, "0") - bundle.putString(FirebaseAnalytics.Param.ITEM_NAME, "GSR") - bundle.putString(FirebaseAnalytics.Param.ITEM_CATEGORY, "App Feature") - FirebaseAnalytics.getInstance(mActivity).logEvent(FirebaseAnalytics.Event.VIEW_ITEM, bundle) */ + val applicationInfo = requireContext().packageManager + .getApplicationInfo(requireContext().packageName, PackageManager.GET_META_DATA) + val apiKey = applicationInfo.metaData.getString("com.google.android.geo.API_KEY") + ?: throw IllegalStateException("API key not found in AndroidManifest.xml") + + // Initialize Places SDK with API key from manifest + if (!Places.isInitialized()) { + Places.initialize(requireContext(), apiKey) + } + placesClient = Places.createClient(requireContext()) } - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, - savedInstanceState: Bundle?): View? { + + override fun onCreateView( + inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle?, + ): View { _binding = FragmentSubletteeViewBinding.inflate(inflater, container, false) return binding.root } + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + + // Initialize address adapter with default addresses + addressAdapter = ArrayAdapter(requireContext(), android.R.layout.simple_dropdown_item_1line, defaultAddresses) + binding.subletteeLocationEdittext.setAdapter(addressAdapter) + binding.subletteeLocationEdittext.threshold = 0 + + + setupAddressAutocomplete() + setupDatePickers() + val marketplaceButton: Button = view.findViewById(R.id.sublettee_enter_subletting_button) + marketplaceButton.setOnClickListener { - //load new fragment, which will hold the subletting marketplace in whole + if (!validateDates()) { + Toast.makeText(context, "Please select valid start and end dates", Toast.LENGTH_SHORT).show() + return@setOnClickListener + } + + + // Load new fragment, which will hold the subletting marketplace in whole mActivity.supportFragmentManager.beginTransaction() - .replace(((view as ViewGroup).parent as View).id, SubletteeMarketplace()) - .addToBackStack(null) - .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN) - .commit() + .replace(((view as ViewGroup).parent as View).id, SubletteeMarketplace()) + .addToBackStack(null) + .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN) + .commit() + } + + + // Handle selection from dropdown + binding.subletteeLocationEdittext.setOnItemClickListener { parent, _, position, _ -> + val selectedAddress = parent.getItemAtPosition(position) as String + // Update the address text view with the selected address + binding.subletteeLocationAddressView.text = selectedAddress } } + + private fun setupDatePickers() { + // Start Date + btnStartDate = binding.subletteeStartDateButton + btnStartDate.setOnClickListener { + showDatePicker(btnStartDate, startCalendar) + } + btnEndDate = binding.subletteeEndDateButton + btnEndDate.setOnClickListener { + showDatePicker(btnEndDate, endCalendar) + } + } + + + private fun showDatePicker(btn: Button, cal: Calendar) { + val datePickerDialog = context?.let { + DatePickerDialog( + it, + { _: DatePicker, year: Int, monthOfYear: Int, dayOfMonth: Int -> + // Update calendar instance + cal.set(Calendar.YEAR, year) + cal.set(Calendar.MONTH, monthOfYear) + cal.set(Calendar.DAY_OF_MONTH, dayOfMonth) + // Update Button + val selectedDate = Calendar.getInstance() + selectedDate.set(year, monthOfYear, dayOfMonth) + val dateFormat = SimpleDateFormat("MM/dd/yyyy", Locale.getDefault()) + val formattedDate = dateFormat.format(selectedDate.time) + btn.text = formattedDate + }, + cal.get(Calendar.YEAR), + cal.get(Calendar.MONTH), + cal.get(Calendar.DAY_OF_MONTH), + ) + } + datePickerDialog?.show() + } + + + private fun validateDates(): Boolean { + val currentDate = Calendar.getInstance() + return !(startCalendar < currentDate || startCalendar > endCalendar) + } + + override fun onDestroy() { super.onDestroy() _binding = null } -} \ No newline at end of file + + private fun setupAddressAutocomplete() { + binding.subletteeLocationEdittext.addTextChangedListener(object : TextWatcher { + override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {} + + + override fun onTextChanged(query: CharSequence?, p1: Int, p2: Int, p3: Int) { + getAddressPredictions(query.toString()) + } + + + override fun afterTextChanged(p0: Editable?) {} + }) + + + // Show the dropdown when the view gains focus and update when it loses focus + binding.subletteeLocationEdittext.setOnFocusChangeListener { _, hasFocus -> + if (hasFocus) { + binding.subletteeLocationEdittext.showDropDown() + } else { + // When the view loses focus, update the address text view + updateAddressTextView() + } + } + } + + + private fun updateAddressTextView() { + val query = binding.subletteeLocationEdittext.text.toString() + if (query.isNotEmpty()) { + val request = FindAutocompletePredictionsRequest.builder() + .setQuery(query) + .build() + + + placesClient.findAutocompletePredictions(request) + .addOnSuccessListener { response -> + val predictions = response.autocompletePredictions + if (predictions.isNotEmpty()) { + val bestPrediction = predictions[0].getFullText(null).toString() + binding.subletteeLocationAddressView.text = bestPrediction + } else { + // No predictions found; set to original query + binding.subletteeLocationAddressView.text = query + } + } + .addOnFailureListener { exception: Exception -> + if (exception is ApiException) { + Log.e("Places", "Place not found: ${exception.message}") + } + // On failure, set to original query + binding.subletteeLocationAddressView.text = query + } + } else { + // Clear the address text view if the query is empty + binding.subletteeLocationAddressView.text = "" + } + } + + + private fun getAddressPredictions(query: String) { + if (query.isEmpty()) { + // Show default addresses + addressAdapter.clear() + addressAdapter.addAll(defaultAddresses) + addressAdapter.notifyDataSetChanged() + } else { + val request = FindAutocompletePredictionsRequest.builder() + .setQuery(query) + .build() + + + placesClient.findAutocompletePredictions(request) + .addOnSuccessListener { response -> + val predictions = response.autocompletePredictions + val addresses = predictions.take(3).map { it.getFullText(null).toString() } + addressAdapter.clear() + addressAdapter.addAll(addresses) + addressAdapter.notifyDataSetChanged() + // Show the dropdown if the text box is focused + if (binding.subletteeLocationEdittext.hasFocus()) { + binding.subletteeLocationEdittext.showDropDown() + } + } + .addOnFailureListener { exception: Exception -> + if (exception is ApiException) { + Log.e("Places", "Place not found: ${exception.message}") + } + } + } + } +} diff --git a/PennMobile/src/main/java/com/pennapps/labs/pennmobile/adapters/SublettingPagerAdapter.kt b/PennMobile/src/main/java/com/pennapps/labs/pennmobile/adapters/SublettingPagerAdapter.kt index 3a5d91f0..d7731eb7 100644 --- a/PennMobile/src/main/java/com/pennapps/labs/pennmobile/adapters/SublettingPagerAdapter.kt +++ b/PennMobile/src/main/java/com/pennapps/labs/pennmobile/adapters/SublettingPagerAdapter.kt @@ -2,7 +2,7 @@ package com.pennapps.labs.pennmobile.adapters import androidx.fragment.app.Fragment import androidx.viewpager2.adapter.FragmentStateAdapter -import com.pennapps.labs.pennmobile.Subletting.SubletteeFragment +import com.pennapps.labs.pennmobile.SubletteeFragment import com.pennapps.labs.pennmobile.Subletting.SubletterPostedListingsFragment class SublettingPagerAdapter(fragment: Fragment) : FragmentStateAdapter(fragment) { diff --git a/PennMobile/src/main/res/layout/fragment_sublettee_view.xml b/PennMobile/src/main/res/layout/fragment_sublettee_view.xml index a8ca1bbe..86d53b4c 100644 --- a/PennMobile/src/main/res/layout/fragment_sublettee_view.xml +++ b/PennMobile/src/main/res/layout/fragment_sublettee_view.xml @@ -9,6 +9,8 @@ android:layout_marginStart="16dp"> + + + - + + + + + + + + + + + +