;
+ }
}
diff --git a/src/app/(dashboard)/docs/page.tsx b/src/app/(dashboard)/docs/page.tsx
new file mode 100644
index 0000000..86c904b
--- /dev/null
+++ b/src/app/(dashboard)/docs/page.tsx
@@ -0,0 +1,71 @@
+"use client";
+
+import {useEffect} from 'react';
+import {motion} from "framer-motion";
+import {Loader2} from "lucide-react"; // Changed icon to something more docs-related, or keep Loader2
+import {BACKEND_BASE_URL} from "@/lib/const";
+
+export default function DocsRedirectPage() { // Renamed component for clarity
+ const swaggerDocsUrl = `${BACKEND_BASE_URL}/docs`; // Use the constant for the backend URL
+
+ useEffect(() => {
+ // Wait for a short period (e.g., 1.5 seconds) and then redirect
+ const timer = setTimeout(() => {
+ window.location.href = swaggerDocsUrl;
+ }, 1500); // Adjust delay as needed
+
+ // Cleanup function to clear the timer if the component unmounts
+ return () => clearTimeout(timer);
+ }, [swaggerDocsUrl]); // Add swaggerDocsUrl to dependency array if it could change, though it's constant here
+
+ return (
+
+
+
+ {/* You can use Loader2 or a more specific icon like BookOpenCheck */}
+
+ {/* */}
+
+
+ Redirecting to API Docs
+
+
+ Please wait while we take you to the Swagger UI for our API.
+
+
+ Click here if you are not redirected automatically.
+
+
+
+ );
+}
diff --git a/src/app/(dashboard)/layout.tsx b/src/app/(dashboard)/layout.tsx
index 7733b8d..803e983 100644
--- a/src/app/(dashboard)/layout.tsx
+++ b/src/app/(dashboard)/layout.tsx
@@ -1,54 +1,62 @@
import {AppSidebar} from "@/app/(dashboard)/_components/app-sidebar"
import {Separator} from "@/components/ui/separator"
import {SidebarInset, SidebarProvider, SidebarTrigger,} from "@/components/ui/sidebar"
-import {Bell, LogOut} from "lucide-react"
+import {LogOut} from "lucide-react"
import {ModeToggle} from "@/components/ThemeProvider";
-import {Button} from "@/components/ui/button";
import React, {Suspense} from "react";
import {SidebarSkeleton} from "@/app/(dashboard)/_components/sidebar-skeleton";
import Link from "next/link";
+import HeaderSearchBar from "./_components/HeaderSearchBar";
+import {BalanceProvider} from "@/context/BalanceContext";
+import BalanceDisplay from "@/app/(dashboard)/_components/BalanceDisplay"; // Import the new component
export default function DashboardLayout({children}: { children: React.ReactNode }) {
return (
-
- }>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+ }>
+
+
+
+
+
+
+
+
+ {/* Search bar in the middle */}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {children}
+ {/**/}
-
-
- {children}
- {/**/}
-
-
-
+
+
+
)
}
\ No newline at end of file
diff --git a/src/app/globals.css b/src/app/globals.css
index 8080f5a..dea7c6f 100644
--- a/src/app/globals.css
+++ b/src/app/globals.css
@@ -217,33 +217,33 @@
justify-content: center;
align-items: center;
gap: 5px;
- }
-
- .typing-dots span {
+}
+
+.typing-dots span {
width: 8px;
height: 8px;
background-color: #4f46e5; /* Customize the color */
border-radius: 50%;
animation: typing 1.5s infinite ease-in-out;
- }
-
- .typing-dots span:nth-child(1) {
+}
+
+.typing-dots span:nth-child(1) {
animation-delay: 0s;
- }
-
- .typing-dots span:nth-child(2) {
+}
+
+.typing-dots span:nth-child(2) {
animation-delay: 0.2s;
- }
-
- .typing-dots span:nth-child(3) {
+}
+
+.typing-dots span:nth-child(3) {
animation-delay: 0.4s;
- }
-
- @keyframes typing {
+}
+
+@keyframes typing {
0%, 80%, 100% {
- transform: scale(0);
+ transform: scale(0);
}
40% {
- transform: scale(1);
+ transform: scale(1);
}
- }
\ No newline at end of file
+}
\ No newline at end of file
diff --git a/src/app/page.tsx b/src/app/page.tsx
index 9da8c59..bd286d9 100644
--- a/src/app/page.tsx
+++ b/src/app/page.tsx
@@ -95,7 +95,7 @@ export default function Home() {
Get Started
diff --git a/src/context/BalanceContext.tsx b/src/context/BalanceContext.tsx
new file mode 100644
index 0000000..76c514b
--- /dev/null
+++ b/src/context/BalanceContext.tsx
@@ -0,0 +1,42 @@
+// context/BalanceContext.tsx
+'use client';
+import React, {createContext, useContext} from 'react';
+import useSWR from 'swr';
+import AxiosInstance from '@/lib/client-fetcher';
+import {getCurrentUser} from "@/actions/auth";
+import {budgetData} from "@/app/(dashboard)/dashboard/portfolio/_components/port-opt-form"; // your interceptor-based Axios instance
+
+const fetcher = async () => {
+ const currentUser = await getCurrentUser()
+
+ const res = await AxiosInstance.get(`/budget/transactions/summary/${currentUser?.user_id}`);
+ return res.data;
+};
+
+const BalanceContext = createContext<{
+ balance: number | null;
+ isLoading: boolean;
+ refetch: () => void;
+} | null>(null);
+
+export const BalanceProvider = ({children}: { children: React.ReactNode }) => {
+ const {data, error, mutate} = useSWR('/balance', fetcher);
+
+ return (
+ mutate(),
+ }}
+ >
+ {children}
+
+ );
+};
+
+export const useBalance = () => {
+ const context = useContext(BalanceContext);
+ if (!context) throw new Error('useBalance must be used within a BalanceProvider');
+ return context;
+};
diff --git a/src/middleware.ts b/src/middleware.ts
index 5310589..b1c5341 100644
--- a/src/middleware.ts
+++ b/src/middleware.ts
@@ -82,7 +82,7 @@ export default async function middleware(req: NextRequest) {
// Redirect authenticated users away from login page
if (session?.sub && (path === "/auth/login" || path === "/auth/register")) {
- return NextResponse.redirect(new URL("/dashboard", req.nextUrl));
+ return NextResponse.redirect(new URL("/global-assets/lookup", req.nextUrl));
}
// Authentication check: Redirect to login if accessing protected route without a session