feat: add app header, sidebar, and mobile navigation components
Deploy to VPS / deploy (push) Failing after 1m45s

- Implemented AppHeader component with theme toggle and connection status.
- Created AppSidebar component for navigation with connection status indicator.
- Added MobileNav component for mobile navigation with responsive design.
- Introduced shared components: DetailStat, EmptyState, ErrorState, LoadingSkeleton, and StatCard for consistent UI.
- Developed hooks for async data fetching: useAsync, useConfig, useDashboard, useGuilds, useMedia, useMessages, useRecordings, and useVoice.
- Added chatbot API functions for sending messages and managing chat history.
This commit is contained in:
asepharyana
2026-07-26 16:14:32 +07:00
parent 726ea8fca5
commit d5a547eb25
35 changed files with 2385 additions and 1733 deletions
+38
View File
@@ -0,0 +1,38 @@
import { useCallback, useEffect, useState } from "react";
import { voiceApi } from "@/lib/api";
import type { Guild } from "@/lib/types";
interface UseGuildsReturn {
guilds: Guild[];
loading: boolean;
error: string | null;
refetch: () => void;
}
/**
* Fetch the list of available Discord guilds.
*/
export function useGuilds(): UseGuildsReturn {
const [guilds, setGuilds] = useState<Guild[]>([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
const fetchGuilds = useCallback(() => {
setLoading(true);
setError(null);
voiceApi
.getGuilds()
.then(setGuilds)
.catch((err: unknown) =>
setError(err instanceof Error ? err.message : "Failed to load guilds"),
)
.finally(() => setLoading(false));
}, []);
useEffect(() => {
fetchGuilds();
}, [fetchGuilds]);
return { guilds, loading, error, refetch: fetchGuilds };
}