diff --git a/.idea/other.xml b/.idea/other.xml
new file mode 100644
index 0000000..22069ff
--- /dev/null
+++ b/.idea/other.xml
@@ -0,0 +1,549 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 2ae92ff..df69c67 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -23,7 +23,7 @@ android {
buildTypes {
release {
- buildConfigField("String", "BASE_URL", "\"http://192.168.1.13:3000/\"")
+ buildConfigField("String", "BASE_URL", "\"http://192.168.1.4:3000/\"")
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
@@ -31,7 +31,7 @@ android {
)
}
debug {
- buildConfigField("String", "BASE_URL", "\"http://192.168.1.13:3000/\"")
+ buildConfigField("String", "BASE_URL", "\"http://192.168.1.4:3000/\"")
}
}
compileOptions {
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 4e96ec6..c4e9461 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -1,8 +1,9 @@
+ xmlns:tools="http://schemas.android.com/tools">
+
+ tools:targetApi="31">
+
@@ -41,14 +45,26 @@
android:name=".ui.profile.mystore.TokoSayaActivity"
android:exported="false" />
+ android:name=".ui.product.DetailProductActivity"
+ android:exported="false" />
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/java/com/alya/ecommerce_serang/data/api/dto/Category.kt b/app/src/main/java/com/alya/ecommerce_serang/data/api/dto/Category.kt
deleted file mode 100644
index 95fe0bc..0000000
--- a/app/src/main/java/com/alya/ecommerce_serang/data/api/dto/Category.kt
+++ /dev/null
@@ -1,11 +0,0 @@
-package com.alya.ecommerce_serang.data.api.dto
-
-import android.os.Parcelable
-import kotlinx.parcelize.Parcelize
-
-@Parcelize
-data class Category(
- val id: String,
- val image: String,
- val title: String
-): Parcelable
\ No newline at end of file
diff --git a/app/src/main/java/com/alya/ecommerce_serang/data/api/dto/CategoryItem.kt b/app/src/main/java/com/alya/ecommerce_serang/data/api/dto/CategoryItem.kt
new file mode 100644
index 0000000..ca0963d
--- /dev/null
+++ b/app/src/main/java/com/alya/ecommerce_serang/data/api/dto/CategoryItem.kt
@@ -0,0 +1,22 @@
+package com.alya.ecommerce_serang.data.api.dto
+
+import android.os.Parcelable
+import com.google.gson.annotations.SerializedName
+import kotlinx.parcelize.Parcelize
+
+@Parcelize
+
+data class CategoryItem(
+
+ @field:SerializedName("image")
+ val image: String,
+
+ @field:SerializedName("name")
+ val name: String,
+
+ @field:SerializedName("id")
+ val id: Int,
+
+ @field:SerializedName("store_type_id")
+ val storeTypeId: Int
+) : Parcelable
\ No newline at end of file
diff --git a/app/src/main/java/com/alya/ecommerce_serang/data/api/dto/DetailProduct.kt b/app/src/main/java/com/alya/ecommerce_serang/data/api/dto/DetailProduct.kt
index fe2355f..0680a18 100644
--- a/app/src/main/java/com/alya/ecommerce_serang/data/api/dto/DetailProduct.kt
+++ b/app/src/main/java/com/alya/ecommerce_serang/data/api/dto/DetailProduct.kt
@@ -14,7 +14,7 @@ data class DetailProduct(
val inStock: Int,
val price: Double,
val rating: Double,
- val related: List,
+ val related: List,
val reviews: Int,
val title: String,
@SerializedName("free_delivery")
diff --git a/app/src/main/java/com/alya/ecommerce_serang/data/api/dto/LoginRequest.kt b/app/src/main/java/com/alya/ecommerce_serang/data/api/dto/LoginRequest.kt
new file mode 100644
index 0000000..3f98cc8
--- /dev/null
+++ b/app/src/main/java/com/alya/ecommerce_serang/data/api/dto/LoginRequest.kt
@@ -0,0 +1,8 @@
+package com.alya.ecommerce_serang.data.api.dto
+
+import com.google.gson.annotations.SerializedName
+
+data class LoginRequest (
+ @SerializedName("emailOrPhone") val email: String,
+ @SerializedName("password") val password: String,
+)
\ No newline at end of file
diff --git a/app/src/main/java/com/alya/ecommerce_serang/data/api/dto/OtpRequest.kt b/app/src/main/java/com/alya/ecommerce_serang/data/api/dto/OtpRequest.kt
new file mode 100644
index 0000000..00f383b
--- /dev/null
+++ b/app/src/main/java/com/alya/ecommerce_serang/data/api/dto/OtpRequest.kt
@@ -0,0 +1,7 @@
+package com.alya.ecommerce_serang.data.api.dto
+
+import com.google.gson.annotations.SerializedName
+
+data class OtpRequest(
+ @SerializedName("email") val email: String
+)
\ No newline at end of file
diff --git a/app/src/main/java/com/alya/ecommerce_serang/data/api/dto/Product.kt b/app/src/main/java/com/alya/ecommerce_serang/data/api/dto/Product.kt
deleted file mode 100644
index 4af2851..0000000
--- a/app/src/main/java/com/alya/ecommerce_serang/data/api/dto/Product.kt
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.alya.ecommerce_serang.data.api.dto
-
-
-import com.google.gson.annotations.SerializedName
-
-data class Product (
- val id: String,
- val discount: Double?,
- @SerializedName("favorite")
- var wishlist: Boolean,
- val image: String,
- val price: Double,
- val rating: Double,
- @SerializedName("rating_count")
- val ratingCount: Int,
- val title: String,
-)
\ No newline at end of file
diff --git a/app/src/main/java/com/alya/ecommerce_serang/data/model/Product.kt b/app/src/main/java/com/alya/ecommerce_serang/data/api/dto/ProductsItem.kt
similarity index 68%
rename from app/src/main/java/com/alya/ecommerce_serang/data/model/Product.kt
rename to app/src/main/java/com/alya/ecommerce_serang/data/api/dto/ProductsItem.kt
index a5f79ea..37a5bf2 100644
--- a/app/src/main/java/com/alya/ecommerce_serang/data/model/Product.kt
+++ b/app/src/main/java/com/alya/ecommerce_serang/data/api/dto/ProductsItem.kt
@@ -1,8 +1,9 @@
-package com.alya.ecommerce_serang.data.model
+package com.alya.ecommerce_serang.data.api.dto
+
import com.google.gson.annotations.SerializedName
-data class Product(
+data class ProductsItem(
@field:SerializedName("store_id")
val storeId: Int,
@@ -19,23 +20,20 @@ data class Product(
@field:SerializedName("weight")
val weight: Int,
- @field:SerializedName("product_name")
- val productName: String,
-
@field:SerializedName("is_pre_order")
val isPreOrder: Boolean,
- @field:SerializedName("duration")
- val duration: Any,
-
@field:SerializedName("category_id")
val categoryId: Int,
@field:SerializedName("price")
val price: String,
- @field:SerializedName("product_id")
- val productId: Int,
+ @field:SerializedName("name")
+ val name: String,
+
+ @field:SerializedName("id")
+ val id: Int,
@field:SerializedName("min_order")
val minOrder: Int,
@@ -46,6 +44,6 @@ data class Product(
@field:SerializedName("stock")
val stock: Int,
- @field:SerializedName("product_category")
- val productCategory: String
+ @field:SerializedName("status")
+ val status: String
)
\ No newline at end of file
diff --git a/app/src/main/java/com/alya/ecommerce_serang/data/api/dto/RegisterRequest.kt b/app/src/main/java/com/alya/ecommerce_serang/data/api/dto/RegisterRequest.kt
new file mode 100644
index 0000000..650eab3
--- /dev/null
+++ b/app/src/main/java/com/alya/ecommerce_serang/data/api/dto/RegisterRequest.kt
@@ -0,0 +1,14 @@
+package com.alya.ecommerce_serang.data.api.dto
+
+import com.google.gson.annotations.SerializedName
+
+data class RegisterRequest (
+ val name: String?,
+ val email: String?,
+ val password: String?,
+ val username: String?,
+ val phone: String?,
+ @SerializedName("birth_date") val birthDate: String?,
+ @SerializedName("userimg") val image: String?,
+ val otp: String? = null
+)
\ No newline at end of file
diff --git a/app/src/main/java/com/alya/ecommerce_serang/data/api/dto/UserProfile.kt b/app/src/main/java/com/alya/ecommerce_serang/data/api/dto/UserProfile.kt
new file mode 100644
index 0000000..8a0a173
--- /dev/null
+++ b/app/src/main/java/com/alya/ecommerce_serang/data/api/dto/UserProfile.kt
@@ -0,0 +1,30 @@
+package com.alya.ecommerce_serang.data.api.dto
+
+import com.google.gson.annotations.SerializedName
+
+data class UserProfile(
+
+ @field:SerializedName("image")
+ val image: String? = null,
+
+ @field:SerializedName("role")
+ val role: String,
+
+ @field:SerializedName("user_id")
+ val userId: Int,
+
+ @field:SerializedName("phone")
+ val phone: String,
+
+ @field:SerializedName("birth_date")
+ val birthDate: String,
+
+ @field:SerializedName("name")
+ val name: String,
+
+ @field:SerializedName("email")
+ val email: String,
+
+ @field:SerializedName("username")
+ val username: String
+)
\ No newline at end of file
diff --git a/app/src/main/java/com/alya/ecommerce_serang/data/api/response/AllProductResponse.kt b/app/src/main/java/com/alya/ecommerce_serang/data/api/response/AllProductResponse.kt
index f4fd1a5..e45093f 100644
--- a/app/src/main/java/com/alya/ecommerce_serang/data/api/response/AllProductResponse.kt
+++ b/app/src/main/java/com/alya/ecommerce_serang/data/api/response/AllProductResponse.kt
@@ -1,5 +1,6 @@
package com.alya.ecommerce_serang.data.api.response
+import com.alya.ecommerce_serang.data.api.dto.ProductsItem
import com.google.gson.annotations.SerializedName
data class AllProductResponse(
@@ -11,47 +12,4 @@ data class AllProductResponse(
val products: List
)
-data class ProductsItem(
- @field:SerializedName("store_id")
- val storeId: Int,
-
- @field:SerializedName("image")
- val image: String,
-
- @field:SerializedName("rating")
- val rating: String,
-
- @field:SerializedName("description")
- val description: String,
-
- @field:SerializedName("weight")
- val weight: Int,
-
- @field:SerializedName("is_pre_order")
- val isPreOrder: Boolean,
-
- @field:SerializedName("category_id")
- val categoryId: Int,
-
- @field:SerializedName("price")
- val price: String,
-
- @field:SerializedName("name")
- val name: String,
-
- @field:SerializedName("id")
- val id: Int,
-
- @field:SerializedName("min_order")
- val minOrder: Int,
-
- @field:SerializedName("total_sold")
- val totalSold: Int,
-
- @field:SerializedName("stock")
- val stock: Int,
-
- @field:SerializedName("status")
- val status: String
-)
diff --git a/app/src/main/java/com/alya/ecommerce_serang/data/api/response/AllStoreResponse.kt b/app/src/main/java/com/alya/ecommerce_serang/data/api/response/AllStoreResponse.kt
new file mode 100644
index 0000000..4d2f860
--- /dev/null
+++ b/app/src/main/java/com/alya/ecommerce_serang/data/api/response/AllStoreResponse.kt
@@ -0,0 +1,33 @@
+package com.alya.ecommerce_serang.data.api.response
+
+import com.google.gson.annotations.SerializedName
+
+data class AllStoreResponse(
+
+ @field:SerializedName("store")
+ val store: AllStore,
+
+ @field:SerializedName("message")
+ val message: String
+)
+
+data class AllStore(
+
+ @field:SerializedName("store_name")
+ val storeName: String,
+
+ @field:SerializedName("description")
+ val description: String,
+
+ @field:SerializedName("store_type")
+ val storeType: String,
+
+ @field:SerializedName("store_location")
+ val storeLocation: String,
+
+ @field:SerializedName("store_image")
+ val storeImage: Any,
+
+ @field:SerializedName("status")
+ val status: String
+)
diff --git a/app/src/main/java/com/alya/ecommerce_serang/data/api/response/CategoryResponse.kt b/app/src/main/java/com/alya/ecommerce_serang/data/api/response/CategoryResponse.kt
new file mode 100644
index 0000000..26867ca
--- /dev/null
+++ b/app/src/main/java/com/alya/ecommerce_serang/data/api/response/CategoryResponse.kt
@@ -0,0 +1,15 @@
+package com.alya.ecommerce_serang.data.api.response
+
+import com.alya.ecommerce_serang.data.api.dto.CategoryItem
+import com.google.gson.annotations.SerializedName
+
+data class CategoryResponse(
+
+ @field:SerializedName("Category")
+ val category: List,
+
+ @field:SerializedName("message")
+ val message: String
+)
+
+
diff --git a/app/src/main/java/com/alya/ecommerce_serang/data/api/response/DetailStoreProductResponse.kt b/app/src/main/java/com/alya/ecommerce_serang/data/api/response/DetailStoreProductResponse.kt
new file mode 100644
index 0000000..4f83751
--- /dev/null
+++ b/app/src/main/java/com/alya/ecommerce_serang/data/api/response/DetailStoreProductResponse.kt
@@ -0,0 +1,33 @@
+package com.alya.ecommerce_serang.data.api.response
+
+import com.google.gson.annotations.SerializedName
+
+data class DetailStoreProductResponse(
+
+ @field:SerializedName("store")
+ val store: StoreProduct,
+
+ @field:SerializedName("message")
+ val message: String
+)
+
+data class StoreProduct(
+
+ @field:SerializedName("store_name")
+ val storeName: String,
+
+ @field:SerializedName("description")
+ val description: String,
+
+ @field:SerializedName("store_type")
+ val storeType: String,
+
+ @field:SerializedName("store_location")
+ val storeLocation: String,
+
+ @field:SerializedName("store_image")
+ val storeImage: Any,
+
+ @field:SerializedName("status")
+ val status: String
+)
diff --git a/app/src/main/java/com/alya/ecommerce_serang/data/api/response/LoginResponse.kt b/app/src/main/java/com/alya/ecommerce_serang/data/api/response/LoginResponse.kt
new file mode 100644
index 0000000..58c9206
--- /dev/null
+++ b/app/src/main/java/com/alya/ecommerce_serang/data/api/response/LoginResponse.kt
@@ -0,0 +1,15 @@
+package com.alya.ecommerce_serang.data.api.response
+
+import com.google.gson.annotations.SerializedName
+
+data class LoginResponse(
+
+ @field:SerializedName("role")
+ val role: String,
+
+ @field:SerializedName("message")
+ val message: String,
+
+ @field:SerializedName("accessToken")
+ val accessToken: String
+)
diff --git a/app/src/main/java/com/alya/ecommerce_serang/data/api/response/OtpResponse.kt b/app/src/main/java/com/alya/ecommerce_serang/data/api/response/OtpResponse.kt
new file mode 100644
index 0000000..60a87f5
--- /dev/null
+++ b/app/src/main/java/com/alya/ecommerce_serang/data/api/response/OtpResponse.kt
@@ -0,0 +1,9 @@
+package com.alya.ecommerce_serang.data.api.response
+
+import com.google.gson.annotations.SerializedName
+
+data class OtpResponse(
+
+ @field:SerializedName("message")
+ val message: String
+)
diff --git a/app/src/main/java/com/alya/ecommerce_serang/data/api/response/ProductResponse.kt b/app/src/main/java/com/alya/ecommerce_serang/data/api/response/ProductResponse.kt
index 26b1130..448ad92 100644
--- a/app/src/main/java/com/alya/ecommerce_serang/data/api/response/ProductResponse.kt
+++ b/app/src/main/java/com/alya/ecommerce_serang/data/api/response/ProductResponse.kt
@@ -17,7 +17,7 @@ data class Product(
val storeId: Int,
@field:SerializedName("image")
- val image: String,
+ val image: String? = null,
@field:SerializedName("rating")
val rating: String,
@@ -35,7 +35,7 @@ data class Product(
val isPreOrder: Boolean,
@field:SerializedName("duration")
- val duration: Any,
+ val duration: Any?,
@field:SerializedName("category_id")
val categoryId: Int,
diff --git a/app/src/main/java/com/alya/ecommerce_serang/data/api/response/ProfileResponse.kt b/app/src/main/java/com/alya/ecommerce_serang/data/api/response/ProfileResponse.kt
new file mode 100644
index 0000000..d9fe08d
--- /dev/null
+++ b/app/src/main/java/com/alya/ecommerce_serang/data/api/response/ProfileResponse.kt
@@ -0,0 +1,15 @@
+package com.alya.ecommerce_serang.data.api.response
+
+import com.alya.ecommerce_serang.data.api.dto.UserProfile
+import com.google.gson.annotations.SerializedName
+
+data class ProfileResponse(
+
+ @field:SerializedName("message")
+ val message: String,
+
+ @field:SerializedName("user")
+ val user: UserProfile
+)
+
+
diff --git a/app/src/main/java/com/alya/ecommerce_serang/data/api/response/RegisterResponse.kt b/app/src/main/java/com/alya/ecommerce_serang/data/api/response/RegisterResponse.kt
new file mode 100644
index 0000000..1136015
--- /dev/null
+++ b/app/src/main/java/com/alya/ecommerce_serang/data/api/response/RegisterResponse.kt
@@ -0,0 +1,42 @@
+package com.alya.ecommerce_serang.data.api.response
+
+import com.google.gson.annotations.SerializedName
+
+data class RegisterResponse(
+
+ @field:SerializedName("message")
+ val message: String,
+
+ @field:SerializedName("user")
+ val user: User
+)
+
+data class User(
+
+ @field:SerializedName("image")
+ val image: String,
+
+ @field:SerializedName("password")
+ val password: String,
+
+ @field:SerializedName("role")
+ val role: String,
+
+ @field:SerializedName("phone")
+ val phone: String,
+
+ @field:SerializedName("birth_date")
+ val birthDate: String,
+
+ @field:SerializedName("name")
+ val name: String,
+
+ @field:SerializedName("id")
+ val id: Int,
+
+ @field:SerializedName("email")
+ val email: String,
+
+ @field:SerializedName("username")
+ val username: String
+)
diff --git a/app/src/main/java/com/alya/ecommerce_serang/data/api/response/ReviewProductResponse.kt b/app/src/main/java/com/alya/ecommerce_serang/data/api/response/ReviewProductResponse.kt
new file mode 100644
index 0000000..f9a927c
--- /dev/null
+++ b/app/src/main/java/com/alya/ecommerce_serang/data/api/response/ReviewProductResponse.kt
@@ -0,0 +1,39 @@
+package com.alya.ecommerce_serang.data.api.response
+
+import com.google.gson.annotations.SerializedName
+
+data class ReviewProductResponse(
+
+ @field:SerializedName("reviews")
+ val reviews: List,
+
+ @field:SerializedName("message")
+ val message: String
+)
+
+data class ReviewsItem(
+
+ @field:SerializedName("order_item_id")
+ val orderItemId: Int,
+
+ @field:SerializedName("review_date")
+ val reviewDate: String,
+
+ @field:SerializedName("user_image")
+ val userImage: String? = null,
+
+ @field:SerializedName("product_id")
+ val productId: Int,
+
+ @field:SerializedName("rating")
+ val rating: Int,
+
+ @field:SerializedName("review_text")
+ val reviewText: String,
+
+ @field:SerializedName("product_name")
+ val productName: String,
+
+ @field:SerializedName("username")
+ val username: String
+)
diff --git a/app/src/main/java/com/alya/ecommerce_serang/data/api/response/StoreResponse.kt b/app/src/main/java/com/alya/ecommerce_serang/data/api/response/StoreResponse.kt
new file mode 100644
index 0000000..386de42
--- /dev/null
+++ b/app/src/main/java/com/alya/ecommerce_serang/data/api/response/StoreResponse.kt
@@ -0,0 +1,138 @@
+package com.alya.ecommerce_serang.data.api.response
+
+import com.google.gson.annotations.SerializedName
+
+data class StoreResponse(
+
+ @field:SerializedName("shipping")
+ val shipping: List,
+
+ @field:SerializedName("payment")
+ val payment: List,
+
+ @field:SerializedName("store")
+ val store: Store,
+
+ @field:SerializedName("message")
+ 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")
+ val courier: String
+)
+
+data class PaymentItem(
+
+ @field:SerializedName("qris_image")
+ val qrisImage: String,
+
+ @field:SerializedName("bank_num")
+ val bankNum: String,
+
+ @field:SerializedName("bank_name")
+ val bankName: String,
+
+ @field:SerializedName("id")
+ val id: Int
+)
diff --git a/app/src/main/java/com/alya/ecommerce_serang/data/api/retrofit/ApiConfig.kt b/app/src/main/java/com/alya/ecommerce_serang/data/api/retrofit/ApiConfig.kt
index 3a2e8f4..e8ddcb0 100644
--- a/app/src/main/java/com/alya/ecommerce_serang/data/api/retrofit/ApiConfig.kt
+++ b/app/src/main/java/com/alya/ecommerce_serang/data/api/retrofit/ApiConfig.kt
@@ -1,24 +1,52 @@
package com.alya.ecommerce_serang.data.api.retrofit
import com.alya.ecommerce_serang.BuildConfig
+import com.alya.ecommerce_serang.utils.AuthInterceptor
+import com.alya.ecommerce_serang.utils.SessionManager
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
class ApiConfig {
- companion object{
- fun getApiService(): ApiService {
- val loggingInterceptor =
- HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY)
+ companion object {
+ fun getApiService(tokenManager: SessionManager): ApiService {
+
+ val loggingInterceptor = HttpLoggingInterceptor().apply {
+ level = HttpLoggingInterceptor.Level.BODY
+ }
+
+ val authInterceptor = AuthInterceptor(tokenManager)
+
val client = OkHttpClient.Builder()
.addInterceptor(loggingInterceptor)
+ .addInterceptor(authInterceptor)
.build()
+
val retrofit = Retrofit.Builder()
.baseUrl(BuildConfig.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build()
+
+ return retrofit.create(ApiService::class.java)
+ }
+
+ fun getUnauthenticatedApiService(): ApiService {
+ val loggingInterceptor = HttpLoggingInterceptor().apply {
+ level = HttpLoggingInterceptor.Level.BODY
+ }
+
+ val client = OkHttpClient.Builder()
+ .addInterceptor(loggingInterceptor)
+ .build()
+
+ val retrofit = Retrofit.Builder()
+ .baseUrl(BuildConfig.BASE_URL)
+ .addConverterFactory(GsonConverterFactory.create())
+ .client(client)
+ .build()
+
return retrofit.create(ApiService::class.java)
}
}
diff --git a/app/src/main/java/com/alya/ecommerce_serang/data/api/retrofit/ApiService.kt b/app/src/main/java/com/alya/ecommerce_serang/data/api/retrofit/ApiService.kt
index 711291d..5cf478a 100644
--- a/app/src/main/java/com/alya/ecommerce_serang/data/api/retrofit/ApiService.kt
+++ b/app/src/main/java/com/alya/ecommerce_serang/data/api/retrofit/ApiService.kt
@@ -1,22 +1,67 @@
package com.alya.ecommerce_serang.data.api.retrofit
+import com.alya.ecommerce_serang.data.api.dto.LoginRequest
+import com.alya.ecommerce_serang.data.api.dto.OtpRequest
+import com.alya.ecommerce_serang.data.api.dto.RegisterRequest
import com.alya.ecommerce_serang.data.api.response.AllProductResponse
+import com.alya.ecommerce_serang.data.api.response.CategoryResponse
+import com.alya.ecommerce_serang.data.api.response.DetailStoreProductResponse
+import com.alya.ecommerce_serang.data.api.response.LoginResponse
+import com.alya.ecommerce_serang.data.api.response.OtpResponse
import com.alya.ecommerce_serang.data.api.response.ProductResponse
+import com.alya.ecommerce_serang.data.api.response.ProfileResponse
+import com.alya.ecommerce_serang.data.api.response.RegisterResponse
+import com.alya.ecommerce_serang.data.api.response.ReviewProductResponse
+import com.alya.ecommerce_serang.data.api.response.StoreResponse
import retrofit2.Call
+import retrofit2.Response
+import retrofit2.http.Body
import retrofit2.http.GET
-import retrofit2.http.Header
+import retrofit2.http.POST
import retrofit2.http.Path
interface ApiService {
- @GET("product")
- fun getAllProduct(
- @Header("Authorization") token: String = "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6NzEsIm5hbWUiOiJhbHlhIiwiZW1haWwiOiJha3VuYmVsYWphci5hbHlhQGdtYWlsLmNvbSIsInJvbGUiOiJ1c2VyIiwiaWF0IjoxNzM4NDg0OTc0LCJleHAiOjE3NDEwNzY5NzR9.0JyXJQ_6CKiZEi0gvk1gcn-0ILu3a9lOr3HqjhJXbBE"
- ): Call
+ @POST("registeruser")
+ suspend fun register (
+ @Body registerRequest: RegisterRequest
+ ): Response
+ @POST("otp")
+ suspend fun getOTP(
+ @Body otpRequest: OtpRequest
+ ):OtpResponse
+
+ @POST("login")
+ suspend fun login(
+ @Body loginRequest: LoginRequest
+ ): Response
+
+ @GET("category")
+ suspend fun allCategory(
+ ): Response
+
+ @GET("product")
+ suspend fun getAllProduct(): Response
+
+ @GET("product/review/{id}")
+ suspend fun getProductReview(
+ @Path("id") productId: Int
+ ): Response
@GET("product/detail/{id}")
- fun getDetailProduct (
- @Header("Authorization") token: String,
+ suspend fun getDetailProduct (
@Path("id") productId: Int
- ): Call
+ ): Response
+
+ @GET("profile")
+ suspend fun getUserProfile(): Response
+
+ @GET("store/detail/{id}")
+ suspend fun getDetailStore (
+ @Path("id") storeId: Int
+ ): Response
+
+
+ @GET("mystore")
+ fun getStore (): Call
}
\ No newline at end of file
diff --git a/app/src/main/java/com/alya/ecommerce_serang/data/repository/ProductRepository.kt b/app/src/main/java/com/alya/ecommerce_serang/data/repository/ProductRepository.kt
index 1f73cbd..519b5d4 100644
--- a/app/src/main/java/com/alya/ecommerce_serang/data/repository/ProductRepository.kt
+++ b/app/src/main/java/com/alya/ecommerce_serang/data/repository/ProductRepository.kt
@@ -1,7 +1,10 @@
package com.alya.ecommerce_serang.data.repository
import android.util.Log
-import com.alya.ecommerce_serang.data.api.response.ProductsItem
+import com.alya.ecommerce_serang.data.api.dto.CategoryItem
+import com.alya.ecommerce_serang.data.api.dto.ProductsItem
+import com.alya.ecommerce_serang.data.api.response.ProductResponse
+import com.alya.ecommerce_serang.data.api.response.ReviewsItem
import com.alya.ecommerce_serang.data.api.retrofit.ApiService
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
@@ -11,25 +14,84 @@ class ProductRepository(private val apiService: ApiService) {
withContext(Dispatchers.IO) {
try {
Log.d("ProductRepository", "Attempting to fetch products")
- val response = apiService.getAllProduct().execute()
- Log.d("ProductRepository", "Response received. Success: ${response.isSuccessful}")
- Log.d("ProductRepository", "Response code: ${response.code()}")
- Log.d("ProductRepository", "Response message: ${response.message()}")
+ val response = apiService.getAllProduct()
if (response.isSuccessful) {
- Result.success(response.body()?.products ?: emptyList())
+ // Return a Result.Success with the list of products
+
+ Result.Success(response.body()?.products ?: emptyList())
+
} else {
- Result.failure(Exception("Failed to fetch products"))
+ // Return a Result.Error with a custom Exception
+ Log.e("ProductRepository", "Error: ${response.errorBody()?.string()}")
+ Result.Error(Exception("Failed to fetch products. Code: ${response.code()}"))
}
} catch (e: Exception) {
- Result.failure(e)
+ // Return a Result.Error with the exception caught
+ Result.Error(e)
}
}
-// suspend fun getCategories():List
+
+ suspend fun fetchProductDetail(productId: Int): ProductResponse? {
+ return try {
+ val response = apiService.getDetailProduct(productId)
+ if (response.isSuccessful) {
+ response.body()
+ } else {
+ Log.e("ProductRepository", "Error: ${response.errorBody()?.string()}")
+ null
+ }
+ } catch (e: Exception) {
+ null
+ }
+ }
+
+ suspend fun getAllCategories(): Result> =
+ withContext(Dispatchers.IO) {
+ try {
+ Log.d("Categories", "Attempting to fetch categories")
+ val response = apiService.allCategory()
+
+ if (response.isSuccessful) {
+ val categories = response.body()?.category ?: emptyList()
+ Log.d("Categories", "Fetched categories: $categories")
+ categories.forEach { Log.d("Category Image", "Category: ${it.name}, Image: ${it.image}") }
+ Result.Success(categories)
+ } else {
+ Result.Error(Exception("Failed to fetch categories. Code: ${response.code()}"))
+ }
+ } catch (e: Exception) {
+ Log.e("Categories", "Error fetching categories", e)
+ Result.Error(e)
+ }
+ }
+
+ suspend fun fetchProductReview(productId: Int): List? {
+ return try {
+ val response = apiService.getProductReview(productId)
+ if (response.isSuccessful) {
+ response.body()?.reviews // Ambil daftar review dari response
+ } else {
+ Log.e("ProductRepository", "Error: ${response.errorBody()?.string()}")
+ null
+ }
+ } catch (e: Exception) {
+ null
+ }
+ }
+}
+
+// suspend fun fetchStoreDetail(storeId: Int): Store? {
+// return try {
+// val response = apiService.getStore(storeId)
+// if (response.isSucessful) {
+// response.body()?.store
+// } else {
+// Log.e("ProductRepository", "Error: ${response.errorBody()?.string()}")
//
-// fun getProducts(query: ProductQuery) : Flow>
-// fun getRecentSearchs(): Flow>
-// suspend fun clearRecents()
-// suspend fun addRecents(search:String)
-// suspend fun getProduct(id:String):DetailProduct
-}
\ No newline at end of file
+// null
+// }
+// } catch (e: Exception) {
+// null
+// }
+// }
\ No newline at end of file
diff --git a/app/src/main/java/com/alya/ecommerce_serang/data/repository/UserRepository.kt b/app/src/main/java/com/alya/ecommerce_serang/data/repository/UserRepository.kt
new file mode 100644
index 0000000..0977624
--- /dev/null
+++ b/app/src/main/java/com/alya/ecommerce_serang/data/repository/UserRepository.kt
@@ -0,0 +1,69 @@
+package com.alya.ecommerce_serang.data.repository
+
+import com.alya.ecommerce_serang.data.api.dto.LoginRequest
+import com.alya.ecommerce_serang.data.api.dto.OtpRequest
+import com.alya.ecommerce_serang.data.api.dto.RegisterRequest
+import com.alya.ecommerce_serang.data.api.dto.UserProfile
+import com.alya.ecommerce_serang.data.api.response.LoginResponse
+import com.alya.ecommerce_serang.data.api.response.OtpResponse
+import com.alya.ecommerce_serang.data.api.retrofit.ApiService
+
+class UserRepository(private val apiService: ApiService) {
+
+ suspend fun requestOtpRep(email: String): OtpResponse {
+
+// fun requestOtpRep(email: String): Result {
+
+ return apiService.getOTP(OtpRequest(email))
+
+ }
+
+ suspend fun registerUser(request: RegisterRequest): String {
+ val response = apiService.register(request) // API call
+
+ if (response.isSuccessful) {
+ val responseBody = response.body() ?: throw Exception("Empty response body")
+ return responseBody.message // Get the message from RegisterResponse
+ } else {
+ throw Exception("Registration failed: ${response.errorBody()?.string()}")
+ }
+ }
+
+ suspend fun login(email: String, password: String): Result {
+ return try {
+ val response = apiService.login(LoginRequest(email, password))
+ if (response.isSuccessful) {
+ response.body()?.let {
+ Result.Success(it)
+ } ?: Result.Error(Exception("Login response is empty"))
+ } else {
+ Result.Error(Exception(response.errorBody()?.string() ?: "Unknown error"))
+ }
+ } catch (e: Exception) {
+ Result.Error(e)
+ }
+ }
+
+ suspend fun fetchUserProfile(): Result {
+ return try {
+ val response = apiService.getUserProfile()
+ if (response.isSuccessful) {
+ response.body()?.user?.let {
+ Result.Success(it) // ✅ Returning only UserProfile
+ } ?: Result.Error(Exception("User data not found"))
+ } else {
+ Result.Error(Exception("Error fetching profile: ${response.code()}"))
+ }
+ } catch (e: Exception) {
+ Result.Error(e)
+ }
+ }
+
+
+}
+
+sealed class Result {
+ data class Success(val data: T) : Result()
+ data class Error(val exception: Throwable) : Result()
+ object Loading : Result()
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/MainActivity.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/MainActivity.kt
index 9450c13..3877327 100644
--- a/app/src/main/java/com/alya/ecommerce_serang/ui/MainActivity.kt
+++ b/app/src/main/java/com/alya/ecommerce_serang/ui/MainActivity.kt
@@ -6,11 +6,16 @@ import androidx.core.view.isVisible
import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.ui.setupWithNavController
import com.alya.ecommerce_serang.R
+import com.alya.ecommerce_serang.data.api.retrofit.ApiConfig
+import com.alya.ecommerce_serang.data.api.retrofit.ApiService
import com.alya.ecommerce_serang.databinding.ActivityMainBinding
+import com.alya.ecommerce_serang.utils.SessionManager
//@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
+ private lateinit var apiService: ApiService
+ private lateinit var sessionManager: SessionManager
private val navController by lazy {
(supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment).navController
}
@@ -19,6 +24,9 @@ class MainActivity : AppCompatActivity() {
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
+ sessionManager = SessionManager(this)
+ apiService = ApiConfig.getApiService(sessionManager) // Inject SessionManager
+
setupBottomNavigation()
observeDestinationChanges()
diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/auth/LoginActivity.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/auth/LoginActivity.kt
new file mode 100644
index 0000000..9ae19c4
--- /dev/null
+++ b/app/src/main/java/com/alya/ecommerce_serang/ui/auth/LoginActivity.kt
@@ -0,0 +1,75 @@
+package com.alya.ecommerce_serang.ui.auth
+
+import android.content.Intent
+import android.os.Bundle
+import android.widget.Toast
+import androidx.activity.enableEdgeToEdge
+import androidx.activity.viewModels
+import androidx.appcompat.app.AppCompatActivity
+import com.alya.ecommerce_serang.data.api.retrofit.ApiConfig
+import com.alya.ecommerce_serang.data.repository.Result
+import com.alya.ecommerce_serang.data.repository.UserRepository
+import com.alya.ecommerce_serang.databinding.ActivityLoginBinding
+import com.alya.ecommerce_serang.ui.MainActivity
+import com.alya.ecommerce_serang.utils.BaseViewModelFactory
+import com.alya.ecommerce_serang.utils.SessionManager
+
+class LoginActivity : AppCompatActivity() {
+
+ private lateinit var binding: ActivityLoginBinding
+ private val loginViewModel: LoginViewModel by viewModels{
+ BaseViewModelFactory {
+ val apiService = ApiConfig.getUnauthenticatedApiService()
+ val userRepository = UserRepository(apiService)
+ LoginViewModel(userRepository)
+ }
+ }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ enableEdgeToEdge()
+
+ binding = ActivityLoginBinding.inflate(layoutInflater)
+ setContentView(binding.root)
+
+ setupListeners()
+ observeLoginState()
+ }
+
+ private fun setupListeners() {
+ binding.btnLogin.setOnClickListener {
+ val email = binding.etLoginEmail.text.toString()
+ val password = binding.etLoginPassword.text.toString()
+
+ if (email.isEmpty() || password.isEmpty()) {
+ Toast.makeText(this, "Please fill in all fields", Toast.LENGTH_SHORT).show()
+ } else {
+ loginViewModel.login(email, password)
+ }
+ }
+ }
+
+ private fun observeLoginState() {
+ loginViewModel.loginState.observe(this) { result ->
+ when (result) {
+ is com.alya.ecommerce_serang.data.repository.Result.Success -> {
+ val accessToken = result.data.accessToken
+
+ val sessionManager = SessionManager(this)
+ sessionManager.saveToken(accessToken)
+
+ Toast.makeText(this, "Login Successful", Toast.LENGTH_SHORT).show()
+
+ startActivity(Intent(this, MainActivity::class.java))
+ finish()
+ }
+ is com.alya.ecommerce_serang.data.repository.Result.Error -> {
+ Toast.makeText(this, "Login Failed: ${result.exception.message}", Toast.LENGTH_LONG).show()
+ }
+ is Result.Loading -> {
+ // Show loading state
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/auth/LoginViewModel.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/auth/LoginViewModel.kt
new file mode 100644
index 0000000..8b4c27d
--- /dev/null
+++ b/app/src/main/java/com/alya/ecommerce_serang/ui/auth/LoginViewModel.kt
@@ -0,0 +1,23 @@
+package com.alya.ecommerce_serang.ui.auth
+
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
+import com.alya.ecommerce_serang.data.api.response.LoginResponse
+import com.alya.ecommerce_serang.data.repository.Result
+import com.alya.ecommerce_serang.data.repository.UserRepository
+import kotlinx.coroutines.launch
+
+class LoginViewModel(private val repository: UserRepository) : ViewModel() {
+ private val _loginState = MutableLiveData>()
+ val loginState: LiveData> get() = _loginState
+
+ fun login(email: String, password: String) {
+ viewModelScope.launch {
+ _loginState.value = com.alya.ecommerce_serang.data.repository.Result.Loading
+ val result = repository.login(email, password)
+ _loginState.value = result
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/auth/OtpBottomsheetDialog.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/auth/OtpBottomsheetDialog.kt
new file mode 100644
index 0000000..c20b7f9
--- /dev/null
+++ b/app/src/main/java/com/alya/ecommerce_serang/ui/auth/OtpBottomsheetDialog.kt
@@ -0,0 +1,41 @@
+package com.alya.ecommerce_serang.ui.auth
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.Button
+import android.widget.EditText
+import android.widget.Toast
+import com.alya.ecommerce_serang.R
+import com.alya.ecommerce_serang.data.api.dto.RegisterRequest
+import com.google.android.material.bottomsheet.BottomSheetDialogFragment
+
+class OtpBottomSheetDialog(
+ private val userData: RegisterRequest, // Store user data
+ private val onRegister: (RegisterRequest) -> Unit)
+ : BottomSheetDialogFragment() {
+
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
+ val view = inflater.inflate(R.layout.dialog_otp, container, false)
+
+ val etOtp = view.findViewById(R.id.etOtp)
+ val btnSubmit = view.findViewById