From 6d83697def4388ad34233da48a0b48226cd6862f Mon Sep 17 00:00:00 2001 From: "Carlos (Almeira)" Date: Sat, 28 Mar 2026 16:26:09 -0500 Subject: [PATCH] fix: explicit double click handler on cards, explicit create button on related fields, and correct RBAC labels parsing --- src/components/publications/PostCard.tsx | 26 ++++++++++++++++--- .../publications/PublicationsList.tsx | 3 ++- .../publications/RelationSelectField.tsx | 13 +++++++--- src/types/publications.ts | 1 + 4 files changed, 35 insertions(+), 8 deletions(-) diff --git a/src/components/publications/PostCard.tsx b/src/components/publications/PostCard.tsx index fa47b3f..ed7a004 100644 --- a/src/components/publications/PostCard.tsx +++ b/src/components/publications/PostCard.tsx @@ -10,7 +10,7 @@ * - The `onEdit` callback is injected by the parent — this component stays pure. */ -import React from 'react'; +import React, { useRef } from 'react'; import Link from 'next/link'; import { Edit2, Trash2, Eye, Calendar, Tag } from 'lucide-react'; import { Post, PostCardProps, UserRole } from '@/types/publications'; @@ -81,16 +81,36 @@ export const PostCard: React.FC = ({ ? post.tipo_publicacion_id.descripcion : post.tipo_publicacion_id; + const clickTimer = useRef(null); + const handleCardClick = (e: React.MouseEvent) => { if ((e.target as HTMLElement).closest('button, a, [role="button"]')) return; - // Single click: abre vista de detalle - window.open(`/${post.slug || post.$id}`, '_blank'); + + // Clear previous timer if any + if (clickTimer.current) { + clearTimeout(clickTimer.current); + clickTimer.current = null; + return; // It's a double click, let onDoubleClick handle it + } + + // Set a timer to wait and see if it's a single or double click + clickTimer.current = setTimeout(() => { + window.open(`/${post.slug || post.$id}`, '_blank'); + clickTimer.current = null; + }, 250); }; const handleCardDoubleClick = (e: React.MouseEvent) => { e.preventDefault(); e.stopPropagation(); + + if (clickTimer.current) { + clearTimeout(clickTimer.current); + clickTimer.current = null; + } + if ((e.target as HTMLElement).closest('button, a, [role="button"]')) return; + // Double click: abre edición si es admin/editor if (userRole === 'admin' || userRole === 'editor') { onEdit?.(post); diff --git a/src/components/publications/PublicationsList.tsx b/src/components/publications/PublicationsList.tsx index 45d0b62..e4ba1ad 100644 --- a/src/components/publications/PublicationsList.tsx +++ b/src/components/publications/PublicationsList.tsx @@ -74,7 +74,8 @@ export const PublicationsList: React.FC = ({ // Lazy-load Drawer to avoid shipping it unless needed const [DrawerComponent, setDrawerComponent] = useState | null>(null); - const userRole = (user?.prefs?.role as UserRole) ?? 'viewer'; + const canEdit = user?.$id === 'admin-emergency' || user?.labels?.includes('admin') || user?.labels?.includes('editor'); + const userRole = canEdit ? 'admin' : 'viewer'; // ── DERIVED STATE ──────────────────────────── diff --git a/src/components/publications/RelationSelectField.tsx b/src/components/publications/RelationSelectField.tsx index 04ca534..7765894 100644 --- a/src/components/publications/RelationSelectField.tsx +++ b/src/components/publications/RelationSelectField.tsx @@ -261,7 +261,7 @@ export const RelationSelectField: React.FC = ({ return (
- {/* Label with hint */} + {/* Label with Explicit Quick Create Action */}
- +
{/* Select Wrapper */} diff --git a/src/types/publications.ts b/src/types/publications.ts index 1ee4f76..24f84da 100644 --- a/src/types/publications.ts +++ b/src/types/publications.ts @@ -24,6 +24,7 @@ export interface AuthUser { $id: string; name: string; email: string; + labels?: string[]; prefs: { role?: UserRole; [key: string]: unknown;