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

[AN/USER] feat: 검색 화면을 구현한다.(#784) #799

Merged
merged 61 commits into from
Apr 1, 2024
Merged
Show file tree
Hide file tree
Changes from 52 commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
297ca64
feat(RecentSearchQuery): 최근검색어 도메인 모델 정의
SeongHoonC Mar 13, 2024
9a90406
feat(data): Room 의존성 추가
SeongHoonC Mar 13, 2024
49eea4e
feat(RecentSearchRepository): 최근검색어 저장소 정의
SeongHoonC Mar 13, 2024
f9a9bc5
feat(RecentSearchQueryEntity): 최근검색어 entity 정의
SeongHoonC Mar 13, 2024
6d1c8dc
feat(RecentSearchQueryEntity): 최근검색어 dao 정의
SeongHoonC Mar 13, 2024
919abd1
feat(DefaultRecentSearchRepository): 최근검색어 Default 저장소 정의
SeongHoonC Mar 13, 2024
af01257
feat(DefaultRecentSearchRepository): 최근검색어 저장소 의존성 주입
SeongHoonC Mar 13, 2024
f434031
feat(FestagoDatabase): 페스타고 데이터베이스 정의
SeongHoonC Mar 13, 2024
2d7b021
feat(DaosModule): 최근검색어 Dao 모듈 정의
SeongHoonC Mar 13, 2024
7383906
feat(DatabaseModule): FestagoDatabase 모듈 정의
SeongHoonC Mar 13, 2024
7299a59
feat(RecentSearchQueryDao): 최근 검색어 목록을 flow 가 아닌 단일 요청으로 변경
SeongHoonC Mar 13, 2024
6a12d25
feat(SearchViewModel): 검색 ViewModel 생성
SeongHoonC Mar 13, 2024
71a3b74
feat(SearchUiState): 검색 화면의 상태에 따라 다른 화면을 보여준다
SeongHoonC Mar 13, 2024
c9caa61
feat(recentsearch): 최근검색어 뷰홀더 및 어댑터 정의
SeongHoonC Mar 13, 2024
b886d73
feat(custom): custom clearEditText 추가
SeongHoonC Mar 14, 2024
aacafe4
fix(room): 룸 instant 타입 인자 오류 수정
SeongHoonC Mar 14, 2024
92b65f0
feat: 검색 클릭시 검색 화면으로 이동
SeongHoonC Mar 14, 2024
62b0c12
feat: 검색 화면 최근 검색 기록 보기 구현
SeongHoonC Mar 14, 2024
15c2265
refactor: 주석 제거
SeongHoonC Mar 14, 2024
e8c841d
feat: 사용하지않는 의존성 제거
SeongHoonC Mar 14, 2024
d9b3ed2
feat: 아티스트, 학교 검색 모델 정의
SeongHoonC Mar 14, 2024
f9a7bf3
feat: 검색 저장소 역할 정의
SeongHoonC Mar 14, 2024
467ae4d
feat: 가짜 검색 저장소 구현
SeongHoonC Mar 15, 2024
7161edc
feat: 최근 검색어 도메인 모델 kotlin Instant 제거
SeongHoonC Mar 15, 2024
b06ba2b
feat: 최근 검색어는 단일 결과를 반환한다
SeongHoonC Mar 19, 2024
3282b5a
feat(SearchUiState): 검색 화면 상태 정의
SeongHoonC Mar 19, 2024
7bdb25b
feat(FakeSearchRepository): 가짜 검색 저장소 저장소 주입
SeongHoonC Mar 19, 2024
207f8ef
feat(SearchEvent): 검색 화면 이벤트 정의
SeongHoonC Mar 19, 2024
c2780a3
feat(SearchViewModel): 뷰모델 검색 기능 작성
SeongHoonC Mar 19, 2024
fcca6af
feat(FakeSearchRepository): 가짜 검색 저장소가 요청마다 다른 결과를 뱉는다
SeongHoonC Mar 19, 2024
2f6520d
feat(FestivalSearchScreenViewHolder): 축제 검색 화면 뷰홀더 정의
SeongHoonC Mar 19, 2024
25efddf
feat(ArtistSearchScreenViewHolder): 아티스트 검색 화면 뷰홀더 정의
SeongHoonC Mar 19, 2024
0a55d3e
feat(SchoolSearchScreenViewHolder): 학교 검색 화면 뷰홀더 정의
SeongHoonC Mar 19, 2024
0b19919
feat(SearchScreenAdapter): 검색 화면 멀티 뷰타입 어댑터 정의
SeongHoonC Mar 19, 2024
e25cc66
feat(ItemSearchScreenUiState): 검색 화면 상태 정의
SeongHoonC Mar 19, 2024
a4d9c16
feat(navigation): 검색 화면 이동 애니메이션 추가
SeongHoonC Mar 19, 2024
8c94ce8
feat(ArtistSearch): 아티스트 검색 아이템 및 어댑터 정의
SeongHoonC Mar 19, 2024
b8972bd
feat(SchoolSearch): 학교 검색 아이템 및 어댑터 정의
SeongHoonC Mar 19, 2024
c763e05
feat(FestivalSearchArtist): 축제 상세 아이템의 아티스트 목록 어댑터 및 아이템 구현
SeongHoonC Mar 19, 2024
1af50c5
feat(FestivalSearchArtist): 축제 상세 아이템 및 어댑터 구현
SeongHoonC Mar 19, 2024
d376bd6
feat(Search): 검색 화면 문자열 정의
SeongHoonC Mar 19, 2024
71d041e
feat(SearchFragment): 검색 화면 상태에 따라 뷰 그리기 적용
SeongHoonC Mar 19, 2024
fedcadf
refactor(SearchFragment): remove unused import
SeongHoonC Mar 19, 2024
8e71f71
refactor(ArtistAdapter): reformat ktlint
SeongHoonC Mar 19, 2024
fbdf673
feat(SchoolSearchResponse): 학교 검색 응답 정의
SeongHoonC Mar 19, 2024
30e158e
feat(ArtistSearchResponse): 아티스트 검색 응답 정의
SeongHoonC Mar 19, 2024
86ee872
feat(SearchRetrofitService): 검색 Retrofit service 정의
SeongHoonC Mar 20, 2024
42bac4b
feat(FakeSearchRepository): 가짜 검색 객체가 오류를 뱉도록 변경
SeongHoonC Mar 20, 2024
9231234
feat(DefaultSearchRepository): 검색 저장소 정의
SeongHoonC Mar 20, 2024
c0a20fa
refactor(SchoolSearchItemUiState): ktlint check
SeongHoonC Mar 20, 2024
85e53d5
fix(SearchFragment): 검색 화면 탭 포지션 강제 초기화 문제 해결
SeongHoonC Mar 20, 2024
4bf4fde
feat: 디자인과 다른 아이콘 크기 반영
SeongHoonC Mar 21, 2024
49db2d9
refator(SearchUiState): 검색 상태 확인 커스텀 게터 이름 수정
SeongHoonC Mar 24, 2024
2af29a1
refator(SearchUiState): 상태 확인 커스텀 게터 이름 변경
SeongHoonC Mar 24, 2024
4b3e9ac
refator(FestivalListFragment): 사용하지 않는 대학교 상세 이동 제거
SeongHoonC Mar 24, 2024
edff851
feat(FestagoButton): 페스타고 커스텀 버튼 생성
SeongHoonC Mar 25, 2024
973a1ce
feat: 검색 결과가 없으면 검색 추가를 권장한다.
SeongHoonC Mar 25, 2024
c6d596b
feat(ClearEditText): 검색 시 키보드 및 이벤트 컨트롤
SeongHoonC Mar 25, 2024
d014ad4
feat: 버튼 클릭 시 검색어 요청으로 이동
SeongHoonC Mar 25, 2024
a2151f5
feat: 검색창 그림자를 제거한다.
SeongHoonC Mar 31, 2024
c0a7f47
feat: 최근 검색어 텍스트 font 적용
SeongHoonC Mar 31, 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
7 changes: 7 additions & 0 deletions android/festago/data/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,13 @@ dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-jdk8:1.6.4")
testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.6.4")

// room
val room_version = "2.6.1"
implementation("androidx.room:room-runtime:$room_version")
annotationProcessor("androidx.room:room-compiler:$room_version")
kapt("androidx.room:room-compiler:$room_version")
implementation("androidx.room:room-ktx:$room_version")
}

