Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feat] 메인 지도 뷰 카드 구현 #40

Merged
merged 27 commits into from
Jan 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
1becc47
[add] #31 메인 지도 뷰 카드 구현을 위한 dimens 추가
jihyunniiii Jan 5, 2024
331424d
[add] #31 메인 지도 뷰 카드 구현을 위한 drawable 리소스 추가
jihyunniiii Jan 5, 2024
8f07327
[add] #31 메인 지도 뷰 카드 구현을 위한 color selector 리소스 추가
jihyunniiii Jan 5, 2024
d9610da
[add] #31 메인 지도 뷰 카드 구현을 위한 string 리소스 추가
jihyunniiii Jan 5, 2024
75f45d1
[chore] #31 button s theme 수정
jihyunniiii Jan 5, 2024
c4291fc
[feat] #31 메인 지도 뷰 카드 구현 (ui)
jihyunniiii Jan 5, 2024
50163a8
[add] #31 dimens 추가
jihyunniiii Jan 5, 2024
9319ca9
Merge branch 'develop' into feat-main-map-card
jihyunniiii Jan 5, 2024
8fd9ada
[feat] #31 모달 종료 시 실행되는 함수 추가
jihyunniiii Jan 5, 2024
ba4c6a1
[feat] #31 card customView
jihyunniiii Jan 5, 2024
cc74003
[feat] #31 String -> category 반환 함수 구현
jihyunniiii Jan 5, 2024
ce97cb0
[add] #31 map cancel 모달 구현을 위한 스트링 리소스 추가
jihyunniiii Jan 5, 2024
7e1ac86
[add] #31 shape_oval_stroke_1.xml stroke 색상 변경
jihyunniiii Jan 5, 2024
694a46b
[feat] #31 PingleEntity
jihyunniiii Jan 5, 2024
6281026
[feat] #31 카드 - 모달 연결 구현
jihyunniiii Jan 5, 2024
cbff2be
[feat] #31 dummyData 추가
jihyunniiii Jan 5, 2024
6c8b03c
[chore] #31 CategoryType 네이밍 수정
jihyunniiii Jan 5, 2024
ba4b11e
[chore] #31 convertToCalenderDetail 함수 공백 추가
jihyunniiii Jan 5, 2024
58071f2
[chore] #31 ktintFormat
jihyunniiii Jan 5, 2024
a945e52
[chore] #31 card middle line 마진 수정
jihyunniiii Jan 5, 2024
9233886
Merge branch 'develop' into feat-main-map-card
jihyunniiii Jan 6, 2024
69b5994
[feat] #31 폰트 스타일 추가
jihyunniiii Jan 6, 2024
ca39761
[chore] #31 card view 변경된 폰트 스타일 적용
jihyunniiii Jan 6, 2024
f500d7c
[chore] #31 button s theme 수정
jihyunniiii Jan 6, 2024
ef95fe8
[chore] #31 ktlintFormat
jihyunniiii Jan 6, 2024
4216c4a
[chore] #31 card layout 수정
jihyunniiii Jan 6, 2024
2404efa
Merge branch 'develop' into feat-main-map-card
jihyunniiii Jan 7, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions app/src/main/java/org/sopt/pingle/domain/model/PingleEntity.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package org.sopt.pingle.domain.model

data class PingleEntity(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

네이밍이 어떤 엔티티인지 잘 알아보기 어려운거 같은데 수정하는건 어떨까염!

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저도 이 부분 알아보기 좀 힘들다구 느꼈어여ㅜ,ㅜ

val id: Long,
val category: String,
val name: String,
val ownerName: String,
val location: String,
val date: String,
val startAt: String,
val endAt: String,
val maxParticipants: Int,
val curParticipants: Int,
val isParticipating: Boolean,
val chatLink: String
)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

카테고리 타입 쓰는 거 진짜 좋은 것 같아요

Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,16 @@ enum class CategoryType(
backgroundBadgeColor = R.color.badge_yellow,
categoryNameRes = R.string.category_multi
),
OTHER(
OTHERS(
textColor = R.color.g_01,
activatedOutLinedColor = R.color.g_01,
backgroundChipColor = R.color.g_10,
backgroundBadgeColor = R.color.g_07,
categoryNameRes = R.string.category_others
)
);

