New alert service

This commit is contained in:
Urtzi Alfaro
2025-12-05 20:07:01 +01:00
parent 1fe3a73549
commit 667e6e0404
393 changed files with 26002 additions and 61033 deletions

View File

@@ -8,6 +8,7 @@ import { useHasAccess } from '../../../hooks/useAccessControl';
import { getNavigationRoutes, canAccessRoute, ROUTES } from '../../../router/routes.config';
import { useSubscriptionAwareRoutes } from '../../../hooks/useSubscriptionAwareRoutes';
import { useSubscriptionEvents } from '../../../contexts/SubscriptionEventsContext';
import { useSubscription } from '../../../api/hooks/subscription';
import { Button } from '../../ui';
import { Badge } from '../../ui';
import { Tooltip } from '../../ui';
@@ -136,6 +137,7 @@ const iconMap: Record<string, React.ComponentType<{ className?: string }>> = {
insights: Lightbulb,
events: Activity,
list: List,
distribution: Truck,
};
/**
@@ -162,7 +164,7 @@ export const Sidebar = forwardRef<SidebarRef, SidebarProps>(({
showCollapseButton = true,
showFooter = true,
}, ref) => {
const { t } = useTranslation();
const { t } = useTranslation(['common']);
const location = useLocation();
const navigate = useNavigate();
const user = useAuthUser();
@@ -170,7 +172,7 @@ export const Sidebar = forwardRef<SidebarRef, SidebarProps>(({
const hasAccess = useHasAccess(); // For UI visibility
const currentTenantAccess = useCurrentTenantAccess();
const { logout } = useAuthActions();
const [expandedItems, setExpandedItems] = useState<Set<string>>(new Set());
const [hoveredItem, setHoveredItem] = useState<string | null>(null);
const [isProfileMenuOpen, setIsProfileMenuOpen] = useState(false);
@@ -179,6 +181,7 @@ export const Sidebar = forwardRef<SidebarRef, SidebarProps>(({
const searchInputRef = React.useRef<HTMLInputElement>(null);
const sidebarRef = React.useRef<HTMLDivElement>(null);
const { subscriptionVersion } = useSubscriptionEvents();
const { subscriptionInfo } = useSubscription();
// Get subscription-aware navigation routes
const baseNavigationRoutes = useMemo(() => getNavigationRoutes(), []);
@@ -186,6 +189,11 @@ export const Sidebar = forwardRef<SidebarRef, SidebarProps>(({
// Map route paths to translation keys
const getTranslationKey = (routePath: string): string => {
// Special case for Enterprise tier: Rename "Mi Panadería" to "Central Baker"
if (routePath === '/app/database' && subscriptionInfo.plan === 'enterprise') {
return 'navigation.central_baker';
}
const pathMappings: Record<string, string> = {
'/app/dashboard': 'navigation.dashboard',
'/app/operations': 'navigation.operations',
@@ -193,6 +201,7 @@ export const Sidebar = forwardRef<SidebarRef, SidebarProps>(({
'/app/operations/production': 'navigation.production',
'/app/operations/maquinaria': 'navigation.equipment',
'/app/operations/pos': 'navigation.pos',
'/app/operations/distribution': 'navigation.distribution',
'/app/bakery': 'navigation.bakery',
'/app/bakery/recipes': 'navigation.recipes',
'/app/database': 'navigation.data',
@@ -436,11 +445,11 @@ export const Sidebar = forwardRef<SidebarRef, SidebarProps>(({
const findParentPaths = useCallback((items: NavigationItem[], targetPath: string, parents: string[] = []): string[] => {
for (const item of items) {
const currentPath = [...parents, item.id];
if (item.path === targetPath) {
return parents;
}
if (item.children) {
const found = findParentPaths(item.children, targetPath, currentPath);
if (found.length > 0) {
@@ -479,7 +488,7 @@ export const Sidebar = forwardRef<SidebarRef, SidebarProps>(({
let touchStartX = 0;
let touchStartY = 0;
const handleTouchStart = (e: TouchEvent) => {
if (isOpen) {
touchStartX = e.touches[0].clientX;
@@ -489,12 +498,12 @@ export const Sidebar = forwardRef<SidebarRef, SidebarProps>(({
const handleTouchMove = (e: TouchEvent) => {
if (!isOpen || !onClose) return;
const touchCurrentX = e.touches[0].clientX;
const touchCurrentY = e.touches[0].clientY;
const deltaX = touchStartX - touchCurrentX;
const deltaY = Math.abs(touchStartY - touchCurrentY);
// Only trigger swipe left to close if it's more horizontal than vertical
// and the swipe distance is significant
if (deltaX > 50 && deltaX > deltaY * 2) {
@@ -536,7 +545,7 @@ export const Sidebar = forwardRef<SidebarRef, SidebarProps>(({
e.preventDefault();
focusSearch();
}
// Escape to close menus
if (e.key === 'Escape') {
setIsProfileMenuOpen(false);
@@ -651,18 +660,18 @@ export const Sidebar = forwardRef<SidebarRef, SidebarProps>(({
)}
/>
)}
{/* Submenu indicator for collapsed sidebar */}
{isCollapsed && hasChildren && level === 0 && item.children && item.children.length > 0 && (
<div className="absolute -bottom-1 -right-1 w-2 h-2 bg-[var(--color-primary)] rounded-full opacity-75" />
)}
</div>
{!ItemIcon && level > 0 && (
<Dot className={clsx(
'flex-shrink-0 w-4 h-4 mr-3 transition-colors duration-200',
isActive
? 'text-[var(--color-primary)]'
isActive
? 'text-[var(--color-primary)]'
: 'text-[var(--text-tertiary)]'
)} />
)}
@@ -671,8 +680,8 @@ export const Sidebar = forwardRef<SidebarRef, SidebarProps>(({
<>
<span className={clsx(
'flex-1 truncate transition-colors duration-200 text-sm font-medium',
isActive
? 'text-[var(--color-primary)]'
isActive
? 'text-[var(--color-primary)]'
: 'text-[var(--text-primary)] group-hover:text-[var(--text-primary)]'
)}>
{item.label}
@@ -692,8 +701,8 @@ export const Sidebar = forwardRef<SidebarRef, SidebarProps>(({
<ChevronDown className={clsx(
'flex-shrink-0 w-4 h-4 ml-2 transition-transform duration-200',
isExpanded && 'transform rotate-180',
isActive
? 'text-[var(--color-primary)]'
isActive
? 'text-[var(--color-primary)]'
: 'text-[var(--text-tertiary)] group-hover:text-[var(--text-primary)]'
)} />
)}
@@ -733,7 +742,7 @@ export const Sidebar = forwardRef<SidebarRef, SidebarProps>(({
>
{itemContent}
</button>
{/* Submenu overlay for collapsed sidebar */}
{isCollapsed && hasChildren && level === 0 && isHovered && item.children && item.children.length > 0 && (
<div
@@ -788,7 +797,7 @@ export const Sidebar = forwardRef<SidebarRef, SidebarProps>(({
{/* Search */}
{!isCollapsed && (
<div className="px-4 pt-4" data-search>
<form
<form
onSubmit={handleSearchSubmit}
className="relative"
>
@@ -989,7 +998,7 @@ export const Sidebar = forwardRef<SidebarRef, SidebarProps>(({
{/* Mobile search - always visible in mobile view */}
<div className="p-4 border-b border-[var(--border-primary)]">
<form
<form
onSubmit={handleSearchSubmit}
className="relative"
>