feat : Création de l'api, chargement des mockups

This commit is contained in:
Yaël Perret
2026-09-01 18:48:41 +02:00
parent fde710b607
commit 68d7ea3f9a
69 changed files with 1134 additions and 6 deletions

11
src/api/client.ts Normal file
View File

@@ -0,0 +1,11 @@
import axios from 'axios';
import { API_BASE_URL } from './config';
export const apiClient = axios.create({
baseURL: API_BASE_URL,
timeout: 10000,
headers: {
'Content-Type': 'application/json',
},
});

4
src/api/config.ts Normal file
View File

@@ -0,0 +1,4 @@
export const API_BASE_URL = process.env.EXPO_PUBLIC_API_BASE_URL ?? 'http://localhost:3000';
// Toggle once here to switch all API functions between mocks and real backend.
export const API_USE_MOCKS = (process.env.EXPO_PUBLIC_API_USE_MOCKS ?? 'true') === 'true';

View File

@@ -0,0 +1,9 @@
import type { Animator } from '@/models';
import { mockAnimators } from '@/mocks';
import { createResourceApi } from '../resourceFactory';
export const animatorsApi = createResourceApi<Animator>({
endpoint: 'animators',
mockData: mockAnimators,
resolveMockKey: (item) => item.id,
});

View File

@@ -0,0 +1,9 @@
import { mockCommentLikes } from '@/mocks';
import type { CommentLike } from '@/models';
import { createResourceApi } from '../resourceFactory';
export const comment_likesApi = createResourceApi<CommentLike>({
endpoint: 'comment_likes',
mockData: mockCommentLikes,
resolveMockKey: (item) => `${item.user_id}:${item.comment_id}`,
});

View File

@@ -0,0 +1,9 @@
import type { Comment } from '@/models';
import { mockComments } from '@/mocks';
import { createResourceApi } from '../resourceFactory';
export const commentsApi = createResourceApi<Comment>({
endpoint: 'comments',
mockData: mockComments,
resolveMockKey: (item) => item.id,
});

View File

@@ -0,0 +1,9 @@
import type { EventExternalLink } from '@/models';
import { mockEventExternalLinks } from '@/mocks';
import { createResourceApi } from '../resourceFactory';
export const event_external_linksApi = createResourceApi<EventExternalLink>({
endpoint: 'event_external_links',
mockData: mockEventExternalLinks,
resolveMockKey: (item) => item.id,
});

View File

@@ -0,0 +1,9 @@
import { mockEventHashtags } from '@/mocks';
import type { EventHashtag } from '@/models';
import { createResourceApi } from '../resourceFactory';
export const event_hashtagsApi = createResourceApi<EventHashtag>({
endpoint: 'event_hashtags',
mockData: mockEventHashtags,
resolveMockKey: (item) => `${item.event_id}:${item.hashtag_id}`,
});

View File

@@ -0,0 +1,9 @@
import type { EventImage } from '@/models';
import { mockEventImages } from '@/mocks';
import { createResourceApi } from '../resourceFactory';
export const event_imagesApi = createResourceApi<EventImage>({
endpoint: 'event_images',
mockData: mockEventImages,
resolveMockKey: (item) => item.id,
});

View File

@@ -0,0 +1,9 @@
import type { EventLineup } from '@/models';
import { mockEventLineup } from '@/mocks';
import { createResourceApi } from '../resourceFactory';
export const event_lineupApi = createResourceApi<EventLineup>({
endpoint: 'event_lineup',
mockData: mockEventLineup,
resolveMockKey: (item) => item.id,
});

View File

@@ -0,0 +1,9 @@
import type { EventStatsSnapshot } from '@/models';
import { mockEventStatsSnapshots } from '@/mocks';
import { createResourceApi } from '../resourceFactory';
export const event_stats_snapshotsApi = createResourceApi<EventStatsSnapshot>({
endpoint: 'event_stats_snapshots',
mockData: mockEventStatsSnapshots,
resolveMockKey: (item) => item.id,
});

View File

