Files
honeyDueKMP/composeApp/src/commonMain/kotlin/com/example/mycrib/cache/DataCache.kt
Trey t f1f71224aa Add Android theme system and fix package naming issues
This commit adds a comprehensive theming system to Android matching iOS, and fixes package declarations throughout the codebase to match directory structure.

Theme System Additions:
- Added 11 themes matching iOS: Default, Teal, Ocean, Forest, Sunset, Monochrome, Lavender, Crimson, Midnight, Desert, Mint
- Created ThemeColors.kt with exact iOS color values for light/dark modes
- Added ThemeManager.kt for dynamic theme switching
- Created Spacing.kt with standardized spacing constants (xs/sm/md/lg/xl)
- Added ThemePickerDialog.kt for theme selection UI
- Integrated theme switching in ProfileScreen.kt
- Updated App.kt to observe ThemeManager for reactive theming

Component Library:
- Added StandardCard.kt and CompactCard.kt for consistent card styling
- Added FormTextField.kt with error/helper text support
- Added FormSection.kt for grouping related form fields
- Added StandardEmptyState.kt for empty state UI

Package Migration:
- Fixed all package declarations to match directory structure (com.example.mycrib.*)
- Updated package declarations in commonMain, androidMain, and iosMain
- Fixed all import statements across entire codebase
- Ensures compilation on both Android and iOS platforms

iOS Theme Rename:
- Renamed "Default" theme to "Teal" in iOS
- Renamed "Bright" theme to "Default" in iOS to make vibrant colors the default

Build Status:
-  Android builds successfully
-  iOS builds successfully

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-22 10:44:54 -06:00

257 lines
9.2 KiB
Kotlin

