Рефакторинг компонентов и исправление календаря

This commit is contained in:
2023-04-03 22:36:14 +03:00
parent bf54dbb67a
commit 97551f0332
16 changed files with 760 additions and 962 deletions
+1 -1
View File
@@ -12,6 +12,6 @@
</deviceKey> </deviceKey>
</Target> </Target>
</runningDeviceTargetSelectedWithDropDown> </runningDeviceTargetSelectedWithDropDown>
<timeTargetWasSelectedWithDropDown value="2023-02-28T10:56:39.519355800Z" /> <timeTargetWasSelectedWithDropDown value="2023-04-02T15:04:59.965857200Z" />
</component> </component>
</project> </project>
@@ -1,5 +1,6 @@
package ru.megboyzz.dnevnik package ru.megboyzz.dnevnik
import android.content.Context
import android.os.Bundle import android.os.Bundle
import android.window.SplashScreen import android.window.SplashScreen
import androidx.activity.ComponentActivity import androidx.activity.ComponentActivity
@@ -13,7 +14,6 @@ import ru.megboyzz.dnevnik.ui.theme.*
class MainActivity : ComponentActivity() { class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContent { setContent {
Surface( Surface(
+34 -24
View File
@@ -7,9 +7,7 @@ import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.width
import androidx.compose.material.ripple.rememberRipple import androidx.compose.material.ripple.rememberRipple
import androidx.compose.runtime.Composable import androidx.compose.runtime.*
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.drawBehind import androidx.compose.ui.draw.drawBehind
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
@@ -24,14 +22,12 @@ import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.navigation.NavController import androidx.navigation.NavController
import com.kizitonwose.calendar.compose.CalendarLayoutInfo
import com.kizitonwose.calendar.compose.CalendarState
import com.kizitonwose.calendar.core.CalendarMonth
import kotlinx.coroutines.flow.filterNotNull
import ru.megboyzz.dnevnik.navigation.BaseNavRote import ru.megboyzz.dnevnik.navigation.BaseNavRote
import ru.megboyzz.dnevnik.screens.ui.Month
import ru.megboyzz.dnevnik.ui.theme.dark import ru.megboyzz.dnevnik.ui.theme.dark
import java.time.DayOfWeek
import java.time.LocalDate
import java.time.Year
import java.time.temporal.TemporalAdjusters
import java.util.*
@Composable @Composable
fun Int.AsPainter() = painterResource(this) fun Int.AsPainter() = painterResource(this)
@@ -110,21 +106,6 @@ fun Modifier.drawColoredShadow(
} }
} else this } else this
fun getMonthDaysBy(year: Int, month: Month, dayOfWeek: DayOfWeek): List<Int>{
var date: LocalDate =
Year.of(year).atMonth(month.ordinal + 1).atDay(1).with(TemporalAdjusters.firstInMonth(dayOfWeek))
var mi = date.month
val list = mutableListOf<Int>()
while (mi.ordinal == month.ordinal) {
list.add(date.dayOfMonth)
date = date.with(TemporalAdjusters.next(dayOfWeek))
mi = date.month
}
return list
}
@Composable @Composable
fun Modifier.mainClickable( fun Modifier.mainClickable(
radius: Dp = Dp.Unspecified, radius: Dp = Dp.Unspecified,
@@ -138,4 +119,33 @@ fun Modifier.mainClickable(
onClick = onClick onClick = onClick
) )
@Composable
fun rememberFirstMostVisibleMonth(
state: CalendarState,
viewportPercent: Float = 50f,
): CalendarMonth {
val visibleMonth = remember(state) { mutableStateOf(state.firstVisibleMonth) }
LaunchedEffect(state) {
snapshotFlow { state.layoutInfo.firstMostVisibleMonth(viewportPercent) }
.filterNotNull()
.collect { month -> visibleMonth.value = month }
}
return visibleMonth.value
}
private fun CalendarLayoutInfo.firstMostVisibleMonth(viewportPercent: Float = 50f): CalendarMonth? {
return if (visibleMonthsInfo.isEmpty()) {
null
} else {
val viewportSize = (viewportEndOffset + viewportStartOffset) * viewportPercent / 100f
visibleMonthsInfo.firstOrNull { itemInfo ->
if (itemInfo.offset < 0) {
itemInfo.offset + itemInfo.size >= viewportSize
} else {
itemInfo.size - itemInfo.offset >= viewportSize
}
}?.month
}
}
@@ -38,13 +38,6 @@ sealed class AppNavRoute(override val route: String): BaseNavRote(route){
@Composable @Composable
fun AppNavHost(){ fun AppNavHost(){
/*val activity = LocalContext.current as MainActivity
val application = activity.application as App
val viewModel: AppViewModel = viewModel(factory = AppViewModelFactory(application))*/
val scaffoldState = rememberScaffoldState() val scaffoldState = rememberScaffoldState()
val navController = rememberAnimatedNavController() val navController = rememberAnimatedNavController()
@@ -0,0 +1,115 @@
package ru.megboyzz.dnevnik.screens.ui
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
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.graphics.Color
import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.navigation.NavController
import ru.megboyzz.dnevnik.*
import ru.megboyzz.dnevnik.navigation.AppNavRoute
import ru.megboyzz.dnevnik.ui.theme.MainText
import ru.megboyzz.dnevnik.ui.theme.mainBlue
import ru.megboyzz.dnevnik.ui.theme.white
import ru.megboyzz.dnevnik.R
@Composable
fun BottomBar(navController: NavController) {
//Box(Modifier.fillMaxWidth().height(90.dp).shadow(8.dp))
// УЖАСНЫЙ КОСТЫЛЬ ДЛЯ ПЕРЕХОДОВ С ПОМОЩЬЮ СТЕЙТОВ TODO - УБРАТЬ
val goToMarks = remember { mutableStateOf(false) }
val goToHw = remember { mutableStateOf(false) }
val goToSchedule = remember { mutableStateOf(false) }
if(goToMarks.value){
navController.navigate(AppNavRoute.Marks)
//goToMarks.value = false
}
if(goToHw.value){
navController.navigate(AppNavRoute.HomeWorks)
//goToHw.value = false
}
if(goToSchedule.value){
navController.navigate(AppNavRoute.Schedule)
//goToSchedule.value = false
}
Box(
modifier = Modifier
.fillMaxWidth()
.drawColoredShadow(
offsetY = 1.dp
)
.height(90.dp)
.background(white)
.padding(10.dp, 10.dp, 10.dp, 15.dp),
){
Box(
Modifier
.fillMaxSize()
.clip(RoundedCornerShape(20.dp))
.background(mainBlue)
){
Row(
horizontalArrangement = Arrangement.SpaceEvenly,
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.fillMaxSize()
) {
BottomNavButton(
icon = R.drawable.ic_marks.AsPainter(),
text = R.string.title_marks.AsString()
) { goToMarks.value = true }
BottomNavButton(
icon = R.drawable.ic_homework.AsPainter(),
text = R.string.title_hw.AsString()
) { goToHw.value = true }
BottomNavButton(
icon = R.drawable.ic_schedule.AsPainter(),
text = R.string.title_schedule.AsString()
) { goToSchedule.value = true }
}
}
}
}
@Composable
fun BottomNavButton(
icon: Painter,
text: String,
color: Color = white,
onClick: () -> Unit,
) {
//Возможно стоит убрать анимацию клика
Box(
Modifier
.mainClickable(onClick = onClick, radius = 20.dp)
.padding(10.dp)) {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Image(
painter = icon,
contentDescription = "",
modifier = Modifier.padding(5.dp)
)
Text(
text = text,
style = MainText,
color = color,
overflow = TextOverflow.Ellipsis
)
}
}
}
@@ -1,205 +0,0 @@
package ru.megboyzz.dnevnik.screens.ui
import android.util.Log
import androidx.compose.foundation.*
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Card
import androidx.compose.material.Divider
import androidx.compose.material.IconButton
import androidx.compose.material.Text
import androidx.compose.runtime.*
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.text.style.TextAlign
import androidx.compose.ui.unit.dp
import com.kizitonwose.calendar.compose.CalendarState
import com.kizitonwose.calendar.compose.HorizontalCalendar
import com.kizitonwose.calendar.compose.WeekCalendar
import com.kizitonwose.calendar.compose.rememberCalendarState
import com.kizitonwose.calendar.compose.weekcalendar.rememberWeekCalendarState
import com.kizitonwose.calendar.core.CalendarDay
import com.kizitonwose.calendar.core.CalendarMonth
import com.kizitonwose.calendar.core.DayPosition
import com.kizitonwose.calendar.core.firstDayOfWeekFromLocale
import ru.megboyzz.dnevnik.AsPainter
import ru.megboyzz.dnevnik.AsString
import ru.megboyzz.dnevnik.R
import ru.megboyzz.dnevnik.ui.theme.*
import java.time.DayOfWeek
import java.time.LocalDate
import java.time.YearMonth
import java.time.format.TextStyle
import java.util.*
@Composable
fun MonthToggler(calendarState: CalendarState) {
//TODO убрать это куда нибудь
var listOfMonth = listOf(
R.string.title_january.AsString(),
R.string.title_february.AsString(),
R.string.title_march.AsString(),
R.string.title_april.AsString(),
R.string.title_may.AsString(),
R.string.title_june.AsString(),
R.string.title_july.AsString(),
R.string.title_august.AsString(),
R.string.title_september.AsString(),
R.string.title_october.AsString(),
R.string.title_november.AsString(),
R.string.title_december.AsString()
)
Row(
modifier = Modifier
.fillMaxWidth()
.padding(0.dp, 20.dp),
horizontalArrangement = Arrangement.Center
) {
Row(
horizontalArrangement = Arrangement.SpaceEvenly,
verticalAlignment = Alignment.CenterVertically
) {
IconButton(onClick = { calendarState.startMonth = calendarState.startMonth.minusMonths(1) }) {
Image(
painter = R.drawable.ic_month_swipe_left.AsPainter(),
contentDescription = "left",
alignment = Alignment.Center
)
}
for(style in TextStyle.values())
Log.i("check", calendarState.startMonth.month.getDisplayName(style, Locale.getDefault()))
Text(
//TODO Возможно стоит сделать эту строчку меньше((
text = "${listOfMonth[calendarState.startMonth.month.ordinal]} ${calendarState.startMonth.year}",
style = H1,
color = dark
)
IconButton(
onClick = { calendarState.startMonth = calendarState.startMonth.plusMonths(1) }
) {
Image(
painter = R.drawable.ic_month_swipe_right.AsPainter(),
contentDescription = "right",
alignment = Alignment.Center
)
}
}
}
}
//TODO доделать свертку календаря, он почти идеально работает
@Composable
fun NiceCalendar(
startMonth: YearMonth,
onClick: (day: CalendarDay, month: YearMonth, year: Int) -> Unit
) {
val endMonth = startMonth.plusMonths(100) // Adjust as needed
val firstDayOfWeek = remember { firstDayOfWeekFromLocale() } // Available from the library
val state = rememberCalendarState(
startMonth = startMonth,
endMonth = endMonth,
firstVisibleMonth = startMonth,
firstDayOfWeek = firstDayOfWeek
)
val weekState = rememberWeekCalendarState(
startDate = startMonth.atDay(1),
endDate = startMonth.atDay(7),
firstVisibleWeekDate = startMonth.atDay(1),
firstDayOfWeek = firstDayOfWeek
)
var selectedDate by remember { mutableStateOf<LocalDate?>(null) }
Column {
MonthToggler(calendarState = state)
Card(
shape = RoundedCornerShape(10.dp),
modifier = Modifier.defaultMinSize(300.dp)
) {
if(selectedDate == null)
HorizontalCalendar(
state = state,
dayContent = { day ->
Day(day, isSelected = selectedDate == day.date) { day ->
selectedDate = if (selectedDate == day.date) null else day.date
onClick(day, startMonth, startMonth.year)
}
},
monthHeader = { DaysOfWeekTitle(daysOfWeek = DayOfWeek.values().asList()) },
modifier = Modifier.padding(10.dp)
)
else
//TODO по возможности устранить повторы
WeekCalendar(
state = weekState,
weekHeader = { _ ->
DaysOfWeekTitle(daysOfWeek = DayOfWeek.values().asList())
},
dayContent = { day ->
Day(CalendarDay(day.date, DayPosition.InDate), isSelected = selectedDate == day.date) { day ->
selectedDate = if (selectedDate == day.date) null else day.date
onClick(day, startMonth, startMonth.year)
}
},
modifier = Modifier.padding(10.dp)
)
}
}
}
@Composable
fun DaysOfWeekTitle(daysOfWeek: List<DayOfWeek>) {
Column {
Row(modifier = Modifier.fillMaxWidth()) {
for (dayOfWeek in daysOfWeek) {
Text(
modifier = Modifier.weight(1f),
textAlign = TextAlign.Center,
text = dayOfWeek.getDisplayName(TextStyle.SHORT, Locale.getDefault()).uppercase(),
style = MainText
)
}
}
Divider(
thickness = 1.dp,
color = dark,
modifier = Modifier.padding(vertical = 10.dp)
)
}
}
@Composable
fun Day(day: CalendarDay, isSelected: Boolean, onClick: (CalendarDay) -> Unit) {
Box(
modifier = Modifier
.aspectRatio(ratio = 1f) // This is important for square sizing!
.clip(CircleShape)
.background(color = if (isSelected) lightGray else Color.Transparent)
.border(
border = BorderStroke(
width = 1.dp,
color = if (isSelected) mainBlue else Color.Transparent
),
shape = CircleShape
)
.clickable(
enabled = day.position == DayPosition.MonthDate,
onClick = { onClick(day) }
),
contentAlignment = Alignment.Center
) {
Text(
text = day.date.dayOfMonth.toString(),
style = MainText,
color = if (day.position == DayPosition.MonthDate) dark else Color.Gray
)
}
}
@@ -50,152 +50,10 @@ import java.time.DayOfWeek
import java.util.* import java.util.*
@Composable //Рефакторинг компонентов: разбиение файла с компонентами на отдельные файлы
fun MainScaffold( //Этот файл должен хранить только базовые реализации компонентов и общие компонеты компонеты
icon: Painter,
title: String,
/* TODO viewModel */
navController: NavController,
scaffoldState: ScaffoldState,
content: (@Composable (it: PaddingValues) -> Unit),
) {
val scope = rememberCoroutineScope()
Scaffold(
scaffoldState = scaffoldState,
topBar = {
TopAppBar(
backgroundColor = mainBlue,
contentColor = Color.White
) {
IconButton(
onClick = {
val drawerState = scaffoldState.drawerState
scope.launch {
if (drawerState.isClosed)
drawerState.open()
else
drawerState.close()
}
}
) {
Icon(
imageVector = Icons.Filled.Menu,
contentDescription = "menu",
tint = white
)
}
SpacerWidth(width = 5.dp)
Text(
text = title,
fontSize = 16.sp,
color = white
)
Spacer(Modifier.weight(1f))
Box(Modifier.padding(15.dp, 15.dp)) {
Image(painter = icon, contentDescription = "icon")
}
}
},
content = content,
drawerBackgroundColor = mainBlue,
drawerContentColor = white,
drawerShape = drawerShape,
drawerContent = { DrawerContent(navController, scaffoldState) },
bottomBar = { BottomBar(navController) }
)
}
@Composable
fun BottomBar(navController: NavController) {
//Box(Modifier.fillMaxWidth().height(90.dp).shadow(8.dp))
// УЖАСНЫЙ КОСТЫЛЬ ДЛЯ ПЕРЕХОДОВ С ПОМОЩЬЮ СТЕЙТОВ TODO - УБРАТЬ
val goToMarks = remember { mutableStateOf(false) }
val goToHw = remember { mutableStateOf(false) }
val goToSchedule = remember { mutableStateOf(false) }
if(goToMarks.value){
navController.navigate(AppNavRoute.Marks)
//goToMarks.value = false
}
if(goToHw.value){
navController.navigate(AppNavRoute.HomeWorks)
//goToHw.value = false
}
if(goToSchedule.value){
navController.navigate(AppNavRoute.Schedule)
//goToSchedule.value = false
}
Box(
modifier = Modifier
.fillMaxWidth()
.drawColoredShadow(
offsetY = 1.dp
)
.height(90.dp)
.background(white)
.padding(10.dp, 10.dp, 10.dp, 15.dp),
){
Box(
Modifier
.fillMaxSize()
.clip(RoundedCornerShape(20.dp))
.background(mainBlue)
){
Row(
horizontalArrangement = Arrangement.SpaceEvenly,
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.fillMaxSize()
) {
BottomNavButton(
icon = R.drawable.ic_marks.AsPainter(),
text = R.string.title_marks.AsString()
) { goToMarks.value = true }
BottomNavButton(
icon = R.drawable.ic_homework.AsPainter(),
text = R.string.title_hw.AsString()
) { goToHw.value = true }
BottomNavButton(
icon = R.drawable.ic_schedule.AsPainter(),
text = R.string.title_schedule.AsString()
) { goToSchedule.value = true }
}
}
}
}
@Composable
fun BottomNavButton(
icon: Painter,
text: String,
color: Color = white,
onClick: () -> Unit,
) {
//Возможно стоит убрать анимацию клика
Box(
Modifier
.mainClickable(onClick = onClick, radius = 20.dp)
.padding(10.dp)) {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Image(
painter = icon,
contentDescription = "",
modifier = Modifier.padding(5.dp)
)
Text(
text = text,
style = MainText,
color = color,
overflow = TextOverflow.Ellipsis
)
}
}
}
@Composable @Composable
fun AlmostOutlinedText( fun AlmostOutlinedText(
@@ -251,34 +109,6 @@ fun ProfileCard(
} }
} }
@Composable
fun LoginBackground() {
val icon = R.drawable.ic_header.AsPainter()
val size = icon.intrinsicSize
Column {
Image(
painter = icon,
contentDescription = "",
modifier = Modifier.fillMaxWidth(),
contentScale = ContentScale.FillWidth,
alignment = Alignment.TopStart
)
}
}
@Composable
fun BigLoginBackground() {
val icon = R.drawable.header_big.AsPainter()
Column(Modifier.fillMaxWidth()) {
Image(
painter = icon,
contentDescription = "",
modifier = Modifier.fillMaxWidth(),
alignment = Alignment.TopStart
)
}
}
@Composable @Composable
fun MainTextField( fun MainTextField(
value: MutableState<String>, value: MutableState<String>,
@@ -425,180 +255,6 @@ fun MainButton(
} }
} }
@Composable
fun LoginScreenContent(
login: MutableState<String>,
password: MutableState<String>,
isError: MutableState<Boolean>,
isRememberMe: MutableState<Boolean>,
onSignIn: () -> Unit,
onSignUp: () -> Unit,
onForgetPassword: () -> Unit
) {
val configuration = LocalConfiguration.current
val screenWidth = configuration.screenWidthDp
var defaultPadding = 65.dp
val isNormal = screenWidth < 500
Box(Modifier.fillMaxSize()) {
if(!isNormal) BigLoginBackground()
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.fillMaxWidth()
) {
if (isNormal) LoginBackground()
else {
defaultPadding *= 4
}
Row(horizontalArrangement = Arrangement.Center) {
Text(
text = R.string.title_welcome.AsString(),
style = Big,
textAlign = TextAlign.Center,
modifier = Modifier.padding(defaultPadding, 20.dp, defaultPadding, 40.dp),
color = dark
)
}
Column(
modifier = Modifier.padding(defaultPadding, 0.dp)
) {
Column(Modifier.fillMaxWidth()) {
MainTextField(
value = login,
label = R.string.title_login.AsString(),
isError = isError
)
SpacerHeight(15.dp)
MainTextField(
value = password,
keyboardType = KeyboardType.Password,
label = R.string.title_password.AsString(),
isError = isError
)
}
SpacerHeight(5.dp)
Row(
modifier = Modifier
.fillMaxWidth()
.height(30.dp),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Row(
modifier = Modifier.fillMaxHeight(),
verticalAlignment = Alignment.CenterVertically
) {
MainCheckbox(isRememberMe) { }
SpacerWidth(5.dp)
Text(
text = R.string.title_remember_me.AsString(),
style = MainText,
color = dark
)
}
Text(
text = R.string.title_forget_password.AsString(),
style = MainText,
color = dark,
modifier = Modifier.clickable(onClick = onForgetPassword)
)
}
Column(
modifier = Modifier
.fillMaxSize()
.padding(0.dp, 10.dp),
verticalArrangement = Arrangement.Center
) {
MainButton(
text = R.string.title_sign_in.AsString(),
onClick = onSignIn
)
SpacerHeight(5.dp)
Text(
text = R.string.title_sign_up.AsString(),
modifier = Modifier
.clickable(onClick = onSignUp)
.padding(5.dp)
.fillMaxWidth(),
textAlign = TextAlign.Center,
style = Mini,
color = dark
)
}
}
}
}
}
@Composable
fun SubScreenNavButton(
text: String,
isClicked: MutableState<Boolean>,
onCLick: () -> Unit
) {
val colors = ButtonDefaults.buttonColors(
backgroundColor = if(isClicked.value) mainBlue else white,
contentColor = if(isClicked.value) white else dark
)
Button(
onClick = {
isClicked.value = !isClicked.value
onCLick.invoke()
},
shape = RoundedCornerShape(20.dp),
border = BorderStroke(
width = 1.dp,
color = mainBlue,
),
colors = colors,
) {
Text(
text = text,
style= MainText
)
}
}
data class SubScreenData(
val title: String,
val to: BaseNavRote,
val isClicked: MutableState<Boolean>
)
@Composable
fun SubScreenNavBar(
list: List<SubScreenData>,
subScreenNavController: NavController
) {
val horizontalScroll = rememberScrollState()
Row(
modifier = Modifier
.fillMaxWidth()
.horizontalScroll(horizontalScroll)
.padding(15.dp),
horizontalArrangement = Arrangement.spacedBy(15.dp)
){
for(data in list){
if(data.isClicked.value)
subScreenNavController.navigate(data.to)
SubScreenNavButton(
text = data.title,
isClicked = data.isClicked
) {
for(d in list){
if(data != d)
d.isClicked.value = false
}
}
}
}
}
//Базовая карточка для оценок, карточек с диаграммами //Базовая карточка для оценок, карточек с диаграммами
@Composable @Composable
fun BaseCard( fun BaseCard(
@@ -746,349 +402,6 @@ fun LastMarkCard(
} }
} }
enum class Month{
January,
February,
March,
April,
May,
June,
July,
August,
September,
October,
November,
December,
}
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun NewCardCalendar(
month: Month,
year: Int,
onClick: (day: Int) -> Unit,
) {
val listOfDays = listOf(
R.string.title_mon.AsString(),
R.string.title_tue.AsString(),
R.string.title_wed.AsString(),
R.string.title_thu.AsString(),
R.string.title_fri.AsString(),
R.string.title_sat.AsString(),
)
//TODO Сделать сворачивание календаря
val expanded = remember {
mutableStateOf(true)
}
Card(
backgroundColor = white,
modifier = Modifier.defaultMinSize(minWidth = 300.dp),
shape = RoundedCornerShape(10.dp),
elevation = 5.dp
){
Column(
modifier = Modifier.padding(0.dp)
) {
/*LazyRow(
horizontalArrangement = Arrangement.SpaceBetween,
modifier = Modifier
.padding(10.dp, 10.dp, 10.dp, 5.dp)
.defaultMinSize(minWidth = 300.dp)
){
items(listOfDays){
Text(
text = it,
style = MainText,
color = dark
)
}
}
Box(
Modifier
.defaultMinSize(minWidth = 320.dp)
.height(1.dp)
.background(Color.Black))*/
LazyVerticalGrid(
columns = GridCells.Fixed(count = 6),
horizontalArrangement = Arrangement.spacedBy(0.dp),
){
items(listOfDays){
Text(
text = it,
style = MainText,
color = dark
)
}
items((1..30).toList()){
NumberOnCalendar(
isClicked = remember { mutableStateOf(false) },
number = it.toString()
) {
}
}
}
val offset = 8 - getMonthDaysBy(year, month, DayOfWeek.MONDAY)[0]
val clicked = mutableListOf<MutableState<Boolean>>()
}
}
}
@Composable
fun CardCalendar(
month: Month,
year: Int,
onClick: (day: Int) -> Unit,
) {
val listOfDays = listOf(
R.string.title_mon.AsString(),
R.string.title_tue.AsString(),
R.string.title_wed.AsString(),
R.string.title_thu.AsString(),
R.string.title_fri.AsString(),
R.string.title_sat.AsString(),
)
//TODO Сделать сворачивание календаря
val expanded = remember {
mutableStateOf(true)
}
Card(
backgroundColor = white,
modifier = Modifier.defaultMinSize(minWidth = 200.dp),
shape = RoundedCornerShape(10.dp),
elevation = 5.dp
){
Box(
modifier = Modifier
.fillMaxWidth()
.padding(15.dp)
){
Column(
modifier = Modifier.fillMaxWidth()
) {
Row(
horizontalArrangement = Arrangement.SpaceBetween,
modifier = Modifier
.fillMaxWidth()
.padding(10.dp, 0.dp, 10.dp, 5.dp)
){
for(day in listOfDays){
Text(
text = day,
style = MainText,
color = dark
)
}
}
Divider(
thickness = 1.dp,
color = dark,
modifier = Modifier.padding(0.dp, 0.dp, 0.dp, 10.dp)
)
val offset = 8 - getMonthDaysBy(year, month, DayOfWeek.MONDAY)[0]
val clicked = mutableListOf<MutableState<Boolean>>()
var lastClicked = 0
var lastInd = 0
Row(
horizontalArrangement = Arrangement.SpaceBetween,
modifier = Modifier
.fillMaxWidth()
.padding(0.dp, 10.dp, 0.dp, 5.dp)
) {
if(expanded.value)
for(day in DayOfWeek.values()){
if(day != DayOfWeek.SUNDAY) Column {
val list = getMonthDaysBy(year, month, day)
var len = 0
if(day.ordinal + 1 <= offset && offset !in 6..7){
EmptyNumberOnCalendar()
len++
}
for(i in list.indices){
val data = list[i]
val isClicked = remember { mutableStateOf(false) }
clicked.add(isClicked)
NumberOnCalendar(
isClicked = isClicked,
number = data.toString()
) {
expanded.value != expanded.value
lastClicked = data
lastInd = i
for(click in clicked)
if(click != isClicked)
click.value = false
onClick.invoke(data)
}
len++
}
if(day.ordinal + 1 > offset && len < 5){
EmptyNumberOnCalendar()
}
}
}
else{
}
}
}
}
}
}
@Composable
fun EmptyNumberOnCalendar(){
NumberOnCalendar(isClicked = remember {
mutableStateOf(false)
}, number = "") {}
}
@Composable
fun NumberOnCalendar(
isClicked: MutableState<Boolean>,
number: String,
onClick: () -> Unit
) {
val isClickedModifier = if(isClicked.value)
Modifier
.border(
width = 1.dp,
color = mainBlue,
shape = RoundedCornerShape(20.dp)
)
.background(
color = lightGray,
shape = RoundedCornerShape(20.dp)
)
.padding(2.dp)
else Modifier
Box(
modifier = Modifier
.size(30.dp)
.clickable(
interactionSource = remember { MutableInteractionSource() },
indication = rememberRipple(radius = 15.dp, color = dark),
onClick = {
if (number != "") {
isClicked.value = !isClicked.value
onClick.invoke()
}
}
)
.then(isClickedModifier),
contentAlignment = Alignment.Center,
){
Text(
text = number,
style = H2,
color = dark,
)
}
}
@Composable
fun MonthToggle(
startMonth: Month,
startYear: Int,
onClick: (day: Int) -> Unit
) {
var listOfMonth = listOf(
R.string.title_january.AsString(),
R.string.title_february.AsString(),
R.string.title_march.AsString(),
R.string.title_april.AsString(),
R.string.title_may.AsString(),
R.string.title_june.AsString(),
R.string.title_july.AsString(),
R.string.title_august.AsString(),
R.string.title_september.AsString(),
R.string.title_october.AsString(),
R.string.title_november.AsString(),
R.string.title_december.AsString()
)
val month = remember {
mutableStateOf(startMonth)
}
val year = remember {
mutableStateOf(startYear)
}
val configuration = LocalConfiguration.current
val screenWidth = configuration.screenWidthDp
var defaultPadding = 35.dp
val isNormal = screenWidth < 500
if(!isNormal) defaultPadding *= 4
Column() {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(0.dp, 20.dp),
horizontalArrangement = Arrangement.Center
) {
Row(
horizontalArrangement = Arrangement.spacedBy(10.dp),
verticalAlignment = Alignment.CenterVertically
) {
IconButton(onClick = {
var ind = month.value.ordinal - 1
if(ind == -1){
ind = 11
year.value = year.value - 1
}
month.value = Month.values()[ind]
}) {
Image(
painter = R.drawable.ic_month_swipe_left.AsPainter(),
contentDescription = "left",
alignment = Alignment.Center
)
}
Text(
text = "${listOfMonth[month.value.ordinal]} ${year.value}",
style = H1,
color = dark
)
IconButton(
onClick = {
var ind = month.value.ordinal + 1
if(ind == 12){
ind = 0
year.value = year.value + 1
}
month.value = Month.values()[ind]
}
) {
Image(
painter = R.drawable.ic_month_swipe_right.AsPainter(),
contentDescription = "right",
alignment = Alignment.Center
)
}
}
}
CardCalendar(
month = month.value,
year = year.value,
onClick = onClick
)
}
}
@Composable @Composable
fun UnderlinedText( fun UnderlinedText(
text: String text: String
@@ -0,0 +1,158 @@
package ru.megboyzz.dnevnik.screens.ui
import androidx.compose.foundation.Image
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import ru.megboyzz.dnevnik.*
import ru.megboyzz.dnevnik.ui.theme.Big
import ru.megboyzz.dnevnik.ui.theme.MainText
import ru.megboyzz.dnevnik.ui.theme.Mini
import ru.megboyzz.dnevnik.ui.theme.dark
import ru.megboyzz.dnevnik.R
@Composable
fun LoginScreenContent(
login: MutableState<String>,
password: MutableState<String>,
isError: MutableState<Boolean>,
isRememberMe: MutableState<Boolean>,
onSignIn: () -> Unit,
onSignUp: () -> Unit,
onForgetPassword: () -> Unit
) {
val configuration = LocalConfiguration.current
val screenWidth = configuration.screenWidthDp
var defaultPadding = 65.dp
val isNormal = screenWidth < 500
Box(Modifier.fillMaxSize()) {
if(!isNormal) BigLoginBackground()
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.fillMaxWidth()
) {
if (isNormal) LoginBackground()
else {
defaultPadding *= 4
}
Row(horizontalArrangement = Arrangement.Center) {
Text(
text = R.string.title_welcome.AsString(),
style = Big,
textAlign = TextAlign.Center,
modifier = Modifier.padding(defaultPadding, 20.dp, defaultPadding, 40.dp),
color = dark
)
}
Column(
modifier = Modifier.padding(defaultPadding, 0.dp)
) {
Column(Modifier.fillMaxWidth()) {
MainTextField(
value = login,
label = R.string.title_login.AsString(),
isError = isError
)
SpacerHeight(15.dp)
MainTextField(
value = password,
keyboardType = KeyboardType.Password,
label = R.string.title_password.AsString(),
isError = isError
)
}
SpacerHeight(5.dp)
Row(
modifier = Modifier
.fillMaxWidth()
.height(30.dp),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Row(
modifier = Modifier.fillMaxHeight(),
verticalAlignment = Alignment.CenterVertically
) {
MainCheckbox(isRememberMe) { }
SpacerWidth(5.dp)
Text(
text = R.string.title_remember_me.AsString(),
style = MainText,
color = dark
)
}
Text(
text = R.string.title_forget_password.AsString(),
style = MainText,
color = dark,
modifier = Modifier.clickable(onClick = onForgetPassword)
)
}
Column(
modifier = Modifier
.fillMaxSize()
.padding(0.dp, 10.dp),
verticalArrangement = Arrangement.Center
) {
MainButton(
text = R.string.title_sign_in.AsString(),
onClick = onSignIn
)
SpacerHeight(5.dp)
Text(
text = R.string.title_sign_up.AsString(),
modifier = Modifier
.clickable(onClick = onSignUp)
.padding(5.dp)
.fillMaxWidth(),
textAlign = TextAlign.Center,
style = Mini,
color = dark
)
}
}
}
}
}
@Composable
fun LoginBackground() {
val icon = R.drawable.ic_header.AsPainter()
val size = icon.intrinsicSize
Column {
Image(
painter = icon,
contentDescription = "",
modifier = Modifier.fillMaxWidth(),
contentScale = ContentScale.FillWidth,
alignment = Alignment.TopStart
)
}
}
@Composable
fun BigLoginBackground() {
val icon = R.drawable.header_big.AsPainter()
Column(Modifier.fillMaxWidth()) {
Image(
painter = icon,
contentDescription = "",
modifier = Modifier.fillMaxWidth(),
alignment = Alignment.TopStart
)
}
}
@@ -0,0 +1,78 @@
package ru.megboyzz.dnevnik.screens.ui
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.padding
import androidx.compose.material.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Menu
import androidx.compose.runtime.Composable
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.navigation.NavController
import kotlinx.coroutines.launch
import ru.megboyzz.dnevnik.SpacerWidth
import ru.megboyzz.dnevnik.ui.theme.mainBlue
import ru.megboyzz.dnevnik.ui.theme.white
@Composable
fun MainScaffold(
icon: Painter,
title: String,
/* TODO viewModel */
navController: NavController,
scaffoldState: ScaffoldState,
content: (@Composable (it: PaddingValues) -> Unit),
) {
val scope = rememberCoroutineScope()
Scaffold(
scaffoldState = scaffoldState,
topBar = {
TopAppBar(
backgroundColor = mainBlue,
contentColor = Color.White
) {
IconButton(
onClick = {
val drawerState = scaffoldState.drawerState
scope.launch {
if (drawerState.isClosed)
drawerState.open()
else
drawerState.close()
}
}
) {
Icon(
imageVector = Icons.Filled.Menu,
contentDescription = "menu",
tint = white
)
}
SpacerWidth(width = 5.dp)
Text(
text = title,
fontSize = 16.sp,
color = white
)
Spacer(Modifier.weight(1f))
Box(Modifier.padding(15.dp, 15.dp)) {
Image(painter = icon, contentDescription = "icon")
}
}
},
content = content,
drawerBackgroundColor = mainBlue,
drawerContentColor = white,
drawerShape = drawerShape,
drawerContent = { DrawerContent(navController, scaffoldState) },
bottomBar = { BottomBar(navController) }
)
}
@@ -8,7 +8,7 @@ import androidx.compose.foundation.rememberScrollState
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.* import androidx.compose.material.*
import androidx.compose.runtime.Composable import androidx.compose.runtime.*
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
@@ -16,6 +16,10 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.google.accompanist.navigation.animation.rememberAnimatedNavController import com.google.accompanist.navigation.animation.rememberAnimatedNavController
import ru.megboyzz.dnevnik.screens.ui.* import ru.megboyzz.dnevnik.screens.ui.*
import ru.megboyzz.dnevnik.screens.ui.calendar.NiceCalendar
import ru.megboyzz.dnevnik.screens.ui.piechart.PieChart
import ru.megboyzz.dnevnik.screens.ui.piechart.PieChartCard
import ru.megboyzz.dnevnik.screens.ui.piechart.PieChartData
import ru.megboyzz.dnevnik.ui.theme.mainBlue import ru.megboyzz.dnevnik.ui.theme.mainBlue
import ru.megboyzz.dnevnik.ui.theme.white import ru.megboyzz.dnevnik.ui.theme.white
import java.time.YearMonth import java.time.YearMonth
@@ -103,16 +107,6 @@ fun BaseCardPrev() {
} }
} }
@Preview
@Composable
fun MonthTglPrev() {
MonthToggle(
startMonth = Month.January, startYear = 2023
){
}
}
@Preview @Preview
@Composable @Composable
fun UnderlinedTextPrev() { fun UnderlinedTextPrev() {
@@ -217,22 +211,16 @@ fun AllMarksCardPrev1() {
} }
} }
@Preview
@Composable
fun NewCalendarPrev() {
NewCardCalendar(
month = Month.January,
year = 2023
){
}
}
@Preview @Preview
@Composable @Composable
fun NiceCalendarPrev() { fun NiceCalendarPrev() {
var startMonth by remember{
mutableStateOf(YearMonth.now())
}
NiceCalendar( NiceCalendar(
startMonth = YearMonth.now() currentMonth = startMonth,
){ day, month, year -> ){ day, month, year ->
} }
@@ -0,0 +1,89 @@
package ru.megboyzz.dnevnik.screens.ui
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.horizontalScroll
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Button
import androidx.compose.material.ButtonDefaults
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.navigation.NavController
import ru.megboyzz.dnevnik.navigate
import ru.megboyzz.dnevnik.navigation.BaseNavRote
import ru.megboyzz.dnevnik.ui.theme.MainText
import ru.megboyzz.dnevnik.ui.theme.dark
import ru.megboyzz.dnevnik.ui.theme.mainBlue
import ru.megboyzz.dnevnik.ui.theme.white
@Composable
fun SubScreenNavButton(
text: String,
isClicked: MutableState<Boolean>,
onCLick: () -> Unit
) {
val colors = ButtonDefaults.buttonColors(
backgroundColor = if(isClicked.value) mainBlue else white,
contentColor = if(isClicked.value) white else dark
)
Button(
onClick = {
isClicked.value = !isClicked.value
onCLick.invoke()
},
shape = RoundedCornerShape(20.dp),
border = BorderStroke(
width = 1.dp,
color = mainBlue,
),
colors = colors,
) {
Text(
text = text,
style= MainText
)
}
}
data class SubScreenData(
val title: String,
val to: BaseNavRote,
val isClicked: MutableState<Boolean>
)
@Composable
fun SubScreenNavBar(
list: List<SubScreenData>,
subScreenNavController: NavController
) {
val horizontalScroll = rememberScrollState()
Row(
modifier = Modifier
.fillMaxWidth()
.horizontalScroll(horizontalScroll)
.padding(15.dp),
horizontalArrangement = Arrangement.spacedBy(15.dp)
){
for(data in list){
if(data.isClicked.value)
subScreenNavController.navigate(data.to)
SubScreenNavButton(
text = data.title,
isClicked = data.isClicked
) {
for(d in list){
if(data != d)
d.isClicked.value = false
}
}
}
}
}
@@ -0,0 +1,259 @@
package ru.megboyzz.dnevnik.screens.ui.calendar
import android.util.Log
import androidx.compose.foundation.*
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.*
import androidx.compose.runtime.*
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.graphics.painter.Painter
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import com.kizitonwose.calendar.compose.HorizontalCalendar
import com.kizitonwose.calendar.compose.WeekCalendar
import com.kizitonwose.calendar.compose.rememberCalendarState
import com.kizitonwose.calendar.compose.weekcalendar.rememberWeekCalendarState
import com.kizitonwose.calendar.core.*
import kotlinx.coroutines.launch
import ru.megboyzz.dnevnik.*
import ru.megboyzz.dnevnik.R
import ru.megboyzz.dnevnik.ui.theme.*
import java.time.DayOfWeek
import java.time.LocalDate
import java.time.Month
import java.time.YearMonth
import java.time.format.TextStyle
import java.util.*
//TODO доделать свертку календаря, он почти идеально работает
@Composable
fun NiceCalendar(
currentMonth: YearMonth,
onClick: (day: CalendarDay, month: YearMonth, year: Int) -> Unit
) {
val selections = remember { mutableStateListOf<CalendarDay>() }
val daysOfWeek = remember { daysOfWeek() }
val state = rememberCalendarState(
startMonth = startMonth,
endMonth = endMonth,
firstVisibleMonth = currentMonth,
firstDayOfWeek = daysOfWeek.first()
)
val weekState = rememberWeekCalendarState(
startDate = currentMonth.atDay(1),
endDate = currentMonth.atDay(7),
firstVisibleWeekDate = currentMonth.atDay(1),
firstDayOfWeek = daysOfWeek.first()
)
var selectedDate by remember { mutableStateOf<LocalDate?>(null) }
val coroutineScope = rememberCoroutineScope()
val visibleMonth = rememberFirstMostVisibleMonth(state, viewportPercent = 90f)
Column {
SimpleCalendarTitle(
currentMonth = visibleMonth.yearMonth,
goToPrevious = {
coroutineScope.launch {
state.animateScrollToMonth(state.firstVisibleMonth.yearMonth.previousMonth)
}
},
goToNext = {
coroutineScope.launch {
state.animateScrollToMonth(state.firstVisibleMonth.yearMonth.nextMonth)
}
}
)
Card(
shape = RoundedCornerShape(10.dp),
modifier = Modifier.defaultMinSize(300.dp)
) {
if(selectedDate == null) {
HorizontalCalendar(
state = state,
dayContent = { day ->
Day(day, isSelected = selectedDate == day.date) { day ->
selectedDate = if (selectedDate == day.date) null else day.date
onClick(day, currentMonth, currentMonth.year)
}
},
monthHeader = { DaysOfWeekTitle(daysOfWeek = DayOfWeek.values().asList()) },
modifier = Modifier.padding(10.dp)
)
}
else {
//TODO по возможности устранить повторы
WeekCalendar(
state = weekState,
weekHeader = { _ ->
DaysOfWeekTitle(daysOfWeek = DayOfWeek.values().asList())
},
dayContent = { day ->
Day(
CalendarDay(day.date, DayPosition.InDate),
isSelected = selectedDate == day.date
) { calendarDay ->
selectedDate = if (selectedDate == calendarDay.date) null else calendarDay.date
onClick(calendarDay, currentMonth, currentMonth.year)
}
},
modifier = Modifier.padding(10.dp)
)
}
}
}
}
@Composable
fun CalendarNavigationIcon(
icon: Painter,
contentDescription: String,
onClick: () -> Unit,
) = Box(
modifier = Modifier
.size(35.dp)
.aspectRatio(1f)
.clip(shape = CircleShape)
.clickable(role = Role.Button, onClick = onClick),
) {
Icon(
modifier = Modifier
.fillMaxSize()
.padding(4.dp)
.align(Alignment.Center),
painter = icon,
contentDescription = contentDescription,
)
}
@Composable
fun SimpleCalendarTitle(
modifier: Modifier = Modifier,
currentMonth: YearMonth,
goToPrevious: () -> Unit,
goToNext: () -> Unit,
) {
val listOfMonth = listOf(
R.string.title_january.AsString(),
R.string.title_february.AsString(),
R.string.title_march.AsString(),
R.string.title_april.AsString(),
R.string.title_may.AsString(),
R.string.title_june.AsString(),
R.string.title_july.AsString(),
R.string.title_august.AsString(),
R.string.title_september.AsString(),
R.string.title_october.AsString(),
R.string.title_november.AsString(),
R.string.title_december.AsString()
)
Box(
modifier = Modifier.fillMaxWidth().padding(10.dp),
contentAlignment = Alignment.Center,
) {
Row(
modifier = modifier
.height(40.dp)
.padding(vertical = 0.dp),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(10.dp)
) {
CalendarNavigationIcon(
icon = R.drawable.ic_month_swipe_left.AsPainter(),
contentDescription = "Previous",
onClick = goToPrevious,
)
Text(
text = currentMonth.displayText(listOfMonth),
style = H1,
color = dark
)
CalendarNavigationIcon(
icon = R.drawable.ic_month_swipe_right.AsPainter(),
contentDescription = "Next",
onClick = goToNext,
)
}
}
}
fun YearMonth.displayText(list: List<String>): String {
return "${list[this.month.ordinal]} ${this.year}"
}
fun Month.displayText(short: Boolean = true): String {
val style = if (short) TextStyle.SHORT else TextStyle.FULL_STANDALONE
return getDisplayName(style, Locale.getDefault())
}
fun DayOfWeek.displayText(uppercase: Boolean = false): String {
return getDisplayName(TextStyle.SHORT, Locale.getDefault()).let { value ->
if (uppercase) value.uppercase(Locale.getDefault()) else value
}
}
@Composable
fun DaysOfWeekTitle(daysOfWeek: List<DayOfWeek>) {
Column {
Row(modifier = Modifier.fillMaxWidth()) {
for (dayOfWeek in daysOfWeek) {
Text(
modifier = Modifier.weight(1f),
textAlign = TextAlign.Center,
text = dayOfWeek.getDisplayName(TextStyle.SHORT, Locale.getDefault()).uppercase(),
style = MainText
)
}
}
Divider(
thickness = 1.dp,
color = dark,
modifier = Modifier.padding(vertical = 10.dp)
)
}
}
@Composable
fun Day(day: CalendarDay, isSelected: Boolean, onClick: (CalendarDay) -> Unit) {
Box(
modifier = Modifier
.aspectRatio(ratio = 1f) // This is important for square sizing!
.clip(CircleShape)
.background(color = if (isSelected) lightGray else Color.Transparent)
.border(
border = BorderStroke(
width = 1.dp,
color = if (isSelected) mainBlue else Color.Transparent
),
shape = CircleShape
)
.clickable(
enabled = day.position == DayPosition.MonthDate,
onClick = { onClick(day) }
),
contentAlignment = Alignment.Center
) {
Text(
text = day.date.dayOfMonth.toString(),
style = MainText,
color = if (day.position == DayPosition.MonthDate) dark else Color.Gray
)
}
}
@@ -0,0 +1,8 @@
package ru.megboyzz.dnevnik.screens.ui.calendar
import java.time.YearMonth
//Константы для календаря
val startMonth = YearMonth.of(2009, 9)
val endMonth = YearMonth.of(2100, 9)
@@ -1,8 +1,7 @@
package ru.megboyzz.dnevnik.screens.ui package ru.megboyzz.dnevnik.screens.ui.piechart
import android.content.Context import android.content.Context
import android.graphics.Typeface import android.graphics.Typeface
import android.view.ViewGroup
import android.widget.LinearLayout import android.widget.LinearLayout
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.toArgb import androidx.compose.ui.graphics.toArgb
@@ -12,7 +11,6 @@ import com.github.mikephil.charting.data.PieData
import com.github.mikephil.charting.data.PieDataSet import com.github.mikephil.charting.data.PieDataSet
import com.github.mikephil.charting.data.PieEntry import com.github.mikephil.charting.data.PieEntry
import com.github.mikephil.charting.formatter.PercentFormatter import com.github.mikephil.charting.formatter.PercentFormatter
import ru.megboyzz.dnevnik.ui.theme.MainText
class DataPieChart(context: Context) : PieChart(context) { class DataPieChart(context: Context) : PieChart(context) {
@@ -1,4 +1,4 @@
package ru.megboyzz.dnevnik.screens.ui package ru.megboyzz.dnevnik.screens.ui.piechart
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.*
import androidx.compose.material.Text import androidx.compose.material.Text
@@ -12,6 +12,8 @@ import ru.megboyzz.dnevnik.AsString
import ru.megboyzz.dnevnik.ui.theme.H2 import ru.megboyzz.dnevnik.ui.theme.H2
import ru.megboyzz.dnevnik.ui.theme.dark import ru.megboyzz.dnevnik.ui.theme.dark
import ru.megboyzz.dnevnik.R import ru.megboyzz.dnevnik.R
import ru.megboyzz.dnevnik.screens.ui.BaseCard
import ru.megboyzz.dnevnik.screens.ui.EmptyMessage
/** /**
* Класс для предоставления данных для круговых диаграм * Класс для предоставления данных для круговых диаграм
@@ -8,12 +8,4 @@ import java.time.DayOfWeek
class UtilsTest { class UtilsTest {
@Test
fun testForDaysFunc(){
val days = getMonthDaysBy(2023, Month.January, DayOfWeek.MONDAY)
assertEquals(
listOf(2, 9, 16, 23, 30),
days
)
}
} }