Compare commits

...
Sign in to create a new pull request.

22 commits
master ... dev

Author SHA1 Message Date
ca36c17011
added skillschais screen 2025-06-08 10:37:52 +02:00
a35e7992b2
designed favourites screen 2025-06-05 22:26:07 +02:00
972823c5b8
search bar in skillslist 2025-06-05 17:44:44 +02:00
bdc3a50a53
fixed favouriting problem 2025-06-05 16:41:58 +02:00
6092c8f5e3
* fixed scrolling issue
* fixed preview of main screen
2025-06-04 22:29:54 +02:00
c236507045
comments 2025-06-04 01:02:01 +02:00
50fba5f697
worked on trackers screen 2025-06-04 00:07:08 +02:00
70acdc756a
worked on tracking screen 2025-06-02 21:53:59 +02:00
f76ec41891
AGP update 2025-06-02 16:34:24 +02:00
869d6881b4
Added button to jump to todays date 2025-05-30 20:11:35 +02:00
45085cdba4
worked on tracking screen 2025-05-30 18:46:22 +02:00
c6dd2c633b
some colors and correct clipping 2025-05-30 17:44:06 +02:00
b22c82de00
worked on calendar 2025-05-30 13:04:26 +02:00
8350ef65b5
working calendar!!! 2025-05-29 18:58:58 +02:00
a1d0e46bfe
began implementing calendar 2025-05-29 15:04:11 +02:00
5c653f5dce
agp update 2025-05-26 14:10:18 +02:00
f45f1cc77b
database setup 2025-05-14 12:55:07 +02:00
004824636d
add room as dependency 2025-05-14 09:49:06 +02:00
d432adc142
navigation compose -> 2.9.0 2025-05-14 09:42:00 +02:00
2c7819f524
imports 2025-05-14 09:41:23 +02:00
1203b5735a
smol UX fix 2025-05-13 23:14:36 +02:00
5b9d2b756b
make skills cards expandable 2025-05-13 23:11:36 +02:00
29 changed files with 1270 additions and 106 deletions

158
DBTApp/.idea/codeStyles/Project.xml generated Normal file
View file

@ -0,0 +1,158 @@
<component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173">
<JavaCodeStyleSettings>
<option name="IMPORT_LAYOUT_TABLE">
<value>
<package name="" withSubpackages="true" static="false" module="true" />
<package name="android" withSubpackages="true" static="true" />
<package name="androidx" withSubpackages="true" static="true" />
<package name="com" withSubpackages="true" static="true" />
<package name="junit" withSubpackages="true" static="true" />
<package name="net" withSubpackages="true" static="true" />
<package name="org" withSubpackages="true" static="true" />
<package name="java" withSubpackages="true" static="true" />
<package name="javax" withSubpackages="true" static="true" />
<package name="" withSubpackages="true" static="true" />
<emptyLine />
<package name="android" withSubpackages="true" static="false" />
<emptyLine />
<package name="androidx" withSubpackages="true" static="false" />
<emptyLine />
<package name="com" withSubpackages="true" static="false" />
<emptyLine />
<package name="junit" withSubpackages="true" static="false" />
<emptyLine />
<package name="net" withSubpackages="true" static="false" />
<emptyLine />
<package name="org" withSubpackages="true" static="false" />
<emptyLine />
<package name="java" withSubpackages="true" static="false" />
<emptyLine />
<package name="javax" withSubpackages="true" static="false" />
<emptyLine />
<package name="" withSubpackages="true" static="false" />
<emptyLine />
</value>
</option>
</JavaCodeStyleSettings>
<JetCodeStyleSettings>
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
</JetCodeStyleSettings>
<codeStyleSettings language="XML">
<option name="FORCE_REARRANGE_MODE" value="1" />
<indentOptions>
<option name="CONTINUATION_INDENT_SIZE" value="4" />
</indentOptions>
<arrangement>
<rules>
<section>
<rule>
<match>
<AND>
<NAME>xmlns:android</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>xmlns:.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:id</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:name</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>name</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>style</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
<order>ANDROID_ATTRIBUTE_ORDER</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>.*</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
</rules>
</arrangement>
</codeStyleSettings>
<codeStyleSettings language="kotlin">
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
</codeStyleSettings>
</code_scheme>
</component>

View file

@ -0,0 +1,5 @@
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
</state>
</component>

View file

