You've already forked RekomenciMobile
fix fix and fix
This commit is contained in:
+14
-11
@@ -1,5 +1,6 @@
|
||||
package com.prodhack.moscow2025.data.data_providers.api
|
||||
|
||||
import android.util.Log
|
||||
import com.prodhack.moscow2025.common.Constants
|
||||
import com.prodhack.moscow2025.data.data_providers.localInfo.AuthorizationDataStore
|
||||
import io.ktor.client.HttpClient
|
||||
@@ -48,19 +49,21 @@ class ApiKtorClient(authorizationDataStore: AuthorizationDataStore) {
|
||||
}
|
||||
install(Auth) {
|
||||
bearer {
|
||||
sendWithoutRequest { request ->
|
||||
val segments = request.url.pathSegments
|
||||
|
||||
val endpointsWithoutAuth = listOf(
|
||||
"sign_in",
|
||||
"sign_up"
|
||||
)
|
||||
|
||||
endpointsWithoutAuth.any { segments.contains(it) }.not()
|
||||
}
|
||||
// sendWithoutRequest { request ->
|
||||
// val segments = request.url.pathSegments
|
||||
//
|
||||
// val endpointsWithoutAuth = listOf(
|
||||
// "sign_in",
|
||||
// "sign_up"
|
||||
// )
|
||||
//
|
||||
// endpointsWithoutAuth.any { segments.contains(it) }.not()
|
||||
// }
|
||||
loadTokens {
|
||||
return@loadTokens authorizationDataStore.token.first()
|
||||
.toBearerTokens()
|
||||
.toBearerTokens().also {
|
||||
Log.d("csmlc", it.accessToken)
|
||||
}
|
||||
}
|
||||
refreshTokens {
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
|
||||
@@ -6,6 +6,7 @@ import com.prodhack.moscow2025.domain.models.Education
|
||||
import com.prodhack.moscow2025.domain.models.EducationGrades
|
||||
import com.prodhack.moscow2025.domain.models.ExperienceType
|
||||
import com.prodhack.moscow2025.domain.models.Project
|
||||
import com.prodhack.moscow2025.domain.models.ResumeCreationModel
|
||||
import com.prodhack.moscow2025.domain.models.ResumeModel
|
||||
import com.prodhack.moscow2025.domain.models.WorkExperience
|
||||
import kotlinx.serialization.SerialName
|
||||
@@ -55,11 +56,12 @@ data class ResumeDTO(
|
||||
@SerialName("key_skills")
|
||||
val keySkills: List<String>,
|
||||
val position: String,
|
||||
@SerialName("location")
|
||||
val city: String,
|
||||
val experience: List<ExperienceDTO>,
|
||||
val education: List<EducationDTO>,
|
||||
val project: List<ProjectDTO>,
|
||||
val prediction: PredictionDTO
|
||||
val experience: List<ExperienceDTO> = emptyList(),
|
||||
val education: List<EducationDTO> = emptyList(),
|
||||
val project: List<ProjectDTO> = emptyList(),
|
||||
val prediction: PredictionDTO? = null
|
||||
) {
|
||||
fun mapToDomain(): ResumeModel = ResumeModel(
|
||||
id = id,
|
||||
@@ -67,11 +69,13 @@ data class ResumeDTO(
|
||||
skills = keySkills,
|
||||
position = position,
|
||||
experienceType = experienceType.mapToDomain(),
|
||||
prediction = Pair(
|
||||
prediction.fromSalary.toIntOrNull(),
|
||||
prediction.toSalary.toIntOrNull()
|
||||
),
|
||||
recommendedSkills = prediction.recommendedSkills,
|
||||
prediction = prediction?.let {
|
||||
Pair(
|
||||
it.fromSalary.toIntOrNull(),
|
||||
it.toSalary.toIntOrNull()
|
||||
)
|
||||
},
|
||||
recommendedSkills = prediction?.recommendedSkills,
|
||||
city = city,
|
||||
experience = experience.map { it.mapToDomain() },
|
||||
education = education.map { it.mapToDomain() },
|
||||
@@ -83,9 +87,9 @@ data class ResumeDTO(
|
||||
aboutMe = aboutMe,
|
||||
keySkills = keySkills.joinToString("|"),
|
||||
position = position,
|
||||
fromSalary = prediction.fromSalary.toIntOrNull(),
|
||||
toSalary = prediction.toSalary.toIntOrNull(),
|
||||
recommendedSkills = prediction.recommendedSkills.joinToString("|"),
|
||||
fromSalary = prediction?.fromSalary?.toIntOrNull(),
|
||||
toSalary = prediction?.toSalary?.toIntOrNull(),
|
||||
recommendedSkills = prediction?.recommendedSkills?.joinToString("|") ?: "",
|
||||
experienceType = experienceType.mapToDomain().name,
|
||||
city = city,
|
||||
experience = JsonTypeConverters.fromWorkExperienceList(experience.map { it.mapToDomain() }),
|
||||
@@ -108,6 +112,12 @@ data class ExperienceDTO(
|
||||
)
|
||||
}
|
||||
|
||||
fun WorkExperience.mapToData(): ExperienceDTO = ExperienceDTO(
|
||||
place = place,
|
||||
description = description,
|
||||
monthDuration = monthDuration ?: 0
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class EducationDTO(
|
||||
val place: String,
|
||||
@@ -123,6 +133,13 @@ data class EducationDTO(
|
||||
)
|
||||
}
|
||||
|
||||
fun Education.mapToData(): EducationDTO = EducationDTO(
|
||||
place = place,
|
||||
grade = grade.mapToData(),
|
||||
specialization = specialization,
|
||||
description = description
|
||||
)
|
||||
|
||||
@Serializable
|
||||
enum class EducationGradesDTO {
|
||||
@SerialName("basic_general_education")
|
||||
@@ -161,6 +178,18 @@ enum class EducationGradesDTO {
|
||||
}
|
||||
}
|
||||
|
||||
fun EducationGrades.mapToData(): EducationGradesDTO =
|
||||
when (this) {
|
||||
EducationGrades.BasicGeneralEducation -> EducationGradesDTO.BasicGeneralEducation
|
||||
EducationGrades.SecondaryGeneralEducation -> EducationGradesDTO.SecondaryGeneralEducation
|
||||
EducationGrades.SecondaryProfessionalEducation -> EducationGradesDTO.SecondaryProfessionalEducation
|
||||
EducationGrades.Bachelor -> EducationGradesDTO.Bachelor
|
||||
EducationGrades.Specialist -> EducationGradesDTO.Specialist
|
||||
EducationGrades.Master -> EducationGradesDTO.Master
|
||||
EducationGrades.PostgraduateStudies -> EducationGradesDTO.PostgraduateStudies
|
||||
EducationGrades.Other -> EducationGradesDTO.Other
|
||||
}
|
||||
|
||||
@Serializable
|
||||
data class ProjectDTO(
|
||||
val name: String,
|
||||
@@ -172,6 +201,11 @@ data class ProjectDTO(
|
||||
)
|
||||
}
|
||||
|
||||
fun Project.mapToData(): ProjectDTO = ProjectDTO(
|
||||
name = name,
|
||||
description = description
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class ResumeCreateDTO(
|
||||
@SerialName("experience_type")
|
||||
@@ -181,12 +215,24 @@ data class ResumeCreateDTO(
|
||||
@SerialName("key_skills")
|
||||
val keySkills: List<String>,
|
||||
val position: String,
|
||||
@SerialName("location")
|
||||
val city: String,
|
||||
val experience: List<ExperienceDTO>,
|
||||
val education: List<EducationDTO>,
|
||||
val project: List<ProjectDTO>,
|
||||
)
|
||||
|
||||
fun ResumeCreationModel.mapToData(): ResumeCreateDTO = ResumeCreateDTO(
|
||||
experienceType = experienceType.mapToData(),
|
||||
aboutMe = about,
|
||||
keySkills = skills,
|
||||
position = position,
|
||||
city = city,
|
||||
experience = experience.map { it.mapToData() },
|
||||
education = education.map { it.mapToData() },
|
||||
project = projects.map { it.mapToData() }
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class PredictionDTO(
|
||||
@SerialName("from_salary")
|
||||
|
||||
+2
@@ -1,5 +1,6 @@
|
||||
package com.prodhack.moscow2025.data.repImplementations
|
||||
|
||||
import android.util.Log
|
||||
import com.prodhack.moscow2025.data.base.BaseRepository
|
||||
import com.prodhack.moscow2025.data.data_providers.api.ApiKtorClient
|
||||
import com.prodhack.moscow2025.data.data_providers.localInfo.AuthorizationDataStore
|
||||
@@ -14,6 +15,7 @@ import io.ktor.http.ContentType
|
||||
import io.ktor.http.HttpMethod
|
||||
import io.ktor.http.contentType
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.flow.map
|
||||
import org.koin.core.annotation.Single
|
||||
|
||||
|
||||
+2
-1
@@ -8,6 +8,7 @@ import com.prodhack.moscow2025.data.dto.ResumeCreateDTO
|
||||
import com.prodhack.moscow2025.data.dto.ResumeIdDTO
|
||||
import com.prodhack.moscow2025.data.dto.ResumeListDTO
|
||||
import com.prodhack.moscow2025.data.dto.ResumeSkillDTO
|
||||
import com.prodhack.moscow2025.data.dto.mapToData
|
||||
import com.prodhack.moscow2025.domain.interfaces.resumes.ResumeRepository
|
||||
import com.prodhack.moscow2025.domain.models.ResumeCreationModel
|
||||
import com.prodhack.moscow2025.domain.models.ResumeModel
|
||||
@@ -64,7 +65,7 @@ class ResumeRepositoryImpl(
|
||||
url("/resume")
|
||||
}
|
||||
|
||||
setBody(ResumeCreateDTO)
|
||||
setBody(resumeForm.mapToData())
|
||||
contentType(ContentType.Application.Json)
|
||||
}.map { it.resumeId }
|
||||
}
|
||||
@@ -10,15 +10,15 @@ data class ResumeModel(
|
||||
val experience: List<WorkExperience>,
|
||||
val education: List<Education>,
|
||||
val projects: List<Project>,
|
||||
val prediction: Pair<Int?, Int?>,
|
||||
val recommendedSkills: List<String>
|
||||
val prediction: Pair<Int?, Int?>?,
|
||||
val recommendedSkills: List<String>?
|
||||
)
|
||||
|
||||
data class ResumeCreationModel(
|
||||
val position: String,
|
||||
val about: String,
|
||||
val skills: List<String>,
|
||||
val city: String?,
|
||||
val city: String,
|
||||
val experienceType: ExperienceType,
|
||||
val experience: List<WorkExperience>,
|
||||
val education: List<Education>,
|
||||
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
package com.prodhack.moscow2025.domain.usecase.resumes
|
||||
|
||||
import com.prodhack.moscow2025.domain.models.ResumeModel
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import org.koin.core.annotation.Single
|
||||
|
||||
@Single
|
||||
class GetResumeInfoUseCase {
|
||||
operator fun invoke(): Flow<Result<ResumeModel>> {
|
||||
TODO()
|
||||
}
|
||||
}
|
||||
+29
-29
@@ -10,35 +10,35 @@ import org.koin.core.annotation.Single
|
||||
|
||||
@Single
|
||||
class LoadResumeListUseCase(private val resumeRepository: ResumeRepository) {
|
||||
// operator fun invoke(): RemotePagingWrapper<ResumeModel> = resumeRepository.loadResumeList()
|
||||
operator fun invoke(): RemotePagingWrapper<ResumeModel> = resumeRepository.loadResumeList()
|
||||
|
||||
// Mocked data
|
||||
operator fun invoke(): RemotePagingWrapper<ResumeModel> = flow {
|
||||
emit(
|
||||
PagingData.from(
|
||||
listOf(
|
||||
ResumeModel(
|
||||
id = "iajxioasdkmcaolsd,c",
|
||||
position = "Android разработчик",
|
||||
about = "Ну оооочень крутой андроид разраб, с огромным количеством опыта. " +
|
||||
"И нет это я не про себя, это просто какие-то данные," +
|
||||
" чтобы проверить, что это чудовище работает",
|
||||
skills = listOf(
|
||||
"Android SDK",
|
||||
"Kotlin",
|
||||
"Room",
|
||||
"Ktor"
|
||||
),
|
||||
experienceType = ExperienceType.Between3And6,
|
||||
city = "Moscow",
|
||||
experience = listOf(),
|
||||
education = listOf(),
|
||||
projects = listOf(),
|
||||
prediction = Pair(200000, 230000),
|
||||
recommendedSkills = listOf("KMP")
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
// operator fun invoke(): RemotePagingWrapper<ResumeModel> = flow {
|
||||
// emit(
|
||||
// PagingData.from(
|
||||
// listOf(
|
||||
// ResumeModel(
|
||||
// id = "iajxioasdkmcaolsd,c",
|
||||
// position = "Android разработчик",
|
||||
// about = "Ну оооочень крутой андроид разраб, с огромным количеством опыта. " +
|
||||
// "И нет это я не про себя, это просто какие-то данные," +
|
||||
// " чтобы проверить, что это чудовище работает",
|
||||
// skills = listOf(
|
||||
// "Android SDK",
|
||||
// "Kotlin",
|
||||
// "Room",
|
||||
// "Ktor"
|
||||
// ),
|
||||
// experienceType = ExperienceType.Between3And6,
|
||||
// city = "Moscow",
|
||||
// experience = listOf(),
|
||||
// education = listOf(),
|
||||
// projects = listOf(),
|
||||
// prediction = Pair(200000, 230000),
|
||||
// recommendedSkills = listOf("KMP")
|
||||
// )
|
||||
// )
|
||||
// )
|
||||
// )
|
||||
// }
|
||||
}
|
||||
|
||||
+9
@@ -8,6 +8,7 @@ import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.offset
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.foundation.text.KeyboardActions
|
||||
@@ -36,6 +37,7 @@ import androidx.compose.ui.text.input.VisualTransformation
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import com.prodhack.moscow2025.R
|
||||
import com.prodhack.moscow2025.presentation.theme.Paddings
|
||||
import com.prodhack.moscow2025.presentation.utils.ui.noRippleClickable
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3Api::class)
|
||||
@@ -254,6 +256,10 @@ fun <T> TTTextFieldWithDropdown(
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
if (dropdownItems.isEmpty()){
|
||||
Text(modifier = Modifier.padding(Paddings.small), text = "Ничего нет", style = typography.labelLarge, fontSize = 16.sp)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -362,6 +368,9 @@ fun <T> TTTextFieldWithSearch(
|
||||
}
|
||||
)
|
||||
}
|
||||
if (dropdownItems.isEmpty()){
|
||||
Text(modifier = Modifier.padding(Paddings.small), text = "Ничего не нашлось", style = typography.labelLarge, fontSize = 16.sp)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -11,7 +11,7 @@ data class UIResumeBaseInfo(
|
||||
fun ResumeModel.mapToBaseUIInfo(): UIResumeBaseInfo = UIResumeBaseInfo(
|
||||
id = id,
|
||||
positionName = position,
|
||||
salary = prediction.first?.let { from ->
|
||||
prediction.second?.let { to -> "$from-$to" } ?: from.toString()
|
||||
} ?: prediction.second?.toString() ?: "Ошибка"
|
||||
salary = prediction?.first?.let { from ->
|
||||
prediction.second?.let { to -> "$from-$to₽" } ?: "$from₽"
|
||||
} ?: prediction?.second?.let { "$it₽" } ?: "Загрузка..."
|
||||
)
|
||||
@@ -118,7 +118,7 @@ fun TTasksNavHost(
|
||||
}
|
||||
|
||||
composable(AppDestination.ResumeCreation.route) {
|
||||
CreateResumeScreen()
|
||||
CreateResumeScreen({ navController.popBackStack() })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+81
-6
@@ -15,7 +15,7 @@ import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.ButtonColors
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.material3.Card
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
@@ -43,6 +43,7 @@ import org.koin.androidx.compose.koinViewModel
|
||||
|
||||
@Composable
|
||||
fun CreateResumeScreen(
|
||||
goBack: () -> Unit,
|
||||
viewModel: CreateResumeViewModel = koinViewModel()
|
||||
) {
|
||||
val colorScheme = MaterialTheme.colorScheme
|
||||
@@ -64,7 +65,8 @@ fun CreateResumeScreen(
|
||||
Icon(
|
||||
modifier = Modifier
|
||||
.rotate(180f)
|
||||
.size(24.dp),
|
||||
.size(24.dp)
|
||||
.noRippleClickable(goBack),
|
||||
painter = painterResource(R.drawable.ic_arr_details),
|
||||
tint = colorScheme.onBackground,
|
||||
contentDescription = "go back"
|
||||
@@ -114,7 +116,7 @@ fun CreateResumeScreen(
|
||||
error = formState.value.errors[ResumeField.Experience],
|
||||
dropdownItems = viewModel.experienceOptions,
|
||||
dropDownItem = {
|
||||
Text(text = it.friendlyName, style = typography.titleMedium, fontSize = 16.sp)
|
||||
Text(text = it.friendlyName, style = typography.labelLarge, fontSize = 16.sp)
|
||||
},
|
||||
onDropdownItemSelected = viewModel::onExperienceSelect
|
||||
)
|
||||
@@ -179,6 +181,8 @@ fun CreateResumeScreen(
|
||||
|
||||
Spacer(modifier = Modifier.height(Paddings.large))
|
||||
|
||||
Card {
|
||||
Column(modifier = Modifier.padding(Paddings.medium)) {
|
||||
Text(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
text = "Подробнее о вашем опыте работы:",
|
||||
@@ -186,10 +190,10 @@ fun CreateResumeScreen(
|
||||
fontSize = 20.sp,
|
||||
textAlign = TextAlign.Center
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.height(Paddings.large))
|
||||
|
||||
|
||||
|
||||
formState.value.workExperience.forEachIndexed { index, workExp ->
|
||||
Text(
|
||||
text = "№${index + 1}:",
|
||||
@@ -214,7 +218,9 @@ fun CreateResumeScreen(
|
||||
singleLine = false,
|
||||
maxLines = 10,
|
||||
label = "Расскажите подробнее",
|
||||
error = formState.value.errors[ResumeField.WorkExperienceDescription(index)]
|
||||
error = formState.value.errors[ResumeField.WorkExperienceDescription(
|
||||
index
|
||||
)]
|
||||
)
|
||||
Spacer(modifier = Modifier.height(Paddings.medium))
|
||||
TTTextField(
|
||||
@@ -223,9 +229,30 @@ fun CreateResumeScreen(
|
||||
viewModel.changeWorkExperienceMonthDuration(index, it)
|
||||
},
|
||||
label = "Продолжительность (в месяцах)",
|
||||
error = formState.value.errors[ResumeField.WorkExperienceMonthDuration(index)]
|
||||
error = formState.value.errors[ResumeField.WorkExperienceMonthDuration(
|
||||
index
|
||||
)]
|
||||
)
|
||||
Spacer(modifier = Modifier.height(Paddings.medium))
|
||||
Button(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth(),
|
||||
shape = Shapes.smallRoundedBox,
|
||||
onClick = { viewModel.removeExperience(index) },
|
||||
colors = ButtonColors(
|
||||
containerColor = colorScheme.errorContainer,
|
||||
contentColor = colorScheme.onErrorContainer,
|
||||
disabledContainerColor = colorScheme.errorContainer,
|
||||
disabledContentColor = colorScheme.onErrorContainer
|
||||
)
|
||||
) {
|
||||
Text(
|
||||
text = "Удалить",
|
||||
style = typography.labelLarge,
|
||||
fontSize = 18.sp,
|
||||
)
|
||||
}
|
||||
Spacer(modifier = Modifier.height(Paddings.medium))
|
||||
}
|
||||
|
||||
if (formState.value.workExperience.isEmpty()) {
|
||||
@@ -257,8 +284,12 @@ fun CreateResumeScreen(
|
||||
fontSize = 18.sp,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
Spacer(modifier = Modifier.height(Paddings.large))
|
||||
|
||||
Card {
|
||||
Column(modifier = Modifier.padding(Paddings.medium)) {
|
||||
Text(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
text = "Ваше образование:",
|
||||
@@ -318,6 +349,25 @@ fun CreateResumeScreen(
|
||||
error = formState.value.errors[ResumeField.EducationDescription(index)]
|
||||
)
|
||||
Spacer(modifier = Modifier.height(Paddings.medium))
|
||||
Button(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth(),
|
||||
shape = Shapes.smallRoundedBox,
|
||||
onClick = { viewModel.removeEducation(index) },
|
||||
colors = ButtonColors(
|
||||
containerColor = colorScheme.errorContainer,
|
||||
contentColor = colorScheme.onErrorContainer,
|
||||
disabledContainerColor = colorScheme.errorContainer,
|
||||
disabledContentColor = colorScheme.onErrorContainer
|
||||
)
|
||||
) {
|
||||
Text(
|
||||
text = "Удалить",
|
||||
style = typography.labelLarge,
|
||||
fontSize = 18.sp,
|
||||
)
|
||||
}
|
||||
Spacer(modifier = Modifier.height(Paddings.medium))
|
||||
}
|
||||
|
||||
if (formState.value.education.isEmpty()) {
|
||||
@@ -349,9 +399,13 @@ fun CreateResumeScreen(
|
||||
fontSize = 18.sp,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(Paddings.large))
|
||||
|
||||
Card {
|
||||
Column(modifier = Modifier.padding(Paddings.medium)) {
|
||||
Text(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
text = "Интересные проекты:",
|
||||
@@ -386,6 +440,25 @@ fun CreateResumeScreen(
|
||||
error = formState.value.errors[ResumeField.ProjectDescription(index)]
|
||||
)
|
||||
Spacer(modifier = Modifier.height(Paddings.medium))
|
||||
Spacer(modifier = Modifier.height(Paddings.medium))
|
||||
Button(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth(),
|
||||
shape = Shapes.smallRoundedBox,
|
||||
onClick = { viewModel.removeProject(index) },
|
||||
colors = ButtonColors(
|
||||
containerColor = colorScheme.errorContainer,
|
||||
contentColor = colorScheme.onErrorContainer,
|
||||
disabledContainerColor = colorScheme.errorContainer,
|
||||
disabledContentColor = colorScheme.onErrorContainer
|
||||
)
|
||||
) {
|
||||
Text(
|
||||
text = "Удалить",
|
||||
style = typography.labelLarge,
|
||||
fontSize = 18.sp,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (formState.value.projects.isEmpty()) {
|
||||
@@ -417,6 +490,8 @@ fun CreateResumeScreen(
|
||||
fontSize = 18.sp,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(Paddings.large))
|
||||
BigButton(
|
||||
|
||||
+26
-1
@@ -161,6 +161,7 @@ class CreateResumeViewModel(
|
||||
errors = it.errors - ResumeField.KeySkills
|
||||
)
|
||||
}
|
||||
skillSearchQuery.value = ""
|
||||
}
|
||||
|
||||
fun onRemoveSkill(value: String) {
|
||||
@@ -270,6 +271,19 @@ class CreateResumeViewModel(
|
||||
}
|
||||
}
|
||||
|
||||
fun removeEducation(id: Int) {
|
||||
_formStateFillResume.update {
|
||||
it.copy(
|
||||
education = it.education.filterIndexed { index, _ -> index != id },
|
||||
errors = it.errors
|
||||
- ResumeField.EducationSpecialization(id)
|
||||
- ResumeField.EducationDescription(id)
|
||||
- ResumeField.EducationPlace(id)
|
||||
- ResumeField.EducationGrade(id)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun changeEducationPlace(index: Int, value: String) {
|
||||
_formStateFillResume.update {
|
||||
it.copy(
|
||||
@@ -323,6 +337,17 @@ class CreateResumeViewModel(
|
||||
}
|
||||
}
|
||||
|
||||
fun removeProject(id: Int) {
|
||||
_formStateFillResume.update {
|
||||
it.copy(
|
||||
projects = it.projects.filterIndexed { index, _ -> index != id },
|
||||
errors = it.errors
|
||||
- ResumeField.ProjectDescription(id)
|
||||
- ResumeField.ProjectName(id)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun changeProjectName(index: Int, value: String) {
|
||||
_formStateFillResume.update {
|
||||
it.copy(
|
||||
@@ -372,7 +397,7 @@ class CreateResumeViewModel(
|
||||
about = about,
|
||||
skills = keySkills.toList(),
|
||||
experienceType = experience!!.mapToDomain(),
|
||||
city = city.ifBlank { null },
|
||||
city = city,
|
||||
experience = workExperience,
|
||||
education = education.map {
|
||||
Education(
|
||||
|
||||
@@ -79,6 +79,8 @@ fun ErrorCollectorScope.MainScreen(
|
||||
color = colorScheme.onBackground
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.height(Paddings.large))
|
||||
|
||||
BigButton(
|
||||
onClick = {
|
||||
TODO()
|
||||
@@ -165,7 +167,7 @@ fun ResumeShortInfoCard(
|
||||
fontSize = 18.sp
|
||||
)
|
||||
Text(
|
||||
"${info.salary}₽",
|
||||
info.salary,
|
||||
style = typography.titleMedium,
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
fontSize = 18.sp
|
||||
|
||||
-2
@@ -17,6 +17,4 @@ fun ResumeDetailsScreen(
|
||||
}
|
||||
) {
|
||||
|
||||
Text("Opened resume details for id ${navBackStackEntry.arguments?.getString(AppDestination.ResumeDetails.ARG_ID, "") ?: ""}")
|
||||
|
||||
}
|
||||
+3
-1
@@ -1,11 +1,13 @@
|
||||
package com.prodhack.moscow2025.presentation.screens.resumeDetails
|
||||
|
||||
import com.prodhack.moscow2025.domain.usecase.resumes.GetResumeInfoUseCase
|
||||
import com.prodhack.moscow2025.presentation.utils.base.BaseViewModel
|
||||
import org.koin.android.annotation.KoinViewModel
|
||||
import org.koin.core.annotation.Provided
|
||||
|
||||
@KoinViewModel
|
||||
class ResumeDetailsViewModel(
|
||||
@Provided resumeId: String
|
||||
@Provided resumeId: String,
|
||||
private val getResumeInfoUseCase: GetResumeInfoUseCase
|
||||
) : BaseViewModel() {
|
||||
}
|
||||
Reference in New Issue
Block a user