feat: integrate all backend APIs into frontend apps
- Fix API service paths to use /v1/iam/, /v1/dimentorin/, /v1/gacha/, /v1/hackathon/ prefixes - Add roles, permissions, events, testimonials, sessions API services and hooks - Rewrite gacha service with full CRUD + roll/claim endpoints - Replace all mock data in backoffice pages with real API calls (accounts, roles, permissions, gacha-roll, dashboard, sessions, users-dimentorin, feedback-review, settings) - Wire dimentorin mentoring list to useMentorList with search + pagination - Wire dimentorin mentor detail page to useMentorById, pass real data to all sections - Wire appointment modal to useBookSession with controlled schedule inputs - Wire gacha app Spin Now to useExecuteGachaRoll, show credits and real items Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
8d2aaf5188
commit
53ad40f3fd
@@ -1,69 +1,30 @@
|
||||
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
import { hackathonApi, HackathonApiResponse } from '../../api/hackathon';
|
||||
import { useAuthStore } from '../auth';
|
||||
|
||||
interface User {
|
||||
id: string;
|
||||
email: string;
|
||||
fullname: string;
|
||||
bio?: string;
|
||||
location?: string;
|
||||
avatar?: string;
|
||||
skills?: string[];
|
||||
created_at: string;
|
||||
updated_at?: string;
|
||||
}
|
||||
|
||||
interface CertificateUserData {
|
||||
id: string;
|
||||
fullname: string;
|
||||
email: string;
|
||||
avatar?: string;
|
||||
}
|
||||
|
||||
interface CertificateTeamData {
|
||||
id: string;
|
||||
name: string;
|
||||
logo?: string;
|
||||
is_leader: boolean;
|
||||
}
|
||||
|
||||
interface CertificateSubmissionData {
|
||||
id: string;
|
||||
title: string;
|
||||
description: string;
|
||||
repository_url?: string;
|
||||
demo_url?: string;
|
||||
}
|
||||
|
||||
interface CertificateWinnerData {
|
||||
rank: number;
|
||||
prize?: string;
|
||||
}
|
||||
import {
|
||||
getUserMe,
|
||||
getUserById,
|
||||
getUserList,
|
||||
updateUserMe,
|
||||
updateUserById,
|
||||
} from '../../api/users';
|
||||
import { api } from '../../api/index';
|
||||
import type { TApiPaginated, TPaginationParams } from '../../types/common';
|
||||
import type { TUsersDetailItem, TUserUpdateRequest } from '../../types/users';
|
||||
|
||||
export interface CertificatePublicData {
|
||||
user: CertificateUserData;
|
||||
team?: CertificateTeamData;
|
||||
submission?: CertificateSubmissionData;
|
||||
winner?: CertificateWinnerData;
|
||||
}
|
||||
|
||||
interface UpdateUserRequest {
|
||||
fullname?: string;
|
||||
bio?: string;
|
||||
location?: string;
|
||||
avatar?: string;
|
||||
skills?: string[];
|
||||
user: { id: string; fullname: string; email: string; avatar?: string };
|
||||
team?: { id: string; name: string; logo?: string; is_leader: boolean };
|
||||
submission?: { id: string; title: string; description: string; repository_url?: string; demo_url?: string };
|
||||
winner?: { rank: number; prize?: string };
|
||||
}
|
||||
|
||||
export const useUserMe = () => {
|
||||
const { session } = useAuthStore();
|
||||
|
||||
return useQuery({
|
||||
queryKey: ['user-me'],
|
||||
queryFn: async () => {
|
||||
const response = await hackathonApi.get<HackathonApiResponse<User>>('/users/me');
|
||||
return { data: response.data.data };
|
||||
const data = await getUserMe();
|
||||
return { data };
|
||||
},
|
||||
enabled: !!session?.user?.id,
|
||||
});
|
||||
@@ -73,45 +34,52 @@ export const useUserById = (id: string) => {
|
||||
return useQuery({
|
||||
queryKey: ['user-by-id', id],
|
||||
queryFn: async () => {
|
||||
const response = await hackathonApi.get<HackathonApiResponse<User>>(`/users/${id}`);
|
||||
return { data: response.data.data };
|
||||
const data = await getUserById(id);
|
||||
return { data };
|
||||
},
|
||||
enabled: !!id,
|
||||
});
|
||||
};
|
||||
|
||||
export const useUserDetailsById = (userId: string) => {
|
||||
return useQuery({
|
||||
queryKey: ['user-details', userId],
|
||||
queryFn: async () => {
|
||||
const data = await getUserById(userId);
|
||||
return { data };
|
||||
},
|
||||
enabled: !!userId,
|
||||
});
|
||||
};
|
||||
|
||||
export const useUserList = (params?: TPaginationParams) => {
|
||||
return useQuery({
|
||||
queryKey: ['user-list', params],
|
||||
queryFn: () => getUserList(params),
|
||||
});
|
||||
};
|
||||
|
||||
export const useUpdateUserMe = () => {
|
||||
const queryClient = useQueryClient();
|
||||
const { session, setSession } = useAuthStore();
|
||||
|
||||
return useMutation({
|
||||
mutationKey: ['update-user-me'],
|
||||
mutationFn: async (data: UpdateUserRequest) => {
|
||||
if (!session?.user?.id) {
|
||||
throw new Error('You must be logged in to update profile');
|
||||
}
|
||||
|
||||
const response = await hackathonApi.put<HackathonApiResponse<User>>('/users/me', {
|
||||
fullname: data.fullname,
|
||||
bio: data.bio,
|
||||
location: data.location,
|
||||
avatar: data.avatar,
|
||||
skills: data.skills,
|
||||
});
|
||||
|
||||
return { data: response.data.data };
|
||||
mutationFn: (data: TUserUpdateRequest) => {
|
||||
if (!session?.user?.id) throw new Error('You must be logged in to update profile');
|
||||
return updateUserMe(data);
|
||||
},
|
||||
onSuccess: (result) => {
|
||||
if (session?.user && result.data) {
|
||||
if (session?.user && result) {
|
||||
setSession({
|
||||
token: session.token,
|
||||
user: {
|
||||
...session.user,
|
||||
fullname: result.data.fullname || session.user.fullname,
|
||||
bio: result.data.bio || '',
|
||||
location: result.data.location || '',
|
||||
avatar: result.data.avatar || session.user.avatar,
|
||||
skills: result.data.skills || [],
|
||||
fullname: result.fullname || session.user.fullname,
|
||||
bio: result.profile_extension?.bio || '',
|
||||
location: result.profile_extension?.location || '',
|
||||
avatar: result.avatar || session.user.avatar,
|
||||
skills: result.profile_extension?.skills || [],
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -125,33 +93,20 @@ export const useUpdateUserById = () => {
|
||||
|
||||
return useMutation({
|
||||
mutationKey: ['update-user-by-id'],
|
||||
mutationFn: async ({ id, data }: { id: string; data: UpdateUserRequest }) => {
|
||||
const response = await hackathonApi.put<HackathonApiResponse<User>>(`/users/${id}`, data);
|
||||
return { data: response.data.data };
|
||||
},
|
||||
mutationFn: ({ id, data }: { id: string; data: TUserUpdateRequest }) => updateUserById(id, data),
|
||||
onSuccess: (_, variables) => {
|
||||
queryClient.invalidateQueries({ queryKey: ['user-by-id', variables.id] });
|
||||
queryClient.invalidateQueries({ queryKey: ['user-list'] });
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export const useUserDetailsById = (userId: string) => {
|
||||
return useQuery({
|
||||
queryKey: ['user-details', userId],
|
||||
queryFn: async () => {
|
||||
const response = await hackathonApi.get<HackathonApiResponse<User>>(`/users/${userId}`);
|
||||
return { data: response.data.data };
|
||||
},
|
||||
enabled: !!userId,
|
||||
});
|
||||
};
|
||||
|
||||
export const useCertificatePublicData = (userId: string, enabled = true) => {
|
||||
return useQuery({
|
||||
queryKey: ['certificate-public-data', userId],
|
||||
queryFn: async () => {
|
||||
const response = await hackathonApi.get<HackathonApiResponse<CertificatePublicData>>(
|
||||
`/certificates/${userId}`
|
||||
const response = await api.get<{ data: CertificatePublicData }>(
|
||||
`/v1/hackathon/certificates/${userId}`
|
||||
);
|
||||
return { data: response.data.data };
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user