-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #40 from Ruang-Opini/38-another-popular
38 another popular
- Loading branch information
Showing
17 changed files
with
517 additions
and
35 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
package id.ruangopini.data.model | ||
|
||
import com.google.firebase.Timestamp | ||
import com.google.firebase.firestore.DocumentId | ||
import id.ruangopini.utils.Helpers | ||
|
||
data class CategoryAnalytics( | ||
val name: String? = null, | ||
var discussion: Int? = 0, | ||
var join: Int? = 0, | ||
) | ||
|
||
data class DiscussionAnalytics( | ||
val join: Int? = 0, | ||
val comment: Int? = 0, | ||
val post: Int? = 0, | ||
@DocumentId | ||
val discussionId: String? = null | ||
) | ||
|
||
data class PostAnalytics( | ||
val voteUp: Int? = 0, | ||
val voteDown: Int? = 0, | ||
val comment: Int? = 0, | ||
@DocumentId | ||
val postId: String? = null, | ||
) | ||
|
||
data class Analytics( | ||
val createdAt: Timestamp? = Helpers.getTodayTime(), | ||
@DocumentId | ||
val time: String? = null | ||
) |
21 changes: 21 additions & 0 deletions
21
...d/ruangopini/data/repo/remote/firebase/firestore/analytics/FirestoreAnalyticsDataStore.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package id.ruangopini.data.repo.remote.firebase.firestore.analytics | ||
|
||
import id.ruangopini.data.model.CategoryAnalytics | ||
import id.ruangopini.data.repo.State | ||
import kotlinx.coroutines.flow.Flow | ||
|
||
interface FirestoreAnalyticsDataStore { | ||
fun updateDiscussion(category: String): Flow<State<Boolean>> | ||
fun updateJoinCategory(category: String, isJoin: Boolean): Flow<State<Boolean>> | ||
|
||
fun getAnotherPopular(): Flow<State<List<CategoryAnalytics>>> | ||
|
||
fun updateJoinDiscussion(discussionId: String, isJoin: Boolean): Flow<State<Boolean>> | ||
fun updateCommentDiscussion(discussionId: String): Flow<State<Boolean>> | ||
fun updatePostDiscussion(discussionId: String): Flow<State<Boolean>> | ||
|
||
fun updateCommentPost(postId: String): Flow<State<Boolean>> | ||
fun updateVoteUpPost(postId: String, vote: Int): Flow<State<Boolean>> | ||
fun updateVoteDownPost(postId: String, vote: Int): Flow<State<Boolean>> | ||
|
||
} |
265 changes: 265 additions & 0 deletions
265
.../ruangopini/data/repo/remote/firebase/firestore/analytics/FirestoreAnalyticsRepository.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,265 @@ | ||
package id.ruangopini.data.repo.remote.firebase.firestore.analytics | ||
|
||
import android.util.Log | ||
import com.google.firebase.Timestamp | ||
import com.google.firebase.firestore.FieldValue | ||
import com.google.firebase.firestore.ktx.firestore | ||
import com.google.firebase.ktx.Firebase | ||
import id.ruangopini.data.model.Analytics | ||
import id.ruangopini.data.model.CategoryAnalytics | ||
import id.ruangopini.data.model.DiscussionAnalytics | ||
import id.ruangopini.data.model.PostAnalytics | ||
import id.ruangopini.data.repo.State | ||
import id.ruangopini.utils.COLLECTION | ||
import id.ruangopini.utils.DateFormat | ||
import id.ruangopini.utils.Helpers | ||
import id.ruangopini.utils.Helpers.formatDate | ||
import kotlinx.coroutines.Dispatchers | ||
import kotlinx.coroutines.ExperimentalCoroutinesApi | ||
import kotlinx.coroutines.channels.awaitClose | ||
import kotlinx.coroutines.flow.* | ||
import kotlinx.coroutines.tasks.await | ||
|
||
@ExperimentalCoroutinesApi | ||
class FirestoreAnalyticsRepository : FirestoreAnalyticsDataStore { | ||
|
||
private val instance = Firebase.firestore.collection(COLLECTION.ANALYTICS) | ||
|
||
override fun updateDiscussion(category: String): Flow<State<Boolean>> = flow<State<Boolean>> { | ||
emit(State.loading()) | ||
val date = Timestamp.now().formatDate(DateFormat.SHORT) | ||
val snapshot = instance.document(date ?: "").collection(COLLECTION.CATEGORY) | ||
.document(category).update("discussion", FieldValue.increment(1)) | ||
snapshot.await() | ||
emit(State.success(snapshot.isSuccessful)) | ||
}.catch { | ||
emit(State.loading()) | ||
val mCategory = CategoryAnalytics(category, 1, 0) | ||
|
||
val date = Timestamp.now().formatDate(DateFormat.SHORT) | ||
val docSnap = instance.document(date ?: "") | ||
docSnap.set(Analytics()).await() | ||
|
||
val snapshot = docSnap.collection(COLLECTION.CATEGORY) | ||
.document(category).set(mCategory) | ||
snapshot.await() | ||
|
||
if (snapshot.isSuccessful) emit(State.success(true)) | ||
else { | ||
Log.d("TAG", "updateDiscussion: failed = ${it.message}") | ||
emit(State.failed(it.message ?: "")) | ||
} | ||
}.flowOn(Dispatchers.IO) | ||
|
||
override fun updateJoinCategory(category: String, isJoin: Boolean) = flow<State<Boolean>> { | ||
emit(State.loading()) | ||
val date = Timestamp.now().formatDate(DateFormat.SHORT) | ||
val snapshot = instance.document(date ?: "").collection(COLLECTION.CATEGORY) | ||
.document(category).update("join", FieldValue.increment(if (isJoin) 1 else -1)) | ||
snapshot.await() | ||
emit(State.success(snapshot.isSuccessful)) | ||
}.catch { | ||
emit(State.loading()) | ||
val mCategory = CategoryAnalytics(category, 0, 1) | ||
|
||
val date = Timestamp.now().formatDate(DateFormat.SHORT) | ||
val docSnap = instance.document(date ?: "") | ||
docSnap.set(Analytics()).await() | ||
|
||
val snapshot = docSnap.collection(COLLECTION.CATEGORY) | ||
.document(category).set(mCategory) | ||
snapshot.await() | ||
|
||
if (snapshot.isSuccessful) emit(State.success(true)) | ||
else { | ||
Log.d("TAG", "updateJoinCategory: failed = ${it.message}") | ||
emit(State.failed(it.message ?: "")) | ||
} | ||
}.flowOn(Dispatchers.IO) | ||
|
||
override fun getAnotherPopular() = callbackFlow<State<List<CategoryAnalytics>>> { | ||
trySend(State.loading()).isSuccess | ||
instance.whereLessThan("createdAt", Timestamp.now()) | ||
.whereGreaterThan("createdAt", Helpers.getSevenDayAgo()) | ||
.addSnapshotListener { value, error -> | ||
if (error != null) { | ||
trySend(State.failed(error.message ?: "")).isSuccess | ||
close(error) | ||
return@addSnapshotListener | ||
} | ||
if (value != null && !value.isEmpty) value.toObjects(Analytics::class.java) | ||
.forEach { data -> | ||
instance.document(data.time ?: "").collection(COLLECTION.CATEGORY) | ||
.addSnapshotListener { result, error -> | ||
if (error != null) { | ||
trySend(State.failed(error.message ?: "")).isSuccess | ||
close(error) | ||
} | ||
|
||
val category = if (result != null && !result.isEmpty) | ||
result.toObjects(CategoryAnalytics::class.java) | ||
else emptyList() | ||
|
||
trySend(State.success(category)).isSuccess | ||
} | ||
} | ||
} | ||
awaitClose() | ||
}.catch { | ||
emit(State.failed(it.message ?: "")) | ||
}.flowOn(Dispatchers.IO) | ||
|
||
override fun updatePostDiscussion(discussionId: String) = flow<State<Boolean>> { | ||
emit(State.loading()) | ||
val date = Timestamp.now().formatDate(DateFormat.SHORT) | ||
val snapshot = instance.document(date ?: "").collection(COLLECTION.DISCUSSION) | ||
.document(discussionId).update("post", FieldValue.increment(1)) | ||
snapshot.await() | ||
emit(State.success(snapshot.isSuccessful)) | ||
}.catch { | ||
emit(State.loading()) | ||
val discussion = DiscussionAnalytics(0, 0, 1) | ||
|
||
val date = Timestamp.now().formatDate(DateFormat.SHORT) | ||
val docSnap = instance.document(date ?: "") | ||
docSnap.set(Analytics()).await() | ||
|
||
val snapshot = docSnap.collection(COLLECTION.DISCUSSION) | ||
.document(discussionId).set(discussion) | ||
snapshot.await() | ||
|
||
if (snapshot.isSuccessful) emit(State.success(true)) | ||
else { | ||
Log.d("TAG", "updatePostDiscussion: failed = ${it.message}") | ||
emit(State.failed(it.message ?: "")) | ||
} | ||
}.flowOn(Dispatchers.IO) | ||
|
||
override fun updateJoinDiscussion(discussionId: String, isJoin: Boolean) = | ||
flow<State<Boolean>> { | ||
emit(State.loading()) | ||
val date = Timestamp.now().formatDate(DateFormat.SHORT) | ||
val snapshot = instance.document(date ?: "").collection(COLLECTION.DISCUSSION) | ||
.document(discussionId).update("join", FieldValue.increment(if (isJoin) 1 else -1)) | ||
snapshot.await() | ||
emit(State.success(snapshot.isSuccessful)) | ||
}.catch { | ||
emit(State.loading()) | ||
val discussion = DiscussionAnalytics(1, 0, 0) | ||
|
||
val date = Timestamp.now().formatDate(DateFormat.SHORT) | ||
val docSnap = instance.document(date ?: "") | ||
docSnap.set(Analytics()).await() | ||
|
||
val snapshot = docSnap.collection(COLLECTION.DISCUSSION) | ||
.document(discussionId).set(discussion) | ||
snapshot.await() | ||
|
||
if (snapshot.isSuccessful) emit(State.success(true)) | ||
else { | ||
Log.d("TAG", "updateJoinDiscussion: failed = ${it.message}") | ||
emit(State.failed(it.message ?: "")) | ||
} | ||
}.flowOn(Dispatchers.IO) | ||
|
||
override fun updateCommentDiscussion(discussionId: String) = flow<State<Boolean>> { | ||
emit(State.loading()) | ||
val date = Timestamp.now().formatDate(DateFormat.SHORT) | ||
val snapshot = instance.document(date ?: "").collection(COLLECTION.DISCUSSION) | ||
.document(discussionId).update("comment", FieldValue.increment(1)) | ||
snapshot.await() | ||
emit(State.success(snapshot.isSuccessful)) | ||
}.catch { | ||
emit(State.loading()) | ||
val discussion = DiscussionAnalytics(0, 1, 0) | ||
|
||
val date = Timestamp.now().formatDate(DateFormat.SHORT) | ||
val docSnap = instance.document(date ?: "") | ||
docSnap.set(Analytics()).await() | ||
|
||
val snapshot = docSnap.collection(COLLECTION.DISCUSSION) | ||
.document(discussionId).set(discussion) | ||
snapshot.await() | ||
|
||
if (snapshot.isSuccessful) emit(State.success(true)) | ||
else { | ||
Log.d("TAG", "updateCommentDiscussion: failed = ${it.message}") | ||
emit(State.failed(it.message ?: "")) | ||
} | ||
}.flowOn(Dispatchers.IO) | ||
|
||
override fun updateCommentPost(postId: String) = flow<State<Boolean>> { | ||
emit(State.loading()) | ||
val date = Timestamp.now().formatDate(DateFormat.SHORT) | ||
val snapshot = instance.document(date ?: "").collection(COLLECTION.POST) | ||
.document(postId).update("comment", FieldValue.increment(1)) | ||
snapshot.await() | ||
emit(State.success(snapshot.isSuccessful)) | ||
}.catch { | ||
emit(State.loading()) | ||
val post = PostAnalytics(0, 0, 1) | ||
|
||
val date = Timestamp.now().formatDate(DateFormat.SHORT) | ||
val docSnap = instance.document(date ?: "") | ||
docSnap.set(Analytics()).await() | ||
|
||
val snapshot = docSnap.collection(COLLECTION.POST) | ||
.document(postId).set(post) | ||
snapshot.await() | ||
if (snapshot.isSuccessful) emit(State.success(true)) | ||
else { | ||
Log.d("TAG", "updateCommentPost: failed = ${it.message}") | ||
emit(State.failed(it.message ?: "")) | ||
} | ||
}.flowOn(Dispatchers.IO) | ||
|
||
override fun updateVoteUpPost(postId: String, vote: Int) = flow<State<Boolean>> { | ||
emit(State.loading()) | ||
val date = Timestamp.now().formatDate(DateFormat.SHORT) | ||
val snapshot = instance.document(date ?: "").collection(COLLECTION.POST) | ||
.document(postId).update("voteUp", FieldValue.increment(vote.toLong())) | ||
snapshot.await() | ||
emit(State.success(snapshot.isSuccessful)) | ||
}.catch { | ||
emit(State.loading()) | ||
val post = PostAnalytics(1, 0, 0) | ||
|
||
val date = Timestamp.now().formatDate(DateFormat.SHORT) | ||
val docSnap = instance.document(date ?: "") | ||
docSnap.set(Analytics()).await() | ||
|
||
val snapshot = docSnap.collection(COLLECTION.POST) | ||
.document(postId).set(post) | ||
snapshot.await() | ||
if (snapshot.isSuccessful) emit(State.success(true)) | ||
else { | ||
Log.d("TAG", "updateVoteUpPost: failed = ${it.message}") | ||
emit(State.failed(it.message ?: "")) | ||
} | ||
}.flowOn(Dispatchers.IO) | ||
|
||
override fun updateVoteDownPost(postId: String, vote: Int) = flow<State<Boolean>> { | ||
emit(State.loading()) | ||
val date = Timestamp.now().formatDate(DateFormat.SHORT) | ||
val snapshot = instance.document(date ?: "").collection(COLLECTION.POST) | ||
.document(postId).update("voteDown", FieldValue.increment(vote.toLong())) | ||
snapshot.await() | ||
emit(State.success(snapshot.isSuccessful)) | ||
}.catch { | ||
emit(State.loading()) | ||
val post = PostAnalytics(0, 1, 0) | ||
|
||
val date = Timestamp.now().formatDate(DateFormat.SHORT) | ||
val docSnap = instance.document(date ?: "") | ||
docSnap.set(Analytics()).await() | ||
|
||
val snapshot = docSnap.collection(COLLECTION.POST) | ||
.document(postId).set(post) | ||
snapshot.await() | ||
if (snapshot.isSuccessful) emit(State.success(true)) | ||
else { | ||
Log.d("TAG", "updateVoteDownPost: failed = ${it.message}") | ||
emit(State.failed(it.message ?: "")) | ||
} | ||
}.flowOn(Dispatchers.IO) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.