fun getSecretKey(propertyKey: String): String {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.festago.festago.data.dao

import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Query
import androidx.room.Upsert
import com.festago.festago.data.model.RecentSearchQueryEntity

@Dao
interface RecentSearchQueryDao {
@Query(value = "SELECT * FROM recentSearchQueries ORDER BY created_at DESC LIMIT :limit")
suspend fun getRecentSearchQueryEntities(limit: Int): List<RecentSearchQueryEntity>

@Upsert
suspend fun insertOrReplaceRecentSearchQuery(recentSearchQuery: RecentSearchQueryEntity)

@Delete
suspend fun deleteRecentSearchQuery(recentSearchQuery: RecentSearchQueryEntity)

@Query(value = "DELETE FROM recentSearchQueries")
suspend fun clearRecentSearchQueries()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.festago.festago.data.database

import androidx.room.Database
import androidx.room.RoomDatabase
import com.festago.festago.data.dao.RecentSearchQueryDao
import com.festago.festago.data.model.RecentSearchQueryEntity

@Database(entities = [RecentSearchQueryEntity::class], version = 1)
abstract class FestagoDatabase : RoomDatabase() {
abstract fun recentSearchQueryDao(): RecentSearchQueryDao
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.festago.festago.data.di.singletonscope

import com.festago.festago.data.dao.RecentSearchQueryDao
import com.festago.festago.data.database.FestagoDatabase
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent

@Module
@InstallIn(SingletonComponent::class)
object DaosModule {

@Provides
fun providesRecentSearchQueryDao(database: FestagoDatabase): RecentSearchQueryDao =
database.recentSearchQueryDao()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.festago.festago.data.di.singletonscope

import android.content.Context
import androidx.room.Room
import com.festago.festago.data.database.FestagoDatabase
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton

@Module
@InstallIn(SingletonComponent::class)
object DatabaseModule {
@Provides
@Singleton
fun providesFestagoDatabase(
@ApplicationContext context: Context,
): FestagoDatabase = Room.databaseBuilder(
context,
FestagoDatabase::class.java,
"festago-database",
).build()
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
package com.festago.festago.data.di.singletonscope

import com.festago.festago.data.repository.DefaultRecentSearchRepository
import com.festago.festago.data.repository.FakeArtistRepository
import com.festago.festago.data.repository.FakeFestivalRepository
import com.festago.festago.data.repository.FakeSchoolRepository
import com.festago.festago.data.repository.FakeSearchRepository
import com.festago.festago.domain.repository.ArtistRepository
import com.festago.festago.domain.repository.FestivalRepository
import com.festago.festago.domain.repository.RecentSearchRepository
import com.festago.festago.domain.repository.SchoolRepository
import com.festago.festago.domain.repository.SearchRepository
import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
Expand All @@ -27,4 +31,12 @@ interface RepositoryModule {
@Binds
@Singleton
fun bindsSchoolRepository(schoolRepository: FakeSchoolRepository): SchoolRepository

@Binds
@Singleton
fun bindsRecentSearchRepository(recentSearchRepository: DefaultRecentSearchRepository): RecentSearchRepository

@Binds
@Singleton
fun bindsSearchRepository(searchRepository: FakeSearchRepository): SearchRepository
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.festago.festago.data.dto.artist

import com.festago.festago.domain.model.search.ArtistSearch
import kotlinx.serialization.Serializable

@Serializable
data class ArtistSearchResponse(
val id: Long,
val name: String,
val profileImageUrl: String,
val todayStage: Int,
val upcomingStage: Int,
) {
fun toDomain() = ArtistSearch(
id = id,
name = name,
profileImageUrl = profileImageUrl,
todayStage = todayStage,
upcomingStage = upcomingStage,
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.festago.festago.data.dto.school

import com.festago.festago.domain.model.search.SchoolSearch
import kotlinx.serialization.Serializable
import java.time.LocalDate

@Serializable
data class SchoolSearchResponse(
val id: Long,
val name: String,
val logoUrl: String,
val upcomingFestivalStartDate: String?,
) {
fun toDomain() = SchoolSearch(
id = id,
name = name,
logoUrl = logoUrl,
upcomingFestivalStartDate = upcomingFestivalStartDate?.let { LocalDate.parse(it) },
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.festago.festago.data.model

import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
import com.festago.festago.domain.model.recentsearch.RecentSearchQuery

@Entity(
tableName = "recentSearchQueries",
)
data class RecentSearchQueryEntity(
@PrimaryKey
val query: String,
@ColumnInfo(name = "created_at")
val createdAt: Long,
) {
fun toDomain() = RecentSearchQuery(query = query, queriedDate = createdAt)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.festago.festago.data.repository

import com.festago.festago.data.dao.RecentSearchQueryDao
import com.festago.festago.data.model.RecentSearchQueryEntity
import com.festago.festago.domain.model.recentsearch.RecentSearchQuery
import com.festago.festago.domain.repository.RecentSearchRepository
import kotlinx.coroutines.flow.map
import javax.inject.Inject

class DefaultRecentSearchRepository @Inject constructor(
private val recentSearchQueryDao: RecentSearchQueryDao,
) : RecentSearchRepository {

override suspend fun insertOrReplaceRecentSearch(searchQuery: String) {
recentSearchQueryDao.insertOrReplaceRecentSearchQuery(
RecentSearchQueryEntity(
query = searchQuery,
createdAt = System.currentTimeMillis(),
),
)
}

override suspend fun deleteRecentSearch(searchQuery: String) {
recentSearchQueryDao.deleteRecentSearchQuery(
RecentSearchQueryEntity(
query = searchQuery,
createdAt = System.currentTimeMillis(),
),
)
}

override suspend fun getRecentSearchQueries(limit: Int): List<RecentSearchQuery> {
return recentSearchQueryDao.getRecentSearchQueryEntities(limit).map { recentSearchQueries ->
recentSearchQueries.toDomain()
}
}

override suspend fun clearRecentSearches() = recentSearchQueryDao.clearRecentSearchQueries()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.festago.festago.data.repository

import com.festago.festago.data.service.SearchRetrofitService
import com.festago.festago.data.util.onSuccessOrCatch
import com.festago.festago.data.util.runCatchingResponse
import com.festago.festago.domain.model.festival.Festival
import com.festago.festago.domain.model.search.ArtistSearch
import com.festago.festago.domain.model.search.SchoolSearch
import com.festago.festago.domain.repository.SearchRepository
import javax.inject.Inject

class DefaultSearchRepository @Inject constructor(
private val searchRetrofitService: SearchRetrofitService,
) : SearchRepository {

override suspend fun searchFestivals(searchQuery: String): Result<List<Festival>> {
return runCatchingResponse { searchRetrofitService.searchFestivals(searchQuery) }.onSuccessOrCatch { festivalResponses ->
festivalResponses.map { it.toDomain() }
}
}

override suspend fun searchArtists(searchQuery: String): Result<List<ArtistSearch>> {
return runCatchingResponse {
searchRetrofitService.searchArtists(searchQuery)
}.onSuccessOrCatch { artistSearchResponses -> artistSearchResponses.map { it.toDomain() } }
}

override suspend fun searchSchools(searchQuery: String): Result<List<SchoolSearch>> {
return runCatchingResponse {
searchRetrofitService.searchSchools(searchQuery)
}.onSuccessOrCatch { schoolSearchResponses -> schoolSearchResponses.map { it.toDomain() } }
}
}
Loading
Loading