@@ -0,0 +1,9 @@
import { mockEventThemes } from '@/mocks';
import type { EventTheme } from '@/models';
import { createResourceApi } from '../resourceFactory';
export const event_themesApi = createResourceApi<EventTheme>({
endpoint: 'event_themes',
mockData: mockEventThemes,
resolveMockKey: (item) => `${item.event_id}:${item.theme_id}`,
});

View File

@@ -0,0 +1,9 @@
import type { Event } from '@/models';
import { mockEvents } from '@/mocks';
import { createResourceApi } from '../resourceFactory';
export const eventsApi = createResourceApi<Event>({
endpoint: 'events',
mockData: mockEvents,
resolveMockKey: (item) => item.id,
});

View File

@@ -0,0 +1,9 @@
import type { Hashtag } from '@/models';
import { mockHashtags } from '@/mocks';
import { createResourceApi } from '../resourceFactory';
export const hashtagsApi = createResourceApi<Hashtag>({
endpoint: 'hashtags',
mockData: mockHashtags,
resolveMockKey: (item) => item.id,
});

29
src/api/entities/index.ts Normal file
View File

@@ -0,0 +1,29 @@
export * from './animators';
export * from './comment_likes';
export * from './comments';
export * from './event_external_links';
export * from './event_hashtags';
export * from './event_images';
export * from './event_lineup';
export * from './event_stats_snapshots';
export * from './event_themes';
export * from './events';
export * from './hashtags';
export * from './organizer_members';
export * from './organizer_subscriptions';
export * from './organizers';
export * from './plans';
export * from './post_likes';
export * from './post_media';
export * from './posts';
export * from './search_history';
export * from './social_auth_providers';
export * from './themes';
export * from './tickets';
export * from './user_animator_follows';
export * from './user_event_interactions';
export * from './user_event_shares';
export * from './user_organizer_follows';
export * from './user_theme_preferences';
export * from './users';

View File

@@ -0,0 +1,9 @@
import type { OrganizerMember } from '@/models';
import { mockOrganizerMembers } from '@/mocks';
import { createResourceApi } from '../resourceFactory';
export const organizer_membersApi = createResourceApi<OrganizerMember>({
endpoint: 'organizer_members',
mockData: mockOrganizerMembers,
resolveMockKey: (item) => item.id,
});

View File

@@ -0,0 +1,9 @@
import type { OrganizerSubscription } from '@/models';
import { mockOrganizerSubscriptions } from '@/mocks';
import { createResourceApi } from '../resourceFactory';
export const organizer_subscriptionsApi = createResourceApi<OrganizerSubscription>({
endpoint: 'organizer_subscriptions',
mockData: mockOrganizerSubscriptions,
resolveMockKey: (item) => item.id,
});

View File

@@ -0,0 +1,9 @@
import type { Organizer } from '@/models';
import { mockOrganizers } from '@/mocks';
import { createResourceApi } from '../resourceFactory';
export const organizersApi = createResourceApi<Organizer>({
endpoint: 'organizers',
mockData: mockOrganizers,
resolveMockKey: (item) => item.id,
});

View File

@@ -0,0 +1,9 @@
import type { Plan } from '@/models';
import { mockPlans } from '@/mocks';
import { createResourceApi } from '../resourceFactory';
export const plansApi = createResourceApi<Plan>({
endpoint: 'plans',
mockData: mockPlans,
resolveMockKey: (item) => item.id,
});

View File

@@ -0,0 +1,9 @@
import { mockPostLikes } from '@/mocks';
import type { PostLike } from '@/models';
import { createResourceApi } from '../resourceFactory';
export const post_likesApi = createResourceApi<PostLike>({
endpoint: 'post_likes',
mockData: mockPostLikes,
resolveMockKey: (item) => `${item.user_id}:${item.post_id}`,
});

View File

@@ -0,0 +1,9 @@
import type { PostMedia } from '@/models';
import { mockPostMedia } from '@/mocks';
import { createResourceApi } from '../resourceFactory';
export const post_mediaApi = createResourceApi<PostMedia>({
endpoint: 'post_media',
mockData: mockPostMedia,
resolveMockKey: (item) => item.id,
});

