Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.staggeredgrid.rememberLazyStaggeredGridState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import com.cornellappdev.resell.android.R
Expand All @@ -18,6 +21,7 @@ import com.cornellappdev.resell.android.ui.components.profile.ProfileEmptyState
import com.cornellappdev.resell.android.ui.components.profile.ProfileHeader
import com.cornellappdev.resell.android.ui.components.profile.ResellRequestsScroll
import com.cornellappdev.resell.android.ui.theme.simpleFadeInOut
import com.cornellappdev.resell.android.util.LocalInfiniteShimmer
import com.cornellappdev.resell.android.viewmodel.main.ProfileViewModel

@Composable
Expand All @@ -37,10 +41,13 @@ fun ProfileScreen(
vendorName = uiState.vendorName,
bio = uiState.bio,
selectedTab = uiState.profileTab,
rightIcon = R.drawable.ic_settings,
leftIcon = R.drawable.ic_settings,
rightIcon = R.drawable.ic_calendar,
onTabSelected = { profileViewModel.onTabSelected(it) },
onRightPressed = { profileViewModel.onSettingsPressed() },
)
onLeftPressed = { profileViewModel.onSettingsPressed() },
onRightPressed = { profileViewModel.onCalendarPressed() },
Comment on lines +45 to +48
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Calendar button is likely announced with the wrong accessibility label.

With rightIcon = R.drawable.ic_calendar at Line 45, the current ProfileHeader implementation (see app/src/main/java/com/cornellappdev/resell/android/ui/components/profile/ProfileHeader.kt:73-88) still uses a hardcoded contentDescription = "search" for the right icon. This is an accessibility defect for screen-reader users.

Consider making icon descriptions configurable from ProfileScreen or updating ProfileHeader to use calendar-specific text in this path.

