@shaykec/app-agent 1.0.4 → 1.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/skills/ui-tester/SKILL.md +59 -0
- package/.cursor/skills/android-customizer/SKILL.md +50 -16
- package/.cursor/skills/appconfig-customization/SKILL.md +15 -0
- package/.cursor/skills/customization-planner/SKILL.md +17 -1
- package/.cursor/skills/ios-customizer/SKILL.md +54 -13
- package/.cursor/skills/mock-data-update/SKILL.md +11 -3
- package/.cursor/skills/ui-tester/SKILL.md +59 -0
- package/dist/cli.d.ts +18 -4
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +134 -14
- package/dist/cli.js.map +1 -1
- package/dist/github.d.ts +5 -0
- package/dist/github.d.ts.map +1 -1
- package/dist/github.js +27 -0
- package/dist/github.js.map +1 -1
- package/dist/index.js +218 -24
- package/dist/index.js.map +1 -1
- package/dist/preview-generator.d.ts +35 -0
- package/dist/preview-generator.d.ts.map +1 -0
- package/dist/preview-generator.js +546 -0
- package/dist/preview-generator.js.map +1 -0
- package/package.json +4 -1
- package/templates/android/BookTemplate/app/src/main/kotlin/com/appship/book/features/booking/BookingScreen.kt +5 -3
- package/templates/android/BookTemplate/app/src/main/kotlin/com/appship/book/features/bookings/BookingsScreen.kt +7 -5
- package/templates/android/BookTemplate/app/src/main/kotlin/com/appship/book/features/discovery/DiscoveryViewModel.kt +3 -2
- package/templates/android/BookTemplate/app/src/main/kotlin/com/appship/book/features/profile/ProfileScreen.kt +4 -2
- package/templates/android/ChatTemplate/app/src/main/kotlin/com/appship/chat/AppConfig.kt +9 -0
- package/templates/android/ChatTemplate/app/src/main/kotlin/com/appship/chat/data/DataRepository.kt +23 -0
- package/templates/android/ChatTemplate/app/src/main/kotlin/com/appship/chat/data/DataSourceResolver.kt +23 -0
- package/templates/android/ChatTemplate/app/src/main/kotlin/com/appship/chat/features/calls/CallsScreen.kt +4 -3
- package/templates/android/ChatTemplate/app/src/main/kotlin/com/appship/chat/features/contacts/ContactsScreen.kt +3 -2
- package/templates/android/ChatTemplate/app/src/main/kotlin/com/appship/chat/features/conversations/ChatScreen.kt +11 -10
- package/templates/android/ChatTemplate/app/src/main/kotlin/com/appship/chat/features/conversations/ConversationsScreen.kt +5 -5
- package/templates/android/ChatTemplate/app/src/main/kotlin/com/appship/chat/features/navigation/Navigation.kt +4 -2
- package/templates/android/ChatTemplate/app/src/main/kotlin/com/appship/chat/features/settings/SettingsScreen.kt +6 -4
- package/templates/android/ChatTemplate/app/src/main/kotlin/com/appship/chat/mock/MockDataProvider.kt +7 -7
- package/templates/android/DashTemplate/app/src/main/kotlin/com/appship/dash/data/DataRepository.kt +46 -0
- package/templates/android/DashTemplate/app/src/main/kotlin/com/appship/dash/data/DataSourceResolver.kt +23 -0
- package/templates/android/DashTemplate/app/src/main/kotlin/com/appship/dash/features/alerts/AlertsScreen.kt +4 -3
- package/templates/android/DashTemplate/app/src/main/kotlin/com/appship/dash/features/dashboard/DashboardScreen.kt +3 -2
- package/templates/android/DashTemplate/app/src/main/kotlin/com/appship/dash/features/datasources/DataSourcesScreen.kt +3 -2
- package/templates/android/DashTemplate/app/src/main/kotlin/com/appship/dash/features/reports/ReportsScreen.kt +3 -2
- package/templates/android/DashTemplate/app/src/main/kotlin/com/appship/dash/mock/MockDataProvider.kt +16 -15
- package/templates/android/FamilyTemplate/app/src/main/java/com/appship/family/AppConfig.kt +9 -0
- package/templates/android/FamilyTemplate/app/src/main/java/com/appship/family/features/calendar/CalendarScreen.kt +5 -5
- package/templates/android/FamilyTemplate/app/src/main/java/com/appship/family/features/chores/ChoreBoardScreen.kt +3 -3
- package/templates/android/FamilyTemplate/app/src/main/java/com/appship/family/features/familyhub/FamilyHubScreen.kt +4 -4
- package/templates/android/FamilyTemplate/app/src/main/java/com/appship/family/features/gallery/GalleryScreen.kt +3 -3
- package/templates/android/FamilyTemplate/app/src/main/java/com/appship/family/features/members/MembersListScreen.kt +5 -5
- package/templates/android/FamilyTemplate/app/src/main/java/com/appship/family/features/rewards/RewardsScreen.kt +5 -5
- package/templates/android/FamilyTemplate/app/src/main/java/com/appship/family/features/settings/SettingsScreen.kt +3 -3
- package/templates/android/FamilyTemplate/app/src/main/java/com/appship/family/mock/MockDataProvider.kt +29 -32
- package/templates/android/FinanceTemplate/app/src/main/kotlin/com/appship/finance/AppConfig.kt +9 -0
- package/templates/android/FinanceTemplate/app/src/main/kotlin/com/appship/finance/data/DataRepository.kt +70 -0
- package/templates/android/FinanceTemplate/app/src/main/kotlin/com/appship/finance/data/DataSourceResolver.kt +23 -0
- package/templates/android/FinanceTemplate/app/src/main/kotlin/com/appship/finance/features/budgets/BudgetsScreen.kt +3 -2
- package/templates/android/FinanceTemplate/app/src/main/kotlin/com/appship/finance/features/goals/GoalsScreen.kt +5 -3
- package/templates/android/FinanceTemplate/app/src/main/kotlin/com/appship/finance/features/home/HomeScreen.kt +8 -7
- package/templates/android/FinanceTemplate/app/src/main/kotlin/com/appship/finance/features/settings/SettingsScreen.kt +0 -1
- package/templates/android/FinanceTemplate/app/src/main/kotlin/com/appship/finance/features/transactions/TransactionsScreen.kt +9 -4
- package/templates/android/FinanceTemplate/app/src/main/kotlin/com/appship/finance/mock/MockDataProvider.kt +103 -11
- package/templates/android/GameTemplate/app/src/main/kotlin/com/appship/game/data/DataRepository.kt +19 -0
- package/templates/android/GameTemplate/app/src/main/kotlin/com/appship/game/features/leaderboard/LeaderboardScreen.kt +2 -1
- package/templates/android/GameTemplate/app/src/main/kotlin/com/appship/game/features/results/ResultsScreen.kt +3 -2
- package/templates/android/HealthTemplate/app/src/main/kotlin/com/appship/health/data/DataRepository.kt +46 -0
- package/templates/android/HealthTemplate/app/src/main/kotlin/com/appship/health/data/DataSourceResolver.kt +23 -0
- package/templates/android/HealthTemplate/app/src/main/kotlin/com/appship/health/features/dashboard/DashboardScreen.kt +3 -2
- package/templates/android/HealthTemplate/app/src/main/kotlin/com/appship/health/features/profile/ProfileScreen.kt +3 -2
- package/templates/android/HealthTemplate/app/src/main/kotlin/com/appship/health/features/workouts/WorkoutListScreen.kt +3 -2
- package/templates/android/HealthTemplate/app/src/main/kotlin/com/appship/health/mock/MockDataProvider.kt +13 -13
- package/templates/android/LearnTemplate/app/src/main/kotlin/com/appship/learn/AppConfig.kt +9 -0
- package/templates/android/LearnTemplate/app/src/main/kotlin/com/appship/learn/data/DataRepository.kt +48 -0
- package/templates/android/LearnTemplate/app/src/main/kotlin/com/appship/learn/data/DataSourceResolver.kt +23 -0
- package/templates/android/LearnTemplate/app/src/main/kotlin/com/appship/learn/features/courses/CourseListScreen.kt +4 -3
- package/templates/android/LearnTemplate/app/src/main/kotlin/com/appship/learn/features/leaderboard/LeaderboardScreen.kt +3 -2
- package/templates/android/LearnTemplate/app/src/main/kotlin/com/appship/learn/features/profile/ProfileScreen.kt +3 -2
- package/templates/android/LearnTemplate/app/src/main/kotlin/com/appship/learn/features/progress/ProgressDashboardScreen.kt +3 -2
- package/templates/android/LearnTemplate/app/src/main/kotlin/com/appship/learn/mock/MockDataProvider.kt +41 -11
- package/templates/android/MapTemplate/app/src/main/kotlin/com/appship/map/data/DataSourceResolver.kt +11 -6
- package/templates/android/MapTemplate/app/src/main/kotlin/com/appship/map/di/AppModule.kt +11 -2
- package/templates/android/MapTemplate/app/src/main/kotlin/com/appship/map/features/favorites/FavoritesViewModel.kt +4 -4
- package/templates/android/MapTemplate/app/src/main/kotlin/com/appship/map/features/map/MapViewModel.kt +4 -4
- package/templates/android/MapTemplate/app/src/main/kotlin/com/appship/map/features/place/PlaceDetailViewModel.kt +5 -5
- package/templates/android/MapTemplate/app/src/main/kotlin/com/appship/map/features/place/PlaceListViewModel.kt +4 -4
- package/templates/android/MapTemplate/app/src/main/kotlin/com/appship/map/features/profile/ProfileViewModel.kt +5 -5
- package/templates/android/MapTemplate/app/src/main/kotlin/com/appship/map/features/route/RouteViewModel.kt +3 -3
- package/templates/android/MapTemplate/app/src/main/kotlin/com/appship/map/features/search/SearchViewModel.kt +3 -3
- package/templates/android/MapTemplate/app/src/main/kotlin/com/appship/map/features/settings/SettingsViewModel.kt +3 -3
- package/templates/android/MapTemplate/app/src/main/kotlin/com/appship/map/mock/MockDataProvider.kt +54 -41
- package/templates/android/MediaTemplate/app/src/main/kotlin/com/appship/media/AppConfig.kt +9 -0
- package/templates/android/MediaTemplate/app/src/main/kotlin/com/appship/media/features/browse/BrowseScreen.kt +2 -1
- package/templates/android/MediaTemplate/app/src/main/kotlin/com/appship/media/features/detail/DetailScreen.kt +3 -1
- package/templates/android/MediaTemplate/app/src/main/kotlin/com/appship/media/features/home/HomeScreen.kt +3 -2
- package/templates/android/MediaTemplate/app/src/main/kotlin/com/appship/media/mock/MockDataProvider.kt +63 -132
- package/templates/android/ReferenceTemplate/app/src/main/kotlin/com/appship/reference/AppConfig.kt +9 -0
- package/templates/android/ShopTemplate/app/src/main/kotlin/com/appship/shop/features/home/HomeViewModel.kt +2 -1
- package/templates/android/ShopTemplate/app/src/main/kotlin/com/appship/shop/features/products/ProductViewModels.kt +12 -7
- package/templates/android/ShopTemplate/app/src/main/kotlin/com/appship/shop/mock/MockDataProvider.kt +3 -3
- package/templates/android/SocialTemplate/app/src/main/kotlin/com/appship/social/data/DataRepository.kt +0 -1
- package/templates/android/SocialTemplate/app/src/main/kotlin/com/appship/social/features/createpost/CreatePostScreen.kt +3 -2
- package/templates/android/SocialTemplate/app/src/main/kotlin/com/appship/social/features/feed/CommentsScreen.kt +4 -3
- package/templates/android/SocialTemplate/app/src/main/kotlin/com/appship/social/features/feed/FeedScreen.kt +3 -2
- package/templates/android/SocialTemplate/app/src/main/kotlin/com/appship/social/features/messages/MessagesScreen.kt +9 -8
- package/templates/android/SocialTemplate/app/src/main/kotlin/com/appship/social/features/notifications/NotificationsScreen.kt +3 -2
- package/templates/android/SocialTemplate/app/src/main/kotlin/com/appship/social/features/profile/ProfileScreen.kt +5 -4
- package/templates/android/SocialTemplate/app/src/main/kotlin/com/appship/social/features/search/SearchScreen.kt +3 -2
- package/templates/android/TaskTemplate/app/src/main/kotlin/com/appship/task/AppConfig.kt +9 -0
- package/templates/android/TaskTemplate/app/src/main/kotlin/com/appship/task/data/DataRepository.kt +38 -0
- package/templates/android/TaskTemplate/app/src/main/kotlin/com/appship/task/data/DataSourceResolver.kt +23 -0
- package/templates/android/TaskTemplate/app/src/main/kotlin/com/appship/task/features/calendar/CalendarScreen.kt +0 -1
- package/templates/android/TaskTemplate/app/src/main/kotlin/com/appship/task/features/inbox/InboxScreen.kt +4 -2
- package/templates/android/TaskTemplate/app/src/main/kotlin/com/appship/task/features/kanban/KanbanBoardScreen.kt +5 -3
- package/templates/android/TaskTemplate/app/src/main/kotlin/com/appship/task/features/projects/ProjectDetailScreen.kt +9 -5
- package/templates/android/TaskTemplate/app/src/main/kotlin/com/appship/task/features/projects/ProjectListScreen.kt +6 -4
- package/templates/android/TaskTemplate/app/src/main/kotlin/com/appship/task/features/search/SearchScreen.kt +1 -1
- package/templates/android/TaskTemplate/app/src/main/kotlin/com/appship/task/features/tasks/TaskDetailScreen.kt +0 -1
- package/templates/android/TaskTemplate/app/src/main/kotlin/com/appship/task/mock/MockDataProvider.kt +13 -12
- package/templates/android/TrackTemplate/app/src/main/kotlin/com/appship/track/AppConfig.kt +9 -0
- package/templates/android/TrackTemplate/app/src/main/kotlin/com/appship/track/data/DataRepository.kt +34 -0
- package/templates/android/TrackTemplate/app/src/main/kotlin/com/appship/track/data/DataSourceResolver.kt +23 -0
- package/templates/android/TrackTemplate/app/src/main/kotlin/com/appship/track/features/achievements/AchievementsViewModel.kt +4 -2
- package/templates/android/TrackTemplate/app/src/main/kotlin/com/appship/track/features/dashboard/TodayViewModel.kt +4 -2
- package/templates/android/TrackTemplate/app/src/main/kotlin/com/appship/track/features/habits/HabitDetailViewModel.kt +4 -2
- package/templates/android/TrackTemplate/app/src/main/kotlin/com/appship/track/features/habits/HabitsListViewModel.kt +4 -2
- package/templates/android/TrackTemplate/app/src/main/kotlin/com/appship/track/mock/MockDataProvider.kt +13 -11
- package/templates/ios/ChatTemplate/ChatTemplate/App/AppConfig.swift +9 -0
- package/templates/ios/ChatTemplate/ChatTemplate/Data/DataRepository.swift +43 -0
- package/templates/ios/ChatTemplate/ChatTemplate/Data/DataSourceResolver.swift +20 -0
- package/templates/ios/DashTemplate/DashTemplate/App/AppConfig.swift +9 -0
- package/templates/ios/DashTemplate/DashTemplate/Data/DataRepository.swift +53 -0
- package/templates/ios/DashTemplate/DashTemplate/MockData/MockDataProvider.swift +1 -1
- package/templates/ios/FamilyTemplate/FamilyTemplate/App/AppConfig.swift +9 -0
- package/templates/ios/FamilyTemplate/FamilyTemplate/App/FamilyTemplateApp.swift +4 -2
- package/templates/ios/FamilyTemplate/FamilyTemplate/MockData/MockDataProvider.swift +1 -1
- package/templates/ios/FinanceTemplate/FinanceTemplate/App/AppConfig.swift +9 -0
- package/templates/ios/FinanceTemplate/FinanceTemplate/Data/DataRepository.swift +75 -0
- package/templates/ios/FinanceTemplate/FinanceTemplate/Data/DataSourceResolver.swift +20 -0
- package/templates/ios/FinanceTemplate/FinanceTemplate/Features/Budgets/BudgetsView.swift +3 -1
- package/templates/ios/FinanceTemplate/FinanceTemplate/Features/Goals/GoalsView.swift +3 -1
- package/templates/ios/FinanceTemplate/FinanceTemplate/Features/Home/HomeView.swift +13 -6
- package/templates/ios/FinanceTemplate/FinanceTemplate/Features/Settings/SettingsView.swift +6 -2
- package/templates/ios/FinanceTemplate/FinanceTemplate/Features/Transactions/AddTransactionView.swift +4 -2
- package/templates/ios/FinanceTemplate/FinanceTemplate/Features/Transactions/TransactionsView.swift +3 -1
- package/templates/ios/FinanceTemplate/FinanceTemplate/MockData/MockDataProvider.swift +1 -1
- package/templates/ios/GameTemplate/GameTemplate/App/AppConfig.swift +9 -0
- package/templates/ios/GameTemplate/GameTemplate/Data/DataRepository.swift +30 -0
- package/templates/ios/GameTemplate/GameTemplate/Data/DataSourceResolver.swift +20 -0
- package/templates/ios/GameTemplate/GameTemplate/MockData/MockDataProvider.swift +1 -1
- package/templates/ios/HealthTemplate/HealthTemplate/App/AppConfig.swift +9 -0
- package/templates/ios/HealthTemplate/HealthTemplate/Data/DataRepository.swift +60 -0
- package/templates/ios/HealthTemplate/HealthTemplate/MockData/MockDataProvider.swift +1 -1
- package/templates/ios/LearnTemplate/LearnTemplate/App/AppConfig.swift +9 -0
- package/templates/ios/LearnTemplate/LearnTemplate/Features/Courses/CourseDetailView.swift +3 -2
- package/templates/ios/LearnTemplate/LearnTemplate/Features/Courses/CourseListView.swift +3 -2
- package/templates/ios/LearnTemplate/LearnTemplate/Features/Flashcards/FlashcardView.swift +2 -1
- package/templates/ios/LearnTemplate/LearnTemplate/Features/Leaderboard/LeaderboardView.swift +2 -1
- package/templates/ios/LearnTemplate/LearnTemplate/Features/Lessons/LessonPlayerView.swift +4 -2
- package/templates/ios/LearnTemplate/LearnTemplate/Features/Profile/ProfileView.swift +4 -2
- package/templates/ios/LearnTemplate/LearnTemplate/Features/Progress/ProgressDashboardView.swift +3 -2
- package/templates/ios/LearnTemplate/LearnTemplate/Features/Quiz/QuizView.swift +2 -1
- package/templates/ios/LearnTemplate/LearnTemplate/MockData/MockDataProvider.swift +1 -1
- package/templates/ios/MediaTemplate/MediaTemplate/App/AppConfig.swift +9 -0
- package/templates/ios/MediaTemplate/MediaTemplate/Data/DataRepository.swift +52 -0
- package/templates/ios/MediaTemplate/MediaTemplate/Data/DataSourceResolver.swift +20 -0
- package/templates/ios/MediaTemplate/MediaTemplate/MockData/MockDataProvider.swift +1 -1
- package/templates/ios/ReferenceTemplate/ReferenceTemplate/App/AppConfig.swift +9 -0
- package/templates/ios/ReferenceTemplate/ReferenceTemplate/Data/DataRepository.swift +28 -0
- package/templates/ios/ReferenceTemplate/ReferenceTemplate/Data/DataSourceResolver.swift +20 -0
- package/templates/ios/ReferenceTemplate/ReferenceTemplate/MockData/MockDataProvider.swift +1 -1
- package/templates/ios/TaskTemplate/TaskTemplate/App/AppConfig.swift +9 -0
- package/templates/ios/TaskTemplate/TaskTemplate/Data/DataRepository.swift +38 -0
- package/templates/ios/TaskTemplate/TaskTemplate/Data/DataSourceResolver.swift +20 -0
- package/templates/ios/TaskTemplate/TaskTemplate/Features/Calendar/CalendarView.swift +6 -2
- package/templates/ios/TaskTemplate/TaskTemplate/Features/Inbox/InboxView.swift +2 -1
- package/templates/ios/TaskTemplate/TaskTemplate/Features/Kanban/KanbanBoardView.swift +9 -3
- package/templates/ios/TaskTemplate/TaskTemplate/Features/Projects/ProjectDetailView.swift +3 -1
- package/templates/ios/TaskTemplate/TaskTemplate/Features/Projects/ProjectListView.swift +3 -1
- package/templates/ios/TaskTemplate/TaskTemplate/Features/Search/SearchView.swift +3 -1
- package/templates/ios/TaskTemplate/TaskTemplate/MockData/MockDataProvider.swift +1 -1
- package/templates/ios/TrackTemplate/TrackTemplate/App/AppConfig.swift +9 -0
- package/templates/ios/TrackTemplate/TrackTemplate/Data/DataRepository.swift +29 -0
- package/templates/ios/TrackTemplate/TrackTemplate/Data/DataSourceResolver.swift +20 -0
- package/templates/ios/TrackTemplate/TrackTemplate/MockData/MockDataProvider.swift +1 -1
- package/templates/ios/TrackTemplate/TrackTemplate/Services/HabitManager.swift +1 -1
|
@@ -11,12 +11,12 @@ import androidx.compose.ui.Modifier
|
|
|
11
11
|
import androidx.compose.ui.platform.testTag
|
|
12
12
|
import androidx.compose.ui.unit.dp
|
|
13
13
|
import com.appship.family.data.Chore
|
|
14
|
-
import com.appship.family.
|
|
14
|
+
import com.appship.family.data.DataSourceResolver
|
|
15
15
|
|
|
16
16
|
@OptIn(ExperimentalMaterial3Api::class)
|
|
17
17
|
@Composable
|
|
18
18
|
fun ChoreBoardScreen() {
|
|
19
|
-
val
|
|
19
|
+
val repository = remember { DataSourceResolver.repository }
|
|
20
20
|
val chores by dataProvider.chores.collectAsState()
|
|
21
21
|
val members by dataProvider.members.collectAsState()
|
|
22
22
|
var showingAddChore by remember { mutableStateOf(false) }
|
|
@@ -63,7 +63,7 @@ fun ChoreBoardScreen() {
|
|
|
63
63
|
AddChoreDialog(
|
|
64
64
|
onDismiss = { showingAddChore = false },
|
|
65
65
|
onSave = { chore ->
|
|
66
|
-
|
|
66
|
+
repository.createChore(chore)
|
|
67
67
|
showingAddChore = false
|
|
68
68
|
}
|
|
69
69
|
)
|
|
@@ -13,15 +13,15 @@ import androidx.compose.ui.Modifier
|
|
|
13
13
|
import androidx.compose.ui.platform.testTag
|
|
14
14
|
import androidx.compose.ui.unit.dp
|
|
15
15
|
import androidx.navigation.NavController
|
|
16
|
+
import com.appship.family.data.DataSourceResolver
|
|
16
17
|
import com.appship.family.data.FamilyMember
|
|
17
|
-
import com.appship.family.mock.MockDataProvider
|
|
18
18
|
import com.appship.family.features.members.MemberProfileScreen
|
|
19
19
|
|
|
20
20
|
@Composable
|
|
21
21
|
fun FamilyHubScreen(navController: NavController) {
|
|
22
|
-
val
|
|
23
|
-
val members by
|
|
24
|
-
val chores by
|
|
22
|
+
val repository = remember { DataSourceResolver.repository }
|
|
23
|
+
val members by repository.members.collectAsState()
|
|
24
|
+
val chores by repository.chores.collectAsState()
|
|
25
25
|
var selectedMember by remember { mutableStateOf<FamilyMember?>(null) }
|
|
26
26
|
|
|
27
27
|
Column(
|
|
@@ -11,14 +11,14 @@ import androidx.compose.runtime.*
|
|
|
11
11
|
import androidx.compose.ui.Modifier
|
|
12
12
|
import androidx.compose.ui.platform.testTag
|
|
13
13
|
import androidx.compose.ui.unit.dp
|
|
14
|
+
import com.appship.family.data.DataSourceResolver
|
|
14
15
|
import com.appship.family.data.Photo
|
|
15
|
-
import com.appship.family.mock.MockDataProvider
|
|
16
16
|
|
|
17
17
|
@OptIn(ExperimentalMaterial3Api::class)
|
|
18
18
|
@Composable
|
|
19
19
|
fun GalleryScreen() {
|
|
20
|
-
val
|
|
21
|
-
val photos by
|
|
20
|
+
val repository = remember { DataSourceResolver.repository }
|
|
21
|
+
val photos by repository.photos.collectAsState()
|
|
22
22
|
var showingAddPhoto by remember { mutableStateOf(false) }
|
|
23
23
|
|
|
24
24
|
Scaffold(
|
|
@@ -10,14 +10,14 @@ import androidx.compose.ui.Modifier
|
|
|
10
10
|
import androidx.compose.ui.platform.testTag
|
|
11
11
|
import androidx.compose.ui.unit.dp
|
|
12
12
|
import androidx.navigation.NavController
|
|
13
|
+
import com.appship.family.data.DataSourceResolver
|
|
13
14
|
import com.appship.family.data.FamilyMember
|
|
14
|
-
import com.appship.family.mock.MockDataProvider
|
|
15
15
|
|
|
16
16
|
@OptIn(ExperimentalMaterial3Api::class)
|
|
17
17
|
@Composable
|
|
18
18
|
fun MembersListScreen(navController: NavController) {
|
|
19
|
-
val
|
|
20
|
-
val members by
|
|
19
|
+
val repository = remember { DataSourceResolver.repository }
|
|
20
|
+
val members by repository.members.collectAsState()
|
|
21
21
|
var selectedMember by remember { mutableStateOf<FamilyMember?>(null) }
|
|
22
22
|
|
|
23
23
|
Scaffold(
|
|
@@ -68,8 +68,8 @@ fun MemberRow(member: FamilyMember, onClick: () -> Unit) {
|
|
|
68
68
|
|
|
69
69
|
@Composable
|
|
70
70
|
fun MemberProfileScreen(member: FamilyMember, onDismiss: () -> Unit) {
|
|
71
|
-
val
|
|
72
|
-
val chores =
|
|
71
|
+
val repository = remember { DataSourceResolver.repository }
|
|
72
|
+
val chores = repository.choresForMember(member.id)
|
|
73
73
|
|
|
74
74
|
AlertDialog(
|
|
75
75
|
onDismissRequest = onDismiss,
|
|
@@ -9,16 +9,16 @@ import androidx.compose.runtime.*
|
|
|
9
9
|
import androidx.compose.ui.Modifier
|
|
10
10
|
import androidx.compose.ui.platform.testTag
|
|
11
11
|
import androidx.compose.ui.unit.dp
|
|
12
|
+
import com.appship.family.data.DataSourceResolver
|
|
12
13
|
import com.appship.family.data.Reward
|
|
13
|
-
import com.appship.family.mock.MockDataProvider
|
|
14
14
|
|
|
15
15
|
@OptIn(ExperimentalMaterial3Api::class)
|
|
16
16
|
@Composable
|
|
17
17
|
fun RewardsScreen() {
|
|
18
|
-
val
|
|
19
|
-
val allRewards by
|
|
18
|
+
val repository = remember { DataSourceResolver.repository }
|
|
19
|
+
val allRewards by repository.rewards.collectAsState()
|
|
20
20
|
val rewards = allRewards.filter { !it.isRedeemed }
|
|
21
|
-
val members by
|
|
21
|
+
val members by repository.members.collectAsState()
|
|
22
22
|
val currentMember = members.firstOrNull()
|
|
23
23
|
|
|
24
24
|
Scaffold(
|
|
@@ -62,7 +62,7 @@ fun RewardsScreen() {
|
|
|
62
62
|
canAfford = currentMember?.points ?: 0 >= reward.pointsCost,
|
|
63
63
|
onRedeem = {
|
|
64
64
|
currentMember?.let {
|
|
65
|
-
|
|
65
|
+
repository.redeemReward(reward, it.id)
|
|
66
66
|
}
|
|
67
67
|
},
|
|
68
68
|
modifier = Modifier.testTag("reward_${index}_card")
|
|
@@ -9,12 +9,12 @@ import androidx.compose.ui.Modifier
|
|
|
9
9
|
import androidx.compose.ui.unit.dp
|
|
10
10
|
import androidx.navigation.NavController
|
|
11
11
|
import com.appship.family.AppConfig
|
|
12
|
-
import com.appship.family.
|
|
12
|
+
import com.appship.family.data.DataSourceResolver
|
|
13
13
|
|
|
14
14
|
@OptIn(ExperimentalMaterial3Api::class)
|
|
15
15
|
@Composable
|
|
16
16
|
fun SettingsScreen(navController: NavController) {
|
|
17
|
-
val
|
|
17
|
+
val repository = remember { DataSourceResolver.repository }
|
|
18
18
|
var isChildMode by remember { mutableStateOf(false) }
|
|
19
19
|
var showingResetAlert by remember { mutableStateOf(false) }
|
|
20
20
|
|
|
@@ -121,7 +121,7 @@ fun SettingsScreen(navController: NavController) {
|
|
|
121
121
|
confirmButton = {
|
|
122
122
|
TextButton(
|
|
123
123
|
onClick = {
|
|
124
|
-
|
|
124
|
+
repository.reset()
|
|
125
125
|
showingResetAlert = false
|
|
126
126
|
}
|
|
127
127
|
) {
|
|
@@ -1,20 +1,17 @@
|
|
|
1
1
|
package com.appship.family.mock
|
|
2
2
|
|
|
3
3
|
import com.appship.family.data.*
|
|
4
|
+
import com.appship.family.data.DataRepository
|
|
4
5
|
import kotlinx.coroutines.flow.MutableStateFlow
|
|
5
6
|
import kotlinx.coroutines.flow.StateFlow
|
|
6
7
|
import kotlinx.coroutines.flow.asStateFlow
|
|
7
8
|
import java.util.*
|
|
8
9
|
|
|
9
10
|
// CUSTOMIZE:API - Replace mock data with real data source
|
|
10
|
-
|
|
11
|
-
companion object {
|
|
12
|
-
val shared = MockDataProvider()
|
|
13
|
-
}
|
|
14
|
-
|
|
11
|
+
object MockDataProvider : DataRepository {
|
|
15
12
|
// MARK: - State Flows
|
|
16
13
|
private val _members = MutableStateFlow<List<FamilyMember>>(emptyList())
|
|
17
|
-
val members: StateFlow<List<FamilyMember>> = _members.asStateFlow()
|
|
14
|
+
override val members: StateFlow<List<FamilyMember>> = _members.asStateFlow()
|
|
18
15
|
|
|
19
16
|
private val _chores = MutableStateFlow<List<Chore>>(emptyList())
|
|
20
17
|
val chores: StateFlow<List<Chore>> = _chores.asStateFlow()
|
|
@@ -53,32 +50,32 @@ class MockDataProvider {
|
|
|
53
50
|
_members.value = _members.value + member
|
|
54
51
|
}
|
|
55
52
|
|
|
56
|
-
fun updateMember(member: FamilyMember) {
|
|
53
|
+
override fun updateMember(member: FamilyMember) {
|
|
57
54
|
_members.value = _members.value.map { if (it.id == member.id) member else it }
|
|
58
55
|
}
|
|
59
56
|
|
|
60
|
-
fun deleteMember(member: FamilyMember) {
|
|
57
|
+
override fun deleteMember(member: FamilyMember) {
|
|
61
58
|
_members.value = _members.value.filter { it.id != member.id }
|
|
62
59
|
}
|
|
63
60
|
|
|
64
|
-
fun memberById(id: String): FamilyMember? {
|
|
61
|
+
override fun memberById(id: String): FamilyMember? {
|
|
65
62
|
return _members.value.firstOrNull { it.id == id }
|
|
66
63
|
}
|
|
67
64
|
|
|
68
65
|
// MARK: - CRUD Operations - Chores
|
|
69
|
-
fun createChore(chore: Chore) {
|
|
66
|
+
override fun createChore(chore: Chore) {
|
|
70
67
|
_chores.value = _chores.value + chore
|
|
71
68
|
}
|
|
72
69
|
|
|
73
|
-
fun updateChore(chore: Chore) {
|
|
70
|
+
override fun updateChore(chore: Chore) {
|
|
74
71
|
_chores.value = _chores.value.map { if (it.id == chore.id) chore else it }
|
|
75
72
|
}
|
|
76
73
|
|
|
77
|
-
fun deleteChore(chore: Chore) {
|
|
74
|
+
override fun deleteChore(chore: Chore) {
|
|
78
75
|
_chores.value = _chores.value.filter { it.id != chore.id }
|
|
79
76
|
}
|
|
80
77
|
|
|
81
|
-
fun completeChore(chore: Chore, memberId: String) {
|
|
78
|
+
override fun completeChore(chore: Chore, memberId: String) {
|
|
82
79
|
val updated = chore.copy(
|
|
83
80
|
isCompleted = true,
|
|
84
81
|
completedAt = Date(),
|
|
@@ -92,28 +89,28 @@ class MockDataProvider {
|
|
|
92
89
|
}
|
|
93
90
|
}
|
|
94
91
|
|
|
95
|
-
fun choresForMember(memberId: String): List<Chore> {
|
|
92
|
+
override fun choresForMember(memberId: String): List<Chore> {
|
|
96
93
|
return _chores.value.filter { it.assignedTo == memberId }
|
|
97
94
|
}
|
|
98
95
|
|
|
99
|
-
fun pendingChores(): List<Chore> {
|
|
96
|
+
override fun pendingChores(): List<Chore> {
|
|
100
97
|
return _chores.value.filter { !it.isCompleted }
|
|
101
98
|
}
|
|
102
99
|
|
|
103
100
|
// MARK: - CRUD Operations - Rewards
|
|
104
|
-
fun createReward(reward: Reward) {
|
|
101
|
+
override fun createReward(reward: Reward) {
|
|
105
102
|
_rewards.value = _rewards.value + reward
|
|
106
103
|
}
|
|
107
104
|
|
|
108
|
-
fun updateReward(reward: Reward) {
|
|
105
|
+
override fun updateReward(reward: Reward) {
|
|
109
106
|
_rewards.value = _rewards.value.map { if (it.id == reward.id) reward else it }
|
|
110
107
|
}
|
|
111
108
|
|
|
112
|
-
fun deleteReward(reward: Reward) {
|
|
109
|
+
override fun deleteReward(reward: Reward) {
|
|
113
110
|
_rewards.value = _rewards.value.filter { it.id != reward.id }
|
|
114
111
|
}
|
|
115
112
|
|
|
116
|
-
fun redeemReward(reward: Reward, memberId: String): Boolean {
|
|
113
|
+
override fun redeemReward(reward: Reward, memberId: String): Boolean {
|
|
117
114
|
val member = memberById(memberId) ?: return false
|
|
118
115
|
if (member.points < reward.pointsCost || reward.isRedeemed) return false
|
|
119
116
|
|
|
@@ -128,24 +125,24 @@ class MockDataProvider {
|
|
|
128
125
|
return true
|
|
129
126
|
}
|
|
130
127
|
|
|
131
|
-
fun availableRewards(): List<Reward> {
|
|
128
|
+
override fun availableRewards(): List<Reward> {
|
|
132
129
|
return _rewards.value.filter { !it.isRedeemed }
|
|
133
130
|
}
|
|
134
131
|
|
|
135
132
|
// MARK: - CRUD Operations - Calendar Events
|
|
136
|
-
fun createEvent(event: CalendarEvent) {
|
|
133
|
+
override fun createEvent(event: CalendarEvent) {
|
|
137
134
|
_calendarEvents.value = _calendarEvents.value + event
|
|
138
135
|
}
|
|
139
136
|
|
|
140
|
-
fun updateEvent(event: CalendarEvent) {
|
|
137
|
+
override fun updateEvent(event: CalendarEvent) {
|
|
141
138
|
_calendarEvents.value = _calendarEvents.value.map { if (it.id == event.id) event else it }
|
|
142
139
|
}
|
|
143
140
|
|
|
144
|
-
fun deleteEvent(event: CalendarEvent) {
|
|
141
|
+
override fun deleteEvent(event: CalendarEvent) {
|
|
145
142
|
_calendarEvents.value = _calendarEvents.value.filter { it.id != event.id }
|
|
146
143
|
}
|
|
147
144
|
|
|
148
|
-
fun eventsForDate(date: Date): List<CalendarEvent> {
|
|
145
|
+
override fun eventsForDate(date: Date): List<CalendarEvent> {
|
|
149
146
|
val calendar = Calendar.getInstance()
|
|
150
147
|
calendar.time = date
|
|
151
148
|
val dayOfYear = calendar.get(Calendar.DAY_OF_YEAR)
|
|
@@ -160,37 +157,37 @@ class MockDataProvider {
|
|
|
160
157
|
}
|
|
161
158
|
|
|
162
159
|
// MARK: - CRUD Operations - Milestones
|
|
163
|
-
fun createMilestone(milestone: Milestone) {
|
|
160
|
+
override fun createMilestone(milestone: Milestone) {
|
|
164
161
|
_milestones.value = _milestones.value + milestone
|
|
165
162
|
}
|
|
166
163
|
|
|
167
|
-
fun updateMilestone(milestone: Milestone) {
|
|
164
|
+
override fun updateMilestone(milestone: Milestone) {
|
|
168
165
|
_milestones.value = _milestones.value.map { if (it.id == milestone.id) milestone else it }
|
|
169
166
|
}
|
|
170
167
|
|
|
171
|
-
fun deleteMilestone(milestone: Milestone) {
|
|
168
|
+
override fun deleteMilestone(milestone: Milestone) {
|
|
172
169
|
_milestones.value = _milestones.value.filter { it.id != milestone.id }
|
|
173
170
|
}
|
|
174
171
|
|
|
175
|
-
fun milestonesForMember(memberId: String): List<Milestone> {
|
|
172
|
+
override fun milestonesForMember(memberId: String): List<Milestone> {
|
|
176
173
|
return _milestones.value.filter { it.memberId == memberId }
|
|
177
174
|
}
|
|
178
175
|
|
|
179
176
|
// MARK: - CRUD Operations - Photos
|
|
180
|
-
fun createPhoto(photo: Photo) {
|
|
177
|
+
override fun createPhoto(photo: Photo) {
|
|
181
178
|
_photos.value = _photos.value + photo
|
|
182
179
|
}
|
|
183
180
|
|
|
184
|
-
fun updatePhoto(photo: Photo) {
|
|
181
|
+
override fun updatePhoto(photo: Photo) {
|
|
185
182
|
_photos.value = _photos.value.map { if (it.id == photo.id) photo else it }
|
|
186
183
|
}
|
|
187
184
|
|
|
188
|
-
fun deletePhoto(photo: Photo) {
|
|
185
|
+
override fun deletePhoto(photo: Photo) {
|
|
189
186
|
_photos.value = _photos.value.filter { it.id != photo.id }
|
|
190
187
|
}
|
|
191
188
|
|
|
192
189
|
// MARK: - Reset
|
|
193
|
-
fun reset() {
|
|
190
|
+
override fun reset() {
|
|
194
191
|
loadData()
|
|
195
192
|
}
|
|
196
193
|
|
package/templates/android/FinanceTemplate/app/src/main/kotlin/com/appship/finance/AppConfig.kt
CHANGED
|
@@ -41,6 +41,15 @@ object AppConfig {
|
|
|
41
41
|
const val TERMS_URL = "https://example.com/terms"
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
+
// CUSTOMIZE:DATASOURCE - Data source configuration
|
|
45
|
+
object DataSource {
|
|
46
|
+
enum class SourceType {
|
|
47
|
+
LOCAL_STORAGE, // Room — real local database (DEFAULT)
|
|
48
|
+
MOCK // In-memory seed data — for development/testing only
|
|
49
|
+
}
|
|
50
|
+
val active: SourceType = SourceType.MOCK
|
|
51
|
+
}
|
|
52
|
+
|
|
44
53
|
// CUSTOMIZE:THEME — colors are defined in core/theme/Theme.kt
|
|
45
54
|
object Theme {
|
|
46
55
|
val primaryColor get() = Primary
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
package com.appship.finance.data
|
|
2
|
+
|
|
3
|
+
import kotlinx.coroutines.flow.StateFlow
|
|
4
|
+
import java.util.Date
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Abstracts the data layer. Both MockDataProvider and LocalStorageProvider
|
|
8
|
+
* implement this, allowing the app to swap data sources via AppConfig.DataSource.active.
|
|
9
|
+
*
|
|
10
|
+
* Screens and ViewModels depend on this interface rather than on a concrete implementation.
|
|
11
|
+
* Use [DataSourceResolver.repository] to get the active provider.
|
|
12
|
+
*/
|
|
13
|
+
interface DataRepository {
|
|
14
|
+
// Observable state
|
|
15
|
+
val accounts: StateFlow<List<Account>>
|
|
16
|
+
val transactions: StateFlow<List<Transaction>>
|
|
17
|
+
val budgets: StateFlow<List<Budget>>
|
|
18
|
+
val goals: StateFlow<List<Goal>>
|
|
19
|
+
val categories: StateFlow<List<Category>>
|
|
20
|
+
val bills: StateFlow<List<Bill>>
|
|
21
|
+
val insights: StateFlow<List<SpendingInsight>>
|
|
22
|
+
|
|
23
|
+
// Computed properties
|
|
24
|
+
val totalBalance: Double
|
|
25
|
+
val monthlyIncome: Double
|
|
26
|
+
val monthlyExpenses: Double
|
|
27
|
+
|
|
28
|
+
// Account operations
|
|
29
|
+
fun getAccounts(): List<Account>
|
|
30
|
+
fun getAccount(id: String): Account?
|
|
31
|
+
|
|
32
|
+
// Transaction operations
|
|
33
|
+
fun getTransactions(): List<Transaction>
|
|
34
|
+
fun getTransactions(accountId: String): List<Transaction>
|
|
35
|
+
fun createTransaction(transaction: Transaction)
|
|
36
|
+
fun updateTransaction(transaction: Transaction)
|
|
37
|
+
fun deleteTransaction(id: String)
|
|
38
|
+
|
|
39
|
+
// Budget operations
|
|
40
|
+
fun getBudgets(): List<Budget>
|
|
41
|
+
fun getBudget(id: String): Budget?
|
|
42
|
+
fun createBudget(budget: Budget)
|
|
43
|
+
fun updateBudget(budget: Budget)
|
|
44
|
+
fun deleteBudget(id: String)
|
|
45
|
+
|
|
46
|
+
// Goal operations
|
|
47
|
+
fun getGoals(): List<Goal>
|
|
48
|
+
fun getGoal(id: String): Goal?
|
|
49
|
+
fun createGoal(goal: Goal)
|
|
50
|
+
fun updateGoal(goal: Goal)
|
|
51
|
+
fun deleteGoal(id: String)
|
|
52
|
+
|
|
53
|
+
// Category operations
|
|
54
|
+
fun getCategories(): List<Category>
|
|
55
|
+
fun getCategory(id: String): Category?
|
|
56
|
+
|
|
57
|
+
// Query operations
|
|
58
|
+
fun getTransactionsByCategory(categoryId: String): List<Transaction>
|
|
59
|
+
fun getTransactionsByDateRange(start: Date, end: Date): List<Transaction>
|
|
60
|
+
|
|
61
|
+
// Analytics operations
|
|
62
|
+
fun getBalance(): Double
|
|
63
|
+
fun getTotalIncome(): Double
|
|
64
|
+
fun getTotalExpenses(): Double
|
|
65
|
+
fun getBudgetProgress(budgetId: String): Double
|
|
66
|
+
fun getGoalProgress(goalId: String): Double
|
|
67
|
+
|
|
68
|
+
// Reset
|
|
69
|
+
fun reset()
|
|
70
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
package com.appship.finance.data
|
|
2
|
+
|
|
3
|
+
import com.appship.finance.AppConfig
|
|
4
|
+
import com.appship.finance.mock.MockDataProvider
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Resolves the active [DataRepository] implementation based on [AppConfig.DataSource.active].
|
|
8
|
+
* Screens use this to obtain the correct data source without knowing the concrete type.
|
|
9
|
+
*
|
|
10
|
+
* Usage:
|
|
11
|
+
* val repository = DataSourceResolver.repository
|
|
12
|
+
* val accounts by repository.accounts.collectAsState()
|
|
13
|
+
*/
|
|
14
|
+
object DataSourceResolver {
|
|
15
|
+
val repository: DataRepository
|
|
16
|
+
get() = when (AppConfig.DataSource.active) {
|
|
17
|
+
AppConfig.DataSource.SourceType.LOCAL_STORAGE -> {
|
|
18
|
+
// TODO: Return LocalStorageProvider once implemented
|
|
19
|
+
MockDataProvider
|
|
20
|
+
}
|
|
21
|
+
AppConfig.DataSource.SourceType.MOCK -> MockDataProvider
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -23,12 +23,13 @@ import androidx.compose.ui.unit.sp
|
|
|
23
23
|
import com.appship.finance.AppConfig
|
|
24
24
|
import com.appship.finance.data.Budget
|
|
25
25
|
import com.appship.finance.features.home.formatCurrency
|
|
26
|
-
import com.appship.finance.
|
|
26
|
+
import com.appship.finance.data.DataSourceResolver
|
|
27
27
|
|
|
28
28
|
@OptIn(ExperimentalMaterial3Api::class)
|
|
29
29
|
@Composable
|
|
30
30
|
fun BudgetsScreen() {
|
|
31
|
-
val
|
|
31
|
+
val repository = remember { DataSourceResolver.repository }
|
|
32
|
+
val budgets by repository.budgets.collectAsState()
|
|
32
33
|
val totalBudget = budgets.sumOf { it.limit }
|
|
33
34
|
val totalSpent = budgets.sumOf { it.spent }
|
|
34
35
|
|
|
@@ -25,12 +25,13 @@ import androidx.compose.ui.unit.sp
|
|
|
25
25
|
import com.appship.finance.AppConfig
|
|
26
26
|
import com.appship.finance.data.Goal
|
|
27
27
|
import com.appship.finance.features.home.formatCurrency
|
|
28
|
-
import com.appship.finance.
|
|
28
|
+
import com.appship.finance.data.DataSourceResolver
|
|
29
29
|
|
|
30
30
|
@OptIn(ExperimentalMaterial3Api::class)
|
|
31
31
|
@Composable
|
|
32
32
|
fun GoalsScreen(onGoalClick: (String) -> Unit) {
|
|
33
|
-
val
|
|
33
|
+
val repository = remember { DataSourceResolver.repository }
|
|
34
|
+
val goals by repository.goals.collectAsState()
|
|
34
35
|
val totalSaved = goals.sumOf { it.currentAmount }
|
|
35
36
|
val totalTarget = goals.sumOf { it.targetAmount }
|
|
36
37
|
|
|
@@ -220,7 +221,8 @@ fun GoalCard(goal: Goal, onClick: () -> Unit, testTag: String) {
|
|
|
220
221
|
@OptIn(ExperimentalMaterial3Api::class)
|
|
221
222
|
@Composable
|
|
222
223
|
fun GoalDetailScreen(goalId: String, onBack: () -> Unit) {
|
|
223
|
-
val
|
|
224
|
+
val repository = remember { DataSourceResolver.repository }
|
|
225
|
+
val goals by repository.goals.collectAsState()
|
|
224
226
|
val goal = goals.find { it.id == goalId } ?: return
|
|
225
227
|
var addAmount by remember { mutableStateOf("") }
|
|
226
228
|
|
|
@@ -30,7 +30,7 @@ import com.appship.finance.data.Account
|
|
|
30
30
|
import com.appship.finance.data.SpendingInsight
|
|
31
31
|
import com.appship.finance.data.Transaction
|
|
32
32
|
import com.appship.finance.data.TransactionType
|
|
33
|
-
import com.appship.finance.
|
|
33
|
+
import com.appship.finance.data.DataSourceResolver
|
|
34
34
|
import java.text.NumberFormat
|
|
35
35
|
import java.util.Locale
|
|
36
36
|
|
|
@@ -40,9 +40,10 @@ fun HomeScreen(
|
|
|
40
40
|
onAddTransaction: () -> Unit,
|
|
41
41
|
onViewAllTransactions: () -> Unit
|
|
42
42
|
) {
|
|
43
|
-
val
|
|
44
|
-
val
|
|
45
|
-
val
|
|
43
|
+
val repository = remember { DataSourceResolver.repository }
|
|
44
|
+
val accounts by repository.accounts.collectAsState()
|
|
45
|
+
val transactions by repository.transactions.collectAsState()
|
|
46
|
+
val insights by repository.insights.collectAsState()
|
|
46
47
|
|
|
47
48
|
Scaffold(
|
|
48
49
|
topBar = {
|
|
@@ -69,9 +70,9 @@ fun HomeScreen(
|
|
|
69
70
|
// Balance Card
|
|
70
71
|
item {
|
|
71
72
|
TotalBalanceCard(
|
|
72
|
-
balance =
|
|
73
|
-
income =
|
|
74
|
-
expenses =
|
|
73
|
+
balance = repository.totalBalance,
|
|
74
|
+
income = repository.monthlyIncome,
|
|
75
|
+
expenses = repository.monthlyExpenses
|
|
75
76
|
)
|
|
76
77
|
}
|
|
77
78
|
|
|
@@ -23,7 +23,6 @@ import com.appship.finance.AppConfig
|
|
|
23
23
|
import com.appship.finance.core.theme.*
|
|
24
24
|
import com.appship.finance.data.Bill
|
|
25
25
|
import com.appship.finance.features.home.formatCurrency
|
|
26
|
-
import com.appship.finance.mock.MockDataProvider
|
|
27
26
|
import java.time.format.DateTimeFormatter
|
|
28
27
|
|
|
29
28
|
@OptIn(ExperimentalMaterial3Api::class)
|
|
@@ -27,13 +27,14 @@ import com.appship.finance.data.Transaction
|
|
|
27
27
|
import com.appship.finance.data.TransactionType
|
|
28
28
|
import com.appship.finance.features.home.TransactionRow
|
|
29
29
|
import com.appship.finance.features.home.formatCurrency
|
|
30
|
-
import com.appship.finance.
|
|
30
|
+
import com.appship.finance.data.DataSourceResolver
|
|
31
31
|
import java.time.format.DateTimeFormatter
|
|
32
32
|
|
|
33
33
|
@OptIn(ExperimentalMaterial3Api::class)
|
|
34
34
|
@Composable
|
|
35
35
|
fun TransactionsScreen(onAddTransaction: () -> Unit) {
|
|
36
|
-
val
|
|
36
|
+
val repository = remember { DataSourceResolver.repository }
|
|
37
|
+
val transactionsFlow by repository.transactions.collectAsState()
|
|
37
38
|
val transactions = remember(transactionsFlow) { transactionsFlow.toMutableStateList() }
|
|
38
39
|
var searchText by remember { mutableStateOf("") }
|
|
39
40
|
var selectedFilter by remember { mutableStateOf<TransactionType?>(null) }
|
|
@@ -141,7 +142,11 @@ fun AddTransactionScreen(
|
|
|
141
142
|
var amount by remember { mutableStateOf("") }
|
|
142
143
|
var type by remember { mutableStateOf(TransactionType.EXPENSE) }
|
|
143
144
|
var selectedCategory by remember { mutableStateOf(AppConfig.expenseCategories[0]) }
|
|
144
|
-
|
|
145
|
+
val repository = remember { DataSourceResolver.repository }
|
|
146
|
+
val accounts by repository.accounts.collectAsState()
|
|
147
|
+
var selectedAccount by remember(accounts) {
|
|
148
|
+
mutableStateOf(accounts.firstOrNull() ?: throw IllegalStateException("No accounts available"))
|
|
149
|
+
}
|
|
145
150
|
var notes by remember { mutableStateOf("") }
|
|
146
151
|
|
|
147
152
|
val categories = if (type == TransactionType.EXPENSE) AppConfig.expenseCategories else AppConfig.incomeCategories
|
|
@@ -242,7 +247,7 @@ fun AddTransactionScreen(
|
|
|
242
247
|
// Account
|
|
243
248
|
Text("Account", fontWeight = FontWeight.Medium)
|
|
244
249
|
LazyRow(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
|
|
245
|
-
itemsIndexed(
|
|
250
|
+
itemsIndexed(accounts) { index, account ->
|
|
246
251
|
FilterChip(
|
|
247
252
|
selected = selectedAccount.id == account.id,
|
|
248
253
|
onClick = { selectedAccount = account },
|