View File

@@ -0,0 +1,9 @@
import type { Post } from '@/models';
import { mockPosts } from '@/mocks';
import { createResourceApi } from '../resourceFactory';
export const postsApi = createResourceApi<Post>({
endpoint: 'posts',
mockData: mockPosts,
resolveMockKey: (item) => item.id,
});

View File

@@ -0,0 +1,9 @@
import type { SearchHistory } from '@/models';
import { mockSearchHistory } from '@/mocks';
import { createResourceApi } from '../resourceFactory';
export const search_historyApi = createResourceApi<SearchHistory>({
endpoint: 'search_history',
mockData: mockSearchHistory,
resolveMockKey: (item) => item.id,
});

View File

@@ -0,0 +1,9 @@
import type { SocialAuthProvider } from '@/models';
import { mockSocialAuthProviders } from '@/mocks';
import { createResourceApi } from '../resourceFactory';
export const social_auth_providersApi = createResourceApi<SocialAuthProvider>({
endpoint: 'social_auth_providers',
mockData: mockSocialAuthProviders,
resolveMockKey: (item) => item.id,
});

View File

@@ -0,0 +1,9 @@
import type { Theme } from '@/models';
import { mockThemes } from '@/mocks';
import { createResourceApi } from '../resourceFactory';
export const themesApi = createResourceApi<Theme>({
endpoint: 'themes',
mockData: mockThemes,
resolveMockKey: (item) => item.id,
});

View File

@@ -0,0 +1,9 @@
import type { Ticket } from '@/models';
import { mockTickets } from '@/mocks';
import { createResourceApi } from '../resourceFactory';
export const ticketsApi = createResourceApi<Ticket>({
endpoint: 'tickets',
mockData: mockTickets,
resolveMockKey: (item) => item.id,
});

View File

@@ -0,0 +1,9 @@
import { mockUserAnimatorFollows } from '@/mocks';
import type { UserAnimatorFollow } from '@/models';
import { createResourceApi } from '../resourceFactory';
export const user_animator_followsApi = createResourceApi<UserAnimatorFollow>({
endpoint: 'user_animator_follows',
mockData: mockUserAnimatorFollows,
resolveMockKey: (item) => `${item.user_id}:${item.animator_id}`,
});

View File

@@ -0,0 +1,9 @@
import { mockUserEventInteractions } from '@/mocks';
import type { UserEventInteraction } from '@/models';
import { createResourceApi } from '../resourceFactory';
export const user_event_interactionsApi = createResourceApi<UserEventInteraction>({
endpoint: 'user_event_interactions',
mockData: mockUserEventInteractions,
resolveMockKey: (item) => `${item.user_id}:${item.event_id}`,
});

View File

@@ -0,0 +1,9 @@
import type { UserEventShare } from '@/models';
import { mockUserEventShares } from '@/mocks';
import { createResourceApi } from '../resourceFactory';
export const user_event_sharesApi = createResourceApi<UserEventShare>({
endpoint: 'user_event_shares',
mockData: mockUserEventShares,
resolveMockKey: (item) => item.id,
});

View File

@@ -0,0 +1,9 @@
import { mockUserOrganizerFollows } from '@/mocks';
import type { UserOrganizerFollow } from '@/models';
import { createResourceApi } from '../resourceFactory';
export const user_organizer_followsApi = createResourceApi<UserOrganizerFollow>({
endpoint: 'user_organizer_follows',
mockData: mockUserOrganizerFollows,
resolveMockKey: (item) => `${item.user_id}:${item.organizer_id}`,
});

View File

@@ -0,0 +1,9 @@
import { mockUserThemePreferences } from '@/mocks';
import type { UserThemePreference } from '@/models';
import { createResourceApi } from '../resourceFactory';
export const user_theme_preferencesApi = createResourceApi<UserThemePreference>({
endpoint: 'user_theme_preferences',
mockData: mockUserThemePreferences,
resolveMockKey: (item) => `${item.user_id}:${item.theme_id}`,
});

