♻️ refactor: Replace useQuery with Zustand store for subscription and node data management
This commit is contained in:
@@ -0,0 +1,113 @@
|
||||
import { filterNodeList, queryNodeTag } from '@/services/admin/server';
|
||||
import { create } from 'zustand';
|
||||
|
||||
interface NodeState {
|
||||
// Data
|
||||
nodes: API.Node[];
|
||||
tags: string[];
|
||||
|
||||
// Actions
|
||||
fetchNodes: () => Promise<void>;
|
||||
fetchTags: () => Promise<void>;
|
||||
|
||||
// Getters
|
||||
getNodeById: (nodeId: number) => API.Node | undefined;
|
||||
isProtocolUsedInNodes: (serverId: number, protocolType: string) => boolean;
|
||||
isServerReferencedByNodes: (serverId: number) => boolean;
|
||||
getNodesByTag: (tag: string) => API.Node[];
|
||||
getNodesWithoutTags: () => API.Node[];
|
||||
getNodeTags: () => string[];
|
||||
getAllAvailableTags: () => string[];
|
||||
}
|
||||
|
||||
export const useNodeStore = create<NodeState>((set, get) => ({
|
||||
// Initial state
|
||||
nodes: [],
|
||||
tags: [],
|
||||
|
||||
// Actions
|
||||
fetchNodes: async () => {
|
||||
try {
|
||||
const { data } = await filterNodeList({ page: 1, size: 999999999 });
|
||||
set({ nodes: data?.data?.list || [] });
|
||||
} catch (error) {
|
||||
// Handle error silently
|
||||
}
|
||||
},
|
||||
|
||||
fetchTags: async () => {
|
||||
try {
|
||||
const { data } = await queryNodeTag();
|
||||
set({ tags: data?.data?.tags || [] });
|
||||
} catch (error) {
|
||||
// Handle error silently
|
||||
}
|
||||
},
|
||||
|
||||
// Getters
|
||||
getNodeById: (nodeId: number) => {
|
||||
return get().nodes.find((n) => n.id === nodeId);
|
||||
},
|
||||
|
||||
isProtocolUsedInNodes: (serverId: number, protocolType: string) => {
|
||||
return get().nodes.some(
|
||||
(node) => node.server_id === serverId && node.protocol === protocolType,
|
||||
);
|
||||
},
|
||||
|
||||
isServerReferencedByNodes: (serverId: number) => {
|
||||
return get().nodes.some((node) => node.server_id === serverId);
|
||||
},
|
||||
|
||||
getNodesByTag: (tag: string) => {
|
||||
return get().nodes.filter((node) => (node.tags || []).includes(tag));
|
||||
},
|
||||
|
||||
getNodesWithoutTags: () => {
|
||||
return get().nodes.filter((node) => (node.tags || []).length === 0);
|
||||
},
|
||||
|
||||
getNodeTags: () => {
|
||||
return Array.from(
|
||||
new Set(
|
||||
get()
|
||||
.nodes.flatMap((node) => (Array.isArray(node.tags) ? node.tags : []))
|
||||
.filter(Boolean),
|
||||
),
|
||||
) as string[];
|
||||
},
|
||||
|
||||
getAllAvailableTags: () => {
|
||||
const nodeExtractedTags = get().getNodeTags();
|
||||
const allApiTags = get().tags;
|
||||
return Array.from(new Set([...allApiTags, ...nodeExtractedTags])).filter(Boolean);
|
||||
},
|
||||
}));
|
||||
|
||||
export const useNode = () => {
|
||||
const store = useNodeStore();
|
||||
|
||||
// Auto-fetch nodes and tags
|
||||
if (store.nodes.length === 0) {
|
||||
store.fetchNodes();
|
||||
}
|
||||
if (store.tags.length === 0) {
|
||||
store.fetchTags();
|
||||
}
|
||||
|
||||
return {
|
||||
nodes: store.nodes,
|
||||
tags: store.tags,
|
||||
fetchNodes: store.fetchNodes,
|
||||
fetchTags: store.fetchTags,
|
||||
getNodeById: store.getNodeById,
|
||||
isProtocolUsedInNodes: store.isProtocolUsedInNodes,
|
||||
isServerReferencedByNodes: store.isServerReferencedByNodes,
|
||||
getNodesByTag: store.getNodesByTag,
|
||||
getNodesWithoutTags: store.getNodesWithoutTags,
|
||||
getNodeTags: store.getNodeTags,
|
||||
getAllAvailableTags: store.getAllAvailableTags,
|
||||
};
|
||||
};
|
||||
|
||||
export default useNodeStore;
|
||||
@@ -0,0 +1,94 @@
|
||||
import { filterServerList } from '@/services/admin/server';
|
||||
import { create } from 'zustand';
|
||||
|
||||
interface ServerState {
|
||||
// Data
|
||||
servers: API.Server[];
|
||||
|
||||
// Actions
|
||||
fetchServers: () => Promise<void>;
|
||||
|
||||
// Getters
|
||||
getServerById: (serverId: number) => API.Server | undefined;
|
||||
getServerName: (serverId?: number) => string;
|
||||
getServerAddress: (serverId?: number) => string;
|
||||
getServerEnabledProtocols: (serverId: number) => API.Protocol[];
|
||||
getProtocolPort: (serverId?: number, protocol?: string) => string;
|
||||
getAvailableProtocols: (serverId?: number) => Array<{ protocol: string; port: number }>;
|
||||
}
|
||||
|
||||
export const useServerStore = create<ServerState>((set, get) => ({
|
||||
// Initial state
|
||||
servers: [],
|
||||
|
||||
// Actions
|
||||
fetchServers: async () => {
|
||||
try {
|
||||
const { data } = await filterServerList({ page: 1, size: 999999999 });
|
||||
set({ servers: data?.data?.list || [] });
|
||||
} catch (error) {
|
||||
// Handle error silently
|
||||
}
|
||||
},
|
||||
|
||||
// Getters
|
||||
getServerById: (serverId: number) => {
|
||||
return get().servers.find((s) => s.id === serverId);
|
||||
},
|
||||
|
||||
getServerName: (serverId?: number) => {
|
||||
if (!serverId) return '—';
|
||||
const server = get().servers.find((s) => s.id === serverId);
|
||||
return server?.name ?? `#${serverId}`;
|
||||
},
|
||||
|
||||
getServerAddress: (serverId?: number) => {
|
||||
if (!serverId) return '—';
|
||||
const server = get().servers.find((s) => s.id === serverId);
|
||||
return server?.address ?? '—';
|
||||
},
|
||||
|
||||
getServerEnabledProtocols: (serverId: number) => {
|
||||
const server = get().servers.find((s) => s.id === serverId);
|
||||
return server?.protocols?.filter((p) => p.enable !== false) || [];
|
||||
},
|
||||
|
||||
getProtocolPort: (serverId?: number, protocol?: string) => {
|
||||
if (!serverId || !protocol) return '—';
|
||||
const enabledProtocols = get().getServerEnabledProtocols(serverId);
|
||||
const protocolConfig = enabledProtocols.find((p) => p.type === protocol);
|
||||
return protocolConfig?.port ? String(protocolConfig.port) : '—';
|
||||
},
|
||||
|
||||
getAvailableProtocols: (serverId?: number) => {
|
||||
if (!serverId) return [];
|
||||
return get()
|
||||
.getServerEnabledProtocols(serverId)
|
||||
.map((p) => ({
|
||||
protocol: p.type,
|
||||
port: p.port,
|
||||
}));
|
||||
},
|
||||
}));
|
||||
|
||||
export const useServer = () => {
|
||||
const store = useServerStore();
|
||||
|
||||
// Auto-fetch servers
|
||||
if (store.servers.length === 0) {
|
||||
store.fetchServers();
|
||||
}
|
||||
|
||||
return {
|
||||
servers: store.servers,
|
||||
fetchServers: store.fetchServers,
|
||||
getServerById: store.getServerById,
|
||||
getServerName: store.getServerName,
|
||||
getServerAddress: store.getServerAddress,
|
||||
getServerEnabledProtocols: store.getServerEnabledProtocols,
|
||||
getProtocolPort: store.getProtocolPort,
|
||||
getAvailableProtocols: store.getAvailableProtocols,
|
||||
};
|
||||
};
|
||||
|
||||
export default useServerStore;
|
||||
@@ -0,0 +1,58 @@
|
||||
import { getSubscribeList } from '@/services/admin/subscribe';
|
||||
import { create } from 'zustand';
|
||||
|
||||
interface SubscribeState {
|
||||
// Data
|
||||
subscribes: API.SubscribeItem[];
|
||||
|
||||
// Actions
|
||||
fetchSubscribes: () => Promise<void>;
|
||||
|
||||
// Getters
|
||||
getSubscribeName: (subscribeId?: number) => string;
|
||||
getSubscribeById: (subscribeId: number) => API.SubscribeItem | undefined;
|
||||
}
|
||||
|
||||
export const useSubscribeStore = create<SubscribeState>((set, get) => ({
|
||||
// Initial state
|
||||
subscribes: [],
|
||||
|
||||
// Actions
|
||||
fetchSubscribes: async () => {
|
||||
try {
|
||||
const { data } = await getSubscribeList({ page: 1, size: 999999999 });
|
||||
set({ subscribes: data?.data?.list || [] });
|
||||
} catch (error) {
|
||||
// Handle error silently
|
||||
}
|
||||
},
|
||||
|
||||
// Getters
|
||||
getSubscribeName: (subscribeId?: number) => {
|
||||
if (!subscribeId) return 'Unknown';
|
||||
const subscribe = get().subscribes.find((s) => s.id === subscribeId);
|
||||
return subscribe?.name ?? `Subscribe ${subscribeId}`;
|
||||
},
|
||||
|
||||
getSubscribeById: (subscribeId: number) => {
|
||||
return get().subscribes.find((s) => s.id === subscribeId);
|
||||
},
|
||||
}));
|
||||
|
||||
export const useSubscribe = () => {
|
||||
const store = useSubscribeStore();
|
||||
|
||||
// Auto-fetch subscribes
|
||||
if (store.subscribes.length === 0) {
|
||||
store.fetchSubscribes();
|
||||
}
|
||||
|
||||
return {
|
||||
subscribes: store.subscribes,
|
||||
fetchSubscribes: store.fetchSubscribes,
|
||||
getSubscribeName: store.getSubscribeName,
|
||||
getSubscribeById: store.getSubscribeById,
|
||||
};
|
||||
};
|
||||
|
||||
export default useSubscribeStore;
|
||||
Reference in New Issue
Block a user