initial commit: upload project

This commit is contained in:
Wisnu Andika
2025-04-09 12:19:46 +07:00
commit e24753f7a2
108 changed files with 3897 additions and 0 deletions

15
.gitignore vendored Normal file
View File

@ -0,0 +1,15 @@
*.iml
.gradle
/local.properties
/.idea/caches
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
/.idea/navEditor.xml
/.idea/assetWizardSettings.xml
.DS_Store
/build
/captures
.externalNativeBuild
.cxx
local.properties

3
.idea/.gitignore generated vendored Normal file
View File

@ -0,0 +1,3 @@
# Default ignored files
/shelf/
/workspace.xml

6
.idea/compiler.xml generated Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<bytecodeTargetLevel target="21" />
</component>
</project>

10
.idea/deploymentTargetDropDown.xml generated Normal file
View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="deploymentTargetDropDown">
<value>
<entry key="app">
<State />
</entry>
</value>
</component>
</project>

18
.idea/deploymentTargetSelector.xml generated Normal file
View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="deploymentTargetSelector">
<selectionStates>
<SelectionState runConfigName="app">
<option name="selectionMode" value="DROPDOWN" />
<DropdownSelection timestamp="2024-07-20T06:36:39.946968600Z">
<Target type="DEFAULT_BOOT">
<handle>
<DeviceId pluginId="LocalEmulator" identifier="path=C:\Users\rizky\.android\avd\Pixel_7_API_33.avd" />
</handle>
</Target>
</DropdownSelection>
<DialogSelection />
</SelectionState>
</selectionStates>
</component>
</project>

21
.idea/gradle.xml generated Normal file
View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleMigrationSettings" migrationVersion="1" />
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="testRunner" value="CHOOSE_PER_TEST" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleHome" value="$PROJECT_DIR$/../../../../../../../../gradle/gradle-8.3" />
<option name="gradleJvm" value="#GRADLE_LOCAL_JAVA_HOME" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/app" />
</set>
</option>
<option name="resolveExternalAnnotations" value="false" />
</GradleProjectSettings>
</option>
</component>
</project>

View File

@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="AndroidDomInspection" enabled="false" level="ERROR" enabled_by_default="false" />
</profile>
</component>

6
.idea/kotlinc.xml generated Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="KotlinJpsPluginSettings">
<option name="version" value="1.9.0" />
</component>
</project>

10
.idea/migrations.xml generated Normal file
View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectMigrations">
<option name="MigrateToGradleLocalJavaHome">
<set>
<option value="$PROJECT_DIR$" />
</set>
</option>
</component>
</project>

9
.idea/misc.xml generated Normal file
View File

@ -0,0 +1,9 @@
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="jbr-21" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
<option name="id" value="Android" />
</component>
</project>

17
.idea/runConfigurations.xml generated Normal file
View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RunConfigurationProducerService">
<option name="ignoredProducers">
<set>
<option value="com.intellij.execution.junit.AbstractAllInDirectoryConfigurationProducer" />
<option value="com.intellij.execution.junit.AllInPackageConfigurationProducer" />
<option value="com.intellij.execution.junit.PatternConfigurationProducer" />
<option value="com.intellij.execution.junit.TestInClassConfigurationProducer" />
<option value="com.intellij.execution.junit.UniqueIdConfigurationProducer" />
<option value="com.intellij.execution.junit.testDiscovery.JUnitTestDiscoveryConfigurationProducer" />
<option value="org.jetbrains.kotlin.idea.junit.KotlinJUnitRunConfigurationProducer" />
<option value="org.jetbrains.kotlin.idea.junit.KotlinPatternConfigurationProducer" />
</set>
</option>
</component>
</project>

6
.idea/vcs.xml generated Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

1
app/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/build

72
app/build.gradle.kts Normal file
View File

@ -0,0 +1,72 @@
plugins {
alias(libs.plugins.androidApplication)
alias(libs.plugins.jetbrainsKotlinAndroid)
id("kotlin-parcelize")
id("com.google.devtools.ksp") version "1.9.0-1.0.11"
}
android {
namespace = "com.example.palmguardapp"
compileSdk = 34
defaultConfig {
applicationId = "com.example.palmguardapp"
minSdk = 24
targetSdk = 34
versionCode = 1
versionName = "1.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
buildConfigField("String", "BASE_URL", "\"https://www.teamteaguard.com/\"")
}
buildTypes {
release {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
buildFeatures {
viewBinding = true
mlModelBinding = true
buildConfig = true
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = "1.8"
}
}
dependencies {
implementation("com.github.yalantis:ucrop:2.2.9")
implementation("com.github.bumptech.glide:glide:4.16.0")
implementation("com.squareup.retrofit2:retrofit:2.9.0")
implementation("com.squareup.retrofit2:converter-gson:2.9.0")
implementation("com.squareup.okhttp3:logging-interceptor:4.11.0")
implementation("androidx.datastore:datastore-preferences:1.0.0")
implementation("com.google.android.material:material:1.11.0")
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2")
implementation("androidx.fragment:fragment-ktx:1.3.6")
implementation("androidx.core:core-splashscreen:1.0.1")
implementation("de.hdodenhof:circleimageview:3.1.0")
implementation(libs.room.runtime)
implementation(libs.room.ktx)
implementation(libs.androidx.scenecore)
ksp(libs.room.compiler)
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.appcompat)
implementation(libs.material)
implementation(libs.androidx.activity)
implementation(libs.androidx.constraintlayout)
implementation(libs.tensorflow.lite.support)
implementation(libs.tensorflow.lite.metadata)
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)
}

21
app/proguard-rules.pro vendored Normal file
View File

@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

View File

@ -0,0 +1,24 @@
package com.example.palmguardapp
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.Assert.*
/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
@Test
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("com.example.teaguard", appContext.packageName)
}
}

View File

@ -0,0 +1,54 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="28" />
<uses-permission
android:name="android.permission.READ_EXTERNAL_STORAGE"
android:maxSdkVersion="32" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@drawable/splash_screen_ic"
android:label="@string/app_name"
android:roundIcon="@drawable/splash_screen_ic"
android:supportsRtl="true"
android:theme="@style/Theme.TeaGuard"
android:usesCleartextTraffic="true"
tools:targetApi="31">
<activity
android:name=".ui.errorDetection.ErrorDetectionActivity"
android:exported="false" />
<activity
android:name=".ui.listDisease.DiseaseDetailActivity"
android:exported="false" />
<activity
android:name=".ui.MainActivity"
android:exported="false" />
<activity
android:name=".ui.diagnose.DiagnoseDetailActivity"
android:exported="false" />
<activity
android:name=".ui.SplashScreenActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="com.yalantis.ucrop.UCropActivity"
android:screenOrientation="portrait"
android:theme="@style/Theme.AppCompat.Light.NoActionBar" />
</application>
</manifest>

View File

@ -0,0 +1,20 @@
package com.example.palmguardapp.data.local.entity
import android.os.Parcelable
import androidx.room.Entity
import androidx.room.PrimaryKey
import kotlinx.parcelize.Parcelize
@Entity
@Parcelize
data class DiseaseDiagnose(
@PrimaryKey()
val id: String = "",
val diseaseName: String,
val diseaseExplanation: String,
val diseaseRecommendation: String,
val detailExplanation: String,
val detailPrevention: String,
val detailRecommendation: String,
val date: String
) : Parcelable

View File

@ -0,0 +1,19 @@
package com.example.palmguardapp.data.local.entity
import android.os.Parcelable
import androidx.room.Entity
import androidx.room.PrimaryKey
import kotlinx.parcelize.Parcelize
@Entity
@Parcelize
data class HistoryDiagnose(
@PrimaryKey(autoGenerate = true)
val id: Int = 0,
val name: String,
val imageUri: String,
val diagnosis: String,
val recommendation: String,
val confidence: String,
val date: String
) : Parcelable

View File

