diff --git a/skills b/skills index 2275afb46..87d75f69b 160000 --- a/skills +++ b/skills @@ -1 +1 @@ -Subproject commit 2275afb4668ef99d5e6ac4246d4a1d150605444f +Subproject commit 87d75f69b7e600ab9fc5cee9d861546e01c89fac diff --git a/src/App.tsx b/src/App.tsx index 63751d9a5..c611e3768 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -4,6 +4,7 @@ import { HashRouter as Router } from 'react-router-dom'; import { PersistGate } from 'redux-persist/integration/react'; import AppRoutes from './AppRoutes'; +import MiniSidebar from './components/MiniSidebar'; import AIProvider from './providers/AIProvider'; import ModelProvider from './providers/ModelProvider'; import SkillProvider from './providers/SkillProvider'; @@ -23,14 +24,19 @@ function App() {
-
-
- AlphaHuman is in early beta. +
+ +
+
+ +
+
+
+ AlphaHuman is in early beta. Version 0.1.0 +
+
-
- -
diff --git a/src/AppRoutes.tsx b/src/AppRoutes.tsx index 6cf59dc2a..e1d91eb79 100644 --- a/src/AppRoutes.tsx +++ b/src/AppRoutes.tsx @@ -4,10 +4,12 @@ import { Navigate, Route, Routes } from 'react-router-dom'; import DefaultRedirect from './components/DefaultRedirect'; import ProtectedRoute from './components/ProtectedRoute'; import PublicRoute from './components/PublicRoute'; -import SettingsModal from './components/settings/SettingsModal'; +import Agents from './pages/Agents'; +import Conversations from './pages/Conversations'; import Home from './pages/Home'; import Login from './pages/Login'; import Onboarding from './pages/onboarding/Onboarding'; +import Settings from './pages/Settings'; import Welcome from './pages/Welcome'; import { selectIsOnboarded } from './store/authSelectors'; import { useAppSelector } from './store/hooks'; @@ -85,12 +87,32 @@ const AppRoutes = () => { } /> - {/* Settings modal routes - protected */} + {/* Conversations */} + + + + } + /> + + {/* Agents */} + + + + } + /> + + {/* Settings - rendered as page content */} - + } /> @@ -98,9 +120,6 @@ const AppRoutes = () => { {/* Default redirect based on auth status */} } /> - - {/* Settings Modal - renders over existing content when on settings routes */} - ); }; diff --git a/src/components/MiniSidebar.tsx b/src/components/MiniSidebar.tsx new file mode 100644 index 000000000..85331d9ff --- /dev/null +++ b/src/components/MiniSidebar.tsx @@ -0,0 +1,117 @@ +import { useLocation, useNavigate } from 'react-router-dom'; + +import { useAppSelector } from '../store/hooks'; + +const navItems = [ + { + id: 'home', + label: 'Home', + path: '/home', + icon: ( + + + + ), + }, + // { + // id: 'conversations', + // label: 'Conversations', + // path: '/conversations', + // icon: ( + // + // + // + // ), + // }, + // { + // id: 'agents', + // label: 'Agents', + // path: '/agents', + // icon: ( + // + // + // + // ), + // }, + { + id: 'settings', + label: 'Settings', + path: '/settings', + icon: ( + + + + + ), + }, +]; + +const MiniSidebar = () => { + const location = useLocation(); + const navigate = useNavigate(); + const token = useAppSelector(state => state.auth.token); + + // Hide sidebar when not authenticated or on public/onboarding routes + const hiddenPaths = ['/', '/login', '/onboarding']; + if (!token || hiddenPaths.includes(location.pathname)) { + return null; + } + + const isActive = (path: string) => { + if (path === '/settings') return location.pathname.startsWith('/settings'); + return location.pathname === path; + }; + + return ( +
+ {navItems.map(item => { + const active = isActive(item.path); + return ( +
+ + {/* Tooltip - appears to the right */} +
+ {item.label} +
+
+ ); + })} +
+ ); +}; + +export default MiniSidebar; diff --git a/src/components/settings/SettingsHome.tsx b/src/components/settings/SettingsHome.tsx index 6b9cbffa6..2ede7815e 100644 --- a/src/components/settings/SettingsHome.tsx +++ b/src/components/settings/SettingsHome.tsx @@ -196,10 +196,10 @@ const SettingsHome = () => { ]; return ( -
+
-
+
{/* Main Settings */}
diff --git a/src/components/settings/SettingsLayout.tsx b/src/components/settings/SettingsLayout.tsx deleted file mode 100644 index aba1b19b8..000000000 --- a/src/components/settings/SettingsLayout.tsx +++ /dev/null @@ -1,73 +0,0 @@ -import { ReactNode, useEffect, useRef } from 'react'; -import { createPortal } from 'react-dom'; - -interface SettingsLayoutProps { - children: ReactNode; - onClose: () => void; -} - -const SettingsLayout = ({ children, onClose }: SettingsLayoutProps) => { - const modalRef = useRef(null); - - // Handle escape key - useEffect(() => { - const handleEscape = (e: KeyboardEvent) => { - if (e.key === 'Escape') { - onClose(); - } - }; - - document.addEventListener('keydown', handleEscape); - return () => document.removeEventListener('keydown', handleEscape); - }, [onClose]); - - // Handle backdrop click - const handleBackdropClick = (e: React.MouseEvent) => { - if (e.target === e.currentTarget) { - onClose(); - } - }; - - // Focus management for accessibility - useEffect(() => { - const previousFocus = document.activeElement as HTMLElement; - - // Focus the modal container - if (modalRef.current) { - modalRef.current.focus(); - } - - // Restore focus when modal closes - return () => { - if (previousFocus && previousFocus.focus) { - previousFocus.focus(); - } - }; - }, []); - - const modalContent = ( -
-
e.stopPropagation()}> - {children} -
-
- ); - - return createPortal(modalContent, document.body); -}; - -export default SettingsLayout; diff --git a/src/components/settings/SettingsModal.tsx b/src/components/settings/SettingsModal.tsx deleted file mode 100644 index 4248d0d00..000000000 --- a/src/components/settings/SettingsModal.tsx +++ /dev/null @@ -1,45 +0,0 @@ -import { Route, Routes, useLocation } from 'react-router-dom'; - -import { useSettingsNavigation } from './hooks/useSettingsNavigation'; -import AdvancedPanel from './panels/AdvancedPanel'; -import BillingPanel from './panels/BillingPanel'; -import ConnectionsPanel from './panels/ConnectionsPanel'; -import MessagingPanel from './panels/MessagingPanel'; -import PrivacyPanel from './panels/PrivacyPanel'; -import ProfilePanel from './panels/ProfilePanel'; -import TeamInvitesPanel from './panels/TeamInvitesPanel'; -import TeamMembersPanel from './panels/TeamMembersPanel'; -import TeamPanel from './panels/TeamPanel'; -import SettingsHome from './SettingsHome'; -import SettingsLayout from './SettingsLayout'; - -const SettingsModal = () => { - const location = useLocation(); - const { closeSettings } = useSettingsNavigation(); - - // Only render modal when on settings routes - const isSettingsRoute = location.pathname.startsWith('/settings'); - - if (!isSettingsRoute) { - return null; - } - - return ( - - - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - - - ); -}; - -export default SettingsModal; diff --git a/src/components/settings/components/SettingsHeader.tsx b/src/components/settings/components/SettingsHeader.tsx index c9e025520..5bb1fbb6b 100644 --- a/src/components/settings/components/SettingsHeader.tsx +++ b/src/components/settings/components/SettingsHeader.tsx @@ -1,5 +1,3 @@ -import { useSettingsNavigation } from '../hooks/useSettingsNavigation'; - interface SettingsHeaderProps { className?: string; title?: string; @@ -13,53 +11,32 @@ const SettingsHeader = ({ showBackButton = false, onBack, }: SettingsHeaderProps) => { - const { closeSettings } = useSettingsNavigation(); - return ( -
-
-
- {/* Back button */} - {showBackButton && onBack && ( - - )} +
+
+ {/* Back button */} + {showBackButton && onBack && ( + + )} - {/* Title */} -

- {title} -

-
- - {/* Close button */} - + {/* Title */} +

{title}

); diff --git a/src/components/settings/panels/BillingPanel.tsx b/src/components/settings/panels/BillingPanel.tsx index 2bedbae71..58b1da445 100644 --- a/src/components/settings/panels/BillingPanel.tsx +++ b/src/components/settings/panels/BillingPanel.tsx @@ -225,152 +225,137 @@ const BillingPanel = () => {
- {/* ── Plan tier cards ───────────────────────────────────── */} -
- {PLANS.map(plan => { - const isCurrent = plan.tier === currentTier; - const isUpgrade = checkIsUpgrade(plan.tier, currentTier); - const savings = annualSavings(plan, billingInterval); - const isThisPurchasing = isPurchasing && purchasingTier === plan.tier; +
+ {/* ── Plan tier cards ───────────────────────────────────── */} +
+ {PLANS.map(plan => { + const isCurrent = plan.tier === currentTier; + const isUpgrade = checkIsUpgrade(plan.tier, currentTier); + const savings = annualSavings(plan, billingInterval); + const isThisPurchasing = isPurchasing && purchasingTier === plan.tier; - return ( -
-
-
-
-

{plan.name}

- {/* Features inline with title */} - {plan.features.map(f => ( - - - {f.text} + return ( +
+
+
+
+

{plan.name}

+ {/* Features inline with title */} + {plan.features.map(f => ( + + + {f.text} + + ))} + {isCurrent && ( + + Current + + )} + {savings && ( + + Save {savings}% + + )} +
+
+ + {displayPrice(plan, billingInterval)} - ))} - {isCurrent && ( - - Current - - )} - {savings && ( - - Save {savings}% - - )} -
-
- - {displayPrice(plan, billingInterval)} - - {plan.tier !== 'FREE' && ( - /mo - )} - {plan.tier !== 'FREE' && billingInterval === 'annual' && ( - - (billed ${plan.annualPrice}/yr) - - )} + {plan.tier !== 'FREE' && ( + /mo + )} + {plan.tier !== 'FREE' && billingInterval === 'annual' && ( + + (billed ${plan.annualPrice}/yr) + + )} +
+ + {/* Action button */} + {isUpgrade && ( + + )}
- - {/* Action button */} - {isUpgrade && ( - - )}
-
- ); - })} -
- - {/* ── Purchasing overlay message ────────────────────────── */} - {isPurchasing && ( -
-
- - - - -

- Waiting for payment confirmation... Complete checkout in the browser window that - opened. -

-
+ ); + })}
- )} - {/* ── Pay with crypto toggle ────────────────────────────── */} -
-
-

Pay with Crypto

-

- You can choose to pay annually using crypto -

-
- -
- - {/* ── Upgrade benefits ───────────────────────────────────── */} -
-
-

Why upgrade?

-
    -
  • + {/* ── Purchasing overlay message ────────────────────────── */} + {isPurchasing && ( +
    +
    + - Unlock higher daily limits for more AI interactions -
  • - {currentTier === 'FREE' && ( +

    + Waiting for payment confirmation... Complete checkout in the browser window that + opened. +

    +
+
+ )} + + {/* ── Pay with crypto toggle ────────────────────────────── */} +
+
+

Pay with Crypto

+

+ You can choose to pay annually using crypto +

+
+ +
+ + {/* ── Upgrade benefits ───────────────────────────────────── */} +
+
+

Why upgrade?

+
  • { d="M5 13l4 4L19 7" /> - - Save up to 20% with annual plans and never worry about hitting limits - + Unlock higher daily limits for more AI interactions
  • - )} -
+ {currentTier === 'FREE' && ( +
  • + + + + + Save up to 20% with annual plans and never worry about hitting limits + +
  • + )} + +
    diff --git a/src/pages/Agents.tsx b/src/pages/Agents.tsx new file mode 100644 index 000000000..ef4c7b532 --- /dev/null +++ b/src/pages/Agents.tsx @@ -0,0 +1,32 @@ +const Agents = () => { + return ( +
    +
    +
    +
    +
    +
    + + + +
    +

    Agents

    +

    Your AI agents will appear here

    +
    +
    +
    +
    +
    + ); +}; + +export default Agents; diff --git a/src/pages/Conversations.tsx b/src/pages/Conversations.tsx new file mode 100644 index 000000000..49e813074 --- /dev/null +++ b/src/pages/Conversations.tsx @@ -0,0 +1,32 @@ +const Conversations = () => { + return ( +
    +
    +
    +
    +
    +
    + + + +
    +

    Conversations

    +

    Your conversations will appear here

    +
    +
    +
    +
    +
    + ); +}; + +export default Conversations; diff --git a/src/pages/Home.tsx b/src/pages/Home.tsx index a2bd44149..6d0307564 100644 --- a/src/pages/Home.tsx +++ b/src/pages/Home.tsx @@ -25,10 +25,6 @@ const Home = () => { await openUrl(`https://t.me/${TELEGRAM_BOT_USERNAME}`); }; - const handleManageConnections = () => { - navigate('/settings'); - }; - const handleUpgrade = () => { navigate('/settings/billing'); }; @@ -103,39 +99,6 @@ const Home = () => {
    - {/* Action buttons */} -
    - {/* Settings */} - -
    - {/* Skills Grid */} diff --git a/src/pages/Settings.tsx b/src/pages/Settings.tsx new file mode 100644 index 000000000..e13e3a54c --- /dev/null +++ b/src/pages/Settings.tsx @@ -0,0 +1,33 @@ +import { Route, Routes } from 'react-router-dom'; + +import AdvancedPanel from '../components/settings/panels/AdvancedPanel'; +import BillingPanel from '../components/settings/panels/BillingPanel'; +import ConnectionsPanel from '../components/settings/panels/ConnectionsPanel'; +import MessagingPanel from '../components/settings/panels/MessagingPanel'; +import PrivacyPanel from '../components/settings/panels/PrivacyPanel'; +import ProfilePanel from '../components/settings/panels/ProfilePanel'; +import TeamInvitesPanel from '../components/settings/panels/TeamInvitesPanel'; +import TeamMembersPanel from '../components/settings/panels/TeamMembersPanel'; +import TeamPanel from '../components/settings/panels/TeamPanel'; +import SettingsHome from '../components/settings/SettingsHome'; + +const Settings = () => { + return ( +
    + + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + +
    + ); +}; + +export default Settings;