fix: explicit double click handler on cards, explicit create button on related fields, and correct RBAC labels parsing

This commit is contained in:
Carlos (Almeira) 2026-03-28 16:26:09 -05:00
parent 682d6620b9
commit 6d83697def
4 changed files with 35 additions and 8 deletions

View File

@ -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<PostCardProps> = ({
? post.tipo_publicacion_id.descripcion
: post.tipo_publicacion_id;
const clickTimer = useRef<NodeJS.Timeout | null>(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);

View File

@ -74,7 +74,8 @@ export const PublicationsList: React.FC<PublicationsListProps> = ({
// Lazy-load Drawer to avoid shipping it unless needed
const [DrawerComponent, setDrawerComponent] = useState<React.ComponentType<import('./PublicationDrawer').PublicationDrawerProps> | 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 ────────────────────────────

View File

@ -261,7 +261,7 @@ export const RelationSelectField: React.FC<RelationSelectFieldProps> = ({
return (
<div className="flex flex-col gap-1.5 w-full">
{/* Label with hint */}
{/* Label with Explicit Quick Create Action */}
<div className="flex items-center justify-between">
<label
htmlFor={`field-${name}`}
@ -270,10 +270,15 @@ export const RelationSelectField: React.FC<RelationSelectFieldProps> = ({
{label}
{required && <span className="text-cyan-400 ml-1">*</span>}
</label>
<span className="flex items-center gap-1 text-[9px] text-slate-600 font-bold uppercase tracking-wider">
<button
type="button"
onClick={(e) => { e.preventDefault(); handleDoubleClick(); }}
className="flex items-center gap-1.5 text-[10px] bg-cyan-500/10 text-cyan-400 hover:bg-cyan-500/20 px-2 py-1 rounded-md font-bold uppercase tracking-wider transition-colors border border-cyan-500/20"
title="Añadir una nueva opción a la base de datos"
>
<MousePointerClick size={10} />
Doble-click para crear nuevo
</span>
Crear Nuevo
</button>
</div>
{/* Select Wrapper */}

View File

@ -24,6 +24,7 @@ export interface AuthUser {
$id: string;
name: string;
email: string;
labels?: string[];
prefs: {
role?: UserRole;
[key: string]: unknown;