@ -0,0 +1,134 @@
package com.example.palmguardapp.data.local.room
import android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
import androidx.sqlite.db.SupportSQLiteDatabase
import com.example.palmguardapp.data.local.entity.DiseaseDiagnose
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@Database(entities = [DiseaseDiagnose::class], version = 1)
abstract class DiseaseDatabase : RoomDatabase() {
abstract fun diseaseDiagnoseDao(): DiseaseDiagnoseDao
companion object {
@Volatile
private var INSTANCE : DiseaseDatabase? = null
@JvmStatic
fun getDatabase(context : Context) : DiseaseDatabase {
if (INSTANCE == null) {
synchronized(DiseaseDatabase::class.java) {
INSTANCE = Room.databaseBuilder(context.applicationContext,
DiseaseDatabase::class.java, "disease_diagnose_database")
.addCallback(DatabaseCallback())
.build()
}
}
return INSTANCE as DiseaseDatabase
}
}
private class DatabaseCallback : RoomDatabase.Callback() {
override fun onCreate(db: SupportSQLiteDatabase) {
super.onCreate(db)
INSTANCE?.let { diseaseDatabase ->
CoroutineScope(Dispatchers.IO).launch {
populateDatabase(diseaseDatabase.diseaseDiagnoseDao())
}
}
}
private suspend fun populateDatabase(dao: DiseaseDiagnoseDao) {
val diseaseData = listOf(
DiseaseDiagnose(
id = "D-001",
diseaseName = "Brown Spots",
diseaseExplanation = "Brown spots adalah penyakit yang menyerang daun tanaman kelapa sawit, ditandai dengan munculnya bercak-bercak coklat yang dapat menyebar dengan cepat. Penyakit ini disebabkan oleh jamur Helminthosporium, yang berkembang biak di lingkungan dengan kelembaban tinggi dan sirkulasi udara yang buruk.",
diseaseRecommendation = "Untuk mengatasi penyakit brown spots, diperlukan tindakan yang cepat dan tepat agar tidak menyebar ke seluruh bagian tanaman atau ke tanaman lain di sekitarnya. Salah satu langkah utama yang dapat dilakukan adalah menyemprotkan fungisida berbasis tembaga secara berkala, karena tembaga memiliki sifat fungisida yang efektif dalam menghambat pertumbuhan jamur penyebab penyakit ini.",
detailExplanation = "Brown spots adalah penyakit yang umum ditemukan pada tanaman kelapa sawit dan disebabkan oleh jamur Helminthosporium. Jamur ini menyerang bagian daun dan menimbulkan bercak-bercak coklat yang dapat menyebar dengan cepat, terutama di lingkungan yang lembab. Jika tidak segera ditangani, infeksi dapat menyebabkan daun mengering, menurunkan efisiensi fotosintesis, dan pada akhirnya menghambat pertumbuhan tanaman. Penyakit ini sering muncul pada musim hujan atau di daerah dengan tingkat kelembaban yang tinggi.",
detailPrevention = "Pencegahan penyakit brown spots dapat dilakukan dengan berbagai cara. Salah satu metode efektif adalah dengan memberikan pupuk yang mengandung tembaga, karena tembaga memiliki sifat fungisida alami yang dapat membantu mengurangi risiko infeksi jamur. Selain itu, penting untuk menjaga kebersihan lahan dengan memastikan sirkulasi udara yang baik di sekitar tanaman, sehingga kelembaban tidak terlalu tinggi. Pemangkasan daun yang terlalu lebat juga diperlukan agar sinar matahari dapat mencapai seluruh bagian tanaman dan mengurangi kemungkinan jamur berkembang. Penggunaan varietas kelapa sawit yang lebih tahan terhadap penyakit juga dapat menjadi strategi jangka panjang dalam mengurangi risiko infeksi.",
detailRecommendation = "Jika tanaman sudah terinfeksi brown spots, tindakan cepat perlu dilakukan untuk mencegah penyebaran penyakit ke tanaman lain. Salah satu cara yang direkomendasikan adalah menyemprotkan fungisida berbasis tembaga secara berkala, karena tembaga efektif dalam menghambat pertumbuhan jamur penyebab penyakit ini. Penyemprotan harus dilakukan pada pagi atau sore hari untuk memastikan fungisida dapat bekerja secara optimal tanpa cepat menguap akibat sinar matahari. Selain itu, pastikan dosis yang digunakan sesuai dengan anjuran agar tidak merusak tanaman. Jika infeksi sudah parah, pemangkasan daun yang terdampak dapat membantu mengurangi penyebaran spora jamur ke bagian tanaman yang masih sehat.",
date = "2025-02-10"
),
DiseaseDiagnose(
id = "D-002",
diseaseName = "Healthy",
diseaseExplanation = "Tanaman dalam kondisi sehat tanpa menunjukkan gejala penyakit atau gangguan pertumbuhan. Semua bagian tanaman, mulai dari daun, batang, hingga akar, berkembang dengan baik dan berfungsi secara optimal. Warna daun hijau segar menandakan tanaman mendapatkan nutrisi yang cukup, sementara batang yang kokoh menunjukkan sistem perakaran yang sehat. Tidak ada tanda-tanda infeksi jamur, bakteri, atau serangan hama yang dapat mengganggu pertumbuhan.",
diseaseRecommendation = "Untuk menjaga kondisi tanaman tetap sehat, penting untuk terus melanjutkan pola perawatan yang telah dilakukan. Pastikan tanaman mendapatkan nutrisi yang cukup melalui pemupukan yang seimbang dan sesuai dengan kebutuhannya. Selain itu, lakukan pemantauan secara rutin untuk memastikan tidak ada tanda-tanda awal penyakit atau serangan hama yang berpotensi merusak tanaman. Perhatikan juga faktor lingkungan seperti kelembaban, sirkulasi udara, dan intensitas cahaya, karena keseimbangan faktor-faktor ini sangat berpengaruh terhadap kesehatan tanaman dalam jangka panjang.",
detailExplanation = "Tanaman ini berada dalam kondisi optimal tanpa adanya gejala penyakit atau gangguan pertumbuhan. Daun tampak hijau segar, batang kuat, serta sistem perakaran berkembang dengan baik. Tidak ditemukan bercak, layu, atau tanda-tanda serangan hama dan penyakit. Lingkungan tumbuh yang sehat dengan kadar air, nutrisi, dan pencahayaan yang cukup mendukung pertumbuhan tanaman secara maksimal. Tanaman yang sehat juga menunjukkan tingkat fotosintesis yang baik, sehingga mampu menghasilkan energi yang cukup untuk pertumbuhan dan perkembangan.",
detailPrevention = "Untuk menjaga tanaman tetap sehat, penting untuk memastikan kondisi lingkungan tumbuh yang optimal. Faktor utama yang harus diperhatikan adalah ketersediaan air yang cukup tanpa menyebabkan kelebihan kelembaban, karena kondisi yang terlalu lembab dapat memicu pertumbuhan jamur dan bakteri patogen. Selain itu, penggunaan pupuk yang seimbang sesuai dengan kebutuhan tanaman sangat dianjurkan untuk mendukung pertumbuhan yang kuat. Pengendalian hama secara berkala juga diperlukan, baik dengan cara alami maupun menggunakan pestisida ramah lingkungan jika diperlukan. Rotasi tanaman dan sanitasi lahan dapat membantu mencegah munculnya hama dan penyakit yang dapat mengganggu kesehatan tanaman.",
detailRecommendation = "Untuk mempertahankan kondisi tanaman yang sehat, lakukan perawatan secara rutin dengan memastikan tanaman mendapatkan nutrisi yang cukup melalui pemupukan yang tepat. Pastikan tanaman mendapatkan sinar matahari yang cukup dan memiliki sistem drainase yang baik agar tidak terjadi genangan air yang dapat merusak akar. Selain itu, lakukan pemantauan berkala terhadap kemungkinan munculnya gejala penyakit atau serangan hama agar dapat segera diatasi jika ditemukan tanda-tanda awal gangguan. Dengan menjaga keseimbangan antara faktor lingkungan, nutrisi, dan perlindungan tanaman, kondisi sehat ini dapat dipertahankan dalam jangka panjang.",
date = "2025-02-10"
),
DiseaseDiagnose(
id = "D-003",
diseaseName = "Brown Spots",
diseaseExplanation = "Brown spots adalah penyakit yang menyerang daun tanaman kelapa sawit, ditandai dengan munculnya bercak-bercak coklat yang dapat menyebar dengan cepat. Penyakit ini disebabkan oleh jamur Helminthosporium, yang berkembang biak di lingkungan dengan kelembaban tinggi dan sirkulasi udara yang buruk.",
diseaseRecommendation = "Untuk mengatasi penyakit brown spots, diperlukan tindakan yang cepat dan tepat agar tidak menyebar ke seluruh bagian tanaman atau ke tanaman lain di sekitarnya. Salah satu langkah utama yang dapat dilakukan adalah menyemprotkan fungisida berbasis tembaga secara berkala, karena tembaga memiliki sifat fungisida yang efektif dalam menghambat pertumbuhan jamur penyebab penyakit ini.",
detailExplanation = "Brown spots adalah penyakit yang umum ditemukan pada tanaman kelapa sawit dan disebabkan oleh jamur Helminthosporium. Jamur ini menyerang bagian daun dan menimbulkan bercak-bercak coklat yang dapat menyebar dengan cepat, terutama di lingkungan yang lembab. Jika tidak segera ditangani, infeksi dapat menyebabkan daun mengering, menurunkan efisiensi fotosintesis, dan pada akhirnya menghambat pertumbuhan tanaman. Penyakit ini sering muncul pada musim hujan atau di daerah dengan tingkat kelembaban yang tinggi.",
detailPrevention = "Pencegahan penyakit brown spots dapat dilakukan dengan berbagai cara. Salah satu metode efektif adalah dengan memberikan pupuk yang mengandung tembaga, karena tembaga memiliki sifat fungisida alami yang dapat membantu mengurangi risiko infeksi jamur. Selain itu, penting untuk menjaga kebersihan lahan dengan memastikan sirkulasi udara yang baik di sekitar tanaman, sehingga kelembaban tidak terlalu tinggi. Pemangkasan daun yang terlalu lebat juga diperlukan agar sinar matahari dapat mencapai seluruh bagian tanaman dan mengurangi kemungkinan jamur berkembang. Penggunaan varietas kelapa sawit yang lebih tahan terhadap penyakit juga dapat menjadi strategi jangka panjang dalam mengurangi risiko infeksi.",
detailRecommendation = "Jika tanaman sudah terinfeksi brown spots, tindakan cepat perlu dilakukan untuk mencegah penyebaran penyakit ke tanaman lain. Salah satu cara yang direkomendasikan adalah menyemprotkan fungisida berbasis tembaga secara berkala, karena tembaga efektif dalam menghambat pertumbuhan jamur penyebab penyakit ini. Penyemprotan harus dilakukan pada pagi atau sore hari untuk memastikan fungisida dapat bekerja secara optimal tanpa cepat menguap akibat sinar matahari. Selain itu, pastikan dosis yang digunakan sesuai dengan anjuran agar tidak merusak tanaman. Jika infeksi sudah parah, pemangkasan daun yang terdampak dapat membantu mengurangi penyebaran spora jamur ke bagian tanaman yang masih sehat.",
date = "2025-02-10"
),
DiseaseDiagnose(
id = "D-004",
diseaseName = "Healthy",
diseaseExplanation = "Tanaman dalam kondisi sehat tanpa menunjukkan gejala penyakit atau gangguan pertumbuhan. Semua bagian tanaman, mulai dari daun, batang, hingga akar, berkembang dengan baik dan berfungsi secara optimal. Warna daun hijau segar menandakan tanaman mendapatkan nutrisi yang cukup, sementara batang yang kokoh menunjukkan sistem perakaran yang sehat. Tidak ada tanda-tanda infeksi jamur, bakteri, atau serangan hama yang dapat mengganggu pertumbuhan.",
diseaseRecommendation = "Untuk menjaga kondisi tanaman tetap sehat, penting untuk terus melanjutkan pola perawatan yang telah dilakukan. Pastikan tanaman mendapatkan nutrisi yang cukup melalui pemupukan yang seimbang dan sesuai dengan kebutuhannya. Selain itu, lakukan pemantauan secara rutin untuk memastikan tidak ada tanda-tanda awal penyakit atau serangan hama yang berpotensi merusak tanaman. Perhatikan juga faktor lingkungan seperti kelembaban, sirkulasi udara, dan intensitas cahaya, karena keseimbangan faktor-faktor ini sangat berpengaruh terhadap kesehatan tanaman dalam jangka panjang.",
detailExplanation = "Tanaman ini berada dalam kondisi optimal tanpa adanya gejala penyakit atau gangguan pertumbuhan. Daun tampak hijau segar, batang kuat, serta sistem perakaran berkembang dengan baik. Tidak ditemukan bercak, layu, atau tanda-tanda serangan hama dan penyakit. Lingkungan tumbuh yang sehat dengan kadar air, nutrisi, dan pencahayaan yang cukup mendukung pertumbuhan tanaman secara maksimal. Tanaman yang sehat juga menunjukkan tingkat fotosintesis yang baik, sehingga mampu menghasilkan energi yang cukup untuk pertumbuhan dan perkembangan.",
detailPrevention = "Untuk menjaga tanaman tetap sehat, penting untuk memastikan kondisi lingkungan tumbuh yang optimal. Faktor utama yang harus diperhatikan adalah ketersediaan air yang cukup tanpa menyebabkan kelebihan kelembaban, karena kondisi yang terlalu lembab dapat memicu pertumbuhan jamur dan bakteri patogen. Selain itu, penggunaan pupuk yang seimbang sesuai dengan kebutuhan tanaman sangat dianjurkan untuk mendukung pertumbuhan yang kuat. Pengendalian hama secara berkala juga diperlukan, baik dengan cara alami maupun menggunakan pestisida ramah lingkungan jika diperlukan. Rotasi tanaman dan sanitasi lahan dapat membantu mencegah munculnya hama dan penyakit yang dapat mengganggu kesehatan tanaman.",
detailRecommendation = "Untuk mempertahankan kondisi tanaman yang sehat, lakukan perawatan secara rutin dengan memastikan tanaman mendapatkan nutrisi yang cukup melalui pemupukan yang tepat. Pastikan tanaman mendapatkan sinar matahari yang cukup dan memiliki sistem drainase yang baik agar tidak terjadi genangan air yang dapat merusak akar. Selain itu, lakukan pemantauan berkala terhadap kemungkinan munculnya gejala penyakit atau serangan hama agar dapat segera diatasi jika ditemukan tanda-tanda awal gangguan. Dengan menjaga keseimbangan antara faktor lingkungan, nutrisi, dan perlindungan tanaman, kondisi sehat ini dapat dipertahankan dalam jangka panjang.",
date = "2025-02-10"
),
DiseaseDiagnose(
id = "D-005",
diseaseName = "Brown Spots",
diseaseExplanation = "Brown spots adalah penyakit yang menyerang daun tanaman kelapa sawit, ditandai dengan munculnya bercak-bercak coklat yang dapat menyebar dengan cepat. Penyakit ini disebabkan oleh jamur Helminthosporium, yang berkembang biak di lingkungan dengan kelembaban tinggi dan sirkulasi udara yang buruk.",
diseaseRecommendation = "Untuk mengatasi penyakit brown spots, diperlukan tindakan yang cepat dan tepat agar tidak menyebar ke seluruh bagian tanaman atau ke tanaman lain di sekitarnya. Salah satu langkah utama yang dapat dilakukan adalah menyemprotkan fungisida berbasis tembaga secara berkala, karena tembaga memiliki sifat fungisida yang efektif dalam menghambat pertumbuhan jamur penyebab penyakit ini.",
detailExplanation = "Brown spots adalah penyakit yang umum ditemukan pada tanaman kelapa sawit dan disebabkan oleh jamur Helminthosporium. Jamur ini menyerang bagian daun dan menimbulkan bercak-bercak coklat yang dapat menyebar dengan cepat, terutama di lingkungan yang lembab. Jika tidak segera ditangani, infeksi dapat menyebabkan daun mengering, menurunkan efisiensi fotosintesis, dan pada akhirnya menghambat pertumbuhan tanaman. Penyakit ini sering muncul pada musim hujan atau di daerah dengan tingkat kelembaban yang tinggi.",
detailPrevention = "Pencegahan penyakit brown spots dapat dilakukan dengan berbagai cara. Salah satu metode efektif adalah dengan memberikan pupuk yang mengandung tembaga, karena tembaga memiliki sifat fungisida alami yang dapat membantu mengurangi risiko infeksi jamur. Selain itu, penting untuk menjaga kebersihan lahan dengan memastikan sirkulasi udara yang baik di sekitar tanaman, sehingga kelembaban tidak terlalu tinggi. Pemangkasan daun yang terlalu lebat juga diperlukan agar sinar matahari dapat mencapai seluruh bagian tanaman dan mengurangi kemungkinan jamur berkembang. Penggunaan varietas kelapa sawit yang lebih tahan terhadap penyakit juga dapat menjadi strategi jangka panjang dalam mengurangi risiko infeksi.",
detailRecommendation = "Jika tanaman sudah terinfeksi brown spots, tindakan cepat perlu dilakukan untuk mencegah penyebaran penyakit ke tanaman lain. Salah satu cara yang direkomendasikan adalah menyemprotkan fungisida berbasis tembaga secara berkala, karena tembaga efektif dalam menghambat pertumbuhan jamur penyebab penyakit ini. Penyemprotan harus dilakukan pada pagi atau sore hari untuk memastikan fungisida dapat bekerja secara optimal tanpa cepat menguap akibat sinar matahari. Selain itu, pastikan dosis yang digunakan sesuai dengan anjuran agar tidak merusak tanaman. Jika infeksi sudah parah, pemangkasan daun yang terdampak dapat membantu mengurangi penyebaran spora jamur ke bagian tanaman yang masih sehat.",
date = "2025-02-10"
),
DiseaseDiagnose(
id = "D-006",
diseaseName = "Healthy",
diseaseExplanation = "Tanaman dalam kondisi sehat tanpa menunjukkan gejala penyakit atau gangguan pertumbuhan. Semua bagian tanaman, mulai dari daun, batang, hingga akar, berkembang dengan baik dan berfungsi secara optimal. Warna daun hijau segar menandakan tanaman mendapatkan nutrisi yang cukup, sementara batang yang kokoh menunjukkan sistem perakaran yang sehat. Tidak ada tanda-tanda infeksi jamur, bakteri, atau serangan hama yang dapat mengganggu pertumbuhan.",
diseaseRecommendation = "Untuk menjaga kondisi tanaman tetap sehat, penting untuk terus melanjutkan pola perawatan yang telah dilakukan. Pastikan tanaman mendapatkan nutrisi yang cukup melalui pemupukan yang seimbang dan sesuai dengan kebutuhannya. Selain itu, lakukan pemantauan secara rutin untuk memastikan tidak ada tanda-tanda awal penyakit atau serangan hama yang berpotensi merusak tanaman. Perhatikan juga faktor lingkungan seperti kelembaban, sirkulasi udara, dan intensitas cahaya, karena keseimbangan faktor-faktor ini sangat berpengaruh terhadap kesehatan tanaman dalam jangka panjang.",
detailExplanation = "Tanaman ini berada dalam kondisi optimal tanpa adanya gejala penyakit atau gangguan pertumbuhan. Daun tampak hijau segar, batang kuat, serta sistem perakaran berkembang dengan baik. Tidak ditemukan bercak, layu, atau tanda-tanda serangan hama dan penyakit. Lingkungan tumbuh yang sehat dengan kadar air, nutrisi, dan pencahayaan yang cukup mendukung pertumbuhan tanaman secara maksimal. Tanaman yang sehat juga menunjukkan tingkat fotosintesis yang baik, sehingga mampu menghasilkan energi yang cukup untuk pertumbuhan dan perkembangan.",
detailPrevention = "Untuk menjaga tanaman tetap sehat, penting untuk memastikan kondisi lingkungan tumbuh yang optimal. Faktor utama yang harus diperhatikan adalah ketersediaan air yang cukup tanpa menyebabkan kelebihan kelembaban, karena kondisi yang terlalu lembab dapat memicu pertumbuhan jamur dan bakteri patogen. Selain itu, penggunaan pupuk yang seimbang sesuai dengan kebutuhan tanaman sangat dianjurkan untuk mendukung pertumbuhan yang kuat. Pengendalian hama secara berkala juga diperlukan, baik dengan cara alami maupun menggunakan pestisida ramah lingkungan jika diperlukan. Rotasi tanaman dan sanitasi lahan dapat membantu mencegah munculnya hama dan penyakit yang dapat mengganggu kesehatan tanaman.",
detailRecommendation = "Untuk mempertahankan kondisi tanaman yang sehat, lakukan perawatan secara rutin dengan memastikan tanaman mendapatkan nutrisi yang cukup melalui pemupukan yang tepat. Pastikan tanaman mendapatkan sinar matahari yang cukup dan memiliki sistem drainase yang baik agar tidak terjadi genangan air yang dapat merusak akar. Selain itu, lakukan pemantauan berkala terhadap kemungkinan munculnya gejala penyakit atau serangan hama agar dapat segera diatasi jika ditemukan tanda-tanda awal gangguan. Dengan menjaga keseimbangan antara faktor lingkungan, nutrisi, dan perlindungan tanaman, kondisi sehat ini dapat dipertahankan dalam jangka panjang.",
date = "2025-02-10"
),
DiseaseDiagnose(
id = "D-007",
diseaseName = "Brown Spots",
diseaseExplanation = "Brown spots adalah penyakit yang menyerang daun tanaman kelapa sawit, ditandai dengan munculnya bercak-bercak coklat yang dapat menyebar dengan cepat. Penyakit ini disebabkan oleh jamur Helminthosporium, yang berkembang biak di lingkungan dengan kelembaban tinggi dan sirkulasi udara yang buruk.",
diseaseRecommendation = "Untuk mengatasi penyakit brown spots, diperlukan tindakan yang cepat dan tepat agar tidak menyebar ke seluruh bagian tanaman atau ke tanaman lain di sekitarnya. Salah satu langkah utama yang dapat dilakukan adalah menyemprotkan fungisida berbasis tembaga secara berkala, karena tembaga memiliki sifat fungisida yang efektif dalam menghambat pertumbuhan jamur penyebab penyakit ini.",
detailExplanation = "Brown spots adalah penyakit yang umum ditemukan pada tanaman kelapa sawit dan disebabkan oleh jamur Helminthosporium. Jamur ini menyerang bagian daun dan menimbulkan bercak-bercak coklat yang dapat menyebar dengan cepat, terutama di lingkungan yang lembab. Jika tidak segera ditangani, infeksi dapat menyebabkan daun mengering, menurunkan efisiensi fotosintesis, dan pada akhirnya menghambat pertumbuhan tanaman. Penyakit ini sering muncul pada musim hujan atau di daerah dengan tingkat kelembaban yang tinggi.",
detailPrevention = "Pencegahan penyakit brown spots dapat dilakukan dengan berbagai cara. Salah satu metode efektif adalah dengan memberikan pupuk yang mengandung tembaga, karena tembaga memiliki sifat fungisida alami yang dapat membantu mengurangi risiko infeksi jamur. Selain itu, penting untuk menjaga kebersihan lahan dengan memastikan sirkulasi udara yang baik di sekitar tanaman, sehingga kelembaban tidak terlalu tinggi. Pemangkasan daun yang terlalu lebat juga diperlukan agar sinar matahari dapat mencapai seluruh bagian tanaman dan mengurangi kemungkinan jamur berkembang. Penggunaan varietas kelapa sawit yang lebih tahan terhadap penyakit juga dapat menjadi strategi jangka panjang dalam mengurangi risiko infeksi.",
detailRecommendation = "Jika tanaman sudah terinfeksi brown spots, tindakan cepat perlu dilakukan untuk mencegah penyebaran penyakit ke tanaman lain. Salah satu cara yang direkomendasikan adalah menyemprotkan fungisida berbasis tembaga secara berkala, karena tembaga efektif dalam menghambat pertumbuhan jamur penyebab penyakit ini. Penyemprotan harus dilakukan pada pagi atau sore hari untuk memastikan fungisida dapat bekerja secara optimal tanpa cepat menguap akibat sinar matahari. Selain itu, pastikan dosis yang digunakan sesuai dengan anjuran agar tidak merusak tanaman. Jika infeksi sudah parah, pemangkasan daun yang terdampak dapat membantu mengurangi penyebaran spora jamur ke bagian tanaman yang masih sehat.",
date = "2025-02-10"
),
DiseaseDiagnose(
id = "D-008",
diseaseName = "Healthy",
diseaseExplanation = "Tanaman dalam kondisi sehat tanpa menunjukkan gejala penyakit atau gangguan pertumbuhan. Semua bagian tanaman, mulai dari daun, batang, hingga akar, berkembang dengan baik dan berfungsi secara optimal. Warna daun hijau segar menandakan tanaman mendapatkan nutrisi yang cukup, sementara batang yang kokoh menunjukkan sistem perakaran yang sehat. Tidak ada tanda-tanda infeksi jamur, bakteri, atau serangan hama yang dapat mengganggu pertumbuhan.",
diseaseRecommendation = "Untuk menjaga kondisi tanaman tetap sehat, penting untuk terus melanjutkan pola perawatan yang telah dilakukan. Pastikan tanaman mendapatkan nutrisi yang cukup melalui pemupukan yang seimbang dan sesuai dengan kebutuhannya. Selain itu, lakukan pemantauan secara rutin untuk memastikan tidak ada tanda-tanda awal penyakit atau serangan hama yang berpotensi merusak tanaman. Perhatikan juga faktor lingkungan seperti kelembaban, sirkulasi udara, dan intensitas cahaya, karena keseimbangan faktor-faktor ini sangat berpengaruh terhadap kesehatan tanaman dalam jangka panjang.",
detailExplanation = "Tanaman ini berada dalam kondisi optimal tanpa adanya gejala penyakit atau gangguan pertumbuhan. Daun tampak hijau segar, batang kuat, serta sistem perakaran berkembang dengan baik. Tidak ditemukan bercak, layu, atau tanda-tanda serangan hama dan penyakit. Lingkungan tumbuh yang sehat dengan kadar air, nutrisi, dan pencahayaan yang cukup mendukung pertumbuhan tanaman secara maksimal. Tanaman yang sehat juga menunjukkan tingkat fotosintesis yang baik, sehingga mampu menghasilkan energi yang cukup untuk pertumbuhan dan perkembangan.",
detailPrevention = "Untuk menjaga tanaman tetap sehat, penting untuk memastikan kondisi lingkungan tumbuh yang optimal. Faktor utama yang harus diperhatikan adalah ketersediaan air yang cukup tanpa menyebabkan kelebihan kelembaban, karena kondisi yang terlalu lembab dapat memicu pertumbuhan jamur dan bakteri patogen. Selain itu, penggunaan pupuk yang seimbang sesuai dengan kebutuhan tanaman sangat dianjurkan untuk mendukung pertumbuhan yang kuat. Pengendalian hama secara berkala juga diperlukan, baik dengan cara alami maupun menggunakan pestisida ramah lingkungan jika diperlukan. Rotasi tanaman dan sanitasi lahan dapat membantu mencegah munculnya hama dan penyakit yang dapat mengganggu kesehatan tanaman.",
detailRecommendation = "Untuk mempertahankan kondisi tanaman yang sehat, lakukan perawatan secara rutin dengan memastikan tanaman mendapatkan nutrisi yang cukup melalui pemupukan yang tepat. Pastikan tanaman mendapatkan sinar matahari yang cukup dan memiliki sistem drainase yang baik agar tidak terjadi genangan air yang dapat merusak akar. Selain itu, lakukan pemantauan berkala terhadap kemungkinan munculnya gejala penyakit atau serangan hama agar dapat segera diatasi jika ditemukan tanda-tanda awal gangguan. Dengan menjaga keseimbangan antara faktor lingkungan, nutrisi, dan perlindungan tanaman, kondisi sehat ini dapat dipertahankan dalam jangka panjang.",
date = "2025-02-10"
),
)
diseaseData.forEach{ dao.insert(it) }
}
}
}

