diff --git a/app/build.gradle b/app/build.gradle
index 1d81506..c64892a 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -62,7 +62,7 @@ dependencies {
//레트로핏 서버
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
- implementation 'com.google.android.gms:play-services-location:19.0.1'
+ implementation 'com.google.android.gms:play-services-location:21.0.1'
//비동기
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.0"
@@ -79,4 +79,7 @@ dependencies {
//날씨
implementation 'com.loopj.android:android-async-http:1.4.11'
+
+ // Calendar
+ implementation 'com.github.prolificinteractive:material-calendarview:1.4.3'
}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 78937b8..7052703 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -5,6 +5,13 @@
+
+
+
+
+
+
+
@@ -12,29 +19,28 @@
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
- android:icon="@mipmap/ic_launcher"
+ android:icon="@mipmap/ic_launcher1"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/Theme.MyApplication"
android:usesCleartextTraffic="true"
tools:targetApi="31">
-
-
-
+
diff --git a/app/src/main/ic_launcher1-playstore.png b/app/src/main/ic_launcher1-playstore.png
new file mode 100644
index 0000000..543f1f0
Binary files /dev/null and b/app/src/main/ic_launcher1-playstore.png differ
diff --git a/app/src/main/java/com/example/farmmate1/ApiService.kt b/app/src/main/java/com/example/farmmate1/ApiService.kt
index c2a3e8a..dd4c800 100644
--- a/app/src/main/java/com/example/farmmate1/ApiService.kt
+++ b/app/src/main/java/com/example/farmmate1/ApiService.kt
@@ -1,36 +1,141 @@
package com.example.farmmate1
-import com.example.farmmate1.data.TodoItem
-import com.example.farmmate1.network.ToDoListInterface
import retrofit2.Call
-import retrofit2.Response
-import retrofit2.Retrofit
-import retrofit2.converter.gson.GsonConverterFactory
import retrofit2.http.*
+import okhttp3.MultipartBody
+import okhttp3.RequestBody
+import com.example.farmmate1.api.SearchResponse
interface ApiService {
- @GET("plants")
- fun getPlantList(): Call>
- // 서버에서 식물 정보를 가져오는 GET 요청을 정의
- @POST("plants")
+ // 기기 등록
+ @POST("device")
@Headers("Content-Type: application/json")
- fun createPlant(@Body plant: Plant): Call
+ fun saveDeviceInfo(@Body deviceInfo: DeviceInfo): Call
- @GET("plants")
- fun getPlant(): Call
+ //-------------------------------------------------------------------------------
+ // 식물 전체 GET 요청
+ @GET("plant/device/{deviceId}")
+ fun getPlantList(@Path("deviceId") deviceId: String): Call>
+ // 서버에서 식물 정보를 가져오는 GET 요청을 정의
- @GET("history")
- fun getHistoryList(): Call>
- // 서버에서 진단 결과를 가져오는 GET 요청을 정의
+ // 식물 POST 요청
+ @Multipart
+ @POST("plant")
+ fun postPlant(
+ @PartMap data: HashMap,
+ @Part image: MultipartBody.Part? // 이미지 파일을 MultipartBody.Part로 전송
+ ): Call
- @POST("history")
- @Headers("Content-Type: application/json")
- fun saveResult(@Body history: History): Call
+ // 식물 개별 GET 요청
+ @GET("plant/{plantUuid}")
+ fun getPlant(@Path("plantUuid") plantUuid: String?): Call
+
+ // 식물 개별 PUT 요청
+ @Multipart
+ @PUT("plant/{plantUuid}")
+ fun editPlant(
+ @Path("plantUuid") plantUuid: String,
+ @PartMap data: HashMap,
+ @Part image: MultipartBody.Part? // 이미지 파일을 MultipartBody.Part로 전송
+ ): Call
+
+ // 북마크 POST 요청
+ @POST("plant/{plantUuid}/bookmark")
+ fun postBookmark(@Path("plantUuid")plantUuid: String): Call
+
+ // 식물 DELETE 요청
+ @DELETE("plant/{plantUuid}")
+ fun deletePlant(@Path("plantUuid")plantUuid: String?): Call
+
+ // 북마크 GET 요청
+ @GET("plant/device/{deviceId}/bookmark")
+ fun getBookmark(@Path("deviceId")deviceId: String): Call>
+
+ //-------------------------------------------------------------------------------
+
+ // 일지 post 요청
+ @Multipart
+ @POST("diary")
+ fun postDiary(
+ //@Query("plant_uuid") plantUuid: String?,
+ //@Path("plantUuid") plantUuid: String,
+ @PartMap data: HashMap,
+ @Part image: MultipartBody.Part? // 이미지 파일을 MultipartBody.Part로 전송
+ ): Call
+
+ // 일지 개별 GET 요청
+ @GET("diary/{diaryUuid}")
+ fun getDiary(@Path("diaryUuid") diaryUuid: String?): Call
+
+ // 모든 일지 GET 요청
+ @GET("diary")
+ //fun getDiaryList(@Query("plant.plant_name") plantName: String?): Call>
+ fun getDiaryList(): Call>
+
+ // 일지 개별 PUT 요청
+ @Multipart
+ @PUT("diary/{diaryUuid}")
+ fun editDiary(
+ @Path("diaryUuid") diaryUuid: String,
+ @PartMap data: HashMap,
+ @Part image: MultipartBody.Part? // 이미지 파일을 MultipartBody.Part로 전송
+ ): Call
+
+ // 이미지를 포함하지 않은 PUT 요청
+ @Multipart
+ @PUT("diary/{diaryUuid}")
+ fun editDiaryWithoutImage(
+ @Path("diaryUuid") diaryUuid: String,
+ @PartMap data: HashMap,
+ ): Call
+
+
+ // 일지 개별 DELETE 요청
+ @DELETE("diary/{diaryUuid}")
+ fun deleteDiary(@Path("diaryUuid")diaryUuid: String?): Call
+
+ //-------------------------------------------------------------------------------
+
+ // 진단 POST 요청
+ @Multipart
+ @POST("plant/diagnose")
+ fun postDiagnosis(
+ @Part("plantType") plantType: RequestBody,
+ @Part image: MultipartBody.Part
+ ): Call
+
+ // 진단 결과 저장 POST 요청
+ @POST("plant/diagnose/result")
+ fun postDiagnosisSave(@Body request: DiagnosisSaveRequest): Call
+
+ // 식물별 진단 결과 GET 요청
+ @GET("plant/diagnose/result/plant/{plantUuid}")
+ fun getSavedResult(@Path("plantUuid") plantUuid: String?): Call>
+
+ // 개별 진단 결과 GET 요청
+ @GET("plant/diagnose/result/{plantDiseaseUuid}")
+ fun getResult(@Path("plantDiseaseUuid") plantDiseaseUuid: String?): Call
+
+//-------------------------------------------------------------------------------
- @GET("history")
- fun getHistory(): Call
+ @GET("service")
+ fun searchDiseases(
+ @Query("apiKey") apiKey: String,
+ @Query("serviceCode") serviceCode: String,
+ @Query("serviceType") serviceType: String,
+ @Query("cropName") cropName: String,
+ @Query("sickNameKor") sickNameKor: String,
+ @Query("displayCount") displayCount: Int,
+ @Query("startPoint") startPoint: Int
+ ): Call
+ @GET("service")
+ fun getDetail(
+ @Query("apiKey") apiKey: String,
+ @Query("serviceCode") serviceCode: String,
+ @Query("sickKey") sickKey: String
+ ): Call
}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/farmmate1/BookmarkAdapter.kt b/app/src/main/java/com/example/farmmate1/BookmarkAdapter.kt
new file mode 100644
index 0000000..a7e823b
--- /dev/null
+++ b/app/src/main/java/com/example/farmmate1/BookmarkAdapter.kt
@@ -0,0 +1,74 @@
+package com.example.farmmate1
+
+import android.content.Context
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.BaseAdapter
+import android.widget.ImageView
+import android.widget.TextView
+import androidx.appcompat.app.AppCompatActivity
+
+class BookmarkAdapter(private val context: Context, private val bookmarkedPlants: List) : BaseAdapter() {
+
+ override fun getCount(): Int {
+ return bookmarkedPlants.size
+ }
+
+ override fun getItem(position: Int): Any {
+ return bookmarkedPlants[position]
+ }
+
+ override fun getItemId(position: Int): Long {
+ return position.toLong()
+ }
+
+ override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
+ val view: View = convertView ?: LayoutInflater.from(context).inflate(R.layout.list_item_bookmark, parent, false)
+
+ val plantNameTextView: TextView = view.findViewById(R.id.bookmark_list_item_name)
+ val plantTypeTextView: TextView = view.findViewById(R.id.bookmark_list_item_type)
+ val firstPlantingDateTextView: TextView = view.findViewById(R.id.bookmark_list_item_startdate)
+ val bookmarkImg = view.findViewById(R.id.bookmark_list_item_profile)
+
+ val plant = bookmarkedPlants[position]
+ plantNameTextView.text = plant.plant_name
+ plantTypeTextView.text = plant.plant_type
+ firstPlantingDateTextView.text = plant.first_planting_date
+
+ val imageUrl = plant.image_url
+ ImageLoaderTask(bookmarkImg).execute(imageUrl)
+
+ view.setOnClickListener {
+ // 해당 항목의 plant_uuid 가져오기
+ val plantUuid = plant.plant_uuid
+
+ // 다음 프래그먼트로 전환하기 위해 번들에 데이터 추가
+ val bundle = Bundle()
+ bundle.putString("plantUuid", plantUuid)
+
+ val plantInfoFragment = PlantInfoFragment()
+ plantInfoFragment.arguments = bundle
+//
+ // 다음 프래그먼트로 이동하고 번들에 담긴 데이터 전달
+ val transaction = (context as AppCompatActivity).supportFragmentManager.beginTransaction()
+ transaction.replace(R.id.main_fl, plantInfoFragment)
+ transaction.addToBackStack(null)
+ transaction.commit()
+
+// parentFragmentManager
+// requireActivity().supportFragmentManager
+// .beginTransaction()
+// .replace(R.id.main_fl, plantInfoFragment)
+// .commit()
+
+// val transaction = parentFragmentManager
+// .beginTransaction()
+// .replace(R.id.main_fl, diaryAddFragment)
+// transaction.commit()
+ }
+
+ return view
+ }
+}
diff --git a/app/src/main/java/com/example/farmmate1/CustomMultipleDotSpan.kt b/app/src/main/java/com/example/farmmate1/CustomMultipleDotSpan.kt
new file mode 100644
index 0000000..4914bd1
--- /dev/null
+++ b/app/src/main/java/com/example/farmmate1/CustomMultipleDotSpan.kt
@@ -0,0 +1,71 @@
+package com.example.farmmate1
+
+import android.graphics.Canvas
+import android.graphics.Paint
+import android.text.style.LineBackgroundSpan
+import android.util.Log
+
+class CustomMultipleDotSpan(private val radius: Float = DEFAULT_RADIUS, private val colors: IntArray) : LineBackgroundSpan {
+
+ companion object {
+ private const val DEFAULT_RADIUS = 5f
+ }
+
+// override fun drawBackground(
+// canvas: Canvas, paint: Paint, left: Int, right: Int, top: Int, baseline: Int, bottom: Int,
+// charSequence: CharSequence, start: Int, end: Int, lineNum: Int
+// ) {
+// val total = if (colors.size > 3) 3 else colors.size
+// var leftMost = (total - 1) * -12
+//
+// for (i in 0 until total) {
+// val oldColor = paint.color
+// if (colors[i] != 0) {
+// paint.color = colors[i]
+// }
+// canvas.drawCircle(((left + right) / 2 - leftMost).toFloat(), bottom + radius, radius, paint)
+// paint.color = oldColor
+// leftMost += 24
+// }
+// }
+override fun drawBackground(
+ canvas: Canvas, paint: Paint, left: Int, right: Int, top: Int, baseline: Int, bottom: Int,
+ charSequence: CharSequence, start: Int, end: Int, lineNum: Int
+) {
+ val total = colors.size
+ val centerX = (left + right) / 2 // 가운데 x 좌표
+
+ // 각 점 사이의 간격 계산
+ val interval: Float = if (total > 1) {
+ if (total % 2 == 0) { // 짝수인 경우
+ (right - left - radius * 2) / (total*3.3 - 1).toFloat()
+ } else { // 홀수인 경우
+ (right - left - radius * 2) / (total*2).toFloat()
+ }
+ } else {
+ 0f
+ }
+
+ var currentX = centerX - (interval * (total - 1) / 2) // 첫 번째 점의 x 좌표 계산
+
+ for (i in 0 until total) {
+ val oldColor = paint.color
+ if (colors[i] != 0) {
+ paint.color = colors[i]
+ }
+
+ // 각 점의 x 좌표 계산
+ val x = currentX.toFloat()
+ Log.d("CustomMultipleDotSpan", "점 ${i + 1}의 x 좌표: $x")
+
+ canvas.drawCircle(x, bottom + radius, radius, paint) // 점 그리기
+ paint.color = oldColor
+
+ currentX += interval.toInt() // 다음 점으로 이동
+ }
+}
+
+
+
+
+}
diff --git a/app/src/main/java/com/example/farmmate1/DeviceInfo.kt b/app/src/main/java/com/example/farmmate1/DeviceInfo.kt
new file mode 100644
index 0000000..5140150
--- /dev/null
+++ b/app/src/main/java/com/example/farmmate1/DeviceInfo.kt
@@ -0,0 +1,3 @@
+package com.example.farmmate1
+
+data class DeviceInfo(val deviceId: String)
diff --git a/app/src/main/java/com/example/farmmate1/DiagnosisCameraFragment.kt b/app/src/main/java/com/example/farmmate1/DiagnosisCameraFragment.kt
new file mode 100644
index 0000000..021b502
--- /dev/null
+++ b/app/src/main/java/com/example/farmmate1/DiagnosisCameraFragment.kt
@@ -0,0 +1,271 @@
+package com.example.farmmate1
+
+import android.Manifest
+import android.content.pm.PackageManager
+import android.os.Bundle
+import android.os.Environment
+import androidx.fragment.app.Fragment
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.Toast
+import android.content.Intent
+import android.provider.MediaStore
+import android.app.Activity
+import java.io.File
+import android.graphics.Bitmap
+import androidx.core.content.ContextCompat
+import com.example.farmmate1.databinding.FragmentDiagnosisCameraBinding
+import com.example.farmmate1.DiagnosisResult
+import okhttp3.MediaType
+import okhttp3.MultipartBody
+import okhttp3.RequestBody
+import java.io.FileOutputStream
+import java.io.IOException
+import android.util.Log
+import retrofit2.Call
+import retrofit2.Callback
+import retrofit2.Response
+
+class DiagnosisCameraFragment : Fragment() {
+
+ private val REQUEST_IMAGE_CAPTURE = 101
+ private val CAMERA_PERMISSION_CODE = 102
+ private val REQUEST_IMAGE_FROM_GALLERY = 103
+ private val REQUEST_PERMISSION_CODE = 104
+
+ private var imagePath: String = ""
+
+ private var _binding: FragmentDiagnosisCameraBinding? = null
+ private val binding get() = _binding!!
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ _binding = FragmentDiagnosisCameraBinding.inflate(inflater, container, false)
+ val view = binding.root
+ return view
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+
+ val selectedCrop = arguments?.getString("selectedCrop")
+ binding.diagnosisCameraTvPlant.text = "진단 할 식물: $selectedCrop"
+
+ binding.diagnosisCameraBtnOpencam.setOnClickListener{
+ checkCameraPermission()
+ }
+
+ binding.diagnosisCameraBtnGallery.setOnClickListener {
+ getAlbum()
+ }
+
+ // 초기에 진단하기 버튼 비활성화
+ binding.diagnosisCameraBtnNext.visibility = View.INVISIBLE
+
+ binding.diagnosisCameraBackIb.setOnClickListener {
+ moveToDiagnosisFragment()
+ }
+
+ binding.diagnosisCameraBtnNext.setOnClickListener {
+ // 서버에 이미지 보내기
+ sendDiagnosisToServer(selectedCrop)
+ }
+
+ }
+
+ private fun checkPermission(): Boolean {
+ val cameraPermission = ContextCompat.checkSelfPermission(
+ requireContext(),
+ Manifest.permission.CAMERA
+ ) == PackageManager.PERMISSION_GRANTED
+
+ val storagePermission = ContextCompat.checkSelfPermission(
+ requireContext(),
+ Manifest.permission.READ_EXTERNAL_STORAGE
+ ) == PackageManager.PERMISSION_GRANTED
+
+ return cameraPermission && storagePermission
+ }
+
+ private fun checkCameraPermission() {
+ // 카메라 권한이 부여되었는지 확인
+ if (ContextCompat.checkSelfPermission(
+ requireContext(),
+ Manifest.permission.CAMERA
+ ) != PackageManager.PERMISSION_GRANTED
+ ) {
+ // 권한이 없다면 권한 요청
+ requestPermissions(
+ arrayOf(Manifest.permission.CAMERA),
+ CAMERA_PERMISSION_CODE
+ )
+ } else {
+ // 권한이 이미 허용되었다면 사진 촬영 진행
+ dispatchTakePictureIntent()
+ }
+ }
+
+ // 권한이 없다면 권한 요청 > 요청 결과 처리
+ override fun onRequestPermissionsResult(
+ requestCode: Int,
+ permissions: Array,
+ grantResults: IntArray
+ ) {
+ if (requestCode == CAMERA_PERMISSION_CODE) {
+ if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
+ // 권한이 허용되면 사진 촬영 진행
+ dispatchTakePictureIntent()
+ } else {
+ // 권한이 거부되었을 때 처리
+ Toast.makeText(requireContext(), "권한이 필요합니다", Toast.LENGTH_SHORT).show()
+ }
+ }
+ }
+
+ override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
+ super.onActivityResult(requestCode, resultCode, data)
+
+ if (resultCode == Activity.RESULT_OK) {
+ when (requestCode) {
+ REQUEST_IMAGE_CAPTURE -> {
+ // 사진 찍기 후 결과 이미지 처리
+ saveCapturedImage(data)
+ }
+ REQUEST_IMAGE_FROM_GALLERY -> {
+ // 갤러리에서 이미지 선택 후 처리
+ saveGalleryImage(data)
+ }
+ }
+ }
+ }
+
+ private fun dispatchTakePictureIntent() {
+ val takePictureIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
+ startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE)
+ }
+
+ fun getAlbum() {
+ if (checkPermission()) {
+ val intent = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI)
+ startActivityForResult(intent, REQUEST_IMAGE_FROM_GALLERY)
+ } else {
+ requestPermissions(
+ arrayOf(
+ Manifest.permission.READ_EXTERNAL_STORAGE
+ ),
+ REQUEST_PERMISSION_CODE
+ )
+ }
+ }
+
+ private fun saveCapturedImage(data: Intent?) {
+ if (data != null && data.extras != null) {
+ val imageBitmap = data.extras!!.get("data") as Bitmap
+
+ // 이미지를 파일로 저장
+ imagePath = saveImageToFile(imageBitmap)
+
+ // 이미지를 ImageView에 표시
+ binding.diagnosisCameraIvImage.setImageBitmap(imageBitmap)
+ binding.diagnosisCameraBtnNext.visibility = View.VISIBLE
+ }
+ }
+
+ private fun saveGalleryImage(data: Intent?) {
+ val imageUri = data?.data
+ val imageBitmap = MediaStore.Images.Media.getBitmap(requireActivity().contentResolver, imageUri)
+
+ // 이미지를 파일로 저장
+ imagePath = saveImageToFile(imageBitmap)
+
+ // 이미지를 ImageView에 표시
+ binding.diagnosisCameraIvImage.setImageBitmap(imageBitmap)
+ binding.diagnosisCameraBtnNext.visibility = View.VISIBLE
+ }
+
+ private fun saveImageToFile(bitmap: Bitmap): String {
+ val filesDir = requireContext().getExternalFilesDir(Environment.DIRECTORY_PICTURES)
+ val imageFile = File(filesDir, "captured_image.jpg")
+
+ try {
+ FileOutputStream(imageFile).use { fos ->
+ bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos)
+ fos.flush()
+ }
+ } catch (e: IOException) {
+ e.printStackTrace()
+ }
+
+ return imageFile.absolutePath
+ }
+
+ private fun moveToDiagnosisFragment() {
+ val transaction = parentFragmentManager
+ .beginTransaction()
+ .replace(R.id.main_fl, DiagnosisFragment())
+ transaction.commit()
+ }
+
+ private fun sendDiagnosisToServer(plantType: String?) {
+
+ val retrofit = RetrofitClient.instance
+ val apiService = retrofit.create(ApiService::class.java)
+
+ try {
+ val plantTypeBody = RequestBody.create(MediaType.parse("text/plain"), plantType)
+
+ val imageFile = File(imagePath)
+ val imageRequestBody = RequestBody.create(MediaType.parse("image/*"), imageFile)
+ val imageBody = MultipartBody.Part.createFormData("image", imageFile.name, imageRequestBody)
+
+ apiService.postDiagnosis(plantTypeBody, imageBody)
+ .enqueue(object : Callback {
+ override fun onResponse(
+ call: Call,
+ response: Response
+ ) {
+ // 요청 성공 시 처리
+ if (response.isSuccessful) {
+ val diagnosisResult = response.body()?.let {
+ // 응답 데이터를 DiagnosisResult 객체로 변환
+ DiagnosisResult(
+ it.diseaseUuid,
+ it.plantName,
+ it.diseaseName,
+ it.diseaseCode,
+ it.diseaseSymptom,
+ it.diseaseCause,
+ it.diseaseTreatment,
+ it.diagnosisCode,
+ it.plantImg
+ )
+ }
+ val bundle = Bundle().apply {
+ putParcelable("diagnosisResult", diagnosisResult)
+ }
+ // Fragment 전환
+ val diagnosisResultFragment = DiagnosisResultFragment()
+ diagnosisResultFragment.arguments = bundle
+ parentFragmentManager.beginTransaction()
+ .replace(R.id.main_fl, diagnosisResultFragment)
+ .commit()
+ } else {
+ // API 요청 실패 처리
+ Log.e("CameraFragment", "Failed to fetch plant list: ${response.message()}")
+ }
+ }
+
+ override fun onFailure(call: Call, t: Throwable) {
+ // 통신 오류 처리
+ Log.e("CameraFragment", "Network error: ${t.message}")
+ }
+ })
+ } catch (e: Exception) {
+ e.printStackTrace()
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/farmmate1/DiagnosisFragment.kt b/app/src/main/java/com/example/farmmate1/DiagnosisFragment.kt
index 2dc6f25..c406228 100644
--- a/app/src/main/java/com/example/farmmate1/DiagnosisFragment.kt
+++ b/app/src/main/java/com/example/farmmate1/DiagnosisFragment.kt
@@ -1,66 +1,212 @@
package com.example.farmmate1
+import android.content.Context
+import android.graphics.Color
import android.os.Bundle
import android.util.Log
+import android.view.Gravity
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
+import android.widget.*
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
+import androidx.appcompat.app.AlertDialog
import com.example.farmmate1.databinding.FragmentDiagnosisBinding
+import com.prolificinteractive.materialcalendarview.CalendarDay
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
-
+import java.util.ArrayList
class DiagnosisFragment : Fragment() {
private var _binding: FragmentDiagnosisBinding? = null
private val binding get() = _binding!!
+ private var selectedDate: CalendarDay? = null
+ private var selectedPlantName: String? = ""
+ private var selectedPlantUuid: String? = ""
+ private var historyList: ArrayList? = null
+
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
-
}
-
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
_binding = FragmentDiagnosisBinding.inflate(inflater, container, false)
val view = binding.root
+
+ // 상단바 get
+ val retrofit = RetrofitClient.instance
+ val apiService = retrofit.create(ApiService::class.java)
+
+ // SharedPreferences에서 디바이스 ID 가져오기
+ val sharedPreferences = requireActivity().getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
+ val deviceId: String = sharedPreferences.getString(DEVICE_ID_KEY, "") ?: ""
+
+ val plantInfoName = arguments?.getString("plantInfoName")
+
+ apiService.getPlantList(deviceId).enqueue(object : Callback> {
+ override fun onResponse(call: Call>, response: Response>) {
+ val plantList = response.body() as? ArrayList
+ if (plantList != null) {
+
+ setButtonTextForLinearLayout(plantList)
+
+ // 이미 있는 버튼에 데이터 할당
+ for (i in 0 until 5) {
+ val button = binding.diagnosisLinearlayout.getChildAt(i) as? Button
+ button?.setOnClickListener {
+ // 클릭된 버튼을 강조하기 위해 색상 변경
+ onButtonClicked(button)
+ selectedPlantName = button?.text.toString()
+ selectedPlantUuid = plantList[i].plant_uuid
+ fetchDiaryListFromServer(selectedPlantUuid)
+ }
+ }
+
+ // 동적으로 생성된 버튼
+ for (i in 5 until binding.diagnosisLinearlayout.childCount) {
+ val button = binding.diagnosisLinearlayout.getChildAt(i) as? Button
+ button?.setOnClickListener {
+ // 클릭된 버튼을 강조하기 위해 색상 변경
+ onButtonClicked(button)
+ selectedPlantName = button?.text.toString()
+ selectedPlantUuid = plantList[i].plant_uuid
+ fetchDiaryListFromServer(selectedPlantUuid)
+ }
+ }
+
+ plantInfoName?.let { plantName ->
+ for (i in 0 until binding.diagnosisLinearlayout.childCount) {
+ val button = binding.diagnosisLinearlayout.getChildAt(i) as? Button
+ if (button?.text.toString() == plantName) {
+ button?.isSelected = true
+ selectedPlantName = plantName
+ selectedPlantUuid = plantList.find { it.plant_name == plantName }?.plant_uuid
+ fetchDiaryListFromServer(selectedPlantUuid)
+ break
+ }
+ }
+ } ?: run {
+ // 넘겨준 값이 없을 경우에는 맨 처음 버튼을 선택 상태로 지정
+ val firstButton = binding.diagnosisLinearlayout.getChildAt(0) as? Button
+ firstButton?.isSelected = true
+ selectedPlantName = firstButton?.text.toString()
+ selectedPlantUuid = plantList[0].plant_uuid
+ fetchDiaryListFromServer(selectedPlantUuid)
+ }
+ } else {
+ // API 요청 실패 처리
+ Log.e("DiagnosisFragment", "Failed to fetch plant list: ${response.message()}")
+ }
+ }
+
+ override fun onFailure(call: Call>, t: Throwable) {
+ // 통신 오류 처리
+ Log.e("DiaryFragment", "Network error: ${t.message}")
+ }
+ })
+
return view
}
-// var HistoryList = arrayListOf(
-// History(R.drawable.number_one, "2023-06-01", "정상"),
-// History(R.drawable.number_two, "2023-06-01", "정상"),
-// History(R.drawable.number_three, "2023-06-01", "정상"),
-// History(R.drawable.number_four, "2023-06-01", "정상"),
-// History(R.drawable.number_five, "2023-06-01", "정상"),
-// History(R.drawable.number_six, "2023-06-01", "정상"),
-// History(R.drawable.number_seven, "2023-06-01", "정상"),
-// History(R.drawable.number_eight, "2023-06-01", "정상"),
-// History(R.drawable.number_nine, "2023-06-01", "정상"),
-// History(R.drawable.number_ten, "2023-06-01", "정상")
-// )
-
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
+ // 진단하기 버튼 클릭 시 알림창 (진단할 작물 선택)
+ binding.diagnosisBtnDiagnosis.setOnClickListener{
+ showCropSelectionDialog()
+ }
+
+ // 리스트 객체 클릭 시 진단 결과 페이지로 이동..
+ binding.diagnosisListLvHistory.setOnItemClickListener { parent, view, position, id ->
+ historyList?.let { list ->
+ if (position < list.size) {
+ val selectedHistory = list[position]
+ val bundle = Bundle().apply {
+ putString("plantDiseaseUuid", selectedHistory.plantDiseaseUuid)
+ }
+ val diagnosisSavedFragment = DiagnosisSavedFragment()
+ diagnosisSavedFragment.arguments = bundle
+
+ val transaction = parentFragmentManager
+ .beginTransaction()
+ .replace(R.id.main_fl, diagnosisSavedFragment)
+ transaction.commit()
+ }
+ }
+ }
+
+ }
+
+ override fun onDestroyView() {
+ super.onDestroyView()
+
+ // 메모리 누수를 방지하기 위해 Fragment View에 대한 참조를 제거하여 가비지 컬렉터가 수거
+ _binding = null
+ }
+
+ // LinearLayout에 버튼을 추가하는 함수
+ fun setButtonTextForLinearLayout(plantList: List) {
+ for (i in 0 until plantList.size) {
+ val plantName = plantList[i].plant_name
+ if (i < 5) {
+ // 처음 다섯 개의 버튼에 텍스트만 할당
+ val button = binding.diagnosisLinearlayout.getChildAt(i) as? Button
+ button?.text = plantName ?: ""
+ } else {
+ // 여섯 번째 요소부터 동적으로 버튼을 추가하며 텍스트 할당
+ val button = Button(requireContext())
+ button.text = plantName ?: ""
+ val layoutParams = LinearLayout.LayoutParams(
+ resources.getDimensionPixelSize(R.dimen.button_width),
+ resources.getDimensionPixelSize(R.dimen.button_height)
+ )
+ val marginHorizontalPx = resources.getDimensionPixelSize(R.dimen.button_margin_horizontal)
+ layoutParams.setMargins(marginHorizontalPx, 0, marginHorizontalPx, 0) // 좌우 마진과 상단 마진을 dimens.xml에서 가져온 값으로 설정
+ button.layoutParams = layoutParams
+ button.setTextColor(Color.BLACK) // 텍스트 색상 설정
+ button.setBackgroundResource(R.drawable.rounded_btn)
+ button.gravity = Gravity.CENTER
+
+ button.setPadding(0, -3, 0, 0)
+ layoutParams.weight = 1f
+
+ button.setOnClickListener {
+ // 버튼이 클릭되었을 때 수행할 작업 추가
+ }
+ binding.diagnosisLinearlayout.addView(button)
+ }
+ }
+ }
+
+ // 모든 버튼을 클릭했을 때 호출되는 메서드
+ fun onButtonClicked(clickedButton: Button) {
+ // 모든 버튼을 탐색하면서 클릭된 버튼인지 확인하고 상태를 변경합니다.
+ for (i in 0 until binding.diagnosisLinearlayout.childCount) {
+ val button = binding.diagnosisLinearlayout.getChildAt(i) as? Button
+ button?.isSelected = (button == clickedButton)
+ }
+ }
+
+ private fun fetchDiaryListFromServer(plantUuid: String?){
val retrofit = RetrofitClient.instance
val apiService = retrofit.create(ApiService::class.java)
- // 데이터 요청
- apiService.getHistoryList().enqueue(object : Callback> {
+ apiService.getSavedResult(plantUuid).enqueue(object : Callback> {
override fun onResponse(call: Call>, response: Response>) {
if (response.isSuccessful) {
- val historyList = response.body() as? ArrayList
+ historyList = response.body() as? ArrayList
if (historyList != null) {
- val adapter = HistoryAdapter(requireContext(), historyList)
+ // history 어댑터 연결
+ val adapter = HistoryAdapter(requireContext(), historyList!!)
binding.diagnosisListLvHistory.adapter = adapter
}
} else {
@@ -75,51 +221,50 @@ class DiagnosisFragment : Fragment() {
}
})
- // history 어댑터 연결
-// val Adapter = HistoryAdapter(requireContext(),HistoryList)
-// binding.diagnosisListLvHistory.adapter = Adapter
+ }
- // 진단하기 버튼 클릭 시 페이지 이동 (진단할 작물 선택)
- binding.diagnosisHistoryBtnDiagnosis.setOnClickListener{
- moveToDiagnosisSelectFragment()
+ private fun moveToDiagnosisCameraFragment(selectedCrop: String?) {
+ val bundle = Bundle().apply {
+ putString("selectedCrop", selectedCrop) // 선택한 작물을 번들에 저장
}
- // 리스트 객체 클릭 시 진단 결과 페이지로 이동..
- binding.diagnosisListLvHistory.setOnItemClickListener { parent, view, position, id ->
- moveToDiagnosisResultFragment()}
-
- }
+ val fragment = DiagnosisCameraFragment().apply {
+ arguments = bundle // 번들을 프래그먼트에 전달
+ }
- private fun moveToDiagnosisSelectFragment() {
val transaction = parentFragmentManager
.beginTransaction()
- .replace(R.id.main_fl, DiagnosisSelectFragment())
+ .replace(R.id.main_fl, fragment)
transaction.commit()
}
- private fun moveToDiagnosisResultFragment() {
- val transaction = parentFragmentManager
- .beginTransaction()
- .replace(R.id.main_fl, DiagnosisResultFragment())
- transaction.commit()
- }
+ private var selectedCrop: String? = null // 선택한 작물을 저장할 변수
- override fun onDestroyView() {
- super.onDestroyView()
+ private fun showCropSelectionDialog() {
+ val crops = arrayOf("가지", "고추", "단호박", "딸기", "상추", "수박", "애호박", "오이", "쥬키니호박", "참외", "토마토", "포도")
+ val checkedItem = -1
- // 메모리 누수를 방지하기 위해 Fragment View에 대한 참조를 제거하여 가비지 컬렉터가 수거
- _binding = null
+ val builder = AlertDialog.Builder(requireContext())
+ builder.setTitle("작물 종류를 선택하세요")
+ .setSingleChoiceItems(crops, checkedItem) { dialog, which ->
+ // 라디오 버튼을 클릭한 경우의 동작 설정
+ selectedCrop = crops[which] // 선택한 작물 저장
+ }
+ .setPositiveButton("다음") { dialog, which ->
+ // "다음" 버튼을 클릭한 경우의 동작 설정
+ if (selectedCrop != null) {
+ moveToDiagnosisCameraFragment(selectedCrop!!)
+ dialog.dismiss() // 다이얼로그 닫기
+ } else {
+ Toast.makeText(requireContext(), "진단할 작물을 선택하세요", Toast.LENGTH_SHORT).show()
+ // 왜 알림창이 닫힐까 ^^
+ }
+ }
+ .setNegativeButton("취소") { dialog, which ->
+ // "취소" 버튼을 클릭한 경우의 동작 설정
+ dialog.dismiss() // 다이얼로그 닫기
+ }
+ .show() // 다이얼로그 표시
}
- class MainViewModel : ViewModel() {
-
- private val _count = MutableLiveData()
- val count : LiveData get() = _count
- init {
- _count.value = 5
- }
- fun getUpdatedCount(plusCount: Int){
- _count.value = (_count.value)?.plus(plusCount)
- }
- }
}
diff --git a/app/src/main/java/com/example/farmmate1/DiagnosisPost.kt b/app/src/main/java/com/example/farmmate1/DiagnosisPost.kt
new file mode 100644
index 0000000..09f8e8d
--- /dev/null
+++ b/app/src/main/java/com/example/farmmate1/DiagnosisPost.kt
@@ -0,0 +1,9 @@
+package com.example.farmmate1
+
+import okhttp3.MultipartBody
+import okhttp3.RequestBody
+
+class DiagnosisPost (
+ val plantType: String,
+ var diagnosisImg: RequestBody
+)
\ No newline at end of file
diff --git a/app/src/main/java/com/example/farmmate1/DiagnosisResult.kt b/app/src/main/java/com/example/farmmate1/DiagnosisResult.kt
new file mode 100644
index 0000000..f28ac99
--- /dev/null
+++ b/app/src/main/java/com/example/farmmate1/DiagnosisResult.kt
@@ -0,0 +1,54 @@
+package com.example.farmmate1
+
+import android.os.Parcel
+import android.os.Parcelable
+
+data class DiagnosisResult(
+ val diseaseUuid: String,
+ val plantName: String,
+ val diseaseName: String,
+ val diseaseCode: Int,
+ val diseaseSymptom: String?,
+ val diseaseCause: String?,
+ val diseaseTreatment: String?,
+ val diagnosisCode: Int,
+ val plantImg: String? // 추가된 필드
+) : Parcelable {
+ constructor(parcel: Parcel) : this(
+ parcel.readString()!!,
+ parcel.readString()!!,
+ parcel.readString()!!,
+ parcel.readInt(),
+ parcel.readString(),
+ parcel.readString(),
+ parcel.readString(),
+ parcel.readInt(),
+ parcel.readString() // 추가된 필드 읽기
+ )
+
+ override fun writeToParcel(parcel: Parcel, flags: Int) {
+ parcel.writeString(diseaseUuid)
+ parcel.writeString(plantName)
+ parcel.writeString(diseaseName)
+ parcel.writeInt(diseaseCode)
+ parcel.writeString(diseaseSymptom)
+ parcel.writeString(diseaseCause)
+ parcel.writeString(diseaseTreatment)
+ parcel.writeInt(diagnosisCode)
+ parcel.writeString(plantImg) // 추가된 필드 쓰기
+ }
+
+ override fun describeContents(): Int {
+ return 0
+ }
+
+ companion object CREATOR : Parcelable.Creator {
+ override fun createFromParcel(parcel: Parcel): DiagnosisResult {
+ return DiagnosisResult(parcel)
+ }
+
+ override fun newArray(size: Int): Array {
+ return arrayOfNulls(size)
+ }
+ }
+}
diff --git a/app/src/main/java/com/example/farmmate1/DiagnosisResultFragment.kt b/app/src/main/java/com/example/farmmate1/DiagnosisResultFragment.kt
index b15d20d..4f5a599 100644
--- a/app/src/main/java/com/example/farmmate1/DiagnosisResultFragment.kt
+++ b/app/src/main/java/com/example/farmmate1/DiagnosisResultFragment.kt
@@ -1,11 +1,15 @@
package com.example.farmmate1
+import android.app.AlertDialog
+import android.content.Context
import android.os.Bundle
import android.util.Log
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
+import android.widget.ArrayAdapter
+import android.widget.TextView
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
@@ -14,15 +18,12 @@ import com.example.farmmate1.databinding.FragmentDiagnosisResultBinding
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
+import java.util.ArrayList
class DiagnosisResultFragment : Fragment() {
private var _binding: FragmentDiagnosisResultBinding? = null
private val binding get() = _binding!!
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- }
-
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
@@ -32,33 +33,91 @@ class DiagnosisResultFragment : Fragment() {
return view
}
+ private var selectedButtonId: Int = R.id.diagnosis_result_btn_symptom
+ private var plantList: ArrayList? = null
+ private var plantData: List> = emptyList()
+ private var diseaseUuid: String = ""
+
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
- val retrofit = RetrofitClient.instance
- val apiService = retrofit.create(ApiService::class.java)
+ val diagnosisResult = arguments?.getParcelable("diagnosisResult")
+
+ var diseaseName: String? = ""
+ var symptom: String? = ""
+ var cause: String? = ""
+ var treatment: String? = ""
+ var plantType: String? = ""
+
+ if (diagnosisResult != null) {
+ diseaseUuid = diagnosisResult.diseaseUuid
+
+ // 사진
+ val plantImg = binding.diagnosisResultIvPhoto
+
+ val imageUrl = diagnosisResult?.plantImg
+ ImageLoaderTask(plantImg).execute(imageUrl)
+
+ // 결과
+ diseaseName = diagnosisResult.diseaseName
+ binding.diagnosisResultTvName.text = diseaseName
+ // 처음에는 증상
+ binding.diagnosisResultTvDetail.text = diagnosisResult.diseaseSymptom
+
+ plantType = diagnosisResult.plantName
+ symptom = diagnosisResult.diseaseSymptom
+ cause = diagnosisResult.diseaseCause
+ treatment = diagnosisResult.diseaseTreatment
+
+ if (diseaseName == "정상") {
+ binding.diagnosisResultBtnSymptom.visibility = View.GONE
+ binding.diagnosisResultBtnCause.visibility = View.GONE
+ binding.diagnosisResultBtnCure.visibility = View.GONE
+ binding.diagnosisResultTvDetail.text = "$plantType 진단 결과 정상 작물로 예측됩니다."
+ }
+
+ } else {
+ Log.e("DiagnosisResultFragment", "DiagnosisResult object is null")
+ }
+
+ selectButton(binding.diagnosisResultBtnSymptom)
- // 데이터 요청
-// apiService.getHistoryList().enqueue(object : Callback> {
-// override fun onResponse(call: Call>, response: Response>) {
-// if (response.isSuccessful) {
-// val historyList = response.body() as? ArrayList
-// if (historyList != null) {
-// val adapter = HistoryAdapter(requireContext(), historyList)
-// binding.diagnosisListLvHistory.adapter = adapter
-// }
-// } else {
-// // API 요청 실패 처리
-// Log.e("DiagnosisResultFragment", "Failed to fetch plant list: ${response.message()}")
-// }
-// }
-//
-// override fun onFailure(call: Call>, t: Throwable) {
-// // 통신 오류 처리
-// Log.e("DiagnosisResultFragment", "Network error: ${t.message}")
-// }
-// })
+ // 증상
+ binding.diagnosisResultBtnSymptom.setOnClickListener {
+ selectButton(it)
+ binding.diagnosisResultTvDetail.text = symptom
+ }
+
+ // 원인
+ binding.diagnosisResultBtnCause.setOnClickListener {
+ selectButton(it)
+ binding.diagnosisResultTvDetail.text = cause
+ }
+
+ // 치료법
+ binding.diagnosisResultBtnCure.setOnClickListener {
+ selectButton(it)
+ binding.diagnosisResultTvDetail.text = treatment
+ }
+
+
+ // back button
+ binding.diagnosisResultBackIb.setOnClickListener {
+ moveToDiagnosisFragment()
+ }
+ // plantList GET
+ getPlantList()
+
+ // 저장
+ binding.diagnosisResultBtnSave.setOnClickListener {
+ showPlantSelectionDialog()
+ }
+
+ // 재측정
+ binding.diagnosisResultBtnRecheck.setOnClickListener {
+ moveToDiagnosisCameraFragment(plantType)
+ }
}
override fun onDestroyView() {
@@ -68,15 +127,121 @@ class DiagnosisResultFragment : Fragment() {
_binding = null
}
- class MainViewModel : ViewModel() {
+ private fun moveToDiagnosisFragment() {
+ val transaction = parentFragmentManager
+ .beginTransaction()
+ .replace(R.id.main_fl, DiagnosisFragment())
+ transaction.commit()
+ }
+
+ private fun moveToDiagnosisCameraFragment(plantType: String?) {
+ val transaction = parentFragmentManager.beginTransaction()
+ val fragment = DiagnosisCameraFragment()
+
+ // 번들에 데이터 추가
+ val bundle = Bundle()
+ bundle.putString("selectedCrop", plantType)
+ fragment.arguments = bundle
- private val _count = MutableLiveData()
- val count : LiveData get() = _count
- init {
- _count.value = 5
+ transaction.replace(R.id.main_fl, fragment)
+ transaction.commit()
+ }
+
+
+ // 버튼을 선택 상태로 변경하는 함수
+ private fun selectButton(button: View) {
+ // 이전에 선택된 버튼의 isSelected 속성을 false로 설정하여 선택 해제
+ binding.diagnosisResultBtnSymptom.isSelected = false
+ binding.diagnosisResultBtnCause.isSelected = false
+ binding.diagnosisResultBtnCure.isSelected = false
+
+ // 현재 선택된 버튼의 isSelected 속성을 true로 설정하여 선택
+ button.isSelected = true
+
+ // 선택된 버튼의 ID를 추적
+ selectedButtonId = button.id
+ }
+
+ private fun getPlantList(){
+ // Retrofit 인스턴스 생성
+ val retrofit = RetrofitClient.instance
+ val apiService = retrofit.create(ApiService::class.java)
+
+ // SharedPreferences에서 디바이스 ID 가져오기
+ val sharedPreferences = requireActivity().getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
+ val deviceId: String = sharedPreferences.getString(DEVICE_ID_KEY, "") ?: ""
+
+ apiService.getPlantList(deviceId).enqueue(object : Callback> {
+ override fun onResponse(call: Call>, response: Response>) {
+ val plantList = response.body() as? ArrayList
+ if (plantList != null) {
+ // 작물 이름과 plant_uuid를 매핑하여 리스트에 저장
+ plantData = plantList.map { (it.plant_name ?: "Unknown") to it.plant_uuid }
+ } else {
+ Log.e("DiaryResultFragment", "Failed to fetch user crops: ${response.message()}")
+ }
+ }
+
+ override fun onFailure(call: Call>, t: Throwable) {
+ Log.e("DiaryResultFragment", "Network error: ${t.message}")
+ }
+ })
+ }
+
+ private fun showPlantSelectionDialog() {
+ val builder = AlertDialog.Builder(requireContext())
+ builder.setTitle("작물 선택")
+
+ val plantNames = plantData.map { it.first }.toTypedArray()
+ var selectedPlantIndex = 0 // 초기 선택된 항목의 인덱스를 추적
+
+ // 라디오 버튼으로 작물 목록 표시
+ builder.setSingleChoiceItems(plantNames, selectedPlantIndex) { dialog, which ->
+ selectedPlantIndex = which // 선택한 항목의 인덱스 업데이트
}
- fun getUpdatedCount(plusCount: Int){
- _count.value = (_count.value)?.plus(plusCount)
+
+ // 다음 버튼
+ builder.setPositiveButton("다음") { dialog, _ ->
+ val selectedPlantUuid = plantData[selectedPlantIndex].second
+ val request = DiagnosisSaveRequest(selectedPlantUuid, diseaseUuid)
+ Log.d("DiagnosisResultFragment", "$selectedPlantUuid, $diseaseUuid")
+ postDiagnosisSave(request)
+
+ dialog.dismiss()
}
+
+ // 취소 버튼
+ builder.setNegativeButton("취소") { dialog, _ ->
+ dialog.dismiss()
+ }
+
+ builder.show()
+ }
+
+ private fun postDiagnosisSave(request: DiagnosisSaveRequest) {
+ // Retrofit 인스턴스 생성
+ val retrofit = RetrofitClient.instance
+ val apiService = retrofit.create(ApiService::class.java)
+
+ // POST 요청 보내기
+ apiService.postDiagnosisSave(request).enqueue(object : Callback {
+ override fun onResponse(call: Call, response: Response) {
+ if (response.isSuccessful) {
+ // 요청이 성공적으로 처리된 경우의 처리 로직
+ Log.d("DiagnosisResultFragment", "Diagnosis saved successfully.")
+ moveToDiagnosisFragment()
+ } else {
+ // 요청이 실패한 경우의 처리 로직
+ Log.e("DiagnosisResultFragment", "Failed to save diagnosis: ${response.message()}")
+ }
+ }
+
+ override fun onFailure(call: Call, t: Throwable) {
+ // 네트워크 오류 또는 예외 발생 시의 처리 로직
+ Log.e("DiagnosisResultFragment", "Network error: ${t.message}")
+ }
+ })
}
+
+
}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/farmmate1/DiagnosisSaveRequest.kt b/app/src/main/java/com/example/farmmate1/DiagnosisSaveRequest.kt
new file mode 100644
index 0000000..0678214
--- /dev/null
+++ b/app/src/main/java/com/example/farmmate1/DiagnosisSaveRequest.kt
@@ -0,0 +1,6 @@
+package com.example.farmmate1
+
+data class DiagnosisSaveRequest(
+ val plantUuid: String,
+ val diseaseUuid: String
+)
\ No newline at end of file
diff --git a/app/src/main/java/com/example/farmmate1/DiagnosisSavedFragment.kt b/app/src/main/java/com/example/farmmate1/DiagnosisSavedFragment.kt
new file mode 100644
index 0000000..933255e
--- /dev/null
+++ b/app/src/main/java/com/example/farmmate1/DiagnosisSavedFragment.kt
@@ -0,0 +1,144 @@
+package com.example.farmmate1
+
+import android.os.Bundle
+import android.util.Log
+import androidx.fragment.app.Fragment
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import com.example.farmmate1.databinding.FragmentDiagnosisSavedBinding
+import retrofit2.Call
+import retrofit2.Callback
+import retrofit2.Response
+import java.text.SimpleDateFormat
+import java.util.*
+
+class DiagnosisSavedFragment : Fragment() {
+
+ private var _binding: FragmentDiagnosisSavedBinding? = null
+ private val binding get() = _binding!!
+
+ private lateinit var plantDiseaseUuid: String
+
+ private var symptom: String? = ""
+ private var cause: String? = ""
+ private var treatment: String? = ""
+ private var selectedButtonId: Int = R.id.diagnosis_result_btn_symptom
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ arguments?.let {
+ }
+ }
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ _binding = FragmentDiagnosisSavedBinding.inflate(inflater, container, false)
+ val view = binding.root
+
+ plantDiseaseUuid = arguments?.getString("plantDiseaseUuid") ?: ""
+ plantDiseaseUuid?.let { uuid ->
+
+ // Retrofit 인스턴스 생성
+ val retrofit = RetrofitClient.instance
+ val apiService = retrofit.create(ApiService::class.java)
+
+ Log.d("DiagnosisSavedFragment", "Uuid: $plantDiseaseUuid")
+
+ apiService.getResult(plantDiseaseUuid).enqueue(object : Callback {
+ override fun onResponse(call: Call, response: Response) {
+ if (response.isSuccessful) {
+ val historyget = response.body()
+ // 데이터를 받아온 후에 해당 데이터를 View에 설정해주는 작업을 수행
+
+ Log.d("DiagnosisSavedFragment", "$historyget")
+
+ binding.diagnosisSavedTvName.text = historyget?.disease?.diseaseName
+ binding.diagnosisSavedTvDetail.text = historyget?.disease?.diseaseSymptom
+
+ // 사진
+ val plantImg = binding.diagnosisSavedIvPhoto
+
+ val imageUrl = historyget?.disease?.plantImg
+ ImageLoaderTask(plantImg).execute(imageUrl)
+
+ symptom = historyget?.disease?.diseaseSymptom
+ cause = historyget?.disease?.diseaseCause
+ treatment = historyget?.disease?.diseaseTreatment
+ val plantType = historyget?.disease?.plantName
+
+ if (historyget?.disease?.diseaseName == "정상") {
+ binding.diagnosisSavedBtnSymptom.visibility = View.GONE
+ binding.diagnosisSavedBtnCause.visibility = View.GONE
+ binding.diagnosisSavedBtnCure.visibility = View.GONE
+ binding.diagnosisSavedTvDetail.text = "$plantType 진단 결과 정상 작물로 예측됩니다."
+ }
+ } else {
+ // API 요청 실패 처리
+ Log.e("DiagnosisSavedFragment", "Failed to fetch plant: ${response.message()}")
+ }
+ }
+
+ override fun onFailure(call: Call, t: Throwable) {
+ // 통신 오류 처리
+ Log.e("DiagnosisSavedFragment", "Network error: ${t.message}")
+ }
+ })
+ }
+
+ return view
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+
+ selectButton(binding.diagnosisSavedBtnSymptom)
+
+ // 증상
+ binding.diagnosisSavedBtnSymptom.setOnClickListener {
+ selectButton(it)
+ binding.diagnosisSavedTvDetail.text = symptom
+ }
+
+ // 원인
+ binding.diagnosisSavedBtnCause.setOnClickListener {
+ selectButton(it)
+ binding.diagnosisSavedTvDetail.text = cause
+ }
+
+ // 치료법
+ binding.diagnosisSavedBtnCure.setOnClickListener {
+ selectButton(it)
+ binding.diagnosisSavedTvDetail.text = treatment
+ }
+
+
+ // back button
+ binding.diagnosisSavedBackIb.setOnClickListener {
+ moveToDiagnosisFragment()
+ }
+ }
+
+ private fun selectButton(button: View) {
+ // 이전에 선택된 버튼의 isSelected 속성을 false로 설정하여 선택 해제
+ binding.diagnosisSavedBtnSymptom.isSelected = false
+ binding.diagnosisSavedBtnCause.isSelected = false
+ binding.diagnosisSavedBtnCure.isSelected = false
+
+ // 현재 선택된 버튼의 isSelected 속성을 true로 설정하여 선택
+ button.isSelected = true
+
+ // 선택된 버튼의 ID를 추적
+ selectedButtonId = button.id
+ }
+
+ private fun moveToDiagnosisFragment() {
+ val transaction = parentFragmentManager
+ .beginTransaction()
+ .replace(R.id.main_fl, DiagnosisFragment())
+ transaction.commit()
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/farmmate1/DiagnosisSelectFragment.kt b/app/src/main/java/com/example/farmmate1/DiagnosisSelectFragment.kt
deleted file mode 100644
index 072adc6..0000000
--- a/app/src/main/java/com/example/farmmate1/DiagnosisSelectFragment.kt
+++ /dev/null
@@ -1,92 +0,0 @@
-package com.example.farmmate1
-
-import android.os.Bundle
-import androidx.fragment.app.Fragment
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import android.widget.ArrayAdapter
-import com.example.farmmate1.databinding.FragmentDiagnosisSelectBinding
-import com.example.farmmate1.databinding.FragmentPlantAddBinding
-
-
-class DiagnosisSelectFragment : Fragment() {
-
- private var _binding: FragmentDiagnosisSelectBinding? = null
- private val binding get() = _binding!!
-
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- }
-
- override fun onCreateView(
- inflater: LayoutInflater, container: ViewGroup?,
- savedInstanceState: Bundle?
- ): View? {
- _binding = FragmentDiagnosisSelectBinding.inflate(inflater, container, false)
- val view = binding.root
- return view
- }
-
- override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
- super.onViewCreated(view, savedInstanceState)
-
- val retrofit = RetrofitClient.instance
- val apiService = retrofit.create(ApiService::class.java)
-
- // 데이터 요청
-// apiService.getHistoryList().enqueue(object : Callback> {
-// override fun onResponse(call: Call>, response: Response>) {
-// if (response.isSuccessful) {
-// val historyList = response.body() as? ArrayList
-// if (historyList != null) {
-// val adapter = HistoryAdapter(requireContext(), historyList)
-// binding.diagnosisListLvHistory.adapter = adapter
-// }
-// } else {
-// // API 요청 실패 처리
-// Log.e("DiagnosisResultFragment", "Failed to fetch plant list: ${response.message()}")
-// }
-// }
-//
-// override fun onFailure(call: Call>, t: Throwable) {
-// // 통신 오류 처리
-// Log.e("DiagnosisResultFragment", "Network error: ${t.message}")
-// }
-// })
-
- // 작물 종류 선택 (등록한 작물)
- setUpSpinnerMyplants()
-
- // 작물 종류 선택 (등록하지 않은 작물)
- setUpSpinnerAnyplants()
-
- // 뒤로 가기 버튼 클릭 후 진단 메인 페이지로 이동
- binding.diagnosisSelectBackIb.setOnClickListener{
- moveToDiagnosisFragment()
- }
- }
-
- private fun setUpSpinnerMyplants() {
- val myplants = resources.getStringArray(R.array.myplants)
- val adapter = ArrayAdapter(requireContext(),R.layout.spinner_item_myplant, myplants)
- val spinner = binding.diagnosisSelectSpinnerMyplant
- spinner.adapter = adapter
- }
-
- private fun setUpSpinnerAnyplants() {
- val anyplants = resources.getStringArray(R.array.anyplants)
- val adapter = ArrayAdapter(requireContext(),R.layout.spinner_item_anyplant, anyplants)
- val spinner = binding.diagnosisSelectSpinnerAnyplant
- spinner.adapter = adapter
- }
-
- private fun moveToDiagnosisFragment() {
- val transaction = parentFragmentManager
- .beginTransaction()
- .replace(R.id.main_fl, DiagnosisFragment())
- transaction.commit()
- }
-
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/farmmate1/Diary b/app/src/main/java/com/example/farmmate1/Diary
new file mode 100644
index 0000000..7e0974e
--- /dev/null
+++ b/app/src/main/java/com/example/farmmate1/Diary
@@ -0,0 +1,18 @@
+package com.example.farmmate1
+
+data class Diary(
+ val plantName: String,
+ val diaryDate: String,
+ val plantWeather: String,
+ val temperature: String,
+ val humidity: String,
+ val waterFlag: Boolean,
+ val fertilizeFlag: Boolean,
+ val fertilizeName: String,
+ val fertilizeUsage: String,
+ val pesticideFlag: Boolean,
+ val pesticideName: String,
+ val pesticideUsage: String,
+ val memo: String,
+ val imageData: ByteArray? = null
+)
diff --git a/app/src/main/java/com/example/farmmate1/DiaryAddFragment.kt b/app/src/main/java/com/example/farmmate1/DiaryAddFragment.kt
new file mode 100644
index 0000000..3185388
--- /dev/null
+++ b/app/src/main/java/com/example/farmmate1/DiaryAddFragment.kt
@@ -0,0 +1,375 @@
+package com.example.farmmate1
+
+import android.Manifest
+import android.app.Activity
+import android.content.Context
+import android.content.Intent
+import android.content.pm.PackageManager
+import android.net.Uri
+import android.os.Bundle
+import android.provider.MediaStore
+import android.provider.OpenableColumns
+import android.util.Log
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.*
+import androidx.core.content.ContextCompat
+import androidx.fragment.app.Fragment
+import com.example.farmmate1.data.*
+import com.example.farmmate1.databinding.FragmentDiaryAddBinding
+import retrofit2.Call
+import retrofit2.Callback
+import retrofit2.Response
+import java.text.SimpleDateFormat
+import java.util.*
+import com.prolificinteractive.materialcalendarview.*
+import okhttp3.MediaType
+import okhttp3.MultipartBody
+import okhttp3.RequestBody
+
+class DiaryAddFragment : Fragment() {
+
+ // 날짜 데이터 전달받아 인스턴스 생성
+ companion object {
+ private const val ARG_DATE = "arg_date"
+
+ fun newInstance(date: Calendar): DiaryAddFragment {
+ val args = Bundle().apply {
+ putSerializable(ARG_DATE, date)
+ }
+ val fragment = DiaryAddFragment()
+ fragment.arguments = args
+ return fragment
+ }
+ }
+
+ private val REQUEST_IMAGE_FROM_GALLERY = 103
+ private val REQUEST_PERMISSION_CODE = 104
+
+ private var selectedPlantUuid: String = ""
+ private var plantList: ArrayList? = null
+
+ private var _binding: FragmentDiaryAddBinding? = null
+ private val binding get() = _binding!! // !! -> non-null assertion
+
+ private var imageData: ByteArray? = null
+ private var image: MultipartBody.Part? = null
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ _binding = FragmentDiaryAddBinding.inflate(inflater, container, false)
+ val view = binding.root
+
+ return view
+ }
+
+ private var checkedItems = mutableSetOf() // 체크된 항목 기록
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+
+ // 스피너에 사용자 작물 목록 설정
+ loadUserCropsToSpinner()
+
+ // 스피너에서 항목을 선택할 때마다 선택한 작물의 plant_uuid를 저장
+ binding.diaryAddSpinnerSelect.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
+ override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
+ // 선택한 작물의 plant_uuid 저장
+ selectedPlantUuid = (binding.diaryAddSpinnerSelect.selectedItem as? Pair)?.second ?: ""
+ Log.d("DiaryAdd-- plant_uuid", "$selectedPlantUuid")
+ }
+
+ override fun onNothingSelected(parent: AdapterView<*>?) {
+ // 아무것도 선택하지 않았을 때, 첫 번째 항목을 기본값으로 설정
+ selectedPlantUuid = (binding.diaryAddSpinnerSelect.getItemAtPosition(0) as? Pair)?.second ?: ""
+
+ }
+ }
+
+ // Post 요청할 때 selectedPlantUuid 사용
+ // 예: saveDiaryEntry(selectedPlantUuid, ...)
+
+ // 일지 작성 페이지 상단에 기록하는 날짜 표시
+ val selectedDate = arguments?.getSerializable(ARG_DATE) as? Calendar
+ selectedDate?.let {
+ val dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault())
+ val formattedDate = dateFormat.format(it.time)
+ binding.diaryAddTvDate.text = formattedDate
+ } ?: run {
+ binding.diaryAddTvDate.text = "에러 발생" // 날짜가 없을 경우에 대한 처리 (빈 문자열로 표시)
+ }
+
+ binding.diaryAddIbImage.setOnClickListener {
+ openGallery()
+ }
+
+ binding.diaryAddBtnEnroll.setOnClickListener {
+ val selectedPlant = binding.diaryAddSpinnerSelect.selectedItem.toString()
+ val temperatureText = binding.diaryAddEtTemperature.text.toString()
+ val humidityText = binding.diaryAddEtHumidity.text.toString()
+
+ if (validateTemperature(temperatureText) && validateHumidity(humidityText)) {
+ postDiary()
+ }
+ }
+
+ //back button
+ binding.diaryAddBackIb.setOnClickListener {
+ moveToDiaryFragment()
+ }
+ }
+
+ // 스피너에 사용자 작물 목록 설정
+ private fun loadUserCropsToSpinner() {
+ // Retrofit 인스턴스 생성
+ val retrofit = RetrofitClient.instance
+ val apiService = retrofit.create(ApiService::class.java)
+
+ // SharedPreferences에서 디바이스 ID 가져오기
+ val sharedPreferences = requireActivity().getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
+ val deviceId: String = sharedPreferences.getString(DEVICE_ID_KEY, "") ?: ""
+
+ apiService.getPlantList(deviceId).enqueue(object : Callback> {
+ override fun onResponse(call: Call>, response: Response>) {
+ val plantList = response.body() as? ArrayList
+ if (plantList != null) {
+ // 작물 이름과 plant_uuid를 매핑하여 리스트에 저장
+ val plantData = plantList.map { (it.plant_name ?: "Unknown") to it.plant_uuid }
+ val spinnerAdapter = object : ArrayAdapter>(
+ requireContext(),
+ android.R.layout.simple_spinner_item,
+ plantData
+ ) {
+ override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
+ val view = super.getView(position, convertView, parent)
+ val plantName = getItem(position)?.first
+ val textView = view.findViewById(android.R.id.text1)
+ textView.text = plantName
+ return view
+ }
+ override fun getDropDownView(position: Int, convertView: View?, parent: ViewGroup): View {
+ val view = super.getDropDownView(position, convertView, parent)
+ val plantName = getItem(position)?.first
+ val textView = view.findViewById(android.R.id.text1)
+ textView.text = plantName
+ return view
+ }
+ }
+ spinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
+ binding.diaryAddSpinnerSelect.adapter = spinnerAdapter
+ } else {
+ Log.e("DiaryAddFragment", "Failed to fetch user crops: ${response.message()}")
+ }
+ }
+
+ override fun onFailure(call: Call>, t: Throwable) {
+ Log.e("DiaryAddFragment", "Network error: ${t.message}")
+ }
+ })
+ }
+
+ private fun postDiary() {
+
+ Log.d("DiaryAdd-- Post plant_uuid","$selectedPlantUuid")
+ val diaryDate = binding.diaryAddTvDate.text.toString()
+ val plantUuid = selectedPlantUuid
+ val plantWeather = binding.diaryAddEtWeather.text.toString()
+ val temperature = binding.diaryAddEtTemperature.text.toString()
+ val humidity = binding.diaryAddEtHumidity.text.toString()
+ val waterFlag = binding.diaryAddCbWater.isChecked.toString()
+ val fertilizeFlag = binding.diaryAddCbFert.isChecked.toString()
+ val fertilizeName = binding.diaryAddEtFert.text.toString()
+ val fertilizeUsage = binding.diaryAddEtFertuse.text.toString()
+ val pesticideFlag = binding.diaryAddCbPes.isChecked.toString()
+ val pesticideName = binding.diaryAddEtPes.text.toString()
+ val pesticideUsage = binding.diaryAddEtPesuse.text.toString()
+ val memo = binding.diaryAddEtMemo.text.toString()
+
+ val requestBodyMap = hashMapOf()
+ requestBodyMap["plantUuid"] = createPartFromString(plantUuid)
+ requestBodyMap["diaryDate"] = createPartFromString(diaryDate)
+ requestBodyMap["plantWeather"] = createPartFromString(plantWeather)
+ requestBodyMap["temperature"] = createPartFromString(temperature)
+ requestBodyMap["humidity"] = createPartFromString(humidity)
+ requestBodyMap["waterFlag"] = createPartFromString(waterFlag)
+ requestBodyMap["fertilizeFlag"] = createPartFromString(fertilizeFlag)
+ requestBodyMap["fertilizeName"] = createPartFromString(fertilizeName)
+ requestBodyMap["fertilizeUsage"] = createPartFromString(fertilizeUsage)
+ requestBodyMap["pesticideFlag"] = createPartFromString(pesticideFlag)
+ requestBodyMap["pesticideName"] = createPartFromString(pesticideName)
+ requestBodyMap["pesticideUsage"] = createPartFromString(pesticideUsage)
+ requestBodyMap["memo"] = createPartFromString(memo)
+
+ // 이미지 데이터를 MultipartBody.Part로 변환
+ val imagePart = image
+
+ // Retrofit 인스턴스 생성
+ val retrofit = RetrofitClient.instance
+ val apiService = retrofit.create(ApiService::class.java)
+
+ plantUuid?.let {
+ apiService.postDiary(requestBodyMap, imagePart).enqueue(object : Callback {
+ override fun onResponse(call: Call, response: Response) {
+ if (response.isSuccessful) {
+ Log.d("전송성공", "전송성공")
+ moveToDiaryFragment()
+ } else {
+ // 전송 실패
+ Log.d("전송실패", "전송실패")
+ }
+ }
+
+ override fun onFailure(call: Call, t: Throwable) {
+ // 전송 실패
+ Log.d("전송실패who", "전송실who패")
+ }
+ })
+ } ?: Log.d("전송실패", "플랜트 UUID가 null입니다.")
+ }
+
+ private fun createPartFromString(string: String): RequestBody {
+ return RequestBody.create(MediaType.parse("text/plain"), string)
+ }
+
+ private fun validateTemperature(temperatureText: String): Boolean {
+ if (temperatureText.isEmpty()) {
+ // 온도가 비어있는 경우
+ Toast.makeText(requireContext(), "온도를 입력하세요.", Toast.LENGTH_SHORT).show()
+ return false
+ }
+
+ val temperature = temperatureText.toIntOrNull()
+ if (temperature == null) {
+ // 온도가 숫자로 변환할 수 없는 경우
+ Toast.makeText(requireContext(), "온도는 숫자로 입력하세요.", Toast.LENGTH_SHORT).show()
+ return false
+ }
+
+ if (temperature < -40 || temperature > 40) {
+ // 온도가 범위를 벗어난 경우
+ Toast.makeText(requireContext(), "온도는 -40도에서 50도 사이로 입력하세요.", Toast.LENGTH_SHORT).show()
+ return false
+ }
+
+ return true
+ }
+
+ private fun validateHumidity(humidityText: String): Boolean {
+ if (humidityText.isEmpty()) {
+ // 습도가 비어있는 경우
+ Toast.makeText(requireContext(), "습도를 입력하세요.", Toast.LENGTH_SHORT).show()
+ return false
+ }
+
+ val humidity = humidityText.toIntOrNull()
+ if (humidity == null) {
+ // 습도가 숫자로 변환할 수 없는 경우
+ Toast.makeText(requireContext(), "습도는 숫자로 입력하세요.", Toast.LENGTH_SHORT).show()
+ return false
+ }
+
+ if (humidity < 50 || humidity > 100) {
+ // 습도가 범위를 벗어난 경우
+ Toast.makeText(requireContext(), "습도는 50에서 100 사이로 입력하세요.", Toast.LENGTH_SHORT).show()
+ return false
+ }
+
+ return true
+ }
+
+ private fun openGallery() {
+ if (checkStoragePermission()) {
+ val galleryIntent = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI)
+ startActivityForResult(galleryIntent, REQUEST_IMAGE_FROM_GALLERY)
+ } else {
+ requestStoragePermission()
+ }
+ }
+
+ private fun checkStoragePermission(): Boolean {
+ return ContextCompat.checkSelfPermission(
+ requireContext(),
+ Manifest.permission.READ_EXTERNAL_STORAGE
+ ) == PackageManager.PERMISSION_GRANTED
+ }
+
+ private fun requestStoragePermission() {
+ requestPermissions(
+ arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE),
+ REQUEST_PERMISSION_CODE
+ )
+ }
+
+ override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) {
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults)
+ if (requestCode == REQUEST_PERMISSION_CODE) {
+ if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
+ openGallery()
+ } else {
+ Toast.makeText(requireContext(), "저장소 권한이 필요합니다.", Toast.LENGTH_SHORT).show()
+ }
+ }
+ }
+
+ override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
+ super.onActivityResult(requestCode, resultCode, data)
+ if (resultCode == Activity.RESULT_OK) {
+ when (requestCode) {
+ REQUEST_IMAGE_FROM_GALLERY -> {
+ data?.data?.let { uri ->
+ val inputStream = requireActivity().contentResolver.openInputStream(uri)
+ val bytes = inputStream?.readBytes()
+ inputStream?.close()
+ imageData = bytes
+
+ // 이미지 파일의 MIME 타입 가져오기
+ val contentType = requireActivity().contentResolver.getType(uri)
+ //파일명
+ val fileName = getFileNameFromUri(uri)
+ binding.diaryAddTvUploadFileinfo.text = "파일 선택됨: $fileName"
+
+ // 이미지 파일을 MultipartBody.Part로 변환
+ val requestBody = RequestBody.create(MediaType.parse(contentType), bytes)
+ val multipart = MultipartBody.Part.createFormData("image", fileName, requestBody)
+ image = multipart
+ }
+ }
+ }
+ }
+ }
+
+ private fun getFileNameFromUri(uri: Uri): String {
+ var fileName = ""
+ val cursor = requireActivity().contentResolver.query(uri, null, null, null, null)
+ cursor?.use {
+ if (it.moveToFirst()) {
+ val displayNameIndex = it.getColumnIndex(OpenableColumns.DISPLAY_NAME)
+ if (displayNameIndex >= 0) {
+ fileName = it.getString(displayNameIndex)
+ }
+ }
+ }
+ return fileName
+ }
+
+ private fun moveToDiaryFragment() {
+ val transaction = parentFragmentManager
+ .beginTransaction()
+ .replace(R.id.main_fl, DiaryFragment())
+ transaction.commit()
+ }
+
+
+
+// fun getCheckedItems(): Set {
+// return checkedItems
+// }
+//
+// fun getSelectedDate(): CalendarDay? {
+// return (requireArguments().getSerializable(ARG_DATE) as? CalendarDay)
+// }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/farmmate1/DiaryDataListener.kt b/app/src/main/java/com/example/farmmate1/DiaryDataListener.kt
deleted file mode 100644
index addc9d8..0000000
--- a/app/src/main/java/com/example/farmmate1/DiaryDataListener.kt
+++ /dev/null
@@ -1,10 +0,0 @@
-package com.example.farmmate1
-
-import java.util.Calendar
-
-interface DiaryDataListener {
- fun onDiaryDataReceived(date: Calendar, data: String){
-
-
- }
-}
diff --git a/app/src/main/java/com/example/farmmate1/DiaryFragment.kt b/app/src/main/java/com/example/farmmate1/DiaryFragment.kt
index 5e32878..f984e7e 100644
--- a/app/src/main/java/com/example/farmmate1/DiaryFragment.kt
+++ b/app/src/main/java/com/example/farmmate1/DiaryFragment.kt
@@ -1,147 +1,387 @@
package com.example.farmmate1
+import android.content.Context
+import android.graphics.Color
import android.os.Bundle
+import android.util.Log
+import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
-import android.widget.ArrayAdapter
-import android.widget.Button
-import android.widget.CalendarView
-import android.widget.ListView
+import android.widget.*
import androidx.fragment.app.Fragment
-import java.text.SimpleDateFormat
+import com.example.farmmate1.databinding.FragmentDiaryBinding
import java.util.*
+import com.prolificinteractive.materialcalendarview.*
+import com.prolificinteractive.materialcalendarview.format.TitleFormatter
+import retrofit2.Call
+import retrofit2.Callback
+import retrofit2.Response
+
+class DiaryFragment : Fragment() {
+
+ private var _binding: FragmentDiaryBinding? = null
+ private val binding get() = _binding!!
+
+ private var diaryList: ArrayList? = null
+ private lateinit var calendarView: MaterialCalendarView
+ private var selectedDate: CalendarDay? = null
+ private var selectedPlantName: String? = null
+ //private var filteredDiaryList: List? = null
+
+ private lateinit var diaryUuid: String
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ _binding = FragmentDiaryBinding.inflate(inflater, container, false)
+ val view = binding.root
+
+ calendarView = binding.diaryFragmentCal
+
+ val today = CalendarDay.today()
+ val oneDayDecorator = OneDayDecorator()
+
+ calendarView.selectedDate = today
+ calendarView.setDateSelected(today, true)
+ calendarView.addDecorators(
+ SundayDecorator(),
+ SaturdayDecorator(),
+ oneDayDecorator
+ )
+
+ calendarView.setTitleFormatter(object : TitleFormatter {
+ override fun format(day: CalendarDay): CharSequence {
+ // 원하는 형식으로 제목을 지정
+ return "${day.year}년 ${day.month + 1}월" // month는 0부터 시작하므로 +1 해줍니다.
+ }
+ })
+
+ // 상단바 get
+ val retrofit = RetrofitClient.instance
+ val apiService = retrofit.create(ApiService::class.java)
+
+ // SharedPreferences에서 디바이스 ID 가져오기
+ val sharedPreferences = requireActivity().getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
+ val deviceId: String = sharedPreferences.getString(DEVICE_ID_KEY, "") ?: ""
+
+ val plantInfoName = arguments?.getString("plantInfoName")
+
+ apiService.getPlantList(deviceId).enqueue(object : Callback> {
+ override fun onResponse(call: Call>, response: Response>) {
+ val plantList = response.body() as? ArrayList
+ if (plantList != null) {
+ Log.d("DiaryFragment", "$plantList")
+
+ setButtonTextForLinearLayout(plantList)
+ // 동적으로 버튼 추가
+ for (plant in plantList) {
+ Log.d("DiaryFragment", "${plant.plant_name}")
+ }
+
+ for (i in 0 until 5) {
+ val button = binding.diaryLinearlayout.getChildAt(i) as? Button
+ button?.setOnClickListener {
+ // 클릭된 버튼을 강조하기 위해 색상 변경
+ onButtonClicked(button)
+ selectedPlantName = button?.text.toString()
+ Log.d("DiaryPlantName","$selectedPlantName")
+ fetchDiaryListFromServer()
+ }
+ }
+
+ // 동적으로 생성된 버튼에 클릭 이벤트 처리기 추가
+ for (i in 5 until binding.diaryLinearlayout.childCount) {
+ val button = binding.diaryLinearlayout.getChildAt(i) as? Button
+ button?.setOnClickListener {
+ // 클릭된 버튼을 강조하기 위해 색상 변경
+ onButtonClicked(button)
+ selectedPlantName = button?.text.toString()
+ Log.d("DiaryPlantName","$selectedPlantName")
+ fetchDiaryListFromServer()
+ }
+ }
+
+ // plantInfo에서 넘어온 경우
+ plantInfoName?.let { plantName ->
+ for (i in 0 until binding.diaryLinearlayout.childCount) {
+ val button = binding.diaryLinearlayout.getChildAt(i) as? Button
+ if (button?.text.toString() == plantName) {
+ button?.isSelected = true
+ selectedPlantName = plantName
+ Log.d("DiaryPlantName", "$selectedPlantName")
+ fetchDiaryListFromServer()
+ break
+ }
+ }
+ } ?: run {
+ // 넘겨준 값이 없을 경우에는 맨 처음 버튼을 선택 상태로 지정
+ val firstButton = binding.diaryLinearlayout.getChildAt(0) as? Button
+ firstButton?.isSelected = true
+ selectedPlantName = firstButton?.text.toString()
+ Log.d("DiaryPlantName", "$selectedPlantName")
+ fetchDiaryListFromServer()
+ }
+
+ } else {
+ // API 요청 실패 처리
+ Log.e("DiaryFragment", "Failed to fetch plant list: ${response.message()}")
+ }
+ }
-// TODO: Rename parameter arguments, choose names that match
-// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
-private const val ARG_PARAM1 = "param1"
-private const val ARG_PARAM2 = "param2"
+ override fun onFailure(call: Call>, t: Throwable) {
+ // 통신 오류 처리
+ Log.e("DiaryFragment", "Network error: ${t.message}")
+ }
+ })
+ return view
+ }
-/**
- * A simple [Fragment] subclass.
- * Use the [DiaryFragment.newInstance] factory method to
- * create an instance of this fragment.
- */
-class DiaryFragment : Fragment(), DiaryDataListener {
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
- private lateinit var fragment2: WriteDiaryFragment
- private lateinit var calendarView: CalendarView
- private lateinit var writeButton: Button
- private lateinit var listView : ListView
+ binding.diaryRegitstBtn.setOnClickListener {
+ // selectedDate가 null이 아닌 경우에만 DiaryAddFragment를 생성하고 전환
+ Log.d("-------","$selectedDate")
+ selectedDate?.let { date ->
+ moveToAddDiaryFragment(date)
+ }
+ }
- override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
- val view = inflater.inflate(R.layout.fragment_diary, container, false)
+ binding.diaryContentLayout.setOnClickListener {
+ val bundle = Bundle()
+ bundle.putString("diaryUuid", diaryUuid)
+ bundle.putString("selectedPlantName", selectedPlantName)
- calendarView = view.findViewById(R.id.diary_calview)
- listView = view.findViewById(R.id.diary_todo_list_view)
+ val diaryInfoFragment = DiaryInfoFragment()
+ diaryInfoFragment.arguments = bundle
+ requireActivity().supportFragmentManager
+ .beginTransaction()
+ .replace(R.id.main_fl, diaryInfoFragment)
+ .commit()
+ }
- // 프래그먼트 인스턴스 생성
- fragment2 = WriteDiaryFragment()
- calendarView = view.findViewById(R.id.diary_calview)
- writeButton = view.findViewById(R.id.diary_regitst_btn)
+ }
- //캘린더 날짜 선택 이벤트 처리
- calendarView.setOnDateChangeListener{_, year, month, dayOfMonth ->
- val selectDate = Calendar.getInstance().apply{
- set(year, month, dayOfMonth)
- }
- val todoList = getTodoList(selectDate)
- val adapter = ArrayAdapter(requireContext(),android.R.layout.simple_list_item_1, todoList)
- listView.adapter=adapter
- }
+ override fun onDestroyView() {
+ super.onDestroyView()
+ // 메모리 누수를 방지하기 위해 Fragment View에 대한 참조를 제거하여 가비지 컬렉터가 수거
+ _binding = null
+ }
- //버튼 클릭시 이벤트 처리
- writeButton.setOnClickListener {
- val selectDate = Calendar.getInstance().apply{
- timeInMillis = calendarView.date
+ // LinearLayout에 버튼을 추가하는 함수
+ fun setButtonTextForLinearLayout(plantList: List) {
+ for (i in 0 until plantList.size) {
+ val plantName = plantList[i].plant_name
+ if (i < 5) {
+ // 처음 다섯 개의 버튼에 텍스트만 할당
+ val button = binding.diaryLinearlayout.getChildAt(i) as? Button
+ button?.text = plantName ?: ""
+ } else {
+ // 여섯 번째 요소부터 동적으로 버튼을 추가하며 텍스트 할당
+ val button = Button(requireContext())
+ button.text = plantName ?: ""
+ val layoutParams = LinearLayout.LayoutParams(
+ resources.getDimensionPixelSize(R.dimen.button_width),
+ resources.getDimensionPixelSize(R.dimen.button_height)
+ )
+ val marginHorizontalPx = resources.getDimensionPixelSize(R.dimen.button_margin_horizontal)
+ layoutParams.setMargins(marginHorizontalPx, 0, marginHorizontalPx, 0) // 좌우 마진과 상단 마진을 dimens.xml에서 가져온 값으로 설정
+ button.layoutParams = layoutParams
+ button.setTextColor(Color.BLACK) // 텍스트 색상 설정
+ button.setBackgroundResource(R.drawable.rounded_btn)
+ button.gravity = Gravity.CENTER
+
+ button.setPadding(0, -3, 0, 0)
+ layoutParams.weight = 1f
+
+ button.setOnClickListener {
+ // 버튼이 클릭되었을 때 수행할 작업 추가
+ }
+ binding.diaryLinearlayout.addView(button)
}
- //TODO: 선택된 날짜에 데이터 저장
}
+ }
- //캘린더 날짜 선택 이벤트 처리
- calendarView.setOnDateChangeListener{_, year, month, dayOfMonth->
- val selectedDate = Calendar.getInstance().apply{
- set(year,month,dayOfMonth)
- }
- val todoList = getTodoList(selectedDate)
- val adapter = ArrayAdapter(requireContext(),android.R.layout.simple_list_item_1, todoList )
- listView.adapter = adapter
+ // 모든 버튼을 클릭했을 때 호출되는 메서드
+ fun onButtonClicked(clickedButton: Button) {
+ // 모든 버튼을 탐색하면서 클릭된 버튼인지 확인하고 상태를 변경합니다.
+ for (i in 0 until binding.diaryLinearlayout.childCount) {
+ val button = binding.diaryLinearlayout.getChildAt(i) as? Button
+ button?.isSelected = (button == clickedButton)
+ }
- /* val hasData = checkDataExist(selectedDate)
- if (hasData){
+ // 일지 요약 초기화
+ binding.diaryContentDate.text = ""
+ binding.diaryContentWeather.text = "일지를 등록하세요"
+ binding.diaryContentMemo.text = ""
+ }
- }*/
+ private fun moveToAddDiaryFragment(selectedDate: CalendarDay?) {
+ selectedDate?.let { date ->
+ val diaryAddFragment = DiaryAddFragment.newInstance(date.calendar)
+ val transaction = parentFragmentManager
+ .beginTransaction()
+ .replace(R.id.main_fl, diaryAddFragment)
+ transaction.commit()
}
+ }
+ private fun fetchDiaryListFromServer() {
+ val retrofit = RetrofitClient.instance
+ val apiService = retrofit.create(ApiService::class.java)
- // 버튼 클릭 시 Fragment2로 전환
- view.findViewById