├── .gitignore ├── .idea ├── .gitignore ├── .name ├── codeStyles │ ├── Project.xml │ └── codeStyleConfig.xml ├── compiler.xml ├── deploymentTargetDropDown.xml ├── gradle.xml ├── kotlinc.xml ├── migrations.xml ├── misc.xml ├── other.xml └── vcs.xml ├── README.md ├── app ├── .gitignore ├── build.gradle.kts ├── google-services.json ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── commandiron │ │ └── vacationchecklist │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ ├── ic_launcher-playstore.png │ ├── java │ │ └── com │ │ │ └── commandiron │ │ │ └── vacationchecklist │ │ │ ├── AppViewModel.kt │ │ │ ├── MainActivity.kt │ │ │ ├── VacationCheckListApp.kt │ │ │ ├── data │ │ │ ├── broadcast_receiver │ │ │ │ └── AlarmReceiver.kt │ │ │ ├── di │ │ │ │ └── DataModule.kt │ │ │ ├── local │ │ │ │ ├── ChecklistDao.kt │ │ │ │ ├── ChecklistDatabase.kt │ │ │ │ └── entity │ │ │ │ │ └── CheckItemEntity.kt │ │ │ ├── mapper │ │ │ │ └── CheckItemMapper.kt │ │ │ ├── preferences │ │ │ │ └── DefaultPreferences.kt │ │ │ ├── repository │ │ │ │ └── DefaultRepositoryImpl.kt │ │ │ └── service │ │ │ │ └── NotificationService.kt │ │ │ ├── di │ │ │ └── AppModule.kt │ │ │ ├── domain │ │ │ ├── di │ │ │ │ └── DomainModule.kt │ │ │ ├── model │ │ │ │ ├── CheclistItem.kt │ │ │ │ └── Vacation.kt │ │ │ ├── preferences │ │ │ │ └── Preferences.kt │ │ │ ├── repository │ │ │ │ └── Repository.kt │ │ │ └── use_cases │ │ │ │ ├── DeleteAllCheckItems.kt │ │ │ │ ├── GetAllCheckItems.kt │ │ │ │ ├── GetAllVacations.kt │ │ │ │ ├── InsertAllCheckItems.kt │ │ │ │ ├── InsertCheckItem.kt │ │ │ │ ├── SetAlarm.kt │ │ │ │ └── UseCases.kt │ │ │ ├── navigation │ │ │ ├── BottomNavigation.kt │ │ │ ├── NavControllerExt.kt │ │ │ └── NavigationItem.kt │ │ │ ├── presentation │ │ │ ├── checklist │ │ │ │ ├── ChecklistScreen.kt │ │ │ │ ├── ChecklistState.kt │ │ │ │ ├── ChecklistUserEvent.kt │ │ │ │ ├── ChecklistViewModel.kt │ │ │ │ └── components │ │ │ │ │ ├── CheckListGridView.kt │ │ │ │ │ ├── CheckListListView.kt │ │ │ │ │ ├── CheckListUiPrefView.kt │ │ │ │ │ ├── ChecklistHeader.kt │ │ │ │ │ ├── ColumnItem.kt │ │ │ │ │ ├── GridItem.kt │ │ │ │ │ ├── MarkAlertDialog.kt │ │ │ │ │ ├── ReadyToGoView.kt │ │ │ │ │ └── SetAlarmAlertDialog.kt │ │ │ ├── components │ │ │ │ ├── AppLogoWithName.kt │ │ │ │ ├── CreateVacationBody.kt │ │ │ │ ├── CustomAlertDialog.kt │ │ │ │ ├── CustomButton.kt │ │ │ │ ├── CustomCircularIcon.kt │ │ │ │ ├── CustomHeader.kt │ │ │ │ ├── CustomSnackbar.kt │ │ │ │ ├── CustomTextField.kt │ │ │ │ ├── FromCompanyComponent.kt │ │ │ │ ├── ImportanceLevelDot.kt │ │ │ │ ├── LoadingBarAnimation.kt │ │ │ │ ├── LoadingThreeDotAnimation.kt │ │ │ │ ├── VacationItem.kt │ │ │ │ └── VacationsVerticalList.kt │ │ │ ├── create_vacation │ │ │ │ ├── CreateVacationScreen.kt │ │ │ │ ├── CreateVacationState.kt │ │ │ │ ├── CreateVacationUserEvent.kt │ │ │ │ └── CreateVacationViewModel.kt │ │ │ ├── get_started │ │ │ │ ├── GetStartedScreen.kt │ │ │ │ ├── GetStartedState.kt │ │ │ │ ├── GetStartedUserEvent.kt │ │ │ │ └── GetStartedViewModel.kt │ │ │ ├── hot_splash │ │ │ │ ├── HotSplashScreen.kt │ │ │ │ └── HotSplashViewModel.kt │ │ │ └── settings │ │ │ │ ├── SettingsScreen.kt │ │ │ │ ├── SettingsState.kt │ │ │ │ ├── SettingsUserEvent.kt │ │ │ │ └── SettingsViewModel.kt │ │ │ ├── ui │ │ │ └── theme │ │ │ │ ├── Color.kt │ │ │ │ ├── Shape.kt │ │ │ │ ├── Theme.kt │ │ │ │ └── Type.kt │ │ │ └── util │ │ │ ├── LocalProvidedValues.kt │ │ │ ├── Response.kt │ │ │ ├── UiEvent.kt │ │ │ └── UiText.kt │ └── res │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ ├── after_shave.png │ │ ├── all_weather_boots.png │ │ ├── balaclava.png │ │ ├── beach_ball.png │ │ ├── beach_chair.png │ │ ├── beach_towel.png │ │ ├── beach_umbrella.png │ │ ├── belt.png │ │ ├── board_game.png │ │ ├── book.png │ │ ├── camera.png │ │ ├── camera_charger.png │ │ ├── camping_tent.png │ │ ├── car_rental.png │ │ ├── casual_outfit.png │ │ ├── charger.png │ │ ├── checkpack_logo.xml │ │ ├── checkpack_logo_cold_splash.xml │ │ ├── ci_tech_logo.png │ │ ├── comb.png │ │ ├── contact_lens.png │ │ ├── deodorant.png │ │ ├── digital.png │ │ ├── electrical_converters.png │ │ ├── everyday_bag.png │ │ ├── first_aid_kit.png │ │ ├── game_console.png │ │ ├── hair_spray.png │ │ ├── hand_face_cream.png │ │ ├── hand_sanitizer.png │ │ ├── headphones.png │ │ ├── heavy_coat.png │ │ ├── hotel_reservation.png │ │ ├── ic_baseline_notifications_active_24.xml │ │ ├── ic_launcher_background.xml │ │ ├── identification.png │ │ ├── jacket.png │ │ ├── jewelry.png │ │ ├── laptop.png │ │ ├── laptop_charger.png │ │ ├── laundry_bag.png │ │ ├── leather_gloves.png │ │ ├── makeup.png │ │ ├── medication.png │ │ ├── nail_clippers.png │ │ ├── pajamas.png │ │ ├── pants.png │ │ ├── parfume.png │ │ ├── passport.png │ │ ├── personal_care.png │ │ ├── pillow_case.png │ │ ├── portable_charger.png │ │ ├── prescription_glasses.png │ │ ├── raincoat.png │ │ ├── razor.png │ │ ├── sandals.png │ │ ├── scarf.png │ │ ├── shampoo_conditioner.png │ │ ├── shaving_cream.png │ │ ├── shoes.png │ │ ├── shorts.png │ │ ├── ski_board_boots.png │ │ ├── ski_board_equipments.png │ │ ├── ski_board_glasses.png │ │ ├── ski_board_gloves.png │ │ ├── ski_board_helmet.png │ │ ├── ski_board_jacket.png │ │ ├── ski_board_pants.png │ │ ├── ski_board_socks.png │ │ ├── ski_trip.xml │ │ ├── smartphone.png │ │ ├── snack.png │ │ ├── snorkel.png │ │ ├── soap.png │ │ ├── socks.png │ │ ├── summer_vacation.xml │ │ ├── sun_block.png │ │ ├── sun_hat.png │ │ ├── sunglasses.png │ │ ├── sweater.png │ │ ├── swimwear.png │ │ ├── tampons_pad.png │ │ ├── tank_tops.png │ │ ├── tickets.png │ │ ├── toothbrush_toothpaste.png │ │ ├── towel.png │ │ ├── toys.png │ │ ├── umbrella.png │ │ ├── underwear.png │ │ ├── wallet.png │ │ ├── watch.png │ │ ├── water_shoe.png │ │ ├── wet_wipes.png │ │ └── winter_hat.png │ │ ├── font │ │ ├── poppins_black.ttf │ │ ├── poppins_black_italic.ttf │ │ ├── poppins_bold.ttf │ │ ├── poppins_bold_italic.ttf │ │ ├── poppins_extra_bold.ttf │ │ ├── poppins_extra_bold_italic.ttf │ │ ├── poppins_extra_light.ttf │ │ ├── poppins_extra_light_italic.ttf │ │ ├── poppins_italic.ttf │ │ ├── poppins_light.ttf │ │ ├── poppins_light_italic.ttf │ │ ├── poppins_medium.ttf │ │ ├── poppins_medium_italic.ttf │ │ ├── poppins_regular.ttf │ │ ├── poppins_semi_bold.ttf │ │ ├── poppins_semi_bold_italic.ttf │ │ ├── poppins_thin.ttf │ │ └── poppins_thin_italic.ttf │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── values-tr-rTR │ │ └── strings.xml │ │ ├── values │ │ ├── colors.xml │ │ ├── splash.xml │ │ ├── strings.xml │ │ └── themes.xml │ │ └── xml │ │ ├── backup_rules.xml │ │ └── data_extraction_rules.xml │ └── test │ └── java │ └── com │ └── commandiron │ └── vacationchecklist │ └── ExampleUnitTest.kt ├── build.gradle.kts ├── buildSrc ├── .gitignore ├── build.gradle.kts └── src │ └── main │ └── java │ ├── Accompanist.kt │ ├── AndroidX.kt │ ├── Build.kt │ ├── CommandIron.kt │ ├── Compose.kt │ ├── Coroutines.kt │ ├── DaggerHilt.kt │ ├── Firebase.kt │ ├── Google.kt │ ├── ProjectConfig.kt │ ├── Room.kt │ └── Testing.kt ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | .cxx 15 | local.properties 16 | 17 | /buildSrc/build/release\ 18 | app-release.apk 19 | output-metadata.json 20 | app-release.aab 21 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | -------------------------------------------------------------------------------- /.idea/.name: -------------------------------------------------------------------------------- 1 | VacationCheckList -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 9 | 10 | 122 | 123 | 125 | 126 | -------------------------------------------------------------------------------- /.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/deploymentTargetDropDown.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 20 | 21 | -------------------------------------------------------------------------------- /.idea/kotlinc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /.idea/migrations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/other.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |

4 | 5 |

CheckPack

6 | 7 |

8 | 9 | 10 | 11 |

12 | 13 |

14 | 15 | 16 | 17 |

18 | 19 |

20 | CheckPack is a native android checklist app for those going on vacation, written in Kotlin using Jetpack Compose. 21 |

