Skip to content

Commit 30be74f

Browse files
committed
- Created DetailScreen for displaying topic details with the help of DetailViewModel
- Created `TopicListScreen` for displaying list of topics - Set up navigation
1 parent 7fbc3af commit 30be74f

File tree

8 files changed

+175
-36
lines changed

8 files changed

+175
-36
lines changed
Lines changed: 23 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,36 @@
11
package com.developersbreach.kotlindictionarymultiplatform
22

3-
import androidx.compose.animation.AnimatedVisibility
4-
import androidx.compose.foundation.Image
5-
import androidx.compose.foundation.layout.Column
6-
import androidx.compose.foundation.layout.fillMaxWidth
7-
import androidx.compose.material.Button
83
import androidx.compose.material.MaterialTheme
9-
import androidx.compose.material.Text
104
import androidx.compose.runtime.*
11-
import androidx.compose.ui.Alignment
12-
import androidx.compose.ui.Modifier
13-
import org.jetbrains.compose.resources.painterResource
14-
import org.jetbrains.compose.ui.tooling.preview.Preview
15-
16-
import kotlindictionarymultiplatform.composeapp.generated.resources.Res
17-
import kotlindictionarymultiplatform.composeapp.generated.resources.compose_multiplatform
5+
import androidx.navigation.NavType
6+
import androidx.navigation.compose.NavHost
7+
import androidx.navigation.compose.composable
8+
import androidx.navigation.compose.rememberNavController
9+
import androidx.navigation.navArgument
1810