View File

@ -0,0 +1,29 @@
package com.example.palmguardapp.data.local.room
import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import androidx.room.Update
import com.example.palmguardapp.data.local.entity.DiseaseDiagnose
import kotlinx.coroutines.flow.Flow
@Dao
interface DiseaseDiagnoseDao {
@Insert(onConflict = OnConflictStrategy.IGNORE)
suspend fun insert(diseaseDiagnose: DiseaseDiagnose)
@Update
suspend fun update(diseaseDiagnose: DiseaseDiagnose)
@Delete
suspend fun delete(diseaseDiagnose: DiseaseDiagnose)
@Query("SELECT * FROM diseasediagnose")
fun getAllDisease(): Flow<List<DiseaseDiagnose>>
@Query("SELECT * FROM diseasediagnose WHERE id = :id")
fun getDiseaseById(id: String): Flow<DiseaseDiagnose>
}

View File

@ -0,0 +1,30 @@
package com.example.palmguardapp.data.local.room
import android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
import com.example.palmguardapp.data.local.entity.HistoryDiagnose
@Database(entities = [HistoryDiagnose::class], version = 1)
abstract class HistoryDatabase : RoomDatabase() {
abstract fun historyDao(): HistoryDiagnoseDao
companion object {
@Volatile
private var INSTANCE : HistoryDatabase? = null
@JvmStatic
fun getDatabase(context : Context) : HistoryDatabase {
if (INSTANCE == null) {
synchronized(HistoryDatabase::class.java) {
INSTANCE = Room.databaseBuilder(context.applicationContext,
HistoryDatabase::class.java, "history_diagnose_database")
.build()
}
}
return INSTANCE as HistoryDatabase
}
}
}

View File

@ -0,0 +1,28 @@
package com.example.palmguardapp.data.local.room
import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import androidx.room.Update
import com.example.palmguardapp.data.local.entity.HistoryDiagnose
import kotlinx.coroutines.flow.Flow
@Dao
interface HistoryDiagnoseDao {
@Insert(onConflict = OnConflictStrategy.IGNORE)
suspend fun insert(historyDiagnose: HistoryDiagnose)
@Update
suspend fun update(historyDiagnose: HistoryDiagnose)
@Delete
suspend fun delete(historyDiagnose: HistoryDiagnose)
@Query("SELECT * FROM historydiagnose ORDER BY id DESC")
fun getAllHistory(): Flow<List<HistoryDiagnose>>
@Query("SELECT * FROM historydiagnose ORDER BY id DESC LIMIT 1")
fun getLastHistory(): Flow<HistoryDiagnose>
}

View File

@ -0,0 +1,75 @@
package com.example.palmguardapp.data.repository
import com.example.palmguardapp.data.local.entity.DiseaseDiagnose
import com.example.palmguardapp.data.local.room.DiseaseDiagnoseDao
import kotlinx.coroutines.flow.Flow
//class DiseaseRepository private constructor(
// private val apiService: ApiService
//) {
//
// suspend fun getDiseaseById(id: String): Flow<Result<DiseaseByIdResponse>> = flow {
// emit(Result.Loading)
// val response = apiService.getDiseaseById(id)
// emit(Result.Success(response))
// }.catch { e ->
// emit(Result.Error(e.message.toString()))
// }
//
// suspend fun getAllDiseaseDetail(): Flow<Result<DiseaseDetailResponse>> = flow {
// emit(Result.Loading)
// val response = apiService.getAllDiseaseDetail()
// emit(Result.Success(response))
// }.catch { e ->
// emit(Result.Error(e.message.toString()))
// }
//
// suspend fun getDiseaseDetailById(id: String): Flow<Result<DiseaseDetailByIdResponse>> = flow {
// emit(Result.Loading)
// val response = apiService.getDiseaseDetailById(id)
// emit(Result.Success(response))
// }.catch { e ->
// emit(Result.Error(e.message.toString()))
// }
//
// companion object {
// @Volatile
// private var instance: DiseaseRepository? = null
//
// fun getInstance(apiService: ApiService): DiseaseRepository =
// instance ?: synchronized(this) {
// instance ?: DiseaseRepository(apiService).also { instance = it }
// }
// }
//}
class DiseaseRepository private constructor(
private val diseaseDiagnoseDao: DiseaseDiagnoseDao
) {
suspend fun insert(diseaseDiagnose: DiseaseDiagnose) {
diseaseDiagnoseDao.insert(diseaseDiagnose)
}
suspend fun update(diseaseDiagnose: DiseaseDiagnose) {
diseaseDiagnoseDao.update(diseaseDiagnose)
}
suspend fun delete(diseaseDiagnose: DiseaseDiagnose) {
diseaseDiagnoseDao.delete(diseaseDiagnose)
}
fun getAllDisease(): Flow<List<DiseaseDiagnose>> = diseaseDiagnoseDao.getAllDisease()
fun getDiseaseById(id: String): Flow<DiseaseDiagnose> = diseaseDiagnoseDao.getDiseaseById(id)
companion object {
@Volatile
private var instance: DiseaseRepository? = null
fun getInstance(diseaseDiagnoseDao: DiseaseDiagnoseDao): DiseaseRepository =
instance ?: synchronized(this) {
instance ?: DiseaseRepository(diseaseDiagnoseDao).also { instance = it }
}
}
}

View File

@ -0,0 +1,36 @@
package com.example.palmguardapp.data.repository
import com.example.palmguardapp.data.local.entity.HistoryDiagnose
import com.example.palmguardapp.data.local.room.HistoryDiagnoseDao
import kotlinx.coroutines.flow.Flow
class HistoryDiagnoseRepository private constructor(
private val historyDiagnoseDao: HistoryDiagnoseDao
) {
fun getAllHistory(): Flow<List<HistoryDiagnose>> = historyDiagnoseDao.getAllHistory()
suspend fun insert(historyDiagnose: HistoryDiagnose) {
historyDiagnoseDao.insert(historyDiagnose)
}
suspend fun update(historyDiagnose: HistoryDiagnose) {
historyDiagnoseDao.update(historyDiagnose)
}
suspend fun delete(historyDiagnose: HistoryDiagnose) {
historyDiagnoseDao.delete(historyDiagnose)
}
fun getLastHistory() : Flow<HistoryDiagnose> = historyDiagnoseDao.getLastHistory()
companion object {
@Volatile
private var instance: HistoryDiagnoseRepository? = null
fun getInstance(historyDiagnoseDao: HistoryDiagnoseDao): HistoryDiagnoseRepository =
instance ?: synchronized(this) {
instance ?: HistoryDiagnoseRepository(historyDiagnoseDao).also { instance = it }
}
}
}

