Skip to content

Commit

Permalink
v0.2
Browse files Browse the repository at this point in the history
  • Loading branch information
antoineverin committed Oct 21, 2023
1 parent defbe65 commit 7bd900b
Show file tree
Hide file tree
Showing 16 changed files with 596 additions and 246 deletions.
1 change: 1 addition & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ android {
buildTypes {
release {
isMinifyEnabled = false
isDebuggable = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
Expand Down

This file was deleted.

16 changes: 13 additions & 3 deletions app/src/main/java/fr/antoineverin/worktime/WtAppRoute.kt
Original file line number Diff line number Diff line change
@@ -1,14 +1,24 @@
package fr.antoineverin.worktime

import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavType
import androidx.navigation.compose.composable
import fr.antoineverin.worktime.ui.screen.AddEntryScreen
import androidx.navigation.navArgument
import fr.antoineverin.worktime.ui.screen.EditEntryScreen
import fr.antoineverin.worktime.ui.screen.ListEntriesScreen
import fr.antoineverin.worktime.ui.screen.MainScreen

fun NavGraphBuilder.wtAppRoute(appState: WtAppState) {
composable(HOME_ROUTE) { MainScreen({ appState.navigate(it) }) }
composable(ADD_ENTRY) { AddEntryScreen(popUp = { appState.popUp() }) }
composable(LIST_ENTRIES) { ListEntriesScreen({ appState.navigate(it) }) }
composable(
route = "$EDIT_ENTRY/{entryId}",
arguments = listOf(navArgument("entryId") { type = NavType.IntType })
) { backEntryStack ->
backEntryStack.arguments?.getInt("entryId")?.let { EditEntryScreen(it, { appState.popUp() }) }
}
}

const val HOME_ROUTE = "home"
const val ADD_ENTRY = "add_entry"
const val LIST_ENTRIES = "entry/list"
const val EDIT_ENTRY = "entry/edit"
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ interface TimeSpentDao: WtDao<TimeSpent> {
@Query("SELECT * FROM time_spent")
suspend fun getAllTimeSpent(): List<TimeSpent>

@Query("SELECT * FROM time_spent WHERE id = :id")
suspend fun getTimeSpent(id: Int): TimeSpent

@Query("SELECT * FROM time_spent WHERE period = :period")
suspend fun getTimeSpentFromPeriod(period: String): List<TimeSpent>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ package fr.antoineverin.worktime.database.entities

import androidx.room.Entity
import androidx.room.PrimaryKey
import java.time.Duration
import java.time.LocalDate
import java.time.LocalTime
import java.time.YearMonth
import java.time.format.DateTimeFormatter

@Entity(tableName = "time_spent")
data class TimeSpent(
Expand All @@ -13,4 +15,20 @@ data class TimeSpent(
var date: LocalDate,
var from: LocalTime,
var to: LocalTime?,
)
) {

fun formatDuration(): String {
return (
from.format(DateTimeFormatter.ofPattern("HH:mm"))
+ " - "
+ (to?.format(DateTimeFormatter.ofPattern("HH:mm")) ?: "??:??")
)
}

fun getDuration(): Duration? {
if(to == null) return null
return Duration.ofSeconds(to!!.toSecondOfDay().toLong())
.minusSeconds(from.toSecondOfDay().toLong())
}

}
93 changes: 93 additions & 0 deletions app/src/main/java/fr/antoineverin/worktime/ui/field/DateField.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package fr.antoineverin.worktime.ui.field

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.width
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusDirection
import androidx.compose.ui.focus.FocusManager
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.unit.dp
import androidx.core.text.isDigitsOnly
import fr.antoineverin.worktime.ui.screen.checkDigitAndRange
import java.time.DateTimeException
import java.time.LocalDate


@Composable
fun DateField(
value: DateFieldValue,
onValueChange: (DateFieldValue) -> Unit,
focusManager: FocusManager,
modifier: Modifier = Modifier,
imeAction: ImeAction = ImeAction.Next,
action: () -> Unit = { focusManager.moveFocus(FocusDirection.Next) }
) {
Row(
modifier = modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
NumberField(
label = "Day",
value = value.day,
onValueChange = { onValueChange(value.copy(day = it)) },
checkValue = { checkDigitAndRange(it, 0..31) },
focusManager = focusManager,
modifier = Modifier.weight(1f)
)
Spacer(Modifier.width(5.dp))
NumberField(
label = "Month",
value = value.month,
onValueChange = { onValueChange(value.copy(month = it)) },
checkValue = { checkDigitAndRange(it, 0..12) },
focusManager = focusManager,
modifier = Modifier.weight(1f)
)
Spacer(Modifier.width(5.dp))
NumberField(
label = "Year",
value = value.year,
onValueChange = { onValueChange(value.copy(year = it)) },
checkValue = { it.isDigitsOnly() },
focusManager = focusManager,
modifier = Modifier.weight(1f),
imeAction = imeAction,
action = action
)
}
}

data class DateFieldValue(
val day: String,
val month: String,
val year: String
) {

fun isValid(): Boolean {
if (!(day.isDigitsOnly() && month.isDigitsOnly() && year.isDigitsOnly()))
return false
if (isEmpty())
return false
return try {
LocalDate.of(year.toInt(), month.toInt(), day.toInt())
true
}catch (e: DateTimeException) {
false
}
}

fun isEmpty(): Boolean {
return day == "" || month == "" || year == ""
}

fun toLocalDate(): LocalDate {
return LocalDate.of(year.toInt(), month.toInt(), day.toInt())
}

}
49 changes: 49 additions & 0 deletions app/src/main/java/fr/antoineverin/worktime/ui/field/NumberField.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package fr.antoineverin.worktime.ui.field

import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
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.Modifier
import androidx.compose.ui.focus.FocusDirection
import androidx.compose.ui.focus.FocusManager
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.KeyboardType

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun NumberField(
label: String,
value: String,
onValueChange: (String) -> Unit,
checkValue: (String) -> Boolean,
focusManager: FocusManager,
modifier: Modifier = Modifier,
imeAction: ImeAction = ImeAction.Next,
action: () -> Unit = { focusManager.moveFocus(FocusDirection.Next) }
) {
var isError by remember { mutableStateOf(false) }

TextField(
label = { Text(label) },
value = value,
onValueChange = {
isError = !checkValue(it)
onValueChange(it)
},
keyboardOptions = KeyboardOptions(
autoCorrect = false,
keyboardType = KeyboardType.Number,
imeAction = imeAction
),
keyboardActions = KeyboardActions { action() },
isError = isError,
modifier = modifier
)
}
82 changes: 82 additions & 0 deletions app/src/main/java/fr/antoineverin/worktime/ui/field/TimeField.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package fr.antoineverin.worktime.ui.field

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.width
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusDirection
import androidx.compose.ui.focus.FocusManager
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.unit.dp
import androidx.core.text.isDigitsOnly
import fr.antoineverin.worktime.ui.screen.checkDigitAndRange
import java.time.DateTimeException
import java.time.LocalTime

@Composable
fun TimeField(
value: TimeFieldValue,
onValueChange: (TimeFieldValue) -> Unit,
focusManager: FocusManager,
modifier: Modifier = Modifier,
imeAction: ImeAction = ImeAction.Next,
action: () -> Unit = { focusManager.moveFocus(FocusDirection.Next) }
) {
Row(
modifier = modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
NumberField(
label = "Hour",
value = value.hours,
onValueChange = { onValueChange(value.copy(hours = it)) },
checkValue = { checkDigitAndRange(it, 0..24) },
focusManager = focusManager,
modifier = Modifier.weight(1f)
)
Spacer(Modifier.width(5.dp))
NumberField(
label = "Minutes",
value = value.minutes,
onValueChange = { onValueChange(value.copy(minutes = it)) },
checkValue = { checkDigitAndRange(it, 0..60) },
focusManager = focusManager,
modifier = Modifier.weight(1f),
imeAction = imeAction,
action = action
)
}
}

data class TimeFieldValue(
val minutes: String,
val hours: String
) {

fun isValid(): Boolean {
if (!(minutes.isDigitsOnly() && hours.isDigitsOnly()))
return false
if (isEmpty())
return false
return try {
LocalTime.of(hours.toInt(), minutes.toInt())
true
}catch (e: DateTimeException) {
false
}
}

fun isEmpty(): Boolean {
return minutes == "" || hours == ""
}

fun toLocalTime(): LocalTime {
return LocalTime.of(hours.toInt(), minutes.toInt())
}

}
Loading

0 comments on commit 7bd900b

Please sign in to comment.