1911
@Composable
20-
@Preview
2112
fun App() {
13+
val navController = rememberNavController()
14+
2215
MaterialTheme {
23-
var showContent by remember { mutableStateOf(false) }
24-
Column(Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) {
25-
Button(onClick = { showContent = !showContent }) {
26-
Text("Click me!")
16+
NavHost(navController = navController, startDestination = "list") {
17+
18+
composable("list") {
19+
TopicListScreen { selectedTopic ->
20+
navController.navigate("detail/$selectedTopic")
21+
}
2722
}
28-
AnimatedVisibility(showContent) {
29-
val greeting = remember { Greeting().greet() }
30-
Column(Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) {
31-
Image(painterResource(Res.drawable.compose_multiplatform), null)
32-
Text("Compose: $greeting")
23+
24+
composable(
25+
"detail/{topicId}",
26+
arguments = listOf(navArgument("topicId") { type = NavType.StringType })
27+
) { navBackStackEntry ->
28+
val topicId = navBackStackEntry.savedStateHandle.get<String>("topicId")
29+
println("Navigating to DetailScreen with topicId: $topicId")
30+
if (topicId != null) {
31+
DetailScreen(viewModel = DetailViewModel(API_KEY), topicId = topicId)
3332
}
3433
}
3534
}
3635
}
37-
}
36+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
package com.developersbreach.kotlindictionarymultiplatform
2+
3+
import androidx.compose.runtime.*
4+
import androidx.compose.material.*
5+
import androidx.compose.foundation.layout.*
6+
import androidx.compose.foundation.lazy.*
7+
import androidx.compose.ui.Alignment
8+
import androidx.compose.ui.Modifier
9+
import androidx.compose.ui.unit.dp
10+
11+
@Composable
12+
fun DetailScreen(viewModel: DetailViewModel, topicId: String?) {
13+
val topicState by viewModel.state.collectAsState()
14+
println("check topicState: $topicState")
15+
16+
//I suspect the issue is here
17+
LaunchedEffect(topicId) {
18+
if (!topicId.isNullOrEmpty() && topicState != null) {
19+
viewModel.fetchTopic(topicId)
20+
}
21+
}
22+
23+
topicState?.let { topic ->
24+
println("Topic data fetched: $topic")
25+
LazyColumn(modifier = Modifier.padding(16.dp)) {
26+
item {
27+
Text(text = topic.topicName, style = MaterialTheme.typography.h5)
28+
Spacer(modifier = Modifier.height(8.dp))
29+
Text(text = topic.intro)
30+
Spacer(modifier = Modifier.height(16.dp))
31+
32+
Text(text = "Signature: ${topic.syntax.signature}", style = MaterialTheme.typography.subtitle1)
33+
topic.syntax.notes?.let {
34+
Text(text = "Notes: $it")
35+
}
36+
Spacer(modifier = Modifier.height(16.dp))
37+
}
38+
39+
items(topic.sections) { section ->
40+
section.heading?.let { Text(text = it, style = MaterialTheme.typography.h6) }
41+
section.content?.let { Text(text = it) }
42+
43+
section.codeExamples.forEach { example ->
44+
example.description?.let { Text(text = "Description: $it") }
45+
Text(text = example.code, style = MaterialTheme.typography.body2)
46+
Spacer(modifier = Modifier.height(8.dp))
47+
}
48+
49+
Spacer(modifier = Modifier.height(16.dp))
50+
}
51+
52+
if (topic.pitfalls.isNotEmpty()) {
53+
item {
54+
Text(text = "Pitfalls", style = MaterialTheme.typography.h6)
55+
topic.pitfalls.forEach { Text("- $it") }
56+
}
57+
}
58+
59+
if (topic.relatedTopics.isNotEmpty()) {
60+
item {
61+
Spacer(modifier = Modifier.height(16.dp))
62+
Text(text = "Related Topics", style = MaterialTheme.typography.h6)
63+
topic.relatedTopics.forEach { Text("$it") }
64+
}
65+
}
66+
}
67+
} ?: run {
68+
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
69+
CircularProgressIndicator()
70+
}
71+
}
72+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package com.developersbreach.kotlindictionarymultiplatform
2+
3+
import androidx.lifecycle.ViewModel
4+
import androidx.lifecycle.viewModelScope
5+
import kotlinx.coroutines.flow.MutableStateFlow
6+
import kotlinx.coroutines.flow.StateFlow
7+
import kotlinx.coroutines.launch
8+
9+
class DetailViewModel(private val API_KEY: String) : ViewModel() {
10+
private val _state = MutableStateFlow<KotlinTopicDetails?>(null)
11+
val state: StateFlow<KotlinTopicDetails?> = _state
12+
13+
fun fetchTopic(topicId: String) {
14+
viewModelScope.launch {
15+
try {
16+
val topic = KtorHttpClient.generateTopicDetails(topicId, API_KEY)
17+
println("Fetched details: $topic")
18+
_state.value = topic
19+
println("State updated with topic: $topic")
20+
} catch (e: Exception) {
21+
println("Error fetching topic: ${e.message}")
22+
}
23+
}
24+
}
25+
}

composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/Greeting.kt

Lines changed: 0 additions & 9 deletions
This file was deleted.

composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/KotlinTopicDetails.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ data class ChatCompletionResponseMessage(
7171

7272
@Serializable
7373
data class ChatCompletionResponse(
74-
val choices: List<ChatCompletionChoice>
74+
val choices: List<ChatCompletionChoice>?
7575
)
7676

7777
@Serializable

composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/KtorHttpClient.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,8 @@ object KtorHttpClient {
112112

113113
// Parse response
114114
val chatResp = json.decodeFromString(ChatCompletionResponse.serializer(), text)
115-
val funcCall = chatResp.choices.first().message.functionCall ?: error("No function call in response")
115+
println(chatResp)
116+
val funcCall = chatResp.choices?.first()?.message?.functionCall ?: error("No function call in response")
116117

117118
// The arguments field is a JSON string: parse and decode into our DTO
118119
val argsJson = json.parseToJsonElement(funcCall.arguments)

composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/Runner.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ package com.developersbreach.kotlindictionarymultiplatform
22

33
const val API_KEY =""
44

5-
suspend fun main() {
5+
suspend fun details() {
66
val details = KtorHttpClient.generateTopicDetails("variables", API_KEY)
77
println(details)
88
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package com.developersbreach.kotlindictionarymultiplatform
2+
3+
import androidx.compose.foundation.clickable
4+
import androidx.compose.foundation.layout.fillMaxSize
5+
import androidx.compose.foundation.layout.fillMaxWidth
6+
import androidx.compose.foundation.layout.padding
7+
import androidx.compose.foundation.lazy.LazyColumn
8+
import androidx.compose.foundation.lazy.items
9+
import androidx.compose.material.Card
10+
import androidx.compose.material.MaterialTheme
11+
import androidx.compose.material.Text
12+
import androidx.compose.runtime.Composable
13+
import androidx.compose.ui.Modifier
14+
import androidx.compose.ui.unit.dp
15+
import org.jetbrains.compose.ui.tooling.preview.Preview
16+
17+
@Composable
18+
fun TopicListScreen(onTopicClick: (String) -> Unit) {
19+
val topics = listOf(
20+
"Variables", "Strings", "Functions", "Coroutines",
21+
"Classes", "Interfaces", "Objects", "Collections",
22+
"Null Safety", "Lambdas", "Higher-Order Functions",
23+
"Delegation", "Sealed Classes", "Generics", "Annotations"
24+
)
25+
26+
LazyColumn(modifier = Modifier.fillMaxSize().padding(16.dp)) {
27+
items(topics) { topic ->
28+
Card(
29+
elevation = 4.dp,
30+
modifier = Modifier
31+
.fillMaxWidth()
32+
.padding(vertical = 8.dp)
33+
.clickable { onTopicClick(topic) }
34+
) {
35+
Text(
36+
text = topic,
37+
style = MaterialTheme.typography.h6,
38+
modifier = Modifier.padding(16.dp)
39+
)
40+
}
41+
}
42+
}
43+
}
44+
45+
@Preview
46+
@Composable
47+
fun ListScreenPreview(){
48+
MaterialTheme {
49+
TopicListScreen(onTopicClick = {})
50+
}
51+
}

0 commit comments

Comments
 (0)