-
Notifications
You must be signed in to change notification settings - Fork 44
feat: add enhanced navigation system with active route indicators #102
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| 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> | ||
| ) | ||
| } | ||
|
|
||
| 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 |
| 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
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
|
|
||
| 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 | ||
| 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
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The conditional rendering for navigation links introduces some UX inconsistencies:
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 | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a lot of repeated layout code across the new page components (
APIPage,ChatPage,DocumentsPage,SettingsPage). Specifically, thedivwith background color, padding, and max-width container is duplicated. To improve maintainability and reduce code duplication, consider creating a reusablePageLayoutcomponent that wraps the content of each page.For example, you could create a
PageLayoutcomponent:And then use it in your page components like this: