Skip to content
Merged
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
06fc80d
[FEAT/#1457] viewType 수정
Hyobeen-Park Jan 6, 2026
00c8d3a
[FEAT/#1457] 로컬 로직 구현
Hyobeen-Park Jan 6, 2026
93e2cbb
Merge remote-tracking branch 'origin/develop' into feat/#1457-appjamt…
Hyobeen-Park Jan 6, 2026
ee55237
[FEAT/#1457] 스탬프 조회 구현
Hyobeen-Park Jan 6, 2026
59b6ef3
[FEAT/#1457] 스탬프 등록 구현
Hyobeen-Park Jan 6, 2026
30b1f00
[FEAT/#1457] 박수치기 구현
Hyobeen-Park Jan 6, 2026
2b5b5a1
[FEAT/#1457] 스탬프 수정 구현
Hyobeen-Park Jan 6, 2026
2d5d123
[FEAT/#1457] 박수 친 목록 조회 구현
Hyobeen-Park Jan 6, 2026
864e310
[FEAT/#1457] 미션 삭제 구현
Hyobeen-Park Jan 6, 2026
6131220
[MOD/#1457] 헤더 -> 팀 이름으로 수정
Hyobeen-Park Jan 6, 2026
200c101
[MOD/#1457] 헤더 -> 팀 이름으로 수정
Hyobeen-Park Jan 7, 2026
64672a6
[FEAT/#1464] 라우트 세팅
Hyobeen-Park Jan 7, 2026
5fcf4e9
[CHORE/#1464] AppjamtampMissionsResponseDto nullable 처리
Hyobeen-Park Jan 7, 2026
5c2908f
[CHORE/#1464] 미션 목록 ui 수정
Hyobeen-Park Jan 7, 2026
40ce050
[FEAT/#1464] 미션 목록 화면전환 이벤트 연결
Hyobeen-Park Jan 7, 2026
38dc759
[FEAT/#1464] 랭킹 화면전환 이벤트 연결
Hyobeen-Park Jan 7, 2026
125cf5a
[MOD/#1464] 랭킹뷰 네비게이션 수정
Hyobeen-Park Jan 7, 2026
a0f05cd
[MOD/#1464] 오류 수정
Hyobeen-Park Jan 7, 2026
1d00b9d
[FEAT/#1464] 딥링크 추가
Hyobeen-Park Jan 7, 2026
504eb3c
Merge remote-tracking branch 'origin/develop' into feat/#1464-appjamt…
Hyobeen-Park Jan 7, 2026
c6220bf
Merge remote-tracking branch 'origin/develop' into feat/#1464-appjamt…
Hyobeen-Park Jan 7, 2026
f1fc9b2
[FIX/#1457] align 수정
Hyobeen-Park Jan 7, 2026
262d64c
[FIX/#1457] nullable 처리
Hyobeen-Park Jan 7, 2026
a1a73c4
[FIX/#1457] spacer 추가
Hyobeen-Park Jan 7, 2026
427a132
[FIX/#1464] qa 반영
Hyobeen-Park Jan 7, 2026
df801da
[FIX/#1464] qa 반영
Hyobeen-Park Jan 7, 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 @@ -27,6 +27,7 @@ package org.sopt.official.feature.navigator
import android.content.Context
import android.content.Intent
import dagger.hilt.android.qualifiers.ApplicationContext
import javax.inject.Inject
import org.sopt.official.common.navigator.DeepLinkType
import org.sopt.official.common.navigator.NavigatorProvider
import org.sopt.official.feature.attendance.AttendanceActivity
Expand All @@ -41,7 +42,6 @@ import org.sopt.official.feature.notification.detail.NotificationDetailActivity
import org.sopt.official.feature.schedule.ScheduleActivity
import org.sopt.official.model.UserStatus
import org.sopt.official.stamp.feature.navigation.SoptampMissionArgs
import javax.inject.Inject

class NavigatorProviderIntent @Inject constructor(
@param:ApplicationContext private val context: Context,
Expand Down Expand Up @@ -114,15 +114,22 @@ class NavigatorProviderIntent @Inject constructor(
}
}

override fun getPokeNotificationActivityIntent(name: String) : Intent {
override fun getAppjamtampActivityIntent(): Intent {
return Intent(context, MainActivity::class.java).apply {
putExtra("isAppjamtampDeepLink", true)
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP)
}
}

override fun getPokeNotificationActivityIntent(name: String): Intent {
return Intent(context, MainActivity::class.java).apply {
putExtra("userStatus", name)
putExtra("isPokeNotification", true)
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP)
}
}

override fun getPokeFriendListSummaryActivityIntent(name: String, friendType: String?) : Intent {
override fun getPokeFriendListSummaryActivityIntent(name: String, friendType: String?): Intent {
return Intent(context, MainActivity::class.java).apply {
putExtra("userStatus", name)
putExtra("friendType", friendType)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,11 @@ enum class DeepLinkType(
override fun getIntent(context: Context, userStatus: UserStatus, deepLink: String) =
userStatus.setIntent(navigator.getSoptampActivityIntent())
},
APPJAMTAMP("appjamtamp") {
override fun getIntent(context: Context, userStatus: UserStatus, deepLink: String) =
userStatus.setIntent(navigator.getAppjamtampActivityIntent())
},

// TODO - 콕찌르기 이슈 해결되면 딥링크에서 home 제거해야 함 (서버 변경으로 home 제거)
POKE_NOTIFICATION_LIST("home/poke/notification-list") {
override fun getIntent(context: Context, userStatus: UserStatus, deepLink: String) =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ interface NavigatorProvider {
fun getAdjustSentenceActivityIntent(): Intent
fun getAttendanceActivityIntent(): Intent
fun getSoptampActivityIntent(): Intent
fun getAppjamtampActivityIntent(): Intent
fun getPokeNotificationActivityIntent(name: String): Intent
fun getPokeFriendListSummaryActivityIntent(name: String, friendType: String?): Intent
fun getPokeActivityIntent(userStatus: UserStatus): Intent
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,16 @@ import org.sopt.official.domain.appjamtamp.entity.AppjamtampMissionListEntity
@Serializable
data class AppjamtampMissionsResponseDto(
@SerialName("teamNumber")
val teamNumber: String,
val teamNumber: String?,
@SerialName("teamName")
val teamName: String,
val teamName: String?,
@SerialName("missions")
val missions: List<AppjamtampMissionItemDto>
) {
fun toEntity(): AppjamtampMissionListEntity {
return AppjamtampMissionListEntity(
teamNumber = teamNumber,
teamName = teamName,
teamNumber = teamNumber.orEmpty(),
teamName = teamName.orEmpty(),
missions = missions.map { it.toEntity() }
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,18 @@ import org.sopt.official.domain.appjamtamp.entity.AppjamtampMyAppjamInfoEntity
@Serializable
data class AppjamtampMyAppjamInfoResponseDto(
@SerialName("teamNumber")
val teamNumber: String,
val teamNumber: String?,

@SerialName("teamName")
val teamName: String,
val teamName: String?,

@SerialName("isAppjamJoined")
val isAppjamJoined: Boolean
) {
fun toEntity(): AppjamtampMyAppjamInfoEntity {
return AppjamtampMyAppjamInfoEntity(
teamNumber = teamNumber,
teamName = teamName,
teamNumber = teamNumber.orEmpty(),
teamName = teamName.orEmpty(),
isAppjamJoined = isAppjamJoined
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,12 @@ data class AppjamtampTop10MissionScoreResponse(
data class AppjamtampMissionScoreResponse(
@SerialName("rank")
val rank: Int,

@SerialName("teamName")
val teamName: String,

@SerialName("teamNumber")
val teamNumber: String,
@SerialName("todayPoints")
val todayPoints: Int,

@SerialName("totalPoints")
val totalPoints: Int
)
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ package org.sopt.official.data.appjamtamp.mapper

import org.sopt.official.data.appjamtamp.dto.response.AppjamtampMissionScoreResponse
import org.sopt.official.data.appjamtamp.dto.response.AppjamtampRecentMissionResponse
import org.sopt.official.data.appjamtamp.dto.response.AppjamtampTop3RecentMissionResponse
import org.sopt.official.data.appjamtamp.dto.response.AppjamtampTop10MissionScoreResponse
import org.sopt.official.data.appjamtamp.dto.response.AppjamtampTop3RecentMissionResponse
import org.sopt.official.domain.appjamtamp.entity.AppjamtampMissionScore
import org.sopt.official.domain.appjamtamp.entity.AppjamtampRecentMission

Expand Down Expand Up @@ -34,6 +34,7 @@ internal fun AppjamtampMissionScoreResponse.toDomain(): AppjamtampMissionScore {
return AppjamtampMissionScore(
rank = this.rank,
teamName = this.teamName,
teamNumber = this.teamNumber,
todayPoints = this.todayPoints,
totalPoints = this.todayPoints
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package org.sopt.official.domain.appjamtamp.entity
data class AppjamtampMissionScore(
val rank: Int,
val teamName: String,
val teamNumber: String,
val todayPoints: Int,
val totalPoints: Int
)
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ package org.sopt.official.feature.appjamtamp.component

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.foundation.lazy.grid.items
Expand All @@ -17,27 +15,24 @@ import org.sopt.official.feature.appjamtamp.missionlist.model.AppjamtampMissionU

@Composable
internal fun MissionsGridComponent(
missionList : ImmutableList<AppjamtampMissionUiModel>,
missionList: ImmutableList<AppjamtampMissionUiModel>,
modifier: Modifier = Modifier,
onMissionItemClick: (item: AppjamtampMissionUiModel) -> Unit = {},
onMissionItemClick: (item: AppjamtampMissionUiModel) -> Unit = {}
) {
LazyVerticalGrid(
modifier = modifier,
columns = GridCells.Fixed(2),
verticalArrangement = Arrangement.spacedBy(40.dp, Alignment.Top),
horizontalArrangement = Arrangement.spacedBy(8.dp),
contentPadding = PaddingValues(bottom = 80.dp),
contentPadding = PaddingValues(bottom = 80.dp)
) {
items(items = missionList) { mission ->
MissionComponent(
mission = mission,
onClick = {
onMissionItemClick(mission)
},
}
)
}
item {
Spacer(modifier = Modifier.padding(vertical = 20.dp))
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.sopt.official.feature.appjamtamp.missiondetail

import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
Expand Down Expand Up @@ -194,7 +195,9 @@ private fun MyEmptyMissionDetailScreen(
) {
BackButtonHeader(
title = "미션",
onBackButtonClick = onBackButtonClick
onBackButtonClick = onBackButtonClick,
modifier = Modifier
.padding(vertical = 12.dp)
)

Spacer(modifier = Modifier.height(10.dp))
Expand Down Expand Up @@ -257,80 +260,89 @@ private fun MissionDetailScreen(
val scrollState = rememberScrollState()
var isEditable by remember(uiState.viewType) { mutableStateOf(uiState.viewType == DetailViewType.EDIT) }

Column(
Box(
modifier = Modifier
.fillMaxSize()
.systemBarsPadding()
.padding(horizontal = 16.dp)
.verticalScroll(scrollState)
.systemBarsPadding(),
contentAlignment = Alignment.BottomCenter
) {
BackButtonHeader(
title = if (uiState.viewType == DetailViewType.COMPLETE) "내 미션" else uiState.teamName,
onBackButtonClick = onBackButtonClick,
trailingIcon = {
uiState.viewType.toolbarIcon?.let {
Icon(
imageVector = ImageVector.vectorResource(uiState.viewType.toolbarIcon),
contentDescription = null,
tint = SoptTheme.colors.onSurface10,
modifier = Modifier
.clickable(onClick = onToolbarIconClick)
)
}
}
)
Column(
modifier = Modifier
.fillMaxSize()
.verticalScroll(scrollState)
.align(Alignment.TopCenter)
) {
BackButtonHeader(
title = if (uiState.viewType == DetailViewType.COMPLETE) "내 미션" else uiState.teamName,
onBackButtonClick = onBackButtonClick,
trailingIcon = {
uiState.viewType.toolbarIcon?.let {
Icon(
imageVector = ImageVector.vectorResource(uiState.viewType.toolbarIcon),
contentDescription = null,
tint = SoptTheme.colors.onSurface10,
modifier = Modifier
.clickable(onClick = onToolbarIconClick)
)
}
},
modifier = Modifier
.padding(vertical = 12.dp)
)

Spacer(modifier = Modifier.height(10.dp))
Spacer(modifier = Modifier.height(10.dp))

MissionHeader(
title = uiState.mission.title,
stamp = Stamp.findStampByLevel(uiState.mission.level)
)
MissionHeader(
title = uiState.mission.title,
stamp = Stamp.findStampByLevel(uiState.mission.level)
)

Spacer(modifier = Modifier.height(5.dp))
Spacer(modifier = Modifier.height(5.dp))

ImageContent(
imageModel = uiState.imageModel,
onChangeImage = onChangeImage,
onClickZoomIn = onClickZoomIn,
isEditable = isEditable
)
ImageContent(
imageModel = uiState.imageModel,
onChangeImage = onChangeImage,
onClickZoomIn = onClickZoomIn,
isEditable = isEditable
)

Spacer(modifier = Modifier.height(12.dp))
Spacer(modifier = Modifier.height(12.dp))

ProfileTag(
name = uiState.writer.name,
profileImage = uiState.writer.profileImage
)
ProfileTag(
name = uiState.writer.name,
profileImage = uiState.writer.profileImage
)

Spacer(modifier = Modifier.height(16.dp))
Spacer(modifier = Modifier.height(16.dp))

if (isEditable) {
DatePicker(
value = uiState.date,
placeHolder = "날짜를 입력해주세요.",
isEditable = true,
onClicked = onDatePickerClick
)
if (isEditable) {
DatePicker(
value = uiState.date,
placeHolder = "날짜를 입력해주세요.",
isEditable = true,
onClicked = onDatePickerClick
)

Spacer(modifier = Modifier.height(8.dp))
}
Spacer(modifier = Modifier.height(8.dp))
}

Memo(
value = uiState.content,
placeHolder = "함께한 사람과 어떤 추억을 남겼는지 작성해 주세요.",
onValueChange = onMemoChange,
isEditable = isEditable
)
Spacer(modifier = Modifier.height(8.dp))
Memo(
value = uiState.content,
placeHolder = "함께한 사람과 어떤 추억을 남겼는지 작성해 주세요.",
onValueChange = onMemoChange,
isEditable = isEditable
)
Spacer(modifier = Modifier.height(8.dp))

DetailInfo(
date = uiState.date,
clapCount = uiState.clapCount,
viewCount = uiState.viewCount
)
DetailInfo(
date = uiState.date,
clapCount = uiState.clapCount,
viewCount = uiState.viewCount
)

Spacer(modifier = Modifier.weight(1f))
Spacer(modifier = Modifier.height(120.dp))
}

when (uiState.viewType) {
DetailViewType.READ_ONLY -> {
Expand All @@ -340,7 +352,6 @@ private fun MissionDetailScreen(
onPressClap = onActionButtonClick,
modifier = Modifier
.fillMaxWidth()
.align(Alignment.CenterHorizontally)
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ internal data class MissionDetailState(
val isLoading: Boolean = true,
val isFailed: Boolean = false,

val viewType: DetailViewType = DetailViewType.WRITE,
val viewType: DetailViewType = DetailViewType.READ_ONLY,
val mission: Mission = Mission.DEFAULT,
val imageModel: ImageModel = ImageModel.Empty,
val date: String = "",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,12 @@ internal class MissionDetailViewModel @Inject constructor(
}

fun handleSubmit() {
with(_missionDetailState.value) {
if (content.isBlank()) return
if (imageModel is ImageModel.Empty) return
if (date.isBlank()) return
}

_missionDetailState.update {
it.copy(isLoading = true)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import kotlinx.serialization.Serializable
import org.sopt.official.core.navigation.Route

@Serializable
data class AppjamtampMissionDetail(
internal data class AppjamtampMissionDetail(
val missionId: Int = -1,
val missionLevel: Int = 1,
val title: String = "",
Expand Down
Loading