diff --git a/app/build.gradle.kts b/app/build.gradle.kts index c0e251eff8..adf3dd63e8 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -2,6 +2,8 @@ plugins { id("com.android.application") id("org.jetbrains.kotlin.android") id("ru.practicum.android.diploma.plugins.developproperties") + id("com.google.devtools.ksp") + id("kotlin-parcelize") } android { @@ -36,16 +38,30 @@ android { buildFeatures { buildConfig = true + viewBinding = true } } dependencies { implementation(libs.androidX.core) implementation(libs.androidX.appCompat) - + ksp(libs.room.compiler) + implementation(libs.room.runtime) + implementation(libs.room.ktx) + implementation(libs.kotlinx.coroutines.android) + implementation(libs.fragment.ktx) // UI layer libraries implementation(libs.ui.material) implementation(libs.ui.constraintLayout) + implementation(libs.glide) + implementation(libs.retrofit.v290) + implementation(libs.converter.gson.v290) + implementation(libs.gson) + implementation(libs.koin.android) + implementation(libs.navigation.fragment.ktx) + implementation(libs.navigation.ui.ktx) + annotationProcessor(libs.compiler) + implementation(libs.byViewBinding) // region Unit tests testImplementation(libs.unitTests.junit) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 267e284599..18a9e33e89 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -2,7 +2,11 @@ + + + + android:screenOrientation="portrait" + android:exported="true" + tools:ignore="DiscouragedApi,LockedOrientationActivity"> @@ -22,5 +28,4 @@ - - \ No newline at end of file + diff --git a/app/src/main/java/ru/practicum/android/diploma/data/db/AppDatabase.kt b/app/src/main/java/ru/practicum/android/diploma/data/db/AppDatabase.kt new file mode 100644 index 0000000000..2e90c111b1 --- /dev/null +++ b/app/src/main/java/ru/practicum/android/diploma/data/db/AppDatabase.kt @@ -0,0 +1,11 @@ +package ru.practicum.android.diploma.data.db + +import androidx.room.Database +import androidx.room.RoomDatabase + +@Database( + version = 1, + entities = [VacancyEntity::class] +) +abstract class AppDatabase : RoomDatabase() + diff --git a/app/src/main/java/ru/practicum/android/diploma/data/db/VacancyEntity.kt b/app/src/main/java/ru/practicum/android/diploma/data/db/VacancyEntity.kt new file mode 100644 index 0000000000..d5a1e03d7d --- /dev/null +++ b/app/src/main/java/ru/practicum/android/diploma/data/db/VacancyEntity.kt @@ -0,0 +1,11 @@ +package ru.practicum.android.diploma.data.db + +import androidx.room.Entity +import androidx.room.PrimaryKey + +@Entity(tableName = "vacancy_table") +data class VacancyEntity( + @PrimaryKey(autoGenerate = true) + val vacancyId: Int +) + diff --git a/app/src/main/java/ru/practicum/android/diploma/data/db/dao/VacancyDao.kt b/app/src/main/java/ru/practicum/android/diploma/data/db/dao/VacancyDao.kt new file mode 100644 index 0000000000..4078d3a17f --- /dev/null +++ b/app/src/main/java/ru/practicum/android/diploma/data/db/dao/VacancyDao.kt @@ -0,0 +1,7 @@ +package ru.practicum.android.diploma.data.db.dao + +import androidx.room.Dao + +@Dao +interface VacancyDao + diff --git a/app/src/main/java/ru/practicum/android/diploma/data/dto/Responce.kt b/app/src/main/java/ru/practicum/android/diploma/data/dto/Responce.kt new file mode 100644 index 0000000000..d8013d9066 --- /dev/null +++ b/app/src/main/java/ru/practicum/android/diploma/data/dto/Responce.kt @@ -0,0 +1,10 @@ +package ru.practicum.android.diploma.data.dto + +const val RESULT_CODE_NO_INTERNET = -1 +const val RESULT_CODE_SUCCESS = 200 +const val RESULT_CODE_BAD_REQUEST = 400 +const val RESULT_CODE_SERVER_ERROR = 500 + +class Responce { + var resultCode = 0 +} diff --git a/app/src/main/java/ru/practicum/android/diploma/data/dto/SearchRequest.kt b/app/src/main/java/ru/practicum/android/diploma/data/dto/SearchRequest.kt new file mode 100644 index 0000000000..2ae463e734 --- /dev/null +++ b/app/src/main/java/ru/practicum/android/diploma/data/dto/SearchRequest.kt @@ -0,0 +1,5 @@ +package ru.practicum.android.diploma.data.dto + +data class SearchRequest( + val options: Map +) diff --git a/app/src/main/java/ru/practicum/android/diploma/data/dto/VacancyRequest.kt b/app/src/main/java/ru/practicum/android/diploma/data/dto/VacancyRequest.kt new file mode 100644 index 0000000000..236acd0838 --- /dev/null +++ b/app/src/main/java/ru/practicum/android/diploma/data/dto/VacancyRequest.kt @@ -0,0 +1,5 @@ +package ru.practicum.android.diploma.data.dto + +data class VacancyRequest( + val id: Int +) diff --git a/app/src/main/java/ru/practicum/android/diploma/data/network/HHApiService.kt b/app/src/main/java/ru/practicum/android/diploma/data/network/HHApiService.kt new file mode 100644 index 0000000000..61c45fde27 --- /dev/null +++ b/app/src/main/java/ru/practicum/android/diploma/data/network/HHApiService.kt @@ -0,0 +1,21 @@ +package ru.practicum.android.diploma.data.network + +import retrofit2.http.GET +import retrofit2.http.Headers +import retrofit2.http.Path +import retrofit2.http.QueryMap +import ru.practicum.android.diploma.BuildConfig +import ru.practicum.android.diploma.data.dto.Responce + +const val USER_AGENT_AUTHORIZATION = "Authorization: Bearer ${BuildConfig.HH_ACCESS_TOKEN}" +const val USER_AGENT_APP_NAME = "HH-User-Agent: CareerHub (e.gasymov@hh.ru)" + +interface HHApiService { + @Headers(USER_AGENT_AUTHORIZATION, USER_AGENT_APP_NAME) + @GET("vacancies/{vacancy_id}") + suspend fun getVacancy(@Path("vacancy_id") id: Int): Responce + + @Headers(USER_AGENT_AUTHORIZATION, USER_AGENT_APP_NAME) + @GET("vacancies") + suspend fun searchVacancies(@QueryMap options: Map): Responce +} diff --git a/app/src/main/java/ru/practicum/android/diploma/data/network/NetworkClient.kt b/app/src/main/java/ru/practicum/android/diploma/data/network/NetworkClient.kt new file mode 100644 index 0000000000..0a3a0bd9b2 --- /dev/null +++ b/app/src/main/java/ru/practicum/android/diploma/data/network/NetworkClient.kt @@ -0,0 +1,7 @@ +package ru.practicum.android.diploma.data.network + +import ru.practicum.android.diploma.data.dto.Responce + +interface NetworkClient { + suspend fun doRequest(dto: Any): Responce +} diff --git a/app/src/main/java/ru/practicum/android/diploma/data/network/RetrofitNetworkClient.kt b/app/src/main/java/ru/practicum/android/diploma/data/network/RetrofitNetworkClient.kt new file mode 100644 index 0000000000..a70fd915c9 --- /dev/null +++ b/app/src/main/java/ru/practicum/android/diploma/data/network/RetrofitNetworkClient.kt @@ -0,0 +1,54 @@ +package ru.practicum.android.diploma.data.network + +import android.content.Context +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext +import retrofit2.HttpException +import ru.practicum.android.diploma.data.dto.RESULT_CODE_BAD_REQUEST +import ru.practicum.android.diploma.data.dto.RESULT_CODE_NO_INTERNET +import ru.practicum.android.diploma.data.dto.RESULT_CODE_SERVER_ERROR +import ru.practicum.android.diploma.data.dto.RESULT_CODE_SUCCESS +import ru.practicum.android.diploma.data.dto.Responce +import ru.practicum.android.diploma.data.dto.SearchRequest +import ru.practicum.android.diploma.data.dto.VacancyRequest +import ru.practicum.android.diploma.util.isInternetAvailable + +class RetrofitNetworkClient( + private val hhApiService: HHApiService, + private val context: Context +) : NetworkClient { + + override suspend fun doRequest(dto: Any): Responce { + if (!isInternetAvailable(context)) { + return Responce().apply { resultCode = RESULT_CODE_NO_INTERNET } + } + return getResponce(dto = dto) + } + + private suspend fun getResponce(dto: Any): Responce { + return withContext(Dispatchers.IO) { + try { + when (dto) { + is VacancyRequest -> { + val response = hhApiService.getVacancy(dto.id) + response.apply { resultCode = RESULT_CODE_SUCCESS } + } + + is SearchRequest -> { + val response = hhApiService.searchVacancies(options = dto.options) + response.apply { resultCode = RESULT_CODE_SUCCESS } + } + + else -> { + Responce().apply { resultCode = RESULT_CODE_BAD_REQUEST } + } + } + + } catch (e: HttpException) { + println("RetrofitClient error code: ${e.code()} message: ${e.message}") + Responce().apply { resultCode = RESULT_CODE_SERVER_ERROR } + } + } + } + +} diff --git a/app/src/main/java/ru/practicum/android/diploma/di/DataModule.kt b/app/src/main/java/ru/practicum/android/diploma/di/DataModule.kt new file mode 100644 index 0000000000..eff76dc501 --- /dev/null +++ b/app/src/main/java/ru/practicum/android/diploma/di/DataModule.kt @@ -0,0 +1,35 @@ +package ru.practicum.android.diploma.di + +import androidx.room.Room +import org.koin.android.ext.koin.androidContext +import org.koin.dsl.module +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import ru.practicum.android.diploma.data.db.AppDatabase +import ru.practicum.android.diploma.data.network.HHApiService +import ru.practicum.android.diploma.data.network.NetworkClient +import ru.practicum.android.diploma.data.network.RetrofitNetworkClient + +const val BASE_URL = "https://api.hh.ru/" +val dataModule = module { + single { + RetrofitNetworkClient( + hhApiService = get(), + context = androidContext() + ) + } + + single { + Retrofit.Builder() + .baseUrl(BASE_URL) + .addConverterFactory(GsonConverterFactory.create()) + .build() + .create(HHApiService::class.java) + } + single { + Room.databaseBuilder(androidContext(), AppDatabase::class.java, "database.db") + .fallbackToDestructiveMigration() + .build() + } + +} diff --git a/app/src/main/java/ru/practicum/android/diploma/di/InteractorModule.kt b/app/src/main/java/ru/practicum/android/diploma/di/InteractorModule.kt new file mode 100644 index 0000000000..364c0184dd --- /dev/null +++ b/app/src/main/java/ru/practicum/android/diploma/di/InteractorModule.kt @@ -0,0 +1,7 @@ +package ru.practicum.android.diploma.di + +import org.koin.dsl.module + +val interactorModule = module { + +} diff --git a/app/src/main/java/ru/practicum/android/diploma/di/RepositoryModule.kt b/app/src/main/java/ru/practicum/android/diploma/di/RepositoryModule.kt new file mode 100644 index 0000000000..317f923070 --- /dev/null +++ b/app/src/main/java/ru/practicum/android/diploma/di/RepositoryModule.kt @@ -0,0 +1,7 @@ +package ru.practicum.android.diploma.di + +import org.koin.dsl.module + +val repositoryModule = module { + +} diff --git a/app/src/main/java/ru/practicum/android/diploma/di/ViewModelModule.kt b/app/src/main/java/ru/practicum/android/diploma/di/ViewModelModule.kt new file mode 100644 index 0000000000..c08d5fd3e9 --- /dev/null +++ b/app/src/main/java/ru/practicum/android/diploma/di/ViewModelModule.kt @@ -0,0 +1,7 @@ +package ru.practicum.android.diploma.di + +import org.koin.dsl.module + +val viewModelModule = module { + +} diff --git a/app/src/main/java/ru/practicum/android/diploma/ui/fragments/FavouritesFragment.kt b/app/src/main/java/ru/practicum/android/diploma/ui/fragments/FavouritesFragment.kt new file mode 100644 index 0000000000..449eb08409 --- /dev/null +++ b/app/src/main/java/ru/practicum/android/diploma/ui/fragments/FavouritesFragment.kt @@ -0,0 +1,24 @@ +package ru.practicum.android.diploma.ui.fragments + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment +import by.kirich1409.viewbindingdelegate.CreateMethod +import by.kirich1409.viewbindingdelegate.viewBinding +import ru.practicum.android.diploma.databinding.FragmentFavouritesBinding + +class FavouritesFragment : Fragment() { + + private val binding: FragmentFavouritesBinding by viewBinding(CreateMethod.INFLATE) + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + return binding.root + } + +} diff --git a/app/src/main/java/ru/practicum/android/diploma/ui/fragments/FilterFragment.kt b/app/src/main/java/ru/practicum/android/diploma/ui/fragments/FilterFragment.kt new file mode 100644 index 0000000000..7432aff7ed --- /dev/null +++ b/app/src/main/java/ru/practicum/android/diploma/ui/fragments/FilterFragment.kt @@ -0,0 +1,34 @@ +package ru.practicum.android.diploma.ui.fragments + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment +import androidx.navigation.fragment.findNavController +import by.kirich1409.viewbindingdelegate.CreateMethod +import by.kirich1409.viewbindingdelegate.viewBinding +import ru.practicum.android.diploma.R +import ru.practicum.android.diploma.databinding.FragmentFilterBinding + +class FilterFragment : Fragment() { + + private val binding: FragmentFilterBinding by viewBinding(CreateMethod.INFLATE) + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + return binding.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + binding.buttonBackToSearchFromFilter.setOnClickListener { + findNavController().navigate(R.id.mainFragment) + } + } + +} diff --git a/app/src/main/java/ru/practicum/android/diploma/ui/fragments/SearchFragment.kt b/app/src/main/java/ru/practicum/android/diploma/ui/fragments/SearchFragment.kt new file mode 100644 index 0000000000..50bc2005f4 --- /dev/null +++ b/app/src/main/java/ru/practicum/android/diploma/ui/fragments/SearchFragment.kt @@ -0,0 +1,38 @@ +package ru.practicum.android.diploma.ui.fragments + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment +import androidx.navigation.fragment.findNavController +import by.kirich1409.viewbindingdelegate.CreateMethod +import by.kirich1409.viewbindingdelegate.viewBinding +import ru.practicum.android.diploma.R +import ru.practicum.android.diploma.databinding.FragmentSearchBinding + +class SearchFragment : Fragment() { + + private val binding: FragmentSearchBinding by viewBinding(CreateMethod.INFLATE) + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + return binding.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + binding.buttonToFilter.setOnClickListener { + findNavController().navigate(R.id.action_searchFragment_to_filterFragment) + } + + binding.buttonToVacancy.setOnClickListener { + findNavController().navigate(R.id.action_searchFragment_to_vacancyFragment) + } + } + +} diff --git a/app/src/main/java/ru/practicum/android/diploma/ui/fragments/TeamFragment.kt b/app/src/main/java/ru/practicum/android/diploma/ui/fragments/TeamFragment.kt new file mode 100644 index 0000000000..40ee0e2913 --- /dev/null +++ b/app/src/main/java/ru/practicum/android/diploma/ui/fragments/TeamFragment.kt @@ -0,0 +1,24 @@ +package ru.practicum.android.diploma.ui.fragments + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment +import by.kirich1409.viewbindingdelegate.CreateMethod +import by.kirich1409.viewbindingdelegate.viewBinding +import ru.practicum.android.diploma.databinding.FragmentTeamBinding + +class TeamFragment : Fragment() { + + private val binding: FragmentTeamBinding by viewBinding(CreateMethod.INFLATE) + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + return binding.root + } + +} diff --git a/app/src/main/java/ru/practicum/android/diploma/ui/fragments/VacancyFragment.kt b/app/src/main/java/ru/practicum/android/diploma/ui/fragments/VacancyFragment.kt new file mode 100644 index 0000000000..0328c61b23 --- /dev/null +++ b/app/src/main/java/ru/practicum/android/diploma/ui/fragments/VacancyFragment.kt @@ -0,0 +1,34 @@ +package ru.practicum.android.diploma.ui.fragments + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment +import androidx.navigation.fragment.findNavController +import by.kirich1409.viewbindingdelegate.CreateMethod +import by.kirich1409.viewbindingdelegate.viewBinding +import ru.practicum.android.diploma.R +import ru.practicum.android.diploma.databinding.FragmentVacancyBinding + +class VacancyFragment : Fragment() { + + private val binding: FragmentVacancyBinding by viewBinding(CreateMethod.INFLATE) + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + return binding.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + binding.buttonBackToSearchFromVacancy.setOnClickListener { + findNavController().navigate(R.id.mainFragment) + } + } + +} diff --git a/app/src/main/java/ru/practicum/android/diploma/ui/root/RootActivity.kt b/app/src/main/java/ru/practicum/android/diploma/ui/root/RootActivity.kt index b02bd17d18..9509fcf6e6 100644 --- a/app/src/main/java/ru/practicum/android/diploma/ui/root/RootActivity.kt +++ b/app/src/main/java/ru/practicum/android/diploma/ui/root/RootActivity.kt @@ -2,13 +2,48 @@ package ru.practicum.android.diploma.ui.root import android.os.Bundle import androidx.appcompat.app.AppCompatActivity +import androidx.core.view.isVisible +import androidx.navigation.fragment.NavHostFragment +import androidx.navigation.ui.setupWithNavController +import by.kirich1409.viewbindingdelegate.CreateMethod +import by.kirich1409.viewbindingdelegate.viewBinding import ru.practicum.android.diploma.BuildConfig import ru.practicum.android.diploma.R +import ru.practicum.android.diploma.databinding.ActivityRootBinding class RootActivity : AppCompatActivity() { + + private val binding: ActivityRootBinding by viewBinding(CreateMethod.INFLATE) + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - setContentView(R.layout.activity_root) + + setContentView(binding.root) + + val navHostFragment = supportFragmentManager.findFragmentById(R.id.container) as NavHostFragment + val navController = navHostFragment.navController + + binding.bottomNavigationView.setupWithNavController(navController) + + navController.addOnDestinationChangedListener { _, destination, _ -> + when (destination.id) { + R.id.mainFragment -> { + binding.bottomNavigationView.isVisible = true + } + + R.id.favoriteFragment -> { + binding.bottomNavigationView.isVisible = true + } + + R.id.teamFragment -> { + binding.bottomNavigationView.isVisible = true + } + + else -> { + binding.bottomNavigationView.isVisible = false + } + } + } // Пример использования access token для HeadHunter API networkRequestExample(accessToken = BuildConfig.HH_ACCESS_TOKEN) diff --git a/app/src/main/java/ru/practicum/android/diploma/util/App.kt b/app/src/main/java/ru/practicum/android/diploma/util/App.kt new file mode 100644 index 0000000000..04cb982990 --- /dev/null +++ b/app/src/main/java/ru/practicum/android/diploma/util/App.kt @@ -0,0 +1,24 @@ +package ru.practicum.android.diploma.util + +import android.app.Application +import org.koin.android.ext.koin.androidContext +import org.koin.core.context.startKoin +import ru.practicum.android.diploma.di.dataModule +import ru.practicum.android.diploma.di.interactorModule +import ru.practicum.android.diploma.di.repositoryModule +import ru.practicum.android.diploma.di.viewModelModule + +class App : Application() { + override fun onCreate() { + super.onCreate() + startKoin { + androidContext(this@App) + modules( + viewModelModule, + interactorModule, + repositoryModule, + dataModule + ) + } + } +} diff --git a/app/src/main/java/ru/practicum/android/diploma/util/DebounceExtension.kt b/app/src/main/java/ru/practicum/android/diploma/util/DebounceExtension.kt new file mode 100644 index 0000000000..d0e2479f70 --- /dev/null +++ b/app/src/main/java/ru/practicum/android/diploma/util/DebounceExtension.kt @@ -0,0 +1,40 @@ +package ru.practicum.android.diploma.util + +import android.view.View +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch +import ru.practicum.android.diploma.util.DebounceExtension.Companion.HALF_SECOND + +class DebounceExtension( + private val delayMillis: Long, + private val action: () -> Unit +) { + companion object { + const val HALF_SECOND = 500L + } + private var debounceJob: Job? = null + fun debounce() { + debounceJob?.cancel() + debounceJob = CoroutineScope(Dispatchers.Main).launch { + delay(delayMillis) + action.invoke() + } + } +} + +fun View.setDebouncedClickListener( + delayMillis: Long = HALF_SECOND, + onClick: () -> Unit +) { + var debounceJob: Job? = null + setOnClickListener { + debounceJob?.cancel() + debounceJob = CoroutineScope(Dispatchers.Main).launch { + delay(delayMillis) + onClick() + } + } +} diff --git a/app/src/main/java/ru/practicum/android/diploma/util/NetworkUtils.kt b/app/src/main/java/ru/practicum/android/diploma/util/NetworkUtils.kt new file mode 100644 index 0000000000..15c3e5e800 --- /dev/null +++ b/app/src/main/java/ru/practicum/android/diploma/util/NetworkUtils.kt @@ -0,0 +1,21 @@ + +package ru.practicum.android.diploma.util + +import android.content.Context +import android.net.ConnectivityManager +import android.net.NetworkCapabilities + +fun isInternetAvailable(context: Context): Boolean { + val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager + val capabilities = connectivityManager.getNetworkCapabilities(connectivityManager.activeNetwork) + var result = false + if (capabilities != null) { + result = when { + capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> true + capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> true + capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> true + else -> false + } + } + return result +} diff --git a/app/src/main/res/drawable/favorite_list_empty.webp b/app/src/main/res/drawable/favorite_list_empty.webp new file mode 100644 index 0000000000..579a6b17e8 Binary files /dev/null and b/app/src/main/res/drawable/favorite_list_empty.webp differ diff --git a/app/src/main/res/drawable/ic_arrow_back_16px.xml b/app/src/main/res/drawable/ic_arrow_back_16px.xml new file mode 100644 index 0000000000..687feddaa0 --- /dev/null +++ b/app/src/main/res/drawable/ic_arrow_back_16px.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_arrow_forward_14px.xml b/app/src/main/res/drawable/ic_arrow_forward_14px.xml new file mode 100644 index 0000000000..1c67cfceec --- /dev/null +++ b/app/src/main/res/drawable/ic_arrow_forward_14px.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_bottom_navigation_favorites_20px.xml b/app/src/main/res/drawable/ic_bottom_navigation_favorites_20px.xml new file mode 100644 index 0000000000..6f3f74b05f --- /dev/null +++ b/app/src/main/res/drawable/ic_bottom_navigation_favorites_20px.xml @@ -0,0 +1,12 @@ + + + diff --git a/app/src/main/res/drawable/ic_bottom_navigation_main_20px.xml b/app/src/main/res/drawable/ic_bottom_navigation_main_20px.xml new file mode 100644 index 0000000000..2fc4b7f5a5 --- /dev/null +++ b/app/src/main/res/drawable/ic_bottom_navigation_main_20px.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_bottom_navigation_team_20px.xml b/app/src/main/res/drawable/ic_bottom_navigation_team_20px.xml new file mode 100644 index 0000000000..62bdf9f3ca --- /dev/null +++ b/app/src/main/res/drawable/ic_bottom_navigation_team_20px.xml @@ -0,0 +1,12 @@ + + + diff --git a/app/src/main/res/drawable/ic_check_box_off_18px.xml b/app/src/main/res/drawable/ic_check_box_off_18px.xml new file mode 100644 index 0000000000..4e79128d2e --- /dev/null +++ b/app/src/main/res/drawable/ic_check_box_off_18px.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_check_box_on_18px.xml b/app/src/main/res/drawable/ic_check_box_on_18px.xml new file mode 100644 index 0000000000..f0660527da --- /dev/null +++ b/app/src/main/res/drawable/ic_check_box_on_18px.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_circle_button_off_20px.xml b/app/src/main/res/drawable/ic_circle_button_off_20px.xml new file mode 100644 index 0000000000..7c38e15687 --- /dev/null +++ b/app/src/main/res/drawable/ic_circle_button_off_20px.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_circle_button_on_20px.xml b/app/src/main/res/drawable/ic_circle_button_on_20px.xml new file mode 100644 index 0000000000..845d1dc586 --- /dev/null +++ b/app/src/main/res/drawable/ic_circle_button_on_20px.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_close_cross_14px.xml b/app/src/main/res/drawable/ic_close_cross_14px.xml new file mode 100644 index 0000000000..fa811ebf41 --- /dev/null +++ b/app/src/main/res/drawable/ic_close_cross_14px.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_edit_text_cursor.xml b/app/src/main/res/drawable/ic_edit_text_cursor.xml new file mode 100644 index 0000000000..198879ccc7 --- /dev/null +++ b/app/src/main/res/drawable/ic_edit_text_cursor.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_favorites_off_23px.xml b/app/src/main/res/drawable/ic_favorites_off_23px.xml new file mode 100644 index 0000000000..3e70aeaa56 --- /dev/null +++ b/app/src/main/res/drawable/ic_favorites_off_23px.xml @@ -0,0 +1,12 @@ + + + diff --git a/app/src/main/res/drawable/ic_favorites_on_20px.xml b/app/src/main/res/drawable/ic_favorites_on_20px.xml new file mode 100644 index 0000000000..9704bb012d --- /dev/null +++ b/app/src/main/res/drawable/ic_favorites_on_20px.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_filter_off_12px.xml b/app/src/main/res/drawable/ic_filter_off_12px.xml new file mode 100644 index 0000000000..3d49a8c915 --- /dev/null +++ b/app/src/main/res/drawable/ic_filter_off_12px.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_filter_on_24px.xml b/app/src/main/res/drawable/ic_filter_on_24px.xml new file mode 100644 index 0000000000..895eec1309 --- /dev/null +++ b/app/src/main/res/drawable/ic_filter_on_24px.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/ic_loader_36px.xml b/app/src/main/res/drawable/ic_loader_36px.xml new file mode 100644 index 0000000000..353f4ed834 --- /dev/null +++ b/app/src/main/res/drawable/ic_loader_36px.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_placeholder_30px.xml b/app/src/main/res/drawable/ic_placeholder_30px.xml new file mode 100644 index 0000000000..0a01279897 --- /dev/null +++ b/app/src/main/res/drawable/ic_placeholder_30px.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_search_18px.xml b/app/src/main/res/drawable/ic_search_18px.xml new file mode 100644 index 0000000000..47af517479 --- /dev/null +++ b/app/src/main/res/drawable/ic_search_18px.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_share_20px.xml b/app/src/main/res/drawable/ic_share_20px.xml new file mode 100644 index 0000000000..660fff81fa --- /dev/null +++ b/app/src/main/res/drawable/ic_share_20px.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/nav_color.xml b/app/src/main/res/drawable/nav_color.xml new file mode 100644 index 0000000000..51351ef4ca --- /dev/null +++ b/app/src/main/res/drawable/nav_color.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/app/src/main/res/drawable/no_connection_sceleton_head.webp b/app/src/main/res/drawable/no_connection_sceleton_head.webp new file mode 100644 index 0000000000..8a99bbf723 Binary files /dev/null and b/app/src/main/res/drawable/no_connection_sceleton_head.webp differ diff --git a/app/src/main/res/drawable/no_such_list_found.webp b/app/src/main/res/drawable/no_such_list_found.webp new file mode 100644 index 0000000000..7aadb909e8 Binary files /dev/null and b/app/src/main/res/drawable/no_such_list_found.webp differ diff --git a/app/src/main/res/drawable/no_vacancy_list.webp b/app/src/main/res/drawable/no_vacancy_list.webp new file mode 100644 index 0000000000..2cb57da1fe Binary files /dev/null and b/app/src/main/res/drawable/no_vacancy_list.webp differ diff --git a/app/src/main/res/drawable/search_image_default.webp b/app/src/main/res/drawable/search_image_default.webp new file mode 100644 index 0000000000..f69ccca69f Binary files /dev/null and b/app/src/main/res/drawable/search_image_default.webp differ diff --git a/app/src/main/res/drawable/server_error_placeholder_search.webp b/app/src/main/res/drawable/server_error_placeholder_search.webp new file mode 100644 index 0000000000..fb1e5cf2f2 Binary files /dev/null and b/app/src/main/res/drawable/server_error_placeholder_search.webp differ diff --git a/app/src/main/res/drawable/server_error_placeholder_vacancy.webp b/app/src/main/res/drawable/server_error_placeholder_vacancy.webp new file mode 100644 index 0000000000..65f8978e67 Binary files /dev/null and b/app/src/main/res/drawable/server_error_placeholder_vacancy.webp differ diff --git a/app/src/main/res/font/ys_display_bold.ttf b/app/src/main/res/font/ys_display_bold.ttf new file mode 100644 index 0000000000..f9b3f03cce Binary files /dev/null and b/app/src/main/res/font/ys_display_bold.ttf differ diff --git a/app/src/main/res/font/ys_display_medium.ttf b/app/src/main/res/font/ys_display_medium.ttf new file mode 100644 index 0000000000..cc63032e21 Binary files /dev/null and b/app/src/main/res/font/ys_display_medium.ttf differ diff --git a/app/src/main/res/font/ys_display_regular.ttf b/app/src/main/res/font/ys_display_regular.ttf new file mode 100644 index 0000000000..02173eb829 Binary files /dev/null and b/app/src/main/res/font/ys_display_regular.ttf differ diff --git a/app/src/main/res/layout/activity_root.xml b/app/src/main/res/layout/activity_root.xml index ea46b92d7b..5d0d44e0b4 100644 --- a/app/src/main/res/layout/activity_root.xml +++ b/app/src/main/res/layout/activity_root.xml @@ -6,14 +6,40 @@ android:layout_height="match_parent" tools:context=".ui.root.RootActivity"> - + + + + + app:menu="@menu/bottom_navigation_menu" /> + + + - \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_favourites.xml b/app/src/main/res/layout/fragment_favourites.xml new file mode 100644 index 0000000000..97b73e1ce0 --- /dev/null +++ b/app/src/main/res/layout/fragment_favourites.xml @@ -0,0 +1,23 @@ + + + + + + + diff --git a/app/src/main/res/layout/fragment_filter.xml b/app/src/main/res/layout/fragment_filter.xml new file mode 100644 index 0000000000..82b7e40871 --- /dev/null +++ b/app/src/main/res/layout/fragment_filter.xml @@ -0,0 +1,37 @@ + + + + + +