View File

@ -0,0 +1,23 @@
package com.example.palmguardapp.di
import android.content.Context
import com.example.palmguardapp.data.local.room.DiseaseDatabase
import com.example.palmguardapp.data.local.room.HistoryDatabase
import com.example.palmguardapp.data.repository.DiseaseRepository
import com.example.palmguardapp.data.repository.HistoryDiagnoseRepository
object Injection {
fun provideDiagnoseRepository(context : Context) : HistoryDiagnoseRepository {
val database = HistoryDatabase.getDatabase(context)
val dao = database.historyDao()
return HistoryDiagnoseRepository.getInstance(dao)
}
fun provideDiseaseRepository(context: Context): DiseaseRepository {
val database = DiseaseDatabase.getDatabase(context)
val dao = database.diseaseDiagnoseDao()
return DiseaseRepository.getInstance(dao)
}
}

View File

@ -0,0 +1,59 @@
package com.example.palmguardapp.foundation.adapter
import android.net.Uri
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import com.example.palmguardapp.data.local.entity.HistoryDiagnose
import com.example.palmguardapp.databinding.ItemResultBinding
class HistoryDiagnoseAdapter : ListAdapter<HistoryDiagnose, HistoryDiagnoseAdapter.ViewHolder>(DIFF_CALLBACK) {
private lateinit var onItemClickCallback: OnItemClickCallback
companion object {
private val DIFF_CALLBACK = object : DiffUtil.ItemCallback<HistoryDiagnose>() {
override fun areItemsTheSame(oldItem: HistoryDiagnose, newItem: HistoryDiagnose): Boolean {
return oldItem.id == newItem.id
}
override fun areContentsTheSame(oldItem: HistoryDiagnose, newItem: HistoryDiagnose): Boolean {
return oldItem == newItem
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val binding = ItemResultBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return ViewHolder(binding)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val history = getItem(position)
holder.bind(history)
holder.itemView.setOnClickListener {
onItemClickCallback.onItemClicked(history)
}
}
inner class ViewHolder(private val binding: ItemResultBinding) : RecyclerView.ViewHolder(binding.root) {
fun bind(historyDiagnose: HistoryDiagnose) {
binding.apply {
binding.imgResultDiagnosis.setImageURI(Uri.parse(historyDiagnose.imageUri))
titleResultDiagnosis.text = historyDiagnose.name
val date = historyDiagnose.date.replace("-", " ")
dateResultDiagnosis.text = date
}
}
}
interface OnItemClickCallback {
fun onItemClicked(data: HistoryDiagnose)
}
fun setOnItemClickCallback(onItemClickCallback: OnItemClickCallback) {
this.onItemClickCallback = onItemClickCallback
}
}

View File

@ -0,0 +1,26 @@
package com.example.palmguardapp.foundation.adapter
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.viewpager2.adapter.FragmentStateAdapter
import com.example.palmguardapp.data.local.entity.HistoryDiagnose
import com.example.palmguardapp.ui.diagnose.DiagnoseFragment
import com.example.palmguardapp.ui.diagnose.RecommendationFragment
class VPAdapter(
fa: FragmentActivity,
private val historyDiagnose: HistoryDiagnose
): FragmentStateAdapter(fa) {
override fun getItemCount(): Int {
return 2
}
override fun createFragment(position: Int): Fragment {
return when(position) {
0 -> DiagnoseFragment.newInstance(historyDiagnose.diagnosis)
1 -> RecommendationFragment.newInstance(historyDiagnose.recommendation)
else -> DiagnoseFragment()
}
}
}

View File

@ -0,0 +1,56 @@
import android.content.Context
import android.graphics.Bitmap
import android.util.Log
import com.example.palmguardapp.ml.Model
import org.tensorflow.lite.DataType
import org.tensorflow.lite.support.image.ImageProcessor
import org.tensorflow.lite.support.image.TensorImage
import org.tensorflow.lite.support.image.ops.ResizeOp
import org.tensorflow.lite.support.tensorbuffer.TensorBuffer
class ImageClassifier(private val context: Context) {
private val imageSize = 224
private val classes = arrayOf("Brown Spots", "Healthy")
private val imageProcessor = ImageProcessor.Builder()
.add(ResizeOp(imageSize, imageSize, ResizeOp.ResizeMethod.BILINEAR))
.build()
fun classifyImage(image: Bitmap): Pair<String, Float>? {
val model = Model.newInstance(context)
val tensorImage = TensorImage(DataType.FLOAT32)
tensorImage.load(image)
val processedImage = imageProcessor.process(tensorImage)
val inputFeature0 = TensorBuffer.createFixedSize(intArrayOf(1, imageSize, imageSize, 3), DataType.FLOAT32)
inputFeature0.loadBuffer(processedImage.buffer)
val outputs = model.process(inputFeature0)
val outputFeature0 = outputs.outputFeature0AsTensorBuffer
val confidences = outputFeature0.floatArray
for (i in confidences.indices) {
Log.d("ImageClassifier", "Class $i (${classes[i]}): ${confidences[i]}")
}
val maxPos = confidences.indices.maxByOrNull { confidences[it] } ?: -1
val maxConfidence = confidences[maxPos]
model.close()
return if (maxPos >= 0 && maxConfidence > THRESHOLD_CONFIDENCE) {
Pair(classes[maxPos], maxConfidence)
} else {
null
}
}
companion object {
private const val THRESHOLD_CONFIDENCE = 0.5f
}
}

View File

@ -0,0 +1,126 @@
package com.example.palmguardapp.foundation.utils
import android.annotation.TargetApi
import android.content.ContentValues
import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Matrix
import android.media.ExifInterface
import android.net.Uri
import android.os.Build
import android.os.Environment
import android.provider.MediaStore
import androidx.core.content.FileProvider
import com.example.palmguardapp.BuildConfig
import java.io.ByteArrayOutputStream
import java.io.File
import java.io.FileOutputStream
import java.io.InputStream
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
import java.util.UUID
private const val FILENAME_FORMAT = "yyyyMMdd_HHmmssSSS"
private val timeStamp: String = SimpleDateFormat(FILENAME_FORMAT, Locale.US).format(Date())
private val uniqueID: String = UUID.randomUUID().toString()
fun getImageUri(context: Context): Uri {
var uri: Uri? = null
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
val contentValues = ContentValues().apply {
put(MediaStore.MediaColumns.DISPLAY_NAME, "$timeStamp.jpg")
put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg")
put(MediaStore.MediaColumns.RELATIVE_PATH, "Pictures/MyCamera/")
}
uri = context.contentResolver.insert(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
contentValues
)
}
return uri ?: getImageUriForPreQ(context)
}
private fun getImageUriForPreQ(context: Context): Uri {
val filesDir = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES)
val imageFile = File(filesDir, "/MyCamera/$timeStamp.jpg")
if (imageFile.parentFile?.exists() == false) imageFile.parentFile?.mkdir()
return FileProvider.getUriForFile(
context,
"${BuildConfig.APPLICATION_ID}.fileprovider",
imageFile
)
}
fun createCustomTempFile(context: Context): File {
val filesDir = context.externalCacheDir
return File.createTempFile(timeStamp, ".jpg", filesDir)
}
fun uriToFile(imageUri : Uri, context: Context): File {
val myFile = createCustomTempFile(context)
val inputStream = context.contentResolver.openInputStream(imageUri) as InputStream
val outputStream = FileOutputStream(myFile)
val buffer = ByteArray(1024)
var length: Int
while (inputStream.read(buffer).also { length = it } > 0) outputStream.write(buffer, 0, length)
outputStream.close()
inputStream.close()
return myFile
}
private const val MAXIMAL_SIZE = 1000000
fun File.reduceFileImage(): File {
val file = this
val bitmap = BitmapFactory.decodeFile(file.path).getRotatedBitmap(file)
var compressQuality = 100
var streamLength: Int
do {
val bmpStream = ByteArrayOutputStream()
bitmap?.compress(Bitmap.CompressFormat.JPEG, compressQuality, bmpStream)
val bmpPicByteArray = bmpStream.toByteArray()
streamLength = bmpPicByteArray.size
compressQuality -= 5
} while (streamLength > MAXIMAL_SIZE)
bitmap?.compress(Bitmap.CompressFormat.JPEG, compressQuality, FileOutputStream(file))
return file
}
@TargetApi(Build.VERSION_CODES.Q)
fun Bitmap.getRotatedBitmap(file: File): Bitmap? {
val orientation = ExifInterface(file).getAttributeInt(
ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED
)
return when (orientation) {
ExifInterface.ORIENTATION_ROTATE_90 -> rotateImage(this, 90F)
ExifInterface.ORIENTATION_ROTATE_180 -> rotateImage(this, 180F)
ExifInterface.ORIENTATION_ROTATE_270 -> rotateImage(this, 270F)
ExifInterface.ORIENTATION_NORMAL -> this
else -> this
}
}
fun rotateImage(source: Bitmap, angle: Float): Bitmap? {
val matrix = Matrix()
matrix.postRotate(angle)
return Bitmap.createBitmap(
source, 0, 0, source.width, source.height, matrix, true
)
}
fun saveImageToLocalStorage(context: Context, image: Bitmap): Uri {
val timeStamp = SimpleDateFormat(FILENAME_FORMAT, Locale.US).format(Date())
val uniqueID = UUID.randomUUID().toString()
val filename = "${timeStamp}_${uniqueID}.jpg"
val filesDir = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES)
val imageFile = File(filesDir, filename)
val fos = FileOutputStream(imageFile)
image.compress(Bitmap.CompressFormat.JPEG, 100, fos)
fos.flush()
fos.close()
val reducedFile = imageFile.reduceFileImage()
return Uri.fromFile(reducedFile)
}

View File

@ -0,0 +1,7 @@
package com.example.palmguardapp.foundation.utils
sealed class Result<out R> private constructor() {
data class Success<out T>(val data: T) : Result<T>()
data class Error(val error: String) : Result<Nothing>()
object Loading : Result<Nothing>()
}

View File

@ -0,0 +1,62 @@
package com.example.palmguardapp.ui
import android.annotation.SuppressLint
import android.content.Intent
import android.os.Bundle
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.fragment.app.Fragment
import com.example.palmguardapp.R
import com.example.palmguardapp.databinding.ActivityMainBinding
import com.example.palmguardapp.ui.detection.DetectionFragment
import com.example.palmguardapp.ui.home.HomeFragment
import com.example.palmguardapp.ui.listDisease.DiseaseDetailActivity
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
@SuppressLint("MissingInflatedId")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContentView(R.layout.activity_main)
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
insets
}
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
replaceFragment(HomeFragment())
binding.bottomNavigationView.setOnItemSelectedListener { item ->
when(item.itemId) {
R.id.home -> {
replaceFragment(HomeFragment())
true
}
R.id.detection -> {
replaceFragment(DetectionFragment())
true
}
else -> false
}
}
}
private fun replaceFragment(fragment: Fragment) {
val fragmentManager = supportFragmentManager
val fragmentTransaction = fragmentManager.beginTransaction()
fragmentTransaction.replace(R.id.frame_layout, fragment)
fragmentTransaction.commit()
}
override fun onDestroy() {
super.onDestroy()
}
}

View File

@ -0,0 +1,28 @@
package com.example.palmguardapp.ui
import android.content.Intent
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import com.example.palmguardapp.R
class SplashScreenActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContentView(R.layout.activity_splash_screen)
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
insets
}
Handler(Looper.getMainLooper()).postDelayed({
startActivity(Intent(this, MainActivity::class.java))
finish()
}, 1500)
}
}

View File

@ -0,0 +1,48 @@
package com.example.palmguardapp.ui
import android.content.Context
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import com.example.palmguardapp.data.repository.DiseaseRepository
import com.example.palmguardapp.data.repository.HistoryDiagnoseRepository
import com.example.palmguardapp.di.Injection
import com.example.palmguardapp.ui.detection.DetectionViewModel
import com.example.palmguardapp.ui.home.HomeViewModel
import com.example.palmguardapp.ui.listDisease.DiseaseViewModel
class ViewModelFactory private constructor(
private val historyDiagnoseRepository: HistoryDiagnoseRepository,
private val diseaseRepository: DiseaseRepository
) : ViewModelProvider.NewInstanceFactory() {
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel> create(modelClass: Class<T>): T {
return when {
modelClass.isAssignableFrom(HomeViewModel::class.java) -> {
HomeViewModel(historyDiagnoseRepository, diseaseRepository) as T
}
modelClass.isAssignableFrom(DetectionViewModel::class.java) -> {
DetectionViewModel(historyDiagnoseRepository) as T
}
modelClass.isAssignableFrom(DiseaseViewModel::class.java) -> {
DiseaseViewModel(diseaseRepository) as T
}
else -> throw IllegalArgumentException("Unknown ViewModel class: ${modelClass.name}")
}
}
companion object {
@Volatile
private var INSTANCE: ViewModelFactory? = null
fun getInstance(context: Context): ViewModelFactory {
return INSTANCE ?: synchronized(this) {
val historyDiagnoseRepository = Injection.provideDiagnoseRepository(context)
val diseaseRepository = Injection.provideDiseaseRepository(context)
ViewModelFactory(historyDiagnoseRepository, diseaseRepository).also {
INSTANCE = it
}
}
}
}
}

View File