22 |
23 | 24 | 25 | 26 | * Application - Features ☕ 27 | * Set alarm 28 | * One time splash screen 29 | * Multiple view mode for checklist 30 | * View scale for checklist 31 | * Settings 32 | * Language - English, Turkish 33 | * Tech-stack ⚛️ 34 | * [Kotlin](https://kotlinlang.org/) + [Coroutines](https://kotlinlang.org/docs/reference/coroutines-overview.html) - perform background operation 35 | * [Jetpack](https://developer.android.com/jetpack) 36 | * [Compose](https://developer.android.com/jetpack/compose) - toolkit for building native UI 37 | * [Navigation](https://developer.android.com/topic/libraries/architecture/navigation/) - deal with whole in-app navigation 38 | * [ViewModel](https://developer.android.com/topic/libraries/architecture/viewmodel) - store and manage UI-related data in a lifecycle conscious way 39 | * [Room](https://developer.android.com/jetpack/androidx/releases/room) - database object mapping 40 | * [Gson](https://github.com/google/gson) - serialization/deserialization library 41 | * [Accompanist](https://github.com/google/accompanist) 42 | * systemUi 43 | * [Hilt](https://dagger.dev/hilt/) - DI 44 | * [Material 3](https://m3.material.io) - design 45 | * [Google Firebase](https://firebase.google.com) 46 | * crashlytics 47 | * Architecture 🏗️ 48 | * Model-View-Intent 49 | * [Android Architecture components](https://developer.android.com/topic/libraries/architecture) ([ViewModel](https://developer.android.com/topic/libraries/architecture/viewmodel), [Navigation](https://developer.android.com/jetpack/androidx/releases/navigation)) 50 | 51 | * Todo ✔️ 52 | * Dark Theme ❌ 53 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /app/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("com.android.application") 3 | kotlin("android") 4 | id("dagger.hilt.android.plugin") 5 | id("kotlin-kapt") 6 | id("com.google.gms.google-services") 7 | id("com.google.firebase.crashlytics") 8 | } 9 | 10 | android { 11 | compileSdk = ProjectConfig.compileSdk 12 | 13 | defaultConfig { 14 | applicationId = ProjectConfig.appId 15 | minSdk = ProjectConfig.minSdk 16 | targetSdk = ProjectConfig.targetSdk 17 | versionCode = ProjectConfig.versionCode 18 | versionName = ProjectConfig.versionName 19 | 20 | vectorDrawables { 21 | useSupportLibrary = true 22 | } 23 | } 24 | buildTypes { 25 | getByName("release") { 26 | isMinifyEnabled = true 27 | isShrinkResources = true 28 | proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") 29 | } 30 | } 31 | buildFeatures { 32 | compose = true 33 | } 34 | compileOptions { 35 | sourceCompatibility = JavaVersion.VERSION_1_8 36 | targetCompatibility = JavaVersion.VERSION_1_8 37 | } 38 | kotlinOptions { 39 | jvmTarget = "1.8" 40 | freeCompilerArgs = freeCompilerArgs + listOf( 41 | "-opt-in=com.google.accompanist.pager.ExperimentalPagerApi", 42 | "-opt-in=androidx.compose.animation.ExperimentalAnimationApi", 43 | "-opt-in=androidx.compose.material3.ExperimentalMaterial3Api", 44 | "-opt-in=androidx.compose.ui.ExperimentalComposeUiApi", 45 | "-opt-in=androidx.compose.foundation.ExperimentalFoundationApi", 46 | ) 47 | } 48 | composeOptions { 49 | kotlinCompilerExtensionVersion = Compose.composeVersion 50 | } 51 | packagingOptions { 52 | resources.excludes.add("/META-INF/{AL2.0,LGPL2.1}") 53 | } 54 | } 55 | 56 | dependencies { 57 | implementation(Accompanist.systemUi) 58 | implementation(Accompanist.navigationAnimation) 59 | implementation(Accompanist.pager) 60 | 61 | implementation(AndroidX.coreKtx) 62 | implementation(AndroidX.appCompat) 63 | implementation(AndroidX.splashScreen) 64 | 65 | implementation(Compose.compiler) 66 | implementation(Compose.ui) 67 | implementation(Compose.uiToolingPreview) 68 | implementation(Compose.runtime) 69 | implementation(Compose.navigation) 70 | implementation(Compose.viewModelCompose) 71 | implementation(Compose.activityCompose) 72 | implementation(Compose.hiltNavigationCompose) 73 | 74 | implementation(Coroutines.coroutines) 75 | kapt(DaggerHilt.hiltCompiler) 76 | implementation(DaggerHilt.hiltAndroid) 77 | 78 | implementation(Google.material) 79 | implementation(Google.material3) 80 | implementation(Google.materialIconsCore) 81 | implementation(Google.materialIconsExtended) 82 | implementation(Google.gson) 83 | 84 | implementation(platform(Firebase.bom)) 85 | implementation(Firebase.analytics) 86 | implementation(Firebase.crashlytics) 87 | 88 | implementation(Room.runtime) 89 | kapt(Room.compiler) 90 | implementation(Room.ktx) 91 | 92 | implementation(CommandIron.wheelPickerCompose) 93 | 94 | testImplementation(Testing.junit) 95 | 96 | androidTestImplementation(Testing.junitAndroidExt) 97 | androidTestImplementation(Testing.composeUiTestJunit4) 98 | 99 | debugImplementation(Testing.composeUiTooling) 100 | debugImplementation(Testing.composeUiTestManifest) 101 | } -------------------------------------------------------------------------------- /app/google-services.json: -------------------------------------------------------------------------------- 1 | { 2 | "project_info": { 3 | "project_number": "954474646555", 4 | "project_id": "checkpack-f2bb6", 5 | "storage_bucket": "checkpack-f2bb6.appspot.com" 6 | }, 7 | "client": [ 8 | { 9 | "client_info": { 10 | "mobilesdk_app_id": "1:954474646555:android:29a77351bf45641949fcbe", 11 | "android_client_info": { 12 | "package_name": "com.commandiron.vacationchecklist" 13 | } 14 | }, 15 | "oauth_client": [ 16 | { 17 | "client_id": "954474646555-is8keins8qi823ts0u5gp582t555sk7v.apps.googleusercontent.com", 18 | "client_type": 3 19 | } 20 | ], 21 | "api_key": [ 22 | { 23 | "current_key": "AIzaSyDOMmB8D9bygIqgrnXx-UplPkmjW9j3GPE" 24 | } 25 | ], 26 | "services": { 27 | "appinvite_service": { 28 | "other_platform_oauth_client": [ 29 | { 30 | "client_id": "954474646555-is8keins8qi823ts0u5gp582t555sk7v.apps.googleusercontent.com", 31 | "client_type": 3 32 | } 33 | ] 34 | } 35 | } 36 | } 37 | ], 38 | "configuration_version": "1" 39 | } -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle.kts. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /app/src/androidTest/java/com/commandiron/vacationchecklist/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist 2 | 3 | import androidx.test.platform.app.InstrumentationRegistry 4 | import androidx.test.ext.junit.runners.AndroidJUnit4 5 | 6 | import org.junit.Test 7 | import org.junit.runner.RunWith 8 | 9 | import org.junit.Assert.* 10 | 11 | /** 12 | * Instrumented test, which will execute on an Android device. 13 | * 14 | * See [testing documentation](http://d.android.com/tools/testing). 15 | */ 16 | @RunWith(AndroidJUnit4::class) 17 | class ExampleInstrumentedTest { 18 | @Test 19 | fun useAppContext() { 20 | // Context of the app under test. 21 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext 22 | assertEquals("com.commandiron.vacationchecklist", appContext.packageName) 23 | } 24 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 17 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 31 | 32 | -------------------------------------------------------------------------------- /app/src/main/ic_launcher-playstore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/ic_launcher-playstore.png -------------------------------------------------------------------------------- /app/src/main/java/com/commandiron/vacationchecklist/AppViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist 2 | 3 | import androidx.compose.runtime.getValue 4 | import androidx.compose.runtime.mutableStateOf 5 | import androidx.compose.runtime.setValue 6 | import androidx.lifecycle.ViewModel 7 | import androidx.lifecycle.viewModelScope 8 | import dagger.hilt.android.lifecycle.HiltViewModel 9 | import kotlinx.coroutines.delay 10 | import kotlinx.coroutines.launch 11 | import javax.inject.Inject 12 | 13 | @HiltViewModel 14 | class AppViewModel @Inject constructor( 15 | ): ViewModel() { 16 | 17 | var state by mutableStateOf(AppState()) 18 | private set 19 | 20 | init { 21 | viewModelScope.launch { 22 | delay(timeMillis = state.coldSplashScreenDelay) 23 | state = state.copy( 24 | isColdSplashScreenVisible = false 25 | ) 26 | } 27 | } 28 | } 29 | 30 | data class AppState( 31 | val isColdSplashScreenVisible: Boolean = true, 32 | val coldSplashScreenDelay: Long = 500L 33 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/commandiron/vacationchecklist/VacationCheckListApp.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist 2 | 3 | import android.app.Application 4 | import dagger.hilt.android.HiltAndroidApp 5 | 6 | @HiltAndroidApp 7 | class VacationCheckListApp: Application() -------------------------------------------------------------------------------- /app/src/main/java/com/commandiron/vacationchecklist/data/broadcast_receiver/AlarmReceiver.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist.data.broadcast_receiver 2 | 3 | import android.content.BroadcastReceiver 4 | import android.content.Context 5 | import android.content.Intent 6 | import android.util.Log 7 | import com.commandiron.vacationchecklist.data.service.NotificationService 8 | 9 | class AlarmReceiver: BroadcastReceiver() { 10 | override fun onReceive(context: Context, intent: Intent) { 11 | val service = NotificationService(context) 12 | try { 13 | service.showNotification() 14 | } catch (ex: Exception) { 15 | Log.d("Receive Ex", "onReceive: ${ex.printStackTrace()}") 16 | } 17 | } 18 | } 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /app/src/main/java/com/commandiron/vacationchecklist/data/di/DataModule.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist.data.di 2 | 3 | import android.content.Context 4 | import androidx.room.Room 5 | import com.commandiron.vacationchecklist.data.local.ChecklistDao 6 | import com.commandiron.vacationchecklist.data.local.ChecklistDatabase 7 | import com.commandiron.vacationchecklist.data.repository.DefaultRepositoryImpl 8 | import com.commandiron.vacationchecklist.domain.repository.Repository 9 | import dagger.Module 10 | import dagger.Provides 11 | import dagger.hilt.InstallIn 12 | import dagger.hilt.android.qualifiers.ApplicationContext 13 | import dagger.hilt.components.SingletonComponent 14 | import javax.inject.Singleton 15 | 16 | @Module 17 | @InstallIn(SingletonComponent::class) 18 | object DataModule { 19 | 20 | @Provides 21 | @Singleton 22 | fun provideChecklistDatabase( 23 | @ApplicationContext context: Context, 24 | ): ChecklistDatabase { 25 | return Room.databaseBuilder( 26 | context, 27 | ChecklistDatabase::class.java, 28 | "checklist_db" 29 | ).build() 30 | } 31 | 32 | @Provides 33 | fun provideChecklistDao(database: ChecklistDatabase) = database.dao 34 | 35 | @Provides 36 | @Singleton 37 | fun provideToolsRepository( 38 | checklistDao: ChecklistDao 39 | ): Repository { 40 | return DefaultRepositoryImpl( 41 | dao = checklistDao 42 | ) 43 | } 44 | } -------------------------------------------------------------------------------- /app/src/main/java/com/commandiron/vacationchecklist/data/local/ChecklistDao.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist.data.local 2 | 3 | import androidx.room.Dao 4 | import androidx.room.Insert 5 | import androidx.room.OnConflictStrategy 6 | import androidx.room.Query 7 | import com.commandiron.vacationchecklist.data.local.entity.CheckItemEntity 8 | 9 | @Dao 10 | interface ChecklistDao { 11 | 12 | @Insert(onConflict = OnConflictStrategy.REPLACE) 13 | suspend fun insert(vararg checkItemEntity: CheckItemEntity) 14 | 15 | @Query("DELETE FROM checkitementity") 16 | suspend fun deleteAll() 17 | 18 | @Query("SELECT * FROM checkitementity") 19 | suspend fun getAll(): List 20 | } -------------------------------------------------------------------------------- /app/src/main/java/com/commandiron/vacationchecklist/data/local/ChecklistDatabase.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist.data.local 2 | 3 | import androidx.room.Database 4 | import androidx.room.RoomDatabase 5 | import com.commandiron.vacationchecklist.data.local.entity.CheckItemEntity 6 | 7 | @Database( 8 | entities = [CheckItemEntity::class], 9 | version = 1, 10 | exportSchema = false 11 | ) 12 | abstract class ChecklistDatabase: RoomDatabase(){ 13 | abstract val dao: ChecklistDao 14 | } -------------------------------------------------------------------------------- /app/src/main/java/com/commandiron/vacationchecklist/data/local/entity/CheckItemEntity.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist.data.local.entity 2 | 3 | import androidx.room.Entity 4 | import androidx.room.PrimaryKey 5 | 6 | @Entity 7 | data class CheckItemEntity( 8 | @PrimaryKey(autoGenerate = true) 9 | val id: Int? = null, 10 | val name: String, 11 | val isChecked: Boolean, 12 | val isMarked: Boolean, 13 | val iconDrawable: Int, 14 | val importanceLevel: Int, 15 | val gender: Int, 16 | val category: Int, 17 | val vacationType: Int 18 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/commandiron/vacationchecklist/data/mapper/CheckItemMapper.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist.data.mapper 2 | 3 | import com.commandiron.vacationchecklist.data.local.entity.CheckItemEntity 4 | import com.commandiron.vacationchecklist.domain.model.CheckItem 5 | 6 | fun CheckItemEntity.toCheckItem(): CheckItem { 7 | return CheckItem( 8 | id = id, 9 | name = name, 10 | isChecked = isChecked, 11 | isMarked = isMarked, 12 | iconDrawable = iconDrawable, 13 | importanceLevel = intToImportanceLevel(importanceLevel), 14 | gender = gender, 15 | category = category, 16 | vacationType = vacationType 17 | ) 18 | } 19 | 20 | fun CheckItem.toCheckItemEntity(): CheckItemEntity { 21 | return CheckItemEntity( 22 | id = id, 23 | name = name, 24 | isChecked = isChecked, 25 | isMarked = isMarked, 26 | iconDrawable = iconDrawable, 27 | importanceLevel = importanceLevelToInt(importanceLevel), 28 | gender = gender, 29 | category = category, 30 | vacationType = vacationType 31 | ) 32 | } 33 | 34 | private fun importanceLevelToInt(importanceLevel: CheckItem.ImportanceLevel): Int { 35 | return when(importanceLevel){ 36 | CheckItem.ImportanceLevel.MUST -> 0 37 | CheckItem.ImportanceLevel.OPTIONAL -> 1 38 | } 39 | } 40 | 41 | private fun intToImportanceLevel(importanceLevel: Int): CheckItem.ImportanceLevel { 42 | return when(importanceLevel){ 43 | 0 -> CheckItem.ImportanceLevel.MUST 44 | 1 -> CheckItem.ImportanceLevel.OPTIONAL 45 | else -> CheckItem.ImportanceLevel.MUST 46 | } 47 | } -------------------------------------------------------------------------------- /app/src/main/java/com/commandiron/vacationchecklist/data/preferences/DefaultPreferences.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist.data.preferences 2 | 3 | import android.content.SharedPreferences 4 | import com.commandiron.vacationchecklist.domain.preferences.Preferences 5 | 6 | class DefaultPreferences( 7 | private val sharedPref: SharedPreferences 8 | ): Preferences { 9 | override fun saveShouldShowHotSplash(shouldShow: Boolean) { 10 | sharedPref.edit() 11 | .putBoolean(Preferences.KEY_SHOULD_SHOW_HOT_SPLASH, shouldShow) 12 | .apply() 13 | } 14 | 15 | override fun loadShouldShowHotSplash(): Boolean { 16 | return sharedPref.getBoolean( 17 | Preferences.KEY_SHOULD_SHOW_HOT_SPLASH, 18 | true 19 | ) 20 | } 21 | 22 | override fun saveActiveVacationId(id: Int) { 23 | sharedPref.edit() 24 | .putInt(Preferences.KEY_SAVE_LOAD_ACTIVE_VACATION, id) 25 | .apply() 26 | } 27 | 28 | override fun loadActiveVacationId(): Int { 29 | return sharedPref.getInt( 30 | Preferences.KEY_SAVE_LOAD_ACTIVE_VACATION, 31 | 0 32 | ) 33 | } 34 | 35 | override fun saveShouldDoubleCheck(shouldDoubleCheck: Boolean) { 36 | sharedPref.edit() 37 | .putBoolean(Preferences.KEY_SHOULD_DOUBLE_CHECK, shouldDoubleCheck) 38 | .apply() 39 | } 40 | 41 | override fun loadShouldDoubleCheck(): Boolean { 42 | return sharedPref.getBoolean( 43 | Preferences.KEY_SHOULD_DOUBLE_CHECK, 44 | false 45 | ) 46 | } 47 | 48 | override fun saveShouldShowGridView(shouldShow: Boolean) { 49 | sharedPref.edit() 50 | .putBoolean(Preferences.KEY_SHOULD_SHOW_GRID_VIEW, shouldShow) 51 | .apply() 52 | } 53 | 54 | override fun loadShouldShowGridView(): Boolean { 55 | return sharedPref.getBoolean( 56 | Preferences.KEY_SHOULD_SHOW_GRID_VIEW, 57 | false 58 | ) 59 | } 60 | 61 | override fun saveSliderValue(sliderValue: Float) { 62 | sharedPref.edit() 63 | .putFloat(Preferences.KEY_SAVE_LOAD_SLIDER_VALUE, sliderValue) 64 | .apply() 65 | } 66 | 67 | override fun loadSliderValue(): Float { 68 | return sharedPref.getFloat( 69 | Preferences.KEY_SAVE_LOAD_SLIDER_VALUE, 70 | 0.5f 71 | ) 72 | } 73 | 74 | override fun saveListFirstVisibleItemIndex(itemIndex: Int) { 75 | sharedPref.edit() 76 | .putInt(Preferences.KEY_SAVE_LOAD_LIST_FIRST_VISIBLE_ITEM_INDEX, itemIndex) 77 | .apply() 78 | } 79 | 80 | override fun loadListFirstVisibleItemIndex(): Int { 81 | return sharedPref.getInt( 82 | Preferences.KEY_SAVE_LOAD_LIST_FIRST_VISIBLE_ITEM_INDEX, 83 | 0 84 | ) 85 | } 86 | } -------------------------------------------------------------------------------- /app/src/main/java/com/commandiron/vacationchecklist/data/repository/DefaultRepositoryImpl.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist.data.repository 2 | 3 | import com.commandiron.vacationchecklist.data.local.ChecklistDao 4 | import com.commandiron.vacationchecklist.data.mapper.toCheckItem 5 | import com.commandiron.vacationchecklist.data.mapper.toCheckItemEntity 6 | import com.commandiron.vacationchecklist.domain.model.CheckItem 7 | import com.commandiron.vacationchecklist.domain.repository.Repository 8 | 9 | class DefaultRepositoryImpl( 10 | private val dao: ChecklistDao, 11 | ): Repository { 12 | 13 | override suspend fun insertCheckItems(checkItems: List) { 14 | val checklistItemEntities = checkItems.map { it.toCheckItemEntity() } 15 | dao.insert(*checklistItemEntities.toTypedArray()) 16 | } 17 | 18 | override suspend fun deleteAllCheckItems() { 19 | dao.deleteAll() 20 | } 21 | 22 | override suspend fun getAllCheckItems(): List { 23 | return dao.getAll().map { it.toCheckItem() } 24 | } 25 | } -------------------------------------------------------------------------------- /app/src/main/java/com/commandiron/vacationchecklist/data/service/NotificationService.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist.data.service 2 | 3 | import android.app.NotificationChannel 4 | import android.app.NotificationManager 5 | import android.content.Context 6 | import android.graphics.Bitmap 7 | import android.graphics.Bitmap.createBitmap 8 | import android.graphics.Canvas 9 | import android.os.Build 10 | import androidx.appcompat.content.res.AppCompatResources 11 | import androidx.compose.material.icons.Icons 12 | import androidx.compose.material.icons.filled.Alarm 13 | import androidx.core.app.NotificationCompat 14 | import androidx.core.content.ContextCompat 15 | import com.commandiron.vacationchecklist.R 16 | 17 | class NotificationService( 18 | private val context: Context 19 | ) { 20 | fun showNotification(){ 21 | val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager 22 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { 23 | val channel = NotificationChannel(CHANNEL_ID, CHANNEL_NAME, NotificationManager.IMPORTANCE_DEFAULT) 24 | notificationManager.createNotificationChannel(channel) 25 | } 26 | val notification = NotificationCompat.Builder(context, CHANNEL_ID) 27 | .setContentTitle(NotificationAttr.title) 28 | .setContentText(NotificationAttr.desc) 29 | .setLargeIcon(context.vectorToBitmap(R.drawable.checkpack_logo)) 30 | .setSmallIcon(R.drawable.ic_baseline_notifications_active_24) 31 | .setColor(ContextCompat.getColor(context,R.color.notificationColor)) 32 | .build() 33 | notificationManager.notify(1, notification) 34 | } 35 | 36 | companion object{ 37 | const val CHANNEL_ID = "channel_id" 38 | const val CHANNEL_NAME = "channel_name" 39 | } 40 | } 41 | 42 | object NotificationAttr { 43 | var title: String = "" 44 | var desc: String = "" 45 | } 46 | 47 | fun Context.vectorToBitmap(drawableId: Int): Bitmap? { 48 | val drawable = AppCompatResources.getDrawable(this, drawableId) ?: return null 49 | val bitmap = createBitmap( 50 | drawable.intrinsicWidth, drawable.intrinsicHeight, Bitmap.Config.ARGB_8888 51 | ) ?: return null 52 | val canvas = Canvas(bitmap) 53 | drawable.setBounds(0, 0, canvas.width, canvas.height) 54 | drawable.draw(canvas) 55 | return bitmap 56 | } -------------------------------------------------------------------------------- /app/src/main/java/com/commandiron/vacationchecklist/di/AppModule.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist.di 2 | 3 | import android.app.Application 4 | import android.content.Context 5 | import android.content.SharedPreferences 6 | import com.commandiron.vacationchecklist.data.preferences.DefaultPreferences 7 | import com.commandiron.vacationchecklist.domain.preferences.Preferences 8 | import dagger.Module 9 | import dagger.Provides 10 | import dagger.hilt.InstallIn 11 | import dagger.hilt.components.SingletonComponent 12 | import javax.inject.Singleton 13 | 14 | @Module 15 | @InstallIn(SingletonComponent::class) 16 | object AppModule { 17 | 18 | @Provides 19 | @Singleton 20 | fun provideSharedPreferences( 21 | app: Application 22 | ): SharedPreferences { 23 | return app.getSharedPreferences("shared_pref", Context.MODE_PRIVATE) 24 | } 25 | 26 | @Provides 27 | @Singleton 28 | fun providePreferences(sharedPreferences: SharedPreferences): Preferences { 29 | return DefaultPreferences(sharedPreferences) 30 | } 31 | } -------------------------------------------------------------------------------- /app/src/main/java/com/commandiron/vacationchecklist/domain/di/DomainModule.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist.domain.di 2 | 3 | import android.content.Context 4 | import com.commandiron.vacationchecklist.domain.repository.Repository 5 | import com.commandiron.vacationchecklist.domain.use_cases.* 6 | import dagger.Module 7 | import dagger.Provides 8 | import dagger.hilt.InstallIn 9 | import dagger.hilt.android.components.ViewModelComponent 10 | import dagger.hilt.android.qualifiers.ApplicationContext 11 | import dagger.hilt.android.scopes.ViewModelScoped 12 | 13 | @Module 14 | @InstallIn(ViewModelComponent::class) 15 | object DomainModule { 16 | 17 | @ViewModelScoped 18 | @Provides 19 | fun provideUseCases( 20 | @ApplicationContext context: Context, 21 | repository: Repository 22 | ): UseCases { 23 | return UseCases( 24 | getAllVacations = GetAllVacations(), 25 | insertAllCheckItems = InsertAllCheckItems(repository), 26 | deleteAllCheckItems = DeleteAllCheckItems(repository), 27 | getAllCheckItems = GetAllCheckItems(repository), 28 | insertCheckItem = InsertCheckItem(repository), 29 | setAlarm = SetAlarm(context) 30 | ) 31 | } 32 | } -------------------------------------------------------------------------------- /app/src/main/java/com/commandiron/vacationchecklist/domain/model/Vacation.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist.domain.model 2 | 3 | import com.commandiron.vacationchecklist.R 4 | 5 | data class Vacation( 6 | val id: Int, 7 | val name: String, 8 | val iconDrawable: Int, 9 | ) 10 | 11 | val vacations = listOf( 12 | Vacation( 13 | id = 0, 14 | name = "Summer Vacation", 15 | iconDrawable = R.drawable.summer_vacation 16 | ), 17 | Vacation( 18 | id = 1, 19 | name = "Ski Trip", 20 | iconDrawable = R.drawable.ski_trip 21 | ) 22 | // Vacation( 23 | // id = 2, 24 | // name = "Camping", 25 | // iconDrawable = R.drawable.camping_tent 26 | // ), 27 | // Vacation( 28 | // id = 3, 29 | // name = "Caravan", 30 | // iconDrawable = R.drawable.caravan 31 | // ), 32 | // Vacation( 33 | // id = 4, 34 | // name = "Digital Detox", 35 | // iconDrawable = R.drawable.digital 36 | // ), 37 | // Vacation( 38 | // id = 5, 39 | // name = "Backpacking", 40 | // iconDrawable = R.drawable.backpack 41 | // ) 42 | ) 43 | -------------------------------------------------------------------------------- /app/src/main/java/com/commandiron/vacationchecklist/domain/preferences/Preferences.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist.domain.preferences 2 | 3 | interface Preferences { 4 | fun saveShouldShowHotSplash(shouldShow: Boolean) 5 | fun loadShouldShowHotSplash(): Boolean 6 | 7 | fun saveActiveVacationId(id: Int) 8 | fun loadActiveVacationId(): Int 9 | 10 | fun saveShouldDoubleCheck(shouldDoubleCheck: Boolean) 11 | fun loadShouldDoubleCheck(): Boolean 12 | 13 | fun saveShouldShowGridView(shouldShow: Boolean) 14 | fun loadShouldShowGridView(): Boolean 15 | 16 | fun saveSliderValue(sliderValue: Float) 17 | fun loadSliderValue(): Float 18 | 19 | fun saveListFirstVisibleItemIndex(itemIndex: Int) 20 | fun loadListFirstVisibleItemIndex(): Int 21 | 22 | companion object { 23 | const val KEY_SHOULD_SHOW_HOT_SPLASH = "should_show_hotSplash" 24 | const val KEY_SAVE_LOAD_ACTIVE_VACATION = "save_load_active_vacation" 25 | const val KEY_SHOULD_DOUBLE_CHECK = "should_double_check" 26 | const val KEY_SHOULD_SHOW_GRID_VIEW = "should_show_grid_view" 27 | const val KEY_SAVE_LOAD_SLIDER_VALUE = "save_load_slider_value" 28 | const val KEY_SAVE_LOAD_LIST_FIRST_VISIBLE_ITEM_INDEX = "save_load_list_first_visible_item_index" 29 | } 30 | } -------------------------------------------------------------------------------- /app/src/main/java/com/commandiron/vacationchecklist/domain/repository/Repository.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist.domain.repository 2 | 3 | import com.commandiron.vacationchecklist.domain.model.CheckItem 4 | 5 | interface Repository { 6 | suspend fun insertCheckItems(checkItems: List) 7 | suspend fun deleteAllCheckItems() 8 | suspend fun getAllCheckItems(): List 9 | } -------------------------------------------------------------------------------- /app/src/main/java/com/commandiron/vacationchecklist/domain/use_cases/DeleteAllCheckItems.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist.domain.use_cases 2 | 3 | import com.commandiron.vacationchecklist.domain.repository.Repository 4 | 5 | class DeleteAllCheckItems( 6 | private val repository: Repository 7 | ) { 8 | suspend operator fun invoke(){ 9 | repository.deleteAllCheckItems() 10 | } 11 | } -------------------------------------------------------------------------------- /app/src/main/java/com/commandiron/vacationchecklist/domain/use_cases/GetAllCheckItems.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist.domain.use_cases 2 | 3 | import com.commandiron.vacationchecklist.domain.model.CheckItem 4 | import com.commandiron.vacationchecklist.domain.repository.Repository 5 | 6 | class GetAllCheckItems( 7 | private val repository: Repository 8 | ) { 9 | suspend operator fun invoke(): List { 10 | return repository.getAllCheckItems() 11 | } 12 | } -------------------------------------------------------------------------------- /app/src/main/java/com/commandiron/vacationchecklist/domain/use_cases/GetAllVacations.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist.domain.use_cases 2 | 3 | import com.commandiron.vacationchecklist.domain.model.vacations 4 | 5 | class GetAllVacations { 6 | operator fun invoke() = vacations 7 | } -------------------------------------------------------------------------------- /app/src/main/java/com/commandiron/vacationchecklist/domain/use_cases/InsertAllCheckItems.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist.domain.use_cases 2 | 3 | import com.commandiron.vacationchecklist.domain.model.Vacation 4 | import com.commandiron.vacationchecklist.domain.model.commonCheckItems 5 | import com.commandiron.vacationchecklist.domain.model.skiTripCheckItems 6 | import com.commandiron.vacationchecklist.domain.model.summerVacationCheckItems 7 | import com.commandiron.vacationchecklist.domain.repository.Repository 8 | 9 | class InsertAllCheckItems( 10 | private val repository: Repository 11 | ) { 12 | suspend operator fun invoke(vacation: Vacation){ 13 | when(vacation.id){ 14 | 0 -> { 15 | val checklistItems = commonCheckItems + summerVacationCheckItems 16 | repository.insertCheckItems(checklistItems) 17 | } 18 | 1 -> { 19 | val checklistItems = commonCheckItems + skiTripCheckItems 20 | repository.insertCheckItems(checklistItems) 21 | } 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /app/src/main/java/com/commandiron/vacationchecklist/domain/use_cases/InsertCheckItem.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist.domain.use_cases 2 | 3 | import com.commandiron.vacationchecklist.domain.model.CheckItem 4 | import com.commandiron.vacationchecklist.domain.repository.Repository 5 | 6 | class InsertCheckItem( 7 | private val repository: Repository 8 | ) { 9 | suspend operator fun invoke(checkItem: CheckItem){ 10 | repository.insertCheckItems(listOf(checkItem)) 11 | } 12 | } -------------------------------------------------------------------------------- /app/src/main/java/com/commandiron/vacationchecklist/domain/use_cases/SetAlarm.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist.domain.use_cases 2 | 3 | import android.app.AlarmManager 4 | import android.app.Application 5 | import android.app.PendingIntent 6 | import android.content.Context 7 | import android.content.Intent 8 | import android.os.Build 9 | import com.commandiron.vacationchecklist.data.broadcast_receiver.AlarmReceiver 10 | import com.commandiron.vacationchecklist.data.service.NotificationAttr 11 | import java.time.LocalDateTime 12 | import java.time.temporal.ChronoUnit 13 | 14 | class SetAlarm( 15 | private val context: Context 16 | ) { 17 | operator fun invoke( 18 | notificationTitle: String, 19 | notificationDesc: String, 20 | time: LocalDateTime 21 | ) { 22 | if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){ 23 | NotificationAttr.title = notificationTitle 24 | NotificationAttr.desc = notificationDesc 25 | val alarmTime = 26 | System.currentTimeMillis() + 27 | ChronoUnit.MILLIS.between( 28 | LocalDateTime.now(), time 29 | ) 30 | 31 | val intent = Intent(context, AlarmReceiver::class.java) 32 | val pendingIntent = PendingIntent.getBroadcast( 33 | context, 34 | 0, 35 | intent, 36 | if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) PendingIntent.FLAG_IMMUTABLE else 0 37 | ) 38 | 39 | val alarmManager = context.getSystemService(Application.ALARM_SERVICE) as AlarmManager 40 | alarmManager.set(AlarmManager.RTC_WAKEUP, alarmTime, pendingIntent) 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /app/src/main/java/com/commandiron/vacationchecklist/domain/use_cases/UseCases.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist.domain.use_cases 2 | 3 | class UseCases( 4 | val getAllVacations: GetAllVacations, 5 | val insertAllCheckItems: InsertAllCheckItems, 6 | val deleteAllCheckItems: DeleteAllCheckItems, 7 | val getAllCheckItems: GetAllCheckItems, 8 | val insertCheckItem: InsertCheckItem, 9 | val setAlarm: SetAlarm 10 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/commandiron/vacationchecklist/navigation/BottomNavigation.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist.navigation 2 | 3 | import androidx.compose.animation.AnimatedVisibility 4 | import androidx.compose.animation.fadeIn 5 | import androidx.compose.animation.fadeOut 6 | import androidx.compose.foundation.clickable 7 | import androidx.compose.foundation.layout.fillMaxSize 8 | import androidx.compose.foundation.layout.fillMaxHeight 9 | import androidx.compose.foundation.layout.Row 10 | import androidx.compose.foundation.layout.Box 11 | import androidx.compose.foundation.layout.Column 12 | import androidx.compose.foundation.layout.fillMaxWidth 13 | import androidx.compose.foundation.layout.height 14 | import androidx.compose.foundation.layout.padding 15 | import androidx.compose.foundation.layout.Arrangement 16 | import androidx.compose.foundation.layout.aspectRatio 17 | import androidx.compose.foundation.layout.Spacer 18 | import androidx.compose.foundation.shape.RoundedCornerShape 19 | import androidx.compose.material.ripple.LocalRippleTheme 20 | import androidx.compose.material3.Icon 21 | import androidx.compose.material3.MaterialTheme 22 | import androidx.compose.material3.Surface 23 | import androidx.compose.material3.Text 24 | import androidx.compose.runtime.Composable 25 | import androidx.compose.runtime.CompositionLocalProvider 26 | import androidx.compose.ui.Alignment 27 | import androidx.compose.ui.Modifier 28 | import androidx.compose.ui.res.stringResource 29 | import androidx.compose.ui.text.font.FontWeight 30 | import com.commandiron.vacationchecklist.util.LocalSpacing 31 | import com.commandiron.vacationchecklist.util.NoRippleTheme 32 | 33 | @Composable 34 | fun BottomNavigation( 35 | modifier: Modifier = Modifier, 36 | currentRoute: String?, 37 | onBottomNavItemClick:(String) -> Unit 38 | ) { 39 | val spacing = LocalSpacing.current 40 | val navigationItems = listOf( 41 | NavigationItem.ChecklistScreen, 42 | NavigationItem.CreateVacationScreen, 43 | NavigationItem.SettingsScreen 44 | ) 45 | CompositionLocalProvider(LocalRippleTheme provides NoRippleTheme) { 46 | AnimatedVisibility( 47 | visible = navigationItems.map { it.route }.contains(currentRoute), 48 | enter = fadeIn(), 49 | exit = fadeOut() 50 | ) { 51 | Surface( 52 | modifier = Modifier 53 | .padding(spacing.bottomNavigationPadding) 54 | .height(spacing.bottomNavigationHeight) 55 | .fillMaxWidth(), 56 | color = MaterialTheme.colorScheme.primary, 57 | contentColor = MaterialTheme.colorScheme.onPrimary, 58 | shape = RoundedCornerShape(spacing.spaceExtraLarge) 59 | ) { 60 | Row( 61 | modifier 62 | .fillMaxSize() 63 | .padding(horizontal = spacing.spaceLarge) 64 | ) { 65 | navigationItems.forEach { item -> 66 | Box( 67 | modifier = Modifier 68 | .weight(1f) 69 | .fillMaxHeight() 70 | .clickable { onBottomNavItemClick(item.route) }, 71 | contentAlignment = Alignment.Center 72 | ) { 73 | Column( 74 | modifier = Modifier 75 | .fillMaxSize(), 76 | verticalArrangement = Arrangement.Center, 77 | horizontalAlignment = Alignment.CenterHorizontally 78 | ) { 79 | Icon( 80 | modifier = Modifier 81 | .fillMaxHeight(0.40f) 82 | .aspectRatio(1f), 83 | imageVector = if(currentRoute == item.route) { 84 | item.selectedIcon!! 85 | } else item.unSelectedIcon!!, 86 | contentDescription = null, 87 | tint = if(currentRoute == item.route) { 88 | MaterialTheme.colorScheme.onPrimaryContainer 89 | } else MaterialTheme.colorScheme.onPrimaryContainer.copy(alpha = 0.3f) 90 | ) 91 | Spacer(modifier = Modifier.height(spacing.spaceExtraSmall)) 92 | AnimatedVisibility( 93 | visible = currentRoute == item.route 94 | ) { 95 | Text( 96 | text = stringResource(item.titleResource), 97 | style = MaterialTheme.typography.labelLarge.copy( 98 | fontWeight = FontWeight.Bold 99 | ) 100 | ) 101 | } 102 | } 103 | } 104 | } 105 | } 106 | } 107 | } 108 | } 109 | } -------------------------------------------------------------------------------- /app/src/main/java/com/commandiron/vacationchecklist/navigation/NavControllerExt.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist.navigation 2 | 3 | import androidx.compose.runtime.Composable 4 | import androidx.compose.runtime.getValue 5 | import androidx.navigation.NavController 6 | import androidx.navigation.compose.currentBackStackEntryAsState 7 | 8 | @Composable 9 | fun NavController.currentRoute(): String? { 10 | val navBackStackEntry by this.currentBackStackEntryAsState() 11 | return navBackStackEntry?.destination?.route 12 | } 13 | 14 | 15 | fun NavController.bottomNavigate(route: String) { 16 | this.navigate(route) { 17 | this@bottomNavigate.graph.startDestinationRoute?.let { screen_route -> 18 | popUpTo(screen_route) { 19 | saveState = true 20 | } 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/src/main/java/com/commandiron/vacationchecklist/navigation/NavigationItem.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist.navigation 2 | 3 | import androidx.compose.material.icons.Icons 4 | import androidx.compose.material.icons.filled.Add 5 | import androidx.compose.material.icons.filled.LibraryAddCheck 6 | import androidx.compose.material.icons.filled.Settings 7 | import androidx.compose.material.icons.outlined.Add 8 | import androidx.compose.material.icons.outlined.LibraryAddCheck 9 | import androidx.compose.material.icons.outlined.Settings 10 | import androidx.compose.ui.graphics.vector.ImageVector 11 | import com.commandiron.vacationchecklist.R 12 | 13 | sealed class NavigationItem( 14 | val route: String, 15 | val titleResource: Int = 0, 16 | val selectedIcon: ImageVector? = null, 17 | val unSelectedIcon: ImageVector? = null, 18 | ){ 19 | object HotSplashScreen : NavigationItem( 20 | route = "hotSplash" 21 | ) 22 | object GetStartedScreen : NavigationItem( 23 | route = "getStarted" 24 | ) 25 | object ChecklistScreen : NavigationItem( 26 | route = "checklist", 27 | titleResource = R.string.checklist, 28 | selectedIcon = Icons.Default.LibraryAddCheck, 29 | unSelectedIcon = Icons.Outlined.LibraryAddCheck 30 | ) 31 | object CreateVacationScreen : NavigationItem( 32 | route = "createVacation", 33 | titleResource = R.string.create_vacation, 34 | selectedIcon = Icons.Default.Add, 35 | unSelectedIcon = Icons.Outlined.Add 36 | ) 37 | object SettingsScreen : NavigationItem( 38 | route = "settings", 39 | titleResource = R.string.settings, 40 | selectedIcon = Icons.Default.Settings, 41 | unSelectedIcon = Icons.Outlined.Settings 42 | ) 43 | } 44 | -------------------------------------------------------------------------------- /app/src/main/java/com/commandiron/vacationchecklist/presentation/checklist/ChecklistState.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist.presentation.checklist 2 | 3 | import com.commandiron.vacationchecklist.domain.model.CheckItem 4 | import com.commandiron.vacationchecklist.domain.model.Vacation 5 | 6 | data class ChecklistState( 7 | val activeVacation: Vacation? = null, 8 | val checkItems: List? = null, 9 | val checkedItem: CheckItem? = null, 10 | val markedItem: CheckItem? = null, 11 | 12 | val showCheckAlertDialog: Boolean = false, 13 | val showMarkAlertDialog: Boolean = false, 14 | val showSetAlarmAlertDialog: Boolean = false, 15 | 16 | val doubleCheckEnabled: Boolean = false, 17 | val gridViewEnabled: Boolean = false, 18 | val sliderValue: Float = 0.5f, 19 | val gridColumnCount: Int = 3, 20 | val listItemHeightValue: Float = 64f, 21 | val firstVisibleItemIndex: Int = 0, 22 | 23 | val checkCount: Int = 0, 24 | val totalCheckCount: Int = 0, 25 | val isChecklistCompeted: Boolean = false, 26 | 27 | val isLoading: Boolean = false, 28 | ) 29 | -------------------------------------------------------------------------------- /app/src/main/java/com/commandiron/vacationchecklist/presentation/checklist/ChecklistUserEvent.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist.presentation.checklist 2 | 3 | import com.commandiron.vacationchecklist.domain.model.CheckItem 4 | import java.time.LocalDateTime 5 | 6 | sealed class ChecklistUserEvent{ 7 | data class OnCheck(val checkedItem: CheckItem): ChecklistUserEvent() 8 | object OnCheckAlertDialogConfirm : ChecklistUserEvent() 9 | object OnCheckAlertDialogDismiss : ChecklistUserEvent() 10 | 11 | data class OnMark(val markedItem: CheckItem): ChecklistUserEvent() 12 | object OnMarkAlertDialogConfirm : ChecklistUserEvent() 13 | object OnMarkAlertDialogDismiss : ChecklistUserEvent() 14 | 15 | object OnSetAlarm : ChecklistUserEvent() 16 | data class OnSetAlarmAlertDialogConfirm(val dateTime: LocalDateTime) : ChecklistUserEvent() 17 | object OnSetAlarmAlertDialogDismiss : ChecklistUserEvent() 18 | 19 | object OnGridViewClick: ChecklistUserEvent() 20 | object OnListViewClick: ChecklistUserEvent() 21 | data class OnSliderChange(val value: Float): ChecklistUserEvent() 22 | object OnSliderValueChangeFinished: ChecklistUserEvent() 23 | data class OnScrollCompleted(val firstVisibleItemIndex: Int): ChecklistUserEvent() 24 | object OnChecklistCompleteBack: ChecklistUserEvent() 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/java/com/commandiron/vacationchecklist/presentation/checklist/components/CheckListGridView.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist.presentation.checklist.components 2 | 3 | import androidx.compose.foundation.layout.Spacer 4 | import androidx.compose.foundation.layout.aspectRatio 5 | import androidx.compose.foundation.layout.height 6 | import androidx.compose.foundation.layout.padding 7 | import androidx.compose.foundation.lazy.grid.GridCells 8 | import androidx.compose.foundation.lazy.grid.LazyVerticalGrid 9 | import androidx.compose.foundation.lazy.grid.itemsIndexed 10 | import androidx.compose.runtime.Composable 11 | import androidx.compose.runtime.key 12 | import androidx.compose.ui.Modifier 13 | import com.commandiron.vacationchecklist.domain.model.CheckItem 14 | import com.commandiron.vacationchecklist.util.LocalSpacing 15 | 16 | @Composable 17 | fun CheckListGridView( 18 | modifier: Modifier = Modifier, 19 | columnCount: Int, 20 | checkItems: List, 21 | onItemLongClick: (CheckItem) -> Unit, 22 | onItemClick: (CheckItem) -> Unit 23 | ) { 24 | val spacing = LocalSpacing.current 25 | LazyVerticalGrid( 26 | modifier = modifier, 27 | columns = GridCells.Fixed(columnCount) 28 | ){ 29 | itemsIndexed(checkItems) { _, item -> 30 | key(item.id) { 31 | GridItem( 32 | modifier = Modifier 33 | .aspectRatio(1f) 34 | .padding(spacing.spaceExtraSmall), 35 | columnCount = columnCount, 36 | checkItem = item, 37 | onItemLongClick = onItemLongClick, 38 | onItemClick = onItemClick 39 | ) 40 | } 41 | } 42 | item { 43 | Spacer(modifier = Modifier.height(spacing.spaceXXXLarge)) 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /app/src/main/java/com/commandiron/vacationchecklist/presentation/checklist/components/CheckListListView.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist.presentation.checklist.components 2 | 3 | import androidx.compose.foundation.layout.Spacer 4 | import androidx.compose.foundation.layout.fillMaxWidth 5 | import androidx.compose.foundation.layout.height 6 | import androidx.compose.foundation.layout.padding 7 | import androidx.compose.foundation.lazy.LazyColumn 8 | import androidx.compose.foundation.lazy.itemsIndexed 9 | import androidx.compose.runtime.Composable 10 | import androidx.compose.runtime.key 11 | import androidx.compose.ui.Modifier 12 | import androidx.compose.ui.unit.Dp 13 | import com.commandiron.vacationchecklist.domain.model.CheckItem 14 | import com.commandiron.vacationchecklist.util.LocalSpacing 15 | 16 | @Composable 17 | fun CheckListListView( 18 | modifier: Modifier = Modifier, 19 | listItemHeightValue: Float, 20 | gridColumnCount: Int, 21 | checkItems: List, 22 | onFlagClick: (CheckItem) -> Unit, 23 | onCheckedChange: (CheckItem) -> Unit 24 | ) { 25 | val spacing = LocalSpacing.current 26 | LazyColumn( 27 | modifier = modifier 28 | ) { 29 | itemsIndexed(checkItems) { _, item -> 30 | key(item.id) { 31 | ColumnItem( 32 | modifier = Modifier 33 | .height(Dp(listItemHeightValue)) 34 | .fillMaxWidth() 35 | .padding(spacing.spaceXXSmall), 36 | gridCellsCount = gridColumnCount, 37 | checkItem = item, 38 | onFlagClick = onFlagClick, 39 | onCheckedChange = onCheckedChange 40 | ) 41 | } 42 | } 43 | item { 44 | Spacer(modifier = Modifier.height(spacing.spaceXXLarge)) 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /app/src/main/java/com/commandiron/vacationchecklist/presentation/checklist/components/CheckListUiPrefView.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist.presentation.checklist.components 2 | 3 | import androidx.compose.foundation.border 4 | import androidx.compose.foundation.layout.Row 5 | import androidx.compose.foundation.layout.Spacer 6 | import androidx.compose.foundation.layout.width 7 | import androidx.compose.foundation.layout.fillMaxWidth 8 | import androidx.compose.material.icons.Icons 9 | import androidx.compose.material.icons.rounded.GridView 10 | import androidx.compose.material.icons.rounded.ViewList 11 | import androidx.compose.material3.IconButton 12 | import androidx.compose.material3.Icon 13 | import androidx.compose.material3.MaterialTheme 14 | import androidx.compose.material3.Slider 15 | import androidx.compose.material3.SliderDefaults 16 | import androidx.compose.runtime.Composable 17 | import androidx.compose.ui.Alignment 18 | import androidx.compose.ui.Modifier 19 | import androidx.compose.ui.graphics.Color 20 | import androidx.compose.ui.unit.dp 21 | import com.commandiron.vacationchecklist.util.LocalSpacing 22 | 23 | @Composable 24 | fun CheckListUiPrefView( 25 | modifier: Modifier = Modifier, 26 | gridViewEnabled: Boolean, 27 | sliderValue: Float, 28 | onListViewClick: () -> Unit, 29 | onGridViewClick: () -> Unit, 30 | onSliderValueChange: (Float) -> Unit, 31 | onSliderValueChangeFinished: () -> Unit, 32 | ) { 33 | val spacing = LocalSpacing.current 34 | Row( 35 | modifier = modifier, 36 | verticalAlignment = Alignment.CenterVertically 37 | ) { 38 | IconButton( 39 | modifier = Modifier.border(1.dp, if(!gridViewEnabled) Color.Gray else Color.LightGray), 40 | onClick = onListViewClick 41 | ) { 42 | Icon( 43 | imageVector = Icons.Rounded.ViewList, 44 | contentDescription = null, 45 | tint = if(!gridViewEnabled){ 46 | MaterialTheme.colorScheme.primaryContainer 47 | } else Color.Gray.copy( 48 | alpha = 0.2f 49 | ) 50 | ) 51 | } 52 | IconButton( 53 | modifier = Modifier.border(1.dp, if(gridViewEnabled) Color.Gray else Color.LightGray), 54 | onClick = onGridViewClick 55 | ) { 56 | Icon( 57 | imageVector = Icons.Rounded.GridView, 58 | contentDescription = null, 59 | tint = if(gridViewEnabled){ 60 | MaterialTheme.colorScheme.primaryContainer 61 | } else Color.Gray.copy( 62 | alpha = 0.2f 63 | ) 64 | ) 65 | } 66 | Spacer(modifier = Modifier.width(spacing.spaceSmall)) 67 | Slider( 68 | modifier = Modifier.fillMaxWidth(), 69 | value = sliderValue, 70 | onValueChange = onSliderValueChange, 71 | steps = 3, 72 | colors = SliderDefaults.colors( 73 | thumbColor = MaterialTheme.colorScheme.primaryContainer, 74 | activeTrackColor = MaterialTheme.colorScheme.primaryContainer 75 | ), 76 | onValueChangeFinished = onSliderValueChangeFinished 77 | ) 78 | } 79 | } -------------------------------------------------------------------------------- /app/src/main/java/com/commandiron/vacationchecklist/presentation/checklist/components/ChecklistHeader.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist.presentation.checklist.components 2 | 3 | 4 | import androidx.compose.foundation.layout.Column 5 | import androidx.compose.foundation.layout.Row 6 | import androidx.compose.foundation.layout.height 7 | import androidx.compose.foundation.layout.padding 8 | import androidx.compose.foundation.layout.fillMaxSize 9 | import androidx.compose.foundation.layout.Spacer 10 | import androidx.compose.foundation.layout.width 11 | import androidx.compose.foundation.layout.Arrangement 12 | import androidx.compose.foundation.shape.RoundedCornerShape 13 | import androidx.compose.material3.Text 14 | import androidx.compose.material3.MaterialTheme 15 | import androidx.compose.material3.Divider 16 | import androidx.compose.material3.LocalContentColor 17 | import androidx.compose.material3.Surface 18 | import androidx.compose.runtime.Composable 19 | import androidx.compose.ui.Alignment 20 | import androidx.compose.ui.Modifier 21 | import androidx.compose.ui.graphics.Color 22 | import androidx.compose.ui.text.style.TextAlign 23 | import androidx.compose.ui.text.style.TextOverflow 24 | import com.commandiron.vacationchecklist.presentation.components.CustomCircularIcon 25 | import com.commandiron.vacationchecklist.util.LocalSpacing 26 | 27 | @Composable 28 | fun ChecklistHeader( 29 | modifier: Modifier = Modifier, 30 | title: String, 31 | vacationName: String, 32 | drawableId: Int, 33 | checkCount: Int, 34 | totalCount: Int, 35 | isChecklistCompeted: Boolean 36 | ) { 37 | val spacing = LocalSpacing.current 38 | Row(modifier = modifier) { 39 | Column( 40 | modifier = Modifier 41 | .weight(1f) 42 | .padding(horizontal = spacing.spaceMedium), 43 | horizontalAlignment = Alignment.CenterHorizontally 44 | ) { 45 | Text( 46 | text = title, 47 | style = MaterialTheme.typography.displayMedium 48 | ) 49 | Divider(color = LocalContentColor.current.copy(alpha = 0.2f)) 50 | } 51 | Surface( 52 | modifier = Modifier 53 | .weight(1f) 54 | .height(spacing.bottomNavigationHeight), 55 | shape = RoundedCornerShape( 56 | topStart = spacing.spaceLarge, 57 | bottomStart = spacing.spaceLarge 58 | ), 59 | color = MaterialTheme.colorScheme.primary 60 | ) { 61 | Row( 62 | modifier = Modifier 63 | .fillMaxSize() 64 | .padding(spacing.spaceSmall), 65 | verticalAlignment = Alignment.CenterVertically 66 | ) { 67 | CustomCircularIcon( 68 | iconDrawable = drawableId 69 | ) 70 | Spacer(modifier = Modifier.width(spacing.spaceMedium)) 71 | Row( 72 | horizontalArrangement = Arrangement.Center, 73 | verticalAlignment = Alignment.CenterVertically 74 | ) { 75 | Text( 76 | modifier = Modifier.weight(2f), 77 | text = vacationName, 78 | style = MaterialTheme.typography.bodyLarge, 79 | overflow = TextOverflow.Ellipsis 80 | ) 81 | Spacer(modifier = Modifier.width(spacing.spaceSmall)) 82 | Text( 83 | modifier = Modifier.weight(1f), 84 | text = "${checkCount}/${totalCount}", 85 | style = MaterialTheme.typography.bodyMedium, 86 | color = if(isChecklistCompeted){ 87 | Color.Green 88 | }else LocalContentColor.current.copy(alpha = 0.5f), 89 | textAlign = TextAlign.Center 90 | ) 91 | } 92 | } 93 | } 94 | } 95 | } -------------------------------------------------------------------------------- /app/src/main/java/com/commandiron/vacationchecklist/presentation/checklist/components/GridItem.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist.presentation.checklist.components 2 | 3 | import androidx.compose.foundation.* 4 | import androidx.compose.foundation.interaction.MutableInteractionSource 5 | import androidx.compose.foundation.layout.Box 6 | import androidx.compose.foundation.layout.Column 7 | import androidx.compose.foundation.layout.fillMaxSize 8 | import androidx.compose.foundation.layout.fillMaxWidth 9 | import androidx.compose.foundation.layout.padding 10 | import androidx.compose.foundation.layout.size 11 | import androidx.compose.foundation.shape.RoundedCornerShape 12 | import androidx.compose.material3.Card 13 | import androidx.compose.material3.CardDefaults 14 | import androidx.compose.material3.Icon 15 | import androidx.compose.material3.Text 16 | import androidx.compose.material3.MaterialTheme 17 | import androidx.compose.runtime.Composable 18 | import androidx.compose.runtime.remember 19 | import androidx.compose.ui.Alignment 20 | import androidx.compose.ui.Modifier 21 | import androidx.compose.ui.draw.clip 22 | import androidx.compose.ui.graphics.Color 23 | import androidx.compose.ui.res.painterResource 24 | import androidx.compose.ui.text.TextStyle 25 | import androidx.compose.ui.text.style.TextAlign 26 | import androidx.compose.ui.text.style.TextOverflow 27 | import androidx.compose.ui.unit.dp 28 | import com.commandiron.vacationchecklist.domain.model.CheckItem 29 | import com.commandiron.vacationchecklist.presentation.components.ImportanceLevelDot 30 | import com.commandiron.vacationchecklist.ui.theme.importantBorderColor 31 | import com.commandiron.vacationchecklist.util.LocalSpacing 32 | 33 | @Composable 34 | fun GridItem( 35 | modifier: Modifier = Modifier, 36 | columnCount: Int, 37 | checkItem: CheckItem, 38 | onItemLongClick: (CheckItem) -> Unit, 39 | onItemClick: (CheckItem) -> Unit, 40 | ) { 41 | val spacing = LocalSpacing.current 42 | Card( 43 | modifier = modifier 44 | .clip(shape = RoundedCornerShape(12.dp)) 45 | .combinedClickable( 46 | interactionSource = remember { MutableInteractionSource()}, 47 | indication = if(!checkItem.isMarked) LocalIndication.current else null, 48 | onLongClick = { onItemLongClick(checkItem) }, 49 | onClick = { onItemClick(checkItem) } 50 | ) 51 | .border( 52 | width = 2.dp, 53 | color = if(checkItem.isMarked) importantBorderColor else Color.Transparent, 54 | shape = RoundedCornerShape(12.dp) 55 | ), 56 | colors = CardDefaults.cardColors( 57 | containerColor = getContainerColor(checkItem.isChecked, checkItem.isMarked), 58 | ) 59 | ) { 60 | Box(modifier = Modifier.fillMaxSize()) { 61 | Column(modifier = Modifier.fillMaxSize()) { 62 | Box( 63 | modifier = Modifier 64 | .fillMaxWidth() 65 | .weight(2f), 66 | contentAlignment = Alignment.Center 67 | ) { 68 | Icon( 69 | modifier = Modifier.padding(spacing.spaceSmall), 70 | painter = painterResource(checkItem.iconDrawable), 71 | contentDescription = null, 72 | tint = Color.Unspecified 73 | ) 74 | } 75 | Box( 76 | modifier = Modifier 77 | .fillMaxWidth() 78 | .weight(1f), 79 | contentAlignment = Alignment.Center 80 | ) { 81 | Text( 82 | modifier = Modifier 83 | .padding( 84 | start = spacing.spaceExtraSmall, 85 | end = spacing.spaceExtraSmall, 86 | bottom = spacing.spaceExtraSmall 87 | ), 88 | text = checkItem.name, 89 | textAlign = TextAlign.Center, 90 | overflow = TextOverflow.Ellipsis, 91 | style = getTextStyle(columnCount) 92 | ) 93 | } 94 | } 95 | Box( 96 | modifier = Modifier 97 | .fillMaxSize() 98 | .padding(spacing.spaceSmall), 99 | contentAlignment = Alignment.TopStart 100 | ) { 101 | if(!checkItem.isChecked){ 102 | ImportanceLevelDot( 103 | modifier = Modifier.size(spacing.spaceExtraSmall), 104 | importanceLevel = checkItem.importanceLevel 105 | ) 106 | } 107 | } 108 | } 109 | } 110 | } 111 | 112 | @Composable 113 | private fun getContainerColor(isChecked: Boolean, isMarked: Boolean): Color{ 114 | return if(isMarked){ 115 | MaterialTheme.colorScheme.tertiaryContainer 116 | }else{ 117 | if(isChecked){ 118 | MaterialTheme.colorScheme.primaryContainer 119 | }else{ 120 | MaterialTheme.colorScheme.secondaryContainer 121 | } 122 | } 123 | } 124 | 125 | @Composable 126 | private fun getTextStyle(columnCount: Int): TextStyle { 127 | return when(columnCount){ 128 | 1 -> MaterialTheme.typography.headlineSmall 129 | 2 -> MaterialTheme.typography.bodyMedium 130 | 3 -> MaterialTheme.typography.bodySmall 131 | 4 -> MaterialTheme.typography.labelLarge 132 | 5 -> MaterialTheme.typography.labelLarge 133 | else -> MaterialTheme.typography.bodySmall 134 | } 135 | } -------------------------------------------------------------------------------- /app/src/main/java/com/commandiron/vacationchecklist/presentation/checklist/components/MarkAlertDialog.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist.presentation.checklist.components 2 | 3 | import androidx.compose.foundation.layout.Row 4 | import androidx.compose.foundation.layout.Spacer 5 | import androidx.compose.foundation.layout.width 6 | import androidx.compose.material3.AlertDialog 7 | import androidx.compose.material3.Button 8 | import androidx.compose.material3.ButtonDefaults 9 | import androidx.compose.material3.MaterialTheme 10 | import androidx.compose.material3.Text 11 | import androidx.compose.runtime.Composable 12 | import androidx.compose.ui.Modifier 13 | import androidx.compose.ui.unit.dp 14 | 15 | @Composable 16 | fun MarkAlertDialog( 17 | title: String, 18 | setAlarmButtonText: String, 19 | confirmButtonText: String, 20 | dismissButtonText: String, 21 | setAlarmButtonEnabled: Boolean = false, 22 | onSetAlarm: () -> Unit, 23 | onDismiss: () -> Unit, 24 | onConfirm: () -> Unit 25 | ) { 26 | AlertDialog( 27 | onDismissRequest = onDismiss, 28 | confirmButton = { 29 | Button( 30 | onClick = onConfirm, 31 | colors = ButtonDefaults.buttonColors( 32 | containerColor = MaterialTheme.colorScheme.primaryContainer 33 | ) 34 | ) { 35 | Text( 36 | text = confirmButtonText, 37 | style = MaterialTheme.typography.bodyMedium 38 | ) 39 | } 40 | }, 41 | dismissButton = { 42 | Row() { 43 | if(setAlarmButtonEnabled){ 44 | Button( 45 | onClick = onSetAlarm, 46 | colors = ButtonDefaults.buttonColors( 47 | containerColor = MaterialTheme.colorScheme.tertiaryContainer, 48 | contentColor = MaterialTheme.colorScheme.onTertiaryContainer 49 | ) 50 | ) { 51 | Text( 52 | text = setAlarmButtonText, 53 | style = MaterialTheme.typography.bodyMedium 54 | ) 55 | } 56 | Spacer(modifier = Modifier.width(16.dp)) 57 | } 58 | Button( 59 | onClick = onDismiss, 60 | colors = ButtonDefaults.buttonColors( 61 | containerColor = MaterialTheme.colorScheme.primaryContainer 62 | ) 63 | ) { 64 | Text( 65 | text = dismissButtonText, 66 | style = MaterialTheme.typography.bodyMedium 67 | ) 68 | } 69 | } 70 | }, 71 | title = { 72 | Text( 73 | text = title, 74 | style = MaterialTheme.typography.bodyLarge 75 | ) 76 | }, 77 | containerColor = MaterialTheme.colorScheme.primary, 78 | titleContentColor = MaterialTheme.colorScheme.onPrimary 79 | ) 80 | } -------------------------------------------------------------------------------- /app/src/main/java/com/commandiron/vacationchecklist/presentation/checklist/components/ReadyToGoView.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist.presentation.checklist.components 2 | 3 | 4 | import androidx.compose.foundation.layout.Arrangement 5 | import androidx.compose.foundation.layout.Column 6 | import androidx.compose.foundation.layout.Spacer 7 | import androidx.compose.foundation.layout.height 8 | import androidx.compose.material3.Button 9 | import androidx.compose.material3.ButtonDefaults 10 | import androidx.compose.material3.MaterialTheme 11 | import androidx.compose.material3.Text 12 | import androidx.compose.runtime.Composable 13 | import androidx.compose.ui.Alignment 14 | import androidx.compose.ui.Modifier 15 | import androidx.compose.ui.res.stringResource 16 | import androidx.compose.ui.text.font.FontWeight 17 | import androidx.compose.ui.text.style.TextAlign 18 | import com.commandiron.vacationchecklist.R 19 | import com.commandiron.vacationchecklist.util.LocalSpacing 20 | 21 | @Composable 22 | fun ReadyToGoView( 23 | modifier: Modifier = Modifier, 24 | onClick:() -> Unit 25 | ) { 26 | val spacing = LocalSpacing.current 27 | Column( 28 | modifier = modifier, 29 | horizontalAlignment = Alignment.CenterHorizontally, 30 | verticalArrangement = Arrangement.Center 31 | ) { 32 | Text( 33 | text = stringResource(R.string.you_are_ready_to_go), 34 | style = MaterialTheme.typography.headlineLarge.copy( 35 | fontWeight = FontWeight.Bold 36 | ), 37 | color = MaterialTheme.colorScheme.primaryContainer 38 | ) 39 | Spacer(modifier = Modifier.height(spacing.spaceMedium)) 40 | Button( 41 | onClick = onClick, 42 | colors = ButtonDefaults.buttonColors( 43 | containerColor = MaterialTheme.colorScheme.primaryContainer 44 | ) 45 | ) { 46 | Text( 47 | text = stringResource(R.string.back), 48 | style = MaterialTheme.typography.titleMedium, 49 | textAlign = TextAlign.Center 50 | ) 51 | } 52 | } 53 | } -------------------------------------------------------------------------------- /app/src/main/java/com/commandiron/vacationchecklist/presentation/checklist/components/SetAlarmAlertDialog.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist.presentation.checklist.components 2 | 3 | import android.os.Build 4 | import androidx.annotation.RequiresApi 5 | import androidx.compose.foundation.BorderStroke 6 | import androidx.compose.material3.* 7 | import androidx.compose.runtime.Composable 8 | import androidx.compose.runtime.mutableStateOf 9 | import androidx.compose.runtime.remember 10 | import androidx.compose.ui.unit.dp 11 | import com.commandiron.vacationchecklist.ui.theme.importantBorderColor 12 | import com.commandiron.wheel_picker_compose.WheelDateTimePicker 13 | import java.time.LocalDateTime 14 | 15 | @RequiresApi(Build.VERSION_CODES.O) 16 | @Composable 17 | fun SetAlarmAlertDialog( 18 | title: String, 19 | confirmButtonText: String, 20 | dismissButtonText: String, 21 | onDismiss: () -> Unit, 22 | onConfirm: (LocalDateTime) -> Unit, 23 | ) { 24 | val snappedDateTime = remember { mutableStateOf(LocalDateTime.now())} 25 | AlertDialog( 26 | title = { 27 | Text( 28 | text = title, 29 | style = MaterialTheme.typography.bodyLarge 30 | ) 31 | }, 32 | confirmButton = { 33 | Button( 34 | onClick = { 35 | onConfirm(snappedDateTime.value) 36 | }, 37 | colors = ButtonDefaults.buttonColors( 38 | containerColor = MaterialTheme.colorScheme.tertiaryContainer, 39 | contentColor = MaterialTheme.colorScheme.onTertiaryContainer 40 | ) 41 | ) { 42 | Text( 43 | text = confirmButtonText, 44 | style = MaterialTheme.typography.bodySmall 45 | ) 46 | } 47 | }, 48 | dismissButton = { 49 | Button( 50 | onClick = onDismiss, 51 | colors = ButtonDefaults.buttonColors( 52 | containerColor = MaterialTheme.colorScheme.tertiaryContainer, 53 | contentColor = MaterialTheme.colorScheme.onTertiaryContainer 54 | ) 55 | ) { 56 | Text( 57 | text = dismissButtonText, 58 | style = MaterialTheme.typography.bodySmall 59 | ) 60 | } 61 | }, 62 | text = { 63 | WheelDateTimePicker( 64 | disablePastDateTime = true, 65 | textColor = MaterialTheme.colorScheme.onPrimaryContainer, 66 | selectorColor = MaterialTheme.colorScheme.primaryContainer.copy(alpha = 0.75f), 67 | selectorBorder = BorderStroke(1.dp, importantBorderColor) 68 | ) { 69 | snappedDateTime.value = it 70 | } 71 | }, 72 | onDismissRequest = onDismiss, 73 | containerColor = MaterialTheme.colorScheme.primary, 74 | titleContentColor = MaterialTheme.colorScheme.onPrimary 75 | ) 76 | } -------------------------------------------------------------------------------- /app/src/main/java/com/commandiron/vacationchecklist/presentation/components/AppLogoWithName.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist.presentation.components 2 | 3 | import androidx.compose.foundation.layout.Row 4 | import androidx.compose.foundation.layout.Arrangement 5 | import androidx.compose.foundation.layout.Spacer 6 | import androidx.compose.foundation.layout.width 7 | import androidx.compose.foundation.layout.size 8 | import androidx.compose.material3.Icon 9 | import androidx.compose.material3.MaterialTheme 10 | import androidx.compose.material3.Text 11 | import androidx.compose.runtime.Composable 12 | import androidx.compose.ui.Alignment 13 | import androidx.compose.ui.Modifier 14 | import androidx.compose.ui.graphics.Color 15 | import androidx.compose.ui.res.painterResource 16 | import androidx.compose.ui.res.stringResource 17 | import androidx.compose.ui.text.font.FontWeight 18 | import androidx.compose.ui.unit.Dp 19 | import androidx.compose.ui.unit.dp 20 | import com.commandiron.vacationchecklist.R 21 | import com.commandiron.vacationchecklist.util.LocalSpacing 22 | 23 | @Composable 24 | fun AppLogoWithName( 25 | modifier: Modifier = Modifier 26 | ) { 27 | val spacing = LocalSpacing.current 28 | Row( 29 | modifier = modifier, 30 | horizontalArrangement = Arrangement.Center, 31 | verticalAlignment = Alignment.CenterVertically 32 | ) { 33 | AppName() 34 | Spacer(modifier = Modifier.width(spacing.spaceMedium)) 35 | AppLogo() 36 | } 37 | } 38 | 39 | @Composable 40 | fun AppLogo( 41 | modifier: Modifier = Modifier, 42 | size: Dp = 80.dp, 43 | ) { 44 | Icon( 45 | modifier = modifier.size(size), 46 | painter = painterResource(id = R.drawable.checkpack_logo), 47 | contentDescription = null, 48 | tint = Color.Unspecified 49 | ) 50 | } 51 | 52 | @Composable 53 | fun AppName( 54 | modifier: Modifier = Modifier, 55 | color: Color = MaterialTheme.colorScheme.primaryContainer 56 | ) { 57 | Text( 58 | modifier = modifier, 59 | text = stringResource(R.string.app_name_first_word), 60 | style = MaterialTheme.typography.titleMedium.copy( 61 | fontWeight = FontWeight.Bold 62 | ), 63 | color = color 64 | ) 65 | } -------------------------------------------------------------------------------- /app/src/main/java/com/commandiron/vacationchecklist/presentation/components/CreateVacationBody.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist.presentation.components 2 | 3 | 4 | import androidx.compose.foundation.border 5 | import androidx.compose.foundation.layout.Column 6 | import androidx.compose.foundation.layout.fillMaxSize 7 | import androidx.compose.foundation.layout.Spacer 8 | import androidx.compose.foundation.layout.height 9 | import androidx.compose.foundation.layout.fillMaxWidth 10 | import androidx.compose.material3.Button 11 | import androidx.compose.material3.ButtonDefaults 12 | import androidx.compose.material3.MaterialTheme 13 | import androidx.compose.material3.Text 14 | import androidx.compose.runtime.Composable 15 | import androidx.compose.ui.Alignment 16 | import androidx.compose.ui.Modifier 17 | import androidx.compose.ui.graphics.Color 18 | import androidx.compose.ui.res.stringResource 19 | import androidx.compose.ui.text.style.TextAlign 20 | import androidx.compose.ui.unit.dp 21 | import com.commandiron.vacationchecklist.R 22 | import com.commandiron.vacationchecklist.domain.model.Vacation 23 | import com.commandiron.vacationchecklist.util.LocalSpacing 24 | import com.google.accompanist.pager.HorizontalPager 25 | import com.google.accompanist.pager.PagerState 26 | 27 | @Composable 28 | fun CreateVacationBody( 29 | pagerState: PagerState, 30 | vacations: List, 31 | onSelect: (Vacation) -> Unit, 32 | selectedVacation: Vacation?, 33 | nextButtonEnabled: Boolean = true, 34 | onNextClick: () -> Unit = {}, 35 | onVacationNameChange: (String) -> Unit, 36 | onFinishClick: (Vacation) -> Unit, 37 | showAlertDialog: Boolean = false, 38 | onAlertDismiss: () -> Unit = {}, 39 | onAlertConfirm: (Vacation) -> Unit = {} 40 | ) { 41 | val spacing = LocalSpacing.current 42 | HorizontalPager( 43 | count = 2, 44 | state = pagerState, 45 | userScrollEnabled = false, 46 | verticalAlignment = Alignment.Top 47 | ) { page -> 48 | when(page){ 49 | 0 -> { 50 | Column { 51 | VacationsVerticalList( 52 | vacations = vacations, 53 | onSelect = onSelect 54 | ) 55 | if(nextButtonEnabled){ 56 | selectedVacation?.let { 57 | Button( 58 | modifier = Modifier.align(Alignment.CenterHorizontally), 59 | onClick = onNextClick, 60 | colors = ButtonDefaults.buttonColors( 61 | containerColor = MaterialTheme.colorScheme.primaryContainer 62 | ) 63 | ) { 64 | Text( 65 | text = stringResource(R.string.next), 66 | style = MaterialTheme.typography.titleMedium, 67 | textAlign = TextAlign.Center 68 | ) 69 | } 70 | } 71 | } 72 | } 73 | } 74 | 1 -> { 75 | Column( 76 | modifier = Modifier.fillMaxSize(), 77 | horizontalAlignment = Alignment.CenterHorizontally 78 | ) { 79 | selectedVacation?.let { 80 | Text( 81 | text = stringResource(R.string.enter_vacation_name), 82 | style = MaterialTheme.typography.titleMedium 83 | ) 84 | Spacer(modifier = Modifier.height(spacing.spaceLarge)) 85 | Column(modifier = Modifier.weight(1f)) { 86 | VacationItem( 87 | showTitle = false, 88 | vacation = it, 89 | iconPadding = spacing.spaceSmall 90 | ) 91 | } 92 | Spacer(modifier = Modifier.height(spacing.spaceLarge)) 93 | Column( 94 | modifier = Modifier.weight(2f), 95 | horizontalAlignment = Alignment.CenterHorizontally 96 | ) { 97 | CustomTextField( 98 | modifier = Modifier.fillMaxWidth(0.75f), 99 | value = it.name, 100 | onValueChange = onVacationNameChange 101 | ) 102 | Spacer(modifier = Modifier.height(spacing.spaceLarge)) 103 | CustomButton(text = stringResource(R.string.finish)) { 104 | onFinishClick(it) 105 | } 106 | } 107 | if(showAlertDialog){ 108 | CustomAlertDialog( 109 | title = stringResource(R.string.your_previous_checklist_will_be_lost_are_you_sure), 110 | firstButtonText = stringResource(R.string.yes), 111 | secondButtonText = stringResource(R.string.no), 112 | onDismiss = onAlertDismiss, 113 | onConfirm = { onAlertConfirm(it) } 114 | ) 115 | } 116 | } 117 | } 118 | } 119 | } 120 | } 121 | } -------------------------------------------------------------------------------- /app/src/main/java/com/commandiron/vacationchecklist/presentation/components/CustomAlertDialog.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist.presentation.components 2 | 3 | import androidx.compose.material3.AlertDialog 4 | import androidx.compose.material3.Button 5 | import androidx.compose.material3.ButtonDefaults 6 | import androidx.compose.material3.MaterialTheme 7 | import androidx.compose.material3.Text 8 | import androidx.compose.runtime.Composable 9 | 10 | @Composable 11 | fun CustomAlertDialog( 12 | title: String, 13 | firstButtonText: String, 14 | secondButtonText: String, 15 | onDismiss:() -> Unit, 16 | onConfirm:() -> Unit 17 | ) { 18 | AlertDialog( 19 | onDismissRequest = onDismiss, 20 | confirmButton = { 21 | Button( 22 | onClick = onConfirm, 23 | colors = ButtonDefaults.buttonColors( 24 | containerColor = MaterialTheme.colorScheme.primaryContainer 25 | ) 26 | ) { 27 | Text( 28 | text = firstButtonText, 29 | style = MaterialTheme.typography.titleSmall 30 | ) 31 | } 32 | }, 33 | dismissButton = { 34 | Button( 35 | onClick = onDismiss, 36 | colors = ButtonDefaults.buttonColors( 37 | containerColor = MaterialTheme.colorScheme.primaryContainer 38 | ) 39 | ) { 40 | Text( 41 | text = secondButtonText, 42 | style = MaterialTheme.typography.titleSmall 43 | ) 44 | } 45 | }, 46 | title = { 47 | Text( 48 | text = title, 49 | style = MaterialTheme.typography.bodyLarge 50 | ) 51 | }, 52 | containerColor = MaterialTheme.colorScheme.primary, 53 | titleContentColor = MaterialTheme.colorScheme.onPrimary 54 | ) 55 | } -------------------------------------------------------------------------------- /app/src/main/java/com/commandiron/vacationchecklist/presentation/components/CustomButton.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist.presentation.components 2 | 3 | import androidx.compose.foundation.border 4 | import androidx.compose.foundation.layout.height 5 | import androidx.compose.foundation.shape.RoundedCornerShape 6 | import androidx.compose.material3.Button 7 | import androidx.compose.material3.ButtonDefaults 8 | import androidx.compose.material3.MaterialTheme 9 | import androidx.compose.material3.Text 10 | import androidx.compose.runtime.Composable 11 | import androidx.compose.ui.Alignment 12 | import androidx.compose.ui.Modifier 13 | import androidx.compose.ui.graphics.Color 14 | import androidx.compose.ui.text.style.TextAlign 15 | import androidx.compose.ui.unit.dp 16 | import com.commandiron.vacationchecklist.util.LocalSpacing 17 | 18 | @Composable 19 | fun CustomButton( 20 | modifier: Modifier = Modifier, 21 | text: String, 22 | onClick:() -> Unit, 23 | ) { 24 | val spacing = LocalSpacing.current 25 | Button( 26 | modifier = modifier.height(spacing.defaultButtonHeight), 27 | onClick = onClick, 28 | shape = RoundedCornerShape(12.dp), 29 | colors = ButtonDefaults.buttonColors( 30 | containerColor = MaterialTheme.colorScheme.primary 31 | ) 32 | ) { 33 | Text( 34 | text = text, 35 | style = MaterialTheme.typography.bodyMedium 36 | ) 37 | } 38 | } -------------------------------------------------------------------------------- /app/src/main/java/com/commandiron/vacationchecklist/presentation/components/CustomCircularIcon.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist.presentation.components 2 | 3 | import androidx.compose.foundation.layout.padding 4 | import androidx.compose.foundation.shape.CircleShape 5 | import androidx.compose.material3.Icon 6 | import androidx.compose.material3.Surface 7 | import androidx.compose.runtime.Composable 8 | import androidx.compose.ui.Modifier 9 | import androidx.compose.ui.graphics.Color 10 | import androidx.compose.ui.graphics.Shape 11 | import androidx.compose.ui.res.painterResource 12 | import androidx.compose.ui.unit.Dp 13 | import androidx.compose.ui.unit.dp 14 | 15 | @Composable 16 | fun CustomCircularIcon( 17 | modifier: Modifier = Modifier, 18 | surfaceShape: Shape = CircleShape, 19 | surfaceColor: Color = Color.White, 20 | iconPadding: Dp = 0.dp, 21 | iconDrawable: Int, 22 | ) { 23 | Surface( 24 | modifier = modifier, 25 | shape = surfaceShape, 26 | color = surfaceColor 27 | ) { 28 | Icon( 29 | modifier = Modifier.padding(iconPadding), 30 | painter = painterResource(iconDrawable), 31 | contentDescription = null, 32 | tint = Color.Unspecified 33 | ) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/src/main/java/com/commandiron/vacationchecklist/presentation/components/CustomHeader.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist.presentation.components 2 | 3 | import androidx.compose.foundation.layout.Column 4 | import androidx.compose.material3.LocalContentColor 5 | import androidx.compose.material3.MaterialTheme 6 | import androidx.compose.material3.Text 7 | import androidx.compose.runtime.Composable 8 | import androidx.compose.ui.Alignment 9 | import androidx.compose.ui.Modifier 10 | import androidx.compose.ui.text.style.TextAlign 11 | 12 | @Composable 13 | fun CustomHeader( 14 | modifier: Modifier = Modifier, 15 | title: String, 16 | subTitle: String? = null 17 | ) { 18 | Column( 19 | modifier = modifier, 20 | horizontalAlignment = Alignment.CenterHorizontally 21 | ) { 22 | Text( 23 | text = title, 24 | style = MaterialTheme.typography.displayMedium 25 | ) 26 | subTitle?.let { 27 | Text( 28 | text = it, 29 | style = MaterialTheme.typography.bodyMedium, 30 | color = LocalContentColor.current.copy(alpha = 0.5f), 31 | textAlign = TextAlign.Center 32 | ) 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /app/src/main/java/com/commandiron/vacationchecklist/presentation/components/CustomSnackbar.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist.presentation.components 2 | 3 | import androidx.compose.foundation.layout.padding 4 | import androidx.compose.foundation.shape.RoundedCornerShape 5 | import androidx.compose.material3.MaterialTheme 6 | import androidx.compose.material3.Snackbar 7 | import androidx.compose.material3.SnackbarData 8 | import androidx.compose.runtime.Composable 9 | import androidx.compose.ui.Modifier 10 | import androidx.compose.ui.unit.dp 11 | 12 | @Composable 13 | fun CustomSnackbar( 14 | data : SnackbarData 15 | ) { 16 | Snackbar( 17 | shape = RoundedCornerShape(20.dp), 18 | modifier = Modifier.padding(horizontal = 40.dp), 19 | containerColor = MaterialTheme.colorScheme.primary, 20 | contentColor = MaterialTheme.colorScheme.onPrimary, 21 | actionColor = MaterialTheme.colorScheme.onPrimary, 22 | snackbarData = data 23 | ) 24 | } -------------------------------------------------------------------------------- /app/src/main/java/com/commandiron/vacationchecklist/presentation/components/CustomTextField.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist.presentation.components 2 | 3 | import androidx.compose.foundation.text.KeyboardActions 4 | import androidx.compose.foundation.text.KeyboardOptions 5 | import androidx.compose.material3.MaterialTheme 6 | import androidx.compose.material3.OutlinedTextField 7 | import androidx.compose.material3.TextFieldDefaults 8 | import androidx.compose.runtime.Composable 9 | import androidx.compose.ui.Modifier 10 | import androidx.compose.ui.platform.LocalSoftwareKeyboardController 11 | 12 | @Composable 13 | fun CustomTextField( 14 | modifier: Modifier = Modifier, 15 | value: String, 16 | onValueChange: (String) -> Unit, 17 | singleLine: Boolean = true 18 | ) { 19 | val keyboardController = LocalSoftwareKeyboardController.current 20 | OutlinedTextField( 21 | modifier = modifier, 22 | value = value, 23 | onValueChange = onValueChange, 24 | singleLine = singleLine, 25 | colors = TextFieldDefaults.textFieldColors( 26 | textColor = MaterialTheme.colorScheme.onSecondaryContainer, 27 | containerColor = MaterialTheme.colorScheme.secondaryContainer 28 | ), 29 | keyboardOptions = KeyboardOptions(), 30 | keyboardActions = KeyboardActions( 31 | onDone = { 32 | keyboardController?.hide() 33 | } 34 | ) 35 | ) 36 | } -------------------------------------------------------------------------------- /app/src/main/java/com/commandiron/vacationchecklist/presentation/components/FromCompanyComponent.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist.presentation.components 2 | 3 | import androidx.compose.foundation.layout.Column 4 | import androidx.compose.foundation.layout.Spacer 5 | import androidx.compose.foundation.layout.Row 6 | import androidx.compose.foundation.layout.height 7 | import androidx.compose.foundation.layout.width 8 | import androidx.compose.material3.Icon 9 | import androidx.compose.material3.LocalContentColor 10 | import androidx.compose.material3.MaterialTheme 11 | import androidx.compose.material3.Text 12 | import androidx.compose.runtime.Composable 13 | import androidx.compose.ui.Alignment 14 | import androidx.compose.ui.Modifier 15 | import androidx.compose.ui.res.painterResource 16 | import androidx.compose.ui.res.stringResource 17 | import androidx.compose.ui.text.font.FontWeight 18 | import androidx.compose.ui.unit.dp 19 | import com.commandiron.vacationchecklist.R 20 | import com.commandiron.vacationchecklist.ui.theme.companyColor 21 | import com.commandiron.vacationchecklist.util.LocalSpacing 22 | 23 | @Composable 24 | fun FromCompanyComponent( 25 | modifier: Modifier = Modifier, 26 | companyName: String = stringResource(R.string.company_name), 27 | fromText: String = stringResource(R.string.from), 28 | ) { 29 | val spacing = LocalSpacing.current 30 | Column( 31 | modifier = modifier, 32 | horizontalAlignment = Alignment.CenterHorizontally 33 | ) { 34 | Text( 35 | text = fromText, 36 | style = MaterialTheme.typography.bodyMedium.copy( 37 | fontWeight = FontWeight.Medium 38 | ), 39 | color = LocalContentColor.current.copy( 40 | alpha = 0.5f 41 | ) 42 | ) 43 | Spacer(modifier = Modifier.height(spacing.spaceExtraSmall)) 44 | Row( 45 | verticalAlignment = Alignment.CenterVertically 46 | ) { 47 | Icon( 48 | modifier = Modifier.height(20.dp), 49 | painter = painterResource(id = R.drawable.ci_tech_logo), 50 | contentDescription = companyName, 51 | tint = companyColor 52 | ) 53 | Spacer(modifier = Modifier.width(spacing.spaceSmall)) 54 | Text( 55 | text = companyName, 56 | style = MaterialTheme.typography.bodyLarge.copy( 57 | fontWeight = FontWeight.Medium 58 | ), 59 | color = companyColor 60 | ) 61 | } 62 | } 63 | } -------------------------------------------------------------------------------- /app/src/main/java/com/commandiron/vacationchecklist/presentation/components/ImportanceLevelDot.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist.presentation.components 2 | 3 | import androidx.compose.foundation.shape.CircleShape 4 | import androidx.compose.material3.Surface 5 | import androidx.compose.runtime.Composable 6 | import androidx.compose.ui.Modifier 7 | import androidx.compose.ui.graphics.Color 8 | import com.commandiron.vacationchecklist.domain.model.CheckItem 9 | 10 | @Composable 11 | fun ImportanceLevelDot( 12 | modifier: Modifier = Modifier, 13 | importanceLevel: CheckItem.ImportanceLevel 14 | ) { 15 | Surface( 16 | modifier = modifier, 17 | color = when(importanceLevel){ 18 | CheckItem.ImportanceLevel.MUST -> Color.Red 19 | CheckItem.ImportanceLevel.OPTIONAL -> Color.Blue 20 | }, 21 | shape = CircleShape 22 | ) { 23 | } 24 | } -------------------------------------------------------------------------------- /app/src/main/java/com/commandiron/vacationchecklist/presentation/components/LoadingBarAnimation.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist.presentation.components 2 | 3 | import androidx.compose.animation.core.Animatable 4 | import androidx.compose.animation.core.LinearEasing 5 | import androidx.compose.animation.core.tween 6 | import androidx.compose.foundation.BorderStroke 7 | import androidx.compose.foundation.Canvas 8 | import androidx.compose.foundation.layout.fillMaxSize 9 | import androidx.compose.foundation.layout.fillMaxWidth 10 | import androidx.compose.foundation.layout.height 11 | import androidx.compose.foundation.shape.RoundedCornerShape 12 | import androidx.compose.material3.MaterialTheme 13 | import androidx.compose.material3.Surface 14 | import androidx.compose.runtime.Composable 15 | import androidx.compose.runtime.LaunchedEffect 16 | import androidx.compose.runtime.mutableStateOf 17 | import androidx.compose.runtime.remember 18 | import androidx.compose.ui.Modifier 19 | import androidx.compose.ui.geometry.Offset 20 | import androidx.compose.ui.geometry.Size 21 | import androidx.compose.ui.graphics.Color 22 | import androidx.compose.ui.unit.Dp 23 | import androidx.compose.ui.unit.dp 24 | 25 | @Composable 26 | fun LoadingBarAnimation( 27 | modifier: Modifier = Modifier, 28 | thickness: Dp = 16.dp, 29 | fractionOfWidth: Float = 0.64f, 30 | backgroundColor: Color = MaterialTheme.colorScheme.background, 31 | fillColor: Color = MaterialTheme.colorScheme.primaryContainer, 32 | borderColor: Color = MaterialTheme.colorScheme.primary, 33 | loadingBarDurationMillis: Int = 5000 34 | ) { 35 | val loadingBarProgress = remember { 36 | Animatable(0f) 37 | } 38 | val canvasWidth = remember { mutableStateOf(0f)} 39 | LaunchedEffect(key1 = Unit){ 40 | loadingBarProgress.animateTo( 41 | targetValue = canvasWidth.value, 42 | animationSpec = tween( 43 | durationMillis = loadingBarDurationMillis, 44 | easing = LinearEasing 45 | ) 46 | ) 47 | } 48 | Surface( 49 | modifier = modifier 50 | .height(thickness) 51 | .fillMaxWidth(fractionOfWidth), 52 | color = backgroundColor, 53 | shape = RoundedCornerShape(thickness), 54 | border = BorderStroke(thickness / 8, borderColor) 55 | ) { 56 | Canvas( 57 | modifier = Modifier.fillMaxSize(), 58 | onDraw = { 59 | canvasWidth.value = size.width 60 | val canvasHeight = size.height 61 | drawRect( 62 | color = fillColor, 63 | topLeft = Offset(0f, 0f), 64 | size = Size(loadingBarProgress.value, canvasHeight) 65 | ) 66 | } 67 | ) 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /app/src/main/java/com/commandiron/vacationchecklist/presentation/components/LoadingThreeDotAnimation.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist.presentation.components 2 | 3 | import androidx.compose.foundation.layout.Row 4 | import androidx.compose.material3.MaterialTheme 5 | import androidx.compose.material3.Text 6 | import androidx.compose.runtime.Composable 7 | import androidx.compose.runtime.LaunchedEffect 8 | import androidx.compose.runtime.mutableStateOf 9 | import androidx.compose.runtime.remember 10 | import androidx.compose.ui.graphics.Color 11 | import kotlinx.coroutines.delay 12 | 13 | @Composable 14 | fun LoadingThreeDotAnimation( 15 | text: String, 16 | backgroundColor: Color = MaterialTheme.colorScheme.background, 17 | enableThreeDot: Boolean = true, 18 | delayBetweenDots: Long = 500 19 | ) { 20 | val dotText = remember { mutableStateOf("")} 21 | LaunchedEffect(key1 = Unit){ 22 | while (enableThreeDot){ 23 | delay(delayBetweenDots) 24 | dotText.value = "." 25 | delay(delayBetweenDots) 26 | dotText.value = ".." 27 | delay(delayBetweenDots) 28 | dotText.value = "..." 29 | delay(delayBetweenDots) 30 | dotText.value = "" 31 | } 32 | } 33 | Row { 34 | Text(text = dotText.value, color = backgroundColor) 35 | Text(text = text) 36 | Text(text = dotText.value) 37 | } 38 | 39 | } -------------------------------------------------------------------------------- /app/src/main/java/com/commandiron/vacationchecklist/presentation/components/VacationItem.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist.presentation.components 2 | 3 | import androidx.compose.foundation.border 4 | import androidx.compose.foundation.layout.Column 5 | import androidx.compose.foundation.layout.aspectRatio 6 | import androidx.compose.foundation.layout.Spacer 7 | import androidx.compose.foundation.layout.Box 8 | import androidx.compose.foundation.layout.height 9 | import androidx.compose.foundation.shape.CircleShape 10 | import androidx.compose.material3.MaterialTheme 11 | import androidx.compose.material3.Text 12 | import androidx.compose.runtime.Composable 13 | import androidx.compose.ui.Alignment 14 | import androidx.compose.ui.Modifier 15 | import androidx.compose.ui.graphics.Brush 16 | import androidx.compose.ui.graphics.Color 17 | import androidx.compose.ui.text.style.TextAlign 18 | import androidx.compose.ui.unit.Dp 19 | import androidx.compose.ui.unit.dp 20 | import com.commandiron.vacationchecklist.domain.model.Vacation 21 | import com.commandiron.vacationchecklist.util.LocalSpacing 22 | 23 | @Composable 24 | fun VacationItem( 25 | modifier: Modifier = Modifier, 26 | showTitle: Boolean = true, 27 | isSelected: Boolean = false, 28 | vacation: Vacation, 29 | iconPadding: Dp = 0.dp 30 | ) { 31 | val spacing = LocalSpacing.current 32 | Column( 33 | modifier = modifier, 34 | horizontalAlignment = Alignment.CenterHorizontally 35 | ) { 36 | CustomCircularIcon( 37 | modifier = Modifier 38 | .aspectRatio(1f) 39 | .weight(2f) 40 | .border( 41 | width = 2.dp, 42 | brush = if (isSelected) 43 | Brush.linearGradient( 44 | listOf( 45 | Color(0xFFA5BADE), 46 | Color(0xFFBCEBE3) 47 | ) 48 | ) 49 | else Brush.linearGradient( 50 | listOf( 51 | Color.White, 52 | Color.White 53 | ) 54 | ), 55 | shape = CircleShape 56 | ), 57 | iconPadding = iconPadding, 58 | iconDrawable = vacation.iconDrawable 59 | ) 60 | if(showTitle) { 61 | Spacer(modifier = Modifier.height(spacing.spaceSmall)) 62 | Box( 63 | modifier = Modifier 64 | .weight(1f), 65 | contentAlignment = Alignment.TopCenter 66 | ){ 67 | Text( 68 | text = vacation.name, 69 | style = MaterialTheme.typography.bodyMedium, 70 | textAlign = TextAlign.Center, 71 | color = MaterialTheme.colorScheme.onBackground 72 | ) 73 | } 74 | } 75 | } 76 | } -------------------------------------------------------------------------------- /app/src/main/java/com/commandiron/vacationchecklist/presentation/components/VacationsVerticalList.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist.presentation.components 2 | 3 | import androidx.compose.foundation.clickable 4 | import androidx.compose.foundation.layout.aspectRatio 5 | import androidx.compose.foundation.layout.padding 6 | import androidx.compose.foundation.lazy.grid.GridCells 7 | import androidx.compose.foundation.lazy.grid.LazyVerticalGrid 8 | import androidx.compose.foundation.lazy.grid.items 9 | import androidx.compose.material.ripple.LocalRippleTheme 10 | import androidx.compose.runtime.Composable 11 | import androidx.compose.runtime.CompositionLocalProvider 12 | import androidx.compose.runtime.mutableStateOf 13 | import androidx.compose.runtime.remember 14 | import androidx.compose.ui.Modifier 15 | import com.commandiron.vacationchecklist.domain.model.Vacation 16 | import com.commandiron.vacationchecklist.util.LocalSpacing 17 | import com.commandiron.vacationchecklist.util.NoRippleTheme 18 | 19 | @Composable 20 | fun VacationsVerticalList( 21 | modifier: Modifier = Modifier, 22 | userScrollEnabled: Boolean = false, 23 | vacations: List, 24 | selectable: Boolean = true, 25 | onSelect:(Vacation) -> Unit 26 | ) { 27 | val spacing = LocalSpacing.current 28 | val selectedItem = remember { mutableStateOf(null)} 29 | CompositionLocalProvider(LocalRippleTheme provides NoRippleTheme) { 30 | LazyVerticalGrid( 31 | modifier = modifier, 32 | columns = GridCells.Fixed(3), 33 | userScrollEnabled = userScrollEnabled 34 | ){ 35 | items(vacations){ vacation -> 36 | val isSelected = vacation == selectedItem.value 37 | VacationItem( 38 | modifier = Modifier 39 | .aspectRatio(0.67f) 40 | .padding(spacing.spaceSmall) 41 | .clickable { 42 | if (selectable) { 43 | selectedItem.value = vacation 44 | onSelect(vacation) 45 | } 46 | }, 47 | isSelected = isSelected, 48 | vacation = vacation, 49 | iconPadding = spacing.spaceSmall 50 | ) 51 | } 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /app/src/main/java/com/commandiron/vacationchecklist/presentation/create_vacation/CreateVacationScreen.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist.presentation.create_vacation 2 | 3 | import androidx.activity.compose.BackHandler 4 | import androidx.compose.foundation.layout.Column 5 | import androidx.compose.foundation.layout.fillMaxSize 6 | import androidx.compose.foundation.layout.fillMaxWidth 7 | import androidx.compose.foundation.layout.padding 8 | import androidx.compose.foundation.layout.Spacer 9 | import androidx.compose.foundation.layout.height 10 | import androidx.compose.foundation.layout.Arrangement 11 | import androidx.compose.material3.Divider 12 | import androidx.compose.material3.LocalContentColor 13 | import androidx.compose.runtime.Composable 14 | import androidx.compose.runtime.LaunchedEffect 15 | import androidx.compose.runtime.rememberCoroutineScope 16 | import androidx.compose.ui.Alignment 17 | import androidx.compose.ui.Modifier 18 | import androidx.compose.ui.res.stringResource 19 | import androidx.hilt.navigation.compose.hiltViewModel 20 | import com.commandiron.vacationchecklist.R 21 | import com.commandiron.vacationchecklist.presentation.components.CustomHeader 22 | import com.commandiron.vacationchecklist.presentation.components.CreateVacationBody 23 | import com.commandiron.vacationchecklist.presentation.components.LoadingBarAnimation 24 | import com.commandiron.vacationchecklist.presentation.components.LoadingThreeDotAnimation 25 | import com.commandiron.vacationchecklist.util.LocalSpacing 26 | import com.commandiron.vacationchecklist.util.UiEvent 27 | import com.google.accompanist.pager.rememberPagerState 28 | import kotlinx.coroutines.launch 29 | 30 | @Composable 31 | fun CreateVacationScreen( 32 | viewModel: CreateVacationViewModel = hiltViewModel(), 33 | navigate: (String) -> Unit 34 | ) { 35 | LaunchedEffect(key1 = true){ 36 | viewModel.uiEvent.collect{ event -> 37 | when(event) { 38 | is UiEvent.Navigate -> { 39 | navigate(event.route) 40 | } 41 | else -> {} 42 | } 43 | } 44 | } 45 | val state = viewModel.state 46 | val spacing = LocalSpacing.current 47 | val pagerState = rememberPagerState() 48 | val coroutineScope = rememberCoroutineScope() 49 | Column( 50 | modifier = Modifier 51 | .fillMaxSize() 52 | .padding(spacing.defaultScreenPadding), 53 | ) { 54 | CustomHeader( 55 | modifier = Modifier.fillMaxWidth(), 56 | title = stringResource(R.string.create_new_vacation), 57 | subTitle = stringResource(R.string.you_can_create_new_vacation_for_generate_checklist), 58 | ) 59 | Spacer(modifier = Modifier.height(spacing.spaceMedium)) 60 | Divider(color = LocalContentColor.current.copy(alpha = 0.2f)) 61 | Spacer(modifier = Modifier.height(spacing.spaceMedium)) 62 | if(!state.fakeLoading){ 63 | state.vacations?.let { vacations -> 64 | CreateVacationBody( 65 | pagerState = pagerState, 66 | vacations = vacations, 67 | onSelect = { vacation -> 68 | viewModel.onEvent(CreateVacationUserEvent.OnSelect(vacation)) 69 | }, 70 | selectedVacation = state.selectedVacation, 71 | onNextClick = { 72 | coroutineScope.launch { 73 | pagerState.animateScrollToPage(1) 74 | } 75 | }, 76 | onVacationNameChange = { vacationName -> 77 | viewModel.onEvent(CreateVacationUserEvent.OnNameChange(vacationName)) 78 | }, 79 | onFinishClick = { viewModel.onEvent(CreateVacationUserEvent.OnFinish) }, 80 | showAlertDialog = state.showAlertDialog, 81 | onAlertDismiss = { viewModel.onEvent(CreateVacationUserEvent.OnAlertDialogDismiss) }, 82 | onAlertConfirm = { viewModel.onEvent(CreateVacationUserEvent.OnAlertDialogConfirm(it)) } 83 | ) 84 | } 85 | }else{ 86 | Column( 87 | modifier = Modifier 88 | .fillMaxSize() 89 | .padding(bottom = spacing.bottomNavigationPadding.calculateBottomPadding()) 90 | .padding(bottom = spacing.bottomNavigationHeight), 91 | horizontalAlignment = Alignment.CenterHorizontally, 92 | verticalArrangement = Arrangement.Center 93 | ){ 94 | LoadingBarAnimation(loadingBarDurationMillis = state.fakeLoadingDelay.toInt()) 95 | Spacer(modifier = Modifier.height(spacing.spaceSmall)) 96 | LoadingThreeDotAnimation(stringResource(R.string.creating)) 97 | } 98 | } 99 | } 100 | BackHandler(enabled = pagerState.currentPage == 1) { 101 | coroutineScope.launch { 102 | pagerState.animateScrollToPage(0) 103 | } 104 | } 105 | } -------------------------------------------------------------------------------- /app/src/main/java/com/commandiron/vacationchecklist/presentation/create_vacation/CreateVacationState.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist.presentation.create_vacation 2 | 3 | import com.commandiron.vacationchecklist.domain.model.Vacation 4 | 5 | data class CreateVacationState( 6 | val vacations: List? = null, 7 | val selectedVacation: Vacation? = null, 8 | val showAlertDialog: Boolean = false, 9 | val fakeLoading: Boolean = false, 10 | val fakeLoadingDelay: Long = 3000 11 | ) 12 | -------------------------------------------------------------------------------- /app/src/main/java/com/commandiron/vacationchecklist/presentation/create_vacation/CreateVacationUserEvent.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist.presentation.create_vacation 2 | 3 | import com.commandiron.vacationchecklist.domain.model.Vacation 4 | 5 | sealed class CreateVacationUserEvent{ 6 | data class OnSelect(val vacation: Vacation) : CreateVacationUserEvent() 7 | data class OnNameChange(val text: String) : CreateVacationUserEvent() 8 | object OnFinish : CreateVacationUserEvent() 9 | object OnAlertDialogDismiss : CreateVacationUserEvent() 10 | data class OnAlertDialogConfirm(val vacation: Vacation) : CreateVacationUserEvent() 11 | } 12 | -------------------------------------------------------------------------------- /app/src/main/java/com/commandiron/vacationchecklist/presentation/create_vacation/CreateVacationViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist.presentation.create_vacation 2 | 3 | import androidx.compose.runtime.getValue 4 | import androidx.compose.runtime.mutableStateOf 5 | import androidx.compose.runtime.setValue 6 | import androidx.lifecycle.ViewModel 7 | import androidx.lifecycle.viewModelScope 8 | import com.commandiron.vacationchecklist.domain.preferences.Preferences 9 | import com.commandiron.vacationchecklist.domain.use_cases.UseCases 10 | import com.commandiron.vacationchecklist.navigation.NavigationItem 11 | import com.commandiron.vacationchecklist.util.UiEvent 12 | import dagger.hilt.android.lifecycle.HiltViewModel 13 | import kotlinx.coroutines.channels.Channel 14 | import kotlinx.coroutines.delay 15 | import kotlinx.coroutines.flow.receiveAsFlow 16 | import kotlinx.coroutines.launch 17 | import javax.inject.Inject 18 | 19 | @HiltViewModel 20 | class CreateVacationViewModel @Inject constructor( 21 | private val useCases: UseCases, 22 | private val preferences: Preferences 23 | ): ViewModel() { 24 | 25 | var state by mutableStateOf(CreateVacationState()) 26 | private set 27 | 28 | private val _uiEvent = Channel() 29 | val uiEvent = _uiEvent.receiveAsFlow() 30 | 31 | init { 32 | 33 | state = state.copy( 34 | fakeLoading = false, 35 | vacations = useCases.getAllVacations() 36 | ) 37 | } 38 | 39 | fun onEvent(userEvent: CreateVacationUserEvent) { 40 | when (userEvent) { 41 | is CreateVacationUserEvent.OnSelect -> { 42 | state = state.copy( 43 | selectedVacation = userEvent.vacation 44 | ) 45 | } 46 | is CreateVacationUserEvent.OnNameChange -> { 47 | state = state.copy( 48 | selectedVacation = state.selectedVacation?.copy( 49 | name = userEvent.text 50 | ) 51 | ) 52 | } 53 | is CreateVacationUserEvent.OnFinish -> { 54 | state = state.copy( 55 | showAlertDialog = true 56 | ) 57 | } 58 | CreateVacationUserEvent.OnAlertDialogDismiss -> { 59 | state = state.copy( 60 | showAlertDialog = false 61 | ) 62 | } 63 | is CreateVacationUserEvent.OnAlertDialogConfirm -> { 64 | state.selectedVacation?.let { 65 | state = state.copy( 66 | showAlertDialog = false 67 | ) 68 | viewModelScope.launch { 69 | useCases.deleteAllCheckItems() 70 | useCases.insertAllCheckItems(it) 71 | } 72 | preferences.saveActiveVacationId(userEvent.vacation.id) 73 | viewModelScope.launch { 74 | state = state.copy( 75 | fakeLoading = true 76 | ) 77 | delay(state.fakeLoadingDelay) 78 | sendUiEvent(UiEvent.Navigate(NavigationItem.ChecklistScreen.route)) 79 | } 80 | } 81 | } 82 | } 83 | } 84 | 85 | private fun sendUiEvent(uiEvent: UiEvent){ 86 | viewModelScope.launch() { 87 | _uiEvent.send(uiEvent) 88 | } 89 | } 90 | } -------------------------------------------------------------------------------- /app/src/main/java/com/commandiron/vacationchecklist/presentation/get_started/GetStartedScreen.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist.presentation.get_started 2 | 3 | import androidx.activity.compose.BackHandler 4 | import androidx.compose.foundation.layout.Column 5 | import androidx.compose.foundation.layout.fillMaxSize 6 | import androidx.compose.foundation.layout.fillMaxWidth 7 | import androidx.compose.foundation.layout.Spacer 8 | import androidx.compose.foundation.layout.height 9 | import androidx.compose.foundation.layout.Box 10 | import androidx.compose.foundation.layout.padding 11 | import androidx.compose.foundation.layout.Arrangement 12 | import androidx.compose.material3.Divider 13 | import androidx.compose.material3.LocalContentColor 14 | import androidx.compose.runtime.Composable 15 | import androidx.compose.runtime.LaunchedEffect 16 | import androidx.compose.runtime.rememberCoroutineScope 17 | import androidx.compose.ui.Alignment 18 | import androidx.compose.ui.Modifier 19 | import androidx.compose.ui.res.stringResource 20 | import androidx.hilt.navigation.compose.hiltViewModel 21 | import com.commandiron.vacationchecklist.R 22 | import com.commandiron.vacationchecklist.presentation.components.CustomHeader 23 | import com.commandiron.vacationchecklist.presentation.components.CreateVacationBody 24 | import com.commandiron.vacationchecklist.presentation.components.LoadingBarAnimation 25 | import com.commandiron.vacationchecklist.presentation.components.LoadingThreeDotAnimation 26 | import com.commandiron.vacationchecklist.presentation.components.CustomButton 27 | import com.commandiron.vacationchecklist.util.LocalSpacing 28 | import com.commandiron.vacationchecklist.util.UiEvent 29 | import com.google.accompanist.pager.rememberPagerState 30 | import kotlinx.coroutines.launch 31 | 32 | @Composable 33 | fun GetStartedScreen( 34 | viewModel: GetStartedViewModel = hiltViewModel(), 35 | navigate: (String) -> Unit 36 | ) { 37 | LaunchedEffect(key1 = true){ 38 | viewModel.uiEvent.collect{ event -> 39 | when(event) { 40 | is UiEvent.Navigate -> { 41 | navigate(event.route) 42 | } 43 | else -> {} 44 | } 45 | } 46 | } 47 | val state = viewModel.state 48 | val spacing = LocalSpacing.current 49 | val pagerState = rememberPagerState() 50 | val coroutineScope = rememberCoroutineScope() 51 | Column( 52 | modifier = Modifier 53 | .fillMaxSize() 54 | .padding(spacing.defaultScreenPadding), 55 | ) { 56 | CustomHeader( 57 | modifier = Modifier.fillMaxWidth(), 58 | title = stringResource(R.string.select_vacation), 59 | subTitle = stringResource(R.string.select_a_vacation_for_generate_checklist), 60 | ) 61 | Spacer(modifier = Modifier.height(spacing.spaceMedium)) 62 | Divider(color = LocalContentColor.current.copy(alpha = 0.2f)) 63 | Spacer(modifier = Modifier.height(spacing.spaceMedium)) 64 | if(!state.fakeLoading){ 65 | state.vacations?.let { vacations -> 66 | CreateVacationBody( 67 | pagerState = pagerState, 68 | vacations = vacations, 69 | onSelect = { vacation -> 70 | viewModel.onEvent(GetStartedUserEvent.OnSelect(vacation)) 71 | }, 72 | selectedVacation = state.selectedVacation, 73 | nextButtonEnabled = false, 74 | onVacationNameChange = { vacationName -> 75 | viewModel.onEvent(GetStartedUserEvent.OnNameChange(vacationName)) 76 | }, 77 | onFinishClick = { viewModel.onEvent(GetStartedUserEvent.OnFinish(it)) }, 78 | ) 79 | } 80 | }else{ 81 | Column( 82 | modifier = Modifier 83 | .fillMaxSize() 84 | .padding(bottom = spacing.bottomNavigationPadding.calculateBottomPadding()) 85 | .padding(bottom = spacing.bottomNavigationHeight), 86 | horizontalAlignment = Alignment.CenterHorizontally, 87 | verticalArrangement = Arrangement.Center 88 | ){ 89 | LoadingBarAnimation(loadingBarDurationMillis = state.fakeLoadingDelay.toInt()) 90 | Spacer(modifier = Modifier.height(spacing.spaceSmall)) 91 | LoadingThreeDotAnimation(stringResource(R.string.creating)) 92 | } 93 | } 94 | BackHandler(enabled = pagerState.currentPage == 1) { 95 | coroutineScope.launch { 96 | pagerState.animateScrollToPage(0) 97 | } 98 | } 99 | } 100 | state.selectedVacation?.let { 101 | if(pagerState.currentPage != 1){ 102 | Box( 103 | modifier = Modifier 104 | .fillMaxSize() 105 | .padding(bottom = spacing.bottomNavigationPadding.calculateBottomPadding()) 106 | .padding(bottom = spacing.bottomNavigationHeight), 107 | contentAlignment = Alignment.BottomCenter 108 | ) { 109 | CustomButton( 110 | modifier = Modifier.fillMaxWidth(0.60f), 111 | text = stringResource(R.string.get_started), 112 | onClick = { 113 | coroutineScope.launch { 114 | pagerState.animateScrollToPage(1) 115 | } 116 | } 117 | ) 118 | } 119 | } 120 | } 121 | } -------------------------------------------------------------------------------- /app/src/main/java/com/commandiron/vacationchecklist/presentation/get_started/GetStartedState.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist.presentation.get_started 2 | 3 | import com.commandiron.vacationchecklist.domain.model.Vacation 4 | 5 | data class GetStartedState( 6 | val vacations: List? = null, 7 | val selectedVacation: Vacation? = null, 8 | val isChecklistExist: Boolean? = false, 9 | val fakeLoading: Boolean = false, 10 | val fakeLoadingDelay: Long = 3000 11 | ) 12 | -------------------------------------------------------------------------------- /app/src/main/java/com/commandiron/vacationchecklist/presentation/get_started/GetStartedUserEvent.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist.presentation.get_started 2 | 3 | import com.commandiron.vacationchecklist.domain.model.Vacation 4 | 5 | sealed class GetStartedUserEvent{ 6 | data class OnSelect(val vacation: Vacation) : GetStartedUserEvent() 7 | data class OnNameChange(val text: String) : GetStartedUserEvent() 8 | data class OnFinish(val vacation: Vacation) : GetStartedUserEvent() 9 | } 10 | -------------------------------------------------------------------------------- /app/src/main/java/com/commandiron/vacationchecklist/presentation/get_started/GetStartedViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist.presentation.get_started 2 | 3 | import androidx.compose.runtime.getValue 4 | import androidx.compose.runtime.mutableStateOf 5 | import androidx.compose.runtime.setValue 6 | import androidx.lifecycle.ViewModel 7 | import androidx.lifecycle.viewModelScope 8 | import com.commandiron.vacationchecklist.domain.preferences.Preferences 9 | import com.commandiron.vacationchecklist.domain.use_cases.UseCases 10 | import com.commandiron.vacationchecklist.navigation.NavigationItem 11 | import com.commandiron.vacationchecklist.util.UiEvent 12 | import dagger.hilt.android.lifecycle.HiltViewModel 13 | import kotlinx.coroutines.channels.Channel 14 | import kotlinx.coroutines.delay 15 | import kotlinx.coroutines.flow.receiveAsFlow 16 | import kotlinx.coroutines.launch 17 | import javax.inject.Inject 18 | 19 | @HiltViewModel 20 | class GetStartedViewModel @Inject constructor( 21 | private val useCases: UseCases, 22 | private val preferences: Preferences 23 | ): ViewModel() { 24 | 25 | var state by mutableStateOf(GetStartedState()) 26 | private set 27 | 28 | private val _uiEvent = Channel() 29 | val uiEvent = _uiEvent.receiveAsFlow() 30 | 31 | init { 32 | viewModelScope.launch { 33 | if(useCases.getAllCheckItems().isNotEmpty()){ 34 | sendUiEvent(UiEvent.Navigate(NavigationItem.ChecklistScreen.route)) 35 | } 36 | } 37 | state = state.copy( 38 | fakeLoading = false, 39 | vacations = useCases.getAllVacations() 40 | ) 41 | } 42 | 43 | fun onEvent(userEvent: GetStartedUserEvent) { 44 | when (userEvent) { 45 | is GetStartedUserEvent.OnSelect -> { 46 | state = state.copy( 47 | selectedVacation = userEvent.vacation 48 | ) 49 | } 50 | is GetStartedUserEvent.OnNameChange -> { 51 | state = state.copy( 52 | selectedVacation = state.selectedVacation?.copy( 53 | name = userEvent.text 54 | ) 55 | ) 56 | } 57 | is GetStartedUserEvent.OnFinish -> { 58 | state.selectedVacation?.let { 59 | viewModelScope.launch { 60 | useCases.deleteAllCheckItems() 61 | useCases.insertAllCheckItems(it) 62 | } 63 | preferences.saveActiveVacationId(userEvent.vacation.id) 64 | viewModelScope.launch { 65 | state = state.copy( 66 | fakeLoading = true 67 | ) 68 | delay(state.fakeLoadingDelay) 69 | sendUiEvent(UiEvent.Navigate(NavigationItem.ChecklistScreen.route)) 70 | } 71 | } 72 | } 73 | } 74 | } 75 | 76 | private fun sendUiEvent(uiEvent: UiEvent){ 77 | viewModelScope.launch() { 78 | _uiEvent.send(uiEvent) 79 | } 80 | } 81 | } -------------------------------------------------------------------------------- /app/src/main/java/com/commandiron/vacationchecklist/presentation/hot_splash/HotSplashScreen.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist.presentation.hot_splash 2 | 3 | import androidx.compose.foundation.layout.Box 4 | import androidx.compose.foundation.layout.fillMaxSize 5 | import androidx.compose.foundation.layout.padding 6 | import androidx.compose.runtime.Composable 7 | import androidx.compose.runtime.LaunchedEffect 8 | import androidx.compose.ui.Alignment 9 | import androidx.compose.ui.Modifier 10 | import androidx.hilt.navigation.compose.hiltViewModel 11 | import com.commandiron.vacationchecklist.presentation.components.AppLogoWithName 12 | import com.commandiron.vacationchecklist.util.LocalSpacing 13 | import com.commandiron.vacationchecklist.presentation.components.FromCompanyComponent 14 | import kotlinx.coroutines.delay 15 | 16 | @Composable 17 | fun HotSplashScreen( 18 | viewModel: HotSplashViewModel = hiltViewModel(), 19 | onFinish:() -> Unit 20 | ) { 21 | val spacing = LocalSpacing.current 22 | LaunchedEffect(key1 = Unit){ 23 | viewModel.setShouldShowSplashScreenFalse() 24 | delay(viewModel.hotSplashDelay) 25 | onFinish() 26 | } 27 | Box( 28 | modifier = Modifier.fillMaxSize(), 29 | contentAlignment = Alignment.Center 30 | ) { 31 | AppLogoWithName() 32 | } 33 | Box( 34 | modifier = Modifier 35 | .fillMaxSize() 36 | .padding(bottom = spacing.spaceExtraLarge), 37 | contentAlignment = Alignment.BottomCenter 38 | ) { 39 | FromCompanyComponent() 40 | } 41 | } -------------------------------------------------------------------------------- /app/src/main/java/com/commandiron/vacationchecklist/presentation/hot_splash/HotSplashViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist.presentation.hot_splash 2 | 3 | import androidx.compose.runtime.getValue 4 | import androidx.compose.runtime.mutableStateOf 5 | import androidx.compose.runtime.setValue 6 | import androidx.lifecycle.ViewModel 7 | import com.commandiron.vacationchecklist.domain.preferences.Preferences 8 | import dagger.hilt.android.lifecycle.HiltViewModel 9 | import javax.inject.Inject 10 | 11 | @HiltViewModel 12 | class HotSplashViewModel @Inject constructor( 13 | private val preferences: Preferences 14 | ): ViewModel() { 15 | 16 | var hotSplashDelay by mutableStateOf(5000L) 17 | 18 | fun setShouldShowSplashScreenFalse(){ 19 | preferences.saveShouldShowHotSplash(false) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/commandiron/vacationchecklist/presentation/settings/SettingsScreen.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist.presentation.settings 2 | 3 | import androidx.compose.foundation.layout.Column 4 | import androidx.compose.foundation.layout.fillMaxSize 5 | import androidx.compose.foundation.layout.fillMaxWidth 6 | import androidx.compose.foundation.layout.padding 7 | import androidx.compose.foundation.layout.Spacer 8 | import androidx.compose.foundation.layout.height 9 | import androidx.compose.foundation.layout.Arrangement 10 | import androidx.compose.foundation.layout.Row 11 | import androidx.compose.material3.Divider 12 | import androidx.compose.material3.LocalContentColor 13 | import androidx.compose.material3.Text 14 | import androidx.compose.material3.MaterialTheme 15 | import androidx.compose.material3.Switch 16 | import androidx.compose.material3.SwitchDefaults 17 | import androidx.compose.runtime.Composable 18 | import androidx.compose.ui.Alignment 19 | import androidx.compose.ui.Modifier 20 | import androidx.compose.ui.graphics.Color 21 | import androidx.compose.ui.res.stringResource 22 | import androidx.hilt.navigation.compose.hiltViewModel 23 | import com.commandiron.vacationchecklist.R 24 | import com.commandiron.vacationchecklist.presentation.components.CustomHeader 25 | import com.commandiron.vacationchecklist.util.LocalSpacing 26 | 27 | @Composable 28 | fun SettingsScreen( 29 | viewModel: SettingsViewModel = hiltViewModel() 30 | ) { 31 | val state = viewModel.state 32 | val spacing = LocalSpacing.current 33 | Column( 34 | modifier = Modifier 35 | .fillMaxSize() 36 | .padding(spacing.defaultScreenPadding), 37 | ) { 38 | CustomHeader( 39 | modifier = Modifier.fillMaxWidth(), 40 | title = stringResource(R.string.settings) 41 | ) 42 | Spacer(modifier = Modifier.height(spacing.spaceMedium)) 43 | Divider(color = LocalContentColor.current.copy(alpha = 0.2f)) 44 | Spacer(modifier = Modifier.height(spacing.spaceMedium)) 45 | Row( 46 | modifier = Modifier.fillMaxWidth(), 47 | verticalAlignment = Alignment.CenterVertically, 48 | horizontalArrangement = Arrangement.SpaceBetween 49 | ) { 50 | Text( 51 | text = stringResource(R.string.double_Check), 52 | style = MaterialTheme.typography.titleMedium 53 | ) 54 | Switch( 55 | checked = state.switchChecked, 56 | onCheckedChange = { viewModel.onEvent(SettingsUserEvent.OnSwitchCheckedChange) }, 57 | colors = SwitchDefaults.colors( 58 | checkedTrackColor = MaterialTheme.colorScheme.primaryContainer, 59 | uncheckedThumbColor = MaterialTheme.colorScheme.primaryContainer, 60 | uncheckedTrackColor = Color.White, 61 | uncheckedBorderColor = MaterialTheme.colorScheme.primaryContainer 62 | ) 63 | ) 64 | } 65 | Spacer(modifier = Modifier.height(spacing.spaceMedium)) 66 | Divider(color = LocalContentColor.current.copy(alpha = 0.2f)) 67 | Spacer(modifier = Modifier.height(spacing.spaceMedium)) 68 | } 69 | } -------------------------------------------------------------------------------- /app/src/main/java/com/commandiron/vacationchecklist/presentation/settings/SettingsState.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist.presentation.settings 2 | 3 | data class SettingsState( 4 | val switchChecked: Boolean = false 5 | ) 6 | -------------------------------------------------------------------------------- /app/src/main/java/com/commandiron/vacationchecklist/presentation/settings/SettingsUserEvent.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist.presentation.settings 2 | 3 | sealed class SettingsUserEvent{ 4 | object OnSwitchCheckedChange: SettingsUserEvent() 5 | } 6 | -------------------------------------------------------------------------------- /app/src/main/java/com/commandiron/vacationchecklist/presentation/settings/SettingsViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist.presentation.settings 2 | 3 | import androidx.compose.runtime.getValue 4 | import androidx.compose.runtime.mutableStateOf 5 | import androidx.compose.runtime.setValue 6 | import androidx.lifecycle.ViewModel 7 | import androidx.lifecycle.viewModelScope 8 | import com.commandiron.vacationchecklist.domain.preferences.Preferences 9 | import com.commandiron.vacationchecklist.util.UiEvent 10 | import dagger.hilt.android.lifecycle.HiltViewModel 11 | import kotlinx.coroutines.channels.Channel 12 | import kotlinx.coroutines.flow.receiveAsFlow 13 | import kotlinx.coroutines.launch 14 | import javax.inject.Inject 15 | 16 | @HiltViewModel 17 | class SettingsViewModel @Inject constructor( 18 | private val preferences: Preferences 19 | ): ViewModel() { 20 | 21 | var state by mutableStateOf(SettingsState()) 22 | private set 23 | 24 | private val _uiEvent = Channel() 25 | val uiEvent = _uiEvent.receiveAsFlow() 26 | 27 | init { 28 | loadDoubleCheck() 29 | } 30 | 31 | fun onEvent(userEvent: SettingsUserEvent) { 32 | when (userEvent) { 33 | SettingsUserEvent.OnSwitchCheckedChange -> { 34 | saveDoubleCheck() 35 | loadDoubleCheck() 36 | } 37 | } 38 | } 39 | 40 | private fun loadDoubleCheck(){ 41 | state = state.copy( 42 | switchChecked = preferences.loadShouldDoubleCheck() 43 | ) 44 | } 45 | 46 | private fun saveDoubleCheck(){ 47 | preferences.saveShouldDoubleCheck(!state.switchChecked) 48 | } 49 | 50 | private fun sendUiEvent(uiEvent: UiEvent){ 51 | viewModelScope.launch() { 52 | _uiEvent.send(uiEvent) 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /app/src/main/java/com/commandiron/vacationchecklist/ui/theme/Color.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist.ui.theme 2 | 3 | import androidx.compose.ui.graphics.Color 4 | 5 | val Cultured = Color(0xFFF9F9FB) 6 | val OxfordBlue = Color(0xFF001429) 7 | val Bluetiful = Color(0xFF266EF1) 8 | val MaximumYellowRed = Color(0xFFfcbf49) 9 | 10 | val companyColor = Color(0xFFED7600) 11 | val importantBorderColor = Color(0xFFf77f00) 12 | 13 | 14 | -------------------------------------------------------------------------------- /app/src/main/java/com/commandiron/vacationchecklist/ui/theme/Shape.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist.ui.theme 2 | 3 | import androidx.compose.material3.Shapes 4 | 5 | val Shapes = Shapes() -------------------------------------------------------------------------------- /app/src/main/java/com/commandiron/vacationchecklist/ui/theme/Theme.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist.ui.theme 2 | 3 | import androidx.compose.foundation.isSystemInDarkTheme 4 | import androidx.compose.material3.MaterialTheme 5 | import androidx.compose.material3.darkColorScheme 6 | import androidx.compose.material3.lightColorScheme 7 | import androidx.compose.runtime.Composable 8 | import androidx.compose.ui.graphics.Color 9 | 10 | private val DarkColorPalette = darkColorScheme( 11 | background = Cultured, 12 | onBackground = OxfordBlue, 13 | primary = OxfordBlue, 14 | onPrimary = Color.White, 15 | primaryContainer = Bluetiful, 16 | onPrimaryContainer = Color.White, 17 | secondaryContainer = Color.White, 18 | onSecondaryContainer = Color.Black, 19 | tertiaryContainer = MaximumYellowRed, 20 | onTertiaryContainer = OxfordBlue 21 | ) 22 | 23 | private val LightColorPalette = lightColorScheme( 24 | background = Cultured, 25 | onBackground = OxfordBlue, 26 | primary = OxfordBlue, 27 | onPrimary = Color.White, 28 | primaryContainer = Bluetiful, 29 | onPrimaryContainer = Color.White, 30 | secondaryContainer = Color.White, 31 | onSecondaryContainer = Color.Black, 32 | tertiaryContainer = MaximumYellowRed, 33 | onTertiaryContainer = OxfordBlue 34 | ) 35 | 36 | @Composable 37 | fun VacationCheckListTheme( 38 | darkTheme: Boolean = isSystemInDarkTheme(), 39 | content: @Composable () -> Unit 40 | ) { 41 | val colorScheme = if (darkTheme) { 42 | DarkColorPalette 43 | } else { 44 | LightColorPalette 45 | } 46 | MaterialTheme( 47 | colorScheme = colorScheme, 48 | typography = Typography, 49 | shapes = Shapes, 50 | content = content 51 | ) 52 | } -------------------------------------------------------------------------------- /app/src/main/java/com/commandiron/vacationchecklist/ui/theme/Type.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist.ui.theme 2 | 3 | import androidx.compose.material3.Typography 4 | import androidx.compose.ui.text.TextStyle 5 | import androidx.compose.ui.text.font.Font 6 | import androidx.compose.ui.text.font.FontFamily 7 | import androidx.compose.ui.text.font.FontStyle 8 | import androidx.compose.ui.text.font.FontWeight 9 | import androidx.compose.ui.unit.sp 10 | import com.commandiron.vacationchecklist.R 11 | 12 | val Poppins = FontFamily( 13 | Font(R.font.poppins_black, FontWeight.Black, FontStyle.Normal), 14 | Font(R.font.poppins_black_italic, FontWeight.Black, FontStyle.Italic), 15 | Font(R.font.poppins_bold, FontWeight.Bold, FontStyle.Normal), 16 | Font(R.font.poppins_bold_italic, FontWeight.Bold, FontStyle.Italic), 17 | Font(R.font.poppins_extra_bold, FontWeight.ExtraBold, FontStyle.Normal), 18 | Font(R.font.poppins_extra_bold_italic, FontWeight.ExtraBold, FontStyle.Italic), 19 | Font(R.font.poppins_extra_light, FontWeight.Light, FontStyle.Normal), 20 | Font(R.font.poppins_extra_light_italic, FontWeight.Light, FontStyle.Italic), 21 | Font(R.font.poppins_italic, FontWeight.Normal, FontStyle.Italic), 22 | Font(R.font.poppins_light, FontWeight.Light, FontStyle.Normal), 23 | Font(R.font.poppins_light_italic, FontWeight.Light, FontStyle.Italic), 24 | Font(R.font.poppins_medium, FontWeight.Medium, FontStyle.Normal), 25 | Font(R.font.poppins_medium_italic, FontWeight.Medium, FontStyle.Italic), 26 | Font(R.font.poppins_regular, FontWeight.Normal, FontStyle.Normal), 27 | Font(R.font.poppins_semi_bold, FontWeight.SemiBold, FontStyle.Normal), 28 | Font(R.font.poppins_semi_bold_italic, FontWeight.SemiBold, FontStyle.Italic), 29 | Font(R.font.poppins_thin, FontWeight.Thin, FontStyle.Normal), 30 | Font(R.font.poppins_thin_italic, FontWeight.Thin, FontStyle.Italic), 31 | ) 32 | 33 | val Typography = Typography( 34 | displayMedium = TextStyle( 35 | fontFamily = Poppins, 36 | fontSize = 30.sp 37 | ), 38 | displaySmall = TextStyle( 39 | fontFamily = Poppins, 40 | fontSize = 28.sp 41 | ), 42 | headlineLarge = TextStyle( 43 | fontFamily = Poppins, 44 | fontSize = 26.sp 45 | ), 46 | headlineMedium = TextStyle( 47 | fontFamily = Poppins, 48 | fontSize = 24.sp 49 | ), 50 | headlineSmall = TextStyle( 51 | fontFamily = Poppins, 52 | fontSize = 22.sp 53 | ), 54 | titleLarge = TextStyle( 55 | fontFamily = Poppins, 56 | fontSize = 20.sp 57 | ), 58 | titleMedium = TextStyle( 59 | fontFamily = Poppins, 60 | fontSize = 18.sp 61 | ), 62 | titleSmall = TextStyle( 63 | fontFamily = Poppins, 64 | fontSize = 16.sp 65 | ), 66 | bodyLarge = TextStyle( 67 | fontFamily = Poppins, 68 | fontSize = 14.sp 69 | ), 70 | bodyMedium = TextStyle( 71 | fontFamily = Poppins, 72 | fontSize = 12.sp 73 | ), 74 | bodySmall = TextStyle( 75 | fontFamily = Poppins, 76 | fontSize = 10.sp 77 | ), 78 | labelLarge = TextStyle( 79 | fontFamily = Poppins, 80 | fontSize = 8.sp 81 | ), 82 | labelMedium = TextStyle( 83 | fontFamily = Poppins, 84 | fontSize = 6.sp 85 | ) 86 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/commandiron/vacationchecklist/util/LocalProvidedValues.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist.util 2 | 3 | import androidx.compose.foundation.layout.PaddingValues 4 | import androidx.compose.material.ripple.RippleAlpha 5 | import androidx.compose.material.ripple.RippleTheme 6 | import androidx.compose.material3.SnackbarHostState 7 | import androidx.compose.runtime.Composable 8 | import androidx.compose.runtime.ProvidedValue 9 | import androidx.compose.runtime.compositionLocalOf 10 | import androidx.compose.ui.graphics.Color 11 | import androidx.compose.ui.unit.Dp 12 | import androidx.compose.ui.unit.dp 13 | 14 | val LocalSpacing = compositionLocalOf { Dimensions() } 15 | 16 | data class Dimensions( 17 | val default: Dp = 0.dp, 18 | val spaceXXSmall: Dp = 2.dp, 19 | val spaceExtraSmall: Dp = 4.dp, 20 | val spaceSmall: Dp = 8.dp, 21 | val spaceMedium: Dp = 16.dp, 22 | val spaceLarge: Dp = 32.dp, 23 | val spaceExtraLarge: Dp = 64.dp, 24 | val spaceXXLarge: Dp = 128.dp, 25 | val spaceXXXLarge: Dp = 256.dp, 26 | 27 | val bottomNavigationHeight: Dp = 64.dp, 28 | val defaultButtonHeight: Dp = 52.dp, 29 | val bottomNavigationPadding: PaddingValues = PaddingValues( 30 | bottom = 24.dp, 31 | start = 24.dp, 32 | end = 24.dp 33 | ), 34 | val defaultScreenPadding: PaddingValues = PaddingValues( 35 | top = spaceLarge, 36 | start = spaceLarge, 37 | end = spaceLarge 38 | ), 39 | ) 40 | val LocalSnackbarHostState = compositionLocalOf { 41 | error("No Permission State") 42 | } 43 | 44 | fun getProvidedValues( 45 | snackbarHostState: SnackbarHostState 46 | ): Array> { 47 | return arrayOf( 48 | LocalSnackbarHostState provides snackbarHostState 49 | ) 50 | } 51 | 52 | object NoRippleTheme : RippleTheme { 53 | @Composable 54 | override fun defaultColor(): Color = Color.Transparent 55 | 56 | @Composable 57 | override fun rippleAlpha() = RippleAlpha( 58 | draggedAlpha = 0.0f, 59 | focusedAlpha = 0.0f, 60 | hoveredAlpha = 0.0f, 61 | pressedAlpha = 0.0f, 62 | ) 63 | } 64 | -------------------------------------------------------------------------------- /app/src/main/java/com/commandiron/vacationchecklist/util/Response.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist.util 2 | 3 | sealed class Response { 4 | object Loading: Response() 5 | 6 | data class Success( 7 | val data: T 8 | ): Response() 9 | 10 | data class Error( 11 | val message: String 12 | ): Response() 13 | } 14 | -------------------------------------------------------------------------------- /app/src/main/java/com/commandiron/vacationchecklist/util/UiEvent.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist.util 2 | 3 | sealed class UiEvent { 4 | data class Navigate(val route: String): UiEvent() 5 | data class ShowSnackbar(val uiText: UiText): UiEvent() 6 | } -------------------------------------------------------------------------------- /app/src/main/java/com/commandiron/vacationchecklist/util/UiText.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist.util 2 | 3 | import android.content.Context 4 | import androidx.annotation.StringRes 5 | 6 | sealed class UiText { 7 | class StringResource( 8 | @StringRes val resId: Int, 9 | vararg val args: Any 10 | ): UiText() 11 | 12 | fun asString(context: Context): String { 13 | return when(this) { 14 | is StringResource -> context.getString(resId, *args) 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 15 | 18 | 21 | 22 | 23 | 24 | 30 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/after_shave.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/after_shave.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/all_weather_boots.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/all_weather_boots.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/balaclava.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/balaclava.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/beach_ball.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/beach_ball.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/beach_chair.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/beach_chair.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/beach_towel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/beach_towel.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/beach_umbrella.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/beach_umbrella.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/belt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/belt.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/board_game.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/board_game.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/book.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/book.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/camera.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/camera.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/camera_charger.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/camera_charger.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/camping_tent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/camping_tent.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/car_rental.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/car_rental.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/casual_outfit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/casual_outfit.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/charger.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/charger.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ci_tech_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/ci_tech_logo.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/comb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/comb.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/contact_lens.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/contact_lens.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/deodorant.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/deodorant.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/digital.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/digital.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/electrical_converters.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/electrical_converters.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/everyday_bag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/everyday_bag.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/first_aid_kit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/first_aid_kit.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/game_console.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/game_console.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/hair_spray.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/hair_spray.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/hand_face_cream.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/hand_face_cream.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/hand_sanitizer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/hand_sanitizer.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/headphones.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/headphones.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/heavy_coat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/heavy_coat.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/hotel_reservation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/hotel_reservation.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_notifications_active_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 10 | 12 | 14 | 16 | 18 | 20 | 22 | 24 | 26 | 28 | 30 | 32 | 34 | 36 | 38 | 40 | 42 | 44 | 46 | 48 | 50 | 52 | 54 | 56 | 58 | 60 | 62 | 64 | 66 | 68 | 70 | 72 | 74 | 75 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/identification.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/identification.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/jacket.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/jacket.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/jewelry.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/jewelry.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/laptop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/laptop.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/laptop_charger.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/laptop_charger.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/laundry_bag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/laundry_bag.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/leather_gloves.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/leather_gloves.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/makeup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/makeup.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/medication.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/medication.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/nail_clippers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/nail_clippers.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/pajamas.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/pajamas.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/pants.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/pants.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/parfume.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/parfume.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/passport.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/passport.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/personal_care.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/personal_care.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/pillow_case.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/pillow_case.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/portable_charger.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/portable_charger.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/prescription_glasses.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/prescription_glasses.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/raincoat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/raincoat.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/razor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/razor.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/sandals.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/sandals.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/scarf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/scarf.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/shampoo_conditioner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/shampoo_conditioner.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/shaving_cream.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/shaving_cream.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/shoes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/shoes.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/shorts.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/shorts.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ski_board_boots.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/ski_board_boots.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ski_board_equipments.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/ski_board_equipments.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ski_board_glasses.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/ski_board_glasses.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ski_board_gloves.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/ski_board_gloves.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ski_board_helmet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/ski_board_helmet.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ski_board_jacket.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/ski_board_jacket.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ski_board_pants.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/ski_board_pants.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ski_board_socks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/ski_board_socks.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/smartphone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/smartphone.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/snack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/snack.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/snorkel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/snorkel.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/soap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/soap.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/socks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/socks.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/sun_block.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/sun_block.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/sun_hat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/sun_hat.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/sunglasses.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/sunglasses.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/sweater.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/sweater.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/swimwear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/swimwear.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/tampons_pad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/tampons_pad.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/tank_tops.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/tank_tops.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/tickets.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/tickets.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/toothbrush_toothpaste.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/toothbrush_toothpaste.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/towel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/towel.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/toys.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/toys.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/umbrella.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/umbrella.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/underwear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/underwear.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/wallet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/wallet.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/watch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/watch.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/water_shoe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/water_shoe.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/wet_wipes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/wet_wipes.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/winter_hat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/drawable/winter_hat.png -------------------------------------------------------------------------------- /app/src/main/res/font/poppins_black.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/font/poppins_black.ttf -------------------------------------------------------------------------------- /app/src/main/res/font/poppins_black_italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/font/poppins_black_italic.ttf -------------------------------------------------------------------------------- /app/src/main/res/font/poppins_bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/font/poppins_bold.ttf -------------------------------------------------------------------------------- /app/src/main/res/font/poppins_bold_italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/font/poppins_bold_italic.ttf -------------------------------------------------------------------------------- /app/src/main/res/font/poppins_extra_bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/font/poppins_extra_bold.ttf -------------------------------------------------------------------------------- /app/src/main/res/font/poppins_extra_bold_italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/font/poppins_extra_bold_italic.ttf -------------------------------------------------------------------------------- /app/src/main/res/font/poppins_extra_light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/font/poppins_extra_light.ttf -------------------------------------------------------------------------------- /app/src/main/res/font/poppins_extra_light_italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/font/poppins_extra_light_italic.ttf -------------------------------------------------------------------------------- /app/src/main/res/font/poppins_italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/font/poppins_italic.ttf -------------------------------------------------------------------------------- /app/src/main/res/font/poppins_light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/font/poppins_light.ttf -------------------------------------------------------------------------------- /app/src/main/res/font/poppins_light_italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/font/poppins_light_italic.ttf -------------------------------------------------------------------------------- /app/src/main/res/font/poppins_medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/font/poppins_medium.ttf -------------------------------------------------------------------------------- /app/src/main/res/font/poppins_medium_italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/font/poppins_medium_italic.ttf -------------------------------------------------------------------------------- /app/src/main/res/font/poppins_regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/font/poppins_regular.ttf -------------------------------------------------------------------------------- /app/src/main/res/font/poppins_semi_bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/font/poppins_semi_bold.ttf -------------------------------------------------------------------------------- /app/src/main/res/font/poppins_semi_bold_italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/font/poppins_semi_bold_italic.ttf -------------------------------------------------------------------------------- /app/src/main/res/font/poppins_thin.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/font/poppins_thin.ttf -------------------------------------------------------------------------------- /app/src/main/res/font/poppins_thin_italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/font/poppins_thin_italic.ttf -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/values-tr-rTR/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | CheckPack 4 | Check 5 | CITECH 6 | From 7 | Checklist 8 | Hazırsın! 9 | Geri 10 | İleri 11 | Bitir 12 | Evet 13 | Hayır 14 | Kur 15 | İptal 16 | Yükleniyor 17 | Oluşturuluyor 18 | Başla 19 | Tatil seç 20 | Lütfen tatil oluşturun. 21 | Yeni tatil oluştur 22 | Tatiline isim ver 23 | Çantanda mı? 24 | Önemli olarak işaretle? 25 | İşareti Kaldırılsın mı? 26 | Önceki checklist\'in kaybolacak. Emin misin? 27 | Checklist için yeni bir tatil oluşturabilirsin 28 | Checklist için yeni bir tatil oluştur 29 | Ayarlar 30 | Çifte sorgu 31 | Tatil Oluştur 32 | Alarm 33 | Lütfen android versionunuzu güncelleyin 34 | Alarmınızı kurduk 35 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FFF9F9FB 4 | #FF266EF1 5 | -------------------------------------------------------------------------------- /app/src/main/res/values/splash.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | CheckPack 3 | Check 4 | CITECH 5 | From 6 | Checklist 7 | You are ready to go! 8 | Back 9 | Next 10 | Finish 11 | Yes 12 | No 13 | Set 14 | Cancel 15 | Loading 16 | Creating 17 | Get Started 18 | Select vacation 19 | Please create vacation. 20 | Create New Vacation 21 | Enter vacation name 22 | In your bag? 23 | Mark as important? 24 | Remove Mark? 25 | Your previous checklist will be lost, are you sure? 26 | You can create new vacation for generate checklist 27 | Select a vacation for generate checklist 28 | Settings 29 | Double Check 30 | Create Vacation 31 | Set Alarm 32 | Please update your android version 33 | We set your alarm 34 | -------------------------------------------------------------------------------- /app/src/main/res/values/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/xml/backup_rules.xml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/xml/data_extraction_rules.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 12 | 13 | 19 | -------------------------------------------------------------------------------- /app/src/test/java/com/commandiron/vacationchecklist/ExampleUnitTest.kt: -------------------------------------------------------------------------------- 1 | package com.commandiron.vacationchecklist 2 | 3 | import org.junit.Test 4 | 5 | import org.junit.Assert.* 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * See [testing documentation](http://d.android.com/tools/testing). 11 | */ 12 | class ExampleUnitTest { 13 | @Test 14 | fun addition_isCorrect() { 15 | assertEquals(4, 2 + 2) 16 | } 17 | } -------------------------------------------------------------------------------- /build.gradle.kts: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | google() 4 | mavenCentral() 5 | } 6 | dependencies { 7 | classpath(Build.androidBuildTools) 8 | classpath(Build.kotlinGradlePlugin) 9 | classpath(DaggerHilt.hiltAndroidGradlePlugin) 10 | classpath(Google.services) 11 | classpath(Firebase.crashlyticsPlugin) 12 | } 13 | } 14 | 15 | tasks.register("clean", Delete::class){ 16 | delete(rootProject.buildDir) 17 | } -------------------------------------------------------------------------------- /buildSrc/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | build -------------------------------------------------------------------------------- /buildSrc/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import org.gradle.kotlin.dsl.`kotlin-dsl` 2 | 3 | repositories { 4 | mavenCentral() 5 | } 6 | 7 | plugins { 8 | `kotlin-dsl` 9 | } -------------------------------------------------------------------------------- /buildSrc/src/main/java/Accompanist.kt: -------------------------------------------------------------------------------- 1 | object Accompanist { 2 | private const val accompanistVersion = "0.24.9-beta" 3 | const val systemUi = 4 | "com.google.accompanist:accompanist-systemuicontroller:$accompanistVersion" 5 | const val navigationAnimation = 6 | "com.google.accompanist:accompanist-navigation-animation:$accompanistVersion" 7 | const val pager = "com.google.accompanist:accompanist-pager:$accompanistVersion" 8 | } -------------------------------------------------------------------------------- /buildSrc/src/main/java/AndroidX.kt: -------------------------------------------------------------------------------- 1 | object AndroidX { 2 | private const val coreKtxVersion = "1.7.0" 3 | const val coreKtx = "androidx.core:core-ktx:$coreKtxVersion" 4 | 5 | private const val appCompatVersion = "1.4.0" 6 | const val appCompat = "androidx.appcompat:appcompat:$appCompatVersion" 7 | 8 | private const val splashScreenVersion = "1.0.0-rc01" 9 | const val splashScreen = "androidx.core:core-splashscreen:$splashScreenVersion" 10 | } -------------------------------------------------------------------------------- /buildSrc/src/main/java/Build.kt: -------------------------------------------------------------------------------- 1 | object Build { 2 | private const val androidBuildToolsVersion = "7.2.0" 3 | const val androidBuildTools = "com.android.tools.build:gradle:$androidBuildToolsVersion" 4 | 5 | private const val kotlinVersion = "1.6.10" 6 | const val kotlinGradlePlugin = "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion" 7 | } 8 | -------------------------------------------------------------------------------- /buildSrc/src/main/java/CommandIron.kt: -------------------------------------------------------------------------------- 1 | object CommandIron { 2 | private const val wheelPickerComposeVersion = "1.0.9" 3 | const val wheelPickerCompose = "com.github.commandiron:WheelPickerCompose:$wheelPickerComposeVersion" 4 | } -------------------------------------------------------------------------------- /buildSrc/src/main/java/Compose.kt: -------------------------------------------------------------------------------- 1 | object Compose { 2 | const val composeVersion = "1.1.1" 3 | 4 | const val compiler = "androidx.compose.compiler:compiler:$composeVersion" 5 | const val ui = "androidx.compose.ui:ui:$composeVersion" 6 | const val uiToolingPreview = "androidx.compose.ui:ui-tooling-preview:$composeVersion" 7 | const val runtime = "androidx.compose.runtime:runtime:$composeVersion" 8 | 9 | private const val navigationVersion = "2.5.0-rc01" 10 | const val navigation = "androidx.navigation:navigation-compose:$navigationVersion" 11 | 12 | private const val lifecycleVersion = "2.5.0-rc01" 13 | const val viewModelCompose = "androidx.lifecycle:lifecycle-viewmodel-compose:$lifecycleVersion" 14 | 15 | private const val activityComposeVersion = "1.3.1" 16 | const val activityCompose = "androidx.activity:activity-compose:$activityComposeVersion" 17 | 18 | private const val hiltNavigationComposeVersion = "1.0.0-beta01" 19 | const val hiltNavigationCompose = "androidx.hilt:hilt-navigation-compose:$hiltNavigationComposeVersion" 20 | } -------------------------------------------------------------------------------- /buildSrc/src/main/java/Coroutines.kt: -------------------------------------------------------------------------------- 1 | object Coroutines { 2 | private const val version = "1.6.0" 3 | const val coroutines = "org.jetbrains.kotlinx:kotlinx-coroutines-core:$version" 4 | } -------------------------------------------------------------------------------- /buildSrc/src/main/java/DaggerHilt.kt: -------------------------------------------------------------------------------- 1 | object DaggerHilt { 2 | private const val version = "2.42" 3 | const val hiltAndroid = "com.google.dagger:hilt-android:$version" 4 | const val hiltCompiler = "com.google.dagger:hilt-android-compiler:$version" 5 | const val hiltAndroidGradlePlugin = "com.google.dagger:hilt-android-gradle-plugin:$version" 6 | } -------------------------------------------------------------------------------- /buildSrc/src/main/java/Firebase.kt: -------------------------------------------------------------------------------- 1 | object Firebase { 2 | private const val bomVersion = "30.2.0" 3 | const val bom = "com.google.firebase:firebase-bom:$bomVersion" 4 | const val analytics = "com.google.firebase:firebase-analytics-ktx" 5 | const val crashlytics = "com.google.firebase:firebase-crashlytics-ktx" 6 | 7 | private const val crashlyticsPluginVersion = "2.9.1" 8 | const val crashlyticsPlugin = "com.google.firebase:firebase-crashlytics-gradle:$crashlyticsPluginVersion" 9 | } -------------------------------------------------------------------------------- /buildSrc/src/main/java/Google.kt: -------------------------------------------------------------------------------- 1 | object Google { 2 | private const val materialVersion = "1.1.1" 3 | const val material = "androidx.compose.material:material:$materialVersion" 4 | 5 | private const val material3Version = "1.0.0-alpha13" 6 | const val material3 = "androidx.compose.material3:material3:$material3Version" 7 | 8 | private const val materialIconsCoreVersion = "1.1.1" 9 | const val materialIconsCore = "androidx.compose.material:material-icons-core:$materialIconsCoreVersion" 10 | 11 | private const val materialIconsExtendedVersion = "1.1.1" 12 | const val materialIconsExtended = "androidx.compose.material:material-icons-extended:$materialIconsExtendedVersion" 13 | 14 | private const val gsonVersion = "2.9.1" 15 | const val gson = "com.google.code.gson:gson:$gsonVersion" 16 | 17 | private const val servicesVersion = "4.3.13" 18 | const val services = "com.google.gms:google-services:$servicesVersion" 19 | } -------------------------------------------------------------------------------- /buildSrc/src/main/java/ProjectConfig.kt: -------------------------------------------------------------------------------- 1 | object ProjectConfig { 2 | const val appId = "com.commandiron.vacationchecklist" 3 | const val compileSdk = 32 4 | const val minSdk = 23 5 | const val targetSdk = 33 6 | const val versionCode = 8 7 | const val versionName = "1.0.7" 8 | } -------------------------------------------------------------------------------- /buildSrc/src/main/java/Room.kt: -------------------------------------------------------------------------------- 1 | object Room { 2 | private const val version = "2.4.0" 3 | const val runtime = "androidx.room:room-runtime:$version" 4 | const val compiler = "androidx.room:room-compiler:$version" 5 | const val ktx = "androidx.room:room-ktx:$version" 6 | } -------------------------------------------------------------------------------- /buildSrc/src/main/java/Testing.kt: -------------------------------------------------------------------------------- 1 | object Testing { 2 | private const val junitVersion = "4.13.2" 3 | const val junit = "junit:junit:$junitVersion" 4 | 5 | private const val junitAndroidExtVersion = "1.1.3" 6 | const val junitAndroidExt = "androidx.test.ext:junit:$junitAndroidExtVersion" 7 | 8 | const val composeUiTestJunit4 = "androidx.compose.ui:ui-test-junit4:${Compose.composeVersion}" 9 | const val composeUiTooling = "androidx.compose.ui:ui-tooling:${Compose.composeVersion}" 10 | const val composeUiTestManifest = "androidx.compose.ui:ui-test-manifest:${Compose.composeVersion}" 11 | } -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle settings configured through the IDE *will override* 4 | # any settings specified in this file. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 10 | # When configured, Gradle will run in incubating parallel mode. 11 | # This option should only be used with decoupled projects. More details, visit 12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 13 | # org.gradle.parallel=true 14 | # AndroidX package structure to make it clearer which packages are bundled with the 15 | # Android operating system, and which are packaged with your app"s APK 16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 17 | android.useAndroidX=true 18 | # Kotlin code style for this project: "official" or "obsolete": 19 | kotlin.code.style=official 20 | # Enables namespacing of each library's R class so that its R class includes only the 21 | # resources declared in the library itself and none from the library's dependencies, 22 | # thereby reducing the size of the R class for that library 23 | android.nonTransitiveRClass=true -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commandiron/CheckPack/29e8acbb890a9b6e3980c8b155e8bb421fd4b3f6/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Sat Jul 30 15:44:25 TRT 2022 2 | distributionBase=GRADLE_USER_HOME 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip 4 | distributionPath=wrapper/dists 5 | zipStorePath=wrapper/dists 6 | zipStoreBase=GRADLE_USER_HOME 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # 4 | # Copyright 2015 the original author or authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | ## 21 | ## Gradle start up script for UN*X 22 | ## 23 | ############################################################################## 24 | 25 | # Attempt to set APP_HOME 26 | # Resolve links: $0 may be a link 27 | PRG="$0" 28 | # Need this for relative symlinks. 29 | while [ -h "$PRG" ] ; do 30 | ls=`ls -ld "$PRG"` 31 | link=`expr "$ls" : '.*-> \(.*\)$'` 32 | if expr "$link" : '/.*' > /dev/null; then 33 | PRG="$link" 34 | else 35 | PRG=`dirname "$PRG"`"/$link" 36 | fi 37 | done 38 | SAVED="`pwd`" 39 | cd "`dirname \"$PRG\"`/" >/dev/null 40 | APP_HOME="`pwd -P`" 41 | cd "$SAVED" >/dev/null 42 | 43 | APP_NAME="Gradle" 44 | APP_BASE_NAME=`basename "$0"` 45 | 46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 48 | 49 | # Use the maximum available, or set MAX_FD != -1 to use that value. 50 | MAX_FD="maximum" 51 | 52 | warn () { 53 | echo "$*" 54 | } 55 | 56 | die () { 57 | echo 58 | echo "$*" 59 | echo 60 | exit 1 61 | } 62 | 63 | # OS specific support (must be 'true' or 'false'). 64 | cygwin=false 65 | msys=false 66 | darwin=false 67 | nonstop=false 68 | case "`uname`" in 69 | CYGWIN* ) 70 | cygwin=true 71 | ;; 72 | Darwin* ) 73 | darwin=true 74 | ;; 75 | MINGW* ) 76 | msys=true 77 | ;; 78 | NONSTOP* ) 79 | nonstop=true 80 | ;; 81 | esac 82 | 83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 84 | 85 | 86 | # Determine the Java command to use to start the JVM. 87 | if [ -n "$JAVA_HOME" ] ; then 88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 89 | # IBM's JDK on AIX uses strange locations for the executables 90 | JAVACMD="$JAVA_HOME/jre/sh/java" 91 | else 92 | JAVACMD="$JAVA_HOME/bin/java" 93 | fi 94 | if [ ! -x "$JAVACMD" ] ; then 95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 96 | 97 | Please set the JAVA_HOME variable in your environment to match the 98 | location of your Java installation." 99 | fi 100 | else 101 | JAVACMD="java" 102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 103 | 104 | Please set the JAVA_HOME variable in your environment to match the 105 | location of your Java installation." 106 | fi 107 | 108 | # Increase the maximum file descriptors if we can. 109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 110 | MAX_FD_LIMIT=`ulimit -H -n` 111 | if [ $? -eq 0 ] ; then 112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 113 | MAX_FD="$MAX_FD_LIMIT" 114 | fi 115 | ulimit -n $MAX_FD 116 | if [ $? -ne 0 ] ; then 117 | warn "Could not set maximum file descriptor limit: $MAX_FD" 118 | fi 119 | else 120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 121 | fi 122 | fi 123 | 124 | # For Darwin, add options to specify how the application appears in the dock 125 | if $darwin; then 126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 127 | fi 128 | 129 | # For Cygwin or MSYS, switch paths to Windows format before running java 130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then 131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 133 | 134 | JAVACMD=`cygpath --unix "$JAVACMD"` 135 | 136 | # We build the pattern for arguments to be converted via cygpath 137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 138 | SEP="" 139 | for dir in $ROOTDIRSRAW ; do 140 | ROOTDIRS="$ROOTDIRS$SEP$dir" 141 | SEP="|" 142 | done 143 | OURCYGPATTERN="(^($ROOTDIRS))" 144 | # Add a user-defined pattern to the cygpath arguments 145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 147 | fi 148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 149 | i=0 150 | for arg in "$@" ; do 151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 153 | 154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 156 | else 157 | eval `echo args$i`="\"$arg\"" 158 | fi 159 | i=`expr $i + 1` 160 | done 161 | case $i in 162 | 0) set -- ;; 163 | 1) set -- "$args0" ;; 164 | 2) set -- "$args0" "$args1" ;; 165 | 3) set -- "$args0" "$args1" "$args2" ;; 166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;; 167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 172 | esac 173 | fi 174 | 175 | # Escape application args 176 | save () { 177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 178 | echo " " 179 | } 180 | APP_ARGS=`save "$@"` 181 | 182 | # Collect all arguments for the java command, following the shell quoting and substitution rules 183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 184 | 185 | exec "$JAVACMD" "$@" 186 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto execute 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto execute 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :execute 68 | @rem Setup the command line 69 | 70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 71 | 72 | 73 | @rem Execute Gradle 74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 75 | 76 | :end 77 | @rem End local scope for the variables with windows NT shell 78 | if "%ERRORLEVEL%"=="0" goto mainEnd 79 | 80 | :fail 81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 82 | rem the _cmd.exe /c_ return code! 83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 84 | exit /b 1 85 | 86 | :mainEnd 87 | if "%OS%"=="Windows_NT" endlocal 88 | 89 | :omega 90 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | gradlePluginPortal() 4 | google() 5 | mavenCentral() 6 | } 7 | } 8 | dependencyResolutionManagement { 9 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) 10 | repositories { 11 | google() 12 | mavenCentral() 13 | maven { url 'https://jitpack.io' } 14 | } 15 | } 16 | rootProject.name = "VacationCheckList" 17 | include ':app' 18 | --------------------------------------------------------------------------------