Reorganize web folder structurally

This commit is contained in:
Халимов Рустам
2026-03-19 22:24:21 +03:00
parent 11ebbc853b
commit 4384233aa5
62 changed files with 0 additions and 0 deletions
@@ -0,0 +1,166 @@
import { create } from 'zustand';
import { UserApi } from '../../users/infrastructure/userApi';
import { FriendApi } from '../infrastructure/friendApi';
import type { FriendWithId, FriendRequest, UserPresence } from '../../../core/domain/types';
import { getSocket } from '../../../core/infrastructure/socket';
interface FriendState {
friends: FriendWithId[];
friendRequests: FriendRequest[];
isLoading: boolean;
searchQuery: string;
searchResults: UserPresence[];
isSearching: boolean;
setSearchQuery: (query: string) => void;
loadFriends: () => Promise<void>;
acceptRequest: (requestId: string) => Promise<void>;
declineRequest: (requestId: string) => Promise<void>;
removeFriend: (friendshipId: string) => Promise<void>;
sendRequest: (friendId: string) => Promise<void>;
searchFriends: (query: string, currentUserId?: string) => Promise<void>;
clearSearch: () => void;
initializeSocketEvents: () => () => void;
}
export const useFriendStore = create<FriendState>((set, get) => ({
friends: [],
friendRequests: [],
isLoading: false,
searchQuery: '',
searchResults: [],
isSearching: false,
setSearchQuery: (query) => set({ searchQuery: query }),
loadFriends: async () => {
set({ isLoading: true });
try {
const [friendsList, requests] = await Promise.all([
FriendApi.getFriends(),
FriendApi.getFriendRequests(),
]);
set({ friends: friendsList, friendRequests: requests });
} catch (e) {
console.error('Load friends error:', e);
} finally {
set({ isLoading: false });
}
},
acceptRequest: async (requestId) => {
try {
await FriendApi.acceptFriendRequest(requestId);
const req = get().friendRequests.find(r => r.id === requestId);
if (req) {
const socket = getSocket();
if (socket) socket.emit('friend_accepted', { friendId: req.user.id });
}
await get().loadFriends();
} catch (e) {
console.error(e);
}
},
declineRequest: async (requestId) => {
try {
await FriendApi.declineFriendRequest(requestId);
set((state) => ({
friendRequests: state.friendRequests.filter(r => r.id !== requestId)
}));
} catch (e) {
console.error(e);
}
},
removeFriend: async (friendshipId) => {
try {
const friend = get().friends.find(f => f.friendshipId === friendshipId);
await FriendApi.removeFriend(friendshipId);
if (friend) {
const socket = getSocket();
if (socket) socket.emit('friend_removed', { friendId: friend.id });
}
set((state) => ({
friends: state.friends.filter(f => f.friendshipId !== friendshipId)
}));
} catch (e) {
console.error(e);
}
},
sendRequest: async (friendId) => {
try {
const result = await FriendApi.sendFriendRequest(friendId);
const socket = getSocket();
if (socket) socket.emit('friend_request', { friendId });
if (result.status === 'accepted') {
await get().loadFriends();
}
set((state) => ({
searchResults: state.searchResults.filter(u => u.id !== friendId)
}));
} catch (e) {
console.error(e);
}
},
searchFriends: async (query, currentUserId) => {
const raw = query.trim();
const q = raw.startsWith('@') ? raw.slice(1) : raw;
if (q.length < 3) {
set({ searchResults: [] });
return;
}
set({ isSearching: true });
try {
const results = await UserApi.searchUsers(q);
const { friends } = get();
const friendIds = new Set(friends.map(f => f.id));
set({
searchResults: results.filter(u => u.id !== currentUserId && !friendIds.has(u.id))
});
} catch (e) {
console.error(e);
} finally {
set({ isSearching: false });
}
},
clearSearch: () => set({ searchQuery: '', searchResults: [] }),
initializeSocketEvents: () => {
const socket = getSocket();
if (!socket) return () => {};
const onFriendRequestReceived = () => {
FriendApi.getFriendRequests()
.then(reqs => set({ friendRequests: reqs }))
.catch(() => {});
};
const onFriendRequestAccepted = () => {
get().loadFriends();
};
const onFriendRemoved = (data: { userId: string }) => {
set((state) => ({
friends: state.friends.filter(f => f.id !== data.userId)
}));
};
socket.on('friend_request_received', onFriendRequestReceived);
socket.on('friend_request_accepted', onFriendRequestAccepted);
socket.on('friend_removed', onFriendRemoved);
return () => {
socket.off('friend_request_received', onFriendRequestReceived);
socket.off('friend_request_accepted', onFriendRequestAccepted);
socket.off('friend_removed', onFriendRemoved);
};
}
}));
@@ -0,0 +1,39 @@
import { httpClient } from '../../../core/infrastructure/httpClient';
import type { FriendshipStatus, FriendRequest, FriendWithId } from '../../../core/domain/types';
export class FriendApi {
static async getFriends() {
return httpClient.request<FriendWithId[]>('/friends');
}
static async getFriendRequests() {
return httpClient.request<FriendRequest[]>('/friends/requests');
}
static async getOutgoingRequests() {
return httpClient.request<FriendRequest[]>('/friends/outgoing');
}
static async getFriendshipStatus(userId: string) {
return httpClient.request<FriendshipStatus>(`/friends/status/${userId}`);
}
static async sendFriendRequest(friendId: string) {
return httpClient.request<{ status: string }>('/friends/request', {
method: 'POST',
body: JSON.stringify({ friendId }),
});
}
static async acceptFriendRequest(friendshipId: string) {
return httpClient.request<{ id: string }>(`/friends/${friendshipId}/accept`, { method: 'POST' });
}
static async declineFriendRequest(friendshipId: string) {
return httpClient.request<{ success: boolean }>(`/friends/${friendshipId}/decline`, { method: 'POST' });
}
static async removeFriend(friendshipId: string) {
return httpClient.request<{ success: boolean }>(`/friends/${friendshipId}`, { method: 'DELETE' });
}
}