@ -4,22 +4,18 @@
<selectionStates>
<SelectionState runConfigName="app">
<option name="selectionMode" value="DROPDOWN" />
</SelectionState>
<SelectionState runConfigName="BottomNavigationBar">
<option name="selectionMode" value="DROPDOWN" />
<DropdownSelection timestamp="2025-06-06T15:42:28.217017051Z">
<Target type="DEFAULT_BOOT">
<handle>
<DeviceId pluginId="LocalEmulator" identifier="path=/home/clara/.android/avd/Pixel_6.avd" />
</handle>
</Target>
</DropdownSelection>
<DialogSelection />
</SelectionState>
<SelectionState runConfigName="MainContent">
<option name="selectionMode" value="DROPDOWN" />
</SelectionState>
<SelectionState runConfigName="SingleSkillCard">
<option name="selectionMode" value="DROPDOWN" />
</SelectionState>
<SelectionState runConfigName="SingleSkillsCardPreview">
<option name="selectionMode" value="DROPDOWN" />
</SelectionState>
<SelectionState runConfigName="SkillsScreen">
<option name="selectionMode" value="DROPDOWN" />
</SelectionState>
</selectionStates>
</component>
</project>

View file

@ -2,6 +2,7 @@ plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android)
alias(libs.plugins.compose.compiler)
id("com.google.devtools.ksp")
}
android {
@ -37,6 +38,9 @@ android {
buildFeatures {
compose = true
}
ksp {
arg("room.schemaLocation", "$projectDir/schemas")
}
}
dependencies {
@ -70,6 +74,12 @@ dependencies {
//Compose navigation
implementation(libs.androidx.navigation.compose)
//room (for AppDatabase)
implementation(libs.room.runtime)
ksp(libs.androidx.room.compiler)
implementation(libs.androidx.room.ktx)
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.appcompat)
implementation(libs.material)

View file

@ -0,0 +1,43 @@
{
"formatVersion": 1,
"database": {
"version": 1,
"identityHash": "9293dc46eca03d297eae6183174db499",
"entities": [
{
"tableName": "Skill",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`identifier` BLOB NOT NULL, `title` TEXT NOT NULL, `description` TEXT NOT NULL, PRIMARY KEY(`identifier`))",
"fields": [
{
"fieldPath": "identifier",
"columnName": "identifier",
"affinity": "BLOB",
"notNull": true
},
{
"fieldPath": "title",
"columnName": "title",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "description",
"columnName": "description",
"affinity": "TEXT",
"notNull": true
}
],
"primaryKey": {
"autoGenerate": false,
"columnNames": [
"identifier"
]
}
}
],
"setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '9293dc46eca03d297eae6183174db499')"
]
}
}

View file