@ -0,0 +1,76 @@
package com.example.palmguardapp.ui.detection
import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
import com.example.palmguardapp.R
import com.example.palmguardapp.data.local.entity.HistoryDiagnose
import com.example.palmguardapp.databinding.FragmentDetectionBinding
import com.example.palmguardapp.foundation.adapter.HistoryDiagnoseAdapter
import com.example.palmguardapp.ui.ViewModelFactory
import com.example.palmguardapp.ui.diagnose.DiagnoseDetailActivity
import kotlinx.coroutines.launch
class DetectionFragment : Fragment(R.layout.fragment_detection) {
private var _binding: FragmentDetectionBinding? = null
private val binding get() = _binding!!
private val viewModel: DetectionViewModel by viewModels {
ViewModelFactory.getInstance(requireContext())
}
private val detectionAdapter = HistoryDiagnoseAdapter()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentDetectionBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setupRecyclerView()
observeDetectionList()
}
private fun setupRecyclerView() {
binding.rvResultDetection.layoutManager = LinearLayoutManager(requireContext())
binding.rvResultDetection.adapter = detectionAdapter
detectionAdapter.setOnItemClickCallback(object : HistoryDiagnoseAdapter.OnItemClickCallback {
override fun onItemClicked(data: HistoryDiagnose) {
navigateToDiagnoseDetail(data)
}
})
}
private fun navigateToDiagnoseDetail(historyDiagnose: HistoryDiagnose) {
val intent = Intent(requireActivity(), DiagnoseDetailActivity::class.java)
intent.putExtra("HISTORY_DIAGNOSE", historyDiagnose)
intent.putExtra("RETURN_FRAGMENT", "detection")
startActivity(intent)
}
private fun observeDetectionList() {
viewLifecycleOwner.lifecycleScope.launch {
viewModel.detectionList.collect { historyDiagnoses ->
Log.d("DetectionFragment", "Observing detection list. Count: ${historyDiagnoses.size}")
detectionAdapter.submitList(historyDiagnoses)
}
}
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}

View File

@ -0,0 +1,28 @@
package com.example.palmguardapp.ui.detection
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.palmguardapp.data.local.entity.HistoryDiagnose
import com.example.palmguardapp.data.repository.HistoryDiagnoseRepository
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.launch
class DetectionViewModel (private val historyDiagnoseRepository: HistoryDiagnoseRepository) : ViewModel() {
private val _detectionList = MutableSharedFlow<List<HistoryDiagnose>>()
val detectionList : Flow<List<HistoryDiagnose>> = _detectionList.asSharedFlow()
init {
getDetectionList()
}
private fun getDetectionList() {
viewModelScope.launch {
historyDiagnoseRepository.getAllHistory().collect {
_detectionList.emit(it)
}
}
}
}

View File

@ -0,0 +1,80 @@
package com.example.palmguardapp.ui.diagnose
import android.annotation.SuppressLint
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import com.example.palmguardapp.R
import com.example.palmguardapp.data.local.entity.HistoryDiagnose
import com.example.palmguardapp.databinding.ActivityDiagnoseBinding
import com.example.palmguardapp.foundation.adapter.VPAdapter
import com.example.palmguardapp.ui.listDisease.DiseaseDetailActivity
import com.google.android.material.tabs.TabLayoutMediator
class DiagnoseDetailActivity : AppCompatActivity() {
private lateinit var binding: ActivityDiagnoseBinding
private lateinit var historyDiagnose: HistoryDiagnose
private lateinit var returnFragment : String
@SuppressLint("MissingInflatedId")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContentView(R.layout.activity_diagnose)
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
insets
}
binding = ActivityDiagnoseBinding.inflate(layoutInflater)
setContentView(binding.root)
historyDiagnose = intent.getParcelableExtra("HISTORY_DIAGNOSE")!!
returnFragment = intent.getStringExtra("RETURN_FRAGMENT")!!
binding.tvTitle.text = historyDiagnose.name
binding.ivImgTea.setImageURI(Uri.parse(historyDiagnose.imageUri))
binding.tvConfidence.text = confidenceConverter(historyDiagnose.confidence)
binding.viewPager.adapter = VPAdapter(this, historyDiagnose)
binding.btnHsGallery.setOnClickListener {
val bundle = Bundle().apply {
putString("diseaseName", historyDiagnose.name)
}
val intent = Intent(this, DiseaseDetailActivity::class.java)
intent.putExtras(bundle)
startActivity(intent)
}
TabLayoutMediator(binding.tabLayout, binding.viewPager) { tab, position ->
when (position) {
0 -> tab.text = "Diagnosa"
1 -> tab.text = "Rekomendasi"
}
}.attach()
binding.dgsBack.setOnClickListener {
onBackPressed()
}
}
override fun onBackPressed() {
super.onBackPressed()
finish()
}
override fun onDestroy() {
super.onDestroy()
}
fun confidenceConverter(confidence: String): String {
val confidenceValue = confidence.toDouble() * 100
return if (confidenceValue % 1 == 0.0) {
confidenceValue.toInt().toString() + "%"
} else {
String.format("%.1f", confidenceValue) + "%"
}
}
}

View File

@ -0,0 +1,44 @@
package com.example.palmguardapp.ui.diagnose
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import com.example.palmguardapp.databinding.FragmentDiagnoseBinding
class DiagnoseFragment : Fragment() {
private var _binding: FragmentDiagnoseBinding? = null
private val binding get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentDiagnoseBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val diagnosis = arguments?.getString(ARG_DIAGNOSIS) ?: ""
binding.tvDiagnose.text = diagnosis
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
companion object {
private const val ARG_DIAGNOSIS = "diagnosis"
fun newInstance(diagnosis: String): DiagnoseFragment {
val fragment = DiagnoseFragment()
val args = Bundle()
args.putString(ARG_DIAGNOSIS, diagnosis)
fragment.arguments = args
return fragment
}
}
}

View File

@ -0,0 +1,44 @@
package com.example.palmguardapp.ui.diagnose
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import com.example.palmguardapp.databinding.FragmentRecommendationBinding
class RecommendationFragment : Fragment() {
private var _binding: FragmentRecommendationBinding? = null
private val binding get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentRecommendationBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val recommendation = arguments?.getString(ARG_RECOMMENDATION) ?: ""
binding.tvRecommendation.text = recommendation
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
companion object {
private const val ARG_RECOMMENDATION = "recommendation"
fun newInstance(recommendation: String): RecommendationFragment {
val fragment = RecommendationFragment()
val args = Bundle()
args.putString(ARG_RECOMMENDATION, recommendation)
fragment.arguments = args
return fragment
}
}
}

View File

@ -0,0 +1,29 @@
package com.example.palmguardapp.ui.errorDetection
import android.os.Bundle
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import com.example.palmguardapp.R
import com.example.palmguardapp.databinding.ActivityErrorDetectionBinding
class ErrorDetectionActivity : AppCompatActivity() {
private lateinit var binding: ActivityErrorDetectionBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityErrorDetectionBinding.inflate(layoutInflater)
enableEdgeToEdge()
setContentView(binding.root)
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
insets
}
binding.btErrorBack.setOnClickListener {
finish()
}
}
}

View File

@ -0,0 +1,312 @@
package com.example.palmguardapp.ui.home
import ImageClassifier
import android.Manifest
import android.app.Activity
import android.content.Intent
import android.content.pm.PackageManager
import android.graphics.Bitmap
import com.example.palmguardapp.foundation.utils.Result
import android.net.Uri
import android.os.Bundle
import android.provider.MediaStore
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.lifecycle.lifecycleScope
import com.example.palmguardapp.R
import com.example.palmguardapp.data.local.entity.HistoryDiagnose
import com.example.palmguardapp.databinding.FragmentHomeBinding
import com.example.palmguardapp.foundation.utils.saveImageToLocalStorage
import com.example.palmguardapp.ui.ViewModelFactory
import com.example.palmguardapp.ui.diagnose.DiagnoseDetailActivity
import com.example.palmguardapp.ui.listDisease.DiseaseDetailActivity
import com.google.android.material.snackbar.Snackbar
import com.yalantis.ucrop.UCrop
import kotlinx.coroutines.launch
import java.io.File
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
class HomeFragment : Fragment(R.layout.fragment_home) {
private var _binding: FragmentHomeBinding? = null
private val imageSize = 256
private val binding get() = _binding!!
private var lastDiagnosis: HistoryDiagnose? = null
private val viewModel: HomeViewModel by viewModels {
ViewModelFactory.getInstance(requireContext())
}
private val diseaseToId = mapOf(
"Algal Leaf" to "D-001",
"Anthracnose" to "D-002",
"Bird Eye Spot" to "D-003",
"Brown Blight" to "D-004",
"Gray Light" to "D-005",
"Red Leaf Spot" to "D-006",
"White Spot" to "D-007",
"Healthy" to "D-008"
)
private lateinit var cameraLauncher: ActivityResultLauncher<Intent>
private lateinit var galleryLauncher: ActivityResultLauncher<Intent>
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentHomeBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
cameraLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
if (result.resultCode == Activity.RESULT_OK) {
val image = result.data?.extras?.get("data") as? Bitmap
image?.let {
val imageUri = saveImageToLocalStorage(requireContext(), it)
startCrop(imageUri)
}
} else {
showSnackbarError("Permission denied or image capture failed")
}
}
galleryLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
if (result.resultCode == Activity.RESULT_OK) {
val selectedImageUri = result.data?.data
selectedImageUri?.let {
startCrop(it)
}
} else {
showSnackbarError("Permission denied or image selection failed")
}
}
binding.btnHsCamera.setOnClickListener {
if (ContextCompat.checkSelfPermission(
requireContext(),
Manifest.permission.CAMERA
) == PackageManager.PERMISSION_GRANTED
) {
val cameraIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
cameraLauncher.launch(cameraIntent)
} else {
requestPermissions(arrayOf(Manifest.permission.CAMERA), 100)
}
}
binding.btnHsGallery.setOnClickListener {
val galleryIntent = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI)
galleryLauncher.launch(galleryIntent)
}
binding.cdHomeScreenAnalyze.setOnClickListener {
lastDiagnosis?.let { diagnosis ->
navigateToDiagnoseDetail(diagnosis)
}
}
binding.flHomeScreenListDisease.setOnClickListener {
lifecycleScope.launch {
viewModel.getDiseaseById("D-001")
viewModel.dataDisease.collect { result ->
Log.d("flHomeScreen", result.toString())
when (result) {
is Result.Success -> {
val disease = result.data
val bundle = Bundle().apply {
putString("diseaseName", disease.diseaseName)
putString("diseaseExplanation", disease.diseaseExplanation)
putString("diseaseRecommendation", disease.diseaseRecommendation)
putString("detailExplanation", disease.detailExplanation)
putString("detailPrevention", disease.detailPrevention)
putString("detailRecommendation", disease.detailRecommendation)
}
val intent = Intent(requireContext(), DiseaseDetailActivity::class.java)
intent.putExtras(bundle)
startActivity(intent)
}
is Result.Error -> {
Toast.makeText(requireContext(), "Gagal mengambil data", Toast.LENGTH_SHORT).show()
}
Result.Loading -> TODO()
}
}
}
}
viewLifecycleOwner.lifecycleScope.launch {
viewModel.dataLastResult.collect { lastDiagnosis ->
lastDiagnosis?.let {
this@HomeFragment.lastDiagnosis = it
updateResultUi(it)
}
}
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == Activity.RESULT_OK) {
when (requestCode) {
UCrop.REQUEST_CROP -> {
val resultUri = UCrop.getOutput(data!!)
resultUri?.let {
val bitmap = MediaStore.Images.Media.getBitmap(requireContext().contentResolver, it)
lifecycleScope.launch {
classifyImage(bitmap)
}
}
}
UCrop.RESULT_ERROR -> {
val cropError = UCrop.getError(data!!)
cropError?.printStackTrace()
}
}
}
}
private fun startCrop(uri: Uri) {
val destinationUri = Uri.fromFile(File(requireContext().cacheDir, "${System.currentTimeMillis()}.jpg"))
UCrop.of(uri, destinationUri)
.withAspectRatio(1f, 1f)
.withMaxResultSize(imageSize, imageSize)
.start(requireContext(), this)
}
private suspend fun classifyImage(image: Bitmap) {
val classifier = ImageClassifier(requireContext())
val result = classifier.classifyImage(image)
if(result != null) {
val (diagnosis, confidence) = result
Log.d("HomeFragment", "Diagnosis: $result")
saveImageAndFetchData(diagnosis, confidence, image)
} else {
showSnackbarError("Gambar tidak sesuai, silahkan foto ulang")
}
}
private fun showSnackbarError(message: String) {
Snackbar.make(binding.root, message, Snackbar.LENGTH_LONG).show()
}
private suspend fun saveImageAndFetchData(diagnosis: String, confidence: Float, image: Bitmap) {
val imageUri = saveImageToLocalStorage(requireContext(), image)
val formatter = SimpleDateFormat("dd-MMMM-yyyy", Locale("id", "ID"))
val date = Date()
val dateNow = formatter.format(date)
val diseaseId = diseaseToId[diagnosis]
// diseaseId?.let { id ->
// viewModel.getDiseaseById(id)
// viewModel.dataDisease.collect { result ->
// when (result) {
// is Result.Success -> {
// val diseaseData = result.data
// Log.d("HomeFragment", "Disease Data: $diseaseData")
// val historyDiagnose = HistoryDiagnose(
// name = diagnosis,
// imageUri = imageUri.toString(),
// diagnosis = diseaseData.data?.diseaseExplanation ?: "",
// recommendation = diseaseData.data?.diseaseRecommendation ?: "",
// confidence = confidence.toString(),
// date = dateNow
// )
//
// viewModel.saveDiagnose(historyDiagnose)
// lastDiagnosis = historyDiagnose
// Log.d("HomeFragment", "History Diagnose: $historyDiagnose")
// binding.progressResult.visibility = View.GONE
// restartFragment()
// navigateToDiagnoseDetail(historyDiagnose)
// }
// is Result.Error -> {
// // Handle error state
// }
// Result.Loading -> {
// binding.progressResult.visibility = View.VISIBLE
// }
// }
// }
// }
diseaseId?.let { id ->
viewModel.getDiseaseById(id)
viewLifecycleOwner.lifecycleScope.launch {
viewModel.dataDisease.collect { result ->
when (result) {
is Result.Success -> {
val diseaseData = result.data
Log.d("HomeFragment", "Disease Data: $diseaseData")
val historyDiagnose = HistoryDiagnose(
name = diseaseData.diseaseName,
imageUri = imageUri.toString(),
diagnosis = diseaseData.diseaseExplanation,
recommendation = diseaseData.diseaseRecommendation,
confidence = confidence.toString(),
date = dateNow
)
viewModel.saveDiagnose(historyDiagnose)
lastDiagnosis = historyDiagnose
Log.d("HomeFragment", "History Diagnose: $historyDiagnose")
binding.progressResult.visibility = View.GONE
restartFragment()
navigateToDiagnoseDetail(historyDiagnose)
}
is Result.Error -> {
showSnackbarError("Gagal mengambil data penyakit dari database")
}
Result.Loading -> {
binding.progressResult.visibility = View.VISIBLE
}
}
}
}
}
}
private fun restartFragment() {
val fragmentManager = parentFragmentManager
val fragmentTransaction = fragmentManager.beginTransaction()
fragmentTransaction.detach(this).commitNow()
fragmentTransaction.attach(this).commitNow()
}
private fun navigateToDiagnoseDetail(historyDiagnose: HistoryDiagnose) {
val intent = Intent(activity, DiagnoseDetailActivity::class.java)
intent.putExtra("HISTORY_DIAGNOSE", historyDiagnose)
intent.putExtra("RETURN_FRAGMENT", "home")
intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP
startActivity(intent)
}
private fun updateResultUi(historyDiagnose: HistoryDiagnose) {
binding.imgResultDiagnosis.setImageURI(Uri.parse(historyDiagnose.imageUri))
binding.titleResultDiagnosis.text = historyDiagnose.name
val date = historyDiagnose.date.replace("-", " ")
binding.dateResultDiagnosis.text = date
binding.cdHomeScreenAnalyze.visibility = View.VISIBLE
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}

