diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml
index 401569e5..52cce6f8 100644
--- a/.idea/deploymentTargetDropDown.xml
+++ b/.idea/deploymentTargetDropDown.xml
@@ -7,11 +7,11 @@
-
+
-
+
\ No newline at end of file
diff --git a/app/src/main/java/umc/com/mobile/project/data/model/plan/AddTimeRequest.kt b/app/src/main/java/umc/com/mobile/project/data/model/plan/AddTimeRequest.kt
new file mode 100644
index 00000000..fd852fd6
--- /dev/null
+++ b/app/src/main/java/umc/com/mobile/project/data/model/plan/AddTimeRequest.kt
@@ -0,0 +1,18 @@
+package umc.com.mobile.project.data.model.plan
+
+data class AddTimeRequest(
+val semesterDto: SemesterDto,
+val subjectDtoList: List,
+)
+
+data class SemesterDto(
+ val grade: Long,
+ val semester: Long,
+)
+
+data class SubjectDtoList(
+ val type: String,
+ val name: String,
+ val credit: String,
+)
+
diff --git a/app/src/main/java/umc/com/mobile/project/data/model/plan/AddTimeResponse.kt b/app/src/main/java/umc/com/mobile/project/data/model/plan/AddTimeResponse.kt
index 44890c9c..e210bcae 100644
--- a/app/src/main/java/umc/com/mobile/project/data/model/plan/AddTimeResponse.kt
+++ b/app/src/main/java/umc/com/mobile/project/data/model/plan/AddTimeResponse.kt
@@ -1,18 +1,17 @@
package umc.com.mobile.project.data.model.plan
data class AddTimeResponse(
-val semesterDto: SemesterDto,
-val subjectDtoList: List,
+ val isSuccess: Boolean,
+ val code: String,
+ val message: String,
+ val result: AddResponseResult
)
-data class SemesterDto(
- val grade: Long,
- val semester: Long,
+data class AddResponseResult(
+ val addResponseDtos: List
)
-data class SubjectDtoList(
- val type: String,
- val name: String,
- val credit: Long,
+data class AddResponseDto(
+ val subjectId: Long,
+ val createdAt: String
)
-
diff --git a/app/src/main/java/umc/com/mobile/project/data/model/plan/CertificateLicenseRequest.kt b/app/src/main/java/umc/com/mobile/project/data/model/plan/CertificateLicenseRequest.kt
new file mode 100644
index 00000000..4a49f7ef
--- /dev/null
+++ b/app/src/main/java/umc/com/mobile/project/data/model/plan/CertificateLicenseRequest.kt
@@ -0,0 +1,7 @@
+package umc.com.mobile.project.data.model.plan
+
+data class CertificateLicenseRequest(
+ val certificateId: Long,
+ val name: String,
+ val date: String
+)
diff --git a/app/src/main/java/umc/com/mobile/project/data/model/plan/EditMemoRequest.kt b/app/src/main/java/umc/com/mobile/project/data/model/plan/EditMemoRequest.kt
new file mode 100644
index 00000000..20fa4b33
--- /dev/null
+++ b/app/src/main/java/umc/com/mobile/project/data/model/plan/EditMemoRequest.kt
@@ -0,0 +1,6 @@
+package umc.com.mobile.project.data.model.plan
+
+data class EditMemoRequest(
+ val memo: String
+)
+
diff --git a/app/src/main/java/umc/com/mobile/project/data/model/plan/PlanFreeRequest.kt b/app/src/main/java/umc/com/mobile/project/data/model/plan/PlanFreeRequest.kt
new file mode 100644
index 00000000..953dfb79
--- /dev/null
+++ b/app/src/main/java/umc/com/mobile/project/data/model/plan/PlanFreeRequest.kt
@@ -0,0 +1,6 @@
+package umc.com.mobile.project.data.model.plan
+
+data class PlanFreeRequest(
+ val memo: String,
+)
+
diff --git a/app/src/main/java/umc/com/mobile/project/data/model/plan/PlanFreeResponse.kt b/app/src/main/java/umc/com/mobile/project/data/model/plan/PlanFreeResponse.kt
new file mode 100644
index 00000000..ac41ce3c
--- /dev/null
+++ b/app/src/main/java/umc/com/mobile/project/data/model/plan/PlanFreeResponse.kt
@@ -0,0 +1,13 @@
+package umc.com.mobile.project.data.model.plan
+
+data class PlanFreeResponse(
+ val isSuccess: Boolean,
+ val code: String,
+ val message: String,
+ val result: FreeInfo,
+)
+
+data class FreeInfo(
+ val memo: String,
+)
+
diff --git a/app/src/main/java/umc/com/mobile/project/data/network/api/PlanApi.kt b/app/src/main/java/umc/com/mobile/project/data/network/api/PlanApi.kt
index 61e5b44c..614f3748 100644
--- a/app/src/main/java/umc/com/mobile/project/data/network/api/PlanApi.kt
+++ b/app/src/main/java/umc/com/mobile/project/data/network/api/PlanApi.kt
@@ -3,35 +3,56 @@ package umc.com.mobile.project.data.network.api
import retrofit2.http.GET
import retrofit2.Call
import retrofit2.http.Body
+import retrofit2.http.PATCH
import retrofit2.http.POST
import retrofit2.http.Query
+import umc.com.mobile.project.data.model.plan.AddTimeRequest
+import umc.com.mobile.project.data.model.plan.AddTimeResponse
import umc.com.mobile.project.data.model.plan.BringlicenseResponse
import umc.com.mobile.project.data.model.plan.ListTimeResponse
+import umc.com.mobile.project.data.model.plan.PlanFreeRequest
+import umc.com.mobile.project.data.model.plan.PlanFreeResponse
import umc.com.mobile.project.data.model.plan.PlanTrackResponse
import umc.com.mobile.project.data.model.plan.SaveInfo
import umc.com.mobile.project.data.model.plan.SemesterTimeResponse
import umc.com.mobile.project.data.model.plan.UPlicenseResponse
+import umc.com.mobile.project.data.model.plan.EditMemoRequest
interface PlanApi {
- @GET("plans/certifications")
- fun getUPlicense(): Call
+ @GET("plans/certifications")
+ fun getUPlicense(): Call
- @POST("plans/certifications")
- fun saveLicense(@Body request: List): Call
+ @POST("plans/certifications")
+ fun saveLicense(@Body request: List): Call
- @GET("/plans/timetable/searchSubject")
- fun getListTime(@Query("hakki") hakki:String, @Query("track") track : String) : Call
+ @GET("/plans/timetable/searchSubject")
+ fun getListTime(@Query("hakki") hakki:String, @Query("track") track : String) : Call
+
+ @GET("/plans/timetable/searchTrack")
+ fun getTrackInfo(@Query("hakki") hakki: String) : Call
+
+ @GET("/plans/timetable/searchHakki")
+ fun getSemesterInfo():Call
+
+ @POST("/plans/timetable")
+ fun addTime(@Body addTimeRequest: AddTimeRequest): Call
+
+ @GET("/plans/memo")
+ fun getFreeInfo() : Call
+
+ @POST("/plans/memo")
+ fun postFreeMemo(@Body request: PlanFreeRequest): Call
+
+ @PATCH("/plans/memo")
+ fun editMemo(@Body editMemoRequest: EditMemoRequest) : Call
+
- @GET("/plans/timetable/searchTrack")
- fun getTrackInfo(@Query("hakki") hakki: String) : Call
- @GET("/plans/timetable/searchHakki")
- fun getSemesterInfo():Call
diff --git a/app/src/main/java/umc/com/mobile/project/ui/home/HomeFragment.kt b/app/src/main/java/umc/com/mobile/project/ui/home/HomeFragment.kt
index ce980b49..6987dc85 100644
--- a/app/src/main/java/umc/com/mobile/project/ui/home/HomeFragment.kt
+++ b/app/src/main/java/umc/com/mobile/project/ui/home/HomeFragment.kt
@@ -61,6 +61,9 @@ class HomeFragment : Fragment() {
binding.layoutNextPlan.setOnClickListener {
navigate(R.id.action_fragment_home_to_planSettingFragment)
}
+ binding.constraintLayout3.setOnClickListener {
+ navigate(R.id.action_fragment_home_to_planSettingFragment)
+ }
}
private fun setupRecyclerView() {
@@ -87,11 +90,9 @@ class HomeFragment : Fragment() {
/**
* 기본 정보
*/
- binding.tvName.text = it?.result?.name
- binding.tvStdId.text = it?.result?.id.toString()
- binding.tvSchool.text = it?.result?.department
- binding.tvGrade.text = it?.result?.grade
- binding.tvStatus.text = it?.result?.status
+ binding.tvNameStdId.text = "${it?.result?.name} ${it?.result?.id.toString()}"
+ binding.tvSchool.text = "한성대학교 ${it?.result?.department}"
+ binding.tvGradeStatus.text = "${it?.result?.grade} ${it?.result?.status}"
binding.tvGraduateDday.text = it?.result?.dday.toString()
binding.tvCheeringWord.text = it?.result?.message
diff --git a/app/src/main/java/umc/com/mobile/project/ui/plan/PlanFreeFragment.kt b/app/src/main/java/umc/com/mobile/project/ui/plan/PlanFreeFragment.kt
index 9e52d868..ae8e0a56 100644
--- a/app/src/main/java/umc/com/mobile/project/ui/plan/PlanFreeFragment.kt
+++ b/app/src/main/java/umc/com/mobile/project/ui/plan/PlanFreeFragment.kt
@@ -4,14 +4,17 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
+import android.widget.Toast
import androidx.fragment.app.Fragment
+import androidx.fragment.app.activityViewModels
import androidx.fragment.app.viewModels
+import umc.com.mobile.project.data.model.plan.PlanFreeRequest
import umc.com.mobile.project.databinding.FragmentPlanFreeBinding
import umc.com.mobile.project.ui.plan.PlanViewModel
class PlanFreeFragment : Fragment() {
private var _binding: FragmentPlanFreeBinding? = null
- private val viewModel: PlanViewModel by viewModels()
+ private val viewModel: PlanViewModel by activityViewModels()
private val binding get() = _binding!!
override fun onCreateView(
@@ -19,11 +22,39 @@ class PlanFreeFragment : Fragment() {
): View {
_binding = FragmentPlanFreeBinding.inflate(inflater, container, false)
- viewModel.text.observe(viewLifecycleOwner) { text ->
- // Update your UI here with the LiveData update
- // Make sure 'textViewExample' matches the ID of the TextView in your layout
-// binding.textViewExample.text = text
+ // 버튼 클릭 이벤트 설정
+ binding.freeStoreButton.setOnClickListener {
+ val memoText = binding.planFreeMemo.text.toString()
+ if (memoText.isNotEmpty()) {
+ viewModel.postMemo(PlanFreeRequest(memo = memoText))
+ }
}
+
+ // 메모 저장 결과 관찰
+ viewModel.postMemoResult.observe(viewLifecycleOwner) { isSuccess ->
+ if (isSuccess) {
+ Toast.makeText(context, "메모가 성공적으로 저장되었습니다.", Toast.LENGTH_SHORT).show()
+ viewModel.getFreeInfo() // 저장 후 메모 정보 다시 불러오기
+ } else {
+ Toast.makeText(context, "메모 저장에 실패했습니다.", Toast.LENGTH_SHORT).show()
+ }
+ }
+
+ // 저장된 메모 정보를 불러와서 EditText에 표시
+ viewModel.planFreeInfo.observe(viewLifecycleOwner) { planFreeResponse ->
+ planFreeResponse?.result?.memo?.let {
+ binding.planFreeMemo.setText(it)
+ }
+ }
+
+ binding.editMemo.setOnClickListener {
+ val memoText = binding.planFreeMemo.text.toString()
+ if (memoText.isNotEmpty()) {
+ viewModel.editMemo(memoText) // 수정된 메모를 서버에 전송
+ }
+ }
+
+
return binding.root
}
@@ -32,3 +63,4 @@ class PlanFreeFragment : Fragment() {
_binding = null
}
}
+
diff --git a/app/src/main/java/umc/com/mobile/project/ui/plan/PlanRecyclerAdapter.kt b/app/src/main/java/umc/com/mobile/project/ui/plan/PlanRecyclerAdapter.kt
index b7dad88a..57440ad9 100644
--- a/app/src/main/java/umc/com/mobile/project/ui/plan/PlanRecyclerAdapter.kt
+++ b/app/src/main/java/umc/com/mobile/project/ui/plan/PlanRecyclerAdapter.kt
@@ -10,30 +10,39 @@ import umc.com.mobile.project.data.model.plan.TimeResult
import umc.com.mobile.project.databinding.ItemCertificateBinding
import umc.com.mobile.project.databinding.ItemTimeSubjectBinding
-class PlanRecyclerAdapter( timeList: List): RecyclerView.Adapter(){
- var timeList: List = timeList
- set(value) {
- field = value
- notifyDataSetChanged()
- //데이터가 바뀌었다 알려줌.
- }
-
+class PlanRecyclerAdapter(
+ private var timeList: List,
+ private val onAddButtonClicked: ((TimeResult?) -> Unit)? = null
+) : RecyclerView.Adapter() {
- override fun getItemCount(): Int {
- return timeList?.size ?: 0
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): NonSubjectViewHolder {
+ val itemBinding = ItemTimeSubjectBinding.inflate(LayoutInflater.from(parent.context), parent, false)
+ return NonSubjectViewHolder(itemBinding)
}
- override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PlanRecyclerAdapter.NonSubjectViewHolder {
- val itemBinding = ItemTimeSubjectBinding.inflate(LayoutInflater.from(parent.context), parent, false)
- return PlanRecyclerAdapter.NonSubjectViewHolder(itemBinding)
+ override fun onBindViewHolder(holder: NonSubjectViewHolder, position: Int) {
+ val timeResult = timeList[position]
+ holder.bind(timeResult, onAddButtonClicked)
}
- override fun onBindViewHolder(holder: PlanRecyclerAdapter.NonSubjectViewHolder, position: Int) {
+ override fun getItemCount(): Int = timeList.size
- holder.itemBinding.timeItemScore.text =timeList[position]?.searchCredit.toString()
- holder.itemBinding.timeItemSemester.text =timeList[position]?.searchGrade.toString()
- holder.itemBinding.timeItemSubject.text = timeList[position]?.searchName.toString()
+ fun updateTimeList(newTimeList: List) {
+ this.timeList = newTimeList
+ notifyDataSetChanged() // 데이터가 변경되었음을 알리고 UI를 갱신
}
- class NonSubjectViewHolder(val itemBinding: ItemTimeSubjectBinding) : RecyclerView.ViewHolder(itemBinding.root)
-}
\ No newline at end of file
+ class NonSubjectViewHolder(private val itemBinding: ItemTimeSubjectBinding) : RecyclerView.ViewHolder(itemBinding.root) {
+ fun bind(timeResult: TimeResult?, onAddButtonClicked: ((TimeResult?) -> Unit)?) {
+ itemBinding.timeItemSubject.text=timeResult?.searchName.toString()
+ itemBinding.timeItemSemester.text = timeResult?.searchGrade.toString()
+ val divisionAndCredit = "${timeResult?.searchType} / ${timeResult?.searchCredit}"
+ itemBinding.timeItemScore.text = divisionAndCredit
+
+ // 버튼 클릭 이벤트 설정
+ itemBinding.planTimeAddButton.setOnClickListener {
+ onAddButtonClicked?.invoke(timeResult)
+ }
+ }
+ }
+}
diff --git a/app/src/main/java/umc/com/mobile/project/ui/plan/PlanSemesterAdapter.kt b/app/src/main/java/umc/com/mobile/project/ui/plan/PlanSemesterAdapter.kt
index 912f19e5..4ea7acba 100644
--- a/app/src/main/java/umc/com/mobile/project/ui/plan/PlanSemesterAdapter.kt
+++ b/app/src/main/java/umc/com/mobile/project/ui/plan/PlanSemesterAdapter.kt
@@ -1,37 +1,40 @@
package umc.com.mobile.project.ui.plan
+import android.os.Bundle
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import umc.com.mobile.project.data.model.plan.semesterResult
import umc.com.mobile.project.databinding.ItemChooseSemesterBinding
-class PlanSemesterAdapter( semesterList: List): RecyclerView.Adapter(){
+class PlanSemesterAdapter(semesterList: List, private val onItemClick: (semesterResult) -> Unit): RecyclerView.Adapter() {
var semesterList: List = semesterList
set(value) {
field = value
notifyDataSetChanged()
- //데이터가 바뀌었다 알려줌.
}
-
override fun getItemCount(): Int {
- return semesterList?.size ?: 0
+ return semesterList.size
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PlanSemesterAdapter.NonSubjectViewHolder {
val itemBinding = ItemChooseSemesterBinding.inflate(LayoutInflater.from(parent.context), parent, false)
- return PlanSemesterAdapter.NonSubjectViewHolder(itemBinding)
+ return NonSubjectViewHolder(itemBinding)
}
override fun onBindViewHolder(holder: PlanSemesterAdapter.NonSubjectViewHolder, position: Int) {
-
val semesterInfo = semesterList[position]
if (semesterInfo != null) {
holder.itemBinding.planTimeSemesterItem.text = semesterInfo.hakkiText
}
-
+ holder.itemBinding.root.setOnClickListener {
+ if (semesterInfo != null) {
+ onItemClick(semesterInfo)
+ }
+ }
}
+
class NonSubjectViewHolder(val itemBinding: ItemChooseSemesterBinding) : RecyclerView.ViewHolder(itemBinding.root)
-}
\ No newline at end of file
+}
diff --git a/app/src/main/java/umc/com/mobile/project/ui/plan/PlanSemesterFragment.kt b/app/src/main/java/umc/com/mobile/project/ui/plan/PlanSemesterFragment.kt
index c173abbd..8c754399 100644
--- a/app/src/main/java/umc/com/mobile/project/ui/plan/PlanSemesterFragment.kt
+++ b/app/src/main/java/umc/com/mobile/project/ui/plan/PlanSemesterFragment.kt
@@ -1,68 +1,55 @@
package umc.com.mobile.project.ui.plan
-import android.content.res.ColorStateList
import android.os.Bundle
-import android.text.Editable
-import android.text.TextWatcher
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
-import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
+import androidx.fragment.app.activityViewModels
import androidx.fragment.app.viewModels
-import androidx.gridlayout.widget.GridLayout
-import umc.com.mobile.project.R
-import umc.com.mobile.project.databinding.FragmentPlanlicenseBinding
-import android.widget.EditText
-import androidx.core.view.setMargins
-import androidx.lifecycle.Observer
+import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.LinearLayoutManager
-
-import umc.com.mobile.project.data.model.plan.SavelicenseRequest
-import umc.com.mobile.project.data.model.plan.semesterResult
import umc.com.mobile.project.databinding.SemesterChooseBinding
-import java.time.LocalDate
+
+import umc.com.mobile.project.R
+
class PlanSemesterFragment : Fragment() {
private var _binding: SemesterChooseBinding? = null
- private val viewModel: PlanViewModel by viewModels()
+ private val viewModel: PlanViewModel by activityViewModels()
private val binding get() = _binding!!
- override fun onCreateView(
- inflater: LayoutInflater,
- container: ViewGroup?,
- savedInstanceState: Bundle?
- ): View {
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
_binding = SemesterChooseBinding.inflate(inflater, container, false)
-
-
-
-
-
return binding.root
}
-
-
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
+ viewModel.resetSemesterSelection() // 상태 초기화
- val adapter = PlanSemesterAdapter(listOf()) // 초기 데이터로 빈 리스트 사용
+ val adapter = PlanSemesterAdapter(emptyList()) { selectedItem ->
+ // ViewModel을 통해 hakki 값을 설정
+ viewModel.setHakki(selectedItem.hakkiNum)
+
+ // PlanTrackFragment로 화면 전환. Bundle 대신 ViewModel 사용
+ findNavController().navigate(R.id.action_planSemesterFragment_to_planTrackFragment)
+ }
- // RecyclerView에 어댑터와 레이아웃 매니저 설정
binding.recyclerViewPlanSemester.adapter = adapter
binding.recyclerViewPlanSemester.layoutManager = LinearLayoutManager(context)
-
viewModel.planSemesterInfo.observe(viewLifecycleOwner) { semesterInfo ->
- // 데이터가 업데이트되면 어댑터의 리스트 업데이트
adapter.semesterList = semesterInfo?.result ?: emptyList()
adapter.notifyDataSetChanged()
-
}
viewModel.getSemesterInfo() // 데이터 로드
+
+ binding.planSemesterBackspace.setOnClickListener {
+ findNavController().navigateUp()
+ }
}
override fun onDestroyView() {
@@ -70,5 +57,3 @@ class PlanSemesterFragment : Fragment() {
_binding = null
}
}
-
-
diff --git a/app/src/main/java/umc/com/mobile/project/ui/plan/PlanSettingFragment.kt b/app/src/main/java/umc/com/mobile/project/ui/plan/PlanSettingFragment.kt
index 51b01b19..b14bf819 100644
--- a/app/src/main/java/umc/com/mobile/project/ui/plan/PlanSettingFragment.kt
+++ b/app/src/main/java/umc/com/mobile/project/ui/plan/PlanSettingFragment.kt
@@ -1,43 +1,58 @@
package umc.com.mobile.project.ui.plan
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.activityViewModels
import androidx.fragment.app.viewModels
import androidx.lifecycle.Observer
+import androidx.navigation.fragment.findNavController
import androidx.viewpager.widget.ViewPager
import androidx.viewpager2.widget.ViewPager2
import com.google.android.material.tabs.TabLayout
import com.google.android.material.tabs.TabLayoutMediator
+import umc.com.mobile.project.R
import umc.com.mobile.project.databinding.FragmentSettingBinding
+import umc.com.mobile.project.databinding.PlanSubjectListBinding
import umc.com.mobile.project.databinding.PlanTimeTabMainBinding
+import umc.com.mobile.project.databinding.SemesterChooseBinding
import umc.com.mobile.project.ui.gradInfo.adapter.GradInfoVPAdapter
import umc.com.mobile.project.ui.gradInfo.viewmodel.GradInfoViewModel
class PlanSettingFragment : Fragment() {
- private var _binding:PlanTimeTabMainBinding? = null
- private val viewModel: PlanViewModel by viewModels()
+ private var _binding: PlanTimeTabMainBinding? = null
+ private val viewModel: PlanViewModel by activityViewModels()
private val binding get() = _binding!!
- private lateinit var viewPager : ViewPager2
- private lateinit var tabLayout : TabLayout
+ private lateinit var viewPager: ViewPager2
+ private lateinit var tabLayout: TabLayout
+
+ // 선택된 학기와 트랙 정보
+ private var selectedHakki: String = ""
+ private var selectedTrackId: String = ""
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
+ // PlanTimeTabMainBinding을 인플레이트하여 루트 뷰를 가져옴
_binding = PlanTimeTabMainBinding.inflate(inflater, container, false)
+ val view = binding.root
+
+
+ // 탭 레이아웃 및 뷰페이저 초기화
initTabLayout()
initViewPager()
-
- return binding.root
+ return view
}
+
private fun initTabLayout() {
val tabTitle = arrayOf("시간표", "자격증", "자유")
@@ -65,6 +80,24 @@ class PlanSettingFragment : Fragment() {
binding.viewPagerTimeTabMain.isUserInputEnabled = false
}
+ // 학기 및 트랙 선택 후 호출되는 함수
+// fun onSemesterAndTrackSelected(hakki: String, trackId: String) {
+// selectedHakki = hakki
+// selectedTrackId = trackId
+//
+// Log.d("PlanSettingFragment", "Selected Hakki: $hakki, TrackId: $trackId")
+//
+// }
+//
+//
+// fun navigateToPlanTrackFragment() {
+// val bundle = Bundle().apply {
+// putString("hakki", selectedHakki)
+// putString("trackId", selectedTrackId)
+// }
+// findNavController().navigate(R.id.action_planSettingFragment_to_planTimeFragment, bundle)
+// }
+
override fun onDestroyView() {
super.onDestroyView()
diff --git a/app/src/main/java/umc/com/mobile/project/ui/plan/PlanTimeAdapter.kt b/app/src/main/java/umc/com/mobile/project/ui/plan/PlanTimeAdapter.kt
new file mode 100644
index 00000000..6b143b95
--- /dev/null
+++ b/app/src/main/java/umc/com/mobile/project/ui/plan/PlanTimeAdapter.kt
@@ -0,0 +1,44 @@
+import android.view.LayoutInflater
+import android.view.ViewGroup
+import androidx.recyclerview.widget.DiffUtil
+import androidx.recyclerview.widget.ListAdapter
+import androidx.recyclerview.widget.RecyclerView
+import umc.com.mobile.project.data.model.plan.TimeResult
+import umc.com.mobile.project.databinding.ItemPlanTimeBinding
+
+class PlanTimeAdapter : ListAdapter(TimeResultDiffCallback()) {
+
+ // ViewHolder 클래스는 그대로 유지합니다.
+ class ViewHolder(private val binding: ItemPlanTimeBinding) : RecyclerView.ViewHolder(binding.root) {
+ fun bind(item: TimeResult) {
+ binding.timeKindTitle.text = item.searchType
+ binding.timeClassTitle.text = item.searchName
+ binding.timeGradeTitle.text = item.searchCredit.toString() // toString() 추가, 학점을 문자열로 표시
+ }
+ }
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
+ val binding = ItemPlanTimeBinding.inflate(LayoutInflater.from(parent.context), parent, false)
+ return ViewHolder(binding)
+ }
+
+ override fun onBindViewHolder(holder: ViewHolder, position: Int) {
+ val item = getItem(position)
+ holder.bind(item)
+ }
+
+ // 현재 데이터 리스트를 가져오는 편의 메서드를 추가합니다.
+ fun getCurrentData(): List {
+ return currentList
+ }
+
+ class TimeResultDiffCallback : DiffUtil.ItemCallback() {
+ override fun areItemsTheSame(oldItem: TimeResult, newItem: TimeResult): Boolean {
+ return oldItem.searchName == newItem.searchName
+ }
+
+ override fun areContentsTheSame(oldItem: TimeResult, newItem: TimeResult): Boolean {
+ return oldItem == newItem
+ }
+ }
+}
diff --git a/app/src/main/java/umc/com/mobile/project/ui/plan/PlanTimeFragment.kt b/app/src/main/java/umc/com/mobile/project/ui/plan/PlanTimeFragment.kt
index 8def1b7a..06982e7a 100644
--- a/app/src/main/java/umc/com/mobile/project/ui/plan/PlanTimeFragment.kt
+++ b/app/src/main/java/umc/com/mobile/project/ui/plan/PlanTimeFragment.kt
@@ -1,80 +1,83 @@
package umc.com.mobile.project.ui.plan
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.activityViewModels
import androidx.fragment.app.viewModels
-import androidx.lifecycle.Observer
-import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.LinearLayoutManager
import umc.com.mobile.project.R
-import umc.com.mobile.project.data.model.plan.TimeResult
-import umc.com.mobile.project.databinding.FragmentPlanTimeBinding
import umc.com.mobile.project.databinding.PlanSubjectListBinding
import umc.com.mobile.project.ui.common.NavigationUtil.navigate
-import umc.com.mobile.project.ui.plan.PlanViewModel
+
class PlanTimeFragment : Fragment() {
private var _binding: PlanSubjectListBinding? = null
- private val viewModel: PlanViewModel by viewModels()
+ private val viewModel: PlanViewModel by activityViewModels()
private val binding get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
): View {
_binding = PlanSubjectListBinding.inflate(inflater, container, false)
+ return binding.root
+ }
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ setupRecyclerView()
+ observeViewModel()
+ setupNavigation()
+ }
- viewModel.getListTimeInfo()
- val adapter = viewModel.listTimeInfo.value?.let { PlanRecyclerAdapter(it.result) }
-
- binding.recyclerView.adapter = adapter
- binding.recyclerView.layoutManager =
- LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)
-
-
+ private fun setupRecyclerView() {
+ val adapter = PlanRecyclerAdapter(emptyList(), onAddButtonClicked = { timeResult ->
- viewModel.listTimeInfo.observe(viewLifecycleOwner) { timenewList ->
- if (timenewList != null) {
- if (adapter != null) {
- adapter.timeList=timenewList.result
- adapter.notifyDataSetChanged()
- }
+ if (timeResult != null) {
+ viewModel.setSelectedTimeResult(timeResult)
}
+ })
-
+ binding.recyclerView.apply {
+ this.adapter = adapter
+ layoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)
}
+ }
+ private fun observeViewModel() {
+ // 학기(hakki)와 트랙(trackId) 정보 변경 감지
+ viewModel.hakki.observe(viewLifecycleOwner) { hakki ->
+ viewModel.track.value?.let { trackId ->
+ if (hakki.isNotEmpty() && trackId.isNotEmpty()) {
+ viewModel.getListTimeInfo(hakki, trackId)
+ }
+ }
+ }
-
- return binding.root
-
+ // listTimeInfo LiveData 관찰
+ viewModel.listTimeInfo.observe(viewLifecycleOwner) { timeListResponse ->
+ (binding.recyclerView.adapter as PlanRecyclerAdapter).updateTimeList(timeListResponse?.result ?: emptyList())
+ }
}
- override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
- super.onViewCreated(view, savedInstanceState)
-
+ private fun setupNavigation() {
+ binding.planTimeMoveTimetable.setOnClickListener {
+ navigate(R.id.action_planSettingFragment_to_planTimetableFragment)
+ }
binding.planSubjectListSemester.setOnClickListener {
-
- findNavController().navigate(R.id.action_planTimeFragment_to_planSemesterFragment)
+ navigate(R.id.action_planSettingFragment_to_planSemesterFragment)
}
}
-
-
-
-
-
-
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
-
}
diff --git a/app/src/main/java/umc/com/mobile/project/ui/plan/PlanTimetableFragment.kt b/app/src/main/java/umc/com/mobile/project/ui/plan/PlanTimetableFragment.kt
new file mode 100644
index 00000000..ce079f10
--- /dev/null
+++ b/app/src/main/java/umc/com/mobile/project/ui/plan/PlanTimetableFragment.kt
@@ -0,0 +1,95 @@
+package umc.com.mobile.project.ui.plan
+
+import PlanTimeAdapter
+import android.os.Bundle
+import android.util.Log
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.Toast
+import androidx.fragment.app.Fragment
+import androidx.fragment.app.activityViewModels
+import androidx.navigation.fragment.findNavController
+import androidx.recyclerview.widget.LinearLayoutManager
+import umc.com.mobile.project.databinding.PlanTimeMainBinding
+import umc.com.mobile.project.data.model.plan.AddTimeRequest
+import umc.com.mobile.project.data.model.plan.SemesterDto
+import umc.com.mobile.project.data.model.plan.SubjectDtoList
+
+class PlanTimetableFragment : Fragment() {
+
+ private var _binding: PlanTimeMainBinding? = null
+ private val binding get() = _binding!!
+ private val viewModel: PlanViewModel by activityViewModels()
+ private lateinit var adapter: PlanTimeAdapter
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View {
+ _binding = PlanTimeMainBinding.inflate(inflater, container, false)
+ return binding.root
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ setupRecyclerView()
+ setupSaveButton()
+ observeAddTimeResponse()
+
+ binding.planTimetableBackButton.setOnClickListener {
+ findNavController().navigateUp()
+ }
+ }
+
+ private fun setupRecyclerView() {
+ adapter = PlanTimeAdapter()
+ binding.recyclerView.layoutManager = LinearLayoutManager(context)
+ binding.recyclerView.adapter = adapter
+
+ viewModel.selectedTimeResults.observe(viewLifecycleOwner) { results ->
+ adapter.submitList(results.toList())
+ }
+ }
+
+ private fun setupSaveButton() {
+ binding.timeStoreButton.setOnClickListener {
+ val currentDataList = adapter.getCurrentData()
+
+ // 서버로 전송할 데이터 리스트를 기반으로 AddTimeRequest 객체를 생성합니다.
+ val subjectDtoList = currentDataList.map {
+ SubjectDtoList(
+ it.searchType,
+ it.searchName,
+ it.searchCredit
+ )
+ }
+ val addTimeRequest = AddTimeRequest(
+ SemesterDto(grade = 1, semester = 1),
+ subjectDtoList
+ ) // 예시값을 사용한 SemesterDto
+
+ // ViewModel의 addTime 메서드를 호출하여 서버로 데이터를 전송합니다.
+ viewModel.addTime(addTimeRequest)
+ }
+ }
+
+ private fun observeAddTimeResponse() {
+ viewModel.addTimeResponse.observe(viewLifecycleOwner) { response ->
+ if (response != null && response.isSuccess) {
+ Toast.makeText(context, "Data saved successfully!", Toast.LENGTH_SHORT).show()
+ Log.d("PlanTimetableFragment", "Data saved successfully: ${response.message}")
+ } else {
+ Toast.makeText(context, "Failed to save data.", Toast.LENGTH_SHORT).show()
+ Log.e("PlanTimetableFragment", "Failed to save data")
+ }
+ }
+ }
+
+ override fun onDestroyView() {
+ super.onDestroyView()
+ _binding = null
+ }
+ }
+
diff --git a/app/src/main/java/umc/com/mobile/project/ui/plan/PlanTrackAdapter.kt b/app/src/main/java/umc/com/mobile/project/ui/plan/PlanTrackAdapter.kt
index 3bbc6ae5..36570244 100644
--- a/app/src/main/java/umc/com/mobile/project/ui/plan/PlanTrackAdapter.kt
+++ b/app/src/main/java/umc/com/mobile/project/ui/plan/PlanTrackAdapter.kt
@@ -9,7 +9,8 @@ import umc.com.mobile.project.data.model.plan.semesterResult
import umc.com.mobile.project.databinding.ItemChooseSemesterBinding
import umc.com.mobile.project.databinding.ItemChooseTrackBinding
-class PlanTrackAdapter( trackList: List): RecyclerView.Adapter(){
+class PlanTrackAdapter(trackList: List, private val onItemClick: (TrackResult) -> Unit) : RecyclerView.Adapter() {
+
var trackList: List = trackList
set(value) {
field = value
@@ -18,6 +19,7 @@ class PlanTrackAdapter( trackList: List): RecyclerView.Adapter): RecyclerView.Adapter
+ if (hakkiValue.isNotEmpty()) {
+ Log.d("PlanTrackFragment", "Observed hakki value: $hakkiValue")
+ viewModel.getTrackInfo(hakkiValue)
+ }
+ }
+ // 클릭 리스너 정의
+ val onItemClick: (TrackResult) -> Unit = { selectedItem ->
+ // 옵저빙된 'hakkiValue' 사용
+ viewModel.hakki.value?.let { observedHakki ->
+ // 선택된 트랙 정보를 ViewModel에 저장
+ viewModel.setHakkiAndTrack(observedHakki, selectedItem.trackCode)
+ // PlanSettingFragment로 화면 전환
+ findNavController().navigate(R.id.action_planTrackFragment_to_planSettingFragment)
+ }
+ }
- return binding.root
- }
-
-
+ // Adapter 초기화 및 RecyclerView 설정
+ val adapter = PlanTrackAdapter(emptyList(), onItemClick)
+ binding.recyclerViewPlanTrack.adapter = adapter
+ binding.recyclerViewPlanTrack.layoutManager = LinearLayoutManager(context)
- override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
- super.onViewCreated(view, savedInstanceState)
+ // 트랙 정보 갱신 관찰
+ viewModel.planTrackInfo.observe(viewLifecycleOwner) { trackInfo ->
+ adapter.trackList = trackInfo?.result ?: emptyList()
+ adapter.notifyDataSetChanged()
+ }
+ // 뒤로 가기 버튼 리스너
+ binding.planTrackBackspace.setOnClickListener {
+ findNavController().navigateUp()
+ }
}
+
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}
-
-
diff --git a/app/src/main/java/umc/com/mobile/project/ui/plan/PlanViewModel.kt b/app/src/main/java/umc/com/mobile/project/ui/plan/PlanViewModel.kt
index 268e5193..fba47fdc 100644
--- a/app/src/main/java/umc/com/mobile/project/ui/plan/PlanViewModel.kt
+++ b/app/src/main/java/umc/com/mobile/project/ui/plan/PlanViewModel.kt
@@ -8,12 +8,20 @@ import androidx.lifecycle.ViewModel
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
+import umc.com.mobile.project.data.model.plan.AddTimeRequest
+import umc.com.mobile.project.data.model.plan.AddTimeResponse
import umc.com.mobile.project.data.model.plan.BringlicenseResponse
+import umc.com.mobile.project.data.model.plan.EditMemoRequest
import umc.com.mobile.project.data.model.plan.ListTimeResponse
+import umc.com.mobile.project.data.model.plan.PlanFreeRequest
+import umc.com.mobile.project.data.model.plan.PlanFreeResponse
+import umc.com.mobile.project.data.model.plan.PlanTrackResponse
import umc.com.mobile.project.data.model.plan.SaveInfo
import umc.com.mobile.project.data.model.plan.SavelicenseRequest
import umc.com.mobile.project.data.model.plan.SemesterTimeResponse
+import umc.com.mobile.project.data.model.plan.SubjectDtoList
+import umc.com.mobile.project.data.model.plan.TimeResult
import umc.com.mobile.project.data.model.plan.UPlicenseResponse
import umc.com.mobile.project.data.network.ApiClient
@@ -25,6 +33,27 @@ class PlanViewModel : ViewModel() {
//api
private val planApiService = ApiClient.createService()
+ private val _selectedTimeResults = MutableLiveData>()
+ val selectedTimeResults: LiveData> = _selectedTimeResults
+
+ fun setSelectedTimeResult(timeResult: TimeResult) {
+ val currentList = _selectedTimeResults.value ?: ArrayList()
+ currentList.add(timeResult)
+ _selectedTimeResults.value = currentList
+ Log.d("PlanTimetable", "setSelectedTimeResult: $timeResult")
+ }
+
+
+
+
+ private val _planFreeInfo: MutableLiveData = MutableLiveData()
+ val planFreeInfo: LiveData
+ get() = _planFreeInfo
+
+ private val _postMemoResult = MutableLiveData()
+ val postMemoResult: LiveData
+ get() = _postMemoResult
+
private val _hakki: MutableLiveData = MutableLiveData()
val hakki: LiveData
get() = _hakki
@@ -34,9 +63,16 @@ class PlanViewModel : ViewModel() {
get() = _track
- private val _planSemesterInfo : MutableLiveData = MutableLiveData()
- val planSemesterInfo :LiveData
- get()=_planSemesterInfo
+ private val _planSemesterInfo: MutableLiveData = MutableLiveData()
+ val planSemesterInfo: LiveData
+ get() = _planSemesterInfo
+
+ private val _planTrackInfo: MutableLiveData = MutableLiveData()
+ val planTrackInfo: LiveData
+ get() = _planTrackInfo
+
+ private val _timeTableInfo = MutableLiveData()
+ val timeTableInfo: LiveData = _timeTableInfo
private val _planTimeStatus: MutableLiveData = MutableLiveData()
@@ -55,9 +91,6 @@ class PlanViewModel : ViewModel() {
get() = _bringLicenseInfo
-
-
-
private val _licenseInfo: MutableLiveData = MutableLiveData()
val licenseInfo: LiveData
get() = _licenseInfo
@@ -68,9 +101,11 @@ class PlanViewModel : ViewModel() {
get() = _error
- private val _savelicenseInfo : MutableLiveData =MutableLiveData()
- val savelicenseInfo : LiveData
- get()=_savelicenseInfo
+ private val _savelicenseInfo: MutableLiveData = MutableLiveData()
+ val savelicenseInfo: LiveData
+ get() = _savelicenseInfo
+
+
// 기존에 있던 text LiveData
@@ -89,45 +124,136 @@ class PlanViewModel : ViewModel() {
fun updateIsFilledAllOptions(isFilled: Boolean) {
_isFilledAllOptions.value = isFilled
}
+ fun resetSemesterSelection() {
+ // 학기 정보 관련 상태 초기화
+ _planSemesterInfo.postValue(null) // 학기 정보 초기화
+ _hakki.postValue("") // 학기 식별자 초기화 (또는 적절한 초기 값으로 설정)
+ }
+ fun resetTrackSelection() {
+ // 선택된 트랙 정보 초기화
+ _track.postValue("") // 트랙 식별자 초기화 (또는 적절한 초기 값으로 설정)
+ }
- fun getListTimeInfo() {
- _hakki.value?.let {
- _track.value?.let { it1 ->
- planApiService.getListTime(it, it1).enqueue(object : Callback {
- override fun onResponse(
- call: Call,
- response: Response
- ) {
- if (response.isSuccessful) {
- if (response.body() != null) {
- _listTimeInfo.postValue(response.body())
- Log.d("Planlicense", "${response.body()}")
- } else {
- _error.postValue("서버 응답이 올바르지 않습니다.")
- }
- } else {
- _error.postValue("사용자 정보를 가져오지 못했습니다.")
- try {
- throw response.errorBody()?.string()?.let {
- RuntimeException(it)
- } ?: RuntimeException("Unknown error")
- } catch (e: Exception) {
- Log.e("PlanInfo", "PlanResponse API 오류: ${e.message}")
- }
- }
- }
+ fun setHakki(hakki: String) {
+ _hakki.value = hakki
+ Log.d("hakki value", "setHakki 호출됨: hakki=$hakki")
+ }
+
+
+ fun setHakkiAndTrack(hakki: String, trackId: String) {
+ Log.d("hakkitrackvalue", "setHakkiAndTrack 호출됨: hakki=$hakki, trackId=$trackId")
+ _hakki.value = hakki
+ _track.value = trackId
+ }
+
+ private val _addTimeResponse = MutableLiveData()
+ val addTimeResponse: MutableLiveData = _addTimeResponse
+
+ fun addTime(request: AddTimeRequest) {
+ planApiService.addTime(request).enqueue(object : Callback {
+ override fun onResponse(call: Call, response: Response) {
+ if (response.isSuccessful) {
+ // 서버로부터 응답을 성공적으로 받았을 때 LiveData 업데이트
+ Log.d("TimeTableApi", "getListTimeInfo 성공: ${response.body()}")
+ _addTimeResponse.postValue(response.body())
+ } else {
+ // 에러 처리: 실패 응답 처리
+ Log.e("TimeTableApi", "Error posting memo: ${response.errorBody()?.string()}")
+ _addTimeResponse.postValue(null)
+ }
+ }
+
+ override fun onFailure(call: Call, t: Throwable) {
+ // 네트워크 에러 처리: LiveData 업데이트로 에러 상태 전달 가능
+ _addTimeResponse.postValue(null)
+ }
+ })
+ }
- override fun onFailure(call: Call, t: Throwable) {
- _error.postValue("네트워크 오류: ${t.message}")
- Log.d("gradInfo", "completion: ${t.message}")
+
+
+
+
+ fun postMemo(memoRequest: PlanFreeRequest) {
+ planApiService.postFreeMemo(memoRequest).enqueue(object : Callback {
+ override fun onResponse(
+ call: Call,
+ response: Response
+ ) {
+ if (response.isSuccessful) {
+ // API 호출 성공 시, 성공 LiveData 업데이트
+ _postMemoResult.postValue(true)
+ } else {
+ // 실패 시, 실패 LiveData 업데이트
+ Log.e("PlanViewModel", "Error posting memo: ${response.errorBody()?.string()}")
+ _postMemoResult.postValue(false)
+ }
+ }
+
+ override fun onFailure(call: Call, t: Throwable) {
+ // 네트워크 오류 등으로 호출 실패 시, 실패 LiveData 업데이트
+ _postMemoResult.postValue(false)
+ }
+ })
+ }
+
+
+ fun getFreeInfo() {
+ planApiService.getFreeInfo().enqueue(object : Callback {
+ override fun onResponse(
+ call: Call,
+ response: Response
+ ) {
+ if (response.isSuccessful) {
+ if (response.body() != null) {
+ _planFreeInfo.postValue(response.body())
+ Log.d("PlanFree", "${response.body()}")
+ } else {
+ _error.postValue("서버 응답이 올바르지 않습니다.")
+ }
+ } else {
+ _error.postValue("사용자 정보를 가져오지 못했습니다.")
+ try {
+ throw response.errorBody()?.string()?.let {
+ RuntimeException(it)
+ } ?: RuntimeException("Unknown error")
+ } catch (e: Exception) {
+ Log.e("PlanInfo", "PlanResponse API 오류: ${e.message}")
}
- })
+ }
+ }
+
+ override fun onFailure(call: Call, t: Throwable) {
+ _error.postValue("네트워크 오류: ${t.message}")
+ Log.d("gradInfo", "completion: ${t.message}")
+ }
+ })
+ }
+
+
+ fun getListTimeInfo(hakki: String, track: String) {
+ Log.d("PlanViewModel", "getListTimeInfo 호출됨: hakki=$hakki, track=$track")
+ planApiService.getListTime(hakki, track).enqueue(object : Callback {
+ override fun onResponse(call: Call, response: Response) {
+ if (response.isSuccessful && response.body() != null) {
+ Log.d("PlanViewModel", "getListTimeInfo 성공: ${response.body()}")
+ _listTimeInfo.postValue(response.body())
+ } else {
+ Log.e("PlanViewModel", "getListTimeInfo 실패: ${response.errorBody()?.string()}")
+ _error.postValue("리스트 정보를 가져오는데 실패했습니다.")
+ }
}
- }
+
+ override fun onFailure(call: Call, t: Throwable) {
+ Log.e("PlanViewModel", "getListTimeInfo 네트워크 오류: ${t.message}")
+ _error.postValue("네트워크 오류: ${t.message}")
+ }
+ })
}
+
fun getLicenseInfo() {
planApiService.getUPlicense().enqueue(object : Callback {
override fun onResponse(
@@ -164,7 +290,8 @@ class PlanViewModel : ViewModel() {
fun saveLicense(request: List) {
planApiService.saveLicense(request).enqueue(object : Callback {
- override fun onResponse(call: Call, response: Response
+ override fun onResponse(
+ call: Call, response: Response
) {
if (response.isSuccessful) {
_bringLicenseInfo.postValue(response.body())
@@ -186,7 +313,6 @@ class PlanViewModel : ViewModel() {
}
-
fun getSemesterInfo() {
planApiService.getSemesterInfo().enqueue(object : Callback {
override fun onResponse(
@@ -218,6 +344,64 @@ class PlanViewModel : ViewModel() {
}
})
}
+
+
+ fun getTrackInfo(hakki: String) {
+ planApiService.getTrackInfo(hakki).enqueue(object : Callback {
+ override fun onResponse(
+ call: Call,
+ response: Response
+ ) {
+ if (response.isSuccessful) {
+ if (response.body() != null) {
+ _planTrackInfo.postValue(response.body())
+ Log.d("PlanTrackInfo", "${response.body()}")
+ } else {
+ _error.postValue("서버 응답이 올바르지 않습니다.")
+ }
+ } else {
+ _error.postValue("사용자 정보를 가져오지 못했습니다.")
+ try {
+ throw response.errorBody()?.string()?.let {
+ RuntimeException(it)
+ } ?: RuntimeException("Unknown error")
+ } catch (e: Exception) {
+ Log.e("PlanInfo", "PlanResponse API 오류: ${e.message}")
+ }
+ }
+ }
+
+ override fun onFailure(call: Call, t: Throwable) {
+ _error.postValue("네트워크 오류: ${t.message}")
+ Log.d("gradInfo", "completion: ${t.message}")
+ }
+ })
+ }
+
+
+ fun editMemo(memo: String) {
+ val editMemoRequest = EditMemoRequest(memo = memo)
+ planApiService.editMemo(editMemoRequest).enqueue(object : Callback {
+ override fun onResponse(
+ call: Call,
+ response: Response
+ ) {
+ if (response.isSuccessful) {
+ Log.d("PlanMemoEdit", "Memo successfully edited: ${response.body()}")
+ // 필요한 경우, UI 업데이트를 위한 LiveData 업데이트 로직을 여기에 추가하세요.
+ } else {
+ Log.e("PlanMemoEdit", "Failed to edit memo: ${response.errorBody()?.string()}")
+ }
+ }
+
+ override fun onFailure(call: Call, t: Throwable) {
+ Log.e("PlanMemoEdit", "Network error on edit memo: ${t.message}")
+ }
+ })
+ }
+
+
+
}
@@ -235,3 +419,5 @@ class PlanViewModel : ViewModel() {
+
+
diff --git a/app/src/main/java/umc/com/mobile/project/ui/plan/PlanlicenseFragment.kt b/app/src/main/java/umc/com/mobile/project/ui/plan/PlanlicenseFragment.kt
index 92f2d90e..d2f62494 100644
--- a/app/src/main/java/umc/com/mobile/project/ui/plan/PlanlicenseFragment.kt
+++ b/app/src/main/java/umc/com/mobile/project/ui/plan/PlanlicenseFragment.kt
@@ -10,13 +10,14 @@ import android.view.View
import android.view.ViewGroup
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
+import androidx.fragment.app.activityViewModels
import androidx.fragment.app.viewModels
import umc.com.mobile.project.R
import umc.com.mobile.project.databinding.FragmentPlanlicenseBinding
class PlanlicenseFragment : Fragment() {
private var _binding: FragmentPlanlicenseBinding? = null
- private val viewModel: PlanViewModel by viewModels()
+ private val viewModel: PlanViewModel by activityViewModels()
private val binding get() = _binding!!
override fun onCreateView(
diff --git a/app/src/main/res/drawable/plan_time_back.xml b/app/src/main/res/drawable/plan_time_back.xml
new file mode 100644
index 00000000..b7400623
--- /dev/null
+++ b/app/src/main/res/drawable/plan_time_back.xml
@@ -0,0 +1,13 @@
+
+
+
diff --git a/app/src/main/res/drawable/plan_time_move_table.xml b/app/src/main/res/drawable/plan_time_move_table.xml
new file mode 100644
index 00000000..b4740ef8
--- /dev/null
+++ b/app/src/main/res/drawable/plan_time_move_table.xml
@@ -0,0 +1,11 @@
+
+
+
diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml
index 29b250bb..7b854dcb 100644
--- a/app/src/main/res/layout/activity_login.xml
+++ b/app/src/main/res/layout/activity_login.xml
@@ -74,7 +74,8 @@
android:paddingTop="18dp"
android:paddingBottom="18dp"
android:singleLine="true"
- android:text="@={vm.id}" />
+ android:text="@={vm.id}"
+ android:theme="@style/EditText.DarkMode" />
@@ -114,7 +115,8 @@
android:paddingTop="18dp"
android:paddingBottom="18dp"
android:singleLine="true"
- android:text="@={vm.pw}" />
+ android:text="@={vm.pw}"
+ android:theme="@style/EditText.DarkMode" />
diff --git a/app/src/main/res/layout/fragment_grade.xml b/app/src/main/res/layout/fragment_grade.xml
index d3beceda..f3a597d5 100644
--- a/app/src/main/res/layout/fragment_grade.xml
+++ b/app/src/main/res/layout/fragment_grade.xml
@@ -326,7 +326,8 @@
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginTop="9dp"
- android:background="@color/selector_selected_gray_else_white"
+ android:layout_marginBottom="13dp"
+ app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tv_grade_average_title"
tools:listitem="@layout/item_average_grade" />
@@ -335,7 +336,6 @@
android:id="@+id/layout_average"
android:layout_width="0dp"
android:layout_height="0dp"
- android:layout_marginStart="9dp"
android:layout_marginTop="15dp"
android:layout_marginEnd="19dp"
android:background="@drawable/bg_stroke_gray_radius_16_5"
@@ -348,30 +348,36 @@
app:layout_constraintStart_toEndOf="@+id/recyclerView2"
app:layout_constraintTop_toBottomOf="@+id/tv_grade_average_title">
-
+ app:layout_constraintTop_toTopOf="parent">
+
+
+
+
+
+
-
diff --git a/app/src/main/res/layout/fragment_home.xml b/app/src/main/res/layout/fragment_home.xml
index 315c3a26..f2c0a06e 100644
--- a/app/src/main/res/layout/fragment_home.xml
+++ b/app/src/main/res/layout/fragment_home.xml
@@ -107,7 +107,7 @@
-
-
-
-
+ app:layout_constraintTop_toBottomOf="@+id/tv_name_stdId" />
+
+
+ app:columnCount="2"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toTopOf="parent"
+ app:rowCount="5">
-
-
@@ -63,6 +63,16 @@
android:layout_marginTop="29dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintTop_toBottomOf="@id/appCompatImageView4" />
+ app:layout_constraintTop_toBottomOf="@id/appCompatImageView_memo" />
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/item_average_grade.xml b/app/src/main/res/layout/item_average_grade.xml
index 07d94c89..960c0b3d 100644
--- a/app/src/main/res/layout/item_average_grade.xml
+++ b/app/src/main/res/layout/item_average_grade.xml
@@ -11,20 +11,24 @@
diff --git a/app/src/main/res/layout/item_time_subject.xml b/app/src/main/res/layout/item_time_subject.xml
index f80c954a..d5e2f376 100644
--- a/app/src/main/res/layout/item_time_subject.xml
+++ b/app/src/main/res/layout/item_time_subject.xml
@@ -29,17 +29,17 @@
+ app:layout_constraintTop_toBottomOf="@id/time_item_semester" />
-
+ android:layout_marginBottom="60dp"
+ android:layout_marginRight="10dp"
+ android:background="@drawable/plan_time_move_table"
+ />
+
-
-
-
+ />
+
+ />
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/plan_time_choose_track.xml b/app/src/main/res/layout/plan_time_choose_track.xml
index 9f4d994d..2399f895 100644
--- a/app/src/main/res/layout/plan_time_choose_track.xml
+++ b/app/src/main/res/layout/plan_time_choose_track.xml
@@ -47,9 +47,10 @@
+
+
+
+
+
+
+ >
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/semester_choose.xml b/app/src/main/res/layout/semester_choose.xml
index 7a4ae24f..7b632b45 100644
--- a/app/src/main/res/layout/semester_choose.xml
+++ b/app/src/main/res/layout/semester_choose.xml
@@ -1,10 +1,17 @@
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
\ No newline at end of file
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/navigation/mobile_navigation.xml b/app/src/main/res/navigation/mobile_navigation.xml
index 0323287e..760d2697 100644
--- a/app/src/main/res/navigation/mobile_navigation.xml
+++ b/app/src/main/res/navigation/mobile_navigation.xml
@@ -241,18 +241,43 @@
+
+
+
+ android:label="PlanSemesterFragment" >
+
+
+ android:id="@+id/planTrackFragment"
+ android:name="PlanTrackFragment"
+ android:label="PlanTrackFragment" >
+ android:id="@+id/action_planTrackFragment_to_planTimeFragment"
+ app:destination="@id/planTimeFragment" />
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values-night/themes.xml b/app/src/main/res/values-night/themes.xml
index 00cceb1d..06dbe6fc 100644
--- a/app/src/main/res/values-night/themes.xml
+++ b/app/src/main/res/values-night/themes.xml
@@ -2,15 +2,51 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml
index 676b1094..06dbe6fc 100644
--- a/app/src/main/res/values/themes.xml
+++ b/app/src/main/res/values/themes.xml
@@ -44,4 +44,9 @@
- @drawable/custom_dialog_background
- @android:color/transparent
+
+
+
\ No newline at end of file