From 1a4496c06b3558bbbbff872154b072c51c2b24f7 Mon Sep 17 00:00:00 2001 From: Your Name Date: Mon, 28 Apr 2025 03:08:03 +0300 Subject: [PATCH] allWithout11Window --- composeApp/build.gradle.kts | 15 + .../project/ViewModel/DatePickerField.kt | 80 +++ .../org/example/project/ViewModel/GetPath.kt | 61 +++ .../project/ViewModel/ImageFromPath.kt | 71 +++ .../androidMain/res/drawable/basic_photo.png | Bin 0 -> 10550 bytes .../composeResources/drawable/basicPhoto.png | Bin 0 -> 10550 bytes .../project/ViewModel/DatePickerField.kt | 23 + .../project/ViewModel/FieldWithDropdown.kt | 106 ++++ .../project/ViewModel/FieldWithLabel.kt | 73 +++ .../project/ViewModel/FieldWithLabelInt.kt | 86 ++++ .../org/example/project/ViewModel/GetPath.kt | 7 + .../project/ViewModel/ImageFromPath.kt | 18 + .../project/ui/Screens/ConfirmRunner.kt | 217 ++++++++ .../project/ui/Screens/ConfirmSponsor.kt | 235 +++++++++ .../example/project/ui/Screens/ForSponsor.kt | 464 ++++++++++++++++++ .../example/project/ui/Screens/InfoRunner.kt | 234 +++++++++ .../org/example/project/ui/Screens/Login.kt | 83 +--- .../example/project/ui/Screens/MainScreen.kt | 2 +- .../example/project/ui/Screens/RegMaraphon.kt | 415 ++++++++++++++++ .../example/project/ui/Screens/RegRunner.kt | 409 +++++++++++---- .../project/ViewModel/DatePickerField.kt | 38 ++ .../org/example/project/ViewModel/GetPath.kt | 29 ++ .../project/ViewModel/ImageFromPath.kt | 47 ++ 23 files changed, 2553 insertions(+), 160 deletions(-) create mode 100644 composeApp/src/androidMain/kotlin/org/example/project/ViewModel/DatePickerField.kt create mode 100644 composeApp/src/androidMain/kotlin/org/example/project/ViewModel/GetPath.kt create mode 100644 composeApp/src/androidMain/kotlin/org/example/project/ViewModel/ImageFromPath.kt create mode 100644 composeApp/src/androidMain/res/drawable/basic_photo.png create mode 100644 composeApp/src/commonMain/composeResources/drawable/basicPhoto.png create mode 100644 composeApp/src/commonMain/kotlin/org/example/project/ViewModel/DatePickerField.kt create mode 100644 composeApp/src/commonMain/kotlin/org/example/project/ViewModel/FieldWithDropdown.kt create mode 100644 composeApp/src/commonMain/kotlin/org/example/project/ViewModel/FieldWithLabel.kt create mode 100644 composeApp/src/commonMain/kotlin/org/example/project/ViewModel/FieldWithLabelInt.kt create mode 100644 composeApp/src/commonMain/kotlin/org/example/project/ViewModel/GetPath.kt create mode 100644 composeApp/src/commonMain/kotlin/org/example/project/ViewModel/ImageFromPath.kt create mode 100644 composeApp/src/commonMain/kotlin/org/example/project/ui/Screens/ConfirmRunner.kt create mode 100644 composeApp/src/commonMain/kotlin/org/example/project/ui/Screens/ConfirmSponsor.kt create mode 100644 composeApp/src/commonMain/kotlin/org/example/project/ui/Screens/ForSponsor.kt create mode 100644 composeApp/src/commonMain/kotlin/org/example/project/ui/Screens/InfoRunner.kt create mode 100644 composeApp/src/commonMain/kotlin/org/example/project/ui/Screens/RegMaraphon.kt create mode 100644 composeApp/src/desktopMain/kotlin/org/example/project/ViewModel/DatePickerField.kt create mode 100644 composeApp/src/desktopMain/kotlin/org/example/project/ViewModel/GetPath.kt create mode 100644 composeApp/src/desktopMain/kotlin/org/example/project/ViewModel/ImageFromPath.kt diff --git a/composeApp/build.gradle.kts b/composeApp/build.gradle.kts index af7c6d3..cc9f46b 100644 --- a/composeApp/build.gradle.kts +++ b/composeApp/build.gradle.kts @@ -21,11 +21,16 @@ kotlin { sourceSets { val desktopMain by getting + + val commonMain by getting { + resources.srcDir("src/commonMain/composeResources") + } androidMain.dependencies { implementation(compose.preview) implementation(libs.androidx.activity.compose) implementation(libs.androidx.lifecycle.viewmodel) + implementation("io.ktor:ktor-client-okhttp:2.3.2") } commonMain.dependencies { val voyagerVersion = "1.1.0-beta02" @@ -40,10 +45,20 @@ kotlin { implementation("cafe.adriel.voyager:voyager-screenmodel:$voyagerVersion") implementation(compose.preview) implementation(libs.androidx.lifecycle.viewmodel) + implementation("media.kamel:kamel-image:0.7.0") + implementation("io.ktor:ktor-client-core:2.3.2") + implementation("io.ktor:ktor-client-cio:2.3.2") + implementation("io.ktor:ktor-client-okhttp:2.3.2") + + repositories { + google() + mavenCentral() + } } desktopMain.dependencies { implementation(compose.desktop.currentOs) implementation(libs.kotlinx.coroutines.swing) + implementation("io.ktor:ktor-client-okhttp:2.3.2") } } } diff --git a/composeApp/src/androidMain/kotlin/org/example/project/ViewModel/DatePickerField.kt b/composeApp/src/androidMain/kotlin/org/example/project/ViewModel/DatePickerField.kt new file mode 100644 index 0000000..a922927 --- /dev/null +++ b/composeApp/src/androidMain/kotlin/org/example/project/ViewModel/DatePickerField.kt @@ -0,0 +1,80 @@ +//package org.example.project.ViewModel +// +//import android.app.DatePickerDialog +//import android.widget.DatePicker +//import androidx.compose.material.OutlinedTextField +//import androidx.compose.material.Text +//import androidx.compose.material.icons.Icons +//import androidx.compose.material.icons.filled.DateRange +//import androidx.compose.runtime.* +//import androidx.compose.ui.platform.LocalContext +//import androidx.compose.ui.Modifier +//import androidx.compose.foundation.clickable +//import androidx.compose.material.Icon +//import java.util.* +// +//@Composable +//actual fun DatePickerField( +// onDateSelected: (String) -> Unit, +// trigger: Boolean, +// onDismissRequest: () -> Unit +//) { +//// val context = LocalContext.current +//// val calendar = Calendar.getInstance() +//// +//// val datePickerDialog = remember { +//// DatePickerDialog( +//// context, +//// { _: DatePicker, year: Int, month: Int, dayOfMonth: Int -> +//// val formatted = "%02d.%02d.%04d".format(dayOfMonth, month + 1, year) +//// onDateSelected(formatted) +//// }, +//// calendar.get(Calendar.YEAR), +//// calendar.get(Calendar.MONTH), +//// calendar.get(Calendar.DAY_OF_MONTH) +//// ) +//// } +//// +//// OutlinedTextField( +//// value = selectedDate, +//// onValueChange = {}, +//// label = { Text("Выберите дату") }, +//// trailingIcon = { Icon(Icons.Default.DateRange, contentDescription = null) }, +//// readOnly = true, +//// modifier = modifier.clickable { datePickerDialog.show() } +//// ) +//} + +package org.example.project.ViewModel + +import android.app.DatePickerDialog +import android.widget.DatePicker +import androidx.compose.runtime.* +import androidx.compose.ui.platform.LocalContext +import java.util.* + +@Composable +actual fun DatePickerField( + onDateSelected: (String) -> Unit, + trigger: Boolean, + onDismissRequest: () -> Unit +) { + val context = LocalContext.current + + if (trigger) { + LaunchedEffect(Unit) { + val calendar = Calendar.getInstance() + DatePickerDialog( + context, + { _: DatePicker, year: Int, month: Int, dayOfMonth: Int -> + val formatted = "%02d.%02d.%04d".format(dayOfMonth, month + 1, year) + onDateSelected(formatted) + onDismissRequest() + }, + calendar.get(Calendar.YEAR), + calendar.get(Calendar.MONTH), + calendar.get(Calendar.DAY_OF_MONTH) + ).show() + } + } +} \ No newline at end of file diff --git a/composeApp/src/androidMain/kotlin/org/example/project/ViewModel/GetPath.kt b/composeApp/src/androidMain/kotlin/org/example/project/ViewModel/GetPath.kt new file mode 100644 index 0000000..a9216f7 --- /dev/null +++ b/composeApp/src/androidMain/kotlin/org/example/project/ViewModel/GetPath.kt @@ -0,0 +1,61 @@ +//package org.example.project.ViewModel +// +//import androidx.compose.runtime.Composable +// +//@Composable +//actual fun GetPath(onPathSelected: (String) -> Unit){ +// +//} + +package org.example.project.ViewModel + +import android.app.Activity +import android.content.Intent +import android.net.Uri +import android.provider.OpenableColumns +import androidx.activity.compose.rememberLauncherForActivityResult +import androidx.activity.result.contract.ActivityResultContracts +import androidx.compose.runtime.* +import androidx.compose.ui.platform.LocalContext +import java.io.File +import java.io.FileOutputStream + +@Composable +actual fun GetPath(onPathSelected: (String) -> Unit) { + val context = LocalContext.current + var launched by remember { mutableStateOf(false) } + + val launcher = rememberLauncherForActivityResult( + contract = ActivityResultContracts.GetContent(), + onResult = { uri: Uri? -> + if (uri != null) { + val inputStream = context.contentResolver.openInputStream(uri) + val fileName = getFileName(context.contentResolver, uri) ?: "temp_image.jpg" + val file = File(context.cacheDir, fileName) + val outputStream = FileOutputStream(file) + inputStream?.copyTo(outputStream) + inputStream?.close() + outputStream.close() + onPathSelected(file.absolutePath) + } + } + ) + + LaunchedEffect(Unit) { + if (!launched) { + launched = true + launcher.launch("image/*") + } + } +} + +fun getFileName(contentResolver: android.content.ContentResolver, uri: Uri): String? { + val returnCursor = contentResolver.query(uri, null, null, null, null) + returnCursor?.use { + val nameIndex = it.getColumnIndex(OpenableColumns.DISPLAY_NAME) + if (it.moveToFirst()) { + return it.getString(nameIndex) + } + } + return null +} \ No newline at end of file diff --git a/composeApp/src/androidMain/kotlin/org/example/project/ViewModel/ImageFromPath.kt b/composeApp/src/androidMain/kotlin/org/example/project/ViewModel/ImageFromPath.kt new file mode 100644 index 0000000..7aef5a2 --- /dev/null +++ b/composeApp/src/androidMain/kotlin/org/example/project/ViewModel/ImageFromPath.kt @@ -0,0 +1,71 @@ +package org.example.project.ViewModel + +import android.graphics.BitmapFactory +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.ImageBitmap +import androidx.compose.ui.graphics.asImageBitmap +import androidx.compose.ui.graphics.painter.BitmapPainter +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.res.imageResource +import org.example.project.R +import java.io.File + + +@Composable +actual fun ImageFromPath(path: String, modifier: Modifier) { + val imageBitmap: ImageBitmap? = when { + path.isEmpty() -> { + ImageBitmap.imageResource(id = R.drawable.basic_photo) + } + + else -> { + val file = File(path) + if (file.exists()) { + val bitmap = BitmapFactory.decodeFile(file.absolutePath) + bitmap?.asImageBitmap() + } else null + } + } + + if (imageBitmap != null) { + Image( + painter = BitmapPainter(imageBitmap), + contentDescription = null, + modifier = modifier, + contentScale = ContentScale.Crop + ) + } else { + Box(modifier = modifier.fillMaxSize()) + } +} + +//@Composable +//actual fun ImageFromPath(path: String, modifier: Modifier) { +// // Попытка загрузить изображение из локального пути +// if (path == ""){ +// path = +// } +// +// val file = File(path) +// val imageBitmap: ImageBitmap? = if (file.exists()) { +// val bitmap = BitmapFactory.decodeFile(file.absolutePath) +// bitmap?.asImageBitmap() +// } else { +// null +// } +// +// if (imageBitmap != null) { +// Image( +// painter = BitmapPainter(imageBitmap), +// contentDescription = null, +// modifier = modifier, +// contentScale = ContentScale.Crop +// ) +// } else { +// Box(modifier = modifier.fillMaxSize()) +// } +//} \ No newline at end of file diff --git a/composeApp/src/androidMain/res/drawable/basic_photo.png b/composeApp/src/androidMain/res/drawable/basic_photo.png new file mode 100644 index 0000000000000000000000000000000000000000..854f3630f9b435496ea2ed25878d742b41af3be3 GIT binary patch literal 10550 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 I-?t6>UlhaEF#rGn literal 0 HcmV?d00001 diff --git a/composeApp/src/commonMain/composeResources/drawable/basicPhoto.png b/composeApp/src/commonMain/composeResources/drawable/basicPhoto.png new file mode 100644 index 0000000000000000000000000000000000000000..854f3630f9b435496ea2ed25878d742b41af3be3 GIT binary patch literal 10550 zcmeHscQ{0wby#zckT6-&-?C~XgwWuDhehF5C}x2@j%4@ z1R_uang`hxV5ak6SP=xe`VgwDtf!%@4A%2ZRAGnZ6p(vxq14b!DzSQNNf=lGm z$y`cCF2lPHChi5DHqmKmF>n2n6`VQW z!tDA%*D*qS?@g^0*f@WYhAX*{c{bhV=4hEK5VT_Xc<|y-xv$f|MKbCTTu$3dWRHjI z^l)`w{T?V{^>yiBfAF*##gK%XyD_=Tk}RK}$%{GMuzy36<{3?6$bPMdo?At+l)y7w zRz|#Zjyn&W$SgF^Y1qjFs|q#cN+8CU98?W^o9St_T@F~DDq<(1wS*u!Y&QLU2ul4i zia?I}<1T7gdy^`y&ROW22l4_zVESwxuwJr^4xI+Z-bl8byMI4U|8>{aM=AaDi-tBH zZqwcjB^K_%I97%XBq@EtLpDglvT9cmrn9f+BwN4OZ>JT^;-LhxB_MHu+6wm&Vt$t6 z1pM;W$q9qNM2w2WEV#56e?-IOX#Ef*B=fpaDvI)w18o&1#CzBMex`~{cp?}^yhALE2~p{c)CR$NUT9BVZl4ky$#lHX@>2lJ60gd( zbNdP{Q51V8IEUXY6hCk6Cn<|-Uq;k;#=Ve5;jd@WPLaitNsw)Y%OrNbs%F=JL$al( zP}n99RrpC-AC_L;pn#oi&paY==R7($ zl7tZ$^(sbbgASbzA3asG4YrNk7%|sM^h|qJ_C7465Ji*K5fSh>wvuQ8Xn|p84z|1mAt4oSFS>8J}rnY=C{VIJ$PAI+n_vo>CCR(3qGv z;($SXm!%^O7E)M5Us+zfIulC2L-YcCLnTb| zEiu=ZRgneh)E7mzT<=I@6v<7m{S5W0BzGY(vXz*iURSy7`vsdwU6k%HQclC#FlOIS`lN6~P zu}8)y_KtoFWoj!V+Zh-}YQVo{>ZFuD(vKk}Ry&7-mR zH-03p-Z{83^#-LFC>UB~r}g~??DGTzeQak!mA6(z|JRr*gHqa(E~W)IDx%ijYC`>e zl!yl%7G&ZpE(hnPiXRKW61Kt zx5AafMRv^A!7ZG$(ONlTL#*<#8l8NYs~B3$70fLR`D5l?p{hs~jDWGasI zwsM>5nlhzL^hph>>b&I4 zKQvY3qqNZ|t}*>kM$e+KRWY#ShUFm3RlUxMi(Da<-exSu z*GdpR>0_?WPE3!B1!o^mIpZe3Pw}Bkf4Ia=!ePZy)3UQcwf;5!^{=A4Ok>mN#OT`0 z4EQEf(o&xB51OIstLq+qGIug^Kb$ciOn0=hwX%l~Mm$}7CeoEZyxhb;l;WD<+T4B= z!|J@^oC-Cu^PRj^>sv!V?Oy55ti-S&bYD2ftCOG9hxCmyO8Iq%vUtbI# z9cQ9?IfK93F9~jw0+s?-9ba{590jY9WU=SyGe;T67qD0RheMx+lyX-PZVcz&y3ne> zs)v^9?sfQ-ZrmS#I$q(1brY^Puh;RVJbrY1h^?QH-sCx=J@Tgxi)`y=iQ|fk%W})| z&%(=H?s@HeJDOTM3_=_-483!;zZIC_zu#K#SC6j@GJuQYKjG7Hd+>X3w$n5``FR~) zZgIk^TC!OZa-MnSa1nVn2a{{8Y2YTT44n_fg#J|A`h4QLARYZ2OTVptKj`P{-=u|gEn!T|*v&Gk(T?g*w|lVt8s8@qH3zi&<@knDo@nam zif75XdS#4So8NXtVx%1UlibYSxiquH>%Nuvwf33qobJ_Y40l&Y5b`YMjN0&e{;hZU zV%oxG4o$NMT_ebw#5d1`iID8?hGa*)ms`@P9X+4AroH~IlQApX9W)Ro#R_}5V%(oQ z(3f@mEZcD5+n4(N>njohg64w0?Tg5;kYe6po`jpT=Bu?HBOF2Te)=1jq1bW$3u8V$ zlqu$sf%%?8v~6z}QvKZW2(~?ZkXP0>lj3TrV<})3412X5Q=DvmkJ4D)TI{*etn<%x z%$WPQmN_hYG|zj)eBHcj>Zp3BI>Lu;Bc%dwkYyH}`=#yiU_i%V?0DN8c*esgckb(y zwpzwRaX1iPL4le(DNPScz73akmYrH4-83hjW9g3|W7AZ1sVYOjsC<9odl?%&kn+te&#fxxJr?FooD5hwj2|I+hJNYmb(d@B@|c zUPNMC2DjLpoEUcWaAc^!VlX^YDnxvBvk3Mc);$=AbZ?sXU)WJS>cVNdrLLP>T3kC{ z$8BUA*Z*wl!=^Hq`&mL=m`9#(7H^LwjuVz=whlB0uc>vuuFKe!aG!hFI2LT-hd<4H zFH;fRce%Ac+jvZN9JBol4T0O9eAx4yo;&{3T+0S$*r{C7-^^`}BZ;$-jaN7wuA1lF zg06`qI*tuyA|-sT_*kFXpRut*K0@SuZ=M$&uHaI|A=DR3$0nM`4cIp()h4YKsVzex zHH&3^)5}?fS)|)ubMRoBGo?%AG4-Qv7?M^&4ljF1xu!X3GF|a{?h9&mqkn5FdC%bt zWkYb4r(S#w)Pg1e@soqD%t#n?mmEdHBMOf`!O70JOQ)2N(wITDJ4pE^%8S_@@8_w^QNzj^-Zi4r0}q`(s`(EL6S{tq>Q+6SWlj6HxgkdmRYh6d0Z+Iu-TxWSy< zy;pcsaliz*#{)AM2t;@1cO%d+xV;0&{|S9$>TRm6C2jBSDq#1-{jr09pX;A;K(c<) zz|hsf+YapK>f#2I_LJlIlR_F8|DJ|$fd3@%ekR9Zs;viBcK31siwg(}2y)0%fWcr{ zuP0BX4OG+f|d&rB3OUnL9|9`CfcgKHln*M`RSp1)y|5*9o zIgMZrUdrySz?RP{cn^6|>`{e)7#9wOua~9CEJcTUeKQ@!6z}>#h2AG`% zs-pV{=m97D^J)O@JV5*11C7#K>R`+q=oK|olpgsJY|dyz-Ed?k-5GCykhy)pctvU4 zAfXlj6Kkjpy>to-c%VZdaeF9{gX8W4wF4Sr5;>j#{T7ulVtQHPb`@g!a54dvgPaC; zl{-$NsB?H?oPSe5zT@Ul+Ta|euzzuJNlEbecZIQYW8KJCl=LX`N?RpiG8*s>igI(N zu}0+wJE^^u)hr&na7Io8ersG|ZDl}%NPht$AiTUugE0R+P*N1ULUV_JkeE347FaP< zk%k6AprR29B4{rp1w_#h6WfFIX~Bw$g6jYg88JaSgJKdf89){Q5dF*kuj>AFn}0** z{~x$`d-UkyaNGuZjGc9eoM{WW6!pcudfb}v%ZA%A=wA~IjCu};^X6^E&ut7tGc3KUFP_g__Gjlvaiq20w{nRM(RME zAIva)&^NL(Z{6Y-kDY5nVrQF8aHl7`iw7GOZQ?VlK4V3O1qY`q$O3e0;3Xasf<0*` zWlM5>MnFKgL>N{z^HH1M|76Fm$z$Puli%*+rhr3d9Dcja!aHcT*;khhexT1J<@E%2 zvKVJrPDMx@Lqcp{)hA<+*zzX=y8d3kfU!&Q|kqzeB^Q}OVa9zzCbk6{^ zmEktiuxlK5x2-ix!rglPXW6s`+*()dLm36xSMj}XGbp&s)tiLs@knB{ z1ws476>A(z#B{woq+irT`uz(c(tHT&goBDz`e05w9o9Th`)qs|(sq_mZrQlEy|@^1 zm06sxAF0qLTEaRmRv&z@s^8?jX3!LL>J_jvuk@|`{owvsiAj;;U{)Ro3&@3XtS0Kp z^Y&+%?6aKi0`@O@I+E^^=y;R?yEALPVwIR!l~@dDbnH=C{X)4_^W7`PsKck5YJYaJyVeJ3<1;rJt7b7jy(=F181}VLKX(|x zC}MyrE3Ar-3!H88dF^U2;-egKRYNm{59)<1gQK-?g;F`+1v5PRHhGqrsSqN+HC z*L(03e-5Yh(W0B&FVW8huQ7@8z>jBrx6fMc-3q-~#sOxqcvah!xg1Da?=qQyMYmcU zg$DUF*tUly&7qB%_^H0Ov~jAx`MB5}M~{`B+dk=+n7dJa&-`7-dN*4L@Z0Z2;L!S0 z2(!#{mvj+FofwlIe|1-0hPh>b3FaXp^aDjf)E{#hat&1_T|vzKpP(a5@GuGTuR#`i z*Otz-({rl4*M^f6#!H_9@m1h`JwR;QxVitGko~ZU4cw^C--6<6y+7K4hVD~wsI7|; z`l~N0|9EP1OTrzkHC|z(8*;X*zA)x>KCt&>B%J*Edf)J1P;#sP{_^k>otHOn z#+)gHO76*JoYqV`tI02S#nPv`;_3#QH$i+(Mu0OGw^ zzZBYT8}1z3S?JKL-xhs-^^`NT%%a}-eNXR-5N!E-411FDy~y=65l0GSK43WLWVHkD zpmn`>saZ|_rpTc4Kv~twGwPMuiCv5FPrzxX3XSS|+AL4M6*vW*AC5y0R)>w800^2yLHkT zeccenU6Yq97FH$q-dD3#7OOxQw#({sKZ|id!khl}S)XNpE3B66>siY4={i@{$av#2 zbEDme?I2xDzIFyh1>OGlJpdLckIkS9?Jr43qOWs*GhQkAntacs?j+87RGMMB&p%bk z{0ASPAinY`S4$}7P6(>u`PNi%Rv}&cyEfJuyN-x2E6-dAx#m(5+eTQ`QRbFak5#)A zUr&#ZpMG6s3qHx-sUTgdUp$So{`BN8k@cP5>@T?W*btXMIemFqzJDnW0$t1hT}yAx zIz~P6rSIOgAGOsMjbYN%8jWgy6NS64qDsylJs)eT_gE>KLjYiHY zC8aYV#T6G7DjspZiJO$q?W33cvqY$yu>+R_o8LF(nn>H|J7+I5rH*F?qZOX6peK`< zgrD?;EPqeqbg59YokPK^Jr}>u+ZvS^Cj$eL4Sh-=B_vGNIFdHseN+fG%-16SnM()2 zJo{WQ-gQ)fQQEt3w8BQgYYqS?j_x=%>LUQHbWmq|eYSFmuMRiH`v5!(ixhXAdW1XL zVlH*8{;-n2V(Kvh8;12c?0cab-!l*T^S(XaF1XQtLc3%X1Z1m_UcfA2%B^^8v#{Nl za9cTN_BXac7iW!H8RGoKEdc&$0f5Zh=#HIf+#6K5B*uS5FmjF+8&UogF$3Hqg3qk_ zwx83|w`7Omj~eX(T$G-qxvBdDoe|w1>A(zz)9mqNp zd>L7J!=_+e{HQ2FBkg`%vph6OswdrN)l z*n15O>VnpdUaBb&8|zA!i}CB+I!V50f9^|s3q-)O0jzMgql~UU4RPETSG-6}K$$jp zWY09hxS>YBGTc$|0f*}(8>;-BjEJm(W*+*Z0(vmR2>#txYw&p!pH-7+buf^LegUW- zJ!9e_^u~6k*|)+4-O^|~c~;>#@SYcUSI}R^6BAx)UVGQyOdirJbld~A0+Abu)@0a zqiQT&dw@Qr=at-oeSvSU&eurDz8=Wu2Zo#dn+i>uI$m>_W9gl3IrY-gH$N;c80GJ7;HNvTt=P%)`sWxQA4 zmRdE7PmGtEiL3z$zA~%-i+kHS7m$LevWA;|-J$3f|4Qr8`|sOV*IHt|>_P$v!h~Am z*3dxy=PJj_`|sVB)B&7@*5uXUn0;}XWV_$il$cr7<5#kQM|?b&=)mpX)uCL@Ih#>Z zq^!TeZ&aW65AalhB;0VcX!OdnZ1U#i5%QQ58}e(7#IcQ!e1(?NseE($*zfM1d|+XT~&mf4Tod zmcXi~X!!7Ktlu%#$_)4t-wA@hL3cCw+>!C~=nO*zjNut_>wx+v78Nt_Joe9^sMC=} zRf5`0Cl+gifHFktbgclXQt?RLl}XZdx-J=TmFVCZh|van$Sh@ZJo09U?4HeMKwaf^$#?h$h_oV@r6lgwu}?2xa~; zSFwPKY&7s^O#ZgTI^M6>!qbf?MuwsFy>B)9oFliQ;L{ZcoD-FL>%&Ze&wNZj*z^xC zl&NO5>b*@y)e#JToaTl!O{GF?-dy#E>i`u~o_2=#T2_{q%}o31Qj1|&B_}7~B%Jvs z$KZ1n1iCt>O>e=-<#&OLd92w~GN%t;4b0tN8B7JRl(ZRk>MB`;wHamGJ`B?-rqpY1 zPo%?KQ-iEzc7Com1H#cPtTiTbP)wfFWKaTK~C=cZ}G4jjiT{Oct2=lsecm*>7{gX}gLpY_{7sSWv*(k}sk<*n%s ze@FXHdu8BdMR|qpF)`s5YcGZdsSBDU6QLcrtdHnth1-*Bj#VR8{sSNL(Z)3{lfpxI zpv0 zrC@3UNCjlWrQW5db0rXp_aup^WY2F};n3Mv7D(BG-kv1h{SZcI#LsxMEtFr7Gxro)C;Cp*oQc1WpiGL%WY~aT~94 z2>_6&8YqlSspGLVQb z6gOe=@)sxejDog`?<09VS6DZCTVHgMsdX!lU#iETeu;{VDmAlVFZb8-q*SzqS9&t(XD_72bKrh-I_;dwnsOqSc I-?t6>UlhaEF#rGn literal 0 HcmV?d00001 diff --git a/composeApp/src/commonMain/kotlin/org/example/project/ViewModel/DatePickerField.kt b/composeApp/src/commonMain/kotlin/org/example/project/ViewModel/DatePickerField.kt new file mode 100644 index 0000000..cc03f17 --- /dev/null +++ b/composeApp/src/commonMain/kotlin/org/example/project/ViewModel/DatePickerField.kt @@ -0,0 +1,23 @@ +package org.example.project.ViewModel + +import androidx.compose.foundation.clickable +import androidx.compose.material.OutlinedTextField +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.material.Text +import androidx.compose.ui.Modifier +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.material.Icon +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.DateRange +import java.util.Calendar + +@Composable +expect fun DatePickerField( + onDateSelected: (String) -> Unit, + trigger: Boolean, + onDismissRequest: () -> Unit +) diff --git a/composeApp/src/commonMain/kotlin/org/example/project/ViewModel/FieldWithDropdown.kt b/composeApp/src/commonMain/kotlin/org/example/project/ViewModel/FieldWithDropdown.kt new file mode 100644 index 0000000..acd2645 --- /dev/null +++ b/composeApp/src/commonMain/kotlin/org/example/project/ViewModel/FieldWithDropdown.kt @@ -0,0 +1,106 @@ +package org.example.project.ViewModel + +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.DropdownMenu +import androidx.compose.material.DropdownMenuItem +import androidx.compose.material.Icon +import androidx.compose.material.Text +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.ArrowDropDown +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.TextUnit +import androidx.compose.ui.unit.dp + +@Composable +fun FieldWithDropdown( + label: String, + options: List, + selectedOption: String, + onOptionSelected: (String) -> Unit, + fontSize: TextUnit, + labelWidth: Float +) { + var expanded by remember { mutableStateOf(false) } + + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.Center, + modifier = Modifier.fillMaxWidth() + ) { + Box(modifier = Modifier.weight(labelWidth)) { + Text( + text = label, + color = Color.DarkGray, + textAlign = TextAlign.Start, + fontSize = fontSize, + ) + } + + Box( + modifier = Modifier + .weight(1f) + .fillMaxWidth() + .background(Color.White, shape = RoundedCornerShape(4.dp)) + .border( + width = 1.dp, + color = Color(0xFFCCCCCC), + shape = RoundedCornerShape(4.dp) + ) + .clickable { expanded = true } + .padding(12.dp) + ) { + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween, + modifier = Modifier.fillMaxWidth() + ) { + Text( + text = selectedOption.ifEmpty { "..." }, + fontSize = fontSize, + color = if (selectedOption.isEmpty()) Color.LightGray else Color.Black + ) + + Icon( + imageVector = Icons.Default.ArrowDropDown, + contentDescription = "Dropdown Arrow", + tint = Color.Gray + ) + } + + DropdownMenu( + expanded = expanded, + onDismissRequest = { expanded = false }, + modifier = Modifier + .background(Color.White) + .fillMaxWidth() + ) { + options.forEach { option -> + DropdownMenuItem( + onClick = { + onOptionSelected(option) + expanded = false + } + ) { + Text(option, fontSize = fontSize, color = Color.Black) + } + } + } + } + } +} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/org/example/project/ViewModel/FieldWithLabel.kt b/composeApp/src/commonMain/kotlin/org/example/project/ViewModel/FieldWithLabel.kt new file mode 100644 index 0000000..b60e002 --- /dev/null +++ b/composeApp/src/commonMain/kotlin/org/example/project/ViewModel/FieldWithLabel.kt @@ -0,0 +1,73 @@ +package org.example.project.ViewModel + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.wrapContentWidth +import androidx.compose.material.OutlinedTextField +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.text.style.TextAlign +import androidx.compose.ui.unit.TextUnit +import androidx.compose.ui.unit.dp + +@Composable +fun FieldWithLabel( + label: String, + value: String, + onValueChange: (String) -> Unit, + placeholder: String, + fontSize: TextUnit, + labelWidth: Float, + enabled: Boolean = true, +) { + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.Center, + modifier = Modifier.fillMaxWidth() + ) { + Box(modifier = Modifier.weight(labelWidth)) { + Text( + text = label, + color = Color.DarkGray, + textAlign = TextAlign.Start, + fontSize = fontSize, + modifier = Modifier + ) + } + + OutlinedTextField( + value = value, + onValueChange = onValueChange, + placeholder = { + if (placeholder.isNotEmpty()) { + Text( + text = placeholder, + fontSize = fontSize, + color = Color.LightGray + ) + } + }, + textStyle = androidx.compose.ui.text.TextStyle( + fontSize = fontSize, + color = Color.Black + ), + enabled = enabled, + colors = androidx.compose.material.TextFieldDefaults.outlinedTextFieldColors( + backgroundColor = Color.White, + cursorColor = Color.Black, + textColor = Color.Black, + placeholderColor = Color.LightGray, + focusedBorderColor = Color(0xFFCCCCCC), + unfocusedBorderColor = Color(0xFFCCCCCC), + disabledBorderColor = Color(0xFFCCCCCC) + ), + modifier = Modifier.weight(1f).wrapContentWidth().fillMaxWidth() + ) + } +} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/org/example/project/ViewModel/FieldWithLabelInt.kt b/composeApp/src/commonMain/kotlin/org/example/project/ViewModel/FieldWithLabelInt.kt new file mode 100644 index 0000000..bc5409c --- /dev/null +++ b/composeApp/src/commonMain/kotlin/org/example/project/ViewModel/FieldWithLabelInt.kt @@ -0,0 +1,86 @@ +package org.example.project.ViewModel + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.wrapContentWidth +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.material.OutlinedTextField +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.text.input.KeyboardType +import androidx.compose.ui.text.input.ImeAction +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.TextUnit +import androidx.compose.ui.unit.dp + +@Composable +fun FieldWithLabelInt( + label: String, + value: Int, + onValueChange: (Int) -> Unit, + placeholder: String, + fontSize: TextUnit, + labelWidth: Float, + enabled: Boolean = true, +) { + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.Center, + modifier = Modifier.fillMaxWidth() + ) { + Box(modifier = Modifier.weight(labelWidth)) { + Text( + text = label, + color = Color.DarkGray, + textAlign = TextAlign.Start, + fontSize = fontSize, + ) + } + + OutlinedTextField( + value = value.toString(), + onValueChange = { newValue -> + val intValue = newValue.toIntOrNull() + if (intValue != null) { + onValueChange(intValue) + } + }, + placeholder = { + if (placeholder.isNotEmpty()) { + Text( + text = placeholder, + fontSize = fontSize, + color = Color.LightGray + ) + } + }, + textStyle = androidx.compose.ui.text.TextStyle( + fontSize = fontSize, + color = Color.Black + ), + enabled = enabled, + colors = androidx.compose.material.TextFieldDefaults.outlinedTextFieldColors( + backgroundColor = Color.White, + cursorColor = Color.Black, + textColor = Color.Black, + placeholderColor = Color.LightGray, + focusedBorderColor = Color(0xFFCCCCCC), + unfocusedBorderColor = Color(0xFFCCCCCC), + disabledBorderColor = Color(0xFFCCCCCC) + ), + keyboardOptions = KeyboardOptions( + keyboardType = KeyboardType.Number, + imeAction = ImeAction.Done + ), + modifier = Modifier + .weight(1f) + .wrapContentWidth() + .fillMaxWidth() + ) + } +} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/org/example/project/ViewModel/GetPath.kt b/composeApp/src/commonMain/kotlin/org/example/project/ViewModel/GetPath.kt new file mode 100644 index 0000000..efbcb70 --- /dev/null +++ b/composeApp/src/commonMain/kotlin/org/example/project/ViewModel/GetPath.kt @@ -0,0 +1,7 @@ +package org.example.project.ViewModel + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier + +@Composable +expect fun GetPath(onPathSelected: (String) -> Unit) \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/org/example/project/ViewModel/ImageFromPath.kt b/composeApp/src/commonMain/kotlin/org/example/project/ViewModel/ImageFromPath.kt new file mode 100644 index 0000000..eafe1ae --- /dev/null +++ b/composeApp/src/commonMain/kotlin/org/example/project/ViewModel/ImageFromPath.kt @@ -0,0 +1,18 @@ +package org.example.project.ViewModel + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.remember +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.painter.Painter +import androidx.compose.ui.layout.ContentScale +import io.kamel.image.asyncPainterResource +import io.kamel.core.Resource +import io.kamel.core.getOrNull + +@Composable +expect fun ImageFromPath(path: String = "", modifier: Modifier = Modifier) diff --git a/composeApp/src/commonMain/kotlin/org/example/project/ui/Screens/ConfirmRunner.kt b/composeApp/src/commonMain/kotlin/org/example/project/ui/Screens/ConfirmRunner.kt new file mode 100644 index 0000000..a51a8df --- /dev/null +++ b/composeApp/src/commonMain/kotlin/org/example/project/ui/Screens/ConfirmRunner.kt @@ -0,0 +1,217 @@ +package org.example.project.ui.Screens + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.BoxWithConstraints +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.aspectRatio +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.layout.wrapContentWidth +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.Button +import androidx.compose.material.ButtonDefaults +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Scaffold +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import cafe.adriel.voyager.core.screen.Screen +import cafe.adriel.voyager.navigator.LocalNavigator +import cafe.adriel.voyager.navigator.currentOrThrow +import org.example.project.ViewModel.TimerViewModel + +class ConfirmRunnerScreen(private val timerViewModel: TimerViewModel) : + Screen { + + @Composable + override fun Content() { + val navigator = LocalNavigator.currentOrThrow + + Scaffold( + topBar = { ConfirmRunnerTopBar() }, + bottomBar = { ConfirmRunnerBottomBar(timerViewModel = timerViewModel) } + ) { paddingValues -> + + Box( + modifier = Modifier.padding(paddingValues) + ) { + BoxWithConstraints( + modifier = Modifier + .fillMaxWidth() + .align(Alignment.Center) + .padding(horizontal = 100.dp) + ) { + val fontSizeFirst = (maxWidth.value / 30).sp + val fontSizeSecond = (maxWidth.value / 40).sp + + Column( + modifier = Modifier + .fillMaxWidth().padding(bottom = 16.dp), + horizontalAlignment = Alignment.CenterHorizontally, + ) { + Spacer(modifier = Modifier.weight(0.2f)) + + Box(modifier = Modifier.fillMaxWidth()) { + Text( + text = "Спасибо за вашу регистрацию в качестве бегуна!", + color = Color.Gray, + textAlign = TextAlign.Center, + fontSize = fontSizeFirst, + modifier = Modifier.align(Alignment.Center) + ) + } + + Spacer(modifier = Modifier.weight(0.2f)) + + Box(modifier = Modifier.fillMaxWidth()) { + Text( + text = "Спасибо за вашу регистрацию в качестве бегуна в Marathon Skills 2016!\n С вами свяжутся по поводу оплаты.", + color = Color.Black, + textAlign = TextAlign.Center, + fontSize = fontSizeFirst, + modifier = Modifier.align(Alignment.Center) + ) + } + + Spacer(modifier = Modifier.weight(0.2f)) + + Button( + onClick = { navigator.push(InfoRunnerScreen(timerViewModel)) }, + modifier = Modifier + .fillMaxWidth() + .height(48.dp), + colors = ButtonDefaults.buttonColors( + backgroundColor = Color.LightGray, + contentColor = Color.Black + ), + shape = RoundedCornerShape(15.dp) + ) { + Text("Ок", fontSize = fontSizeSecond) + } + + Spacer(modifier = Modifier.weight(1f)) + } + } + } + } + } + + @Composable + private fun ConfirmRunnerTopBar() { + val navigator = LocalNavigator.currentOrThrow + + Box { + BoxWithConstraints( + modifier = Modifier + .fillMaxWidth() + .align(Alignment.Center) + ) { + val fontSizeButton = (maxWidth.value / 50).sp + val fontSizeText = (maxWidth.value / 25).sp + + Row( + modifier = Modifier + .fillMaxWidth() + .background(Color.DarkGray) + .padding(16.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween + ) { + + Button( + onClick = { }, + colors = ButtonDefaults.buttonColors( + backgroundColor = Color.LightGray, + contentColor = Color.Black + ), + elevation = null, + shape = RoundedCornerShape(15.dp), + modifier = Modifier + .wrapContentWidth() + + ) { + Text( + text = "Назад", + color = Color.Black, + fontSize = fontSizeButton + ) + } + + Spacer(modifier = Modifier.width(24.dp)) + + Text( + text = "MARATHON SKILLS 2016", + style = MaterialTheme.typography.h6, + modifier = Modifier.weight(1f), + textAlign = TextAlign.Left, + fontWeight = FontWeight.Bold, + fontSize = fontSizeText, + color = Color.White + ) + + Spacer(modifier = Modifier.width(64.dp)) + + Button( + onClick = { navigator.push(MainScreen()) }, + colors = ButtonDefaults.buttonColors( + backgroundColor = Color.LightGray, + contentColor = Color.Black + ), + elevation = null, + shape = RoundedCornerShape(15.dp), + modifier = Modifier + .wrapContentWidth() + + ) { + Text( + text = "Logout", + color = Color.Black, + fontSize = fontSizeButton + ) + } + } + } + } + } + + + @Composable + private fun ConfirmRunnerBottomBar(timerViewModel: TimerViewModel) { + val remainingTime = timerViewModel.remainingTime.collectAsState().value + Box { + BoxWithConstraints( + modifier = Modifier + .align(Alignment.Center) + ) { + val fontSize = (maxWidth.value / 50).sp + + Column( + modifier = Modifier + .fillMaxWidth() + .background(Color.DarkGray) + .padding(8.dp), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Text( + text = remainingTime, + color = Color.White, + fontSize = fontSize + ) + } + } + } + } +} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/org/example/project/ui/Screens/ConfirmSponsor.kt b/composeApp/src/commonMain/kotlin/org/example/project/ui/Screens/ConfirmSponsor.kt new file mode 100644 index 0000000..d181f73 --- /dev/null +++ b/composeApp/src/commonMain/kotlin/org/example/project/ui/Screens/ConfirmSponsor.kt @@ -0,0 +1,235 @@ +package org.example.project.ui.Screens + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.BoxWithConstraints +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.aspectRatio +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.layout.wrapContentWidth +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.Button +import androidx.compose.material.ButtonDefaults +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Scaffold +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import cafe.adriel.voyager.core.screen.Screen +import cafe.adriel.voyager.navigator.LocalNavigator +import cafe.adriel.voyager.navigator.currentOrThrow +import org.example.project.ViewModel.TimerViewModel + +class ConfirmSponsorScreen(private val timerViewModel: TimerViewModel, private val sumSpons: String, private val runner: String, private val blagot: String) : + Screen { + + @Composable + override fun Content() { + val navigator = LocalNavigator.currentOrThrow + + Scaffold( + topBar = { ConfirmSponsorTopBar() }, + bottomBar = { ConfirmSponsorBottomBar(timerViewModel = timerViewModel) } + ) { paddingValues -> + + Box( + modifier = Modifier.padding(paddingValues) + ) { + BoxWithConstraints( + modifier = Modifier + .fillMaxWidth() + .align(Alignment.Center) + .padding(horizontal = 100.dp) + ) { + val fontSize = (maxWidth.value / 60).sp + val fontSizeFirst = (maxWidth.value / 30).sp + val fontSizeSecond = (maxWidth.value / 40).sp + val fontSizeThird = (maxWidth.value / 50).sp + val fontSizeFourth = (maxWidth.value / 10).sp + val fontSizeFiveth = (maxWidth.value / 20).sp + + Column( + modifier = Modifier + .fillMaxWidth().padding(bottom = 16.dp), + horizontalAlignment = Alignment.CenterHorizontally, + ) { + Spacer(modifier = Modifier.weight(0.1f)) + + Box(modifier = Modifier.fillMaxWidth()) { + Text( + text = "Спасибо за вашу спонсорскую поддержку!", + color = Color.Gray, + textAlign = TextAlign.Center, + fontSize = fontSizeFirst, + modifier = Modifier.align(Alignment.Center) + ) + } + + Spacer(modifier = Modifier.weight(0.1f)) + + Box(modifier = Modifier.fillMaxWidth()) { + Text( + text = "Спасибо за поддержку бегуна в Marathon Skills 2016! Ваше пожертвование пойдёт в его благотворительную организацию", + color = Color.Black, + textAlign = TextAlign.Center, + fontSize = fontSizeFirst, + modifier = Modifier.align(Alignment.Center) + ) + } + + Spacer(modifier = Modifier.weight(0.1f)) + + Box(modifier = Modifier.fillMaxWidth()) { + Text( + text = runner, + color = Color.Black, + textAlign = TextAlign.Center, + fontSize = fontSizeFirst, + modifier = Modifier.align(Alignment.Center) + ) + } + + Spacer(modifier = Modifier.weight(0.1f)) + + Box(modifier = Modifier.fillMaxWidth()) { + Text( + text = blagot, + color = Color.LightGray, + textAlign = TextAlign.Center, + fontSize = fontSizeFiveth, + modifier = Modifier.align(Alignment.Center) + ) + } + + Spacer(modifier = Modifier.weight(0.1f)) + + Box(modifier = Modifier.fillMaxWidth()) { + Text( + text = sumSpons, + color = Color.LightGray, + textAlign = TextAlign.Center, + fontSize = fontSizeFourth, + modifier = Modifier.align(Alignment.Center) + ) + } + + Spacer(modifier = Modifier.weight(0.1f)) + + Button( + onClick = { navigator.push(MainScreen()) }, + modifier = Modifier + .fillMaxWidth() + .height(48.dp), + colors = ButtonDefaults.buttonColors( + backgroundColor = Color.LightGray, + contentColor = Color.Black + ), + shape = RoundedCornerShape(15.dp) + ) { + Text("Назад", fontSize = fontSizeSecond) + } + } + } + } + } + } + + @Composable + private fun ConfirmSponsorTopBar() { + val navigator = LocalNavigator.currentOrThrow + + Box { + BoxWithConstraints( + modifier = Modifier + .fillMaxWidth() + .align(Alignment.Center) + ) { + val fontSizeButton = (maxWidth.value / 50).sp + val fontSizeText = (maxWidth.value / 25).sp + + Row( + modifier = Modifier + .fillMaxWidth() + .background(Color.DarkGray) + .padding(16.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween + ) { + + Button( + onClick = { }, + colors = ButtonDefaults.buttonColors( + backgroundColor = Color.LightGray, + contentColor = Color.Black + ), + elevation = null, + shape = RoundedCornerShape(15.dp), + modifier = Modifier + .wrapContentWidth() + + ) { + Text( + text = "Назад", + color = Color.Black, + fontSize = fontSizeButton + ) + } + + Spacer(modifier = Modifier.width(24.dp)) + + Text( + text = "MARATHON SKILLS 2016", + style = MaterialTheme.typography.h6, + modifier = Modifier.weight(1f), + textAlign = TextAlign.Left, + fontWeight = FontWeight.Bold, + fontSize = fontSizeText, + color = Color.White + ) + } + } + } + } + + + + @Composable + private fun ConfirmSponsorBottomBar(timerViewModel: TimerViewModel) { + val remainingTime = timerViewModel.remainingTime.collectAsState().value + Box { + BoxWithConstraints( + modifier = Modifier + .align(Alignment.Center) + ) { + val fontSize = (maxWidth.value / 50).sp + + Column( + modifier = Modifier + .fillMaxWidth() + .background(Color.DarkGray) + .padding(8.dp), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Text( + text = remainingTime, + color = Color.White, + fontSize = fontSize + ) + } + } + } + } +} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/org/example/project/ui/Screens/ForSponsor.kt b/composeApp/src/commonMain/kotlin/org/example/project/ui/Screens/ForSponsor.kt new file mode 100644 index 0000000..f9ab453 --- /dev/null +++ b/composeApp/src/commonMain/kotlin/org/example/project/ui/Screens/ForSponsor.kt @@ -0,0 +1,464 @@ +package org.example.project.ui.Screens + +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.BoxWithConstraints +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.aspectRatio +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.layout.wrapContentWidth +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.Button +import androidx.compose.material.ButtonDefaults +import androidx.compose.material.Icon +import androidx.compose.material.MaterialTheme +import androidx.compose.material.OutlinedTextField +import androidx.compose.material.Scaffold +import androidx.compose.material.Text +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.DateRange +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +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.font.FontWeight +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import cafe.adriel.voyager.core.screen.Screen +import cafe.adriel.voyager.navigator.LocalNavigator +import cafe.adriel.voyager.navigator.currentOrThrow +import org.example.project.ViewModel.FieldWithDropdown +import org.example.project.ViewModel.FieldWithLabel +import org.example.project.ViewModel.TimerViewModel + +class ForSponsorScreen(private val timerViewModel: TimerViewModel) : Screen { + + @Composable + override fun Content() { + val navigator = LocalNavigator.currentOrThrow + + Scaffold( + topBar = { ForSponsorTopBar() }, + bottomBar = { ForSposnorBottomBar(timerViewModel = timerViewModel) } + ) { paddingValues -> + + Box( + modifier = Modifier.padding(paddingValues) + ) { + BoxWithConstraints( + modifier = Modifier + .fillMaxWidth() + .align(Alignment.Center) + .padding(horizontal = 100.dp) + ) { + val fontSize = (maxWidth.value / 60).sp + val fontSizeFirst = (maxWidth.value / 30).sp + val fontSizeSecond = (maxWidth.value / 40).sp + val fontSizeThird = (maxWidth.value / 50).sp + val fontSizeFourth = (maxWidth.value / 10).sp + val labelWidth = 0.5f + var fio by remember { mutableStateOf("") } + val runners = listOf( + "bob", + "bobby", + "baby" + ) + var runner by remember { mutableStateOf("") } + var cardName by remember { mutableStateOf("") } + var cardNum by remember { mutableStateOf("") } + var srokM by remember { mutableStateOf("") } + var srokY by remember { mutableStateOf("") } + var cvc by remember { mutableStateOf("") } + var sumChangStr by remember { mutableStateOf("10")} + var sumChang by remember { mutableStateOf(sumChangStr.toInt()) } + var sumSpons by remember { mutableStateOf(0)} + + Column( + modifier = Modifier + .fillMaxWidth().padding(bottom = 16.dp), + horizontalAlignment = Alignment.CenterHorizontally, + ) { + Text( + text = "Спонсор бегуна", + color = Color.DarkGray, + textAlign = TextAlign.Center, + fontSize = fontSizeFirst, + modifier = Modifier.fillMaxWidth() + ) + + Spacer(Modifier.weight(0.1f)) + + Text( + text = "Пожалуйста выберите бегуна, которого вы хотели бы спонсировать и сумму, которую вы хотели бы спонсировать. Спасибо за вашу поддержку бегунов и их благотворительных учреждений.", + color = Color.DarkGray, + textAlign = TextAlign.Center, + fontSize = fontSizeSecond, + modifier = Modifier.fillMaxWidth(), + ) + + Spacer(Modifier.weight(0.2f)) + + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(16.dp) + ) { + Column(modifier = Modifier.weight(1f),) { + Spacer(modifier = Modifier.weight(0.1f)) + + Box(modifier = Modifier.fillMaxWidth()) { + Text( + text = "Информация о спонсоре", + color = Color.LightGray, + textAlign = TextAlign.Center, + fontSize = fontSizeFirst, + modifier = Modifier.align(Alignment.Center) + ) + } + + Spacer(modifier = Modifier.weight(0.1f)) + + FieldWithLabel( + label = "Ваше имя:", + value = fio, + onValueChange = { fio = it }, + placeholder = "Ваше имя", + fontSize = fontSizeSecond, + labelWidth = labelWidth, + ) + + Spacer(modifier = Modifier.weight(0.1f)) + + FieldWithDropdown( + label = "Бегун:", + options = runners, + selectedOption = runner, + onOptionSelected = { runner = it }, + fontSize = fontSizeSecond, + labelWidth = labelWidth + ) + + Spacer(modifier = Modifier.weight(0.1f)) + + FieldWithLabel( + label = "Карта:", + value = cardName, + onValueChange = { cardName = it }, + placeholder = "Владелец карты", + fontSize = fontSizeSecond, + labelWidth = labelWidth, + ) + + Spacer(modifier = Modifier.weight(0.1f)) + + FieldWithLabel( + label = "Номер карты#:", + value = cardNum, + onValueChange = { cardNum = it }, + placeholder = "...", + fontSize = fontSizeSecond, + labelWidth = labelWidth, + ) + + Spacer(modifier = Modifier.weight(0.1f)) + + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier.fillMaxWidth() + ) { + Text( + text = "Срок действия:", + fontSize = fontSizeSecond, + color = Color.Black, + modifier = Modifier.weight(labelWidth) + ) + + OutlinedTextField( + value = srokM, + onValueChange = { srokM = it }, + placeholder = { Text("MM", fontSize = fontSizeSecond) }, + textStyle = androidx.compose.ui.text.TextStyle( + fontSize = fontSizeSecond, + color = Color.Black + ), + modifier = Modifier + .weight((1f - labelWidth) / 2) + .padding(end = 4.dp), + singleLine = true + ) + + OutlinedTextField( + value = srokY, + onValueChange = { srokY = it }, + placeholder = { Text("YY", fontSize = fontSizeSecond) }, + textStyle = androidx.compose.ui.text.TextStyle( + fontSize = fontSizeSecond, + color = Color.Black + ), + modifier = Modifier + .weight((1f - labelWidth) / 2) + .padding(start = 4.dp), + singleLine = true + ) + } + + Spacer(modifier = Modifier.weight(0.1f)) + + FieldWithLabel( + label = "CVC:", + value = cvc, + onValueChange = { cvc = it }, + placeholder = "...", + fontSize = fontSizeSecond, + labelWidth = labelWidth, + ) + } + + Column(modifier = Modifier.weight(1f),) { + Spacer(modifier = Modifier.weight(0.1f)) + + Box(modifier = Modifier.fillMaxWidth()) { + Text( + text = "Благотворительность", + color = Color.LightGray, + textAlign = TextAlign.Center, + fontSize = fontSizeFirst, + modifier = Modifier.align(Alignment.Center) + ) + } + + Spacer(modifier = Modifier.weight(0.1f)) + + Box(modifier = Modifier.fillMaxWidth()) { + Text( + text = "blagot...", + color = Color.Black, + textAlign = TextAlign.Center, + fontSize = fontSizeSecond, + modifier = Modifier.align(Alignment.Center) + ) + } + + Spacer(modifier = Modifier.weight(0.5f)) + + Box(modifier = Modifier.fillMaxWidth()) { + Text( + text = "Сумма пожертвования", + color = Color.LightGray, + textAlign = TextAlign.Center, + fontSize = fontSizeFirst, + modifier = Modifier.align(Alignment.Center) + ) + } + + Spacer(modifier = Modifier.weight(0.1f)) + + Box(modifier = Modifier.fillMaxWidth()) { + Text( + text = "$" + sumSpons.toString(), + color = Color.LightGray, + textAlign = TextAlign.Center, + fontSize = fontSizeFourth, + modifier = Modifier.align(Alignment.Center) + ) + } + + Spacer(modifier = Modifier.weight(0.1f)) + + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier.fillMaxWidth() + ) { + Button( + modifier = Modifier + .weight(0.2f) + .aspectRatio(1f), + onClick = { + sumSpons -= sumChang + }, + shape = RoundedCornerShape(8.dp), + colors = ButtonDefaults.buttonColors( + backgroundColor = Color.LightGray, + contentColor = Color.Black + ), + ) { + Text("-", fontSize = fontSizeSecond) + } + + OutlinedTextField( + value = sumChangStr, + onValueChange = { + sumChangStr = it + sumChang = it.toIntOrNull() ?: 0 + }, + placeholder = { Text("...", fontSize = fontSizeSecond) }, + textStyle = androidx.compose.ui.text.TextStyle( + fontSize = fontSizeSecond, + color = Color.Black, + textAlign = TextAlign.Center + ), + modifier = Modifier + .weight(0.6f) + .padding(horizontal = 4.dp), + singleLine = true + ) + + Button( + modifier = Modifier + .weight(0.2f) + .aspectRatio(1f), + onClick = { + sumSpons += sumChang + }, + shape = RoundedCornerShape(8.dp), + colors = ButtonDefaults.buttonColors( + backgroundColor = Color.LightGray, + contentColor = Color.Black + ), + ) { + Text("+", fontSize = fontSizeSecond) + } + } + + Spacer(modifier = Modifier.weight(0.5f)) + + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceEvenly, + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp, vertical = 8.dp) + ) { + Button( + onClick = { navigator.push(ConfirmSponsorScreen(timerViewModel, sumSpons.toString(), runner, "blagodat..."))}, + modifier = Modifier.weight(1f), + colors = ButtonDefaults.buttonColors( + backgroundColor = Color.LightGray, + contentColor = Color.Black + ), + shape = RoundedCornerShape(15.dp) + ) { + Text("Заплатить", fontSize = fontSizeThird) + } + + Spacer(modifier = Modifier.weight(0.1f)) + + Button( + onClick = { navigator.push(MainScreen()) }, + modifier = Modifier.weight(1f), + colors = ButtonDefaults.buttonColors( + backgroundColor = Color.LightGray, + contentColor = Color.Black + ), + shape = RoundedCornerShape(15.dp) + ) { + Text("Отмена", fontSize = fontSizeThird) + } + } + } + } + } + } + } + } + } + + @Composable + private fun ForSponsorTopBar() { + val navigator = LocalNavigator.currentOrThrow + + Box { + BoxWithConstraints( + modifier = Modifier + .fillMaxWidth() + .align(Alignment.Center) + ) { + val fontSizeButton = (maxWidth.value / 50).sp + val fontSizeText = (maxWidth.value / 25).sp + + Row( + modifier = Modifier + .fillMaxWidth() + .background(Color.DarkGray) + .padding(16.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween + ) { + + Button( + onClick = { }, + colors = ButtonDefaults.buttonColors( + backgroundColor = Color.LightGray, + contentColor = Color.Black + ), + elevation = null, + shape = RoundedCornerShape(15.dp), + modifier = Modifier + .wrapContentWidth() + + ) { + Text( + text = "Назад", + color = Color.Black, + fontSize = fontSizeButton + ) + } + + Spacer(modifier = Modifier.width(24.dp)) + + Text( + text = "MARATHON SKILLS 2016", + style = MaterialTheme.typography.h6, + modifier = Modifier.weight(1f), + textAlign = TextAlign.Left, + fontWeight = FontWeight.Bold, + fontSize = fontSizeText, + color = Color.White + ) + } + } + } + } + + + + @Composable + private fun ForSposnorBottomBar(timerViewModel: TimerViewModel) { + val remainingTime = timerViewModel.remainingTime.collectAsState().value + Box { + BoxWithConstraints( + modifier = Modifier + .align(Alignment.Center) + ) { + val fontSize = (maxWidth.value / 50).sp + + Column( + modifier = Modifier + .fillMaxWidth() + .background(Color.DarkGray) + .padding(8.dp), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Text( + text = remainingTime, + color = Color.White, + fontSize = fontSize + ) + } + } + } + } +} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/org/example/project/ui/Screens/InfoRunner.kt b/composeApp/src/commonMain/kotlin/org/example/project/ui/Screens/InfoRunner.kt new file mode 100644 index 0000000..92aa58a --- /dev/null +++ b/composeApp/src/commonMain/kotlin/org/example/project/ui/Screens/InfoRunner.kt @@ -0,0 +1,234 @@ +package org.example.project.ui.Screens + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.BoxWithConstraints +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.layout.wrapContentWidth +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.Button +import androidx.compose.material.ButtonDefaults +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Scaffold +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.font.FontStyle +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.TextUnit +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import cafe.adriel.voyager.core.screen.Screen +import cafe.adriel.voyager.navigator.LocalNavigator +import cafe.adriel.voyager.navigator.currentOrThrow +import org.example.project.ViewModel.TimerViewModel + + +class InfoRunnerScreen(private val timerViewModel: TimerViewModel) : Screen { + + @Composable + override fun Content() { + val navigator = LocalNavigator.currentOrThrow + + Scaffold( + topBar = { InfoRunnerTopBar() }, + bottomBar = { InfoRunnerBottomBar(timerViewModel = timerViewModel) } + ) { paddingValues -> + + Box( + modifier = Modifier + .padding(paddingValues) + ) { + BoxWithConstraints( + modifier = Modifier + .fillMaxWidth() + .align(Alignment.Center) + .padding(horizontal = 100.dp) + ) { + val fontSize = (maxWidth.value / 25).sp + val fontSizeButton = (maxWidth.value / 40).sp + + Column( + modifier = Modifier + .padding(16.dp) + .fillMaxSize(), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.SpaceBetween + ) { + Text( + text = "Подробная информация", + color = Color.DarkGray, + textAlign = TextAlign.Center, + fontSize = fontSize, + ) + + Row( + modifier = Modifier + .fillMaxWidth() + .weight(1f), + horizontalArrangement = Arrangement.SpaceEvenly, + verticalAlignment = Alignment.CenterVertically + ) { + Column( + modifier = Modifier + .weight(1f) + .padding(end = 8.dp), + verticalArrangement = Arrangement.spacedBy(16.dp), + horizontalAlignment = Alignment.CenterHorizontally + ) { + InfoButton("Регистрация на марафон", fontSizeButton) + InfoButton("Редактирование профиля", fontSizeButton) + InfoButton("Контакты", fontSizeButton) + } + + Column( + modifier = Modifier + .weight(1f) + .padding(start = 8.dp), + verticalArrangement = Arrangement.spacedBy(16.dp), + horizontalAlignment = Alignment.CenterHorizontally + ) { + InfoButton("Мои результаты", fontSizeButton) + InfoButton("Мои спонсоры", fontSizeButton) + } + } + } + } + } + } + } + + @Composable + private fun InfoButton(text: String, fontSize: TextUnit) { + Button( + onClick = { }, + modifier = Modifier + .fillMaxWidth() + .height(80.dp), + colors = ButtonDefaults.buttonColors( + backgroundColor = Color.LightGray, + contentColor = Color.Black + ), + shape = RoundedCornerShape(15.dp) + ) { + Text(text = text, fontStyle = FontStyle.Italic, fontSize = fontSize, textAlign = TextAlign.Center) + } + } + + @Composable + private fun InfoRunnerTopBar() { + val navigator = LocalNavigator.currentOrThrow + + Box { + BoxWithConstraints( + modifier = Modifier + .fillMaxWidth() + .align(Alignment.Center) + ) { + val fontSizeButton = (maxWidth.value / 50).sp + val fontSizeText = (maxWidth.value / 25).sp + + Row( + modifier = Modifier + .fillMaxWidth() + .background(Color.DarkGray) + .padding(16.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween + ) { + + Button( + onClick = { navigator.push(MainScreen()) }, + colors = ButtonDefaults.buttonColors( + backgroundColor = Color.LightGray, + contentColor = Color.Black + ), + elevation = null, + shape = RoundedCornerShape(15.dp), + modifier = Modifier + .wrapContentWidth() + + ) { + Text( + text = "Назад", + color = Color.Black, + fontSize = fontSizeButton + ) + } + + Spacer(modifier = Modifier.width(24.dp)) + + Text( + text = "MARATHON SKILLS 2016", + style = MaterialTheme.typography.h6, + modifier = Modifier.weight(1f), + textAlign = TextAlign.Left, + fontWeight = FontWeight.Bold, + fontSize = fontSizeText, + color = Color.White + ) + + Spacer(modifier = Modifier.width(64.dp)) + + Button( + onClick = { navigator.push(MainScreen()) }, + colors = ButtonDefaults.buttonColors( + backgroundColor = Color.LightGray, + contentColor = Color.Black + ), + elevation = null, + shape = RoundedCornerShape(15.dp), + modifier = Modifier + .wrapContentWidth() + + ) { + Text( + text = "Logout", + color = Color.Black, + fontSize = fontSizeButton + ) + } + } + } + } + } + + @Composable + private fun InfoRunnerBottomBar(timerViewModel: TimerViewModel) { + val remainingTime = timerViewModel.remainingTime.collectAsState().value + Box { + BoxWithConstraints( + modifier = Modifier + .align(Alignment.Center) + ) { + val fontSize = (maxWidth.value / 50).sp + + Column( + modifier = Modifier + .fillMaxWidth() + .background(Color.DarkGray) + .padding(8.dp), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Text( + text = remainingTime, + color = Color.White, + fontSize = fontSize + ) + } + } + } + } +} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/org/example/project/ui/Screens/Login.kt b/composeApp/src/commonMain/kotlin/org/example/project/ui/Screens/Login.kt index a01febf..4c78cb1 100644 --- a/composeApp/src/commonMain/kotlin/org/example/project/ui/Screens/Login.kt +++ b/composeApp/src/commonMain/kotlin/org/example/project/ui/Screens/Login.kt @@ -38,6 +38,7 @@ import androidx.compose.ui.unit.sp import cafe.adriel.voyager.core.screen.Screen import cafe.adriel.voyager.navigator.LocalNavigator import cafe.adriel.voyager.navigator.currentOrThrow +import org.example.project.ViewModel.FieldWithLabel import org.example.project.ViewModel.TimerViewModel class LoginScreen(private val timerViewModel: TimerViewModel) : Screen { @@ -63,7 +64,7 @@ class LoginScreen(private val timerViewModel: TimerViewModel) : Screen { val fontSize = (maxWidth.value / 25).sp val fontSizeFirst = (maxWidth.value / 20).sp val fontSizeSecond = (maxWidth.value / 35).sp - val labelWidth = 120.dp + val labelWidth = 0.25f var email by remember { mutableStateOf("") } var password by remember { mutableStateOf("") } @@ -94,69 +95,25 @@ class LoginScreen(private val timerViewModel: TimerViewModel) : Screen { Spacer(Modifier.weight(0.25f)) - Row( - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.Center, - modifier = Modifier.fillMaxWidth() - ) { - Box(modifier = Modifier.width(labelWidth)) { - Text( - text = "Email:", - color = Color.DarkGray, - textAlign = TextAlign.Start, - fontSize = fontSize, - modifier = Modifier.padding(start = 40.dp), - ) - } - - TextField( - value = email, - onValueChange = { email = it }, - placeholder = { - Text( - text = "Enter your email address", - fontSize = fontSize, - color = Color.LightGray - ) - }, - textStyle = androidx.compose.ui.text.TextStyle( - fontSize = fontSize - ), - modifier = Modifier - .weight(1f) - ) - } + FieldWithLabel( + label = "Email:", + value = email, + onValueChange = { email = it }, + placeholder = "Enter your email address", + fontSize = fontSize, + labelWidth = labelWidth, + ) Spacer(Modifier.weight(0.25f)) - Row( - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.Center, - modifier = Modifier.fillMaxWidth() - ) { - Box(modifier = Modifier.width(labelWidth)) { - Text( - text = "Password:", - color = Color.DarkGray, - textAlign = TextAlign.Start, - fontSize = fontSize, - ) - } - - TextField( - value = password, - onValueChange = { password = it }, - placeholder = { - Text( - text = "Enter your password", - fontSize = fontSize, - color = Color.LightGray - ) - }, - modifier = Modifier - .weight(1f) - ) - } + FieldWithLabel( + label = "Password:", + value = password, + onValueChange = { password = it }, + placeholder = "Enter your password", + fontSize = fontSize, + labelWidth = labelWidth, + ) Spacer(Modifier.weight(0.25f)) @@ -165,7 +122,7 @@ class LoginScreen(private val timerViewModel: TimerViewModel) : Screen { horizontalArrangement = Arrangement.Center ) { Button( - onClick = { }, + onClick = { navigator.push(InfoRunnerScreen(timerViewModel))}, modifier = Modifier .fillMaxWidth() .weight(1f), @@ -184,7 +141,7 @@ class LoginScreen(private val timerViewModel: TimerViewModel) : Screen { Spacer(Modifier.weight(0.25f)) Button( - onClick = { }, + onClick = { navigator.push(MainScreen()) }, modifier = Modifier .fillMaxWidth() .weight(1f), diff --git a/composeApp/src/commonMain/kotlin/org/example/project/ui/Screens/MainScreen.kt b/composeApp/src/commonMain/kotlin/org/example/project/ui/Screens/MainScreen.kt index ab7aeac..27db258 100644 --- a/composeApp/src/commonMain/kotlin/org/example/project/ui/Screens/MainScreen.kt +++ b/composeApp/src/commonMain/kotlin/org/example/project/ui/Screens/MainScreen.kt @@ -65,7 +65,7 @@ class MainScreen : Screen { Spacer(modifier = Modifier.height(16.dp)) Button( - onClick = { }, + onClick = { navigator.push(ForSponsorScreen(timerViewModel))}, modifier = Modifier .fillMaxWidth() .weight(1f), diff --git a/composeApp/src/commonMain/kotlin/org/example/project/ui/Screens/RegMaraphon.kt b/composeApp/src/commonMain/kotlin/org/example/project/ui/Screens/RegMaraphon.kt new file mode 100644 index 0000000..ffe27c4 --- /dev/null +++ b/composeApp/src/commonMain/kotlin/org/example/project/ui/Screens/RegMaraphon.kt @@ -0,0 +1,415 @@ +package org.example.project.ui.Screens + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.BoxWithConstraints +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.layout.wrapContentWidth +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.Button +import androidx.compose.material.ButtonDefaults +import androidx.compose.material.Checkbox +import androidx.compose.material.MaterialTheme +import androidx.compose.material.RadioButton +import androidx.compose.material.Scaffold +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import cafe.adriel.voyager.core.screen.Screen +import cafe.adriel.voyager.navigator.LocalNavigator +import cafe.adriel.voyager.navigator.currentOrThrow +import org.example.project.ViewModel.FieldWithDropdown +import org.example.project.ViewModel.FieldWithLabel +import org.example.project.ViewModel.FieldWithLabelInt +import org.example.project.ViewModel.TimerViewModel + +class RegMaraphonScreen(private val timerViewModel: TimerViewModel) : Screen { + + @Composable + override fun Content() { + val navigator = LocalNavigator.currentOrThrow + + Scaffold( + topBar = { RegMaraphonTopBar() }, + bottomBar = { RegMaraphonBottomBar(timerViewModel = timerViewModel) } + ) { paddingValues -> + + Box( + modifier = Modifier.padding(paddingValues) + ) { + BoxWithConstraints( + modifier = Modifier + .fillMaxWidth() + .align(Alignment.Center) + .padding(horizontal = 100.dp) + ) { + val fontSize = (maxWidth.value / 60).sp + val fontSizeFirst = (maxWidth.value / 30).sp + val fontSizeSecond = (maxWidth.value / 40).sp + val fontSizeThird = (maxWidth.value / 50).sp + val fontSizeFourth = (maxWidth.value / 10).sp + var finalSum by remember { mutableStateOf(0) } + var previousAddonPrice by remember { mutableStateOf(0) } + var checked1 by remember { mutableStateOf(false) } + var checked2 by remember { mutableStateOf(false) } + var checked3 by remember { mutableStateOf(false) } + val options = listOf( + "Вариант А($0): Номер бегуна + RFID браслет", + "Вариант B($20): вариант A + бейсболка + бутылка воды", + "Вариант C($45): Вариант B + футболка + сувенирный буклет" + ) + var blagi = listOf( + "Что-то", + "Ещё что-то" + ) + var selectedOption by remember { mutableStateOf(options[0]) } + var vznos by remember { mutableStateOf("")} + var sumVznos by remember { mutableStateOf(0)} + + Column( + modifier = Modifier + .fillMaxWidth().padding(bottom = 16.dp), + horizontalAlignment = Alignment.CenterHorizontally, + ) { + Text( + text = "Регистрация на марафон", + color = Color.DarkGray, + textAlign = TextAlign.Center, + fontSize = fontSizeFirst, + modifier = Modifier.fillMaxWidth() + ) + + Spacer(Modifier.weight(0.1f)) + + Text( + text = "Пожалуйста, заполните всю информацию, чтобы зарегестрироваться на Skills Marathon 2016 проводимом в Москве. Russia. С вами свяжутся после регистрации для уточнения оплаты и другой информации.", + color = Color.DarkGray, + textAlign = TextAlign.Center, + fontSize = fontSizeSecond, + modifier = Modifier.fillMaxWidth(), + ) + + Spacer(Modifier.weight(0.2f)) + + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(16.dp) + ) { + Column(modifier = Modifier.weight(1f), ) { + Spacer(modifier = Modifier.weight(0.1f)) + + Text( + text = "Вид марафона", + color = Color.LightGray, + textAlign = TextAlign.Center, + fontSize = fontSizeFirst, + modifier = Modifier + ) + + Row(verticalAlignment = Alignment.CenterVertically) { + Checkbox( + checked = checked1, + onCheckedChange = { isChecked -> + checked1 = isChecked + if (isChecked) { + finalSum += 145 + } else { + finalSum -= 145 + } + } + ) + Spacer(modifier = Modifier.width(8.dp)) + Text(text = "42km Полный марафон($145)", fontSize = fontSizeSecond) + } + + Row(verticalAlignment = Alignment.CenterVertically) { + Checkbox( + checked = checked2, + onCheckedChange = { isChecked -> + checked2 = isChecked + if (isChecked) { + finalSum += 75 + } else { + finalSum -= 75 + } + } + ) + Spacer(modifier = Modifier.width(8.dp)) + Text(text = "21km Поулмарафон($75)", fontSize = fontSizeSecond) + } + + Row(verticalAlignment = Alignment.CenterVertically) { + Checkbox( + checked = checked3, + onCheckedChange = { isChecked -> + checked3 = isChecked + if (isChecked) { + finalSum += 20 + } else { + finalSum -= 20 + } + } + ) + Spacer(modifier = Modifier.width(8.dp)) + Text(text = "5km Малая дистанция($20)", fontSize = fontSizeSecond) + } + + Text( + text = "Детали спонсорства", + color = Color.LightGray, + textAlign = TextAlign.Center, + fontSize = fontSizeFirst, + modifier = Modifier + ) + + FieldWithDropdown( + label = "Взнос:", + options = blagi, + selectedOption = vznos, + onOptionSelected = { vznos = it }, + fontSize = fontSizeSecond, + labelWidth = 0.5f + ) + + Spacer(modifier = Modifier.weight(0.1f)) + + FieldWithLabelInt( + label = "Сумма взноса:", + value = sumVznos, + onValueChange = { sumVznos = it }, + placeholder = "$$$", + fontSize = fontSizeSecond, + labelWidth = 0.5f, + ) + + Spacer(modifier = Modifier.weight(0.1f)) + + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceEvenly, + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp, vertical = 8.dp) + ) { + Button( + onClick = { navigator.push(ConfirmRunnerScreen(timerViewModel))}, + modifier = Modifier.weight(1f), + colors = ButtonDefaults.buttonColors( + backgroundColor = Color.LightGray, + contentColor = Color.Black + ), + shape = RoundedCornerShape(15.dp) + ) { + Text("Регистрация", fontSize = fontSizeThird) + } + + Spacer(modifier = Modifier.weight(0.1f)) + + Button( + onClick = { navigator.push(MainScreen()) }, + modifier = Modifier.weight(1f), + colors = ButtonDefaults.buttonColors( + backgroundColor = Color.LightGray, + contentColor = Color.Black + ), + shape = RoundedCornerShape(15.dp) + ) { + Text("Отмена", fontSize = fontSizeThird) + } + } + } + + Column(modifier = Modifier.weight(1f)) { + Spacer(modifier = Modifier.weight(0.1f)) + + Box(modifier = Modifier.fillMaxWidth()) { + Text( + text = "Варианты комплектов", + color = Color.LightGray, + textAlign = TextAlign.Center, + fontSize = fontSizeFirst, + modifier = Modifier.align(Alignment.Center) + ) + } + + options.forEach { text -> + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.Center + ) { + RadioButton( + selected = (text == selectedOption), + onClick = { + val newAddonPrice = when (text) { + options[0] -> 0 + options[1] -> 20 + options[2] -> 45 + else -> 0 + } + + finalSum = finalSum - previousAddonPrice + newAddonPrice + + previousAddonPrice = newAddonPrice + selectedOption = text + } + ) + Spacer(modifier = Modifier.weight(0.01f)) + Text(text = text, fontSize = fontSizeSecond) + } + } + + Spacer(modifier = Modifier.weight(0.1f)) + + Box(modifier = Modifier.fillMaxWidth()) { + Text( + text = "Регистрационный взнос", + color = Color.LightGray, + textAlign = TextAlign.Center, + fontSize = fontSizeFirst, + modifier = Modifier.align(Alignment.Center) + ) + } + + Spacer(modifier = Modifier.weight(0.1f)) + + Box(modifier = Modifier.fillMaxWidth()) { + Text( + text = "$" + finalSum.toString(), + color = Color.LightGray, + textAlign = TextAlign.Center, + fontSize = fontSizeFourth, + modifier = Modifier.align(Alignment.Center) + ) + } + } + } + } + } + } + } + } + + @Composable + private fun RegMaraphonTopBar() { + val navigator = LocalNavigator.currentOrThrow + + Box { + BoxWithConstraints( + modifier = Modifier + .fillMaxWidth() + .align(Alignment.Center) + ) { + val fontSizeButton = (maxWidth.value / 50).sp + val fontSizeText = (maxWidth.value / 25).sp + + Row( + modifier = Modifier + .fillMaxWidth() + .background(Color.DarkGray) + .padding(16.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween + ) { + + Button( + onClick = { }, + colors = ButtonDefaults.buttonColors( + backgroundColor = Color.LightGray, + contentColor = Color.Black + ), + elevation = null, + shape = RoundedCornerShape(15.dp), + modifier = Modifier + .wrapContentWidth() + + ) { + Text( + text = "Назад", + color = Color.Black, + fontSize = fontSizeButton + ) + } + + Spacer(modifier = Modifier.width(24.dp)) + + Text( + text = "MARATHON SKILLS 2016", + style = MaterialTheme.typography.h6, + modifier = Modifier.weight(1f), + textAlign = TextAlign.Left, + fontWeight = FontWeight.Bold, + fontSize = fontSizeText, + color = Color.White + ) + + Spacer(modifier = Modifier.width(64.dp)) + + Button( + onClick = { navigator.push(MainScreen()) }, + colors = ButtonDefaults.buttonColors( + backgroundColor = Color.LightGray, + contentColor = Color.Black + ), + elevation = null, + shape = RoundedCornerShape(15.dp), + modifier = Modifier + .wrapContentWidth() + + ) { + Text( + text = "Logout", + color = Color.Black, + fontSize = fontSizeButton + ) + } + } + } + } + } + + + + @Composable + private fun RegMaraphonBottomBar(timerViewModel: TimerViewModel) { + val remainingTime = timerViewModel.remainingTime.collectAsState().value + Box { + BoxWithConstraints( + modifier = Modifier + .align(Alignment.Center) + ) { + val fontSize = (maxWidth.value / 50).sp + + Column( + modifier = Modifier + .fillMaxWidth() + .background(Color.DarkGray) + .padding(8.dp), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Text( + text = remainingTime, + color = Color.White, + fontSize = fontSize + ) + } + } + } + } +} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/org/example/project/ui/Screens/RegRunner.kt b/composeApp/src/commonMain/kotlin/org/example/project/ui/Screens/RegRunner.kt index 71a6a5e..52dfe42 100644 --- a/composeApp/src/commonMain/kotlin/org/example/project/ui/Screens/RegRunner.kt +++ b/composeApp/src/commonMain/kotlin/org/example/project/ui/Screens/RegRunner.kt @@ -1,23 +1,40 @@ package org.example.project.ui.Screens import androidx.compose.foundation.background +import androidx.compose.foundation.Image +import androidx.compose.ui.res.painterResource +import androidx.compose.foundation.border +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.BoxWithConstraints import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.wrapContentWidth +import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.Button import androidx.compose.material.ButtonDefaults +import androidx.compose.material.DropdownMenu +import androidx.compose.material.DropdownMenuItem +import androidx.compose.material.Icon +import androidx.compose.material.IconButton import androidx.compose.material.MaterialTheme +import androidx.compose.material.OutlinedTextField import androidx.compose.material.Scaffold import androidx.compose.material.Text import androidx.compose.material.TextField +import androidx.compose.material.contentColorFor +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.ArrowDropDown +import androidx.compose.material.icons.filled.DateRange import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue @@ -26,6 +43,7 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue 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.font.FontWeight import androidx.compose.ui.text.style.TextAlign @@ -36,6 +54,11 @@ import androidx.compose.ui.unit.sp import cafe.adriel.voyager.core.screen.Screen import cafe.adriel.voyager.navigator.LocalNavigator import cafe.adriel.voyager.navigator.currentOrThrow +import org.example.project.ViewModel.DatePickerField +import org.example.project.ViewModel.FieldWithDropdown +import org.example.project.ViewModel.FieldWithLabel +import org.example.project.ViewModel.GetPath +import org.example.project.ViewModel.ImageFromPath import org.example.project.ViewModel.TimerViewModel class RegRunnerScreen(private val timerViewModel: TimerViewModel) : Screen { @@ -46,31 +69,53 @@ class RegRunnerScreen(private val timerViewModel: TimerViewModel) : Screen { Scaffold( topBar = { RegRunnerTopBar() }, - bottomBar = { RegRunnerBottomBar(timerViewModel = timerViewModel) } + bottomBar = { BottomSection(timerViewModel = timerViewModel) } ) { paddingValues -> Box( - modifier = Modifier.padding(paddingValues) + modifier = Modifier.padding(paddingValues).fillMaxSize() ) { BoxWithConstraints( modifier = Modifier .fillMaxWidth() .align(Alignment.Center) - .padding(horizontal = 100.dp) + .padding(horizontal = 10.dp) ) { - val fontSize = (maxWidth.value / 25).sp - val fontSizeFirst = (maxWidth.value / 20).sp - val fontSizeSecond = (maxWidth.value / 35).sp - val labelWidth = 120.dp + val fontSize = (maxWidth.value / 60).sp + val fontSizeFirst = (maxWidth.value / 30).sp + val fontSizeSecond = (maxWidth.value / 40).sp + val labelWidth = 0.5f var email by remember { mutableStateOf("") } var password by remember { mutableStateOf("") } + var secondPassword by remember { mutableStateOf("") } + var name by remember { mutableStateOf("") } + var surname by remember { mutableStateOf("") } + var gender by remember { mutableStateOf("") } + var country by remember { mutableStateOf("") } + var photoPath by remember { mutableStateOf("") } + var openPicker by remember { mutableStateOf(false) } + if (openPicker) { + GetPath { selected -> + photoPath = selected + openPicker = false + } + } + var showDatePicker by remember { mutableStateOf(false) } + var dateBirthday by remember { mutableStateOf("") } + if (showDatePicker) { + DatePickerField( + onDateSelected = { + dateBirthday = it + }, + trigger = true, + onDismissRequest = { showDatePicker = false } + ) + } Column( modifier = Modifier - .fillMaxWidth(), + .fillMaxWidth().padding(bottom = 16.dp), horizontalAlignment = Alignment.CenterHorizontally, ) { - Spacer(Modifier.weight(0.25f)) - Text( text = "Регистрация бегуна", color = Color.DarkGray, @@ -79,7 +124,7 @@ class RegRunnerScreen(private val timerViewModel: TimerViewModel) : Screen { modifier = Modifier.fillMaxWidth() ) - Spacer(Modifier.weight(0.25f)) + Spacer(Modifier.weight(0.1f)) Text( text = "Пожалуйста, заполните всю информацию, чтобы зарегестрироваться в качестве участника", @@ -93,50 +138,224 @@ class RegRunnerScreen(private val timerViewModel: TimerViewModel) : Screen { Row( modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.spacedBy(32.dp) + horizontalArrangement = Arrangement.spacedBy(16.dp) ) { - Column(modifier = Modifier.weight(1f)) { + Column(modifier = Modifier.weight(0.8f)) { + Spacer(modifier = Modifier.weight(0.1f)) + FieldWithLabel( label = "Email:", value = email, onValueChange = { email = it }, - placeholder = "Enter your email address", + placeholder = "Email", fontSize = fontSize, - labelWidth = labelWidth + labelWidth = labelWidth, ) Spacer(modifier = Modifier.weight(0.1f)) FieldWithLabel( - label = "Password:", + label = "Пароль:", value = password, onValueChange = { password = it }, - placeholder = "Enter your password", + placeholder = "Пароль", + fontSize = fontSize, + labelWidth = labelWidth, + ) + + Spacer(modifier = Modifier.weight(0.1f)) + + FieldWithLabel( + label = "Повторите пароль:", + value = secondPassword, + onValueChange = { secondPassword = it }, + placeholder = "Повторите пароль", + fontSize = fontSize, + labelWidth = labelWidth, + ) + + Spacer(modifier = Modifier.weight(0.1f)) + + FieldWithLabel( + label = "Имя:", + value = name, + onValueChange = { name = it }, + placeholder = "Имя", + fontSize = fontSize, + labelWidth = labelWidth, + ) + + Spacer(modifier = Modifier.weight(0.1f)) + + FieldWithLabel( + label = "Фамилия:", + value = surname, + onValueChange = { surname = it }, + placeholder = "Фамилия", + fontSize = fontSize, + labelWidth = labelWidth, + ) + + Spacer(modifier = Modifier.weight(0.1f)) + + FieldWithDropdown( + label = "Пол:", + options = listOf("Мужской", "Остальное"), + selectedOption = gender, + onOptionSelected = { gender = it }, fontSize = fontSize, labelWidth = labelWidth ) } Column(modifier = Modifier.weight(1f)) { - FieldWithLabel( - label = "Email:", - value = email, - onValueChange = { email = it }, - placeholder = "Enter your email address", - fontSize = fontSize, - labelWidth = labelWidth + ImageFromPath( + path = photoPath, + modifier = Modifier + .weight(0.4f) + .clip(RoundedCornerShape(8.dp)) + .border(1.dp, Color.Gray, RoundedCornerShape(8.dp)).align(Alignment.End) ) - Spacer(modifier = Modifier.weight(0.1f)) + Spacer(modifier = Modifier.weight(0.05f)) - FieldWithLabel( - label = "Password:", - value = password, - onValueChange = { password = it }, - placeholder = "Enter your password", - fontSize = fontSize, - labelWidth = labelWidth - ) + Column(modifier = Modifier.weight(0.3f)) { + Text( + text = "Фото файл:", + color = Color.DarkGray, + textAlign = TextAlign.Start, + fontSize = fontSize, + modifier = Modifier + ) + + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.Center, + modifier = Modifier.fillMaxWidth() + ) { + + OutlinedTextField( + value = photoPath, + onValueChange = {photoPath = it}, + placeholder = { + Text( + text = "Photo_logo.jpg", + fontSize = fontSize, + color = Color.LightGray + ) + }, + textStyle = androidx.compose.ui.text.TextStyle( + fontSize = fontSize, + color = Color.Black + ), + enabled = true, + colors = androidx.compose.material.TextFieldDefaults.outlinedTextFieldColors( + backgroundColor = Color.White, + cursorColor = Color.Black, + textColor = Color.Black, + placeholderColor = Color.LightGray, + focusedBorderColor = Color(0xFFCCCCCC), + unfocusedBorderColor = Color(0xFFCCCCCC), + disabledBorderColor = Color(0xFFCCCCCC) + ), + modifier = Modifier.weight(0.6f).wrapContentWidth().fillMaxWidth() + ) + + Spacer(modifier = Modifier.weight(0.05f)) + + Button( + onClick = { openPicker = true}, + modifier = Modifier + .fillMaxWidth() + .weight(0.5f), + colors = ButtonDefaults.buttonColors( + backgroundColor = Color.LightGray, + contentColor = Color.Black + ), + shape = RoundedCornerShape(15.dp) + ) { + Text( + "Просмотр", + fontSize = fontSize + ) + } + } + + Spacer(modifier = Modifier.weight(0.05f)) + + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.Center, + modifier = Modifier.fillMaxWidth() + ) { + Box(modifier = Modifier.weight(labelWidth)) { + Text( + text = "Дата рождения", + color = Color.DarkGray, + textAlign = TextAlign.Start, + fontSize = fontSize, + modifier = Modifier + ) + } + + OutlinedTextField( + value = dateBirthday, + onValueChange = {dateBirthday = it}, + placeholder = { + Text( + text = "...", + fontSize = fontSize, + color = Color.LightGray + ) + }, + textStyle = androidx.compose.ui.text.TextStyle( + fontSize = fontSize, + color = Color.Black + ), + enabled = true, + colors = androidx.compose.material.TextFieldDefaults.outlinedTextFieldColors( + backgroundColor = Color.White, + cursorColor = Color.Black, + textColor = Color.Black, + placeholderColor = Color.LightGray, + focusedBorderColor = Color(0xFFCCCCCC), + unfocusedBorderColor = Color(0xFFCCCCCC), + disabledBorderColor = Color(0xFFCCCCCC) + ), + modifier = Modifier.weight(0.9f).wrapContentWidth() + ) + + Spacer(modifier = Modifier.weight(0.05f)) + + Box( + modifier = Modifier + .weight(0.5f) + .fillMaxWidth() + .clip(RoundedCornerShape(15.dp)) + .background(Color.LightGray) + .clickable { showDatePicker = true } + .padding(vertical = 8.dp), + contentAlignment = Alignment.Center + ) { + Icon( + imageVector = Icons.Default.DateRange, + contentDescription = "Выбрать дату", + tint = Color.Black, + modifier = Modifier.size(24.dp) + ) + } + } + Spacer(modifier = Modifier.weight(0.05f)) + + FieldWithDropdown( + label = "Страна:", + options = listOf("Russia", "Other"), + selectedOption = country, + onOptionSelected = { country = it }, + fontSize = fontSize, + labelWidth = labelWidth + ) + } } } } @@ -145,48 +364,6 @@ class RegRunnerScreen(private val timerViewModel: TimerViewModel) : Screen { } } - @Composable - fun FieldWithLabel( - label: String, - value: String, - onValueChange: (String) -> Unit, - placeholder: String, - fontSize: TextUnit, - labelWidth: Dp, - enabled: Boolean = true - ) { - Row( - verticalAlignment = Alignment.CenterVertically, - modifier = Modifier.fillMaxWidth() - ) { - Box(modifier = Modifier.width(labelWidth)) { - Text( - text = label, - color = Color.DarkGray, - textAlign = TextAlign.Start, - fontSize = fontSize, - modifier = Modifier.padding(start = 40.dp), - ) - } - - TextField( - value = value, - onValueChange = onValueChange, - placeholder = { - if (placeholder.isNotEmpty()) { - Text( - text = placeholder, - fontSize = fontSize, - color = Color.LightGray - ) - } - }, - textStyle = androidx.compose.ui.text.TextStyle(fontSize = fontSize), - modifier = Modifier.weight(1f), - enabled = enabled - ) - } - } @Composable private fun RegRunnerTopBar() { @@ -250,27 +427,67 @@ class RegRunnerScreen(private val timerViewModel: TimerViewModel) : Screen { @Composable private fun RegRunnerBottomBar(timerViewModel: TimerViewModel) { val remainingTime = timerViewModel.remainingTime.collectAsState().value - Box { - BoxWithConstraints( - modifier = Modifier - .align(Alignment.Center) - ) { - val fontSize = (maxWidth.value / 50).sp - Column( - modifier = Modifier - .fillMaxWidth() - .background(Color.DarkGray) - .padding(8.dp), - horizontalAlignment = Alignment.CenterHorizontally - ) { - Text( - text = remainingTime, - color = Color.White, - fontSize = fontSize - ) - } - } + Box( + modifier = Modifier + .fillMaxWidth() + .background(Color.DarkGray) + .padding(8.dp), + contentAlignment = Alignment.Center + ) { + Text( + text = remainingTime, + color = Color.White, + fontSize = 16.sp + ) } } -} \ No newline at end of file + + @Composable + private fun BottomSection( + timerViewModel: TimerViewModel + ) { + val navigator = LocalNavigator.currentOrThrow + Column( + modifier = Modifier + .fillMaxWidth() + .background(Color.White) + ) { + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceEvenly, + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp, vertical = 8.dp) + ) { + Button( + onClick = { navigator.push(RegMaraphonScreen(timerViewModel)) }, + modifier = Modifier.weight(1f), + colors = ButtonDefaults.buttonColors( + backgroundColor = Color.LightGray, + contentColor = Color.Black + ), + shape = RoundedCornerShape(15.dp) + ) { + Text("Регистрация") + } + + Spacer(modifier = Modifier.width(16.dp)) + + Button( + onClick = { navigator.push(MainScreen()) }, + modifier = Modifier.weight(1f), + colors = ButtonDefaults.buttonColors( + backgroundColor = Color.LightGray, + contentColor = Color.Black + ), + shape = RoundedCornerShape(15.dp) + ) { + Text("Отмена") + } + } + + RegRunnerBottomBar(timerViewModel = timerViewModel) + } + } +} diff --git a/composeApp/src/desktopMain/kotlin/org/example/project/ViewModel/DatePickerField.kt b/composeApp/src/desktopMain/kotlin/org/example/project/ViewModel/DatePickerField.kt new file mode 100644 index 0000000..36155f4 --- /dev/null +++ b/composeApp/src/desktopMain/kotlin/org/example/project/ViewModel/DatePickerField.kt @@ -0,0 +1,38 @@ +package org.example.project.ViewModel + +import androidx.compose.runtime.* +import java.text.SimpleDateFormat +import javax.swing.* +import java.util.* + +@Composable +actual fun DatePickerField( + onDateSelected: (String) -> Unit, + trigger: Boolean, + onDismissRequest: () -> Unit +) { + if (trigger) { + LaunchedEffect(Unit) { + val dialog = JDialog() + dialog.title = "Выбор даты" + val model = SpinnerDateModel() + val spinner = JSpinner(model) + val panel = JPanel() + val button = JButton("OK") + panel.add(spinner) + panel.add(button) + dialog.contentPane = panel + dialog.setSize(200, 100) + + button.addActionListener { + val date = model.date + val formatted = SimpleDateFormat("dd.MM.yyyy").format(date) + onDateSelected(formatted) + dialog.dispose() + onDismissRequest() + } + + dialog.isVisible = true + } + } +} \ No newline at end of file diff --git a/composeApp/src/desktopMain/kotlin/org/example/project/ViewModel/GetPath.kt b/composeApp/src/desktopMain/kotlin/org/example/project/ViewModel/GetPath.kt new file mode 100644 index 0000000..9880649 --- /dev/null +++ b/composeApp/src/desktopMain/kotlin/org/example/project/ViewModel/GetPath.kt @@ -0,0 +1,29 @@ +package org.example.project.ViewModel + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext +import java.io.File +import javax.swing.JFileChooser + +@Composable +actual fun GetPath(onPathSelected: (String) -> Unit) { + LaunchedEffect(Unit) { + val selectedPath = withContext(Dispatchers.IO) { + val chooser = JFileChooser() + chooser.dialogTitle = "Выберите изображение" + chooser.fileSelectionMode = JFileChooser.FILES_ONLY + + val result = chooser.showOpenDialog(null) + if (result == JFileChooser.APPROVE_OPTION) { + val file: File = chooser.selectedFile + file.absolutePath + } else { + "" + } + } + + onPathSelected(selectedPath) + } +} \ No newline at end of file diff --git a/composeApp/src/desktopMain/kotlin/org/example/project/ViewModel/ImageFromPath.kt b/composeApp/src/desktopMain/kotlin/org/example/project/ViewModel/ImageFromPath.kt new file mode 100644 index 0000000..e47b3fa --- /dev/null +++ b/composeApp/src/desktopMain/kotlin/org/example/project/ViewModel/ImageFromPath.kt @@ -0,0 +1,47 @@ +package org.example.project.ViewModel + +import androidx.compose.runtime.Composable +import androidx.compose.ui.graphics.ImageBitmap +import androidx.compose.ui.graphics.painter.BitmapPainter +import androidx.compose.ui.graphics.toComposeImageBitmap +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.ui.Modifier +import androidx.compose.ui.layout.ContentScale +import org.jetbrains.skia.Image +import java.io.File +import java.nio.file.Files + +@Composable +actual fun ImageFromPath(path: String, modifier: Modifier) { + val imageBitmap: ImageBitmap? = try { + if (path.isBlank()) { + // Загружаем из ресурсов + val resourceStream = Thread.currentThread().contextClassLoader.getResourceAsStream("drawable/basicPhoto.png") + val bytes = resourceStream.readAllBytes() + Image.makeFromEncoded(bytes).toComposeImageBitmap() + } else { + // Загружаем с абсолютного пути + val file = File(path) + if (file.exists()) { + val bytes = Files.readAllBytes(file.toPath()) + Image.makeFromEncoded(bytes).toComposeImageBitmap() + } else null + } + } catch (e: Exception) { + println("Ошибка загрузки изображения: ${e.message}") + null + } + + if (imageBitmap != null) { + Image( + painter = BitmapPainter(imageBitmap), + contentDescription = null, + modifier = modifier, + contentScale = ContentScale.Crop + ) + } else { + Box(modifier = modifier.fillMaxSize()) + } +} \ No newline at end of file