diff --git a/.idea/assetWizardSettings.xml b/.idea/assetWizardSettings.xml
index 5b1384a..d35c90b 100644
--- a/.idea/assetWizardSettings.xml
+++ b/.idea/assetWizardSettings.xml
@@ -23,7 +23,7 @@
@@ -33,8 +33,7 @@
diff --git a/.idea/caches/deviceStreaming.xml b/.idea/caches/deviceStreaming.xml
index 9e9ba09..8178718 100644
--- a/.idea/caches/deviceStreaming.xml
+++ b/.idea/caches/deviceStreaming.xml
@@ -3,6 +3,18 @@
diff --git a/.idea/deploymentTargetSelector.xml b/.idea/deploymentTargetSelector.xml
index 28e6bcd..4c4edab 100644
--- a/.idea/deploymentTargetSelector.xml
+++ b/.idea/deploymentTargetSelector.xml
@@ -4,10 +4,10 @@
-
+
-
+
diff --git a/.idea/navEditor.xml b/.idea/navEditor.xml
index 9c23fda..0f38f32 100644
--- a/.idea/navEditor.xml
+++ b/.idea/navEditor.xml
@@ -3,6 +3,281 @@
+
+
+
+
+
+
+
+
+
diff --git a/.idea/shelf/Uncommitted_changes_before_Update_at_17_3_2025_18_59_[Changes]/shelved.patch b/.idea/shelf/Uncommitted_changes_before_Update_at_17_3_2025_18_59_[Changes]/shelved.patch
deleted file mode 100644
index d3b700a..0000000
--- a/.idea/shelf/Uncommitted_changes_before_Update_at_17_3_2025_18_59_[Changes]/shelved.patch
+++ /dev/null
@@ -1,35 +0,0 @@
-Index: gradle/wrapper/gradle-wrapper.properties
-IDEA additional info:
-Subsystem: com.intellij.openapi.diff.impl.patch.BaseRevisionTextPatchEP
-<+>#Sat Feb 22 12:19:27 CET 2025\r\ndistributionBase=GRADLE_USER_HOME\r\ndistributionPath=wrapper/dists\r\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-8.9-bin.zip\r\nzipStoreBase=GRADLE_USER_HOME\r\nzipStorePath=wrapper/dists\r\n
-Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
-<+>ISO-8859-1
-===================================================================
-diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
---- a/gradle/wrapper/gradle-wrapper.properties (revision 54ea0f0aac8baca060294365b0d758b546ed6783)
-+++ b/gradle/wrapper/gradle-wrapper.properties (date 1742122410305)
-@@ -1,6 +1,6 @@
- #Sat Feb 22 12:19:27 CET 2025
- distributionBase=GRADLE_USER_HOME
- distributionPath=wrapper/dists
--distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
-+distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip
- zipStoreBase=GRADLE_USER_HOME
- zipStorePath=wrapper/dists
-Index: gradle/libs.versions.toml
-IDEA additional info:
-Subsystem: com.intellij.openapi.diff.impl.patch.BaseRevisionTextPatchEP
-<+>[versions]\r\nagp = \"8.7.2\"\r\njwtdecode = \"2.0.2\"\r\nkotlin = \"1.9.24\"\r\ncoreKtx = \"1.15.0\"\r\njunit = \"4.13.2\"\r\njunitVersion = \"1.2.1\"\r\nespressoCore = \"3.6.1\"\r\nappcompat = \"1.7.0\"\r\nkotlinxCoroutinesAndroid = \"1.7.3\"\r\nkotlinxCoroutinesAndroidVersion = \"1.6.4\"\r\nlifecycleViewmodelKtx = \"2.8.7\"\r\nloggingInterceptor = \"4.9.0\"\r\nmaterial = \"1.12.0\"\r\nactivity = \"1.10.0\"\r\nconstraintlayout = \"2.2.0\"\r\nretrofit = \"2.9.0\"\r\nlegacySupportV4 = \"1.0.0\"\r\nlifecycleLivedataKtx = \"2.8.7\"\r\nfragmentKtx = \"1.5.6\"\r\nroomCompiler = \"2.6.1\"\r\nroomRuntimeVersion = \"2.5.2\"\r\nsecurityCrypto = \"1.1.0-alpha06\"\r\n\r\n[libraries]\r\nandroidx-core-ktx = { group = \"androidx.core\", name = \"core-ktx\", version.ref = \"coreKtx\" }\r\nandroidx-lifecycle-viewmodel-ktx = { module = \"androidx.lifecycle:lifecycle-viewmodel-ktx\", version.ref = \"lifecycleViewmodelKtx\" }\r\nandroidx-room-compiler = { module = \"androidx.room:room-compiler\", version.ref = \"roomRuntimeVersion\" }\r\nandroidx-room-compiler-v261 = { module = \"androidx.room:room-compiler\", version.ref = \"roomCompiler\" }\r\nandroidx-room-ktx = { module = \"androidx.room:room-ktx\", version.ref = \"roomCompiler\" }\r\nandroidx-security-crypto = { module = \"androidx.security:security-crypto\", version.ref = \"securityCrypto\" }\r\nconverter-gson = { module = \"com.squareup.retrofit2:converter-gson\", version.ref = \"retrofit\" }\r\njunit = { group = \"junit\", name = \"junit\", version.ref = \"junit\" }\r\nandroidx-junit = { group = \"androidx.test.ext\", name = \"junit\", version.ref = \"junitVersion\" }\r\nandroidx-espresso-core = { group = \"androidx.test.espresso\", name = \"espresso-core\", version.ref = \"espressoCore\" }\r\nandroidx-appcompat = { group = \"androidx.appcompat\", name = \"appcompat\", version.ref = \"appcompat\" }\r\njwtdecode = { module = \"com.auth0.android:jwtdecode\", version.ref = \"jwtdecode\" }\r\nkotlinx-coroutines-android = { module = \"org.jetbrains.kotlinx:kotlinx-coroutines-android\", version.ref = \"kotlinxCoroutinesAndroid\" }\r\nkotlinx-coroutines-android-v164 = { module = \"org.jetbrains.kotlinx:kotlinx-coroutines-android\", version.ref = \"kotlinxCoroutinesAndroidVersion\" }\r\nlogging-interceptor = { module = \"com.squareup.okhttp3:logging-interceptor\", version.ref = \"loggingInterceptor\" }\r\nmaterial = { group = \"com.google.android.material\", name = \"material\", version.ref = \"material\" }\r\nandroidx-activity = { group = \"androidx.activity\", name = \"activity\", version.ref = \"activity\" }\r\nandroidx-constraintlayout = { group = \"androidx.constraintlayout\", name = \"constraintlayout\", version.ref = \"constraintlayout\" }\r\nretrofit = { module = \"com.squareup.retrofit2:retrofit\", version.ref = \"retrofit\" }\r\nandroidx-legacy-support-v4 = { group = \"androidx.legacy\", name = \"legacy-support-v4\", version.ref = \"legacySupportV4\" }\r\nandroidx-lifecycle-livedata-ktx = { group = \"androidx.lifecycle\", name = \"lifecycle-livedata-ktx\", version.ref = \"lifecycleLivedataKtx\" }\r\nandroidx-fragment-ktx = { group = \"androidx.fragment\", name = \"fragment-ktx\", version.ref = \"fragmentKtx\" }\r\nroom-runtime = { module = \"androidx.room:room-runtime\", version.ref = \"roomRuntimeVersion\" }\r\n\r\n[plugins]\r\nandroid-application = { id = \"com.android.application\", version.ref = \"agp\" }\r\nkotlin-android = { id = \"org.jetbrains.kotlin.android\", version = \"2.1.10\" }\r\n\r\n
-Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
-<+>UTF-8
-===================================================================
-diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
---- a/gradle/libs.versions.toml (revision 54ea0f0aac8baca060294365b0d758b546ed6783)
-+++ b/gradle/libs.versions.toml (date 1742122410296)
-@@ -1,5 +1,5 @@
- [versions]
--agp = "8.7.2"
-+agp = "8.9.0"
- jwtdecode = "2.0.2"
- kotlin = "1.9.24"
- coreKtx = "1.15.0"
diff --git a/.idea/shelf/Uncommitted_changes_before_Update_at_17_3_2025_18_59__Changes_.xml b/.idea/shelf/Uncommitted_changes_before_Update_at_17_3_2025_18_59__Changes_.xml
deleted file mode 100644
index ca1a976..0000000
--- a/.idea/shelf/Uncommitted_changes_before_Update_at_17_3_2025_18_59__Changes_.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 381cccc..8327ae1 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -1,10 +1,8 @@
-import org.gradle.kotlin.dsl.implementation
-
plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android)
id("com.google.devtools.ksp")
- id("androidx.navigation.safeargs.kotlin")
+ id("androidx.navigation.safeargs.kotlin") version "2.9.0"
}
android {
diff --git a/app/src/main/java/mk/ukim/finki/my_distributor/data/api/RetrofitClient.kt b/app/src/main/java/mk/ukim/finki/my_distributor/data/api/RetrofitClient.kt
index 3181765..07571cb 100644
--- a/app/src/main/java/mk/ukim/finki/my_distributor/data/api/RetrofitClient.kt
+++ b/app/src/main/java/mk/ukim/finki/my_distributor/data/api/RetrofitClient.kt
@@ -6,6 +6,7 @@ import com.google.gson.GsonBuilder
import mk.ukim.finki.my_distributor.data.api.service.ArticleApiService
import mk.ukim.finki.my_distributor.data.api.service.AuthApiService
import mk.ukim.finki.my_distributor.data.api.service.DashboardApiService
+import mk.ukim.finki.my_distributor.data.api.service.DeliveryApiService
import mk.ukim.finki.my_distributor.data.api.service.OrderApiService
import mk.ukim.finki.my_distributor.data.api.service.UserApiService
import mk.ukim.finki.my_distributor.data.local.UserPreferences
@@ -18,7 +19,9 @@ import retrofit2.converter.gson.GsonConverterFactory
import java.time.LocalDateTime
object RetrofitClient {
- private const val BASE_URL = "https://192.168.31.100:8443/"
+ private const val BASE_URL = "https://10.0.2.2:8443/"
+ // private const val BASE_URL = "https://192.168.31.100:8443/"
+ // private const val BASE_URL = "https://192.168.236.211:8443/"
@SuppressLint("NewApi")
val customGson: Gson = GsonBuilder()
@@ -65,4 +68,8 @@ object RetrofitClient {
fun getOrderApiService(userPreferences: UserPreferences): OrderApiService {
return getRetrofit(userPreferences).create(OrderApiService::class.java)
}
+
+ fun getDeliveryApiService(userPreferences: UserPreferences): DeliveryApiService {
+ return getRetrofit(userPreferences).create(DeliveryApiService::class.java)
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/mk/ukim/finki/my_distributor/data/api/service/DashboardApiService.kt b/app/src/main/java/mk/ukim/finki/my_distributor/data/api/service/DashboardApiService.kt
index 4b2459c..29f63d5 100644
--- a/app/src/main/java/mk/ukim/finki/my_distributor/data/api/service/DashboardApiService.kt
+++ b/app/src/main/java/mk/ukim/finki/my_distributor/data/api/service/DashboardApiService.kt
@@ -1,11 +1,12 @@
package mk.ukim.finki.my_distributor.data.api.service
import mk.ukim.finki.my_distributor.domain.dto.CustomerDashboardData
+import mk.ukim.finki.my_distributor.domain.dto.DriverDashboardData
import retrofit2.Response
import retrofit2.http.GET
import retrofit2.http.Path
interface DashboardApiService {
@GET("api/customer/{customerId}/dashboard")
- suspend fun getDashboardData(@Path("customerId") customerId: Long): Response
+ suspend fun getCustomerDashboardData(@Path("customerId") customerId: Long): Response
}
\ No newline at end of file
diff --git a/app/src/main/java/mk/ukim/finki/my_distributor/data/api/service/DeliveryApiService.kt b/app/src/main/java/mk/ukim/finki/my_distributor/data/api/service/DeliveryApiService.kt
new file mode 100644
index 0000000..16bbad8
--- /dev/null
+++ b/app/src/main/java/mk/ukim/finki/my_distributor/data/api/service/DeliveryApiService.kt
@@ -0,0 +1,16 @@
+package mk.ukim.finki.my_distributor.data.api.service
+
+import mk.ukim.finki.my_distributor.domain.dto.DeliverySimpleDto
+import mk.ukim.finki.my_distributor.domain.dto.DeliveryWithOrdersDto
+import retrofit2.Response
+import retrofit2.http.GET
+import retrofit2.http.Path
+
+interface DeliveryApiService {
+
+ @GET("api/driver/newDeliveries")
+ suspend fun getDriverNewDeliveries(): Response>
+
+ @GET("api/delivery/delivery-with-orders/{deliveryId}")
+ suspend fun getDeliveryWithOrders(@Path("deliveryId") deliveryId: Long): Response
+}
\ No newline at end of file
diff --git a/app/src/main/java/mk/ukim/finki/my_distributor/data/local/UserPreferences.kt b/app/src/main/java/mk/ukim/finki/my_distributor/data/local/UserPreferences.kt
index a0e44b7..300f6ae 100644
--- a/app/src/main/java/mk/ukim/finki/my_distributor/data/local/UserPreferences.kt
+++ b/app/src/main/java/mk/ukim/finki/my_distributor/data/local/UserPreferences.kt
@@ -1,6 +1,7 @@
package mk.ukim.finki.my_distributor.data.local
import android.content.Context
+import androidx.core.content.edit
import androidx.security.crypto.EncryptedSharedPreferences
import androidx.security.crypto.MasterKey
@@ -19,7 +20,7 @@ class UserPreferences(context: Context) {
)
fun saveToken(token: String) {
- sharedPreferences.edit().putString("jwt_token", token).apply()
+ sharedPreferences.edit() { putString("jwt_token", token) }
}
fun getToken(): String? {
@@ -27,7 +28,29 @@ class UserPreferences(context: Context) {
}
fun clearToken() {
- sharedPreferences.edit().remove("jwt_token").apply()
+ sharedPreferences.edit() { remove("jwt_token") }
+ }
+
+ fun saveUserInfo(name: String, email: String) {
+ sharedPreferences.edit {
+ putString("userName", name)
+ putString("userEmail", email)
+ }
+ }
+
+ fun getUserInfo(): UserInfo? {
+ val name = sharedPreferences.getString("userName", null)
+ val email = sharedPreferences.getString("userEmail", null)
+ return if (name != null && email != null) {
+ UserInfo(name, email)
+ } else null
+ }
+
+ fun clearUserInfo() {
+ sharedPreferences.edit {
+ remove("userName")
+ remove("userEmail")
+ }
}
companion object {
@@ -42,4 +65,7 @@ class UserPreferences(context: Context) {
}
}
}
+
+ data class UserInfo(val name: String, val email: String)
+
}
\ No newline at end of file
diff --git a/app/src/main/java/mk/ukim/finki/my_distributor/data/repository/CustomerRepository.kt b/app/src/main/java/mk/ukim/finki/my_distributor/data/repository/CustomerRepository.kt
index b63a858..43bfd74 100644
--- a/app/src/main/java/mk/ukim/finki/my_distributor/data/repository/CustomerRepository.kt
+++ b/app/src/main/java/mk/ukim/finki/my_distributor/data/repository/CustomerRepository.kt
@@ -19,7 +19,7 @@ class CustomerRepository(
return withContext(Dispatchers.IO) {
try {
- val response = dashboardApiService.getDashboardData(customerId)
+ val response = dashboardApiService.getCustomerDashboardData(customerId)
if (response.isSuccessful) {
val data = response.body()
if (data != null) {
diff --git a/app/src/main/java/mk/ukim/finki/my_distributor/data/repository/DeliveryRepository.kt b/app/src/main/java/mk/ukim/finki/my_distributor/data/repository/DeliveryRepository.kt
new file mode 100644
index 0000000..f8f48ae
--- /dev/null
+++ b/app/src/main/java/mk/ukim/finki/my_distributor/data/repository/DeliveryRepository.kt
@@ -0,0 +1,43 @@
+package mk.ukim.finki.my_distributor.data.repository
+
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.withContext
+import mk.ukim.finki.my_distributor.data.api.service.DeliveryApiService
+import mk.ukim.finki.my_distributor.domain.dto.DeliverySimpleDto
+import mk.ukim.finki.my_distributor.domain.dto.DeliveryWithOrdersDto
+
+class DeliveryRepository(
+ private val apiService: DeliveryApiService
+) {
+
+ suspend fun getDriverDeliveries(): Result> {
+ return withContext(Dispatchers.IO) {
+ try {
+ val response = apiService.getDriverNewDeliveries()
+ if (response.isSuccessful) {
+ val deliveries = response.body() ?: emptyList()
+ Result.success(deliveries)
+ } else {
+ Result.failure(Exception("Error: ${response.code()} ${response.message()}"))
+ }
+ } catch (ex: Exception) {
+ Result.failure(ex)
+ }
+ }
+ }
+
+ suspend fun getDeliveryWithOrders(deliveryId: Long): Result =
+ withContext(Dispatchers.IO) {
+ try {
+ val resp = apiService.getDeliveryWithOrders(deliveryId)
+ if (resp.isSuccessful) {
+ resp.body()?.let { Result.success(it) }
+ ?: Result.failure(Exception("Empty delivery data"))
+ } else {
+ Result.failure(Exception("Error ${resp.code()}: ${resp.message()}"))
+ }
+ } catch (e: Exception) {
+ Result.failure(e)
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/mk/ukim/finki/my_distributor/domain/dto/DeliverySimpleDto.kt b/app/src/main/java/mk/ukim/finki/my_distributor/domain/dto/DeliverySimpleDto.kt
new file mode 100644
index 0000000..3c26d59
--- /dev/null
+++ b/app/src/main/java/mk/ukim/finki/my_distributor/domain/dto/DeliverySimpleDto.kt
@@ -0,0 +1,24 @@
+package mk.ukim.finki.my_distributor.domain.dto
+
+import com.google.gson.annotations.SerializedName
+import java.util.Date
+
+data class DeliverySimpleDto(
+ @SerializedName("deliveryId")
+ val deliveryId: Long,
+
+ @SerializedName("driverName")
+ val driverName: String,
+
+ @SerializedName("deliveryDate")
+ val deliveryDate: Date,
+
+ @SerializedName("deliveryCreatedDate")
+ val deliveryCreatedDate: Date,
+
+ @SerializedName("deliveryStatus")
+ val deliveryStatus: Short,
+
+ @SerializedName("deliveryStatusName")
+ val deliveryStatusName: String
+)
diff --git a/app/src/main/java/mk/ukim/finki/my_distributor/domain/dto/DeliveryWithOrdersDto.kt b/app/src/main/java/mk/ukim/finki/my_distributor/domain/dto/DeliveryWithOrdersDto.kt
new file mode 100644
index 0000000..1c284ea
--- /dev/null
+++ b/app/src/main/java/mk/ukim/finki/my_distributor/domain/dto/DeliveryWithOrdersDto.kt
@@ -0,0 +1,6 @@
+package mk.ukim.finki.my_distributor.domain.dto
+
+data class DeliveryWithOrdersDto(
+ val delivery: DeliveryDto,
+ val orders: List
+)
diff --git a/app/src/main/java/mk/ukim/finki/my_distributor/domain/dto/DriverDashboardData.kt b/app/src/main/java/mk/ukim/finki/my_distributor/domain/dto/DriverDashboardData.kt
new file mode 100644
index 0000000..b1adc8d
--- /dev/null
+++ b/app/src/main/java/mk/ukim/finki/my_distributor/domain/dto/DriverDashboardData.kt
@@ -0,0 +1,5 @@
+package mk.ukim.finki.my_distributor.domain.dto
+
+data class DriverDashboardData(
+ var newDeliveries: List
+)
\ No newline at end of file
diff --git a/app/src/main/java/mk/ukim/finki/my_distributor/domain/dto/OrderDeliveryDto.kt b/app/src/main/java/mk/ukim/finki/my_distributor/domain/dto/OrderDeliveryDto.kt
new file mode 100644
index 0000000..629dbb0
--- /dev/null
+++ b/app/src/main/java/mk/ukim/finki/my_distributor/domain/dto/OrderDeliveryDto.kt
@@ -0,0 +1,17 @@
+package mk.ukim.finki.my_distributor.domain.dto
+
+import java.sql.Date
+import java.time.LocalDateTime
+
+data class OrderDeliveryDto(
+ val id: Long,
+ val ordDate: Date,
+ val ordSum: Int,
+ val ordFulfillmentDate: LocalDateTime?,
+ val ordComment: String?,
+ val oStatusId: Short,
+ val customerId: Long,
+ val deliveryId: Long?,
+ val latitude: Double,
+ val longitude: Double
+)
diff --git a/app/src/main/java/mk/ukim/finki/my_distributor/ui/activities/CustomerActivity.kt b/app/src/main/java/mk/ukim/finki/my_distributor/ui/activities/CustomerActivity.kt
index ee0ebac..5bd8beb 100644
--- a/app/src/main/java/mk/ukim/finki/my_distributor/ui/activities/CustomerActivity.kt
+++ b/app/src/main/java/mk/ukim/finki/my_distributor/ui/activities/CustomerActivity.kt
@@ -18,7 +18,6 @@ class CustomerActivity : AppCompatActivity() {
super.onCreate(savedInstanceState)
binding = ActivityCustomerBinding.inflate(layoutInflater)
- enableEdgeToEdge()
setContentView(binding.root)
val navHostFragment = supportFragmentManager
diff --git a/app/src/main/java/mk/ukim/finki/my_distributor/ui/activities/DriverActivity.kt b/app/src/main/java/mk/ukim/finki/my_distributor/ui/activities/DriverActivity.kt
index 9a11a9e..3f11e05 100644
--- a/app/src/main/java/mk/ukim/finki/my_distributor/ui/activities/DriverActivity.kt
+++ b/app/src/main/java/mk/ukim/finki/my_distributor/ui/activities/DriverActivity.kt
@@ -5,17 +5,33 @@ import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
+import androidx.navigation.NavController
+import androidx.navigation.fragment.NavHostFragment
+import androidx.navigation.ui.setupWithNavController
import mk.ukim.finki.my_distributor.R
+import mk.ukim.finki.my_distributor.databinding.ActivityDriverBinding
class DriverActivity : AppCompatActivity() {
+
+ private lateinit var binding: ActivityDriverBinding
+ private lateinit var navController: NavController
+
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- enableEdgeToEdge()
- setContentView(R.layout.activity_driver)
- 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
- }
+
+ binding = ActivityDriverBinding.inflate(layoutInflater)
+
+ setContentView(binding.root)
+
+ val navHostFragment = supportFragmentManager
+ .findFragmentById(R.id.nav_host_fragment) as NavHostFragment
+ navController = navHostFragment.navController
+
+ binding.bottomNavigation.setupWithNavController(navController)
+
+ }
+
+ override fun onSupportNavigateUp(): Boolean {
+ return navController.navigateUp() || super.onSupportNavigateUp()
}
}
\ No newline at end of file
diff --git a/app/src/main/java/mk/ukim/finki/my_distributor/ui/activities/LoginActivity.kt b/app/src/main/java/mk/ukim/finki/my_distributor/ui/activities/LoginActivity.kt
index 1b7d886..ad1c4d9 100644
--- a/app/src/main/java/mk/ukim/finki/my_distributor/ui/activities/LoginActivity.kt
+++ b/app/src/main/java/mk/ukim/finki/my_distributor/ui/activities/LoginActivity.kt
@@ -37,7 +37,6 @@ class LoginActivity : AppCompatActivity() {
super.onCreate(savedInstanceState)
binding = ActivityLoginBinding.inflate(layoutInflater)
- enableEdgeToEdge()
setContentView(binding.root)
viewModel.loginResponse.observe(this) {
@@ -65,7 +64,7 @@ class LoginActivity : AppCompatActivity() {
finish()
}
- decoded.roles.contains("DRIVER") -> {
+ decoded.roles.contains("ROLE_DRIVER") -> {
val intent = Intent(this, DriverActivity::class.java)
startActivity(intent)
finish()
diff --git a/app/src/main/java/mk/ukim/finki/my_distributor/ui/activities/MainActivity.kt b/app/src/main/java/mk/ukim/finki/my_distributor/ui/activities/MainActivity.kt
index 465bb6b..45fd61d 100644
--- a/app/src/main/java/mk/ukim/finki/my_distributor/ui/activities/MainActivity.kt
+++ b/app/src/main/java/mk/ukim/finki/my_distributor/ui/activities/MainActivity.kt
@@ -10,7 +10,6 @@ import mk.ukim.finki.my_distributor.R
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- enableEdgeToEdge()
setContentView(R.layout.activity_main)
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
diff --git a/app/src/main/java/mk/ukim/finki/my_distributor/ui/activities/ManagerActivity.kt b/app/src/main/java/mk/ukim/finki/my_distributor/ui/activities/ManagerActivity.kt
index 7e6e47b..968343b 100644
--- a/app/src/main/java/mk/ukim/finki/my_distributor/ui/activities/ManagerActivity.kt
+++ b/app/src/main/java/mk/ukim/finki/my_distributor/ui/activities/ManagerActivity.kt
@@ -10,7 +10,6 @@ import mk.ukim.finki.my_distributor.R
class ManagerActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- enableEdgeToEdge()
setContentView(R.layout.activity_manager)
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
diff --git a/app/src/main/java/mk/ukim/finki/my_distributor/ui/adapters/DeliveriesAdapter.kt b/app/src/main/java/mk/ukim/finki/my_distributor/ui/adapters/DeliveriesAdapter.kt
index 0341af8..87c6337 100644
--- a/app/src/main/java/mk/ukim/finki/my_distributor/ui/adapters/DeliveriesAdapter.kt
+++ b/app/src/main/java/mk/ukim/finki/my_distributor/ui/adapters/DeliveriesAdapter.kt
@@ -20,7 +20,9 @@ class DeliveriesAdapter(
fun bind(delivery: DeliveryDto) {
binding.deliveryTitle.text = delivery.delDate.toString()
binding.deliverySummary.text = "Driver: " + delivery.driverName
- binding.root.setOnClickListener { onItemClicked(delivery) }
+ binding.root.setOnClickListener {
+ onItemClicked(delivery)
+ }
}
}
diff --git a/app/src/main/java/mk/ukim/finki/my_distributor/ui/adapters/DeliveryOrdersAdapter.kt b/app/src/main/java/mk/ukim/finki/my_distributor/ui/adapters/DeliveryOrdersAdapter.kt
new file mode 100644
index 0000000..9c9bace
--- /dev/null
+++ b/app/src/main/java/mk/ukim/finki/my_distributor/ui/adapters/DeliveryOrdersAdapter.kt
@@ -0,0 +1,43 @@
+package mk.ukim.finki.my_distributor.ui.adapters
+
+import android.annotation.SuppressLint
+import android.view.LayoutInflater
+import android.view.ViewGroup
+import androidx.recyclerview.widget.DiffUtil
+import androidx.recyclerview.widget.ListAdapter
+import androidx.recyclerview.widget.RecyclerView
+import mk.ukim.finki.my_distributor.databinding.ItemOrderDetailBinding
+import mk.ukim.finki.my_distributor.domain.dto.OrderDeliveryDto
+
+object OrderDtoDiffCallback : DiffUtil.ItemCallback() {
+ override fun areItemsTheSame(oldItem: OrderDeliveryDto, newItem: OrderDeliveryDto): Boolean {
+ return oldItem.id == newItem.id
+ }
+
+ override fun areContentsTheSame(oldItem: OrderDeliveryDto, newItem: OrderDeliveryDto): Boolean {
+ return oldItem == newItem
+ }
+}
+
+class DeliveryOrdersAdapter : ListAdapter(OrderDtoDiffCallback) {
+
+ inner class OrderViewHolder(private val binding: ItemOrderDetailBinding) :
+ RecyclerView.ViewHolder(binding.root) {
+ @SuppressLint("SetTextI18n")
+ fun bind(order: OrderDeliveryDto) {
+ binding.articleNameTextView.text = "Order #${order.id}"
+ binding.articleQuantityTextView.text = "Qty: [N/A]"
+ binding.unitPriceTextView.text = "Unit: $${order.ordSum}"
+ binding.totalPriceTextView.text = "Total: $${order.ordSum}"
+ }
+ }
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): OrderViewHolder {
+ val binding = ItemOrderDetailBinding.inflate(LayoutInflater.from(parent.context), parent, false)
+ return OrderViewHolder(binding)
+ }
+
+ override fun onBindViewHolder(holder: OrderViewHolder, position: Int) {
+ holder.bind(getItem(position))
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/mk/ukim/finki/my_distributor/ui/adapters/DeliveryStopsAdapter.kt b/app/src/main/java/mk/ukim/finki/my_distributor/ui/adapters/DeliveryStopsAdapter.kt
new file mode 100644
index 0000000..b0dddcb
--- /dev/null
+++ b/app/src/main/java/mk/ukim/finki/my_distributor/ui/adapters/DeliveryStopsAdapter.kt
@@ -0,0 +1,32 @@
+package mk.ukim.finki.my_distributor.ui.adapters
+
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.recyclerview.widget.ListAdapter
+import androidx.recyclerview.widget.RecyclerView
+import mk.ukim.finki.my_distributor.databinding.ItemOrderDetailBinding
+import mk.ukim.finki.my_distributor.domain.dto.OrderDeliveryDto
+
+class DeliveryStopsAdapter(
+ private val onStopClicked: (OrderDeliveryDto) -> Unit
+) : ListAdapter(OrderDtoDiffCallback) {
+ inner class StopVH(val b: ItemOrderDetailBinding)
+ : RecyclerView.ViewHolder(b.root){
+ fun bind(o: OrderDeliveryDto){
+ b.articleNameTextView.text = "Order #${o.id}"
+ b.articleQuantityTextView.text = "Qty: [N/A]"
+ b.unitPriceTextView.text = "Sum: $${o.ordSum}"
+ b.totalPriceTextView.visibility = View.GONE
+ b.root.setOnClickListener { onStopClicked(o) }
+ }
+ }
+
+ override fun onCreateViewHolder(p: ViewGroup, v: Int) = StopVH(
+ ItemOrderDetailBinding.inflate(
+ LayoutInflater.from(p.context), p, false
+ )
+ )
+
+ override fun onBindViewHolder(h: StopVH, pos: Int) = h.bind(getItem(pos))
+}
\ No newline at end of file
diff --git a/app/src/main/java/mk/ukim/finki/my_distributor/ui/adapters/DriverDeliveriesAdapter.kt b/app/src/main/java/mk/ukim/finki/my_distributor/ui/adapters/DriverDeliveriesAdapter.kt
new file mode 100644
index 0000000..8caa2d4
--- /dev/null
+++ b/app/src/main/java/mk/ukim/finki/my_distributor/ui/adapters/DriverDeliveriesAdapter.kt
@@ -0,0 +1,50 @@
+package mk.ukim.finki.my_distributor.ui.adapters
+
+import android.annotation.SuppressLint
+import android.view.LayoutInflater
+import android.view.ViewGroup
+import androidx.recyclerview.widget.RecyclerView
+import mk.ukim.finki.my_distributor.databinding.ItemDriverDeliveryBinding
+import mk.ukim.finki.my_distributor.domain.dto.DeliverySimpleDto
+
+class DriverDeliveriesAdapter(
+ private var deliveries: List,
+ private val onDeliveryClicked: (DeliverySimpleDto) -> Unit
+) : RecyclerView.Adapter() {
+
+ inner class DeliveryViewHolder(private val binding: ItemDriverDeliveryBinding) :
+ RecyclerView.ViewHolder(binding.root) {
+ @SuppressLint("SetTextI18n")
+ fun bind(delivery: DeliverySimpleDto) {
+ binding.deliveryDateTextView.text = "Delivery Date: ${delivery.deliveryDate}"
+ binding.statusTextView.text = "Status: ${delivery.deliveryStatusName}"
+ binding.routeInfoTextView.text = "Route estimate"
+ binding.root.setOnClickListener {
+ onDeliveryClicked(delivery)
+ }
+ }
+ }
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): DeliveryViewHolder {
+ val binding = ItemDriverDeliveryBinding.inflate(
+ LayoutInflater.from(parent.context),
+ parent,
+ false
+ )
+ return DeliveryViewHolder(binding)
+ }
+
+ override fun onBindViewHolder(holder: DeliveryViewHolder, position: Int) {
+ holder.bind(deliveries[position])
+ }
+
+ override fun getItemCount(): Int {
+ return deliveries.size
+ }
+
+ @SuppressLint("NotifyDataSetChanged")
+ fun updateData(newDelivereis: List) {
+ deliveries = newDelivereis
+ notifyDataSetChanged()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/mk/ukim/finki/my_distributor/ui/adapters/OrderInDeliveryAdapter.kt b/app/src/main/java/mk/ukim/finki/my_distributor/ui/adapters/OrderInDeliveryAdapter.kt
new file mode 100644
index 0000000..4411a19
--- /dev/null
+++ b/app/src/main/java/mk/ukim/finki/my_distributor/ui/adapters/OrderInDeliveryAdapter.kt
@@ -0,0 +1,35 @@
+package mk.ukim.finki.my_distributor.ui.adapters
+
+import android.annotation.SuppressLint
+import android.view.LayoutInflater
+import android.view.ViewGroup
+import androidx.recyclerview.widget.DiffUtil
+import androidx.recyclerview.widget.ListAdapter
+import androidx.recyclerview.widget.RecyclerView
+import mk.ukim.finki.my_distributor.databinding.ItemOrderInDeliveryBinding
+import mk.ukim.finki.my_distributor.domain.dto.OrderDeliveryDto
+
+object OrderDiffCallback : DiffUtil.ItemCallback() {
+ override fun areItemsTheSame(o1: OrderDeliveryDto, o2: OrderDeliveryDto) = o1.id == o2.id
+ override fun areContentsTheSame(o1: OrderDeliveryDto, o2: OrderDeliveryDto) = o1 == o2
+}
+class OrderInDeliveryAdapter :
+ ListAdapter(OrderDiffCallback) {
+
+ inner class VH(private val binding: ItemOrderInDeliveryBinding) :
+ RecyclerView.ViewHolder(binding.root) {
+ @SuppressLint("SetTextI18n")
+ fun bind(o: OrderDeliveryDto) {
+ binding.orderIdTextView.text = "Order #${o.id}"
+ binding.totalPriceTextView.text = "Total: $${o.ordSum}"
+ }
+ }
+
+ override fun onCreateViewHolder(p: ViewGroup, v: Int) = VH(
+ ItemOrderInDeliveryBinding.inflate(
+ LayoutInflater.from(p.context), p, false
+ )
+ )
+
+ override fun onBindViewHolder(h: VH, pos: Int) = h.bind(getItem(pos))
+}
\ No newline at end of file
diff --git a/app/src/main/java/mk/ukim/finki/my_distributor/ui/fragments/customer/ProfileFragment.kt b/app/src/main/java/mk/ukim/finki/my_distributor/ui/fragments/customer/CustomerProfileFragment.kt
similarity index 74%
rename from app/src/main/java/mk/ukim/finki/my_distributor/ui/fragments/customer/ProfileFragment.kt
rename to app/src/main/java/mk/ukim/finki/my_distributor/ui/fragments/customer/CustomerProfileFragment.kt
index 3920d16..7a72e75 100644
--- a/app/src/main/java/mk/ukim/finki/my_distributor/ui/fragments/customer/ProfileFragment.kt
+++ b/app/src/main/java/mk/ukim/finki/my_distributor/ui/fragments/customer/CustomerProfileFragment.kt
@@ -7,15 +7,15 @@ import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import mk.ukim.finki.my_distributor.R
-import mk.ukim.finki.my_distributor.ui.viewmodel.ProfileViewModel
+import mk.ukim.finki.my_distributor.ui.viewmodel.CustomerProfileViewModel
-class ProfileFragment : Fragment() {
+class CustomerProfileFragment : Fragment() {
companion object {
- fun newInstance() = ProfileFragment()
+ fun newInstance() = CustomerProfileFragment()
}
- private val viewModel: ProfileViewModel by viewModels()
+ private val viewModel: CustomerProfileViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
diff --git a/app/src/main/java/mk/ukim/finki/my_distributor/ui/fragments/customer/DeliveryDetailFragment.kt b/app/src/main/java/mk/ukim/finki/my_distributor/ui/fragments/customer/DeliveryDetailFragment.kt
index 55b40c7..c9111df 100644
--- a/app/src/main/java/mk/ukim/finki/my_distributor/ui/fragments/customer/DeliveryDetailFragment.kt
+++ b/app/src/main/java/mk/ukim/finki/my_distributor/ui/fragments/customer/DeliveryDetailFragment.kt
@@ -1,37 +1,75 @@
package mk.ukim.finki.my_distributor.ui.fragments.customer
+import android.annotation.SuppressLint
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
+import android.widget.Toast
import androidx.fragment.app.Fragment
+import androidx.fragment.app.viewModels
+import androidx.navigation.fragment.findNavController
import androidx.navigation.fragment.navArgs
+import androidx.recyclerview.widget.LinearLayoutManager
+import mk.ukim.finki.my_distributor.data.api.RetrofitClient
+import mk.ukim.finki.my_distributor.data.local.UserPreferences
+import mk.ukim.finki.my_distributor.data.repository.DeliveryRepository
import mk.ukim.finki.my_distributor.databinding.FragmentDeliveryDetailBinding
+import mk.ukim.finki.my_distributor.ui.adapters.OrderInDeliveryAdapter
+import mk.ukim.finki.my_distributor.ui.fragments.driver.DeliveryDetailFragmentDirections
+import mk.ukim.finki.my_distributor.ui.viewmodel.DeliveryDetailViewModel
+import mk.ukim.finki.my_distributor.ui.viewmodel.DeliveryDetailViewModelFactory
class DeliveryDetailFragment : Fragment() {
-
private var _binding: FragmentDeliveryDetailBinding? = null
private val binding get() = _binding!!
private val args: DeliveryDetailFragmentArgs by navArgs()
- override fun onCreateView(
- inflater: LayoutInflater, container: ViewGroup?,
- savedInstanceState: Bundle?
- ): View {
- _binding = FragmentDeliveryDetailBinding.inflate(inflater, container, false)
- return binding.root
+ private val repo by lazy {
+ DeliveryRepository(
+ RetrofitClient.getDeliveryApiService(
+ UserPreferences.getInstance(requireContext())
+ )
+ )
+ }
+
+ private val viewModel: DeliveryDetailViewModel by viewModels {
+ DeliveryDetailViewModelFactory(repo)
}
+ private lateinit var adapter: OrderInDeliveryAdapter
+
+ override fun onCreateView(i: LayoutInflater, c: ViewGroup?, s: Bundle?) =
+ FragmentDeliveryDetailBinding.inflate(i, c, false).also { _binding = it }.root
+
+ @SuppressLint("SetTextI18n")
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
- val deliveryId = args.deliveryId
- binding.deliveryIdTextView.text = "Delivery ID: $deliveryId"
- // TODO: Load delivery details if needed
+
+ adapter = OrderInDeliveryAdapter()
+ binding.stopsRv.layoutManager = LinearLayoutManager(requireContext())
+ binding.stopsRv.adapter = adapter
+
+ viewModel.detail.observe(viewLifecycleOwner) { dto ->
+ binding.deliveryDateTv.text = "Date: ${dto?.delivery?.delDate.toString()}"
+ binding.deliveryStatusTv.text = "Status: ${dto?.delivery?.delStatus}"
+ adapter.submitList(dto?.orders)
+ }
+ viewModel.error.observe(viewLifecycleOwner) {
+ Toast.makeText(requireContext(), it, Toast.LENGTH_SHORT).show()
+ }
+
+ viewModel.load(args.deliveryId)
+
+ binding.startDeliveryBtn.setOnClickListener {
+ val action = DeliveryDetailFragmentDirections
+ .actionDeliveryDetailFragmentToStartDeliveryFragment(args.deliveryId)
+ findNavController().navigate(action)
+ }
}
- override fun onDestroy() {
- super.onDestroy()
- _binding = null
+ override fun onDestroyView() {
+ super.onDestroyView(); _binding = null
}
}
\ No newline at end of file
diff --git a/app/src/main/java/mk/ukim/finki/my_distributor/ui/fragments/driver/DeliveryDetailFragment.kt b/app/src/main/java/mk/ukim/finki/my_distributor/ui/fragments/driver/DeliveryDetailFragment.kt
new file mode 100644
index 0000000..5dfc989
--- /dev/null
+++ b/app/src/main/java/mk/ukim/finki/my_distributor/ui/fragments/driver/DeliveryDetailFragment.kt
@@ -0,0 +1,82 @@
+package mk.ukim.finki.my_distributor.ui.fragments.driver
+
+import android.annotation.SuppressLint
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.Toast
+import androidx.fragment.app.Fragment
+import androidx.fragment.app.viewModels
+import androidx.navigation.fragment.findNavController
+import androidx.navigation.fragment.navArgs
+import androidx.recyclerview.widget.LinearLayoutManager
+import mk.ukim.finki.my_distributor.data.api.RetrofitClient
+import mk.ukim.finki.my_distributor.data.local.UserPreferences
+import mk.ukim.finki.my_distributor.data.repository.DeliveryRepository
+import mk.ukim.finki.my_distributor.databinding.FragmentDeliveryDetailBinding
+import mk.ukim.finki.my_distributor.ui.adapters.OrderInDeliveryAdapter
+import mk.ukim.finki.my_distributor.ui.fragments.customer.DeliveryDetailFragmentArgs
+import mk.ukim.finki.my_distributor.ui.viewmodel.DeliveryDetailViewModel
+import mk.ukim.finki.my_distributor.ui.viewmodel.DeliveryDetailViewModelFactory
+
+class DeliveryDetailFragment : Fragment() {
+
+ private var _binding: FragmentDeliveryDetailBinding? = null
+ private val binding get() = _binding!!
+
+ private val args: DeliveryDetailFragmentArgs by navArgs()
+
+ private val deliveryRepository by lazy {
+ DeliveryRepository(
+ RetrofitClient.getDeliveryApiService(
+ UserPreferences.getInstance(requireContext())
+ )
+ )
+ }
+
+ private val viewModel: DeliveryDetailViewModel by viewModels {
+ DeliveryDetailViewModelFactory(deliveryRepository)
+ }
+
+ private lateinit var adapter: OrderInDeliveryAdapter
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ _binding = FragmentDeliveryDetailBinding.inflate(inflater, container, false)
+ return binding.root
+ }
+
+ @SuppressLint("SetTextI18n")
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+
+ adapter = OrderInDeliveryAdapter()
+ binding.stopsRv.layoutManager = LinearLayoutManager(requireContext())
+ binding.stopsRv.adapter = adapter
+
+ viewModel.detail.observe(viewLifecycleOwner) { dto ->
+ binding.deliveryDateTv.text = "Date: ${dto?.delivery?.delDate.toString()}"
+ binding.deliveryDateTv.text = "Status: ${dto?.delivery?.delStatus}"
+ adapter.submitList(dto?.orders)
+ }
+ viewModel.error.observe(viewLifecycleOwner) {
+ Toast.makeText(requireContext(), it, Toast.LENGTH_SHORT).show()
+ }
+
+ viewModel.load(args.deliveryId)
+
+ binding.startDeliveryBtn.setOnClickListener {
+ val action = DeliveryDetailFragmentDirections
+ .actionDeliveryDetailFragmentToStartDeliveryFragment(args.deliveryId)
+ findNavController().navigate(action)
+ }
+ }
+
+ override fun onDestroyView() {
+ super.onDestroyView(); _binding = null
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/mk/ukim/finki/my_distributor/ui/fragments/driver/DriverDashboardFragment.kt b/app/src/main/java/mk/ukim/finki/my_distributor/ui/fragments/driver/DriverDashboardFragment.kt
new file mode 100644
index 0000000..1a52f04
--- /dev/null
+++ b/app/src/main/java/mk/ukim/finki/my_distributor/ui/fragments/driver/DriverDashboardFragment.kt
@@ -0,0 +1,84 @@
+package mk.ukim.finki.my_distributor.ui.fragments.driver
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.Toast
+import androidx.fragment.app.Fragment
+import androidx.fragment.app.viewModels
+import androidx.navigation.fragment.findNavController
+import androidx.recyclerview.widget.LinearLayoutManager
+import mk.ukim.finki.my_distributor.data.api.RetrofitClient
+import mk.ukim.finki.my_distributor.data.local.UserPreferences
+import mk.ukim.finki.my_distributor.data.repository.DeliveryRepository
+import mk.ukim.finki.my_distributor.databinding.FragmentDriverDashboardBinding
+import mk.ukim.finki.my_distributor.ui.adapters.DriverDeliveriesAdapter
+import mk.ukim.finki.my_distributor.ui.viewmodel.DriverDashboardViewModel
+import mk.ukim.finki.my_distributor.ui.viewmodel.DriverDashboardViewModelFactory
+
+class DriverDashboardFragment : Fragment() {
+
+ private var _binding: FragmentDriverDashboardBinding? = null
+ private val binding get() = _binding!!
+
+ private val deliveryRepository: DeliveryRepository by lazy {
+ DeliveryRepository(
+ RetrofitClient.getDeliveryApiService(
+ UserPreferences.getInstance(requireContext())
+ )
+ )
+ }
+
+ private val driverDashboardViewModel: DriverDashboardViewModel by viewModels {
+ DriverDashboardViewModelFactory(deliveryRepository)
+ }
+
+ private lateinit var deliveriesAdapter: DriverDeliveriesAdapter
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View {
+ _binding = FragmentDriverDashboardBinding.inflate(inflater, container, false)
+ return binding.root
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ binding.deliveriesRecyclerView.layoutManager = LinearLayoutManager(requireContext())
+
+ deliveriesAdapter = DriverDeliveriesAdapter(emptyList()) { delivery ->
+ val action = DriverDashboardFragmentDirections
+ .actionDriverDashboardFragmentToDeliveryDetailFragment(delivery.deliveryId)
+ findNavController().navigate(action)
+ }
+ binding.deliveriesRecyclerView.adapter = deliveriesAdapter
+
+ driverDashboardViewModel.deliveries.observe(viewLifecycleOwner) { list ->
+ if(list.isEmpty()){
+ binding.emptyTextView.visibility=View.VISIBLE
+ binding.deliveriesRecyclerView.visibility = View.GONE
+ }else {
+ binding.emptyTextView.visibility = View.GONE
+ binding.deliveriesRecyclerView.visibility = View.VISIBLE
+ deliveriesAdapter.updateData(list)
+ }
+ }
+
+ driverDashboardViewModel.error.observe(viewLifecycleOwner) { errorMsg ->
+ Toast.makeText(
+ requireContext(),
+ errorMsg,
+ Toast.LENGTH_SHORT
+ ).show()
+ }
+
+ driverDashboardViewModel.loadDriverDeliveries()
+ }
+
+ override fun onDestroyView() {
+ super.onDestroyView()
+ _binding = null
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/mk/ukim/finki/my_distributor/ui/fragments/driver/DriverProfileFragment.kt b/app/src/main/java/mk/ukim/finki/my_distributor/ui/fragments/driver/DriverProfileFragment.kt
new file mode 100644
index 0000000..52238d7
--- /dev/null
+++ b/app/src/main/java/mk/ukim/finki/my_distributor/ui/fragments/driver/DriverProfileFragment.kt
@@ -0,0 +1,65 @@
+package mk.ukim.finki.my_distributor.ui.fragments.driver
+
+import android.content.Intent
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.fragment.app.Fragment
+import androidx.navigation.fragment.findNavController
+import mk.ukim.finki.my_distributor.data.local.UserPreferences
+import mk.ukim.finki.my_distributor.databinding.FragmentDriverProfileBinding
+import mk.ukim.finki.my_distributor.ui.activities.LoginActivity
+
+class DriverProfileFragment : Fragment() {
+
+ private var _binding: FragmentDriverProfileBinding? = null
+ private val binding get() = _binding!!
+
+ private val prefs by lazy { UserPreferences.getInstance(requireContext()) }
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
+ ) = FragmentDriverProfileBinding.inflate(inflater, container, false)
+ .also { _binding = it }.root
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+
+ prefs.getUserInfo()?.let { user ->
+ binding.nameTextView.text = user.name
+ binding.emailTextView.text = user.email
+ } ?: run {
+ binding.nameTextView.text = "Unknown User"
+ binding.emailTextView.text = ""
+ }
+
+ binding.viewPastButton.setOnClickListener {
+ findNavController().navigate(
+ DriverProfileFragmentDirections
+ .actionDriverProfileFragmentToPastDeliveriesFragment()
+ )
+ }
+
+ binding.editProfileButton.setOnClickListener {
+ }
+
+ binding.logoutButton.setOnClickListener {
+ prefs.clearToken()
+ prefs.clearUserInfo()
+
+ val intent = Intent(requireContext(), LoginActivity::class.java).apply {
+ flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
+ }
+ startActivity(intent)
+
+ requireActivity().finish()
+ }
+
+ }
+
+ override fun onDestroyView() {
+ super.onDestroyView()
+ _binding = null
+ }
+}
diff --git a/app/src/main/java/mk/ukim/finki/my_distributor/ui/fragments/driver/PastDeliveriesFragment.kt b/app/src/main/java/mk/ukim/finki/my_distributor/ui/fragments/driver/PastDeliveriesFragment.kt
new file mode 100644
index 0000000..d102752
--- /dev/null
+++ b/app/src/main/java/mk/ukim/finki/my_distributor/ui/fragments/driver/PastDeliveriesFragment.kt
@@ -0,0 +1,32 @@
+package mk.ukim.finki.my_distributor.ui.fragments.driver
+
+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 mk.ukim.finki.my_distributor.R
+import mk.ukim.finki.my_distributor.ui.viewmodel.PastDeliveriesViewModel
+
+class PastDeliveriesFragment : Fragment() {
+
+ companion object {
+ fun newInstance() = PastDeliveriesFragment()
+ }
+
+ private val viewModel: PastDeliveriesViewModel by viewModels()
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ // TODO: Use the ViewModel
+ }
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View {
+ return inflater.inflate(R.layout.fragment_past_deliveries, container, false)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/mk/ukim/finki/my_distributor/ui/fragments/driver/PastDeliveryDetailFragment.kt b/app/src/main/java/mk/ukim/finki/my_distributor/ui/fragments/driver/PastDeliveryDetailFragment.kt
new file mode 100644
index 0000000..182d499
--- /dev/null
+++ b/app/src/main/java/mk/ukim/finki/my_distributor/ui/fragments/driver/PastDeliveryDetailFragment.kt
@@ -0,0 +1,32 @@
+package mk.ukim.finki.my_distributor.ui.fragments.driver
+
+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 mk.ukim.finki.my_distributor.R
+import mk.ukim.finki.my_distributor.ui.viewmodel.PastDeliveryDetailViewModel
+
+class PastDeliveryDetailFragment : Fragment() {
+
+ companion object {
+ fun newInstance() = PastDeliveryDetailFragment()
+ }
+
+ private val viewModel: PastDeliveryDetailViewModel by viewModels()
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ // TODO: Use the ViewModel
+ }
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View {
+ return inflater.inflate(R.layout.fragment_past_delivery_detail, container, false)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/mk/ukim/finki/my_distributor/ui/fragments/driver/StartDeliveryFragment.kt b/app/src/main/java/mk/ukim/finki/my_distributor/ui/fragments/driver/StartDeliveryFragment.kt
new file mode 100644
index 0000000..f35c63a
--- /dev/null
+++ b/app/src/main/java/mk/ukim/finki/my_distributor/ui/fragments/driver/StartDeliveryFragment.kt
@@ -0,0 +1,124 @@
+package mk.ukim.finki.my_distributor.ui.fragments.driver
+
+import android.content.Intent
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.Toast
+import androidx.activity.result.contract.ActivityResultContracts
+import androidx.core.net.toUri
+import androidx.fragment.app.Fragment
+import androidx.fragment.app.viewModels
+import androidx.navigation.fragment.navArgs
+import androidx.recyclerview.widget.ItemTouchHelper
+import androidx.recyclerview.widget.LinearLayoutManager
+import androidx.recyclerview.widget.RecyclerView
+import mk.ukim.finki.my_distributor.data.api.RetrofitClient
+import mk.ukim.finki.my_distributor.data.local.UserPreferences
+import mk.ukim.finki.my_distributor.data.repository.DeliveryRepository
+import mk.ukim.finki.my_distributor.databinding.FragmentStartDeliveryBinding
+import mk.ukim.finki.my_distributor.ui.adapters.OrderInDeliveryAdapter
+import mk.ukim.finki.my_distributor.ui.viewmodel.StartDeliveryViewModel
+import mk.ukim.finki.my_distributor.ui.viewmodel.StartDeliveryViewModelFactory
+
+class StartDeliveryFragment : Fragment() {
+ private var _binding: FragmentStartDeliveryBinding? = null
+ private val binding get() = _binding!!
+ private val args: StartDeliveryFragmentArgs by navArgs()
+
+ private val repo by lazy {
+ DeliveryRepository(
+ RetrofitClient.getDeliveryApiService(UserPreferences.getInstance(requireContext()))
+ )
+ }
+ private val viewModel: StartDeliveryViewModel by viewModels {
+ StartDeliveryViewModelFactory(repo)
+ }
+ private lateinit var adapter: OrderInDeliveryAdapter
+
+ // 1) Register an ActivityResultLauncher for Google Maps
+ private val mapsLauncher = registerForActivityResult(
+ ActivityResultContracts.StartActivityForResult()
+ ) {
+ // Called when Maps closes
+ Toast.makeText(requireContext(),
+ "Returned from navigation", Toast.LENGTH_SHORT).show()
+ viewModel.markCurrentStopDone()
+ }
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
+ ) = FragmentStartDeliveryBinding.inflate(inflater, container, false)
+ .also { _binding = it }.root
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+
+ // Set up RecyclerView + ListAdapter
+ adapter = OrderInDeliveryAdapter()
+ binding.stopsRecyclerView.layoutManager = LinearLayoutManager(requireContext())
+ binding.stopsRecyclerView.adapter = adapter
+
+ // Observe the stops list
+ viewModel.orders.observe(viewLifecycleOwner) { list ->
+ adapter.submitList(list.toList()) // submit an immutable copy
+ }
+ viewModel.error.observe(viewLifecycleOwner) {
+ Toast.makeText(requireContext(), it, Toast.LENGTH_SHORT).show()
+ }
+ viewModel.loadDeliveryWithOrders(args.deliveryId)
+
+ // 2) Hook up drag-and-drop using ItemTouchHelper
+ ItemTouchHelper(object : ItemTouchHelper.Callback() {
+ override fun getMovementFlags(
+ recyclerView: RecyclerView,
+ viewHolder: RecyclerView.ViewHolder
+ ) = makeMovementFlags(
+ ItemTouchHelper.UP or ItemTouchHelper.DOWN,
+ 0
+ )
+
+ override fun onMove(
+ rv: RecyclerView,
+ vh: RecyclerView.ViewHolder,
+ target: RecyclerView.ViewHolder
+ ): Boolean {
+ val from = vh.adapterPosition
+ val to = target.adapterPosition
+ viewModel.reorderOrders(from, to)
+ return true
+ }
+
+ override fun onSwiped(vh: RecyclerView.ViewHolder, direction: Int) {
+ // no-op
+ }
+ }).attachToRecyclerView(binding.stopsRecyclerView)
+
+ // 3) Begin navigation button
+ binding.beginNavigationButton.setOnClickListener {
+ val km = binding.startKmEditText.text.toString().toIntOrNull()
+ if (km == null || km <= 0) {
+ Toast.makeText(requireContext(),
+ "Enter valid kilometers", Toast.LENGTH_SHORT).show()
+ return@setOnClickListener
+ }
+
+ viewModel.startDelivery(km)
+
+ // Get the *current* first stop from VM and launch Maps
+ viewModel.currentStopLocation.value?.let { loc ->
+ val uri = "google.navigation:q=${loc.latitude},${loc.longitude}".toUri()
+ val intent = Intent(Intent.ACTION_VIEW, uri)
+ .setPackage("com.google.android.apps.maps")
+ mapsLauncher.launch(intent)
+ } ?: Toast.makeText(requireContext(),
+ "No stops available", Toast.LENGTH_SHORT).show()
+ }
+ }
+
+ override fun onDestroyView() {
+ super.onDestroyView()
+ _binding = null
+ }
+}
diff --git a/app/src/main/java/mk/ukim/finki/my_distributor/ui/viewmodel/CreateOrderViewModel.kt b/app/src/main/java/mk/ukim/finki/my_distributor/ui/viewmodel/CreateOrderViewModel.kt
index d279bfe..4dee56c 100644
--- a/app/src/main/java/mk/ukim/finki/my_distributor/ui/viewmodel/CreateOrderViewModel.kt
+++ b/app/src/main/java/mk/ukim/finki/my_distributor/ui/viewmodel/CreateOrderViewModel.kt
@@ -3,11 +3,24 @@ package mk.ukim.finki.my_distributor.ui.viewmodel
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
+import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.launch
import mk.ukim.finki.my_distributor.data.repository.ArticlesRepository
import mk.ukim.finki.my_distributor.domain.dto.ArticleDto
+class CreateOrderViewModelFactory(
+ private val articlesRepository: ArticlesRepository
+) : ViewModelProvider.Factory {
+ override fun create(modelClass: Class): T {
+ if (modelClass.isAssignableFrom(CreateOrderViewModel::class.java)) {
+ @Suppress("UNCHECKED_CAST")
+ return CreateOrderViewModel(articlesRepository) as T
+ }
+ throw IllegalArgumentException("Unknown ViewModel class")
+ }
+}
+
class CreateOrderViewModel(
private val articlesRepository: ArticlesRepository
) : ViewModel() {
diff --git a/app/src/main/java/mk/ukim/finki/my_distributor/ui/viewmodel/CreateOrderViewModelFactory.kt b/app/src/main/java/mk/ukim/finki/my_distributor/ui/viewmodel/CreateOrderViewModelFactory.kt
deleted file mode 100644
index 121322d..0000000
--- a/app/src/main/java/mk/ukim/finki/my_distributor/ui/viewmodel/CreateOrderViewModelFactory.kt
+++ /dev/null
@@ -1,17 +0,0 @@
-package mk.ukim.finki.my_distributor.ui.viewmodel
-
-import androidx.lifecycle.ViewModel
-import androidx.lifecycle.ViewModelProvider
-import mk.ukim.finki.my_distributor.data.repository.ArticlesRepository
-
-class CreateOrderViewModelFactory(
- private val articlesRepository: ArticlesRepository
-) : ViewModelProvider.Factory {
- override fun create(modelClass: Class): T {
- if (modelClass.isAssignableFrom(CreateOrderViewModel::class.java)) {
- @Suppress("UNCHECKED_CAST")
- return CreateOrderViewModel(articlesRepository) as T
- }
- throw IllegalArgumentException("Unknown ViewModel class")
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/mk/ukim/finki/my_distributor/ui/viewmodel/CustomerProfileViewModel.kt b/app/src/main/java/mk/ukim/finki/my_distributor/ui/viewmodel/CustomerProfileViewModel.kt
new file mode 100644
index 0000000..9df940e
--- /dev/null
+++ b/app/src/main/java/mk/ukim/finki/my_distributor/ui/viewmodel/CustomerProfileViewModel.kt
@@ -0,0 +1,7 @@
+package mk.ukim.finki.my_distributor.ui.viewmodel
+
+import androidx.lifecycle.ViewModel
+
+class CustomerProfileViewModel : ViewModel() {
+ // TODO: Implement the ViewModel
+}
\ No newline at end of file
diff --git a/app/src/main/java/mk/ukim/finki/my_distributor/ui/viewmodel/DeliveryDetailViewModel.kt b/app/src/main/java/mk/ukim/finki/my_distributor/ui/viewmodel/DeliveryDetailViewModel.kt
index 3247ab1..0a9bc19 100644
--- a/app/src/main/java/mk/ukim/finki/my_distributor/ui/viewmodel/DeliveryDetailViewModel.kt
+++ b/app/src/main/java/mk/ukim/finki/my_distributor/ui/viewmodel/DeliveryDetailViewModel.kt
@@ -1,7 +1,28 @@
package mk.ukim.finki.my_distributor.ui.viewmodel
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
+import kotlinx.coroutines.launch
+import mk.ukim.finki.my_distributor.data.repository.DeliveryRepository
+import mk.ukim.finki.my_distributor.domain.dto.DeliveryWithOrdersDto
-class DeliveryDetailViewModel : ViewModel() {
- // TODO: Implement the ViewModel
+class DeliveryDetailViewModel(
+ private val repo: DeliveryRepository
+) : ViewModel() {
+
+ private val _detail = MutableLiveData()
+ val detail: LiveData = _detail
+
+ private val _error = MutableLiveData()
+ val error: LiveData = _error
+
+ fun load(deliveryId: Long){
+ viewModelScope.launch {
+ repo.getDeliveryWithOrders(deliveryId)
+ .onSuccess { _detail.value = it}
+ .onFailure { _error.value = it.message ?: "Unknown error" }
+ }
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/mk/ukim/finki/my_distributor/ui/viewmodel/DeliveryDetailViewModelFactory.kt b/app/src/main/java/mk/ukim/finki/my_distributor/ui/viewmodel/DeliveryDetailViewModelFactory.kt
new file mode 100644
index 0000000..e44d8b2
--- /dev/null
+++ b/app/src/main/java/mk/ukim/finki/my_distributor/ui/viewmodel/DeliveryDetailViewModelFactory.kt
@@ -0,0 +1,17 @@
+package mk.ukim.finki.my_distributor.ui.viewmodel
+
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.ViewModelProvider
+import mk.ukim.finki.my_distributor.data.repository.DeliveryRepository
+
+class DeliveryDetailViewModelFactory(
+ private val repo: DeliveryRepository
+) : ViewModelProvider.Factory{
+ override fun create(cls: Class): T {
+ if(cls.isAssignableFrom(DeliveryDetailViewModel::class.java)){
+ @Suppress("UNCHECKED_CAST")
+ return DeliveryDetailViewModel(repo) as T
+ }
+ throw IllegalArgumentException("Unknown VM")
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/mk/ukim/finki/my_distributor/ui/viewmodel/DriverDashboardViewModel.kt b/app/src/main/java/mk/ukim/finki/my_distributor/ui/viewmodel/DriverDashboardViewModel.kt
new file mode 100644
index 0000000..259463f
--- /dev/null
+++ b/app/src/main/java/mk/ukim/finki/my_distributor/ui/viewmodel/DriverDashboardViewModel.kt
@@ -0,0 +1,30 @@
+package mk.ukim.finki.my_distributor.ui.viewmodel
+
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
+import kotlinx.coroutines.launch
+import mk.ukim.finki.my_distributor.data.repository.DeliveryRepository
+import mk.ukim.finki.my_distributor.domain.dto.DeliverySimpleDto
+
+class DriverDashboardViewModel(
+ private val repository: DeliveryRepository
+) : ViewModel() {
+
+ private val _deliveries = MutableLiveData>()
+ val deliveries: LiveData> get() = _deliveries
+
+ private val _error = MutableLiveData()
+ val error: LiveData get() = _error
+
+ fun loadDriverDeliveries(){
+ viewModelScope.launch {
+ repository.getDriverDeliveries().onSuccess { list ->
+ _deliveries.value = list.sortedBy { it.deliveryDate }
+ }.onFailure { ex ->
+ _error.value = ex.message ?: "An error occurred"
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/mk/ukim/finki/my_distributor/ui/viewmodel/DriverDashboardViewModelFactory.kt b/app/src/main/java/mk/ukim/finki/my_distributor/ui/viewmodel/DriverDashboardViewModelFactory.kt
new file mode 100644
index 0000000..570b782
--- /dev/null
+++ b/app/src/main/java/mk/ukim/finki/my_distributor/ui/viewmodel/DriverDashboardViewModelFactory.kt
@@ -0,0 +1,18 @@
+package mk.ukim.finki.my_distributor.ui.viewmodel
+
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.ViewModelProvider
+import mk.ukim.finki.my_distributor.data.repository.DeliveryRepository
+import mk.ukim.finki.my_distributor.ui.fragments.driver.DriverDashboardFragment
+
+class DriverDashboardViewModelFactory(
+ private val repository: DeliveryRepository
+) : ViewModelProvider.Factory {
+ override fun create(modelClass: Class): T {
+ if (modelClass.isAssignableFrom(DriverDashboardViewModel::class.java)) {
+ @Suppress("UNCHECKED_CAST")
+ return DriverDashboardViewModel(repository) as T
+ }
+ throw IllegalArgumentException("Unknown ViewModel class")
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/mk/ukim/finki/my_distributor/ui/viewmodel/ProfileViewModel.kt b/app/src/main/java/mk/ukim/finki/my_distributor/ui/viewmodel/DriverProfileViewModel.kt
similarity index 73%
rename from app/src/main/java/mk/ukim/finki/my_distributor/ui/viewmodel/ProfileViewModel.kt
rename to app/src/main/java/mk/ukim/finki/my_distributor/ui/viewmodel/DriverProfileViewModel.kt
index 87f5bb7..24c5878 100644
--- a/app/src/main/java/mk/ukim/finki/my_distributor/ui/viewmodel/ProfileViewModel.kt
+++ b/app/src/main/java/mk/ukim/finki/my_distributor/ui/viewmodel/DriverProfileViewModel.kt
@@ -2,6 +2,6 @@ package mk.ukim.finki.my_distributor.ui.viewmodel
import androidx.lifecycle.ViewModel
-class ProfileViewModel : ViewModel() {
+class DriverProfileViewModel : ViewModel() {
// TODO: Implement the ViewModel
}
\ No newline at end of file
diff --git a/app/src/main/java/mk/ukim/finki/my_distributor/ui/viewmodel/PastDeliveriesViewModel.kt b/app/src/main/java/mk/ukim/finki/my_distributor/ui/viewmodel/PastDeliveriesViewModel.kt
new file mode 100644
index 0000000..6f5bd86
--- /dev/null
+++ b/app/src/main/java/mk/ukim/finki/my_distributor/ui/viewmodel/PastDeliveriesViewModel.kt
@@ -0,0 +1,7 @@
+package mk.ukim.finki.my_distributor.ui.viewmodel
+
+import androidx.lifecycle.ViewModel
+
+class PastDeliveriesViewModel : ViewModel() {
+ // TODO: Implement the ViewModel
+}
\ No newline at end of file
diff --git a/app/src/main/java/mk/ukim/finki/my_distributor/ui/viewmodel/PastDeliveryDetailViewModel.kt b/app/src/main/java/mk/ukim/finki/my_distributor/ui/viewmodel/PastDeliveryDetailViewModel.kt
new file mode 100644
index 0000000..f5a0855
--- /dev/null
+++ b/app/src/main/java/mk/ukim/finki/my_distributor/ui/viewmodel/PastDeliveryDetailViewModel.kt
@@ -0,0 +1,7 @@
+package mk.ukim.finki.my_distributor.ui.viewmodel
+
+import androidx.lifecycle.ViewModel
+
+class PastDeliveryDetailViewModel : ViewModel() {
+ // TODO: Implement the ViewModel
+}
\ No newline at end of file
diff --git a/app/src/main/java/mk/ukim/finki/my_distributor/ui/viewmodel/StartDeliveryViewModel.kt b/app/src/main/java/mk/ukim/finki/my_distributor/ui/viewmodel/StartDeliveryViewModel.kt
new file mode 100644
index 0000000..f63ea12
--- /dev/null
+++ b/app/src/main/java/mk/ukim/finki/my_distributor/ui/viewmodel/StartDeliveryViewModel.kt
@@ -0,0 +1,77 @@
+package mk.ukim.finki.my_distributor.ui.viewmodel
+
+import android.location.Location
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
+import kotlinx.coroutines.launch
+import mk.ukim.finki.my_distributor.data.repository.DeliveryRepository
+import mk.ukim.finki.my_distributor.domain.dto.OrderDeliveryDto
+
+class StartDeliveryViewModel(
+ private val repo: DeliveryRepository
+) : ViewModel() {
+
+ // Backing list of stops/orders
+ private val _orders = MutableLiveData>(emptyList())
+ val orders: LiveData> = _orders
+
+ // Any errors
+ private val _error = MutableLiveData()
+ val error: LiveData = _error
+
+ // The current next-stop Location
+ private val _currentStopLocation = MutableLiveData()
+ val currentStopLocation: LiveData = _currentStopLocation
+
+ /** Loads the delivery and its orders, then sets up the first stop’s location. */
+ fun loadDeliveryWithOrders(id: Long) = viewModelScope.launch {
+ repo.getDeliveryWithOrders(id)
+ .onSuccess { dto ->
+ _orders.value = dto.orders
+ updateCurrentLocation()
+ }
+ .onFailure { ex ->
+ _error.value = ex.message
+ }
+ }
+
+ /** Reorders the stops list, then refreshes the first-stop location. */
+ fun reorderOrders(from: Int, to: Int) {
+ val list = _orders.value?.toMutableList() ?: return
+ val item = list.removeAt(from)
+ list.add(to, item)
+ _orders.value = list
+ updateCurrentLocation()
+ }
+
+ /** Call this when the driver returns from navigating to the current stop. */
+ fun markCurrentStopDone() {
+ val list = _orders.value?.toMutableList() ?: return
+ if (list.isNotEmpty()) {
+ list.removeAt(0)
+ _orders.value = list
+ updateCurrentLocation()
+ }
+ }
+
+ /** Records the starting kilometers — you can expand this to POST to your API. */
+ fun startDelivery(km: Int) {
+ // TODO: Save km in local state or send to backend
+ }
+
+ /** Internal: gets the first order’s lat/lng and posts a Location, or null if none. */
+ private fun updateCurrentLocation() {
+ val first = _orders.value?.firstOrNull()
+ if (first != null) {
+ val loc = Location("app").apply {
+ latitude = first.latitude.toDouble()
+ longitude = first.longitude.toDouble()
+ }
+ _currentStopLocation.value = loc
+ } else {
+ _currentStopLocation.value = null
+ }
+ }
+}
diff --git a/app/src/main/java/mk/ukim/finki/my_distributor/ui/viewmodel/StartDeliveryViewModelFactory.kt b/app/src/main/java/mk/ukim/finki/my_distributor/ui/viewmodel/StartDeliveryViewModelFactory.kt
new file mode 100644
index 0000000..50a7268
--- /dev/null
+++ b/app/src/main/java/mk/ukim/finki/my_distributor/ui/viewmodel/StartDeliveryViewModelFactory.kt
@@ -0,0 +1,14 @@
+package mk.ukim.finki.my_distributor.ui.viewmodel
+
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.ViewModelProvider
+import mk.ukim.finki.my_distributor.data.repository.DeliveryRepository
+
+class StartDeliveryViewModelFactory(
+ private val repo: DeliveryRepository
+) : ViewModelProvider.Factory {
+ override fun create(c: Class): T {
+ @Suppress("UNCHECKED_CAST")
+ return StartDeliveryViewModel(repo) as T
+ }
+}
diff --git a/app/src/main/res/drawable/app_logo.xml b/app/src/main/res/drawable/app_logo.xml
index c32c1ec..f0e345b 100644
--- a/app/src/main/res/drawable/app_logo.xml
+++ b/app/src/main/res/drawable/app_logo.xml
@@ -4,706 +4,851 @@
android:height="200dp"
android:viewportWidth="3710"
android:viewportHeight="3710">
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ android:pathData="M0,0h3710v3710h-3710z"
+ android:fillColor="#FFFFFF" />
-
-
-
+ android:pathData="M3211.6,1649.1c-75.8,-495.9 -386.4,-1105.2 -1000.1,-1169c0,0 -466,-56.7 -925.3,29.2c-272.6,51 -511.7,202.7 -662.9,420.9c-151.3,218.1 -201.8,484.1 -140.5,737.6c39.8,164.7 66.7,335.1 59.4,504.4c-12.9,294.5 -5.5,569.5 280.4,745.1c255.2,156.8 576.4,295.2 882.8,319.4c208.2,16.5 441.8,-10.2 642.5,-64.4C3370.7,2896 3287.3,2145 3211.6,1649.1z"
+ android:fillColor="#F4F7FA" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ android:pathData="M2689.6,2702.4l0,-1747.4l-781,0l-234.4,659.8l234.4,1087.5z"
+ android:fillColor="#D8DEE8" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+ android:pathData="M1857.6,3096.6a62.1,89 0,1 0,124.1 0a62.1,89 0,1 0,-124.1 0z"
+ android:fillColor="#D8DEE8" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+ android:pathData="M2753.5,2960.1a51.5,77.5 0,1 0,102.9 0a51.5,77.5 0,1 0,-102.9 0z"
+ android:fillColor="#D8DEE8" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
+ android:pathData="M2625.8,2353.1c108.7,-137 324.8,-35.9 433.8,-189.6c24.6,-34.6 41.7,-70 53.6,-103.4c7.2,4.4 12,12.2 12,21.2v658.8c0,12.4 -9.2,22.9 -21.5,24.6l-676.7,93.7c42.7,-46.7 85.6,-106.3 116.7,-180.9C2611.9,2513.9 2554.8,2442.6 2625.8,2353.1z"
+ android:strokeAlpha="0.3"
+ android:fillAlpha="0.3">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+ android:pathData="M1261.2,2793.6l8.4,9.2c-3.6,102.1 -25.8,138.2 161.3,157.4c187.1,19.2 181.4,-137.9 181.4,-137.9l245.4,-107l204.9,-322.6c40.7,-32.8 111.7,-41.7 159.9,-43.8c10,7.1 17.3,17.6 20.1,30.1c20.3,90.9 67.5,353.1 14.8,634.9c-3.9,21 -20.8,37.2 -41.8,40.5l-182.1,29.1c0,0 -1.8,-172.4 -89.3,-183.7c-87.5,-11.3 -169.5,70.7 -175,212.9c0,0 -189.6,25.5 -475.8,-40.1c0,0 -38.3,-8.2 -54.7,-51.5l12.9,-198.3C1252.2,2812.2 1255.6,2802.2 1261.2,2793.6z"
+ android:strokeAlpha="0.6"
+ android:fillAlpha="0.6">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+ android:pathData="M1628.8,2547.2c105.8,-41.6 193.7,7.7 266.4,-50.5c28,-22.4 44.7,-53.4 54.5,-86.2l37.7,2.3c12.3,0.7 19.5,14.3 13,24.9l-140.3,230.4c-6.6,10.9 -19,16.9 -31.7,15.4l-322.4,-39.5C1548.4,2589 1592,2561.7 1628.8,2547.2z"
+ android:strokeAlpha="0.3"
+ android:fillColor="#FFFFFF"
+ android:fillAlpha="0.3" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ android:pathData="M1635.1,2993.6c16.3,-1.6 30.1,11.4 29.8,27.8c-0.8,34.9 2.8,71.4 5.9,96.1c-83.2,0.2 -214.7,-7.6 -377.5,-45c0,0 -38.3,-8.2 -54.7,-51.5l4.9,-75.4C1360.8,3012.2 1558.4,3001.1 1635.1,2993.6z"
+ android:strokeAlpha="0.6"
+ android:fillAlpha="0.6">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/baseline_delete_24.xml b/app/src/main/res/drawable/baseline_delete_24.xml
index 883bcaa..ee1fd2d 100644
--- a/app/src/main/res/drawable/baseline_delete_24.xml
+++ b/app/src/main/res/drawable/baseline_delete_24.xml
@@ -1,5 +1,12 @@
-
-
-
-
+
+
+
+
diff --git a/app/src/main/res/drawable/baseline_directions_car_24.xml b/app/src/main/res/drawable/baseline_directions_car_24.xml
new file mode 100644
index 0000000..35d0a49
--- /dev/null
+++ b/app/src/main/res/drawable/baseline_directions_car_24.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/app/src/main/res/drawable/baseline_edit_24.xml b/app/src/main/res/drawable/baseline_edit_24.xml
index 3c53db7..8cf71ea 100644
--- a/app/src/main/res/drawable/baseline_edit_24.xml
+++ b/app/src/main/res/drawable/baseline_edit_24.xml
@@ -1,5 +1,12 @@
-
-
-
-
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_create_order.xml b/app/src/main/res/drawable/ic_create_order.xml
index 3c53db7..8cf71ea 100644
--- a/app/src/main/res/drawable/ic_create_order.xml
+++ b/app/src/main/res/drawable/ic_create_order.xml
@@ -1,5 +1,12 @@
-
-
-
-
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_dashboard.xml b/app/src/main/res/drawable/ic_dashboard.xml
index 20cb4d6..5861b75 100644
--- a/app/src/main/res/drawable/ic_dashboard.xml
+++ b/app/src/main/res/drawable/ic_dashboard.xml
@@ -1,5 +1,12 @@
-
-
-
-
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_profile.xml b/app/src/main/res/drawable/ic_profile.xml
index f4cc418..4c9dede 100644
--- a/app/src/main/res/drawable/ic_profile.xml
+++ b/app/src/main/res/drawable/ic_profile.xml
@@ -1,5 +1,12 @@
-
-
-
-
+
+
+
+
diff --git a/app/src/main/res/layout/activity_customer.xml b/app/src/main/res/layout/activity_customer.xml
index 0ed2467..0958611 100644
--- a/app/src/main/res/layout/activity_customer.xml
+++ b/app/src/main/res/layout/activity_customer.xml
@@ -1,11 +1,11 @@
-
+ app:layout_constraintTop_toBottomOf="@id/topAppBar"
+ app:navGraph="@navigation/customer_nav_graph" />
+ app:menu="@menu/customer_bottom_nav_menu" />
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_driver.xml b/app/src/main/res/layout/activity_driver.xml
index 5ddf99c..70c0010 100644
--- a/app/src/main/res/layout/activity_driver.xml
+++ b/app/src/main/res/layout/activity_driver.xml
@@ -1,10 +1,26 @@
-
+ android:fitsSystemWindows="true">
-
\ No newline at end of file
+
+
+
+
+
diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml
index b7e0ab4..e36a74e 100644
--- a/app/src/main/res/layout/activity_login.xml
+++ b/app/src/main/res/layout/activity_login.xml
@@ -5,6 +5,7 @@
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ android:fitsSystemWindows="true"
tools:context=".ui.activities.LoginActivity">
\ No newline at end of file
diff --git a/app/src/main/res/layout/dialog_add_article.xml b/app/src/main/res/layout/dialog_add_article.xml
index 92a36ad..fb510dc 100644
--- a/app/src/main/res/layout/dialog_add_article.xml
+++ b/app/src/main/res/layout/dialog_add_article.xml
@@ -1,6 +1,5 @@
-
-
+ android:padding="16dp"
+ android:fitsSystemWindows="true">
-
+ android:layout_height="match_parent"
+ android:fitsSystemWindows="true">
-
-
-
+ android:orientation="vertical">
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/fragment_driver_dashboard.xml b/app/src/main/res/layout/fragment_driver_dashboard.xml
new file mode 100644
index 0000000..ce01b7e
--- /dev/null
+++ b/app/src/main/res/layout/fragment_driver_dashboard.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_driver_profile.xml b/app/src/main/res/layout/fragment_driver_profile.xml
new file mode 100644
index 0000000..9287109
--- /dev/null
+++ b/app/src/main/res/layout/fragment_driver_profile.xml
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/fragment_order_detail.xml b/app/src/main/res/layout/fragment_order_detail.xml
index 1f462bd..a48bec5 100644
--- a/app/src/main/res/layout/fragment_order_detail.xml
+++ b/app/src/main/res/layout/fragment_order_detail.xml
@@ -1,11 +1,10 @@
-
+ android:padding="16dp"
+ android:fitsSystemWindows="true">
+ android:text="@string/order_date" />
+ android:text="@string/order_sum" />
+ android:text="@string/payment_date" />
+ android:text="@string/comment" />
+ android:text="@string/order_status" />
+ android:layout_margin="4dp" />
diff --git a/app/src/main/res/layout/fragment_order_review.xml b/app/src/main/res/layout/fragment_order_review.xml
index 9b8e2f4..3a5c5d5 100644
--- a/app/src/main/res/layout/fragment_order_review.xml
+++ b/app/src/main/res/layout/fragment_order_review.xml
@@ -1,17 +1,17 @@
-
+ android:padding="16dp"
+ android:fitsSystemWindows="true">
+ android:layout_weight="1" />
+
+ android:text="@string/pro_forma" />
+
+ android:text="@string/cash" />
+ android:layout_margin="4dp" />
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_past_deliveries.xml b/app/src/main/res/layout/fragment_past_deliveries.xml
new file mode 100644
index 0000000..858d861
--- /dev/null
+++ b/app/src/main/res/layout/fragment_past_deliveries.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/fragment_past_delivery_detail.xml b/app/src/main/res/layout/fragment_past_delivery_detail.xml
new file mode 100644
index 0000000..7fbff6f
--- /dev/null
+++ b/app/src/main/res/layout/fragment_past_delivery_detail.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_pro_forma_detail.xml b/app/src/main/res/layout/fragment_pro_forma_detail.xml
index eb53bfd..e1b031e 100644
--- a/app/src/main/res/layout/fragment_pro_forma_detail.xml
+++ b/app/src/main/res/layout/fragment_pro_forma_detail.xml
@@ -1,10 +1,10 @@
-
+ android:padding="16dp"
+ android:fitsSystemWindows="true">
+ app:layout_constraintStart_toStartOf="parent" />
diff --git a/app/src/main/res/layout/fragment_profile.xml b/app/src/main/res/layout/fragment_profile.xml
index c72454d..52a3faf 100644
--- a/app/src/main/res/layout/fragment_profile.xml
+++ b/app/src/main/res/layout/fragment_profile.xml
@@ -3,7 +3,8 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
- tools:context=".ui.fragments.customer.ProfileFragment">
+ android:fitsSystemWindows="true"
+ tools:context=".ui.fragments.customer.CustomerProfileFragment">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/item_article.xml b/app/src/main/res/layout/item_article.xml
index c21eb0c..513a888 100644
--- a/app/src/main/res/layout/item_article.xml
+++ b/app/src/main/res/layout/item_article.xml
@@ -1,6 +1,5 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/item_order.xml b/app/src/main/res/layout/item_order.xml
index 1710f03..0ee3257 100644
--- a/app/src/main/res/layout/item_order.xml
+++ b/app/src/main/res/layout/item_order.xml
@@ -1,6 +1,5 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/menu/bottom_nav_menu.xml b/app/src/main/res/menu/customer_bottom_nav_menu.xml
similarity index 100%
rename from app/src/main/res/menu/bottom_nav_menu.xml
rename to app/src/main/res/menu/customer_bottom_nav_menu.xml
diff --git a/app/src/main/res/menu/driver_bottom_nav_menu.xml b/app/src/main/res/menu/driver_bottom_nav_menu.xml
new file mode 100644
index 0000000..8f5909f
--- /dev/null
+++ b/app/src/main/res/menu/driver_bottom_nav_menu.xml
@@ -0,0 +1,15 @@
+
+
\ No newline at end of file
diff --git a/app/src/main/res/navigation/nav_graph.xml b/app/src/main/res/navigation/customer_nav_graph.xml
similarity index 80%
rename from app/src/main/res/navigation/nav_graph.xml
rename to app/src/main/res/navigation/customer_nav_graph.xml
index 3e2d794..257650b 100644
--- a/app/src/main/res/navigation/nav_graph.xml
+++ b/app/src/main/res/navigation/customer_nav_graph.xml
@@ -4,6 +4,18 @@
android:id="@+id/nav_graph"
app:startDestination="@id/customerDashboardFragment">
+
+
+
+
+
+ android:name="mk.ukim.finki.my_distributor.ui.fragments.customer.CustomerProfileFragment"
+ android:label="Profile" />
+ app:destination="@+id/orderDetailFragment" />
+ app:destination="@+id/deliveryDetailFragment" />
+ app:destination="@+id/proFormaDetailFragment" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/values-night/themes.xml b/app/src/main/res/values-night/themes.xml
index 9263434..50f6f7f 100644
--- a/app/src/main/res/values-night/themes.xml
+++ b/app/src/main/res/values-night/themes.xml
@@ -1,4 +1,4 @@
-
+
-->
+
+
+