Skip to content

GoalProgressScreen Viewmodel and data load #15

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
import androidx.lifecycle.lifecycleScope
import androidx.navigation.compose.rememberNavController
import com.byteutility.dev.leetcode.plus.data.datastore.UserDatastore
import com.byteutility.dev.leetcode.plus.ui.LeetCodePlusNavGraph
import com.byteutility.dev.leetcode.plus.ui.LeetCodePlusNavigationDestinations
import com.byteutility.dev.leetcode.plus.ui.navigation.LeetCodePlusNavGraph
import com.byteutility.dev.leetcode.plus.ui.navigation.LeetCodePlusNavigationDestinations
import com.byteutility.dev.leetcode.plus.ui.theme.LeetcodePlusTheme
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.flow.first
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,17 @@ data class WeeklyGoalEntity(
@ColumnInfo(name = "problems")
val problems: String,
@ColumnInfo(name = "period")
val period: String
val period: String,
) {
fun toProblems(): List<LeetCodeProblem> {
val type = object : TypeToken<List<LeetCodeProblem>>() {}.type
return Gson().fromJson(problems, type)
}

fun toWeeklyGoal(): WeeklyGoalPeriod {
return Gson().fromJson(period, WeeklyGoalPeriod::class.java)
}

companion object {
fun createWeeklyGoalEntity(
problems: List<LeetCodeProblem>,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,24 @@
package com.byteutility.dev.leetcode.plus.monitor

import com.byteutility.dev.leetcode.plus.data.repository.userDetails.UserDetailsRepository
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.launch
import javax.inject.Inject
import javax.inject.Singleton

class WeeklyGoalStatusMonitor @Inject constructor() {
fun start() {
@Singleton
class WeeklyGoalStatusMonitor @Inject constructor(
private val userDetailsRepository: UserDetailsRepository
) {
private val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO)

fun start() {
scope.launch {
userDetailsRepository.getUserRecentSubmissions().collect {

}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.byteutility.dev.leetcode.plus.ui
package com.byteutility.dev.leetcode.plus.ui.navigation

import androidx.compose.runtime.Composable
import androidx.navigation.NavHostController
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.byteutility.dev.leetcode.plus.ui
package com.byteutility.dev.leetcode.plus.ui.navigation

import androidx.navigation.NavController

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,33 +13,56 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.painterResource
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.byteutility.dev.leetcode.plus.R
import com.byteutility.dev.leetcode.plus.data.model.ProblemStatus
import com.byteutility.dev.leetcode.plus.ui.theme.LeetcodePlusTheme

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun GoalProgressScreen() {
// Replace with viewmodel
val problemsWithStatus = emptyList<ProblemStatus>()
val viewmodel: GoalProgressViewModel = hiltViewModel()
viewmodel.init()
val uiState by viewmodel.uiState.collectAsStateWithLifecycle()
Scaffold(
topBar = {
TopAppBar(
title = { Text(text = "My Progress") },
)
},
) { paddingValues ->
ProgressScreenContent(uiState.problemsWithStatus, Modifier.padding(paddingValues))
}
}

@Composable
fun ProgressScreenContent(
problemsWithStatus: List<ProblemStatus>,
modifier: Modifier = Modifier
) {
Column(
modifier = Modifier
.background(Color.White)
.padding(16.dp)
.then(modifier)
) {
Text("Goal Progress (Weekly)", style = MaterialTheme.typography.titleLarge)
Spacer(modifier = Modifier.height(16.dp))

for (problem in problemsWithStatus) {
ProblemCard(problem)
Spacer(modifier = Modifier.height(8.dp))
Expand All @@ -49,7 +72,9 @@ fun GoalProgressScreen() {

@Composable
fun ProblemCard(problemStatus: ProblemStatus) {
Card(modifier = Modifier.fillMaxWidth()) {
Card(
modifier = Modifier.fillMaxWidth(),
) {
Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
Expand All @@ -64,7 +89,7 @@ fun ProblemCard(problemStatus: ProblemStatus) {
text = problemStatus.title,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
style = MaterialTheme.typography.titleMedium
style = MaterialTheme.typography.titleLarge
)
Text("Status: ${problemStatus.status}")
Text("Attempts Count: ${problemStatus.attemptsCount}")
Expand Down Expand Up @@ -122,8 +147,5 @@ fun LeetCodeProgressScreenPreview() {
ProblemStatus("Climbing Stairs", "Completed", "Easy", 2)
)
}

MaterialTheme {
GoalProgressScreen()
}
ProgressScreenContent(problemStatuses)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package com.byteutility.dev.leetcode.plus.ui.targetstatus

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.byteutility.dev.leetcode.plus.data.model.ProblemStatus
import com.byteutility.dev.leetcode.plus.data.repository.userDetails.UserDetailsRepository
import com.byteutility.dev.leetcode.plus.data.repository.weeklyGoal.WeeklyGoalRepository
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.merge
import kotlinx.coroutines.launch
import javax.inject.Inject

data class ProgressScreenState(
val problemsWithStatus: List<ProblemStatus> = emptyList()
)

@HiltViewModel
class GoalProgressViewModel @Inject constructor(
private val userDetailsRepository: UserDetailsRepository,
private val goalRepository: WeeklyGoalRepository
) : ViewModel() {

private val _uiState = MutableStateFlow(ProgressScreenState())
val uiState = _uiState.asStateFlow()

fun init() {
viewModelScope.launch(Dispatchers.IO) {
combine(
userDetailsRepository.getUserRecentSubmissions(),
goalRepository.weeklyGoal
) { recentSubmissions, goalProblems ->
val completedTitles = recentSubmissions?.filter { sub ->
goalProblems?.toProblems()?.any { it.title == sub.title } == true
}?.map {
it.title
} ?: emptyList()

goalProblems?.toProblems()?.map {
if (it.title in completedTitles) {
ProblemStatus(
title = it.title,
status = "Completed",
difficulty = it.difficulty,
attemptsCount = 1,
)
} else {
ProblemStatus(
title = it.title,
status = "Not Started",
difficulty = it.difficulty,
attemptsCount = 0,
)
}
}
}.collect {
if (it != null)
_uiState.value = ProgressScreenState(it)
}
}
}
}