fix: remove tenant switcher from TopBar, fix aiProactive API double-prefix
- Remove tenant switcher dropdown from TopBar (cleanup unused vars/imports) - Fix aiProactive.ts: remove /api/v1 prefix from apiClient calls (baseURL already includes it) - This fixes 404 errors on /api/v1/api/v1/ai-proactive/suggestions
This commit is contained in:
@@ -21,7 +21,7 @@ export function useSuggestions() {
|
||||
|
||||
useEffect(() => {
|
||||
// Initial load
|
||||
apiClient.get('/api/v1/ai-proactive/suggestions').then(r => {
|
||||
apiClient.get('/ai-proactive/suggestions').then(r => {
|
||||
setSuggestions(r.data.items);
|
||||
}).catch(() => {});
|
||||
|
||||
@@ -41,11 +41,11 @@ export function useSuggestions() {
|
||||
|
||||
const dismiss = useCallback(async (id: string) => {
|
||||
setSuggestions(prev => prev.filter(s => s.id !== id));
|
||||
await apiClient.post(`/api/v1/ai-proactive/suggestions/${id}/dismiss`).catch(() => {});
|
||||
await apiClient.post(`/ai-proactive/suggestions/${id}/dismiss`).catch(() => {});
|
||||
}, []);
|
||||
|
||||
const act = useCallback(async (id: string, actionIndex: number) => {
|
||||
const result = await apiClient.post(`/api/v1/ai-proactive/suggestions/${id}/act`, {
|
||||
const result = await apiClient.post(`/ai-proactive/suggestions/${id}/act`, {
|
||||
action_index: actionIndex
|
||||
});
|
||||
setSuggestions(prev => prev.map(s => s.id === id ? { ...s, is_acted_upon: true } : s));
|
||||
@@ -59,11 +59,11 @@ export function useProactiveSettings() {
|
||||
const [settings, setSettings] = useState<any>(null);
|
||||
|
||||
useEffect(() => {
|
||||
apiClient.get('/api/v1/ai-proactive/settings').then(r => setSettings(r.data));
|
||||
apiClient.get('/ai-proactive/settings').then(r => setSettings(r.data));
|
||||
}, []);
|
||||
|
||||
const update = useCallback(async (updates: any) => {
|
||||
const r = await apiClient.put('/api/v1/ai-proactive/settings', updates);
|
||||
const r = await apiClient.put('/ai-proactive/settings', updates);
|
||||
setSettings(r.data);
|
||||
return r.data;
|
||||
}, []);
|
||||
|
||||
@@ -4,7 +4,6 @@ import { useNavigate } from 'react-router-dom';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useAuthStore } from '@/store/authStore';
|
||||
import { useUIStore } from '@/store/uiStore';
|
||||
import { useTenant } from '@/hooks/useTenant';
|
||||
import { useLogout } from '@/api/hooks';
|
||||
import { Avatar } from '@/components/ui/Avatar';
|
||||
import { Badge } from '@/components/ui/Badge';
|
||||
@@ -16,19 +15,15 @@ export function TopBar() {
|
||||
const navigate = useNavigate();
|
||||
const { user } = useAuthStore();
|
||||
const { toggleSidebar, openAISidebarProactive } = useUIStore();
|
||||
const { currentTenant, availableTenants, switchTenant, isSwitching } = useTenant();
|
||||
const logoutMutation = useLogout();
|
||||
|
||||
const [tenantMenuOpen, setTenantMenuOpen] = useState(false);
|
||||
const [userMenuOpen, setUserMenuOpen] = useState(false);
|
||||
const [notifOpen, setNotifOpen] = useState(false);
|
||||
const tenantRef = useRef<HTMLDivElement>(null);
|
||||
const userRef = useRef<HTMLDivElement>(null);
|
||||
const notifRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const handleClickOutside = (e: MouseEvent) => {
|
||||
if (tenantRef.current && !tenantRef.current.contains(e.target as Node)) setTenantMenuOpen(false);
|
||||
if (userRef.current && !userRef.current.contains(e.target as Node)) setUserMenuOpen(false);
|
||||
if (notifRef.current && !notifRef.current.contains(e.target as Node)) setNotifOpen(false);
|
||||
};
|
||||
@@ -45,11 +40,6 @@ export function TopBar() {
|
||||
navigate('/login');
|
||||
};
|
||||
|
||||
const handleTenantSwitch = async (tenantId: string) => {
|
||||
await switchTenant(tenantId);
|
||||
setTenantMenuOpen(false);
|
||||
};
|
||||
|
||||
const fullName = user ? `${user.first_name} ${user.last_name}` : '';
|
||||
|
||||
return (
|
||||
@@ -70,56 +60,6 @@ export function TopBar() {
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
{/* Tenant switcher */}
|
||||
<div ref={tenantRef} className="relative">
|
||||
<button
|
||||
onClick={() => setTenantMenuOpen(!tenantMenuOpen)}
|
||||
className="flex items-center gap-2 px-3 py-2 rounded-md hover:bg-secondary-100 min-h-touch focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500"
|
||||
aria-label={t('topbar.switchTenant')}
|
||||
aria-expanded={tenantMenuOpen}
|
||||
aria-haspopup="listbox"
|
||||
>
|
||||
<svg className="w-4 h-4 text-secondary-500" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4" />
|
||||
</svg>
|
||||
<span className="text-sm font-medium text-secondary-700 max-w-32 truncate">
|
||||
{currentTenant?.name || t('topbar.tenant')}
|
||||
</span>
|
||||
<svg className="w-4 h-4 text-secondary-400" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
|
||||
</svg>
|
||||
</button>
|
||||
{tenantMenuOpen && (
|
||||
<ul
|
||||
className="absolute top-full left-0 mt-1 w-56 bg-white rounded-md shadow-lg border border-secondary-200 py-1 z-50"
|
||||
role="listbox"
|
||||
aria-label={t('topbar.switchTenant')}
|
||||
>
|
||||
{availableTenants.map((tenant) => (
|
||||
<li key={tenant.id}>
|
||||
<button
|
||||
onClick={() => handleTenantSwitch(tenant.id)}
|
||||
className={clsx(
|
||||
'w-full text-left px-3 py-2 text-sm hover:bg-secondary-50 min-h-touch flex items-center justify-between focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500',
|
||||
tenant.id === currentTenant?.id && 'bg-primary-50 text-primary-700'
|
||||
)}
|
||||
role="option"
|
||||
aria-selected={tenant.id === currentTenant?.id}
|
||||
disabled={isSwitching}
|
||||
>
|
||||
{tenant.name}
|
||||
{tenant.id === currentTenant?.id && (
|
||||
<svg className="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
|
||||
</svg>
|
||||
)}
|
||||
</button>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Search */}
|
||||
<div className="hidden md:block">
|
||||
<SearchDropdown placeholder={t('topbar.search')} />
|
||||
|
||||
Reference in New Issue
Block a user