fix: repair invite links, social features, messaging + Discord UI overhaul
Phase 1 - Feature Repair: - Fix member kick/leave: add missing db.delete() call in servers.ts - Stabilize invite codes: return existing code instead of regenerating - Fix user search: use LIKE instead of exact match in social.ts - Wire DM button on FriendsPage to create/navigate to DM channels - Add cancel outgoing friend request (DELETE endpoint + frontend) - Add accept/decline friend request actions with WS real-time events - Fix replyToId persistence in message creation - Hydrate reactions and replyTo in message queries - Add joinByCode to API client and serverStore - Add friend_request_received/accepted WebSocket events Phase 2 - Discord UI Overhaul: - Remove stray borders between layout columns - Replace shadow-sm with shadow-header on content headers - Replace all bg-gray-*/text-gray-* with Discord color tokens - Ensure flat color contrast (#1E1F22, #2B2D31, #313338) Testing: - Set up vitest + @testing-library/react + jsdom - Add 17 tests across InviteModal, JoinServer, FriendsPage (all passing) - Fix vite resolve.extensions to prefer .tsx over stale .js files
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { create } from 'zustand';
|
||||
import type { User } from '@opencord/shared';
|
||||
|
||||
type ModalType =
|
||||
| 'createServer'
|
||||
@@ -18,6 +19,10 @@ interface UIState {
|
||||
isMobile: boolean;
|
||||
showDms: boolean;
|
||||
imagePreviewUrl: string | null;
|
||||
userProfilePopout: {
|
||||
user: User | null;
|
||||
position: { top: number; left: number } | null;
|
||||
};
|
||||
toggleSidebar: () => void;
|
||||
toggleMemberList: () => void;
|
||||
openModal: (modal: ModalType, data?: Record<string, unknown>) => void;
|
||||
@@ -26,6 +31,8 @@ interface UIState {
|
||||
setShowDms: (show: boolean) => void;
|
||||
openImagePreview: (url: string) => void;
|
||||
closeImagePreview: () => void;
|
||||
openUserProfile: (user: User, position: { top: number; left: number }) => void;
|
||||
closeUserProfile: () => void;
|
||||
}
|
||||
|
||||
export const useUIStore = create<UIState>((set) => ({
|
||||
@@ -36,6 +43,10 @@ export const useUIStore = create<UIState>((set) => ({
|
||||
isMobile: false,
|
||||
showDms: false,
|
||||
imagePreviewUrl: null,
|
||||
userProfilePopout: {
|
||||
user: null,
|
||||
position: null,
|
||||
},
|
||||
|
||||
toggleSidebar: () => set((state) => ({ sidebarOpen: !state.sidebarOpen })),
|
||||
toggleMemberList: () => set((state) => ({ memberListOpen: !state.memberListOpen })),
|
||||
@@ -53,4 +64,11 @@ export const useUIStore = create<UIState>((set) => ({
|
||||
|
||||
openImagePreview: (url) => set({ activeModal: 'imagePreview', imagePreviewUrl: url }),
|
||||
closeImagePreview: () => set({ activeModal: null, imagePreviewUrl: null }),
|
||||
|
||||
openUserProfile: (user, position) => set({
|
||||
userProfilePopout: { user, position }
|
||||
}),
|
||||
closeUserProfile: () => set({
|
||||
userProfilePopout: { user: null, position: null }
|
||||
}),
|
||||
}));
|
||||
|
||||
Reference in New Issue
Block a user