본문 바로가기

[TIL][내일배움캠프]

[내일배움캠프][TIL] 24.03.13 (수) - 최종 프로젝트 4주차 : 추가 구현

1. 최종 프로젝트 4주차

 

어제는 추가 구현 중에서 뭘 할 것인지에 대해서 이야기를 나누었다.

 

오늘은 어제 회의를 바탕으로 추가적인 기능들을 구현하고, 보완하는 시간을 가졌다.

 

 

Repository 통합

 

우선은 불필요하게 중복된 Repository를 하나로 통합하는 작업부터 했다.

 

class SanListRepository {
    companion object {
        private const val TAG = "SanListRepository"
    }

    // db 인스턴스 생성
    private val db: FirebaseFirestore = FirebaseFirestore.getInstance()

    // 산 리스트 변수
    private val _sanListDTO: MutableLiveData<List<SanDTO>> =
        MutableLiveData<List<SanDTO>>()
    val sanListDTO: LiveData<List<SanDTO>> = _sanListDTO

    // HomeFragment 변수
    private val _recItems: MutableLiveData<ArrayList<HomeUiState>> = MutableLiveData()
    val recItems: LiveData<ArrayList<HomeUiState>> = _recItems

    // San Detail Activity

    private val _detailInfo: MutableLiveData<SanDetailDTO> = MutableLiveData()
    val detailInfo: LiveData<SanDetailDTO> = _detailInfo


    // 초기 실행
    init {
        Log.d(TAG, "init 함수")
        initPush(0)
    }


    fun editSelectedItem(selectedItem: SanDTO) {
        val position = sanListDTO.value?.indexOf(selectedItem)
        if (position != null) {
            initPush(position)
        } else {
            Log.d(TAG, "선택된 아이템이 인덱스가 널임 ? ")
        }
    }


//    suspend fun editsanDTO(index: Int) {
//        initPush(index)
//    }

    fun getSelectedItemFromRepository(sanName: String?) {
        if (sanName.isNullOrBlank()) {
            Log.d(TAG, "getSelectedItemFromRepository: null sanName")
        } else {
            setSanDetail(sanName)
        }
        Log.d(TAG, "getSelectedItemFromRepository: $sanName")
    }

    fun initPush(index: Int) {

        Log.d(TAG, "initPush 함수 여기에서 데이터베이스에 있는 값 접근")

        db.collection("sanlist").get().addOnSuccessListener { documents ->

            // 산 리스트 DTO를 가져와주는 함수
            setSanListData(index, documents)
            // 홈 화면에 추천 산을 가져와주는 함수
            setHomeData(documents)
        }

    }

    private fun setSanDetail(sanName: String) {
        db.collection("sanlist").get().addOnSuccessListener { documents ->
            documents?.forEach { document ->
                val sanList = SanDetailDTO(
                    document.getString("name") ?: "none",
                    document.getString("address") ?: "none",
                    document.getLong("difficulty") ?: 0,
                    document.getDouble("height") ?: 0.0,
                    document.getLong("time_uphill") ?: 0,
                    document.getLong("time_downhill") ?: 0,
                    document.getString("summary") ?: "none",
                    document.getString("recommend") ?: "none",
                    document["images"] as ArrayList<String>,
                    document.getBoolean("isLiked") ?: false
                )
                if (sanList.mountain == sanName) {
                    _detailInfo.value = sanList
                    Log.d(
                        TAG, "initSanData: $sanList -> ${detailInfo.value}"
                    )
                }
            }
        }
    }

    private fun setHomeData(documents: QuerySnapshot) {
        val rvItems: ArrayList<HomeUiState> = arrayListOf()

        documents.forEach { document ->

            val rec = HomeUiState(
                document.getString("address") ?: "",
                document.getLong("difficulty") ?: 0,
                document.getLong("height") ?: 0,
                document["images"] as ArrayList<String>,
                document.getBoolean("isLiked") ?: false,
                document.getString("name") ?: "",
                document.getString("recommend") ?: "",
                document.getString("summary") ?: "",
                document.getLong("time_downhill") ?: 0,
                document.getLong("time_uphill") ?: 0,
            )
            if (document.getField<Boolean>("isLiked") == true) {
                rvItems.add(rec)

                //데이터 로딩이 완료되면 리사이클러 뷰를 업데이트 한다
//                        updateRecyclerView()
            }
            _recItems.value = rvItems
            Log.d(TAG, "rv : ${recItems.value?.size}")


        }
    }


    private fun setSanListData(index: Int, documents: QuerySnapshot?) {
        val sanArrayList: ArrayList<SanDTO> = arrayListOf()

        if (documents != null) {
            for (i in documents.documents.indices) {
                val sanInfo = documents.documents[i]
                //////////
                sanArrayList.add(
                    SanDTO(
                        sanImage = sanInfo["images"] as ArrayList<String>,
                        sanName = sanInfo["name"] as String,
                        sanDifficulty = sanInfo["difficulty"] as Long?,
                        sanHeight = sanInfo.getLong("height") ?: 0,
                        sanTimeTotal = (sanInfo["time_uphill"] as Long) + (sanInfo["time_downhill"] as Long),
                        sanSelected = false
                    )
                )

            }
        }

        Log.d(
            TAG,
            "DocumentSnapshot Data: ${documents?.documents}"
        ) // HashMap 타입으로 값을 받아옴. 이 그대로 저장해줘도 될듯?

        sanArrayList[index].sanSelected = true

        Log.d(TAG, "값 다 가져옴 $sanArrayList")
        _sanListDTO.value = sanArrayList

    }
}

 

우선, 하나의 공통된 DB를 선언하고, 각 data class마다 하나의 DB를 연결시켜서 적용시키게 했다.

 

 

레벨 & 업적 UI

 

다음으로, 추가 구현 기능 중의 하나인 레벨과 업적 기능의 UI를 우선 만들어봤다.

 

레벨 UI (다이얼로그)
업적 UI (액티비티?)

 

이걸 우선 만들어봤다.

 

업적 부분은 산과 업적 부분을 RecyclerView로 구현하였다.

(왜 둘 다 산이냐면 listitem을 똑같은 걸로 썼다...)

그리고 업적에 있는 저 게이지 부분은 ProgressBar로 구현하려 하는데 과연 될는지...?

 

 

이제 이 외에도 DetailActivity에서 산 개요와 추천 이유가 적힌 부분을 Accodian 메뉴로 수정하는 작업도 진행 중에 있다.

그 결과는 내일 공개 예정...!