Skip to content

Commit

Permalink
Merge pull request #2 from ronjunevaldoz/test
Browse files Browse the repository at this point in the history
Bug fixes ui and date range functionality
  • Loading branch information
ronjunevaldoz authored Mar 13, 2024
2 parents 09cea6f + cab0a64 commit ca4dce7
Show file tree
Hide file tree
Showing 4 changed files with 126 additions and 104 deletions.
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package io.github.ronjunevaldoz.kmp_calendar

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.fillMaxWidth
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.grid.GridCells
Expand All @@ -13,6 +15,7 @@ import androidx.compose.foundation.lazy.items
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Immutable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.State
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
Expand Down Expand Up @@ -42,10 +45,17 @@ enum class CalendarSelection {
Range
}

enum class CalendarCursor {
Clear,
StartDate,
EndDate,
}

interface CalendarState {
var cursor: CalendarCursor
var start: CalendarDay?
var end: CalendarDay?
var selected : CalendarDay?
var selected: CalendarDay?
var currentDate: LocalDate
var type: CalendarType
var selection: CalendarSelection
Expand Down Expand Up @@ -96,13 +106,21 @@ object CalendarDefaults {
)
}

class MutableCalendarState(defaultDate: LocalDate = today) : CalendarState {
override var start: CalendarDay? by mutableStateOf(null)
override var end: CalendarDay? by mutableStateOf(null)
override var selected: CalendarDay? by mutableStateOf(null)
class MutableCalendarState(
defaultDate: LocalDate = today,
cursor: CalendarCursor = CalendarCursor.Clear,
selection: CalendarSelection = CalendarSelection.Single,
selected: CalendarDay? = null,
start: CalendarDay? = null,
end: CalendarDay? = null
) : CalendarState {
override var cursor: CalendarCursor by mutableStateOf(cursor)
override var start: CalendarDay? by mutableStateOf(start)
override var end: CalendarDay? by mutableStateOf(end)
override var selected: CalendarDay? by mutableStateOf(selected)
override var currentDate: LocalDate by mutableStateOf(defaultDate)
override var type: CalendarType by mutableStateOf(CalendarType.Day)
override var selection: CalendarSelection by mutableStateOf(CalendarSelection.Single)
override var selection: CalendarSelection by mutableStateOf(selection)
override var hideTodayHighlight: Boolean by mutableStateOf(false)

override fun increaseMonth(month: Int) {
Expand Down Expand Up @@ -176,8 +194,28 @@ class MutableCalendarState(defaultDate: LocalDate = today) : CalendarState {
}

@Composable
fun rememberCalendarState(): CalendarState {
return remember { MutableCalendarState() }
fun rememberCalendarState(
cursor: CalendarCursor = CalendarCursor.Clear,
selection: CalendarSelection = CalendarSelection.Single,
selected: CalendarDay? = null,
start: CalendarDay? = null,
end: CalendarDay? = null,
): CalendarState {
return remember(
cursor,
selection,
selected,
start,
end
) {
MutableCalendarState(
cursor = cursor,
selection = selection,
selected = selected,
start = start,
end = end,
)
}
}

@Composable
Expand All @@ -198,15 +236,21 @@ fun Calendar(
color = textColor
)
},
calendarDay: @Composable (day: CalendarDay, onSelect: (day: CalendarDay) -> Unit) -> Unit = { day, onSelect ->
CalendarDayItem(day, onSelect)
calendarDay: @Composable (day: CalendarDay, inRange: Boolean, onDaySelected: (day: CalendarDay) -> Unit) -> Unit = { day, inRange, onDaySelected ->
DefaultCalendarDayItem(
modifier = Modifier
.size(30.dp).clickable { onDaySelected(day) },
inRange = inRange,
start = state.start,
end = state.end,
colors = CalendarDefaults.calendarColors(),
selectedDate = state.selected,
day = day,
)
},
calendarMonth: @Composable () -> Unit = {
CalendarMonthView(state = state, colors = colors)
},
onSelectDay: (
CalendarDay
) -> Unit = {}
}
) {
val currentDate = state.currentDate
Column(
Expand All @@ -228,39 +272,56 @@ fun Calendar(
}
val grids = state.generateCalendarGrid(currentDate.year, currentDate.monthNumber)

LazyVerticalGrid(
columns = GridCells.Fixed(7),
contentPadding = PaddingValues(horizontal = 12.dp),
) {
items(grids) {
calendarDay(it) { day ->
if(state.selection == CalendarSelection.Range) {
val end = state.end
val start = state.start

if (start == null) {
state.start = day
}
if (end == null) {
state.end = day
}

if (start != null && day.date <= start.date) {
state.start = day
state.end = null
}
LaunchedEffect(state.selected) {
val selectionDay = state.selected
if (state.selection == CalendarSelection.Range && selectionDay != null) {
when (state.cursor) {
CalendarCursor.Clear -> {
state.cursor = CalendarCursor.StartDate
// state.selected = selectionDay
state.start = selectionDay
state.end = null
}

if (end != null && day.date >= end.date) {
state.end = day
CalendarCursor.StartDate -> {
val start = state.start
val end = state.end
if (start != null) {
if (selectionDay.date < start.date) {
state.start = selectionDay
} else {
state.end = selectionDay
state.cursor = CalendarCursor.Clear
}
} else {
state.start = selectionDay
state.cursor = CalendarCursor.EndDate
}
}

if (end != null && start != null && day.date > start.date && day.date <= end.date) {
state.end = day
}
} else {
state.selected = day
CalendarCursor.EndDate -> {
state.end = selectionDay
state.cursor = CalendarCursor.Clear
}
onSelectDay(day)
}
}
}

LazyVerticalGrid(
columns = GridCells.Fixed(7),
contentPadding = PaddingValues(horizontal = 12.dp),
) {
items(grids) { day ->
val start = state.start?.date
val end = state.end?.date
val inRange = if (start != null && end != null) {
val range = start..end
day.date in range
} else {
false
}
calendarDay(day, inRange) { selectionDay ->
state.selected = selectionDay
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package io.github.ronjunevaldoz.kmp_calendar

import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.size
Expand All @@ -19,14 +18,13 @@ import androidx.compose.ui.unit.dp

@Composable
fun DefaultCalendarDayItem(
modifier: Modifier = Modifier,
inRange: Boolean,
start: CalendarDay?,
end: CalendarDay?,
colors: CalendarColors,
hideTodayHighlight: Boolean,
selectedDate: CalendarDay?,
day: CalendarDay,
onSelect: (CalendarDay) -> Unit
) {
val primaryColor by colors.contentColor(enabled = true)
val isDaySelected = selectedDate?.date == day.date
Expand All @@ -53,9 +51,7 @@ fun DefaultCalendarDayItem(
val endSelected = end?.date == day.date

Box(
modifier = Modifier
.size(30.dp)
.clickable { onSelect(day) },
modifier = modifier,
contentAlignment = Alignment.Center
) {
if (isDaySelected) {
Expand Down Expand Up @@ -97,13 +93,11 @@ fun DefaultCalendarDayItem(
Text(
text = "${day.date.dayOfMonth}",
color = if (isPrimary) Color.White else color,
fontWeight = FontWeight.SemiBold
)
} else {
Text(
text = "${day.date.dayOfMonth}",
color = color,
fontWeight = FontWeight.SemiBold
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ fun CalendarMonthView(state: CalendarState, colors: CalendarColors) {
Text(
text = "${currentDate.year}",
style = MaterialTheme.typography.titleLarge,
fontWeight = FontWeight.Bold,
// fontWeight = FontWeight.Bold,
color = textColor,
)
LazyVerticalGrid(
Expand All @@ -49,7 +49,7 @@ fun CalendarMonthView(state: CalendarState, colors: CalendarColors) {
// change calendar to day view
state.type = CalendarType.Day
},
fontWeight = FontWeight.Bold,
// fontWeight = FontWeight.Bold,
color = textColor
)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package io.github.ronjunevaldoz.kmp_calendar

import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
Expand All @@ -10,29 +12,29 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog
import androidx.compose.ui.window.DialogProperties

@Composable
fun CalendarPicker(
modifier: Modifier = Modifier,
state: CalendarState = rememberCalendarState(),
onDismiss: () -> Unit = {},
onDaySelected: (CalendarDay) -> Unit = {},
onRangeSelected: (start: CalendarDay?, end: CalendarDay?) -> Unit = {_,_->},
content: @Composable () -> Unit = {
DefaultCalendar(state, onSelectDay = {
when (state.selection) {
CalendarSelection.Single -> {
// dismiss immediately on selection
onDaySelected(it)
onDismiss()
}

CalendarSelection.Range -> {
val start = state.start
val end = state.end
onRangeSelected(start, end)
}
Calendar(
modifier = Modifier.padding(vertical = 12.dp),
state = state,
colors = CalendarDefaults.calendarColors(),
calendarDay = { day, inRange, onDaySelected ->
DefaultCalendarDayItem(
modifier = Modifier.size(30.dp).clickable { onDaySelected(day) },
inRange = inRange,
start = state.start,
end = state.end,
colors = CalendarDefaults.calendarColors(),
selectedDate = state.selected,
day = day
)
}
})
)
}
) {
Dialog(onDismissRequest = onDismiss, DialogProperties(usePlatformDefaultWidth = false)) {
Expand All @@ -46,39 +48,4 @@ fun CalendarPicker(
content()
}
}
}

@Composable
fun DefaultCalendar(
state: CalendarState,
onSelectDay: (day: CalendarDay) -> Unit
) {
Calendar(
modifier = Modifier.padding(vertical = 12.dp),
state = state,
colors = CalendarDefaults.calendarColors(),
onSelectDay = {
onSelectDay(it)
},
calendarDay = { day, onDaySelected ->
val start = state.start?.date
val end = state.end?.date
val inRange = if(start != null && end != null) {
val range = start..end
day.date in range
} else {
false
}
DefaultCalendarDayItem(
inRange = inRange,
start = state.start,
end = state.end,
colors = CalendarDefaults.calendarColors(),
hideTodayHighlight = state.hideTodayHighlight,
selectedDate = state.selected,
day = day,
onSelect = onDaySelected
)
}
)
}

0 comments on commit ca4dce7

Please sign in to comment.