136 lines
4 KiB
TypeScript
136 lines
4 KiB
TypeScript
import { SocialGroup } from '../types';
|
|
import { apiClient } from './api/client';
|
|
|
|
interface ApiGroup {
|
|
id: string;
|
|
name: string;
|
|
description?: string;
|
|
avatar_url?: string;
|
|
is_public?: boolean;
|
|
member_count?: number;
|
|
}
|
|
|
|
interface UserStatus {
|
|
is_member: boolean;
|
|
role: string;
|
|
has_pending_request: boolean;
|
|
}
|
|
|
|
function mapRoleToUserRole(role: string): SocialGroup['userRole'] {
|
|
if (role === 'admin') return 'admin';
|
|
if (role === 'moderator') return 'mod';
|
|
if (role === 'member') return 'member';
|
|
return 'none';
|
|
}
|
|
|
|
function mapApiGroupToSocialGroup(
|
|
g: ApiGroup,
|
|
userRole: SocialGroup['userRole'] = 'none',
|
|
hasPendingRequest = false,
|
|
): SocialGroup {
|
|
return {
|
|
id: g.id,
|
|
name: g.name,
|
|
members: g.member_count ?? 0,
|
|
isPrivate: !(g.is_public ?? true),
|
|
userRole: hasPendingRequest ? 'none' : userRole,
|
|
hasPendingRequest,
|
|
description: g.description ?? '',
|
|
coverUrl: g.avatar_url ?? 'https://picsum.photos/id/10/800/400',
|
|
};
|
|
}
|
|
|
|
export const groupService = {
|
|
list: async (): Promise<{ groups: SocialGroup[] }> => {
|
|
const response = await apiClient.get<{ groups: ApiGroup[]; total?: number }>(
|
|
'/social/groups',
|
|
{ params: { limit: 50, offset: 0 } },
|
|
);
|
|
const items = response.data?.groups ?? [];
|
|
return {
|
|
groups: items.map((g) => mapApiGroupToSocialGroup(g)),
|
|
};
|
|
},
|
|
|
|
get: async (id: string) => {
|
|
const response = await apiClient.get<ApiGroup & { user_status?: UserStatus }>(
|
|
`/social/groups/${id}`,
|
|
);
|
|
const g = response.data;
|
|
if (!g) throw new Error('Group not found');
|
|
const status = g.user_status;
|
|
const userRole = status?.is_member
|
|
? mapRoleToUserRole(status.role)
|
|
: 'none';
|
|
const hasPendingRequest = status?.has_pending_request ?? false;
|
|
return {
|
|
group: mapApiGroupToSocialGroup(g, userRole, hasPendingRequest),
|
|
membersList: [],
|
|
events: [],
|
|
};
|
|
},
|
|
|
|
create: async (data: { name: string; description?: string; isPrivate?: boolean; coverUrl?: string }) => {
|
|
const response = await apiClient.post<ApiGroup>('/social/groups', {
|
|
name: data.name,
|
|
description: data.description ?? '',
|
|
is_public: !data.isPrivate,
|
|
});
|
|
const g = response.data;
|
|
if (!g) throw new Error('Failed to create group');
|
|
return mapApiGroupToSocialGroup(g, 'admin');
|
|
},
|
|
|
|
join: async (id: string) => {
|
|
await apiClient.post(`/social/groups/${id}/join`);
|
|
return { success: true };
|
|
},
|
|
|
|
leave: async (id: string) => {
|
|
await apiClient.delete(`/social/groups/${id}/leave`);
|
|
return { success: true };
|
|
},
|
|
|
|
requestJoin: async (id: string) => {
|
|
const response = await apiClient.post<{ id?: string; message?: string }>(
|
|
`/social/groups/${id}/request`,
|
|
);
|
|
return response.data;
|
|
},
|
|
|
|
listJoinRequests: async (id: string) => {
|
|
const response = await apiClient.get<{ requests: Array<{ id: string; user_id: string; status: string; created_at: string }> }>(
|
|
`/social/groups/${id}/requests`,
|
|
);
|
|
return response.data?.requests ?? [];
|
|
},
|
|
|
|
approveRequest: async (groupId: string, requestId: string) => {
|
|
await apiClient.post(`/social/groups/${groupId}/requests/${requestId}/approve`);
|
|
},
|
|
|
|
rejectRequest: async (groupId: string, requestId: string) => {
|
|
await apiClient.post(`/social/groups/${groupId}/requests/${requestId}/reject`);
|
|
},
|
|
|
|
invite: async (id: string, data: { email?: string; user_id?: string }) => {
|
|
await apiClient.post(`/social/groups/${id}/invite`, data);
|
|
},
|
|
|
|
updateMemberRole: async (groupId: string, userId: string, role: string) => {
|
|
await apiClient.put(`/social/groups/${groupId}/members/${userId}/role`, {
|
|
role,
|
|
});
|
|
},
|
|
|
|
listMine: async (): Promise<{ groups: SocialGroup[] }> => {
|
|
const response = await apiClient.get<{ groups: ApiGroup[]; total?: number }>(
|
|
'/social/groups/mine',
|
|
{ params: { limit: 50, offset: 0 } },
|
|
);
|
|
const items = response.data?.groups ?? [];
|
|
return {
|
|
groups: items.map((g) => mapApiGroupToSocialGroup(g, 'member')),
|
|
};
|
|
},
|
|
};
|