View File

@ -0,0 +1,48 @@
package com.example.palmguardapp.ui.home
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.palmguardapp.data.local.entity.DiseaseDiagnose
import com.example.palmguardapp.data.local.entity.HistoryDiagnose
import com.example.palmguardapp.data.repository.DiseaseRepository
import com.example.palmguardapp.data.repository.HistoryDiagnoseRepository
import com.example.palmguardapp.foundation.utils.Result
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.launch
class HomeViewModel (
private val historyDiagnoseRepository: HistoryDiagnoseRepository,
private val diseaseRepository: DiseaseRepository
) : ViewModel() {
private val _dataDisease = MutableSharedFlow<Result<DiseaseDiagnose>>()
val dataDisease : Flow<Result<DiseaseDiagnose>> = _dataDisease.asSharedFlow()
private val _dataLastResult = MutableSharedFlow<HistoryDiagnose>()
val dataLastResult : Flow<HistoryDiagnose> = _dataLastResult.asSharedFlow()
init {
getLastHistory()
}
fun getDiseaseById(id: String) {
viewModelScope.launch {
diseaseRepository.getDiseaseById(id).collect{ disease ->
_dataDisease.emit(Result.Success(disease))
}
}
}
suspend fun saveDiagnose(historyDiagnose: HistoryDiagnose) {
viewModelScope.launch {
historyDiagnoseRepository.insert(historyDiagnose)
}
}
private fun getLastHistory() {
viewModelScope.launch {
historyDiagnoseRepository.getLastHistory().collect{
_dataLastResult.emit(it)
}
}
}
}

View File

@ -0,0 +1,107 @@
package com.example.palmguardapp.ui.listDisease
import android.os.Bundle
import android.util.Log
import androidx.activity.enableEdgeToEdge
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.lifecycle.lifecycleScope
import com.bumptech.glide.Glide
import com.example.palmguardapp.BuildConfig
import com.example.palmguardapp.R
import com.example.palmguardapp.data.local.entity.DiseaseDiagnose
import com.example.palmguardapp.databinding.ActivityDiseaseDetailBinding
import com.example.palmguardapp.foundation.utils.Result
import com.example.palmguardapp.ui.ViewModelFactory
import com.google.android.material.snackbar.Snackbar
import kotlinx.coroutines.launch
class DiseaseDetailActivity : AppCompatActivity() {
private val viewModel: DiseaseViewModel by viewModels {
ViewModelFactory.getInstance(this)
}
private lateinit var binding: ActivityDiseaseDetailBinding
private var diseaseName: String? = null
private val diseaseToId = mapOf(
"Brown Spots" to "D-001",
"Healthy" to "D-002",
"Brown Spots" to "D-003",
"Healthy" to "D-004",
"Brown Spots" to "D-005",
"Healthy" to "D-006",
"Brown Spots" to "D-007",
"Healthy" to "D-008"
)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
binding = ActivityDiseaseDetailBinding.inflate(layoutInflater)
setContentView(binding.root)
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
insets
}
binding.dgsBack.setOnClickListener {
onBackPressed()
}
val bundle = intent.extras
Log.d("bundleObserve", bundle?.getString("id").toString())
diseaseName = bundle?.getString("diseaseName")
observeViewModel()
}
private fun setUpUi(diseaseDetail: DiseaseDiagnose?) {
if(diseaseDetail?.diseaseName == "Brown Spots") {
Glide.with(this)
.load(R.drawable.dgs_wereng_img)
.into(binding.imageDisease)
} else {
Glide.with(this)
.load(R.drawable.upn_logo)
.into(binding.imageDisease)
}
binding.tvDescDisease.text = "Penjelasan Penyakit"
binding.tvTitlePrevention.text = "Pencegahan"
binding.tvTitleRecommended.text = "Rekomendasi Penanganan"
binding.titleDisease.text = diseaseDetail?.diseaseName
binding.descDisease.text = diseaseDetail?.detailExplanation
binding.descPrevention.text = diseaseDetail?.detailPrevention
binding.descRecommended.text = diseaseDetail?.detailRecommendation
}
private fun observeViewModel() {
lifecycleScope.launch {
diseaseName?.let { diseaseToId[it]?.let { it1 -> viewModel.getDiseaseById(it1) } }
viewModel.diseaseById.collect { result ->
when (result) {
is Result.Success -> {
binding.progressResult.visibility = android.view.View.GONE
setUpUi(result.data)
}
is Result.Error -> {
binding.progressResult.visibility = android.view.View.GONE
Snackbar.make(
binding.root,
"Error loading data: ${result.error}",
Snackbar.LENGTH_LONG
).show()
}
is Result.Loading -> {
binding.progressResult.visibility = android.view.View.VISIBLE
}
}
}
}
}
override fun onBackPressed() {
super.onBackPressed()
finish()
}
}

View File

@ -0,0 +1,42 @@
package com.example.palmguardapp.ui.listDisease
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.palmguardapp.data.local.entity.DiseaseDiagnose
import com.example.palmguardapp.data.repository.DiseaseRepository
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.launch
import com.example.palmguardapp.foundation.utils.Result
import kotlinx.coroutines.flow.asSharedFlow
class DiseaseViewModel(private val diseaseRepository: DiseaseRepository) : ViewModel() {
private val _listDisease = MutableSharedFlow<Result<List<DiseaseDiagnose>>>()
val listDisease: Flow<Result<List<DiseaseDiagnose>>> = _listDisease.asSharedFlow()
private val _diseaseById = MutableSharedFlow<Result<DiseaseDiagnose?>>()
val diseaseById: Flow<Result<DiseaseDiagnose?>> = _diseaseById.asSharedFlow()
// fun getAllDisease() {
// viewModelScope.launch {
// _listDisease.emit(Result.Loading)
// diseaseRepository.getAllDisease().collect { diseases ->
// _listDisease.emit(Result.Success(diseases))
// }
// }
// }
fun getDiseaseById(id: String) {
viewModelScope.launch {
_diseaseById.emit(Result.Loading)
diseaseRepository.getDiseaseById(id).collect { disease ->
if (disease != null) {
_diseaseById.emit(Result.Success(disease))
} else {
_diseaseById.emit(Result.Error("Penyakit tidak ditemukan di database lokal"))
}
}
}
}
}

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners
android:topLeftRadius="8dp"
android:topRightRadius="8dp" />
<solid android:color="@color/white" />
</shape>

View File

@ -0,0 +1,6 @@
<!-- res/drawable/button_no_radius.xml -->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/primaryGreen" />
<corners android:radius="0dp" />
</shape>

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 659 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 705 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 616 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 449 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 952 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 337 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -0,0 +1,170 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path
android:fillColor="#3DDC84"
android:pathData="M0,0h108v108h-108z" />
<path
android:fillColor="#00000000"
android:pathData="M9,0L9,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,0L19,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,0L29,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,0L39,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,0L49,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,0L59,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,0L69,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,0L79,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M89,0L89,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M99,0L99,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,9L108,9"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,19L108,19"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,29L108,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,39L108,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,49L108,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,59L108,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,69L108,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,79L108,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,89L108,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,99L108,99"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,29L89,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,39L89,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,49L89,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,59L89,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,69L89,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,79L89,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,19L29,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,19L39,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,19L49,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,19L59,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,19L69,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,19L79,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
</vector>

View File

