From c6c385ec70736b9b4a23757c13a7339748719b4e Mon Sep 17 00:00:00 2001 From: Erik Silva Date: Wed, 21 Jan 2026 01:01:05 -0300 Subject: [PATCH] feat: implement mobile-friendly card layout for tables, remove horizontal scroll --- .../configuracoes/ConfiguracoesClient.tsx | 50 +++++----- .../dashboard/documentos/DocumentsClient.tsx | 98 +++++++++++++++++++ src/app/dashboard/perfil/ProfileClient.tsx | 50 +++++----- src/app/dashboard/usuarios/UsuariosClient.tsx | 74 ++++++++++++-- src/components/StandardTable.tsx | 52 +++++++--- 5 files changed, 249 insertions(+), 75 deletions(-) diff --git a/src/app/dashboard/configuracoes/ConfiguracoesClient.tsx b/src/app/dashboard/configuracoes/ConfiguracoesClient.tsx index 8acc7a9..fa85a2b 100644 --- a/src/app/dashboard/configuracoes/ConfiguracoesClient.tsx +++ b/src/app/dashboard/configuracoes/ConfiguracoesClient.tsx @@ -91,41 +91,41 @@ export default function ConfiguracoesClient({ }; return ( -
+
-
+
{/* Header Section - Integrated */} -
-
+
+
-
- Corporate Branding +
+ Corporate Branding
-

Configurações

-

Personalize a identidade visual do seu portal de transparência.

+

Configurações

+

Personalize a identidade visual do seu portal.

-
+
{message.text && ( {message.text} )} -
+
{/* Identity Section */} -
+
-

Identidade

-

- Defina o nome oficial da organização e a marca que será exibida para o cidadão. +

Identidade

+

+ Defina o nome oficial da organização e a marca que será exibida.

-
+
{/* Colors Section */} -
+
-

Cores e Estilo

-

- Escolha a cor primária que define a identidade do portal administrativo e público. +

Cores e Estilo

+

+ Escolha a cor primária que define a identidade do portal.

-
+
@@ -232,19 +232,19 @@ export default function ConfiguracoesClient({
{/* Actions */} -
+
diff --git a/src/app/dashboard/documentos/DocumentsClient.tsx b/src/app/dashboard/documentos/DocumentsClient.tsx index 8abb52a..0750516 100644 --- a/src/app/dashboard/documentos/DocumentsClient.tsx +++ b/src/app/dashboard/documentos/DocumentsClient.tsx @@ -743,6 +743,104 @@ export default function DocumentsClient({ Ações } + mobileCards={ + <> + {paginatedItems.map((item: any) => ( +
handleRowClick(item)} + > +
+
e.stopPropagation()}> + toggleSelect(item.id)} + className="rounded border-slate-300 data-[state=checked]:bg-red-500 data-[state=checked]:border-red-500 mt-1" + /> +
+
+
+ {item.isFolder ? ( + item.imageUrl ? ( +
+ {item.name} +
+ ) : ( +
+ +
+ ) + ) : ( +
+ +
+ )} +
+

+ {item.isFolder ? item.name : item.title} +

+
+ {item.isFolder ? (!currentFolder ? "PROJETO" : "PASTA") : (item.fileType.split("/")[1]?.toUpperCase() || "DOC")} + {!item.isFolder && ( + <> + + {formatFileSize(item.fileSize)} + + )} + {item.isFolder && ( + <> + + {item._count?.documents || 0} itens + + )} +
+
+
+
+
+ +
e.stopPropagation()}> + +
+ + + +
+
+
+ ))} + + } > {paginatedItems.map((item: any) => ( +
-
+
{/* Header Section - Integrated */} -
-
+
+
-
- Account Settings +
+ Account Settings
-

Meu Perfil

-

Gerencie suas informações pessoais e credenciais de acesso.

+

Meu Perfil

+

Gerencie suas informações pessoais e credenciais de acesso.

-
+
{message.text && ( {message.text} )} -
+ {/* Basic Info Section */} -
+
-

Dados Básicos

-

- Essas informações são usadas para identificar você no sistema e em registros de atividade. +

Dados Básicos

+

+ Essas informações são usadas para identificá-lo no sistema.

-
+
@@ -159,15 +159,15 @@ export default function ProfileClient({
{/* Security Section */} -
+
-

Segurança

-

- Mantenha sua conta segura alterando sua senha regularmente. A senha atual é necessária para validar a troca. +

Segurança

+

+ Altere sua senha regularmente. A senha atual é necessária para validar a troca.

-
+
@@ -211,19 +211,19 @@ export default function ProfileClient({
{/* Submit Bar */} -
+
diff --git a/src/app/dashboard/usuarios/UsuariosClient.tsx b/src/app/dashboard/usuarios/UsuariosClient.tsx index 0872a29..8fb4dee 100644 --- a/src/app/dashboard/usuarios/UsuariosClient.tsx +++ b/src/app/dashboard/usuarios/UsuariosClient.tsx @@ -215,19 +215,19 @@ export default function UsuariosClient({ }; return ( -
+
-
+
{/* Header Section - Integrated */} -
-
+
+
Access Control
-

Usuários

-

Gerencie quem tem permissão para editar no portal.

+

Usuários

+

Gerencie quem tem permissão para editar no portal.

@@ -237,7 +237,7 @@ export default function UsuariosClient({ setShowNewUser(true); }} style={{ backgroundColor: primaryColor }} - className="h-10 px-6 rounded-lg font-bold text-xs shadow-none hover:opacity-90 active:scale-95 transition-all text-white" + className="w-full sm:w-auto h-10 sm:h-10 px-4 sm:px-6 rounded-lg font-bold text-xs shadow-none hover:opacity-90 active:scale-95 transition-all text-white" > Novo Usuário @@ -246,7 +246,7 @@ export default function UsuariosClient({
-
+
{message.text && ( {message.text} @@ -257,7 +257,7 @@ export default function UsuariosClient({ { setSearchTerm(val); setCurrentPage(1); }} - searchPlaceholder="Buscar usuários por nome ou e-mail..." + searchPlaceholder="Buscar usuários..." totalItems={filteredUsers.length} showingCount={paginatedUsers.length} itemName="usuários" @@ -273,6 +273,62 @@ export default function UsuariosClient({ Ações } + mobileCards={ + <> + {paginatedUsers.map((u) => ( +
+
+
+
+ {u.name?.charAt(0) || u.email.charAt(0).toUpperCase()} +
+
+

+ {u.name || "Sem nome"} + {u.id === user.id && ( + Você + )} +

+

{u.email}

+
+
+ {getRoleBadge(u.role)} +
+ +
+ Desde {formatDate(u.createdAt)} +
+ + {u.id !== user.id && ( + + )} +
+
+
+ ))} + + } > {paginatedUsers.map((u) => ( diff --git a/src/components/StandardTable.tsx b/src/components/StandardTable.tsx index cb1f8dd..5c7df87 100644 --- a/src/components/StandardTable.tsx +++ b/src/components/StandardTable.tsx @@ -25,6 +25,7 @@ interface StandardTableProps { // Table Content columns: React.ReactNode; // Os children: React.ReactNode; // Os + mobileCards?: React.ReactNode; // Mobile cards version isLoading?: boolean; } @@ -41,15 +42,16 @@ export function StandardTable({ onPageChange, columns, children, + mobileCards, isLoading = false, }: StandardTableProps) { return (
{/* Table Header with Search and Stats */} -
+
{!hideSearch && ( -
-
+
+
onSearchChange?.(e.target.value)} - className="h-10 pl-11 pr-4 bg-slate-50/50 border-transparent rounded-lg text-sm font-medium text-slate-800 placeholder:text-slate-400 focus:bg-white focus:border-slate-200 focus:ring-0 transition-all duration-300 w-full" + className="h-10 pl-10 sm:pl-11 pr-4 bg-slate-50/50 border-transparent rounded-lg text-sm font-medium text-slate-800 placeholder:text-slate-400 focus:bg-white focus:border-slate-200 focus:ring-0 transition-all duration-300 w-full" />
)} -
+

{showingCount} / @@ -75,8 +77,26 @@ export function StandardTable({

- {/* The Table Itself */} -
+ {/* Mobile Cards View */} + {mobileCards && ( +
+ {isLoading ? ( +
+ +

Processando...

+
+ ) : showingCount === 0 ? ( +
+ Nenhum {itemName} encontrado. +
+ ) : ( + mobileCards + )} +
+ )} + + {/* Desktop Table View */} +
@@ -108,28 +128,28 @@ export function StandardTable({ {/* Table Footer with Pagination */} {totalPages > 1 && ( -
- - Página {currentPage} de {totalPages} +
+ + Pág. {currentPage}/{totalPages}