From 7ada5690a089d9fd4f71d76867508701ff7f0e5c Mon Sep 17 00:00:00 2001 From: kangyuri1114 Date: Fri, 5 Jul 2024 02:46:23 +0900 Subject: [PATCH 01/31] =?UTF-8?q?[feat]:=20=ED=94=84=EB=A1=9C=EC=A0=9D?= =?UTF-8?q?=ED=8A=B8=20=EB=93=B1=EB=A1=9D=20UI=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- feature/projects/src/main/AndroidManifest.xml | 3 + .../projects/projects/ProjectsFragment.kt | 4 +- .../zucchini/submit/SubmitProjectActivity.kt | 15 + .../res/layout/activity_submit_project.xml | 413 ++++++++++++++++++ .../main/res/layout/dialog_radio_buttons.xml | 13 + .../dialog_submit_project_developers.xml | 123 ++++++ .../projects/src/main/res/values/strings.xml | 26 ++ 7 files changed, 595 insertions(+), 2 deletions(-) create mode 100644 feature/projects/src/main/java/com/zucchini/submit/SubmitProjectActivity.kt create mode 100644 feature/projects/src/main/res/layout/activity_submit_project.xml create mode 100644 feature/projects/src/main/res/layout/dialog_radio_buttons.xml create mode 100644 feature/projects/src/main/res/layout/dialog_submit_project_developers.xml diff --git a/feature/projects/src/main/AndroidManifest.xml b/feature/projects/src/main/AndroidManifest.xml index 622e53b..f217fe3 100644 --- a/feature/projects/src/main/AndroidManifest.xml +++ b/feature/projects/src/main/AndroidManifest.xml @@ -2,6 +2,9 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/feature/projects/src/main/res/layout/dialog_radio_buttons.xml b/feature/projects/src/main/res/layout/dialog_radio_buttons.xml new file mode 100644 index 0000000..67a5108 --- /dev/null +++ b/feature/projects/src/main/res/layout/dialog_radio_buttons.xml @@ -0,0 +1,13 @@ + + + + + + diff --git a/feature/projects/src/main/res/layout/dialog_submit_project_developers.xml b/feature/projects/src/main/res/layout/dialog_submit_project_developers.xml new file mode 100644 index 0000000..a4ee241 --- /dev/null +++ b/feature/projects/src/main/res/layout/dialog_submit_project_developers.xml @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/feature/projects/src/main/res/values/strings.xml b/feature/projects/src/main/res/values/strings.xml index 2003048..fa96bbd 100644 --- a/feature/projects/src/main/res/values/strings.xml +++ b/feature/projects/src/main/res/values/strings.xml @@ -10,14 +10,28 @@ 개발자 찾기 개발자 상세 페이지 프로젝트 상세 페이지 + 프로젝트 등록하기 Github + 프로젝트 Github 주소 카카오톡 아이디 이메일 프로젝트 보러가기↗ 개발자 정보 프로젝트 소개 + 프로젝트 소개를 입력해주세요 프로젝트 소개 관련 링크 + 사용가능한 웹 링크를 입력해주세요 + 앱을 다운받을 수 있는 곳의 링크를 입력해주세요 + 프로젝트 소개 페이지 링크를 입력해주세요 + 웹 링크 + 개발자 이름 + 이메일 + 개발한 분야를 선택해주세요 + 앱 다운로드 링크 + 소개 페이지 링크 + 팀 리더 + 함께한 개발자를 선택해주세요! 개발자 정보 화면 터치 시 슈플렉터를 시작할 수 있어요! 내 정보 @@ -64,5 +78,17 @@ 카카오톡 아이디 아직 출시되지 않았어요! 준비 중입니다 :) + 프로젝트의 깃허브 링크를 입력해주세요 + 등록할 프로젝트 이름을 입력해주세요. + 기술 스택을 선택해주세요 + 프로젝트의 카테고리를 선택해주세요 + 언어 + 프로젝트에 대한 상세 설명을 작성해주세요. (500자 제한) + 프로젝트 한줄 소개를 작성해주세요. + 개발자 정보 입력하기↗ + 사용 언어↗ + 기술 스택↗ + 협업툴↗ + 카테고리↗ \ No newline at end of file From e852b137cdcee320fff2fafe06f5b14f9d1a0d34 Mon Sep 17 00:00:00 2001 From: kangyuri1114 Date: Fri, 5 Jul 2024 03:33:16 +0900 Subject: [PATCH 02/31] =?UTF-8?q?[fix]:=20UI=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- feature/projects/src/main/AndroidManifest.xml | 4 +++- .../res/layout/activity_submit_project.xml | 22 ++++++++----------- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/feature/projects/src/main/AndroidManifest.xml b/feature/projects/src/main/AndroidManifest.xml index f217fe3..218067d 100644 --- a/feature/projects/src/main/AndroidManifest.xml +++ b/feature/projects/src/main/AndroidManifest.xml @@ -4,7 +4,9 @@ + android:exported="false" + android:screenOrientation="portrait" + android:theme="@style/Theme.AppCompat.Light.NoActionBar"/> @@ -204,7 +203,7 @@ android:background="@drawable/stack_background" android:fontFamily="@font/pretendardmedium" android:gravity="center" - android:padding="5dp" + android:padding="12dp" android:text="@string/tv_submit_project_category" android:textColor="@color/olive_black" android:textSize="10sp" @@ -234,7 +233,7 @@ android:background="@drawable/stack_background" android:fontFamily="@font/pretendardmedium" android:gravity="center" - android:padding="5dp" + android:padding="12dp" android:text="@string/tv_dev_stack_language" android:textColor="@color/olive_black" android:textSize="10sp" @@ -251,7 +250,7 @@ android:background="@drawable/stack_background" android:fontFamily="@font/pretendardmedium" android:gravity="center" - android:padding="5dp" + android:padding="12dp" android:text="@string/tv_dev_stack_dev_stack" android:textColor="@color/olive_black" android:textSize="10sp" @@ -268,7 +267,7 @@ android:background="@drawable/stack_background" android:fontFamily="@font/pretendardmedium" android:gravity="center" - android:padding="5dp" + android:padding="12dp" android:text="@string/tv_dev_stack_cooperation" android:textColor="@color/olive_black" android:textSize="10sp" @@ -298,10 +297,9 @@ android:fontFamily="@font/pretendardregular" android:gravity="center" android:hint="@string/tv_project_submit_web_link_hint" - android:padding="5dp" android:paddingHorizontal="2dp" android:textColor="@color/olive_black" - android:textSize="12sp" + android:textSize="10sp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/tv_project_submit_web_link_title" /> @@ -329,10 +327,9 @@ android:fontFamily="@font/pretendardregular" android:gravity="center" android:hint="@string/et_project_app_link_hint" - android:padding="5dp" android:paddingHorizontal="2dp" android:textColor="@color/olive_black" - android:textSize="12sp" + android:textSize="10sp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/tv_project_submit_app_link_title" /> @@ -360,10 +357,9 @@ android:fontFamily="@font/pretendardregular" android:gravity="center" android:hint="@string/et_project_info_link_hint" - android:padding="5dp" android:paddingHorizontal="2dp" android:textColor="@color/olive_black" - android:textSize="12sp" + android:textSize="10sp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/tv_project_submit_info_link_title" /> @@ -391,7 +387,7 @@ android:background="@drawable/stack_background" android:fontFamily="@font/pretendardmedium" android:gravity="center" - android:padding="5dp" + android:padding="15dp" android:text="@string/tv_project_submit_developer" android:textColor="@color/olive_black" android:textSize="10sp" From 4869b548fc8509363f3efc97196df8f132a9a4ce Mon Sep 17 00:00:00 2001 From: kangyuri1114 Date: Fri, 5 Jul 2024 03:37:24 +0900 Subject: [PATCH 03/31] =?UTF-8?q?[fix]:=20UI=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/res/layout/activity_submit_project.xml | 9 +++++---- feature/projects/src/main/res/values/strings.xml | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/feature/projects/src/main/res/layout/activity_submit_project.xml b/feature/projects/src/main/res/layout/activity_submit_project.xml index a040f07..6c75ae6 100644 --- a/feature/projects/src/main/res/layout/activity_submit_project.xml +++ b/feature/projects/src/main/res/layout/activity_submit_project.xml @@ -150,7 +150,7 @@ android:layout_marginTop="8dp" android:layout_marginEnd="20dp" android:fontFamily="@font/pretendardregular" - android:gravity="center" + android:gravity="start" android:hint="@string/et_project_intro_content_short_hint" android:maxLines="1" android:paddingHorizontal="2dp" @@ -295,7 +295,7 @@ android:layout_marginTop="8dp" android:layout_marginEnd="20dp" android:fontFamily="@font/pretendardregular" - android:gravity="center" + android:gravity="start" android:hint="@string/tv_project_submit_web_link_hint" android:paddingHorizontal="2dp" android:textColor="@color/olive_black" @@ -325,7 +325,7 @@ android:layout_marginTop="8dp" android:layout_marginEnd="20dp" android:fontFamily="@font/pretendardregular" - android:gravity="center" + android:gravity="start" android:hint="@string/et_project_app_link_hint" android:paddingHorizontal="2dp" android:textColor="@color/olive_black" @@ -355,7 +355,7 @@ android:layout_marginTop="8dp" android:layout_marginEnd="20dp" android:fontFamily="@font/pretendardregular" - android:gravity="center" + android:gravity="start" android:hint="@string/et_project_info_link_hint" android:paddingHorizontal="2dp" android:textColor="@color/olive_black" @@ -398,6 +398,7 @@ android:id="@+id/rv_project_detail_dev" android:layout_width="match_parent" android:layout_height="wrap_content" + android:background="@color/bright_olive" android:layout_marginHorizontal="25dp" android:layout_marginVertical="10dp" app:layout_constraintBottom_toBottomOf="parent" diff --git a/feature/projects/src/main/res/values/strings.xml b/feature/projects/src/main/res/values/strings.xml index fa96bbd..1992f69 100644 --- a/feature/projects/src/main/res/values/strings.xml +++ b/feature/projects/src/main/res/values/strings.xml @@ -31,7 +31,7 @@ 앱 다운로드 링크 소개 페이지 링크 팀 리더 - 함께한 개발자를 선택해주세요! + 함께한 개발자를 정보를 입력해주세요! 개발자 정보 화면 터치 시 슈플렉터를 시작할 수 있어요! 내 정보 From 7c17fb54c0eef8888e6622e922d0c5b17fff290b Mon Sep 17 00:00:00 2001 From: kangyuri1114 Date: Fri, 5 Jul 2024 03:38:40 +0900 Subject: [PATCH 04/31] =?UTF-8?q?[feat]:=20back=20button=20=ED=81=B4?= =?UTF-8?q?=EB=A6=AD=20=EC=9D=B4=EB=B2=A4=ED=8A=B8=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/zucchini/submit/SubmitProjectActivity.kt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/feature/projects/src/main/java/com/zucchini/submit/SubmitProjectActivity.kt b/feature/projects/src/main/java/com/zucchini/submit/SubmitProjectActivity.kt index 06a0235..09256fa 100644 --- a/feature/projects/src/main/java/com/zucchini/submit/SubmitProjectActivity.kt +++ b/feature/projects/src/main/java/com/zucchini/submit/SubmitProjectActivity.kt @@ -11,5 +11,13 @@ class SubmitProjectActivity : AppCompatActivity() { super.onCreate(savedInstanceState) binding = ActivitySubmitProjectBinding.inflate(layoutInflater) setContentView(binding.root) + + backClickListner() + } + + private fun backClickListner() { + binding.ivBackButton.setOnClickListener { + finish() + } } } From 235e1caeb26cc452c8d464c7b66ba1d5cdee4b23 Mon Sep 17 00:00:00 2001 From: kangyuri1114 Date: Fri, 5 Jul 2024 04:13:40 +0900 Subject: [PATCH 05/31] =?UTF-8?q?[feat]:=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20?= =?UTF-8?q?=EC=97=85=EB=A1=9C=EB=93=9C=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../zucchini/data/ContentUriRequestBody.kt | 52 +++++++++++++++++++ feature/projects/build.gradle.kts | 1 + .../zucchini/submit/SubmitProjectActivity.kt | 38 ++++++++++++++ .../res/layout/activity_submit_project.xml | 18 ++++++- .../projects/src/main/res/values/strings.xml | 2 + 5 files changed, 110 insertions(+), 1 deletion(-) create mode 100644 data/src/main/java/com/zucchini/data/ContentUriRequestBody.kt diff --git a/data/src/main/java/com/zucchini/data/ContentUriRequestBody.kt b/data/src/main/java/com/zucchini/data/ContentUriRequestBody.kt new file mode 100644 index 0000000..4a33875 --- /dev/null +++ b/data/src/main/java/com/zucchini/data/ContentUriRequestBody.kt @@ -0,0 +1,52 @@ +package com.zucchini.data + +import android.content.Context +import android.net.Uri +import android.provider.MediaStore +import okhttp3.MediaType +import okhttp3.MediaType.Companion.toMediaTypeOrNull +import okhttp3.MultipartBody +import okhttp3.RequestBody +import okio.BufferedSink +import okio.source + +class ContentUriRequestBody( + context: Context, + private val uri: Uri, +) : RequestBody() { + private val contentResolver = context.contentResolver + + private var fileName = "" + private var size = -1L + + init { + contentResolver.query( + uri, + arrayOf(MediaStore.Images.Media.SIZE, MediaStore.Images.Media.DISPLAY_NAME), + null, + null, + null, + )?.use { cursor -> + if (cursor.moveToFirst()) { + size = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.SIZE)) + fileName = + cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DISPLAY_NAME)) + } + } + } + + fun getFileName() = fileName + + override fun contentLength(): Long = size + + override fun contentType(): MediaType? = + contentResolver.getType(uri)?.toMediaTypeOrNull() + + override fun writeTo(sink: BufferedSink) { + contentResolver.openInputStream(uri)?.source()?.use { source -> + sink.writeAll(source) + } + } + + fun toFormData() = MultipartBody.Part.createFormData("postImg", getFileName(), this) +} \ No newline at end of file diff --git a/feature/projects/build.gradle.kts b/feature/projects/build.gradle.kts index 81e450c..a78c4b0 100644 --- a/feature/projects/build.gradle.kts +++ b/feature/projects/build.gradle.kts @@ -41,6 +41,7 @@ dependencies { implementation(project(":core:designsystem")) implementation(project(":core:common")) implementation(project(":core:network")) + implementation(project(":data")) KotlinDependencies.run { implementation(kotlin) diff --git a/feature/projects/src/main/java/com/zucchini/submit/SubmitProjectActivity.kt b/feature/projects/src/main/java/com/zucchini/submit/SubmitProjectActivity.kt index 09256fa..54909c0 100644 --- a/feature/projects/src/main/java/com/zucchini/submit/SubmitProjectActivity.kt +++ b/feature/projects/src/main/java/com/zucchini/submit/SubmitProjectActivity.kt @@ -1,18 +1,39 @@ package com.zucchini.submit +import android.net.Uri import android.os.Bundle +import androidx.activity.result.contract.ActivityResultContracts import androidx.appcompat.app.AppCompatActivity +import coil.load +import com.zucchini.data.ContentUriRequestBody +import com.zucchini.feature.projects.R import com.zucchini.feature.projects.databinding.ActivitySubmitProjectBinding +import com.zucchini.view.showShortToast +import timber.log.Timber class SubmitProjectActivity : AppCompatActivity() { private lateinit var binding: ActivitySubmitProjectBinding + private var imageUri = Uri.EMPTY + + private val launcher = + registerForActivityResult(ActivityResultContracts.GetContent()) { uri: Uri? -> + imageUri = uri + if (imageUri != null) { + binding.ivProjectSubmit.load(imageUri) + processSelectedImage(imageUri!!) + } else { + showShortToast(getString(R.string.submit_image)) + } + } + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivitySubmitProjectBinding.inflate(layoutInflater) setContentView(binding.root) backClickListner() + initImageSubmitView() } private fun backClickListner() { @@ -20,4 +41,21 @@ class SubmitProjectActivity : AppCompatActivity() { finish() } } + + private fun initImageSubmitView() { + binding.tvProjectSubmitImage.setOnClickListener { + launcher.launch("image/*") + } + } + + private fun processSelectedImage(uri: Uri) { + val requestBody = ContentUriRequestBody( + context = this, + uri = uri + ).toFormData() + + Timber.d("Image Uri: $uri") + Timber.d("Image Path: ${uri.path}") + Timber.d("Request Body: $requestBody") + } } diff --git a/feature/projects/src/main/res/layout/activity_submit_project.xml b/feature/projects/src/main/res/layout/activity_submit_project.xml index 6c75ae6..f426513 100644 --- a/feature/projects/src/main/res/layout/activity_submit_project.xml +++ b/feature/projects/src/main/res/layout/activity_submit_project.xml @@ -54,6 +54,22 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/cl_top_app_bar" /> + + + app:layout_constraintTop_toBottomOf="@+id/tv_project_submit_image" /> 기술 스택↗ 협업툴↗ 카테고리↗ + 이미지 업로드 + 이미지를 선택해주세요. \ No newline at end of file From e70d1e10b8118253f39e743b6ccb4088ff94e26d Mon Sep 17 00:00:00 2001 From: kangyuri1114 Date: Fri, 5 Jul 2024 22:01:39 +0900 Subject: [PATCH 06/31] [feat]: set dialog --- .../zucchini/submit/SubmitProjectActivity.kt | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/feature/projects/src/main/java/com/zucchini/submit/SubmitProjectActivity.kt b/feature/projects/src/main/java/com/zucchini/submit/SubmitProjectActivity.kt index 54909c0..617f5df 100644 --- a/feature/projects/src/main/java/com/zucchini/submit/SubmitProjectActivity.kt +++ b/feature/projects/src/main/java/com/zucchini/submit/SubmitProjectActivity.kt @@ -34,6 +34,11 @@ class SubmitProjectActivity : AppCompatActivity() { backClickListner() initImageSubmitView() + initDialogClickListener() + } + + private fun initDialogClickListener() { + selectProjectCategory() } private fun backClickListner() { @@ -48,11 +53,18 @@ class SubmitProjectActivity : AppCompatActivity() { } } + private fun selectProjectCategory() { + binding.tvSubmitProjectCategory.setOnClickListener { + // TODO: Implement category selection + } + } + private fun processSelectedImage(uri: Uri) { - val requestBody = ContentUriRequestBody( - context = this, - uri = uri - ).toFormData() + val requestBody = + ContentUriRequestBody( + context = this, + uri = uri, + ).toFormData() Timber.d("Image Uri: $uri") Timber.d("Image Path: ${uri.path}") From 8a81386b2b0ff27bcfaef73d2a49da07cd49eec7 Mon Sep 17 00:00:00 2001 From: kangyuri1114 Date: Mon, 8 Jul 2024 20:29:21 +0900 Subject: [PATCH 07/31] =?UTF-8?q?[feat]:=20common=20twobutton=20=EB=8B=A4?= =?UTF-8?q?=EC=9D=B4=EC=96=BC=EB=A1=9C=EA=B7=B8=20=ED=94=84=EB=9E=98?= =?UTF-8?q?=EA=B7=B8=EB=A8=BC=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/common/build.gradle.kts | 2 + .../java/com/zucchini/context/ContextExt.kt | 47 ++++++++ .../zucchini/dialog/TwoButtonCommonDialog.kt | 111 ++++++++++++++++++ .../drawable/button_bright_olive_radius6.xml | 13 ++ .../drawable/button_main_olive_radius6.xml | 13 ++ .../res/layout/dialog_common_two_button.xml | 85 ++++++++++++++ .../projects/mypage/MypageFragment.kt | 26 +++- .../zucchini/submit/SubmitProjectActivity.kt | 1 + .../projects/src/main/res/values/strings.xml | 6 + 9 files changed, 302 insertions(+), 2 deletions(-) create mode 100644 core/common/src/main/java/com/zucchini/context/ContextExt.kt create mode 100644 core/common/src/main/java/com/zucchini/dialog/TwoButtonCommonDialog.kt create mode 100644 core/common/src/main/res/drawable/button_bright_olive_radius6.xml create mode 100644 core/common/src/main/res/drawable/button_main_olive_radius6.xml create mode 100644 core/common/src/main/res/layout/dialog_common_two_button.xml diff --git a/core/common/build.gradle.kts b/core/common/build.gradle.kts index 4367668..9cfa5ea 100644 --- a/core/common/build.gradle.kts +++ b/core/common/build.gradle.kts @@ -28,6 +28,7 @@ android { buildFeatures { buildConfig = true + viewBinding = true } } @@ -38,6 +39,7 @@ dependencies { implementation(coreKtx) implementation(appCompat) implementation(pagingRuntime) + implementation(constraintLayout) } KotlinDependencies.run { diff --git a/core/common/src/main/java/com/zucchini/context/ContextExt.kt b/core/common/src/main/java/com/zucchini/context/ContextExt.kt new file mode 100644 index 0000000..344b0f8 --- /dev/null +++ b/core/common/src/main/java/com/zucchini/context/ContextExt.kt @@ -0,0 +1,47 @@ +package com.zucchini.context + +import android.app.Dialog +import android.content.Context +import android.graphics.Point +import android.os.Build +import android.view.WindowInsets +import android.view.WindowManager + +fun Context.dialogWidthPercent( + dialog: Dialog?, + percent: Double = 0.8, +) { + val deviceSize = getDeviceSize() + dialog?.window?.run { + val params = attributes + params.width = (deviceSize[0] * percent).toInt() + attributes = params + } +} + +fun Context.getDeviceSize(): IntArray { + val windowManager = getSystemService(Context.WINDOW_SERVICE) as WindowManager + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + val windowMetrics = windowManager.currentWindowMetrics + val windowInsets = windowMetrics.windowInsets + + val insets = + windowInsets.getInsetsIgnoringVisibility( + WindowInsets.Type.navigationBars() or WindowInsets.Type.displayCutout(), + ) + val insetsWidth = insets.right + insets.left + val insetsHeight = insets.top + insets.bottom + + val bounds = windowMetrics.bounds + + return intArrayOf(bounds.width() - insetsWidth, bounds.height() - insetsHeight) + } else { + val display = windowManager.defaultDisplay + val size = Point() + + display?.getSize(size) + + return intArrayOf(size.x, size.y) + } +} diff --git a/core/common/src/main/java/com/zucchini/dialog/TwoButtonCommonDialog.kt b/core/common/src/main/java/com/zucchini/dialog/TwoButtonCommonDialog.kt new file mode 100644 index 0000000..20a3d53 --- /dev/null +++ b/core/common/src/main/java/com/zucchini/dialog/TwoButtonCommonDialog.kt @@ -0,0 +1,111 @@ +package com.zucchini.dialog + +import android.graphics.Color +import android.graphics.drawable.ColorDrawable +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.DialogFragment +import androidx.fragment.app.FragmentManager +import com.zucchini.context.dialogWidthPercent +import com.zucchini.core.common.databinding.DialogCommonTwoButtonBinding +import com.zucchini.view.setOnSingleClickListener + +class TwoButtonCommonDialog : DialogFragment() { + private lateinit var binding: DialogCommonTwoButtonBinding + + private var confirmButtonClickListener: (() -> Unit)? = null + private var dismissButtonClickListener: (() -> Unit)? = null + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle?, + ): View = DialogCommonTwoButtonBinding.inflate(inflater, container, false).root + + override fun onViewCreated( + view: View, + savedInstanceState: Bundle?, + ) { + super.onViewCreated(view, savedInstanceState) + initViews() + initButtonListener() + } + + override fun onResume() { + super.onResume() + context?.dialogWidthPercent(dialog) + dialog?.window?.run { + setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT)) + } + } + + fun setConfirmButtonClickListener(confirmButtonClickListener: () -> Unit) { + this.confirmButtonClickListener = confirmButtonClickListener + } + + fun setDismissButtonClickListener(dismissButtonClickListener: () -> Unit) { + this.dismissButtonClickListener = dismissButtonClickListener + } + + private fun initViews() { + val title = arguments?.getString(TITLE, "") + val description = arguments?.getString(DESCRIPTION) + val confirmButtonText = arguments?.getString(CONFIRM_BUTTON_TEXT, "") + val dismissButtonText = arguments?.getString(DISMISS_BUTTON_TEXT, "") + + with(binding) { + tvDialogTitle.text = title + tvDialogDescription.text = description + tvConfirmButton.text = confirmButtonText + tvDismissButton.text = dismissButtonText + } + } + + private fun initButtonListener() { + binding.tvConfirmButton.setOnSingleClickListener { + confirmButtonClickListener?.invoke() + dismiss() + } + binding.tvDismissButton.setOnSingleClickListener { + dismissButtonClickListener?.invoke() + dismiss() + } + } + + fun showAllowingStateLoss( + fm: FragmentManager, + tag: String = "", + ) { + fm + .beginTransaction() + .add(this, tag) + .commitAllowingStateLoss() + } + + companion object { + const val TAG = "TwoButtonCommonDialog" + + const val TITLE = "title" + const val DESCRIPTION = "description" + const val CONFIRM_BUTTON_TEXT = "confirmButtonText" + const val DISMISS_BUTTON_TEXT = "dismissButtonText" + + fun newInstance( + title: String, + description: String? = null, + confirmButtonText: String, + dismissButtonText: String, + ): TwoButtonCommonDialog = + TwoButtonCommonDialog().apply { + arguments = + Bundle().apply { + putString(TITLE, title) + putString(DESCRIPTION, description) + putString(CONFIRM_BUTTON_TEXT, confirmButtonText) + putString(DISMISS_BUTTON_TEXT, dismissButtonText) + } + } + } +} diff --git a/core/common/src/main/res/drawable/button_bright_olive_radius6.xml b/core/common/src/main/res/drawable/button_bright_olive_radius6.xml new file mode 100644 index 0000000..79fe106 --- /dev/null +++ b/core/common/src/main/res/drawable/button_bright_olive_radius6.xml @@ -0,0 +1,13 @@ + + + + + + + diff --git a/core/common/src/main/res/drawable/button_main_olive_radius6.xml b/core/common/src/main/res/drawable/button_main_olive_radius6.xml new file mode 100644 index 0000000..1624798 --- /dev/null +++ b/core/common/src/main/res/drawable/button_main_olive_radius6.xml @@ -0,0 +1,13 @@ + + + + + + + diff --git a/core/common/src/main/res/layout/dialog_common_two_button.xml b/core/common/src/main/res/layout/dialog_common_two_button.xml new file mode 100644 index 0000000..bcb6f3e --- /dev/null +++ b/core/common/src/main/res/layout/dialog_common_two_button.xml @@ -0,0 +1,85 @@ + + + + + + + + + + + + diff --git a/feature/projects/src/main/java/com/zucchini/projects/mypage/MypageFragment.kt b/feature/projects/src/main/java/com/zucchini/projects/mypage/MypageFragment.kt index af6b9e8..c71c07a 100644 --- a/feature/projects/src/main/java/com/zucchini/projects/mypage/MypageFragment.kt +++ b/feature/projects/src/main/java/com/zucchini/projects/mypage/MypageFragment.kt @@ -14,6 +14,7 @@ import coil.load import coil.transform.RoundedCornersTransformation import com.sample.network.datastore.NetworkPreference import com.zucchini.common.NavigationProvider +import com.zucchini.dialog.TwoButtonCommonDialog import com.zucchini.feature.projects.R import com.zucchini.feature.projects.databinding.FragmentMypageBinding import com.zucchini.projects.developer.DevDetailActivity @@ -117,13 +118,34 @@ class MypageFragment : Fragment() { private fun clickLogout() { binding.tvLogout.setOnClickListener { - viewModel.logout() + + } + + binding.tvLogout.setOnClickListener { + TwoButtonCommonDialog.newInstance( + title = getString(R.string.logout_dialog_title), + confirmButtonText = getString(R.string.all_check), + dismissButtonText = getString(R.string.all_cancel), + ).apply { + setConfirmButtonClickListener { + viewModel.logout() + } + }.showAllowingStateLoss(childFragmentManager) } } private fun clickWithdrawal() { binding.tvWithdrawal.setOnClickListener { - viewModel.withdrawal() + TwoButtonCommonDialog.newInstance( + title = getString(R.string.withdrawal_dialog_title), + description = getString(R.string.withdrawal_dialog_description), + confirmButtonText = getString(R.string.all_withdrawal), + dismissButtonText = getString(R.string.all_cancel), + ).apply { + setConfirmButtonClickListener { + viewModel.withdrawal() + } + }.showAllowingStateLoss(childFragmentManager) } } } diff --git a/feature/projects/src/main/java/com/zucchini/submit/SubmitProjectActivity.kt b/feature/projects/src/main/java/com/zucchini/submit/SubmitProjectActivity.kt index 617f5df..7ef26e0 100644 --- a/feature/projects/src/main/java/com/zucchini/submit/SubmitProjectActivity.kt +++ b/feature/projects/src/main/java/com/zucchini/submit/SubmitProjectActivity.kt @@ -56,6 +56,7 @@ class SubmitProjectActivity : AppCompatActivity() { private fun selectProjectCategory() { binding.tvSubmitProjectCategory.setOnClickListener { // TODO: Implement category selection + } } diff --git a/feature/projects/src/main/res/values/strings.xml b/feature/projects/src/main/res/values/strings.xml index 359d380..dddde78 100644 --- a/feature/projects/src/main/res/values/strings.xml +++ b/feature/projects/src/main/res/values/strings.xml @@ -92,5 +92,11 @@ 카테고리↗ 이미지 업로드 이미지를 선택해주세요. + 탈퇴 + 취소 + 확인 + 슈플렉터를 로그아웃 하시겠어요? + 정말 슈플렉터를 탈퇴 하시겠어요? + 회원탈퇴 후 유저 정보는 30일 동안 임시 보관되며, 이후 영구 삭제됩니다. \ No newline at end of file From 6aee0f2033f40a62053ef706aa06ff617d465265 Mon Sep 17 00:00:00 2001 From: kangyuri1114 Date: Tue, 9 Jul 2024 01:03:46 +0900 Subject: [PATCH 08/31] [feat]: init dialog --- .../com/zucchini/buildsrc/Dependencies.kt | 1 + .../java/com/zucchini/buildsrc/Versions.kt | 1 + core/common/build.gradle.kts | 1 + .../zucchini/dialog/CheckBoxListAdapter.kt | 33 ++++++ .../dialog/SelectCheckBoxCommonDialog.kt | 109 ++++++++++++++++++ .../dialog/SubmitProjectDevelopersDialog.kt | 78 +++++++++++++ .../zucchini/dialog/TwoButtonCommonDialog.kt | 5 +- .../drawable/button_olive_brown_radius6.xml | 13 +++ .../drawable/button_olive_white_radius6.xml | 13 +++ .../dialog_common_select_checkbox_button.xml | 76 ++++++++++++ .../res/layout/dialog_common_two_button.xml | 2 +- .../dialog_submit_project_developers.xml | 32 +++-- .../main/res/layout/item_dialog_checkbox.xml | 22 ++++ core/common/src/main/res/values/strings.xml | 9 ++ .../dialog_button_background_main_olive.xml | 9 ++ .../zucchini/submit/SubmitProjectActivity.kt | 68 ++++++++++- .../main/res/layout/dialog_radio_buttons.xml | 13 --- .../projects/src/main/res/values/strings.xml | 4 - 18 files changed, 460 insertions(+), 29 deletions(-) create mode 100644 core/common/src/main/java/com/zucchini/dialog/CheckBoxListAdapter.kt create mode 100644 core/common/src/main/java/com/zucchini/dialog/SelectCheckBoxCommonDialog.kt create mode 100644 core/common/src/main/java/com/zucchini/dialog/SubmitProjectDevelopersDialog.kt create mode 100644 core/common/src/main/res/drawable/button_olive_brown_radius6.xml create mode 100644 core/common/src/main/res/drawable/button_olive_white_radius6.xml create mode 100644 core/common/src/main/res/layout/dialog_common_select_checkbox_button.xml rename {feature/projects => core/common}/src/main/res/layout/dialog_submit_project_developers.xml (82%) create mode 100644 core/common/src/main/res/layout/item_dialog_checkbox.xml create mode 100644 core/common/src/main/res/values/strings.xml create mode 100644 core/designsystem/src/main/res/drawable/dialog_button_background_main_olive.xml delete mode 100644 feature/projects/src/main/res/layout/dialog_radio_buttons.xml diff --git a/buildSrc/src/main/java/com/zucchini/buildsrc/Dependencies.kt b/buildSrc/src/main/java/com/zucchini/buildsrc/Dependencies.kt index 04f28df..266078c 100644 --- a/buildSrc/src/main/java/com/zucchini/buildsrc/Dependencies.kt +++ b/buildSrc/src/main/java/com/zucchini/buildsrc/Dependencies.kt @@ -14,6 +14,7 @@ object AndroidXDependencies { const val appCompat = "androidx.appcompat:appcompat:${Versions.appCompatVersion}" const val constraintLayout = "androidx.constraintlayout:constraintlayout:${Versions.constraintLayoutVersion}" + const val recyclerView = "androidx.recyclerview:recyclerview:${Versions.recyclerViewVersion}" const val startup = "androidx.startup:startup-runtime:${Versions.appStartUpVersion}" const val activity = "androidx.activity:activity-ktx:${Versions.activityKtxVersion}" const val fragment = "androidx.fragment:fragment-ktx:${Versions.fragmentKtxVersion}" diff --git a/buildSrc/src/main/java/com/zucchini/buildsrc/Versions.kt b/buildSrc/src/main/java/com/zucchini/buildsrc/Versions.kt index d5082f0..f13343c 100644 --- a/buildSrc/src/main/java/com/zucchini/buildsrc/Versions.kt +++ b/buildSrc/src/main/java/com/zucchini/buildsrc/Versions.kt @@ -45,6 +45,7 @@ object Versions { const val circleImageViewVersion = "3.1.0" const val dotIndicatorVersion = "5.0" const val processPhoenixVersion = "2.1.2" + const val recyclerViewVersion = "1.3.2" val javaVersion = JavaVersion.VERSION_17 const val jvmVersion = "17" diff --git a/core/common/build.gradle.kts b/core/common/build.gradle.kts index 9cfa5ea..3a026e3 100644 --- a/core/common/build.gradle.kts +++ b/core/common/build.gradle.kts @@ -40,6 +40,7 @@ dependencies { implementation(appCompat) implementation(pagingRuntime) implementation(constraintLayout) + implementation(recyclerView) } KotlinDependencies.run { diff --git a/core/common/src/main/java/com/zucchini/dialog/CheckBoxListAdapter.kt b/core/common/src/main/java/com/zucchini/dialog/CheckBoxListAdapter.kt new file mode 100644 index 0000000..1815838 --- /dev/null +++ b/core/common/src/main/java/com/zucchini/dialog/CheckBoxListAdapter.kt @@ -0,0 +1,33 @@ +package com.zucchini.dialog + +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView +import com.zucchini.core.common.databinding.ItemDialogCheckboxBinding + +class CheckBoxListAdapter( + private val items: List, +) : RecyclerView.Adapter() { + class ViewHolder( + val binding: ItemDialogCheckboxBinding, + ) : RecyclerView.ViewHolder(binding.root) + + override fun onCreateViewHolder( + parent: ViewGroup, + viewType: Int, + ): ViewHolder { + val binding = + ItemDialogCheckboxBinding.inflate(LayoutInflater.from(parent.context), parent, false) + return ViewHolder(binding) + } + + override fun onBindViewHolder( + holder: ViewHolder, + position: Int, + ) { + val item = items[position] + holder.binding.cbDialogContent.text = item + } + + override fun getItemCount() = items.size +} diff --git a/core/common/src/main/java/com/zucchini/dialog/SelectCheckBoxCommonDialog.kt b/core/common/src/main/java/com/zucchini/dialog/SelectCheckBoxCommonDialog.kt new file mode 100644 index 0000000..12ad8d0 --- /dev/null +++ b/core/common/src/main/java/com/zucchini/dialog/SelectCheckBoxCommonDialog.kt @@ -0,0 +1,109 @@ +package com.zucchini.dialog + +import android.graphics.Color +import android.graphics.drawable.ColorDrawable +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.DialogFragment +import androidx.fragment.app.FragmentManager +import androidx.recyclerview.widget.LinearLayoutManager +import com.zucchini.context.dialogWidthPercent +import com.zucchini.core.common.databinding.DialogCommonSelectCheckboxButtonBinding +import com.zucchini.view.setOnSingleClickListener + +class SelectCheckBoxCommonDialog : DialogFragment() { + private lateinit var binding: DialogCommonSelectCheckboxButtonBinding + + private var confirmButtonClickListener: (() -> Unit)? = null + private var items: ArrayList = ArrayList() + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle?, + ): View { + binding = DialogCommonSelectCheckboxButtonBinding.inflate(inflater, container, false) + return binding.root + } + + override fun onViewCreated( + view: View, + savedInstanceState: Bundle?, + ) { + super.onViewCreated(view, savedInstanceState) + initViews() + initButtonListener() + } + + override fun onResume() { + super.onResume() + context?.dialogWidthPercent(dialog) + dialog?.window?.run { + setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT)) + } + } + + fun setConfirmButtonClickListener(confirmButtonClickListener: () -> Unit) { + this.confirmButtonClickListener = confirmButtonClickListener + } + + private fun initViews() { + val title = arguments?.getString(TITLE, "") + val description = arguments?.getString(DESCRIPTION) + val confirmButtonText = arguments?.getString(CONFIRM_BUTTON_TEXT, "") + items = arguments?.getStringArrayList(ITEMS) ?: arrayListOf() + + with(binding) { + tvDialogTitle.text = title + tvDialogDescription.text = description + tvConfirmButton.text = confirmButtonText + + rvDialogContents.layoutManager = LinearLayoutManager(context) + rvDialogContents.adapter = CheckBoxListAdapter(items) + } + } + + private fun initButtonListener() { + binding.tvConfirmButton.setOnSingleClickListener { + confirmButtonClickListener?.invoke() + dismiss() + } + } + + fun showAllowingStateLoss( + fm: FragmentManager, + tag: String = "", + ) { + fm + .beginTransaction() + .add(this, tag) + .commitAllowingStateLoss() + } + + companion object { + const val TAG = "SelectCheckBoxCommonDialog" + + const val TITLE = "title" + const val DESCRIPTION = "description" + const val CONFIRM_BUTTON_TEXT = "confirmButtonText" + const val ITEMS = "items" + + fun newInstance( + title: String, + description: String? = null, + confirmButtonText: String, + items: ArrayList + ): SelectCheckBoxCommonDialog = + SelectCheckBoxCommonDialog().apply { + arguments = + Bundle().apply { + putString(TITLE, title) + putString(DESCRIPTION, description) + putString(CONFIRM_BUTTON_TEXT, confirmButtonText) + putStringArrayList(ITEMS, items) + } + } + } +} diff --git a/core/common/src/main/java/com/zucchini/dialog/SubmitProjectDevelopersDialog.kt b/core/common/src/main/java/com/zucchini/dialog/SubmitProjectDevelopersDialog.kt new file mode 100644 index 0000000..0d079d3 --- /dev/null +++ b/core/common/src/main/java/com/zucchini/dialog/SubmitProjectDevelopersDialog.kt @@ -0,0 +1,78 @@ +package com.zucchini.dialog + +import android.graphics.Color +import android.graphics.drawable.ColorDrawable +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.DialogFragment +import androidx.fragment.app.FragmentManager +import com.zucchini.context.dialogWidthPercent +import com.zucchini.core.common.databinding.DialogCommonTwoButtonBinding +import com.zucchini.core.common.databinding.DialogSubmitProjectDevelopersBinding +import com.zucchini.view.setOnSingleClickListener + +class SubmitProjectDevelopersDialog : DialogFragment() { + private lateinit var binding: DialogSubmitProjectDevelopersBinding + + private var confirmButtonClickListener: (() -> Unit)? = null + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle?, + ): View { + binding = DialogSubmitProjectDevelopersBinding.inflate(inflater, container, false) + return binding.root + } + + override fun onViewCreated( + view: View, + savedInstanceState: Bundle?, + ) { + super.onViewCreated(view, savedInstanceState) + initButtonListener() + initCategoryListner() + } + + override fun onResume() { + super.onResume() + context?.dialogWidthPercent(dialog) + dialog?.window?.run { + setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT)) + } + } + + fun setConfirmButtonClickListener(confirmButtonClickListener: () -> Unit) { + this.confirmButtonClickListener = confirmButtonClickListener + } + + private fun initButtonListener() { + binding.tvConfirmButton.setOnSingleClickListener { + confirmButtonClickListener?.invoke() + dismiss() + } + } + + private fun initUserInputInfo() { + val developerName = binding.etProjectSubmitDeveloperName.text.toString() + val developerEmail = binding.etProjectSubmitDeveloperEmail.text.toString() + val isLeader = binding.cbProjectSubmitDeveloperLeader.isChecked + } + + private fun initCategoryListner() { + binding.tvSubmitProjectDeveloperCategory.setOnSingleClickListener { + TwoButtonCommonDialog.newInstance( + title = "", + description = "", + confirmButtonText = "", + dismissButtonText = "", + ).apply { + setConfirmButtonClickListener { + dismiss() + } + }.showAllowingStateLoss(childFragmentManager) + } + } +} diff --git a/core/common/src/main/java/com/zucchini/dialog/TwoButtonCommonDialog.kt b/core/common/src/main/java/com/zucchini/dialog/TwoButtonCommonDialog.kt index 20a3d53..9d454c8 100644 --- a/core/common/src/main/java/com/zucchini/dialog/TwoButtonCommonDialog.kt +++ b/core/common/src/main/java/com/zucchini/dialog/TwoButtonCommonDialog.kt @@ -22,7 +22,10 @@ class TwoButtonCommonDialog : DialogFragment() { inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?, - ): View = DialogCommonTwoButtonBinding.inflate(inflater, container, false).root + ): View { + binding = DialogCommonTwoButtonBinding.inflate(inflater, container, false) + return binding.root + } override fun onViewCreated( view: View, diff --git a/core/common/src/main/res/drawable/button_olive_brown_radius6.xml b/core/common/src/main/res/drawable/button_olive_brown_radius6.xml new file mode 100644 index 0000000..ca85e4c --- /dev/null +++ b/core/common/src/main/res/drawable/button_olive_brown_radius6.xml @@ -0,0 +1,13 @@ + + + + + + + diff --git a/core/common/src/main/res/drawable/button_olive_white_radius6.xml b/core/common/src/main/res/drawable/button_olive_white_radius6.xml new file mode 100644 index 0000000..6cb92ee --- /dev/null +++ b/core/common/src/main/res/drawable/button_olive_white_radius6.xml @@ -0,0 +1,13 @@ + + + + + + + diff --git a/core/common/src/main/res/layout/dialog_common_select_checkbox_button.xml b/core/common/src/main/res/layout/dialog_common_select_checkbox_button.xml new file mode 100644 index 0000000..0e7aaf7 --- /dev/null +++ b/core/common/src/main/res/layout/dialog_common_select_checkbox_button.xml @@ -0,0 +1,76 @@ + + + + + + + + + + + + + diff --git a/core/common/src/main/res/layout/dialog_common_two_button.xml b/core/common/src/main/res/layout/dialog_common_two_button.xml index bcb6f3e..be89c0e 100644 --- a/core/common/src/main/res/layout/dialog_common_two_button.xml +++ b/core/common/src/main/res/layout/dialog_common_two_button.xml @@ -4,7 +4,7 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="wrap_content" - android:background="@drawable/apply_button_background" + android:background="@drawable/button_olive_white_radius6" android:paddingHorizontal="16dp" android:paddingTop="36dp" android:paddingBottom="24dp"> diff --git a/feature/projects/src/main/res/layout/dialog_submit_project_developers.xml b/core/common/src/main/res/layout/dialog_submit_project_developers.xml similarity index 82% rename from feature/projects/src/main/res/layout/dialog_submit_project_developers.xml rename to core/common/src/main/res/layout/dialog_submit_project_developers.xml index a4ee241..b3dbea2 100644 --- a/feature/projects/src/main/res/layout/dialog_submit_project_developers.xml +++ b/core/common/src/main/res/layout/dialog_submit_project_developers.xml @@ -3,8 +3,10 @@ xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content" + xmlns:tools="http://schemas.android.com/tools" android:layout_marginHorizontal="20dp" - android:layout_marginVertical="20dp"> + android:layout_marginVertical="20dp" + android:background="@drawable/button_olive_white_radius6"> - + \ No newline at end of file diff --git a/core/common/src/main/res/layout/item_dialog_checkbox.xml b/core/common/src/main/res/layout/item_dialog_checkbox.xml new file mode 100644 index 0000000..149fa2b --- /dev/null +++ b/core/common/src/main/res/layout/item_dialog_checkbox.xml @@ -0,0 +1,22 @@ + + + + + \ No newline at end of file diff --git a/core/common/src/main/res/values/strings.xml b/core/common/src/main/res/values/strings.xml new file mode 100644 index 0000000..efd65c6 --- /dev/null +++ b/core/common/src/main/res/values/strings.xml @@ -0,0 +1,9 @@ + + + 개발자 이름 + 이메일 + 개발한 분야를 선택해주세요 + 카테고리↗ + 팀 리더 + 완료 + \ No newline at end of file diff --git a/core/designsystem/src/main/res/drawable/dialog_button_background_main_olive.xml b/core/designsystem/src/main/res/drawable/dialog_button_background_main_olive.xml new file mode 100644 index 0000000..bebf15d --- /dev/null +++ b/core/designsystem/src/main/res/drawable/dialog_button_background_main_olive.xml @@ -0,0 +1,9 @@ + + + diff --git a/feature/projects/src/main/java/com/zucchini/submit/SubmitProjectActivity.kt b/feature/projects/src/main/java/com/zucchini/submit/SubmitProjectActivity.kt index 7ef26e0..260a912 100644 --- a/feature/projects/src/main/java/com/zucchini/submit/SubmitProjectActivity.kt +++ b/feature/projects/src/main/java/com/zucchini/submit/SubmitProjectActivity.kt @@ -2,12 +2,16 @@ package com.zucchini.submit import android.net.Uri import android.os.Bundle +import android.util.Log import androidx.activity.result.contract.ActivityResultContracts import androidx.appcompat.app.AppCompatActivity import coil.load import com.zucchini.data.ContentUriRequestBody +import com.zucchini.dialog.SelectCheckBoxCommonDialog +import com.zucchini.dialog.SubmitProjectDevelopersDialog import com.zucchini.feature.projects.R import com.zucchini.feature.projects.databinding.ActivitySubmitProjectBinding +import com.zucchini.view.setOnSingleClickListener import com.zucchini.view.showShortToast import timber.log.Timber @@ -39,6 +43,8 @@ class SubmitProjectActivity : AppCompatActivity() { private fun initDialogClickListener() { selectProjectCategory() + addDevelopersInfoClickListner() + selectStack() } private fun backClickListner() { @@ -55,8 +61,66 @@ class SubmitProjectActivity : AppCompatActivity() { private fun selectProjectCategory() { binding.tvSubmitProjectCategory.setOnClickListener { - // TODO: Implement category selection - + SelectCheckBoxCommonDialog.newInstance( + title = "Ʈ īװ", + description = "Ʈ īװ ּ. (ִ 1)", + confirmButtonText = getString(R.string.all_check), + items = arrayListOf("", "", "", "ͺ̽", "Ÿ"), + ).apply { + setConfirmButtonClickListener { + // + } + }.showAllowingStateLoss(supportFragmentManager, "SelectCheckBoxCommonDialog") + } + } + + private fun selectStack() { + binding.tvDevStackLanguage.setOnClickListener { + SelectCheckBoxCommonDialog.newInstance( + title = " ", + description = "Ʈ  ּ.\n(ִ 3)", + confirmButtonText = getString(R.string.all_check), + items = arrayListOf("", "", "", "ͺ̽", "Ÿ"), + ).apply { + setConfirmButtonClickListener { + // + } + }.showAllowingStateLoss(supportFragmentManager, "SelectCheckBoxCommonDialog") + } + binding.tvDevStackDevStack.setOnClickListener { + SelectCheckBoxCommonDialog.newInstance( + title = " ", + description = "Ʈ ּ.\n(ִ 3)", + confirmButtonText = getString(R.string.all_check), + items = arrayListOf("", "", "", "ͺ̽", "Ÿ"), + ).apply { + setConfirmButtonClickListener { + // + } + }.showAllowingStateLoss(supportFragmentManager, "SelectCheckBoxCommonDialog") + } + binding.tvDevStackCooperation.setOnClickListener { + SelectCheckBoxCommonDialog.newInstance( + title = " ", + description = "Ʈ ּ.\n(ִ 3)", + confirmButtonText = getString(R.string.all_check), + items = arrayListOf("", "", "", "ͺ̽", "Ÿ"), + ).apply { + setConfirmButtonClickListener { + // + } + }.showAllowingStateLoss(supportFragmentManager, "SelectCheckBoxCommonDialog") + } + } + + private fun addDevelopersInfoClickListner() { + binding.tvProjectSubmitDeveloper.setOnSingleClickListener { + SubmitProjectDevelopersDialog() + .apply { + setConfirmButtonClickListener { + Log.d("SubmitProjectDevelopersDialog", "Confirm Button Clicked") + } + }.show(supportFragmentManager, "SubmitProjectDevelopersDialog") } } diff --git a/feature/projects/src/main/res/layout/dialog_radio_buttons.xml b/feature/projects/src/main/res/layout/dialog_radio_buttons.xml deleted file mode 100644 index 67a5108..0000000 --- a/feature/projects/src/main/res/layout/dialog_radio_buttons.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - diff --git a/feature/projects/src/main/res/values/strings.xml b/feature/projects/src/main/res/values/strings.xml index dddde78..f569c87 100644 --- a/feature/projects/src/main/res/values/strings.xml +++ b/feature/projects/src/main/res/values/strings.xml @@ -25,12 +25,8 @@ 앱을 다운받을 수 있는 곳의 링크를 입력해주세요 프로젝트 소개 페이지 링크를 입력해주세요 웹 링크 - 개발자 이름 - 이메일 - 개발한 분야를 선택해주세요 앱 다운로드 링크 소개 페이지 링크 - 팀 리더 함께한 개발자를 정보를 입력해주세요! 개발자 정보 화면 터치 시 슈플렉터를 시작할 수 있어요! From 2425d681e5a518464504856107a22c6f38aa3115 Mon Sep 17 00:00:00 2001 From: kangyuri1114 Date: Tue, 9 Jul 2024 02:40:24 +0900 Subject: [PATCH 09/31] =?UTF-8?q?[feat]:=20=EB=8B=A4=EC=9D=B4=EC=96=BC?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=20=ED=99=94=EB=A9=B4=20=EB=B9=84=EC=9C=A8=20?= =?UTF-8?q?=EC=A1=B0=EC=A0=95=20=EB=B0=8F=20=EB=A6=AC=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/zucchini/context/ContextExt.kt | 18 ++- .../dialog/SelectCheckBoxCommonDialog.kt | 10 +- .../dialog_common_select_checkbox_button.xml | 135 +++++++++--------- .../dialog_submit_project_developers.xml | 11 +- .../com/zucchini/domain/model/KeywordList.kt | 58 +++++--- .../projects/projects/ProjectsFragment.kt | 3 +- .../zucchini/submit/SubmitProjectActivity.kt | 17 ++- 7 files changed, 147 insertions(+), 105 deletions(-) diff --git a/core/common/src/main/java/com/zucchini/context/ContextExt.kt b/core/common/src/main/java/com/zucchini/context/ContextExt.kt index 344b0f8..3288cce 100644 --- a/core/common/src/main/java/com/zucchini/context/ContextExt.kt +++ b/core/common/src/main/java/com/zucchini/context/ContextExt.kt @@ -7,14 +7,28 @@ import android.os.Build import android.view.WindowInsets import android.view.WindowManager +fun Context.dialogViewPercent( + dialog: Dialog?, + widthPercent: Double = 0.8, + heightPercent: Double = 0.8, +) { + val deviceSize = getDeviceSize() + dialog?.window?.run { + val params = attributes + params.width = (deviceSize[0] * widthPercent).toInt() + params.height = (deviceSize[1] * heightPercent).toInt() + attributes = params + } +} + fun Context.dialogWidthPercent( dialog: Dialog?, - percent: Double = 0.8, + widthPercent: Double = 0.8, ) { val deviceSize = getDeviceSize() dialog?.window?.run { val params = attributes - params.width = (deviceSize[0] * percent).toInt() + params.width = (deviceSize[0] * widthPercent).toInt() attributes = params } } diff --git a/core/common/src/main/java/com/zucchini/dialog/SelectCheckBoxCommonDialog.kt b/core/common/src/main/java/com/zucchini/dialog/SelectCheckBoxCommonDialog.kt index 12ad8d0..7bacd1a 100644 --- a/core/common/src/main/java/com/zucchini/dialog/SelectCheckBoxCommonDialog.kt +++ b/core/common/src/main/java/com/zucchini/dialog/SelectCheckBoxCommonDialog.kt @@ -9,7 +9,7 @@ import android.view.ViewGroup import androidx.fragment.app.DialogFragment import androidx.fragment.app.FragmentManager import androidx.recyclerview.widget.LinearLayoutManager -import com.zucchini.context.dialogWidthPercent +import com.zucchini.context.dialogViewPercent import com.zucchini.core.common.databinding.DialogCommonSelectCheckboxButtonBinding import com.zucchini.view.setOnSingleClickListener @@ -17,7 +17,7 @@ class SelectCheckBoxCommonDialog : DialogFragment() { private lateinit var binding: DialogCommonSelectCheckboxButtonBinding private var confirmButtonClickListener: (() -> Unit)? = null - private var items: ArrayList = ArrayList() + private var items: List = listOf() override fun onCreateView( inflater: LayoutInflater, @@ -39,7 +39,7 @@ class SelectCheckBoxCommonDialog : DialogFragment() { override fun onResume() { super.onResume() - context?.dialogWidthPercent(dialog) + context?.dialogViewPercent(dialog) dialog?.window?.run { setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT)) } @@ -53,7 +53,7 @@ class SelectCheckBoxCommonDialog : DialogFragment() { val title = arguments?.getString(TITLE, "") val description = arguments?.getString(DESCRIPTION) val confirmButtonText = arguments?.getString(CONFIRM_BUTTON_TEXT, "") - items = arguments?.getStringArrayList(ITEMS) ?: arrayListOf() + items = arguments?.getStringArrayList(ITEMS) ?: listOf() with(binding) { tvDialogTitle.text = title @@ -94,7 +94,7 @@ class SelectCheckBoxCommonDialog : DialogFragment() { title: String, description: String? = null, confirmButtonText: String, - items: ArrayList + items: ArrayList, ): SelectCheckBoxCommonDialog = SelectCheckBoxCommonDialog().apply { arguments = diff --git a/core/common/src/main/res/layout/dialog_common_select_checkbox_button.xml b/core/common/src/main/res/layout/dialog_common_select_checkbox_button.xml index 0e7aaf7..254dbcb 100644 --- a/core/common/src/main/res/layout/dialog_common_select_checkbox_button.xml +++ b/core/common/src/main/res/layout/dialog_common_select_checkbox_button.xml @@ -1,76 +1,81 @@ - + android:layout_height="wrap_content"> - + android:background="@color/white" + android:paddingHorizontal="16dp" + android:paddingTop="36dp" + android:paddingBottom="24dp"> - + + - - + + + - + + \ No newline at end of file diff --git a/core/common/src/main/res/layout/dialog_submit_project_developers.xml b/core/common/src/main/res/layout/dialog_submit_project_developers.xml index b3dbea2..0098a64 100644 --- a/core/common/src/main/res/layout/dialog_submit_project_developers.xml +++ b/core/common/src/main/res/layout/dialog_submit_project_developers.xml @@ -3,10 +3,9 @@ xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content" - xmlns:tools="http://schemas.android.com/tools" android:layout_marginHorizontal="20dp" android:layout_marginVertical="20dp" - android:background="@drawable/button_olive_white_radius6"> + android:background="@color/white"> + app:layout_constraintTop_toBottomOf="@id/cb_project_submit_developer_leader" /> \ No newline at end of file diff --git a/domain/src/main/java/com/zucchini/domain/model/KeywordList.kt b/domain/src/main/java/com/zucchini/domain/model/KeywordList.kt index 04dcceb..840eb4e 100644 --- a/domain/src/main/java/com/zucchini/domain/model/KeywordList.kt +++ b/domain/src/main/java/com/zucchini/domain/model/KeywordList.kt @@ -1,39 +1,24 @@ package com.zucchini.domain.model object KeywordList { - val searchKeyword = listOf( + val categoryList = arrayListOf( Keyword(keywordEnglish = "SERVICE", keywordKorean = "서비스"), Keyword(keywordEnglish = "SECURITY", keywordKorean = "보안"), - Keyword(keywordEnglish = "FINANCE", keywordKorean = "금융"), - Keyword(keywordEnglish = "PLATFORM", keywordKorean = "플랫폼"), Keyword(keywordEnglish = "GAME", keywordKorean = "게임"), Keyword(keywordEnglish = "MOBILE_APP", keywordKorean = "모바일"), Keyword(keywordEnglish = "WEB_APPLICATION", keywordKorean = "웹"), Keyword(keywordEnglish = "DATA_ANALYTICS", keywordKorean = "데이터 분석"), Keyword(keywordEnglish = "AI", keywordKorean = "인공지능"), - Keyword(keywordEnglish = "ML", keywordKorean = "머신러닝"), Keyword(keywordEnglish = "IOT", keywordKorean = "IOT"), Keyword(keywordEnglish = "CLOUD_COMPUTING", keywordKorean = "클라우드"), Keyword(keywordEnglish = "BLOCKCHAIN", keywordKorean = "블록체인"), - Keyword(keywordEnglish = "E_COMMERCE", keywordKorean = "전자상거래"), - Keyword(keywordEnglish = "HEALTHCARE_IT", keywordKorean = "헬스케어"), - Keyword(keywordEnglish = "ED_TECH", keywordKorean = "교육"), - Keyword(keywordEnglish = "SOCIAL_MEDIA", keywordKorean = "소셜"), - Keyword(keywordEnglish = "CRM", keywordKorean = "CRM"), - Keyword(keywordEnglish = "ERP", keywordKorean = "ERP"), - Keyword(keywordEnglish = "BI", keywordKorean = "BI"), - Keyword(keywordEnglish = "CPS", keywordKorean = "CPS"), - Keyword(keywordEnglish = "AR", keywordKorean = "AR"), - Keyword("VR", keywordKorean = "VR"), - Keyword(keywordEnglish = "AUTOMATION", keywordKorean = "자동화"), + Keyword("VR", keywordKorean = "VR/AR"), Keyword(keywordEnglish = "ROBOTICS", keywordKorean = "로봇"), Keyword(keywordEnglish = "OTHER", keywordKorean = "기타"), ) - val partList = listOf( - Keyword(keywordEnglish = "FRONTEND", keywordKorean = "프론트엔드"), + val partList = arrayListOf( Keyword(keywordEnglish = "BACKEND", keywordKorean = "백엔드"), - Keyword(keywordEnglish = "FULLSTACK", keywordKorean = "풀스택"), Keyword(keywordEnglish = "MIDDLE_TIER", keywordKorean = "미들웨어"), Keyword(keywordEnglish = "WEB", keywordKorean = "웹"), Keyword(keywordEnglish = "DESKTOP", keywordKorean = "데스크탑"), @@ -43,10 +28,43 @@ object KeywordList { Keyword(keywordEnglish = "DATA_SCIENTIST", keywordKorean = "데이터 과학자"), Keyword(keywordEnglish = "BIG_DATA", keywordKorean = "빅데이터"), Keyword(keywordEnglish = "DEVOPS", keywordKorean = "데브옵스"), - Keyword(keywordEnglish = "CRM", keywordKorean = "CRM"), Keyword(keywordEnglish = "SOFTWARE_TEST", keywordKorean = "테스트"), Keyword(keywordEnglish = "EMBEDDED_SOFTWARE", keywordKorean = "임베디드"), - Keyword(keywordEnglish = "WORDPRESS", keywordKorean = "워드프레스"), Keyword(keywordEnglish = "SECURITY", keywordKorean = "보안"), ) + + val cooperationList = arrayListOf( + Keyword(keywordEnglish = "COOPERATION", keywordKorean = "Notion"), + Keyword(keywordEnglish = "INDIVIDUAL", keywordKorean = "Github"), + Keyword(keywordEnglish = "COOPERATION", keywordKorean = "Slack"), + Keyword(keywordEnglish = "INDIVIDUAL", keywordKorean = "Jira"), + Keyword(keywordEnglish = "COOPERATION", keywordKorean = "Trello"), + Keyword(keywordEnglish = "INDIVIDUAL", keywordKorean = "Figma"), + ) + + val techStackList = arrayListOf( + Keyword(keywordEnglish = "DJANGO", keywordKorean = "Django"), + Keyword(keywordEnglish = "SPRING", keywordKorean = "Spring"), + Keyword(keywordEnglish = "REACT", keywordKorean = "React"), + Keyword(keywordEnglish = "ANGULAR", keywordKorean = "Angular"), + Keyword(keywordEnglish = "AWS", keywordKorean = "AWS"), + ) + + val languageList = arrayListOf( + Keyword(keywordEnglish = "GO", keywordKorean = "Go"), + Keyword(keywordEnglish = "JAVA", keywordKorean = "Java"), + Keyword(keywordEnglish = "KOTLIN", keywordKorean = "Kotlin"), + Keyword(keywordEnglish = "JAVASCRIPT", keywordKorean = "JavaScript"), + Keyword(keywordEnglish = "TS", keywordKorean = "TypeScript"), + Keyword(keywordEnglish = "PYTHON", keywordKorean = "Python"), + Keyword(keywordEnglish = "C", keywordKorean = "C"), + Keyword(keywordEnglish = "CPP", keywordKorean = "C++"), + Keyword(keywordEnglish = "PHP", keywordKorean = "PHP"), + Keyword(keywordEnglish = "R", keywordKorean = "R"), + Keyword(keywordEnglish = "RUBY", keywordKorean = "RUBY"), + Keyword(keywordEnglish = "RUST", keywordKorean = "RUST"), + Keyword(keywordEnglish = "SQL", keywordKorean = "SQL"), + Keyword(keywordEnglish = "HTML", keywordKorean = "HTML"), + Keyword(keywordEnglish = "CSS", keywordKorean = "CSS"), + ) } diff --git a/feature/projects/src/main/java/com/zucchini/projects/projects/ProjectsFragment.kt b/feature/projects/src/main/java/com/zucchini/projects/projects/ProjectsFragment.kt index 1f4973d..ba20a97 100644 --- a/feature/projects/src/main/java/com/zucchini/projects/projects/ProjectsFragment.kt +++ b/feature/projects/src/main/java/com/zucchini/projects/projects/ProjectsFragment.kt @@ -1,7 +1,6 @@ package com.zucchini.projects.projects import android.content.Intent -import android.net.Uri import android.os.Bundle import android.view.LayoutInflater import android.view.View @@ -153,7 +152,7 @@ class ProjectsFragment : Fragment() { binding.rvSearchKeyword.layoutManager = LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false) binding.rvSearchKeyword.adapter = searchKeywordAdapter - searchKeywordAdapter.submitList(KeywordList.searchKeyword) + searchKeywordAdapter.submitList(KeywordList.categoryList) } diff --git a/feature/projects/src/main/java/com/zucchini/submit/SubmitProjectActivity.kt b/feature/projects/src/main/java/com/zucchini/submit/SubmitProjectActivity.kt index 260a912..9eb575f 100644 --- a/feature/projects/src/main/java/com/zucchini/submit/SubmitProjectActivity.kt +++ b/feature/projects/src/main/java/com/zucchini/submit/SubmitProjectActivity.kt @@ -9,6 +9,7 @@ import coil.load import com.zucchini.data.ContentUriRequestBody import com.zucchini.dialog.SelectCheckBoxCommonDialog import com.zucchini.dialog.SubmitProjectDevelopersDialog +import com.zucchini.domain.model.KeywordList import com.zucchini.feature.projects.R import com.zucchini.feature.projects.databinding.ActivitySubmitProjectBinding import com.zucchini.view.setOnSingleClickListener @@ -60,12 +61,14 @@ class SubmitProjectActivity : AppCompatActivity() { } private fun selectProjectCategory() { + val categoryKoreanList = KeywordList.categoryList.map { it.keywordKorean } + binding.tvSubmitProjectCategory.setOnClickListener { SelectCheckBoxCommonDialog.newInstance( title = "Ʈ īװ", - description = "Ʈ īװ ּ. (ִ 1)", + description = "Ʈ īװ ּ. (ִ 2)", confirmButtonText = getString(R.string.all_check), - items = arrayListOf("", "", "", "ͺ̽", "Ÿ"), + items = categoryKoreanList as ArrayList, ).apply { setConfirmButtonClickListener { // @@ -75,12 +78,16 @@ class SubmitProjectActivity : AppCompatActivity() { } private fun selectStack() { + val language = KeywordList.languageList.map { it.keywordKorean } + val techStack = KeywordList.techStackList.map { it.keywordKorean } + val cooperationTool = KeywordList.cooperationList.map { it.keywordKorean } + binding.tvDevStackLanguage.setOnClickListener { SelectCheckBoxCommonDialog.newInstance( title = " ", description = "Ʈ  ּ.\n(ִ 3)", confirmButtonText = getString(R.string.all_check), - items = arrayListOf("", "", "", "ͺ̽", "Ÿ"), + items = language as ArrayList, ).apply { setConfirmButtonClickListener { // @@ -92,7 +99,7 @@ class SubmitProjectActivity : AppCompatActivity() { title = " ", description = "Ʈ ּ.\n(ִ 3)", confirmButtonText = getString(R.string.all_check), - items = arrayListOf("", "", "", "ͺ̽", "Ÿ"), + items = techStack as ArrayList, ).apply { setConfirmButtonClickListener { // @@ -104,7 +111,7 @@ class SubmitProjectActivity : AppCompatActivity() { title = " ", description = "Ʈ ּ.\n(ִ 3)", confirmButtonText = getString(R.string.all_check), - items = arrayListOf("", "", "", "ͺ̽", "Ÿ"), + items = cooperationTool as ArrayList, ).apply { setConfirmButtonClickListener { // From 31fb62e836e994bed574576fbecafd823cae20d6 Mon Sep 17 00:00:00 2001 From: kangyuri1114 Date: Tue, 9 Jul 2024 03:45:43 +0900 Subject: [PATCH 10/31] =?UTF-8?q?[feat]:=20=EB=8B=A4=EC=9D=B4=EC=96=BC?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=20=EC=A0=9C=EC=99=B8,=20=ED=94=84=EB=A1=9C?= =?UTF-8?q?=EC=A0=9D=ED=8A=B8=20=EB=93=B1=EB=A1=9D=20=EC=A0=95=EB=B3=B4=20?= =?UTF-8?q?model=20=EC=A0=80=EC=9E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/model/SubmitProjectInfo.kt | 26 +++++++++++++ .../zucchini/submit/SubmitProjectActivity.kt | 31 +++++++++++++++- .../res/layout/activity_submit_project.xml | 37 ++++++++++++++----- 3 files changed, 83 insertions(+), 11 deletions(-) create mode 100644 domain/src/main/java/com/zucchini/domain/model/SubmitProjectInfo.kt diff --git a/domain/src/main/java/com/zucchini/domain/model/SubmitProjectInfo.kt b/domain/src/main/java/com/zucchini/domain/model/SubmitProjectInfo.kt new file mode 100644 index 0000000..df7995a --- /dev/null +++ b/domain/src/main/java/com/zucchini/domain/model/SubmitProjectInfo.kt @@ -0,0 +1,26 @@ +package com.zucchini.domain.model + +import java.nio.file.Path + +data class SubmitProjectInfo( + val projectName: String, + val projectGithub: String, + val imagePath: String, + val projectShortIntro: String, + val projectLongIntro: String, + val projectCategoryList: List = emptyList(), + val projectTechStackList: List = emptyList(), + val projectLanguageList: List = emptyList(), + val projectCooperationList: List = emptyList(), + val projectWebLink: String, + val projectAppLink: String, + val projectLink: String, + val developerList: List = emptyList() +) { + data class DeveloperInfoInSubmitProject( + val developerName: String, + val developerEmail: String, + val developerCategoryList: List, + val isTeamLeader: Boolean + ) +} diff --git a/feature/projects/src/main/java/com/zucchini/submit/SubmitProjectActivity.kt b/feature/projects/src/main/java/com/zucchini/submit/SubmitProjectActivity.kt index 9eb575f..452cd4d 100644 --- a/feature/projects/src/main/java/com/zucchini/submit/SubmitProjectActivity.kt +++ b/feature/projects/src/main/java/com/zucchini/submit/SubmitProjectActivity.kt @@ -1,8 +1,11 @@ package com.zucchini.submit +import android.app.Activity +import android.content.Intent import android.net.Uri import android.os.Bundle import android.util.Log +import androidx.activity.result.ActivityResultLauncher import androidx.activity.result.contract.ActivityResultContracts import androidx.appcompat.app.AppCompatActivity import coil.load @@ -10,6 +13,8 @@ import com.zucchini.data.ContentUriRequestBody import com.zucchini.dialog.SelectCheckBoxCommonDialog import com.zucchini.dialog.SubmitProjectDevelopersDialog import com.zucchini.domain.model.KeywordList +import com.zucchini.domain.model.SubmitDevInfo +import com.zucchini.domain.model.SubmitProjectInfo import com.zucchini.feature.projects.R import com.zucchini.feature.projects.databinding.ActivitySubmitProjectBinding import com.zucchini.view.setOnSingleClickListener @@ -40,6 +45,8 @@ class SubmitProjectActivity : AppCompatActivity() { backClickListner() initImageSubmitView() initDialogClickListener() + clickSubmitButton() + } private fun initDialogClickListener() { @@ -125,7 +132,7 @@ class SubmitProjectActivity : AppCompatActivity() { SubmitProjectDevelopersDialog() .apply { setConfirmButtonClickListener { - Log.d("SubmitProjectDevelopersDialog", "Confirm Button Clicked") + // ͷ } }.show(supportFragmentManager, "SubmitProjectDevelopersDialog") } @@ -142,4 +149,26 @@ class SubmitProjectActivity : AppCompatActivity() { Timber.d("Image Path: ${uri.path}") Timber.d("Request Body: $requestBody") } + + private fun clickSubmitButton() { + binding.btnSubmit.setOnSingleClickListener { + val submitProjectInfo = SubmitProjectInfo( + projectName = binding.etProjectName.text.toString(), + imagePath = imageUri.toString(), + projectGithub = binding.etGithub.text.toString(), + projectShortIntro = binding.etProjectIntroContentShort.text.toString(), + projectLongIntro = binding.etProjectIntroContentLong.text.toString(), + //projectCategoryList = + //projectLanguageList = // Ʈ, + //projectTechStackList = // Ʈ, + //projectCooperationToolList = // Ʈ, + projectWebLink = binding.etProjectWebLink.text.toString(), + projectAppLink = binding.etProjectAppLink.text.toString(), + projectLink = binding.etProjectInfoLink.text.toString(), + // developerList = + ) + + Log.d("SubmitProjectActivity", "submitProjectInfo: $submitProjectInfo") + } + } } diff --git a/feature/projects/src/main/res/layout/activity_submit_project.xml b/feature/projects/src/main/res/layout/activity_submit_project.xml index f426513..3eb5113 100644 --- a/feature/projects/src/main/res/layout/activity_submit_project.xml +++ b/feature/projects/src/main/res/layout/activity_submit_project.xml @@ -60,15 +60,14 @@ android:layout_height="wrap_content" android:fontFamily="@font/pretendardmedium" android:gravity="center" - android:paddingVertical="10dp" android:paddingHorizontal="6dp" + android:paddingVertical="10dp" android:text="@string/tv_project_submit_image" android:textColor="@color/gray2" android:textSize="12sp" - app:layout_constraintTop_toBottomOf="@+id/iv_project_submit" - app:layout_constraintStart_toStartOf="@+id/iv_project_submit" app:layout_constraintEnd_toEndOf="@+id/iv_project_submit" - /> + app:layout_constraintStart_toStartOf="@+id/iv_project_submit" + app:layout_constraintTop_toBottomOf="@+id/iv_project_submit" /> + app:layout_constraintTop_toBottomOf="@+id/et_project_intro_content_short" /> + app:layout_constraintTop_toBottomOf="@+id/et_project_intro_content_long" /> + + \ No newline at end of file From d33bb7ba6dbcb427096a18f2be7d0f55c266921d Mon Sep 17 00:00:00 2001 From: kangyuri1114 Date: Tue, 9 Jul 2024 04:03:13 +0900 Subject: [PATCH 11/31] =?UTF-8?q?[feat]:=20=EA=B0=9C=EB=B0=9C=EC=9E=90=20?= =?UTF-8?q?=EC=A0=95=EB=B3=B4=20=EC=9E=85=EB=A0=A5=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dialog/SubmitProjectDevelopersDialog.kt | 42 +++--- .../zucchini/submit/SubmitProjectActivity.kt | 129 ++++++++---------- .../res/layout/activity_submit_project.xml | 43 +----- 3 files changed, 82 insertions(+), 132 deletions(-) diff --git a/core/common/src/main/java/com/zucchini/dialog/SubmitProjectDevelopersDialog.kt b/core/common/src/main/java/com/zucchini/dialog/SubmitProjectDevelopersDialog.kt index 0d079d3..167e29c 100644 --- a/core/common/src/main/java/com/zucchini/dialog/SubmitProjectDevelopersDialog.kt +++ b/core/common/src/main/java/com/zucchini/dialog/SubmitProjectDevelopersDialog.kt @@ -7,9 +7,7 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.fragment.app.DialogFragment -import androidx.fragment.app.FragmentManager import com.zucchini.context.dialogWidthPercent -import com.zucchini.core.common.databinding.DialogCommonTwoButtonBinding import com.zucchini.core.common.databinding.DialogSubmitProjectDevelopersBinding import com.zucchini.view.setOnSingleClickListener @@ -50,29 +48,35 @@ class SubmitProjectDevelopersDialog : DialogFragment() { private fun initButtonListener() { binding.tvConfirmButton.setOnSingleClickListener { - confirmButtonClickListener?.invoke() + val developerName = binding.etProjectSubmitDeveloperName.text.toString() + val developerEmail = binding.etProjectSubmitDeveloperEmail.text.toString() + val isLeader = binding.cbProjectSubmitDeveloperLeader.isChecked + + val result = + Bundle().apply { + putString("developerName", developerName) + putString("developerEmail", developerEmail) + putBoolean("isLeader", isLeader) + } + + parentFragmentManager.setFragmentResult("SubmitProjectDevelopersDialogResult", result) dismiss() } } - private fun initUserInputInfo() { - val developerName = binding.etProjectSubmitDeveloperName.text.toString() - val developerEmail = binding.etProjectSubmitDeveloperEmail.text.toString() - val isLeader = binding.cbProjectSubmitDeveloperLeader.isChecked - } - private fun initCategoryListner() { binding.tvSubmitProjectDeveloperCategory.setOnSingleClickListener { - TwoButtonCommonDialog.newInstance( - title = "", - description = "", - confirmButtonText = "", - dismissButtonText = "", - ).apply { - setConfirmButtonClickListener { - dismiss() - } - }.showAllowingStateLoss(childFragmentManager) + TwoButtonCommonDialog + .newInstance( + title = "", + description = "", + confirmButtonText = "", + dismissButtonText = "", + ).apply { + setConfirmButtonClickListener { + dismiss() + } + }.showAllowingStateLoss(childFragmentManager) } } } diff --git a/feature/projects/src/main/java/com/zucchini/submit/SubmitProjectActivity.kt b/feature/projects/src/main/java/com/zucchini/submit/SubmitProjectActivity.kt index 452cd4d..ed473bc 100644 --- a/feature/projects/src/main/java/com/zucchini/submit/SubmitProjectActivity.kt +++ b/feature/projects/src/main/java/com/zucchini/submit/SubmitProjectActivity.kt @@ -1,19 +1,14 @@ package com.zucchini.submit -import android.app.Activity -import android.content.Intent import android.net.Uri import android.os.Bundle import android.util.Log -import androidx.activity.result.ActivityResultLauncher import androidx.activity.result.contract.ActivityResultContracts import androidx.appcompat.app.AppCompatActivity import coil.load import com.zucchini.data.ContentUriRequestBody import com.zucchini.dialog.SelectCheckBoxCommonDialog -import com.zucchini.dialog.SubmitProjectDevelopersDialog import com.zucchini.domain.model.KeywordList -import com.zucchini.domain.model.SubmitDevInfo import com.zucchini.domain.model.SubmitProjectInfo import com.zucchini.feature.projects.R import com.zucchini.feature.projects.databinding.ActivitySubmitProjectBinding @@ -46,12 +41,10 @@ class SubmitProjectActivity : AppCompatActivity() { initImageSubmitView() initDialogClickListener() clickSubmitButton() - } private fun initDialogClickListener() { selectProjectCategory() - addDevelopersInfoClickListner() selectStack() } @@ -71,16 +64,17 @@ class SubmitProjectActivity : AppCompatActivity() { val categoryKoreanList = KeywordList.categoryList.map { it.keywordKorean } binding.tvSubmitProjectCategory.setOnClickListener { - SelectCheckBoxCommonDialog.newInstance( - title = "Ʈ īװ", - description = "Ʈ īװ ּ. (ִ 2)", - confirmButtonText = getString(R.string.all_check), - items = categoryKoreanList as ArrayList, - ).apply { - setConfirmButtonClickListener { - // - } - }.showAllowingStateLoss(supportFragmentManager, "SelectCheckBoxCommonDialog") + SelectCheckBoxCommonDialog + .newInstance( + title = "Ʈ īװ", + description = "Ʈ īװ ּ. (ִ 2)", + confirmButtonText = getString(R.string.all_check), + items = categoryKoreanList as ArrayList, + ).apply { + setConfirmButtonClickListener { + // + } + }.showAllowingStateLoss(supportFragmentManager, "SelectCheckBoxCommonDialog") } } @@ -90,51 +84,43 @@ class SubmitProjectActivity : AppCompatActivity() { val cooperationTool = KeywordList.cooperationList.map { it.keywordKorean } binding.tvDevStackLanguage.setOnClickListener { - SelectCheckBoxCommonDialog.newInstance( - title = " ", - description = "Ʈ  ּ.\n(ִ 3)", - confirmButtonText = getString(R.string.all_check), - items = language as ArrayList, - ).apply { - setConfirmButtonClickListener { - // - } - }.showAllowingStateLoss(supportFragmentManager, "SelectCheckBoxCommonDialog") + SelectCheckBoxCommonDialog + .newInstance( + title = " ", + description = "Ʈ  ּ.\n(ִ 3)", + confirmButtonText = getString(R.string.all_check), + items = language as ArrayList, + ).apply { + setConfirmButtonClickListener { + // + } + }.showAllowingStateLoss(supportFragmentManager, "SelectCheckBoxCommonDialog") } binding.tvDevStackDevStack.setOnClickListener { - SelectCheckBoxCommonDialog.newInstance( - title = " ", - description = "Ʈ ּ.\n(ִ 3)", - confirmButtonText = getString(R.string.all_check), - items = techStack as ArrayList, - ).apply { - setConfirmButtonClickListener { - // - } - }.showAllowingStateLoss(supportFragmentManager, "SelectCheckBoxCommonDialog") + SelectCheckBoxCommonDialog + .newInstance( + title = " ", + description = "Ʈ ּ.\n(ִ 3)", + confirmButtonText = getString(R.string.all_check), + items = techStack as ArrayList, + ).apply { + setConfirmButtonClickListener { + // + } + }.showAllowingStateLoss(supportFragmentManager, "SelectCheckBoxCommonDialog") } binding.tvDevStackCooperation.setOnClickListener { - SelectCheckBoxCommonDialog.newInstance( - title = " ", - description = "Ʈ ּ.\n(ִ 3)", - confirmButtonText = getString(R.string.all_check), - items = cooperationTool as ArrayList, - ).apply { - setConfirmButtonClickListener { - // - } - }.showAllowingStateLoss(supportFragmentManager, "SelectCheckBoxCommonDialog") - } - } - - private fun addDevelopersInfoClickListner() { - binding.tvProjectSubmitDeveloper.setOnSingleClickListener { - SubmitProjectDevelopersDialog() - .apply { + SelectCheckBoxCommonDialog + .newInstance( + title = " ", + description = "Ʈ ּ.\n(ִ 3)", + confirmButtonText = getString(R.string.all_check), + items = cooperationTool as ArrayList, + ).apply { setConfirmButtonClickListener { - // ͷ + // } - }.show(supportFragmentManager, "SubmitProjectDevelopersDialog") + }.showAllowingStateLoss(supportFragmentManager, "SelectCheckBoxCommonDialog") } } @@ -152,21 +138,22 @@ class SubmitProjectActivity : AppCompatActivity() { private fun clickSubmitButton() { binding.btnSubmit.setOnSingleClickListener { - val submitProjectInfo = SubmitProjectInfo( - projectName = binding.etProjectName.text.toString(), - imagePath = imageUri.toString(), - projectGithub = binding.etGithub.text.toString(), - projectShortIntro = binding.etProjectIntroContentShort.text.toString(), - projectLongIntro = binding.etProjectIntroContentLong.text.toString(), - //projectCategoryList = - //projectLanguageList = // Ʈ, - //projectTechStackList = // Ʈ, - //projectCooperationToolList = // Ʈ, - projectWebLink = binding.etProjectWebLink.text.toString(), - projectAppLink = binding.etProjectAppLink.text.toString(), - projectLink = binding.etProjectInfoLink.text.toString(), - // developerList = - ) + val submitProjectInfo = + SubmitProjectInfo( + projectName = binding.etProjectName.text.toString(), + imagePath = imageUri.toString(), + projectGithub = binding.etGithub.text.toString(), + projectShortIntro = binding.etProjectIntroContentShort.text.toString(), + projectLongIntro = binding.etProjectIntroContentLong.text.toString(), + // projectCategoryList = + // projectLanguageList = // Ʈ, + // projectTechStackList = // Ʈ, + // projectCooperationToolList = // Ʈ, + projectWebLink = binding.etProjectWebLink.text.toString(), + projectAppLink = binding.etProjectAppLink.text.toString(), + projectLink = binding.etProjectInfoLink.text.toString(), + // developerList = + ) Log.d("SubmitProjectActivity", "submitProjectInfo: $submitProjectInfo") } diff --git a/feature/projects/src/main/res/layout/activity_submit_project.xml b/feature/projects/src/main/res/layout/activity_submit_project.xml index 3eb5113..4d54df9 100644 --- a/feature/projects/src/main/res/layout/activity_submit_project.xml +++ b/feature/projects/src/main/res/layout/activity_submit_project.xml @@ -379,47 +379,6 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/tv_project_submit_info_link_title" /> - - - - - - + app:layout_constraintTop_toBottomOf="@+id/et_project_info_link" /> \ No newline at end of file From 1c90f44dcc7e26f19335bcca662061c14b4ccd35 Mon Sep 17 00:00:00 2001 From: kangyuri1114 Date: Mon, 15 Jul 2024 21:38:45 +0900 Subject: [PATCH 12/31] =?UTF-8?q?[feat]:=20=EB=8B=A4=EC=9D=B4=EC=96=BC?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=20=EA=B0=92=20=EB=B0=98=ED=99=98=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../di/DefaultNavigationProvider.kt | 42 +++--- .../com/zucchini/common/NavigationProvider.kt | 1 + .../dialog/SubmitProjectDevelopersDialog.kt | 82 ----------- .../dialog_submit_project_developers.xml | 138 ------------------ .../domain/model/FindDeveloperInfo.kt | 7 + .../domain/model/SubmitProjectInfo.kt | 29 ++-- feature/projects/src/main/AndroidManifest.xml | 9 +- .../java/com/zucchini/auth/LoginActivity.kt | 2 +- .../zucchini/dialog/CheckBoxListAdapter.kt | 17 ++- .../dialog/SelectCheckBoxCommonDialog.kt | 9 +- .../zucchini/dialog/TwoButtonCommonDialog.kt | 0 .../projects/projects/ProjectsFragment.kt | 2 +- .../{ => developer}/SubmitDevActivity.kt | 2 +- .../{ => developer}/SubmitDevViewModel.kt | 2 +- .../{ => project}/SubmitProjectActivity.kt | 41 ++++-- .../project/SubmitProjectFindDevActivity.kt | 31 ++++ .../submit/project/SubmitProjectViewModel.kt | 20 +++ .../submit/project/adapter/FindDevAdapter.kt | 57 ++++++++ .../main/res/layout/activity_submit_dev.xml | 2 +- .../res/layout/activity_submit_project.xml | 2 +- .../activity_submit_project_find_dev.xml | 121 +++++++++++++++ .../src/main/res/layout/item_find_dev.xml | 63 ++++++++ .../projects/src/main/res/values/strings.xml | 3 + 23 files changed, 394 insertions(+), 288 deletions(-) delete mode 100644 core/common/src/main/java/com/zucchini/dialog/SubmitProjectDevelopersDialog.kt delete mode 100644 core/common/src/main/res/layout/dialog_submit_project_developers.xml create mode 100644 domain/src/main/java/com/zucchini/domain/model/FindDeveloperInfo.kt rename {core/common => feature/projects}/src/main/java/com/zucchini/dialog/CheckBoxListAdapter.kt (67%) rename {core/common => feature/projects}/src/main/java/com/zucchini/dialog/SelectCheckBoxCommonDialog.kt (93%) rename {core/common => feature/projects}/src/main/java/com/zucchini/dialog/TwoButtonCommonDialog.kt (100%) rename feature/projects/src/main/java/com/zucchini/submit/{ => developer}/SubmitDevActivity.kt (99%) rename feature/projects/src/main/java/com/zucchini/submit/{ => developer}/SubmitDevViewModel.kt (99%) rename feature/projects/src/main/java/com/zucchini/submit/{ => project}/SubmitProjectActivity.kt (79%) create mode 100644 feature/projects/src/main/java/com/zucchini/submit/project/SubmitProjectFindDevActivity.kt create mode 100644 feature/projects/src/main/java/com/zucchini/submit/project/SubmitProjectViewModel.kt create mode 100644 feature/projects/src/main/java/com/zucchini/submit/project/adapter/FindDevAdapter.kt create mode 100644 feature/projects/src/main/res/layout/activity_submit_project_find_dev.xml create mode 100644 feature/projects/src/main/res/layout/item_find_dev.xml diff --git a/app/src/main/java/com/zucchini/ssuplector/di/DefaultNavigationProvider.kt b/app/src/main/java/com/zucchini/ssuplector/di/DefaultNavigationProvider.kt index b21f9d4..486ce38 100644 --- a/app/src/main/java/com/zucchini/ssuplector/di/DefaultNavigationProvider.kt +++ b/app/src/main/java/com/zucchini/ssuplector/di/DefaultNavigationProvider.kt @@ -5,35 +5,33 @@ import android.content.Intent import com.zucchini.auth.LoginActivity import com.zucchini.common.NavigationProvider import com.zucchini.projects.MainActivity -import com.zucchini.submit.SubmitDevActivity +import com.zucchini.submit.developer.SubmitDevActivity +import com.zucchini.submit.project.SubmitProjectFindDevActivity import dagger.hilt.android.qualifiers.ApplicationContext import javax.inject.Inject -class DefaultNavigationProvider @Inject constructor( - @ApplicationContext private val context: Context, -) : NavigationProvider { +class DefaultNavigationProvider + @Inject + constructor( + @ApplicationContext private val context: Context, + ) : NavigationProvider { + override fun toDevInfo(): Intent { + TODO("Not yet implemented") + } - override fun toDevInfo(): Intent { - TODO("Not yet implemented") - } + override fun toProjects(): Intent { + TODO("Not yet implemented") + } - override fun toProjects(): Intent { - TODO("Not yet implemented") - } + override fun toMyPage(): Intent { + TODO("Not yet implemented") + } - override fun toMyPage(): Intent { - TODO("Not yet implemented") - } + override fun toLogin(): Intent = Intent(context, LoginActivity::class.java) - override fun toLogin(): Intent { - return Intent(context, LoginActivity::class.java) - } + override fun toSubmitDev(): Intent = Intent(context, SubmitDevActivity::class.java) - override fun toSubmitDev(): Intent { - return Intent(context, SubmitDevActivity::class.java) - } + override fun toFindDev(): Intent = Intent(context, SubmitProjectFindDevActivity::class.java) - override fun toMain(): Intent { - return Intent(context, MainActivity::class.java) + override fun toMain(): Intent = Intent(context, MainActivity::class.java) } -} diff --git a/core/common/src/main/java/com/zucchini/common/NavigationProvider.kt b/core/common/src/main/java/com/zucchini/common/NavigationProvider.kt index 8964efe..70537e9 100644 --- a/core/common/src/main/java/com/zucchini/common/NavigationProvider.kt +++ b/core/common/src/main/java/com/zucchini/common/NavigationProvider.kt @@ -9,5 +9,6 @@ interface NavigationProvider { fun toLogin(): Intent fun toSubmitDev(): Intent + fun toFindDev(): Intent fun toMain(): Intent } diff --git a/core/common/src/main/java/com/zucchini/dialog/SubmitProjectDevelopersDialog.kt b/core/common/src/main/java/com/zucchini/dialog/SubmitProjectDevelopersDialog.kt deleted file mode 100644 index 167e29c..0000000 --- a/core/common/src/main/java/com/zucchini/dialog/SubmitProjectDevelopersDialog.kt +++ /dev/null @@ -1,82 +0,0 @@ -package com.zucchini.dialog - -import android.graphics.Color -import android.graphics.drawable.ColorDrawable -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import androidx.fragment.app.DialogFragment -import com.zucchini.context.dialogWidthPercent -import com.zucchini.core.common.databinding.DialogSubmitProjectDevelopersBinding -import com.zucchini.view.setOnSingleClickListener - -class SubmitProjectDevelopersDialog : DialogFragment() { - private lateinit var binding: DialogSubmitProjectDevelopersBinding - - private var confirmButtonClickListener: (() -> Unit)? = null - - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle?, - ): View { - binding = DialogSubmitProjectDevelopersBinding.inflate(inflater, container, false) - return binding.root - } - - override fun onViewCreated( - view: View, - savedInstanceState: Bundle?, - ) { - super.onViewCreated(view, savedInstanceState) - initButtonListener() - initCategoryListner() - } - - override fun onResume() { - super.onResume() - context?.dialogWidthPercent(dialog) - dialog?.window?.run { - setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT)) - } - } - - fun setConfirmButtonClickListener(confirmButtonClickListener: () -> Unit) { - this.confirmButtonClickListener = confirmButtonClickListener - } - - private fun initButtonListener() { - binding.tvConfirmButton.setOnSingleClickListener { - val developerName = binding.etProjectSubmitDeveloperName.text.toString() - val developerEmail = binding.etProjectSubmitDeveloperEmail.text.toString() - val isLeader = binding.cbProjectSubmitDeveloperLeader.isChecked - - val result = - Bundle().apply { - putString("developerName", developerName) - putString("developerEmail", developerEmail) - putBoolean("isLeader", isLeader) - } - - parentFragmentManager.setFragmentResult("SubmitProjectDevelopersDialogResult", result) - dismiss() - } - } - - private fun initCategoryListner() { - binding.tvSubmitProjectDeveloperCategory.setOnSingleClickListener { - TwoButtonCommonDialog - .newInstance( - title = "", - description = "", - confirmButtonText = "", - dismissButtonText = "", - ).apply { - setConfirmButtonClickListener { - dismiss() - } - }.showAllowingStateLoss(childFragmentManager) - } - } -} diff --git a/core/common/src/main/res/layout/dialog_submit_project_developers.xml b/core/common/src/main/res/layout/dialog_submit_project_developers.xml deleted file mode 100644 index 0098a64..0000000 --- a/core/common/src/main/res/layout/dialog_submit_project_developers.xml +++ /dev/null @@ -1,138 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/domain/src/main/java/com/zucchini/domain/model/FindDeveloperInfo.kt b/domain/src/main/java/com/zucchini/domain/model/FindDeveloperInfo.kt new file mode 100644 index 0000000..dcade7f --- /dev/null +++ b/domain/src/main/java/com/zucchini/domain/model/FindDeveloperInfo.kt @@ -0,0 +1,7 @@ +package com.zucchini.domain.model + +data class FindDeveloperInfo( + val developerId: Int, + val developerName: String, + val developerEmail: String, +) \ No newline at end of file diff --git a/domain/src/main/java/com/zucchini/domain/model/SubmitProjectInfo.kt b/domain/src/main/java/com/zucchini/domain/model/SubmitProjectInfo.kt index df7995a..eb22ebc 100644 --- a/domain/src/main/java/com/zucchini/domain/model/SubmitProjectInfo.kt +++ b/domain/src/main/java/com/zucchini/domain/model/SubmitProjectInfo.kt @@ -1,26 +1,17 @@ package com.zucchini.domain.model -import java.nio.file.Path - data class SubmitProjectInfo( - val projectName: String, - val projectGithub: String, - val imagePath: String, - val projectShortIntro: String, - val projectLongIntro: String, + val projectName: String = "", + val projectGithub: String = "", + val imagePath: String = "", + val projectShortIntro: String = "", + val projectLongIntro: String = "", val projectCategoryList: List = emptyList(), val projectTechStackList: List = emptyList(), val projectLanguageList: List = emptyList(), val projectCooperationList: List = emptyList(), - val projectWebLink: String, - val projectAppLink: String, - val projectLink: String, - val developerList: List = emptyList() -) { - data class DeveloperInfoInSubmitProject( - val developerName: String, - val developerEmail: String, - val developerCategoryList: List, - val isTeamLeader: Boolean - ) -} + val projectWebLink: String = "", + val projectAppLink: String = "", + val projectLink: String = "", + var projectDeveloperList: List = emptyList(), +) \ No newline at end of file diff --git a/feature/projects/src/main/AndroidManifest.xml b/feature/projects/src/main/AndroidManifest.xml index 218067d..12df42f 100644 --- a/feature/projects/src/main/AndroidManifest.xml +++ b/feature/projects/src/main/AndroidManifest.xml @@ -3,12 +3,17 @@ + diff --git a/feature/projects/src/main/java/com/zucchini/auth/LoginActivity.kt b/feature/projects/src/main/java/com/zucchini/auth/LoginActivity.kt index 90b90e9..aa96a61 100644 --- a/feature/projects/src/main/java/com/zucchini/auth/LoginActivity.kt +++ b/feature/projects/src/main/java/com/zucchini/auth/LoginActivity.kt @@ -10,7 +10,7 @@ import com.zucchini.feature.projects.R import com.zucchini.feature.projects.databinding.ActivityLoginBinding import com.zucchini.projects.MainActivity import com.zucchini.projects.adapter.IntroducePagerAdapter -import com.zucchini.submit.SubmitDevActivity +import com.zucchini.submit.developer.SubmitDevActivity import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job diff --git a/core/common/src/main/java/com/zucchini/dialog/CheckBoxListAdapter.kt b/feature/projects/src/main/java/com/zucchini/dialog/CheckBoxListAdapter.kt similarity index 67% rename from core/common/src/main/java/com/zucchini/dialog/CheckBoxListAdapter.kt rename to feature/projects/src/main/java/com/zucchini/dialog/CheckBoxListAdapter.kt index 1815838..8b6935c 100644 --- a/core/common/src/main/java/com/zucchini/dialog/CheckBoxListAdapter.kt +++ b/feature/projects/src/main/java/com/zucchini/dialog/CheckBoxListAdapter.kt @@ -4,17 +4,20 @@ import android.view.LayoutInflater import android.view.ViewGroup import androidx.recyclerview.widget.RecyclerView import com.zucchini.core.common.databinding.ItemDialogCheckboxBinding +import com.zucchini.domain.model.Keyword class CheckBoxListAdapter( private val items: List, + private val selectedItems: MutableList ) : RecyclerView.Adapter() { + class ViewHolder( - val binding: ItemDialogCheckboxBinding, + val binding: ItemDialogCheckboxBinding ) : RecyclerView.ViewHolder(binding.root) override fun onCreateViewHolder( parent: ViewGroup, - viewType: Int, + viewType: Int ): ViewHolder { val binding = ItemDialogCheckboxBinding.inflate(LayoutInflater.from(parent.context), parent, false) @@ -23,10 +26,18 @@ class CheckBoxListAdapter( override fun onBindViewHolder( holder: ViewHolder, - position: Int, + position: Int ) { val item = items[position] holder.binding.cbDialogContent.text = item + + holder.binding.cbDialogContent.setOnCheckedChangeListener { _, isChecked -> + if (isChecked) { + selectedItems.add(item) + } else { + selectedItems.remove(item) + } + } } override fun getItemCount() = items.size diff --git a/core/common/src/main/java/com/zucchini/dialog/SelectCheckBoxCommonDialog.kt b/feature/projects/src/main/java/com/zucchini/dialog/SelectCheckBoxCommonDialog.kt similarity index 93% rename from core/common/src/main/java/com/zucchini/dialog/SelectCheckBoxCommonDialog.kt rename to feature/projects/src/main/java/com/zucchini/dialog/SelectCheckBoxCommonDialog.kt index 7bacd1a..4171e67 100644 --- a/core/common/src/main/java/com/zucchini/dialog/SelectCheckBoxCommonDialog.kt +++ b/feature/projects/src/main/java/com/zucchini/dialog/SelectCheckBoxCommonDialog.kt @@ -16,8 +16,9 @@ import com.zucchini.view.setOnSingleClickListener class SelectCheckBoxCommonDialog : DialogFragment() { private lateinit var binding: DialogCommonSelectCheckboxButtonBinding - private var confirmButtonClickListener: (() -> Unit)? = null + private var confirmButtonClickListener: ((List) -> Unit)? = null private var items: List = listOf() + private val selectedItems = mutableListOf() override fun onCreateView( inflater: LayoutInflater, @@ -45,7 +46,7 @@ class SelectCheckBoxCommonDialog : DialogFragment() { } } - fun setConfirmButtonClickListener(confirmButtonClickListener: () -> Unit) { + fun setConfirmButtonClickListener(confirmButtonClickListener: (List) -> Unit) { this.confirmButtonClickListener = confirmButtonClickListener } @@ -61,13 +62,13 @@ class SelectCheckBoxCommonDialog : DialogFragment() { tvConfirmButton.text = confirmButtonText rvDialogContents.layoutManager = LinearLayoutManager(context) - rvDialogContents.adapter = CheckBoxListAdapter(items) + rvDialogContents.adapter = CheckBoxListAdapter(items, selectedItems) } } private fun initButtonListener() { binding.tvConfirmButton.setOnSingleClickListener { - confirmButtonClickListener?.invoke() + confirmButtonClickListener?.invoke(selectedItems) dismiss() } } diff --git a/core/common/src/main/java/com/zucchini/dialog/TwoButtonCommonDialog.kt b/feature/projects/src/main/java/com/zucchini/dialog/TwoButtonCommonDialog.kt similarity index 100% rename from core/common/src/main/java/com/zucchini/dialog/TwoButtonCommonDialog.kt rename to feature/projects/src/main/java/com/zucchini/dialog/TwoButtonCommonDialog.kt diff --git a/feature/projects/src/main/java/com/zucchini/projects/projects/ProjectsFragment.kt b/feature/projects/src/main/java/com/zucchini/projects/projects/ProjectsFragment.kt index ba20a97..6a78539 100644 --- a/feature/projects/src/main/java/com/zucchini/projects/projects/ProjectsFragment.kt +++ b/feature/projects/src/main/java/com/zucchini/projects/projects/ProjectsFragment.kt @@ -19,7 +19,7 @@ import com.zucchini.projects.adapter.PageIndicatorAdapter import com.zucchini.projects.projects.adapter.ProjectsAdapter import com.zucchini.projects.projects.adapter.SearchKeywordAdapter import com.zucchini.projects.projects.viewmodel.ProjectsListViewModel -import com.zucchini.submit.SubmitProjectActivity +import com.zucchini.submit.project.SubmitProjectActivity import com.zucchini.view.hideKeyboard import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.flow.launchIn diff --git a/feature/projects/src/main/java/com/zucchini/submit/SubmitDevActivity.kt b/feature/projects/src/main/java/com/zucchini/submit/developer/SubmitDevActivity.kt similarity index 99% rename from feature/projects/src/main/java/com/zucchini/submit/SubmitDevActivity.kt rename to feature/projects/src/main/java/com/zucchini/submit/developer/SubmitDevActivity.kt index 97916c6..982759a 100644 --- a/feature/projects/src/main/java/com/zucchini/submit/SubmitDevActivity.kt +++ b/feature/projects/src/main/java/com/zucchini/submit/developer/SubmitDevActivity.kt @@ -1,4 +1,4 @@ -package com.zucchini.submit +package com.zucchini.submit.developer import android.content.Intent import android.os.Bundle diff --git a/feature/projects/src/main/java/com/zucchini/submit/SubmitDevViewModel.kt b/feature/projects/src/main/java/com/zucchini/submit/developer/SubmitDevViewModel.kt similarity index 99% rename from feature/projects/src/main/java/com/zucchini/submit/SubmitDevViewModel.kt rename to feature/projects/src/main/java/com/zucchini/submit/developer/SubmitDevViewModel.kt index 7a4ca3c..85f6170 100644 --- a/feature/projects/src/main/java/com/zucchini/submit/SubmitDevViewModel.kt +++ b/feature/projects/src/main/java/com/zucchini/submit/developer/SubmitDevViewModel.kt @@ -1,4 +1,4 @@ -package com.zucchini.submit +package com.zucchini.submit.developer import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope diff --git a/feature/projects/src/main/java/com/zucchini/submit/SubmitProjectActivity.kt b/feature/projects/src/main/java/com/zucchini/submit/project/SubmitProjectActivity.kt similarity index 79% rename from feature/projects/src/main/java/com/zucchini/submit/SubmitProjectActivity.kt rename to feature/projects/src/main/java/com/zucchini/submit/project/SubmitProjectActivity.kt index ed473bc..614b9d2 100644 --- a/feature/projects/src/main/java/com/zucchini/submit/SubmitProjectActivity.kt +++ b/feature/projects/src/main/java/com/zucchini/submit/project/SubmitProjectActivity.kt @@ -1,11 +1,13 @@ -package com.zucchini.submit +package com.zucchini.submit.project import android.net.Uri import android.os.Bundle import android.util.Log import androidx.activity.result.contract.ActivityResultContracts +import androidx.activity.viewModels import androidx.appcompat.app.AppCompatActivity import coil.load +import com.zucchini.common.NavigationProvider import com.zucchini.data.ContentUriRequestBody import com.zucchini.dialog.SelectCheckBoxCommonDialog import com.zucchini.domain.model.KeywordList @@ -14,10 +16,15 @@ import com.zucchini.feature.projects.R import com.zucchini.feature.projects.databinding.ActivitySubmitProjectBinding import com.zucchini.view.setOnSingleClickListener import com.zucchini.view.showShortToast +import dagger.hilt.android.AndroidEntryPoint import timber.log.Timber +import javax.inject.Inject +@AndroidEntryPoint class SubmitProjectActivity : AppCompatActivity() { private lateinit var binding: ActivitySubmitProjectBinding + private val viewModel: SubmitProjectViewModel by viewModels() + private lateinit var submitProjectInfo: SubmitProjectInfo private var imageUri = Uri.EMPTY @@ -32,6 +39,9 @@ class SubmitProjectActivity : AppCompatActivity() { } } + @Inject + lateinit var navigationProvider: NavigationProvider + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivitySubmitProjectBinding.inflate(layoutInflater) @@ -61,7 +71,8 @@ class SubmitProjectActivity : AppCompatActivity() { } private fun selectProjectCategory() { - val categoryKoreanList = KeywordList.categoryList.map { it.keywordKorean } + // īװ Ű Ʈ ѱ۰ Ű带 ϴ Map غ + val keywordMap = KeywordList.categoryList.associateBy { it.keywordKorean } binding.tvSubmitProjectCategory.setOnClickListener { SelectCheckBoxCommonDialog @@ -69,15 +80,25 @@ class SubmitProjectActivity : AppCompatActivity() { title = "Ʈ īװ", description = "Ʈ īװ ּ. (ִ 2)", confirmButtonText = getString(R.string.all_check), - items = categoryKoreanList as ArrayList, + items = keywordMap.keys.toList() as ArrayList, // ѱ Ʈ ).apply { - setConfirmButtonClickListener { - // + setConfirmButtonClickListener { selectedItems -> + // ѱ Ű带 Ű ȯ + val selectedEnglishItems = selectedItems.mapNotNull { keywordKorean -> + keywordMap[keywordKorean]?.keywordEnglish + } + + submitProjectInfo = SubmitProjectInfo( + projectCategoryList = selectedEnglishItems + ) + viewModel.setSubmitDevInfo(submitProjectInfo) + Log.d("SubmitProjectActivity", "$selectedEnglishItems") } }.showAllowingStateLoss(supportFragmentManager, "SelectCheckBoxCommonDialog") } } + private fun selectStack() { val language = KeywordList.languageList.map { it.keywordKorean } val techStack = KeywordList.techStackList.map { it.keywordKorean } @@ -138,24 +159,20 @@ class SubmitProjectActivity : AppCompatActivity() { private fun clickSubmitButton() { binding.btnSubmit.setOnSingleClickListener { - val submitProjectInfo = + submitProjectInfo = SubmitProjectInfo( projectName = binding.etProjectName.text.toString(), imagePath = imageUri.toString(), projectGithub = binding.etGithub.text.toString(), projectShortIntro = binding.etProjectIntroContentShort.text.toString(), projectLongIntro = binding.etProjectIntroContentLong.text.toString(), - // projectCategoryList = - // projectLanguageList = // Ʈ, - // projectTechStackList = // Ʈ, - // projectCooperationToolList = // Ʈ, projectWebLink = binding.etProjectWebLink.text.toString(), projectAppLink = binding.etProjectAppLink.text.toString(), projectLink = binding.etProjectInfoLink.text.toString(), - // developerList = ) - Log.d("SubmitProjectActivity", "submitProjectInfo: $submitProjectInfo") + viewModel.setSubmitDevInfo(submitProjectInfo) + startActivity(navigationProvider.toFindDev()) } } } diff --git a/feature/projects/src/main/java/com/zucchini/submit/project/SubmitProjectFindDevActivity.kt b/feature/projects/src/main/java/com/zucchini/submit/project/SubmitProjectFindDevActivity.kt new file mode 100644 index 0000000..83b0547 --- /dev/null +++ b/feature/projects/src/main/java/com/zucchini/submit/project/SubmitProjectFindDevActivity.kt @@ -0,0 +1,31 @@ +package com.zucchini.submit.project + +import android.os.Bundle +import androidx.activity.viewModels +import androidx.appcompat.app.AppCompatActivity +import androidx.recyclerview.widget.GridLayoutManager +import com.zucchini.domain.model.SubmitProjectInfo +import com.zucchini.feature.projects.databinding.ActivitySubmitProjectFindDevBinding +import com.zucchini.submit.project.adapter.FindDevAdapter +import dagger.hilt.android.AndroidEntryPoint + +@AndroidEntryPoint +class SubmitProjectFindDevActivity : AppCompatActivity() { + private lateinit var binding: ActivitySubmitProjectFindDevBinding + private val viewModel: SubmitProjectViewModel by viewModels() + + override fun onCreate(savedInstanceState: Bundle?) { + binding = ActivitySubmitProjectFindDevBinding.inflate(layoutInflater) + super.onCreate(savedInstanceState) + setContentView(binding.root) + + initDevInfoAdapter() + + } + + private fun initDevInfoAdapter() { + val devAdapter = FindDevAdapter(viewModel.submitDevInfo.value ?: SubmitProjectInfo()) + binding.rvFindDev.adapter = devAdapter + binding.rvFindDev.layoutManager = GridLayoutManager(this, 3) + } +} diff --git a/feature/projects/src/main/java/com/zucchini/submit/project/SubmitProjectViewModel.kt b/feature/projects/src/main/java/com/zucchini/submit/project/SubmitProjectViewModel.kt new file mode 100644 index 0000000..3994b65 --- /dev/null +++ b/feature/projects/src/main/java/com/zucchini/submit/project/SubmitProjectViewModel.kt @@ -0,0 +1,20 @@ +package com.zucchini.submit.project + +import androidx.lifecycle.ViewModel +import com.zucchini.domain.model.SubmitProjectInfo +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import javax.inject.Inject + +@HiltViewModel +class SubmitProjectViewModel + @Inject + constructor() : ViewModel() { + private val _submitDevInfo = MutableStateFlow(null) + val submitDevInfo = _submitDevInfo.asStateFlow() + + fun setSubmitDevInfo(submitProjectInfo: SubmitProjectInfo) { + _submitDevInfo.value = submitProjectInfo + } + } diff --git a/feature/projects/src/main/java/com/zucchini/submit/project/adapter/FindDevAdapter.kt b/feature/projects/src/main/java/com/zucchini/submit/project/adapter/FindDevAdapter.kt new file mode 100644 index 0000000..25ce2e3 --- /dev/null +++ b/feature/projects/src/main/java/com/zucchini/submit/project/adapter/FindDevAdapter.kt @@ -0,0 +1,57 @@ +package com.zucchini.submit.project.adapter + +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.recyclerview.widget.ListAdapter +import androidx.recyclerview.widget.RecyclerView +import com.zucchini.domain.model.FindDeveloperInfo +import com.zucchini.domain.model.SubmitProjectInfo +import com.zucchini.feature.projects.databinding.ItemFindDevBinding +import com.zucchini.view.ItemDiffCallback + +class FindDevAdapter( + private val submitProjectInfo: SubmitProjectInfo +) : ListAdapter( + ItemDiffCallback( + onItemsTheSame = { old, new -> old == new }, + onContentsTheSame = { old, new -> old == new }, + ), +) { + override fun onCreateViewHolder( + parent: ViewGroup, + viewType: Int, + ): FindDevViewHolder { + val inflater = LayoutInflater.from(parent.context) + val binding = ItemFindDevBinding.inflate(inflater, parent, false) + return FindDevViewHolder(binding) + } + + override fun onBindViewHolder( + holder: FindDevViewHolder, + position: Int, + ) { + holder.bind(getItem(position)) + } + + inner class FindDevViewHolder( + private val binding: ItemFindDevBinding, + ) : RecyclerView.ViewHolder(binding.root) { + fun bind(findDevInfo: FindDeveloperInfo) { + binding.run { + tvDeveloperName.text = findDevInfo.developerName + tvDeveloperEmail.text = findDevInfo.developerEmail + + cbFindDev.isChecked = submitProjectInfo.projectDeveloperList.contains(findDevInfo.developerId) + + root.setOnClickListener { + cbFindDev.isChecked = !cbFindDev.isChecked + if (cbFindDev.isChecked) { + submitProjectInfo.projectDeveloperList += findDevInfo.developerId + } else { + submitProjectInfo.projectDeveloperList -= findDevInfo.developerId + } + } + } + } + } +} diff --git a/feature/projects/src/main/res/layout/activity_submit_dev.xml b/feature/projects/src/main/res/layout/activity_submit_dev.xml index 7a950f5..8bcbcfe 100644 --- a/feature/projects/src/main/res/layout/activity_submit_dev.xml +++ b/feature/projects/src/main/res/layout/activity_submit_dev.xml @@ -4,7 +4,7 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" - tools:context="com.zucchini.submit.SubmitDevActivity"> + tools:context="com.zucchini.submit.developer.SubmitDevActivity"> + tools:context="com.zucchini.submit.project.SubmitProjectActivity"> + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/feature/projects/src/main/res/layout/item_find_dev.xml b/feature/projects/src/main/res/layout/item_find_dev.xml new file mode 100644 index 0000000..1c95da8 --- /dev/null +++ b/feature/projects/src/main/res/layout/item_find_dev.xml @@ -0,0 +1,63 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/feature/projects/src/main/res/values/strings.xml b/feature/projects/src/main/res/values/strings.xml index f569c87..827badd 100644 --- a/feature/projects/src/main/res/values/strings.xml +++ b/feature/projects/src/main/res/values/strings.xml @@ -94,5 +94,8 @@ 슈플렉터를 로그아웃 하시겠어요? 정말 슈플렉터를 탈퇴 하시겠어요? 회원탈퇴 후 유저 정보는 30일 동안 임시 보관되며, 이후 영구 삭제됩니다. + 프로젝트를 함께한 개발자의 이름을 검색해서 찾아보세요! + 슈플렉터에 등록되어 있는 개발자라면, 프로젝트를 함께 진행한 개발자로 등록할 수 있어요. + 개발자 이름을 검색해주세요 \ No newline at end of file From 7de92696065e0374344595a21ed5adcf65c01a22 Mon Sep 17 00:00:00 2001 From: kangyuri1114 Date: Mon, 15 Jul 2024 22:12:00 +0900 Subject: [PATCH 13/31] =?UTF-8?q?[feat]:=20=EB=8B=A4=EC=9D=B4=EC=96=BC?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=20=EA=B0=92=20=EB=B0=98=ED=99=98=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../zucchini/dialog/CheckBoxListAdapter.kt | 14 +++- .../dialog/SelectCheckBoxCommonDialog.kt | 7 +- .../submit/project/SubmitProjectActivity.kt | 81 ++++++++++++++----- 3 files changed, 77 insertions(+), 25 deletions(-) diff --git a/feature/projects/src/main/java/com/zucchini/dialog/CheckBoxListAdapter.kt b/feature/projects/src/main/java/com/zucchini/dialog/CheckBoxListAdapter.kt index 8b6935c..dca37de 100644 --- a/feature/projects/src/main/java/com/zucchini/dialog/CheckBoxListAdapter.kt +++ b/feature/projects/src/main/java/com/zucchini/dialog/CheckBoxListAdapter.kt @@ -4,11 +4,11 @@ import android.view.LayoutInflater import android.view.ViewGroup import androidx.recyclerview.widget.RecyclerView import com.zucchini.core.common.databinding.ItemDialogCheckboxBinding -import com.zucchini.domain.model.Keyword class CheckBoxListAdapter( private val items: List, - private val selectedItems: MutableList + private val selectedItems: MutableList, + private val maxSelectionCount: Int ) : RecyclerView.Adapter() { class ViewHolder( @@ -31,9 +31,17 @@ class CheckBoxListAdapter( val item = items[position] holder.binding.cbDialogContent.text = item + // Initialize checkbox state + holder.binding.cbDialogContent.isChecked = selectedItems.contains(item) + holder.binding.cbDialogContent.setOnCheckedChangeListener { _, isChecked -> if (isChecked) { - selectedItems.add(item) + // Check if the maximum selection count is not exceeded + if (selectedItems.size < maxSelectionCount) { + selectedItems.add(item) + } else { + holder.binding.cbDialogContent.isChecked = false + } } else { selectedItems.remove(item) } diff --git a/feature/projects/src/main/java/com/zucchini/dialog/SelectCheckBoxCommonDialog.kt b/feature/projects/src/main/java/com/zucchini/dialog/SelectCheckBoxCommonDialog.kt index 4171e67..3d5e11b 100644 --- a/feature/projects/src/main/java/com/zucchini/dialog/SelectCheckBoxCommonDialog.kt +++ b/feature/projects/src/main/java/com/zucchini/dialog/SelectCheckBoxCommonDialog.kt @@ -19,6 +19,7 @@ class SelectCheckBoxCommonDialog : DialogFragment() { private var confirmButtonClickListener: ((List) -> Unit)? = null private var items: List = listOf() private val selectedItems = mutableListOf() + private var maxSelectionCount: Int = Int.MAX_VALUE override fun onCreateView( inflater: LayoutInflater, @@ -55,6 +56,7 @@ class SelectCheckBoxCommonDialog : DialogFragment() { val description = arguments?.getString(DESCRIPTION) val confirmButtonText = arguments?.getString(CONFIRM_BUTTON_TEXT, "") items = arguments?.getStringArrayList(ITEMS) ?: listOf() + maxSelectionCount = arguments?.getInt(MAX_SELECTION_COUNT, Int.MAX_VALUE) ?: Int.MAX_VALUE with(binding) { tvDialogTitle.text = title @@ -62,7 +64,7 @@ class SelectCheckBoxCommonDialog : DialogFragment() { tvConfirmButton.text = confirmButtonText rvDialogContents.layoutManager = LinearLayoutManager(context) - rvDialogContents.adapter = CheckBoxListAdapter(items, selectedItems) + rvDialogContents.adapter = CheckBoxListAdapter(items, selectedItems, maxSelectionCount) } } @@ -90,12 +92,14 @@ class SelectCheckBoxCommonDialog : DialogFragment() { const val DESCRIPTION = "description" const val CONFIRM_BUTTON_TEXT = "confirmButtonText" const val ITEMS = "items" + const val MAX_SELECTION_COUNT = "maxSelectionCount" fun newInstance( title: String, description: String? = null, confirmButtonText: String, items: ArrayList, + maxSelectionCount: Int = Int.MAX_VALUE ): SelectCheckBoxCommonDialog = SelectCheckBoxCommonDialog().apply { arguments = @@ -104,6 +108,7 @@ class SelectCheckBoxCommonDialog : DialogFragment() { putString(DESCRIPTION, description) putString(CONFIRM_BUTTON_TEXT, confirmButtonText) putStringArrayList(ITEMS, items) + putInt(MAX_SELECTION_COUNT, maxSelectionCount) } } } diff --git a/feature/projects/src/main/java/com/zucchini/submit/project/SubmitProjectActivity.kt b/feature/projects/src/main/java/com/zucchini/submit/project/SubmitProjectActivity.kt index 614b9d2..79b6d70 100644 --- a/feature/projects/src/main/java/com/zucchini/submit/project/SubmitProjectActivity.kt +++ b/feature/projects/src/main/java/com/zucchini/submit/project/SubmitProjectActivity.kt @@ -81,28 +81,30 @@ class SubmitProjectActivity : AppCompatActivity() { description = "Ʈ īװ ּ. (ִ 2)", confirmButtonText = getString(R.string.all_check), items = keywordMap.keys.toList() as ArrayList, // ѱ Ʈ + maxSelectionCount = 2, ).apply { setConfirmButtonClickListener { selectedItems -> // ѱ Ű带 Ű ȯ - val selectedEnglishItems = selectedItems.mapNotNull { keywordKorean -> - keywordMap[keywordKorean]?.keywordEnglish - } - - submitProjectInfo = SubmitProjectInfo( - projectCategoryList = selectedEnglishItems - ) + val selectedEnglishItems = + selectedItems.mapNotNull { keywordKorean -> + keywordMap[keywordKorean]?.keywordEnglish + } + + submitProjectInfo = + SubmitProjectInfo( + projectCategoryList = selectedEnglishItems, + ) viewModel.setSubmitDevInfo(submitProjectInfo) - Log.d("SubmitProjectActivity", "$selectedEnglishItems") + Log.d("SubmitProjectActivity", viewModel.submitDevInfo.value.toString()) } }.showAllowingStateLoss(supportFragmentManager, "SelectCheckBoxCommonDialog") } } - private fun selectStack() { - val language = KeywordList.languageList.map { it.keywordKorean } - val techStack = KeywordList.techStackList.map { it.keywordKorean } - val cooperationTool = KeywordList.cooperationList.map { it.keywordKorean } + val languageMap = KeywordList.languageList.associateBy { it.keywordKorean } + val techStackMap = KeywordList.techStackList.associateBy { it.keywordKorean } + val cooperationToolMap = KeywordList.cooperationList.associateBy { it.keywordKorean } binding.tvDevStackLanguage.setOnClickListener { SelectCheckBoxCommonDialog @@ -110,10 +112,22 @@ class SubmitProjectActivity : AppCompatActivity() { title = " ", description = "Ʈ  ּ.\n(ִ 3)", confirmButtonText = getString(R.string.all_check), - items = language as ArrayList, + items = languageMap.keys.toList() as ArrayList, + maxSelectionCount = 3, ).apply { - setConfirmButtonClickListener { - // + setConfirmButtonClickListener { selectedItems -> + // ѱ Ű带 Ű ȯ + val selectedEnglishItems = + selectedItems.mapNotNull { keywordKorean -> + languageMap[keywordKorean]?.keywordEnglish + } + + submitProjectInfo = + SubmitProjectInfo( + projectLanguageList = selectedEnglishItems, + ) + viewModel.setSubmitDevInfo(submitProjectInfo) + Log.d("SubmitProjectActivity", viewModel.submitDevInfo.value.toString()) } }.showAllowingStateLoss(supportFragmentManager, "SelectCheckBoxCommonDialog") } @@ -123,10 +137,22 @@ class SubmitProjectActivity : AppCompatActivity() { title = " ", description = "Ʈ ּ.\n(ִ 3)", confirmButtonText = getString(R.string.all_check), - items = techStack as ArrayList, + items = techStackMap.keys.toList() as ArrayList, + maxSelectionCount = 3, ).apply { - setConfirmButtonClickListener { - // + setConfirmButtonClickListener { selectedItems -> + // ѱ Ű带 Ű ȯ + val selectedEnglishItems = + selectedItems.mapNotNull { keywordKorean -> + techStackMap[keywordKorean]?.keywordEnglish + } + + submitProjectInfo = + SubmitProjectInfo( + projectTechStackList = selectedEnglishItems, + ) + viewModel.setSubmitDevInfo(submitProjectInfo) + Log.d("SubmitProjectActivity", viewModel.submitDevInfo.value.toString()) } }.showAllowingStateLoss(supportFragmentManager, "SelectCheckBoxCommonDialog") } @@ -136,10 +162,22 @@ class SubmitProjectActivity : AppCompatActivity() { title = " ", description = "Ʈ ּ.\n(ִ 3)", confirmButtonText = getString(R.string.all_check), - items = cooperationTool as ArrayList, + items = cooperationToolMap.keys.toList() as ArrayList, + maxSelectionCount = 3, ).apply { - setConfirmButtonClickListener { - // + setConfirmButtonClickListener { selectedItems -> + // ѱ Ű带 Ű ȯ + val selectedEnglishItems = + selectedItems.mapNotNull { keywordKorean -> + cooperationToolMap[keywordKorean]?.keywordEnglish + } + + submitProjectInfo = + SubmitProjectInfo( + projectCooperationList = selectedEnglishItems, + ) + viewModel.setSubmitDevInfo(submitProjectInfo) + Log.d("SubmitProjectActivity", viewModel.submitDevInfo.value.toString()) } }.showAllowingStateLoss(supportFragmentManager, "SelectCheckBoxCommonDialog") } @@ -171,6 +209,7 @@ class SubmitProjectActivity : AppCompatActivity() { projectLink = binding.etProjectInfoLink.text.toString(), ) + Log.d("SubmitProjectActivity", viewModel.submitDevInfo.value.toString()) viewModel.setSubmitDevInfo(submitProjectInfo) startActivity(navigationProvider.toFindDev()) } From 3feebf24540b579643c8a0593e81ce29733fc1a2 Mon Sep 17 00:00:00 2001 From: kangyuri1114 Date: Mon, 15 Jul 2024 22:13:44 +0900 Subject: [PATCH 14/31] =?UTF-8?q?[feat]:=20string=20=EC=B6=94=EC=B6=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../zucchini/submit/project/SubmitProjectActivity.kt | 12 ++++++------ feature/projects/src/main/res/values/strings.xml | 6 ++++++ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/feature/projects/src/main/java/com/zucchini/submit/project/SubmitProjectActivity.kt b/feature/projects/src/main/java/com/zucchini/submit/project/SubmitProjectActivity.kt index 79b6d70..7962f12 100644 --- a/feature/projects/src/main/java/com/zucchini/submit/project/SubmitProjectActivity.kt +++ b/feature/projects/src/main/java/com/zucchini/submit/project/SubmitProjectActivity.kt @@ -109,8 +109,8 @@ class SubmitProjectActivity : AppCompatActivity() { binding.tvDevStackLanguage.setOnClickListener { SelectCheckBoxCommonDialog .newInstance( - title = " ", - description = "Ʈ  ּ.\n(ִ 3)", + title = getString(R.string.dialog_language_title), + description = getString(R.string.dialog_language_description), confirmButtonText = getString(R.string.all_check), items = languageMap.keys.toList() as ArrayList, maxSelectionCount = 3, @@ -134,8 +134,8 @@ class SubmitProjectActivity : AppCompatActivity() { binding.tvDevStackDevStack.setOnClickListener { SelectCheckBoxCommonDialog .newInstance( - title = " ", - description = "Ʈ ּ.\n(ִ 3)", + title = getString(R.string.dialog_techstack_title), + description = getString(R.string.dialog_techstack_description), confirmButtonText = getString(R.string.all_check), items = techStackMap.keys.toList() as ArrayList, maxSelectionCount = 3, @@ -159,8 +159,8 @@ class SubmitProjectActivity : AppCompatActivity() { binding.tvDevStackCooperation.setOnClickListener { SelectCheckBoxCommonDialog .newInstance( - title = " ", - description = "Ʈ ּ.\n(ִ 3)", + title = getString(R.string.dialog_cooperation_title), + description = getString(R.string.dialog_cooperation_description), confirmButtonText = getString(R.string.all_check), items = cooperationToolMap.keys.toList() as ArrayList, maxSelectionCount = 3, diff --git a/feature/projects/src/main/res/values/strings.xml b/feature/projects/src/main/res/values/strings.xml index 827badd..dde6cb5 100644 --- a/feature/projects/src/main/res/values/strings.xml +++ b/feature/projects/src/main/res/values/strings.xml @@ -97,5 +97,11 @@ 프로젝트를 함께한 개발자의 이름을 검색해서 찾아보세요! 슈플렉터에 등록되어 있는 개발자라면, 프로젝트를 함께 진행한 개발자로 등록할 수 있어요. 개발자 이름을 검색해주세요 + 사용 언어 + 프로젝트에서 사용한 언어를 선택해주세요.\n(최대 3개) + 사용 기술 스택 + 프로젝트에서 사용한 기술 스택을 선택해주세요.\n(최대 3개) + 사용 협업툴 + 프로젝트에서 사용한 협업툴을 선택해주세요.\n(최대 3개) \ No newline at end of file From 371b83d27c0f04d33b685d863202ef4daee28c06 Mon Sep 17 00:00:00 2001 From: kangyuri1114 Date: Mon, 15 Jul 2024 22:33:09 +0900 Subject: [PATCH 15/31] =?UTF-8?q?[feat]:=20=EC=9E=85=EB=A0=A5=EA=B0=92=20?= =?UTF-8?q?=EB=B7=B0=EB=AA=A8=EB=8D=B8=20=EC=A0=80=EC=9E=A5=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../submit/project/SubmitProjectActivity.kt | 54 ++++-------- .../submit/project/SubmitProjectViewModel.kt | 83 +++++++++++++++++++ 2 files changed, 99 insertions(+), 38 deletions(-) diff --git a/feature/projects/src/main/java/com/zucchini/submit/project/SubmitProjectActivity.kt b/feature/projects/src/main/java/com/zucchini/submit/project/SubmitProjectActivity.kt index 7962f12..de72944 100644 --- a/feature/projects/src/main/java/com/zucchini/submit/project/SubmitProjectActivity.kt +++ b/feature/projects/src/main/java/com/zucchini/submit/project/SubmitProjectActivity.kt @@ -90,12 +90,7 @@ class SubmitProjectActivity : AppCompatActivity() { keywordMap[keywordKorean]?.keywordEnglish } - submitProjectInfo = - SubmitProjectInfo( - projectCategoryList = selectedEnglishItems, - ) - viewModel.setSubmitDevInfo(submitProjectInfo) - Log.d("SubmitProjectActivity", viewModel.submitDevInfo.value.toString()) + viewModel.updateProjectCategory(projectCategoryList = selectedEnglishItems) } }.showAllowingStateLoss(supportFragmentManager, "SelectCheckBoxCommonDialog") } @@ -122,12 +117,7 @@ class SubmitProjectActivity : AppCompatActivity() { languageMap[keywordKorean]?.keywordEnglish } - submitProjectInfo = - SubmitProjectInfo( - projectLanguageList = selectedEnglishItems, - ) - viewModel.setSubmitDevInfo(submitProjectInfo) - Log.d("SubmitProjectActivity", viewModel.submitDevInfo.value.toString()) + viewModel.updateProjectLanguage(projectLanguageList = selectedEnglishItems) } }.showAllowingStateLoss(supportFragmentManager, "SelectCheckBoxCommonDialog") } @@ -147,12 +137,7 @@ class SubmitProjectActivity : AppCompatActivity() { techStackMap[keywordKorean]?.keywordEnglish } - submitProjectInfo = - SubmitProjectInfo( - projectTechStackList = selectedEnglishItems, - ) - viewModel.setSubmitDevInfo(submitProjectInfo) - Log.d("SubmitProjectActivity", viewModel.submitDevInfo.value.toString()) + viewModel.updateProjectTechStack(projectTechStackList = selectedEnglishItems) } }.showAllowingStateLoss(supportFragmentManager, "SelectCheckBoxCommonDialog") } @@ -172,12 +157,7 @@ class SubmitProjectActivity : AppCompatActivity() { cooperationToolMap[keywordKorean]?.keywordEnglish } - submitProjectInfo = - SubmitProjectInfo( - projectCooperationList = selectedEnglishItems, - ) - viewModel.setSubmitDevInfo(submitProjectInfo) - Log.d("SubmitProjectActivity", viewModel.submitDevInfo.value.toString()) + viewModel.updateProjectCooperation(projectCooperationList = selectedEnglishItems) } }.showAllowingStateLoss(supportFragmentManager, "SelectCheckBoxCommonDialog") } @@ -197,20 +177,18 @@ class SubmitProjectActivity : AppCompatActivity() { private fun clickSubmitButton() { binding.btnSubmit.setOnSingleClickListener { - submitProjectInfo = - SubmitProjectInfo( - projectName = binding.etProjectName.text.toString(), - imagePath = imageUri.toString(), - projectGithub = binding.etGithub.text.toString(), - projectShortIntro = binding.etProjectIntroContentShort.text.toString(), - projectLongIntro = binding.etProjectIntroContentLong.text.toString(), - projectWebLink = binding.etProjectWebLink.text.toString(), - projectAppLink = binding.etProjectAppLink.text.toString(), - projectLink = binding.etProjectInfoLink.text.toString(), - ) - - Log.d("SubmitProjectActivity", viewModel.submitDevInfo.value.toString()) - viewModel.setSubmitDevInfo(submitProjectInfo) + viewModel.updateProjectInfo( + projectName = binding.etProjectName.text.toString(), + imagePath = imageUri.toString(), + projectGithub = binding.etGithub.text.toString(), + projectShortIntro = binding.etProjectIntroContentShort.text.toString(), + projectLongIntro = binding.etProjectIntroContentLong.text.toString(), + projectWebLink = binding.etProjectWebLink.text.toString(), + projectAppLink = binding.etProjectAppLink.text.toString(), + projectLink = binding.etProjectInfoLink.text.toString(), + ) + + Log.d("SubmitProjectActivity", "clickSubmitButton: ${viewModel.projectLink.value}, ${viewModel.projectAppLink.value}, ${viewModel.projectWebLink.value}, ${viewModel.projectLongIntro.value}, ${viewModel.projectShortIntro.value}, ${viewModel.projectGithub.value}, ${viewModel.projectName.value}, ${viewModel.projectCategoryList.value}, ${viewModel.projectTechStackList.value}, ${viewModel.projectLanguageList.value}, ${viewModel.projectCooperationList.value}, ${viewModel.projectDeveloperList.value}") startActivity(navigationProvider.toFindDev()) } } diff --git a/feature/projects/src/main/java/com/zucchini/submit/project/SubmitProjectViewModel.kt b/feature/projects/src/main/java/com/zucchini/submit/project/SubmitProjectViewModel.kt index 3994b65..62be426 100644 --- a/feature/projects/src/main/java/com/zucchini/submit/project/SubmitProjectViewModel.kt +++ b/feature/projects/src/main/java/com/zucchini/submit/project/SubmitProjectViewModel.kt @@ -14,7 +14,90 @@ class SubmitProjectViewModel private val _submitDevInfo = MutableStateFlow(null) val submitDevInfo = _submitDevInfo.asStateFlow() + private val _projectName = MutableStateFlow("") + val projectName = _projectName.asStateFlow() + + private val _projectGithub = MutableStateFlow("") + val projectGithub = _projectGithub.asStateFlow() + + private val _imagePath = MutableStateFlow("") + val imagePath = _imagePath.asStateFlow() + + private val _projectShortIntro = MutableStateFlow("") + val projectShortIntro = _projectShortIntro.asStateFlow() + + private val _projectLongIntro = MutableStateFlow("") + val projectLongIntro = _projectLongIntro.asStateFlow() + + private val _projectCategoryList = MutableStateFlow(emptyList()) + val projectCategoryList = _projectCategoryList.asStateFlow() + + private val _projectTechStackList = MutableStateFlow(emptyList()) + val projectTechStackList = _projectTechStackList.asStateFlow() + + private val _projectLanguageList = MutableStateFlow(emptyList()) + val projectLanguageList = _projectLanguageList.asStateFlow() + + private val _projectCooperationList = MutableStateFlow(emptyList()) + val projectCooperationList = _projectCooperationList.asStateFlow() + + private val _projectWebLink = MutableStateFlow("") + val projectWebLink = _projectWebLink.asStateFlow() + + private val _projectAppLink = MutableStateFlow("") + val projectAppLink = _projectAppLink.asStateFlow() + + private val _projectLink = MutableStateFlow("") + val projectLink = _projectLink.asStateFlow() + + private val _projectDeveloperList = MutableStateFlow(emptyList()) + val projectDeveloperList = _projectDeveloperList.asStateFlow() + fun setSubmitDevInfo(submitProjectInfo: SubmitProjectInfo) { _submitDevInfo.value = submitProjectInfo } + + fun setProjectName(projectName: String) { + _projectName.value = projectName + } + + fun updateProjectInfo( + projectName: String, + projectGithub: String, + imagePath: String, + projectShortIntro: String, + projectLongIntro: String, + projectWebLink: String, + projectAppLink: String, + projectLink: String, + ) { + _projectName.value = projectName + _projectGithub.value = projectGithub + _imagePath.value = imagePath + _projectShortIntro.value = projectShortIntro + _projectLongIntro.value = projectLongIntro + _projectWebLink.value = projectWebLink + _projectAppLink.value = projectAppLink + _projectLink.value = projectLink + } + + fun updateProjectCategory(projectCategoryList: List = emptyList()) { + _projectCategoryList.value = projectCategoryList + } + + fun updateProjectTechStack(projectTechStackList: List = emptyList()) { + _projectTechStackList.value = projectTechStackList + } + + fun updateProjectLanguage(projectLanguageList: List = emptyList()) { + _projectLanguageList.value = projectLanguageList + } + + fun updateProjectCooperation(projectCooperationList: List = emptyList()) { + _projectCooperationList.value = projectCooperationList + } + + fun updateDeveloperList(projectDeveloperList: List) { + _projectDeveloperList.value = projectDeveloperList + } } From a7bd4794284076442626cd134551b0fbd847c004 Mon Sep 17 00:00:00 2001 From: kangyuri1114 Date: Tue, 16 Jul 2024 00:24:39 +0900 Subject: [PATCH 16/31] =?UTF-8?q?[feat]:=20=EA=B0=9C=EB=B0=9C=EC=9E=90=20?= =?UTF-8?q?=EC=B0=BE=EA=B8=B0=20api=20=EB=B6=99=EC=9D=B4=EA=B8=B0=20?= =?UTF-8?q?=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../reponse/SearchDeveloperResultResponse.kt | 14 +++++++ .../network/service/DevelopersService.kt | 6 +++ .../zucchini/data/DevelopersRepositoryImpl.kt | 8 ++++ .../com/zucchini/mapper/SearchDeveloper.kt | 13 ++++++ .../domain/repository/DevelopersRepository.kt | 3 ++ .../submit/project/SubmitProjectActivity.kt | 3 -- .../project/SubmitProjectFindDevActivity.kt | 28 +++++++++++-- .../submit/project/SubmitProjectViewModel.kt | 42 +++++++++---------- .../res/layout/activity_submit_project.xml | 2 +- .../activity_submit_project_find_dev.xml | 20 ++++++++- .../projects/src/main/res/values/strings.xml | 1 + 11 files changed, 109 insertions(+), 31 deletions(-) create mode 100644 core/network/src/main/java/com/sample/network/reponse/SearchDeveloperResultResponse.kt create mode 100644 data/src/main/java/com/zucchini/mapper/SearchDeveloper.kt diff --git a/core/network/src/main/java/com/sample/network/reponse/SearchDeveloperResultResponse.kt b/core/network/src/main/java/com/sample/network/reponse/SearchDeveloperResultResponse.kt new file mode 100644 index 0000000..b12e257 --- /dev/null +++ b/core/network/src/main/java/com/sample/network/reponse/SearchDeveloperResultResponse.kt @@ -0,0 +1,14 @@ +package com.sample.network.reponse + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class SearchDeveloperResultResponse( + @SerialName("id") + val id: Int?, + @SerialName("name") + val name: String?, + @SerialName("email") + val email: String?, +) diff --git a/core/network/src/main/java/com/sample/network/service/DevelopersService.kt b/core/network/src/main/java/com/sample/network/service/DevelopersService.kt index e334874..fd398b8 100644 --- a/core/network/src/main/java/com/sample/network/service/DevelopersService.kt +++ b/core/network/src/main/java/com/sample/network/service/DevelopersService.kt @@ -3,6 +3,7 @@ package com.sample.network.service import com.sample.network.model.BaseResponse import com.sample.network.reponse.DevelopersDetailResponse import com.sample.network.reponse.DevelopersListResponse +import com.sample.network.reponse.SearchDeveloperResultResponse import com.sample.network.request.CreateDevelopersRequest import retrofit2.http.Body import retrofit2.http.GET @@ -31,4 +32,9 @@ interface DevelopersService { @Query("email") email: String? = null, @Body request: CreateDevelopersRequest, ): BaseResponse + + @GET("/api/developers/search") + suspend fun searchDevelopers( + @Query("developerName") developerName: String, + ): BaseResponse> } diff --git a/data/src/main/java/com/zucchini/data/DevelopersRepositoryImpl.kt b/data/src/main/java/com/zucchini/data/DevelopersRepositoryImpl.kt index e977e75..1f06ea8 100644 --- a/data/src/main/java/com/zucchini/data/DevelopersRepositoryImpl.kt +++ b/data/src/main/java/com/zucchini/data/DevelopersRepositoryImpl.kt @@ -3,11 +3,13 @@ package com.zucchini.data import com.sample.network.service.DevelopersService import com.zucchini.domain.model.DevelopersDetailModel import com.zucchini.domain.model.DevelopersListModel +import com.zucchini.domain.model.FindDeveloperInfo import com.zucchini.domain.model.SubmitDevInfo import com.zucchini.domain.repository.DevelopersRepository import com.zucchini.mapper.toCreateDevelopersRequest import com.zucchini.mapper.toDevelopersDetailModel import com.zucchini.mapper.toDevelopersListModel +import com.zucchini.mapper.toSearchDeveloperResult import javax.inject.Inject class DevelopersRepositoryImpl @Inject constructor( @@ -48,4 +50,10 @@ class DevelopersRepositoryImpl @Inject constructor( ).data } } + + override suspend fun searchDevelopers(developerName: String): Result> { + return runCatching { + developersService.searchDevelopers(developerName).data.toSearchDeveloperResult() + } + } } diff --git a/data/src/main/java/com/zucchini/mapper/SearchDeveloper.kt b/data/src/main/java/com/zucchini/mapper/SearchDeveloper.kt new file mode 100644 index 0000000..3563f1a --- /dev/null +++ b/data/src/main/java/com/zucchini/mapper/SearchDeveloper.kt @@ -0,0 +1,13 @@ +package com.zucchini.mapper + +import com.sample.network.reponse.SearchDeveloperResultResponse +import com.zucchini.domain.model.FindDeveloperInfo + +internal fun List.toSearchDeveloperResult(): List = + this.map { developer -> + FindDeveloperInfo( + developerName = developer.name ?: "", + developerEmail = developer.email ?: "", + developerId = developer.id ?: -1, + ) + } \ No newline at end of file diff --git a/domain/src/main/java/com/zucchini/domain/repository/DevelopersRepository.kt b/domain/src/main/java/com/zucchini/domain/repository/DevelopersRepository.kt index 7ecc785..c325cdf 100644 --- a/domain/src/main/java/com/zucchini/domain/repository/DevelopersRepository.kt +++ b/domain/src/main/java/com/zucchini/domain/repository/DevelopersRepository.kt @@ -2,6 +2,7 @@ package com.zucchini.domain.repository import com.zucchini.domain.model.DevelopersDetailModel import com.zucchini.domain.model.DevelopersListModel +import com.zucchini.domain.model.FindDeveloperInfo import com.zucchini.domain.model.SubmitDevInfo interface DevelopersRepository { @@ -9,4 +10,6 @@ interface DevelopersRepository { suspend fun getDevelopersDetailData(developerId: Int): Result suspend fun createDeveloperInfo(accessToken: String, email: String? = null, submitDevInfo: SubmitDevInfo): Result + + suspend fun searchDevelopers(developerName: String): Result> } diff --git a/feature/projects/src/main/java/com/zucchini/submit/project/SubmitProjectActivity.kt b/feature/projects/src/main/java/com/zucchini/submit/project/SubmitProjectActivity.kt index de72944..6430cce 100644 --- a/feature/projects/src/main/java/com/zucchini/submit/project/SubmitProjectActivity.kt +++ b/feature/projects/src/main/java/com/zucchini/submit/project/SubmitProjectActivity.kt @@ -24,7 +24,6 @@ import javax.inject.Inject class SubmitProjectActivity : AppCompatActivity() { private lateinit var binding: ActivitySubmitProjectBinding private val viewModel: SubmitProjectViewModel by viewModels() - private lateinit var submitProjectInfo: SubmitProjectInfo private var imageUri = Uri.EMPTY @@ -187,8 +186,6 @@ class SubmitProjectActivity : AppCompatActivity() { projectAppLink = binding.etProjectAppLink.text.toString(), projectLink = binding.etProjectInfoLink.text.toString(), ) - - Log.d("SubmitProjectActivity", "clickSubmitButton: ${viewModel.projectLink.value}, ${viewModel.projectAppLink.value}, ${viewModel.projectWebLink.value}, ${viewModel.projectLongIntro.value}, ${viewModel.projectShortIntro.value}, ${viewModel.projectGithub.value}, ${viewModel.projectName.value}, ${viewModel.projectCategoryList.value}, ${viewModel.projectTechStackList.value}, ${viewModel.projectLanguageList.value}, ${viewModel.projectCooperationList.value}, ${viewModel.projectDeveloperList.value}") startActivity(navigationProvider.toFindDev()) } } diff --git a/feature/projects/src/main/java/com/zucchini/submit/project/SubmitProjectFindDevActivity.kt b/feature/projects/src/main/java/com/zucchini/submit/project/SubmitProjectFindDevActivity.kt index 83b0547..3a2c285 100644 --- a/feature/projects/src/main/java/com/zucchini/submit/project/SubmitProjectFindDevActivity.kt +++ b/feature/projects/src/main/java/com/zucchini/submit/project/SubmitProjectFindDevActivity.kt @@ -3,16 +3,21 @@ package com.zucchini.submit.project import android.os.Bundle import androidx.activity.viewModels import androidx.appcompat.app.AppCompatActivity +import androidx.lifecycle.flowWithLifecycle +import androidx.lifecycle.lifecycleScope import androidx.recyclerview.widget.GridLayoutManager import com.zucchini.domain.model.SubmitProjectInfo import com.zucchini.feature.projects.databinding.ActivitySubmitProjectFindDevBinding import com.zucchini.submit.project.adapter.FindDevAdapter import dagger.hilt.android.AndroidEntryPoint +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach @AndroidEntryPoint class SubmitProjectFindDevActivity : AppCompatActivity() { private lateinit var binding: ActivitySubmitProjectFindDevBinding private val viewModel: SubmitProjectViewModel by viewModels() + private lateinit var devAdapter: FindDevAdapter override fun onCreate(savedInstanceState: Bundle?) { binding = ActivitySubmitProjectFindDevBinding.inflate(layoutInflater) @@ -20,12 +25,29 @@ class SubmitProjectFindDevActivity : AppCompatActivity() { setContentView(binding.root) initDevInfoAdapter() - + initBackButton() + clickSearchKeyword() } private fun initDevInfoAdapter() { - val devAdapter = FindDevAdapter(viewModel.submitDevInfo.value ?: SubmitProjectInfo()) + devAdapter = FindDevAdapter(viewModel.submitDevInfo.value ?: SubmitProjectInfo()) binding.rvFindDev.adapter = devAdapter - binding.rvFindDev.layoutManager = GridLayoutManager(this, 3) + binding.rvFindDev.layoutManager = GridLayoutManager(this, 2) + } + + private fun clickSearchKeyword() { + binding.ivSearch.setOnClickListener { + viewModel.searchDeveloperList(binding.etSearchbar.text.toString()) + } + + viewModel.searchDeveloperResultList.flowWithLifecycle(lifecycle).onEach { developerList -> + devAdapter.submitList(developerList) + }.launchIn(lifecycleScope) + } + + private fun initBackButton() { + binding.ivBackButton.setOnClickListener { + finish() + } } } diff --git a/feature/projects/src/main/java/com/zucchini/submit/project/SubmitProjectViewModel.kt b/feature/projects/src/main/java/com/zucchini/submit/project/SubmitProjectViewModel.kt index 62be426..f81b43c 100644 --- a/feature/projects/src/main/java/com/zucchini/submit/project/SubmitProjectViewModel.kt +++ b/feature/projects/src/main/java/com/zucchini/submit/project/SubmitProjectViewModel.kt @@ -1,65 +1,53 @@ package com.zucchini.submit.project import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.zucchini.domain.model.FindDeveloperInfo import com.zucchini.domain.model.SubmitProjectInfo +import com.zucchini.domain.repository.DevelopersRepository import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.launch import javax.inject.Inject @HiltViewModel class SubmitProjectViewModel @Inject - constructor() : ViewModel() { + constructor( + private val developersRepository: DevelopersRepository, + ) : ViewModel() { private val _submitDevInfo = MutableStateFlow(null) val submitDevInfo = _submitDevInfo.asStateFlow() private val _projectName = MutableStateFlow("") - val projectName = _projectName.asStateFlow() private val _projectGithub = MutableStateFlow("") - val projectGithub = _projectGithub.asStateFlow() private val _imagePath = MutableStateFlow("") - val imagePath = _imagePath.asStateFlow() private val _projectShortIntro = MutableStateFlow("") - val projectShortIntro = _projectShortIntro.asStateFlow() private val _projectLongIntro = MutableStateFlow("") - val projectLongIntro = _projectLongIntro.asStateFlow() private val _projectCategoryList = MutableStateFlow(emptyList()) - val projectCategoryList = _projectCategoryList.asStateFlow() private val _projectTechStackList = MutableStateFlow(emptyList()) - val projectTechStackList = _projectTechStackList.asStateFlow() private val _projectLanguageList = MutableStateFlow(emptyList()) - val projectLanguageList = _projectLanguageList.asStateFlow() private val _projectCooperationList = MutableStateFlow(emptyList()) - val projectCooperationList = _projectCooperationList.asStateFlow() private val _projectWebLink = MutableStateFlow("") - val projectWebLink = _projectWebLink.asStateFlow() private val _projectAppLink = MutableStateFlow("") - val projectAppLink = _projectAppLink.asStateFlow() private val _projectLink = MutableStateFlow("") - val projectLink = _projectLink.asStateFlow() - private val _projectDeveloperList = MutableStateFlow(emptyList()) - val projectDeveloperList = _projectDeveloperList.asStateFlow() + private val _addProjectDeveloperList = MutableStateFlow(emptyList()) - fun setSubmitDevInfo(submitProjectInfo: SubmitProjectInfo) { - _submitDevInfo.value = submitProjectInfo - } - - fun setProjectName(projectName: String) { - _projectName.value = projectName - } + private val _searchDeveloperResultList = MutableStateFlow(emptyList()) + val searchDeveloperResultList = _searchDeveloperResultList.asStateFlow() fun updateProjectInfo( projectName: String, @@ -98,6 +86,14 @@ class SubmitProjectViewModel } fun updateDeveloperList(projectDeveloperList: List) { - _projectDeveloperList.value = projectDeveloperList + _addProjectDeveloperList.value = projectDeveloperList + } + + fun searchDeveloperList(searchKeyword: String) { + viewModelScope.launch { + developersRepository.searchDevelopers(searchKeyword).onSuccess { + _searchDeveloperResultList.value = it + } + } } } diff --git a/feature/projects/src/main/res/layout/activity_submit_project.xml b/feature/projects/src/main/res/layout/activity_submit_project.xml index e3aca81..9c38d22 100644 --- a/feature/projects/src/main/res/layout/activity_submit_project.xml +++ b/feature/projects/src/main/res/layout/activity_submit_project.xml @@ -389,7 +389,7 @@ android:background="@drawable/submit_button_background" android:fontFamily="@font/pretendardbold" android:gravity="center" - android:text="등록하기" + android:text="@string/submit_project_add_dev" android:textAlignment="center" android:textColor="@color/white" android:textSize="15sp" diff --git a/feature/projects/src/main/res/layout/activity_submit_project_find_dev.xml b/feature/projects/src/main/res/layout/activity_submit_project_find_dev.xml index 465829e..429a805 100644 --- a/feature/projects/src/main/res/layout/activity_submit_project_find_dev.xml +++ b/feature/projects/src/main/res/layout/activity_submit_project_find_dev.xml @@ -113,9 +113,27 @@ android:layout_marginTop="20dp" android:layout_marginEnd="15dp" android:layout_marginBottom="10dp" - app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintBottom_toTopOf="@+id/btn_submit" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/tv_find_dev_description" tools:listitem="@layout/item_find_dev" /> + + \ No newline at end of file diff --git a/feature/projects/src/main/res/values/strings.xml b/feature/projects/src/main/res/values/strings.xml index dde6cb5..3d65b0f 100644 --- a/feature/projects/src/main/res/values/strings.xml +++ b/feature/projects/src/main/res/values/strings.xml @@ -103,5 +103,6 @@ 프로젝트에서 사용한 기술 스택을 선택해주세요.\n(최대 3개) 사용 협업툴 프로젝트에서 사용한 협업툴을 선택해주세요.\n(최대 3개) + 함께한 개발자 추가하러 가기 \ No newline at end of file From f10b4d47dd32c8ae0c5eb0d9189975003e4747ac Mon Sep 17 00:00:00 2001 From: kangyuri1114 Date: Tue, 16 Jul 2024 00:28:07 +0900 Subject: [PATCH 17/31] =?UTF-8?q?[feat]:=20=EA=B0=9C=EB=B0=9C=EC=9E=90=20?= =?UTF-8?q?=EC=B0=BE=EA=B8=B0=20item=20ui=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- feature/projects/src/main/res/layout/item_find_dev.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/feature/projects/src/main/res/layout/item_find_dev.xml b/feature/projects/src/main/res/layout/item_find_dev.xml index 1c95da8..3257164 100644 --- a/feature/projects/src/main/res/layout/item_find_dev.xml +++ b/feature/projects/src/main/res/layout/item_find_dev.xml @@ -17,7 +17,7 @@ Date: Tue, 16 Jul 2024 02:20:08 +0900 Subject: [PATCH 18/31] =?UTF-8?q?[feat]:=20=EA=B0=9C=EB=B0=9C=EC=9E=90=20?= =?UTF-8?q?=EC=B0=BE=EA=B8=B0=20=EC=96=B4=EB=8C=91=ED=84=B0=EC=97=90=20?= =?UTF-8?q?=EB=B7=B0=EB=AA=A8=EB=8D=B8=20=EC=A0=84=EB=8B=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../project/SubmitProjectFindDevActivity.kt | 9 +++++++- .../submit/project/SubmitProjectViewModel.kt | 22 ++++++++++++++----- .../submit/project/adapter/FindDevAdapter.kt | 10 ++++----- 3 files changed, 29 insertions(+), 12 deletions(-) diff --git a/feature/projects/src/main/java/com/zucchini/submit/project/SubmitProjectFindDevActivity.kt b/feature/projects/src/main/java/com/zucchini/submit/project/SubmitProjectFindDevActivity.kt index 3a2c285..5db649a 100644 --- a/feature/projects/src/main/java/com/zucchini/submit/project/SubmitProjectFindDevActivity.kt +++ b/feature/projects/src/main/java/com/zucchini/submit/project/SubmitProjectFindDevActivity.kt @@ -27,10 +27,11 @@ class SubmitProjectFindDevActivity : AppCompatActivity() { initDevInfoAdapter() initBackButton() clickSearchKeyword() + clickSubmitButton() } private fun initDevInfoAdapter() { - devAdapter = FindDevAdapter(viewModel.submitDevInfo.value ?: SubmitProjectInfo()) + devAdapter = FindDevAdapter(viewModel) binding.rvFindDev.adapter = devAdapter binding.rvFindDev.layoutManager = GridLayoutManager(this, 2) } @@ -50,4 +51,10 @@ class SubmitProjectFindDevActivity : AppCompatActivity() { finish() } } + + private fun clickSubmitButton() { + binding.btnSubmit.setOnClickListener { + viewModel.submitProject() + } + } } diff --git a/feature/projects/src/main/java/com/zucchini/submit/project/SubmitProjectViewModel.kt b/feature/projects/src/main/java/com/zucchini/submit/project/SubmitProjectViewModel.kt index f81b43c..4fabd38 100644 --- a/feature/projects/src/main/java/com/zucchini/submit/project/SubmitProjectViewModel.kt +++ b/feature/projects/src/main/java/com/zucchini/submit/project/SubmitProjectViewModel.kt @@ -1,9 +1,9 @@ package com.zucchini.submit.project +import android.util.Log import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.zucchini.domain.model.FindDeveloperInfo -import com.zucchini.domain.model.SubmitProjectInfo import com.zucchini.domain.repository.DevelopersRepository import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow @@ -17,9 +17,6 @@ class SubmitProjectViewModel constructor( private val developersRepository: DevelopersRepository, ) : ViewModel() { - private val _submitDevInfo = MutableStateFlow(null) - val submitDevInfo = _submitDevInfo.asStateFlow() - private val _projectName = MutableStateFlow("") private val _projectGithub = MutableStateFlow("") @@ -85,8 +82,12 @@ class SubmitProjectViewModel _projectCooperationList.value = projectCooperationList } - fun updateDeveloperList(projectDeveloperList: List) { - _addProjectDeveloperList.value = projectDeveloperList + fun addDeveloperToProject(developerId: Int) { + _addProjectDeveloperList.value += developerId + } + + fun removeDeveloperFromProject(developerId: Int) { + _addProjectDeveloperList.value -= developerId } fun searchDeveloperList(searchKeyword: String) { @@ -96,4 +97,13 @@ class SubmitProjectViewModel } } } + + fun submitProject() { + viewModelScope.launch { + + } + } + + fun submitProjectWithDevelopers() { + } } diff --git a/feature/projects/src/main/java/com/zucchini/submit/project/adapter/FindDevAdapter.kt b/feature/projects/src/main/java/com/zucchini/submit/project/adapter/FindDevAdapter.kt index 25ce2e3..9cae3dd 100644 --- a/feature/projects/src/main/java/com/zucchini/submit/project/adapter/FindDevAdapter.kt +++ b/feature/projects/src/main/java/com/zucchini/submit/project/adapter/FindDevAdapter.kt @@ -1,5 +1,6 @@ package com.zucchini.submit.project.adapter +import android.util.Log import android.view.LayoutInflater import android.view.ViewGroup import androidx.recyclerview.widget.ListAdapter @@ -7,10 +8,11 @@ import androidx.recyclerview.widget.RecyclerView import com.zucchini.domain.model.FindDeveloperInfo import com.zucchini.domain.model.SubmitProjectInfo import com.zucchini.feature.projects.databinding.ItemFindDevBinding +import com.zucchini.submit.project.SubmitProjectViewModel import com.zucchini.view.ItemDiffCallback class FindDevAdapter( - private val submitProjectInfo: SubmitProjectInfo + private val viewModel: SubmitProjectViewModel ) : ListAdapter( ItemDiffCallback( onItemsTheSame = { old, new -> old == new }, @@ -41,14 +43,12 @@ class FindDevAdapter( tvDeveloperName.text = findDevInfo.developerName tvDeveloperEmail.text = findDevInfo.developerEmail - cbFindDev.isChecked = submitProjectInfo.projectDeveloperList.contains(findDevInfo.developerId) - root.setOnClickListener { cbFindDev.isChecked = !cbFindDev.isChecked if (cbFindDev.isChecked) { - submitProjectInfo.projectDeveloperList += findDevInfo.developerId + viewModel.addDeveloperToProject(findDevInfo.developerId) } else { - submitProjectInfo.projectDeveloperList -= findDevInfo.developerId + viewModel.removeDeveloperFromProject(findDevInfo.developerId) } } } From 3822a6dfeca6d8779a41f32f0df52225867de4ae Mon Sep 17 00:00:00 2001 From: kangyuri1114 Date: Tue, 16 Jul 2024 03:52:12 +0900 Subject: [PATCH 19/31] =?UTF-8?q?[feat]:=20=ED=94=84=EB=A1=9C=EC=A0=9D?= =?UTF-8?q?=ED=8A=B8=20=EB=93=B1=EB=A1=9D=20=EC=9C=A0=EC=A0=80=20=EC=9E=85?= =?UTF-8?q?=EB=A0=A5=EA=B0=92=20=EC=A0=80=EC=9E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../di/DefaultNavigationProvider.kt | 3 - .../com/zucchini/common/NavigationProvider.kt | 1 - .../main/java/com/zucchini/view/ViewExt.kt | 3 + feature/projects/src/main/AndroidManifest.xml | 5 - .../submit/project/SubmitProjectActivity.kt | 176 +------- .../project/SubmitProjectFindDevActivity.kt | 60 --- .../submit/project/SubmitProjectViewModel.kt | 5 +- .../adapter/SubmitProjectPagerAdapter.kt | 23 + .../project/fragment/SubmitProjectFragment.kt | 187 ++++++++ .../fragment/SubmitProjectWithDevFragment.kt | 70 +++ .../res/layout/activity_submit_project.xml | 413 ++---------------- .../res/layout/fragment_submit_project.xml | 367 ++++++++++++++++ ...l => fragment_submit_project_with_dev.xml} | 48 +- .../projects/src/main/res/values/strings.xml | 1 + 14 files changed, 708 insertions(+), 654 deletions(-) delete mode 100644 feature/projects/src/main/java/com/zucchini/submit/project/SubmitProjectFindDevActivity.kt create mode 100644 feature/projects/src/main/java/com/zucchini/submit/project/adapter/SubmitProjectPagerAdapter.kt create mode 100644 feature/projects/src/main/java/com/zucchini/submit/project/fragment/SubmitProjectFragment.kt create mode 100644 feature/projects/src/main/java/com/zucchini/submit/project/fragment/SubmitProjectWithDevFragment.kt create mode 100644 feature/projects/src/main/res/layout/fragment_submit_project.xml rename feature/projects/src/main/res/layout/{activity_submit_project_find_dev.xml => fragment_submit_project_with_dev.xml} (69%) diff --git a/app/src/main/java/com/zucchini/ssuplector/di/DefaultNavigationProvider.kt b/app/src/main/java/com/zucchini/ssuplector/di/DefaultNavigationProvider.kt index 486ce38..e598b16 100644 --- a/app/src/main/java/com/zucchini/ssuplector/di/DefaultNavigationProvider.kt +++ b/app/src/main/java/com/zucchini/ssuplector/di/DefaultNavigationProvider.kt @@ -6,7 +6,6 @@ import com.zucchini.auth.LoginActivity import com.zucchini.common.NavigationProvider import com.zucchini.projects.MainActivity import com.zucchini.submit.developer.SubmitDevActivity -import com.zucchini.submit.project.SubmitProjectFindDevActivity import dagger.hilt.android.qualifiers.ApplicationContext import javax.inject.Inject @@ -31,7 +30,5 @@ class DefaultNavigationProvider override fun toSubmitDev(): Intent = Intent(context, SubmitDevActivity::class.java) - override fun toFindDev(): Intent = Intent(context, SubmitProjectFindDevActivity::class.java) - override fun toMain(): Intent = Intent(context, MainActivity::class.java) } diff --git a/core/common/src/main/java/com/zucchini/common/NavigationProvider.kt b/core/common/src/main/java/com/zucchini/common/NavigationProvider.kt index 70537e9..8964efe 100644 --- a/core/common/src/main/java/com/zucchini/common/NavigationProvider.kt +++ b/core/common/src/main/java/com/zucchini/common/NavigationProvider.kt @@ -9,6 +9,5 @@ interface NavigationProvider { fun toLogin(): Intent fun toSubmitDev(): Intent - fun toFindDev(): Intent fun toMain(): Intent } diff --git a/core/common/src/main/java/com/zucchini/view/ViewExt.kt b/core/common/src/main/java/com/zucchini/view/ViewExt.kt index 1ed3846..d7ee876 100644 --- a/core/common/src/main/java/com/zucchini/view/ViewExt.kt +++ b/core/common/src/main/java/com/zucchini/view/ViewExt.kt @@ -50,6 +50,9 @@ fun Context.showShortToast(message: String) { ).show() } +fun Fragment.showShortToast(message: String) { + context?.showShortToast(message) +} fun Fragment.hideKeyboard() { view?.let { activity?.hideKeyboard(it) } } diff --git a/feature/projects/src/main/AndroidManifest.xml b/feature/projects/src/main/AndroidManifest.xml index 12df42f..675ba51 100644 --- a/feature/projects/src/main/AndroidManifest.xml +++ b/feature/projects/src/main/AndroidManifest.xml @@ -2,11 +2,6 @@ - - imageUri = uri - if (imageUri != null) { - binding.ivProjectSubmit.load(imageUri) - processSelectedImage(imageUri!!) - } else { - showShortToast(getString(R.string.submit_image)) - } - } - - @Inject - lateinit var navigationProvider: NavigationProvider - override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivitySubmitProjectBinding.inflate(layoutInflater) setContentView(binding.root) - backClickListner() - initImageSubmitView() - initDialogClickListener() - clickSubmitButton() + initViews() + initListeners() } - private fun initDialogClickListener() { - selectProjectCategory() - selectStack() + private fun initViews() { + binding.vpSubmitProject.adapter = SubmitProjectPagerAdapter(this) + binding.vpSubmitProject.isUserInputEnabled = false } - private fun backClickListner() { + private fun initListeners() { binding.ivBackButton.setOnClickListener { - finish() - } - } - - private fun initImageSubmitView() { - binding.tvProjectSubmitImage.setOnClickListener { - launcher.launch("image/*") - } - } - - private fun selectProjectCategory() { - // īװ Ű Ʈ ѱ۰ Ű带 ϴ Map غ - val keywordMap = KeywordList.categoryList.associateBy { it.keywordKorean } - - binding.tvSubmitProjectCategory.setOnClickListener { - SelectCheckBoxCommonDialog - .newInstance( - title = "Ʈ īװ", - description = "Ʈ īװ ּ. (ִ 2)", - confirmButtonText = getString(R.string.all_check), - items = keywordMap.keys.toList() as ArrayList, // ѱ Ʈ - maxSelectionCount = 2, - ).apply { - setConfirmButtonClickListener { selectedItems -> - // ѱ Ű带 Ű ȯ - val selectedEnglishItems = - selectedItems.mapNotNull { keywordKorean -> - keywordMap[keywordKorean]?.keywordEnglish - } - - viewModel.updateProjectCategory(projectCategoryList = selectedEnglishItems) - } - }.showAllowingStateLoss(supportFragmentManager, "SelectCheckBoxCommonDialog") + handleBackNavigation() } } - private fun selectStack() { - val languageMap = KeywordList.languageList.associateBy { it.keywordKorean } - val techStackMap = KeywordList.techStackList.associateBy { it.keywordKorean } - val cooperationToolMap = KeywordList.cooperationList.associateBy { it.keywordKorean } - - binding.tvDevStackLanguage.setOnClickListener { - SelectCheckBoxCommonDialog - .newInstance( - title = getString(R.string.dialog_language_title), - description = getString(R.string.dialog_language_description), - confirmButtonText = getString(R.string.all_check), - items = languageMap.keys.toList() as ArrayList, - maxSelectionCount = 3, - ).apply { - setConfirmButtonClickListener { selectedItems -> - // ѱ Ű带 Ű ȯ - val selectedEnglishItems = - selectedItems.mapNotNull { keywordKorean -> - languageMap[keywordKorean]?.keywordEnglish - } - - viewModel.updateProjectLanguage(projectLanguageList = selectedEnglishItems) - } - }.showAllowingStateLoss(supportFragmentManager, "SelectCheckBoxCommonDialog") - } - binding.tvDevStackDevStack.setOnClickListener { - SelectCheckBoxCommonDialog - .newInstance( - title = getString(R.string.dialog_techstack_title), - description = getString(R.string.dialog_techstack_description), - confirmButtonText = getString(R.string.all_check), - items = techStackMap.keys.toList() as ArrayList, - maxSelectionCount = 3, - ).apply { - setConfirmButtonClickListener { selectedItems -> - // ѱ Ű带 Ű ȯ - val selectedEnglishItems = - selectedItems.mapNotNull { keywordKorean -> - techStackMap[keywordKorean]?.keywordEnglish - } - - viewModel.updateProjectTechStack(projectTechStackList = selectedEnglishItems) - } - }.showAllowingStateLoss(supportFragmentManager, "SelectCheckBoxCommonDialog") - } - binding.tvDevStackCooperation.setOnClickListener { - SelectCheckBoxCommonDialog - .newInstance( - title = getString(R.string.dialog_cooperation_title), - description = getString(R.string.dialog_cooperation_description), - confirmButtonText = getString(R.string.all_check), - items = cooperationToolMap.keys.toList() as ArrayList, - maxSelectionCount = 3, - ).apply { - setConfirmButtonClickListener { selectedItems -> - // ѱ Ű带 Ű ȯ - val selectedEnglishItems = - selectedItems.mapNotNull { keywordKorean -> - cooperationToolMap[keywordKorean]?.keywordEnglish - } - - viewModel.updateProjectCooperation(projectCooperationList = selectedEnglishItems) - } - }.showAllowingStateLoss(supportFragmentManager, "SelectCheckBoxCommonDialog") + private fun handleBackNavigation() { + if (binding.vpSubmitProject.currentItem > 0) { + binding.vpSubmitProject.currentItem -= 1 + } else { + finish() } } - private fun processSelectedImage(uri: Uri) { - val requestBody = - ContentUriRequestBody( - context = this, - uri = uri, - ).toFormData() - - Timber.d("Image Uri: $uri") - Timber.d("Image Path: ${uri.path}") - Timber.d("Request Body: $requestBody") - } - - private fun clickSubmitButton() { - binding.btnSubmit.setOnSingleClickListener { - viewModel.updateProjectInfo( - projectName = binding.etProjectName.text.toString(), - imagePath = imageUri.toString(), - projectGithub = binding.etGithub.text.toString(), - projectShortIntro = binding.etProjectIntroContentShort.text.toString(), - projectLongIntro = binding.etProjectIntroContentLong.text.toString(), - projectWebLink = binding.etProjectWebLink.text.toString(), - projectAppLink = binding.etProjectAppLink.text.toString(), - projectLink = binding.etProjectInfoLink.text.toString(), - ) - startActivity(navigationProvider.toFindDev()) - } + fun setCurrentItem(item: Int) { + binding.vpSubmitProject.setCurrentItem(item, true) } } diff --git a/feature/projects/src/main/java/com/zucchini/submit/project/SubmitProjectFindDevActivity.kt b/feature/projects/src/main/java/com/zucchini/submit/project/SubmitProjectFindDevActivity.kt deleted file mode 100644 index 5db649a..0000000 --- a/feature/projects/src/main/java/com/zucchini/submit/project/SubmitProjectFindDevActivity.kt +++ /dev/null @@ -1,60 +0,0 @@ -package com.zucchini.submit.project - -import android.os.Bundle -import androidx.activity.viewModels -import androidx.appcompat.app.AppCompatActivity -import androidx.lifecycle.flowWithLifecycle -import androidx.lifecycle.lifecycleScope -import androidx.recyclerview.widget.GridLayoutManager -import com.zucchini.domain.model.SubmitProjectInfo -import com.zucchini.feature.projects.databinding.ActivitySubmitProjectFindDevBinding -import com.zucchini.submit.project.adapter.FindDevAdapter -import dagger.hilt.android.AndroidEntryPoint -import kotlinx.coroutines.flow.launchIn -import kotlinx.coroutines.flow.onEach - -@AndroidEntryPoint -class SubmitProjectFindDevActivity : AppCompatActivity() { - private lateinit var binding: ActivitySubmitProjectFindDevBinding - private val viewModel: SubmitProjectViewModel by viewModels() - private lateinit var devAdapter: FindDevAdapter - - override fun onCreate(savedInstanceState: Bundle?) { - binding = ActivitySubmitProjectFindDevBinding.inflate(layoutInflater) - super.onCreate(savedInstanceState) - setContentView(binding.root) - - initDevInfoAdapter() - initBackButton() - clickSearchKeyword() - clickSubmitButton() - } - - private fun initDevInfoAdapter() { - devAdapter = FindDevAdapter(viewModel) - binding.rvFindDev.adapter = devAdapter - binding.rvFindDev.layoutManager = GridLayoutManager(this, 2) - } - - private fun clickSearchKeyword() { - binding.ivSearch.setOnClickListener { - viewModel.searchDeveloperList(binding.etSearchbar.text.toString()) - } - - viewModel.searchDeveloperResultList.flowWithLifecycle(lifecycle).onEach { developerList -> - devAdapter.submitList(developerList) - }.launchIn(lifecycleScope) - } - - private fun initBackButton() { - binding.ivBackButton.setOnClickListener { - finish() - } - } - - private fun clickSubmitButton() { - binding.btnSubmit.setOnClickListener { - viewModel.submitProject() - } - } -} diff --git a/feature/projects/src/main/java/com/zucchini/submit/project/SubmitProjectViewModel.kt b/feature/projects/src/main/java/com/zucchini/submit/project/SubmitProjectViewModel.kt index 4fabd38..0609be7 100644 --- a/feature/projects/src/main/java/com/zucchini/submit/project/SubmitProjectViewModel.kt +++ b/feature/projects/src/main/java/com/zucchini/submit/project/SubmitProjectViewModel.kt @@ -46,6 +46,9 @@ class SubmitProjectViewModel private val _searchDeveloperResultList = MutableStateFlow(emptyList()) val searchDeveloperResultList = _searchDeveloperResultList.asStateFlow() + private val _isSuccessSubmitProject = MutableStateFlow(false) + val isSuccessSubmitProject = _isSuccessSubmitProject.asStateFlow() + fun updateProjectInfo( projectName: String, projectGithub: String, @@ -100,7 +103,7 @@ class SubmitProjectViewModel fun submitProject() { viewModelScope.launch { - + Log.d( "SubmitProjectViewModel", "${_projectName.value}, ${_projectGithub.value}, ${_imagePath.value}, ${_projectShortIntro.value}, ${_projectLongIntro.value}, ${_projectWebLink.value}, ${_projectAppLink.value}, ${_projectLink.value}, ${_projectCategoryList.value}, ${_projectTechStackList.value}, ${_projectLanguageList.value}, ${_projectCooperationList.value}, ${_addProjectDeveloperList.value}") } } diff --git a/feature/projects/src/main/java/com/zucchini/submit/project/adapter/SubmitProjectPagerAdapter.kt b/feature/projects/src/main/java/com/zucchini/submit/project/adapter/SubmitProjectPagerAdapter.kt new file mode 100644 index 0000000..23bf387 --- /dev/null +++ b/feature/projects/src/main/java/com/zucchini/submit/project/adapter/SubmitProjectPagerAdapter.kt @@ -0,0 +1,23 @@ +package com.zucchini.submit.project.adapter + +import androidx.appcompat.app.AppCompatActivity +import androidx.fragment.app.Fragment +import androidx.viewpager2.adapter.FragmentStateAdapter +import com.zucchini.submit.project.fragment.SubmitProjectFragment +import com.zucchini.submit.project.fragment.SubmitProjectWithDevFragment + +class SubmitProjectPagerAdapter( + activity: AppCompatActivity, +) : FragmentStateAdapter(activity) { + override fun getItemCount(): Int { + return 2 + } + + override fun createFragment(position: Int): Fragment { + return when (position) { + 0 -> SubmitProjectFragment() + 1 -> SubmitProjectWithDevFragment() + else -> throw IllegalStateException("Invalid position: $position") + } + } +} diff --git a/feature/projects/src/main/java/com/zucchini/submit/project/fragment/SubmitProjectFragment.kt b/feature/projects/src/main/java/com/zucchini/submit/project/fragment/SubmitProjectFragment.kt new file mode 100644 index 0000000..bb2021d --- /dev/null +++ b/feature/projects/src/main/java/com/zucchini/submit/project/fragment/SubmitProjectFragment.kt @@ -0,0 +1,187 @@ +package com.zucchini.submit.project.fragment + +import android.net.Uri +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.activity.result.contract.ActivityResultContracts +import androidx.fragment.app.Fragment +import androidx.fragment.app.activityViewModels +import coil.load +import com.zucchini.data.ContentUriRequestBody +import com.zucchini.dialog.SelectCheckBoxCommonDialog +import com.zucchini.domain.model.KeywordList +import com.zucchini.feature.projects.R +import com.zucchini.feature.projects.databinding.FragmentSubmitProjectBinding +import com.zucchini.submit.project.SubmitProjectActivity +import com.zucchini.submit.project.SubmitProjectViewModel +import com.zucchini.view.showShortToast +import timber.log.Timber + +class SubmitProjectFragment : Fragment() { + private var _binding: FragmentSubmitProjectBinding? = null + private val binding: FragmentSubmitProjectBinding get() = _binding!! + + private val viewModel: SubmitProjectViewModel by activityViewModels() + + private var imageUri = Uri.EMPTY + + private val launcher = + registerForActivityResult(ActivityResultContracts.GetContent()) { uri: Uri? -> + imageUri = uri + if (imageUri != null) { + binding.ivProjectSubmit.load(imageUri) + processSelectedImage(imageUri!!) + } else { + showShortToast(getString(R.string.submit_image)) + } + } + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle?, + ): View { + _binding = FragmentSubmitProjectBinding.inflate(inflater, container, false) + + initImageSubmitView() + initDialogClickListener() + clickSubmitButton() + + return binding.root + } + + private fun initDialogClickListener() { + selectProjectCategory() + selectStack() + } + + private fun initImageSubmitView() { + binding.tvProjectSubmitImage.setOnClickListener { + launcher.launch("image/*") + } + } + + private fun selectProjectCategory() { + // 카테고리 키워드 리스트를 한글과 영어 키워드를 매핑하는 Map으로 준비 + val keywordMap = KeywordList.categoryList.associateBy { it.keywordKorean } + + binding.tvSubmitProjectCategory.setOnClickListener { + SelectCheckBoxCommonDialog + .newInstance( + title = "프로젝트 카테고리", + description = "프로젝트 카테고리를 선택해주세요. (최대 2개)", + confirmButtonText = getString(R.string.all_check), + items = keywordMap.keys.toList() as ArrayList, // 한글 리스트 전달 + maxSelectionCount = 2, + ).apply { + setConfirmButtonClickListener { selectedItems -> + // 선택한 한글 키워드를 영어 키워드로 변환 + val selectedEnglishItems = + selectedItems.mapNotNull { keywordKorean -> + keywordMap[keywordKorean]?.keywordEnglish + } + + viewModel.updateProjectCategory(projectCategoryList = selectedEnglishItems) + } + }.showAllowingStateLoss(parentFragmentManager, "SelectCheckBoxCommonDialog") + } + } + + private fun selectStack() { + val languageMap = KeywordList.languageList.associateBy { it.keywordKorean } + val techStackMap = KeywordList.techStackList.associateBy { it.keywordKorean } + val cooperationToolMap = KeywordList.cooperationList.associateBy { it.keywordKorean } + + binding.tvDevStackLanguage.setOnClickListener { + SelectCheckBoxCommonDialog + .newInstance( + title = getString(R.string.dialog_language_title), + description = getString(R.string.dialog_language_description), + confirmButtonText = getString(R.string.all_check), + items = languageMap.keys.toList() as ArrayList, + maxSelectionCount = 3, + ).apply { + setConfirmButtonClickListener { selectedItems -> + // 선택한 한글 키워드를 영어 키워드로 변환 + val selectedEnglishItems = + selectedItems.mapNotNull { keywordKorean -> + languageMap[keywordKorean]?.keywordEnglish + } + + viewModel.updateProjectLanguage(projectLanguageList = selectedEnglishItems) + } + }.showAllowingStateLoss(parentFragmentManager, "SelectCheckBoxCommonDialog") + } + binding.tvDevStackDevStack.setOnClickListener { + SelectCheckBoxCommonDialog + .newInstance( + title = getString(R.string.dialog_techstack_title), + description = getString(R.string.dialog_techstack_description), + confirmButtonText = getString(R.string.all_check), + items = techStackMap.keys.toList() as ArrayList, + maxSelectionCount = 3, + ).apply { + setConfirmButtonClickListener { selectedItems -> + // 선택한 한글 키워드를 영어 키워드로 변환 + val selectedEnglishItems = + selectedItems.mapNotNull { keywordKorean -> + techStackMap[keywordKorean]?.keywordEnglish + } + + viewModel.updateProjectTechStack(projectTechStackList = selectedEnglishItems) + } + }.showAllowingStateLoss(parentFragmentManager, "SelectCheckBoxCommonDialog") + } + binding.tvDevStackCooperation.setOnClickListener { + SelectCheckBoxCommonDialog + .newInstance( + title = getString(R.string.dialog_cooperation_title), + description = getString(R.string.dialog_cooperation_description), + confirmButtonText = getString(R.string.all_check), + items = cooperationToolMap.keys.toList() as ArrayList, + maxSelectionCount = 3, + ).apply { + setConfirmButtonClickListener { selectedItems -> + // 선택한 한글 키워드를 영어 키워드로 변환 + val selectedEnglishItems = + selectedItems.mapNotNull { keywordKorean -> + cooperationToolMap[keywordKorean]?.keywordEnglish + } + + viewModel.updateProjectCooperation(projectCooperationList = selectedEnglishItems) + } + }.showAllowingStateLoss(parentFragmentManager, "SelectCheckBoxCommonDialog") + } + } + + private fun processSelectedImage(uri: Uri) { + val requestBody = + ContentUriRequestBody( + context = requireContext(), + uri = uri, + ).toFormData() + + Timber.d("Image Uri: $uri") + Timber.d("Image Path: ${uri.path}") + Timber.d("Request Body: $requestBody") + } + + private fun clickSubmitButton() { + binding.btnNext.setOnClickListener { + viewModel.updateProjectInfo( + projectName = binding.etProjectName.text.toString(), + imagePath = imageUri.toString(), + projectGithub = binding.etGithub.text.toString(), + projectShortIntro = binding.etProjectIntroContentShort.text.toString(), + projectLongIntro = binding.etProjectIntroContentLong.text.toString(), + projectWebLink = binding.etProjectWebLink.text.toString(), + projectAppLink = binding.etProjectAppLink.text.toString(), + projectLink = binding.etProjectInfoLink.text.toString(), + ) + (activity as? SubmitProjectActivity)?.setCurrentItem(1) + } + } + +} diff --git a/feature/projects/src/main/java/com/zucchini/submit/project/fragment/SubmitProjectWithDevFragment.kt b/feature/projects/src/main/java/com/zucchini/submit/project/fragment/SubmitProjectWithDevFragment.kt new file mode 100644 index 0000000..acbff4d --- /dev/null +++ b/feature/projects/src/main/java/com/zucchini/submit/project/fragment/SubmitProjectWithDevFragment.kt @@ -0,0 +1,70 @@ +package com.zucchini.submit.project.fragment + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment +import androidx.fragment.app.activityViewModels +import androidx.lifecycle.flowWithLifecycle +import androidx.lifecycle.lifecycleScope +import androidx.recyclerview.widget.GridLayoutManager +import com.zucchini.common.NavigationProvider +import com.zucchini.feature.projects.databinding.FragmentSubmitProjectWithDevBinding +import com.zucchini.submit.project.SubmitProjectViewModel +import com.zucchini.submit.project.adapter.FindDevAdapter +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach +import javax.inject.Inject + +class SubmitProjectWithDevFragment : Fragment() { + private var _binding: FragmentSubmitProjectWithDevBinding? = null + private val binding: FragmentSubmitProjectWithDevBinding get() = _binding!! + + private val viewModel: SubmitProjectViewModel by activityViewModels() + private lateinit var devAdapter: FindDevAdapter + + @Inject + lateinit var navigationProvider: NavigationProvider + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle?, + ): View { + _binding = FragmentSubmitProjectWithDevBinding.inflate(inflater, container, false) + + initDevInfoAdapter() + clickSearchKeyword() + clickSubmitButton() + + return binding.root + } + + private fun initDevInfoAdapter() { + devAdapter = FindDevAdapter(viewModel) + binding.rvFindDev.adapter = devAdapter + binding.rvFindDev.layoutManager = GridLayoutManager(requireContext(), 2) + } + + private fun clickSearchKeyword() { + binding.ivSearch.setOnClickListener { + viewModel.searchDeveloperList(binding.etSearchbar.text.toString()) + } + + viewModel.searchDeveloperResultList.flowWithLifecycle(lifecycle).onEach { developerList -> + devAdapter.submitList(developerList) + }.launchIn(lifecycleScope) + } + + private fun clickSubmitButton() { + binding.btnNext.setOnClickListener { + viewModel.submitProject() + viewModel.isSuccessSubmitProject.flowWithLifecycle(lifecycle).onEach { isSuccess -> + if (isSuccess) { + startActivity(navigationProvider.toMain()) + } + }.launchIn(lifecycleScope) + } + } +} diff --git a/feature/projects/src/main/res/layout/activity_submit_project.xml b/feature/projects/src/main/res/layout/activity_submit_project.xml index 9c38d22..8bb4b88 100644 --- a/feature/projects/src/main/res/layout/activity_submit_project.xml +++ b/feature/projects/src/main/res/layout/activity_submit_project.xml @@ -1,402 +1,51 @@ - + android:layout_height="match_parent"> - - - - - - - - + android:layout_height="wrap_content" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + app:layout_constraintTop_toTopOf="parent" /> - - - - - - - - - - - - - - - + app:layout_constraintTop_toTopOf="parent" /> - \ No newline at end of file + + + + diff --git a/feature/projects/src/main/res/layout/fragment_submit_project.xml b/feature/projects/src/main/res/layout/fragment_submit_project.xml new file mode 100644 index 0000000..a4108b1 --- /dev/null +++ b/feature/projects/src/main/res/layout/fragment_submit_project.xml @@ -0,0 +1,367 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/feature/projects/src/main/res/layout/activity_submit_project_find_dev.xml b/feature/projects/src/main/res/layout/fragment_submit_project_with_dev.xml similarity index 69% rename from feature/projects/src/main/res/layout/activity_submit_project_find_dev.xml rename to feature/projects/src/main/res/layout/fragment_submit_project_with_dev.xml index 429a805..913b0df 100644 --- a/feature/projects/src/main/res/layout/activity_submit_project_find_dev.xml +++ b/feature/projects/src/main/res/layout/fragment_submit_project_with_dev.xml @@ -4,42 +4,7 @@ xmlns:tools="http://schemas.android.com/tools" android:id="@+id/main" android:layout_width="match_parent" - android:layout_height="match_parent" - tools:context="com.zucchini.submit.project.SubmitProjectFindDevActivity"> - - - - - - - + android:layout_height="match_parent"> + app:layout_constraintTop_toTopOf="parent" /> + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@+id/rv_find_dev" /> \ No newline at end of file diff --git a/feature/projects/src/main/res/values/strings.xml b/feature/projects/src/main/res/values/strings.xml index 3d65b0f..92bc1aa 100644 --- a/feature/projects/src/main/res/values/strings.xml +++ b/feature/projects/src/main/res/values/strings.xml @@ -104,5 +104,6 @@ 사용 협업툴 프로젝트에서 사용한 협업툴을 선택해주세요.\n(최대 3개) 함께한 개발자 추가하러 가기 + 다음 \ No newline at end of file From 1d8919850101b7fe81bdc788cb5c07b0d3eadb69 Mon Sep 17 00:00:00 2001 From: kangyuri1114 Date: Tue, 16 Jul 2024 04:58:01 +0900 Subject: [PATCH 20/31] =?UTF-8?q?[feat]:=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20?= =?UTF-8?q?=EC=97=85=EB=A1=9C=EB=93=9C=20=EC=A0=9C=EC=99=B8,=20=ED=94=84?= =?UTF-8?q?=EB=A1=9C=EC=A0=9D=ED=8A=B8=20=EB=93=B1=EB=A1=9D=20api=20?= =?UTF-8?q?=EB=B6=99=EC=9D=B4=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../network/request/SubmitProjectRequest.kt | 33 +++++++++++ .../sample/network/service/ProjectsService.kt | 10 ++++ .../zucchini/data/ProjectsRepositoryImpl.kt | 57 ++++++++++++------- .../com/zucchini/mapper/SubmitProjectInfo.kt | 23 ++++++++ .../domain/model/SubmitProjectInfo.kt | 24 ++++---- .../domain/repository/ProjectsRepository.kt | 11 +++- .../submit/project/SubmitProjectViewModel.kt | 41 +++++++++---- .../project/fragment/SubmitProjectFragment.kt | 5 +- .../fragment/SubmitProjectWithDevFragment.kt | 4 ++ .../projects/src/main/res/values/strings.xml | 1 + 10 files changed, 165 insertions(+), 44 deletions(-) create mode 100644 core/network/src/main/java/com/sample/network/request/SubmitProjectRequest.kt create mode 100644 data/src/main/java/com/zucchini/mapper/SubmitProjectInfo.kt diff --git a/core/network/src/main/java/com/sample/network/request/SubmitProjectRequest.kt b/core/network/src/main/java/com/sample/network/request/SubmitProjectRequest.kt new file mode 100644 index 0000000..26a5049 --- /dev/null +++ b/core/network/src/main/java/com/sample/network/request/SubmitProjectRequest.kt @@ -0,0 +1,33 @@ +package com.sample.network.request + + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class SubmitProjectRequest( + @SerialName("appLink") + val appLink: String, + @SerialName("category") + val category: String, + @SerialName("devToolList") + val devToolList: List, + @SerialName("githubLink") + val githubLink: String, + @SerialName("infoPageLink") + val infoPageLink: String, + @SerialName("languageList") + val languageList: List, + @SerialName("longIntro") + val longIntro: String, + @SerialName("name") + val name: String, + @SerialName("shortIntro") + val shortIntro: String, + @SerialName("techStackList") + val techStackList: List, + @SerialName("webLink") + val webLink: String, + @SerialName("projectDevloperList") + val projectDeveloperList: List +) \ No newline at end of file diff --git a/core/network/src/main/java/com/sample/network/service/ProjectsService.kt b/core/network/src/main/java/com/sample/network/service/ProjectsService.kt index ad4d8c8..6a58277 100644 --- a/core/network/src/main/java/com/sample/network/service/ProjectsService.kt +++ b/core/network/src/main/java/com/sample/network/service/ProjectsService.kt @@ -3,7 +3,11 @@ package com.sample.network.service import com.sample.network.model.BaseResponse import com.sample.network.reponse.ProjectsDetailResponse import com.sample.network.reponse.ProjectsListResponse +import com.sample.network.request.SubmitProjectRequest +import okhttp3.MultipartBody +import retrofit2.http.Body import retrofit2.http.GET +import retrofit2.http.POST import retrofit2.http.Path import retrofit2.http.Query @@ -20,4 +24,10 @@ interface ProjectsService { suspend fun getProjectsDetailData( @Path("projectId") projectId: Int, ): BaseResponse + + @POST("api/projects") + suspend fun submitProject( + @Body submitProjectRequest: SubmitProjectRequest, + @Body file: MultipartBody.Part + ): BaseResponse } diff --git a/data/src/main/java/com/zucchini/data/ProjectsRepositoryImpl.kt b/data/src/main/java/com/zucchini/data/ProjectsRepositoryImpl.kt index 3f6fd26..666f535 100644 --- a/data/src/main/java/com/zucchini/data/ProjectsRepositoryImpl.kt +++ b/data/src/main/java/com/zucchini/data/ProjectsRepositoryImpl.kt @@ -3,30 +3,47 @@ package com.zucchini.data import com.sample.network.service.ProjectsService import com.zucchini.domain.model.ProjectsDetailModel import com.zucchini.domain.model.ProjectsListModel +import com.zucchini.domain.model.SubmitProjectInfo import com.zucchini.domain.repository.ProjectsRepository import com.zucchini.mapper.toProjectsDetailModel import com.zucchini.mapper.toProjectsListModel +import com.zucchini.mapper.toSubmitProjectRequest +import okhttp3.MultipartBody import javax.inject.Inject -class ProjectsRepositoryImpl @Inject constructor( - private val projectsService: ProjectsService, -) : ProjectsRepository { - override suspend fun getProjectsListData(searchString: String?, category: String?, sortType: String, page: Int): Result { - return runCatching { - projectsService.getProjectsListData( - searchString = searchString, - category = category, - sortType = sortType, - page = page, - ).data.toProjectsListModel() - } - } +class ProjectsRepositoryImpl + @Inject + constructor( + private val projectsService: ProjectsService, + ) : ProjectsRepository { + override suspend fun getProjectsListData( + searchString: String?, + category: String?, + sortType: String, + page: Int, + ): Result = + runCatching { + projectsService + .getProjectsListData( + searchString = searchString, + category = category, + sortType = sortType, + page = page, + ).data + .toProjectsListModel() + } + + override suspend fun getProjectsDetailData(projectId: Int): Result = + runCatching { + projectsService.getProjectsDetailData(projectId).data.toProjectsDetailModel() + } - override suspend fun getProjectsDetailData( - projectId: Int, - ): Result { - return runCatching { - projectsService.getProjectsDetailData(projectId).data.toProjectsDetailModel() - } + override suspend fun submitProject(submitProjectInfo: SubmitProjectInfo, imagePath: MultipartBody.Part): Result = + runCatching { + projectsService + .submitProject( + submitProjectInfo.toSubmitProjectRequest(), + imagePath + ).data + } } -} diff --git a/data/src/main/java/com/zucchini/mapper/SubmitProjectInfo.kt b/data/src/main/java/com/zucchini/mapper/SubmitProjectInfo.kt new file mode 100644 index 0000000..8a932c3 --- /dev/null +++ b/data/src/main/java/com/zucchini/mapper/SubmitProjectInfo.kt @@ -0,0 +1,23 @@ +package com.zucchini.mapper + +import com.sample.network.request.SubmitProjectRequest +import com.zucchini.domain.model.SubmitProjectInfo + + +internal fun SubmitProjectInfo.toSubmitProjectRequest(): SubmitProjectRequest { + return SubmitProjectRequest( + name = projectName, + shortIntro = projectShortIntro, + longIntro = projectLongIntro, + githubLink = projectGithub, + webLink = projectWebLink, + infoPageLink = projectLink, + appLink = projectAppLink, + category = projectCategoryList.get(0), + languageList = projectLanguageList, + devToolList = projectTechStackList, + techStackList = projectTechStackList, + projectDeveloperList = projectDeveloperList + ) +} + diff --git a/domain/src/main/java/com/zucchini/domain/model/SubmitProjectInfo.kt b/domain/src/main/java/com/zucchini/domain/model/SubmitProjectInfo.kt index eb22ebc..d75eb4c 100644 --- a/domain/src/main/java/com/zucchini/domain/model/SubmitProjectInfo.kt +++ b/domain/src/main/java/com/zucchini/domain/model/SubmitProjectInfo.kt @@ -1,17 +1,17 @@ package com.zucchini.domain.model data class SubmitProjectInfo( - val projectName: String = "", - val projectGithub: String = "", - val imagePath: String = "", - val projectShortIntro: String = "", - val projectLongIntro: String = "", - val projectCategoryList: List = emptyList(), - val projectTechStackList: List = emptyList(), - val projectLanguageList: List = emptyList(), - val projectCooperationList: List = emptyList(), - val projectWebLink: String = "", - val projectAppLink: String = "", - val projectLink: String = "", + var projectName: String = "", + var projectGithub: String = "", + var imagePath: String = "", + var projectShortIntro: String = "", + var projectLongIntro: String = "", + var projectCategoryList: List = emptyList(), + var projectTechStackList: List = emptyList(), + var projectLanguageList: List = emptyList(), + var projectCooperationList: List = emptyList(), + var projectWebLink: String = "", + var projectAppLink: String = "", + var projectLink: String = "", var projectDeveloperList: List = emptyList(), ) \ No newline at end of file diff --git a/domain/src/main/java/com/zucchini/domain/repository/ProjectsRepository.kt b/domain/src/main/java/com/zucchini/domain/repository/ProjectsRepository.kt index 4fc1a34..d7355a7 100644 --- a/domain/src/main/java/com/zucchini/domain/repository/ProjectsRepository.kt +++ b/domain/src/main/java/com/zucchini/domain/repository/ProjectsRepository.kt @@ -2,8 +2,17 @@ package com.zucchini.domain.repository import com.zucchini.domain.model.ProjectsDetailModel import com.zucchini.domain.model.ProjectsListModel +import com.zucchini.domain.model.SubmitProjectInfo interface ProjectsRepository { - suspend fun getProjectsListData(searchString: String?, category: String?, sortType: String, page: Int): Result + suspend fun getProjectsListData( + searchString: String?, + category: String?, + sortType: String, + page: Int, + ): Result + suspend fun getProjectsDetailData(projectId: Int): Result + + suspend fun submitProject(submitProjectInfo: SubmitProjectInfo): Result } diff --git a/feature/projects/src/main/java/com/zucchini/submit/project/SubmitProjectViewModel.kt b/feature/projects/src/main/java/com/zucchini/submit/project/SubmitProjectViewModel.kt index 0609be7..608ad94 100644 --- a/feature/projects/src/main/java/com/zucchini/submit/project/SubmitProjectViewModel.kt +++ b/feature/projects/src/main/java/com/zucchini/submit/project/SubmitProjectViewModel.kt @@ -4,11 +4,15 @@ import android.util.Log import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.zucchini.domain.model.FindDeveloperInfo +import com.zucchini.domain.model.SubmitProjectInfo import com.zucchini.domain.repository.DevelopersRepository +import com.zucchini.domain.repository.ProjectsRepository import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.launch +import okhttp3.MultipartBody +import timber.log.Timber import javax.inject.Inject @HiltViewModel @@ -16,13 +20,12 @@ class SubmitProjectViewModel @Inject constructor( private val developersRepository: DevelopersRepository, + private val projectsRepository: ProjectsRepository, ) : ViewModel() { private val _projectName = MutableStateFlow("") private val _projectGithub = MutableStateFlow("") - private val _imagePath = MutableStateFlow("") - private val _projectShortIntro = MutableStateFlow("") private val _projectLongIntro = MutableStateFlow("") @@ -46,13 +49,12 @@ class SubmitProjectViewModel private val _searchDeveloperResultList = MutableStateFlow(emptyList()) val searchDeveloperResultList = _searchDeveloperResultList.asStateFlow() - private val _isSuccessSubmitProject = MutableStateFlow(false) - val isSuccessSubmitProject = _isSuccessSubmitProject.asStateFlow() + private val _isSuccessSubmitProject = MutableStateFlow(false) + val isSuccessSubmitProject = _isSuccessSubmitProject.asStateFlow() fun updateProjectInfo( projectName: String, projectGithub: String, - imagePath: String, projectShortIntro: String, projectLongIntro: String, projectWebLink: String, @@ -61,7 +63,6 @@ class SubmitProjectViewModel ) { _projectName.value = projectName _projectGithub.value = projectGithub - _imagePath.value = imagePath _projectShortIntro.value = projectShortIntro _projectLongIntro.value = projectLongIntro _projectWebLink.value = projectWebLink @@ -69,6 +70,10 @@ class SubmitProjectViewModel _projectLink.value = projectLink } + fun updateImagePath(imagePath: MultipartBody.Part) { + //_imagePath.value = imagePath + } + fun updateProjectCategory(projectCategoryList: List = emptyList()) { _projectCategoryList.value = projectCategoryList } @@ -103,10 +108,26 @@ class SubmitProjectViewModel fun submitProject() { viewModelScope.launch { - Log.d( "SubmitProjectViewModel", "${_projectName.value}, ${_projectGithub.value}, ${_imagePath.value}, ${_projectShortIntro.value}, ${_projectLongIntro.value}, ${_projectWebLink.value}, ${_projectAppLink.value}, ${_projectLink.value}, ${_projectCategoryList.value}, ${_projectTechStackList.value}, ${_projectLanguageList.value}, ${_projectCooperationList.value}, ${_addProjectDeveloperList.value}") + val submit = SubmitProjectInfo() + submit.projectName = _projectName.value + submit.projectGithub = _projectGithub.value + submit.projectShortIntro = _projectShortIntro.value + submit.projectLongIntro = _projectLongIntro.value + submit.projectCategoryList = _projectCategoryList.value + submit.projectTechStackList = _projectTechStackList.value + submit.projectLanguageList = _projectLanguageList.value + submit.projectCooperationList = _projectCooperationList.value + submit.projectWebLink = _projectWebLink.value + submit.projectAppLink = _projectAppLink.value + submit.projectLink = _projectLink.value + submit.projectDeveloperList = _addProjectDeveloperList.value + + projectsRepository.submitProject(submit).onSuccess { + _isSuccessSubmitProject.value = true + }.onFailure { + _isSuccessSubmitProject.value = false + Timber.d("failed to submit project $it") + } } } - - fun submitProjectWithDevelopers() { - } } diff --git a/feature/projects/src/main/java/com/zucchini/submit/project/fragment/SubmitProjectFragment.kt b/feature/projects/src/main/java/com/zucchini/submit/project/fragment/SubmitProjectFragment.kt index bb2021d..58d8a51 100644 --- a/feature/projects/src/main/java/com/zucchini/submit/project/fragment/SubmitProjectFragment.kt +++ b/feature/projects/src/main/java/com/zucchini/submit/project/fragment/SubmitProjectFragment.kt @@ -17,7 +17,11 @@ import com.zucchini.feature.projects.databinding.FragmentSubmitProjectBinding import com.zucchini.submit.project.SubmitProjectActivity import com.zucchini.submit.project.SubmitProjectViewModel import com.zucchini.view.showShortToast +import okhttp3.MediaType.Companion.toMediaTypeOrNull +import okhttp3.MultipartBody +import okhttp3.RequestBody.Companion.asRequestBody import timber.log.Timber +import java.io.File class SubmitProjectFragment : Fragment() { private var _binding: FragmentSubmitProjectBinding? = null @@ -172,7 +176,6 @@ class SubmitProjectFragment : Fragment() { binding.btnNext.setOnClickListener { viewModel.updateProjectInfo( projectName = binding.etProjectName.text.toString(), - imagePath = imageUri.toString(), projectGithub = binding.etGithub.text.toString(), projectShortIntro = binding.etProjectIntroContentShort.text.toString(), projectLongIntro = binding.etProjectIntroContentLong.text.toString(), diff --git a/feature/projects/src/main/java/com/zucchini/submit/project/fragment/SubmitProjectWithDevFragment.kt b/feature/projects/src/main/java/com/zucchini/submit/project/fragment/SubmitProjectWithDevFragment.kt index acbff4d..86263ba 100644 --- a/feature/projects/src/main/java/com/zucchini/submit/project/fragment/SubmitProjectWithDevFragment.kt +++ b/feature/projects/src/main/java/com/zucchini/submit/project/fragment/SubmitProjectWithDevFragment.kt @@ -10,9 +10,11 @@ import androidx.lifecycle.flowWithLifecycle import androidx.lifecycle.lifecycleScope import androidx.recyclerview.widget.GridLayoutManager import com.zucchini.common.NavigationProvider +import com.zucchini.feature.projects.R import com.zucchini.feature.projects.databinding.FragmentSubmitProjectWithDevBinding import com.zucchini.submit.project.SubmitProjectViewModel import com.zucchini.submit.project.adapter.FindDevAdapter +import com.zucchini.view.showShortToast import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import javax.inject.Inject @@ -63,6 +65,8 @@ class SubmitProjectWithDevFragment : Fragment() { viewModel.isSuccessSubmitProject.flowWithLifecycle(lifecycle).onEach { isSuccess -> if (isSuccess) { startActivity(navigationProvider.toMain()) + } else { + showShortToast(getString(R.string.fail_submit_project)) } }.launchIn(lifecycleScope) } diff --git a/feature/projects/src/main/res/values/strings.xml b/feature/projects/src/main/res/values/strings.xml index 92bc1aa..f9d560d 100644 --- a/feature/projects/src/main/res/values/strings.xml +++ b/feature/projects/src/main/res/values/strings.xml @@ -105,5 +105,6 @@ 프로젝트에서 사용한 협업툴을 선택해주세요.\n(최대 3개) 함께한 개발자 추가하러 가기 다음 + 프로젝트 등록에 실패했습니다. 입력 값을 다시 확인해주세요. \ No newline at end of file From 4d9d1cbc206e1b39d9c4a98ec59f0e8565df7196 Mon Sep 17 00:00:00 2001 From: kangyuri1114 Date: Wed, 17 Jul 2024 17:01:33 +0900 Subject: [PATCH 21/31] =?UTF-8?q?[feat]:=20manifest=20=ED=8C=8C=EC=9D=BC?= =?UTF-8?q?=20=EA=B6=8C=ED=95=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- feature/projects/src/main/AndroidManifest.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/feature/projects/src/main/AndroidManifest.xml b/feature/projects/src/main/AndroidManifest.xml index 675ba51..ddeaeba 100644 --- a/feature/projects/src/main/AndroidManifest.xml +++ b/feature/projects/src/main/AndroidManifest.xml @@ -1,6 +1,10 @@ + + + + Date: Wed, 17 Jul 2024 17:02:13 +0900 Subject: [PATCH 22/31] =?UTF-8?q?[feat]:=20request=EC=97=90=20image=20?= =?UTF-8?q?=EB=A7=A4=EA=B0=9C=EB=B3=80=EC=88=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../zucchini/data/ProjectsRepositoryImpl.kt | 31 ++++++++++++++----- .../domain/repository/ProjectsRepository.kt | 5 ++- 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/data/src/main/java/com/zucchini/data/ProjectsRepositoryImpl.kt b/data/src/main/java/com/zucchini/data/ProjectsRepositoryImpl.kt index 666f535..3c1a94e 100644 --- a/data/src/main/java/com/zucchini/data/ProjectsRepositoryImpl.kt +++ b/data/src/main/java/com/zucchini/data/ProjectsRepositoryImpl.kt @@ -1,5 +1,6 @@ package com.zucchini.data +import android.util.Log import com.sample.network.service.ProjectsService import com.zucchini.domain.model.ProjectsDetailModel import com.zucchini.domain.model.ProjectsListModel @@ -8,7 +9,10 @@ import com.zucchini.domain.repository.ProjectsRepository import com.zucchini.mapper.toProjectsDetailModel import com.zucchini.mapper.toProjectsListModel import com.zucchini.mapper.toSubmitProjectRequest +import okhttp3.MediaType.Companion.toMediaTypeOrNull import okhttp3.MultipartBody +import okhttp3.RequestBody.Companion.asRequestBody +import java.io.File import javax.inject.Inject class ProjectsRepositoryImpl @@ -38,12 +42,25 @@ class ProjectsRepositoryImpl projectsService.getProjectsDetailData(projectId).data.toProjectsDetailModel() } - override suspend fun submitProject(submitProjectInfo: SubmitProjectInfo, imagePath: MultipartBody.Part): Result = - runCatching { - projectsService - .submitProject( - submitProjectInfo.toSubmitProjectRequest(), - imagePath - ).data + override suspend fun submitProject(submitProjectInfo: SubmitProjectInfo, imagePath: String): Result = + runCatching { + var uploadImageFile: MultipartBody.Part = MultipartBody.Part.createFormData("image", "") + + val file = File(imagePath) + if (file.exists()) { + val requestFile = file.asRequestBody("image/jpeg".toMediaTypeOrNull()) + Log.e("ProjectsRepositoryImpl Exists", "requestFile: ${requestFile}") + uploadImageFile = MultipartBody.Part.createFormData("image", file.name, requestFile) + } else { + Log.e("prepareFilePart", "File does not exist: $imagePath") } + + Log.e("ProjectsRepositoryImpl", "uploadImageFile: ${file}, ${imagePath}, ${uploadImageFile}") + + projectsService + .submitProject( + submitProjectInfo.toSubmitProjectRequest(), + uploadImageFile + ).data + } } diff --git a/domain/src/main/java/com/zucchini/domain/repository/ProjectsRepository.kt b/domain/src/main/java/com/zucchini/domain/repository/ProjectsRepository.kt index d7355a7..c3386d5 100644 --- a/domain/src/main/java/com/zucchini/domain/repository/ProjectsRepository.kt +++ b/domain/src/main/java/com/zucchini/domain/repository/ProjectsRepository.kt @@ -14,5 +14,8 @@ interface ProjectsRepository { suspend fun getProjectsDetailData(projectId: Int): Result - suspend fun submitProject(submitProjectInfo: SubmitProjectInfo): Result + suspend fun submitProject( + submitProjectInfo: SubmitProjectInfo, + imagePath: String, + ): Result } From ee2abd31f6f3b9a237c90b5eec4add76d2eb9bc6 Mon Sep 17 00:00:00 2001 From: kangyuri1114 Date: Wed, 17 Jul 2024 17:02:36 +0900 Subject: [PATCH 23/31] =?UTF-8?q?[feat]:=20=ED=94=84=EB=A1=9C=EC=A0=9D?= =?UTF-8?q?=ED=8A=B8=20=EB=93=B1=EB=A1=9D=20api=20Multipart=EB=A1=9C=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/sample/network/service/ProjectsService.kt | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/core/network/src/main/java/com/sample/network/service/ProjectsService.kt b/core/network/src/main/java/com/sample/network/service/ProjectsService.kt index 6a58277..48efefe 100644 --- a/core/network/src/main/java/com/sample/network/service/ProjectsService.kt +++ b/core/network/src/main/java/com/sample/network/service/ProjectsService.kt @@ -5,9 +5,10 @@ import com.sample.network.reponse.ProjectsDetailResponse import com.sample.network.reponse.ProjectsListResponse import com.sample.network.request.SubmitProjectRequest import okhttp3.MultipartBody -import retrofit2.http.Body import retrofit2.http.GET +import retrofit2.http.Multipart import retrofit2.http.POST +import retrofit2.http.Part import retrofit2.http.Path import retrofit2.http.Query @@ -25,9 +26,10 @@ interface ProjectsService { @Path("projectId") projectId: Int, ): BaseResponse + @Multipart @POST("api/projects") suspend fun submitProject( - @Body submitProjectRequest: SubmitProjectRequest, - @Body file: MultipartBody.Part + @Part("requestDTO") submitProjectRequest: SubmitProjectRequest, + @Part image: MultipartBody.Part, ): BaseResponse } From 15737d34daae3aead8625132af09cc27c3abec1b Mon Sep 17 00:00:00 2001 From: kangyuri1114 Date: Wed, 17 Jul 2024 17:03:21 +0900 Subject: [PATCH 24/31] =?UTF-8?q?[feat]:=20imagePath=20=EB=A7=A4=EA=B0=9C?= =?UTF-8?q?=EB=B3=80=EC=88=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../submit/project/SubmitProjectViewModel.kt | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/feature/projects/src/main/java/com/zucchini/submit/project/SubmitProjectViewModel.kt b/feature/projects/src/main/java/com/zucchini/submit/project/SubmitProjectViewModel.kt index 608ad94..5bc64db 100644 --- a/feature/projects/src/main/java/com/zucchini/submit/project/SubmitProjectViewModel.kt +++ b/feature/projects/src/main/java/com/zucchini/submit/project/SubmitProjectViewModel.kt @@ -1,6 +1,5 @@ package com.zucchini.submit.project -import android.util.Log import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.zucchini.domain.model.FindDeveloperInfo @@ -11,7 +10,6 @@ import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.launch -import okhttp3.MultipartBody import timber.log.Timber import javax.inject.Inject @@ -24,6 +22,8 @@ class SubmitProjectViewModel ) : ViewModel() { private val _projectName = MutableStateFlow("") + private val _imagePath = MutableStateFlow("") + private val _projectGithub = MutableStateFlow("") private val _projectShortIntro = MutableStateFlow("") @@ -70,9 +70,9 @@ class SubmitProjectViewModel _projectLink.value = projectLink } - fun updateImagePath(imagePath: MultipartBody.Part) { - //_imagePath.value = imagePath - } + fun updateImagePath(imagePath: String) { + _imagePath.value = imagePath + } fun updateProjectCategory(projectCategoryList: List = emptyList()) { _projectCategoryList.value = projectCategoryList @@ -122,12 +122,14 @@ class SubmitProjectViewModel submit.projectLink = _projectLink.value submit.projectDeveloperList = _addProjectDeveloperList.value - projectsRepository.submitProject(submit).onSuccess { - _isSuccessSubmitProject.value = true - }.onFailure { - _isSuccessSubmitProject.value = false - Timber.d("failed to submit project $it") - } + projectsRepository + .submitProject(submit, _imagePath.value) + .onSuccess { + _isSuccessSubmitProject.value = true + }.onFailure { + _isSuccessSubmitProject.value = false + Timber.d("failed to submit project $it") + } } } } From ba1664027e9ce04602555419b7a8e168e7ce410d Mon Sep 17 00:00:00 2001 From: kangyuri1114 Date: Wed, 17 Jul 2024 17:29:46 +0900 Subject: [PATCH 25/31] =?UTF-8?q?[feat]:=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20U?= =?UTF-8?q?RI=EA=B0=80=20=ED=8C=8C=EC=9D=BC=20=EA=B2=BD=EB=A1=9C=EA=B0=80?= =?UTF-8?q?=20=EC=95=84=EB=8B=88=EB=9D=BC=20=EC=BB=A8=ED=85=90=EC=B8=A0=20?= =?UTF-8?q?URI=EB=A1=9C=20=EA=B0=9D=EC=B2=B4=EA=B0=80=20=EC=8B=A4=EC=A0=9C?= =?UTF-8?q?=20=ED=8C=8C=EC=9D=BC=20=EC=8B=9C=EC=8A=A4=ED=85=9C=EC=97=90?= =?UTF-8?q?=EC=84=9C=20=EC=A1=B4=EC=9E=AC=ED=95=98=EC=A7=80=20=EC=95=8A?= =?UTF-8?q?=EB=8A=94=20=EC=9D=B4=EC=8A=88=20=EB=B0=9C=EC=83=9D=20=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../project/fragment/SubmitProjectFragment.kt | 93 +++++++++++-------- 1 file changed, 54 insertions(+), 39 deletions(-) diff --git a/feature/projects/src/main/java/com/zucchini/submit/project/fragment/SubmitProjectFragment.kt b/feature/projects/src/main/java/com/zucchini/submit/project/fragment/SubmitProjectFragment.kt index 58d8a51..a90564a 100644 --- a/feature/projects/src/main/java/com/zucchini/submit/project/fragment/SubmitProjectFragment.kt +++ b/feature/projects/src/main/java/com/zucchini/submit/project/fragment/SubmitProjectFragment.kt @@ -1,27 +1,27 @@ package com.zucchini.submit.project.fragment -import android.net.Uri +import android.Manifest +import android.app.Activity +import android.content.Intent +import android.content.pm.PackageManager import android.os.Bundle +import android.provider.MediaStore +import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.activity.result.ActivityResult +import androidx.activity.result.ActivityResultLauncher import androidx.activity.result.contract.ActivityResultContracts +import androidx.core.content.ContextCompat import androidx.fragment.app.Fragment import androidx.fragment.app.activityViewModels -import coil.load -import com.zucchini.data.ContentUriRequestBody import com.zucchini.dialog.SelectCheckBoxCommonDialog import com.zucchini.domain.model.KeywordList import com.zucchini.feature.projects.R import com.zucchini.feature.projects.databinding.FragmentSubmitProjectBinding import com.zucchini.submit.project.SubmitProjectActivity import com.zucchini.submit.project.SubmitProjectViewModel -import com.zucchini.view.showShortToast -import okhttp3.MediaType.Companion.toMediaTypeOrNull -import okhttp3.MultipartBody -import okhttp3.RequestBody.Companion.asRequestBody -import timber.log.Timber -import java.io.File class SubmitProjectFragment : Fragment() { private var _binding: FragmentSubmitProjectBinding? = null @@ -29,19 +29,20 @@ class SubmitProjectFragment : Fragment() { private val viewModel: SubmitProjectViewModel by activityViewModels() - private var imageUri = Uri.EMPTY - - private val launcher = - registerForActivityResult(ActivityResultContracts.GetContent()) { uri: Uri? -> - imageUri = uri - if (imageUri != null) { - binding.ivProjectSubmit.load(imageUri) - processSelectedImage(imageUri!!) - } else { - showShortToast(getString(R.string.submit_image)) + // 권한 요청 + private val requestPermissionLauncher: ActivityResultLauncher = + registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted -> + if (isGranted) { + navigateToGallery() } } + // 가져온 사진 보여주기 + private val pickImageLauncher: ActivityResultLauncher = + registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> + handleImageResult(result) + } + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -56,17 +57,44 @@ class SubmitProjectFragment : Fragment() { return binding.root } - private fun initDialogClickListener() { - selectProjectCategory() - selectStack() - } - private fun initImageSubmitView() { binding.tvProjectSubmitImage.setOnClickListener { - launcher.launch("image/*") + if (ContextCompat.checkSelfPermission( + requireContext(), + Manifest.permission.READ_EXTERNAL_STORAGE, + ) == PackageManager.PERMISSION_GRANTED + ) { + navigateToGallery() + } else { + requestPermissionLauncher.launch(Manifest.permission.READ_EXTERNAL_STORAGE) + } + } + } + + private fun handleImageResult(result: ActivityResult) { + if (result.resultCode == Activity.RESULT_OK) { + val data: Intent? = result.data + data?.data?.let { uri -> + // 이미지 URI를 사용하여 이미지를 표시하거나 추가 작업을 수행합니다. + binding.ivProjectSubmit.setImageURI(uri) + viewModel.updateImagePath(uri.path ?: "") + Log.d("Selected Image", "Selected Image URI: $uri") + } + } else { + Log.d("Image Failure", "Image selection failed or was canceled.") } } + private fun navigateToGallery() { + val gallery = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.INTERNAL_CONTENT_URI) + pickImageLauncher.launch(gallery) + } + + private fun initDialogClickListener() { + selectProjectCategory() + selectStacks() + } + private fun selectProjectCategory() { // 카테고리 키워드 리스트를 한글과 영어 키워드를 매핑하는 Map으로 준비 val keywordMap = KeywordList.categoryList.associateBy { it.keywordKorean } @@ -93,7 +121,7 @@ class SubmitProjectFragment : Fragment() { } } - private fun selectStack() { + private fun selectStacks() { val languageMap = KeywordList.languageList.associateBy { it.keywordKorean } val techStackMap = KeywordList.techStackList.associateBy { it.keywordKorean } val cooperationToolMap = KeywordList.cooperationList.associateBy { it.keywordKorean } @@ -160,18 +188,6 @@ class SubmitProjectFragment : Fragment() { } } - private fun processSelectedImage(uri: Uri) { - val requestBody = - ContentUriRequestBody( - context = requireContext(), - uri = uri, - ).toFormData() - - Timber.d("Image Uri: $uri") - Timber.d("Image Path: ${uri.path}") - Timber.d("Request Body: $requestBody") - } - private fun clickSubmitButton() { binding.btnNext.setOnClickListener { viewModel.updateProjectInfo( @@ -186,5 +202,4 @@ class SubmitProjectFragment : Fragment() { (activity as? SubmitProjectActivity)?.setCurrentItem(1) } } - } From 466eaf5cfcc956603d10f6a3648ac51c031d3cbb Mon Sep 17 00:00:00 2001 From: kangyuri1114 Date: Thu, 18 Jul 2024 04:04:10 +0900 Subject: [PATCH 26/31] =?UTF-8?q?[feat]:=20multipart=EB=A1=9C=20api=20?= =?UTF-8?q?=ED=86=B5=EC=8B=A0=20=EC=A4=91=20400=20bad=20request=20?= =?UTF-8?q?=EC=98=A4=EB=A5=98=20=EB=B0=9C=EC=83=9D=20=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/AndroidManifest.xml | 1 + .../com/zucchini/buildsrc/Dependencies.kt | 4 +- .../java/com/zucchini/buildsrc/Versions.kt | 1 + .../sample/network/service/ProjectsService.kt | 3 +- data/build.gradle.kts | 1 + .../zucchini/data/ProjectsRepositoryImpl.kt | 39 ++++++++++--------- .../submit/project/SubmitProjectViewModel.kt | 2 + .../project/fragment/SubmitProjectFragment.kt | 20 +++++++++- 8 files changed, 49 insertions(+), 22 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 75bfe77..bf5efe9 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -5,6 +5,7 @@ } diff --git a/data/build.gradle.kts b/data/build.gradle.kts index 9cf27e8..d89266e 100644 --- a/data/build.gradle.kts +++ b/data/build.gradle.kts @@ -56,6 +56,7 @@ dependencies { implementation(okHttpLoggingInterceptor) implementation(retrofitJsonConverter) implementation(timber) + implementation(gson) } TestDependencies.run { diff --git a/data/src/main/java/com/zucchini/data/ProjectsRepositoryImpl.kt b/data/src/main/java/com/zucchini/data/ProjectsRepositoryImpl.kt index 3c1a94e..167f4ac 100644 --- a/data/src/main/java/com/zucchini/data/ProjectsRepositoryImpl.kt +++ b/data/src/main/java/com/zucchini/data/ProjectsRepositoryImpl.kt @@ -1,6 +1,6 @@ package com.zucchini.data -import android.util.Log +import com.google.gson.Gson import com.sample.network.service.ProjectsService import com.zucchini.domain.model.ProjectsDetailModel import com.zucchini.domain.model.ProjectsListModel @@ -12,6 +12,7 @@ import com.zucchini.mapper.toSubmitProjectRequest import okhttp3.MediaType.Companion.toMediaTypeOrNull import okhttp3.MultipartBody import okhttp3.RequestBody.Companion.asRequestBody +import okhttp3.RequestBody.Companion.toRequestBody import java.io.File import javax.inject.Inject @@ -42,25 +43,25 @@ class ProjectsRepositoryImpl projectsService.getProjectsDetailData(projectId).data.toProjectsDetailModel() } - override suspend fun submitProject(submitProjectInfo: SubmitProjectInfo, imagePath: String): Result = - runCatching { - var uploadImageFile: MultipartBody.Part = MultipartBody.Part.createFormData("image", "") + override suspend fun submitProject( + submitProjectInfo: SubmitProjectInfo, + imagePath: String, + ): Result = + runCatching { + // JSON 데이터를 문자열로 변환 + val gson = Gson() + val json = gson.toJson(submitProjectInfo.toSubmitProjectRequest()) + val jsonRequestBody = json.toRequestBody("application/json".toMediaTypeOrNull()) - val file = File(imagePath) - if (file.exists()) { - val requestFile = file.asRequestBody("image/jpeg".toMediaTypeOrNull()) - Log.e("ProjectsRepositoryImpl Exists", "requestFile: ${requestFile}") - uploadImageFile = MultipartBody.Part.createFormData("image", file.name, requestFile) - } else { - Log.e("prepareFilePart", "File does not exist: $imagePath") - } + // JSON requestBody를 MultipartBody.Part로 변환 + val jsonPart = MultipartBody.Part.createFormData("requestDTO", null, jsonRequestBody) - Log.e("ProjectsRepositoryImpl", "uploadImageFile: ${file}, ${imagePath}, ${uploadImageFile}") + // 파일을 MultipartBody.Part로 변환 + val file = File(imagePath) + val fileRequestBody = file.asRequestBody("image/*".toMediaTypeOrNull()) + val imagePart = MultipartBody.Part.createFormData("image", file.name, fileRequestBody) - projectsService - .submitProject( - submitProjectInfo.toSubmitProjectRequest(), - uploadImageFile - ).data - } + // 서비스 호출 + projectsService.submitProject(jsonPart, imagePart).data + } } diff --git a/feature/projects/src/main/java/com/zucchini/submit/project/SubmitProjectViewModel.kt b/feature/projects/src/main/java/com/zucchini/submit/project/SubmitProjectViewModel.kt index 5bc64db..2d6c174 100644 --- a/feature/projects/src/main/java/com/zucchini/submit/project/SubmitProjectViewModel.kt +++ b/feature/projects/src/main/java/com/zucchini/submit/project/SubmitProjectViewModel.kt @@ -1,5 +1,6 @@ package com.zucchini.submit.project +import android.util.Log import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.zucchini.domain.model.FindDeveloperInfo @@ -129,6 +130,7 @@ class SubmitProjectViewModel }.onFailure { _isSuccessSubmitProject.value = false Timber.d("failed to submit project $it") + Log.e("SubmitProjectViewModel", "failed to submit project", it) } } } diff --git a/feature/projects/src/main/java/com/zucchini/submit/project/fragment/SubmitProjectFragment.kt b/feature/projects/src/main/java/com/zucchini/submit/project/fragment/SubmitProjectFragment.kt index a90564a..9c9aa49 100644 --- a/feature/projects/src/main/java/com/zucchini/submit/project/fragment/SubmitProjectFragment.kt +++ b/feature/projects/src/main/java/com/zucchini/submit/project/fragment/SubmitProjectFragment.kt @@ -2,8 +2,11 @@ package com.zucchini.submit.project.fragment import android.Manifest import android.app.Activity +import android.content.Context import android.content.Intent import android.content.pm.PackageManager +import android.database.Cursor +import android.net.Uri import android.os.Bundle import android.provider.MediaStore import android.util.Log @@ -77,7 +80,8 @@ class SubmitProjectFragment : Fragment() { data?.data?.let { uri -> // 이미지 URI를 사용하여 이미지를 표시하거나 추가 작업을 수행합니다. binding.ivProjectSubmit.setImageURI(uri) - viewModel.updateImagePath(uri.path ?: "") + val uriToAbsolutePath = absolutelyPath(uri, requireContext()) + viewModel.updateImagePath(uriToAbsolutePath) Log.d("Selected Image", "Selected Image URI: $uri") } } else { @@ -85,6 +89,20 @@ class SubmitProjectFragment : Fragment() { } } + private fun absolutelyPath( + path: Uri?, + context: Context, + ): String { + val proj: Array = arrayOf(MediaStore.Images.Media.DATA) + val c: Cursor? = context.contentResolver.query(path!!, proj, null, null, null) + val index = c?.getColumnIndexOrThrow(MediaStore.Images.Media.DATA) + c?.moveToFirst() + + val result = c?.getString(index!!) + + return result!! + } + private fun navigateToGallery() { val gallery = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.INTERNAL_CONTENT_URI) pickImageLauncher.launch(gallery) From 78b7525cd497fcedc2724baa5e2ed15cd445a0ee Mon Sep 17 00:00:00 2001 From: kangyuri1114 Date: Mon, 29 Jul 2024 21:00:21 +0900 Subject: [PATCH 27/31] =?UTF-8?q?[feat]:=20=ED=94=84=EB=A1=9C=EC=A0=9D?= =?UTF-8?q?=ED=8A=B8=20=EB=93=B1=EB=A1=9D=20API=20=EC=84=B1=EA=B3=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sample/network/request/SubmitProjectRequest.kt | 2 +- .../java/com/zucchini/mapper/SubmitProjectInfo.kt | 4 ++-- .../java/com/zucchini/domain/model/KeywordList.kt | 12 ++++++------ .../project/fragment/SubmitProjectWithDevFragment.kt | 8 +++++++- feature/projects/src/main/res/values/strings.xml | 1 + 5 files changed, 17 insertions(+), 10 deletions(-) diff --git a/core/network/src/main/java/com/sample/network/request/SubmitProjectRequest.kt b/core/network/src/main/java/com/sample/network/request/SubmitProjectRequest.kt index 26a5049..d164d5b 100644 --- a/core/network/src/main/java/com/sample/network/request/SubmitProjectRequest.kt +++ b/core/network/src/main/java/com/sample/network/request/SubmitProjectRequest.kt @@ -29,5 +29,5 @@ data class SubmitProjectRequest( @SerialName("webLink") val webLink: String, @SerialName("projectDevloperList") - val projectDeveloperList: List + val projectDevloperList: List ) \ No newline at end of file diff --git a/data/src/main/java/com/zucchini/mapper/SubmitProjectInfo.kt b/data/src/main/java/com/zucchini/mapper/SubmitProjectInfo.kt index 8a932c3..515cad1 100644 --- a/data/src/main/java/com/zucchini/mapper/SubmitProjectInfo.kt +++ b/data/src/main/java/com/zucchini/mapper/SubmitProjectInfo.kt @@ -15,9 +15,9 @@ internal fun SubmitProjectInfo.toSubmitProjectRequest(): SubmitProjectRequest { appLink = projectAppLink, category = projectCategoryList.get(0), languageList = projectLanguageList, - devToolList = projectTechStackList, + devToolList = projectCooperationList, techStackList = projectTechStackList, - projectDeveloperList = projectDeveloperList + projectDevloperList = projectDeveloperList ) } diff --git a/domain/src/main/java/com/zucchini/domain/model/KeywordList.kt b/domain/src/main/java/com/zucchini/domain/model/KeywordList.kt index 840eb4e..608c708 100644 --- a/domain/src/main/java/com/zucchini/domain/model/KeywordList.kt +++ b/domain/src/main/java/com/zucchini/domain/model/KeywordList.kt @@ -34,12 +34,12 @@ object KeywordList { ) val cooperationList = arrayListOf( - Keyword(keywordEnglish = "COOPERATION", keywordKorean = "Notion"), - Keyword(keywordEnglish = "INDIVIDUAL", keywordKorean = "Github"), - Keyword(keywordEnglish = "COOPERATION", keywordKorean = "Slack"), - Keyword(keywordEnglish = "INDIVIDUAL", keywordKorean = "Jira"), - Keyword(keywordEnglish = "COOPERATION", keywordKorean = "Trello"), - Keyword(keywordEnglish = "INDIVIDUAL", keywordKorean = "Figma"), + Keyword(keywordEnglish = "NOTION", keywordKorean = "Notion"), + Keyword(keywordEnglish = "GITHUB", keywordKorean = "Github"), + Keyword(keywordEnglish = "SLACK", keywordKorean = "Slack"), + Keyword(keywordEnglish = "JIRA", keywordKorean = "Jira"), + Keyword(keywordEnglish = "TRELLO", keywordKorean = "Trello"), + Keyword(keywordEnglish = "FIGMA", keywordKorean = "Figma"), ) val techStackList = arrayListOf( diff --git a/feature/projects/src/main/java/com/zucchini/submit/project/fragment/SubmitProjectWithDevFragment.kt b/feature/projects/src/main/java/com/zucchini/submit/project/fragment/SubmitProjectWithDevFragment.kt index 86263ba..9a76a96 100644 --- a/feature/projects/src/main/java/com/zucchini/submit/project/fragment/SubmitProjectWithDevFragment.kt +++ b/feature/projects/src/main/java/com/zucchini/submit/project/fragment/SubmitProjectWithDevFragment.kt @@ -15,10 +15,12 @@ import com.zucchini.feature.projects.databinding.FragmentSubmitProjectWithDevBin import com.zucchini.submit.project.SubmitProjectViewModel import com.zucchini.submit.project.adapter.FindDevAdapter import com.zucchini.view.showShortToast +import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import javax.inject.Inject +@AndroidEntryPoint class SubmitProjectWithDevFragment : Fragment() { private var _binding: FragmentSubmitProjectWithDevBinding? = null private val binding: FragmentSubmitProjectWithDevBinding get() = _binding!! @@ -64,7 +66,11 @@ class SubmitProjectWithDevFragment : Fragment() { viewModel.submitProject() viewModel.isSuccessSubmitProject.flowWithLifecycle(lifecycle).onEach { isSuccess -> if (isSuccess) { - startActivity(navigationProvider.toMain()) + showShortToast(getString(R.string.success_sumbit_project)) + navigationProvider.toMain().also { + startActivity(it) + requireActivity().finish() + } } else { showShortToast(getString(R.string.fail_submit_project)) } diff --git a/feature/projects/src/main/res/values/strings.xml b/feature/projects/src/main/res/values/strings.xml index f9d560d..46106b7 100644 --- a/feature/projects/src/main/res/values/strings.xml +++ b/feature/projects/src/main/res/values/strings.xml @@ -106,5 +106,6 @@ 함께한 개발자 추가하러 가기 다음 프로젝트 등록에 실패했습니다. 입력 값을 다시 확인해주세요. + 프로젝트가 등록습니다. \ No newline at end of file From 69c70688144f592601e1c735b253417ac006d720 Mon Sep 17 00:00:00 2001 From: kangyuri1114 Date: Mon, 29 Jul 2024 21:22:49 +0900 Subject: [PATCH 28/31] =?UTF-8?q?[feat]:=20enum=EA=B0=92=20=EC=97=85?= =?UTF-8?q?=EB=8D=B0=EC=9D=B4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/zucchini/domain/model/KeywordList.kt | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/domain/src/main/java/com/zucchini/domain/model/KeywordList.kt b/domain/src/main/java/com/zucchini/domain/model/KeywordList.kt index 608c708..b67e962 100644 --- a/domain/src/main/java/com/zucchini/domain/model/KeywordList.kt +++ b/domain/src/main/java/com/zucchini/domain/model/KeywordList.kt @@ -12,7 +12,7 @@ object KeywordList { Keyword(keywordEnglish = "IOT", keywordKorean = "IOT"), Keyword(keywordEnglish = "CLOUD_COMPUTING", keywordKorean = "클라우드"), Keyword(keywordEnglish = "BLOCKCHAIN", keywordKorean = "블록체인"), - Keyword("VR", keywordKorean = "VR/AR"), + Keyword("VRAR", keywordKorean = "VR/AR"), Keyword(keywordEnglish = "ROBOTICS", keywordKorean = "로봇"), Keyword(keywordEnglish = "OTHER", keywordKorean = "기타"), ) @@ -22,6 +22,8 @@ object KeywordList { Keyword(keywordEnglish = "MIDDLE_TIER", keywordKorean = "미들웨어"), Keyword(keywordEnglish = "WEB", keywordKorean = "웹"), Keyword(keywordEnglish = "DESKTOP", keywordKorean = "데스크탑"), + Keyword(keywordEnglish = "IOS", keywordKorean = "iOS"), + Keyword(keywordEnglish = "ANDROID", keywordKorean = "Android"), Keyword(keywordEnglish = "MOBILE", keywordKorean = "모바일"), Keyword(keywordEnglish = "GRAPHICS", keywordKorean = "그래픽"), Keyword(keywordEnglish = "GAME", keywordKorean = "게임"), @@ -47,24 +49,34 @@ object KeywordList { Keyword(keywordEnglish = "SPRING", keywordKorean = "Spring"), Keyword(keywordEnglish = "REACT", keywordKorean = "React"), Keyword(keywordEnglish = "ANGULAR", keywordKorean = "Angular"), + Keyword(keywordEnglish = "VUE", keywordKorean = "Vue"), Keyword(keywordEnglish = "AWS", keywordKorean = "AWS"), - ) + Keyword(keywordEnglish = "AZURE", keywordKorean = "Azure"), + Keyword(keywordEnglish = "DOCKER", keywordKorean = "Docker"), + Keyword(keywordEnglish = "LARAVEL", keywordKorean = "Laravel"), + Keyword(keywordEnglish = "EXPRESS", keywordKorean = "Express"), + Keyword(keywordEnglish = "NODE_JS", keywordKorean = "Node.js"), + Keyword(keywordEnglish = "DOT_NET", keywordKorean = ".net"), + Keyword(keywordEnglish = "JENKINS", keywordKorean = "Jenkins"), + Keyword(keywordEnglish = "KUBERNETES", keywordKorean = "Kubernetes"), + Keyword(keywordEnglish = "GOOGLE_CLOUD", keywordKorean = "Google Cloud"), + ) val languageList = arrayListOf( Keyword(keywordEnglish = "GO", keywordKorean = "Go"), Keyword(keywordEnglish = "JAVA", keywordKorean = "Java"), Keyword(keywordEnglish = "KOTLIN", keywordKorean = "Kotlin"), + Keyword(keywordEnglish = "SWIFT", keywordKorean = "Swift"), Keyword(keywordEnglish = "JAVASCRIPT", keywordKorean = "JavaScript"), Keyword(keywordEnglish = "TS", keywordKorean = "TypeScript"), Keyword(keywordEnglish = "PYTHON", keywordKorean = "Python"), Keyword(keywordEnglish = "C", keywordKorean = "C"), Keyword(keywordEnglish = "CPP", keywordKorean = "C++"), + Keyword(keywordEnglish = "CS", keywordKorean = "C#"), Keyword(keywordEnglish = "PHP", keywordKorean = "PHP"), Keyword(keywordEnglish = "R", keywordKorean = "R"), Keyword(keywordEnglish = "RUBY", keywordKorean = "RUBY"), Keyword(keywordEnglish = "RUST", keywordKorean = "RUST"), Keyword(keywordEnglish = "SQL", keywordKorean = "SQL"), - Keyword(keywordEnglish = "HTML", keywordKorean = "HTML"), - Keyword(keywordEnglish = "CSS", keywordKorean = "CSS"), ) } From fc9a3ff012a3dd7d8ef4ab6bbfc0d7b713d7c8fe Mon Sep 17 00:00:00 2001 From: kangyuri1114 Date: Mon, 29 Jul 2024 22:56:42 +0900 Subject: [PATCH 29/31] =?UTF-8?q?[feat]:=20ui=20=EB=A7=88=EC=A7=84=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- feature/projects/src/main/res/layout/item_projects.xml | 5 ++--- feature/projects/src/main/res/layout/item_search_keyword.xml | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/feature/projects/src/main/res/layout/item_projects.xml b/feature/projects/src/main/res/layout/item_projects.xml index db474fa..e3f709d 100644 --- a/feature/projects/src/main/res/layout/item_projects.xml +++ b/feature/projects/src/main/res/layout/item_projects.xml @@ -11,7 +11,6 @@ android:id="@+id/iv_project_profile" android:layout_width="60dp" android:layout_height="wrap_content" - android:layout_marginVertical="5dp" android:layout_marginStart="20dp" android:src="@drawable/project_profile_default" app:layout_constraintBottom_toBottomOf="parent" @@ -23,7 +22,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="16dp" - android:layout_marginTop="20dp" + android:layout_marginTop="13dp" android:fontFamily="@font/pretendardextrabold" android:textColor="@color/olive_black" android:textSize="14sp" @@ -68,7 +67,7 @@ android:layout_height="wrap_content" android:layout_marginStart="16dp" android:layout_marginEnd="20dp" - android:layout_marginBottom="15dp" + android:layout_marginBottom="13dp" android:fontFamily="@font/pretendardmedium" android:gravity="end" android:textColor="@color/gray2" diff --git a/feature/projects/src/main/res/layout/item_search_keyword.xml b/feature/projects/src/main/res/layout/item_search_keyword.xml index 86b80b3..7c8e769 100644 --- a/feature/projects/src/main/res/layout/item_search_keyword.xml +++ b/feature/projects/src/main/res/layout/item_search_keyword.xml @@ -16,7 +16,7 @@ android:minWidth="0dp" android:minHeight="0dp" android:paddingHorizontal="15dp" - android:paddingVertical="10dp" + android:paddingVertical="9dp" android:textColor="@color/olive_black" android:textSize="12sp" app:layout_constraintBottom_toBottomOf="parent" From 73833a5fb19f41f8e339fe649a56f1c9300662e4 Mon Sep 17 00:00:00 2001 From: kangyuri1114 Date: Mon, 29 Jul 2024 23:11:58 +0900 Subject: [PATCH 30/31] [feat]: add hidekeyboard --- feature/projects/src/main/AndroidManifest.xml | 1 + .../submit/project/fragment/SubmitProjectFragment.kt | 8 ++++++++ .../project/fragment/SubmitProjectWithDevFragment.kt | 8 ++++++++ .../main/res/layout/fragment_submit_project_with_dev.xml | 3 +-- 4 files changed, 18 insertions(+), 2 deletions(-) diff --git a/feature/projects/src/main/AndroidManifest.xml b/feature/projects/src/main/AndroidManifest.xml index ddeaeba..a3588e0 100644 --- a/feature/projects/src/main/AndroidManifest.xml +++ b/feature/projects/src/main/AndroidManifest.xml @@ -10,6 +10,7 @@ android:name="com.zucchini.submit.project.SubmitProjectActivity" android:exported="false" android:screenOrientation="portrait" + android:windowSoftInputMode="adjustPan" android:theme="@style/Theme.AppCompat.Light.NoActionBar" /> + app:layout_constraintStart_toStartOf="parent" /> \ No newline at end of file From 820dfe35aca9397a216415a15056a841caa9cde8 Mon Sep 17 00:00:00 2001 From: kangyuri1114 Date: Mon, 29 Jul 2024 23:21:30 +0900 Subject: [PATCH 31/31] [fix]: resolve conflict --- .../zucchini/data/DevelopersRepositoryImpl.kt | 3 - .../zucchini/data/ProjectsRepositoryImpl.kt | 88 +++++++++---------- .../domain/repository/DevelopersRepository.kt | 11 +-- .../domain/repository/ProjectsRepository.kt | 4 +- .../project/fragment/SubmitProjectFragment.kt | 2 +- 5 files changed, 51 insertions(+), 57 deletions(-) diff --git a/data/src/main/java/com/zucchini/data/DevelopersRepositoryImpl.kt b/data/src/main/java/com/zucchini/data/DevelopersRepositoryImpl.kt index 6c9ed09..8cee540 100644 --- a/data/src/main/java/com/zucchini/data/DevelopersRepositoryImpl.kt +++ b/data/src/main/java/com/zucchini/data/DevelopersRepositoryImpl.kt @@ -1,10 +1,7 @@ package com.zucchini.data import com.sample.network.service.DevelopersService -import com.zucchini.domain.model.DevelopersDetailModel -import com.zucchini.domain.model.DevelopersListModel import com.zucchini.domain.model.FindDeveloperInfo -import com.zucchini.domain.model.SubmitDevInfo import com.zucchini.domain.model.developers.DevelopersDetailModel import com.zucchini.domain.model.developers.DevelopersListModel import com.zucchini.domain.model.submit.SubmitDevInfo diff --git a/data/src/main/java/com/zucchini/data/ProjectsRepositoryImpl.kt b/data/src/main/java/com/zucchini/data/ProjectsRepositoryImpl.kt index aa1a157..b1516f4 100644 --- a/data/src/main/java/com/zucchini/data/ProjectsRepositoryImpl.kt +++ b/data/src/main/java/com/zucchini/data/ProjectsRepositoryImpl.kt @@ -2,8 +2,6 @@ package com.zucchini.data import com.google.gson.Gson import com.sample.network.service.ProjectsService -import com.zucchini.domain.model.ProjectsDetailModel -import com.zucchini.domain.model.ProjectsListModel import com.zucchini.domain.model.SubmitProjectInfo import com.zucchini.domain.model.projects.ProjectsDetailModel import com.zucchini.domain.model.projects.ProjectsListModel @@ -19,51 +17,51 @@ import java.io.File import javax.inject.Inject class ProjectsRepositoryImpl - @Inject - constructor( - private val projectsService: ProjectsService, - ) : ProjectsRepository { - override suspend fun getProjectsListData( - searchString: String?, - category: String?, - sortType: String, - page: Int, - ): Result = - runCatching { - projectsService - .getProjectsListData( - searchString = searchString, - category = category, - sortType = sortType, - page = page, - ).data - .toProjectsListModel() - } +@Inject +constructor( + private val projectsService: ProjectsService, +) : ProjectsRepository { + override suspend fun getProjectsListData( + searchString: String?, + category: String?, + sortType: String, + page: Int, + ): Result = + runCatching { + projectsService + .getProjectsListData( + searchString = searchString, + category = category, + sortType = sortType, + page = page, + ).data + .toProjectsListModel() + } - override suspend fun getProjectsDetailData(projectId: Int): Result = - runCatching { - projectsService.getProjectsDetailData(projectId).data.toProjectsDetailModel() - } + override suspend fun getProjectsDetailData(projectId: Int): Result = + runCatching { + projectsService.getProjectsDetailData(projectId).data.toProjectsDetailModel() + } - override suspend fun submitProject( - submitProjectInfo: SubmitProjectInfo, - imagePath: String, - ): Result = - runCatching { - // JSON 데이터를 문자열로 변환 - val gson = Gson() - val json = gson.toJson(submitProjectInfo.toSubmitProjectRequest()) - val jsonRequestBody = json.toRequestBody("application/json".toMediaTypeOrNull()) + override suspend fun submitProject( + submitProjectInfo: SubmitProjectInfo, + imagePath: String, + ): Result = + runCatching { + // JSON 데이터를 문자열로 변환 + val gson = Gson() + val json = gson.toJson(submitProjectInfo.toSubmitProjectRequest()) + val jsonRequestBody = json.toRequestBody("application/json".toMediaTypeOrNull()) - // JSON requestBody를 MultipartBody.Part로 변환 - val jsonPart = MultipartBody.Part.createFormData("requestDTO", null, jsonRequestBody) + // JSON requestBody를 MultipartBody.Part로 변환 + val jsonPart = MultipartBody.Part.createFormData("requestDTO", null, jsonRequestBody) - // 파일을 MultipartBody.Part로 변환 - val file = File(imagePath) - val fileRequestBody = file.asRequestBody("image/*".toMediaTypeOrNull()) - val imagePart = MultipartBody.Part.createFormData("image", file.name, fileRequestBody) + // 파일을 MultipartBody.Part로 변환 + val file = File(imagePath) + val fileRequestBody = file.asRequestBody("image/*".toMediaTypeOrNull()) + val imagePart = MultipartBody.Part.createFormData("image", file.name, fileRequestBody) - // 서비스 호출 - projectsService.submitProject(jsonPart, imagePart).data - } - } + // 서비스 호출 + projectsService.submitProject(jsonPart, imagePart).data + } +} diff --git a/domain/src/main/java/com/zucchini/domain/repository/DevelopersRepository.kt b/domain/src/main/java/com/zucchini/domain/repository/DevelopersRepository.kt index 5bdc37a..616448b 100644 --- a/domain/src/main/java/com/zucchini/domain/repository/DevelopersRepository.kt +++ b/domain/src/main/java/com/zucchini/domain/repository/DevelopersRepository.kt @@ -1,18 +1,19 @@ package com.zucchini.domain.repository +import com.zucchini.domain.model.FindDeveloperInfo import com.zucchini.domain.model.developers.DevelopersDetailModel import com.zucchini.domain.model.developers.DevelopersListModel import com.zucchini.domain.model.submit.SubmitDevInfo -import com.zucchini.domain.model.DevelopersDetailModel -import com.zucchini.domain.model.DevelopersListModel -import com.zucchini.domain.model.FindDeveloperInfo -import com.zucchini.domain.model.SubmitDevInfo interface DevelopersRepository { suspend fun getDevelopersListData(page: Int, part: String?): Result suspend fun getDevelopersDetailData(developerId: Int): Result - suspend fun createDeveloperInfo(accessToken: String, email: String? = null, submitDevInfo: SubmitDevInfo): Result + suspend fun createDeveloperInfo( + accessToken: String, + email: String? = null, + submitDevInfo: SubmitDevInfo + ): Result suspend fun searchDevelopers(developerName: String): Result> } diff --git a/domain/src/main/java/com/zucchini/domain/repository/ProjectsRepository.kt b/domain/src/main/java/com/zucchini/domain/repository/ProjectsRepository.kt index dbf96ba..b487301 100644 --- a/domain/src/main/java/com/zucchini/domain/repository/ProjectsRepository.kt +++ b/domain/src/main/java/com/zucchini/domain/repository/ProjectsRepository.kt @@ -1,10 +1,8 @@ package com.zucchini.domain.repository +import com.zucchini.domain.model.SubmitProjectInfo import com.zucchini.domain.model.projects.ProjectsDetailModel import com.zucchini.domain.model.projects.ProjectsListModel -import com.zucchini.domain.model.ProjectsDetailModel -import com.zucchini.domain.model.ProjectsListModel -import com.zucchini.domain.model.SubmitProjectInfo interface ProjectsRepository { suspend fun getProjectsListData( diff --git a/feature/projects/src/main/java/com/zucchini/submit/project/fragment/SubmitProjectFragment.kt b/feature/projects/src/main/java/com/zucchini/submit/project/fragment/SubmitProjectFragment.kt index 180d177..3e2e324 100644 --- a/feature/projects/src/main/java/com/zucchini/submit/project/fragment/SubmitProjectFragment.kt +++ b/feature/projects/src/main/java/com/zucchini/submit/project/fragment/SubmitProjectFragment.kt @@ -20,7 +20,7 @@ import androidx.core.content.ContextCompat import androidx.fragment.app.Fragment import androidx.fragment.app.activityViewModels import com.zucchini.dialog.SelectCheckBoxCommonDialog -import com.zucchini.domain.model.KeywordList +import com.zucchini.domain.model.projects.KeywordList import com.zucchini.feature.projects.R import com.zucchini.feature.projects.databinding.FragmentSubmitProjectBinding import com.zucchini.submit.project.SubmitProjectActivity