diff --git a/be/app/api/v1/endpoints/groups.py b/be/app/api/v1/endpoints/groups.py index 64248f2..6e2acbc 100644 --- a/be/app/api/v1/endpoints/groups.py +++ b/be/app/api/v1/endpoints/groups.py @@ -13,6 +13,7 @@ from app.schemas.invite import InviteCodePublic from app.schemas.message import Message # For simple responses from app.schemas.list import ListPublic, ListDetail from app.schemas.chore import ChoreHistoryPublic, ChoreAssignmentPublic +from app.schemas.user import UserPublic from app.crud import group as crud_group from app.crud import invite as crud_invite from app.crud import list as crud_list @@ -92,6 +93,33 @@ async def read_group( return group +@router.get( + "/{group_id}/members", + response_model=List[UserPublic], + summary="Get Group Members", + tags=["Groups"] +) +async def read_group_members( + group_id: int, + db: AsyncSession = Depends(get_session), # Use read-only session for GET + current_user: UserModel = Depends(current_active_user), +): + """Retrieves all members of a specific group, if the user is part of it.""" + logger.info(f"User {current_user.email} requesting members for group ID: {group_id}") + + # Check if user is a member first + is_member = await crud_group.is_user_member(db=db, group_id=group_id, user_id=current_user.id) + if not is_member: + logger.warning(f"Access denied: User {current_user.email} not member of group {group_id}") + raise GroupMembershipError(group_id, "view group members") + + group = await crud_group.get_group_by_id(db=db, group_id=group_id) + if not group: + logger.error(f"Group {group_id} requested by member {current_user.email} not found (data inconsistency?)") + raise GroupNotFoundError(group_id) + + # Extract and return just the user information from member associations + return [member_assoc.user for member_assoc in group.member_associations] @router.post( "/{group_id}/invites", diff --git a/fe/src/assets/valerie-ui.scss b/fe/src/assets/valerie-ui.scss index 95455cf..b2d5539 100644 --- a/fe/src/assets/valerie-ui.scss +++ b/fe/src/assets/valerie-ui.scss @@ -81,7 +81,8 @@ body { font-family: 'Patrick Hand', cursive; background-color: var(--light); - background-image: var(--paper-texture); + // background-image: var(--paper-texture); + // background-image: url('@/assets/11.webp'); // padding: 2rem 1rem;s color: var(--dark); font-size: 1.1rem; diff --git a/fe/src/i18n/en.json b/fe/src/i18n/en.json index d81ccf4..8d7a972 100644 --- a/fe/src/i18n/en.json +++ b/fe/src/i18n/en.json @@ -97,6 +97,8 @@ "addChore": "+", "edit": "Edit", "delete": "Delete", + "editChore": "Edit Chore", + "createChore": "Create Chore", "empty": { "title": "No Chores Yet", "message": "Get started by adding your first chore!", @@ -170,6 +172,23 @@ "loadingLabel": "Loading group details...", "retryButton": "Retry", "groupNotFound": "Group not found or an error occurred.", + "lists": { + "title": "Group Lists" + }, + "generateScheduleModal": { + "title": "Generate Schedule" + }, + "activityLog": { + "title": "Activity Log", + "emptyState": "No activity to show yet." + }, + "chores": { + "title": "Group Chores", + "manageButton": "Manage Chores", + "duePrefix": "Due:", + "emptyState": "No chores scheduled. Click \"Manage Chores\" to create some!", + "generateScheduleButton": "Generate Schedule" + }, "members": { "title": "Group Members", "defaultRole": "Member", @@ -201,12 +220,6 @@ "console": { "noActiveInvite": "No active invite code found for this group." }, - "chores": { - "title": "Group Chores", - "manageButton": "Manage Chores", - "duePrefix": "Due:", - "emptyState": "No chores scheduled. Click \"Manage Chores\" to create some!" - }, "expenses": { "title": "Group Expenses", "manageButton": "Manage Expenses", @@ -445,6 +458,8 @@ "addExpenseButton": "Add Expense", "loading": "Loading expenses...", "emptyState": "No expenses recorded for this list yet.", + "emptyStateTitle": "No Expenses", + "emptyStateMessage": "Add your first expense to get started.", "paidBy": "Paid by:", "onDate": "on", "owes": "owes", diff --git a/fe/src/i18n/nl.json b/fe/src/i18n/nl.json index ce065d1..365e490 100644 --- a/fe/src/i18n/nl.json +++ b/fe/src/i18n/nl.json @@ -94,6 +94,11 @@ }, "choresPage": { "title": "Taken", + "addChore": "+", + "edit": "Bewerken", + "delete": "Verwijderen", + "editChore": "Taak bewerken", + "createChore": "Nieuwe taak", "tabs": { "overdue": "Achterstallig", "today": "Vandaag", @@ -339,6 +344,16 @@ "partiallyPaid": "Gedeeltelijk betaald", "unpaid": "Onbetaald", "unknown": "Onbekende status" + }, + "lists": { + "title": "Groepslijsten" + }, + "generateScheduleModal": { + "title": "Schema genereren" + }, + "activityLog": { + "title": "Activiteitenlogboek", + "emptyState": "Nog geen activiteiten om weer te geven." } }, "accountPage": { diff --git a/fe/src/pages/ListDetailPage.vue b/fe/src/pages/ListDetailPage.vue index 10e8657..7233852 100644 --- a/fe/src/pages/ListDetailPage.vue +++ b/fe/src/pages/ListDetailPage.vue @@ -316,22 +316,23 @@
-

{{ $t('listDetailPage.costSummaryModal.totalCostLabel') }} {{ +

{{ $t('listDetailPage.modals.costSummary.totalCostLabel') }} {{ formatCurrency(listCostSummary.total_list_cost) }}

-

{{ $t('listDetailPage.costSummaryModal.equalShareLabel') }} {{ +

{{ $t('listDetailPage.modals.costSummary.equalShareLabel') }} {{ formatCurrency(listCostSummary.equal_share_per_user) }}

-

{{ $t('listDetailPage.costSummaryModal.participantsLabel') }} {{ +

{{ $t('listDetailPage.modals.costSummary.participantsLabel') }} {{ listCostSummary.num_participating_users }}

-

{{ $t('listDetailPage.costSummaryModal.userBalancesHeader') }}

+

{{ $t('listDetailPage.modals.costSummary.userBalancesHeader') }}

- - - - + + + + @@ -348,7 +349,7 @@
{{ $t('listDetailPage.costSummaryModal.tableHeaders.user') }}{{ $t('listDetailPage.costSummaryModal.tableHeaders.itemsAddedValue') }}{{ $t('listDetailPage.costSummaryModal.tableHeaders.amountDue') }}{{ $t('listDetailPage.costSummaryModal.tableHeaders.balance') }}{{ $t('listDetailPage.modals.costSummary.tableHeaders.user') }}{{ $t('listDetailPage.modals.costSummary.tableHeaders.itemsAddedValue') }} + {{ $t('listDetailPage.modals.costSummary.tableHeaders.amountDue') }}{{ $t('listDetailPage.modals.costSummary.tableHeaders.balance') }}
-

{{ $t('listDetailPage.costSummaryModal.emptyState') }}

+

{{ $t('listDetailPage.modals.costSummary.emptyState') }}