diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index e59bf23..d07ff18 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -1,6 +1,7 @@
plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.compose)
+ id("com.google.gms.google-services")
}
android {
@@ -46,6 +47,15 @@ dependencies {
implementation(libs.androidx.compose.ui.graphics)
implementation(libs.androidx.compose.ui.tooling.preview)
implementation(libs.androidx.compose.material3)
+ implementation(libs.retrofit)
+ implementation(libs.retrofit.converter.gson)
+ implementation(libs.okhttp)
+ implementation(libs.okhttp.logging)
+ implementation(platform(libs.firebase.bom))
+ implementation(libs.firebase.auth.ktx)
+ implementation(libs.kotlinx.coroutines.play.services)
+ implementation(platform("com.google.firebase:firebase-bom:34.8.0"))
+ implementation(libs.google.firebase.auth.ktx)
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)
@@ -53,4 +63,4 @@ dependencies {
androidTestImplementation(libs.androidx.compose.ui.test.junit4)
debugImplementation(libs.androidx.compose.ui.tooling)
debugImplementation(libs.androidx.compose.ui.test.manifest)
-}
\ No newline at end of file
+}
diff --git a/app/google-services.json b/app/google-services.json
new file mode 100644
index 0000000..13855f9
--- /dev/null
+++ b/app/google-services.json
@@ -0,0 +1,39 @@
+{
+ "project_info": {
+ "project_number": "193837005934",
+ "project_id": "hoteltrisolaris-b1c34",
+ "storage_bucket": "hoteltrisolaris-b1c34.firebasestorage.app"
+ },
+ "client": [
+ {
+ "client_info": {
+ "mobilesdk_app_id": "1:193837005934:android:4eae5c8b77ff988228ba7f",
+ "android_client_info": {
+ "package_name": "com.android.trisolarispms"
+ }
+ },
+ "oauth_client": [
+ {
+ "client_id": "193837005934-vbjdpp55t9s2r8c0l62kt16sic4ipaon.apps.googleusercontent.com",
+ "client_type": 3
+ }
+ ],
+ "api_key": [
+ {
+ "current_key": "AIzaSyC1f0SmJDHk_V9X1SNn_jlXpMc7wjuLfsY"
+ }
+ ],
+ "services": {
+ "appinvite_service": {
+ "other_platform_oauth_client": [
+ {
+ "client_id": "193837005934-vbjdpp55t9s2r8c0l62kt16sic4ipaon.apps.googleusercontent.com",
+ "client_type": 3
+ }
+ ]
+ }
+ }
+ }
+ ],
+ "configuration_version": "1"
+}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index f609afd..941efb4 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -2,6 +2,8 @@
+
+
-
\ No newline at end of file
+
diff --git a/app/src/main/java/com/android/trisolarispms/data/api/ApiClient.kt b/app/src/main/java/com/android/trisolarispms/data/api/ApiClient.kt
new file mode 100644
index 0000000..4dc0978
--- /dev/null
+++ b/app/src/main/java/com/android/trisolarispms/data/api/ApiClient.kt
@@ -0,0 +1,54 @@
+package com.android.trisolarispms.data.api
+
+import com.google.firebase.auth.FirebaseAuth
+import okhttp3.Interceptor
+import okhttp3.OkHttpClient
+import okhttp3.logging.HttpLoggingInterceptor
+import retrofit2.Retrofit
+import retrofit2.converter.gson.GsonConverterFactory
+import java.util.concurrent.TimeUnit
+
+object ApiClient {
+ fun create(
+ auth: FirebaseAuth = FirebaseAuth.getInstance(),
+ baseUrl: String = ApiConstants.BASE_URL,
+ enableLogging: Boolean = true
+ ): ApiService {
+ val tokenProvider = FirebaseAuthTokenProvider(auth)
+ val authInterceptor = Interceptor { chain ->
+ val original = chain.request()
+ val token = try {
+ kotlinx.coroutines.runBlocking { tokenProvider.token() }
+ } catch (e: Exception) {
+ null
+ }
+ val request = if (token.isNullOrBlank()) {
+ original
+ } else {
+ original.newBuilder()
+ .addHeader("Authorization", "Bearer $token")
+ .build()
+ }
+ chain.proceed(request)
+ }
+
+ val logging = HttpLoggingInterceptor().apply {
+ level = if (enableLogging) HttpLoggingInterceptor.Level.BODY else HttpLoggingInterceptor.Level.NONE
+ }
+
+ val client = OkHttpClient.Builder()
+ .addInterceptor(authInterceptor)
+ .addInterceptor(logging)
+ .connectTimeout(30, TimeUnit.SECONDS)
+ .readTimeout(30, TimeUnit.SECONDS)
+ .writeTimeout(30, TimeUnit.SECONDS)
+ .build()
+
+ return Retrofit.Builder()
+ .baseUrl(baseUrl)
+ .client(client)
+ .addConverterFactory(GsonConverterFactory.create())
+ .build()
+ .create(ApiService::class.java)
+ }
+}
diff --git a/app/src/main/java/com/android/trisolarispms/data/api/ApiConstants.kt b/app/src/main/java/com/android/trisolarispms/data/api/ApiConstants.kt
new file mode 100644
index 0000000..a60b3ce
--- /dev/null
+++ b/app/src/main/java/com/android/trisolarispms/data/api/ApiConstants.kt
@@ -0,0 +1,5 @@
+package com.android.trisolarispms.data.api
+
+object ApiConstants {
+ const val BASE_URL = "https://api.hoteltrisolaris.in/"
+}
diff --git a/app/src/main/java/com/android/trisolarispms/data/api/ApiService.kt b/app/src/main/java/com/android/trisolarispms/data/api/ApiService.kt
new file mode 100644
index 0000000..39a0277
--- /dev/null
+++ b/app/src/main/java/com/android/trisolarispms/data/api/ApiService.kt
@@ -0,0 +1,16 @@
+package com.android.trisolarispms.data.api
+
+interface ApiService :
+ AuthApi,
+ OrgApi,
+ PropertyApi,
+ RoomTypeApi,
+ RoomApi,
+ RoomImageApi,
+ BookingApi,
+ RoomStayApi,
+ CardApi,
+ GuestApi,
+ GuestDocumentApi,
+ TransportApi,
+ InboundEmailApi
diff --git a/app/src/main/java/com/android/trisolarispms/data/api/AuthApi.kt b/app/src/main/java/com/android/trisolarispms/data/api/AuthApi.kt
new file mode 100644
index 0000000..0ecaf28
--- /dev/null
+++ b/app/src/main/java/com/android/trisolarispms/data/api/AuthApi.kt
@@ -0,0 +1,15 @@
+package com.android.trisolarispms.data.api
+
+import com.android.trisolarispms.data.api.model.AuthVerifyResponse
+import com.android.trisolarispms.data.api.model.UserDto
+import retrofit2.Response
+import retrofit2.http.GET
+import retrofit2.http.POST
+
+interface AuthApi {
+ @POST("auth/verify")
+ suspend fun verifyAuth(): Response
+
+ @GET("auth/me")
+ suspend fun me(): Response
+}
diff --git a/app/src/main/java/com/android/trisolarispms/data/api/AuthTokenProvider.kt b/app/src/main/java/com/android/trisolarispms/data/api/AuthTokenProvider.kt
new file mode 100644
index 0000000..cc311f8
--- /dev/null
+++ b/app/src/main/java/com/android/trisolarispms/data/api/AuthTokenProvider.kt
@@ -0,0 +1,5 @@
+package com.android.trisolarispms.data.api
+
+interface AuthTokenProvider {
+ suspend fun token(): String?
+}
diff --git a/app/src/main/java/com/android/trisolarispms/data/api/BookingApi.kt b/app/src/main/java/com/android/trisolarispms/data/api/BookingApi.kt
new file mode 100644
index 0000000..5725762
--- /dev/null
+++ b/app/src/main/java/com/android/trisolarispms/data/api/BookingApi.kt
@@ -0,0 +1,50 @@
+package com.android.trisolarispms.data.api
+
+import com.android.trisolarispms.data.api.model.ActionResponse
+import com.android.trisolarispms.data.api.model.BookingCancelRequest
+import com.android.trisolarispms.data.api.model.BookingCheckInRequest
+import com.android.trisolarispms.data.api.model.BookingCheckOutRequest
+import com.android.trisolarispms.data.api.model.BookingNoShowRequest
+import com.android.trisolarispms.data.api.model.BookingRoomStayCreateRequest
+import com.android.trisolarispms.data.api.model.RoomStayDto
+import retrofit2.Response
+import retrofit2.http.Body
+import retrofit2.http.POST
+import retrofit2.http.Path
+
+interface BookingApi {
+ @POST("properties/{propertyId}/bookings/{bookingId}/check-in")
+ suspend fun checkIn(
+ @Path("propertyId") propertyId: String,
+ @Path("bookingId") bookingId: String,
+ @Body body: BookingCheckInRequest
+ ): Response
+
+ @POST("properties/{propertyId}/bookings/{bookingId}/check-out")
+ suspend fun checkOut(
+ @Path("propertyId") propertyId: String,
+ @Path("bookingId") bookingId: String,
+ @Body body: BookingCheckOutRequest
+ ): Response
+
+ @POST("properties/{propertyId}/bookings/{bookingId}/cancel")
+ suspend fun cancelBooking(
+ @Path("propertyId") propertyId: String,
+ @Path("bookingId") bookingId: String,
+ @Body body: BookingCancelRequest
+ ): Response
+
+ @POST("properties/{propertyId}/bookings/{bookingId}/no-show")
+ suspend fun noShow(
+ @Path("propertyId") propertyId: String,
+ @Path("bookingId") bookingId: String,
+ @Body body: BookingNoShowRequest
+ ): Response
+
+ @POST("properties/{propertyId}/bookings/{bookingId}/room-stays")
+ suspend fun preAssignRoomStay(
+ @Path("propertyId") propertyId: String,
+ @Path("bookingId") bookingId: String,
+ @Body body: BookingRoomStayCreateRequest
+ ): Response
+}
diff --git a/app/src/main/java/com/android/trisolarispms/data/api/CardApi.kt b/app/src/main/java/com/android/trisolarispms/data/api/CardApi.kt
new file mode 100644
index 0000000..18a1f57
--- /dev/null
+++ b/app/src/main/java/com/android/trisolarispms/data/api/CardApi.kt
@@ -0,0 +1,39 @@
+package com.android.trisolarispms.data.api
+
+import com.android.trisolarispms.data.api.model.ActionResponse
+import com.android.trisolarispms.data.api.model.CardDto
+import com.android.trisolarispms.data.api.model.CardIssueRequest
+import com.android.trisolarispms.data.api.model.CardPrepareRequest
+import retrofit2.Response
+import retrofit2.http.Body
+import retrofit2.http.GET
+import retrofit2.http.POST
+import retrofit2.http.Path
+
+interface CardApi {
+ @POST("properties/{propertyId}/room-stays/{roomStayId}/cards/prepare")
+ suspend fun prepareCard(
+ @Path("propertyId") propertyId: String,
+ @Path("roomStayId") roomStayId: String,
+ @Body body: CardPrepareRequest
+ ): Response
+
+ @POST("properties/{propertyId}/room-stays/{roomStayId}/cards")
+ suspend fun issueCard(
+ @Path("propertyId") propertyId: String,
+ @Path("roomStayId") roomStayId: String,
+ @Body body: CardIssueRequest
+ ): Response
+
+ @GET("properties/{propertyId}/room-stays/{roomStayId}/cards")
+ suspend fun listCards(
+ @Path("propertyId") propertyId: String,
+ @Path("roomStayId") roomStayId: String
+ ): Response>
+
+ @POST("properties/{propertyId}/room-stays/cards/{cardId}/revoke")
+ suspend fun revokeCard(
+ @Path("propertyId") propertyId: String,
+ @Path("cardId") cardId: String
+ ): Response
+}
diff --git a/app/src/main/java/com/android/trisolarispms/data/api/FirebaseAuthTokenProvider.kt b/app/src/main/java/com/android/trisolarispms/data/api/FirebaseAuthTokenProvider.kt
new file mode 100644
index 0000000..2664895
--- /dev/null
+++ b/app/src/main/java/com/android/trisolarispms/data/api/FirebaseAuthTokenProvider.kt
@@ -0,0 +1,13 @@
+package com.android.trisolarispms.data.api
+
+import com.google.firebase.auth.FirebaseAuth
+import kotlinx.coroutines.tasks.await
+
+class FirebaseAuthTokenProvider(
+ private val auth: FirebaseAuth
+) : AuthTokenProvider {
+ override suspend fun token(): String? {
+ val user = auth.currentUser ?: return null
+ return user.getIdToken(false).await().token
+ }
+}
diff --git a/app/src/main/java/com/android/trisolarispms/data/api/GuestApi.kt b/app/src/main/java/com/android/trisolarispms/data/api/GuestApi.kt
new file mode 100644
index 0000000..6eb55d4
--- /dev/null
+++ b/app/src/main/java/com/android/trisolarispms/data/api/GuestApi.kt
@@ -0,0 +1,42 @@
+package com.android.trisolarispms.data.api
+
+import com.android.trisolarispms.data.api.model.GuestDto
+import com.android.trisolarispms.data.api.model.GuestRatingDto
+import com.android.trisolarispms.data.api.model.GuestRatingRequest
+import com.android.trisolarispms.data.api.model.GuestVehicleDto
+import com.android.trisolarispms.data.api.model.GuestVehicleRequest
+import retrofit2.Response
+import retrofit2.http.Body
+import retrofit2.http.GET
+import retrofit2.http.POST
+import retrofit2.http.Path
+import retrofit2.http.Query
+
+interface GuestApi {
+ @GET("properties/{propertyId}/guests/search")
+ suspend fun searchGuests(
+ @Path("propertyId") propertyId: String,
+ @Query("phone") phone: String? = null,
+ @Query("vehicleNumber") vehicleNumber: String? = null
+ ): Response>
+
+ @POST("properties/{propertyId}/guests/{guestId}/vehicles")
+ suspend fun addGuestVehicle(
+ @Path("propertyId") propertyId: String,
+ @Path("guestId") guestId: String,
+ @Body body: GuestVehicleRequest
+ ): Response
+
+ @POST("properties/{propertyId}/guests/{guestId}/ratings")
+ suspend fun addGuestRating(
+ @Path("propertyId") propertyId: String,
+ @Path("guestId") guestId: String,
+ @Body body: GuestRatingRequest
+ ): Response
+
+ @GET("properties/{propertyId}/guests/{guestId}/ratings")
+ suspend fun listGuestRatings(
+ @Path("propertyId") propertyId: String,
+ @Path("guestId") guestId: String
+ ): Response>
+}
diff --git a/app/src/main/java/com/android/trisolarispms/data/api/GuestDocumentApi.kt b/app/src/main/java/com/android/trisolarispms/data/api/GuestDocumentApi.kt
new file mode 100644
index 0000000..dc57034
--- /dev/null
+++ b/app/src/main/java/com/android/trisolarispms/data/api/GuestDocumentApi.kt
@@ -0,0 +1,39 @@
+package com.android.trisolarispms.data.api
+
+import com.android.trisolarispms.data.api.model.GuestDocumentDto
+import okhttp3.MultipartBody
+import okhttp3.RequestBody
+import okhttp3.ResponseBody
+import retrofit2.Response
+import retrofit2.http.GET
+import retrofit2.http.Multipart
+import retrofit2.http.POST
+import retrofit2.http.Part
+import retrofit2.http.Path
+import retrofit2.http.Streaming
+
+interface GuestDocumentApi {
+ @Multipart
+ @POST("properties/{propertyId}/guests/{guestId}/documents")
+ suspend fun uploadGuestDocument(
+ @Path("propertyId") propertyId: String,
+ @Path("guestId") guestId: String,
+ @Part file: MultipartBody.Part,
+ @Part("docType") docType: RequestBody,
+ @Part("bookingId") bookingId: RequestBody
+ ): Response
+
+ @GET("properties/{propertyId}/guests/{guestId}/documents")
+ suspend fun listGuestDocuments(
+ @Path("propertyId") propertyId: String,
+ @Path("guestId") guestId: String
+ ): Response>
+
+ @Streaming
+ @GET("properties/{propertyId}/guests/{guestId}/documents/{documentId}/file")
+ suspend fun getGuestDocumentFile(
+ @Path("propertyId") propertyId: String,
+ @Path("guestId") guestId: String,
+ @Path("documentId") documentId: String
+ ): Response
+}
diff --git a/app/src/main/java/com/android/trisolarispms/data/api/InboundEmailApi.kt b/app/src/main/java/com/android/trisolarispms/data/api/InboundEmailApi.kt
new file mode 100644
index 0000000..bb08af3
--- /dev/null
+++ b/app/src/main/java/com/android/trisolarispms/data/api/InboundEmailApi.kt
@@ -0,0 +1,30 @@
+package com.android.trisolarispms.data.api
+
+import com.android.trisolarispms.data.api.model.ActionResponse
+import okhttp3.MultipartBody
+import okhttp3.RequestBody
+import okhttp3.ResponseBody
+import retrofit2.Response
+import retrofit2.http.GET
+import retrofit2.http.Multipart
+import retrofit2.http.POST
+import retrofit2.http.Part
+import retrofit2.http.Path
+import retrofit2.http.Streaming
+
+interface InboundEmailApi {
+ @Streaming
+ @GET("properties/{propertyId}/inbound-emails/{emailId}/file")
+ suspend fun getInboundEmailFile(
+ @Path("propertyId") propertyId: String,
+ @Path("emailId") emailId: String
+ ): Response
+
+ @Multipart
+ @POST("properties/{propertyId}/inbound-emails/manual")
+ suspend fun uploadInboundEmail(
+ @Path("propertyId") propertyId: String,
+ @Part file: MultipartBody.Part,
+ @Part("sourceBookingId") sourceBookingId: RequestBody?
+ ): Response
+}
diff --git a/app/src/main/java/com/android/trisolarispms/data/api/OrgApi.kt b/app/src/main/java/com/android/trisolarispms/data/api/OrgApi.kt
new file mode 100644
index 0000000..ddcc903
--- /dev/null
+++ b/app/src/main/java/com/android/trisolarispms/data/api/OrgApi.kt
@@ -0,0 +1,17 @@
+package com.android.trisolarispms.data.api
+
+import com.android.trisolarispms.data.api.model.OrgCreateRequest
+import com.android.trisolarispms.data.api.model.OrgDto
+import retrofit2.Response
+import retrofit2.http.Body
+import retrofit2.http.GET
+import retrofit2.http.POST
+import retrofit2.http.Path
+
+interface OrgApi {
+ @POST("orgs")
+ suspend fun createOrg(@Body body: OrgCreateRequest): Response
+
+ @GET("orgs/{orgId}")
+ suspend fun getOrg(@Path("orgId") orgId: String): Response
+}
diff --git a/app/src/main/java/com/android/trisolarispms/data/api/PropertyApi.kt b/app/src/main/java/com/android/trisolarispms/data/api/PropertyApi.kt
new file mode 100644
index 0000000..bb212be
--- /dev/null
+++ b/app/src/main/java/com/android/trisolarispms/data/api/PropertyApi.kt
@@ -0,0 +1,51 @@
+package com.android.trisolarispms.data.api
+
+import com.android.trisolarispms.data.api.model.PropertyCreateRequest
+import com.android.trisolarispms.data.api.model.PropertyDto
+import com.android.trisolarispms.data.api.model.PropertyUpdateRequest
+import com.android.trisolarispms.data.api.model.UserDto
+import com.android.trisolarispms.data.api.model.UserRolesUpdateRequest
+import com.android.trisolarispms.data.api.model.ActionResponse
+import retrofit2.Response
+import retrofit2.http.Body
+import retrofit2.http.DELETE
+import retrofit2.http.GET
+import retrofit2.http.POST
+import retrofit2.http.PUT
+import retrofit2.http.Path
+
+interface PropertyApi {
+ @POST("orgs/{orgId}/properties")
+ suspend fun createProperty(
+ @Path("orgId") orgId: String,
+ @Body body: PropertyCreateRequest
+ ): Response
+
+ @GET("orgs/{orgId}/properties")
+ suspend fun listProperties(@Path("orgId") orgId: String): Response>
+
+ @PUT("properties/{propertyId}")
+ suspend fun updateProperty(
+ @Path("propertyId") propertyId: String,
+ @Body body: PropertyUpdateRequest
+ ): Response
+
+ @GET("orgs/{orgId}/users")
+ suspend fun listOrgUsers(@Path("orgId") orgId: String): Response>
+
+ @GET("properties/{propertyId}/users")
+ suspend fun listPropertyUsers(@Path("propertyId") propertyId: String): Response>
+
+ @PUT("properties/{propertyId}/users/{userId}/roles")
+ suspend fun updateUserRoles(
+ @Path("propertyId") propertyId: String,
+ @Path("userId") userId: String,
+ @Body body: UserRolesUpdateRequest
+ ): Response
+
+ @DELETE("properties/{propertyId}/users/{userId}")
+ suspend fun deletePropertyUser(
+ @Path("propertyId") propertyId: String,
+ @Path("userId") userId: String
+ ): Response
+}
diff --git a/app/src/main/java/com/android/trisolarispms/data/api/RoomApi.kt b/app/src/main/java/com/android/trisolarispms/data/api/RoomApi.kt
new file mode 100644
index 0000000..b21fcde
--- /dev/null
+++ b/app/src/main/java/com/android/trisolarispms/data/api/RoomApi.kt
@@ -0,0 +1,51 @@
+package com.android.trisolarispms.data.api
+
+import com.android.trisolarispms.data.api.model.AvailabilityResponse
+import com.android.trisolarispms.data.api.model.RoomBoardDto
+import com.android.trisolarispms.data.api.model.RoomCreateRequest
+import com.android.trisolarispms.data.api.model.RoomDto
+import com.android.trisolarispms.data.api.model.RoomUpdateRequest
+import okhttp3.ResponseBody
+import retrofit2.Response
+import retrofit2.http.Body
+import retrofit2.http.GET
+import retrofit2.http.POST
+import retrofit2.http.PUT
+import retrofit2.http.Path
+import retrofit2.http.Query
+import retrofit2.http.Streaming
+
+interface RoomApi {
+ @GET("properties/{propertyId}/rooms")
+ suspend fun listRooms(@Path("propertyId") propertyId: String): Response>
+
+ @POST("properties/{propertyId}/rooms")
+ suspend fun createRoom(
+ @Path("propertyId") propertyId: String,
+ @Body body: RoomCreateRequest
+ ): Response
+
+ @PUT("properties/{propertyId}/rooms/{roomId}")
+ suspend fun updateRoom(
+ @Path("propertyId") propertyId: String,
+ @Path("roomId") roomId: String,
+ @Body body: RoomUpdateRequest
+ ): Response
+
+ @GET("properties/{propertyId}/rooms/board")
+ suspend fun getRoomBoard(@Path("propertyId") propertyId: String): Response
+
+ @Streaming
+ @GET("properties/{propertyId}/rooms/board/stream")
+ suspend fun streamRoomBoard(@Path("propertyId") propertyId: String): Response
+
+ @GET("properties/{propertyId}/rooms/availability")
+ suspend fun getRoomAvailability(@Path("propertyId") propertyId: String): Response
+
+ @GET("properties/{propertyId}/rooms/availability-range")
+ suspend fun getRoomAvailabilityRange(
+ @Path("propertyId") propertyId: String,
+ @Query("from") from: String,
+ @Query("to") to: String
+ ): Response
+}
diff --git a/app/src/main/java/com/android/trisolarispms/data/api/RoomImageApi.kt b/app/src/main/java/com/android/trisolarispms/data/api/RoomImageApi.kt
new file mode 100644
index 0000000..3361f7f
--- /dev/null
+++ b/app/src/main/java/com/android/trisolarispms/data/api/RoomImageApi.kt
@@ -0,0 +1,38 @@
+package com.android.trisolarispms.data.api
+
+import com.android.trisolarispms.data.api.model.ImageDto
+import okhttp3.MultipartBody
+import okhttp3.ResponseBody
+import retrofit2.Response
+import retrofit2.http.GET
+import retrofit2.http.Multipart
+import retrofit2.http.POST
+import retrofit2.http.Part
+import retrofit2.http.Path
+import retrofit2.http.Query
+import retrofit2.http.Streaming
+
+interface RoomImageApi {
+ @GET("properties/{propertyId}/rooms/{roomId}/images")
+ suspend fun listRoomImages(
+ @Path("propertyId") propertyId: String,
+ @Path("roomId") roomId: String
+ ): Response>
+
+ @Multipart
+ @POST("properties/{propertyId}/rooms/{roomId}/images")
+ suspend fun uploadRoomImage(
+ @Path("propertyId") propertyId: String,
+ @Path("roomId") roomId: String,
+ @Part file: MultipartBody.Part
+ ): Response
+
+ @Streaming
+ @GET("properties/{propertyId}/rooms/{roomId}/images/{imageId}/file")
+ suspend fun getRoomImageFile(
+ @Path("propertyId") propertyId: String,
+ @Path("roomId") roomId: String,
+ @Path("imageId") imageId: String,
+ @Query("size") size: String? = null
+ ): Response
+}
diff --git a/app/src/main/java/com/android/trisolarispms/data/api/RoomStayApi.kt b/app/src/main/java/com/android/trisolarispms/data/api/RoomStayApi.kt
new file mode 100644
index 0000000..4bcd651
--- /dev/null
+++ b/app/src/main/java/com/android/trisolarispms/data/api/RoomStayApi.kt
@@ -0,0 +1,17 @@
+package com.android.trisolarispms.data.api
+
+import com.android.trisolarispms.data.api.model.RoomChangeRequest
+import com.android.trisolarispms.data.api.model.RoomStayDto
+import retrofit2.Response
+import retrofit2.http.Body
+import retrofit2.http.POST
+import retrofit2.http.Path
+
+interface RoomStayApi {
+ @POST("properties/{propertyId}/room-stays/{roomStayId}/change-room")
+ suspend fun changeRoom(
+ @Path("propertyId") propertyId: String,
+ @Path("roomStayId") roomStayId: String,
+ @Body body: RoomChangeRequest
+ ): Response
+}
diff --git a/app/src/main/java/com/android/trisolarispms/data/api/RoomTypeApi.kt b/app/src/main/java/com/android/trisolarispms/data/api/RoomTypeApi.kt
new file mode 100644
index 0000000..09c93bb
--- /dev/null
+++ b/app/src/main/java/com/android/trisolarispms/data/api/RoomTypeApi.kt
@@ -0,0 +1,37 @@
+package com.android.trisolarispms.data.api
+
+import com.android.trisolarispms.data.api.model.ActionResponse
+import com.android.trisolarispms.data.api.model.RoomTypeCreateRequest
+import com.android.trisolarispms.data.api.model.RoomTypeDto
+import com.android.trisolarispms.data.api.model.RoomTypeUpdateRequest
+import retrofit2.Response
+import retrofit2.http.Body
+import retrofit2.http.DELETE
+import retrofit2.http.GET
+import retrofit2.http.POST
+import retrofit2.http.PUT
+import retrofit2.http.Path
+
+interface RoomTypeApi {
+ @POST("properties/{propertyId}/room-types")
+ suspend fun createRoomType(
+ @Path("propertyId") propertyId: String,
+ @Body body: RoomTypeCreateRequest
+ ): Response
+
+ @GET("properties/{propertyId}/room-types")
+ suspend fun listRoomTypes(@Path("propertyId") propertyId: String): Response>
+
+ @PUT("properties/{propertyId}/room-types/{roomTypeId}")
+ suspend fun updateRoomType(
+ @Path("propertyId") propertyId: String,
+ @Path("roomTypeId") roomTypeId: String,
+ @Body body: RoomTypeUpdateRequest
+ ): Response
+
+ @DELETE("properties/{propertyId}/room-types/{roomTypeId}")
+ suspend fun deleteRoomType(
+ @Path("propertyId") propertyId: String,
+ @Path("roomTypeId") roomTypeId: String
+ ): Response
+}
diff --git a/app/src/main/java/com/android/trisolarispms/data/api/TransportApi.kt b/app/src/main/java/com/android/trisolarispms/data/api/TransportApi.kt
new file mode 100644
index 0000000..efa0e93
--- /dev/null
+++ b/app/src/main/java/com/android/trisolarispms/data/api/TransportApi.kt
@@ -0,0 +1,11 @@
+package com.android.trisolarispms.data.api
+
+import com.android.trisolarispms.data.api.model.TransportModeDto
+import retrofit2.Response
+import retrofit2.http.GET
+import retrofit2.http.Path
+
+interface TransportApi {
+ @GET("properties/{propertyId}/transport-modes")
+ suspend fun listTransportModes(@Path("propertyId") propertyId: String): Response>
+}
diff --git a/app/src/main/java/com/android/trisolarispms/data/api/model/AuthModels.kt b/app/src/main/java/com/android/trisolarispms/data/api/model/AuthModels.kt
new file mode 100644
index 0000000..53ee367
--- /dev/null
+++ b/app/src/main/java/com/android/trisolarispms/data/api/model/AuthModels.kt
@@ -0,0 +1,7 @@
+package com.android.trisolarispms.data.api.model
+
+data class AuthVerifyResponse(
+ val user: UserDto? = null,
+ val orgId: String? = null,
+ val propertyId: String? = null
+)
diff --git a/app/src/main/java/com/android/trisolarispms/data/api/model/BookingModels.kt b/app/src/main/java/com/android/trisolarispms/data/api/model/BookingModels.kt
new file mode 100644
index 0000000..5a245d9
--- /dev/null
+++ b/app/src/main/java/com/android/trisolarispms/data/api/model/BookingModels.kt
@@ -0,0 +1,58 @@
+package com.android.trisolarispms.data.api.model
+
+data class BookingCheckInRequest(
+ val roomIds: List,
+ val checkInAt: String? = null,
+ val transportMode: String? = null,
+ val transportVehicleNumber: String? = null,
+ val notes: String? = null,
+ val adultCount: Int? = null,
+ val childCount: Int? = null,
+ val maleCount: Int? = null,
+ val femaleCount: Int? = null,
+ val totalGuestCount: Int? = null
+)
+
+data class BookingCheckOutRequest(
+ val checkOutAt: String? = null,
+ val notes: String? = null
+)
+
+data class BookingCancelRequest(
+ val cancelledAt: String? = null,
+ val reason: String? = null
+)
+
+data class BookingNoShowRequest(
+ val noShowAt: String? = null,
+ val reason: String? = null
+)
+
+data class BookingRoomStayCreateRequest(
+ val roomId: String,
+ val fromAt: String,
+ val toAt: String,
+ val notes: String? = null
+)
+
+// Room Stays
+
+data class RoomStayCreateRequest(
+ val roomId: String,
+ val guestId: String? = null,
+ val checkIn: String? = null,
+ val checkOut: String? = null
+)
+
+data class RoomStayDto(
+ val id: String? = null,
+ val bookingId: String? = null,
+ val roomId: String? = null,
+ val status: String? = null
+)
+
+data class RoomChangeRequest(
+ val newRoomId: String,
+ val movedAt: String? = null,
+ val idempotencyKey: String
+)
diff --git a/app/src/main/java/com/android/trisolarispms/data/api/model/CardModels.kt b/app/src/main/java/com/android/trisolarispms/data/api/model/CardModels.kt
new file mode 100644
index 0000000..fe49eb4
--- /dev/null
+++ b/app/src/main/java/com/android/trisolarispms/data/api/model/CardModels.kt
@@ -0,0 +1,18 @@
+package com.android.trisolarispms.data.api.model
+
+data class CardPrepareRequest(
+ val expiresAt: String? = null
+)
+
+data class CardIssueRequest(
+ val cardId: String,
+ val cardIndex: Int,
+ val issuedAt: String? = null,
+ val expiresAt: String
+)
+
+data class CardDto(
+ val id: String? = null,
+ val cardNumber: String? = null,
+ val status: String? = null
+)
diff --git a/app/src/main/java/com/android/trisolarispms/data/api/model/CommonModels.kt b/app/src/main/java/com/android/trisolarispms/data/api/model/CommonModels.kt
new file mode 100644
index 0000000..0edff31
--- /dev/null
+++ b/app/src/main/java/com/android/trisolarispms/data/api/model/CommonModels.kt
@@ -0,0 +1,6 @@
+package com.android.trisolarispms.data.api.model
+
+data class ActionResponse(
+ val success: Boolean? = null,
+ val message: String? = null
+)
diff --git a/app/src/main/java/com/android/trisolarispms/data/api/model/GuestModels.kt b/app/src/main/java/com/android/trisolarispms/data/api/model/GuestModels.kt
new file mode 100644
index 0000000..e4bf097
--- /dev/null
+++ b/app/src/main/java/com/android/trisolarispms/data/api/model/GuestModels.kt
@@ -0,0 +1,37 @@
+package com.android.trisolarispms.data.api.model
+
+data class GuestDto(
+ val id: String? = null,
+ val name: String? = null,
+ val phone: String? = null,
+ val email: String? = null
+)
+
+data class GuestVehicleRequest(
+ val vehicleNumber: String
+)
+
+data class GuestVehicleDto(
+ val id: String? = null,
+ val vehicleNumber: String? = null
+)
+
+data class GuestRatingRequest(
+ val bookingId: String,
+ val score: String,
+ val notes: String? = null
+)
+
+data class GuestRatingDto(
+ val id: String? = null,
+ val score: String? = null,
+ val notes: String? = null,
+ val createdAt: String? = null
+)
+
+data class GuestDocumentDto(
+ val id: String? = null,
+ val type: String? = null,
+ val fileName: String? = null,
+ val createdAt: String? = null
+)
diff --git a/app/src/main/java/com/android/trisolarispms/data/api/model/OrgModels.kt b/app/src/main/java/com/android/trisolarispms/data/api/model/OrgModels.kt
new file mode 100644
index 0000000..9571826
--- /dev/null
+++ b/app/src/main/java/com/android/trisolarispms/data/api/model/OrgModels.kt
@@ -0,0 +1,14 @@
+package com.android.trisolarispms.data.api.model
+
+data class OrgCreateRequest(
+ val name: String,
+ val emailAliases: List? = null,
+ val allowedTransportModes: List? = null
+)
+
+data class OrgDto(
+ val id: String? = null,
+ val name: String? = null,
+ val emailAliases: List? = null,
+ val allowedTransportModes: List? = null
+)
diff --git a/app/src/main/java/com/android/trisolarispms/data/api/model/PropertyModels.kt b/app/src/main/java/com/android/trisolarispms/data/api/model/PropertyModels.kt
new file mode 100644
index 0000000..7f6b5a0
--- /dev/null
+++ b/app/src/main/java/com/android/trisolarispms/data/api/model/PropertyModels.kt
@@ -0,0 +1,38 @@
+package com.android.trisolarispms.data.api.model
+
+data class PropertyCreateRequest(
+ val code: String,
+ val name: String,
+ val addressText: String? = null,
+ val timezone: String? = null,
+ val currency: String? = null,
+ val emailAddresses: List? = null,
+ val otaAliases: List? = null,
+ val allowedTransportModes: List? = null
+)
+
+data class PropertyUpdateRequest(
+ val code: String? = null,
+ val name: String? = null,
+ val addressText: String? = null,
+ val timezone: String? = null,
+ val currency: String? = null,
+ val active: Boolean? = null,
+ val emailAddresses: List? = null,
+ val otaAliases: List? = null,
+ val allowedTransportModes: List? = null
+)
+
+data class PropertyDto(
+ val id: String? = null,
+ val orgId: String? = null,
+ val code: String? = null,
+ val name: String? = null,
+ val addressText: String? = null,
+ val timezone: String? = null,
+ val currency: String? = null,
+ val active: Boolean? = null,
+ val emailAddresses: List? = null,
+ val otaAliases: List? = null,
+ val allowedTransportModes: List? = null
+)
diff --git a/app/src/main/java/com/android/trisolarispms/data/api/model/RoomModels.kt b/app/src/main/java/com/android/trisolarispms/data/api/model/RoomModels.kt
new file mode 100644
index 0000000..6b64ecf
--- /dev/null
+++ b/app/src/main/java/com/android/trisolarispms/data/api/model/RoomModels.kt
@@ -0,0 +1,62 @@
+package com.android.trisolarispms.data.api.model
+
+data class RoomCreateRequest(
+ val roomNumber: String,
+ val floor: String? = null,
+ val roomTypeId: String,
+ val hasNfc: Boolean? = null,
+ val active: Boolean? = null,
+ val maintenance: Boolean? = null,
+ val notes: String? = null
+)
+
+data class RoomUpdateRequest(
+ val roomNumber: String,
+ val floor: String? = null,
+ val roomTypeId: String,
+ val hasNfc: Boolean? = null,
+ val active: Boolean? = null,
+ val maintenance: Boolean? = null,
+ val notes: String? = null
+)
+
+data class RoomDto(
+ val id: String? = null,
+ val roomNumber: String? = null,
+ val roomTypeId: String? = null,
+ val floor: String? = null,
+ val hasNfc: Boolean? = null,
+ val active: Boolean? = null,
+ val maintenance: Boolean? = null,
+ val notes: String? = null
+)
+
+data class RoomBoardDto(
+ val items: List = emptyList()
+)
+
+data class RoomBoardItemDto(
+ val roomId: String? = null,
+ val status: String? = null,
+ val roomStayId: String? = null,
+ val guestName: String? = null
+)
+
+data class AvailabilityResponse(
+ val rooms: List = emptyList()
+)
+
+data class RoomAvailabilityDto(
+ val roomId: String? = null,
+ val date: String? = null,
+ val available: Boolean? = null,
+ val rate: Double? = null
+)
+
+// Images
+
+data class ImageDto(
+ val id: String? = null,
+ val url: String? = null,
+ val fileName: String? = null
+)
diff --git a/app/src/main/java/com/android/trisolarispms/data/api/model/RoomTypeModels.kt b/app/src/main/java/com/android/trisolarispms/data/api/model/RoomTypeModels.kt
new file mode 100644
index 0000000..222ed42
--- /dev/null
+++ b/app/src/main/java/com/android/trisolarispms/data/api/model/RoomTypeModels.kt
@@ -0,0 +1,26 @@
+package com.android.trisolarispms.data.api.model
+
+data class RoomTypeCreateRequest(
+ val code: String,
+ val name: String,
+ val maxAdults: Int? = null,
+ val maxChildren: Int? = null,
+ val otaAliases: List? = null
+)
+
+data class RoomTypeUpdateRequest(
+ val code: String? = null,
+ val name: String? = null,
+ val maxAdults: Int? = null,
+ val maxChildren: Int? = null,
+ val otaAliases: List? = null
+)
+
+data class RoomTypeDto(
+ val id: String? = null,
+ val code: String? = null,
+ val name: String? = null,
+ val maxAdults: Int? = null,
+ val maxChildren: Int? = null,
+ val otaAliases: List? = null
+)
diff --git a/app/src/main/java/com/android/trisolarispms/data/api/model/TransportModels.kt b/app/src/main/java/com/android/trisolarispms/data/api/model/TransportModels.kt
new file mode 100644
index 0000000..81fc4ea
--- /dev/null
+++ b/app/src/main/java/com/android/trisolarispms/data/api/model/TransportModels.kt
@@ -0,0 +1,6 @@
+package com.android.trisolarispms.data.api.model
+
+data class TransportModeDto(
+ val id: String? = null,
+ val name: String? = null
+)
diff --git a/app/src/main/java/com/android/trisolarispms/data/api/model/UserModels.kt b/app/src/main/java/com/android/trisolarispms/data/api/model/UserModels.kt
new file mode 100644
index 0000000..3dead1c
--- /dev/null
+++ b/app/src/main/java/com/android/trisolarispms/data/api/model/UserModels.kt
@@ -0,0 +1,13 @@
+package com.android.trisolarispms.data.api.model
+
+data class UserDto(
+ val id: String? = null,
+ val name: String? = null,
+ val email: String? = null,
+ val phone: String? = null,
+ val roles: List? = null
+)
+
+data class UserRolesUpdateRequest(
+ val roles: List
+)
diff --git a/build.gradle.kts b/build.gradle.kts
index 18318be..1263c00 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -2,4 +2,5 @@
plugins {
alias(libs.plugins.android.application) apply false
alias(libs.plugins.kotlin.compose) apply false
+ id("com.google.gms.google-services") version "4.4.4" apply false
}
\ No newline at end of file
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 8ddeeac..9a00e43 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -8,6 +8,11 @@ lifecycleRuntimeKtx = "2.6.1"
activityCompose = "1.8.0"
kotlin = "2.0.21"
composeBom = "2024.09.00"
+retrofit = "2.11.0"
+okhttp = "4.12.0"
+firebaseBom = "33.5.1"
+coroutinesPlayServices = "1.7.3"
+firebaseAuthKtx = "24.0.1"
[libraries]
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
@@ -24,8 +29,15 @@ androidx-compose-ui-tooling-preview = { group = "androidx.compose.ui", name = "u
androidx-compose-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" }
androidx-compose-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" }
androidx-compose-material3 = { group = "androidx.compose.material3", name = "material3" }
+retrofit = { group = "com.squareup.retrofit2", name = "retrofit", version.ref = "retrofit" }
+retrofit-converter-gson = { group = "com.squareup.retrofit2", name = "converter-gson", version.ref = "retrofit" }
+okhttp = { group = "com.squareup.okhttp3", name = "okhttp", version.ref = "okhttp" }
+okhttp-logging = { group = "com.squareup.okhttp3", name = "logging-interceptor", version.ref = "okhttp" }
+firebase-bom = { group = "com.google.firebase", name = "firebase-bom", version.ref = "firebaseBom" }
+firebase-auth-ktx = { group = "com.google.firebase", name = "firebase-auth-ktx" }
+kotlinx-coroutines-play-services = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-play-services", version.ref = "coroutinesPlayServices" }
+google-firebase-auth-ktx = { group = "com.google.firebase", name = "firebase-auth-ktx", version.ref = "firebaseAuthKtx" }
[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }
kotlin-compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
-