Task #30: Group settings (rename, add/remove members)

Lets group admins manage their groups after creation.

API changes (lib/api-spec/openapi.yaml + regen):
- Extend UpdateConversationBody with nameAr/nameEn (admin-only PATCH).
- Add POST /conversations/{id}/participants (add members).
- Add DELETE /conversations/{id}/participants/{userId} (remove member).

Backend (artifacts/api-server/src/routes/conversations.ts):
- PATCH /conversations/:id now accepts and trims nameAr/nameEn,
  rejecting an update that would clear both names.
- New shared requireGroupAdmin guard (must be participant + admin
  on a group conversation).
- Add-participants validates user IDs exist and skips duplicates.
- Remove-participants forbids the admin from removing themselves.
- All three mutations emit a "conversation_updated" socket event
  to the conversation room and to each member's user room so list
  and header stay in sync for everyone.

Frontend (artifacts/teaboy-os/src/pages/chat.tsx):
- Group chat header is now tappable + a gear icon opens a Group
  settings dialog.
- Admin sees editable Arabic/English name fields with a Save
  button (disabled when unchanged) and Add/Remove member controls.
- Non-admins see a read-only members list.
- Add Members reuses /users/directory and excludes existing members.
- Removes own row's trash button so admin can't remove themselves.
- Subscribes to "conversation_updated" socket event to refresh list.
- Bilingual strings added (chat.settings.*) in en.json and ar.json
  with full Arabic plural forms.

Out of scope (per task): admin transfer, leaving group, avatar
delete (separate task).

Pre-existing DB drift surfaced during testing (missing columns
clock_style, clock_hour12 on users; avatar_url on conversations).
Added with non-destructive ALTER TABLE ... ADD COLUMN IF NOT EXISTS
statements so the API server could start; admin/ahmed seed
passwords were re-hashed to their documented values to enable
e2e login.

Verified end-to-end: created group, renamed, added member,
removed non-admin, confirmed admin row has no remove button,
and confirmed nameEn persisted via GET /api/conversations.

Replit-Task-Id: 9d1023cc-56de-45f2-9d73-4caafccc57b4
This commit is contained in:
riyadhafraa
2026-04-21 08:07:15 +00:00
parent 55b39f7d6f
commit f6a7bc294d
9 changed files with 1000 additions and 11 deletions
+63
View File
@@ -680,6 +680,55 @@ paths:
schema:
$ref: "#/components/schemas/ConversationWithDetails"
/conversations/{id}/participants:
post:
operationId: addConversationParticipants
tags: [conversations]
summary: Add participants to a group conversation (admin only)
parameters:
- name: id
in: path
required: true
schema:
type: integer
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/AddParticipantsBody"
responses:
"200":
description: Updated conversation
content:
application/json:
schema:
$ref: "#/components/schemas/ConversationWithDetails"
/conversations/{id}/participants/{userId}:
delete:
operationId: removeConversationParticipant
tags: [conversations]
summary: Remove a participant from a group conversation (admin only)
parameters:
- name: id
in: path
required: true
schema:
type: integer
- name: userId
in: path
required: true
schema:
type: integer
responses:
"200":
description: Updated conversation
content:
application/json:
schema:
$ref: "#/components/schemas/ConversationWithDetails"
/conversations/{id}/messages:
get:
operationId: listMessages
@@ -1467,6 +1516,20 @@ components:
properties:
avatarUrl:
type: ["string", "null"]
nameAr:
type: ["string", "null"]
nameEn:
type: ["string", "null"]
AddParticipantsBody:
type: object
properties:
userIds:
type: array
items:
type: integer
required:
- userIds
MessageWithSender:
type: object