99 lines
3.8 KiB
TypeScript
99 lines
3.8 KiB
TypeScript
import React from 'react';
|
|
import { Link, useLocation } from 'react-router-dom';
|
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
|
|
import { Button } from '@/components/ui/button';
|
|
import { RefreshCw } from 'lucide-react';
|
|
import { useDashboardPeriod } from '@/hooks/useDashboardPeriod';
|
|
import { DummyDataToggle } from '../DummyDataToggle';
|
|
import { __ } from '@/lib/i18n';
|
|
import { useQueryClient } from '@tanstack/react-query';
|
|
import type { SubItem } from '@/nav/tree';
|
|
|
|
type Props = { items?: SubItem[]; fullscreen?: boolean };
|
|
|
|
export default function DashboardSubmenuBar({ items = [], fullscreen = false }: Props) {
|
|
const { period, setPeriod, useDummy } = useDashboardPeriod();
|
|
const { pathname } = useLocation();
|
|
const queryClient = useQueryClient();
|
|
|
|
const handleRefresh = () => {
|
|
queryClient.invalidateQueries({ queryKey: ['analytics'] });
|
|
};
|
|
|
|
if (items.length === 0) return null;
|
|
|
|
// Calculate top position based on fullscreen state
|
|
// Fullscreen: top-16 (below 64px header)
|
|
// Normal: top-[88px] (below 40px WP admin bar + 48px menu bar)
|
|
const topClass = fullscreen ? 'top-0' : 'top-[calc(7rem+32px)]';
|
|
|
|
return (
|
|
<div data-submenubar className={`border-b border-border bg-background md:bg-background/95 md:backdrop-blur md:supports-[backdrop-filter]:bg-background/60 sticky ${topClass} z-20`}>
|
|
<div className="px-4 py-2">
|
|
<div className="flex items-center justify-between gap-4">
|
|
{/* Submenu Links */}
|
|
<div className="flex gap-2 overflow-x-auto no-scrollbar">
|
|
{items.map((it) => {
|
|
const key = `${it.label}-${it.path || it.href}`;
|
|
const isActive = !!it.path && (
|
|
it.exact ? pathname === it.path : pathname.startsWith(it.path)
|
|
);
|
|
const cls = [
|
|
'inline-flex items-center gap-2 rounded-md px-2.5 py-1.5 border text-sm whitespace-nowrap',
|
|
'focus:outline-none focus:ring-0 focus:shadow-none',
|
|
isActive ? 'bg-accent text-accent-foreground' : 'hover:bg-accent hover:text-accent-foreground',
|
|
].join(' ');
|
|
|
|
if (it.mode === 'spa' && it.path) {
|
|
return (
|
|
<Link key={key} to={it.path} className={cls} data-discover>
|
|
{it.label}
|
|
</Link>
|
|
);
|
|
}
|
|
|
|
if (it.mode === 'bridge' && it.href) {
|
|
return (
|
|
<a key={key} href={it.href} className={cls} data-discover>
|
|
{it.label}
|
|
</a>
|
|
);
|
|
}
|
|
|
|
return null;
|
|
})}
|
|
</div>
|
|
|
|
{/* Period Selector, Refresh & Dummy Toggle */}
|
|
<div className="flex items-center gap-2 flex-shrink-0">
|
|
<Select value={period} onValueChange={setPeriod}>
|
|
<SelectTrigger className="w-[140px] h-8">
|
|
<SelectValue />
|
|
</SelectTrigger>
|
|
<SelectContent>
|
|
<SelectItem value="7">{__('Last 7 days')}</SelectItem>
|
|
<SelectItem value="14">{__('Last 14 days')}</SelectItem>
|
|
<SelectItem value="30">{__('Last 30 days')}</SelectItem>
|
|
<SelectItem value="all">{__('All Time')}</SelectItem>
|
|
</SelectContent>
|
|
</Select>
|
|
{!useDummy && (
|
|
<Button
|
|
variant="outline"
|
|
size="sm"
|
|
onClick={handleRefresh}
|
|
className="h-8"
|
|
title={__('Refresh data (cached for 5 minutes)')}
|
|
>
|
|
<RefreshCw className="w-4 h-4 mr-1" />
|
|
{__('Refresh')}
|
|
</Button>
|
|
)}
|
|
<DummyDataToggle />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|