Skip to content

Commit 6d1b5fb

Browse files
aggarwalpulkit596iamareebjamal
authored andcommitted
feat: Add Event FAQs (#1623)
1 parent 094eeb7 commit 6d1b5fb

File tree

14 files changed

+256
-3
lines changed

14 files changed

+256
-3
lines changed

app/src/main/java/org/fossasia/openevent/general/di/Modules.kt

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ import org.fossasia.openevent.general.event.EventsListAdapter
4444
import org.fossasia.openevent.general.event.EventsViewModel
4545
import org.fossasia.openevent.general.event.feedback.Feedback
4646
import org.fossasia.openevent.general.event.feedback.FeedbackApi
47+
import org.fossasia.openevent.general.event.faq.EventFAQ
48+
import org.fossasia.openevent.general.event.faq.EventFAQApi
4749
import org.fossasia.openevent.general.event.location.EventLocation
4850
import org.fossasia.openevent.general.event.location.EventLocationApi
4951
import org.fossasia.openevent.general.event.subtopic.EventSubTopic
@@ -73,6 +75,7 @@ import org.fossasia.openevent.general.search.SearchTypeViewModel
7375
import org.fossasia.openevent.general.search.LocationServiceImpl
7476
import org.fossasia.openevent.general.auth.SmartAuthViewModel
7577
import org.fossasia.openevent.general.connectivity.MutableConnectionLiveData
78+
import org.fossasia.openevent.general.event.faq.EventFAQViewModel
7679
import org.fossasia.openevent.general.settings.SettingsViewModel
7780
import org.fossasia.openevent.general.social.SocialLink
7881
import org.fossasia.openevent.general.social.SocialLinkApi
@@ -151,11 +154,15 @@ val apiModule = module {
151154
val retrofit: Retrofit = get()
152155
retrofit.create(SpeakerApi::class.java)
153156
}
157+
single {
158+
val retrofit: Retrofit = get()
159+
retrofit.create(EventFAQApi::class.java)
160+
}
154161

155162
factory { AuthHolder(get()) }
156163
factory { AuthService(get(), get(), get()) }
157164

158-
factory { EventService(get(), get(), get(), get(), get(), get(), get()) }
165+
factory { EventService(get(), get(), get(), get(), get(), get(), get(), get()) }
159166
factory { SpeakerService(get(), get(), get()) }
160167
factory { TicketService(get(), get()) }
161168
factory { SocialLinksService(get(), get()) }
@@ -178,6 +185,7 @@ val viewModelModule = module {
178185
viewModel { SearchTypeViewModel(get(), get()) }
179186
viewModel { TicketsViewModel(get(), get(), get(), get(), get()) }
180187
viewModel { AboutEventViewModel(get(), get()) }
188+
viewModel { EventFAQViewModel(get(), get()) }
181189
viewModel { SocialLinksViewModel(get(), get(), get()) }
182190
viewModel { FavoriteEventsViewModel(get(), get()) }
183191
viewModel { SettingsViewModel(get()) }
@@ -228,7 +236,8 @@ val networkModule = module {
228236
EventTopic::class.java, Attendee::class.java, TicketId::class.java, Order::class.java,
229237
AttendeeId::class.java, Charge::class.java, Paypal::class.java, ConfirmOrder::class.java,
230238
CustomForm::class.java, EventLocation::class.java, EventType::class.java,
231-
EventSubTopic::class.java, Feedback::class.java, Speaker::class.java)
239+
EventSubTopic::class.java, Feedback::class.java, Speaker::class.java,
240+
EventFAQ::class.java)
232241

233242
onlineApiResourceConverter.enableSerializationOption(SerializationFeature.INCLUDE_RELATIONSHIP_ATTRIBUTES)
234243

app/src/main/java/org/fossasia/openevent/general/event/EventDetailsFragment.kt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ import org.fossasia.openevent.general.R
5757
import org.fossasia.openevent.general.about.AboutEventFragmentArgs
5858
import org.fossasia.openevent.general.common.SpeakerClickListener
5959
import org.fossasia.openevent.general.event.EventUtils.loadMapUrl
60+
import org.fossasia.openevent.general.event.faq.EventFAQFragmentArgs
6061
import org.fossasia.openevent.general.event.feedback.FeedbackRecyclerAdapter
6162
import org.fossasia.openevent.general.event.topic.SimilarEventsFragment
6263
import org.fossasia.openevent.general.social.SocialLinksFragment
@@ -360,6 +361,16 @@ class EventDetailsFragment : Fragment() {
360361
EventUtils.share(eventShare, rootView.eventImage)
361362
return true
362363
}
364+
R.id.open_faqs -> {
365+
EventFAQFragmentArgs.Builder()
366+
.setEventId(safeArgs.eventId)
367+
.build()
368+
.toBundle()
369+
.also { bundle ->
370+
findNavController(rootView).navigate(R.id.eventFAQFragment, bundle, getAnimSlide())
371+
}
372+
return true
373+
}
363374
else -> super.onOptionsItemSelected(item)
364375
}
365376
}