@ -0,0 +1,30 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
<aapt:attr name="android:fillColor">
<gradient
android:endX="85.84757"
android:endY="92.4963"
android:startX="42.9492"
android:startY="49.59793"
android:type="linear">
<item
android:color="#44000000"
android:offset="0.0" />
<item
android:color="#00000000"
android:offset="1.0" />
</gradient>
</aapt:attr>
</path>
<path
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
android:strokeWidth="1"
android:strokeColor="#00000000" />
</vector>

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,227 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.diagnose.DiagnoseDetailActivity">
<!-- <LinearLayout-->
<!-- android:id="@+id/ll_ds"-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:layout_marginHorizontal="30dp"-->
<!-- android:orientation="vertical"-->
<!-- app:layout_constraintEnd_toEndOf="parent"-->
<!-- app:layout_constraintStart_toStartOf="parent"-->
<!-- app:layout_constraintTop_toTopOf="parent">-->
<!-- <ImageView-->
<!-- android:id="@+id/dgs_back"-->
<!-- android:layout_width="32dp"-->
<!-- android:layout_height="32dp"-->
<!-- android:layout_marginTop="35dp"-->
<!-- android:layout_marginBottom="15dp"-->
<!-- android:src="@drawable/ds_back_arrow_img" />-->
<!-- <LinearLayout-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:orientation="horizontal">-->
<!-- <TextView-->
<!-- android:id="@+id/tv_title"-->
<!-- style="@style/ActivityDiagnoseDiseaseName"-->
<!-- android:layout_width="wrap_content"-->
<!-- android:layout_height="wrap_content"-->
<!-- tools:text="Algal Leaf" />-->
<!-- <TextView-->
<!-- android:id="@+id/tv_confidence"-->
<!-- style="@style/ActivityDiagnoseDiseaseName"-->
<!-- android:layout_marginStart="10dp"-->
<!-- android:layout_width="wrap_content"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:text="80%" />-->
<!-- </LinearLayout>-->
<!-- <com.google.android.material.card.MaterialCardView-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="wrap_content">-->
<!-- <ImageView-->
<!-- android:id="@+id/iv_img_tea"-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="200dp"-->
<!-- android:scaleType="fitXY"-->
<!-- tools:src="@drawable/dgs_wereng_img" />-->
<!-- </com.google.android.material.card.MaterialCardView>-->
<!-- <com.google.android.material.tabs.TabLayout-->
<!-- android:id="@+id/tab_layout"-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:layout_marginVertical="8dp"-->
<!-- app:tabSelectedTextColor="@color/primaryGreen"-->
<!-- app:tabIndicatorColor="@color/primaryGreen"-->
<!-- android:background="@color/grayBackground"-->
<!-- app:layout_constraintTop_toBottomOf="@+id/img">-->
<!-- <com.google.android.material.tabs.TabItem-->
<!-- android:layout_width="wrap_content"-->
<!-- android:layout_height="wrap_content" />-->
<!-- <com.google.android.material.tabs.TabItem-->
<!-- android:layout_width="wrap_content"-->
<!-- android:layout_height="wrap_content" />-->
<!-- </com.google.android.material.tabs.TabLayout>-->
<!-- <androidx.viewpager2.widget.ViewPager2-->
<!-- android:id="@+id/view_pager"-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="wrap_content"-->
<!-- app:layout_constraintBottom_toBottomOf="parent"-->
<!-- app:layout_constraintEnd_toEndOf="parent"-->
<!-- app:layout_constraintHorizontal_bias="0.0"-->
<!-- app:layout_constraintStart_toStartOf="parent"-->
<!-- app:layout_constraintTop_toBottomOf="@id/tab_layout"-->
<!-- app:layout_constraintVertical_bias="1.0" />-->
<!-- </LinearLayout>-->
<ImageView
android:id="@+id/dgs_back"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_marginTop="@dimen/margin_screen"
android:layout_marginStart="@dimen/margin_screen"
android:src="@drawable/back_button"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.google.android.material.card.MaterialCardView
android:id="@+id/ds_mci"
android:layout_marginHorizontal="@dimen/margin_screen"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/margin_component"
app:cardCornerRadius="0dp"
app:cardPreventCornerOverlap="false"
app:cardUseCompatPadding="false"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/dgs_back">
<ImageView
android:id="@+id/iv_img_tea"
android:layout_width="match_parent"
android:layout_height="200dp"
android:scaleType="fitXY"
tools:src="@drawable/dgs_wereng_img" />
</com.google.android.material.card.MaterialCardView>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/ds_cont_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/margin_component"
android:layout_marginHorizontal="@dimen/margin_screen"
android:background="@color/primaryGreen"
android:paddingHorizontal="5dp"
android:paddingVertical="10dp"
app:layout_constraintTop_toBottomOf="@id/ds_mci">
<TextView
android:id="@+id/tv_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textAlignment="center"
android:textColor="@color/white"
android:textSize="24sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="Brown Spots" />
</androidx.constraintlayout.widget.ConstraintLayout>
<TextView
android:id="@+id/tv_confidence_desc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/margin_component"
android:layout_marginHorizontal="@dimen/margin_screen"
android:text="Confidence: "
android:textColor="@color/primaryGreen"
android:textSize="18sp"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/ds_cont_title" />
<TextView
android:id="@+id/tv_confidence"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="80%"
android:textColor="@color/primaryGreen"
android:textSize="18sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="@id/tv_confidence_desc"
app:layout_constraintStart_toEndOf="@+id/tv_confidence_desc"
app:layout_constraintTop_toTopOf="@id/tv_confidence_desc" />
<com.google.android.material.tabs.TabLayout
android:id="@+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/margin_component"
android:layout_marginHorizontal="@dimen/margin_screen"
android:background="@color/white"
app:layout_constraintTop_toBottomOf="@+id/tv_confidence_desc"
app:tabIndicatorColor="@color/primaryGreen"
app:tabSelectedTextColor="@color/primaryGreen">
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</com.google.android.material.tabs.TabLayout>
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/view_pager"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="@dimen/margin_screen"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tab_layout"
app:layout_constraintVertical_bias="1.0" />
<Button
android:id="@+id/btn_hs_gallery"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/button_no_radius"
android:fontFamily="@font/poppins_medium"
android:gravity="center"
android:layout_marginHorizontal="@dimen/margin_screen"
android:layout_marginBottom="@dimen/margin_screen"
android:paddingVertical="14dp"
android:text="Informasi Selengkapnya"
android:textColor="@color/white"
android:textSize="16sp"
android:textStyle="bold"
app:icon="@drawable/diagnose_information_ic"
app:iconGravity="textStart"
app:iconTint="@color/white"
app:iconSize="25dp"
app:iconPadding="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,151 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/main"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context=".ui.listDisease.DiseaseDetailActivity">
<ImageView
android:id="@+id/dgs_back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/margin_screen"
android:layout_marginStart="@dimen/margin_screen"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:src="@drawable/back_button"/>
<ScrollView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginTop="@dimen/margin_component"
app:layout_constraintTop_toBottomOf="@id/dgs_back"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/image_disease"
android:layout_width="match_parent"
android:layout_height="185dp"
android:layout_gravity="center"
android:layout_marginHorizontal="@dimen/margin_screen"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:src="@drawable/dgs_wereng_img"/>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/dd_cont_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/margin_component"
android:layout_marginHorizontal="@dimen/margin_screen"
android:background="@color/primaryGreen"
android:paddingHorizontal="5dp"
android:paddingVertical="10dp"
app:layout_constraintTop_toBottomOf="@id/image_disease">
<TextView
android:id="@+id/title_disease"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textAlignment="center"
android:textColor="@color/white"
android:textSize="24sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="Brown Spots" />
</androidx.constraintlayout.widget.ConstraintLayout>
<TextView
android:id="@+id/tv_desc_disease"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:text="Penjelasan Penyakit"
android:textSize="18sp"
android:textStyle="bold"
android:layout_marginHorizontal="@dimen/margin_screen"
android:layout_marginTop="@dimen/margin_component"
android:textColor="@color/primaryGreen"
app:layout_constraintTop_toBottomOf="@+id/dd_cont_title"/>
<TextView
android:id="@+id/desc_disease"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:justificationMode="inter_word"
tools:text="deskripsi penyakit"
android:textSize="16sp"
android:layout_marginHorizontal="@dimen/margin_screen"
app:layout_constraintTop_toBottomOf="@id/tv_desc_disease"
app:layout_constraintStart_toStartOf="parent"/>
<TextView
android:id="@+id/tv_title_prevention"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:text="Pencegahan"
android:textSize="18sp"
android:textStyle="bold"
android:layout_marginHorizontal="@dimen/margin_screen"
android:layout_marginTop="@dimen/margin_component"
android:textColor="@color/primaryGreen"
app:layout_constraintTop_toBottomOf="@+id/desc_disease"
app:layout_constraintStart_toStartOf="parent"/>
<TextView
android:id="@+id/desc_prevention"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:text="deskripsi pencegahan"
android:justificationMode="inter_word"
android:textSize="16sp"
android:layout_marginHorizontal="@dimen/margin_screen"
app:layout_constraintTop_toBottomOf="@id/tv_title_prevention"
app:layout_constraintStart_toStartOf="parent" />
<TextView
android:id="@+id/tv_title_recommended"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:text="Rekomendasi Penanganan"
android:textSize="18sp"
android:textStyle="bold"
android:layout_marginHorizontal="@dimen/margin_screen"
android:layout_marginTop="@dimen/margin_component"
android:textColor="@color/primaryGreen"
app:layout_constraintTop_toBottomOf="@+id/desc_prevention"
app:layout_constraintStart_toStartOf="parent"/>
<TextView
android:id="@+id/desc_recommended"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:text="desc Penanganan"
android:justificationMode="inter_word"
android:textSize="16sp"
android:layout_marginHorizontal="@dimen/margin_screen"
app:layout_constraintTop_toBottomOf="@id/tv_title_recommended"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>
<ProgressBar
android:id="@+id/progress_result"
android:layout_gravity="center"
android:visibility="invisible"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,93 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.errorDetection.ErrorDetectionActivity">
<ImageView
android:id="@+id/bt_error_back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/back_button"
android:layout_marginTop="@dimen/margin_screen"
android:layout_marginStart="@dimen/margin_screen"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/imageView"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_marginTop="@dimen/margin_component"
android:src="@drawable/error_warning_ic_green"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/ds_cont_title" />
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/ds_cont_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/margin_component"
android:layout_marginHorizontal="@dimen/margin_screen"
android:background="@color/primaryGreen"
android:paddingHorizontal="5dp"
android:paddingVertical="10dp"
app:layout_constraintTop_toBottomOf="@id/bt_error_back">
<TextView
android:id="@+id/tv_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textAlignment="center"
android:textColor="@color/white"
android:textSize="24sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="Kesalahan Deteksi" />
</androidx.constraintlayout.widget.ConstraintLayout>
<TextView
android:id="@+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/margin_component"
android:layout_marginHorizontal="@dimen/margin_screen"
android:justificationMode="inter_word"
android:text="Lorem ipsum, dolor sit amet consectetur adipisicing elit. Impedit eos illo cupiditate, placeat odit dicta similique expedita enim in suscipit, tenetur hic aliquam ad fugiat quaerat."
android:textColor="@color/black"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/imageView" />
<Button
android:id="@+id/es_btn_redo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/button_no_radius"
android:fontFamily="@font/poppins_medium"
android:gravity="center"
android:layout_marginHorizontal="@dimen/margin_screen"
android:layout_marginBottom="@dimen/margin_screen"
android:paddingVertical="14dp"
android:text="Ambil Gambar Ulang"
android:textColor="@color/white"
android:textSize="16sp"
android:textStyle="bold"
app:icon="@drawable/diagnose_information_ic"
app:iconGravity="textStart"
app:iconTint="@color/white"
app:iconSize="25dp"
app:iconPadding="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
tools:context=".ui.MainActivity">
<FrameLayout
android:id="@+id/frame_layout"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="@+id/ma_cv_nav_menu_bg"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
</FrameLayout>
<androidx.cardview.widget.CardView
android:id="@+id/ma_cv_nav_menu_bg"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
app:cardCornerRadius="8dp"
app:cardElevation="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottomNavigationView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:backgroundTint="@color/white"
app:menu="@menu/bottom_nav"/>
</androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
tools:context=".ui.SplashScreenActivity">
<de.hdodenhof.circleimageview.CircleImageView
android:id="@+id/circleImageView"
android:layout_width="180dp"
android:layout_height="180dp"
android:src="@drawable/splash_screen_ic"
app:civ_border_color="@color/grayBackground"
app:civ_border_width="2dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:layout_width="55dp"
android:layout_height="55dp"
android:layout_marginBottom="24dp"
android:src="@drawable/upn_logo"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,62 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.detection.DetectionFragment">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="25dp"
android:paddingBottom="20dp"
android:paddingHorizontal="20dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/dd_cont_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/margin_screen"
android:background="@color/primaryGreen"
android:paddingHorizontal="5dp"
android:paddingVertical="10dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="@+id/title_disease"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:textColor="@color/white"
android:textSize="24sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:text="Riwayat Deteksi" />
</androidx.constraintlayout.widget.ConstraintLayout>
<LinearLayout
android:id="@+id/ll_ds"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingTop="@dimen/margin_component"
app:layout_constraintTop_toBottomOf="@id/dd_cont_title">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_result_detection"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:listitem="@layout/item_result" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.diagnose.DiagnoseFragment">
<!-- TODO: Update blank fragment layout -->
<TextView
android:id="@+id/tv_diagnose"
style="@style/FragmentDiagnoseDescription"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Penyakit Algal Leaf disebabkan oleh alga hijau Cephaleuros virescens yang menyerang daun teh, menyebabkan bintik-bintik hijau kusam atau oranye pada daun." />
</FrameLayout>

View File

@ -0,0 +1,436 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.home.HomeFragment">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="25dp"
android:paddingBottom="20dp"
android:paddingHorizontal="20dp">
<com.google.android.material.card.MaterialCardView
android:id="@+id/cv_headline_top"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardCornerRadius="0dp"
app:cardBackgroundColor="@color/white"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:strokeColor="@color/greenGeneral">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/tv_headline_top"
android:layout_width="250dp"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/margin_component"
android:text="SEMBUHKAN TANAMAN SAWIT ANDA!"
android:textColor="@color/greenGeneral"
android:textSize="18sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:layout_width="78dp"
android:layout_height="78dp"
android:scaleType="fitXY"
android:src="@drawable/hs_top_image"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>
<!-- Jangan lupa tambahin constraint -->
<com.google.android.material.card.MaterialCardView
android:id="@+id/cv_tutorial"
android:layout_width="150dp"
android:layout_height="200dp"
android:layout_marginTop="@dimen/margin_component"
android:backgroundTint="@color/white"
app:cardCornerRadius="0dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/cv_headline_top"
app:strokeColor="@color/greenGeneral">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="@dimen/margin_component">
<ImageView
android:id="@+id/iv_hs_phone_take_pic"
android:layout_width="50dp"
android:layout_height="50dp"
android:src="@drawable/hs_phone_take_pic_img"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_hs_phone_take_pic"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:text="Ambil Gambar"
android:textColor="@color/greenGeneral"
android:textSize="14sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/iv_hs_phone_take_pic" />
<ImageView
android:id="@+id/iv_hs_down_arrow"
android:layout_width="15dp"
android:layout_height="15dp"
android:layout_marginTop="5dp"
android:rotation="270"
android:src="@drawable/back_button"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_hs_phone_take_pic" />
<ImageView
android:id="@+id/iv_hs_phone_analyze"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_marginTop="5dp"
android:src="@drawable/hs_phone_analyze_img"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/iv_hs_down_arrow" />
<TextView
android:id="@+id/tv_hs_phone_analyze"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Ambil Gambar"
android:textColor="@color/greenGeneral"
android:textSize="14sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/iv_hs_phone_analyze" />
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>
<com.google.android.material.card.MaterialCardView
android:id="@+id/btn_hs_camera"
android:layout_width="150dp"
android:layout_height="90dp"
android:backgroundTint="@color/white"
app:cardCornerRadius="0dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/cv_tutorial"
app:strokeColor="@color/greenGeneral">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="@dimen/margin_component">
<ImageView
android:id="@+id/tv_camera_img"
android:layout_width="30dp"
android:layout_height="30dp"
android:scaleType="center"
android:src="@drawable/hs_camera_img"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Gunakan Kamera"
android:textColor="@color/greenGeneral"
android:textSize="14sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_camera_img" />
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>
<com.google.android.material.card.MaterialCardView
android:id="@+id/btn_hs_gallery"
android:layout_width="150dp"
android:layout_height="90dp"
android:backgroundTint="@color/greenGeneral"
app:cardCornerRadius="0dp"
app:layout_constraintBottom_toBottomOf="@id/cv_tutorial"
app:layout_constraintEnd_toEndOf="parent"
app:strokeColor="@color/greenGeneral">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="@dimen/margin_component">
<ImageView
android:id="@+id/tv_gallery_img"
android:layout_width="30dp"
android:layout_height="30dp"
android:scaleType="center"
android:src="@drawable/hs_gallery_img"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Ambil Dari Galeri"
android:textColor="@color/white"
android:textSize="14sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_gallery_img" />
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>
<!-- <Button-->
<!-- android:id="@+id/btn_hs_camera"-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="50dp"-->
<!-- android:layout_marginTop="20dp"-->
<!-- android:backgroundTint="@color/primaryGreen"-->
<!-- android:text="Gunakan Kamera"-->
<!-- android:textColor="@color/black"-->
<!-- android:textSize="16sp"-->
<!-- android:textStyle="bold"-->
<!-- app:layout_constraintEnd_toEndOf="parent"-->
<!-- app:layout_constraintStart_toStartOf="parent"-->
<!-- app:layout_constraintTop_toBottomOf="@+id/cv_headline" />-->
<!-- <Button-->
<!-- android:id="@+id/btn_hs_gallery"-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:layout_marginTop="10dp"-->
<!-- android:backgroundTint="@color/primaryGreen"-->
<!-- android:text="Ambil dari Galeri"-->
<!-- android:textColor="@color/white"-->
<!-- android:textSize="16sp"-->
<!-- app:layout_constraintEnd_toEndOf="parent"-->
<!-- app:layout_constraintStart_toStartOf="parent"-->
<!-- app:layout_constraintTop_toBottomOf="@+id/bt_use_camera" />-->
<com.google.android.material.card.MaterialCardView
android:id="@+id/cv_hs_detail_explanation_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/margin_component"
app:cardCornerRadius="0dp"
app:cardBackgroundColor="@color/white"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/cv_tutorial"
app:strokeColor="@color/greenGeneral">
<TextView
android:id="@+id/tv_headline_sickness_explanation"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/margin_component"
android:text="Baca Tentang Penyakit Brown Spots Pada Daun Tanaman Sawit"
android:textColor="@color/greenGeneral"
android:textSize="16sp"
android:textStyle="bold" />
</com.google.android.material.card.MaterialCardView>
<com.google.android.material.card.MaterialCardView
android:id="@+id/cv_hs_detail_explanation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:strokeColor="@color/greenGeneral"
android:backgroundTint="@color/greenGeneral"
android:layout_marginTop="@dimen/margin_component"
app:cardCornerRadius="0dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/cv_hs_detail_explanation_title">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/iv_hs_detail_explanation"
android:layout_width="120dp"
android:layout_height="100dp"
android:scaleType="center"
android:src="@drawable/hs_detail_explanation_img"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent" />
<com.google.android.material.card.MaterialCardView
android:id="@+id/fl_home_screen_list_disease"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:cardCornerRadius="0dp"
app:strokeColor="@color/white"
android:backgroundTint="@color/greenGeneral"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/iv_hs_detail_explanation">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:textSize="14sp"
android:textStyle="bold"
android:text="Klik Di sini"
android:textColor="@color/white" />
</com.google.android.material.card.MaterialCardView>
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>
<com.google.android.material.card.MaterialCardView
android:id="@+id/cv_hs_history_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/margin_component"
app:cardCornerRadius="0dp"
app:cardBackgroundColor="@color/white"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/cv_hs_detail_explanation"
app:strokeColor="@color/greenGeneral">
<TextView
android:id="@+id/tv_history_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/margin_component"
android:layout_gravity="center"
android:text="Hasil Analisis Terakhir"
android:textColor="@color/greenGeneral"
android:textSize="16sp"
android:textStyle="bold" />
</com.google.android.material.card.MaterialCardView>
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/cd_home_screen_analyze"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:visibility="gone"
app:cardCornerRadius="0dp"
app:strokeColor="@color/greenGeneral"
app:strokeWidth="1dp"
android:layout_marginTop="@dimen/margin_component"
app:layout_constraintTop_toBottomOf="@+id/cv_hs_history_title"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/rl_home_screen_card_analyze"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"
android:gravity="center"
android:paddingHorizontal="25dp"
android:paddingVertical="20dp">
<com.google.android.material.card.MaterialCardView
android:id="@+id/card_result_diagnosis"
android:layout_width="75dp"
android:layout_height="75dp"
app:cardCornerRadius="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:id="@+id/img_result_diagnosis"
android:layout_width="75dp"
android:layout_height="75dp"
android:scaleType="fitXY"
android:src="@drawable/hs_wereng_img" />
</com.google.android.material.card.MaterialCardView>
<TextView
android:id="@+id/date_result_diagnosis"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="11 November 2023"
android:layout_marginStart="@dimen/margin_component"
android:textColor="@color/grayFont"
android:textSize="12sp"
android:textStyle="bold"
app:layout_constraintStart_toEndOf="@id/card_result_diagnosis"
app:layout_constraintTop_toTopOf="@id/card_result_diagnosis" />
<TextView
android:id="@+id/title_result_diagnosis"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/date_result_diagnosis"
android:text="Algal Leaf"
android:textColor="@color/greenGeneral"
android:textSize="20sp"
android:textStyle="bold"
app:layout_constraintTop_toBottomOf="@id/date_result_diagnosis"
app:layout_constraintStart_toStartOf="@id/date_result_diagnosis"/>
<TextView
android:id="@+id/confidence_result_diagnosis"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/title_result_diagnosis"
android:text="Confidence: "
android:textColor="@color/grayFont"
android:textSize="12sp"
android:textStyle="bold"
app:layout_constraintTop_toBottomOf="@id/title_result_diagnosis"
app:layout_constraintStart_toStartOf="@id/title_result_diagnosis"/>
<ImageView
android:id="@+id/img_arrow2"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_below="@id/date_result_diagnosis"
android:layout_alignParentEnd="true"
android:contentDescription="TODO"
android:scaleType="fitXY"
android:rotation="180"
android:src="@drawable/back_button"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>
<ProgressBar
android:id="@+id/progress_result"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:visibility="invisible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.diagnose.RecommendationFragment">
<!-- TODO: Update blank fragment layout -->
<TextView
android:id="@+id/tv_recommendation"
style="@style/FragmentRecommendationDescription"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Pangkas dan buang daun yang terinfeksi, pastikan tanaman mendapatkan sirkulasi udara yang baik, dan gunakan fungisida berbasis tembaga jika diperlukan." />
</FrameLayout>