Suggested direction
- Icon(
-     painter = painterResource(id = rightIcon),
-     contentDescription = "search",
+ Icon(
+     painter = painterResource(id = rightIcon),
+     contentDescription = rightIconContentDescription,
      modifier = Modifier
          .size(25.dp)
          .clickableNoIndication { onRightPressed() }
 )

Then pass "Availability" (or a string resource) from ProfileScreen.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@app/src/main/java/com/cornellappdev/resell/android/ui/screens/main/ProfileScreen.kt`
around lines 45 - 48, ProfileHeader is using a hardcoded contentDescription
"search" for the right icon causing the calendar button in ProfileScreen (where
rightIcon = R.drawable.ic_calendar and onRightPressed =
profileViewModel.onCalendarPressed) to be announced incorrectly; update
ProfileHeader to accept a configurable contentDescription parameter (e.g.,
rightIconContentDescription) and use it instead of the hardcoded string, then
pass a calendar-specific string (or string resource like "Availability") from
ProfileScreen when constructing ProfileHeader so the right icon is accessible
and correctly labeled.


)

AnimatedContent(
targetState = uiState.profileTab,
Expand Down Expand Up @@ -147,3 +154,22 @@ fun ProfileScreen(
}
}
}

@Preview(showBackground = true)
@Composable
fun ProfileScreenPreview() {
CompositionLocalProvider(value = LocalInfiniteShimmer provides Color.LightGray) {
ProfileHeader(
imageUrl = "",
shopName = "ravina.shop",
vendorName = "Ravina Patel",
bio = "selling jin's stuff! selling jin's stuff!",
selectedTab = ProfileViewModel.ProfileTab.SHOP,
leftIcon = R.drawable.ic_settings,
rightIcon = R.drawable.ic_calendar,
onTabSelected = {},
onLeftPressed = {},
onRightPressed = {}
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import com.cornellappdev.resell.android.model.core.UserInfoRepository
import com.cornellappdev.resell.android.model.login.GoogleAuthRepository
import com.cornellappdev.resell.android.model.profile.ProfileRepository
import com.cornellappdev.resell.android.model.settings.BlockedUsersRepository
import com.cornellappdev.resell.android.ui.components.availability.helper.GridSelectionType
import com.cornellappdev.resell.android.ui.components.global.ResellTextButtonContainer
import com.cornellappdev.resell.android.ui.components.global.ResellTextButtonState
import com.cornellappdev.resell.android.ui.screens.root.ResellRootRoute
Expand All @@ -18,7 +19,9 @@ import com.cornellappdev.resell.android.viewmodel.navigation.RootNavigationRepos
import com.cornellappdev.resell.android.viewmodel.root.RootConfirmationRepository
import com.cornellappdev.resell.android.viewmodel.root.RootDialogContent
import com.cornellappdev.resell.android.viewmodel.root.RootDialogRepository
import com.cornellappdev.resell.android.viewmodel.root.RootNavigationSheetRepository
import com.cornellappdev.resell.android.viewmodel.root.RootOptionsMenuRepository
import com.cornellappdev.resell.android.viewmodel.root.RootSheet
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch
import kotlinx.serialization.encodeToString
Expand All @@ -31,8 +34,9 @@ class ProfileViewModel @Inject constructor(
private val rootDialogRepository: RootDialogRepository,
private val rootConfirmationRepository: RootConfirmationRepository,
private val profileRepository: ProfileRepository,
private val userInfoRepository: UserInfoRepository
) : ResellViewModel<ProfileViewModel.ProfileUiState>(
private val userInfoRepository: UserInfoRepository,
private val rootNavigationSheetRepository: RootNavigationSheetRepository // add this
): ResellViewModel<ProfileViewModel.ProfileUiState>(
initialUiState = ProfileUiState(
profileTab = ProfileTab.SHOP,
loadedState = ResellApiState.Loading,
Expand Down Expand Up @@ -86,6 +90,18 @@ class ProfileViewModel @Inject constructor(
fun onSettingsPressed() {
rootNavigationRepository.navigate(ResellRootRoute.SETTINGS)
}
fun onCalendarPressed() {
rootNavigationSheetRepository.showBottomSheet(
RootSheet.Availability(
buttonString = "Propose",
title = "Availability",
description = "Propose a time to meet",
initialTimes = listOf(),
gridSelectionType = GridSelectionType.PROPOSAL,
callback = { /* TODO: handle selected times */ }
)
Comment on lines +93 to +102
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Propose action is wired to a no-op callback.

At Line 101, the availability sheet’s primary action currently does nothing (callback = { /* TODO... */ }). This creates a dead-end flow after user selection. Please either implement handling of selected times now or hide/disable this action until behavior is ready.

Would you like me to draft a concrete callback implementation once you confirm the intended persistence path (local state vs API update)?

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@app/src/main/java/com/cornellappdev/resell/android/viewmodel/main/ProfileViewModel.kt`
around lines 93 - 102, The Availability sheet opened in onCalendarPressed uses
RootSheet.Availability with callback = { /* TODO */ }, leaving the Propose
action as a no-op; replace this no-op with a real handler that accepts the
selected times, e.g. validate/format the times, persist them to the chosen layer
(call your ProfileRepository.updateAvailability(...) or update local ViewModel
state), close the sheet via rootNavigationSheetRepository.dismissBottomSheet()
and surface success/error to the UI, or if you cannot implement persistence yet,
disable or hide the primary button on RootSheet.Availability until a proper
callback is provided.

)
}