View File

@@ -0,0 +1,9 @@
import type { User } from '@/models';
import { mockUsers } from '@/mocks';
import { createResourceApi } from '../resourceFactory';
export const usersApi = createResourceApi<User>({
endpoint: 'users',
mockData: mockUsers,
resolveMockKey: (item) => item.id,
});

33
src/api/index.ts Normal file
View File

@@ -0,0 +1,33 @@
export * from './client';
export * from './config';
export * from './resourceFactory';
export * from './types';
export * from './entities/animators';
export * from './entities/comment_likes';
export * from './entities/comments';
export * from './entities/event_external_links';
export * from './entities/event_hashtags';
export * from './entities/event_images';
export * from './entities/event_lineup';
export * from './entities/event_stats_snapshots';
export * from './entities/event_themes';
export * from './entities/events';
export * from './entities/hashtags';
export * from './entities/organizer_members';
export * from './entities/organizer_subscriptions';
export * from './entities/organizers';
export * from './entities/plans';
export * from './entities/post_likes';
export * from './entities/post_media';
export * from './entities/posts';
export * from './entities/search_history';
export * from './entities/social_auth_providers';
export * from './entities/themes';
export * from './entities/tickets';
export * from './entities/user_animator_follows';
export * from './entities/user_event_interactions';
export * from './entities/user_event_shares';
export * from './entities/user_organizer_follows';
export * from './entities/user_theme_preferences';
export * from './entities/users';

90
src/api/mockStore.ts Normal file
View File

@@ -0,0 +1,90 @@
type KeyResolver<T> = (item: T) => string;
type MockStoreOptions<T> = {
data: T[];
resolveKey: KeyResolver<T>;
};
const clone = <T>(value: T): T => {
if (typeof globalThis.structuredClone === 'function') {
return globalThis.structuredClone(value);
}
return JSON.parse(JSON.stringify(value)) as T;
};
const createMockId = (): string => {
const random = Math.random().toString(16).slice(2, 10).padEnd(8, '0');
return `00000000-0000-4000-8000-${random}`;
};
const ensureHasId = <T>(payload: Partial<T>): Partial<T> => {
if ('id' in payload && typeof payload.id === 'string' && payload.id.length > 0) {
return payload;
}
return {
...payload,
id: createMockId(),
};
};
export const createMockStore = <T>(options: MockStoreOptions<T>) => {
const { resolveKey } = options;
const records = [...options.data];
const findIndex = (id: string): number => records.findIndex((item) => resolveKey(item) === id);
return {
list: async (): Promise<T[]> => clone(records),
get: async (id: string): Promise<T> => {
const index = findIndex(id);
if (index === -1) {
throw new Error(`Mock record not found for id "${id}"`);
}
return clone(records[index]);
},
create: async (payload: Partial<T>): Promise<T> => {
const next = ensureHasId(payload) as T;
records.push(next);
return clone(next);
},
update: async (id: string, payload: Partial<T>): Promise<T> => {
const index = findIndex(id);
if (index === -1) {
throw new Error(`Mock record not found for id "${id}"`);
}
const next = {
...records[index],
...payload,
};
records[index] = next;
return clone(next);
},
patch: async (id: string, payload: Partial<T>): Promise<T> => {
const index = findIndex(id);
if (index === -1) {
throw new Error(`Mock record not found for id "${id}"`);
}
const next = {
...records[index],
...payload,
};
records[index] = next;
return clone(next);
},
remove: async (id: string): Promise<void> => {
const index = findIndex(id);
if (index === -1) {
throw new Error(`Mock record not found for id "${id}"`);
}
records.splice(index, 1);
},
};
};

View File

