Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
9029fe1
feat: 게시글 및 댓글 관리 API 연결 (#10)
bhindor Aug 28, 2026
2c9e033
feat: 게시글 및 댓글 관리 UI 구현 (#10)
bhindor Aug 28, 2026
3f65f3e
fix: 커뮤니티 메인 프리뷰와 카드 클리핑 수정 (#10)
bhindor Aug 28, 2026
8111aa8
fix: NavHost 커뮤니티 프리뷰 연결 (#10)
bhindor Aug 28, 2026
0831ead
fix: 커뮤니티 Fragment 단독 프리뷰 복원 (#10)
bhindor Aug 28, 2026
5eaa3b3
fix: 커뮤니티 카드 그룹 중앙 정렬 (#10)
bhindor Aug 28, 2026
6e0f0e0
fix: 커뮤니티 상세 프리뷰 표시 (#10)
bhindor Aug 28, 2026
f761925
fix: 커뮤니티 상세 좌우 여백 표시 통일 (#10)
bhindor Aug 28, 2026
e2ed053
fix: 커뮤니티 관리 입력 및 화면 상태 안정화 (#10)
bhindor Sep 14, 2026
e266ed1
feat: 계정 갱신과 반려동물·일기 데이터 연결
bhindor Sep 14, 2026
b892e97
feat: 마이에서 반려동물 관리와 대표 아이 선택
bhindor Sep 14, 2026
41c35f4
feat: 반려동물 일기 목록과 작성·관리 화면
bhindor Sep 14, 2026
cbb28f2
feat: 일기 달력과 날짜별 작성 연결 (#12)
bhindor Sep 14, 2026
a8e64de
feat: 일기 사진 첨부와 업로드 연결 (#13)
bhindor Sep 15, 2026
035dab1
feat: 병원 검색과 상세 조회 연결 (#14)
bhindor Sep 15, 2026
6e5338c
feat: 일기 목록 사진 표시 보완 (#15)
bhindor Sep 15, 2026
ad1bea0
fix: 병원 검색 기준을 안동으로 변경 (#14)
bhindor Sep 15, 2026
87d5c0c
feat: 커뮤니티 빠른 메뉴와 시연 화면 마감 (#16)
bhindor Sep 15, 2026
64b6718
fix: 게시글 작성 기본 인자 타입 정리
bhindor Sep 15, 2026
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
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,16 @@ package kr.ac.anu.mumu.data.datasource

import kr.ac.anu.mumu.data.model.LoginRequest
import kr.ac.anu.mumu.data.model.LoginResponse
import kr.ac.anu.mumu.data.model.TokenRefreshRequest
import retrofit2.Call
import retrofit2.Response
import retrofit2.http.Body
import retrofit2.http.POST

interface AuthService {
@POST("/api/auth/login")
suspend fun login(@Body request: LoginRequest): Response<LoginResponse>

@POST("/api/auth/refresh")
fun refresh(@Body request: TokenRefreshRequest): Call<LoginResponse>
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package kr.ac.anu.mumu.data.datasource

import com.google.gson.JsonObject
import kr.ac.anu.mumu.data.model.BaseResponse
import kr.ac.anu.mumu.data.model.BookmarkDto
import kr.ac.anu.mumu.data.model.CommentDto
Expand All @@ -8,10 +9,13 @@ import kr.ac.anu.mumu.data.model.CommunityPostDto
import kr.ac.anu.mumu.data.model.CommunityRequestDto
import kr.ac.anu.mumu.data.model.LikeDto
import kr.ac.anu.mumu.data.model.PaginatedData
import kr.ac.anu.mumu.data.model.UserProfileDto
import retrofit2.Response
import retrofit2.http.Body
import retrofit2.http.DELETE
import retrofit2.http.GET
import retrofit2.http.POST
import retrofit2.http.PUT
import retrofit2.http.Path
import retrofit2.http.Query

Expand All @@ -35,6 +39,17 @@ interface CommunityService {
@Body request: CommunityRequestDto
): Response<BaseResponse<CommunityPostDto>>

@PUT("/api/community/{communityId}")
suspend fun updatePost(
@Path("communityId") communityId: Long,
@Body request: CommunityRequestDto
): Response<BaseResponse<CommunityPostDto>>

@DELETE("/api/community/{communityId}")
suspend fun deletePost(
@Path("communityId") communityId: Long
): Response<BaseResponse<JsonObject>>

@POST("/api/likes/community/{communityId}")
suspend fun toggleLike(
@Path("communityId") communityId: Long
Expand All @@ -55,4 +70,20 @@ interface CommunityService {
@Path("communityId") communityId: Long,
@Body request: CommentRequestDto
): Response<BaseResponse<CommentDto>>

@PUT("/api/community/{communityId}/comments/{commentId}")
suspend fun updateComment(
@Path("communityId") communityId: Long,
@Path("commentId") commentId: Long,
@Body request: CommentRequestDto
): Response<BaseResponse<CommentDto>>

@DELETE("/api/community/{communityId}/comments/{commentId}")
suspend fun deleteComment(
@Path("communityId") communityId: Long,
@Path("commentId") commentId: Long
): Response<BaseResponse<JsonObject>>

@GET("/api/users/profile")
suspend fun getMyProfile(): Response<BaseResponse<UserProfileDto>>
}
55 changes: 55 additions & 0 deletions app/src/main/java/kr/ac/anu/mumu/data/datasource/DiaryService.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package kr.ac.anu.mumu.data.datasource

import kr.ac.anu.mumu.data.model.BaseResponse
import kr.ac.anu.mumu.data.model.DiaryCalendarDto
import kr.ac.anu.mumu.data.model.DiaryDetailDto
import kr.ac.anu.mumu.data.model.DiaryListDto
import kr.ac.anu.mumu.data.model.DiaryRequestDto
import kr.ac.anu.mumu.data.model.PaginatedData
import kr.ac.anu.mumu.data.model.UploadResponseDto
import okhttp3.MultipartBody
import retrofit2.Response
import retrofit2.http.Body
import retrofit2.http.DELETE
import retrofit2.http.GET
import retrofit2.http.Multipart
import retrofit2.http.POST
import retrofit2.http.PUT
import retrofit2.http.Part
import retrofit2.http.Path
import retrofit2.http.Query

interface DiaryService {
@Multipart
@POST("/api/upload/diary")
suspend fun uploadDiaryImage(@Part file: MultipartBody.Part): Response<BaseResponse<UploadResponseDto>>

@GET("/api/diaries/calendar")
suspend fun getCalendar(
@Query("petId") petId: Long,
@Query("year") year: Int,
@Query("month") month: Int
): Response<BaseResponse<DiaryCalendarDto>>

@GET("/api/diaries")
suspend fun getDiaries(
@Query("petId") petId: Long,
@Query("page") page: Int = 0,
@Query("size") size: Int = 20
): Response<BaseResponse<PaginatedData<DiaryListDto>>>

@GET("/api/diaries/{diaryId}")
suspend fun getDiary(@Path("diaryId") diaryId: Long): Response<BaseResponse<DiaryDetailDto>>

@POST("/api/diaries")
suspend fun createDiary(@Body request: DiaryRequestDto): Response<BaseResponse<DiaryDetailDto>>

@PUT("/api/diaries/{diaryId}")
suspend fun updateDiary(
@Path("diaryId") diaryId: Long,
@Body request: DiaryRequestDto
): Response<BaseResponse<DiaryDetailDto>>

@DELETE("/api/diaries/{diaryId}")
suspend fun deleteDiary(@Path("diaryId") diaryId: Long): Response<Unit>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package kr.ac.anu.mumu.data.datasource

import kr.ac.anu.mumu.data.model.BaseResponse
import kr.ac.anu.mumu.data.model.HospitalDetailDto
import kr.ac.anu.mumu.data.model.HospitalListDto
import kr.ac.anu.mumu.data.model.HospitalPriceDto
import kr.ac.anu.mumu.data.model.HospitalReviewDto
import kr.ac.anu.mumu.data.model.PaginatedData
import retrofit2.Response
import retrofit2.http.GET
import retrofit2.http.Path
import retrofit2.http.Query

interface HospitalService {
@GET("/api/hospitals")
suspend fun search(
@Query("lat") lat: Double,
@Query("lng") lng: Double,
@Query("radius") radius: Double = 20.0,
@Query("keyword") keyword: String? = null,
@Query("page") page: Int = 0,
@Query("size") size: Int = 20
): Response<BaseResponse<PaginatedData<HospitalListDto>>>

@GET("/api/hospitals/{hospitalId}")
suspend fun getDetail(@Path("hospitalId") hospitalId: Long): Response<BaseResponse<HospitalDetailDto>>

@GET("/api/hospitals/{hospitalId}/prices")
suspend fun getPrices(@Path("hospitalId") hospitalId: Long): Response<BaseResponse<List<HospitalPriceDto>>>

@GET("/api/hospitals/{hospitalId}/reviews")
suspend fun getReviews(
@Path("hospitalId") hospitalId: Long,
@Query("page") page: Int = 0,
@Query("size") size: Int = 10
): Response<BaseResponse<PaginatedData<HospitalReviewDto>>>
}
18 changes: 18 additions & 0 deletions app/src/main/java/kr/ac/anu/mumu/data/datasource/PetService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,28 @@ package kr.ac.anu.mumu.data.datasource

import kr.ac.anu.mumu.data.model.BaseResponse
import kr.ac.anu.mumu.data.model.PetDto
import kr.ac.anu.mumu.data.model.PetRequestDto
import retrofit2.Response
import retrofit2.http.Body
import retrofit2.http.DELETE
import retrofit2.http.GET
import retrofit2.http.POST
import retrofit2.http.PUT
import retrofit2.http.Path

interface PetService {
@GET("/api/pets")
suspend fun getMyPets(): Response<BaseResponse<List<PetDto>>>

@POST("/api/pets")
suspend fun createPet(@Body request: PetRequestDto): Response<BaseResponse<PetDto>>

@PUT("/api/pets/{petId}")
suspend fun updatePet(
@Path("petId") petId: Long,
@Body request: PetRequestDto
): Response<BaseResponse<PetDto>>

@DELETE("/api/pets/{petId}")
suspend fun deletePet(@Path("petId") petId: Long): Response<BaseResponse<Unit>>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package kr.ac.anu.mumu.data.local

import kr.ac.anu.mumu.data.datasource.AuthService
import kr.ac.anu.mumu.data.model.TokenRefreshRequest
import okhttp3.Authenticator
import okhttp3.Request
import okhttp3.Response
import okhttp3.Route
import javax.inject.Inject

class SessionAuthenticator @Inject constructor(
private val sessionManager: SessionManager,
private val authService: AuthService
) : Authenticator {

override fun authenticate(route: Route?, response: Response): Request? {
val previousToken = response.request.header("Authorization")?.removePrefix("Bearer ") ?: return null
if (responseCount(response) >= 2) return null

synchronized(this) {
val currentToken = sessionManager.accessToken ?: return null
if (currentToken != previousToken) {
return response.request.newBuilder().header("Authorization", "Bearer $currentToken").build()
}

val refreshToken = sessionManager.refreshToken ?: return null
val result = try {
authService.refresh(TokenRefreshRequest(refreshToken)).execute()
} catch (_: Exception) {
return null
}
val body = result.body()
if (!result.isSuccessful || body?.success != true) {
if (result.code() in 400..403) sessionManager.clearTokens()
return null
}
if (sessionManager.refreshToken != refreshToken) return null
val tokens = body.data
sessionManager.saveTokens(tokens.accessToken, tokens.refreshToken, tokens.tokenType)
return response.request.newBuilder()
.header("Authorization", "Bearer ${tokens.accessToken}")
.build()
}
}

private fun responseCount(response: Response): Int {
var current: Response? = response
var count = 0
while (current != null) {
count++
current = current.priorResponse
}
return count
}
}
20 changes: 20 additions & 0 deletions app/src/main/java/kr/ac/anu/mumu/data/local/SessionManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,18 @@ class SessionManager @Inject constructor(
val accessToken: String?
get() = preferences.getString(KEY_ACCESS_TOKEN, null)

val refreshToken: String?
get() = preferences.getString(KEY_REFRESH_TOKEN, null)

val selectedPetId: Long?
get() = preferences.getLong(KEY_SELECTED_PET_ID, -1L).takeIf { it > 0L }

fun selectPet(petId: Long?) {
preferences.edit().apply {
if (petId == null) remove(KEY_SELECTED_PET_ID) else putLong(KEY_SELECTED_PET_ID, petId)
}.apply()
}

fun saveTokens(accessToken: String, refreshToken: String, tokenType: String) {
preferences.edit()
.putString(KEY_ACCESS_TOKEN, accessToken)
Expand All @@ -22,10 +34,18 @@ class SessionManager @Inject constructor(
.apply()
}

fun clearTokens() {
preferences.edit()
.remove(KEY_ACCESS_TOKEN).remove(KEY_REFRESH_TOKEN).remove(KEY_TOKEN_TYPE)
.remove(KEY_SELECTED_PET_ID)
.apply()
}

private companion object {
const val PREFERENCES_NAME = "mumu_session"
const val KEY_ACCESS_TOKEN = "access_token"
const val KEY_REFRESH_TOKEN = "refresh_token"
const val KEY_TOKEN_TYPE = "token_type"
const val KEY_SELECTED_PET_ID = "selected_pet_id"
}
}
25 changes: 24 additions & 1 deletion app/src/main/java/kr/ac/anu/mumu/data/model/AnalysisDtos.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,28 @@ data class AnalysisDetailDto(

data class PetDto(
val petId: Long,
val name: String?
val name: String?,
val species: String? = null,
val breed: String? = null,
val gender: String? = null,
val birthDate: String? = null,
val weight: Double? = null,
val neutered: Boolean = false,
val allergies: String? = null,
val chronicDiseases: String? = null,
val medications: String? = null,
val profileImageUrl: String? = null
)

data class PetRequestDto(
val name: String,
val species: String,
val breed: String?,
val gender: String?,
val birthDate: String?,
val weight: Double?,
val neutered: Boolean,
val allergies: String?,
val chronicDiseases: String?,
val medications: String?
)
2 changes: 2 additions & 0 deletions app/src/main/java/kr/ac/anu/mumu/data/model/AuthDtos.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ data class LoginResponse(
val data: TokenDto
)

data class TokenRefreshRequest(val refreshToken: String)

data class TokenDto(
val accessToken: String,
val refreshToken: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,10 @@ data class BookmarkDto(
val bookmarked: Boolean,
val bookmarkCount: Int
)

data class UserProfileDto(
val userId: Long,
val loginId: String,
val name: String,
val phone: String
)
48 changes: 48 additions & 0 deletions app/src/main/java/kr/ac/anu/mumu/data/model/DiaryDtos.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package kr.ac.anu.mumu.data.model

data class UploadResponseDto(val key: String?, val url: String?)

data class DiaryRequestDto(
val petId: Long,
val mood: String,
val title: String,
val content: String,
val diaryDate: String,
val imageKeys: List<String>? = null,
val behaviorAnalysisId: Long? = null,
val soundAnalysisId: Long? = null,
val foodSafetyAnalysisId: Long? = null
)

data class DiaryAnalysisSummaryDto(
val analysisId: Long,
val type: String,
val resultLabel: String?
)

data class DiaryListDto(
val diaryId: Long,
val mood: String,
val title: String,
val contentPreview: String?,
val diaryDate: String,
val thumbnailUrl: String?
)

data class DiaryDetailDto(
val diaryId: Long,
val petId: Long,
val mood: String,
val title: String,
val content: String,
val diaryDate: String,
val imageUrls: List<String>?,
val analysisSummary: DiaryAnalysisSummaryDto?
)

data class DiaryCalendarDto(
val petId: Long,
val year: Int,
val month: Int,
val writtenDates: List<String>
)
Loading
Loading