Update Kotlin models and iOS Swift to align with new Go API format
- Update all Kotlin API models to match Go API response structures - Fix Swift type aliases (TaskDetail→TaskResponse, Residence→ResidenceResponse, etc.) - Update TaskCompletionCreateRequest to simplified Go API format (taskId, notes, actualCost, photoUrl) - Fix optional handling for frequency, priority, category, status in task models - Replace isPrimaryOwner with ownerId comparison against current user - Update ResidenceUsersResponse to use owner.id instead of ownerId - Fix non-optional String fields to use isEmpty checks instead of optional binding - Add type aliases for backwards compatibility in Kotlin models 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -3,38 +3,81 @@ package com.example.mycrib.models
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
/**
|
||||
* User reference for residence responses - matching Go API ResidenceUserResponse
|
||||
*/
|
||||
@Serializable
|
||||
data class Residence(
|
||||
data class ResidenceUserResponse(
|
||||
val id: Int,
|
||||
val owner: Int? = null,
|
||||
@SerialName("owner_username") val ownerUsername: String,
|
||||
@SerialName("is_primary_owner") val isPrimaryOwner: Boolean = false,
|
||||
@SerialName("user_count") val userCount: Int = 1,
|
||||
val username: String,
|
||||
val email: String,
|
||||
@SerialName("first_name") val firstName: String = "",
|
||||
@SerialName("last_name") val lastName: String = ""
|
||||
) {
|
||||
val displayName: String
|
||||
get() = when {
|
||||
firstName.isNotBlank() && lastName.isNotBlank() -> "$firstName $lastName"
|
||||
firstName.isNotBlank() -> firstName
|
||||
lastName.isNotBlank() -> lastName
|
||||
else -> username
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Residence response matching Go API ResidenceResponse
|
||||
*/
|
||||
@Serializable
|
||||
data class ResidenceResponse(
|
||||
val id: Int,
|
||||
@SerialName("owner_id") val ownerId: Int,
|
||||
val owner: ResidenceUserResponse? = null,
|
||||
val users: List<ResidenceUserResponse> = emptyList(),
|
||||
val name: String,
|
||||
@SerialName("property_type") val propertyType: String? = null,
|
||||
@SerialName("street_address") val streetAddress: String? = null,
|
||||
@SerialName("apartment_unit") val apartmentUnit: String? = null,
|
||||
val city: String? = null,
|
||||
@SerialName("state_province") val stateProvince: String? = null,
|
||||
@SerialName("postal_code") val postalCode: String? = null,
|
||||
val country: String? = null,
|
||||
@SerialName("property_type_id") val propertyTypeId: Int? = null,
|
||||
@SerialName("property_type") val propertyType: ResidenceType? = null,
|
||||
@SerialName("street_address") val streetAddress: String = "",
|
||||
@SerialName("apartment_unit") val apartmentUnit: String = "",
|
||||
val city: String = "",
|
||||
@SerialName("state_province") val stateProvince: String = "",
|
||||
@SerialName("postal_code") val postalCode: String = "",
|
||||
val country: String = "",
|
||||
val bedrooms: Int? = null,
|
||||
val bathrooms: Float? = null,
|
||||
val bathrooms: Double? = null,
|
||||
@SerialName("square_footage") val squareFootage: Int? = null,
|
||||
@SerialName("lot_size") val lotSize: Float? = null,
|
||||
@SerialName("lot_size") val lotSize: Double? = null,
|
||||
@SerialName("year_built") val yearBuilt: Int? = null,
|
||||
val description: String? = null,
|
||||
val description: String = "",
|
||||
@SerialName("purchase_date") val purchaseDate: String? = null,
|
||||
@SerialName("purchase_price") val purchasePrice: Double? = null,
|
||||
@SerialName("is_primary") val isPrimary: Boolean = false,
|
||||
@SerialName("is_active") val isActive: Boolean = true,
|
||||
@SerialName("created_at") val createdAt: String,
|
||||
@SerialName("updated_at") val updatedAt: String
|
||||
)
|
||||
) {
|
||||
// Helper to get owner username
|
||||
val ownerUsername: String get() = owner?.displayName ?: ""
|
||||
|
||||
// Helper to get property type name
|
||||
val propertyTypeName: String? get() = propertyType?.name
|
||||
|
||||
// Backwards compatibility for UI code
|
||||
// Note: isPrimaryOwner requires comparing with current user - can't be computed here
|
||||
// UI components should check ownerId == currentUserId instead
|
||||
|
||||
// Stub task summary for UI compatibility (Go API doesn't return this per-residence)
|
||||
val taskSummary: ResidenceTaskSummary get() = ResidenceTaskSummary()
|
||||
|
||||
// Stub summary for UI compatibility
|
||||
val summary: ResidenceSummaryResponse get() = ResidenceSummaryResponse(id = id, name = name)
|
||||
}
|
||||
|
||||
/**
|
||||
* Residence create request matching Go API CreateResidenceRequest
|
||||
*/
|
||||
@Serializable
|
||||
data class ResidenceCreateRequest(
|
||||
val name: String,
|
||||
@SerialName("property_type") val propertyType: Int? = null,
|
||||
@SerialName("property_type_id") val propertyTypeId: Int? = null,
|
||||
@SerialName("street_address") val streetAddress: String? = null,
|
||||
@SerialName("apartment_unit") val apartmentUnit: String? = null,
|
||||
val city: String? = null,
|
||||
@@ -42,189 +85,172 @@ data class ResidenceCreateRequest(
|
||||
@SerialName("postal_code") val postalCode: String? = null,
|
||||
val country: String? = null,
|
||||
val bedrooms: Int? = null,
|
||||
val bathrooms: Float? = null,
|
||||
val bathrooms: Double? = null,
|
||||
@SerialName("square_footage") val squareFootage: Int? = null,
|
||||
@SerialName("lot_size") val lotSize: Float? = null,
|
||||
@SerialName("year_built") val yearBuilt: Int? = null,
|
||||
val description: String? = null,
|
||||
@SerialName("purchase_date") val purchaseDate: String? = null,
|
||||
@SerialName("purchase_price") val purchasePrice: String? = null,
|
||||
@SerialName("is_primary") val isPrimary: Boolean = false
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class TaskColumnIcon(
|
||||
val ios: String,
|
||||
val android: String,
|
||||
val web: String
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class TaskColumnCategory(
|
||||
val name: String,
|
||||
@SerialName("display_name") val displayName: String,
|
||||
val icons: TaskColumnIcon,
|
||||
val color: String,
|
||||
val count: Int
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class TaskSummary(
|
||||
val total: Int,
|
||||
val categories: List<TaskColumnCategory>
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class ResidenceSummary(
|
||||
val id: Int,
|
||||
val owner: Int,
|
||||
@SerialName("owner_username") val ownerUsername: String,
|
||||
val name: String,
|
||||
@SerialName("property_type") val propertyType: String? = null,
|
||||
@SerialName("street_address") val streetAddress: String? = null,
|
||||
@SerialName("apartment_unit") val apartmentUnit: String? = null,
|
||||
val city: String? = null,
|
||||
@SerialName("state_province") val stateProvince: String? = null,
|
||||
@SerialName("postal_code") val postalCode: String? = null,
|
||||
val country: String? = null,
|
||||
@SerialName("is_primary") val isPrimary: Boolean,
|
||||
@SerialName("task_summary") val taskSummary: TaskSummary,
|
||||
@SerialName("last_completed_task") val lastCompletedCustomTask: CustomTask?,
|
||||
@SerialName("next_upcoming_task") val nextUpcomingCustomTask: CustomTask?,
|
||||
@SerialName("created_at") val createdAt: String,
|
||||
@SerialName("updated_at") val updatedAt: String
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class ResidenceSummaryResponse(
|
||||
val summary: OverallSummary,
|
||||
val residences: List<ResidenceSummary>
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class OverallSummary(
|
||||
@SerialName("total_residences") val totalResidences: Int,
|
||||
@SerialName("total_tasks") val totalTasks: Int,
|
||||
@SerialName("total_completed") val totalCompleted: Int,
|
||||
@SerialName("total_pending") val totalPending: Int,
|
||||
@SerialName("tasks_due_next_week") val tasksDueNextWeek: Int,
|
||||
@SerialName("tasks_due_next_month") val tasksDueNextMonth: Int
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class ResidenceWithTasks(
|
||||
val id: Int,
|
||||
val owner: Int,
|
||||
@SerialName("owner_username") val ownerUsername: String,
|
||||
@SerialName("is_primary_owner") val isPrimaryOwner: Boolean = false,
|
||||
@SerialName("user_count") val userCount: Int = 1,
|
||||
val name: String,
|
||||
@SerialName("property_type") val propertyType: String? = null,
|
||||
@SerialName("street_address") val streetAddress: String? = null,
|
||||
@SerialName("apartment_unit") val apartmentUnit: String? = null,
|
||||
val city: String? = null,
|
||||
@SerialName("state_province") val stateProvince: String? = null,
|
||||
@SerialName("postal_code") val postalCode: String? = null,
|
||||
val country: String? = null,
|
||||
val bedrooms: Int? = null,
|
||||
val bathrooms: Float? = null,
|
||||
@SerialName("square_footage") val squareFootage: Int? = null,
|
||||
@SerialName("lot_size") val lotSize: Float? = null,
|
||||
@SerialName("lot_size") val lotSize: Double? = null,
|
||||
@SerialName("year_built") val yearBuilt: Int? = null,
|
||||
val description: String? = null,
|
||||
@SerialName("purchase_date") val purchaseDate: String? = null,
|
||||
@SerialName("purchase_price") val purchasePrice: Double? = null,
|
||||
@SerialName("is_primary") val isPrimary: Boolean,
|
||||
@SerialName("task_summary") val taskSummary: TaskSummary,
|
||||
val tasks: List<TaskDetail>,
|
||||
@SerialName("created_at") val createdAt: String,
|
||||
@SerialName("updated_at") val updatedAt: String
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class MyResidencesSummary(
|
||||
@SerialName("total_residences") val totalResidences: Int,
|
||||
@SerialName("total_tasks") val totalTasks: Int,
|
||||
@SerialName("tasks_due_next_week") val tasksDueNextWeek: Int,
|
||||
@SerialName("tasks_due_next_month") val tasksDueNextMonth: Int
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class MyResidencesResponse(
|
||||
val summary: MyResidencesSummary,
|
||||
val residences: List<ResidenceWithTasks>
|
||||
@SerialName("is_primary") val isPrimary: Boolean? = null
|
||||
)
|
||||
|
||||
/**
|
||||
* Minimal residence model for list views.
|
||||
* Uses property_type_id and annotated counts instead of nested objects.
|
||||
* Resolve property type via DataCache.getResidenceType(residence.propertyTypeId)
|
||||
* Residence update request matching Go API UpdateResidenceRequest
|
||||
*/
|
||||
@Serializable
|
||||
data class ResidenceMinimal(
|
||||
val id: Int,
|
||||
val name: String,
|
||||
data class ResidenceUpdateRequest(
|
||||
val name: String? = null,
|
||||
@SerialName("property_type_id") val propertyTypeId: Int? = null,
|
||||
@SerialName("street_address") val streetAddress: String? = null,
|
||||
@SerialName("apartment_unit") val apartmentUnit: String? = null,
|
||||
val city: String? = null,
|
||||
@SerialName("state_province") val stateProvince: String? = null,
|
||||
@SerialName("postal_code") val postalCode: String? = null,
|
||||
val country: String? = null,
|
||||
val bedrooms: Int? = null,
|
||||
val bathrooms: Float? = null,
|
||||
@SerialName("is_primary") val isPrimary: Boolean = false,
|
||||
@SerialName("is_primary_owner") val isPrimaryOwner: Boolean = false,
|
||||
@SerialName("user_count") val userCount: Int = 1,
|
||||
// Annotated counts from database (no N+1 queries)
|
||||
@SerialName("task_count") val taskCount: Int = 0,
|
||||
@SerialName("tasks_pending") val tasksPending: Int = 0,
|
||||
@SerialName("tasks_overdue") val tasksOverdue: Int = 0,
|
||||
@SerialName("tasks_due_week") val tasksDueWeek: Int = 0,
|
||||
// Reference to last/next task (just ID and date, not full object)
|
||||
@SerialName("last_completed_task_id") val lastCompletedTaskId: Int? = null,
|
||||
@SerialName("last_completed_date") val lastCompletedDate: String? = null,
|
||||
@SerialName("next_task_id") val nextTaskId: Int? = null,
|
||||
@SerialName("next_task_date") val nextTaskDate: String? = null,
|
||||
val bathrooms: Double? = null,
|
||||
@SerialName("square_footage") val squareFootage: Int? = null,
|
||||
@SerialName("lot_size") val lotSize: Double? = null,
|
||||
@SerialName("year_built") val yearBuilt: Int? = null,
|
||||
val description: String? = null,
|
||||
@SerialName("purchase_date") val purchaseDate: String? = null,
|
||||
@SerialName("purchase_price") val purchasePrice: Double? = null,
|
||||
@SerialName("is_primary") val isPrimary: Boolean? = null
|
||||
)
|
||||
|
||||
/**
|
||||
* Share code response matching Go API ShareCodeResponse
|
||||
*/
|
||||
@Serializable
|
||||
data class ShareCodeResponse(
|
||||
val id: Int,
|
||||
val code: String,
|
||||
@SerialName("residence_id") val residenceId: Int,
|
||||
@SerialName("created_by_id") val createdById: Int,
|
||||
@SerialName("is_active") val isActive: Boolean,
|
||||
@SerialName("expires_at") val expiresAt: String?,
|
||||
@SerialName("created_at") val createdAt: String
|
||||
)
|
||||
|
||||
// Share Code Models
|
||||
/**
|
||||
* Generate share code request
|
||||
*/
|
||||
@Serializable
|
||||
data class ResidenceShareCode(
|
||||
val id: Int,
|
||||
val code: String,
|
||||
val residence: Int,
|
||||
@SerialName("residence_name") val residenceName: String,
|
||||
@SerialName("created_by") val createdBy: Int,
|
||||
@SerialName("created_by_username") val createdByUsername: String,
|
||||
@SerialName("is_active") val isActive: Boolean,
|
||||
@SerialName("created_at") val createdAt: String,
|
||||
@SerialName("expires_at") val expiresAt: String?
|
||||
data class GenerateShareCodeRequest(
|
||||
@SerialName("expires_in_hours") val expiresInHours: Int? = null
|
||||
)
|
||||
|
||||
/**
|
||||
* Generate share code response matching Go API GenerateShareCodeResponse
|
||||
*/
|
||||
@Serializable
|
||||
data class GenerateShareCodeResponse(
|
||||
val message: String,
|
||||
@SerialName("share_code") val shareCode: ShareCodeResponse
|
||||
)
|
||||
|
||||
/**
|
||||
* Join residence request
|
||||
*/
|
||||
@Serializable
|
||||
data class JoinResidenceRequest(
|
||||
val code: String
|
||||
)
|
||||
|
||||
/**
|
||||
* Join residence response matching Go API JoinResidenceResponse
|
||||
*/
|
||||
@Serializable
|
||||
data class JoinResidenceResponse(
|
||||
val message: String,
|
||||
val residence: Residence
|
||||
val residence: ResidenceResponse
|
||||
)
|
||||
|
||||
// User Management Models
|
||||
/**
|
||||
* Total summary for dashboard display
|
||||
*/
|
||||
@Serializable
|
||||
data class ResidenceUser(
|
||||
val id: Int,
|
||||
val username: String,
|
||||
val email: String,
|
||||
@SerialName("first_name") val firstName: String?,
|
||||
@SerialName("last_name") val lastName: String?
|
||||
data class TotalSummary(
|
||||
@SerialName("total_residences") val totalResidences: Int = 0,
|
||||
@SerialName("total_tasks") val totalTasks: Int = 0,
|
||||
@SerialName("total_pending") val totalPending: Int = 0,
|
||||
@SerialName("total_overdue") val totalOverdue: Int = 0,
|
||||
@SerialName("tasks_due_next_week") val tasksDueNextWeek: Int = 0,
|
||||
@SerialName("tasks_due_next_month") val tasksDueNextMonth: Int = 0
|
||||
)
|
||||
|
||||
/**
|
||||
* My residences response - list of user's residences
|
||||
* Go API returns array directly, this wraps for consistency
|
||||
*/
|
||||
@Serializable
|
||||
data class MyResidencesResponse(
|
||||
val residences: List<ResidenceResponse>,
|
||||
val summary: TotalSummary = TotalSummary()
|
||||
)
|
||||
|
||||
/**
|
||||
* Residence summary response for dashboard
|
||||
*/
|
||||
@Serializable
|
||||
data class ResidenceSummaryResponse(
|
||||
val id: Int = 0,
|
||||
val name: String = "",
|
||||
@SerialName("task_count") val taskCount: Int = 0,
|
||||
@SerialName("pending_count") val pendingCount: Int = 0,
|
||||
@SerialName("overdue_count") val overdueCount: Int = 0
|
||||
)
|
||||
|
||||
/**
|
||||
* Task category summary for residence
|
||||
*/
|
||||
@Serializable
|
||||
data class TaskCategorySummary(
|
||||
val name: String,
|
||||
@SerialName("display_name") val displayName: String,
|
||||
val icons: TaskCategoryIcons,
|
||||
val color: String,
|
||||
val count: Int
|
||||
)
|
||||
|
||||
/**
|
||||
* Icons for task category (Android/iOS)
|
||||
*/
|
||||
@Serializable
|
||||
data class TaskCategoryIcons(
|
||||
val android: String = "",
|
||||
val ios: String = ""
|
||||
)
|
||||
|
||||
/**
|
||||
* Task summary per residence (for UI backwards compatibility)
|
||||
*/
|
||||
@Serializable
|
||||
data class ResidenceTaskSummary(
|
||||
val categories: List<TaskCategorySummary> = emptyList()
|
||||
)
|
||||
|
||||
/**
|
||||
* Residence users response
|
||||
*/
|
||||
@Serializable
|
||||
data class ResidenceUsersResponse(
|
||||
@SerialName("owner_id") val ownerId: Int,
|
||||
val users: List<ResidenceUser>
|
||||
val owner: ResidenceUserResponse,
|
||||
val users: List<ResidenceUserResponse>
|
||||
)
|
||||
|
||||
/**
|
||||
* Remove user response
|
||||
*/
|
||||
@Serializable
|
||||
data class RemoveUserResponse(
|
||||
val message: String
|
||||
)
|
||||
)
|
||||
|
||||
// Type aliases for backwards compatibility with existing code
|
||||
typealias Residence = ResidenceResponse
|
||||
typealias ResidenceShareCode = ShareCodeResponse
|
||||
typealias ResidenceUser = ResidenceUserResponse
|
||||
typealias TaskSummary = ResidenceTaskSummary
|
||||
typealias TaskColumnCategory = TaskCategorySummary
|
||||
Reference in New Issue
Block a user