Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
d3b894f
refactor: Contributors 사진 크기 조절
dpcks0509 Mar 23, 2025
7c9dbad
test: ci/cd
jinuemong Mar 23, 2025
004da66
test: ci/cd
jinuemong Mar 23, 2025
e2507b0
test: ci/cd
jinuemong Mar 23, 2025
42928bb
test: ci/cd
jinuemong Mar 23, 2025
ead818f
test: ci/cd
jinuemong Mar 23, 2025
e635760
test: ci/cd
jinuemong Mar 23, 2025
c00343e
Merge pull request #5 from TeamDATEROAD/test/cicd
jinuemong Mar 23, 2025
2407123
[feat] KaKao 장소 검색 API 연결 (#9)
dpcks0509 Mar 25, 2025
1e55fae
[feat] DefaultButtonSheet 생성 & Point 수집 UI 적용 (#10)
jinuemong Mar 26, 2025
3e38d70
[feat] 썸네일 UI & 로직 구현 (#16)
jinuemong Mar 27, 2025
9cbfc1f
[feat] 코스 등록 네비게이션 구현 & 디자인 요구사항 적용 (#18)
jinuemong Mar 29, 2025
f34e4ce
[feat] 장소 검색 바텀시트 UI 구현 및 데이터 연결 (#19)
dpcks0509 Mar 30, 2025
b8f5148
[feat] 장소에 도로명 주소 추가 (#21)
dpcks0509 Mar 31, 2025
611d1b6
[feat] 시청형 광고 구현 (#26)
jinuemong Apr 3, 2025
5b1f9c5
[feat] 장소검색 Paging 무한스크롤 & Debounce 적용 (#28)
dpcks0509 Apr 5, 2025
65c816b
[feat] 포인트 로깅 추가 (#31)
jinuemong Apr 7, 2025
0584234
fix : Date 인덱스 수정 (#32)
jinuemong Apr 7, 2025
387214d
[refactor] 장소 검색 LazyPaging 로직 개선 (#34)
jinuemong Apr 7, 2025
b630cbd
fix: 장소 등록 키보드, 바텀시트 애니메이션 겹침 해결 (#36)
dpcks0509 Apr 7, 2025
244332c
[release] 1.0.1 (#39)
jinuemong Apr 7, 2025
fc25615
feat : 빌드 키 추가
jinuemong Apr 8, 2025
c98c937
_
jinuemong Mar 23, 2025
2f08725
_
jinuemong Mar 23, 2025
e0d2668
_
jinuemong Mar 23, 2025
c89c999
test: ci/cd
jinuemong Mar 23, 2025
579b259
[feat] KaKao 장소 검색 API 연결 (#9)
dpcks0509 Mar 25, 2025
a4b3078
[feat] DefaultButtonSheet 생성 & Point 수집 UI 적용 (#10)
jinuemong Mar 26, 2025
016ad44
[feat] 썸네일 UI & 로직 구현 (#16)
jinuemong Mar 27, 2025
a721c0a
[feat] 코스 등록 네비게이션 구현 & 디자인 요구사항 적용 (#18)
jinuemong Mar 29, 2025
7cdcd9d
[feat] 장소 검색 바텀시트 UI 구현 및 데이터 연결 (#19)
dpcks0509 Mar 30, 2025
48f4151
[feat] 장소에 도로명 주소 추가 (#21)
dpcks0509 Mar 31, 2025
c3a6196
[feat] 시청형 광고 구현 (#26)
jinuemong Apr 3, 2025
5ebb6cf
[feat] 장소검색 Paging 무한스크롤 & Debounce 적용 (#28)
dpcks0509 Apr 5, 2025
3882d96
[feat] 포인트 로깅 추가 (#31)
jinuemong Apr 7, 2025
67d727c
[refactor] 장소 검색 LazyPaging 로직 개선 (#34)
jinuemong Apr 7, 2025
635d3e9
fix: 장소 등록 키보드, 바텀시트 애니메이션 겹침 해결 (#36)
dpcks0509 Apr 7, 2025
705fc7a
feat : 빌드 키 추가
jinuemong Apr 8, 2025
7ececae
Merge remote-tracking branch 'origin/develop' into develop
jinuemong Apr 8, 2025
3b688fa
feat : 빌드 키 추가
jinuemong Apr 8, 2025
7821b1b
feat : 빌드 키 추가
jinuemong Apr 8, 2025
45d6747
feat : 빌드 키 추가
jinuemong Apr 8, 2025
9d25e88
feat : 빌드 키 추가
jinuemong Apr 8, 2025
56ce39c
feat : 빌드 키 추가
jinuemong Apr 8, 2025
1e1511b
feat : 빌드 키 추가
jinuemong Apr 8, 2025
acc3785
1차 QA 반영 (#42)
jinuemong Apr 29, 2025
3ec1518
1차 QA 반영-2 (#45)
dpcks0509 Apr 30, 2025
bfa1932
1차 QA 반영-3 (#48)
dpcks0509 May 8, 2025
f497914
1차 QA 반영-4 (#49)
jinuemong May 8, 2025
dd1bc5a
1차 QA 반영-5 (#50)
jinuemong May 13, 2025
161f65a
[release] 1.0.2 version (#52)
dpcks0509 May 13, 2025
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
42 changes: 30 additions & 12 deletions .github/workflows/android_cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ jobs:
restore-keys: |
${{ runner.os }}-gradle-

- name: set up JDK 17
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: 17
Expand All @@ -43,7 +43,7 @@ jobs:
- name: Decode google-services.json
env:
FIREBASE_SECRET: ${{ secrets.FIREBASE_SECRET }}
run: echo $FIREBASE_SECRET > app/google-services.json
run: echo "$FIREBASE_SECRET" > app/google-services.json

- name: Access local properties
env:
Expand All @@ -52,24 +52,41 @@ jobs:
KAKAO_NATIVE_APP_KEY: ${{ secrets.KAKAO_NATIVE_APP_KEY }}
AMPLITUDE_API_KEY: ${{ secrets.AMPLITUDE_API_KEY }}
GOOGLE_ADS_API_ID: ${{ secrets.GOOGLE_ADS_API_ID }}
GOOGLE_ADS_API_ID_MANIFEST: ${{ secrets.GOOGLE_ADS_API_ID }}
GOOGLE_ADS_API_ID_MANIFEST: ${{ secrets.GOOGLE_ADS_API_ID_MANIFEST }}
run: |
echo "dev.base.url=\"$BASE_URL\"" >> local.properties
echo "dev.base.url=\"$HFM_BASE_URL\"" >> local.properties
echo "kakao.native.app.key.manifest=\"$KAKAO_NATIVE_APP_KEY_MANIFEST\"" >> local.properties
echo "kakao.native.app.key=\"$KAKAO_NATIVE_APP_KEY\"" >> local.properties
echo "amplitude.dev.api.key=\"$AMPLITUDE_API_KEY\"" >> local.properties
echo "google.ads.api.id=\"GOOGLE_ADS_API_ID\"" >> local.properties
echo "google.ads.api.id.manifest=\"GOOGLE_ADS_API_ID_MANIFEST\"" >> local.properties
echo "google.ads.api.id=\"$GOOGLE_ADS_API_ID\"" >> local.properties
echo "google.ads.api.id.manifest=\"$GOOGLE_ADS_API_ID_MANIFEST\"" >> local.properties

- name: Build Release APK
- name: Decode Keystore
run: echo "${{ secrets.KEYSTORE_BASE64 }}" | base64 -d > app/date_road.keystore

- name: Export signing environment
run: |
./gradlew :app:assembleRelease
echo "STORE_PASSWORD=${{ secrets.KEYSTORE_PASSWORD }}" >> $GITHUB_ENV
echo "KEY_ALIAS=${{ secrets.KEY_ALIAS }}" >> $GITHUB_ENV
echo "KEY_PASSWORD=${{ secrets.KEY_PASSWORD }}" >> $GITHUB_ENV

- name: Build Signed Release APK
run: ./gradlew :app:assembleRelease

- name: Upload Signed APK
uses: actions/upload-artifact@v4
with:
name: release-apk
path: ./app/build/outputs/apk/release/app-release.apk

- name: Build Signed Release AAB
run: ./gradlew :app:bundleRelease

- name: Upload Release APK
- name: Upload Signed AAB
uses: actions/upload-artifact@v4
with:
name: release
path: ./app/build/outputs/apk/release/app-release-unsigned.apk
name: release-aab
path: ./app/build/outputs/bundle/release/app-release.aab

- name: Discord Notify - Success
if: ${{ success() }}
Expand All @@ -81,7 +98,8 @@ jobs:
username: DATEROAD-ANDROID 🍫
content: |
Release Test가 완료되었습니다!
[❇️ APK를 다운로드해 보세요! ❇️](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})
[❇️ APK 다운로드](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})
[📦 AAB 다운로드](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})

- name: Discord Notify - Failure
if: ${{ failure() }}
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/android_ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ jobs:
KAKAO_REST_API_KEY: ${{ secrets.KAKAO_REST_API_KEY }}
AMPLITUDE_API_KEY: ${{ secrets.AMPLITUDE_API_KEY }}
GOOGLE_ADS_API_ID: ${{ secrets.GOOGLE_ADS_API_ID }}
GOOGLE_ADS_API_ID_MANIFEST: ${{ secrets.GOOGLE_ADS_API_ID }}
GOOGLE_ADS_API_ID_MANIFEST: ${{ secrets.GOOGLE_ADS_API_ID_MANIFEST }}
run: |
echo "dev.base.url=\"$BASE_URL\"" >> local.properties
echo "kakao.base.url=\"$KAKAO_BASE_URL\"" >> local.properties
Expand Down
16 changes: 16 additions & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ val properties = Properties().apply {
}

android {
val keystoreFile = file("date_road.keystore")

namespace = "org.sopt.teamdateroad"
compileSdk = libs.versions.compileSdk.get().toInt()

Expand All @@ -37,6 +39,16 @@ android {
manifestPlaceholders["KAKAO_NATIVE_APP_KEY_MANIFEST"] = properties["kakao.native.app.key.manifest"] as String
manifestPlaceholders["GOOGLE_ADS_API_ID_MANIFEST"] = properties["google.ads.api.id.manifest"] as String
}
signingConfigs {
if (keystoreFile.exists()) {
create("release") {
storeFile = keystoreFile
storePassword = System.getenv("STORE_PASSWORD")
keyAlias = System.getenv("KEY_ALIAS")
keyPassword = System.getenv("KEY_PASSWORD")
}
}
}

buildTypes {
debug {
Expand All @@ -47,6 +59,9 @@ android {
}

release {
if (keystoreFile.exists()) {
signingConfig = signingConfigs.getByName("release")
}
isMinifyEnabled = true
isShrinkResources = true
buildConfigField("String", "BASE_URL", properties["prod.base.url"].toString())
Expand All @@ -58,6 +73,7 @@ android {
)
}
}

compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,10 @@ enum class DateChipGroupType(
titleRes = R.string.date_chip_group_enroll_course,
titleTextStyle = defaultDateRoadTypography.bodySemi15,
maxSize = 3
),
TIMELINE(
titleRes = R.string.date_chip_group_enroll_timeline,
titleTextStyle = defaultDateRoadTypography.bodySemi15,
maxSize = 3
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ enum class TagType(
PLACE_CARD_TIME(
backgroundColor = defaultDateRoadColors.gray200,
contentColor = defaultDateRoadColors.black,
paddingHorizontal = 14,
paddingHorizontal = 0,
paddingVertical = 5,
textStyle = defaultDateRoadTypography.bodyMed13,
roundedCornerShape = 10
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
package org.sopt.teamdateroad.presentation.ui.component.bottomsheet

import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.material3.Button
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import org.sopt.teamdateroad.presentation.ui.component.bottomsheet.model.Picker
import org.sopt.teamdateroad.presentation.ui.component.numberpicker.DateRoadNumberPicker
import org.sopt.teamdateroad.presentation.ui.component.numberpicker.state.PickerState
import org.sopt.teamdateroad.presentation.util.DatePicker
import org.sopt.teamdateroad.ui.theme.DateRoadTheme

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun DateRoadDatePickerBottomSheet(
isBottomSheetOpen: Boolean,
isButtonEnabled: Boolean,
buttonText: String,
onDatePickerBottomSheetButtonClick: (String) -> Unit,
onDismissRequest: () -> Unit = {}
) {
val yearItems = (DatePicker.YEAR_START..DatePicker.YEAR_END).map { it.toString() }
val monthItems = (DatePicker.MONTH_START..DatePicker.MONTH_END).map { it.toString().padStart(2, '0') }

val yearState = remember { PickerState() }
val monthState = remember { PickerState() }
val dayState = remember { PickerState() }
val dayItemsState = remember { mutableStateOf((1..31).map { it.toString().padStart(2, '0') }) }

LaunchedEffect(yearState.selectedItem, monthState.selectedItem) {
val year = yearState.selectedItem.toIntOrNull() ?: DatePicker.YEAR_START
val month = monthState.selectedItem.toIntOrNull() ?: DatePicker.MONTH_START
val lastDay = getLastDayOfMonth(year, month)
val newDays = (DatePicker.DAY_START..lastDay).map { it.toString().padStart(2, '0') }

dayItemsState.value = newDays
if (dayState.selectedItem !in newDays) {
dayState.selectedItem = newDays.first()
}
}

val yearPicker = Picker(
items = yearItems,
startIndex = yearItems.indexOf(yearState.selectedItem),
pickerState = yearState
)
val monthPicker = Picker(
items = monthItems,
startIndex = monthItems.indexOf(monthState.selectedItem),
pickerState = monthState
)
val dayPicker = Picker(
items = dayItemsState.value,
startIndex = dayItemsState.value.indexOf(dayState.selectedItem),
pickerState = dayState
)

val pickers = listOf(yearPicker, monthPicker, dayPicker)

LaunchedEffect(Unit) {
yearState.selectedItem = yearItems[DatePicker.YEAR_START_INDEX]
monthState.selectedItem = monthItems.first()
dayState.selectedItem = dayItemsState.value.first()
}

DateRoadBottomSheet(
modifier = Modifier.padding(top = 20.dp, bottom = 16.dp, start = 16.dp, end = 16.dp),
isBottomSheetOpen = isBottomSheetOpen,
isButtonEnabled = isButtonEnabled,
buttonText = buttonText,
onButtonClick = {
val selectedDate = pickers.joinToString(separator = DatePicker.SEPARATOR) {
it.pickerState.selectedItem.padStart(2, '0')
}
onDatePickerBottomSheetButtonClick(selectedDate)
// 상태 초기화
yearState.selectedItem = yearItems[DatePicker.YEAR_START_INDEX]
monthState.selectedItem = monthItems.first()
dayState.selectedItem = dayItemsState.value.first()
},
onDismissRequest = {
yearState.selectedItem = yearItems[DatePicker.YEAR_START_INDEX]
monthState.selectedItem = monthItems.first()
dayState.selectedItem = dayItemsState.value.first()
onDismissRequest()
}
) {
Column {
Row(modifier = Modifier.fillMaxWidth()) {
pickers.forEachIndexed { index, item ->
DateRoadNumberPicker(
modifier = Modifier.weight(1f),
items = item.items,
startIndex = if (index == 0)item.items.indexOf(item.pickerState.selectedItem) else 0,
pickerState = item.pickerState
)
if (index != pickers.size - 1) {
Spacer(modifier = Modifier.width(17.dp))
}
}
}
Spacer(modifier = Modifier.height(19.dp))
}
}
}

fun getLastDayOfMonth(year: Int, month: Int): Int {
return when (month) {
1, 3, 5, 7, 8, 10, 12 -> 31
4, 6, 9, 11 -> 30
2 -> if (isLeapYear(year)) 29 else 28
else -> 31
}
}

fun isLeapYear(year: Int): Boolean {
return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)
}

@Preview
@Composable
fun DateRoadDatePickerBottomSheetPreview() {
var isBottomSheetOpen by rememberSaveable { mutableStateOf(false) }

Button(onClick = { isBottomSheetOpen = true }) {
Text(
text = "DateRoadPickerBottomSheet",
color = DateRoadTheme.colors.black,
style = DateRoadTheme.typography.titleExtra24
)
}

DateRoadDatePickerBottomSheet(
isBottomSheetOpen = isBottomSheetOpen,
isButtonEnabled = true,
buttonText = "취소",
onDatePickerBottomSheetButtonClick = {}
)
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
package org.sopt.teamdateroad.presentation.ui.component.button

import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
Expand Down Expand Up @@ -39,16 +37,16 @@ fun DateRoadKakaoLoginButton(
paddingHorizontal = 14.dp,
onClick = onClick
) {
Row(
verticalAlignment = Alignment.CenterVertically
Box(
modifier.fillMaxWidth()
) {
Image(
painter = painterResource(id = R.drawable.ic_kakao_logo),
contentDescription = null,
modifier = Modifier
.clip(CircleShape)
.align(Alignment.CenterStart)
)
Spacer(modifier = Modifier.size(5.dp))
Text(
text = stringResource(id = R.string.kakao_login),
fontSize = 15.sp,
Expand All @@ -57,7 +55,7 @@ fun DateRoadKakaoLoginButton(
color = contentColor,
textAlign = TextAlign.Center,
modifier = Modifier
.align(Alignment.CenterVertically)
.align(Alignment.Center)
.fillMaxWidth()
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ fun DateRoadCourseCard(
Row(
modifier = modifier
.fillMaxWidth()
.padding(end = 16.dp)
.height(130.dp)
.background(DateRoadTheme.colors.white)
.noRippleClickable(onClick = { onClick(course.courseId) })
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ fun DateRoadPlaceCard(
place: Place,
onIconClick: (() -> Unit)? = null
) {
val paddingValues = Modifier.padding(start = placeCardType.startPadding, end = 17.dp)
val paddingValues = Modifier.padding(start = placeCardType.startPadding, end = 13.dp)

Row(
modifier = modifier
Expand Down Expand Up @@ -75,6 +75,7 @@ fun DateRoadPlaceCard(
Spacer(modifier = Modifier.width(10.dp))

DateRoadTextTag(
modifier = Modifier.width(61.dp),
textContent = place.duration,
tagContentType = TagType.PLACE_CARD_TIME
)
Expand Down Expand Up @@ -130,7 +131,7 @@ fun DateRoadPlaceCardPreview() {
DateRoadPlaceCard(
placeCardType = PlaceCardType.COURSE_NORMAL,
sequence = 0,
place = Place(title = "성수미술관 성수점성수미술관 성수점성수미술관 성수점성수미술관 성수점성수미술관 성수점", address = "서울 광진구 자양동 704-1", duration = "2.5시간")
place = Place(title = "성수미술관 성수점성수미술관 성수점성수미술관 성수점성수미술관 성수점성수미술관 성수점", address = "서울 광진구 자양동 704-1", duration = "4.0시간")
)
Spacer(modifier = Modifier.height(8.dp))
DateRoadPlaceCard(
Expand Down
Loading