@@ -0,0 +1,66 @@
import type { AxiosInstance } from 'axios';
import { apiClient } from './client';
import { API_USE_MOCKS } from './config';
import { createMockStore } from './mockStore';
import type { CreatePayload, CrudApi, UpdatePayload } from './types';
type CreateResourceApiOptions<T> = {
endpoint: string;
mockData: T[];
resolveMockKey: (item: T) => string;
client?: AxiosInstance;
useMocks?: boolean;
};
export const createResourceApi = <T>(options: CreateResourceApiOptions<T>): CrudApi<T> => {
const {
endpoint,
mockData,
resolveMockKey,
client = apiClient,
useMocks = API_USE_MOCKS,
} = options;
const mockStore = createMockStore<T>({
data: mockData,
resolveKey: resolveMockKey,
});
if (useMocks) {
return {
list: () => mockStore.list(),
get: (id) => mockStore.get(id),
create: (payload) => mockStore.create(payload),
update: (id, payload) => mockStore.update(id, payload),
patch: (id, payload) => mockStore.patch(id, payload),
remove: (id) => mockStore.remove(id),
};
}
return {
list: async () => {
const response = await client.get<T[]>(`/${endpoint}`);
return response.data;
},
get: async (id: string) => {
const response = await client.get<T>(`/${endpoint}/${id}`);
return response.data;
},
create: async (payload: CreatePayload<T>) => {
const response = await client.post<T>(`/${endpoint}`, payload);
return response.data;
},
update: async (id: string, payload: UpdatePayload<T>) => {
const response = await client.put<T>(`/${endpoint}/${id}`, payload);
return response.data;
},
patch: async (id: string, payload: UpdatePayload<T>) => {
const response = await client.patch<T>(`/${endpoint}/${id}`, payload);
return response.data;
},
remove: async (id: string) => {
await client.delete(`/${endpoint}/${id}`);
},
};
};

13
src/api/types.ts Normal file
View File

@@ -0,0 +1,13 @@
export type EntityWithId = { id: string };
export type CreatePayload<T> = Partial<T>;
export type UpdatePayload<T> = Partial<T>;
export type CrudApi<T> = {
list: () => Promise<T[]>;
get: (id: string) => Promise<T>;
create: (payload: CreatePayload<T>) => Promise<T>;
update: (id: string, payload: UpdatePayload<T>) => Promise<T>;
patch: (id: string, payload: UpdatePayload<T>) => Promise<T>;
remove: (id: string) => Promise<void>;
};

View File

@@ -1,5 +1,7 @@
import { QueryClientProvider } from '@tanstack/react-query';
import { Stack } from 'expo-router';
import { queryClient } from '../hooks/queryClient';
import { useAppFonts } from '../theme/typography';
export default function RootLayout() {
@@ -10,6 +12,8 @@ export default function RootLayout() {
}
return (
<Stack />
<QueryClientProvider client={queryClient}>
<Stack />
</QueryClientProvider>
);
}

View File

@@ -0,0 +1,5 @@
import type { Animator } from '@/models';
import { animatorsApi } from '@/api/entities/animators';
import { createCrudHooks } from './createCrudHooks';
export const animatorsHooks = createCrudHooks<Animator>('animators', animatorsApi);

View File

@@ -0,0 +1,5 @@
import type { CommentLike } from '@/models';
import { comment_likesApi } from '@/api/entities/comment_likes';
import { createCrudHooks } from './createCrudHooks';
export const comment_likesHooks = createCrudHooks<CommentLike>('comment_likes', comment_likesApi);

View File

@@ -0,0 +1,5 @@
import type { Comment } from '@/models';
import { commentsApi } from '@/api/entities/comments';
import { createCrudHooks } from './createCrudHooks';
export const commentsHooks = createCrudHooks<Comment>('comments', commentsApi);

View File

