From 6412bb20d14eb0d3d5684be0f0d3e96ee35a2d1d Mon Sep 17 00:00:00 2001 From: Gabriel Menezes Date: Sat, 10 Oct 2026 23:18:50 -0400 Subject: [PATCH] style: elevate logged-in experience with ambient glows, glassmorphism, and landing page visual polish --- .../src/components/layout/AppShell.tsx | 10 +- .../src/components/layout/Sidebar.tsx | 2 +- .../src/components/tasks/TaskCard.tsx | 6 +- .../src/components/tasks/TaskKanbanView.tsx | 2 +- .../src/components/tasks/TaskListView.tsx | 2 +- new-frontend/src/pages/AnalyticsPage.tsx | 151 ++++----- new-frontend/src/pages/CategoriesPage.tsx | 35 +- new-frontend/src/pages/DashboardPage.tsx | 310 ++++++++++-------- new-frontend/src/pages/MembersPage.tsx | 65 ++-- .../src/pages/OrganizationSettingsPage.tsx | 29 +- new-frontend/src/pages/ProfilePage.tsx | 30 +- new-frontend/src/pages/ProjectsPage.tsx | 33 +- new-frontend/src/pages/TasksPage.tsx | 75 ++--- 13 files changed, 396 insertions(+), 354 deletions(-) diff --git a/new-frontend/src/components/layout/AppShell.tsx b/new-frontend/src/components/layout/AppShell.tsx index 482dc1a..435db8f 100644 --- a/new-frontend/src/components/layout/AppShell.tsx +++ b/new-frontend/src/components/layout/AppShell.tsx @@ -7,7 +7,11 @@ export const AppShell = () => { const [isMobileOpen, setIsMobileOpen] = useState(false) return ( -
+
+ {/* Decorative ambient background glows matching Landing Page aesthetic */} +
+
+ {/* Sidebar Navigation */} { /> {/* Main Content Area */} -
+
setIsMobileOpen(true)} /> -
+
diff --git a/new-frontend/src/components/layout/Sidebar.tsx b/new-frontend/src/components/layout/Sidebar.tsx index 005d791..a8aec72 100644 --- a/new-frontend/src/components/layout/Sidebar.tsx +++ b/new-frontend/src/components/layout/Sidebar.tsx @@ -51,7 +51,7 @@ export const Sidebar = ({ isMobileOpen, onCloseMobile }: SidebarProps) => { ] const navContent = ( -
+
{/* Brand & Logo */}
diff --git a/new-frontend/src/components/tasks/TaskCard.tsx b/new-frontend/src/components/tasks/TaskCard.tsx index 5d38c9a..8bea348 100644 --- a/new-frontend/src/components/tasks/TaskCard.tsx +++ b/new-frontend/src/components/tasks/TaskCard.tsx @@ -52,10 +52,10 @@ export const TaskCard: React.FC = ({
{/* Top Row: Project & Quick Status Menu */} diff --git a/new-frontend/src/components/tasks/TaskKanbanView.tsx b/new-frontend/src/components/tasks/TaskKanbanView.tsx index 8ef58f1..340e1e1 100644 --- a/new-frontend/src/components/tasks/TaskKanbanView.tsx +++ b/new-frontend/src/components/tasks/TaskKanbanView.tsx @@ -112,7 +112,7 @@ export const TaskKanbanView: React.FC = ({ onDragOver={(e) => handleDragOver(e, col.status)} onDragLeave={handleDragLeave} onDrop={(e) => handleDrop(e, col.status)} - className={`flex flex-col rounded-2xl border transition-all duration-200 min-h-[480px] bg-surface-sunken/40 ${ + className={`flex flex-col rounded-3xl border transition-all duration-200 min-h-[500px] bg-surface/60 backdrop-blur-md shadow-xs ${ isOver ? 'border-brand ring-2 ring-brand/30 bg-brand/5' : col.borderColor diff --git a/new-frontend/src/components/tasks/TaskListView.tsx b/new-frontend/src/components/tasks/TaskListView.tsx index 6a3453a..26b8185 100644 --- a/new-frontend/src/components/tasks/TaskListView.tsx +++ b/new-frontend/src/components/tasks/TaskListView.tsx @@ -42,7 +42,7 @@ export const TaskListView: React.FC = ({ const [activeMenuId, setActiveMenuId] = React.useState(null) return ( -
+
diff --git a/new-frontend/src/pages/AnalyticsPage.tsx b/new-frontend/src/pages/AnalyticsPage.tsx index ff888c6..32bc5d2 100644 --- a/new-frontend/src/pages/AnalyticsPage.tsx +++ b/new-frontend/src/pages/AnalyticsPage.tsx @@ -211,11 +211,12 @@ export const AnalyticsPage: React.FC = () => { {/* Header */}
-
-

+
+

Analytics & Produtividade

- + + {activeOrg?.name || 'Workspace'}
@@ -229,14 +230,14 @@ export const AnalyticsPage: React.FC = () => { onClick={loadData} disabled={refreshing} title="Recarregar métricas" - className="self-start sm:self-auto p-2 rounded-xl border border-border bg-surface text-muted hover:text-foreground hover:bg-surface-raised transition-colors disabled:opacity-50" + className="self-start sm:self-auto p-2.5 rounded-xl border border-border-soft bg-surface/90 backdrop-blur-md text-muted hover:text-foreground hover:bg-surface-raised transition-all shadow-panel disabled:opacity-50" >

{error && ( -
+
{error} @@ -256,7 +257,7 @@ export const AnalyticsPage: React.FC = () => { {[1, 2, 3, 4].map((i) => (
))}
@@ -264,86 +265,86 @@ export const AnalyticsPage: React.FC = () => { <> {/* Top 4 KPI Cards */}
- {/* Total Time */} -
-
- Tempo Total Dedicado -
- + {/* Total Time */} +
+
+ Tempo Total Dedicado +
+ +
+
+
+

+ {formatSecondsToTimer(kpis.totalSecondsTracked)} +

+

+ Equivalente a {formatSecondsToHuman(kpis.totalSecondsTracked)} +

+
-
-
-

- {formatSecondsToTimer(kpis.totalSecondsTracked)} -

-

- Equivalente a {formatSecondsToHuman(kpis.totalSecondsTracked)} -

-
-
- {/* Completion Rate */} -
-
- Taxa de Conclusão -
- + {/* Completion Rate */} +
+
+ Taxa de Conclusão +
+ +
+
+
+

+ {kpis.completionRate}% +

+

+ {kpis.completedTasks} de {kpis.totalTasks} demandas finalizadas +

+
-
-
-

- {kpis.completionRate}% -

-

- {kpis.completedTasks} de {kpis.totalTasks} demandas finalizadas -

-
-
- {/* In Progress vs Backlog */} -
-
- Em Execução Agora -
- + {/* In Progress vs Backlog */} +
+
+ Em Execução Agora +
+ +
+
+
+

+ {kpis.inProgressTasks} tarefas +

+

+ {kpis.notStartedTasks} no backlog aguardando início +

+
-
-
-

- {kpis.inProgressTasks} tarefas -

-

- {kpis.notStartedTasks} no backlog aguardando início -

-
-
- {/* Avg Time per Task */} -
-
- Média por Entrega -
- + {/* Avg Time per Task */} +
+
+ Média por Entrega +
+ +
+
+
+

+ {formatSecondsToHuman(kpis.avgSecondsPerCompletedTask)} +

+

+ Tempo médio gasto em cada entrega concluída +

+
-
-

- {formatSecondsToHuman(kpis.avgSecondsPerCompletedTask)} -

-

- Tempo médio gasto em cada entrega concluída -

-
-
-
{/* Main Grid: Projects & Categories Breakdown */}
{/* Project Time Distribution */} -
+
-
+

@@ -405,10 +406,10 @@ export const AnalyticsPage: React.FC = () => {

{/* Category Time Distribution */} -
+
-
+

@@ -471,7 +472,7 @@ export const AnalyticsPage: React.FC = () => {

{/* Team Productivity Table */} -
+
diff --git a/new-frontend/src/pages/CategoriesPage.tsx b/new-frontend/src/pages/CategoriesPage.tsx index 6f4bf32..9d6f884 100644 --- a/new-frontend/src/pages/CategoriesPage.tsx +++ b/new-frontend/src/pages/CategoriesPage.tsx @@ -157,11 +157,12 @@ export const CategoriesPage: React.FC = () => { {/* Header */}
-
-

+
+

Categorias & Tags

- + + {activeOrg?.name || 'Workspace'}
@@ -176,7 +177,7 @@ export const CategoriesPage: React.FC = () => { onClick={loadData} disabled={refreshing} title="Recarregar categorias" - className="p-2 rounded-xl border border-border bg-surface text-muted hover:text-foreground hover:bg-surface-raised transition-colors disabled:opacity-50" + className="p-2.5 rounded-xl border border-border-soft bg-surface/90 backdrop-blur-md text-muted hover:text-foreground hover:bg-surface-raised transition-all shadow-panel disabled:opacity-50" > @@ -184,7 +185,7 @@ export const CategoriesPage: React.FC = () => {

{error && ( -
+
{error} @@ -209,15 +210,15 @@ export const CategoriesPage: React.FC = () => { )} {/* Search Bar */} -
+
- + setSearchQuery(e.target.value)} placeholder="Buscar categoria por nome..." - className="w-full pl-9 pr-3 py-2 rounded-xl border border-border bg-surface-raised text-xs text-foreground placeholder-muted/60 focus:outline-none focus:ring-2 focus:ring-accent/40 focus:border-accent transition-all" + className="w-full pl-9 pr-3.5 py-2 rounded-xl border border-border-soft bg-surface-raised/80 text-xs text-foreground placeholder-muted focus:outline-none focus:ring-2 focus:ring-accent/40 focus:border-accent transition-all" />
@@ -227,11 +228,11 @@ export const CategoriesPage: React.FC = () => { {/* Grid of Categories */} {loading ? ( -
+
{[1, 2, 3].map((i) => (
@@ -239,12 +240,12 @@ export const CategoriesPage: React.FC = () => { ))}
) : filteredCategories.length === 0 ? ( -
+

- Nenhuma categoria cadastrada + Nenhum categoria cadastrada

{searchQuery @@ -254,7 +255,7 @@ export const CategoriesPage: React.FC = () => { - + + +

{error && ( -
-
+
+
{error}
@@ -199,183 +208,189 @@ export const DashboardPage: React.FC = () => {
)} - {/* KPI Cards */} + {/* 4 Premium KPI Cards with shadow-panel & backdrop-blur */} {loading ? ( -
+
{[1, 2, 3, 4].map((i) => (
))}
) : ( -
+
{/* In Progress */} -
+
- Tarefas em Andamento -
+ Tarefas em Andamento +
-

+

{stats.inProgress}

-

- {stats.notStarted} no backlog para iniciar +

+ {stats.notStarted} tarefas aguardando no backlog

{/* Completed */} -
+
- Entregas Concluídas -
+ Entregas Concluídas +
-

+

{stats.completed}

-

- de {tasks.length} tarefas cadastradas +

+ de {tasks.length} demandas cadastradas

{/* Time Tracked */} -
+
- Tempo Total Dedicado -
+ Tempo Total Dedicado +
-

+

{formatSecondsToTimer(stats.totalSeconds)}

-

- {formatSecondsToHuman(stats.totalSeconds)} acumuladas +

+ {formatSecondsToHuman(stats.totalSeconds)} auditadas no time

{/* Projects */} -
+
- Projetos Ativos -
- + Projetos Ativos +
+
-

+

{stats.projectsCount}

-

- Iniciativas no workspace +

+ Iniciativas ativas no workspace

)} - {/* Main Content: Focus Session (Left) + Recent Tasks (Right) */} -
- {/* Focus Session Card (Left 5 cols) */} -
-
-
-
-
- -
-
-

Sessão em Foco

-

Cronômetro em tempo real

-
+ {/* Main Grid: Focus Session (5 cols) + Recent Sprint Tasks (7 cols) */} +
+ {/* Focus Session Hero Card (Left 5 cols) */} +
+
+ {/* Header with macOS style dots */} +
+
+ + + + + + Sessão em Foco +
- - {activeTask ? 'ATIVO' : 'EM ESPERA'} - +
+ + + {activeTask ? 'CRONOMETRANDO' : 'EM ESPERA'} + +
- {/* Active or Suggested Task Info */} + {/* Active or Suggested Task Info Box */} {activeTask ? ( -
-
+
+
{activeTask.project && ( {activeTask.project.name} )} {activeTask.category && ( - + {activeTask.category.name} )}
-

+

{activeTask.title}

) : suggestedTask ? ( -
+
- - Próxima da fila + + Sugerida para Focar {suggestedTask.project && ( - + {suggestedTask.project.name} )}
-

+

{suggestedTask.title}

) : ( -
- Nenhuma tarefa pendente. Crie uma nova tarefa para iniciar o foco! +
+ Nenhuma tarefa ativa. Crie uma demanda para iniciar sua sessão produtiva!
)} - {/* Big Timer Display */} -
- - {activeTask ? 'Tempo Decorrido na Tarefa' : 'Pronto para Cronometrar'} + {/* Big Bold Timer Display */} +
+ + {activeTask ? 'Tempo Decorrido na Tarefa' : 'Pronto para Iniciar'} -

+

{activeTask ? formatSecondsToTimer(activeSeconds) : '00:00:00'}

- {/* Controls */} + {/* Timer Actions */} {activeTask ? ( ) : ( )} -
- Usuário ativo: - +
+ Usuário conectado + {user?.name || user?.email}
- {/* Quick Shortcuts */} -
+ {/* Quick Shortcuts Card */} +
- Atalhos de Gestão + Acesso Rápido ao Workspace
- Projetos + Ver Projetos - - Analytics + + Analytics da Org
- {/* Recent Tasks List (Right 7 cols) */} + {/* Recent Sprint Tasks (Right 7 cols) */}
-

- - Tarefas Recentes +

+ + Tarefas Recentes da Equipe

{ {[1, 2, 3].map((i) => (
))}
) : recentTasks.length === 0 ? ( -
+
-

+

Nenhuma tarefa encontrada neste workspace.

@@ -481,45 +496,62 @@ export const DashboardPage: React.FC = () => { return (
-
+
{task.project && ( - + {task.project.name} )} {task.category && ( - + {task.category.name} )} + + {task.status === 'COMPLETED' + ? 'Concluído' + : task.status === 'IN_PROGRESS' + ? 'Em Andamento' + : task.status === 'CANCELED' + ? 'Cancelado' + : 'A Fazer'} +

navigate('/tasks')} - className="text-xs font-bold text-foreground hover:text-brand cursor-pointer truncate" + className="text-sm font-bold text-foreground hover:text-brand cursor-pointer truncate transition-colors" > {task.title}

@@ -527,13 +559,13 @@ export const DashboardPage: React.FC = () => {
- + {formatSecondsToTimer(taskSec)}
@@ -541,10 +573,10 @@ export const DashboardPage: React.FC = () => { type="button" onClick={() => handleToggleTimer(task)} title={isTracking ? 'Pausar cronômetro' : 'Iniciar cronômetro'} - className={`p-1.5 rounded-lg transition-colors ${ + className={`p-2 rounded-xl transition-all shadow-xs ${ isTracking - ? 'bg-rose-500/20 text-rose-300 hover:bg-rose-500/30' - : 'bg-brand/15 text-teal-300 hover:bg-brand/25' + ? 'bg-rose-500/20 text-rose-300 hover:bg-rose-500/30 ring-1 ring-rose-500/40' + : 'bg-brand/15 text-teal-300 hover:bg-brand/25 ring-1 ring-brand/30' }`} > {isTracking ? ( diff --git a/new-frontend/src/pages/MembersPage.tsx b/new-frontend/src/pages/MembersPage.tsx index 7785b68..a4051d5 100644 --- a/new-frontend/src/pages/MembersPage.tsx +++ b/new-frontend/src/pages/MembersPage.tsx @@ -153,11 +153,12 @@ export const MembersPage: React.FC = () => { {/* Header */}
-
-

+
+

Membros & Equipe

- + + {activeOrg?.name || 'Workspace'}
@@ -171,7 +172,7 @@ export const MembersPage: React.FC = () => { onClick={loadData} disabled={refreshing} title="Recarregar dados" - className="self-start sm:self-auto p-2 rounded-xl border border-border bg-surface text-muted hover:text-foreground hover:bg-surface-raised transition-colors disabled:opacity-50" + className="self-start sm:self-auto p-2.5 rounded-xl border border-border-soft bg-surface/90 backdrop-blur-md text-muted hover:text-foreground hover:bg-surface-raised transition-all shadow-panel disabled:opacity-50" > @@ -180,7 +181,7 @@ export const MembersPage: React.FC = () => { {/* Feedback Alert */} {feedbackMsg && (
{ )} {/* Tabs Switcher */} -
+
@@ -228,14 +229,14 @@ export const MembersPage: React.FC = () => { onClick={() => setActiveTab('pending')} className={`flex items-center gap-2 px-4 py-2.5 rounded-xl text-xs font-semibold transition-all whitespace-nowrap ${ activeTab === 'pending' - ? 'bg-amber-600 text-white shadow-xs' - : 'text-muted hover:text-foreground hover:bg-surface-raised' + ? 'bg-amber-600 text-white shadow-md shadow-amber-600/20' + : 'text-muted hover:text-foreground hover:bg-surface-raised/80' }`} > Solicitações Pendentes {pendingRequests.length > 0 && ( - + {pendingRequests.length} )} @@ -247,8 +248,8 @@ export const MembersPage: React.FC = () => { onClick={() => setActiveTab('discover')} className={`flex items-center gap-2 px-4 py-2.5 rounded-xl text-xs font-semibold transition-all whitespace-nowrap ${ activeTab === 'discover' - ? 'bg-brand text-white shadow-xs' - : 'text-muted hover:text-foreground hover:bg-surface-raised' + ? 'bg-brand text-white shadow-md shadow-brand/20' + : 'text-muted hover:text-foreground hover:bg-surface-raised/80' }`} > @@ -260,15 +261,15 @@ export const MembersPage: React.FC = () => { {activeTab === 'members' && (
{/* Member Search Bar */} -
+
- + setMemberSearchTerm(e.target.value)} placeholder="Filtrar por nome ou e-mail..." - className="w-full pl-9 pr-3 py-2 rounded-xl border border-border bg-surface-raised text-xs text-foreground placeholder-muted/60 focus:outline-none focus:ring-2 focus:ring-brand/40 focus:border-brand" + className="w-full pl-9 pr-3.5 py-2 rounded-xl border border-border-soft bg-surface-raised/80 text-xs text-foreground placeholder-muted focus:outline-none focus:ring-2 focus:ring-brand/40 focus:border-brand transition-all" />
@@ -281,12 +282,12 @@ export const MembersPage: React.FC = () => { {[1, 2, 3].map((i) => (
))}
) : filteredMembers.length === 0 ? ( -
+

Nenhum membro encontrado com este termo.

@@ -297,7 +298,7 @@ export const MembersPage: React.FC = () => { return (
@@ -322,7 +323,7 @@ export const MembersPage: React.FC = () => {
- + Ativo @@ -349,7 +350,7 @@ export const MembersPage: React.FC = () => {
{pendingRequests.length === 0 ? ( -
+

Tudo limpo!

Não há solicitações pendentes de aprovação no momento.

@@ -359,7 +360,7 @@ export const MembersPage: React.FC = () => { {pendingRequests.map((req) => (
@@ -376,7 +377,7 @@ export const MembersPage: React.FC = () => { type="button" disabled={actionLoadingId === req.userId} onClick={() => handleReject(req.userId)} - className="p-2 rounded-xl border border-rose-500/30 text-rose-400 hover:bg-rose-500/15 transition-colors" + className="p-2.5 rounded-xl border border-rose-500/30 text-rose-400 hover:bg-rose-500/15 transition-colors" title="Rejeitar" > @@ -385,7 +386,7 @@ export const MembersPage: React.FC = () => { type="button" disabled={actionLoadingId === req.userId} onClick={() => handleApprove(req.userId)} - className="flex items-center gap-1.5 px-3 py-1.5 rounded-xl bg-brand text-white text-xs font-bold hover:bg-brand-hover shadow-xs transition-colors" + className="flex items-center gap-1.5 px-4 py-2 rounded-xl bg-brand text-white text-xs font-bold hover:bg-brand-hover shadow-md shadow-brand/20 transition-all" > {actionLoadingId === req.userId ? ( @@ -406,7 +407,7 @@ export const MembersPage: React.FC = () => { {activeTab === 'discover' && (
{/* Search other organizations */} -
+
@@ -423,19 +424,19 @@ export const MembersPage: React.FC = () => {
- + setSearchOrgTerm(e.target.value)} placeholder="Digite o nome da organização (ex: BeeTech, Squad Core...)" - className="w-full pl-9 pr-3 py-2.5 rounded-xl border border-border bg-surface-raised text-xs text-foreground placeholder-muted/60 focus:outline-none focus:ring-2 focus:ring-brand/40 focus:border-brand" + className="w-full pl-9 pr-3.5 py-2.5 rounded-xl border border-border-soft bg-surface-raised/80 text-xs text-foreground placeholder-muted focus:outline-none focus:ring-2 focus:ring-brand/40 focus:border-brand transition-all" />

{loading ? ( -
+
Carregando estatísticas pessoais...
) : (
-
+
Tempo Registrado @@ -118,7 +118,7 @@ export const ProfilePage: React.FC = () => {
-
+
Tarefas Concluídas @@ -130,7 +130,7 @@ export const ProfilePage: React.FC = () => {
-
+
Workspace Ativo @@ -168,18 +168,18 @@ export const ProfilePage: React.FC = () => {
setActiveOrg(org.id)} - className={`p-3.5 rounded-xl border cursor-pointer transition-all flex items-center justify-between gap-3 ${ + className={`p-4 rounded-2xl border cursor-pointer transition-all flex items-center justify-between gap-3 ${ isCurrent - ? 'border-brand bg-brand/5 ring-1 ring-brand/30' - : 'border-border bg-surface-raised hover:border-zinc-700' + ? 'border-brand bg-brand/10 ring-1 ring-brand/40 shadow-xs' + : 'border-border-soft bg-surface-raised/80 hover:border-brand/40 hover:-translate-y-0.5' }`} >
{org.name.slice(0, 2).toUpperCase()} @@ -191,7 +191,7 @@ export const ProfilePage: React.FC = () => {
{isCurrent && ( - + Ativo )} diff --git a/new-frontend/src/pages/ProjectsPage.tsx b/new-frontend/src/pages/ProjectsPage.tsx index ff935f0..03a656e 100644 --- a/new-frontend/src/pages/ProjectsPage.tsx +++ b/new-frontend/src/pages/ProjectsPage.tsx @@ -138,11 +138,12 @@ export const ProjectsPage: React.FC = () => { {/* Header */}
-
-

+
+

Projetos

- + + {activeOrg?.name || 'Workspace'}
@@ -157,7 +158,7 @@ export const ProjectsPage: React.FC = () => { onClick={loadData} disabled={refreshing} title="Recarregar projetos" - className="p-2 rounded-xl border border-border bg-surface text-muted hover:text-foreground hover:bg-surface-raised transition-colors disabled:opacity-50" + className="p-2.5 rounded-xl border border-border-soft bg-surface/90 backdrop-blur-md text-muted hover:text-foreground hover:bg-surface-raised transition-all shadow-panel disabled:opacity-50" > @@ -165,7 +166,7 @@ export const ProjectsPage: React.FC = () => {

{error && ( -
+
{error} @@ -190,15 +191,15 @@ export const ProjectsPage: React.FC = () => { )} {/* Search Bar */} -
+
- + setSearchQuery(e.target.value)} placeholder="Buscar projeto por nome..." - className="w-full pl-9 pr-3 py-2 rounded-xl border border-border bg-surface-raised text-xs text-foreground placeholder-muted/60 focus:outline-none focus:ring-2 focus:ring-brand/40 focus:border-brand transition-all" + className="w-full pl-9 pr-3.5 py-2 rounded-xl border border-border-soft bg-surface-raised/80 text-xs text-foreground placeholder-muted focus:outline-none focus:ring-2 focus:ring-brand/40 focus:border-brand transition-all" />
@@ -208,11 +209,11 @@ export const ProjectsPage: React.FC = () => { {/* Grid of Projects */} {loading ? ( -
+
{[1, 2, 3].map((i) => (
@@ -221,7 +222,7 @@ export const ProjectsPage: React.FC = () => { ))}
) : filteredProjects.length === 0 ? ( -
+
@@ -236,7 +237,7 @@ export const ProjectsPage: React.FC = () => { {/* Kanban / List Toggle */} -
+
@@ -354,10 +355,10 @@ export const TasksPage: React.FC = () => {