Compare commits
22 commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ca36c17011 | |||
| a35e7992b2 | |||
| 972823c5b8 | |||
| bdc3a50a53 | |||
| 6092c8f5e3 | |||
| c236507045 | |||
| 50fba5f697 | |||
| 70acdc756a | |||
| f76ec41891 | |||
| 869d6881b4 | |||
| 45085cdba4 | |||
| c6dd2c633b | |||
| b22c82de00 | |||
| 8350ef65b5 | |||
| a1d0e46bfe | |||
| 5c653f5dce | |||
| f45f1cc77b | |||
| 004824636d | |||
| d432adc142 | |||
| 2c7819f524 | |||
| 1203b5735a | |||
| 5b9d2b756b |
29 changed files with 1270 additions and 106 deletions
158
DBTApp/.idea/codeStyles/Project.xml
generated
Normal file
158
DBTApp/.idea/codeStyles/Project.xml
generated
Normal 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>
|
||||||
5
DBTApp/.idea/codeStyles/codeStyleConfig.xml
generated
Normal file
5
DBTApp/.idea/codeStyles/codeStyleConfig.xml
generated
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
<component name="ProjectCodeStyleConfiguration">
|
||||||
|
<state>
|
||||||
|
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
|
||||||
|
</state>
|
||||||
|
</component>
|
||||||
20
DBTApp/.idea/deploymentTargetSelector.xml
generated
20
DBTApp/.idea/deploymentTargetSelector.xml
generated
|
|
@ -4,22 +4,18 @@
|
||||||
<selectionStates>
|
<selectionStates>
|
||||||
<SelectionState runConfigName="app">
|
<SelectionState runConfigName="app">
|
||||||
<option name="selectionMode" value="DROPDOWN" />
|
<option name="selectionMode" value="DROPDOWN" />
|
||||||
</SelectionState>
|
<DropdownSelection timestamp="2025-06-06T15:42:28.217017051Z">
|
||||||
<SelectionState runConfigName="BottomNavigationBar">
|
<Target type="DEFAULT_BOOT">
|
||||||
<option name="selectionMode" value="DROPDOWN" />
|
<handle>
|
||||||
|
<DeviceId pluginId="LocalEmulator" identifier="path=/home/clara/.android/avd/Pixel_6.avd" />
|
||||||
|
</handle>
|
||||||
|
</Target>
|
||||||
|
</DropdownSelection>
|
||||||
|
<DialogSelection />
|
||||||
</SelectionState>
|
</SelectionState>
|
||||||
<SelectionState runConfigName="MainContent">
|
<SelectionState runConfigName="MainContent">
|
||||||
<option name="selectionMode" value="DROPDOWN" />
|
<option name="selectionMode" value="DROPDOWN" />
|
||||||
</SelectionState>
|
</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>
|
</selectionStates>
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
|
|
@ -2,6 +2,7 @@ plugins {
|
||||||
alias(libs.plugins.android.application)
|
alias(libs.plugins.android.application)
|
||||||
alias(libs.plugins.kotlin.android)
|
alias(libs.plugins.kotlin.android)
|
||||||
alias(libs.plugins.compose.compiler)
|
alias(libs.plugins.compose.compiler)
|
||||||
|
id("com.google.devtools.ksp")
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
|
|
@ -37,6 +38,9 @@ android {
|
||||||
buildFeatures {
|
buildFeatures {
|
||||||
compose = true
|
compose = true
|
||||||
}
|
}
|
||||||
|
ksp {
|
||||||
|
arg("room.schemaLocation", "$projectDir/schemas")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
|
@ -70,6 +74,12 @@ dependencies {
|
||||||
//Compose navigation
|
//Compose navigation
|
||||||
implementation(libs.androidx.navigation.compose)
|
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.core.ktx)
|
||||||
implementation(libs.androidx.appcompat)
|
implementation(libs.androidx.appcompat)
|
||||||
implementation(libs.material)
|
implementation(libs.material)
|
||||||
|
|
|
||||||
43
DBTApp/app/schemas/de.cdaut.dbtapp.model.AppDatabase/1.json
Normal file
43
DBTApp/app/schemas/de.cdaut.dbtapp.model.AppDatabase/1.json
Normal 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')"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,36 +1,30 @@
|
||||||
package de.cdaut.dbtapp
|
package de.cdaut.dbtapp
|
||||||
|
|
||||||
import android.graphics.drawable.shapes.Shape
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import androidx.activity.ComponentActivity
|
import androidx.activity.ComponentActivity
|
||||||
import androidx.activity.compose.setContent
|
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.Box
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.Emergency
|
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.FloatingActionButton
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.material3.Shapes
|
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.navigation.compose.NavHost
|
import androidx.navigation.compose.NavHost
|
||||||
import androidx.navigation.compose.composable
|
import androidx.navigation.compose.composable
|
||||||
import androidx.navigation.compose.rememberNavController
|
import androidx.navigation.compose.rememberNavController
|
||||||
import com.google.android.material.floatingactionbutton.FloatingActionButton
|
|
||||||
import de.cdaut.dbtapp.components.BottomNavigationBar
|
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.SkillsScreen
|
||||||
|
import de.cdaut.dbtapp.components.TrackingScreen
|
||||||
import de.cdaut.dbtapp.navigation.Screens
|
import de.cdaut.dbtapp.navigation.Screens
|
||||||
|
|
||||||
class MainActivity : ComponentActivity() {
|
class MainActivity : ComponentActivity() {
|
||||||
|
|
@ -42,49 +36,52 @@ class MainActivity : ComponentActivity() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Preview(locale = "en-US")
|
@Preview(locale = "en-US", device = "id:pixel_6")
|
||||||
@Composable
|
@Composable
|
||||||
private fun MainContent() {
|
private fun MainContent() {
|
||||||
val navController = rememberNavController()
|
val navController = rememberNavController()
|
||||||
Box {
|
MaterialTheme {
|
||||||
Scaffold(
|
Box {
|
||||||
modifier = Modifier.fillMaxSize(),
|
Scaffold(
|
||||||
bottomBar = { BottomNavigationBar(navController) },
|
modifier = Modifier.fillMaxSize(),
|
||||||
floatingActionButton = { EmergencyButton() }
|
bottomBar = { BottomNavigationBar(navController) },
|
||||||
) { paddingValues ->
|
floatingActionButton = { EmergencyButton() }
|
||||||
NavHost(
|
) { paddingValues ->
|
||||||
navController = navController,
|
NavHost(
|
||||||
startDestination = Screens.Home.route,
|
navController = navController,
|
||||||
modifier = Modifier.padding(paddingValues = paddingValues)
|
startDestination = Screens.Home.route,
|
||||||
) {
|
modifier = Modifier.padding(paddingValues = paddingValues)
|
||||||
composable(Screens.Tracking.route) {
|
) {
|
||||||
Text("Tracking")
|
composable(Screens.Tracking.route) {
|
||||||
}
|
TrackingScreen()
|
||||||
composable(Screens.Skillslist.route) {
|
}
|
||||||
SkillsScreen()
|
composable(Screens.Skillslist.route) {
|
||||||
}
|
SkillsScreen()
|
||||||
composable(Screens.Home.route) {
|
}
|
||||||
Text("Home")
|
composable(Screens.Home.route) {
|
||||||
}
|
Text("Home")
|
||||||
composable(Screens.Favourites.route) {
|
}
|
||||||
Text("Favourites")
|
composable(Screens.Favourites.route) {
|
||||||
|
FavouritesScreen()
|
||||||
|
|
||||||
}
|
}
|
||||||
composable(Screens.Skillschains.route) {
|
composable(Screens.Skillschains.route) {
|
||||||
Text("Skillschains")
|
SkillsChainsScreen()
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Preview
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun EmergencyButton() {
|
private fun EmergencyButton() {
|
||||||
FloatingActionButton(
|
FloatingActionButton(
|
||||||
onClick = {},
|
onClick = {
|
||||||
containerColor = Color.Red
|
//TODO: Implement function for emergency Button
|
||||||
|
},
|
||||||
|
containerColor = MaterialTheme.colorScheme.error
|
||||||
) {
|
) {
|
||||||
Icon(
|
Icon(
|
||||||
imageVector = Icons.Filled.Emergency,
|
imageVector = Icons.Filled.Emergency,
|
||||||
|
|
|
||||||
|
|
@ -19,17 +19,19 @@ import de.cdaut.dbtapp.navigation.BottomNavigationItem
|
||||||
fun BottomNavigationBar(navController: NavController) {
|
fun BottomNavigationBar(navController: NavController) {
|
||||||
var context = LocalContext.current
|
var context = LocalContext.current
|
||||||
//remember the currently selected view
|
//remember the currently selected view
|
||||||
|
//default view is home
|
||||||
|
val homeView = BottomNavigationItem()
|
||||||
|
.bottomNavigationItems()
|
||||||
|
.find { item -> item.label == "Home" }!!.idx
|
||||||
var navigationSelectedItem by remember {
|
var navigationSelectedItem by remember {
|
||||||
mutableIntStateOf(
|
mutableIntStateOf(
|
||||||
//default view is home
|
homeView
|
||||||
BottomNavigationItem().bottomNavigationItems(ctx = context)
|
|
||||||
.find { item -> item.label == "Home" }!!.idx
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
NavigationBar {
|
NavigationBar {
|
||||||
//Create an entry in the bottom bar for each view
|
//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 ->
|
.forEachIndexed { index, item ->
|
||||||
NavigationBarItem(
|
NavigationBarItem(
|
||||||
selected = index == navigationSelectedItem,
|
selected = index == navigationSelectedItem,
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,12 +1,9 @@
|
||||||
package de.cdaut.dbtapp.components
|
package de.cdaut.dbtapp.components
|
||||||
|
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.border
|
|
||||||
import androidx.compose.foundation.clickable
|
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.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.IntrinsicSize
|
import androidx.compose.foundation.layout.IntrinsicSize
|
||||||
import androidx.compose.foundation.layout.Row
|
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.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.width
|
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.foundation.shape.CircleShape
|
import androidx.compose.foundation.shape.CircleShape
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.material.icons.Icons
|
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.filled.Star
|
||||||
import androidx.compose.material.icons.outlined.Star
|
|
||||||
import androidx.compose.material.icons.outlined.StarOutline
|
import androidx.compose.material.icons.outlined.StarOutline
|
||||||
import androidx.compose.material3.Button
|
|
||||||
import androidx.compose.material3.Card
|
import androidx.compose.material3.Card
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
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.res.stringResource
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.em
|
|
||||||
import de.cdaut.dbtapp.R
|
import de.cdaut.dbtapp.R
|
||||||
import de.cdaut.dbtapp.model.Skill
|
import de.cdaut.dbtapp.model.Skill
|
||||||
import de.cdaut.dbtapp.model.SkillCategory
|
import de.cdaut.dbtapp.model.SkillCategory
|
||||||
|
|
@ -49,8 +43,10 @@ import de.cdaut.dbtapp.model.SkillCategory
|
||||||
@Composable
|
@Composable
|
||||||
fun SkillsScreen() {
|
fun SkillsScreen() {
|
||||||
Column(
|
Column(
|
||||||
Modifier.verticalScroll(rememberScrollState())
|
Modifier.verticalScroll(rememberScrollState()),
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
) {
|
) {
|
||||||
|
RoundedSearchBar(onSearch = {}, stringResource(R.string.label_skills_search_bar))
|
||||||
SkillCategory.entries.forEach { skillCategory ->
|
SkillCategory.entries.forEach { skillCategory ->
|
||||||
SkillsCategoryCard(skillCategory.skills, skillCategory.title)
|
SkillsCategoryCard(skillCategory.skills, skillCategory.title)
|
||||||
Spacer(Modifier.height(5.dp))
|
Spacer(Modifier.height(5.dp))
|
||||||
|
|
@ -58,7 +54,6 @@ fun SkillsScreen() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Preview
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun SkillsCategoryCardPrev() {
|
private fun SkillsCategoryCardPrev() {
|
||||||
SkillsCategoryCard(Skill.mockSkills(), "Skill")
|
SkillsCategoryCard(Skill.mockSkills(), "Skill")
|
||||||
|
|
@ -66,22 +61,41 @@ private fun SkillsCategoryCardPrev() {
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun SkillsCategoryCard(skills: List<Skill>, title: String) {
|
fun SkillsCategoryCard(skills: List<Skill>, title: String) {
|
||||||
|
var enabled by remember {
|
||||||
|
mutableStateOf(false)
|
||||||
|
}
|
||||||
|
|
||||||
Card(
|
Card(
|
||||||
Modifier
|
Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(10.dp)
|
.padding(10.dp)
|
||||||
) {
|
) {
|
||||||
TitleText(
|
Row(
|
||||||
modifier = Modifier.padding(10.dp),
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
content = title
|
horizontalArrangement = Arrangement.SpaceBetween,
|
||||||
)
|
modifier = Modifier
|
||||||
skills.forEach { skill ->
|
.fillMaxWidth()
|
||||||
SingleSkillCard(skill.title, skill.description)
|
.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
|
@Composable
|
||||||
private fun SingleSkillsCardPreview() {
|
private fun SingleSkillsCardPreview() {
|
||||||
SingleSkillCard(
|
SingleSkillCard(
|
||||||
|
|
@ -118,16 +132,29 @@ private fun SingleSkillCard(title: String, description: String) {
|
||||||
DescriptionText(description)
|
DescriptionText(description)
|
||||||
}
|
}
|
||||||
|
|
||||||
Icon(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier.clip(CircleShape),
|
||||||
.padding(10.dp)
|
contentAlignment = Alignment.Center
|
||||||
.clickable(onClick = {
|
) {
|
||||||
selected = !selected
|
if (selected) {
|
||||||
}),
|
Icon(
|
||||||
imageVector = if (selected) Icons.Outlined.Star else Icons.Outlined.StarOutline,
|
modifier = Modifier.clip(CircleShape),
|
||||||
contentDescription = stringResource(R.string.desc_btn_fav),
|
imageVector = Icons.Filled.Star,
|
||||||
tint = if (selected) Color.Yellow else Color.Black
|
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)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -6,10 +6,8 @@ import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.text.TextStyle
|
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.TextUnit
|
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
|
|
||||||
@Preview
|
@Preview
|
||||||
|
|
|
||||||
400
DBTApp/app/src/main/java/de/cdaut/dbtapp/components/Tracking.kt
Normal file
400
DBTApp/app/src/main/java/de/cdaut/dbtapp/components/Tracking.kt
Normal 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
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
@ -1,24 +1,53 @@
|
||||||
package de.cdaut.dbtapp.model
|
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 {
|
companion object {
|
||||||
fun mockSkills(): List<Skill> {
|
fun mockSkills(): List<Skill> {
|
||||||
return listOf(
|
return listOf(
|
||||||
Skill(
|
Skill(
|
||||||
title = "Test Hallo :3",
|
title = "5-4-3-2-1",
|
||||||
description = "lorem ipsum dolor sid amnet consequetur blabla yada yada"
|
description = "5 sehen, 5 hören, 5 fühlen, 4 sehen, 4 hören…"
|
||||||
),
|
),
|
||||||
Skill(
|
Skill(
|
||||||
title = "5-4-3-2-1",
|
title = "Skilltitel",
|
||||||
description = "Hier kurz beschreiben wie die Übung funktioniert. Ggf. mehrere Zeilen aber nicht super lang"
|
description = "Hier kurz beschreiben wie die Übung funktioniert. Ggf. mehrere Zeilen aber nicht super lang"
|
||||||
),
|
),
|
||||||
Skill(
|
// Skill(
|
||||||
title = "UwU UwU awawawa",
|
// title = "UwU UwU awawawa",
|
||||||
description = "Just arf a little like the good fopsgirl you are :3"
|
// 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)
|
||||||
}
|
}
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
package de.cdaut.dbtapp.model
|
package de.cdaut.dbtapp.model
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
|
||||||
|
|
||||||
enum class SkillCategory(val title: String, val skills: List<Skill> = Skill.mockSkills()) {
|
enum class SkillCategory(val title: String, val skills: List<Skill> = Skill.mockSkills()) {
|
||||||
Mindfulness("Achtsamkeitsübungen"),
|
Mindfulness("Achtsamkeitsübungen"),
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
26
DBTApp/app/src/main/java/de/cdaut/dbtapp/model/Tracker.kt
Normal file
26
DBTApp/app/src/main/java/de/cdaut/dbtapp/model/Tracker.kt
Normal 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"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,15 +1,14 @@
|
||||||
package de.cdaut.dbtapp.navigation
|
package de.cdaut.dbtapp.navigation
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.automirrored.filled.MenuBook
|
import androidx.compose.material.icons.automirrored.filled.MenuBook
|
||||||
import androidx.compose.material.icons.filled.CalendarToday
|
import androidx.compose.material.icons.filled.CalendarToday
|
||||||
import androidx.compose.material.icons.filled.Checklist
|
import androidx.compose.material.icons.filled.Checklist
|
||||||
import androidx.compose.material.icons.filled.Home
|
import androidx.compose.material.icons.filled.Home
|
||||||
import androidx.compose.material.icons.outlined.Star
|
import androidx.compose.material.icons.outlined.Star
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.graphics.vector.ImageVector
|
import androidx.compose.ui.graphics.vector.ImageVector
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.core.content.ContextCompat.getString
|
|
||||||
import de.cdaut.dbtapp.R
|
import de.cdaut.dbtapp.R
|
||||||
|
|
||||||
data class BottomNavigationItem(
|
data class BottomNavigationItem(
|
||||||
|
|
@ -18,34 +17,35 @@ data class BottomNavigationItem(
|
||||||
val route: String = "",
|
val route: String = "",
|
||||||
val idx: Int = 0
|
val idx: Int = 0
|
||||||
) {
|
) {
|
||||||
fun bottomNavigationItems(ctx: Context): List<BottomNavigationItem> {
|
@Composable
|
||||||
|
fun bottomNavigationItems(): List<BottomNavigationItem> {
|
||||||
return listOf(
|
return listOf(
|
||||||
BottomNavigationItem(
|
BottomNavigationItem(
|
||||||
label = getString(ctx, R.string.label_tracking),
|
label = stringResource(R.string.label_tracking),
|
||||||
icon = Icons.Filled.CalendarToday,
|
icon = Icons.Filled.CalendarToday,
|
||||||
route = Screens.Tracking.route,
|
route = Screens.Tracking.route,
|
||||||
idx = 0
|
idx = 0
|
||||||
),
|
),
|
||||||
BottomNavigationItem(
|
BottomNavigationItem(
|
||||||
label = getString(ctx, R.string.label_skillslist),
|
label = stringResource(R.string.label_skillslist),
|
||||||
icon = Icons.AutoMirrored.Filled.MenuBook,
|
icon = Icons.AutoMirrored.Filled.MenuBook,
|
||||||
route = Screens.Skillslist.route,
|
route = Screens.Skillslist.route,
|
||||||
idx = 1
|
idx = 1
|
||||||
),
|
),
|
||||||
BottomNavigationItem(
|
BottomNavigationItem(
|
||||||
label = getString(ctx, R.string.label_home),
|
label = stringResource(R.string.label_home),
|
||||||
icon = Icons.Filled.Home,
|
icon = Icons.Filled.Home,
|
||||||
route = Screens.Home.route,
|
route = Screens.Home.route,
|
||||||
idx = 2
|
idx = 2
|
||||||
),
|
),
|
||||||
BottomNavigationItem(
|
BottomNavigationItem(
|
||||||
label = getString(ctx, R.string.label_favourites),
|
label = stringResource(R.string.label_favourites),
|
||||||
icon = Icons.Outlined.Star,
|
icon = Icons.Outlined.Star,
|
||||||
route = Screens.Favourites.route,
|
route = Screens.Favourites.route,
|
||||||
idx = 3
|
idx = 3
|
||||||
),
|
),
|
||||||
BottomNavigationItem(
|
BottomNavigationItem(
|
||||||
label = getString(ctx, R.string.label_skillschains),
|
label = stringResource(R.string.label_skillschains),
|
||||||
icon = Icons.Filled.Checklist,
|
icon = Icons.Filled.Checklist,
|
||||||
route = Screens.Skillschains.route,
|
route = Screens.Skillschains.route,
|
||||||
idx = 4
|
idx = 4
|
||||||
|
|
|
||||||
15
DBTApp/app/src/main/java/de/cdaut/dbtapp/util/DateHelpers.kt
Normal file
15
DBTApp/app/src/main/java/de/cdaut/dbtapp/util/DateHelpers.kt
Normal 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
|
||||||
|
}
|
||||||
|
|
@ -8,4 +8,14 @@
|
||||||
<string name="label_skillschains">Skillsketten</string>
|
<string name="label_skillschains">Skillsketten</string>
|
||||||
<string name="emergency_button_description">Notfallknopf</string>
|
<string name="emergency_button_description">Notfallknopf</string>
|
||||||
<string name="desc_btn_fav">Favorisieren Button</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>
|
</resources>
|
||||||
|
|
@ -7,4 +7,14 @@
|
||||||
<string name="label_skillschains">Skills Chains</string>
|
<string name="label_skillschains">Skills Chains</string>
|
||||||
<string name="emergency_button_description">Emergency Button</string>
|
<string name="emergency_button_description">Emergency Button</string>
|
||||||
<string name="desc_btn_fav">Favourte 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>
|
</resources>
|
||||||
|
|
@ -3,4 +3,5 @@ plugins {
|
||||||
alias(libs.plugins.android.application) apply false
|
alias(libs.plugins.android.application) apply false
|
||||||
alias(libs.plugins.kotlin.android) apply false
|
alias(libs.plugins.kotlin.android) apply false
|
||||||
alias(libs.plugins.compose.compiler) apply false
|
alias(libs.plugins.compose.compiler) apply false
|
||||||
|
id("com.google.devtools.ksp") version "2.0.21-1.0.27" apply false
|
||||||
}
|
}
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
[versions]
|
[versions]
|
||||||
activityCompose = "1.10.1"
|
activityCompose = "1.10.1"
|
||||||
agp = "8.9.2"
|
agp = "8.10.1"
|
||||||
kotlin = "2.0.21"
|
kotlin = "2.0.21"
|
||||||
coreKtx = "1.16.0"
|
coreKtx = "1.16.0"
|
||||||
junit = "4.13.2"
|
junit = "4.13.2"
|
||||||
|
|
@ -8,7 +8,10 @@ junitVersion = "1.2.1"
|
||||||
espressoCore = "3.6.1"
|
espressoCore = "3.6.1"
|
||||||
appcompat = "1.7.0"
|
appcompat = "1.7.0"
|
||||||
material = "1.12.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]
|
[libraries]
|
||||||
androidx-activity-compose = { module = "androidx.activity:activity-compose", version.ref = "activityCompose" }
|
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-material-icons-extended = { module = "androidx.compose.material:material-icons-extended" }
|
||||||
androidx-material3 = { module = "androidx.compose.material3:material3" }
|
androidx-material3 = { module = "androidx.compose.material3:material3" }
|
||||||
androidx-navigation-compose = { module = "androidx.navigation:navigation-compose", version.ref = "navigationCompose" }
|
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-manifest = { module = "androidx.compose.ui:ui-test-manifest" }
|
||||||
androidx-ui-test-junit4 = { module = "androidx.compose.ui:ui-test-junit4" }
|
androidx-ui-test-junit4 = { module = "androidx.compose.ui:ui-test-junit4" }
|
||||||
androidx-ui-tooling = { module = "androidx.compose.ui:ui-tooling" }
|
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-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }
|
||||||
androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }
|
androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }
|
||||||
material = { group = "com.google.android.material", name = "material", version.ref = "material" }
|
material = { group = "com.google.android.material", name = "material", version.ref = "material" }
|
||||||
|
room-runtime = { module = "androidx.room:room-runtime", version.ref = "roomRuntime" }
|
||||||
|
|
||||||
[plugins]
|
[plugins]
|
||||||
android-application = { id = "com.android.application", version.ref = "agp" }
|
android-application = { id = "com.android.application", version.ref = "agp" }
|
||||||
|
|
|
||||||
BIN
planning/screenshots/favourites_screen.png
Normal file
BIN
planning/screenshots/favourites_screen.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 551 KiB |
BIN
planning/screenshots/skillschains_screen.png
Normal file
BIN
planning/screenshots/skillschains_screen.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 532 KiB |
BIN
planning/screenshots/skillslist.png
Normal file
BIN
planning/screenshots/skillslist.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 549 KiB |
BIN
planning/screenshots/tracking_screen.png
Normal file
BIN
planning/screenshots/tracking_screen.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 544 KiB |
Loading…
Add table
Add a link
Reference in a new issue