@@ -0,0 +1,102 @@
import type { CrudApi } from '@/api/types';
import {
useMutation,
useQuery,
useQueryClient,
type UseMutationOptions,
type UseQueryOptions,
} from '@tanstack/react-query';
type ResourceId = string;
type ListKey = [string, 'list'];
type DetailKey = [string, 'detail', ResourceId];
export const createCrudHooks = <T>(resourceKey: string, api: CrudApi<T>) => {
const listKey: ListKey = [resourceKey, 'list'];
const useListQuery = (options?: Omit<UseQueryOptions<T[], Error, T[], ListKey>, 'queryKey' | 'queryFn'>) =>
useQuery({
queryKey: listKey,
queryFn: () => api.list(),
...options,
});
const useDetailQuery = (
id: ResourceId,
options?: Omit<UseQueryOptions<T, Error, T, DetailKey>, 'queryKey' | 'queryFn'>,
) =>
useQuery({
queryKey: [resourceKey, 'detail', id],
queryFn: () => api.get(id),
enabled: id !== undefined && id !== null && (options?.enabled ?? true),
...options,
});
const useCreateMutation = (
options?: UseMutationOptions<T, Error, Partial<T>>,
) => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (data) => api.create(data),
...options,
onSuccess: (data, variables, onMutateResult, context) => {
queryClient.invalidateQueries({ queryKey: listKey });
options?.onSuccess?.(data, variables, onMutateResult, context);
},
});
};
const useUpdateMutation = (
options?: UseMutationOptions<T, Error, { id: ResourceId; data: Partial<T> }>,
) => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: ({ id, data }) => api.update(id, data),
...options,
onSuccess: (data, variables, onMutateResult, context) => {
queryClient.invalidateQueries({ queryKey: listKey });
queryClient.invalidateQueries({ queryKey: [resourceKey, 'detail', variables.id] });
options?.onSuccess?.(data, variables, onMutateResult, context);
},
});
};
const usePatchMutation = (
options?: UseMutationOptions<T, Error, { id: ResourceId; data: Partial<T> }>,
) => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: ({ id, data }) => api.patch(id, data),
...options,
onSuccess: (data, variables, onMutateResult, context) => {
queryClient.invalidateQueries({ queryKey: listKey });
queryClient.invalidateQueries({ queryKey: [resourceKey, 'detail', variables.id] });
options?.onSuccess?.(data, variables, onMutateResult, context);
},
});
};
const useDeleteMutation = (
options?: UseMutationOptions<void, Error, ResourceId>,
) => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (id) => api.remove(id),
...options,
onSuccess: (data, variables, onMutateResult, context) => {
queryClient.invalidateQueries({ queryKey: listKey });
queryClient.invalidateQueries({ queryKey: [resourceKey, 'detail', variables] });
options?.onSuccess?.(data, variables, onMutateResult, context);
},
});
};
return {
useListQuery,
useDetailQuery,
useCreateMutation,
useUpdateMutation,
usePatchMutation,
useDeleteMutation,
};
};

View File

@@ -0,0 +1,5 @@
import type { EventExternalLink } from '@/models';
import { event_external_linksApi } from '@/api/entities/event_external_links';
import { createCrudHooks } from './createCrudHooks';
export const event_external_linksHooks = createCrudHooks<EventExternalLink>('event_external_links', event_external_linksApi);

View File

@@ -0,0 +1,5 @@
import type { EventHashtag } from '@/models';
import { event_hashtagsApi } from '@/api/entities/event_hashtags';
import { createCrudHooks } from './createCrudHooks';
export const event_hashtagsHooks = createCrudHooks<EventHashtag>('event_hashtags', event_hashtagsApi);

View File

@@ -0,0 +1,5 @@
import type { EventImage } from '@/models';
import { event_imagesApi } from '@/api/entities/event_images';
import { createCrudHooks } from './createCrudHooks';
export const event_imagesHooks = createCrudHooks<EventImage>('event_images', event_imagesApi);

View File

@@ -0,0 +1,5 @@
import type { EventLineup } from '@/models';
import { event_lineupApi } from '@/api/entities/event_lineup';
import { createCrudHooks } from './createCrudHooks';
export const event_lineupHooks = createCrudHooks<EventLineup>('event_lineup', event_lineupApi);

View File

