Fix logout, share code display, loading states, and multi-user support

iOS Logout Fix:
- Use @EnvironmentObject in MainTabView and ProfileTabView
- Pass loginViewModel from LoginView to MainTabView
- Handle logout by dismissing main tab when isAuthenticated becomes false
- Logout button now properly returns user to login screen

Share Code UX:
- Clear share code on ManageUsers screen open (iOS & Android)
- Remove auto-loading of share codes
- User must explicitly generate code each time
- Improves security with fresh codes

Loading State Improvements:
- iOS ResidenceDetailView shows loading immediately on navigation
- Android ResidenceDetailScreen enhanced with "Loading residence..." text
- Better user feedback during API calls

Multi-User Support:
- Add isPrimaryOwner and userCount to ResidenceWithTasks model
- Update iOS toResidences() extension to include new fields
- Sync with backend API changes for shared user access

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Trey t
2025-11-08 10:51:51 -06:00
parent e271403d9b
commit 364f98a303
8 changed files with 686 additions and 8 deletions

View File

@@ -8,6 +8,8 @@ data class Residence(
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 name: String,
@SerialName("property_type") val propertyType: String,
@SerialName("street_address") val streetAddress: String,
@@ -101,6 +103,8 @@ 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,
@SerialName("street_address") val streetAddress: String,
@@ -136,4 +140,50 @@ data class MyResidencesSummary(
data class MyResidencesResponse(
val summary: MyResidencesSummary,
val residences: List<ResidenceWithTasks>
)
// Share Code Models
@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?
)
@Serializable
data class JoinResidenceRequest(
val code: String
)
@Serializable
data class JoinResidenceResponse(
val message: String,
val residence: Residence
)
// User Management Models
@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?
)
@Serializable
data class ResidenceUsersResponse(
@SerialName("owner_id") val ownerId: Int,
val users: List<ResidenceUser>
)
@Serializable
data class RemoveUserResponse(
val message: String
)