feat: 즐겨찾기 기능 데이터 레이어 추가
- HotDeal, HotDealEntity에 isFavorite 필드 추가 - HotDealDao에 즐겨찾기 관련 쿼리 메서드 추가 - 데이터베이스 마이그레이션 (v3 -> v4) 추가 Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -21,7 +21,7 @@ import com.hotdeal.alarm.data.local.db.entity.SiteConfigEntity
|
|||||||
SiteConfigEntity::class,
|
SiteConfigEntity::class,
|
||||||
KeywordEntity::class
|
KeywordEntity::class
|
||||||
],
|
],
|
||||||
version = 3,
|
version = 4,
|
||||||
exportSchema = false
|
exportSchema = false
|
||||||
)
|
)
|
||||||
@TypeConverters(Converters::class)
|
@TypeConverters(Converters::class)
|
||||||
@@ -51,6 +51,14 @@ abstract class AppDatabase : RoomDatabase() {
|
|||||||
db.execSQL("CREATE INDEX IF NOT EXISTS index_hot_deals_siteName_boardName ON hot_deals(siteName, boardName)")
|
db.execSQL("CREATE INDEX IF NOT EXISTS index_hot_deals_siteName_boardName ON hot_deals(siteName, boardName)")
|
||||||
db.execSQL("CREATE INDEX IF NOT EXISTS index_hot_deals_createdAt ON hot_deals(createdAt)")
|
db.execSQL("CREATE INDEX IF NOT EXISTS index_hot_deals_createdAt ON hot_deals(createdAt)")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Migration 3 -> 4: 즐겨찾기 필드 추가
|
||||||
|
*/
|
||||||
|
val MIGRATION_3_4 = object : Migration(3, 4) {
|
||||||
|
override fun migrate(db: SupportSQLiteDatabase) {
|
||||||
|
db.execSQL("ALTER TABLE hot_deals ADD COLUMN isFavorite INTEGER NOT NULL DEFAULT 0")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -99,4 +99,26 @@ interface HotDealDao {
|
|||||||
*/
|
*/
|
||||||
@Query("SELECT * FROM hot_deals WHERE title LIKE '%' || :query || '%' ORDER BY createdAt DESC")
|
@Query("SELECT * FROM hot_deals WHERE title LIKE '%' || :query || '%' ORDER BY createdAt DESC")
|
||||||
fun searchDeals(query: String): Flow<List<HotDealEntity>>
|
fun searchDeals(query: String): Flow<List<HotDealEntity>>
|
||||||
|
|
||||||
|
// =========================
|
||||||
|
// 즐겨찾기 관련 메서드
|
||||||
|
// =========================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 즐겨찾기 핫딜 조회
|
||||||
|
*/
|
||||||
|
@Query("SELECT * FROM hot_deals WHERE isFavorite = 1 ORDER BY createdAt DESC")
|
||||||
|
fun observeFavoriteDeals(): Flow<List<HotDealEntity>>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 즐겨찾기 상태 토글
|
||||||
|
*/
|
||||||
|
@Query("UPDATE hot_deals SET isFavorite = NOT isFavorite WHERE id = :id")
|
||||||
|
suspend fun toggleFavorite(id: String)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 즐겨찾기 상태 설정
|
||||||
|
*/
|
||||||
|
@Query("UPDATE hot_deals SET isFavorite = :isFavorite WHERE id = :id")
|
||||||
|
suspend fun setFavorite(id: String, isFavorite: Boolean)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,8 @@ data class HotDealEntity(
|
|||||||
val mallUrl: String?,
|
val mallUrl: String?,
|
||||||
val createdAt: Long,
|
val createdAt: Long,
|
||||||
val isNotified: Boolean = false,
|
val isNotified: Boolean = false,
|
||||||
val isKeywordMatch: Boolean = false
|
val isKeywordMatch: Boolean = false,
|
||||||
|
val isFavorite: Boolean = false // 즐겨찾기 여부
|
||||||
) {
|
) {
|
||||||
/**
|
/**
|
||||||
* Domain 모델로 변환
|
* Domain 모델로 변환
|
||||||
@@ -40,7 +41,8 @@ data class HotDealEntity(
|
|||||||
mallUrl = mallUrl,
|
mallUrl = mallUrl,
|
||||||
createdAt = createdAt,
|
createdAt = createdAt,
|
||||||
isNotified = isNotified,
|
isNotified = isNotified,
|
||||||
isKeywordMatch = isKeywordMatch
|
isKeywordMatch = isKeywordMatch,
|
||||||
|
isFavorite = isFavorite
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,7 +60,8 @@ data class HotDealEntity(
|
|||||||
mallUrl = domain.mallUrl,
|
mallUrl = domain.mallUrl,
|
||||||
createdAt = domain.createdAt,
|
createdAt = domain.createdAt,
|
||||||
isNotified = domain.isNotified,
|
isNotified = domain.isNotified,
|
||||||
isKeywordMatch = domain.isKeywordMatch
|
isKeywordMatch = domain.isKeywordMatch,
|
||||||
|
isFavorite = domain.isFavorite
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,8 @@ object DatabaseModule {
|
|||||||
)
|
)
|
||||||
.addMigrations(
|
.addMigrations(
|
||||||
AppDatabase.MIGRATION_1_2,
|
AppDatabase.MIGRATION_1_2,
|
||||||
AppDatabase.MIGRATION_2_3
|
AppDatabase.MIGRATION_2_3,
|
||||||
|
AppDatabase.MIGRATION_3_4
|
||||||
)
|
)
|
||||||
.fallbackToDestructiveMigration()
|
.fallbackToDestructiveMigration()
|
||||||
.build()
|
.build()
|
||||||
|
|||||||
@@ -12,7 +12,8 @@ data class HotDeal(
|
|||||||
val mallUrl: String? = null, // 쇼핑몰 URL (추출된 경우)
|
val mallUrl: String? = null, // 쇼핑몰 URL (추출된 경우)
|
||||||
val createdAt: Long, // 수집 시간 (timestamp)
|
val createdAt: Long, // 수집 시간 (timestamp)
|
||||||
val isNotified: Boolean = false,
|
val isNotified: Boolean = false,
|
||||||
val isKeywordMatch: Boolean = false
|
val isKeywordMatch: Boolean = false,
|
||||||
|
val isFavorite: Boolean = false // 즐겨찾기 여부
|
||||||
) {
|
) {
|
||||||
/**
|
/**
|
||||||
* 사이트 타입 반환
|
* 사이트 타입 반환
|
||||||
|
|||||||
Reference in New Issue
Block a user