diff --git a/app/src/main/java/kr/co/vividnext/sodalive/live/GetRoomListResponse.kt b/app/src/main/java/kr/co/vividnext/sodalive/live/GetRoomListResponse.kt index 72d6da26..27d35187 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/live/GetRoomListResponse.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/live/GetRoomListResponse.kt @@ -9,6 +9,7 @@ data class GetRoomListResponse( @SerializedName("title") val title: String, @SerializedName("content") val content: String, @SerializedName("beginDateTime") val beginDateTime: String, + @SerializedName("beginDateTimeUtc") val beginDateTimeUtc: String, @SerializedName("numberOfParticipate") val numberOfParticipate: Int, @SerializedName("numberOfPeople") val numberOfPeople: Int, @SerializedName("coverImageUrl") val coverImageUrl: String, diff --git a/app/src/main/java/kr/co/vividnext/sodalive/live/LiveFragment.kt b/app/src/main/java/kr/co/vividnext/sodalive/live/LiveFragment.kt index 54a088bd..22b56bac 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/live/LiveFragment.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/live/LiveFragment.kt @@ -489,23 +489,23 @@ class LiveFragment : BaseFragment(FragmentLiveBinding::infl ) { super.getItemOffsets(outRect, view, parent, state) - outRect.left = 13.3f.dpToPx().toInt() - outRect.right = 13.3f.dpToPx().toInt() + outRect.left = 0 + outRect.right = 0 when (parent.getChildAdapterPosition(view)) { 0 -> { outRect.top = 0f.dpToPx().toInt() - outRect.bottom = 6.7f.dpToPx().toInt() + outRect.bottom = 8.dpToPx().toInt() } liveReservationAdapter.itemCount - 1 -> { - outRect.top = 6.7f.dpToPx().toInt() - outRect.bottom = 13.3f.dpToPx().toInt() + outRect.top = 8.dpToPx().toInt() + outRect.bottom = 0.dpToPx().toInt() } else -> { - outRect.top = 6.7f.dpToPx().toInt() - outRect.bottom = 6.7f.dpToPx().toInt() + outRect.top = 8.dpToPx().toInt() + outRect.bottom = 8.dpToPx().toInt() } } } @@ -549,6 +549,21 @@ class LiveFragment : BaseFragment(FragmentLiveBinding::infl @SuppressLint("NotifyDataSetChanged") private fun setupCommunityPost() { + creatorCommunityAdapter = CreatorCommunityAdapter { + if (SharedPreferenceManager.token.isNotBlank()) { + startActivity( + Intent( + requireActivity(), + CreatorCommunityAllActivity::class.java + ).apply { + putExtra(Constants.EXTRA_COMMUNITY_CREATOR_ID, it) + } + ) + } else { + (requireActivity() as MainActivity).showLoginActivity() + } + } + val recyclerView = binding.rvCommunityPost recyclerView.layoutManager = LinearLayoutManager( @@ -568,37 +583,23 @@ class LiveFragment : BaseFragment(FragmentLiveBinding::infl when (parent.getChildAdapterPosition(view)) { 0 -> { - outRect.left = 13.3f.dpToPx().toInt() - outRect.right = 5.dpToPx().toInt() + outRect.left = 0 + outRect.right = 8.dpToPx().toInt() } - liveNowAdapter.itemCount - 1 -> { - outRect.left = 6.7f.dpToPx().toInt() - outRect.right = 13.3f.dpToPx().toInt() + creatorCommunityAdapter.itemCount - 1 -> { + outRect.left = 8.dpToPx().toInt() + outRect.right = 0 } else -> { - outRect.left = 6.7f.dpToPx().toInt() - outRect.right = 6.7f.dpToPx().toInt() + outRect.left = 8.dpToPx().toInt() + outRect.right = 8.dpToPx().toInt() } } } }) - creatorCommunityAdapter = CreatorCommunityAdapter { - if (SharedPreferenceManager.token.isNotBlank()) { - startActivity( - Intent( - requireActivity(), - CreatorCommunityAllActivity::class.java - ).apply { - putExtra(Constants.EXTRA_COMMUNITY_CREATOR_ID, it) - } - ) - } else { - (requireActivity() as MainActivity).showLoginActivity() - } - } recyclerView.adapter = creatorCommunityAdapter viewModel.communityPostItemLiveData.observe(viewLifecycleOwner) { diff --git a/app/src/main/java/kr/co/vividnext/sodalive/live/reservation/LiveReservationAdapter.kt b/app/src/main/java/kr/co/vividnext/sodalive/live/reservation/LiveReservationAdapter.kt index 0a2018e5..7eb7b827 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/live/reservation/LiveReservationAdapter.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/live/reservation/LiveReservationAdapter.kt @@ -2,8 +2,6 @@ package kr.co.vividnext.sodalive.live.reservation import android.annotation.SuppressLint import android.content.Context -import android.graphics.Bitmap -import android.graphics.drawable.Drawable import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -11,14 +9,15 @@ import androidx.recyclerview.widget.RecyclerView import com.bumptech.glide.Glide import com.bumptech.glide.load.resource.bitmap.CenterCrop import com.bumptech.glide.load.resource.bitmap.RoundedCorners -import com.bumptech.glide.request.target.CustomTarget -import com.bumptech.glide.request.transition.Transition import kr.co.vividnext.sodalive.common.SharedPreferenceManager -import kr.co.vividnext.sodalive.databinding.ItemLiveReservationBinding import kr.co.vividnext.sodalive.databinding.ItemMyLiveReservationBinding +import kr.co.vividnext.sodalive.databinding.LiveBookingCardBinding import kr.co.vividnext.sodalive.extensions.dpToPx import kr.co.vividnext.sodalive.extensions.moneyFormat import kr.co.vividnext.sodalive.live.GetRoomListResponse +import java.text.SimpleDateFormat +import java.util.Locale +import java.util.TimeZone class LiveReservationAdapter( private val isMain: Boolean = false, @@ -39,7 +38,7 @@ class LiveReservationAdapter( } else { ViewHolder( parent.context, - ItemLiveReservationBinding.inflate( + LiveBookingCardBinding.inflate( LayoutInflater.from(parent.context), parent, false @@ -78,54 +77,45 @@ class LiveReservationAdapter( inner class ViewHolder( private val context: Context, - private val binding: ItemLiveReservationBinding + private val binding: LiveBookingCardBinding ) : RecyclerView.ViewHolder(binding.root) { + @SuppressLint("SetTextI18n") fun bind(item: GetRoomListResponse) { - val lp = binding.ivCover.layoutParams - lp.width = 80f.dpToPx().toInt() - lp.height = 116.7f.dpToPx().toInt() + val dateMap = parseUtcIsoLocalDateTime(item.beginDateTimeUtc) Glide .with(context) .asBitmap() .transform(CenterCrop(), RoundedCorners(16f.dpToPx().toInt())) - .load(item.coverImageUrl) - .into(object : CustomTarget() { - override fun onResourceReady( - resource: Bitmap, - transition: Transition? - ) { - binding.ivCover.setImageBitmap(resource) - binding.ivCover.layoutParams = lp - } + .load(item.creatorProfileImage) + .into(binding.ivProfile) - override fun onLoadCleared(placeholder: Drawable?) { - } - }) - binding.tvDate.text = item.beginDateTime binding.tvNickname.text = item.creatorNickname binding.tvTitle.text = item.title - binding.root.setOnClickListener { onClick(item) } - binding.ivLock.visibility = if (item.isPrivateRoom) { - View.VISIBLE - } else { - View.GONE - } + binding.tvDayOfWeek.text = dateMap["dayOfWeek"] + binding.tvTime.text = dateMap["time"] + + binding.tvMonth.text = "${dateMap["month"]}월" + binding.tvDay.text = dateMap["day"] if (item.isReservation) { - binding.tvPrice.visibility = View.GONE + binding.tvCan.visibility = View.GONE + binding.tvFree.visibility = View.GONE binding.tvCompleteReservation.visibility = View.VISIBLE - } else { - binding.tvPrice.visibility = View.VISIBLE + } else if (item.price <= 0) { + binding.tvCan.visibility = View.GONE binding.tvCompleteReservation.visibility = View.GONE + binding.tvFree.visibility = View.VISIBLE + } else { + binding.tvFree.visibility = View.GONE + binding.tvCompleteReservation.visibility = View.GONE + binding.tvCan.visibility = View.VISIBLE - binding.tvPrice.text = if (item.price <= 0) { - "무료" - } else { - "${item.price.moneyFormat()}캔" - } + binding.tvCan.text = item.price.moneyFormat() } + + binding.root.setOnClickListener { onClick(item) } } } @@ -133,6 +123,7 @@ class LiveReservationAdapter( private val context: Context, private val binding: ItemMyLiveReservationBinding ) : RecyclerView.ViewHolder(binding.root) { + @SuppressLint("SetTextI18n") fun bind(item: GetRoomListResponse, position: Int) { binding.tvMyLive.visibility = if (position == 0) { View.VISIBLE @@ -140,37 +131,62 @@ class LiveReservationAdapter( View.GONE } - val lp = binding.ivCover.layoutParams - lp.width = 80f.dpToPx().toInt() - lp.height = 116.7f.dpToPx().toInt() + val dateMap = parseUtcIsoLocalDateTime(item.beginDateTimeUtc) Glide .with(context) .asBitmap() - .load(item.coverImageUrl) .transform(CenterCrop(), RoundedCorners(16f.dpToPx().toInt())) - .into(object : CustomTarget() { - override fun onResourceReady( - resource: Bitmap, - transition: Transition? - ) { - binding.ivCover.setImageBitmap(resource) - binding.ivCover.layoutParams = lp - } + .load(item.creatorProfileImage) + .into(binding.ivProfile) - override fun onLoadCleared(placeholder: Drawable?) { - } - }) - binding.tvDate.text = item.beginDateTime binding.tvNickname.text = item.creatorNickname binding.tvTitle.text = item.title - binding.root.setOnClickListener { onClick(item) } + binding.tvDayOfWeek.text = dateMap["dayOfWeek"] + binding.tvTime.text = dateMap["time"] - binding.ivLock.visibility = if (item.isPrivateRoom) { - View.VISIBLE + binding.tvMonth.text = "${dateMap["month"]}월" + binding.tvDay.text = dateMap["day"] + + if (item.price <= 0) { + binding.tvCan.visibility = View.GONE + binding.tvFree.visibility = View.VISIBLE } else { - View.GONE + binding.tvFree.visibility = View.GONE + binding.tvCan.visibility = View.VISIBLE + + binding.tvCan.text = item.price.moneyFormat() } + + binding.root.setOnClickListener { onClick(item) } } } + + private fun parseUtcIsoLocalDateTime(utcString: String): Map { + // 1. 서버가 내려준 포맷: "yyyy-MM-dd'T'HH:mm:ss" + val utcFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.getDefault()) + utcFormat.timeZone = TimeZone.getTimeZone("UTC") // 서버가 UTC 기준으로 보낸 것 + + // 2. Date 객체 생성 + val date = utcFormat.parse(utcString)!! + + // 3. 월 (1~12) + val month = SimpleDateFormat("M", Locale.getDefault()).format(date) + + // 4. 일 (1~31) + val day = SimpleDateFormat("d", Locale.getDefault()).format(date) + + // 5. 요일 (예: "Mon", "목") + val dayOfWeek = SimpleDateFormat("E", Locale.getDefault()).format(date) + + // 6. 시간 (예: "AM 05:00") + val time = SimpleDateFormat("a hh:mm", Locale.getDefault()).format(date) + + return mapOf( + "month" to month, + "day" to day, + "dayOfWeek" to dayOfWeek, + "time" to time + ) + } } diff --git a/app/src/main/res/drawable/date_day_background.xml b/app/src/main/res/drawable/date_day_background.xml new file mode 100644 index 00000000..2c67a701 --- /dev/null +++ b/app/src/main/res/drawable/date_day_background.xml @@ -0,0 +1,10 @@ + + + + + diff --git a/app/src/main/res/drawable/date_month_background.xml b/app/src/main/res/drawable/date_month_background.xml new file mode 100644 index 00000000..798e28f5 --- /dev/null +++ b/app/src/main/res/drawable/date_month_background.xml @@ -0,0 +1,10 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_placeholder_profile.xml b/app/src/main/res/drawable/ic_placeholder_profile.xml new file mode 100644 index 00000000..f0240406 --- /dev/null +++ b/app/src/main/res/drawable/ic_placeholder_profile.xml @@ -0,0 +1,18 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/live_booking_card_background.xml b/app/src/main/res/drawable/live_booking_card_background.xml new file mode 100644 index 00000000..f9fe55c5 --- /dev/null +++ b/app/src/main/res/drawable/live_booking_card_background.xml @@ -0,0 +1,6 @@ + + + + + diff --git a/app/src/main/res/drawable/live_booking_card_background_with_stroke.xml b/app/src/main/res/drawable/live_booking_card_background_with_stroke.xml new file mode 100644 index 00000000..8dcd245d --- /dev/null +++ b/app/src/main/res/drawable/live_booking_card_background_with_stroke.xml @@ -0,0 +1,9 @@ + + + + + + diff --git a/app/src/main/res/drawable/payment_background.xml b/app/src/main/res/drawable/payment_background.xml new file mode 100644 index 00000000..804add5d --- /dev/null +++ b/app/src/main/res/drawable/payment_background.xml @@ -0,0 +1,6 @@ + + + + + diff --git a/app/src/main/res/drawable/payment_free_background.xml b/app/src/main/res/drawable/payment_free_background.xml new file mode 100644 index 00000000..38e2b493 --- /dev/null +++ b/app/src/main/res/drawable/payment_free_background.xml @@ -0,0 +1,6 @@ + + + + + diff --git a/app/src/main/res/drawable/reservation_complete_background.xml b/app/src/main/res/drawable/reservation_complete_background.xml new file mode 100644 index 00000000..a37d6f56 --- /dev/null +++ b/app/src/main/res/drawable/reservation_complete_background.xml @@ -0,0 +1,6 @@ + + + + + diff --git a/app/src/main/res/layout/fragment_live.xml b/app/src/main/res/layout/fragment_live.xml index 3d449d56..41eb2f6e 100644 --- a/app/src/main/res/layout/fragment_live.xml +++ b/app/src/main/res/layout/fragment_live.xml @@ -91,6 +91,8 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="48dp" + android:clipToPadding="false" + android:paddingHorizontal="24dp" android:visibility="gone" /> - + android:background="@drawable/live_booking_card_background_with_stroke" + android:padding="14dp"> + app:layout_constraintTop_toTopOf="parent" + tools:src="@tools:sample/avatars" /> + - - + + + android:gravity="center_vertical" + android:orientation="horizontal"> - + - + + + + android:orientation="vertical"> + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + - + android:layout_alignParentBottom="true" + android:background="@drawable/payment_background" + android:gravity="center_vertical" + android:minWidth="52dp" + android:orientation="horizontal" + android:padding="4dp" + android:visibility="gone" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent"> - + + + + + + + diff --git a/app/src/main/res/layout/live_booking_card.xml b/app/src/main/res/layout/live_booking_card.xml new file mode 100644 index 00000000..8bad7ac8 --- /dev/null +++ b/app/src/main/res/layout/live_booking_card.xml @@ -0,0 +1,219 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +