diff --git a/app/build.gradle b/app/build.gradle index b189c4f..9e96163 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,8 +1,12 @@ plugins { id 'com.android.application' + id 'org.jetbrains.kotlin.plugin.serialization' version '1.9.0' id 'org.jetbrains.kotlin.android' } +Properties properties = new Properties() +properties.load(project.rootProject.file('local.properties').newDataInputStream()) + android { namespace 'com.sopt.now' compileSdk 34 @@ -15,6 +19,9 @@ android { versionName "1.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + + buildConfigField "String", "AUTH_BASE_URL", properties["base.url"] + buildConfigField "String", "FRIEND_BASE_URL", properties["friend.base.url"] } buildTypes { @@ -33,6 +40,7 @@ android { buildFeatures { viewBinding true + buildConfig true } } @@ -48,9 +56,25 @@ dependencies { androidTestImplementation 'androidx.test.ext:junit:1.1.5' androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' -// ViewModel 의존성 설정 + // ViewModel 의존성 설정 implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2" implementation "androidx.fragment:fragment-ktx:1.6.1" implementation "androidx.activity:activity-ktx:1.8.0" + + // Network + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'org.jetbrains.kotlinx:kotlinx-serialization-json:1.4.1' + implementation 'com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:1.0.0' + + // define a BOM and its version + implementation(platform("com.squareup.okhttp3:okhttp-bom:4.10.0")) + + // define any required OkHttp artifacts without version + implementation("com.squareup.okhttp3:okhttp") + implementation("com.squareup.okhttp3:logging-interceptor") + + // Glide 라이브러리 추가 + implementation 'com.github.bumptech.glide:glide:4.12.0' + annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0' } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 110a3f6..ece8e3d 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -2,6 +2,10 @@ + + + + @@ -21,10 +26,10 @@ diff --git a/app/src/main/java/com/sopt/now/activity/SignInActivity.kt b/app/src/main/java/com/sopt/now/activity/SignInActivity.kt deleted file mode 100644 index 55c1f0a..0000000 --- a/app/src/main/java/com/sopt/now/activity/SignInActivity.kt +++ /dev/null @@ -1,62 +0,0 @@ -package com.sopt.now.activity - -import android.content.Intent -import android.os.Bundle -import android.widget.Toast -import androidx.appcompat.app.AppCompatActivity -import com.sopt.now.R -import com.sopt.now.databinding.ActivitySigninBinding - -class SignInActivity : AppCompatActivity() { - private lateinit var binding: ActivitySigninBinding - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - binding = ActivitySigninBinding.inflate(layoutInflater) - setContentView(binding.root) - - val userId = intent.getStringExtra("ID") - val userPw = intent.getStringExtra("PW") - val userName = intent.getStringExtra("Name") - val userPlace = intent.getStringExtra("Place") - - binding.btnSignInSignIn.setOnClickListener { - isSignInValid(userId, userPw, userName, userPlace) - } - - binding.btnSignInSignUp.setOnClickListener { - val intent = Intent(this, SignUpActivity::class.java) - startActivity(intent) - } - } - - private fun isSignInValid(userId: String?, userPw: String?, userName: String?, userPlace: String?) { - when { - binding.etSignInId.text.toString() != userId -> { - showToast(getString(R.string.toast_SignInActivity_InvalidId)) - } - binding.etSignInPw.text.toString() != userPw -> { - showToast(getString(R.string.toast_SignInActivity_InvalidPw)) - } - else -> { - showToast(getString(R.string.toast_SignInActivity_ValidSignIn)) - navigateToMainActivity(userId, userPw, userName, userPlace) - } - } - } - - private fun showToast(message: String) { - Toast.makeText(this, message, Toast.LENGTH_SHORT).show() - } - - private fun navigateToMainActivity(userId: String?, userPw: String?, userName: String?, userPlace: String?) { - val intent = Intent(this, MainActivity::class.java) - intent.putExtra("ID", userId) - intent.putExtra("PW", userPw) - intent.putExtra("Name", userName) - intent.putExtra("Place", userPlace) - startActivity(intent) - } -} - - - diff --git a/app/src/main/java/com/sopt/now/activity/SignUpActivity.kt b/app/src/main/java/com/sopt/now/activity/SignUpActivity.kt deleted file mode 100644 index a04a1cf..0000000 --- a/app/src/main/java/com/sopt/now/activity/SignUpActivity.kt +++ /dev/null @@ -1,63 +0,0 @@ -package com.sopt.now.activity - -import android.content.Intent -import android.os.Bundle -import android.widget.Toast -import androidx.appcompat.app.AppCompatActivity -import com.sopt.now.R -import com.sopt.now.databinding.ActivitySignupBinding - -class SignUpActivity : AppCompatActivity() { - private lateinit var binding: ActivitySignupBinding - - val ID_MIN_LENGTH = 6 - val ID_MAX_LENGTH = 10 - val PW_MIN_LENGTH = 8 - val PW_MAX_LENGTH = 12 - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - binding = ActivitySignupBinding.inflate(layoutInflater) - setContentView(binding.root) - - binding.btnSignUpSignUp.setOnClickListener { - isSignUpValid() - } - } - - private fun isSignUpValid() { - - val id = binding.etSignUpId.text.toString() - val pw = binding.etSignUpPw.text.toString() - val name = binding.etSignUpName.text.toString() - val place = binding.etSignUpPlace.text.toString() - - when { - id.isEmpty() || pw.isEmpty() || name.isEmpty() || place.isEmpty() -> { - showToast(getString(R.string.toast_SignUpActivity_InvalidSignUp_Blank)) - } - - id.length !in ID_MIN_LENGTH..ID_MAX_LENGTH || pw.length !in PW_MIN_LENGTH..PW_MAX_LENGTH -> { - showToast(getString(R.string.toast_SignUpActivity_InvalidSignUp_Blank)) - } - - else -> { - showToast(getString(R.string.toast_SignUpActivity_ValidSignUp)) - navigateToSignInActivity() - } - } - } - - private fun showToast(message: String) { - Toast.makeText(this, message, Toast.LENGTH_SHORT).show() - } - - private fun navigateToSignInActivity() { - val intent = Intent(this, SignInActivity::class.java) - intent.putExtra("ID", binding.etSignUpId.text.toString()) - intent.putExtra("PW", binding.etSignUpPw.text.toString()) - intent.putExtra("Name", binding.etSignUpName.text.toString()) - intent.putExtra("Place", binding.etSignUpPlace.text.toString()) - startActivity(intent) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/sopt/now/homeFragment/HomeFragment.kt b/app/src/main/java/com/sopt/now/homeFragment/HomeFragment.kt deleted file mode 100644 index 2600b1d..0000000 --- a/app/src/main/java/com/sopt/now/homeFragment/HomeFragment.kt +++ /dev/null @@ -1,44 +0,0 @@ -package com.sopt.now.homeFragment - -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.viewModels -import androidx.recyclerview.widget.LinearLayoutManager -import com.sopt.now.databinding.FragmentHomeBinding - -class HomeFragment : Fragment() { - - private var _binding: FragmentHomeBinding? = null - private val binding - get() = requireNotNull(_binding) { - "바인딩 객체 생성 해라" - } - private val viewModel by viewModels() - - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ): View { - _binding = FragmentHomeBinding.inflate(inflater, container, false) - return binding.root - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - val homeProfiledAdapter = HomeProfileAdapter() - binding.rvHomeFriendList.run { - adapter = homeProfiledAdapter - layoutManager = LinearLayoutManager(requireContext()) - } - homeProfiledAdapter.setProfileList(viewModel.mockMyProfile, viewModel.mockFriendProfileList) - } - - override fun onDestroyView() { - super.onDestroyView() - _binding = null - } -} \ No newline at end of file diff --git a/app/src/main/java/com/sopt/now/homeFragment/HomeProfileAdapter.kt b/app/src/main/java/com/sopt/now/homeFragment/HomeProfileAdapter.kt deleted file mode 100644 index de5395e..0000000 --- a/app/src/main/java/com/sopt/now/homeFragment/HomeProfileAdapter.kt +++ /dev/null @@ -1,68 +0,0 @@ -package com.sopt.now.homeFragment - -import android.view.LayoutInflater -import android.view.ViewGroup -import androidx.recyclerview.widget.RecyclerView -import androidx.recyclerview.widget.RecyclerView.ViewHolder -import com.sopt.now.databinding.ItemFriendBinding -import com.sopt.now.databinding.ItemMyprofileBinding -import com.sopt.now.homeFragment.homeViewHolder.FriendViewHolder -import com.sopt.now.homeFragment.homeViewHolder.MyProfileViewHolder - -class HomeProfileAdapter() : RecyclerView.Adapter() { - - private lateinit var myProfile: HomeViewObject.MyProfile - private var friendList: List = emptyList() - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { - val inflater = LayoutInflater.from(parent.context) - - return when (viewType) { - TYPE_MY_PROFILE -> { - val binding = ItemMyprofileBinding.inflate(inflater, parent, false) - MyProfileViewHolder(binding) - } - - TYPE_FRIEND_PROFILE -> { - val binding = ItemFriendBinding.inflate(inflater, parent, false) - FriendViewHolder(binding) - } - - else -> throw IllegalArgumentException("오류") - } - } - - override fun onBindViewHolder(holder: ViewHolder, position: Int) { - - when (holder) { - is MyProfileViewHolder -> { - holder.onBind(myProfile) - } - - is FriendViewHolder -> { - holder.onBind(friendList[position - 1]) - } - } - } - - override fun getItemViewType(position: Int): Int { - return if (position == 0) TYPE_MY_PROFILE else TYPE_FRIEND_PROFILE - } - - override fun getItemCount(): Int { - return friendList.size + 1 - } - - fun setProfileList( - myProfile: HomeViewObject.MyProfile, - friendProfileList: List - ) { - this.myProfile = myProfile - this.friendList = friendProfileList.toList() - notifyDataSetChanged() - } - - companion object { - const val TYPE_MY_PROFILE = 0 - const val TYPE_FRIEND_PROFILE = 1 - } -} \ No newline at end of file diff --git a/app/src/main/java/com/sopt/now/homeFragment/HomeViewModel.kt b/app/src/main/java/com/sopt/now/homeFragment/HomeViewModel.kt deleted file mode 100644 index 8884ec9..0000000 --- a/app/src/main/java/com/sopt/now/homeFragment/HomeViewModel.kt +++ /dev/null @@ -1,77 +0,0 @@ -package com.sopt.now.homeFragment - -import androidx.lifecycle.ViewModel -import com.sopt.now.R - -class HomeViewModel : ViewModel() { - - val mockMyProfile = HomeViewObject.MyProfile( - profileImage = R.drawable.sonminjae_profile, - name = "Son minjae", - place = "Korea, Seoul", - selfDescription = "i can win", - enable = true, - ) - val mockFriendProfileList = listOf( - HomeViewObject.FriendProfile( - profileImage = R.drawable.michaeljordan_profile, - name = "Michael jordan", - place = "USA, Chicago", - selfDescription = "I'm the GOAT", - ), - HomeViewObject.FriendProfile( - profileImage = R.drawable.stephcurry_profile, - name = "Steph Curry", - place = "USA, San Francisco", - selfDescription = "I can shoot with ma eyes closed", - ), - HomeViewObject.FriendProfile( - profileImage = R.drawable.nikolajokic_profile, - name = "Nikola Jokic", - place = "USA, Denver", - selfDescription = "Basketball? It's EEEEEasy", - ), - HomeViewObject.FriendProfile( - profileImage = R.drawable.lukadoncic_profile, - name = "Luka Doncic", - place = "USA, Dallas", - selfDescription = "Love you, Kyle" - ), - HomeViewObject.FriendProfile( - profileImage = R.drawable.lebronjames_profile, - name = "Lebron James", - place = "USA, Los Angeles", - selfDescription = "I'm the real GOAT" - ), - HomeViewObject.FriendProfile( - profileImage = R.drawable.kevindurant_profile, - name = "Kevin Durant", - place = "USA, Phoenix", - selfDescription = "2 CHAMPS, 2 MVP. That's it" - ), - HomeViewObject.FriendProfile( - profileImage = R.drawable.jimmybutler_profile, - name = "Jimmy Butler", - place = "USA, Miami", - selfDescription = "I NEED RINGS" - ), - HomeViewObject.FriendProfile( - profileImage = R.drawable.dirknowitzki_profile, - name = "Dirk Nowitzki", - place = "USA, Dallas", - selfDescription = "Have you heard about German Wunderkind?" - ), - HomeViewObject.FriendProfile( - profileImage = R.drawable.demianlillard_profile, - name = "Demian Lillard", - place = "USA, Portland", - selfDescription = "It's DAME TIME." - ), - HomeViewObject.FriendProfile( - profileImage = R.drawable.charlesbarkley_profile, - name = "Charles Barkley", - place = "USA, Philadelphia", - selfDescription = "CHUCK CHUCK" - ) - ) -} diff --git a/app/src/main/java/com/sopt/now/homeFragment/HomeViewObject.kt b/app/src/main/java/com/sopt/now/homeFragment/HomeViewObject.kt deleted file mode 100644 index d58dd5d..0000000 --- a/app/src/main/java/com/sopt/now/homeFragment/HomeViewObject.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.sopt.now.homeFragment - -import androidx.annotation.DrawableRes - -sealed class HomeViewObject { - data class MyProfile( - @DrawableRes val profileImage: Int, - val name: String, - val place: String, - val selfDescription: String, - val enable: Boolean, - ) - data class FriendProfile( - @DrawableRes val profileImage: Int, - val name: String, - val place: String, - val selfDescription: String, - ) -} \ No newline at end of file diff --git a/app/src/main/java/com/sopt/now/homeFragment/homeViewHolder/FriendViewHolder.kt b/app/src/main/java/com/sopt/now/homeFragment/homeViewHolder/FriendViewHolder.kt deleted file mode 100644 index 867b67b..0000000 --- a/app/src/main/java/com/sopt/now/homeFragment/homeViewHolder/FriendViewHolder.kt +++ /dev/null @@ -1,18 +0,0 @@ -package com.sopt.now.homeFragment.homeViewHolder - -import androidx.recyclerview.widget.RecyclerView -import com.sopt.now.databinding.ItemFriendBinding -import com.sopt.now.homeFragment.HomeViewObject - -class FriendViewHolder(private val binding: ItemFriendBinding) : - RecyclerView.ViewHolder(binding.root) { - - fun onBind(friendData: HomeViewObject.FriendProfile) { - binding.run { - ivFriendProfile.setImageResource(friendData.profileImage) - tvFriendName.text = friendData.name - tvFriendPlace.text = friendData.place - tvFriendSelfDescription.text = friendData.selfDescription - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/sopt/now/homeFragment/homeViewHolder/MyProfileViewHolder.kt b/app/src/main/java/com/sopt/now/homeFragment/homeViewHolder/MyProfileViewHolder.kt deleted file mode 100644 index 168b3ba..0000000 --- a/app/src/main/java/com/sopt/now/homeFragment/homeViewHolder/MyProfileViewHolder.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.sopt.now.homeFragment.homeViewHolder - -import androidx.recyclerview.widget.RecyclerView -import com.sopt.now.databinding.ItemMyprofileBinding -import com.sopt.now.homeFragment.HomeViewObject - -class MyProfileViewHolder(private val binding: ItemMyprofileBinding) : - RecyclerView.ViewHolder(binding.root) { - - fun onBind(myProfileData: HomeViewObject.MyProfile) { - binding.run { - ivMyProfileProfile.setImageResource(myProfileData.profileImage) - tvMyProfileName.text = myProfileData.name - tvMyProfilePlace.text = myProfileData.place - tvMyProfileSelfDescription.text = myProfileData.selfDescription - switchMyProfileEnable - } - } -} diff --git a/app/src/main/java/com/sopt/now/activity/MainActivity.kt b/app/src/main/java/com/sopt/now/main/MainActivity.kt similarity index 53% rename from app/src/main/java/com/sopt/now/activity/MainActivity.kt rename to app/src/main/java/com/sopt/now/main/MainActivity.kt index 5efabb9..4cb3d88 100644 --- a/app/src/main/java/com/sopt/now/activity/MainActivity.kt +++ b/app/src/main/java/com/sopt/now/main/MainActivity.kt @@ -1,13 +1,14 @@ -package com.sopt.now.activity +package com.sopt.now.main import android.os.Bundle +import android.util.Log import androidx.appcompat.app.AppCompatActivity import androidx.fragment.app.Fragment -import com.sopt.now.homeFragment.HomeFragment -import com.sopt.now.myPageFragment.MyPageFragment import com.sopt.now.R -import com.sopt.now.searchFragment.SearchFragment import com.sopt.now.databinding.ActivityMainBinding +import com.sopt.now.main.homeFragment.HomeFragment +import com.sopt.now.main.myPageFragment.MyPageFragment +import com.sopt.now.main.searchFragment.SearchFragment class MainActivity : AppCompatActivity() { private lateinit var binding: ActivityMainBinding @@ -16,10 +17,8 @@ class MainActivity : AppCompatActivity() { binding = ActivityMainBinding.inflate(layoutInflater) setContentView(binding.root) - val userId = intent.getStringExtra("ID") - val userPw = intent.getStringExtra("PW") - val userName = intent.getStringExtra("Name") - val userPlace = intent.getStringExtra("Place") + val memberId = intent.getStringExtra("memberId") + Log.e("MainActivity", "memberId: ${memberId}") val currentFragment = supportFragmentManager.findFragmentById(binding.fcvMain.id) if (currentFragment == null) { @@ -27,20 +26,15 @@ class MainActivity : AppCompatActivity() { .add(binding.fcvMain.id, HomeFragment()) .commit() } - clickBottomNavigation(userId,userPw,userName,userPlace) + clickBottomNavigation(memberId) } - private fun clickBottomNavigation(userId:String?,userPw:String?,userName:String?,userPlace:String?) { + private fun clickBottomNavigation(memberId: String?) { binding.bnvMain.setOnItemSelectedListener { when (it.itemId) { R.id.menu_home -> { - val homeFragment = HomeFragment().apply { - arguments = Bundle().apply { - putString("Name", userName) - putString("Place", userPlace) - } - } - replaceFragment(HomeFragment()) + val homeFragment = HomeFragment.newInstance(memberId) + replaceFragment(homeFragment) true } @@ -50,14 +44,7 @@ class MainActivity : AppCompatActivity() { } R.id.menu_mypage -> { - val myPageFragment = MyPageFragment().apply { - arguments = Bundle().apply { - putString("ID", userId) - putString("PW", userPw) - putString("Name", userName) - putString("Place", userPlace) - } - } + val myPageFragment = MyPageFragment.newInstance(memberId) replaceFragment(myPageFragment) true } diff --git a/app/src/main/java/com/sopt/now/main/ResponseUserInfoDto.kt b/app/src/main/java/com/sopt/now/main/ResponseUserInfoDto.kt new file mode 100644 index 0000000..7f3d7be --- /dev/null +++ b/app/src/main/java/com/sopt/now/main/ResponseUserInfoDto.kt @@ -0,0 +1,29 @@ +package com.sopt.now.main + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class ResponseUserInfoDto( + @SerialName("code") + val code: Int, + @SerialName("message") + val message: String, + @SerialName("data") + val data: User, +) { + @Serializable + data class User( + @SerialName("authenticationId") + val authenticationId: String? = "", + @SerialName("nickname") + val nickname: String? = "", + @SerialName("phone") + val phone: String? = "", + ) +} + + + + + diff --git a/app/src/main/java/com/sopt/now/main/homeFragment/HomeData.kt b/app/src/main/java/com/sopt/now/main/homeFragment/HomeData.kt new file mode 100644 index 0000000..def39d7 --- /dev/null +++ b/app/src/main/java/com/sopt/now/main/homeFragment/HomeData.kt @@ -0,0 +1,21 @@ +package com.sopt.now.main.homeFragment + +import androidx.annotation.DrawableRes +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +class HomeData { + data class UserProfile( + @DrawableRes var profileImg: Int?, + var name: String?, + var phoneNumber: String?, + var authenticationId: String?, + ) + + data class FriendProfile( + var profileImg: String, + var name: String, + var authenticationId: String + ) +} + diff --git a/app/src/main/java/com/sopt/now/main/homeFragment/HomeFragment.kt b/app/src/main/java/com/sopt/now/main/homeFragment/HomeFragment.kt new file mode 100644 index 0000000..73b2a62 --- /dev/null +++ b/app/src/main/java/com/sopt/now/main/homeFragment/HomeFragment.kt @@ -0,0 +1,69 @@ +package com.sopt.now.main.homeFragment + +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.viewModels +import androidx.lifecycle.Observer +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import com.sopt.now.databinding.FragmentHomeBinding + +class HomeFragment : Fragment() { + private var _binding: FragmentHomeBinding? = null + private val binding + get() = requireNotNull(_binding) { + "바인딩 객체를 생성해야 합니다." + } + private val viewModel by viewModels() + + companion object { + fun newInstance(memberId: String?): HomeFragment { + val fragment = HomeFragment() + val args = Bundle().apply { + putString("memberId", memberId) + } + fragment.arguments = args + return fragment + } + } + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + _binding = FragmentHomeBinding.inflate(inflater, container, false) + return binding.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + val memberId = activity?.intent?.getStringExtra("memberId") ?: "0" + val homeProfiledAdapter = HomeViewAdapter() + + viewModel.fetchUserInfo(memberId.toInt()) + viewModel.fetchFriendsInfo() + + binding.rvHomeFriendList.run { + adapter = homeProfiledAdapter + layoutManager = LinearLayoutManager(requireContext()) + homeProfiledAdapter.setUserProfileList(viewModel.userInfo.value) + homeProfiledAdapter.setFriendProfileList(viewModel.friendsInfo.value) + + viewModel.userInfo.observe(viewLifecycleOwner, Observer { userProfile -> + userProfile?.let { viewModel.updateUserProfileUI(this,it) } + }) + viewModel.friendsInfo.observe(viewLifecycleOwner, Observer { friendProfiles -> + friendProfiles?.let { viewModel.updateFriendProfilesUI(this,it) } + }) + } + } + + override fun onDestroyView() { + super.onDestroyView() + _binding = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sopt/now/main/homeFragment/HomeViewAdapter.kt b/app/src/main/java/com/sopt/now/main/homeFragment/HomeViewAdapter.kt new file mode 100644 index 0000000..89554e5 --- /dev/null +++ b/app/src/main/java/com/sopt/now/main/homeFragment/HomeViewAdapter.kt @@ -0,0 +1,75 @@ +package com.sopt.now.main.homeFragment + +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView +import com.sopt.now.databinding.ItemFriendBinding +import com.sopt.now.databinding.ItemUserBinding + +class HomeViewAdapter() : RecyclerView.Adapter() { + + private var userProfile: HomeData.UserProfile? = null + private var friendsProfile: List? = null + + companion object { + const val TYPE_MY_PROFILE = 0 + const val TYPE_FRIEND_PROFILE = 1 + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { + val inflater = LayoutInflater.from(parent.context) + + return when (viewType) { + TYPE_MY_PROFILE -> { + val binding = ItemUserBinding.inflate(inflater, parent, false) + HomeViewHolder.UserViewHolder(binding) + } + + TYPE_FRIEND_PROFILE -> { + val binding = ItemFriendBinding.inflate(inflater, parent, false) + HomeViewHolder.FriendViewHolder(binding) + } + + else -> throw IllegalArgumentException("오류") + } + } + + override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { + + when (holder) { + is HomeViewHolder.UserViewHolder -> { + userProfile?.let { holder.onBind(it) } + } + + is HomeViewHolder.FriendViewHolder -> { + friendsProfile?.getOrNull(position - 1)?.let { holder.onBind(it) } + } + } + } + + override fun getItemViewType(position: Int): Int { + return if (position == 0) TYPE_MY_PROFILE else TYPE_FRIEND_PROFILE + } + + override fun getItemCount(): Int { + return friendsProfile?.size?.plus(1) ?: 0 + } + + fun setUserProfileList( + myProfile: HomeData.UserProfile?, + ) { + if (myProfile != null) { + this.userProfile = myProfile + } + notifyDataSetChanged() + } + + fun setFriendProfileList( + friendProfileList: List? + ) { + if (friendProfileList != null) { + this.friendsProfile = friendProfileList + } + notifyDataSetChanged() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sopt/now/main/homeFragment/HomeViewHolder.kt b/app/src/main/java/com/sopt/now/main/homeFragment/HomeViewHolder.kt new file mode 100644 index 0000000..4e83498 --- /dev/null +++ b/app/src/main/java/com/sopt/now/main/homeFragment/HomeViewHolder.kt @@ -0,0 +1,36 @@ +package com.sopt.now.main.homeFragment + +import androidx.lifecycle.LiveData +import androidx.recyclerview.widget.RecyclerView +import com.bumptech.glide.Glide +import com.sopt.now.R +import com.sopt.now.databinding.ItemFriendBinding +import com.sopt.now.databinding.ItemUserBinding +import com.sopt.now.main.ResponseUserInfoDto + +class HomeViewHolder { + class UserViewHolder(private val binding: ItemUserBinding) : + RecyclerView.ViewHolder(binding.root) { + fun onBind(userInfo: HomeData.UserProfile) { + binding.run { + Glide.with(root.context).load(userInfo.profileImg).into(ivUserProfile) + tvUserName.text = userInfo.name + tvUserPhoneNumber.text = userInfo.phoneNumber + tvUserAuthenticationId.text = userInfo.authenticationId + } + } + } + + class FriendViewHolder(private val binding: ItemFriendBinding) : + RecyclerView.ViewHolder(binding.root) { + fun onBind(friendInfo: HomeData.FriendProfile) { + binding.run { + Glide.with(root.context).load(friendInfo.profileImg).into(ivFriendProfile) + tvFriendName.text = friendInfo.name + tvFriendSelfDescription.text = friendInfo.authenticationId + } + } + } +} + + diff --git a/app/src/main/java/com/sopt/now/main/homeFragment/HomeViewModel.kt b/app/src/main/java/com/sopt/now/main/homeFragment/HomeViewModel.kt new file mode 100644 index 0000000..c6db394 --- /dev/null +++ b/app/src/main/java/com/sopt/now/main/homeFragment/HomeViewModel.kt @@ -0,0 +1,86 @@ +package com.sopt.now.main.homeFragment + +import android.util.Log +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import androidx.recyclerview.widget.RecyclerView +import com.sopt.now.R +import com.sopt.now.main.ResponseUserInfoDto +import com.sopt.now.service.ServicePool +import retrofit2.Call +import retrofit2.Callback +import retrofit2.Response + +class HomeViewModel : ViewModel() { + + private val _userInfo = MutableLiveData() + val userInfo: LiveData + get() = _userInfo + + private val _friendsInfo = MutableLiveData?>() + val friendsInfo: LiveData?> + get() = _friendsInfo + + private val userService by lazy { ServicePool.userService } + private val friendService by lazy { ServicePool.friendService } + + fun fetchUserInfo(userId: Int) { + userService.getUserInfo(userId).enqueue(object : Callback { + override fun onResponse( + call: Call, + response: Response + ) { + if (response.isSuccessful) { + val responseUserInfoDto = response.body() + val userProfileInfo = responseUserInfoDto?.data?.let { userData -> + HomeData.UserProfile( + R.drawable.sonminjae_profile, + userData.nickname, + userData.phone, + userData.authenticationId) + } + _userInfo.value = userProfileInfo + } + } + override fun onFailure(call: Call, t: Throwable) { + Log.e("HomeViewModel", t.message.toString()) + } + }) + } + + fun fetchFriendsInfo() { + friendService.getFriendsInfo(2).enqueue(object : Callback { + override fun onResponse( + call: Call, + response: Response + ) { + if (response.isSuccessful) { + val responseFriendsInfoDto = response.body() + val friendProfiles = responseFriendsInfoDto?.data?.map { friendData -> + HomeData.FriendProfile( + friendData.avatar, + "${friendData.firstName} ${ friendData.lastName}", + friendData.email + ) + } + _friendsInfo.postValue(friendProfiles) + } + } + + override fun onFailure(call: Call, t: Throwable) { + Log.e("HomeViewModel", t.message.toString()) + } + }) + } + fun updateUserProfileUI(view: RecyclerView, it: HomeData.UserProfile) { + val adapter = view.adapter as? HomeViewAdapter + adapter?.setUserProfileList(it) + } + + + fun updateFriendProfilesUI(view: RecyclerView, it: List) { + val adapter = view.adapter as? HomeViewAdapter + adapter?.setFriendProfileList(it) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sopt/now/main/homeFragment/ResponseFriendsInfoDto.kt b/app/src/main/java/com/sopt/now/main/homeFragment/ResponseFriendsInfoDto.kt new file mode 100644 index 0000000..dd06c50 --- /dev/null +++ b/app/src/main/java/com/sopt/now/main/homeFragment/ResponseFriendsInfoDto.kt @@ -0,0 +1,42 @@ +package com.sopt.now.main.homeFragment + +import kotlinx.serialization.Serializable +import kotlinx.serialization.SerialName + +@Serializable +data class ResponseFriendsInfoDto( + @SerialName("page") + val page: Int, + @SerialName("per_page") + val perPage: Int, + @SerialName("total") + val total: Int, + @SerialName("total_pages") + val totalPages: Int, + @SerialName("data") + val data: List, + @SerialName("support") + val support: Support +) { + @Serializable + data class FriendInfo( + @SerialName("id") + val id: Int, + @SerialName("email") + val email: String, + @SerialName("first_name") + val firstName: String, + @SerialName("last_name") + val lastName: String, + @SerialName("avatar") + val avatar: String + ) + + @Serializable + data class Support( + @SerialName("url") + val url: String, + @SerialName("text") + val text: String + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/sopt/now/main/myPageFragment/MyPageFragment.kt b/app/src/main/java/com/sopt/now/main/myPageFragment/MyPageFragment.kt new file mode 100644 index 0000000..45cc66a --- /dev/null +++ b/app/src/main/java/com/sopt/now/main/myPageFragment/MyPageFragment.kt @@ -0,0 +1,84 @@ +package com.sopt.now.main.myPageFragment + +import android.os.Bundle +import android.util.Log +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.Toast +import androidx.fragment.app.Fragment +import com.sopt.now.service.ServicePool +import com.sopt.now.main.ResponseUserInfoDto +import com.sopt.now.databinding.FragmentMypageBinding +import retrofit2.Call +import retrofit2.Callback +import retrofit2.Response + +class MyPageFragment : Fragment() { + private var _binding: FragmentMypageBinding? = null + private val binding + get() = requireNotNull(_binding) { + "바인딩 객체를 생성해야 합니다." + } + + private var memberId: String? = null + + companion object { + fun newInstance(memberId: String?): MyPageFragment { + val fragment = MyPageFragment() + val args = Bundle().apply { + putString("memberId", memberId) + } + fragment.arguments = args + return fragment + } + } + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + _binding = FragmentMypageBinding.inflate(inflater, container, false) + return binding.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + memberId = activity?.intent?.getStringExtra("memberId") ?: "0" + + memberId?.let { memberId -> + ServicePool.userService.getUserInfo(memberId.toInt()).enqueue(object : + Callback { + override fun onResponse( + call: Call, + response: Response + ) { + if (response.isSuccessful) { + val userInfo = response.body()?.data + + userInfo?.let { + binding.tvMyPageId.text = " ${it.authenticationId}" + binding.tvMyPagePw.text = " ${it.nickname}" + binding.tvMyPagePhoneNumber.text = " ${it.phone}" + } + } else { + Toast.makeText(requireContext(), "회원 정보를 가져오는데 실패했습니다.", Toast.LENGTH_SHORT) + .show() + } + } + + override fun onFailure(call: Call, t: Throwable) { + Log.e("MyPageFragment", "Failed to fetch user info: ${t.message}") + Toast.makeText(requireContext(), "서버와의 통신 실패", Toast.LENGTH_SHORT).show() + } + }) + } + } + + override fun onDestroyView() { + super.onDestroyView() + _binding = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sopt/now/searchFragment/SearchFragment.kt b/app/src/main/java/com/sopt/now/main/searchFragment/SearchFragment.kt similarity index 89% rename from app/src/main/java/com/sopt/now/searchFragment/SearchFragment.kt rename to app/src/main/java/com/sopt/now/main/searchFragment/SearchFragment.kt index 6c4c628..ec452e8 100644 --- a/app/src/main/java/com/sopt/now/searchFragment/SearchFragment.kt +++ b/app/src/main/java/com/sopt/now/main/searchFragment/SearchFragment.kt @@ -1,4 +1,4 @@ -package com.sopt.now.searchFragment +package com.sopt.now.main.searchFragment import android.os.Bundle import android.view.LayoutInflater @@ -11,7 +11,7 @@ class SearchFragment : Fragment() { private var _binding: FragmentSearchBinding? = null private val binding get() = requireNotNull(_binding) { - "바인딩 객체 생성 해라" + "바인딩 객체를 생성해야 합니다." } override fun onCreateView( diff --git a/app/src/main/java/com/sopt/now/myPageFragment/MyPageFragment.kt b/app/src/main/java/com/sopt/now/myPageFragment/MyPageFragment.kt deleted file mode 100644 index 66bf8ab..0000000 --- a/app/src/main/java/com/sopt/now/myPageFragment/MyPageFragment.kt +++ /dev/null @@ -1,48 +0,0 @@ -package com.sopt.now.myPageFragment - -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import androidx.fragment.app.Fragment -import com.sopt.now.databinding.FragmentMypageBinding - -class MyPageFragment : Fragment() { - private var _binding: FragmentMypageBinding? = null - private val binding - get() = requireNotNull(_binding) { - "바인딩 객체 생성 해라" - } - - private var userId: String? = null - private var userPw: String? = null - private var userName: String? = null - private var userPlace: String? = null - - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ): View { - _binding = FragmentMypageBinding.inflate(inflater, container, false) - userId = arguments?.getString("ID") - userPw = arguments?.getString("PW") - userName = arguments?.getString("Name") - userPlace = arguments?.getString("Place") - return binding.root - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - - binding.tvMyPageShowId.text = userId - binding.tvMyPageShowPw.text = userPw - binding.tvMyPageShowName.text = userName - binding.tvMyPageShowPlace.text = userPlace - } - - override fun onDestroyView() { - super.onDestroyView() - _binding = null - } -} \ No newline at end of file diff --git a/app/src/main/java/com/sopt/now/service/ApiFactory.kt b/app/src/main/java/com/sopt/now/service/ApiFactory.kt new file mode 100644 index 0000000..3b58c85 --- /dev/null +++ b/app/src/main/java/com/sopt/now/service/ApiFactory.kt @@ -0,0 +1,46 @@ +package com.sopt.now.service + +import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory +import com.sopt.now.BuildConfig +import com.sopt.now.BuildConfig.AUTH_BASE_URL +import com.sopt.now.BuildConfig.FRIEND_BASE_URL +import kotlinx.serialization.json.Json +import okhttp3.MediaType.Companion.toMediaType +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import retrofit2.Retrofit +import java.util.concurrent.TimeUnit + + +object ApiFactory { + private const val AUTH_BASE_URL: String = BuildConfig.AUTH_BASE_URL + private const val FRIEND_BASE_URL: String = BuildConfig.FRIEND_BASE_URL + + // HTTP 로깅 인터셉터 설정 + private val loggingInterceptor = HttpLoggingInterceptor().apply { + level = HttpLoggingInterceptor.Level.BODY + } + + // OkHttpClient 설정 + private val okHttpClient = OkHttpClient.Builder() + .addInterceptor(loggingInterceptor) // 로깅 인터셉터 추가 + .connectTimeout(30, TimeUnit.SECONDS) // 연결 타임아웃 + .readTimeout(30, TimeUnit.SECONDS) // 읽기 타임아웃 + .writeTimeout(30, TimeUnit.SECONDS) // 쓰기 타임아웃 + .build() + + fun provideRetrofit(url:String): Retrofit { + return Retrofit.Builder() + .baseUrl(url) + .client(okHttpClient) + .addConverterFactory(Json.asConverterFactory("application/json".toMediaType())) + .build() + } + inline fun create(url: String): T = provideRetrofit(url).create(T::class.java) +} + +object ServicePool { + val authService = ApiFactory.create(AUTH_BASE_URL) + val userService = ApiFactory.create(AUTH_BASE_URL) + val friendService = ApiFactory.create(FRIEND_BASE_URL) +} \ No newline at end of file diff --git a/app/src/main/java/com/sopt/now/service/AuthService.kt b/app/src/main/java/com/sopt/now/service/AuthService.kt new file mode 100644 index 0000000..a4b7014 --- /dev/null +++ b/app/src/main/java/com/sopt/now/service/AuthService.kt @@ -0,0 +1,25 @@ +package com.sopt.now.service + +import com.sopt.now.main.ResponseUserInfoDto +import com.sopt.now.signIn.RequestSignInDto +import com.sopt.now.signUp.RequestSignUpDto +import com.sopt.now.signIn.ResponseSignInDto +import com.sopt.now.signUp.ResponseSignUpDto +import retrofit2.Call +import retrofit2.Response +import retrofit2.http.Body +import retrofit2.http.GET +import retrofit2.http.Header +import retrofit2.http.POST + +interface AuthService { + @POST("member/join") + suspend fun signUp( + @Body request: RequestSignUpDto, + ): Response + + @POST("member/login") + fun signIn( + @Body request: RequestSignInDto, + ): Call +} \ No newline at end of file diff --git a/app/src/main/java/com/sopt/now/service/FriendService.kt b/app/src/main/java/com/sopt/now/service/FriendService.kt new file mode 100644 index 0000000..276865c --- /dev/null +++ b/app/src/main/java/com/sopt/now/service/FriendService.kt @@ -0,0 +1,13 @@ +package com.sopt.now.service + +import com.sopt.now.main.homeFragment.ResponseFriendsInfoDto +import retrofit2.Call +import retrofit2.http.GET +import retrofit2.http.Query + +interface FriendService { + @GET("/api/users") + fun getFriendsInfo( + @Query("page") page: Int, + ): Call +} \ No newline at end of file diff --git a/app/src/main/java/com/sopt/now/service/UserService.kt b/app/src/main/java/com/sopt/now/service/UserService.kt new file mode 100644 index 0000000..58bea8c --- /dev/null +++ b/app/src/main/java/com/sopt/now/service/UserService.kt @@ -0,0 +1,13 @@ +package com.sopt.now.service + +import com.sopt.now.main.ResponseUserInfoDto +import retrofit2.Call +import retrofit2.http.GET +import retrofit2.http.Header + +interface UserService { + @GET("member/info") + fun getUserInfo( + @Header("memberId") memberId: Int, + ): Call +} \ No newline at end of file diff --git a/app/src/main/java/com/sopt/now/signIn/RequestSignInDto.kt b/app/src/main/java/com/sopt/now/signIn/RequestSignInDto.kt new file mode 100644 index 0000000..1bb6002 --- /dev/null +++ b/app/src/main/java/com/sopt/now/signIn/RequestSignInDto.kt @@ -0,0 +1,12 @@ +package com.sopt.now.signIn + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class RequestSignInDto( + @SerialName("authenticationId") + val authenticationId: String, + @SerialName("password") + val password: String, +) \ No newline at end of file diff --git a/app/src/main/java/com/sopt/now/signIn/ResponseSignInDto.kt b/app/src/main/java/com/sopt/now/signIn/ResponseSignInDto.kt new file mode 100644 index 0000000..e27244d --- /dev/null +++ b/app/src/main/java/com/sopt/now/signIn/ResponseSignInDto.kt @@ -0,0 +1,12 @@ +package com.sopt.now.signIn + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class ResponseSignInDto( + @SerialName("code") + val status: Int, + @SerialName("message") + val message: String, +) \ No newline at end of file diff --git a/app/src/main/java/com/sopt/now/signIn/SignInActivity.kt b/app/src/main/java/com/sopt/now/signIn/SignInActivity.kt new file mode 100644 index 0000000..e19c097 --- /dev/null +++ b/app/src/main/java/com/sopt/now/signIn/SignInActivity.kt @@ -0,0 +1,55 @@ +package com.sopt.now.signIn + +import android.content.Intent +import android.os.Bundle +import android.widget.Toast +import androidx.activity.viewModels +import androidx.appcompat.app.AppCompatActivity +import com.sopt.now.main.MainActivity +import com.sopt.now.signUp.SignUpActivity +import com.sopt.now.databinding.ActivitySigninBinding + +class SignInActivity : AppCompatActivity() { + + private val binding by lazy { ActivitySigninBinding.inflate(layoutInflater) } + private val viewModel by viewModels() + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(binding.root) + initViews() + initObserver() + } + + private fun initViews() { + binding.btnSignInSignIn.setOnClickListener { + viewModel.signIn(getSignInRequestDto()) + } + + binding.btnSignInSignUp.setOnClickListener { + val intent = Intent(this, SignUpActivity::class.java) + startActivity(intent) + } + } + + private fun initObserver() { + viewModel.liveData.observe(this) { + signInState -> + Toast.makeText(this,signInState.message,Toast.LENGTH_SHORT).show() + if(signInState.isSuccess) { + val intent = Intent(this@SignInActivity, MainActivity::class.java).apply{ + signInState.memberId?.let { memberId -> putExtra("memberId",memberId) } + } + startActivity(intent) + } + } + } + + private fun getSignInRequestDto(): RequestSignInDto { + val id = binding.etSignInId.text.toString() + val password = binding.etSignInPw.text.toString() + return RequestSignInDto( + authenticationId = id, + password = password, + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sopt/now/signIn/SignInState.kt b/app/src/main/java/com/sopt/now/signIn/SignInState.kt new file mode 100644 index 0000000..8399f3f --- /dev/null +++ b/app/src/main/java/com/sopt/now/signIn/SignInState.kt @@ -0,0 +1,7 @@ +package com.sopt.now.signIn + +data class SignInState( + val isSuccess: Boolean, + val message: String, + val memberId: String? = "" +) \ No newline at end of file diff --git a/app/src/main/java/com/sopt/now/signIn/SignInViewModel.kt b/app/src/main/java/com/sopt/now/signIn/SignInViewModel.kt new file mode 100644 index 0000000..41a83bc --- /dev/null +++ b/app/src/main/java/com/sopt/now/signIn/SignInViewModel.kt @@ -0,0 +1,49 @@ +package com.sopt.now.signIn + +import android.util.Log +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.sopt.now.service.ServicePool +import retrofit2.Call +import retrofit2.Callback +import retrofit2.Response + +class SignInViewModel : ViewModel() { + private val authService by lazy { ServicePool.authService } + val liveData = MutableLiveData() + + fun signIn(request: RequestSignInDto) { + authService.signIn(request).enqueue(object : Callback { + override fun onResponse( + call: Call, + response: Response, + ) { + if (response.isSuccessful) { + val data: ResponseSignInDto? = response.body() + val memberId = response.headers()["location"] + liveData.value = SignInState( + isSuccess = true, + message = "로그인 성공! 유저의 ID는 $memberId 입니둥", + memberId = memberId + ) + Log.d("SignIn", "data: $data, userId: $memberId") + } else { + val error = response.message() + liveData.value = SignInState( + isSuccess = false, + message = "로그인 실패 $error", + memberId = null + ) + } + } + + override fun onFailure(call: Call, t: Throwable) { + liveData.value = SignInState( + isSuccess = false, + message = "서버 에러", + memberId = null + ) + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sopt/now/signUp/RequestSignUpDto.kt b/app/src/main/java/com/sopt/now/signUp/RequestSignUpDto.kt new file mode 100644 index 0000000..25c0ef9 --- /dev/null +++ b/app/src/main/java/com/sopt/now/signUp/RequestSignUpDto.kt @@ -0,0 +1,16 @@ +package com.sopt.now.signUp + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class RequestSignUpDto( + @SerialName("authenticationId") + val authenticationId: String, + @SerialName("password") + val password: String, + @SerialName("nickname") + val nickname: String, + @SerialName("phone") + val phone: String, +) \ No newline at end of file diff --git a/app/src/main/java/com/sopt/now/signUp/ResponseSignUpDto.kt b/app/src/main/java/com/sopt/now/signUp/ResponseSignUpDto.kt new file mode 100644 index 0000000..5247516 --- /dev/null +++ b/app/src/main/java/com/sopt/now/signUp/ResponseSignUpDto.kt @@ -0,0 +1,12 @@ +package com.sopt.now.signUp + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class ResponseSignUpDto( + @SerialName("code") + val status: Int, + @SerialName("message") + val message: String, +) \ No newline at end of file diff --git a/app/src/main/java/com/sopt/now/signUp/SignUpActivity.kt b/app/src/main/java/com/sopt/now/signUp/SignUpActivity.kt new file mode 100644 index 0000000..d04813c --- /dev/null +++ b/app/src/main/java/com/sopt/now/signUp/SignUpActivity.kt @@ -0,0 +1,58 @@ +package com.sopt.now.signUp + +import android.content.Intent +import android.os.Bundle +import android.widget.Toast +import androidx.activity.viewModels +import androidx.appcompat.app.AppCompatActivity +import com.sopt.now.databinding.ActivitySignupBinding +import com.sopt.now.signIn.SignInActivity + +class SignUpActivity : AppCompatActivity() { + + private val binding by lazy { ActivitySignupBinding.inflate(layoutInflater) } + private val viewModel by viewModels() + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(binding.root) + initViews() + initObserver() + } + + private fun initViews() { + binding.btnSignUpSignUp.setOnClickListener { + viewModel.signUp(getSignUpRequestDto()) + } + } + + private fun initObserver() { + viewModel.liveData.observe(this) { + showToast(it.message) + } + + viewModel.navigateToSignIn.observe(this) { navigate -> + if (navigate) { + val intent = Intent(this, SignInActivity::class.java) + startActivity(intent) + viewModel.doneNavigatingToSignIn() + } + } + } + + private fun getSignUpRequestDto(): RequestSignUpDto { + val id = binding.etSignUpId.text.toString() + val password = binding.etSignUpPw.text.toString() + val nickname = binding.etSignUpName.text.toString() + val phoneNumber = binding.etSignUpPhoneNumber.text.toString() + return RequestSignUpDto( + authenticationId = id, + password = password, + nickname = nickname, + phone = phoneNumber + ) + } + + private fun showToast(message: String) { + Toast.makeText(this, message, Toast.LENGTH_SHORT).show() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sopt/now/signUp/SignUpState.kt b/app/src/main/java/com/sopt/now/signUp/SignUpState.kt new file mode 100644 index 0000000..eb5b271 --- /dev/null +++ b/app/src/main/java/com/sopt/now/signUp/SignUpState.kt @@ -0,0 +1,6 @@ +package com.sopt.now.signUp + +data class SignUpState( + val isSuccess: Boolean, + val message: String +) diff --git a/app/src/main/java/com/sopt/now/signUp/SignUpViewModel.kt b/app/src/main/java/com/sopt/now/signUp/SignUpViewModel.kt new file mode 100644 index 0000000..d39f77d --- /dev/null +++ b/app/src/main/java/com/sopt/now/signUp/SignUpViewModel.kt @@ -0,0 +1,42 @@ +package com.sopt.now.signUp + +import android.util.Log +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.sopt.now.service.ServicePool +import kotlinx.coroutines.launch +import retrofit2.Call +import retrofit2.Callback +import retrofit2.Response + +class SignUpViewModel : ViewModel() { + private val authService by lazy { ServicePool.authService } + val liveData = MutableLiveData() + + private val _navigateToSignIn = MutableLiveData() + val navigateToSignIn: LiveData + get() = _navigateToSignIn + + fun signUp(request: RequestSignUpDto) { + viewModelScope.launch { + runCatching { + authService.signUp(request) + }.onSuccess { + liveData.value = SignUpState(true, "회원가입 성공") + moveToSignInActivity() + }.onFailure { + liveData.value = SignUpState(false, "회원가입 실패") + } + } + } + + private fun moveToSignInActivity() { + _navigateToSignIn.value = true + } + + fun doneNavigatingToSignIn() { + _navigateToSignIn.value = false + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable/charlesbarkley_profile.png b/app/src/main/res/drawable/charlesbarkley_profile.png deleted file mode 100644 index f6771a9..0000000 Binary files a/app/src/main/res/drawable/charlesbarkley_profile.png and /dev/null differ diff --git a/app/src/main/res/drawable/demianlillard_profile.png b/app/src/main/res/drawable/demianlillard_profile.png deleted file mode 100644 index b6d338b..0000000 Binary files a/app/src/main/res/drawable/demianlillard_profile.png and /dev/null differ diff --git a/app/src/main/res/drawable/dirknowitzki_profile.png b/app/src/main/res/drawable/dirknowitzki_profile.png deleted file mode 100644 index c4a1530..0000000 Binary files a/app/src/main/res/drawable/dirknowitzki_profile.png and /dev/null differ diff --git a/app/src/main/res/drawable/jimmybutler_profile.png b/app/src/main/res/drawable/jimmybutler_profile.png deleted file mode 100644 index 4b2853e..0000000 Binary files a/app/src/main/res/drawable/jimmybutler_profile.png and /dev/null differ diff --git a/app/src/main/res/drawable/kevindurant_profile.png b/app/src/main/res/drawable/kevindurant_profile.png deleted file mode 100644 index c8264c4..0000000 Binary files a/app/src/main/res/drawable/kevindurant_profile.png and /dev/null differ diff --git a/app/src/main/res/drawable/lebronjames_profile.png b/app/src/main/res/drawable/lebronjames_profile.png deleted file mode 100644 index 4231f99..0000000 Binary files a/app/src/main/res/drawable/lebronjames_profile.png and /dev/null differ diff --git a/app/src/main/res/drawable/lukadoncic_profile.png b/app/src/main/res/drawable/lukadoncic_profile.png deleted file mode 100644 index 93b94b6..0000000 Binary files a/app/src/main/res/drawable/lukadoncic_profile.png and /dev/null differ diff --git a/app/src/main/res/drawable/michaeljordan_profile.png b/app/src/main/res/drawable/michaeljordan_profile.png deleted file mode 100644 index 754b9e9..0000000 Binary files a/app/src/main/res/drawable/michaeljordan_profile.png and /dev/null differ diff --git a/app/src/main/res/drawable/nikolajokic_profile.png b/app/src/main/res/drawable/nikolajokic_profile.png deleted file mode 100644 index 7b783a4..0000000 Binary files a/app/src/main/res/drawable/nikolajokic_profile.png and /dev/null differ diff --git a/app/src/main/res/drawable/stephcurry_profile.png b/app/src/main/res/drawable/stephcurry_profile.png deleted file mode 100644 index dfe3088..0000000 Binary files a/app/src/main/res/drawable/stephcurry_profile.png and /dev/null differ diff --git a/app/src/main/res/layout/activity_signup.xml b/app/src/main/res/layout/activity_signup.xml index 9debf1f..374cb9f 100644 --- a/app/src/main/res/layout/activity_signup.xml +++ b/app/src/main/res/layout/activity_signup.xml @@ -4,7 +4,6 @@ android:layout_width="match_parent" android:layout_height="match_parent"> - - + android:hint="@string/et_SignUp_PhoneNumber" + app:layout_constraintTop_toBottomOf="@+id/tvSignUpPhoneNumber" />