New simplified navigation.
Info overlay api testing screen
This commit is contained in:
parent
feca34f892
commit
f8882c1dcc
|
|
@ -7,7 +7,10 @@ import androidx.lifecycle.viewModelScope
|
|||
import com.example.livingai_lg.api.AuthApiClient
|
||||
import com.example.livingai_lg.api.TokenManager
|
||||
import com.example.livingai_lg.api.UserDetails
|
||||
import com.example.livingai_lg.ui.navigation.NavEvent
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.asSharedFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
|
|
@ -343,4 +346,14 @@ class MainViewModel(context: Context) : ViewModel() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Used in navigation logic.
|
||||
private val _navEvents = MutableSharedFlow<NavEvent>()
|
||||
val navEvents = _navEvents.asSharedFlow()
|
||||
|
||||
fun emitNavEvent(event: NavEvent) {
|
||||
viewModelScope.launch {
|
||||
_navEvents.emit(event)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,7 +44,8 @@ fun BuyAnimalCard(
|
|||
onSavedChange: (Boolean) -> Unit,
|
||||
onProductClick: () -> Unit,
|
||||
onSellerClick:(sellerId: String)-> Unit,
|
||||
onBookmarkClick: () -> Unit
|
||||
onBookmarkClick: () -> Unit,
|
||||
onInfoClick: () -> Unit,
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
|
|
@ -164,7 +165,7 @@ fun BuyAnimalCard(
|
|||
Icon(
|
||||
imageVector = Icons.Outlined.Info,
|
||||
contentDescription = null,
|
||||
Modifier.padding(horizontal = 4.dp).size(16.dp).align(Alignment.CenterVertically),
|
||||
Modifier.padding(horizontal = 4.dp).size(16.dp).align(Alignment.CenterVertically).clickable{onInfoClick()},
|
||||
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,142 @@
|
|||
package com.example.livingai_lg.ui.components
|
||||
|
||||
import androidx.activity.compose.BackHandler
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.fadeIn
|
||||
import androidx.compose.animation.fadeOut
|
||||
import androidx.compose.animation.slideInVertically
|
||||
import androidx.compose.animation.slideOutVertically
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.icons.filled.Close
|
||||
import androidx.compose.material.icons.filled.Info
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.shadow
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.zIndex
|
||||
import com.example.livingai_lg.ui.screens.align
|
||||
import com.example.livingai_lg.ui.theme.AppTypography
|
||||
|
||||
@Composable
|
||||
fun InfoOverlay(
|
||||
visible: Boolean,
|
||||
title: String,
|
||||
text: String,
|
||||
onDismiss: () -> Unit
|
||||
) {
|
||||
BackHandler(enabled = visible) { onDismiss() }
|
||||
|
||||
Box(
|
||||
modifier = Modifier.fillMaxSize()
|
||||
) {
|
||||
// Dimmed background
|
||||
AnimatedVisibility(
|
||||
visible = visible,
|
||||
enter = fadeIn(),
|
||||
exit = fadeOut()
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.background(Color.Black.copy(alpha = 0.35f))
|
||||
.clickable(
|
||||
indication = null,
|
||||
interactionSource = remember { MutableInteractionSource() }
|
||||
) { onDismiss() }
|
||||
)
|
||||
}
|
||||
|
||||
// Sliding content
|
||||
AnimatedVisibility(
|
||||
visible = visible,
|
||||
enter = slideInVertically { it }, // from bottom
|
||||
exit = slideOutVertically { it },
|
||||
modifier = Modifier.align(Alignment.BottomCenter)
|
||||
) {
|
||||
InfoOverlayContent(
|
||||
title = title,
|
||||
text = text,
|
||||
onDismiss = onDismiss
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Composable
|
||||
private fun InfoOverlayContent(
|
||||
title: String,
|
||||
text: String,
|
||||
onDismiss: () -> Unit
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.background(
|
||||
Color.White,
|
||||
RoundedCornerShape(topStart = 16.dp, topEnd = 16.dp)
|
||||
)
|
||||
.padding(20.dp)
|
||||
) {
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp)
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.SpaceBetween
|
||||
) {
|
||||
Text(
|
||||
text = title,
|
||||
fontSize = AppTypography.Title,
|
||||
fontWeight = FontWeight.Medium,
|
||||
color = Color.Black
|
||||
)
|
||||
|
||||
Icon(
|
||||
imageVector = Icons.Default.Close,
|
||||
contentDescription = "Close",
|
||||
modifier = Modifier
|
||||
.size(24.dp)
|
||||
.clickable { onDismiss() }
|
||||
)
|
||||
}
|
||||
|
||||
Text(
|
||||
text = text,
|
||||
fontSize = AppTypography.Body,
|
||||
color = Color(0xFF4A5565),
|
||||
lineHeight = 20.sp
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.height(18.dp))
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -29,7 +29,7 @@ val sampleAnimals = listOf(
|
|||
name = "Rita",
|
||||
age = 45,
|
||||
breed = "Gir",
|
||||
breedInfo = "The 2nd best in India",
|
||||
breedInfo = "The best in India",
|
||||
location = "Punjab",
|
||||
distance = 12000,
|
||||
imageUrl = listOf("https://external-content.duckduckgo.com/iu/?u=http%3A%2F%2F4.bp.blogspot.com%2F_tecSnxaePMo%2FTLLVknW8dOI%2FAAAAAAAAACo%2F_kd1ZNBXU1o%2Fs1600%2FGIR%2CGujrat.jpg&f=1&nofb=1&ipt=da6ba1d040c396b64d3f08cc99998f66200dcd6c001e4a56def143ab3d1a87ea","https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Fcpimg.tistatic.com%2F4478702%2Fb%2F4%2Fgir-cow.jpg&f=1&nofb=1&ipt=19bf391461480585c786d01433d863a383c60048ac2ce063ce91f173e215205d"),
|
||||
|
|
|
|||
|
|
@ -1,24 +1,19 @@
|
|||
package com.example.livingai_lg.ui.navigation
|
||||
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import android.util.Log
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.navigation.NavController
|
||||
import androidx.navigation.NavHostController
|
||||
import androidx.navigation.NavType
|
||||
import androidx.navigation.compose.NavHost
|
||||
import androidx.navigation.compose.composable
|
||||
import androidx.navigation.compose.rememberNavController
|
||||
import androidx.navigation.NavType
|
||||
import androidx.navigation.navArgument
|
||||
import kotlinx.coroutines.delay
|
||||
import com.example.farmmarketplace.ui.screens.CallsScreen
|
||||
import com.example.farmmarketplace.ui.screens.ContactsScreen
|
||||
import com.example.livingai_lg.ui.AuthState
|
||||
import com.example.livingai_lg.ui.MainViewModel
|
||||
import com.example.livingai_lg.ui.screens.AccountsScreen
|
||||
import com.example.livingai_lg.ui.screens.AnimalProfileScreen
|
||||
import com.example.livingai_lg.ui.screens.BuyScreen
|
||||
import com.example.livingai_lg.ui.screens.ChooseServiceScreen
|
||||
|
|
@ -27,429 +22,471 @@ import com.example.livingai_lg.ui.screens.FilterScreen
|
|||
import com.example.livingai_lg.ui.screens.NewListingScreen
|
||||
import com.example.livingai_lg.ui.screens.PostSaleSurveyScreen
|
||||
import com.example.livingai_lg.ui.screens.SaleArchiveScreen
|
||||
import com.example.livingai_lg.ui.screens.SavedListingsScreen
|
||||
import com.example.livingai_lg.ui.screens.SellerProfileScreen
|
||||
import com.example.livingai_lg.ui.screens.SortScreen
|
||||
import com.example.livingai_lg.ui.screens.auth.LandingScreen
|
||||
import com.example.livingai_lg.ui.screens.auth.OtpScreen
|
||||
import com.example.livingai_lg.ui.screens.auth.SignInScreen
|
||||
import com.example.livingai_lg.ui.screens.auth.SignUpScreen
|
||||
import com.example.livingai_lg.ui.navigation.authNavGraph
|
||||
import com.example.livingai_lg.ui.navigation.mainNavGraph
|
||||
import com.example.livingai_lg.ui.screens.chat.ChatScreen
|
||||
import com.example.livingai_lg.ui.screens.chat.ChatsScreen
|
||||
import com.example.livingai_lg.ui.screens.testing.ApiTestScreen
|
||||
|
||||
object AppScreen {
|
||||
const val LANDING = "landing"
|
||||
const val SIGN_IN = "sign_in"
|
||||
const val SIGN_UP = "sign_up"
|
||||
|
||||
const val OTP = "otp"
|
||||
|
||||
const val CHOOSE_SERVICE = "choose_service"
|
||||
|
||||
const val CREATE_PROFILE = "create_profile"
|
||||
|
||||
const val BUY_ANIMALS = "buy_animals"
|
||||
const val ANIMAL_PROFILE = "animal_profile"
|
||||
|
||||
const val CREATE_ANIMAL_LISTING = "create_animal_listing"
|
||||
|
||||
const val BUY_ANIMALS_FILTERS = "buy_animals_filters"
|
||||
const val BUY_ANIMALS_SORT = "buy_animals_sort"
|
||||
|
||||
const val SELLER_PROFILE = "seller_profile"
|
||||
|
||||
const val SALE_ARCHIVE = "sale_archive"
|
||||
|
||||
const val POST_SALE_SURVEY = "post_sale_survey"
|
||||
|
||||
const val SAVED_LISTINGS = "saved_listings"
|
||||
|
||||
const val CONTACTS = "contacts"
|
||||
|
||||
const val CALLS = "calls"
|
||||
|
||||
const val CHAT = "chat"
|
||||
|
||||
const val CHATS = "chats"
|
||||
|
||||
const val ACCOUNTS = "accounts"
|
||||
|
||||
fun chats(contact: String) =
|
||||
"$CHAT/$contact"
|
||||
|
||||
fun otp(phone: String, name: String) =
|
||||
"$OTP/$phone/$name"
|
||||
|
||||
fun otpWithSignup(phone: String, name: String, state: String, district: String, village: String) =
|
||||
"$OTP/$phone/$name/$state/$district/$village"
|
||||
|
||||
fun createProfile(name: String) =
|
||||
"$CREATE_PROFILE/$name"
|
||||
|
||||
fun chooseService(profileId: String) =
|
||||
"$CHOOSE_SERVICE/$profileId"
|
||||
fun postSaleSurvey(animalId: String) =
|
||||
"$POST_SALE_SURVEY/$animalId"
|
||||
|
||||
fun animalProfile(animalId: String) =
|
||||
"$ANIMAL_PROFILE/$animalId"
|
||||
|
||||
fun sellerProfile(sellerId: String) =
|
||||
"$SELLER_PROFILE/$sellerId"
|
||||
|
||||
fun saleArchive(saleId: String) =
|
||||
"$SALE_ARCHIVE/$saleId"
|
||||
|
||||
}
|
||||
|
||||
object Graph {
|
||||
const val AUTH = "auth"
|
||||
const val MAIN = "main"
|
||||
|
||||
fun auth(route: String)=
|
||||
"$AUTH/$route"
|
||||
|
||||
fun main(route: String)=
|
||||
"$MAIN/$route"
|
||||
}
|
||||
@Composable
|
||||
fun AppNavigation(
|
||||
fun NavController.navigateIfAuthenticated(
|
||||
authState: AuthState,
|
||||
mainViewModel: com.example.livingai_lg.ui.MainViewModel
|
||||
targetRoute: String,
|
||||
fallbackRoute: String = AppScreen.LANDING
|
||||
) {
|
||||
val navController = rememberNavController()
|
||||
|
||||
// Determine start destination based on initial auth state
|
||||
// This prevents showing landing screen when user is already logged in
|
||||
val startDestination = remember(authState) {
|
||||
when (authState) {
|
||||
is AuthState.Authenticated -> Graph.MAIN
|
||||
is AuthState.Unauthenticated -> Graph.AUTH
|
||||
is AuthState.Unknown -> Graph.AUTH // Show landing while checking
|
||||
}
|
||||
}
|
||||
|
||||
NavHost(
|
||||
navController = navController,
|
||||
startDestination = startDestination
|
||||
) {
|
||||
authNavGraph(navController, mainViewModel)
|
||||
mainNavGraph(navController)
|
||||
}
|
||||
|
||||
// Handle navigation based on auth state changes
|
||||
LaunchedEffect(authState) {
|
||||
android.util.Log.d("AppNavigation", "LaunchedEffect triggered with authState: $authState")
|
||||
when (authState) {
|
||||
is AuthState.Authenticated -> {
|
||||
// User is authenticated, navigate to ChooseServiceScreen
|
||||
// Add a small delay to ensure NavHost graphs are fully built
|
||||
delay(100)
|
||||
|
||||
val currentRoute = navController.currentBackStackEntry?.destination?.route
|
||||
android.util.Log.d("AppNavigation", "Authenticated - currentRoute: $currentRoute")
|
||||
// Only navigate if we're not already in the MAIN graph or ChooseServiceScreen
|
||||
if (currentRoute?.startsWith(Graph.MAIN) != true &&
|
||||
currentRoute?.startsWith(AppScreen.CHOOSE_SERVICE) != true) {
|
||||
android.util.Log.d("AppNavigation", "Navigating to ChooseServiceScreen (default profileId: 1)")
|
||||
try {
|
||||
// Navigate directly to the start destination route of MAIN graph
|
||||
// This avoids the "Sequence is empty" error when navigating to Graph.MAIN
|
||||
navController.navigate(AppScreen.chooseService("1")) {
|
||||
// Clear back stack to prevent going back to auth screens
|
||||
popUpTo(Graph.AUTH) { inclusive = true }
|
||||
// Prevent multiple navigations
|
||||
if (authState is AuthState.Authenticated) {
|
||||
navigate(targetRoute) {
|
||||
launchSingleTop = true
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
android.util.Log.e("AppNavigation", "Navigation error: ${e.message}", e)
|
||||
// Fallback: try navigating to Graph.MAIN if direct route fails
|
||||
try {
|
||||
navController.navigate(Graph.MAIN) {
|
||||
popUpTo(Graph.AUTH) { inclusive = true }
|
||||
launchSingleTop = true
|
||||
}
|
||||
} catch (e2: Exception) {
|
||||
android.util.Log.e("AppNavigation", "Fallback navigation also failed: ${e2.message}", e2)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
android.util.Log.d("AppNavigation", "Already in MAIN graph or ChooseServiceScreen, skipping navigation")
|
||||
}
|
||||
}
|
||||
is AuthState.Unauthenticated -> {
|
||||
// User is not authenticated, ensure we're in auth graph (landing screen)
|
||||
val currentRoute = navController.currentBackStackEntry?.destination?.route
|
||||
if (currentRoute?.startsWith(Graph.MAIN) == true ||
|
||||
currentRoute?.startsWith(Graph.AUTH) != true) {
|
||||
navController.navigate(Graph.AUTH) {
|
||||
// Clear back stack to prevent going back to main screens
|
||||
navigate(fallbackRoute) {
|
||||
popUpTo(0) { inclusive = true }
|
||||
launchSingleTop = true
|
||||
}
|
||||
}
|
||||
}
|
||||
is AuthState.Unknown -> {
|
||||
// Still checking auth status
|
||||
// If we're on landing screen, stay there
|
||||
// If we're on main screen and checking, don't navigate yet
|
||||
// This prevents flickering during token validation
|
||||
}
|
||||
}
|
||||
}
|
||||
// MainNavGraph(navController)
|
||||
// AuthNavGraph(navController)
|
||||
// when (authState) {
|
||||
// is AuthState.Unauthenticated -> {AuthNavGraph()}
|
||||
// is AuthState.Authenticated -> {MainNavGraph()}
|
||||
// is AuthState.Unknown -> {
|
||||
// Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
|
||||
// CircularProgressIndicator()
|
||||
// }
|
||||
// }
|
||||
// AuthState.Loading -> SplashScreen()
|
||||
// }
|
||||
|
||||
// val onNavClick: (String) -> Unit = { route ->
|
||||
// val currentRoute =
|
||||
// navController.currentBackStackEntry?.destination?.route
|
||||
//
|
||||
// if (currentRoute != route) {
|
||||
// navController.navigate(route) {
|
||||
// launchSingleTop = true
|
||||
@Composable
|
||||
fun AppNavigation(
|
||||
authState: AuthState,
|
||||
mainViewModel: MainViewModel
|
||||
) {
|
||||
val navController = rememberNavController()
|
||||
|
||||
/* ---------------------------------------------------
|
||||
* Collect one-time navigation events (OTP, login, logout)
|
||||
* --------------------------------------------------- */
|
||||
LaunchedEffect(Unit) {
|
||||
mainViewModel.navEvents.collect { event ->
|
||||
when (event) {
|
||||
|
||||
is NavEvent.ToCreateProfile -> {
|
||||
navController.navigate(
|
||||
AppScreen.createProfile(event.name)
|
||||
) {
|
||||
popUpTo(0) { inclusive = true }
|
||||
launchSingleTop = true
|
||||
}
|
||||
}
|
||||
|
||||
is NavEvent.ToChooseService -> {
|
||||
navController.navigate(
|
||||
AppScreen.chooseService(event.profileId)
|
||||
) {
|
||||
popUpTo(0) { inclusive = true }
|
||||
launchSingleTop = true
|
||||
}
|
||||
}
|
||||
|
||||
NavEvent.ToLanding -> {
|
||||
navController.navigate(AppScreen.LANDING) {
|
||||
popUpTo(0) { inclusive = true }
|
||||
launchSingleTop = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val onNavClick: (String) -> Unit = { route ->
|
||||
val currentRoute =
|
||||
navController.currentBackStackEntry?.destination?.route
|
||||
Log.d("Current Route:"," $currentRoute $route")
|
||||
|
||||
if (currentRoute != route) {
|
||||
navController.navigate(route) {
|
||||
launchSingleTop = true
|
||||
//restoreState = true
|
||||
// popUpTo(navController.graph.startDestinationId) {
|
||||
// saveState = true
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------
|
||||
* Single NavHost
|
||||
* --------------------------------------------------- */
|
||||
NavHost(
|
||||
navController = navController,
|
||||
startDestination = AppScreen.LANDING
|
||||
) {
|
||||
|
||||
/* ---------------- AUTH ---------------- */
|
||||
|
||||
// NavHost(
|
||||
// navController = navController,
|
||||
// startDestination = AppScreen.LANDING,
|
||||
//
|
||||
// ) {
|
||||
// composable(AppScreen.LANDING) {
|
||||
// LandingScreen(
|
||||
// onSignUpClick = { navController.navigate(AppScreen.SIGN_UP) },
|
||||
// onSignInClick = { navController.navigate(AppScreen.SIGN_IN) },
|
||||
// onGuestClick = { navController.navigate(AppScreen.CREATE_PROFILE) }
|
||||
// )
|
||||
// }
|
||||
//
|
||||
// composable(AppScreen.SIGN_IN) {
|
||||
// SignInScreen(
|
||||
// onSignUpClick = { navController.navigate(AppScreen.SIGN_UP) },
|
||||
// onSignInClick = {
|
||||
// navController.navigate(AppScreen.OTP)
|
||||
// }
|
||||
// )
|
||||
// }
|
||||
//
|
||||
// composable(AppScreen.SIGN_UP) {
|
||||
// SignUpScreen(
|
||||
// onSignUpClick = {
|
||||
// navController.navigate(AppScreen.OTP)
|
||||
// },
|
||||
// onSignInClick = {
|
||||
// navController.navigate(AppScreen.SIGN_IN) {
|
||||
// popUpTo(AppScreen.SIGN_UP) { inclusive = true }
|
||||
// }
|
||||
// }
|
||||
// )
|
||||
// }
|
||||
//
|
||||
// composable(AppScreen.OTP) {
|
||||
// OtpScreen(
|
||||
// onContinue = { navController.navigate(AppScreen.CREATE_PROFILE) }
|
||||
// )
|
||||
// }
|
||||
composable(AppScreen.LANDING) {
|
||||
LandingScreen(
|
||||
onSignUpClick = {
|
||||
navController.navigate(AppScreen.SIGN_UP)
|
||||
},
|
||||
onSignInClick = {
|
||||
navController.navigate(AppScreen.SIGN_IN)
|
||||
},
|
||||
onGuestClick = {
|
||||
mainViewModel.emitNavEvent(
|
||||
NavEvent.ToCreateProfile("guest")
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
// composable(AppScreen.CREATE_PROFILE) {
|
||||
// CreateProfileScreen (
|
||||
// onProfileSelected = { profileId ->
|
||||
// if (profileId == "buyer_seller") {
|
||||
// navController.navigate(AppScreen.BUY_ANIMALS)
|
||||
// } else {
|
||||
// navController.navigate(AppScreen.CHOOSE_SERVICE)
|
||||
// } },
|
||||
// )
|
||||
// }
|
||||
//
|
||||
// composable(AppScreen.CHOOSE_SERVICE) {
|
||||
// ChooseServiceScreen (
|
||||
// onServiceSelected = { navController.navigate(AppScreen.LANDING) },
|
||||
// )
|
||||
// }
|
||||
//
|
||||
// composable(AppScreen.BUY_ANIMALS) {
|
||||
// BuyScreen(
|
||||
// onBackClick = {
|
||||
// navController.popBackStack()
|
||||
// },
|
||||
// onProductClick = { animalId ->
|
||||
// navController.navigate(
|
||||
// AppScreen.animalProfile(animalId)
|
||||
// )
|
||||
// },
|
||||
// onNavClick = onNavClick,
|
||||
// onFilterClick = {navController.navigate(AppScreen.BUY_ANIMALS_FILTERS)},
|
||||
// onSortClick = {navController.navigate(AppScreen.BUY_ANIMALS_SORT)},
|
||||
// onSellerClick = { sellerId ->
|
||||
// navController.navigate(
|
||||
// AppScreen.sellerProfile(sellerId)
|
||||
// )
|
||||
// },
|
||||
// )
|
||||
// }
|
||||
//
|
||||
// composable(AppScreen.BUY_ANIMALS_FILTERS) {
|
||||
// FilterScreen(
|
||||
// onSubmitClick = {navController.navigate(AppScreen.BUY_ANIMALS)},
|
||||
// onBackClick = {
|
||||
// navController.popBackStack()
|
||||
// },
|
||||
// onSkipClick = {
|
||||
// navController.popBackStack()
|
||||
// },
|
||||
// onCancelClick = {
|
||||
// navController.popBackStack()
|
||||
// },
|
||||
//
|
||||
// )
|
||||
// }
|
||||
//
|
||||
// composable(AppScreen.BUY_ANIMALS_SORT) {
|
||||
// SortScreen(
|
||||
// onApplyClick = {navController.navigate(AppScreen.BUY_ANIMALS)},
|
||||
// onBackClick = {
|
||||
// navController.popBackStack()
|
||||
// },
|
||||
// onSkipClick = {
|
||||
// navController.popBackStack()
|
||||
// },
|
||||
// onCancelClick = {
|
||||
// navController.popBackStack()
|
||||
// },
|
||||
//
|
||||
// )
|
||||
// }
|
||||
//
|
||||
// composable(AppScreen.CREATE_ANIMAL_LISTING) {
|
||||
// NewListingScreen (
|
||||
// onSaveClick = {navController.navigate(
|
||||
// AppScreen.postSaleSurvey("2")
|
||||
// )},
|
||||
// onBackClick = {
|
||||
// navController.popBackStack()
|
||||
// }
|
||||
// )
|
||||
// }
|
||||
//
|
||||
// composable(
|
||||
// route = "${AppScreen.SALE_ARCHIVE}/{saleId}",
|
||||
// arguments = listOf(
|
||||
// navArgument("saleId") { type = NavType.StringType }
|
||||
// )
|
||||
// ) { backStackEntry ->
|
||||
//
|
||||
// val saleId = backStackEntry
|
||||
// .arguments
|
||||
// ?.getString("saleId")
|
||||
// ?: return@composable
|
||||
//
|
||||
// SaleArchiveScreen(
|
||||
// saleId = saleId,
|
||||
// onBackClick = {
|
||||
// navController.popBackStack()
|
||||
// },
|
||||
// onSaleSurveyClick = { saleId ->
|
||||
// navController.navigate(
|
||||
// AppScreen.sellerProfile(saleId)
|
||||
// )
|
||||
// },
|
||||
// )
|
||||
// }
|
||||
//
|
||||
// composable(
|
||||
// route = "${AppScreen.POST_SALE_SURVEY}/{animalId}",
|
||||
// arguments = listOf(
|
||||
// navArgument("animalId") { type = NavType.StringType }
|
||||
// )
|
||||
// ) { backStackEntry ->
|
||||
//
|
||||
// val animalId = backStackEntry
|
||||
// .arguments
|
||||
// ?.getString("animalId")
|
||||
// ?: return@composable
|
||||
//
|
||||
// PostSaleSurveyScreen (
|
||||
// animalId = animalId,
|
||||
// onBackClick = {
|
||||
// navController.popBackStack()
|
||||
// },
|
||||
// onSubmit = {navController.navigate(
|
||||
// AppScreen.saleArchive("2")
|
||||
// )}
|
||||
// )
|
||||
// }
|
||||
//
|
||||
// composable(
|
||||
// route = "${AppScreen.ANIMAL_PROFILE}/{animalId}",
|
||||
// arguments = listOf(
|
||||
// navArgument("animalId") { type = NavType.StringType }
|
||||
// )
|
||||
// ) { backStackEntry ->
|
||||
//
|
||||
// val animalId = backStackEntry
|
||||
// .arguments
|
||||
// ?.getString("animalId")
|
||||
// ?: return@composable
|
||||
//
|
||||
// AnimalProfileScreen(
|
||||
// animalId = animalId,
|
||||
// onBackClick = {
|
||||
// navController.popBackStack()
|
||||
// },
|
||||
// onSellerClick = { sellerId ->
|
||||
// navController.navigate(
|
||||
// AppScreen.sellerProfile(sellerId)
|
||||
// )
|
||||
// },
|
||||
// )
|
||||
// }
|
||||
//
|
||||
// composable(
|
||||
// route = "${AppScreen.SELLER_PROFILE}/{sellerId}",
|
||||
// arguments = listOf(
|
||||
// navArgument("sellerId") { type = NavType.StringType }
|
||||
// )
|
||||
// ) { backStackEntry ->
|
||||
//
|
||||
// val sellerId = backStackEntry
|
||||
// .arguments
|
||||
// ?.getString("sellerId")
|
||||
// ?: return@composable
|
||||
//
|
||||
// SellerProfileScreen(
|
||||
// sellerId = sellerId,
|
||||
// onBackClick = {
|
||||
// navController.popBackStack()
|
||||
// }
|
||||
// )
|
||||
// }
|
||||
// composable(AppScreen.SELLER_PROFILE) {
|
||||
// SellerProfileScreen (
|
||||
// onBackClick = {
|
||||
// navController.popBackStack()
|
||||
// }
|
||||
// )
|
||||
// }
|
||||
composable(AppScreen.SIGN_IN) {
|
||||
SignInScreen(
|
||||
onSignUpClick = {
|
||||
navController.navigate(AppScreen.SIGN_UP)
|
||||
},
|
||||
onSignInClick = { phone, name ->
|
||||
navController.navigate(
|
||||
AppScreen.otp(phone, name)
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
composable(AppScreen.SIGN_UP) {
|
||||
SignUpScreen(
|
||||
onSignUpClick = { phone, name, state, district, village ->
|
||||
navController.navigate(
|
||||
AppScreen.otpWithSignup(
|
||||
phone, name, state, district, village
|
||||
)
|
||||
)
|
||||
},
|
||||
onSignInClick = {
|
||||
navController.navigate(AppScreen.SIGN_IN)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
// }
|
||||
composable(
|
||||
"${AppScreen.OTP}/{phoneNumber}/{name}",
|
||||
arguments = listOf(
|
||||
navArgument("phoneNumber") { type = NavType.StringType },
|
||||
navArgument("name") { type = NavType.StringType }
|
||||
)
|
||||
) { backStackEntry ->
|
||||
OtpScreen(
|
||||
mainViewModel = mainViewModel,
|
||||
phoneNumber = backStackEntry.arguments?.getString("phoneNumber") ?: "",
|
||||
name = backStackEntry.arguments?.getString("name") ?: "",
|
||||
onCreateProfile = { name ->
|
||||
// navController.navigateIfAuthenticated(
|
||||
// authState,
|
||||
// AppScreen.createProfile(name),
|
||||
// AppScreen.LANDING
|
||||
// )
|
||||
mainViewModel.emitNavEvent(
|
||||
NavEvent.ToCreateProfile(name)
|
||||
)
|
||||
},
|
||||
onSuccess = {
|
||||
// navController.navigateIfAuthenticated(
|
||||
// authState,
|
||||
// AppScreen.chooseService(""),
|
||||
// AppScreen.LANDING
|
||||
// )
|
||||
mainViewModel.emitNavEvent(
|
||||
NavEvent.ToChooseService()
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
composable(
|
||||
"${AppScreen.OTP}/{phoneNumber}/{name}/{state}/{district}/{village}",
|
||||
arguments = listOf(
|
||||
navArgument("phoneNumber") { type = NavType.StringType },
|
||||
navArgument("name") { type = NavType.StringType },
|
||||
navArgument("state") { type = NavType.StringType },
|
||||
navArgument("district") { type = NavType.StringType },
|
||||
navArgument("village") { type = NavType.StringType }
|
||||
)
|
||||
) { backStackEntry ->
|
||||
OtpScreen(
|
||||
mainViewModel = mainViewModel,
|
||||
phoneNumber = backStackEntry.arguments?.getString("phoneNumber") ?: "",
|
||||
name = backStackEntry.arguments?.getString("name") ?: "",
|
||||
signupState = backStackEntry.arguments?.getString("state"),
|
||||
signupDistrict = backStackEntry.arguments?.getString("district"),
|
||||
signupVillage = backStackEntry.arguments?.getString("village"),
|
||||
onCreateProfile = { name ->
|
||||
mainViewModel.emitNavEvent(
|
||||
NavEvent.ToCreateProfile(name)
|
||||
)
|
||||
},
|
||||
onSuccess = {
|
||||
mainViewModel.emitNavEvent(
|
||||
NavEvent.ToChooseService()
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
/* ---------------- MAIN ---------------- */
|
||||
|
||||
composable(
|
||||
"${AppScreen.CREATE_PROFILE}/{name}",
|
||||
arguments = listOf(
|
||||
navArgument("name") { type = NavType.StringType }
|
||||
)
|
||||
) { backStackEntry ->
|
||||
CreateProfileScreen(
|
||||
name = backStackEntry.arguments?.getString("name") ?: "",
|
||||
onProfileSelected = { profileId ->
|
||||
mainViewModel.emitNavEvent(
|
||||
NavEvent.ToChooseService(profileId)
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
composable(
|
||||
"${AppScreen.CHOOSE_SERVICE}/{profileId}",
|
||||
arguments = listOf(
|
||||
navArgument("profileId") { type = NavType.StringType }
|
||||
)
|
||||
) { backStackEntry ->
|
||||
ChooseServiceScreen(
|
||||
profileId = backStackEntry.arguments?.getString("profileId") ?: "",
|
||||
onServiceSelected = {
|
||||
navController.navigate(AppScreen.BUY_ANIMALS)
|
||||
// navController.navigateIfAuthenticated(
|
||||
// authState,
|
||||
// AppScreen.BUY_ANIMALS
|
||||
// )
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
composable(AppScreen.BUY_ANIMALS) {
|
||||
BuyScreen(
|
||||
onBackClick = {
|
||||
navController.popBackStack()
|
||||
},
|
||||
onProductClick = { animalId ->
|
||||
navController.navigate(
|
||||
AppScreen.animalProfile(animalId)
|
||||
)
|
||||
},
|
||||
onNavClick = onNavClick,
|
||||
onSellerClick = { sellerId ->
|
||||
navController.navigate(
|
||||
AppScreen.sellerProfile(sellerId)
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
composable(AppScreen.BUY_ANIMALS_FILTERS) {
|
||||
FilterScreen(
|
||||
onBackClick = {
|
||||
navController.popBackStack()
|
||||
},
|
||||
onSubmitClick = {navController.navigate(AppScreen.BUY_ANIMALS)},
|
||||
onCancelClick = {
|
||||
navController.popBackStack()
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
composable(AppScreen.BUY_ANIMALS_SORT) {
|
||||
SortScreen(
|
||||
onApplyClick = {navController.navigate(AppScreen.BUY_ANIMALS)},
|
||||
onBackClick = {
|
||||
navController.popBackStack()
|
||||
},
|
||||
onCancelClick = {
|
||||
navController.popBackStack()
|
||||
},
|
||||
|
||||
)
|
||||
}
|
||||
|
||||
composable(AppScreen.SAVED_LISTINGS) {
|
||||
SavedListingsScreen(
|
||||
onNavClick = onNavClick,
|
||||
onBackClick = { navController.popBackStack() })
|
||||
}
|
||||
|
||||
composable(AppScreen.ACCOUNTS) {
|
||||
AccountsScreen(
|
||||
onBackClick = { navController.popBackStack() },
|
||||
onLogout = {
|
||||
// Navigate to auth graph after logout
|
||||
navController.navigate(AppScreen.LANDING) {
|
||||
popUpTo(0) { inclusive = true }
|
||||
}
|
||||
},
|
||||
onApiTest = {
|
||||
navController.navigate(AppScreen.API_TEST)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
composable(AppScreen.CREATE_ANIMAL_LISTING) {
|
||||
NewListingScreen (
|
||||
onSaveClick = {navController.navigate(
|
||||
AppScreen.postSaleSurvey("2")
|
||||
)},
|
||||
onBackClick = {
|
||||
navController.navigate(AppScreen.BUY_ANIMALS){
|
||||
popUpTo(AppScreen.BUY_ANIMALS){
|
||||
inclusive = true
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
composable(
|
||||
route = "${AppScreen.SALE_ARCHIVE}/{saleId}",
|
||||
arguments = listOf(
|
||||
navArgument("saleId") { type = NavType.StringType }
|
||||
)
|
||||
) { backStackEntry ->
|
||||
|
||||
val saleId = backStackEntry
|
||||
.arguments
|
||||
?.getString("saleId")
|
||||
?: return@composable
|
||||
|
||||
SaleArchiveScreen(
|
||||
saleId = saleId,
|
||||
onBackClick = {
|
||||
navController.popBackStack()
|
||||
},
|
||||
onSaleSurveyClick = { saleId ->
|
||||
navController.navigate(
|
||||
AppScreen.sellerProfile(saleId)
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
composable(
|
||||
route = "${AppScreen.POST_SALE_SURVEY}/{animalId}",
|
||||
arguments = listOf(
|
||||
navArgument("animalId") { type = NavType.StringType }
|
||||
)
|
||||
) { backStackEntry ->
|
||||
|
||||
val animalId = backStackEntry
|
||||
.arguments
|
||||
?.getString("animalId")
|
||||
?: return@composable
|
||||
|
||||
PostSaleSurveyScreen (
|
||||
animalId = animalId,
|
||||
onBackClick = {
|
||||
navController.navigate(AppScreen.CREATE_ANIMAL_LISTING)
|
||||
},
|
||||
onSubmit = {navController.navigate(
|
||||
AppScreen.saleArchive("2")
|
||||
)}
|
||||
)
|
||||
}
|
||||
|
||||
composable(
|
||||
route = "${AppScreen.ANIMAL_PROFILE}/{animalId}",
|
||||
arguments = listOf(
|
||||
navArgument("animalId") { type = NavType.StringType }
|
||||
)
|
||||
) { backStackEntry ->
|
||||
|
||||
val animalId = backStackEntry
|
||||
.arguments
|
||||
?.getString("animalId")
|
||||
?: return@composable
|
||||
|
||||
AnimalProfileScreen(
|
||||
animalId = animalId,
|
||||
onBackClick = {
|
||||
navController.popBackStack()
|
||||
},
|
||||
onNavClick = onNavClick,
|
||||
onSellerClick = { sellerId ->
|
||||
navController.navigate(
|
||||
AppScreen.sellerProfile(sellerId)
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
composable(
|
||||
route = "${AppScreen.SELLER_PROFILE}/{sellerId}",
|
||||
arguments = listOf(
|
||||
navArgument("sellerId") { type = NavType.StringType }
|
||||
)
|
||||
) { backStackEntry ->
|
||||
|
||||
val sellerId = backStackEntry
|
||||
.arguments
|
||||
?.getString("sellerId")
|
||||
?: return@composable
|
||||
|
||||
SellerProfileScreen(
|
||||
sellerId = sellerId,
|
||||
onBackClick = {
|
||||
navController.popBackStack()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
composable(AppScreen.CONTACTS) {
|
||||
ContactsScreen(
|
||||
onBackClick = {navController.navigate(AppScreen.BUY_ANIMALS)},//{navController.popBackStack()},
|
||||
onTabClick = onNavClick,
|
||||
)
|
||||
}
|
||||
|
||||
composable(AppScreen.CALLS) {
|
||||
CallsScreen(
|
||||
onBackClick = {navController.navigate(AppScreen.BUY_ANIMALS)},//{navController.popBackStack()},
|
||||
onTabClick = onNavClick,
|
||||
)
|
||||
}
|
||||
|
||||
composable(AppScreen.CHATS) {
|
||||
ChatsScreen(
|
||||
onBackClick = {navController.navigate(AppScreen.BUY_ANIMALS)},//{navController.popBackStack()},
|
||||
onTabClick = onNavClick,
|
||||
onChatItemClick = {navController.navigate(AppScreen.chats("2"))}
|
||||
)
|
||||
}
|
||||
|
||||
composable(
|
||||
route = "${AppScreen.CHAT}/{contact}",
|
||||
arguments = listOf(
|
||||
navArgument("contact") { type = NavType.StringType }
|
||||
)
|
||||
) { backStackEntry ->
|
||||
|
||||
val sellerId = backStackEntry
|
||||
.arguments
|
||||
?.getString("contact")
|
||||
?: return@composable
|
||||
|
||||
ChatScreen(
|
||||
sellerId,
|
||||
onBackClick = {
|
||||
navController.navigate(AppScreen.CHATS)
|
||||
//navController.popBackStack()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
//A route for testing
|
||||
composable(AppScreen.API_TEST) {
|
||||
ApiTestScreen(
|
||||
onBackClick = { navController.popBackStack() }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,79 @@
|
|||
package com.example.livingai_lg.ui.navigation
|
||||
|
||||
object AppScreen {
|
||||
const val LANDING = "landing"
|
||||
const val SIGN_IN = "sign_in"
|
||||
const val SIGN_UP = "sign_up"
|
||||
|
||||
const val OTP = "otp"
|
||||
|
||||
fun otp(phone: String, name: String) =
|
||||
"$OTP/$phone/$name"
|
||||
|
||||
fun otpWithSignup(phone: String, name: String, state: String, district: String, village: String) =
|
||||
"$OTP/$phone/$name/$state/$district/$village"
|
||||
|
||||
const val CHOOSE_SERVICE = "choose_service"
|
||||
fun chooseService(profileId: String?) =
|
||||
"$CHOOSE_SERVICE/$profileId"
|
||||
|
||||
const val CREATE_PROFILE = "create_profile"
|
||||
|
||||
fun createProfile(name: String) =
|
||||
"$CREATE_PROFILE/$name"
|
||||
|
||||
const val BUY_ANIMALS = "buy_animals"
|
||||
const val ANIMAL_PROFILE = "animal_profile"
|
||||
fun animalProfile(animalId: String) =
|
||||
"$ANIMAL_PROFILE/$animalId"
|
||||
|
||||
const val CREATE_ANIMAL_LISTING = "create_animal_listing"
|
||||
|
||||
const val BUY_ANIMALS_FILTERS = "buy_animals_filters"
|
||||
const val BUY_ANIMALS_SORT = "buy_animals_sort"
|
||||
|
||||
const val SELLER_PROFILE = "seller_profile"
|
||||
fun sellerProfile(sellerId: String) =
|
||||
"$SELLER_PROFILE/$sellerId"
|
||||
|
||||
const val SALE_ARCHIVE = "sale_archive"
|
||||
fun saleArchive(saleId: String) =
|
||||
"$SALE_ARCHIVE/$saleId"
|
||||
|
||||
const val POST_SALE_SURVEY = "post_sale_survey"
|
||||
fun postSaleSurvey(animalId: String) =
|
||||
"$POST_SALE_SURVEY/$animalId"
|
||||
|
||||
const val SAVED_LISTINGS = "saved_listings"
|
||||
|
||||
const val CONTACTS = "contacts"
|
||||
|
||||
fun chats(contact: String) =
|
||||
"$CHAT/$contact"
|
||||
|
||||
const val CALLS = "calls"
|
||||
|
||||
const val CHAT = "chat"
|
||||
|
||||
const val CHATS = "chats"
|
||||
|
||||
const val ACCOUNTS = "accounts"
|
||||
|
||||
|
||||
|
||||
// Test screens::
|
||||
const val API_TEST = "api_test"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
package com.example.livingai_lg.ui.navigation
|
||||
sealed class NavEvent {
|
||||
data class ToCreateProfile(val name: String) : NavEvent()
|
||||
data class ToChooseService(val profileId: String = "") : NavEvent()
|
||||
object ToLanding : NavEvent()
|
||||
}
|
||||
|
|
@ -1,27 +1,25 @@
|
|||
package com.example.livingai_lg.ui.navigation
|
||||
package com.example.livingai_lg.ui.navigation.navigation_legacy
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import android.util.Log
|
||||
import androidx.navigation.NavController
|
||||
import androidx.navigation.NavGraphBuilder
|
||||
import androidx.navigation.NavHostController
|
||||
import androidx.navigation.NavType
|
||||
import androidx.navigation.compose.NavHost
|
||||
import androidx.navigation.compose.composable
|
||||
import androidx.navigation.compose.navigation
|
||||
import androidx.navigation.compose.rememberNavController
|
||||
import androidx.navigation.navArgument
|
||||
import com.example.livingai_lg.ui.MainViewModel
|
||||
import com.example.livingai_lg.ui.navigation.AppScreen
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
// Note: CoroutineScope, Dispatchers, delay, launch still used in onCreateProfile callbacks
|
||||
import com.example.livingai_lg.ui.screens.SaleArchiveScreen
|
||||
import com.example.livingai_lg.ui.screens.auth.LandingScreen
|
||||
import com.example.livingai_lg.ui.screens.auth.OtpScreen
|
||||
import com.example.livingai_lg.ui.screens.auth.SignInScreen
|
||||
import com.example.livingai_lg.ui.screens.auth.SignUpScreen
|
||||
|
||||
fun NavGraphBuilder.authNavGraph(navController: NavController, mainViewModel: com.example.livingai_lg.ui.MainViewModel) {
|
||||
fun NavGraphBuilder.authNavGraph(navController: NavController, mainViewModel: MainViewModel) {
|
||||
navigation(
|
||||
route = Graph.AUTH,
|
||||
startDestination = AppScreen.LANDING
|
||||
|
|
@ -70,7 +68,7 @@ fun NavGraphBuilder.authNavGraph(navController: NavController, mainViewModel: co
|
|||
name = backStackEntry.arguments?.getString("name") ?: "",
|
||||
mainViewModel = mainViewModel,
|
||||
onCreateProfile = {name ->
|
||||
android.util.Log.d("AuthNavGraph", "Navigating to create profile with name: $name")
|
||||
Log.d("AuthNavGraph", "Navigating to create profile with name: $name")
|
||||
// Navigate to main graph first without popping, then navigate to specific route
|
||||
try {
|
||||
// Navigate to main graph (this will use its start destination)
|
||||
|
|
@ -87,15 +85,15 @@ fun NavGraphBuilder.authNavGraph(navController: NavController, mainViewModel: co
|
|||
popUpTo(Graph.AUTH) { inclusive = true }
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
android.util.Log.e("AuthNavGraph", "Secondary navigation error: ${e.message}", e)
|
||||
Log.e("AuthNavGraph", "Secondary navigation error: ${e.message}", e)
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
android.util.Log.e("AuthNavGraph", "Navigation error: ${e.message}", e)
|
||||
Log.e("AuthNavGraph", "Navigation error: ${e.message}", e)
|
||||
}
|
||||
},
|
||||
onLanding = {
|
||||
android.util.Log.d("AuthNavGraph", "Navigating to landing page for new user")
|
||||
Log.d("AuthNavGraph", "Navigating to landing page for new user")
|
||||
// Navigate to landing page within AUTH graph
|
||||
try {
|
||||
navController.navigate(AppScreen.LANDING) {
|
||||
|
|
@ -104,11 +102,11 @@ fun NavGraphBuilder.authNavGraph(navController: NavController, mainViewModel: co
|
|||
launchSingleTop = true
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
android.util.Log.e("AuthNavGraph", "Navigation to landing error: ${e.message}", e)
|
||||
Log.e("AuthNavGraph", "Navigation to landing error: ${e.message}", e)
|
||||
}
|
||||
},
|
||||
onSuccess = {
|
||||
android.util.Log.d("AuthNavGraph", "Sign-in successful - navigating to ChooseServiceScreen")
|
||||
Log.d("AuthNavGraph", "Sign-in successful - navigating to ChooseServiceScreen")
|
||||
// Navigate to MAIN graph which starts at ChooseServiceScreen (startDestination)
|
||||
try {
|
||||
navController.navigate(Graph.MAIN) {
|
||||
|
|
@ -117,7 +115,7 @@ fun NavGraphBuilder.authNavGraph(navController: NavController, mainViewModel: co
|
|||
launchSingleTop = true
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
android.util.Log.e("AuthNavGraph", "Navigation error: ${e.message}", e)
|
||||
Log.e("AuthNavGraph", "Navigation error: ${e.message}", e)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
|
@ -141,7 +139,7 @@ fun NavGraphBuilder.authNavGraph(navController: NavController, mainViewModel: co
|
|||
signupVillage = backStackEntry.arguments?.getString("village"),
|
||||
mainViewModel = mainViewModel,
|
||||
onCreateProfile = {name ->
|
||||
android.util.Log.d("AuthNavGraph", "Navigating to create profile with name: $name")
|
||||
Log.d("AuthNavGraph", "Navigating to create profile with name: $name")
|
||||
// Navigate to main graph first without popping, then navigate to specific route
|
||||
try {
|
||||
// Navigate to main graph (this will use its start destination)
|
||||
|
|
@ -158,15 +156,15 @@ fun NavGraphBuilder.authNavGraph(navController: NavController, mainViewModel: co
|
|||
popUpTo(Graph.AUTH) { inclusive = true }
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
android.util.Log.e("AuthNavGraph", "Secondary navigation error: ${e.message}", e)
|
||||
Log.e("AuthNavGraph", "Secondary navigation error: ${e.message}", e)
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
android.util.Log.e("AuthNavGraph", "Navigation error: ${e.message}", e)
|
||||
Log.e("AuthNavGraph", "Navigation error: ${e.message}", e)
|
||||
}
|
||||
},
|
||||
onLanding = {
|
||||
android.util.Log.d("AuthNavGraph", "Navigating to landing page for new user")
|
||||
Log.d("AuthNavGraph", "Navigating to landing page for new user")
|
||||
// Navigate to landing page within AUTH graph
|
||||
try {
|
||||
navController.navigate(AppScreen.LANDING) {
|
||||
|
|
@ -175,11 +173,11 @@ fun NavGraphBuilder.authNavGraph(navController: NavController, mainViewModel: co
|
|||
launchSingleTop = true
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
android.util.Log.e("AuthNavGraph", "Navigation to landing error: ${e.message}", e)
|
||||
Log.e("AuthNavGraph", "Navigation to landing error: ${e.message}", e)
|
||||
}
|
||||
},
|
||||
onSuccess = {
|
||||
android.util.Log.d("AuthNavGraph", "Sign-in successful - navigating to ChooseServiceScreen")
|
||||
Log.d("AuthNavGraph", "Sign-in successful - navigating to ChooseServiceScreen")
|
||||
// Navigate to MAIN graph which starts at ChooseServiceScreen (startDestination)
|
||||
try {
|
||||
navController.navigate(Graph.MAIN) {
|
||||
|
|
@ -188,7 +186,7 @@ fun NavGraphBuilder.authNavGraph(navController: NavController, mainViewModel: co
|
|||
launchSingleTop = true
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
android.util.Log.e("AuthNavGraph", "Navigation error: ${e.message}", e)
|
||||
Log.e("AuthNavGraph", "Navigation error: ${e.message}", e)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
|
@ -1,18 +1,15 @@
|
|||
package com.example.livingai_lg.ui.navigation
|
||||
package com.example.livingai_lg.ui.navigation.navigation_legacy
|
||||
|
||||
import android.util.Log
|
||||
import androidx.navigation.NavController
|
||||
import androidx.navigation.NavGraphBuilder
|
||||
import androidx.navigation.NavType
|
||||
import androidx.navigation.compose.NavHost
|
||||
import androidx.navigation.compose.composable
|
||||
import androidx.navigation.compose.navigation
|
||||
import androidx.navigation.navArgument
|
||||
import com.example.livingai_lg.ui.navigation.AppScreen
|
||||
import com.example.livingai_lg.ui.navigation.Graph
|
||||
import com.example.farmmarketplace.ui.screens.CallsScreen
|
||||
import com.example.farmmarketplace.ui.screens.ContactsScreen
|
||||
import com.example.livingai_lg.ui.models.profileTypes
|
||||
import com.example.livingai_lg.ui.navigation.AppScreen
|
||||
import com.example.livingai_lg.ui.screens.AccountsScreen
|
||||
import com.example.livingai_lg.ui.screens.AnimalProfileScreen
|
||||
import com.example.livingai_lg.ui.screens.BuyScreen
|
||||
|
|
@ -137,7 +134,8 @@ fun NavGraphBuilder.mainNavGraph(navController: NavController) {
|
|||
navController.navigate(Graph.AUTH) {
|
||||
popUpTo(0) { inclusive = true }
|
||||
}
|
||||
}
|
||||
},
|
||||
onApiTest = {navController.navigate(AppScreen.API_TEST)}
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,430 @@
|
|||
package com.example.livingai_lg.ui.navigation.navigation_legacy
|
||||
|
||||
import android.util.Log
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.navigation.compose.NavHost
|
||||
import androidx.navigation.compose.rememberNavController
|
||||
import kotlinx.coroutines.delay
|
||||
import com.example.livingai_lg.ui.AuthState
|
||||
import com.example.livingai_lg.ui.MainViewModel
|
||||
import com.example.livingai_lg.ui.navigation.AppScreen
|
||||
|
||||
object OldAppScreen {
|
||||
const val LANDING = "landing"
|
||||
const val SIGN_IN = "sign_in"
|
||||
const val SIGN_UP = "sign_up"
|
||||
|
||||
const val OTP = "otp"
|
||||
|
||||
const val CHOOSE_SERVICE = "choose_service"
|
||||
|
||||
const val CREATE_PROFILE = "create_profile"
|
||||
|
||||
const val BUY_ANIMALS = "buy_animals"
|
||||
const val ANIMAL_PROFILE = "animal_profile"
|
||||
|
||||
const val CREATE_ANIMAL_LISTING = "create_animal_listing"
|
||||
|
||||
const val BUY_ANIMALS_FILTERS = "buy_animals_filters"
|
||||
const val BUY_ANIMALS_SORT = "buy_animals_sort"
|
||||
|
||||
const val SELLER_PROFILE = "seller_profile"
|
||||
|
||||
const val SALE_ARCHIVE = "sale_archive"
|
||||
|
||||
const val POST_SALE_SURVEY = "post_sale_survey"
|
||||
|
||||
const val SAVED_LISTINGS = "saved_listings"
|
||||
|
||||
const val CONTACTS = "contacts"
|
||||
|
||||
const val CALLS = "calls"
|
||||
|
||||
const val CHAT = "chat"
|
||||
|
||||
const val CHATS = "chats"
|
||||
|
||||
const val ACCOUNTS = "accounts"
|
||||
|
||||
fun chats(contact: String) =
|
||||
"$CHAT/$contact"
|
||||
|
||||
fun otp(phone: String, name: String) =
|
||||
"$OTP/$phone/$name"
|
||||
|
||||
fun otpWithSignup(phone: String, name: String, state: String, district: String, village: String) =
|
||||
"$OTP/$phone/$name/$state/$district/$village"
|
||||
|
||||
fun createProfile(name: String) =
|
||||
"$CREATE_PROFILE/$name"
|
||||
|
||||
fun chooseService(profileId: String) =
|
||||
"$CHOOSE_SERVICE/$profileId"
|
||||
fun postSaleSurvey(animalId: String) =
|
||||
"$POST_SALE_SURVEY/$animalId"
|
||||
|
||||
fun animalProfile(animalId: String) =
|
||||
"$ANIMAL_PROFILE/$animalId"
|
||||
|
||||
fun sellerProfile(sellerId: String) =
|
||||
"$SELLER_PROFILE/$sellerId"
|
||||
|
||||
fun saleArchive(saleId: String) =
|
||||
"$SALE_ARCHIVE/$saleId"
|
||||
|
||||
}
|
||||
|
||||
object Graph {
|
||||
const val AUTH = "auth"
|
||||
const val MAIN = "main"
|
||||
|
||||
fun auth(route: String)=
|
||||
"$AUTH/$route"
|
||||
|
||||
fun main(route: String)=
|
||||
"$MAIN/$route"
|
||||
}
|
||||
@Composable
|
||||
fun OldAppNavigation(
|
||||
authState: AuthState,
|
||||
mainViewModel: MainViewModel
|
||||
) {
|
||||
val navController = rememberNavController()
|
||||
|
||||
// Determine start destination based on initial auth state
|
||||
// This prevents showing landing screen when user is already logged in
|
||||
val startDestination = remember(authState) {
|
||||
when (authState) {
|
||||
is AuthState.Authenticated -> Graph.MAIN
|
||||
is AuthState.Unauthenticated -> Graph.AUTH
|
||||
is AuthState.Unknown -> Graph.AUTH // Show landing while checking
|
||||
}
|
||||
}
|
||||
|
||||
NavHost(
|
||||
navController = navController,
|
||||
startDestination = startDestination
|
||||
) {
|
||||
authNavGraph(navController, mainViewModel)
|
||||
mainNavGraph(navController)
|
||||
}
|
||||
|
||||
// Handle navigation based on auth state changes
|
||||
LaunchedEffect(authState) {
|
||||
Log.d("AppNavigation", "LaunchedEffect triggered with authState: $authState")
|
||||
when (authState) {
|
||||
is AuthState.Authenticated -> {
|
||||
// User is authenticated, navigate to ChooseServiceScreen
|
||||
// Add a small delay to ensure NavHost graphs are fully built
|
||||
delay(100)
|
||||
|
||||
val currentRoute = navController.currentBackStackEntry?.destination?.route
|
||||
Log.d("AppNavigation", "Authenticated - currentRoute: $currentRoute")
|
||||
// Only navigate if we're not already in the MAIN graph or ChooseServiceScreen
|
||||
if (currentRoute?.startsWith(Graph.MAIN) != true &&
|
||||
currentRoute?.startsWith(AppScreen.CHOOSE_SERVICE) != true) {
|
||||
Log.d("AppNavigation", "Navigating to ChooseServiceScreen (default profileId: 1)")
|
||||
try {
|
||||
// Navigate directly to the start destination route of MAIN graph
|
||||
// This avoids the "Sequence is empty" error when navigating to Graph.MAIN
|
||||
navController.navigate(AppScreen.chooseService("1")) {
|
||||
// Clear back stack to prevent going back to auth screens
|
||||
popUpTo(Graph.AUTH) { inclusive = true }
|
||||
// Prevent multiple navigations
|
||||
launchSingleTop = true
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.e("AppNavigation", "Navigation error: ${e.message}", e)
|
||||
// Fallback: try navigating to Graph.MAIN if direct route fails
|
||||
try {
|
||||
navController.navigate(Graph.MAIN) {
|
||||
popUpTo(Graph.AUTH) { inclusive = true }
|
||||
launchSingleTop = true
|
||||
}
|
||||
} catch (e2: Exception) {
|
||||
Log.e("AppNavigation", "Fallback navigation also failed: ${e2.message}", e2)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Log.d("AppNavigation", "Already in MAIN graph or ChooseServiceScreen, skipping navigation")
|
||||
}
|
||||
}
|
||||
is AuthState.Unauthenticated -> {
|
||||
// User is not authenticated, ensure we're in auth graph (landing screen)
|
||||
val currentRoute = navController.currentBackStackEntry?.destination?.route
|
||||
if (currentRoute?.startsWith(Graph.MAIN) == true ||
|
||||
currentRoute?.startsWith(Graph.AUTH) != true) {
|
||||
navController.navigate(Graph.AUTH) {
|
||||
// Clear back stack to prevent going back to main screens
|
||||
popUpTo(0) { inclusive = true }
|
||||
launchSingleTop = true
|
||||
}
|
||||
}
|
||||
}
|
||||
is AuthState.Unknown -> {
|
||||
// Still checking auth status
|
||||
// If we're on landing screen, stay there
|
||||
// If we're on main screen and checking, don't navigate yet
|
||||
// This prevents flickering during token validation
|
||||
}
|
||||
}
|
||||
}
|
||||
// MainNavGraph(navController)
|
||||
// AuthNavGraph(navController)
|
||||
// when (authState) {
|
||||
// is AuthState.Unauthenticated -> {AuthNavGraph()}
|
||||
// is AuthState.Authenticated -> {MainNavGraph()}
|
||||
// is AuthState.Unknown -> {
|
||||
// Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
|
||||
// CircularProgressIndicator()
|
||||
// }
|
||||
// }
|
||||
// AuthState.Loading -> SplashScreen()
|
||||
// }
|
||||
|
||||
// val onNavClick: (String) -> Unit = { route ->
|
||||
// val currentRoute =
|
||||
// navController.currentBackStackEntry?.destination?.route
|
||||
//
|
||||
// if (currentRoute != route) {
|
||||
// navController.navigate(route) {
|
||||
// launchSingleTop = true
|
||||
// restoreState = true
|
||||
// popUpTo(navController.graph.startDestinationId) {
|
||||
// saveState = true
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
|
||||
// NavHost(
|
||||
// navController = navController,
|
||||
// startDestination = AppScreen.LANDING,
|
||||
//
|
||||
// ) {
|
||||
// composable(AppScreen.LANDING) {
|
||||
// LandingScreen(
|
||||
// onSignUpClick = { navController.navigate(AppScreen.SIGN_UP) },
|
||||
// onSignInClick = { navController.navigate(AppScreen.SIGN_IN) },
|
||||
// onGuestClick = { navController.navigate(AppScreen.CREATE_PROFILE) }
|
||||
// )
|
||||
// }
|
||||
//
|
||||
// composable(AppScreen.SIGN_IN) {
|
||||
// SignInScreen(
|
||||
// onSignUpClick = { navController.navigate(AppScreen.SIGN_UP) },
|
||||
// onSignInClick = {
|
||||
// navController.navigate(AppScreen.OTP)
|
||||
// }
|
||||
// )
|
||||
// }
|
||||
//
|
||||
// composable(AppScreen.SIGN_UP) {
|
||||
// SignUpScreen(
|
||||
// onSignUpClick = {
|
||||
// navController.navigate(AppScreen.OTP)
|
||||
// },
|
||||
// onSignInClick = {
|
||||
// navController.navigate(AppScreen.SIGN_IN) {
|
||||
// popUpTo(AppScreen.SIGN_UP) { inclusive = true }
|
||||
// }
|
||||
// }
|
||||
// )
|
||||
// }
|
||||
//
|
||||
// composable(AppScreen.OTP) {
|
||||
// OtpScreen(
|
||||
// onContinue = { navController.navigate(AppScreen.CREATE_PROFILE) }
|
||||
// )
|
||||
// }
|
||||
|
||||
// composable(AppScreen.CREATE_PROFILE) {
|
||||
// CreateProfileScreen (
|
||||
// onProfileSelected = { profileId ->
|
||||
// if (profileId == "buyer_seller") {
|
||||
// navController.navigate(AppScreen.BUY_ANIMALS)
|
||||
// } else {
|
||||
// navController.navigate(AppScreen.CHOOSE_SERVICE)
|
||||
// } },
|
||||
// )
|
||||
// }
|
||||
//
|
||||
// composable(AppScreen.CHOOSE_SERVICE) {
|
||||
// ChooseServiceScreen (
|
||||
// onServiceSelected = { navController.navigate(AppScreen.LANDING) },
|
||||
// )
|
||||
// }
|
||||
//
|
||||
// composable(AppScreen.BUY_ANIMALS) {
|
||||
// BuyScreen(
|
||||
// onBackClick = {
|
||||
// navController.popBackStack()
|
||||
// },
|
||||
// onProductClick = { animalId ->
|
||||
// navController.navigate(
|
||||
// AppScreen.animalProfile(animalId)
|
||||
// )
|
||||
// },
|
||||
// onNavClick = onNavClick,
|
||||
// onFilterClick = {navController.navigate(AppScreen.BUY_ANIMALS_FILTERS)},
|
||||
// onSortClick = {navController.navigate(AppScreen.BUY_ANIMALS_SORT)},
|
||||
// onSellerClick = { sellerId ->
|
||||
// navController.navigate(
|
||||
// AppScreen.sellerProfile(sellerId)
|
||||
// )
|
||||
// },
|
||||
// )
|
||||
// }
|
||||
//
|
||||
// composable(AppScreen.BUY_ANIMALS_FILTERS) {
|
||||
// FilterScreen(
|
||||
// onSubmitClick = {navController.navigate(AppScreen.BUY_ANIMALS)},
|
||||
// onBackClick = {
|
||||
// navController.popBackStack()
|
||||
// },
|
||||
// onSkipClick = {
|
||||
// navController.popBackStack()
|
||||
// },
|
||||
// onCancelClick = {
|
||||
// navController.popBackStack()
|
||||
// },
|
||||
//
|
||||
// )
|
||||
// }
|
||||
//
|
||||
// composable(AppScreen.BUY_ANIMALS_SORT) {
|
||||
// SortScreen(
|
||||
// onApplyClick = {navController.navigate(AppScreen.BUY_ANIMALS)},
|
||||
// onBackClick = {
|
||||
// navController.popBackStack()
|
||||
// },
|
||||
// onSkipClick = {
|
||||
// navController.popBackStack()
|
||||
// },
|
||||
// onCancelClick = {
|
||||
// navController.popBackStack()
|
||||
// },
|
||||
//
|
||||
// )
|
||||
// }
|
||||
//
|
||||
// composable(AppScreen.CREATE_ANIMAL_LISTING) {
|
||||
// NewListingScreen (
|
||||
// onSaveClick = {navController.navigate(
|
||||
// AppScreen.postSaleSurvey("2")
|
||||
// )},
|
||||
// onBackClick = {
|
||||
// navController.popBackStack()
|
||||
// }
|
||||
// )
|
||||
// }
|
||||
//
|
||||
// composable(
|
||||
// route = "${AppScreen.SALE_ARCHIVE}/{saleId}",
|
||||
// arguments = listOf(
|
||||
// navArgument("saleId") { type = NavType.StringType }
|
||||
// )
|
||||
// ) { backStackEntry ->
|
||||
//
|
||||
// val saleId = backStackEntry
|
||||
// .arguments
|
||||
// ?.getString("saleId")
|
||||
// ?: return@composable
|
||||
//
|
||||
// SaleArchiveScreen(
|
||||
// saleId = saleId,
|
||||
// onBackClick = {
|
||||
// navController.popBackStack()
|
||||
// },
|
||||
// onSaleSurveyClick = { saleId ->
|
||||
// navController.navigate(
|
||||
// AppScreen.sellerProfile(saleId)
|
||||
// )
|
||||
// },
|
||||
// )
|
||||
// }
|
||||
//
|
||||
// composable(
|
||||
// route = "${AppScreen.POST_SALE_SURVEY}/{animalId}",
|
||||
// arguments = listOf(
|
||||
// navArgument("animalId") { type = NavType.StringType }
|
||||
// )
|
||||
// ) { backStackEntry ->
|
||||
//
|
||||
// val animalId = backStackEntry
|
||||
// .arguments
|
||||
// ?.getString("animalId")
|
||||
// ?: return@composable
|
||||
//
|
||||
// PostSaleSurveyScreen (
|
||||
// animalId = animalId,
|
||||
// onBackClick = {
|
||||
// navController.popBackStack()
|
||||
// },
|
||||
// onSubmit = {navController.navigate(
|
||||
// AppScreen.saleArchive("2")
|
||||
// )}
|
||||
// )
|
||||
// }
|
||||
//
|
||||
// composable(
|
||||
// route = "${AppScreen.ANIMAL_PROFILE}/{animalId}",
|
||||
// arguments = listOf(
|
||||
// navArgument("animalId") { type = NavType.StringType }
|
||||
// )
|
||||
// ) { backStackEntry ->
|
||||
//
|
||||
// val animalId = backStackEntry
|
||||
// .arguments
|
||||
// ?.getString("animalId")
|
||||
// ?: return@composable
|
||||
//
|
||||
// AnimalProfileScreen(
|
||||
// animalId = animalId,
|
||||
// onBackClick = {
|
||||
// navController.popBackStack()
|
||||
// },
|
||||
// onSellerClick = { sellerId ->
|
||||
// navController.navigate(
|
||||
// AppScreen.sellerProfile(sellerId)
|
||||
// )
|
||||
// },
|
||||
// )
|
||||
// }
|
||||
//
|
||||
// composable(
|
||||
// route = "${AppScreen.SELLER_PROFILE}/{sellerId}",
|
||||
// arguments = listOf(
|
||||
// navArgument("sellerId") { type = NavType.StringType }
|
||||
// )
|
||||
// ) { backStackEntry ->
|
||||
//
|
||||
// val sellerId = backStackEntry
|
||||
// .arguments
|
||||
// ?.getString("sellerId")
|
||||
// ?: return@composable
|
||||
//
|
||||
// SellerProfileScreen(
|
||||
// sellerId = sellerId,
|
||||
// onBackClick = {
|
||||
// navController.popBackStack()
|
||||
// }
|
||||
// )
|
||||
// }
|
||||
// composable(AppScreen.SELLER_PROFILE) {
|
||||
// SellerProfileScreen (
|
||||
// onBackClick = {
|
||||
// navController.popBackStack()
|
||||
// }
|
||||
// )
|
||||
// }
|
||||
|
||||
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -8,6 +8,7 @@ import androidx.compose.foundation.shape.RoundedCornerShape
|
|||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
||||
import androidx.compose.material.icons.automirrored.filled.Logout
|
||||
import androidx.compose.material.icons.filled.Construction
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
|
|
@ -34,7 +35,8 @@ import kotlinx.coroutines.launch
|
|||
@Composable
|
||||
fun AccountsScreen(
|
||||
onBackClick: () -> Unit,
|
||||
onLogout: () -> Unit
|
||||
onLogout: () -> Unit,
|
||||
onApiTest: () -> Unit,
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
val scope = rememberCoroutineScope()
|
||||
|
|
@ -123,6 +125,43 @@ fun AccountsScreen(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
Surface(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth().padding(vertical = 12.dp)
|
||||
.clickable {
|
||||
onApiTest()
|
||||
},
|
||||
shape = RoundedCornerShape(12.dp),
|
||||
color = Color.White,
|
||||
shadowElevation = 2.dp
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp, vertical = 20.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.SpaceBetween
|
||||
) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.spacedBy(16.dp)
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Construction,
|
||||
contentDescription = "Api test",
|
||||
tint = Color.Gray,
|
||||
modifier = Modifier.size(24.dp)
|
||||
)
|
||||
Text(
|
||||
text = "Test API",
|
||||
fontSize = 16.sp,
|
||||
fontWeight = FontWeight.Medium,
|
||||
color = Color.Gray
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ import com.example.livingai_lg.R
|
|||
import com.example.livingai_lg.ui.components.ActionPopup
|
||||
import com.example.livingai_lg.ui.components.AddressSelectorOverlay
|
||||
import com.example.livingai_lg.ui.components.FilterOverlay
|
||||
import com.example.livingai_lg.ui.components.InfoOverlay
|
||||
import com.example.livingai_lg.ui.components.NotificationsOverlay
|
||||
import com.example.livingai_lg.ui.components.SortOverlay
|
||||
import com.example.livingai_lg.ui.models.sampleNotifications
|
||||
|
|
@ -59,6 +60,9 @@ fun BuyScreen(
|
|||
var showSavedPopup by remember { mutableStateOf(false) }
|
||||
var showNotifications by remember { mutableStateOf(false) }
|
||||
val sampleNotifications = sampleNotifications
|
||||
var showInfoOverlay by remember { mutableStateOf(false) }
|
||||
var selectedItemId by remember { mutableStateOf<String?>(null) }
|
||||
|
||||
|
||||
Box(
|
||||
modifier = Modifier
|
||||
|
|
@ -168,7 +172,9 @@ fun BuyScreen(
|
|||
onSavedChange = { isSaved.value = it },
|
||||
onProductClick = { onProductClick(animal.id)},
|
||||
onSellerClick = onSellerClick,
|
||||
onBookmarkClick = { showSavedPopup = true }
|
||||
onBookmarkClick = { showSavedPopup = true },
|
||||
onInfoClick = { showInfoOverlay = true
|
||||
selectedItemId=animal.id},
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
|
|
@ -213,6 +219,15 @@ fun BuyScreen(
|
|||
}
|
||||
)
|
||||
|
||||
val animal = sampleAnimals.find { it.id == selectedItemId }
|
||||
|
||||
InfoOverlay(
|
||||
visible = showInfoOverlay,
|
||||
title = animal?.breed ?:"",
|
||||
text = animal?.breedInfo ?: "",
|
||||
onDismiss = { showInfoOverlay = false }
|
||||
)
|
||||
|
||||
ActionPopup(
|
||||
visible = showSavedPopup,
|
||||
text = "Saved",
|
||||
|
|
|
|||
|
|
@ -239,7 +239,7 @@ Column(
|
|||
val needsProfile = signupResponse.needsProfile == true || verifyResponse.needsProfile
|
||||
android.util.Log.d("OTPScreen", "Signup successful. needsProfile=$needsProfile, navigating...")
|
||||
// Refresh auth status - this will trigger navigation via AppNavigation's LaunchedEffect
|
||||
mainViewModel.refreshAuthStatus()
|
||||
// mainViewModel.refreshAuthStatus()
|
||||
try {
|
||||
if (needsProfile) {
|
||||
android.util.Log.d("OTPScreen", "Navigating to create profile screen with name: $name")
|
||||
|
|
@ -247,6 +247,7 @@ Column(
|
|||
} else {
|
||||
// Don't manually navigate - let AppNavigation handle it
|
||||
android.util.Log.d("OTPScreen", "Signup successful - auth state updated, navigation will happen automatically")
|
||||
onSuccess()
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
android.util.Log.e("OTPScreen", "Navigation error: ${e.message}", e)
|
||||
|
|
@ -266,6 +267,7 @@ Column(
|
|||
} else {
|
||||
// Don't manually navigate - let AppNavigation handle it
|
||||
android.util.Log.d("OTPScreen", "Signup successful - auth state updated, navigation will happen automatically")
|
||||
onSuccess()
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
android.util.Log.e("OTPScreen", "Navigation error: ${e.message}", e)
|
||||
|
|
@ -325,7 +327,12 @@ Column(
|
|||
// Tokens are now saved (synchronously via commit())
|
||||
// Refresh auth status - this will optimistically set authState to Authenticated
|
||||
// The LaunchedEffect in AppNavigation will automatically navigate to ChooseServiceScreen
|
||||
mainViewModel.refreshAuthStatus()
|
||||
//mainViewModel.refreshAuthStatus()
|
||||
if(response.needsProfile) {
|
||||
onCreateProfile(name)
|
||||
} else {
|
||||
onSuccess()
|
||||
}
|
||||
android.util.Log.d("OTPScreen", "Auth status refreshed - navigation will happen automatically via LaunchedEffect")
|
||||
}
|
||||
.onFailure { error ->
|
||||
|
|
|
|||
|
|
@ -0,0 +1,156 @@
|
|||
package com.example.livingai_lg.ui.screens.testing
|
||||
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun ApiTestScreen(
|
||||
onBackClick: () -> Unit
|
||||
) {
|
||||
val scope = rememberCoroutineScope()
|
||||
|
||||
// Default API endpoint
|
||||
var apiEndpoint by remember {
|
||||
mutableStateOf("https://jsonplaceholder.typicode.com/posts/1")
|
||||
}
|
||||
|
||||
var isLoading by remember { mutableStateOf(false) }
|
||||
var responseText by remember { mutableStateOf<String?>(null) }
|
||||
var errorText by remember { mutableStateOf<String?>(null) }
|
||||
|
||||
val client = remember { OkHttpClient() }
|
||||
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.background(Color(0xFFF7F4EE))
|
||||
) {
|
||||
// Top App Bar
|
||||
TopAppBar(
|
||||
title = {
|
||||
Text(
|
||||
text = "API Test",
|
||||
fontSize = 20.sp,
|
||||
fontWeight = FontWeight.SemiBold,
|
||||
color = Color.Black
|
||||
)
|
||||
},
|
||||
navigationIcon = {
|
||||
IconButton(onClick = onBackClick) {
|
||||
Icon(
|
||||
imageVector = Icons.AutoMirrored.Filled.ArrowBack,
|
||||
contentDescription = "Back",
|
||||
tint = Color.Black
|
||||
)
|
||||
}
|
||||
},
|
||||
colors = TopAppBarDefaults.topAppBarColors(
|
||||
containerColor = Color(0xFFF7F4EE)
|
||||
)
|
||||
)
|
||||
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(16.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(16.dp)
|
||||
) {
|
||||
|
||||
// API endpoint input
|
||||
OutlinedTextField(
|
||||
value = apiEndpoint,
|
||||
onValueChange = { apiEndpoint = it },
|
||||
label = { Text("API Endpoint") },
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
singleLine = true
|
||||
)
|
||||
|
||||
// Call API button
|
||||
Button(
|
||||
onClick = {
|
||||
scope.launch {
|
||||
isLoading = true
|
||||
responseText = null
|
||||
errorText = null
|
||||
|
||||
try {
|
||||
val result = withContext(Dispatchers.IO) {
|
||||
val request = Request.Builder()
|
||||
.url(apiEndpoint)
|
||||
.get()
|
||||
.build()
|
||||
|
||||
client.newCall(request).execute().use { response ->
|
||||
val body = response.body?.string()
|
||||
Pair(response.code, body)
|
||||
}
|
||||
}
|
||||
|
||||
val (code, body) = result
|
||||
responseText = "Status: $code\n\n$body"
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
errorText = e.toString()
|
||||
} finally {
|
||||
isLoading = false
|
||||
}
|
||||
}
|
||||
},
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
enabled = !isLoading
|
||||
) {
|
||||
Text(if (isLoading) "Calling API..." else "Call API")
|
||||
}
|
||||
|
||||
// Result display
|
||||
when {
|
||||
responseText != null -> {
|
||||
Surface(
|
||||
shape = RoundedCornerShape(12.dp),
|
||||
color = Color.White,
|
||||
shadowElevation = 2.dp,
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
) {
|
||||
Text(
|
||||
text = responseText ?: "",
|
||||
modifier = Modifier.padding(16.dp),
|
||||
fontSize = 14.sp
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
errorText != null -> {
|
||||
Surface(
|
||||
shape = RoundedCornerShape(12.dp),
|
||||
color = Color(0xFFFFEBEE),
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
) {
|
||||
Text(
|
||||
text = errorText ?: "",
|
||||
modifier = Modifier.padding(16.dp),
|
||||
fontSize = 14.sp,
|
||||
color = Color(0xFFE53935)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -12,6 +12,7 @@ navigationCompose = "2.7.7"
|
|||
ktor = "2.3.12"
|
||||
kotlinxSerialization = "1.6.3"
|
||||
securityCrypto = "1.1.0-alpha06"
|
||||
navigationComposeJvmstubs = "2.9.6"
|
||||
|
||||
[libraries]
|
||||
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
|
||||
|
|
@ -42,6 +43,7 @@ kotlinx-serialization-json = { group = "org.jetbrains.kotlinx", name = "kotlinx-
|
|||
|
||||
# AndroidX Security
|
||||
androidx-security-crypto = { group = "androidx.security", name = "security-crypto", version.ref = "securityCrypto" }
|
||||
androidx-navigation-compose-jvmstubs = { group = "androidx.navigation", name = "navigation-compose-jvmstubs", version.ref = "navigationComposeJvmstubs" }
|
||||
|
||||
[plugins]
|
||||
android-application = { id = "com.android.application", version.ref = "agp" }
|
||||
|
|
|
|||
Loading…
Reference in New Issue