@ -1,36 +1,30 @@
package de.cdaut.dbtapp
import android.graphics.drawable.shapes.Shape
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Emergency
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonColors
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.FloatingActionButton
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Shapes
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import com.google.android.material.floatingactionbutton.FloatingActionButton
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
class MainActivity : ComponentActivity() {
@ -42,49 +36,52 @@ class MainActivity : ComponentActivity() {
}
}
@Preview(locale = "en-US")
@Preview(locale = "en-US", device = "id:pixel_6")
@Composable
private fun MainContent() {
val navController = rememberNavController()
Box {
Scaffold(
modifier = Modifier.fillMaxSize(),
bottomBar = { BottomNavigationBar(navController) },
floatingActionButton = { EmergencyButton() }
) { paddingValues ->
NavHost(
navController = navController,
startDestination = Screens.Home.route,
modifier = Modifier.padding(paddingValues = paddingValues)
) {
composable(Screens.Tracking.route) {
Text("Tracking")
}
composable(Screens.Skillslist.route) {
SkillsScreen()
}
composable(Screens.Home.route) {
Text("Home")
}
composable(Screens.Favourites.route) {
Text("Favourites")
MaterialTheme {
Box {
Scaffold(
modifier = Modifier.fillMaxSize(),
bottomBar = { BottomNavigationBar(navController) },
floatingActionButton = { EmergencyButton() }
) { paddingValues ->
NavHost(
navController = navController,
startDestination = Screens.Home.route,
modifier = Modifier.padding(paddingValues = paddingValues)
) {
composable(Screens.Tracking.route) {
TrackingScreen()
}
composable(Screens.Skillslist.route) {
SkillsScreen()
}
composable(Screens.Home.route) {
Text("Home")
}
composable(Screens.Favourites.route) {
FavouritesScreen()
}
composable(Screens.Skillschains.route) {
Text("Skillschains")
}
composable(Screens.Skillschains.route) {
SkillsChainsScreen()
}
}
}
}
}
}
@Preview
@Composable
private fun EmergencyButton() {
FloatingActionButton(
onClick = {},
containerColor = Color.Red
onClick = {
//TODO: Implement function for emergency Button
},
containerColor = MaterialTheme.colorScheme.error
) {
Icon(
imageVector = Icons.Filled.Emergency,

View file

@ -19,17 +19,19 @@ import de.cdaut.dbtapp.navigation.BottomNavigationItem
fun BottomNavigationBar(navController: NavController) {
var context = LocalContext.current
//remember the currently selected view
//default view is home
val homeView = BottomNavigationItem()
.bottomNavigationItems()
.find { item -> item.label == "Home" }!!.idx
var navigationSelectedItem by remember {
mutableIntStateOf(
//default view is home
BottomNavigationItem().bottomNavigationItems(ctx = context)
.find { item -> item.label == "Home" }!!.idx
homeView
)
}
NavigationBar {
//Create an entry in the bottom bar for each view
BottomNavigationItem().bottomNavigationItems(ctx = context).sortedBy { item -> item.idx }
BottomNavigationItem().bottomNavigationItems().sortedBy { item -> item.idx }
.forEachIndexed { index, item ->
NavigationBarItem(
selected = index == navigationSelectedItem,

View file

@ -0,0 +1,136 @@
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.IntrinsicSize
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.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.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.SkillCategory
@Preview
@Composable
fun FavouritesScreen() {
Column(
Modifier.verticalScroll(rememberScrollState()),
horizontalAlignment = Alignment.CenterHorizontally
) {
RoundedSearchBar(onSearch = {}, stringResource(R.string.label_skills_search_bar))
SkillCategory.entries.forEach { skillCategory ->
FavouritesCategoryCard(skillCategory)
}
}
}
@Composable
private fun FavouritesCategoryCard(category: SkillCategory) {
var enabled by remember {
mutableStateOf(false)
}
Card(
Modifier
.fillMaxWidth()
.padding(10.dp)
) {
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween,
modifier = Modifier
.fillMaxWidth()
.clickable(onClick = { enabled = !enabled }),
) {
TitleText(
modifier = Modifier.padding(10.dp),
content = category.title
)
Icon(
modifier = Modifier
.padding(5.dp),
imageVector = if (enabled) Icons.Filled.ArrowDropUp else Icons.Filled.ArrowDropDown,
contentDescription = stringResource(R.string.desc_btn_expand)
)
}
if (enabled) {
category.skills.forEach { skill ->
SingleSkillCard(skill = skill)
}
}
}
}
@Composable
private fun SingleSkillCard(skill: Skill) {
Row(
modifier = Modifier
.fillMaxWidth()
.height(IntrinsicSize.Min)
.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(fraction = 0.8f),
verticalArrangement = Arrangement.SpaceBetween,
) {
TitleText(skill.title)
Spacer(modifier = Modifier.height(10.dp))
DescriptionText(skill.description)
}
Button(
modifier = Modifier
.clip(CircleShape)
.size(50.dp),
contentPadding = PaddingValues(0.dp),
shape = CircleShape,
onClick = {
//TODO: Start Skill
}
) {
Icon(
imageVector = Icons.Filled.PlayArrow,
contentDescription = "TODO: PROVIDE"
)
}
}
}

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

@ -1,12 +1,9 @@
package de.cdaut.dbtapp.components
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.gestures.ScrollableState
import androidx.compose.foundation.gestures.scrollable
import androidx.compose.foundation.interaction.Interaction
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.IntrinsicSize
import androidx.compose.foundation.layout.Row
@ -15,19 +12,17 @@ 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.width
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.ArrowDropDown
import androidx.compose.material.icons.filled.ArrowDropUp
import androidx.compose.material.icons.filled.Star
import androidx.compose.material.icons.outlined.Star
import androidx.compose.material.icons.outlined.StarOutline
import androidx.compose.material3.Button
import androidx.compose.material3.Card
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
@ -40,7 +35,6 @@ 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 androidx.compose.ui.unit.em
import de.cdaut.dbtapp.R
import de.cdaut.dbtapp.model.Skill
import de.cdaut.dbtapp.model.SkillCategory
@ -49,8 +43,10 @@ import de.cdaut.dbtapp.model.SkillCategory
@Composable
fun SkillsScreen() {
Column(
Modifier.verticalScroll(rememberScrollState())
Modifier.verticalScroll(rememberScrollState()),
horizontalAlignment = Alignment.CenterHorizontally
) {
RoundedSearchBar(onSearch = {}, stringResource(R.string.label_skills_search_bar))
SkillCategory.entries.forEach { skillCategory ->
SkillsCategoryCard(skillCategory.skills, skillCategory.title)
Spacer(Modifier.height(5.dp))
@ -58,7 +54,6 @@ fun SkillsScreen() {
}
}
@Preview
@Composable
private fun SkillsCategoryCardPrev() {
SkillsCategoryCard(Skill.mockSkills(), "Skill")
@ -66,22 +61,41 @@ private fun SkillsCategoryCardPrev() {
@Composable
fun SkillsCategoryCard(skills: List<Skill>, title: String) {
var enabled by remember {
mutableStateOf(false)
}
Card(
Modifier
.fillMaxWidth()
.padding(10.dp)
) {
TitleText(
modifier = Modifier.padding(10.dp),
content = title
)
skills.forEach { skill ->
SingleSkillCard(skill.title, skill.description)
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween,
modifier = Modifier
.fillMaxWidth()
.clickable(onClick = { enabled = !enabled }),
) {
TitleText(
modifier = Modifier.padding(10.dp),
content = title
)
Icon(
modifier = Modifier
.padding(5.dp),
imageVector = if (enabled) Icons.Filled.ArrowDropUp else Icons.Filled.ArrowDropDown,
contentDescription = stringResource(R.string.desc_btn_expand)
)
}
if (enabled) {
skills.forEach { skill ->
SingleSkillCard(skill.title, skill.description)
}
}
}
}
@Preview
@Composable
private fun SingleSkillsCardPreview() {
SingleSkillCard(
@ -118,16 +132,29 @@ private fun SingleSkillCard(title: String, description: String) {
DescriptionText(description)
}
Icon(
modifier = Modifier
.padding(10.dp)
.clickable(onClick = {
selected = !selected
}),
imageVector = if (selected) Icons.Outlined.Star else Icons.Outlined.StarOutline,
contentDescription = stringResource(R.string.desc_btn_fav),
tint = if (selected) Color.Yellow else Color.Black
)
Box(
modifier = Modifier.clip(CircleShape),
contentAlignment = Alignment.Center
) {
if (selected) {
Icon(
modifier = Modifier.clip(CircleShape),
imageVector = Icons.Filled.Star,
contentDescription = "Filled Star",
tint = Color.Yellow
)
}
Icon(
modifier = Modifier
.clip(CircleShape)
.padding(10.dp)
.clickable(onClick = {
selected = !selected
}),
imageVector = Icons.Outlined.StarOutline,
contentDescription = stringResource(R.string.desc_btn_fav)
)
}
}
}
}

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

@ -6,10 +6,8 @@ import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.TextUnit
import androidx.compose.ui.unit.sp
@Preview

View file

@ -0,0 +1,400 @@
package de.cdaut.dbtapp.components
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.aspectRatio
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.layout.width
import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.CalendarMonth
import androidx.compose.material.icons.filled.ChevronLeft
import androidx.compose.material.icons.filled.ChevronRight
import androidx.compose.material.icons.filled.RemoveRedEye
import androidx.compose.material3.Button
import androidx.compose.material3.Card
import androidx.compose.material3.Checkbox
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
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.platform.LocalConfiguration
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.em
import de.cdaut.dbtapp.R
import de.cdaut.dbtapp.model.TherapyAssignment
import de.cdaut.dbtapp.model.TherapyAssignment.Companion.mockTherapyAssignments
import de.cdaut.dbtapp.model.Tracker
import de.cdaut.dbtapp.model.Tracker.Companion.mockTrackers
import de.cdaut.dbtapp.util.weekdayListByLocale
import java.time.LocalDate
import java.time.format.DateTimeFormatter
import java.time.format.FormatStyle
import java.time.temporal.WeekFields
@Preview(device = "id:pixel_6")
@Composable
fun TrackingScreen() {
Column(
modifier = Modifier
.verticalScroll(rememberScrollState())
.fillMaxWidth()
.background(MaterialTheme.colorScheme.background),
horizontalAlignment = Alignment.CenterHorizontally
) {
Column(
modifier = Modifier
.fillMaxWidth(0.9f),
horizontalAlignment = Alignment.CenterHorizontally
) {
Spacer(modifier = Modifier.height(20.dp))
Card {
TopCalendar()
}
Spacer(modifier = Modifier.height(10.dp))
Row(
modifier = Modifier
.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceEvenly
) {
Button(
onClick = {
//TODO: Add tracker
}
) {
Icon(
Icons.Filled.Add,
contentDescription = "//TODO: Provide",
tint = MaterialTheme.colorScheme.onPrimary
)
Text(
text = stringResource(R.string.add_trackter),
style = MaterialTheme.typography.labelLarge,
color = MaterialTheme.colorScheme.onPrimary
)
}
Button(
onClick = {
//TODO: View statistics
}
) {
Text(
modifier = Modifier.padding(horizontal = 5.dp),
text = stringResource(R.string.view_stats),
style = MaterialTheme.typography.labelLarge,
color = MaterialTheme.colorScheme.onPrimary
)
Icon(
Icons.Filled.RemoveRedEye,
contentDescription = "//TODO: Provide",
tint = MaterialTheme.colorScheme.onPrimary
)
}
}
Button(
onClick = {
//TODO: Add diary card here
},
modifier = Modifier.fillMaxWidth(),
) {
Icon(Icons.Filled.Add, stringResource(R.string.btn_add_diarycard))
Text(stringResource(R.string.btn_add_diarycard))
}
Spacer(modifier = Modifier.height(10.dp))
TitledListCard<TherapyAssignment>(
stringResource(R.string.card_therapy_hw_heading),
//cannot eta reduce because
//Function References of @Composable functions are not currently supported
rows = { assignments ->
TherapyAssignmentCardContent(assignments)
},
addAction = {
//TODO: Add Therapy assignment
},
items = mockTherapyAssignments()
)
Spacer(modifier = Modifier.height(10.dp))
TitledListCard<Tracker>(
stringResource(R.string.tracker_card_title),
//cannot eta reduce because
//Function References of @Composable functions are not currently supported
rows = { trackers -> OtherTrackersCardContent(trackers = List(4) { _ -> trackers[0] }) },
addAction = {
//TODO: Add new tracker
},
items = mockTrackers()
)
}
}
}
@Composable
private fun TopCalendar() {
var currentDateMut: MutableState<LocalDate> = remember {
mutableStateOf(LocalDate.now())
}
Column(
horizontalAlignment = Alignment.CenterHorizontally
) {
//Top Navigation and display items
Row(
modifier = Modifier
.fillMaxWidth()
.padding(10.dp),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween
) {
//Header stating the currently selected date
Text(
fontSize = 4.5.em,
text = currentDateMut.value.format(
DateTimeFormatter.ofLocalizedDate(FormatStyle.LONG)
.withLocale(LocalConfiguration.current.locales[0])
)
)
// arrows to switch month
Row(
verticalAlignment = Alignment.CenterVertically
) {
Icon(
modifier = Modifier
.clip(CircleShape)
.clickable(onClick = {
currentDateMut.value = LocalDate.now()
}),
imageVector = Icons.Filled.CalendarMonth,
contentDescription = "//TODO: Provide"
)
Spacer(modifier = Modifier.width(10.dp))
Icon(
modifier = Modifier
.clip(CircleShape)
.clickable(onClick = {
currentDateMut.value = currentDateMut.value.minusMonths(1)
})
.size(30.dp),
imageVector = Icons.Filled.ChevronLeft,
contentDescription = "TODO: Provide"
)
Icon(
modifier = Modifier
.clip(CircleShape)
.clickable(onClick = {
currentDateMut.value = currentDateMut.value.plusMonths(1)
})
.size(30.dp),
imageVector = Icons.Filled.ChevronRight,
contentDescription = "TODO: Provide"
)
}
}
// labels for current day
Row(
modifier = Modifier
.fillMaxWidth()
.padding(10.dp),
horizontalArrangement = Arrangement.SpaceBetween,
) {
weekdayListByLocale(LocalConfiguration.current.locales[0]).map { label ->
Text(
text = label,
modifier = Modifier.padding(10.dp),
textAlign = TextAlign.Center,
fontWeight = FontWeight.Bold
)
}
}
CalendarDaysGrid(currentDateMut)
}
}
@Composable
private fun CalendarDaysGrid(selectedDateMut: MutableState<LocalDate>) {
val locale = LocalConfiguration.current.locales[0]
val selectedDate = selectedDateMut.value
val firstDayOfMonth = LocalDate.of(selectedDate.year, selectedDate.month, 1)
val totalDaysInMonth = firstDayOfMonth.lengthOfMonth()
val firstDayOfWeek = WeekFields.of(locale).firstDayOfWeek
//calculate shift required in the beginning
val shift = (firstDayOfMonth.dayOfWeek.value - firstDayOfWeek.value + 7) % 7
val totalCells = ((shift + totalDaysInMonth + 6) / 7) * 7
val days = List(totalCells) { index ->
val dayNumber = index - shift + 1
if (dayNumber in 1..totalDaysInMonth) dayNumber else null
}
// Calendar Grid
// FIXME: Something better than a lazy grid would be good because scrolling
LazyVerticalGrid(
columns = GridCells.Fixed(7),
userScrollEnabled = false,
modifier = Modifier
.fillMaxWidth()
.height(320.dp)
) {
items(days.size) { index ->
days[index]?.let { day ->
var dayBoxModifier = Modifier
.padding(4.dp)
.clip(CircleShape)
.aspectRatio(1f)
.clickable(onClick = {
selectedDateMut.value = LocalDate.of(
selectedDate.year,
selectedDate.month,
day
)
})
.clip(CircleShape)
//add a mark to the currently selected day
if (day == selectedDate.dayOfMonth) {
dayBoxModifier = dayBoxModifier.border(
2.dp,
MaterialTheme.colorScheme.onPrimaryContainer,
CircleShape
)
}
Box(
modifier = dayBoxModifier,
contentAlignment = Alignment.Center
) {
Text(text = day.toString())
}
}
}
}
}
@Composable
private fun <T> TitledListCard(
title: String,
rows: @Composable Function1<List<T>, Unit>,
addAction: () -> Unit,
items: List<T>
) {
Card(
modifier = Modifier.fillMaxWidth()
) {
Column {
Row(
modifier = Modifier
.padding(10.dp)
.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Text(
text = title,
style = MaterialTheme.typography.titleMedium
)
Icon(
modifier = Modifier
.size(30.dp)
.clip(CircleShape)
.clickable(onClick = addAction),
imageVector = Icons.Filled.Add,
contentDescription = "TODO: Provide"
)
}
HorizontalDivider()
rows(items)
}
}
}
@Composable
private fun TherapyAssignmentCardContent(assignments: List<TherapyAssignment>) {
for (assignment in assignments) {
Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween,
) {
Column {
Text(
modifier = Modifier.padding(horizontal = 10.dp, vertical = 0.dp),
text = assignment.title,
style = MaterialTheme.typography.bodyMedium
)
Text(
modifier = Modifier.padding(horizontal = 10.dp, vertical = 0.dp),
text = assignment.description,
style = MaterialTheme.typography.bodySmall
)
}
Checkbox(
onCheckedChange = {
assignment.done = !assignment.done
},
checked = assignment.done
)
}
}
}
@Composable
private fun OtherTrackersCardContent(trackers: List<Tracker>) {
for (tracker in trackers) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(5.dp),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween,
) {
Column {
Text(
modifier = Modifier.padding(horizontal = 10.dp, vertical = 0.dp),
text = tracker.title,
style = MaterialTheme.typography.bodyMedium
)
Text(
modifier = Modifier.padding(horizontal = 10.dp, vertical = 0.dp),
text = tracker.description,
style = MaterialTheme.typography.bodySmall
)
}
}
}
}

View file

@ -0,0 +1,9 @@
package de.cdaut.dbtapp.model
import androidx.room.Database
import androidx.room.RoomDatabase
@Database(entities = [Skill::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
abstract fun skillDao() : SkillDao
}

View file

@ -1,24 +1,53 @@
package de.cdaut.dbtapp.model
class Skill(val title: String, val description: String) {
import androidx.room.ColumnInfo
import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Entity
import androidx.room.Insert
import androidx.room.PrimaryKey
import androidx.room.Query
import java.util.UUID
@Entity
class Skill(
@PrimaryKey val identifier: UUID = UUID.randomUUID(),
@ColumnInfo(name = "title") val title: String,
@ColumnInfo(name = "description") val description: String
) {
companion object {
fun mockSkills(): List<Skill> {
return listOf(
Skill(
title = "Test Hallo :3",
description = "lorem ipsum dolor sid amnet consequetur blabla yada yada"
title = "5-4-3-2-1",
description = "5 sehen, 5 hören, 5 fühlen, 4 sehen, 4 hören…"
),
Skill(
title = "5-4-3-2-1",
title = "Skilltitel",
description = "Hier kurz beschreiben wie die Übung funktioniert. Ggf. mehrere Zeilen aber nicht super lang"
),
Skill(
title = "UwU UwU awawawa",
description = "Just arf a little like the good fopsgirl you are :3"
)
// Skill(
// title = "UwU UwU awawawa",
// description = "Just arf a little like the good fopsgirl you are :3"
// )
)
}
}
}
@Dao
interface SkillDao {
@Query("SELECT * FROM Skill")
fun getAll(): List<Skill>
@Query("SELECT * FROM Skill WHERE title LIKE :title LIMIT 1")
fun findByName(title: String): Skill
@Insert
fun insertAll(vararg skills: Skill)
@Delete
fun delete(skill: Skill)
}

View file

@ -1,6 +1,5 @@
package de.cdaut.dbtapp.model
import androidx.compose.foundation.layout.Arrangement
enum class SkillCategory(val title: String, val skills: List<Skill> = Skill.mockSkills()) {
Mindfulness("Achtsamkeitsübungen"),

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

@ -0,0 +1,33 @@
package de.cdaut.dbtapp.model
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
import java.util.UUID
@Entity
class TherapyAssignment(
@PrimaryKey val identifier: UUID = UUID.randomUUID(),
@ColumnInfo(name = "title") val title: String,
@ColumnInfo(name = "description") val description: String,
@ColumnInfo(name = "done") var done: Boolean
) {
companion object {
fun mockTherapyAssignments(): List<TherapyAssignment> {
return listOf(
TherapyAssignment(
title = "Selbstfürsorge",
description = "Mir selbst eine gute Sache tun",
done = true
),
TherapyAssignment(
title = "Bedürfnis durchsetzen",
description = "Eine Sache durchsetzen, die mir schwer fällt",
done = false
)
)
}
}
}

View file

@ -0,0 +1,26 @@
package de.cdaut.dbtapp.model
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
import java.util.UUID
@Entity
class Tracker(
@PrimaryKey val identifier: UUID = UUID.randomUUID(),
@ColumnInfo(name = "title") val title: String,
@ColumnInfo(name = "description") val description: String
) {
companion object {
fun mockTrackers(): List<Tracker> {
return listOf(
Tracker(
title = "Stimmung",
description = "Deine aktuelle Stimmung"
)
)
}
}
}

View file

@ -1,15 +1,14 @@
package de.cdaut.dbtapp.navigation
import android.content.Context
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.MenuBook
import androidx.compose.material.icons.filled.CalendarToday
import androidx.compose.material.icons.filled.Checklist
import androidx.compose.material.icons.filled.Home
import androidx.compose.material.icons.outlined.Star
import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.LocalContext
import androidx.core.content.ContextCompat.getString
import androidx.compose.ui.res.stringResource
import de.cdaut.dbtapp.R
data class BottomNavigationItem(
@ -18,34 +17,35 @@ data class BottomNavigationItem(
val route: String = "",
val idx: Int = 0
) {
fun bottomNavigationItems(ctx: Context): List<BottomNavigationItem> {
@Composable
fun bottomNavigationItems(): List<BottomNavigationItem> {
return listOf(
BottomNavigationItem(
label = getString(ctx, R.string.label_tracking),
label = stringResource(R.string.label_tracking),
icon = Icons.Filled.CalendarToday,
route = Screens.Tracking.route,
idx = 0
),
BottomNavigationItem(
label = getString(ctx, R.string.label_skillslist),
label = stringResource(R.string.label_skillslist),
icon = Icons.AutoMirrored.Filled.MenuBook,
route = Screens.Skillslist.route,
idx = 1
),
BottomNavigationItem(
label = getString(ctx, R.string.label_home),
label = stringResource(R.string.label_home),
icon = Icons.Filled.Home,
route = Screens.Home.route,
idx = 2
),
BottomNavigationItem(
label = getString(ctx, R.string.label_favourites),
label = stringResource(R.string.label_favourites),
icon = Icons.Outlined.Star,
route = Screens.Favourites.route,
idx = 3
),
BottomNavigationItem(
label = getString(ctx, R.string.label_skillschains),
label = stringResource(R.string.label_skillschains),
icon = Icons.Filled.Checklist,
route = Screens.Skillschains.route,
idx = 4

View file

@ -0,0 +1,15 @@
package de.cdaut.dbtapp.util
import java.time.DayOfWeek
import java.time.format.TextStyle
import java.time.temporal.WeekFields
import java.util.Locale
fun weekdayListByLocale(locale: Locale): List<String> {
val listOfDayNames = DayOfWeek.entries.map { it.getDisplayName(TextStyle.NARROW, locale).substring(0, 1) }
val firstDayOfWeek = WeekFields.of(locale).firstDayOfWeek.ordinal
val orderedListOfDayNames =
listOfDayNames.subList(firstDayOfWeek, 7) + listOfDayNames.subList(0, firstDayOfWeek)
return orderedListOfDayNames
}

View file

@ -8,4 +8,14 @@
<string name="label_skillschains">Skillsketten</string>
<string name="emergency_button_description">Notfallknopf</string>
<string name="desc_btn_fav">Favorisieren Button</string>
<string name="desc_btn_expand">Ausklappen</string>
<string name="btn_add_diarycard">Diary Card Hinzufügen</string>
<string name="card_therapy_hw_heading">Therapiehausaufgaben</string>
<string name="add_trackter">Tracker hinzufügen</string>
<string name="view_stats">Statistiken</string>
<string name="tracker_card_title">Tracker</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

@ -7,4 +7,14 @@
<string name="label_skillschains">Skills Chains</string>
<string name="emergency_button_description">Emergency Button</string>
<string name="desc_btn_fav">Favourte Button</string>
<string name="desc_btn_expand">Expand</string>
<string name="btn_add_diarycard">Add Diary Card</string>
<string name="card_therapy_hw_heading">Therapy Assignments</string>
<string name="add_trackter">Add Tracker</string>
<string name="view_stats">View Statistics</string>
<string name="tracker_card_title">Trackers</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>

View file

@ -3,4 +3,5 @@ plugins {
alias(libs.plugins.android.application) apply false
alias(libs.plugins.kotlin.android) apply false
alias(libs.plugins.compose.compiler) apply false
id("com.google.devtools.ksp") version "2.0.21-1.0.27" apply false
}

View file

@ -1,6 +1,6 @@
[versions]
activityCompose = "1.10.1"
agp = "8.9.2"
agp = "8.10.1"
kotlin = "2.0.21"
coreKtx = "1.16.0"
junit = "4.13.2"
@ -8,7 +8,10 @@ junitVersion = "1.2.1"
espressoCore = "3.6.1"
appcompat = "1.7.0"
material = "1.12.0"
navigationCompose = "2.7.0-rc01"
navigationCompose = "2.9.0"
roomCompiler = "2.7.1"
roomKtx = "2.7.1"
roomRuntime = "2.7.1"
[libraries]
androidx-activity-compose = { module = "androidx.activity:activity-compose", version.ref = "activityCompose" }
@ -18,6 +21,9 @@ androidx-material-icons-core = { module = "androidx.compose.material:material-ic
androidx-material-icons-extended = { module = "androidx.compose.material:material-icons-extended" }
androidx-material3 = { module = "androidx.compose.material3:material3" }
androidx-navigation-compose = { module = "androidx.navigation:navigation-compose", version.ref = "navigationCompose" }
androidx-room-compiler = { module = "androidx.room:room-compiler", version.ref = "roomCompiler" }
androidx-room-ktx = { module = "androidx.room:room-ktx", version.ref = "roomKtx" }
androidx-room-runtime = { module = "androidx.room:room-runtime" }
androidx-ui-test-manifest = { module = "androidx.compose.ui:ui-test-manifest" }
androidx-ui-test-junit4 = { module = "androidx.compose.ui:ui-test-junit4" }
androidx-ui-tooling = { module = "androidx.compose.ui:ui-tooling" }
@ -27,6 +33,7 @@ androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "j
androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }
androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }
material = { group = "com.google.android.material", name = "material", version.ref = "material" }
room-runtime = { module = "androidx.room:room-runtime", version.ref = "roomRuntime" }
[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }

Binary file not shown.

After

Width:  |  Height:  |  Size: 551 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 532 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 549 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 544 KiB