@@ -0,0 +1,5 @@
import type { EventStatsSnapshot } from '@/models';
import { event_stats_snapshotsApi } from '@/api/entities/event_stats_snapshots';
import { createCrudHooks } from './createCrudHooks';
export const event_stats_snapshotsHooks = createCrudHooks<EventStatsSnapshot>('event_stats_snapshots', event_stats_snapshotsApi);

View File

@@ -0,0 +1,5 @@
import type { EventTheme } from '@/models';
import { event_themesApi } from '@/api/entities/event_themes';
import { createCrudHooks } from './createCrudHooks';
export const event_themesHooks = createCrudHooks<EventTheme>('event_themes', event_themesApi);

5
src/hooks/api/events.ts Normal file
View File

@@ -0,0 +1,5 @@
import type { Event } from '@/models';
import { eventsApi } from '@/api/entities/events';
import { createCrudHooks } from './createCrudHooks';
export const eventsHooks = createCrudHooks<Event>('events', eventsApi);

View File

@@ -0,0 +1,5 @@
import type { Hashtag } from '@/models';
import { hashtagsApi } from '@/api/entities/hashtags';
import { createCrudHooks } from './createCrudHooks';
export const hashtagsHooks = createCrudHooks<Hashtag>('hashtags', hashtagsApi);

30
src/hooks/api/index.ts Normal file
View File

@@ -0,0 +1,30 @@
export * from './createCrudHooks';
export * from './animators';
export * from './comment_likes';
export * from './comments';
export * from './event_external_links';
export * from './event_hashtags';
export * from './event_images';
export * from './event_lineup';
export * from './event_stats_snapshots';
export * from './event_themes';
export * from './events';
export * from './hashtags';
export * from './organizer_members';
export * from './organizer_subscriptions';
export * from './organizers';
export * from './plans';
export * from './post_likes';
export * from './post_media';
export * from './posts';
export * from './search_history';
export * from './social_auth_providers';
export * from './themes';
export * from './tickets';
export * from './user_animator_follows';
export * from './user_event_interactions';
export * from './user_event_shares';
export * from './user_organizer_follows';
export * from './user_theme_preferences';
export * from './users';

View File

@@ -0,0 +1,5 @@
import type { OrganizerMember } from '@/models';
import { organizer_membersApi } from '@/api/entities/organizer_members';
import { createCrudHooks } from './createCrudHooks';
export const organizer_membersHooks = createCrudHooks<OrganizerMember>('organizer_members', organizer_membersApi);

View File

@@ -0,0 +1,5 @@
import type { OrganizerSubscription } from '@/models';
import { organizer_subscriptionsApi } from '@/api/entities/organizer_subscriptions';
import { createCrudHooks } from './createCrudHooks';
export const organizer_subscriptionsHooks = createCrudHooks<OrganizerSubscription>('organizer_subscriptions', organizer_subscriptionsApi);

View File

@@ -0,0 +1,5 @@
import type { Organizer } from '@/models';
import { organizersApi } from '@/api/entities/organizers';
import { createCrudHooks } from './createCrudHooks';
export const organizersHooks = createCrudHooks<Organizer>('organizers', organizersApi);

5
src/hooks/api/plans.ts Normal file
View File

@@ -0,0 +1,5 @@
import type { Plan } from '@/models';
import { plansApi } from '@/api/entities/plans';
import { createCrudHooks } from './createCrudHooks';
export const plansHooks = createCrudHooks<Plan>('plans', plansApi);

View File

@@ -0,0 +1,5 @@
import type { PostLike } from '@/models';
import { post_likesApi } from '@/api/entities/post_likes';
import { createCrudHooks } from './createCrudHooks';
export const post_likesHooks = createCrudHooks<PostLike>('post_likes', post_likesApi);

View File

@@ -0,0 +1,5 @@
import type { PostMedia } from '@/models';
import { post_mediaApi } from '@/api/entities/post_media';
import { createCrudHooks } from './createCrudHooks';
export const post_mediaHooks = createCrudHooks<PostMedia>('post_media', post_mediaApi);

5
src/hooks/api/posts.ts Normal file
View File

