Content is user-generated and unverified.
// MainActivity.kt package com.paynesland.fitness import android.Manifest import android.content.pm.PackageManager import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.activity.result.contract.ActivityResultContracts import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.* import androidx.compose.material3.* import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.core.content.ContextCompat import com.paynesland.fitness.ui.theme.PaynesLandFitnessTheme class MainActivity : ComponentActivity() { private val requestPermissionLauncher = registerForActivityResult( ActivityResultContracts.RequestMultiplePermissions() ) { permissions -> // Handle permission results } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // Request necessary permissions requestPermissions() setContent { PaynesLandFitnessTheme { FitnessApp() } } } private fun requestPermissions() { val permissions = arrayOf( Manifest.permission.CAMERA, Manifest.permission.BLUETOOTH, Manifest.permission.BLUETOOTH_ADMIN, Manifest.permission.RECORD_AUDIO ) val permissionsToRequest = permissions.filter { ContextCompat.checkSelfPermission(this, it) != PackageManager.PERMISSION_GRANTED } if (permissionsToRequest.isNotEmpty()) { requestPermissionLauncher.launch(permissionsToRequest.toTypedArray()) } } } @OptIn(ExperimentalMaterial3Api::class) @Composable fun FitnessApp() { var selectedDay by remember { mutableStateOf(DayOfWeek.MONDAY) } var userProfile by remember { mutableStateOf(UserProfile()) } var showProfile by remember { mutableStateOf(false) } Column( modifier = Modifier .fillMaxSize() .padding(16.dp) ) { // Header Card( modifier = Modifier.fillMaxWidth(), colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.primary) ) { Row( modifier = Modifier .fillMaxWidth() .padding(16.dp), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically ) { Column { Text( text = "PaynesLand Fitness", fontSize = 24.sp, fontWeight = FontWeight.Bold, color = Color.White ) Text( text = "Your Personal Trainer", fontSize = 14.sp, color = Color.White.copy(alpha = 0.8f) ) } IconButton(onClick = { showProfile = true }) { Icon( imageVector = Icons.Default.Person, contentDescription = "Profile", tint = Color.White ) } } } Spacer(modifier = Modifier.height(16.dp)) // Day Selection DaySelector( selectedDay = selectedDay, onDaySelected = { selectedDay = it } ) Spacer(modifier = Modifier.height(16.dp)) // Main Content DayContent(day = selectedDay, userProfile = userProfile) // Profile Dialog if (showProfile) { ProfileDialog( userProfile = userProfile, onProfileUpdate = { userProfile = it }, onDismiss = { showProfile = false } ) } } } @Composable fun DaySelector(selectedDay: DayOfWeek, onDaySelected: (DayOfWeek) -> Unit) { LazyColumn { items(DayOfWeek.values()) { day -> Card( modifier = Modifier .fillMaxWidth() .padding(vertical = 4.dp), colors = CardDefaults.cardColors( containerColor = if (selectedDay == day) MaterialTheme.colorScheme.primaryContainer else MaterialTheme.colorScheme.surface ), onClick = { onDaySelected(day) } ) { Row( modifier = Modifier .fillMaxWidth() .padding(16.dp), verticalAlignment = Alignment.CenterVertically ) { Icon( imageVector = day.icon, contentDescription = day.displayName, tint = if (selectedDay == day) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.onSurface ) Spacer(modifier = Modifier.width(12.dp)) Text( text = day.displayName, fontWeight = if (selectedDay == day) FontWeight.Bold else FontWeight.Normal ) } } } } } @Composable fun DayContent(day: DayOfWeek, userProfile: UserProfile) { var currentExercise by remember { mutableStateOf<Exercise?>(null) } var currentMeal by remember { mutableStateOf<Meal?>(null) } Column { Text( text = "${day.displayName} Workout & Nutrition", fontSize = 20.sp, fontWeight = FontWeight.Bold, modifier = Modifier.padding(bottom = 16.dp) ) // Exercise Section Card( modifier = Modifier.fillMaxWidth(), colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.secondaryContainer) ) { Column(modifier = Modifier.padding(16.dp)) { Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically ) { Text( text = "Today's Exercise", fontSize = 18.sp, fontWeight = FontWeight.SemiBold ) Button( onClick = { currentExercise = ExerciseGenerator.getRandomExercise(userProfile.fitnessLevel) } ) { Icon(Icons.Default.Refresh, contentDescription = "Generate") Spacer(modifier = Modifier.width(8.dp)) Text("Generate") } } Spacer(modifier = Modifier.height(12.dp)) currentExercise?.let { exercise -> ExerciseCard(exercise = exercise) } ?: Text( text = "Tap 'Generate' to get your workout!", color = MaterialTheme.colorScheme.onSecondaryContainer.copy(alpha = 0.7f) ) } } Spacer(modifier = Modifier.height(16.dp)) // Meal Section Card( modifier = Modifier.fillMaxWidth(), colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.tertiaryContainer) ) { Column(modifier = Modifier.padding(16.dp)) { Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically ) { Text( text = "Meal Suggestion", fontSize = 18.sp, fontWeight = FontWeight.SemiBold ) Button( onClick = { currentMeal = MealGenerator.getRandomMeal(userProfile.dietaryPreference) } ) { Icon(Icons.Default.Restaurant, contentDescription = "Generate") Spacer(modifier = Modifier.width(8.dp)) Text("Generate") } } Spacer(modifier = Modifier.height(12.dp)) currentMeal?.let { meal -> MealCard(meal = meal) } ?: Text( text = "Tap 'Generate' to get meal ideas!", color = MaterialTheme.colorScheme.onTertiaryContainer.copy(alpha = 0.7f) ) } } } } @Composable fun ExerciseCard(exercise: Exercise) { Card( modifier = Modifier.fillMaxWidth(), colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.surface) ) { Column(modifier = Modifier.padding(16.dp)) { Row(verticalAlignment = Alignment.CenterVertically) { Icon( imageVector = Icons.Default.FitnessCenter, contentDescription = "Exercise", tint = MaterialTheme.colorScheme.primary ) Spacer(modifier = Modifier.width(8.dp)) Text( text = exercise.name, fontSize = 16.sp, fontWeight = FontWeight.Bold ) } Spacer(modifier = Modifier.height(8.dp)) Text( text = "Duration: ${exercise.duration}", color = MaterialTheme.colorScheme.primary ) Spacer(modifier = Modifier.height(8.dp)) Text( text = exercise.instructions, fontSize = 14.sp, lineHeight = 20.sp ) } } } @Composable fun MealCard(meal: Meal) { Card( modifier = Modifier.fillMaxWidth(), colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.surface) ) { Column(modifier = Modifier.padding(16.dp)) { Row(verticalAlignment = Alignment.CenterVertically) { Icon( imageVector = Icons.Default.Restaurant, contentDescription = "Meal", tint = MaterialTheme.colorScheme.primary ) Spacer(modifier = Modifier.width(8.dp)) Text( text = meal.name, fontSize = 16.sp, fontWeight = FontWeight.Bold ) } Spacer(modifier = Modifier.height(8.dp)) Text( text = "Calories: ${meal.calories} | Prep: ${meal.prepTime}", color = MaterialTheme.colorScheme.primary ) Spacer(modifier = Modifier.height(8.dp)) Text( text = "Ingredients:", fontWeight = FontWeight.SemiBold ) Text( text = meal.ingredients.joinToString(", "), fontSize = 14.sp ) Spacer(modifier = Modifier.height(8.dp)) Text( text = "Instructions:", fontWeight = FontWeight.SemiBold ) Text( text = meal.instructions, fontSize = 14.sp, lineHeight = 20.sp ) } } } @Composable fun ProfileDialog( userProfile: UserProfile, onProfileUpdate: (UserProfile) -> Unit, onDismiss: () -> Unit ) { var name by remember { mutableStateOf(userProfile.name) } var age by remember { mutableStateOf(userProfile.age.toString()) } var weight by remember { mutableStateOf(userProfile.weight.toString()) } var height by remember { mutableStateOf(userProfile.height.toString()) } var fitnessLevel by remember { mutableStateOf(userProfile.fitnessLevel) } var dietaryPreference by remember { mutableStateOf(userProfile.dietaryPreference) } AlertDialog( onDismissRequest = onDismiss, title = { Text("Fitness Profile") }, text = { Column { OutlinedTextField( value = name, onValueChange = { name = it }, label = { Text("Name") }, modifier = Modifier.fillMaxWidth() ) Spacer(modifier = Modifier.height(8.dp)) OutlinedTextField( value = age, onValueChange = { age = it }, label = { Text("Age") }, modifier = Modifier.fillMaxWidth() ) Spacer(modifier = Modifier.height(8.dp)) OutlinedTextField( value = weight, onValueChange = { weight = it }, label = { Text("Weight (lbs)") }, modifier = Modifier.fillMaxWidth() ) Spacer(modifier = Modifier.height(8.dp)) OutlinedTextField( value = height, onValueChange = { height = it }, label = { Text("Height (inches)") }, modifier = Modifier.fillMaxWidth() ) } }, confirmButton = { TextButton( onClick = { onProfileUpdate( UserProfile( name = name, age = age.toIntOrNull() ?: 25, weight = weight.toFloatOrNull() ?: 150f, height = height.toFloatOrNull() ?: 68f, fitnessLevel = fitnessLevel, dietaryPreference = dietaryPreference ) ) onDismiss() } ) { Text("Save") } }, dismissButton = { TextButton(onClick = onDismiss) { Text("Cancel") } } ) } // Data Classes data class UserProfile( val name: String = "Fitness Enthusiast", val age: Int = 25, val weight: Float = 150f, val height: Float = 68f, val fitnessLevel: FitnessLevel = FitnessLevel.INTERMEDIATE, val dietaryPreference: DietaryPreference = DietaryPreference.BALANCED ) enum class FitnessLevel { BEGINNER, INTERMEDIATE, ADVANCED } enum class DietaryPreference { BALANCED, VEGETARIAN, VEGAN, KETO, PALEO } enum class DayOfWeek(val displayName: String, val icon: ImageVector) { MONDAY("Monday", Icons.Default.DirectionsRun), TUESDAY("Tuesday", Icons.Default.FitnessCenter), WEDNESDAY("Wednesday", Icons.Default.Pool), THURSDAY("Thursday", Icons.Default.SportsGymnastics), FRIDAY("Friday", Icons.Default.Sports), SATURDAY("Saturday", Icons.Default.Hiking), SUNDAY("Sunday", Icons.Default.SelfImprovement) } data class Exercise( val name: String, val duration: String, val instructions: String, val difficulty: FitnessLevel ) data class Meal( val name: String, val calories: Int, val prepTime: String, val ingredients: List<String>, val instructions: String, val dietaryType: DietaryPreference ) // Exercise Generator object ExerciseGenerator { private val exercises = listOf( Exercise( "Push-ups", "3 sets of 10-15 reps", "Start in plank position. Lower your body until chest nearly touches the floor. Push back up to starting position. Keep your core tight throughout the movement.", FitnessLevel.BEGINNER ), Exercise( "Burpees", "3 sets of 8-12 reps", "Start standing. Drop into squat, place hands on floor, jump feet back into plank. Do a push-up, jump feet forward, then jump up with arms overhead.", FitnessLevel.INTERMEDIATE ), Exercise( "Mountain Climbers", "3 sets of 30 seconds", "Start in plank position. Alternate bringing knees to chest rapidly while maintaining plank form. Keep hips level and core engaged.", FitnessLevel.INTERMEDIATE ), Exercise( "Squats", "3 sets of 15-20 reps", "Stand with feet shoulder-width apart. Lower your body as if sitting back into a chair. Keep chest up, knees behind toes. Return to starting position.", FitnessLevel.BEGINNER ), Exercise( "Plank", "3 sets of 30-60 seconds", "Hold a push-up position with forearms on ground. Keep body straight from head to heels. Engage core and breathe steadily.", FitnessLevel.BEGINNER ), Exercise( "High-Intensity Interval Training", "20 minutes", "Alternate between 30 seconds high-intensity exercise and 30 seconds rest. Include jumping jacks, burpees, mountain climbers, and squat jumps.", FitnessLevel.ADVANCED ), Exercise( "Lunges", "3 sets of 12 per leg", "Step forward with one leg, lowering hips until both knees are bent at 90 degrees. Push back to starting position. Alternate legs.", FitnessLevel.INTERMEDIATE ), Exercise( "Jumping Jacks", "3 sets of 20-30 reps", "Start with feet together, arms at sides. Jump while spreading legs shoulder-width apart and raising arms overhead. Jump back to starting position.", FitnessLevel.BEGINNER ) ) fun getRandomExercise(fitnessLevel: FitnessLevel): Exercise { val filteredExercises = exercises.filter { it.difficulty <= fitnessLevel } return filteredExercises.random() } } // Meal Generator object MealGenerator { private val meals = listOf( Meal( "Grilled Chicken Salad", 450, "15 minutes", listOf("Chicken breast", "Mixed greens", "Cherry tomatoes", "Cucumber", "Olive oil", "Lemon"), "Grill chicken breast and slice. Combine greens, tomatoes, cucumber in bowl. Top with chicken and dress with olive oil and lemon.", DietaryPreference.BALANCED ), Meal( "Protein Smoothie Bowl", 320, "10 minutes", listOf("Protein powder", "Banana", "Berries", "Almond milk", "Granola", "Chia seeds"), "Blend protein powder, half banana, and almond milk. Pour into bowl, top with berries, granola, chia seeds, and remaining banana slices.", DietaryPreference.BALANCED ), Meal( "Quinoa Buddha Bowl", 380, "25 minutes", listOf("Quinoa", "Sweet potato", "Chickpeas", "Avocado", "Spinach", "Tahini"), "Cook quinoa. Roast diced sweet potato and chickpeas. Combine with spinach and avocado. Drizzle with tahini dressing.", DietaryPreference.VEGETARIAN ), Meal( "Salmon with Vegetables", 520, "20 minutes", listOf("Salmon fillet", "Broccoli", "Bell peppers", "Brown rice", "Olive oil", "Garlic"), "Bake salmon with olive oil and garlic. Steam broccoli and sauté bell peppers. Serve over brown rice.", DietaryPreference.BALANCED ), Meal( "Vegan Lentil Curry", 340, "30 minutes", listOf("Red lentils", "Coconut milk", "Curry powder", "Onion", "Garlic", "Spinach"), "Sauté onion and garlic. Add lentils, coconut milk, and curry powder. Simmer 20 minutes. Stir in spinach until wilted.", DietaryPreference.VEGAN ), Meal( "Keto Avocado Egg Salad", 420, "10 minutes", listOf("Hard-boiled eggs", "Avocado", "Bacon", "Mayo", "Lettuce", "Cheese"), "Mash avocado and eggs together. Add crumbled bacon and mayo. Serve over lettuce with cheese.", DietaryPreference.KETO ), Meal( "Paleo Beef Stir-fry", 480, "15 minutes", listOf("Beef strips", "Mixed vegetables", "Coconut oil", "Ginger", "Garlic", "Coconut aminos"), "Heat coconut oil in pan. Stir-fry beef until browned. Add vegetables, ginger, garlic. Cook until tender. Season with coconut aminos.", DietaryPreference.PALEO ) ) fun getRandomMeal(dietaryPreference: DietaryPreference): Meal { val filteredMeals = meals.filter { it.dietaryType == dietaryPreference || it.dietaryType == DietaryPreference.BALANCED } return filteredMeals.random() } } // Theme // ui/theme/Theme.kt package com.paynesland.fitness.ui.theme import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.material3.* import androidx.compose.runtime.Composable import androidx.compose.ui.graphics.Color private val DarkColorScheme = darkColorScheme( primary = Color(0xFF6200EE), secondary = Color(0xFF03DAC6), tertiary = Color(0xFF3700B3), background = Color(0xFF121212), surface = Color(0xFF1E1E1E), onPrimary = Color.White, onSecondary = Color.Black, onTertiary = Color.White, onBackground = Color.White, onSurface = Color.White, ) private val LightColorScheme = lightColorScheme( primary = Color(0xFF6200EE), secondary = Color(0xFF03DAC6), tertiary = Color(0xFF3700B3), background = Color(0xFFFFFBFE), surface = Color(0xFFFFFBFE), onPrimary = Color.White, onSecondary = Color.Black, onTertiary = Color.White, onBackground = Color(0xFF1C1B1F), onSurface = Color(0xFF1C1B1F), ) @Composable fun PaynesLandFitnessTheme( darkTheme: Boolean = isSystemInDarkTheme(), content: @Composable () -> Unit ) { val colorScheme = when { darkTheme -> DarkColorScheme else -> LightColorScheme } MaterialTheme( colorScheme = colorScheme, typography = Typography(), content = content ) } // AndroidManifest.xml /* <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"> <uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.BLUETOOTH" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> <uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" /> <uses-permission android:name="android.permission.BLUETOOTH_SCAN" /> <application android:allowBackup="true" android:dataExtractionRules="@xml/data_extraction_rules" android:fullBackupContent="@xml/backup_rules" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.PaynesLandFitness" tools:targetApi="31"> <activity android:name=".MainActivity" android:exported="true" android:theme="@style/Theme.PaynesLandFitness"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest> */ // build.gradle (Module: app) /* plugins { id 'com.android.application' id 'org.jetbrains.kotlin.android' } android { namespace 'com.paynesland.fitness' compileSdk 34 defaultConfig { applicationId "com.paynesland.fitness" minSdk 24 targetSdk 34 versionCode 1 versionName "1.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" vectorDrawables { useSupportLibrary true } } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } kotlinOptions { jvmTarget = '1.8' } buildFeatures { compose true } composeOptions { kotlinCompilerExtensionVersion '1.5.4' } packagingOptions { resources { excludes += '/META-INF/{AL2.0,LGPL2.1}' } } } dependencies { implementation 'androidx.core:core-ktx:1.12.0' implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.7.0' implementation 'androidx.activity:activity-compose:1.8.2' implementation platform('androidx.compose:compose-bom:2023.10.01') implementation 'androidx.compose.ui:ui' implementation 'androidx.compose.ui:ui-graphics' implementation 'androidx.compose.ui:ui-tooling-preview' implementation 'androidx.compose.material3:material3' implementation 'androidx.compose.material:material-icons-extended' testImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test.ext:junit:1.1.5' androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' androidTestImplementation platform('androidx.compose:compose-bom:2023.10.01') androidTestImplementation 'androidx.compose.ui:ui-test-junit4' debugImplementation 'androidx.compose.ui:ui-tooling' debugImplementation 'androidx.compose.ui:ui-test-manifest' } */
Content is user-generated and unverified.
    PaynesLand Fitness - Complete Android App | Claude