Skip to content
Merged
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
2 changes: 1 addition & 1 deletion .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: Deploy to EC2
on:
push:
branches:
- fcm
- member-setting
- prod
paths:
- 'backend/**'
Expand Down
36 changes: 35 additions & 1 deletion backend/src/controllers/group.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ export class GroupController {
}
}

async updateGroupByJoinCode(
async joinGroupByJoinCode(
req: Request<unknown, unknown, UpdateGroupRequest>,
res: Response<GetGroupResponse>,
next: NextFunction
Expand Down Expand Up @@ -210,6 +210,40 @@ export class GroupController {
}
}

async updateGroupByJoinCode(
req: Request<unknown, unknown, UpdateGroupRequest>,
res: Response<GetGroupResponse>,
next: NextFunction
) {
try {
const {joinCode, expectedPeople, groupMemberIds, meetingTime} = req.body;
const updatedGroup = await groupModel.updateGroupByJoinCode(joinCode,
{joinCode, expectedPeople,
groupMemberIds: groupMemberIds || [], meetingTime});

if (!updatedGroup) {
return res.status(404).json({
message: 'Group not found',
});
}

res.status(200).json({
message: 'Group info updated successfully',
data: { group: updatedGroup },
});
} catch (error) {
logger.error('Failed to update group info:', error);

if (error instanceof Error) {
return res.status(500).json({
message: error.message || 'Failed to update group info',
});
}

next(error);
}
}

async deleteGroupByJoinCode(
req: Request<{joinCode: string}>,
res: Response,
Expand Down
7 changes: 6 additions & 1 deletion backend/src/routes/group.routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ router.post( //have seperate endpoint for updating?
);

router.post( //have seperate endpoint for updating?
'/join',
validateBody<UpdateGroupRequest>(updateGroupSchema), // Validate the request body
groupController.joinGroupByJoinCode.bind(groupController)
);

router.post(
'/update',
validateBody<UpdateGroupRequest>(updateGroupSchema), // Validate the request body
groupController.updateGroupByJoinCode.bind(groupController)
Expand All @@ -35,7 +41,6 @@ router.get(
groupController.getMidpointByJoinCode.bind(groupController)
);


router.post(
'/leave/:joinCode', // Define the route parameter
groupController.leaveGroup.bind(groupController) // Bind the controller method
Expand Down
1 change: 1 addition & 0 deletions backend/src/types/group.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ export const updateGroupSchema = z.object({
address: addressSchema.optional(),
transitType: transitTypeSchema.optional()
})).optional(),
meetingTime: z.string().optional(),
midpoint: z.string().default('').optional()
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,18 @@ interface GroupInterface {
@retrofit2.http.Path("joinCode") joinCode: String
): Response<ApiResponse<SquadGoal>>

@POST("group/update")
@POST("group/join")
suspend fun joinGroup(
@Header("Authorization") authHeader: String,
@Body request: UpdateGroupRequest
): Response<Unit>

@POST("group/update")
suspend fun updateGroup(
@Header("Authorization") authHeader: String,
@Body request: UpdateGroupRequest
): Response<Unit>

@DELETE("group/delete/{joinCode}")
suspend fun deleteGroup(
@Header("Authorization") authHeader: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ data class CreateGroupRequest(
data class UpdateGroupRequest(
val joinCode: String? = null,
val expectedPeople: Number? = null,
val groupMemberIds: List<GroupUser>?= null
val groupMemberIds: List<GroupUser>?= null,
val meetingTime: String? = null
)

data class LeaveGroupRequest(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,14 @@ interface GroupRepository {
suspend fun joinGroup(
joinCode: String,
expectedPeople: Number,
updatedMembers: List<GroupUser>
updatedMembers: List<GroupUser>,
): Result<Unit> //add exp members later
suspend fun updateGroup(
joinCode: String,
expectedPeople: Number?,
updatedMembers: List<GroupUser>?,
meetingTime: String?
): Result<Unit>
suspend fun getMidpointByJoinCode(joinCode: String): Result<SquadGoal>

suspend fun leaveGroup(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.cpen321.squadup.data.repository

import android.health.connect.ReadRecordsRequestUsingIds
import android.util.Log
import com.cpen321.squadup.data.local.preferences.TokenManager
import com.cpen321.squadup.data.remote.api.GroupInterface
Expand Down Expand Up @@ -144,6 +145,38 @@ class GroupRepositoryImpl @Inject constructor(
}
}

override suspend fun updateGroup(
joinCode: String,
expectedPeople: Number?,
updatedMembers: List<GroupUser>?,
meetingTime: String?
): Result<Unit> {
return try {
val authToken = tokenManager.getToken() ?: ""
val request = UpdateGroupRequest(
joinCode = joinCode,
expectedPeople = expectedPeople,
groupMemberIds = updatedMembers,
meetingTime = meetingTime
)
Log.d(TAG, "GroupRepImpl updateGroupRequest ${request}")
val response = groupInterface.updateGroup(
authHeader = "Bearer $authToken",
request = request
)
Log.d(TAG, "GroupRepImpl updateGroupRequest response ${response}")
if (response.isSuccessful) {
Result.success(Unit)
} else {
val errorBodyString = response.errorBody()?.string()
val errorMessage = parseErrorMessage(errorBodyString, "Failed to join group.")
Result.failure(Exception(errorMessage))
}
} catch (e: Exception) {
Result.failure(e)
}
}

override suspend fun getMidpointByJoinCode(joinCode: String): Result<SquadGoal> {
return try {
val authToken = tokenManager.getToken() ?: ""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import com.cpen321.squadup.ui.screens.ProfileScreenActions
import com.cpen321.squadup.ui.screens.ProfileCompletionScreen
import com.cpen321.squadup.ui.screens.ProfileScreen
import com.cpen321.squadup.ui.screens.JoinGroupScreen
import com.cpen321.squadup.ui.screens.MemberSettingsScreen
import com.cpen321.squadup.ui.viewmodels.AuthViewModel
import com.cpen321.squadup.ui.viewmodels.MainViewModel
import com.cpen321.squadup.ui.viewmodels.NavigationViewModel
Expand All @@ -43,7 +44,8 @@ object NavRoutes {
const val PROFILE_COMPLETION = "profile_completion"
const val GROUP_DETAILS = "group_details"
const val GROUP_LIST = "group_list"
const val JOIN_GROUP = "join_group"
const val JOIN_GROUP = "join_group"
const val MEMBER_SETTINGS = "member_settings"
}

@Composable
Expand Down Expand Up @@ -235,7 +237,8 @@ private fun AppNavHost(
actions = ProfileScreenActions(
onBackClick = { navigationStateManager.navigateBack() },
onManageProfileClick = { navigationStateManager.navigateToManageProfile() },
onAccountDeleted = { navigationStateManager.handleAccountDeletion() }
onAccountDeleted = { navigationStateManager.handleAccountDeletion() },
onAccountLogOut = { navigationStateManager.handleAccountLogOut() }
)
)
}
Expand Down Expand Up @@ -290,14 +293,28 @@ private fun AppNavHost(
}
}

composable("${NavRoutes.MEMBER_SETTINGS}/{joinCode}") { backStackEntry ->
val joinCode = backStackEntry.arguments?.getString("joinCode") ?: ""
val group = mainViewModel.getGroupById(joinCode)

group?.let {
MemberSettingsScreen(
navController = navController,
group = group,
groupViewModel = groupViewModel,
profileViewModel = profileViewModel
)
}
}

composable(NavRoutes.JOIN_GROUP) {
JoinGroupScreen(
navController = navController,
mainViewModel = mainViewModel,
navController = navController,
mainViewModel = mainViewModel,
profileViewModel = profileViewModel,

)
}
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,20 @@ class NavigationStateManager @Inject constructor() {
navigateToAuthWithMessage("Account deleted successfully!")
}

/**
* Handle account deletion
*/
fun handleAccountLogOut() {
_navigationState.value = _navigationState.value.copy(isNavigating = true)

updateAuthenticationState(
isAuthenticated = false,
needsProfileCompletion = false,
isLoading = false
)
navigateToAuthWithMessage("Account logged out successfully!")
}

/**
* Handle profile completion
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ fun GroupDetailsScreen(
}
},
navigationIcon = {
IconButton(onClick = { navController.navigateUp() }) {
IconButton(onClick = { navController.navigate(NavRoutes.MAIN) }){
Icon(Icons.Default.ArrowBack, contentDescription = "Back")
}
}
Expand Down Expand Up @@ -250,7 +250,7 @@ fun GroupDetailsScreen(

// See Details button
Button(
onClick = { // Suppose you already have the group object
onClick = {
navController.navigate("${NavRoutes.GROUP_LIST}/${group.joinCode}")
},
modifier = Modifier
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,9 @@ fun GroupListScreen(
)
},
navigationIcon = {
IconButton(onClick = { navController.navigateUp() }) {
IconButton(onClick = {
navController.navigate("${NavRoutes.GROUP_DETAILS}/${group.joinCode}")
},) {
Icon(Icons.Default.ArrowBack, contentDescription = "Back")
}
},
Expand Down Expand Up @@ -111,7 +113,7 @@ fun GroupListScreen(
)
NavigationBarItem(
selected = false,
onClick = { navController.navigate(NavRoutes.PROFILE) },
onClick = {navController.navigate("${NavRoutes.MEMBER_SETTINGS}/${group.joinCode}") },
icon = { Icon(Icons.Default.Settings, contentDescription = "Settings") },
label = { Text("Settings") }
)
Expand Down
Loading