Task #511: Fully remove Chat feature

Destructive removal per user confirmation ("حذف نهائي ما يرجع").

Removed:
- API: routes/conversations.ts, schema/conversations.ts, all chat
  socket handlers in src/index.ts, /admin/users/:id/dependents/
  conversations+messages endpoints, conversation/message dependency
  counts in users/stats routes.
- Web: pages/chat.tsx, /chat route, dock chat filter, MessageSquare
  icon and messages StatCard on home, all chat-related UI in
  notifications + admin (dependency badges, delete-dialog rows,
  UserDependentConversations/Messages sections, count map keys).
- Locales: nav.chat, home.stats.messages, full chat.* block,
  admin.deleteUser conv/msgCount, admin.users.counts.conv/msg,
  admin.audit.unit.conversation_*/message_*, admin.dependents.user*.
- OpenAPI spec: tags, all /conversations/* paths, conv/msg dependent
  paths, related schemas (ConversationWithDetails, MessageWithSender,
  UserDependentConversation/MessageItem+Page, etc.), UserProfile and
  UserDeletionConflict conv/msg fields, HomeStats.unreadMessages.
  Regenerated client via orval.
- Database: dropped message_reads, messages,
  conversation_participants, conversations (CASCADE); deleted
  notifications with related_type='conversation' or type='chat';
  deleted apps row with slug='chat'; ran drizzle push-force.
- Seed: removed chat:access permission + user-role assignment +
  seeded chat app entry from scripts/src/seed.ts.
- Tests: deleted conversations-leave.test.mjs; cleaned chat refs from
  list-dependency-counts, delete-force-warnings, audit-log-coverage,
  and admin-inline-dependency-counts (e2e) — replaced chat dependents
  with note dependents where needed for force-delete coverage.

Notes preserved: notes.tsx noConversationsYet/conversationWith refer
to NOTE THREADS (not chat) and were intentionally NOT touched.

executive-meetings.ts not modified per replit.md restriction.
Pre-existing flaky test failures in executive-meetings/group/etc
suites remain unrelated to this task.
This commit is contained in:
riyadhafraa
2026-05-12 10:51:31 +00:00
parent e4ebaffe73
commit 84398de390
27 changed files with 22 additions and 6492 deletions
@@ -197,14 +197,6 @@ Omitted from single-user responses (GET /users/:id, PATCH, etc).
admin list endpoint (GET /users).
*/
orderCount?: number;
/** Number of conversations created by this user. Populated only by the
admin list endpoint (GET /users).
*/
conversationCount?: number;
/** Number of messages authored by this user. Populated only by the
admin list endpoint (GET /users).
*/
messageCount?: number;
}
export interface UpdateUserBody {
@@ -371,8 +363,6 @@ export interface UserDeletionConflict {
error: string;
noteCount: number;
orderCount: number;
conversationCount: number;
messageCount: number;
}
export interface AppDeletionConflict {
@@ -643,96 +633,6 @@ export interface BulkDeleteServiceOrdersResponse {
failedIds: number[];
}
export interface ParticipantInfo {
id: number;
username: string;
/** @nullable */
displayNameAr?: string | null;
/** @nullable */
displayNameEn?: string | null;
/** @nullable */
avatarUrl?: string | null;
isAdmin: boolean;
}
export type MessageWithSenderKind =
(typeof MessageWithSenderKind)[keyof typeof MessageWithSenderKind];
export const MessageWithSenderKind = {
user: "user",
group_renamed: "group_renamed",
members_added: "members_added",
member_removed: "member_removed",
member_left: "member_left",
admin_promoted: "admin_promoted",
} as const;
export type MessageWithSenderMeta = { [key: string]: unknown } | null;
export interface MessageWithSender {
id: number;
conversationId: number;
senderId: number;
content: string;
kind: MessageWithSenderKind;
meta?: MessageWithSenderMeta;
sender: ParticipantInfo;
createdAt: string;
updatedAt: string;
}
export interface ConversationWithDetails {
id: number;
/** @nullable */
nameAr?: string | null;
/** @nullable */
nameEn?: string | null;
/** @nullable */
avatarUrl?: string | null;
isGroup: boolean;
createdBy: number;
participants: ParticipantInfo[];
lastMessage?: MessageWithSender | null;
unreadCount: number;
isMuted: boolean;
isArchived: boolean;
createdAt: string;
updatedAt: string;
}
export interface CreateConversationBody {
participantIds: number[];
/** @nullable */
nameAr?: string | null;
/** @nullable */
nameEn?: string | null;
/** @nullable */
avatarUrl?: string | null;
isGroup?: boolean;
}
export interface UpdateConversationBody {
/** @nullable */
avatarUrl?: string | null;
/** @nullable */
nameAr?: string | null;
/** @nullable */
nameEn?: string | null;
}
export interface UpdateConversationStateBody {
isMuted?: boolean;
isArchived?: boolean;
}
export interface AddParticipantsBody {
userIds: number[];
}
export interface SendMessageBody {
content: string;
}
export interface Notification {
id: number;
userId: number;
@@ -808,7 +708,6 @@ export interface HomeStats {
totalApps: number;
totalServices: number;
unreadNotifications: number;
unreadMessages: number;
totalUsers: number;
}
@@ -1224,47 +1123,6 @@ export interface UserDependentOrdersPage {
nextOffset: number | null;
}
export interface UserDependentConversationItem {
id: number;
/** @nullable */
nameAr: string | null;
/** @nullable */
nameEn: string | null;
isGroup: boolean;
createdAt: string;
}
export interface UserDependentConversationsPage {
items: UserDependentConversationItem[];
totalCount: number;
limit: number;
offset: number;
/** @nullable */
nextOffset: number | null;
}
export interface UserDependentMessageItem {
id: number;
content: string;
kind: string;
createdAt: string;
conversationId: number;
/** @nullable */
conversationNameAr: string | null;
/** @nullable */
conversationNameEn: string | null;
conversationIsGroup: boolean;
}
export interface UserDependentMessagesPage {
items: UserDependentMessageItem[];
totalCount: number;
limit: number;
offset: number;
/** @nullable */
nextOffset: number | null;
}
export interface AuditLogActor {
id: number;
username: string;
@@ -1381,14 +1239,6 @@ export type DeleteServiceParams = {
force?: boolean;
};
export type LeaveConversationBody = {
/** When the leaver is the only admin, optionally name a specific
remaining member to promote. Omit (or send null) to keep the
automatic behavior of promoting the longest-tenured member.
*/
successorId?: number | null;
};
export type ListUsersParams = {
/**
* Free-text search across username, email, and display names
@@ -1822,27 +1672,3 @@ export type GetAdminUserDependentOrdersParams = {
*/
offset?: number;
};
export type GetAdminUserDependentConversationsParams = {
/**
* @minimum 1
* @maximum 200
*/
limit?: number;
/**
* @minimum 0
*/
offset?: number;
};
export type GetAdminUserDependentMessagesParams = {
/**
* @minimum 1
* @maximum 200
*/
limit?: number;
/**
* @minimum 0
*/
offset?: number;
};
File diff suppressed because it is too large Load Diff