app/src/main/java/org/fossasia/openevent/general/event/EventService.kt

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import io.reactivex.Flowable
55
import io.reactivex.Single
66
import org.fossasia.openevent.general.event.feedback.Feedback
77
import org.fossasia.openevent.general.event.feedback.FeedbackApi
8+
import org.fossasia.openevent.general.event.faq.EventFAQ
9+
import org.fossasia.openevent.general.event.faq.EventFAQApi
810
import org.fossasia.openevent.general.event.location.EventLocation
911
import org.fossasia.openevent.general.event.location.EventLocationApi
1012
import org.fossasia.openevent.general.event.topic.EventTopic
@@ -22,7 +24,8 @@ class EventService(
2224
private val eventTopicsDao: EventTopicsDao,
2325
private val eventTypesApi: EventTypesApi,
2426
private val eventLocationApi: EventLocationApi,
25-
private val eventFeedbackApi: FeedbackApi
27+
private val eventFeedbackApi: FeedbackApi,
28+
private val eventFAQApi: EventFAQApi
2629
) {
2730

2831
fun getEvents(): Flowable<List<Event>> {
@@ -47,6 +50,10 @@ class EventService(
4750
return eventLocationApi.getEventLocation()
4851
}
4952

53+
fun getEventFAQs(id: Long): Single<List<EventFAQ>> {
54+
return eventFAQApi.getEventFAQ(id)
55+
}
56+
5057
private fun getEventTopicList(eventsList: List<Event>): List<EventTopic?> {
5158
return eventsList
5259
.filter { it.eventTopic != null }
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package org.fossasia.openevent.general.event.faq
2+
3+
import com.github.jasminb.jsonapi.LongIdHandler
4+
import com.github.jasminb.jsonapi.annotations.Id
5+
import com.github.jasminb.jsonapi.annotations.Type
6+
7+
@Type("faq")
8+
data class EventFAQ(
9+
@Id(LongIdHandler::class)
10+
val id: Long,
11+
val question: String,
12+
val answer: String
13+
)
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package org.fossasia.openevent.general.event.faq
2+
3+
import io.reactivex.Single
4+
import retrofit2.http.GET
5+
import retrofit2.http.Path
6+
7+
interface EventFAQApi {
8+
9+
@GET("events/{id}/faqs?sort=question")
10+
fun getEventFAQ(@Path("id") id: Long): Single<List<EventFAQ>>
11+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package org.fossasia.openevent.general.event.faq
2+
3+
import android.os.Bundle
4+
import android.view.LayoutInflater
5+
import android.view.MenuItem
6+
import android.view.View
7+
import android.view.ViewGroup
8+
import androidx.core.view.isVisible
9+
import androidx.fragment.app.Fragment
10+
import androidx.lifecycle.Observer
11+
import androidx.navigation.fragment.navArgs
12+
import androidx.recyclerview.widget.LinearLayoutManager
13+
import kotlinx.android.synthetic.main.fragment_event_faq.view.faqContainer
14+
import kotlinx.android.synthetic.main.fragment_event_faq.view.faqRv
15+
import org.fossasia.openevent.general.R
16+
import org.fossasia.openevent.general.about.AboutEventFragmentArgs
17+
import org.fossasia.openevent.general.utils.Utils
18+
import org.koin.androidx.viewmodel.ext.android.viewModel
19+
20+
class EventFAQFragment : Fragment() {
21+
private lateinit var rootView: View
22+
private val eventFAQViewModel by viewModel<EventFAQViewModel>()
23+
private val faqAdapter = FAQRecyclerAdapter()
24+
private val safeArgs: AboutEventFragmentArgs by navArgs()
25+
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
26+
rootView = layoutInflater.inflate(R.layout.fragment_event_faq, container, false)
27+
28+
rootView.faqRv.layoutManager = LinearLayoutManager(context)
29+
rootView.faqRv.adapter = faqAdapter
30+
31+
Utils.setToolbar(activity, getString(R.string.frequently_asked_questions))
32+
setHasOptionsMenu(true)
33+
34+
eventFAQViewModel.eventFAQ.observe(viewLifecycleOwner, Observer {
35+
faqAdapter.addAll(it)
36+
rootView.faqContainer.isVisible = !it.isEmpty()
37+
})
38+
39+
eventFAQViewModel.loadEventFaq(safeArgs.eventId)
40+
41+
return rootView
42+
}
43+
44+
override fun onOptionsItemSelected(item: MenuItem): Boolean {
45+
return when (item.itemId) {
46+
android.R.id.home -> {
47+
activity?.onBackPressed()
48+
true
49+
}
50+
else -> super.onOptionsItemSelected(item)
51+
}
52+
}
53+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package org.fossasia.openevent.general.event.faq
2+
3+
import androidx.lifecycle.LiveData
4+
import androidx.lifecycle.MutableLiveData
5+
import androidx.lifecycle.ViewModel
6+
import io.reactivex.android.schedulers.AndroidSchedulers
7+
import io.reactivex.disposables.CompositeDisposable
8+
import io.reactivex.schedulers.Schedulers
9+
import org.fossasia.openevent.general.R
10+
import org.fossasia.openevent.general.common.SingleLiveEvent
11+
import org.fossasia.openevent.general.data.Resource
12+
import org.fossasia.openevent.general.event.EventService
13+
import timber.log.Timber
14+
15+
class EventFAQViewModel(private val eventService: EventService, private val resource: Resource) : ViewModel() {
16+
17+
private val compositeDisposable = CompositeDisposable()
18+
private val mutableEventFAQ = MutableLiveData<List<EventFAQ>>()
19+
val eventFAQ: LiveData<List<EventFAQ>> = mutableEventFAQ
20+
private val mutableError = SingleLiveEvent<String>()
21+
val error: LiveData<String> = mutableError
22+
23+
fun loadEventFaq(id: Long) {
24+
if (id.equals(-1)) {
25+
mutableError.value = Resource().getString(R.string.error_fetching_event_message)
26+
return
27+
}
28+
compositeDisposable.add(eventService.getEventFAQs(id)
29+
.subscribeOn(Schedulers.io())
30+
.observeOn(AndroidSchedulers.mainThread())
31+
.subscribe({ faqList ->
32+
mutableEventFAQ.value = faqList
33+
}, {
34+
mutableError.value = resource.getString(R.string.error_fetching_event_message)
35+
Timber.e(it, "Error fetching event %d", id)
36+
})
37+
)
38+
}
39+
40+
override fun onCleared() {
41+
super.onCleared()
42+
compositeDisposable.clear()
43+
}
44+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package org.fossasia.openevent.general.event.faq
2+
3+
import android.view.LayoutInflater
4+
import android.view.ViewGroup
5+
import androidx.recyclerview.widget.RecyclerView
6+
import org.fossasia.openevent.general.R
7+
8+
class FAQRecyclerAdapter : RecyclerView.Adapter<FAQViewHolder>() {
9+
val faqList = ArrayList<EventFAQ>()
10+
11+
fun addAll(faqList: List<EventFAQ>) {
12+
if (faqList.isNotEmpty())
13+
this.faqList.clear()
14+
this.faqList.addAll(faqList)
15+
notifyDataSetChanged()
16+
}
17+
18+
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FAQViewHolder {
19+
val view = LayoutInflater.from(parent.context).inflate(R.layout.item_faq, parent, false)
20+
return FAQViewHolder(view)
21+
}
22+
23+
override fun onBindViewHolder(holder: FAQViewHolder, position: Int) {
24+
val faq = faqList[position]
25+
26+
holder.bind(faq)
27+
}
28+
29+
override fun getItemCount(): Int {
30+
return faqList.size
31+
}
32+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package org.fossasia.openevent.general.event.faq
2+
3+
import android.view.View
4+
import androidx.recyclerview.widget.RecyclerView
5+
import kotlinx.android.synthetic.main.item_faq.view.answerTv
6+
import kotlinx.android.synthetic.main.item_faq.view.questiontv
7+
8+
class FAQViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
9+
10+
fun bind(faq: EventFAQ) {
11+
itemView.questiontv.text = faq.question
12+
itemView.answerTv.text = faq.answer
13+
}
14+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3+
xmlns:tools="http://schemas.android.com/tools"
4+
android:id="@+id/faqContainer"
5+
android:layout_width="match_parent"
6+
android:layout_margin="@dimen/layout_margin_large"
7+
android:layout_height="wrap_content"
8+
android:orientation="vertical"
9+
tools:visibility="visible">
10+
11+
<androidx.recyclerview.widget.RecyclerView
12+
android:id="@+id/faqRv"
13+
android:layout_width="wrap_content"
14+
android:layout_height="wrap_content"
15+
android:layout_marginLeft="@dimen/layout_margin_medium"
16+
android:layout_marginRight="@dimen/layout_margin_medium"
17+
android:layout_marginBottom="@dimen/layout_margin_large"
18+
android:orientation="vertical"
19+
tools:itemCount="3"
20+
tools:listitem="@layout/item_faq" />
21+
22+
</LinearLayout>

app/src/main/res/layout/item_faq.xml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3+
android:layout_width="match_parent"
4+
android:layout_height="wrap_content"
5+
android:orientation="vertical">
6+
7+
<TextView
8+
android:id="@+id/questiontv"
9+
android:layout_width="match_parent"
10+
android:layout_height="wrap_content"
11+
android:textColor="@color/black"
12+
android:textSize="16sp"
13+
android:layout_margin="@dimen/layout_margin_medium" />
14+
15+
<TextView
16+
android:id="@+id/answerTv"
17+
android:textSize="16sp"
18+
android:layout_width="match_parent"
19+
android:layout_height="wrap_content"
20+
android:layout_margin="@dimen/layout_margin_medium" />
21+
22+
</LinearLayout>

app/src/main/res/menu/event_details.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111
<item
1212
android:id="@+id/open_external_event_url"
1313
android:title="@string/open_external_event_url"/>
14+
<item
15+
android:id="@+id/open_faqs"
16+
android:title="@string/frequently_asked_questions"/>
1417
</group>
1518
<item
1619
android:id="@+id/event_share"

app/src/main/res/navigation/navigation_graph.xml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,17 @@
195195
app:argType="long"
196196
android:defaultValue="-1L"/>
197197
</fragment>
198+
<fragment
199+
android:id="@+id/eventFAQFragment"
200+
android:name="org.fossasia.openevent.general.event.faq.EventFAQFragment"
201+
android:label="EventFAQFragment"
202+
tools:layout="@layout/fragment_event_faq">
203+
204+
<argument
205+
android:name="eventId"
206+
app:argType="long"
207+
android:defaultValue="-1L"/>
208+
</fragment>
198209
<fragment
199210
android:id="@+id/ticketsFragment"
200211
android:name="org.fossasia.openevent.general.ticket.TicketsFragment"

app/src/main/res/values/strings.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,7 @@
308308
<string name="savedType">savedType</string>
309309
<string name="what_type">What Sounds good?</string>
310310
<string name="feedback">Feedback</string>
311+
<string name="frequently_asked_questions">Frequently Asked Questions</string>
311312

312313
<string name="filter_set">Filter Done</string>
313314
<string name="filter">Filter Search</string>

0 commit comments

Comments
 (0)