@@ -0,0 +1,5 @@
import type { Post } from '@/models';
import { postsApi } from '@/api/entities/posts';
import { createCrudHooks } from './createCrudHooks';
export const postsHooks = createCrudHooks<Post>('posts', postsApi);

View File

@@ -0,0 +1,5 @@
import type { SearchHistory } from '@/models';
import { search_historyApi } from '@/api/entities/search_history';
import { createCrudHooks } from './createCrudHooks';
export const search_historyHooks = createCrudHooks<SearchHistory>('search_history', search_historyApi);

View File

@@ -0,0 +1,5 @@
import type { SocialAuthProvider } from '@/models';
import { social_auth_providersApi } from '@/api/entities/social_auth_providers';
import { createCrudHooks } from './createCrudHooks';
export const social_auth_providersHooks = createCrudHooks<SocialAuthProvider>('social_auth_providers', social_auth_providersApi);

5
src/hooks/api/themes.ts Normal file
View File

@@ -0,0 +1,5 @@
import type { Theme } from '@/models';
import { themesApi } from '@/api/entities/themes';
import { createCrudHooks } from './createCrudHooks';
export const themesHooks = createCrudHooks<Theme>('themes', themesApi);

5
src/hooks/api/tickets.ts Normal file
View File

@@ -0,0 +1,5 @@
import type { Ticket } from '@/models';
import { ticketsApi } from '@/api/entities/tickets';
import { createCrudHooks } from './createCrudHooks';
export const ticketsHooks = createCrudHooks<Ticket>('tickets', ticketsApi);

View File

@@ -0,0 +1,5 @@
import type { UserAnimatorFollow } from '@/models';
import { user_animator_followsApi } from '@/api/entities/user_animator_follows';
import { createCrudHooks } from './createCrudHooks';
export const user_animator_followsHooks = createCrudHooks<UserAnimatorFollow>('user_animator_follows', user_animator_followsApi);

View File

@@ -0,0 +1,5 @@
import type { UserEventInteraction } from '@/models';
import { user_event_interactionsApi } from '@/api/entities/user_event_interactions';
import { createCrudHooks } from './createCrudHooks';
export const user_event_interactionsHooks = createCrudHooks<UserEventInteraction>('user_event_interactions', user_event_interactionsApi);

View File

@@ -0,0 +1,5 @@
import type { UserEventShare } from '@/models';
import { user_event_sharesApi } from '@/api/entities/user_event_shares';
import { createCrudHooks } from './createCrudHooks';
export const user_event_sharesHooks = createCrudHooks<UserEventShare>('user_event_shares', user_event_sharesApi);

View File

@@ -0,0 +1,5 @@
import type { UserOrganizerFollow } from '@/models';
import { user_organizer_followsApi } from '@/api/entities/user_organizer_follows';
import { createCrudHooks } from './createCrudHooks';
export const user_organizer_followsHooks = createCrudHooks<UserOrganizerFollow>('user_organizer_follows', user_organizer_followsApi);

View File

@@ -0,0 +1,5 @@
import type { UserThemePreference } from '@/models';
import { user_theme_preferencesApi } from '@/api/entities/user_theme_preferences';
import { createCrudHooks } from './createCrudHooks';
export const user_theme_preferencesHooks = createCrudHooks<UserThemePreference>('user_theme_preferences', user_theme_preferencesApi);

5
src/hooks/api/users.ts Normal file
View File

@@ -0,0 +1,5 @@
import type { User } from '@/models';
import { usersApi } from '@/api/entities/users';
import { createCrudHooks } from './createCrudHooks';
export const usersHooks = createCrudHooks<User>('users', usersApi);

15
src/hooks/queryClient.ts Normal file
View File

@@ -0,0 +1,15 @@
import { QueryClient } from '@tanstack/react-query';
export const queryClient = new QueryClient({
defaultOptions: {
queries: {
staleTime: 30_000,
gcTime: 5 * 60_000,
refetchOnWindowFocus: false,
retry: 1,
},
mutations: {
retry: 0,
},
},
});