fun onRequestPressed(request: RequestListing) {
rootNavigationRepository.navigate(
Expand Down
18 changes: 8 additions & 10 deletions app/src/main/res/drawable/ic_calendar.xml
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="22.666666dp" android:viewportHeight="17" android:viewportWidth="18" android:width="24dp">

<path android:fillColor="#00000000" android:pathData="M13.958,2.833H4.042C3.259,2.833 2.625,3.468 2.625,4.25V14.167C2.625,14.949 3.259,15.583 4.042,15.583H13.958C14.741,15.583 15.375,14.949 15.375,14.167V4.25C15.375,3.468 14.741,2.833 13.958,2.833Z" android:strokeColor="#000000" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="1.2"/>

<path android:fillColor="#00000000" android:pathData="M11.833,1.416V4.25" android:strokeColor="#000000" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="1.2"/>

<path android:fillColor="#00000000" android:pathData="M6.167,1.416V4.25" android:strokeColor="#000000" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="1.2"/>

<path android:fillColor="#00000000" android:pathData="M2.625,7.083H15.375" android:strokeColor="#000000" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="1.2"/>

<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="20dp"
android:height="19dp"
android:viewportWidth="20"
android:viewportHeight="19">
<path
android:pathData="M3.203,18.232C1.094,18.232 0,17.148 0,15.059V3.174C0,1.084 1.094,0 3.203,0H16.641C18.75,0 19.844,1.084 19.844,3.174V15.059C19.844,17.139 18.75,18.232 16.641,18.232H3.203ZM3.174,16.318H16.65C17.471,16.318 17.93,15.889 17.93,15.039V6.016C17.93,5.156 17.471,4.736 16.65,4.736H3.174C2.363,4.736 1.914,5.156 1.914,6.016V15.039C1.914,15.889 2.363,16.318 3.174,16.318ZM8.037,8.125C7.695,8.125 7.578,8.018 7.578,7.666V7.1C7.578,6.748 7.695,6.641 8.037,6.641H8.613C8.965,6.641 9.082,6.748 9.082,7.1V7.666C9.082,8.018 8.965,8.125 8.613,8.125H8.037ZM11.24,8.125C10.889,8.125 10.771,8.018 10.771,7.666V7.1C10.771,6.748 10.889,6.641 11.24,6.641H11.807C12.158,6.641 12.275,6.748 12.275,7.1V7.666C12.275,8.018 12.158,8.125 11.807,8.125H11.24ZM14.434,8.125C14.082,8.125 13.965,8.018 13.965,7.666V7.1C13.965,6.748 14.082,6.641 14.434,6.641H15C15.352,6.641 15.469,6.748 15.469,7.1V7.666C15.469,8.018 15.352,8.125 15,8.125H14.434ZM4.844,11.269C4.502,11.269 4.385,11.162 4.385,10.811V10.244C4.385,9.893 4.502,9.785 4.844,9.785H5.42C5.771,9.785 5.889,9.893 5.889,10.244V10.811C5.889,11.162 5.771,11.269 5.42,11.269H4.844ZM8.037,11.269C7.695,11.269 7.578,11.162 7.578,10.811V10.244C7.578,9.893 7.695,9.785 8.037,9.785H8.613C8.965,9.785 9.082,9.893 9.082,10.244V10.811C9.082,11.162 8.965,11.269 8.613,11.269H8.037ZM11.24,11.269C10.889,11.269 10.771,11.162 10.771,10.811V10.244C10.771,9.893 10.889,9.785 11.24,9.785H11.807C12.158,9.785 12.275,9.893 12.275,10.244V10.811C12.275,11.162 12.158,11.269 11.807,11.269H11.24ZM14.434,11.269C14.082,11.269 13.965,11.162 13.965,10.811V10.244C13.965,9.893 14.082,9.785 14.434,9.785H15C15.352,9.785 15.469,9.893 15.469,10.244V10.811C15.469,11.162 15.352,11.269 15,11.269H14.434ZM4.844,14.414C4.502,14.414 4.385,14.307 4.385,13.955V13.389C4.385,13.037 4.502,12.93 4.844,12.93H5.42C5.771,12.93 5.889,13.037 5.889,13.389V13.955C5.889,14.307 5.771,14.414 5.42,14.414H4.844ZM8.037,14.414C7.695,14.414 7.578,14.307 7.578,13.955V13.389C7.578,13.037 7.695,12.93 8.037,12.93H8.613C8.965,12.93 9.082,13.037 9.082,13.389V13.955C9.082,14.307 8.965,14.414 8.613,14.414H8.037ZM11.24,14.414C10.889,14.414 10.771,14.307 10.771,13.955V13.389C10.771,13.037 10.889,12.93 11.24,12.93H11.807C12.158,12.93 12.275,13.037 12.275,13.389V13.955C12.275,14.307 12.158,14.414 11.807,14.414H11.24Z"
android:fillColor="#000000"/>
</vector>