Merge pull request #9 from shaulascr/gracia

fetch my store profile
This commit is contained in:
Gracia Hotmauli
2025-03-30 01:19:06 +07:00
committed by GitHub
13 changed files with 244 additions and 184 deletions

View File

@ -23,7 +23,7 @@ android {
buildTypes {
release {
buildConfigField("String", "BASE_URL", "\"http://192.168.1.4:3000/\"")
buildConfigField("String", "BASE_URL", "\"http://192.168.100.156:3000/\"")
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
@ -31,7 +31,7 @@ android {
)
}
debug {
buildConfigField("String", "BASE_URL", "\"http://192.168.1.4:3000/\"")
buildConfigField("String", "BASE_URL", "\"http://192.168.100.156:3000/\"")
}
}
compileOptions {
@ -66,13 +66,14 @@ dependencies {
androidTestImplementation(libs.androidx.espresso.core)
//retrofit
implementation(libs.retrofit)
implementation(libs.converter.gson)
implementation(libs.logging.interceptor)
implementation("com.squareup.retrofit2:retrofit:2.9.0")
implementation("com.squareup.retrofit2:converter-gson:2.9.0")
implementation("com.squareup.okhttp3:logging-interceptor:4.11.0")
implementation(libs.glide)
implementation(libs.androidx.paging.runtime)
implementation(libs.androidx.swiperefreshlayout)
implementation("com.github.bumptech.glide:glide:4.16.0")
implementation("androidx.paging:paging-runtime:3.2.1")
implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0")
implementation("de.hdodenhof:circleimageview:3.1.0")
// implementation(libs.hilt.android)

View File

@ -42,7 +42,7 @@
android:name=".ui.profile.mystore.profile.EditStoreProfileActivity"
android:exported="false" />
<activity
android:name=".ui.profile.mystore.TokoSayaActivity"
android:name=".ui.profile.mystore.MyStoreActivity"
android:exported="false" />
<activity
android:name=".ui.product.DetailProductActivity"

View File

@ -0,0 +1,102 @@
package com.alya.ecommerce_serang.data.api.dto
import com.google.gson.annotations.SerializedName
data class Store(
@field:SerializedName("approval_reason")
val approvalReason: String,
@field:SerializedName("store_status")
val storeStatus: String,
@field:SerializedName("sppirt")
val sppirt: String,
@field:SerializedName("user_name")
val userName: String,
@field:SerializedName("nib")
val nib: String,
@field:SerializedName("latitude")
val latitude: String,
@field:SerializedName("store_type_id")
val storeTypeId: Int,
@field:SerializedName("balance")
val balance: String,
@field:SerializedName("street")
val street: String,
@field:SerializedName("store_name")
val storeName: String,
@field:SerializedName("user_phone")
val userPhone: String,
@field:SerializedName("halal")
val halal: String,
@field:SerializedName("id")
val id: Int,
@field:SerializedName("email")
val email: String,
@field:SerializedName("store_image")
val storeImage: Any,
@field:SerializedName("longitude")
val longitude: String,
@field:SerializedName("store_id")
val storeId: Int,
@field:SerializedName("is_store_location")
val isStoreLocation: Boolean,
@field:SerializedName("ktp")
val ktp: String,
@field:SerializedName("approval_status")
val approvalStatus: String,
@field:SerializedName("npwp")
val npwp: String,
@field:SerializedName("store_type")
val storeType: String,
@field:SerializedName("is_on_leave")
val isOnLeave: Boolean,
@field:SerializedName("user_id")
val userId: Int,
@field:SerializedName("province_id")
val provinceId: Int,
@field:SerializedName("phone")
val phone: String,
@field:SerializedName("subdistrict")
val subdistrict: String,
@field:SerializedName("recipient")
val recipient: String,
@field:SerializedName("detail")
val detail: String,
@field:SerializedName("postal_code")
val postalCode: String,
@field:SerializedName("store_description")
val storeDescription: String,
@field:SerializedName("city_id")
val cityId: Int
)

View File

@ -1,5 +1,6 @@
package com.alya.ecommerce_serang.data.api.response
import com.alya.ecommerce_serang.data.api.dto.Store
import com.google.gson.annotations.SerializedName
data class StoreResponse(
@ -17,105 +18,6 @@ data class StoreResponse(
val message: String
)
data class Store(
@field:SerializedName("approval_reason")
val approvalReason: String,
@field:SerializedName("store_status")
val storeStatus: String,
@field:SerializedName("sppirt")
val sppirt: String,
@field:SerializedName("user_name")
val userName: String,
@field:SerializedName("nib")
val nib: String,
@field:SerializedName("latitude")
val latitude: String,
@field:SerializedName("store_type_id")
val storeTypeId: Int,
@field:SerializedName("balance")
val balance: String,
@field:SerializedName("street")
val street: String,
@field:SerializedName("store_name")
val storeName: String,
@field:SerializedName("user_phone")
val userPhone: String,
@field:SerializedName("halal")
val halal: String,
@field:SerializedName("id")
val id: Int,
@field:SerializedName("email")
val email: String,
@field:SerializedName("store_image")
val storeImage: Any,
@field:SerializedName("longitude")
val longitude: String,
@field:SerializedName("store_id")
val storeId: Int,
@field:SerializedName("is_store_location")
val isStoreLocation: Boolean,
@field:SerializedName("ktp")
val ktp: String,
@field:SerializedName("approval_status")
val approvalStatus: String,
@field:SerializedName("npwp")
val npwp: String,
@field:SerializedName("store_type")
val storeType: String,
@field:SerializedName("is_on_leave")
val isOnLeave: Boolean,
@field:SerializedName("user_id")
val userId: Int,
@field:SerializedName("province_id")
val provinceId: Int,
@field:SerializedName("phone")
val phone: String,
@field:SerializedName("subdistrict")
val subdistrict: String,
@field:SerializedName("recipient")
val recipient: String,
@field:SerializedName("detail")
val detail: String,
@field:SerializedName("postal_code")
val postalCode: String,
@field:SerializedName("store_description")
val storeDescription: String,
@field:SerializedName("city_id")
val cityId: Int
)
data class ShippingItem(
@field:SerializedName("courier")

View File

@ -63,5 +63,5 @@ interface ApiService {
@GET("mystore")
fun getStore (): Call<StoreResponse>
suspend fun getStore (): Response<StoreResponse>
}

View File

@ -0,0 +1,31 @@
package com.alya.ecommerce_serang.data.repository
import android.util.Log
import com.alya.ecommerce_serang.data.api.dto.Store
import com.alya.ecommerce_serang.data.api.response.StoreResponse
import com.alya.ecommerce_serang.data.api.retrofit.ApiService
import retrofit2.HttpException
import java.io.IOException
class MyStoreRepository(private val apiService: ApiService) {
suspend fun fetchMyStoreProfile(): Result<Store?> {
return try {
val response = apiService.getStore()
if (response.isSuccessful) {
val storeResponse: StoreResponse? = response.body()
Result.Success(storeResponse?.store) // ✅ Return Success with Store data
} else {
val errorMessage = response.errorBody()?.string() ?: "Unknown API error"
Log.e("MyStoreRepository", "Error: $errorMessage")
Result.Error(HttpException(response)) // ✅ Wrap API error in Result.Error
}
} catch (e: IOException) {
Log.e("MyStoreRepository", "Network error: ${e.message}")
Result.Error(e) // ✅ Handle network-related errors
} catch (e: Exception) {
Log.e("MyStoreRepository", "Unexpected error: ${e.message}")
Result.Error(e) // ✅ Handle unexpected errors
}
}
}

View File

@ -4,9 +4,9 @@ import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.alya.ecommerce_serang.data.api.dto.Store
import com.alya.ecommerce_serang.data.api.response.Product
import com.alya.ecommerce_serang.data.api.response.ReviewsItem
import com.alya.ecommerce_serang.data.api.response.Store
import com.alya.ecommerce_serang.data.repository.ProductRepository
import kotlinx.coroutines.launch

View File

@ -15,7 +15,7 @@ import com.alya.ecommerce_serang.data.api.dto.UserProfile
import com.alya.ecommerce_serang.data.api.retrofit.ApiConfig
import com.alya.ecommerce_serang.data.repository.UserRepository
import com.alya.ecommerce_serang.databinding.FragmentProfileBinding
import com.alya.ecommerce_serang.ui.profile.mystore.TokoSayaActivity
import com.alya.ecommerce_serang.ui.profile.mystore.MyStoreActivity
import com.alya.ecommerce_serang.utils.BaseViewModelFactory
import com.alya.ecommerce_serang.utils.SessionManager
import com.bumptech.glide.Glide
@ -54,7 +54,7 @@ class ProfileFragment : Fragment() {
viewModel.loadUserProfile()
binding.cardBukaToko.setOnClickListener{
val intentBuka = Intent(requireContext(), TokoSayaActivity::class.java)
val intentBuka = Intent(requireContext(), MyStoreActivity::class.java)
startActivity(intentBuka)
}

View File

@ -0,0 +1,67 @@
package com.alya.ecommerce_serang.ui.profile.mystore
import android.os.Bundle
import android.widget.Toast
import androidx.activity.enableEdgeToEdge
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.viewModels
import com.alya.ecommerce_serang.data.api.dto.Store
import com.alya.ecommerce_serang.data.api.dto.UserProfile
import com.alya.ecommerce_serang.data.api.retrofit.ApiConfig
import com.alya.ecommerce_serang.data.api.retrofit.ApiService
import com.alya.ecommerce_serang.data.repository.MyStoreRepository
import com.alya.ecommerce_serang.data.repository.UserRepository
import com.alya.ecommerce_serang.databinding.ActivityMyStoreBinding
import com.alya.ecommerce_serang.ui.profile.ProfileViewModel
import com.alya.ecommerce_serang.utils.BaseViewModelFactory
import com.alya.ecommerce_serang.utils.SessionManager
import com.bumptech.glide.Glide
import kotlin.getValue
class MyStoreActivity : AppCompatActivity() {
private lateinit var binding: ActivityMyStoreBinding
private lateinit var apiService: ApiService
private lateinit var sessionManager: SessionManager
private val viewModel: MyStoreViewModel by viewModels {
BaseViewModelFactory {
val apiService = ApiConfig.getApiService(sessionManager)
val myStoreRepository = MyStoreRepository(apiService)
MyStoreViewModel(myStoreRepository)
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMyStoreBinding.inflate(layoutInflater)
setContentView(binding.root)
sessionManager = SessionManager(this)
apiService = ApiConfig.getApiService(sessionManager)
enableEdgeToEdge()
viewModel.loadMyStore()
viewModel.myStoreProfile.observe(this){ user ->
user?.let { myStoreProfileOverview(it) }
}
viewModel.errorMessage.observe(this) { error ->
Toast.makeText(this, error, Toast.LENGTH_SHORT).show()
}
}
private fun myStoreProfileOverview(store: Store){
binding.tvStoreName.setText(store.storeName.toString())
binding.tvStoreType.setText(store.storeType.toString())
// if (store.storeImage != null && user.image is String) {
// Glide.with(this)
// .load(user.image)
// .into(binding.profileImage)
// }
}
}

View File

@ -0,0 +1,28 @@
package com.alya.ecommerce_serang.ui.profile.mystore
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.alya.ecommerce_serang.data.api.dto.Store
import com.alya.ecommerce_serang.data.repository.MyStoreRepository
import com.alya.ecommerce_serang.data.repository.Result
import kotlinx.coroutines.launch
class MyStoreViewModel(private val myStoreRepository: MyStoreRepository): ViewModel() {
private val _myStoreProfile = MutableLiveData<Store?>()
val myStoreProfile: LiveData<Store?> = _myStoreProfile
private val _errorMessage = MutableLiveData<String>()
val errorMessage : LiveData<String> = _errorMessage
fun loadMyStore(){
viewModelScope.launch {
when (val result = myStoreRepository.fetchMyStoreProfile()){
is Result.Success -> _myStoreProfile.postValue(result.data)
is Result.Error -> _errorMessage.postValue(result.exception.message ?: "Unknown Error")
is Result.Loading -> null
}
}
}
}

View File

@ -1,21 +0,0 @@
package com.alya.ecommerce_serang.ui.profile.mystore
import android.os.Bundle
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import com.alya.ecommerce_serang.R
class TokoSayaActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContentView(R.layout.activity_toko_saya)
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
insets
}
}
}

View File

@ -1,50 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".ui.profile.mystore.TokoSayaActivity">
<include layout="@layout/header" />
<ScrollView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/layout_profile"
android:layout_width="match_parent"
android:layout_height="143dp"
android:paddingHorizontal="@dimen/horizontal_safe_area"
android:paddingVertical="@dimen/vertical_safe_area">
<com.google.android.material.imageview.ShapeableImageView
android:id="@+id/iv_profile"
android:layout_width="72dp"
android:layout_height="72dp"
android:src="@drawable/placeholder_image"
android:scaleType="centerCrop"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:shapeAppearanceOverlay="@style/circular_image"/>
<TextView
android:id="@+id/tv_store_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Nama Toko"
android:layout_marginStart="8dp"
style="@style/body_large"
android:textFontWeight="700"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toEndOf="@id/iv_profile"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>
</LinearLayout>

View File

@ -6,7 +6,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".ui.profile.mystore.TokoSayaActivity">
tools:context=".ui.profile.mystore.MyStoreActivity">
<include layout="@layout/header" />