-
Notifications
You must be signed in to change notification settings - Fork 8
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
[AN/USER] feat: 학교 상세 페이지 구현 (#697) #722
Changes from 20 commits
64e8759
8469319
5ef793a
2aa3b2b
61d0ffe
b48c2bf
6eb05c6
d6cd393
bc6da8e
d1f1f2b
f74935f
5e724f6
3832327
cc91707
a025518
b555447
60357d6
2a85266
702afb4
48848ad
7a30d1c
f1c5aec
52824ad
6fe46ff
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package com.festago.festago.data.dto.school | ||
|
||
import com.festago.festago.domain.model.school.SchoolInfo | ||
import kotlinx.serialization.Serializable | ||
|
||
@Serializable | ||
data class SchoolInfoResponse( | ||
val id: Int, | ||
val schoolName: String, | ||
val logoUrl: String, | ||
val backgroundUrl: String, | ||
val socialMediaResponse: List<SocialMediaResponse>, | ||
) { | ||
fun toDomain(): SchoolInfo = SchoolInfo( | ||
id = id, | ||
schoolName = schoolName, | ||
logoUrl = logoUrl, | ||
backgroundUrl = backgroundUrl, | ||
socialMedia = socialMediaResponse.map { it.toDomain() }, | ||
) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package com.festago.festago.data.dto.school | ||
|
||
import com.festago.festago.domain.model.social.SocialMedia | ||
import kotlinx.serialization.Serializable | ||
|
||
@Serializable | ||
data class SocialMediaResponse( | ||
val type: String, | ||
val name: String, | ||
val logoUrl: String, | ||
val url: String, | ||
) { | ||
fun toDomain(): SocialMedia = SocialMedia( | ||
type = type, | ||
name = name, | ||
logoUrl = logoUrl, | ||
url = url, | ||
) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
package com.festago.festago.data.repository | ||
|
||
import com.festago.festago.domain.model.school.SchoolInfo | ||
import com.festago.festago.domain.model.social.SocialMedia | ||
|
||
object FakeSchool { | ||
val googleSchool = SchoolInfo( | ||
id = 1, | ||
schoolName = "구글대학교", | ||
logoUrl = "https://cdn1.iconfinder.com/data/icons/logos-brands-in-colors/544/Google__G__Logo-512.png", | ||
backgroundUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/2/2f/Google_2015_logo.svg/1200px-Google_2015_logo.svg.png", | ||
socialMedia = listOf( | ||
SocialMedia( | ||
type = "INSTAGRAM", | ||
name = "구글대학교 인스타", | ||
logoUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/e/e7/Instagram_logo_2016.svg/2048px-Instagram_logo_2016.svg.png", | ||
url = "https://www.instagram.com/", | ||
), | ||
SocialMedia( | ||
type = "INSTAGRAM", | ||
name = "구글대학교 X", | ||
logoUrl = "https://about.x.com/content/dam/about-twitter/x/brand-toolkit/logo-black.png.twimg.1920.png", | ||
url = "https://twitter.com/?lang=en", | ||
) | ||
) | ||
) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
package com.festago.festago.data.repository | ||
|
||
import com.festago.festago.domain.model.festival.FestivalsPage | ||
import com.festago.festago.domain.model.school.SchoolInfo | ||
import com.festago.festago.domain.repository.SchoolRepository | ||
import javax.inject.Inject | ||
|
||
class SchoolDefaultRepository @Inject constructor( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 현재 Festival과 Artist는 Fake객체를 반환하는 리포지터리 네이밍은 다음과 같이 구분되어있는데요! FakeFestivalRepository : FestivalRepository
FestivalDefaultRepository : FestivalRepository There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Festival, Artist와 동일하게 FakeSchoolRepository로 변경했습니다. API 연동할 때 SchoolDefaultRepository 추가할게요. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fake**Repository 로 통일하는게 어떤가요? FakeFestivalRepository : FestivalRepository
DefaultFestivalRepository : FestivalRepository 본래 Default 보다 인터페이스 네이밍이 더 잘보이게 하려고 앞에 배치한 것 같은데 권장이나 어순을 고려해서 수식어를 앞에 배치하는게 좋다고 생각합니다:) |
||
// TODO: Service 연결 | ||
) : SchoolRepository { | ||
override suspend fun loadSchoolInfo(schoolId: Long): Result<SchoolInfo> { | ||
// TODO: API 연동 | ||
return Result.success(FakeSchool.googleSchool) | ||
} | ||
|
||
override suspend fun loadSchoolFestivals(schoolId: Long): Result<FestivalsPage> { | ||
// TODO: API 연동 | ||
return Result.success( | ||
FestivalsPage( | ||
isLastPage = true, | ||
festivals = FakeFestivals.progressFestivals, | ||
) | ||
) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package com.festago.festago.domain.model.school | ||
|
||
import com.festago.festago.domain.model.social.SocialMedia | ||
|
||
data class SchoolInfo( | ||
val id: Int, | ||
val schoolName: String, | ||
val logoUrl: String, | ||
val backgroundUrl: String, | ||
val socialMedia: List<SocialMedia> | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package com.festago.festago.domain.model.social | ||
|
||
data class SocialMedia( | ||
val type: String, | ||
val name: String, | ||
val logoUrl: String, | ||
val url: String | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package com.festago.festago.domain.repository | ||
|
||
import com.festago.festago.domain.model.festival.FestivalsPage | ||
import com.festago.festago.domain.model.school.SchoolInfo | ||
|
||
interface SchoolRepository { | ||
suspend fun loadSchoolInfo(schoolId: Long): Result<SchoolInfo> | ||
suspend fun loadSchoolFestivals(schoolId: Long): Result<FestivalsPage> | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package com.festago.festago.presentation.ui.schooldetail | ||
|
||
import android.view.ViewGroup | ||
import androidx.recyclerview.widget.DiffUtil | ||
import androidx.recyclerview.widget.ListAdapter | ||
import com.festago.festago.presentation.ui.schooldetail.uistate.ArtistUiState | ||
|
||
class ArtistAdapter : ListAdapter<ArtistUiState, ArtistViewHolder>(diffUtil) { | ||
|
||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ArtistViewHolder { | ||
return ArtistViewHolder.of(parent) | ||
} | ||
|
||
override fun onBindViewHolder(holder: ArtistViewHolder, position: Int) { | ||
holder.bind(getItem(position)) | ||
} | ||
|
||
companion object { | ||
private val diffUtil = object : DiffUtil.ItemCallback<ArtistUiState>() { | ||
override fun areItemsTheSame( | ||
oldItem: ArtistUiState, | ||
newItem: ArtistUiState, | ||
): Boolean { | ||
return oldItem.id == newItem.id | ||
} | ||
|
||
override fun areContentsTheSame( | ||
oldItem: ArtistUiState, | ||
newItem: ArtistUiState, | ||
): Boolean { | ||
return oldItem == newItem | ||
} | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
package com.festago.festago.presentation.ui.schooldetail | ||
|
||
import android.view.LayoutInflater | ||
import android.view.ViewGroup | ||
import androidx.recyclerview.widget.RecyclerView | ||
import com.festago.festago.presentation.databinding.ItemSchoolDetailArtistBinding | ||
import com.festago.festago.presentation.ui.schooldetail.uistate.ArtistUiState | ||
|
||
class ArtistViewHolder( | ||
private val binding: ItemSchoolDetailArtistBinding, | ||
) : RecyclerView.ViewHolder(binding.root) { | ||
|
||
fun bind(item: ArtistUiState) { | ||
binding.artist = item | ||
} | ||
|
||
companion object { | ||
fun of(parent: ViewGroup): ArtistViewHolder { | ||
val binding = ItemSchoolDetailArtistBinding.inflate( | ||
LayoutInflater.from(parent.context), | ||
parent, | ||
false, | ||
) | ||
return ArtistViewHolder(binding) | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
package com.festago.festago.presentation.ui.schooldetail | ||
|
||
import android.content.res.Resources | ||
import android.graphics.Rect | ||
import android.util.TypedValue | ||
import android.view.LayoutInflater | ||
import android.view.View | ||
import android.view.ViewGroup | ||
import androidx.appcompat.content.res.AppCompatResources | ||
import androidx.recyclerview.widget.RecyclerView | ||
import androidx.recyclerview.widget.RecyclerView.ItemDecoration | ||
import com.festago.festago.presentation.R | ||
import com.festago.festago.presentation.databinding.ItemSchoolDetailFestivalBinding | ||
import com.festago.festago.presentation.ui.schooldetail.uistate.FestivalItemUiState | ||
import java.time.LocalDate | ||
|
||
class SchoolDetailFestivalViewHolder( | ||
private val binding: ItemSchoolDetailFestivalBinding | ||
) : RecyclerView.ViewHolder(binding.root) { | ||
private val artistAdapter = ArtistAdapter() | ||
|
||
init { | ||
binding.rvFestivalArtists.adapter = artistAdapter | ||
binding.rvFestivalArtists.addItemDecoration(ArtistItemDecoration()) | ||
} | ||
|
||
fun bind(item: FestivalItemUiState) { | ||
binding.item = item | ||
artistAdapter.submitList(item.artists) | ||
bindDDayView(item) | ||
} | ||
|
||
private fun bindDDayView(item: FestivalItemUiState) { | ||
val context = binding.root.context | ||
|
||
val dDayView = binding.tvFestivalDDay | ||
when { | ||
LocalDate.now() > item.endDate -> Unit | ||
|
||
LocalDate.now() >= item.startDate -> { | ||
dDayView.text = context.getString(R.string.festival_list_tv_dday_in_progress) | ||
dDayView.setTextColor(context.getColor(R.color.secondary_pink_01)) | ||
dDayView.background = AppCompatResources.getDrawable( | ||
context, | ||
R.drawable.bg_festival_list_dday_in_progress, | ||
) | ||
} | ||
|
||
LocalDate.now() == item.startDate.minusDays(1) -> { | ||
dDayView.setTextColor(context.getColor(R.color.background_gray_01)) | ||
dDayView.text = context.getString( | ||
R.string.festival_list_tv_dday_format, | ||
LocalDate.now().compareTo(item.startDate).toString(), | ||
) | ||
dDayView.setBackgroundColor(0xffff1273.toInt()) | ||
} | ||
|
||
else -> binding.tvFestivalDDay.apply { | ||
dDayView.setTextColor(context.getColor(R.color.background_gray_01)) | ||
dDayView.text = context.getString( | ||
R.string.festival_list_tv_dday_format, | ||
(LocalDate.now().toEpochDay() - item.startDate.toEpochDay()).toString(), | ||
) | ||
dDayView.setBackgroundColor(context.getColor(android.R.color.black)) | ||
} | ||
} | ||
} | ||
|
||
private class ArtistItemDecoration : ItemDecoration() { | ||
override fun getItemOffsets( | ||
outRect: Rect, | ||
view: View, | ||
parent: RecyclerView, | ||
state: RecyclerView.State, | ||
) { | ||
super.getItemOffsets(outRect, view, parent, state) | ||
outRect.right = 8.dpToPx | ||
} | ||
|
||
private val Int.dpToPx: Int | ||
get() = TypedValue.applyDimension( | ||
TypedValue.COMPLEX_UNIT_DIP, | ||
this.toFloat(), | ||
Resources.getSystem().displayMetrics, | ||
).toInt() | ||
} | ||
|
||
companion object { | ||
fun of(parent: ViewGroup): SchoolDetailFestivalViewHolder { | ||
val binding = ItemSchoolDetailFestivalBinding.inflate( | ||
LayoutInflater.from(parent.context), | ||
parent, | ||
false, | ||
) | ||
return SchoolDetailFestivalViewHolder(binding) | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
명세 이름이 변경되면 반영해주세요!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
API 연동이랑 변경된 명세 반영은 따로 이슈 파서 작업하겠습니다!