package com.example.mycrib.cache
import com.example.mycrib.models.*
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlin.time.Clock
import kotlin.time.ExperimentalTime
//import kotlinx.datetime.Clock
//import kotlinx.datetime.Instant
/**
* Centralized data cache for the application.
* This singleton holds all frequently accessed data in memory to avoid redundant API calls.
*/
object DataCache {
// User & Authentication
private val _currentUser = MutableStateFlow<User?>(null)
val currentUser: StateFlow<User?> = _currentUser.asStateFlow()
// Residences
private val _residences = MutableStateFlow<List<Residence>>(emptyList())
val residences: StateFlow<List<Residence>> = _residences.asStateFlow()
private val _myResidences = MutableStateFlow<MyResidencesResponse?>(null)
val myResidences: StateFlow<MyResidencesResponse?> = _myResidences.asStateFlow()
private val _residenceSummaries = MutableStateFlow<Map<Int, ResidenceSummaryResponse>>(emptyMap())
val residenceSummaries: StateFlow<Map<Int, ResidenceSummaryResponse>> = _residenceSummaries.asStateFlow()
// Tasks
private val _allTasks = MutableStateFlow<TaskColumnsResponse?>(null)
val allTasks: StateFlow<TaskColumnsResponse?> = _allTasks.asStateFlow()
private val _tasksByResidence = MutableStateFlow<Map<Int, TaskColumnsResponse>>(emptyMap())
val tasksByResidence: StateFlow<Map<Int, TaskColumnsResponse>> = _tasksByResidence.asStateFlow()
// Documents
private val _documents = MutableStateFlow<List<Document>>(emptyList())
val documents: StateFlow<List<Document>> = _documents.asStateFlow()
private val _documentsByResidence = MutableStateFlow<Map<Int, List<Document>>>(emptyMap())
val documentsByResidence: StateFlow<Map<Int, List<Document>>> = _documentsByResidence.asStateFlow()
// Contractors
private val _contractors = MutableStateFlow<List<Contractor>>(emptyList())
val contractors: StateFlow<List<Contractor>> = _contractors.asStateFlow()
// Lookups/Reference Data
private val _residenceTypes = MutableStateFlow<List<ResidenceType>>(emptyList())
val residenceTypes: StateFlow<List<ResidenceType>> = _residenceTypes.asStateFlow()
private val _taskFrequencies = MutableStateFlow<List<TaskFrequency>>(emptyList())
val taskFrequencies: StateFlow<List<TaskFrequency>> = _taskFrequencies.asStateFlow()
private val _taskPriorities = MutableStateFlow<List<TaskPriority>>(emptyList())
val taskPriorities: StateFlow<List<TaskPriority>> = _taskPriorities.asStateFlow()
private val _taskStatuses = MutableStateFlow<List<TaskStatus>>(emptyList())
val taskStatuses: StateFlow<List<TaskStatus>> = _taskStatuses.asStateFlow()
private val _taskCategories = MutableStateFlow<List<TaskCategory>>(emptyList())
val taskCategories: StateFlow<List<TaskCategory>> = _taskCategories.asStateFlow()
private val _contractorSpecialties = MutableStateFlow<List<ContractorSpecialty>>(emptyList())
val contractorSpecialties: StateFlow<List<ContractorSpecialty>> = _contractorSpecialties.asStateFlow()
private val _lookupsInitialized = MutableStateFlow(false)
val lookupsInitialized: StateFlow<Boolean> = _lookupsInitialized.asStateFlow()
// Cache metadata
private val _lastRefreshTime = MutableStateFlow<Long>(0L)
val lastRefreshTime: StateFlow<Long> = _lastRefreshTime.asStateFlow()
private val _isCacheInitialized = MutableStateFlow(false)
val isCacheInitialized: StateFlow<Boolean> = _isCacheInitialized.asStateFlow()
// Update methods
fun updateCurrentUser(user: User?) {
_currentUser.value = user
}
fun updateResidences(residences: List<Residence>) {
_residences.value = residences
updateLastRefreshTime()
}
fun updateMyResidences(myResidences: MyResidencesResponse) {
_myResidences.value = myResidences
updateLastRefreshTime()
}
fun updateResidenceSummary(residenceId: Int, summary: ResidenceSummaryResponse) {
_residenceSummaries.value = _residenceSummaries.value + (residenceId to summary)
}
fun updateAllTasks(tasks: TaskColumnsResponse) {
_allTasks.value = tasks
updateLastRefreshTime()
}
fun updateTasksByResidence(residenceId: Int, tasks: TaskColumnsResponse) {
_tasksByResidence.value = _tasksByResidence.value + (residenceId to tasks)
}
fun updateDocuments(documents: List<Document>) {
_documents.value = documents
updateLastRefreshTime()
}
fun updateDocumentsByResidence(residenceId: Int, documents: List<Document>) {
_documentsByResidence.value = _documentsByResidence.value + (residenceId to documents)
}
fun updateContractors(contractors: List<Contractor>) {
_contractors.value = contractors
updateLastRefreshTime()
}
// Lookup update methods removed - lookups are handled by LookupsViewModel
fun setCacheInitialized(initialized: Boolean) {
_isCacheInitialized.value = initialized
}
@OptIn(ExperimentalTime::class)
private fun updateLastRefreshTime() {
_lastRefreshTime.value = Clock.System.now().toEpochMilliseconds()
}
// Helper methods to add/update/remove individual items
fun addResidence(residence: Residence) {
_residences.value = _residences.value + residence
}
fun updateResidence(residence: Residence) {
_residences.value = _residences.value.map {
if (it.id == residence.id) residence else it
}
}
fun removeResidence(residenceId: Int) {
_residences.value = _residences.value.filter { it.id != residenceId }
// Also clear related caches
_tasksByResidence.value = _tasksByResidence.value - residenceId
_documentsByResidence.value = _documentsByResidence.value - residenceId
_residenceSummaries.value = _residenceSummaries.value - residenceId
}
fun addDocument(document: Document) {
_documents.value = _documents.value + document
}
fun updateDocument(document: Document) {
_documents.value = _documents.value.map {
if (it.id == document.id) document else it
}
}
fun removeDocument(documentId: Int) {
_documents.value = _documents.value.filter { it.id != documentId }
}
fun addContractor(contractor: Contractor) {
_contractors.value = _contractors.value + contractor
}
fun updateContractor(contractor: Contractor) {
_contractors.value = _contractors.value.map {
if (it.id == contractor.id) contractor else it
}
}
fun removeContractor(contractorId: Int) {
_contractors.value = _contractors.value.filter { it.id != contractorId }
}
// Lookup update methods
fun updateResidenceTypes(types: List<ResidenceType>) {
_residenceTypes.value = types
}
fun updateTaskFrequencies(frequencies: List<TaskFrequency>) {
_taskFrequencies.value = frequencies
}
fun updateTaskPriorities(priorities: List<TaskPriority>) {
_taskPriorities.value = priorities
}
fun updateTaskStatuses(statuses: List<TaskStatus>) {
_taskStatuses.value = statuses
}
fun updateTaskCategories(categories: List<TaskCategory>) {
_taskCategories.value = categories
}
fun updateContractorSpecialties(specialties: List<ContractorSpecialty>) {
_contractorSpecialties.value = specialties
}
fun updateAllLookups(staticData: StaticDataResponse) {
_residenceTypes.value = staticData.residenceTypes
_taskFrequencies.value = staticData.taskFrequencies
_taskPriorities.value = staticData.taskPriorities
_taskStatuses.value = staticData.taskStatuses
_taskCategories.value = staticData.taskCategories
_contractorSpecialties.value = staticData.contractorSpecialties
}
fun markLookupsInitialized() {
_lookupsInitialized.value = true
}
// Clear methods
fun clearAll() {
_currentUser.value = null
_residences.value = emptyList()
_myResidences.value = null
_residenceSummaries.value = emptyMap()
_allTasks.value = null
_tasksByResidence.value = emptyMap()
_documents.value = emptyList()
_documentsByResidence.value = emptyMap()
_contractors.value = emptyList()
clearLookups()
_lastRefreshTime.value = 0L
_isCacheInitialized.value = false
}
fun clearLookups() {
_residenceTypes.value = emptyList()
_taskFrequencies.value = emptyList()
_taskPriorities.value = emptyList()
_taskStatuses.value = emptyList()
_taskCategories.value = emptyList()
_contractorSpecialties.value = emptyList()
_lookupsInitialized.value = false
}
fun clearUserData() {
_currentUser.value = null
_residences.value = emptyList()
_myResidences.value = null
_residenceSummaries.value = emptyMap()
_allTasks.value = null
_tasksByResidence.value = emptyMap()
_documents.value = emptyList()
_documentsByResidence.value = emptyMap()
_contractors.value = emptyList()
_isCacheInitialized.value = false
}
}