added skillschais screen

This commit is contained in:
Clara Dautermann 2025-06-08 10:37:52 +02:00
parent a35e7992b2
commit ca36c17011
Signed by: clara
GPG key ID: 223391B52FAD4463
13 changed files with 264 additions and 48 deletions

View file

@ -22,6 +22,7 @@ import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import de.cdaut.dbtapp.components.BottomNavigationBar
import de.cdaut.dbtapp.components.FavouritesScreen
import de.cdaut.dbtapp.components.SkillsChainsScreen
import de.cdaut.dbtapp.components.SkillsScreen
import de.cdaut.dbtapp.components.TrackingScreen
import de.cdaut.dbtapp.navigation.Screens
@ -65,7 +66,7 @@ private fun MainContent() {
}
composable(Screens.Skillschains.route) {
Text("Skillschains")
SkillsChainsScreen()
}
}

View file

@ -47,7 +47,7 @@ fun FavouritesScreen() {
Modifier.verticalScroll(rememberScrollState()),
horizontalAlignment = Alignment.CenterHorizontally
) {
RoundedSearchBar(onSearch = {})
RoundedSearchBar(onSearch = {}, stringResource(R.string.label_skills_search_bar))
SkillCategory.entries.forEach { skillCategory ->
FavouritesCategoryCard(skillCategory)
}

View file

@ -0,0 +1,58 @@
package de.cdaut.dbtapp.components
import androidx.compose.foundation.text.input.rememberTextFieldState
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Search
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.SearchBar
import androidx.compose.material3.SearchBarDefaults
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import de.cdaut.dbtapp.R
@Preview
@Composable
private fun RoundedSearchBarPrev() {
RoundedSearchBar(onSearch = {}, stringResource(R.string.label_skills_search_bar))
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun RoundedSearchBar(onSearch: (String) -> Unit = {}, placeholder: String) {
// Controls expansion state of the search bar
var expanded by rememberSaveable { mutableStateOf(false) }
var textFieldState = rememberTextFieldState()
SearchBar(
inputField = {
SearchBarDefaults.InputField(
query = textFieldState.text.toString(),
onQueryChange = { textFieldState.edit { replace(0, length, it) } },
onSearch = {
onSearch(textFieldState.text.toString())
expanded = false
},
expanded = expanded,
onExpandedChange = { expanded = it },
leadingIcon = {
Icon(
Icons.Filled.Search,
contentDescription = stringResource(R.string.content_desc_search_bar)
)
},
placeholder = { Text(placeholder) }
)
},
expanded = expanded,
onExpandedChange = { expanded = it }
) {
Text("Placeholder")
}
}

View file

@ -15,25 +15,18 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.input.rememberTextFieldState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowDropDown
import androidx.compose.material.icons.filled.ArrowDropUp
import androidx.compose.material.icons.filled.Search
import androidx.compose.material.icons.filled.Star
import androidx.compose.material.icons.outlined.StarOutline
import androidx.compose.material3.Card
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.SearchBar
import androidx.compose.material3.SearchBarDefaults
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@ -53,7 +46,7 @@ fun SkillsScreen() {
Modifier.verticalScroll(rememberScrollState()),
horizontalAlignment = Alignment.CenterHorizontally
) {
RoundedSearchBar(onSearch = {})
RoundedSearchBar(onSearch = {}, stringResource(R.string.label_skills_search_bar))
SkillCategory.entries.forEach { skillCategory ->
SkillsCategoryCard(skillCategory.skills, skillCategory.title)
Spacer(Modifier.height(5.dp))
@ -165,38 +158,3 @@ private fun SingleSkillCard(title: String, description: String) {
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Preview(locale = "de")
@Composable
fun RoundedSearchBar(onSearch: (String) -> Unit = {}) {
// Controls expansion state of the search bar
var expanded by rememberSaveable { mutableStateOf(false) }
var textFieldState = rememberTextFieldState()
SearchBar(
inputField = {
SearchBarDefaults.InputField(
query = textFieldState.text.toString(),
onQueryChange = { textFieldState.edit { replace(0, length, it) } },
onSearch = {
onSearch(textFieldState.text.toString())
expanded = false
},
expanded = expanded,
onExpandedChange = { expanded = it },
leadingIcon = {
Icon(
Icons.Filled.Search,
contentDescription = stringResource(R.string.content_desc_search_bar)
)
},
placeholder = { Text(stringResource(R.string.label_search_bar)) }
)
},
expanded = expanded,
onExpandedChange = { expanded = it }
) {
Text("Placeholder")
}
}

View file

@ -0,0 +1,167 @@
package de.cdaut.dbtapp.components
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.ArrowDropDown
import androidx.compose.material.icons.filled.ArrowDropUp
import androidx.compose.material.icons.filled.PlayArrow
import androidx.compose.material3.Button
import androidx.compose.material3.Card
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
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.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import de.cdaut.dbtapp.R
import de.cdaut.dbtapp.model.Skill
import de.cdaut.dbtapp.model.Skillschain
import de.cdaut.dbtapp.model.Skillschain.Companion.mockSkillschains
@Preview
@Composable
fun SkillsChainsScreen() {
Column(
Modifier.verticalScroll(rememberScrollState()),
horizontalAlignment = Alignment.CenterHorizontally
) {
RoundedSearchBar(onSearch = {}, stringResource(R.string.label_skillschains_search_bar))
Spacer(Modifier.height(10.dp))
AddSkillschainBtn()
mockSkillschains().forEach {
SkillschainCard(skillschain = it)
}
}
}
@Composable
private fun AddSkillschainBtn(modifier: Modifier = Modifier) {
Button(
onClick = {
//TODO: Add Skillschain
},
modifier = Modifier.fillMaxWidth(0.9f)
) {
Icon(
imageVector = Icons.Filled.Add,
contentDescription = "//TODO: Provide"
)
Text(stringResource(R.string.btn_add_skillschain))
}
}
@Composable
fun SkillschainCard(modifier: Modifier = Modifier, skillschain: Skillschain) {
var open by remember {
mutableStateOf(false)
}
Card(
Modifier
.fillMaxWidth()
.padding(10.dp)
.background(MaterialTheme.colorScheme.primaryContainer, CircleShape)
) {
Column {
Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween,
) {
TitleText(
modifier = Modifier.padding(10.dp),
content = skillschain.title
)
Row(
modifier = Modifier
.padding(10.dp),
verticalAlignment = Alignment.CenterVertically
) {
Button(
modifier = Modifier
.clip(CircleShape)
.size(50.dp),
contentPadding = PaddingValues(0.dp),
shape = CircleShape,
onClick = {
//TODO: Start Skills Chain
}
) {
Icon(
imageVector = Icons.Filled.PlayArrow,
contentDescription = "TODO: PROVIDE"
)
}
Icon(
modifier = Modifier
.padding(5.dp)
.clickable(onClick = { open = !open }),
imageVector = if (open) Icons.Filled.ArrowDropUp else Icons.Filled.ArrowDropDown,
contentDescription = stringResource(R.string.desc_btn_expand)
)
}
}
if (open) {
skillschain.skills.forEach {
SkillCard(skill = it)
}
}
}
}
}
@Composable
fun SkillCard(modifier: Modifier = Modifier, skill: Skill) {
Row(
modifier = Modifier
.fillMaxWidth()
.background(Color.Transparent)
.padding(10.dp)
.background(Color.White, shape = RoundedCornerShape(5.dp))
.padding(10.dp),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Column(
modifier = Modifier
.fillMaxHeight()
.fillMaxWidth(),
verticalArrangement = Arrangement.SpaceBetween,
) {
TitleText(skill.title)
Spacer(modifier = Modifier.height(10.dp))
DescriptionText(skill.description)
}
}
}

View file

@ -0,0 +1,28 @@
package de.cdaut.dbtapp.model
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
import java.util.UUID
@Entity
class Skillschain(
@PrimaryKey val identifier: UUID = UUID.randomUUID(),
@ColumnInfo(name = "name") val title: String,
@ColumnInfo(name = "skills") val skills: List<Skill>
) {
companion object {
fun mockSkillschains(): List<Skillschain> {
return listOf(
Skillschain(
title = "Skillskette 1",
skills = Skill.mockSkills()
),
Skillschain(
title = "Skillskette 2",
skills = Skill.mockSkills()
)
)
}
}
}

View file

@ -14,6 +14,8 @@
<string name="add_trackter">Tracker hinzufügen</string>
<string name="view_stats">Statistiken</string>
<string name="tracker_card_title">Tracker</string>
<string name="label_search_bar">Skill Suchen</string>
<string name="label_skills_search_bar">Skill Suchen</string>
<string name="content_desc_search_bar">Suche Icon</string>
<string name="label_skillschains_search_bar">Skillskette Suchen</string>
<string name="btn_add_skillschain">Skillskette hinzufügen</string>
</resources>

View file

@ -13,6 +13,8 @@
<string name="add_trackter">Add Tracker</string>
<string name="view_stats">View Statistics</string>
<string name="tracker_card_title">Trackers</string>
<string name="label_search_bar">Search Skill</string>
<string name="label_skills_search_bar">Search Skill</string>
<string name="content_desc_search_bar">Search Icon</string>
<string name="label_skillschains_search_bar">Search Skills Chain</string>
<string name="btn_add_skillschain">Add Skillschain</string>
</resources>