View File

@ -0,0 +1,88 @@
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/cd_home_screen_analyze"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
app:cardCornerRadius="0dp"
app:strokeColor="@color/greenGeneral"
app:strokeWidth="1dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/rl_home_screen_card_analyze"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"
android:gravity="center"
android:paddingHorizontal="25dp"
android:paddingVertical="20dp">
<com.google.android.material.card.MaterialCardView
android:id="@+id/card_result_diagnosis"
android:layout_width="75dp"
android:layout_height="75dp"
app:cardCornerRadius="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:id="@+id/img_result_diagnosis"
android:layout_width="75dp"
android:layout_height="75dp"
android:scaleType="fitXY"
android:src="@drawable/hs_wereng_img" />
</com.google.android.material.card.MaterialCardView>
<TextView
android:id="@+id/date_result_diagnosis"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="11 November 2023"
android:layout_marginStart="@dimen/margin_component"
android:textColor="@color/grayFont"
android:textSize="12sp"
android:textStyle="bold"
app:layout_constraintStart_toEndOf="@id/card_result_diagnosis"
app:layout_constraintTop_toTopOf="@id/card_result_diagnosis" />
<TextView
android:id="@+id/title_result_diagnosis"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/date_result_diagnosis"
android:text="Algal Leaf"
android:textColor="@color/greenGeneral"
android:textSize="20sp"
android:textStyle="bold"
app:layout_constraintTop_toBottomOf="@id/date_result_diagnosis"
app:layout_constraintStart_toStartOf="@id/date_result_diagnosis"/>
<TextView
android:id="@+id/confidence_result_diagnosis"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/title_result_diagnosis"
android:text="Confidence: "
android:textColor="@color/grayFont"
android:textSize="12sp"
android:textStyle="bold"
app:layout_constraintTop_toBottomOf="@id/title_result_diagnosis"
app:layout_constraintStart_toStartOf="@id/title_result_diagnosis"/>
<ImageView
android:id="@+id/img_arrow2"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_below="@id/date_result_diagnosis"
android:layout_alignParentEnd="true"
android:contentDescription="TODO"
android:scaleType="fitXY"
android:rotation="180"
android:src="@drawable/back_button"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/home"
android:icon="@drawable/hs_home_img"
android:title="Beranda" />
<item
android:id="@+id/detection"
android:icon="@drawable/hs_trace_black_img"
android:title="Deteksi" />
</menu>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 982 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="FragmentDiagnoseDescription">
<item name="fontFamily">@font/poppins_medium</item>
<item name="android:justificationMode">inter_word</item>
<item name="android:textSize">16sp</item>
<item name="android:layout_marginBottom">25dp</item>
</style>
<style name="FragmentRecommendationDescription">
<item name="fontFamily">@font/poppins_medium</item>
<item name="android:justificationMode">inter_word</item>
<item name="android:textSize">16sp</item>
<item name="android:layout_marginBottom">25dp</item>
</style>
</resources>

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="black">#FF000000</color>
<color name="white">#FFFFFF</color>
<color name="grayBackground">#EEEEEE</color>
<color name="grayBackgroundCard">#F1F2F2</color>
<color name="grayFont">#AEAEAE</color>
<color name="greenGeneral">#d2eac1</color>
<color name="primaryGreen">#d2eac1</color>
</resources>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="padding_horizontal">30dp</dimen>
<dimen name="padding_vertical_top">60dp</dimen>
<dimen name="margin_screen">20dp</dimen>
<dimen name="margin_component">15dp</dimen>
</resources>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="Theme.MyApp.MySplash" parent="Theme.SplashScreen">
<item name="windowSplashScreenBackground">@color/white</item>
<item name="windowSplashScreenAnimatedIcon">@drawable/splash_screen_ic</item>
</style>
</resources>

View File

@ -0,0 +1,7 @@
<resources>
<string name="app_name">PalmGuard</string>
<!-- TODO: Remove or change this placeholder text -->
<string name="hello_blank_fragment">Hello blank fragment</string>
<string name="ig_teaguard">@teaguardteam</string>
</resources>

View File

@ -0,0 +1,115 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Base.Theme.TeaGuard" parent="Theme.Material3.DayNight.NoActionBar">
<!-- Customize your light theme here. -->
<item name="colorPrimary">@color/primaryGreen</item>
<item name="android:windowBackground">@color/white</item>
<item name="bottomNavigationStyle">@style/Widget.App.BottomNavigationView</item>
<item name="android:windowIsTranslucent">true</item>
</style>
<style name="Widget.App.BottomNavigationView" parent="Widget.MaterialComponents.BottomNavigationView.Colored">
<item name="materialThemeOverlay">@style/ThemeOverlay.App.BottomNavigationView</item>
</style>
<style name="ThemeOverlay.App.BottomNavigationView" parent="">
<item name="colorOnPrimary">@color/black</item>
</style>
<style name="NavigationCardView" parent="@style/Widget.MaterialComponents.CardView">
<item name="shapeAppearanceOverlay">@style/ShapeAppearanceOverlay.MaterialCardView.Cut</item>
<item name="strokeWidth">0dp</item>
</style>
<style name="ButtonGeneral" parent="@style/ShapeAppearanceOverlay.Material3.Corner.Bottom">
<item name="shapeAppearanceOverlay">@style/ShapeAppearanceOverlay.Material3.CustomCut</item>
</style>
<style name="ShapeAppearanceOverlay.Material3.CustomCut" parent="">
<item name="cornerSize">8dp</item>
</style>
<style name="ShapeAppearanceOverlay.MaterialCardView.Cut" parent="">
<item name="cornerSizeTopRight">8dp</item>
<item name="cornerSizeTopLeft">8dp</item>
<item name="cornerSizeBottomRight">0dp</item>
<item name="cornerSizeBottomLeft">0dp</item>
</style>
<!-- DIAGNOSE ACTIVITY START -->
<style name="ActivityDiagnoseDiseaseName">
<item name="fontFamily">@font/poppins_regular</item>
<item name="android:textAlignment">center</item>
<item name="android:textSize">24sp</item>
<item name="android:textStyle">bold</item>
<item name="android:textColor">@color/black</item>
<item name="android:layout_marginBottom">25dp</item>
</style>
<!-- DIAGNOSE ACTIVITY END -->
<!-- DETECTION FRAGMENT START -->
<style name="FragmentDetectionTitle">
<item name="fontFamily">@font/poppins_bold</item>
<item name="android:textAlignment">center</item>
<item name="android:textSize">16sp</item>
<item name="android:textColor">@color/black</item>
<item name="android:layout_marginBottom">25dp</item>
</style>
<style name="FragmentDetectionCardDate">
<item name="fontFamily">@font/poppins_regular</item>
<item name="android:textColor">@color/grayFont</item>
<item name="android:textSize">14sp</item>
</style>
<style name="FragmentDetectionCardDiseaseTitle">
<item name="fontFamily">@font/poppins_regular</item>
<item name="android:textColor">@color/primaryGreen</item>
<item name="android:textSize">14sp</item>
<item name="android:textStyle">bold</item>
</style>
<!-- DETECTION FRAGMENT END -->
<!-- HOME FRAGMENT START -->
<style name="FragmentHomeTitle">
<item name="fontFamily">@font/poppins_regular</item>
<item name="android:layout_marginBottom">24dp</item>
<item name="android:textSize">18sp</item>
<item name="android:textColor">@color/black</item>
<item name="android:textStyle">bold</item>
</style>
<style name="FragmentHomeCardTutorial">
<item name="fontFamily">@font/poppins_regular</item>
<item name="android:textSize">14sp</item>
<item name="android:textAlignment">center</item>
</style>
<style name="FragmentHomeAnalyzeTitle">
<item name="fontFamily">@font/poppins_regular</item>
<item name="android:layout_marginTop">14dp</item>
<item name="android:layout_marginBottom">14dp</item>
<item name="android:textSize">14sp</item>
<item name="android:textColor">@color/black</item>
<item name="android:textStyle">bold</item>
</style>
<style name="FragmentHomeCardDate">
<item name="fontFamily">@font/poppins_regular</item>
<item name="android:textColor">@color/grayFont</item>
<item name="android:textSize">14sp</item>
</style>
<style name="FragmentHomeCardDiseaseTitle">
<item name="fontFamily">@font/poppins_regular</item>
<item name="android:textColor">@color/primaryGreen</item>
<item name="android:textSize">14sp</item>
<item name="android:textStyle">bold</item>
</style>
<!-- HOME FRAGMENT END -->
<style name="Theme.TeaGuard" parent="Base.Theme.TeaGuard" />
</resources>

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?><!--
Sample backup rules file; uncomment and customize as necessary.
See https://developer.android.com/guide/topics/data/autobackup
for details.
Note: This file is ignored for devices older that API 31
See https://developer.android.com/about/versions/12/backup-restore
-->
<full-backup-content>
<!--
<include domain="sharedpref" path="."/>
<exclude domain="sharedpref" path="device.xml"/>
-->
</full-backup-content>

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?><!--
Sample data extraction rules file; uncomment and customize as necessary.
See https://developer.android.com/about/versions/12/backup-restore#xml-changes
for details.
-->
<data-extraction-rules>
<cloud-backup>
<!-- TODO: Use <include> and <exclude> to control what is backed up.
<include .../>
<exclude .../>
-->
</cloud-backup>
<!--
<device-transfer>
<include .../>
<exclude .../>
</device-transfer>
-->
</data-extraction-rules>

View File

@ -0,0 +1,17 @@
package com.example.palmguardapp
import org.junit.Test
import org.junit.Assert.*
/**
* Example local unit test, which will execute on the development machine (host).
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
class ExampleUnitTest {
@Test
fun addition_isCorrect() {
assertEquals(4, 2 + 2)
}
}

Some files were not shown because too many files have changed in this diff Show More