Refactor iOS and Android views into separate files

Organized view components by extracting composables and views into separate files following single responsibility principle.

iOS Changes:
- Split MainTabView → extracted ProfileTabView
- Split CompleteTaskView → extracted ImageThumbnailView, CameraPickerView
- Split ManageUsersView → extracted ShareCodeCard, UserListItem
- Consolidated task action buttons into single TaskActionButtons.swift file
- Split HomeScreenView → extracted OverviewCard, StatView, HomeNavigationCard
- Split AllTasksView → extracted DynamicTaskColumnView, DynamicTaskCard
- Split ContentView → extracted ComposeView, CustomView

Android Changes:
- Split ResetPasswordScreen → extracted RequirementItem component
- Split TasksScreen → extracted TaskPill component
- Created TaskDisplayUtils for shared helper functions (getIconFromName, hexToColor)

All extracted components properly organized in:
- iOS: Subviews/Common, Subviews/Task, Subviews/Residence, Profile
- Android: ui/components/auth, ui/components/task, ui/utils

🤖 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-10 11:38:17 -06:00
parent 29b4c99f08
commit 77a118a6f7
23 changed files with 780 additions and 747 deletions

View File

@@ -155,118 +155,6 @@ struct ManageUsersView: View {
}
}
// MARK: - Share Code Card
struct ShareCodeCard: View {
let shareCode: ResidenceShareCode?
let residenceName: String
let isGeneratingCode: Bool
let onGenerateCode: () -> Void
var body: some View {
VStack(alignment: .leading, spacing: 12) {
HStack {
VStack(alignment: .leading, spacing: 4) {
Text("Share Code")
.font(.subheadline)
.foregroundColor(.secondary)
if let shareCode = shareCode {
Text(shareCode.code)
.font(.title)
.fontWeight(.bold)
.foregroundColor(.blue)
} else {
Text("No active code")
.font(.body)
.foregroundColor(.secondary)
}
}
Spacer()
Button(action: onGenerateCode) {
HStack {
Image(systemName: "square.and.arrow.up")
Text(shareCode != nil ? "New Code" : "Generate")
}
}
.buttonStyle(.borderedProminent)
.disabled(isGeneratingCode)
}
if shareCode != nil {
Text("Share this code with others to give them access to \(residenceName)")
.font(.caption)
.foregroundColor(.secondary)
}
}
.padding()
.background(Color.blue.opacity(0.1))
.cornerRadius(12)
}
}
// MARK: - User List Item
struct UserListItem: View {
let user: ResidenceUser
let isOwner: Bool
let isPrimaryOwner: Bool
let onRemove: () -> Void
var body: some View {
HStack(alignment: .top, spacing: 12) {
VStack(alignment: .leading, spacing: 4) {
HStack {
Text(user.username)
.font(.body)
.fontWeight(.medium)
if isOwner {
Text("Owner")
.font(.caption)
.fontWeight(.semibold)
.foregroundColor(.blue)
.padding(.horizontal, 6)
.padding(.vertical, 2)
.background(Color.blue.opacity(0.1))
.cornerRadius(4)
}
}
if !user.email.isEmpty {
Text(user.email)
.font(.caption)
.foregroundColor(.secondary)
}
let fullName = [user.firstName, user.lastName]
.compactMap { $0 }
.filter { !$0.isEmpty }
.joined(separator: " ")
if !fullName.isEmpty {
Text(fullName)
.font(.caption)
.foregroundColor(.secondary)
}
}
Spacer()
if isPrimaryOwner && !isOwner {
Button(action: onRemove) {
Image(systemName: "trash")
.foregroundColor(.red)
}
}
}
.padding()
.background(Color(.systemBackground))
.cornerRadius(12)
.padding(.horizontal)
}
}
#Preview {
ManageUsersView(residenceId: 1, residenceName: "My Home", isPrimaryOwner: true)
}