diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml
index 3892a83..cdcfba2 100644
--- a/.idea/deploymentTargetDropDown.xml
+++ b/.idea/deploymentTargetDropDown.xml
@@ -12,6 +12,6 @@
-
+
\ 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 b2dbe24..e33e501 100644
--- a/app/src/main/java/ru/megboyzz/dnevnik/MainActivity.kt
+++ b/app/src/main/java/ru/megboyzz/dnevnik/MainActivity.kt
@@ -1,5 +1,6 @@
package ru.megboyzz.dnevnik
+import android.content.Context
import android.os.Bundle
import android.window.SplashScreen
import androidx.activity.ComponentActivity
@@ -13,7 +14,6 @@ import ru.megboyzz.dnevnik.ui.theme.*
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
-
super.onCreate(savedInstanceState)
setContent {
Surface(
diff --git a/app/src/main/java/ru/megboyzz/dnevnik/Utils.kt b/app/src/main/java/ru/megboyzz/dnevnik/Utils.kt
index b84f2d8..6395b4e 100644
--- a/app/src/main/java/ru/megboyzz/dnevnik/Utils.kt
+++ b/app/src/main/java/ru/megboyzz/dnevnik/Utils.kt
@@ -7,9 +7,7 @@ import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.width
import androidx.compose.material.ripple.rememberRipple
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.LaunchedEffect
-import androidx.compose.runtime.remember
+import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.drawBehind
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.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.screens.ui.Month
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
fun Int.AsPainter() = painterResource(this)
@@ -110,21 +106,6 @@ fun Modifier.drawColoredShadow(
}
} else this
-fun getMonthDaysBy(year: Int, month: Month, dayOfWeek: DayOfWeek): List{
- var date: LocalDate =
- Year.of(year).atMonth(month.ordinal + 1).atDay(1).with(TemporalAdjusters.firstInMonth(dayOfWeek))
- var mi = date.month
-
- val list = mutableListOf()
-
- while (mi.ordinal == month.ordinal) {
- list.add(date.dayOfMonth)
- date = date.with(TemporalAdjusters.next(dayOfWeek))
- mi = date.month
- }
- return list
-}
-
@Composable
fun Modifier.mainClickable(
radius: Dp = Dp.Unspecified,
@@ -138,4 +119,33 @@ fun Modifier.mainClickable(
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
+ }
+}
diff --git a/app/src/main/java/ru/megboyzz/dnevnik/navigation/AppNavHost.kt b/app/src/main/java/ru/megboyzz/dnevnik/navigation/AppNavHost.kt
index 597edab..b62b542 100644
--- a/app/src/main/java/ru/megboyzz/dnevnik/navigation/AppNavHost.kt
+++ b/app/src/main/java/ru/megboyzz/dnevnik/navigation/AppNavHost.kt
@@ -38,13 +38,6 @@ sealed class AppNavRoute(override val route: String): BaseNavRote(route){
@Composable
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 navController = rememberAnimatedNavController()
diff --git a/app/src/main/java/ru/megboyzz/dnevnik/screens/ui/BottomBar.kt b/app/src/main/java/ru/megboyzz/dnevnik/screens/ui/BottomBar.kt
new file mode 100644
index 0000000..14bfeec
--- /dev/null
+++ b/app/src/main/java/ru/megboyzz/dnevnik/screens/ui/BottomBar.kt
@@ -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
+ )
+ }
+ }
+}
\ No newline at end of file
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
deleted file mode 100644
index b5aa8e6..0000000
--- a/app/src/main/java/ru/megboyzz/dnevnik/screens/ui/Calendar.kt
+++ /dev/null
@@ -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(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) {
- 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 cc27c38..2aef2f5 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
@@ -50,152 +50,10 @@ import java.time.DayOfWeek
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
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
fun MainTextField(
value: MutableState,
@@ -425,180 +255,6 @@ fun MainButton(
}
}
-@Composable
-fun LoginScreenContent(
- login: MutableState,
- password: MutableState,
- isError: MutableState,
- isRememberMe: MutableState,
- 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,
- 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
-)
-
-
-@Composable
-fun SubScreenNavBar(
- list: List,
- 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
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>()
- }
- }
-}
-
-@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>()
- 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,
- 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
fun UnderlinedText(
text: String
diff --git a/app/src/main/java/ru/megboyzz/dnevnik/screens/ui/LoginScreen.kt b/app/src/main/java/ru/megboyzz/dnevnik/screens/ui/LoginScreen.kt
new file mode 100644
index 0000000..f349e40
--- /dev/null
+++ b/app/src/main/java/ru/megboyzz/dnevnik/screens/ui/LoginScreen.kt
@@ -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,
+ password: MutableState,
+ isError: MutableState,
+ isRememberMe: MutableState,
+ 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
+ )
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/ru/megboyzz/dnevnik/screens/ui/MainScaffold.kt b/app/src/main/java/ru/megboyzz/dnevnik/screens/ui/MainScaffold.kt
new file mode 100644
index 0000000..748ff17
--- /dev/null
+++ b/app/src/main/java/ru/megboyzz/dnevnik/screens/ui/MainScaffold.kt
@@ -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) }
+ )
+}
\ 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
index 6ec873e..f247523 100644
--- a/app/src/main/java/ru/megboyzz/dnevnik/screens/ui/Previews.kt
+++ b/app/src/main/java/ru/megboyzz/dnevnik/screens/ui/Previews.kt
@@ -8,7 +8,7 @@ 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.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
@@ -16,6 +16,10 @@ 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.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.white
import java.time.YearMonth
@@ -103,16 +107,6 @@ fun BaseCardPrev() {
}
}
-@Preview
-@Composable
-fun MonthTglPrev() {
- MonthToggle(
- startMonth = Month.January, startYear = 2023
- ){
-
- }
-}
-
@Preview
@Composable
fun UnderlinedTextPrev() {
@@ -217,22 +211,16 @@ fun AllMarksCardPrev1() {
}
}
-@Preview
-@Composable
-fun NewCalendarPrev() {
- NewCardCalendar(
- month = Month.January,
- year = 2023
- ){
-
- }
-}
-
@Preview
@Composable
fun NiceCalendarPrev() {
+
+ var startMonth by remember{
+ mutableStateOf(YearMonth.now())
+ }
+
NiceCalendar(
- startMonth = YearMonth.now()
+ currentMonth = startMonth,
){ day, month, year ->
}
diff --git a/app/src/main/java/ru/megboyzz/dnevnik/screens/ui/SubScreenNavigation.kt b/app/src/main/java/ru/megboyzz/dnevnik/screens/ui/SubScreenNavigation.kt
new file mode 100644
index 0000000..1d76714
--- /dev/null
+++ b/app/src/main/java/ru/megboyzz/dnevnik/screens/ui/SubScreenNavigation.kt
@@ -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,
+ 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
+)
+
+
+@Composable
+fun SubScreenNavBar(
+ list: List,
+ 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
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/ru/megboyzz/dnevnik/screens/ui/calendar/Calendar.kt b/app/src/main/java/ru/megboyzz/dnevnik/screens/ui/calendar/Calendar.kt
new file mode 100644
index 0000000..19b1c6e
--- /dev/null
+++ b/app/src/main/java/ru/megboyzz/dnevnik/screens/ui/calendar/Calendar.kt
@@ -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() }
+ 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(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 {
+ 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) {
+ 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/calendar/CalendarConstants.kt b/app/src/main/java/ru/megboyzz/dnevnik/screens/ui/calendar/CalendarConstants.kt
new file mode 100644
index 0000000..2673879
--- /dev/null
+++ b/app/src/main/java/ru/megboyzz/dnevnik/screens/ui/calendar/CalendarConstants.kt
@@ -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)
\ 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/piechart/DataPieChart.kt
similarity index 93%
rename from app/src/main/java/ru/megboyzz/dnevnik/screens/ui/DataPieChart.kt
rename to app/src/main/java/ru/megboyzz/dnevnik/screens/ui/piechart/DataPieChart.kt
index 0ce33a6..ef51ef6 100644
--- a/app/src/main/java/ru/megboyzz/dnevnik/screens/ui/DataPieChart.kt
+++ b/app/src/main/java/ru/megboyzz/dnevnik/screens/ui/piechart/DataPieChart.kt
@@ -1,8 +1,7 @@
-package ru.megboyzz.dnevnik.screens.ui
+package ru.megboyzz.dnevnik.screens.ui.piechart
import android.content.Context
import android.graphics.Typeface
-import android.view.ViewGroup
import android.widget.LinearLayout
import androidx.compose.ui.graphics.Color
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.PieEntry
import com.github.mikephil.charting.formatter.PercentFormatter
-import ru.megboyzz.dnevnik.ui.theme.MainText
class DataPieChart(context: Context) : PieChart(context) {
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/PieChart.kt
similarity index 94%
rename from app/src/main/java/ru/megboyzz/dnevnik/screens/ui/PieChart.kt
rename to app/src/main/java/ru/megboyzz/dnevnik/screens/ui/piechart/PieChart.kt
index e96367b..929a582 100644
--- a/app/src/main/java/ru/megboyzz/dnevnik/screens/ui/PieChart.kt
+++ b/app/src/main/java/ru/megboyzz/dnevnik/screens/ui/piechart/PieChart.kt
@@ -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.material.Text
@@ -12,6 +12,8 @@ import ru.megboyzz.dnevnik.AsString
import ru.megboyzz.dnevnik.ui.theme.H2
import ru.megboyzz.dnevnik.ui.theme.dark
import ru.megboyzz.dnevnik.R
+import ru.megboyzz.dnevnik.screens.ui.BaseCard
+import ru.megboyzz.dnevnik.screens.ui.EmptyMessage
/**
* Класс для предоставления данных для круговых диаграм
diff --git a/app/src/test/java/ru/megboyzz/dnevnik/UtilsTest.kt b/app/src/test/java/ru/megboyzz/dnevnik/UtilsTest.kt
index 1e13ec9..0ebc180 100644
--- a/app/src/test/java/ru/megboyzz/dnevnik/UtilsTest.kt
+++ b/app/src/test/java/ru/megboyzz/dnevnik/UtilsTest.kt
@@ -8,12 +8,4 @@ import java.time.DayOfWeek
class UtilsTest {
- @Test
- fun testForDaysFunc(){
- val days = getMonthDaysBy(2023, Month.January, DayOfWeek.MONDAY)
- assertEquals(
- listOf(2, 9, 16, 23, 30),
- days
- )
- }
}
\ No newline at end of file