diff --git a/app/build.gradle b/app/build.gradle index d514e8a..7998b29 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -4,7 +4,7 @@ plugins { } android { - compileSdk 32 + compileSdk 33 defaultConfig { applicationId "ru.megboyzz.dnevnik" @@ -17,6 +17,7 @@ android { vectorDrawables { useSupportLibrary true } + multiDexEnabled true } buildTypes { @@ -32,6 +33,7 @@ android { } kotlinOptions { jvmTarget = '1.8' + freeCompilerArgs = ['-Xjvm-default=compatibility'] } buildFeatures { compose true @@ -75,4 +77,10 @@ dependencies { //Библиотечка для рисования круговых диаграмок implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + + //LazyHorizontalGrid + implementation 'androidx.compose.foundation:foundation:1.3.1' + + // The compose calendar library + implementation 'com.kizitonwose.calendar:compose:2.1.1' } \ No newline at end of file diff --git a/app/src/main/java/ru/megboyzz/dnevnik/MainActivity.kt b/app/src/main/java/ru/megboyzz/dnevnik/MainActivity.kt index 734ac71..b2dbe24 100644 --- a/app/src/main/java/ru/megboyzz/dnevnik/MainActivity.kt +++ b/app/src/main/java/ru/megboyzz/dnevnik/MainActivity.kt @@ -11,6 +11,7 @@ import ru.megboyzz.dnevnik.navigation.AppNavHost import ru.megboyzz.dnevnik.ui.theme.* class MainActivity : ComponentActivity() { + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) diff --git a/app/src/main/java/ru/megboyzz/dnevnik/Previews.kt b/app/src/main/java/ru/megboyzz/dnevnik/Previews.kt deleted file mode 100644 index c683c6a..0000000 --- a/app/src/main/java/ru/megboyzz/dnevnik/Previews.kt +++ /dev/null @@ -1,131 +0,0 @@ -package ru.megboyzz.dnevnik - -import androidx.compose.animation.ExperimentalAnimationApi -import androidx.compose.foundation.BorderStroke -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.* -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.Card -import androidx.compose.material.Text -import androidx.compose.material.rememberScaffoldState -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import com.google.accompanist.navigation.animation.rememberAnimatedNavController -import ru.megboyzz.dnevnik.screens.ui.* -import ru.megboyzz.dnevnik.ui.theme.mainBlue -import ru.megboyzz.dnevnik.ui.theme.white - -//Файл со всеми превьюшками - -@Preview -@Composable -fun text() { - Row(Modifier.fillMaxWidth()) { - AlmostOutlinedText(text = "Здарова карова") - } -} - -@OptIn(ExperimentalAnimationApi::class) -@Preview -@Composable -fun DrawerPrev() { - val scaffoldState = rememberScaffoldState() - val navController = rememberAnimatedNavController() - Box(Modifier.background(mainBlue)) { - DrawerContent(navController = navController, scaffoldState = scaffoldState) - } - -} - - -@Preview -@Composable -fun CardWithAveragePrev() { - CardWithAverage( - averageMark = 4.33f, - resultMark = 4f - ) { - Box(Modifier.padding(10.dp)){ - Text("hehe") - } - } -} - -@Preview -@Composable -fun BaseCardPrev() { - Box( - Modifier - .fillMaxSize() - ){ - Column( - verticalArrangement = Arrangement.spacedBy(10.dp), - horizontalAlignment = Alignment.CenterHorizontally, - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 20.dp) - ) { - - Card( - backgroundColor = white, - shape = RoundedCornerShape(10.dp), - border = BorderStroke( - width = 1.dp, - color = mainBlue - ), - modifier = Modifier.defaultMinSize(minWidth = 300.dp) - ) { - Box( - Modifier - .size(50.dp) - .background(Color.Red)){} - } - } - } -} - -@Preview -@Composable -fun MonthTglPrev() { - MonthToggle( - startMonth = Month.January, startYear = 2023 - ){ - - } -} - -@Preview -@Composable -fun UnderlinedTextPrev() { - Box(Modifier.background(white)){ - UnderlinedText(text = "Общая сводка") - } -} - -@Preview -@Composable -fun CirclePrev() { - val list = listOf( - PieChartData(legend = "История", value=5), - PieChartData(legend = "Русский язык", value=4), - PieChartData(legend = "Химия", value=1), - PieChartData(legend = "Математика", value=3) - ) - PieChart(list) -} - -@Preview -@Composable -fun GoodPieChartPrev() { - val list = listOf( - PieChartData(legend = "История", value=5), - PieChartData(legend = "Русский язык", value=4), - PieChartData(legend = "Химия", value=1), - PieChartData(legend = "Математика", value=3), - ) - PieChart(diagramData = list) -} \ No newline at end of file diff --git a/app/src/main/java/ru/megboyzz/dnevnik/Utils.kt b/app/src/main/java/ru/megboyzz/dnevnik/Utils.kt index d664083..b84f2d8 100644 --- a/app/src/main/java/ru/megboyzz/dnevnik/Utils.kt +++ b/app/src/main/java/ru/megboyzz/dnevnik/Utils.kt @@ -31,6 +31,7 @@ import java.time.DayOfWeek import java.time.LocalDate import java.time.Year import java.time.temporal.TemporalAdjusters +import java.util.* @Composable fun Int.AsPainter() = painterResource(this) @@ -136,3 +137,5 @@ fun Modifier.mainClickable( ), onClick = onClick ) + + diff --git a/app/src/main/java/ru/megboyzz/dnevnik/screens/LoginScreen.kt b/app/src/main/java/ru/megboyzz/dnevnik/screens/LoginScreen.kt index 57dc51d..295740c 100644 --- a/app/src/main/java/ru/megboyzz/dnevnik/screens/LoginScreen.kt +++ b/app/src/main/java/ru/megboyzz/dnevnik/screens/LoginScreen.kt @@ -7,6 +7,7 @@ import androidx.navigation.NavController import ru.megboyzz.dnevnik.navigation.AppNavRoute import ru.megboyzz.dnevnik.screens.ui.LoginScreenContent +//TODO Переверстать экран входа @Composable fun LoginScreen(navController: NavController) { diff --git a/app/src/main/java/ru/megboyzz/dnevnik/screens/ui/Calendar.kt b/app/src/main/java/ru/megboyzz/dnevnik/screens/ui/Calendar.kt new file mode 100644 index 0000000..7fb3005 --- /dev/null +++ b/app/src/main/java/ru/megboyzz/dnevnik/screens/ui/Calendar.kt @@ -0,0 +1,206 @@ +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 + ) + } + } + } +} + + +@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(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 = { month -> + DaysOfWeekTitle(daysOfWeek = DayOfWeek.values().asList()) + }, + modifier = Modifier.padding(10.dp) + ) + else + 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) { + 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 + ) + } +} diff --git a/app/src/main/java/ru/megboyzz/dnevnik/screens/ui/Components.kt b/app/src/main/java/ru/megboyzz/dnevnik/screens/ui/Components.kt index e54ba84..cc27c38 100644 --- a/app/src/main/java/ru/megboyzz/dnevnik/screens/ui/Components.kt +++ b/app/src/main/java/ru/megboyzz/dnevnik/screens/ui/Components.kt @@ -1,11 +1,13 @@ package ru.megboyzz.dnevnik.screens.ui -import android.annotation.SuppressLint import androidx.compose.animation.* import androidx.compose.animation.core.tween import androidx.compose.foundation.* import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.* +import androidx.compose.foundation.lazy.grid.GridCells +import androidx.compose.foundation.lazy.grid.LazyVerticalGrid +import androidx.compose.foundation.lazy.grid.items import androidx.compose.foundation.selection.toggleable import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.text.KeyboardOptions @@ -24,9 +26,6 @@ import androidx.compose.ui.draw.clip import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.focusRequester import androidx.compose.ui.focus.onFocusChanged -import androidx.compose.ui.geometry.CornerRadius -import androidx.compose.ui.geometry.RoundRect -import androidx.compose.ui.geometry.Size import androidx.compose.ui.graphics.* import androidx.compose.ui.graphics.painter.Painter import androidx.compose.ui.layout.ContentScale @@ -38,11 +37,9 @@ import androidx.compose.ui.text.input.PasswordVisualTransformation import androidx.compose.ui.text.input.VisualTransformation import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextOverflow -import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.* import androidx.compose.ui.viewinterop.AndroidView import androidx.navigation.NavController -import com.google.accompanist.navigation.animation.rememberAnimatedNavController import kotlinx.coroutines.launch import ru.megboyzz.dnevnik.* import ru.megboyzz.dnevnik.R @@ -177,7 +174,10 @@ fun BottomNavButton( onClick: () -> Unit, ) { //Возможно стоит убрать анимацию клика - Box(Modifier.mainClickable(onClick = onClick, radius = 20.dp).padding(10.dp)) { + Box( + Modifier + .mainClickable(onClick = onClick, radius = 20.dp) + .padding(10.dp)) { Column( horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center @@ -655,8 +655,8 @@ fun AverageText( @Composable fun CardWithAverage( - averageMark: Float, - resultMark: Float, + averageMark: Float?, + resultMark: Float?, minWidth: Dp = 300.dp, content: @Composable () -> Unit ) { @@ -673,7 +673,10 @@ fun CardWithAverage( modifier = Modifier.size(50.dp), contentAlignment = Alignment.Center ) { - AverageText(title = R.string.title_average_mark.AsString(), mark = averageMark.toString()) + AverageText( + title = R.string.title_average_mark.AsString(), + mark = if(averageMark != null) "%.2f".format(averageMark).replace(",", ".") else "-" + ) } } Box( @@ -686,7 +689,7 @@ fun CardWithAverage( ){ AverageText( title = R.string.title_result_mark.AsString(), - mark = resultMark.toString() + mark = if(resultMark != null) resultMark.toString() else "-" ) } } @@ -701,15 +704,7 @@ fun LastMarkCard( teacher: String, reason: String = "null" ) { - Card( - backgroundColor = white, - shape = RoundedCornerShape(10.dp), - border = BorderStroke( - width = 1.dp, - color = mainBlue - ), - modifier = Modifier.fillMaxWidth() - ) { + BaseCard { Row( horizontalArrangement = Arrangement.SpaceBetween, modifier = Modifier.padding(15.dp) @@ -766,6 +761,84 @@ enum class Month{ 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>() + } + } +} + @Composable fun CardCalendar( month: Month, @@ -785,11 +858,10 @@ fun CardCalendar( val expanded = remember { mutableStateOf(true) } - val expandedModifier = if(expanded.value) Modifier else Modifier.height(100.dp) Card( backgroundColor = white, - modifier = Modifier.fillMaxWidth(), + modifier = Modifier.defaultMinSize(minWidth = 200.dp), shape = RoundedCornerShape(10.dp), elevation = 5.dp ){ @@ -824,6 +896,8 @@ fun CardCalendar( val offset = 8 - getMonthDaysBy(year, month, DayOfWeek.MONDAY)[0] val clicked = mutableListOf>() + var lastClicked = 0 + var lastInd = 0 Row( horizontalArrangement = Arrangement.SpaceBetween, @@ -831,6 +905,7 @@ fun CardCalendar( .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) @@ -848,6 +923,8 @@ fun CardCalendar( number = data.toString() ) { expanded.value != expanded.value + lastClicked = data + lastInd = i for(click in clicked) if(click != isClicked) click.value = false @@ -860,9 +937,10 @@ fun CardCalendar( } } } + else{ + + } } - - } } } @@ -955,7 +1033,7 @@ fun MonthToggle( val isNormal = screenWidth < 500 if(!isNormal) defaultPadding *= 4 - Column(Modifier.padding(defaultPadding, 0.dp)) { + Column() { Row( modifier = Modifier .fillMaxWidth() @@ -1036,53 +1114,133 @@ fun UnderlinedText( } } -/** - * Класс для предоставления данных для круговых диаграм - * Идея предоставить диаграмме массив именованных данных - * напрмер кол-во оцеок отлично по всем предметам: - * CircleDiagramData(parameterName = "История", count=5) = 38% - * CircleDiagramData(parameterName = "Русский язык", count=4) = 31% - * CircleDiagramData(parameterName = "Химия", count=1) = 8% - * CircleDiagramData(parameterName = "Математика", count=3) = 23% - */ -@OptIn(ExperimentalGraphicsApi::class) -data class PieChartData( - val legend: String, - val value: Int -){ - val color: Color - init { - val hue = (0..360).random(kotlin.random.Random(System.nanoTime())).toFloat() - Thread.sleep(10) - color = Color.hsl(hue, 0.5f, 0.6f) +@Composable +fun AllMarksCard( + subjectName: String, + teacher: String?, + marks: List?, + resultMark: Float? +) { + CardWithAverage( + averageMark = marks?.average()?.toFloat(), + resultMark = resultMark + ) { + Box(Modifier.padding(15.dp, 15.dp)) { + Column { + Row( + horizontalArrangement = Arrangement.spacedBy(10.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Image( + painter = R.drawable.ic_subject.AsPainter(), + contentDescription = "" + ) + Column( + verticalArrangement = Arrangement.Center + ) { + Text( + text = subjectName, + color = dark, + style = MainText, + overflow = TextOverflow.Ellipsis + ) + Text( + text = teacher ?: "-", + color = dark, + style = MainText, + overflow = TextOverflow.Ellipsis + ) + } + } + + Divider( + color = dark, + thickness = 1.dp, + modifier = Modifier.padding( + top = 15.dp, + bottom = 10.dp, + ) + ) + + if(marks != null) + LazyVerticalGrid( + columns = GridCells.Adaptive(minSize = 20.dp), + horizontalArrangement = Arrangement.spacedBy(10.dp), + verticalArrangement = Arrangement.spacedBy(10.dp) + ) { + items(marks){ + MarkInBox(mark = it) + } + } + else { + Box( + contentAlignment = Alignment.Center, + modifier = Modifier.fillMaxWidth() + ){ + EmptyMessage(message = R.string.title_no_marks.AsString()) + } + } + } + } } } @Composable -fun PieChart( - diagramData: List +fun MarkInBox(mark: Int) { + Box( + modifier = Modifier + .size(19.dp) + .fillMaxSize() + .background( + color = mainBlue, + shape = RoundedCornerShape(2.dp) + ), + contentAlignment = Alignment.Center + ){ + Text( + text = mark.toString(), + color = white + ) + } +} + +@Composable +fun ContentMessage( + message: String, + isFine: Boolean = true ) { - lateinit var chart: DataPieChart - Column { - AndroidView( - factory = { context -> - chart = DataPieChart(context) - chart - }, - modifier = Modifier - .wrapContentSize() - .padding(5.dp), - update = { chart.updatePieChartWithData(diagramData) } + Column( + modifier = Modifier + .defaultMinSize(200.dp) + .padding(25.dp), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Image( + painter = if(isFine) R.drawable.ic_smile.AsPainter() else R.drawable.ic_sad_smile.AsPainter(), + contentDescription = "" + ) + SpacerHeight(height = 10.dp) + Text( + text = message, + style = MainText, + color = dark ) } } @Composable -fun PieChartCard( - title: String, - data: List +fun EmptyMessage(message: String) = ContentMessage(message = message, isFine = false) + +@Composable +fun FineMessage(message: String) = ContentMessage(message = message) + +@Composable +fun MessageCard( + message: String, + content: @Composable () -> Unit ) { + BaseCard { -} - + } +} \ No newline at end of file diff --git a/app/src/main/java/ru/megboyzz/dnevnik/screens/ui/DataPieChart.kt b/app/src/main/java/ru/megboyzz/dnevnik/screens/ui/DataPieChart.kt index 29ff8ba..0ce33a6 100644 --- a/app/src/main/java/ru/megboyzz/dnevnik/screens/ui/DataPieChart.kt +++ b/app/src/main/java/ru/megboyzz/dnevnik/screens/ui/DataPieChart.kt @@ -22,9 +22,10 @@ class DataPieChart(context: Context) : PieChart(context) { LayoutParams.MATCH_PARENT, ) setUsePercentValues(true) + setEntryLabelTextSize(10f) + description.isEnabled = false isDrawHoleEnabled = false - legend.isEnabled = false legend.orientation = Legend.LegendOrientation.VERTICAL legend.horizontalAlignment = diff --git a/app/src/main/java/ru/megboyzz/dnevnik/screens/ui/PieChart.kt b/app/src/main/java/ru/megboyzz/dnevnik/screens/ui/PieChart.kt new file mode 100644 index 0000000..e96367b --- /dev/null +++ b/app/src/main/java/ru/megboyzz/dnevnik/screens/ui/PieChart.kt @@ -0,0 +1,82 @@ +package ru.megboyzz.dnevnik.screens.ui + +import androidx.compose.foundation.layout.* +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.unit.dp +import androidx.compose.ui.viewinterop.AndroidView +import ru.megboyzz.dnevnik.AsString +import ru.megboyzz.dnevnik.ui.theme.H2 +import ru.megboyzz.dnevnik.ui.theme.dark +import ru.megboyzz.dnevnik.R + +/** + * Класс для предоставления данных для круговых диаграм + * Идея предоставить диаграмме массив именованных данных + * напрмер кол-во оцеок отлично по всем предметам: + * CircleDiagramData(parameterName = "История", count=5) = 38% + * CircleDiagramData(parameterName = "Русский язык", count=4) = 31% + * CircleDiagramData(parameterName = "Химия", count=1) = 8% + * CircleDiagramData(parameterName = "Математика", count=3) = 23% + */ +data class PieChartData( + val legend: String, + val value: Int +){ + val color: Color + init { + val hue = (0..360).random(kotlin.random.Random(System.nanoTime())).toFloat() + Thread.sleep(10) + color = Color.hsl(hue, 0.5f, 0.6f) + } +} + +@Composable +fun PieChart( + diagramData: List +) { + lateinit var chart: DataPieChart + Column(Modifier.size(200.dp)) { + AndroidView( + factory = { context -> + chart = DataPieChart(context) + chart + }, + modifier = Modifier + .wrapContentSize() + .padding(5.dp), + update = { chart.updatePieChartWithData(diagramData) } + ) + } +} + + +@Composable +fun PieChartCard( + title: String, + data: List? +) { + BaseCard { + Column( + modifier = Modifier.padding(15.dp, 10.dp), + ){ + Text( + text = title, + style = H2, + color = dark + ) + Box( + modifier = Modifier.defaultMinSize(300.dp), + contentAlignment = Alignment.Center + ){ + if(data != null) + PieChart(diagramData = data) + else + EmptyMessage(message = R.string.title_no_marks.AsString()) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/ru/megboyzz/dnevnik/screens/ui/Previews.kt b/app/src/main/java/ru/megboyzz/dnevnik/screens/ui/Previews.kt new file mode 100644 index 0000000..6ec873e --- /dev/null +++ b/app/src/main/java/ru/megboyzz/dnevnik/screens/ui/Previews.kt @@ -0,0 +1,266 @@ +package ru.megboyzz.dnevnik + +import androidx.compose.animation.ExperimentalAnimationApi +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.verticalScroll +import androidx.compose.material.* +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.google.accompanist.navigation.animation.rememberAnimatedNavController +import ru.megboyzz.dnevnik.screens.ui.* +import ru.megboyzz.dnevnik.ui.theme.mainBlue +import ru.megboyzz.dnevnik.ui.theme.white +import java.time.YearMonth +import java.util.* + +//Файл со всеми превьюшками + +@Composable +fun NicePreviewContainer( + content: @Composable () -> Unit +) { + Column( + modifier = Modifier + .fillMaxWidth() + .verticalScroll(rememberScrollState()).height(1500.dp), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy(10.dp) + ) { content() } +} + +@Preview +@Composable +fun text() { + Row(Modifier.fillMaxWidth()) { + AlmostOutlinedText(text = "Здарова карова") + } +} + +@OptIn(ExperimentalAnimationApi::class) +@Preview +@Composable +fun DrawerPrev() { + val scaffoldState = rememberScaffoldState() + val navController = rememberAnimatedNavController() + Box(Modifier.background(mainBlue)) { + DrawerContent(navController = navController, scaffoldState = scaffoldState) + } + +} + + +@Preview +@Composable +fun CardWithAveragePrev() { + CardWithAverage( + averageMark = 4.33f, + resultMark = 4f + ) { + Box(Modifier.padding(10.dp)){ + Text("hehe") + } + } +} + +@Preview +@Composable +fun BaseCardPrev() { + Box( + Modifier + .fillMaxSize() + ){ + Column( + verticalArrangement = Arrangement.spacedBy(10.dp), + horizontalAlignment = Alignment.CenterHorizontally, + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 20.dp) + ) { + + Card( + backgroundColor = white, + shape = RoundedCornerShape(10.dp), + border = BorderStroke( + width = 1.dp, + color = mainBlue + ), + modifier = Modifier.defaultMinSize(minWidth = 300.dp) + ) { + Box( + Modifier + .size(50.dp) + .background(Color.Red)){} + } + } + } +} + +@Preview +@Composable +fun MonthTglPrev() { + MonthToggle( + startMonth = Month.January, startYear = 2023 + ){ + + } +} + +@Preview +@Composable +fun UnderlinedTextPrev() { + Box(Modifier.background(white)){ + UnderlinedText(text = "Общая сводка") + } +} + +@Preview +@Composable +fun CirclePrev() { + val list = listOf( + PieChartData(legend = "История", value=5), + PieChartData(legend = "Русский язык", value=4), + PieChartData(legend = "Химия", value=1), + PieChartData(legend = "Математика", value=3) + ) + PieChart(list) +} + +@Preview +@Composable +fun GoodPieChartPrev() { + val list = listOf( + PieChartData(legend = "История", value=5), + PieChartData(legend = "Русский язык", value=4), + PieChartData(legend = "Химия", value=1), + PieChartData(legend = "Математика", value=3), + ) + PieChart(diagramData = list) +} + +@Preview +@Composable +fun PieChartCardPrev() { + val list = listOf( + PieChartData(legend = "История", value=5), + PieChartData(legend = "Русский язык", value=4), + PieChartData(legend = "Химия", value=1), + PieChartData(legend = "Математика", value=3), + ) + PieChartCard( + title = "Сводка по оценкам отлично", + data = list + ) +} + +@Preview +@Composable +fun LastMarkCardPrev() { + LastMarkCard( + subjectName = "Русский язык", + mark = 5, + date = "18.02.2023", + teacher = "Степанова А.С.", + reason = "контрольная" + ) +} + +@Preview +@Composable +fun AllMarksCardPrev1() { + NicePreviewContainer { + AllMarksCard( + subjectName = "Математика", + teacher = "Степанова С.А.", + marks = listOf(4, 5, 5, 5, 5, 5, 4, 5, 3, 2), + resultMark = 4f + ) + AllMarksCard( + subjectName = "Русский язык", + teacher = "Степанова С.А.", + marks = listOf(4, 5, 5, 5, 5, 5, 4, 5, 3, 2), + resultMark = null + ) + AllMarksCard( + subjectName = "Русский язык", + teacher = "Степанова С.А.", + marks = null, + resultMark = 4.2f + ) + AllMarksCard( + subjectName = "Русский язык", + teacher = null, + marks = listOf(4, 5, 5, 5, 5, 5, 4, 5, 3, 2), + resultMark = 4.2f + ) + + AllMarksCard( + subjectName = "Математика", + teacher = "Степанова С.А.", + marks = null, + resultMark = null + ) + + AllMarksCard( + subjectName = "Математика", + teacher = null, + marks = null, + resultMark = null + ) + } +} + +@Preview +@Composable +fun NewCalendarPrev() { + NewCardCalendar( + month = Month.January, + year = 2023 + ){ + + } +} + +@Preview +@Composable +fun NiceCalendarPrev() { + NiceCalendar( + startMonth = YearMonth.now() + ){ day, month, year -> + + } +} + +@Preview +@Composable +fun EmptyPrev() { + ContentMessage(message = "Таких оценок нет") +} + +@Preview +@Composable +fun PieChartNullPrev() { + val list = listOf( + PieChartData(legend = "История", value=5), + PieChartData(legend = "Русский язык", value=4), + PieChartData(legend = "Химия", value=1), + PieChartData(legend = "Математика", value=3), + ) + NicePreviewContainer { + PieChartCard( + title = "Сводка по оценкам отлично", + data = list + ) + PieChartCard( + title = "Сводка по оценкам хорошо", + data = null + ) + } +}