Files
MyClub/frontend/src/services/navigation.ts
T

145 lines
4.7 KiB
TypeScript

import api, { API_URL as API_BASE_URL } from './api';
export interface NavigationItem {
id?: number;
label: string;
url?: string;
icon?: string;
type: 'internal' | 'external' | 'dropdown' | 'page';
page_type?: string;
page_id?: number;
visible: boolean;
display_order: number;
parent_id?: number;
children?: NavigationItem[];
target?: '_self' | '_blank';
css_class?: string;
requires_auth?: boolean;
requires_admin?: boolean;
allow_editor?: boolean;
}
export interface SocialLink {
id?: number;
platform: string;
url: string;
display_order: number;
visible: boolean;
icon?: string;
}
// Normalize backend objects (backend may return `ID` instead of `id`)
function normalizeNavItem(raw: any): NavigationItem {
if (!raw || typeof raw !== 'object') return raw as NavigationItem;
const id = raw.id ?? raw.ID;
const children = Array.isArray(raw.children)
? raw.children.map((c: any) => normalizeNavItem(c))
: undefined;
return {
id,
label: raw.label,
url: raw.url,
icon: raw.icon,
type: raw.type,
page_type: raw.page_type,
page_id: raw.page_id,
visible: raw.visible,
display_order: raw.display_order,
parent_id: raw.parent_id,
children,
target: raw.target,
css_class: raw.css_class,
requires_auth: raw.requires_auth,
requires_admin: raw.requires_admin,
allow_editor: raw.allow_editor,
} as NavigationItem;
}
function normalizeSocialLink(raw: any): SocialLink {
if (!raw || typeof raw !== 'object') return raw as SocialLink;
const id = raw.id ?? raw.ID;
return {
id,
platform: raw.platform,
url: raw.url,
display_order: raw.display_order,
visible: raw.visible,
icon: raw.icon,
} as SocialLink;
}
// Public endpoints
export const getNavigationItems = async (): Promise<NavigationItem[]> => {
const response = await api.get(`/navigation`);
const data = Array.isArray(response.data) ? response.data : [];
return data.map((it: any) => normalizeNavItem(it));
};
export const getSocialLinks = async (): Promise<SocialLink[]> => {
const response = await api.get(`/social-links`);
const data = Array.isArray(response.data) ? response.data : [];
return data.map((it: any) => normalizeSocialLink(it));
};
// Admin endpoints
export const getAllNavigationItems = async (): Promise<NavigationItem[]> => {
const response = await api.get(`/admin/navigation`);
const data = Array.isArray(response.data) ? response.data : [];
return data.map((it: any) => normalizeNavItem(it));
};
export const createNavigationItem = async (item: Partial<NavigationItem>): Promise<NavigationItem> => {
const response = await api.post(`/admin/navigation`, item);
return normalizeNavItem(response.data);
};
export const updateNavigationItem = async (id: number, item: Partial<NavigationItem>): Promise<NavigationItem> => {
const response = await api.put(`/admin/navigation/${id}`, item);
return normalizeNavItem(response.data);
};
export const deleteNavigationItem = async (id: number): Promise<void> => {
await api.delete(`/admin/navigation/${id}`);
};
export const reorderNavigationItems = async (orders: { id: number; display_order: number }[]): Promise<void> => {
await api.post(`/admin/navigation/reorder`, orders);
};
// Editor-allowed admin navigation (for editors' sidebar)
export const getEditorAllowedAdminNav = async (): Promise<NavigationItem[]> => {
const response = await api.get(`/admin/navigation/editor`);
const data = Array.isArray(response.data) ? response.data : [];
return data.map((it: any) => normalizeNavItem(it));
};
// Social links admin endpoints
export const getAllSocialLinks = async (): Promise<SocialLink[]> => {
const response = await api.get(`/admin/social-links`);
const data = Array.isArray(response.data) ? response.data : [];
return data.map((it: any) => normalizeSocialLink(it));
};
export const createSocialLink = async (link: Partial<SocialLink>): Promise<SocialLink> => {
const response = await api.post(`/admin/social-links`, link);
return normalizeSocialLink(response.data);
};
export const updateSocialLink = async (id: number, link: Partial<SocialLink>): Promise<SocialLink> => {
const response = await api.put(`/admin/social-links/${id}`, link);
return normalizeSocialLink(response.data);
};
export const deleteSocialLink = async (id: number): Promise<void> => {
await api.delete(`/admin/social-links/${id}`);
};
export const reorderSocialLinks = async (orders: { id: number; display_order: number }[]): Promise<void> => {
await api.post(`/admin/social-links/reorder`, orders);
};
export const seedDefaultNavigation = async (): Promise<{ message: string; count: number; seeded: boolean }> => {
const response = await api.post(`/admin/navigation/seed`, {});
return response.data;
};