companion object {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

우앙 이렇게두 되는군욤 이런건 보통 어떤 경우에 이렇게 상ㅇ하낭?

fun fromString(categoryName: String) =
CategoryType.values().first() { it.name == categoryName }
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.sopt.pingle.presentation.ui.common

import android.content.DialogInterface
import android.os.Bundle
import android.view.View
import org.sopt.pingle.R
Expand All @@ -12,7 +13,8 @@ class AllModalDialogFragment(
private val buttonText: String,
private val textButtonText: String,
private val clickBtn: () -> Unit,
private val clickTextBtn: () -> Unit
private val clickTextBtn: () -> Unit,
private val onDialogClosed: () -> Unit = {}
) : BindingDialogFragment<DialogAllModalBinding>(R.layout.dialog_all_modal) {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
Expand All @@ -21,6 +23,11 @@ class AllModalDialogFragment(
addListeners()
}

override fun onDismiss(dialog: DialogInterface) {
super.onDismiss(dialog)
onDialogClosed()
}

private fun initLayout() {
with(binding) {
tvAllModalTitle.text = title
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,13 @@ import org.sopt.pingle.R
import org.sopt.pingle.databinding.FragmentMapBinding
import org.sopt.pingle.presentation.mapper.toMarker
import org.sopt.pingle.presentation.type.CategoryType
import org.sopt.pingle.presentation.ui.common.AllModalDialogFragment
import org.sopt.pingle.util.base.BindingFragment
import org.sopt.pingle.util.component.OnPingleCardClickListener
import org.sopt.pingle.util.component.PingleChip
import org.sopt.pingle.util.fragment.navigateToWebView
import org.sopt.pingle.util.fragment.showToast
import org.sopt.pingle.util.fragment.stringOf

class MapFragment : BindingFragment<FragmentMapBinding>(R.layout.fragment_map), OnMapReadyCallback {
private val mapViewModel by viewModels<MapViewModel>()
Expand Down Expand Up @@ -79,7 +83,20 @@ class MapFragment : BindingFragment<FragmentMapBinding>(R.layout.fragment_map),
chipMapCategoryPlay.setChipCategoryType(CategoryType.PLAY)
chipMapCategoryStudy.setChipCategoryType(CategoryType.STUDY)
chipMapCategoryMulti.setChipCategoryType(CategoryType.MULTI)
chipMapCategoryOthers.setChipCategoryType(CategoryType.OTHER)
chipMapCategoryOthers.setChipCategoryType(CategoryType.OTHERS)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OTHERS로 다 바꾼거 완전 꼼꼼핑

cardMap.initLayout(mapViewModel.dummyPingle)
cardMap.listener = object : OnPingleCardClickListener {
override fun onPingleCardChatBtnClickListener() {
startActivity(navigateToWebView(mapViewModel.dummyPingle.chatLink))
}

override fun onPingleCardParticipateBtnClickListener() {
when (mapViewModel.dummyPingle.isParticipating) {
true -> showMapCancelModalDialogFragment()
false -> showMapModalDialogFragment()
}
}
}
}
}

Expand Down Expand Up @@ -168,12 +185,38 @@ class MapFragment : BindingFragment<FragmentMapBinding>(R.layout.fragment_map),
}
}

private fun showMapCancelModalDialogFragment() {
AllModalDialogFragment(
title = stringOf(R.string.map_cancel_modal_title),
detail = stringOf(R.string.map_cancel_modal_detail),
buttonText = stringOf(R.string.map_cancel_modal_button_text),
textButtonText = stringOf(R.string.map_cancel_modal_text_button_text),
clickBtn = { mapViewModel.cancelPingle() },
clickTextBtn = { },
onDialogClosed = { binding.cardMap.initLayout(mapViewModel.dummyPingle) }
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

프래그먼트 이런 식으로 쓰는거 진짜 깔끔하구 좋당..

).show(childFragmentManager, MAP_CANCEL_MODAL)
}

private fun showMapModalDialogFragment() {
with(mapViewModel.dummyPingle) {
MapModalDialogFragment(
category = CategoryType.fromString(categoryName = category),
name = name,
ownerName = ownerName,
clickBtn = { mapViewModel.joinPingle() },
onDialogClosed = { binding.cardMap.initLayout(mapViewModel.dummyPingle) }
).show(childFragmentManager, MAP_MODAL)
}
}

companion object {
private const val LOCATION_PERMISSION_REQUEST_CODE = 1000
private val LOCATION_PERMISSIONS = arrayOf(
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION
)
private const val SINGLE_SELECTION = 0
private const val MAP_CANCEL_MODAL = "mapCancelModal"
private const val MAP_MODAL = "mapModal"
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.sopt.pingle.presentation.ui.main.home.map

import android.content.DialogInterface
import android.os.Bundle
import android.view.View
import org.sopt.pingle.R
Expand All @@ -12,7 +13,8 @@ class MapModalDialogFragment(
private val category: CategoryType,
private val name: String,
private val ownerName: String,
private val clickBtn: () -> Unit
private val clickBtn: () -> Unit,
private val onDialogClosed: () -> Unit = {}
) : BindingDialogFragment<DialogMapModalBinding>(R.layout.dialog_map_modal) {

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
Expand All @@ -22,6 +24,11 @@ class MapModalDialogFragment(
addListeners()
}

override fun onDismiss(dialog: DialogInterface) {
super.onDismiss(dialog)
onDialogClosed.invoke()
}

private fun initLayout() {
with(binding) {
badgeMapModalPingleInfoCategory.setBadgeCategoryType(category)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import androidx.lifecycle.ViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import org.sopt.pingle.domain.model.PinEntity
import org.sopt.pingle.domain.model.PingleEntity
import org.sopt.pingle.presentation.type.CategoryType

class MapViewModel() : ViewModel() {
Expand Down Expand Up @@ -38,10 +39,59 @@ class MapViewModel() : ViewModel() {
)
)

var dummyPingle = PingleEntity(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

더미데이터 댕기욥다 ㅋㅅㅋ

id = 1,
category = "PLAY",
name = "핑글핑글핑글 ~",
ownerName = "배지현",
location = "길음역",
date = "2023-01-06",
startAt = "10:30:00",
endAt = "22:34:00",
maxParticipants = 5,
curParticipants = 4,
isParticipating = false,
chatLink = "https://github.com/TeamPINGLE/PINGLE-ANDROID"
)

private val _category = MutableStateFlow<CategoryType?>(null)
val category get() = _category.asStateFlow()

fun setCategory(category: CategoryType?) {
_category.value = category
}

fun cancelPingle() {
dummyPingle = PingleEntity(
id = 1,
category = "PLAY",
name = "핑글핑글핑글 ~",
ownerName = "배지현",
location = "길음역",
date = "2023-01-06",
startAt = "10:30:00",
endAt = "22:34:00",
maxParticipants = 5,
curParticipants = 4,
isParticipating = false,
chatLink = "https://github.com/TeamPINGLE/PINGLE-ANDROID"
)
}

fun joinPingle() {
dummyPingle = PingleEntity(
id = 1,
category = "PLAY",
name = "핑글핑글핑글 ~",
ownerName = "배지현",
location = "길음역",
date = "2023-01-06",
startAt = "10:30:00",
endAt = "22:34:00",
maxParticipants = 5,
curParticipants = 5,
isParticipating = true,
chatLink = "https://github.com/TeamPINGLE/PINGLE-ANDROID"
)
}
}
132 changes: 132 additions & 0 deletions app/src/main/java/org/sopt/pingle/util/component/PingleCard.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
package org.sopt.pingle.util.component

import android.annotation.SuppressLint
import android.content.Context
import android.text.Spannable
import android.text.SpannableString
import android.text.style.ForegroundColorSpan
import android.text.style.TextAppearanceSpan
import android.util.AttributeSet
import android.view.LayoutInflater
import androidx.constraintlayout.widget.ConstraintLayout
import java.time.LocalDate
import java.time.LocalTime
import java.time.format.DateTimeFormatter
import org.sopt.pingle.R
import org.sopt.pingle.databinding.CardPingleBinding
import org.sopt.pingle.domain.model.PingleEntity
import org.sopt.pingle.presentation.type.CategoryType
import org.sopt.pingle.util.view.colorOf
import org.sopt.pingle.util.view.stringOf

@SuppressLint("CustomViewStyleable")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오호이 현재 프로젝트에 설정된 minSdkVersion 버젼 이후에 나온 API를 사용할때 warning을 없애고 사용할 수 있게 합니다.. 라고 하는데 그게 여기서 머길래 SuppressLint를 사용하신건가요?

class PingleCard @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : ConstraintLayout(context, attrs, defStyleAttr) {
private val binding: CardPingleBinding
var listener: OnPingleCardClickListener? = null

init {
binding = CardPingleBinding.inflate(LayoutInflater.from(context), this, true)

addListeners()
}

private fun addListeners() {
binding.btnCardBottomMapChat.setOnClickListener {
listener?.onPingleCardChatBtnClickListener()
}

binding.btnCardBottomMapParticipate.setOnClickListener {
listener?.onPingleCardParticipateBtnClickListener()
}
}

fun initLayout(pingleEntity: PingleEntity) {
val category: CategoryType = CategoryType.fromString(pingleEntity.category)

with(binding) {
badgeCardTopInfo.setBadgeCategoryType(category)
tvCardTopInfoName.text = pingleEntity.name
tvCardTopInfoName.setTextColor(colorOf(category.textColor))
tvCardTopInfoOwnerName.text = pingleEntity.ownerName
tvCardBottomCalenderDetail.text = pingleEntity.convertToCalenderDetail()
tvCardBottomMapDetail.text = pingleEntity.location
btnCardBottomMapChat.isEnabled = pingleEntity.isParticipating
btnCardBottomMapParticipate.text = when (pingleEntity.isParticipating) {
true -> stringOf(R.string.map_card_cancel)
false -> stringOf(R.string.map_card_participate)
}
btnCardBottomMapParticipate.isEnabled =
pingleEntity.isParticipating || !pingleEntity.isCompleted()

if (pingleEntity.isCompleted()) {
with(tvCardTopInfoParticipantDetail) {
text = stringOf(R.string.map_card_completed)
setTextAppearance(R.style.TextAppearance_Pingle_Sub_Semi_16)
}
} else {
with(tvCardTopInfoParticipantDetail) {
val participantDetail = context.getString(
R.string.map_card_participant_detail,
pingleEntity.curParticipants,
pingleEntity.maxParticipants
)
text = SpannableString(participantDetail).apply {
setSpan(
ForegroundColorSpan(
colorOf(category.textColor)
),
CUR_PARTICIPANTS_START,
pingleEntity.curParticipants.toString().length,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
)
setSpan(
TextAppearanceSpan(
context,
R.style.TextAppearance_Pingle_Title_Semi_30
),
CUR_PARTICIPANTS_START,
pingleEntity.curParticipants.toString().length + 1,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
)
setSpan(
TextAppearanceSpan(
context,
R.style.TextAppearance_Pingle_Title_Semi_20
),
pingleEntity.curParticipants.toString().length + 1,
participantDetail.length,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
)
}
}
}
}
}

companion object {
const val CUR_PARTICIPANTS_START = 0
}
}

interface OnPingleCardClickListener {
fun onPingleCardChatBtnClickListener()
fun onPingleCardParticipateBtnClickListener()
}

fun PingleEntity.isCompleted() = maxParticipants == curParticipants

fun PingleEntity.convertToCalenderDetail(): String {
val localDate = LocalDate.parse(date, DateTimeFormatter.ISO_LOCAL_DATE)
val startTime = LocalTime.parse(startAt, DateTimeFormatter.ISO_LOCAL_TIME)
val endTime = LocalTime.parse(endAt, DateTimeFormatter.ISO_LOCAL_TIME)

return buildString {
append("${localDate.year}년 ${localDate.monthValue}월 ${localDate.dayOfMonth}일\n")
append("${startTime.format(DateTimeFormatter.ofPattern("HH:mm"))} ~ ")
append("${endTime.format(DateTimeFormatter.ofPattern("HH:mm"))}")
}
}
5 changes: 5 additions & 0 deletions app/src/main/res/color/selector_pingle_btn_m.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@color/g_01" android:state_enabled="true" />
<item android:color="@color/g_07" android:state_enabled="false" />
</selector>
5 changes: 5 additions & 0 deletions app/src/main/res/color/selector_pingle_btn_s.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@color/white" android:state_enabled="true" />
<item android:color="@color/g_06" android:state_enabled="false" />
</selector>
5 changes: 5 additions & 0 deletions app/src/main/res/drawable/shape_oval_stroke_1.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<stroke android:width="1dp" android:color="@color/g_06"/>
</shape>
Loading
Loading