Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 11 additions & 7 deletions LocalMind-Frontend/src/app/routes/AppRoutes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,27 @@ import React from 'react'
import { Route, Routes } from 'react-router-dom'
import HomePage from '../../features/Dashboard/V1/Component/Pages/HomePage'
import LoginPage from '../../shared/component/v1/LoginPage'
import ChatPage from '../../features/Dashboard/V1/Component/Pages/ChatPage'
import DocumentsPage from '../../features/Dashboard/V1/Component/Pages/DocumentsPage'
import SettingsPage from '../../features/Dashboard/V1/Component/Pages/SettingsPage'
import APIPage from '../../features/Dashboard/V1/Component/Pages/APIPage'

const AppRoutes: React.FC = () => {
return (
<Routes>
{/* Homepage */}
<Route path="/" element={<HomePage />} />

{/* Sign Up / Login Page */}
<Route path="/login" element={<LoginPage />} />
{/* Main Application Pages */}
<Route path="/chat" element={<ChatPage />} />
<Route path="/documents" element={<DocumentsPage />} />
<Route path="/settings" element={<SettingsPage />} />
<Route path="/api" element={<APIPage />} />

{/* Register Page - TODO: Create dedicated RegisterPage component */}
{/* Authentication Pages */}
<Route path="/login" element={<LoginPage />} />
<Route path="/register" element={<LoginPage />} />

{/* Forgot Password Page - TODO: Create ForgotPasswordPage component */}
<Route path="/forgot-password" element={<LoginPage />} />

{/* Chat Page */}
</Routes>
)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import React from 'react'
import Breadcrumb from '../../../../../shared/component/v1/Breadcrumb'

const APIPage: React.FC = () => {
return (
<div className="min-h-screen bg-[#1E1E1E] text-white pt-20 px-6">
<div className="max-w-6xl mx-auto">
<Breadcrumb />
<header className="mb-8">
<h1 className="text-3xl font-bold mb-2">API Information</h1>
<p className="text-gray-400">Manage API keys and view documentation</p>
</header>

<div className="space-y-6">
<div className="bg-zinc-900/50 rounded-lg p-6 border border-zinc-700">
<h3 className="text-xl font-semibold mb-4">API Keys</h3>
<div className="space-y-4">
<div className="flex items-center justify-between p-4 bg-zinc-800 rounded-lg">
<div>
<h4 className="font-medium">Production Key</h4>
<p className="text-sm text-gray-400 font-mono">lm_****************************</p>
</div>
<button className="px-4 py-2 bg-red-600 text-sm rounded-lg hover:bg-red-700">
Revoke
</button>
</div>
</div>
<button className="mt-4 px-4 py-2 bg-blue-600 text-sm rounded-lg hover:bg-blue-700">
Generate New Key
</button>
</div>

<div className="bg-zinc-900/50 rounded-lg p-6 border border-zinc-700">
<h3 className="text-xl font-semibold mb-4">API Endpoints</h3>
<div className="space-y-3">
<div className="p-3 bg-zinc-800 rounded font-mono text-sm">
<span className="text-green-400">POST</span> /api/v1/chat/send-message
</div>
<div className="p-3 bg-zinc-800 rounded font-mono text-sm">
<span className="text-blue-400">GET</span> /api/v1/upload/files
</div>
<div className="p-3 bg-zinc-800 rounded font-mono text-sm">
<span className="text-yellow-400">PUT</span> /api/v1/user/ai-config
</div>
</div>
</div>
</div>
</div>
</div>
Comment on lines +6 to +49
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

There's a lot of repeated layout code across the new page components (APIPage, ChatPage, DocumentsPage, SettingsPage). Specifically, the div with background color, padding, and max-width container is duplicated. To improve maintainability and reduce code duplication, consider creating a reusable PageLayout component that wraps the content of each page.

For example, you could create a PageLayout component:

// src/shared/component/v1/PageLayout.tsx
import React from 'react';

const PageLayout: React.FC<{ children: React.ReactNode }> = ({ children }) => (
  <div className="min-h-screen bg-[#1E1E1E] text-white pt-20 px-6">
    <div className="max-w-6xl mx-auto">{children}</div>
  </div>
);

export default PageLayout;

And then use it in your page components like this:

// APIPage.tsx
import PageLayout from '...';
// ...

const APIPage: React.FC = () => (
  <PageLayout>
    <Breadcrumb />
    {/* ... rest of the page content */}
  </PageLayout>
);

)
}

export default APIPage
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import React from 'react'
import Breadcrumb from '../../../../../shared/component/v1/Breadcrumb'

const ChatPage: React.FC = () => {
return (
<div className="min-h-screen bg-[#1E1E1E] text-white pt-20 px-6">
<div className="max-w-6xl mx-auto">
<Breadcrumb />
<header className="mb-8">
<h1 className="text-3xl font-bold mb-2">Chat Interface</h1>
<p className="text-gray-400">Interact with AI models in real-time</p>
</header>

<div className="bg-zinc-900/50 rounded-lg p-6 border border-zinc-700">
<div className="text-center py-20">
<h3 className="text-xl mb-4">Chat Interface Coming Soon</h3>
<p className="text-gray-400">Real-time AI chat system will be available here</p>
</div>
</div>
</div>
</div>
)
}

export default ChatPage
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import React from 'react'
import Breadcrumb from '../../../../../shared/component/v1/Breadcrumb'

const DocumentsPage: React.FC = () => {
return (
<div className="min-h-screen bg-[#1E1E1E] text-white pt-20 px-6">
<div className="max-w-6xl mx-auto">
<Breadcrumb />
<header className="mb-8">
<h1 className="text-3xl font-bold mb-2">Document Upload & RAG</h1>
<p className="text-gray-400">Upload documents and train your AI with custom data</p>
</header>

<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
<div className="bg-zinc-900/50 rounded-lg p-6 border border-zinc-700">
<h3 className="text-xl font-semibold mb-4">Upload Documents</h3>
<div className="border-2 border-dashed border-zinc-600 rounded-lg p-8 text-center">
<p className="text-gray-400 mb-4">Drag & drop files here or click to browse</p>
<p className="text-sm text-gray-500">Supported: Excel, CSV, PDF, TXT</p>
</div>
</div>

<div className="bg-zinc-900/50 rounded-lg p-6 border border-zinc-700">
<h3 className="text-xl font-semibold mb-4">Uploaded Files</h3>
<div className="text-center py-8">
<p className="text-gray-400">No files uploaded yet</p>
</div>
</div>
</div>
</div>
</div>
)
}

export default DocumentsPage
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import React from 'react'
import Breadcrumb from '../../../../../shared/component/v1/Breadcrumb'

const SettingsPage: React.FC = () => {
return (
<div className="min-h-screen bg-[#1E1E1E] text-white pt-20 px-6">
<div className="max-w-6xl mx-auto">
<Breadcrumb />
<header className="mb-8">
<h1 className="text-3xl font-bold mb-2">Model Configuration</h1>
<p className="text-gray-400">Configure AI models and API settings</p>
</header>

<div className="space-y-6">
<div className="bg-zinc-900/50 rounded-lg p-6 border border-zinc-700">
<h3 className="text-xl font-semibold mb-4">Local Models (Ollama)</h3>
<div className="space-y-4">
<div className="flex items-center justify-between p-4 bg-zinc-800 rounded-lg">
<div>
<h4 className="font-medium">LLaMA 2</h4>
<p className="text-sm text-gray-400">7B parameter model</p>
</div>
<span className="px-3 py-1 bg-green-600 text-xs rounded-full">Available</span>
</div>
</div>
</div>

<div className="bg-zinc-900/50 rounded-lg p-6 border border-zinc-700">
<h3 className="text-xl font-semibold mb-4">Cloud Models</h3>
<div className="space-y-4">
<div className="flex items-center justify-between p-4 bg-zinc-800 rounded-lg">
<div>
<h4 className="font-medium">Google Gemini</h4>
<p className="text-sm text-gray-400">Configure API key</p>
</div>
<button className="px-4 py-2 bg-blue-600 text-sm rounded-lg hover:bg-blue-700">
Configure
</button>
</div>
</div>
</div>
</div>
</div>
</div>
)
}

export default SettingsPage
60 changes: 60 additions & 0 deletions LocalMind-Frontend/src/shared/component/v1/Breadcrumb.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import React from 'react'
import { Link, useLocation } from 'react-router-dom'

interface BreadcrumbItem {
label: string
path: string
}

const Breadcrumb: React.FC = () => {
const location = useLocation()

const getBreadcrumbs = (): BreadcrumbItem[] => {
const pathMap: Record<string, string> = {
'/': 'Home',
'/chat': 'Chat Interface',
'/documents': 'Documents & RAG',
'/settings': 'Model Settings',
'/api': 'API Information'
}

const currentPath = location.pathname
const breadcrumbs: BreadcrumbItem[] = []

if (currentPath !== '/') {
breadcrumbs.push({ label: 'Home', path: '/' })
}

if (pathMap[currentPath]) {
breadcrumbs.push({ label: pathMap[currentPath], path: currentPath })
}

return breadcrumbs
}

const breadcrumbs = getBreadcrumbs()
Comment on lines +12 to +35
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The getBreadcrumbs function is redefined on every render, which is inefficient. For better performance and cleaner code, you can compute the breadcrumbs array using React.useMemo. This ensures it's only recalculated when the location.pathname changes. Additionally, the pathMap object can be moved outside the component body to be a constant, preventing its redeclaration on each render.

  const breadcrumbs = React.useMemo((): BreadcrumbItem[] => {
    const pathMap: Record<string, string> = {
      '/': 'Home',
      '/chat': 'Chat Interface',
      '/documents': 'Documents & RAG',
      '/settings': 'Model Settings',
      '/api': 'API Information'
    }

    const currentPath = location.pathname
    const crumbs: BreadcrumbItem[] = []

    if (currentPath !== '/') {
      crumbs.push({ label: 'Home', path: '/' })
    }

    if (pathMap[currentPath]) {
      crumbs.push({ label: pathMap[currentPath], path: currentPath })
    }

    return crumbs
  }, [location.pathname])


if (breadcrumbs.length <= 1) return null

return (
<nav className="flex items-center space-x-2 text-sm text-gray-400 mb-6">
{breadcrumbs.map((item, index) => (
<React.Fragment key={item.path}>
{index > 0 && <span className="text-gray-600">/</span>}
{index === breadcrumbs.length - 1 ? (
<span className="text-white font-medium">{item.label}</span>
) : (
<Link
to={item.path}
className="hover:text-white transition-colors"
>
{item.label}
</Link>
)}
</React.Fragment>
))}
</nav>
)
}

export default Breadcrumb
75 changes: 55 additions & 20 deletions LocalMind-Frontend/src/shared/component/v1/Navbar.tsx
Original file line number Diff line number Diff line change
@@ -1,39 +1,74 @@
import React from 'react'
import Artificialintelligence from '../../../assets/Artificial intelligence.png'
import { NavLink } from 'react-router-dom'
import { NavLink, useLocation } from 'react-router-dom'

const Navbar: React.FC = () => {
const location = useLocation()
const isAppRoute = ['/chat', '/documents', '/settings', '/api'].includes(location.pathname)

const navLinkClass = ({ isActive }: { isActive: boolean }) =>
isActive ? 'text-white line-through opacity-80' : 'text-white'
`px-4 py-2 rounded-lg font-medium transition-all duration-200 ${
isActive
? 'bg-blue-600 text-white shadow-lg'
: 'text-gray-300 hover:text-white hover:bg-zinc-700/50'
}`

const publicNavLinkClass = ({ isActive }: { isActive: boolean }) =>
isActive ? 'text-white border-b-2 border-blue-500' : 'text-gray-300 hover:text-white'

return (
<div className="fixed top-2 left-1/2 z-30 flex gap-x-50 items-center justify-between -translate-x-1/2 bg-zinc-900/40 backdrop-blur-md px-5 py-2 rounded-full border border-zinc-500/50 text-white">
<div className="fixed top-2 left-1/2 z-30 flex gap-x-8 items-center justify-between -translate-x-1/2 bg-zinc-900/40 backdrop-blur-md px-6 py-3 rounded-full border border-zinc-500/50 text-white min-w-fit">
<div className="flex gap-x-4 items-center">
<img src={Artificialintelligence} className="w-6 h-6" alt="LocalMind logo" />
<h1 className="uppercase font-Satoshi tracking-wider font-bold text-xl">LocalMind</h1>
<NavLink to="/" className="uppercase font-Satoshi tracking-wider font-bold text-xl hover:text-blue-400 transition-colors">
LocalMind
</NavLink>
</div>

<div className="flex gap-x-5 items-center">
<NavLink to="/" className={navLinkClass}>
Home
</NavLink>
<NavLink to="/docs" className={navLinkClass}>
Docs
</NavLink>
<NavLink to="/models" className={navLinkClass}>
Models
</NavLink>
<NavLink to="/play-ground" className={navLinkClass}>
PlayGround
</NavLink>
<div className="flex gap-x-2 items-center">
{isAppRoute ? (
// App Navigation (when user is in main app sections)
<>
<NavLink to="/chat" className={navLinkClass}>
πŸ’¬ Chat
</NavLink>
<NavLink to="/documents" className={navLinkClass}>
πŸ“š Documents
</NavLink>
<NavLink to="/settings" className={navLinkClass}>
βš™οΈ Settings
</NavLink>
<NavLink to="/api" className={navLinkClass}>
πŸ”Œ API
</NavLink>
</>
) : (
// Public Navigation (for homepage, etc.)
<>
<NavLink to="/" className={publicNavLinkClass}>
Home
</NavLink>
<NavLink to="/chat" className={publicNavLinkClass}>
Chat
</NavLink>
<NavLink to="/documents" className={publicNavLinkClass}>
Documents
</NavLink>
<NavLink to="/settings" className={publicNavLinkClass}>
Settings
</NavLink>
</>
)}
Comment on lines +29 to +61
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The conditional rendering for navigation links introduces some UX inconsistencies:

  1. Missing API Link: The public navigation (for the homepage) is missing a link to the /api page, which is one of the main application sections.
  2. Missing Home Link: The app navigation is missing a link back to the Home page. When a user navigates from the homepage to an app page, the 'Home' link disappears. While the logo links to home, an explicit navigation link provides better and more consistent usability.

Consider unifying the navigation links or ensuring both sets of links provide a consistent way to access all main pages.

</div>

<NavLink
to="/login"
className={({ isActive }) =>
isActive
? 'bg-blue-600 text-white px-8 py-1.5 rounded-full font-medium transition-colors hover:bg-blue-700 whitespace-nowrap'
: 'bg-blue-500 text-white px-8 py-1.5 rounded-full font-medium transition-colors hover:bg-blue-600 whitespace-nowrap'
`px-6 py-2 rounded-full font-medium transition-all duration-200 whitespace-nowrap ${
isActive
? 'bg-blue-700 text-white shadow-lg'
: 'bg-blue-600 text-white hover:bg-blue-700 hover:shadow-lg'
}`
}
>
Sign Up
Expand Down