feat: destaca dados mockados e WIP no app
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { useMemo, useState } from 'react'
|
||||
|
||||
import { BrandLogo } from './Brand.jsx'
|
||||
import { FeatureLegend } from './FeatureState.jsx'
|
||||
|
||||
const navItems = [
|
||||
{ href: '/inicio', label: 'Painel', icon: 'pulse', activePaths: ['/inicio', '/home', '/dashboard'] },
|
||||
@@ -176,6 +177,9 @@ export function AppShell({ children, currentPath, navigate, routeTitle }) {
|
||||
</header>
|
||||
|
||||
<main className="w-full px-4 py-6 md:px-8 md:py-8" id="app-content">
|
||||
<div className="mb-6">
|
||||
<FeatureLegend />
|
||||
</div>
|
||||
<div className="sr-only" aria-live="polite">
|
||||
{pageTitle}
|
||||
</div>
|
||||
|
||||
39
src/components/FeatureState.jsx
Normal file
39
src/components/FeatureState.jsx
Normal file
@@ -0,0 +1,39 @@
|
||||
import { featureStateStyles } from './featureStateStyles.js'
|
||||
|
||||
export function FeatureBadge({ className = '', status = 'partial', text }) {
|
||||
const current = featureStateStyles[status] || featureStateStyles.partial
|
||||
|
||||
return (
|
||||
<span
|
||||
className={`inline-flex items-center rounded-full border px-2.5 py-1 text-[10px] font-bold uppercase tracking-[0.14em] ${current.badge} ${className}`}
|
||||
>
|
||||
{text || current.label}
|
||||
</span>
|
||||
)
|
||||
}
|
||||
|
||||
export function FeatureCallout({ className = '', description, status = 'partial', title }) {
|
||||
const current = featureStateStyles[status] || featureStateStyles.partial
|
||||
|
||||
return (
|
||||
<div className={`rounded-2xl border px-4 py-3 ${current.panel} ${className}`}>
|
||||
<div className="flex flex-wrap items-center gap-3">
|
||||
<FeatureBadge status={status} />
|
||||
{title ? <p className={`text-sm font-semibold ${current.title}`}>{title}</p> : null}
|
||||
</div>
|
||||
{description ? <p className="mt-2 text-sm leading-6 text-[#d4d4d4]">{description}</p> : null}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export function FeatureLegend() {
|
||||
return (
|
||||
<div className="flex flex-wrap items-center gap-2 rounded-xl border border-[#404040] bg-[#202020] px-3 py-2">
|
||||
<span className="text-[11px] font-semibold uppercase tracking-[0.14em] text-[#a3a3a3]">Legenda</span>
|
||||
<FeatureBadge status="live" />
|
||||
<FeatureBadge status="partial" />
|
||||
<FeatureBadge status="mock" />
|
||||
<FeatureBadge status="wip" />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
31
src/components/featureStateStyles.js
Normal file
31
src/components/featureStateStyles.js
Normal file
@@ -0,0 +1,31 @@
|
||||
export const featureStateStyles = {
|
||||
live: {
|
||||
badge: 'border-emerald-500/40 bg-emerald-500/15 text-emerald-300',
|
||||
panel: 'border-emerald-500/35 bg-emerald-500/8',
|
||||
title: 'text-emerald-300',
|
||||
label: 'Integrado',
|
||||
},
|
||||
partial: {
|
||||
badge: 'border-sky-500/40 bg-sky-500/15 text-sky-300',
|
||||
panel: 'border-sky-500/35 bg-sky-500/8',
|
||||
title: 'text-sky-300',
|
||||
label: 'Parcial',
|
||||
},
|
||||
mock: {
|
||||
badge: 'border-amber-500/40 bg-amber-500/15 text-amber-300',
|
||||
panel: 'border-amber-500/35 bg-amber-500/8',
|
||||
title: 'text-amber-300',
|
||||
label: 'Mockado',
|
||||
},
|
||||
wip: {
|
||||
badge: 'border-rose-500/40 bg-rose-500/15 text-rose-300',
|
||||
panel: 'border-rose-500/35 bg-rose-500/8',
|
||||
title: 'text-rose-300',
|
||||
label: 'WIP',
|
||||
},
|
||||
}
|
||||
|
||||
export function featurePanelClass(status = 'partial') {
|
||||
const current = featureStateStyles[status] || featureStateStyles.partial
|
||||
return current.panel
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
import { useEffect, useMemo, useState } from 'react'
|
||||
|
||||
import { appointmentRepository } from '../repositories/appointmentRepository.js'
|
||||
import { FeatureBadge, FeatureCallout } from '../components/FeatureState.jsx'
|
||||
import { featurePanelClass } from '../components/featureStateStyles.js'
|
||||
import { patientRepository } from '../repositories/patientRepository.js'
|
||||
import { professionalRepository } from '../repositories/professionalRepository.js'
|
||||
|
||||
@@ -88,6 +90,12 @@ useEffect(() => {
|
||||
|
||||
return (
|
||||
<div className="mx-auto flex max-w-[1180px] flex-col gap-8 text-[#e5e5e5]">
|
||||
<FeatureCallout
|
||||
description="Listagem e criação de agendamentos usam API. Linha do tempo, resumo preditivo e calendário semanal ainda são visuais simulados."
|
||||
status="partial"
|
||||
title="Agenda com partes reais e partes mockadas"
|
||||
/>
|
||||
|
||||
<section className="flex flex-col gap-4 md:flex-row md:items-center md:justify-between">
|
||||
<div>
|
||||
<h1 className="text-[32px] font-bold leading-8 tracking-[-0.02em] text-[#e5e5e5]">
|
||||
@@ -116,7 +124,7 @@ useEffect(() => {
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="grid gap-4 lg:grid-cols-5">
|
||||
<section className={`grid gap-4 lg:grid-cols-5 ${featurePanelClass('mock')}`}>
|
||||
{weekDays.map((day) => (
|
||||
<button
|
||||
className={`rounded-2xl border p-4 text-left transition ${
|
||||
@@ -137,10 +145,13 @@ useEffect(() => {
|
||||
</section>
|
||||
|
||||
<section className="grid gap-6 xl:grid-cols-[1.45fr_0.85fr]">
|
||||
<div className="rounded-2xl border border-[#404040] bg-[#262626] p-5 shadow-[0_1px_3px_rgba(0,0,0,0.2)]">
|
||||
<div className={`rounded-2xl border bg-[#262626] p-5 shadow-[0_1px_3px_rgba(0,0,0,0.2)] ${featurePanelClass('live')}`}>
|
||||
<div className="flex flex-col gap-4 lg:flex-row lg:items-center lg:justify-between">
|
||||
<div>
|
||||
<h2 className="text-base font-bold leading-6 text-[#e5e5e5]">Terça, 07 abril</h2>
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
<h2 className="text-base font-bold leading-6 text-[#e5e5e5]">Terça, 07 abril</h2>
|
||||
<FeatureBadge status="live" />
|
||||
</div>
|
||||
<p className="mt-1 text-sm leading-5 text-[#a3a3a3]">
|
||||
Visualização: {activeView.toLowerCase()} | {visibleAppointments.length} registros no filtro
|
||||
</p>
|
||||
@@ -202,8 +213,11 @@ useEffect(() => {
|
||||
</div>
|
||||
|
||||
<div className="grid gap-6">
|
||||
<div className="rounded-2xl border border-[#404040] bg-[#262626] p-5">
|
||||
<h2 className="text-base font-bold text-[#e5e5e5]">Linha do tempo</h2>
|
||||
<div className={`rounded-2xl border bg-[#262626] p-5 ${featurePanelClass('mock')}`}>
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
<h2 className="text-base font-bold text-[#e5e5e5]">Linha do tempo</h2>
|
||||
<FeatureBadge status="mock" />
|
||||
</div>
|
||||
<div className="mt-5 grid gap-1">
|
||||
{timeline.map((item) => (
|
||||
<button
|
||||
@@ -223,8 +237,11 @@ useEffect(() => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="rounded-2xl border border-[#404040] bg-[#262626] p-5">
|
||||
<h2 className="text-base font-bold text-[#e5e5e5]">Resumo preditivo</h2>
|
||||
<div className={`rounded-2xl border bg-[#262626] p-5 ${featurePanelClass('mock')}`}>
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
<h2 className="text-base font-bold text-[#e5e5e5]">Resumo preditivo</h2>
|
||||
<FeatureBadge status="mock" />
|
||||
</div>
|
||||
<div className="mt-5 grid gap-3">
|
||||
{queue.map((item) => (
|
||||
<div className="flex items-center justify-between rounded-md bg-[#2a2a2a] px-4 py-3" key={item.label}>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { useState } from 'react'
|
||||
|
||||
import { FeatureCallout } from '../components/FeatureState.jsx'
|
||||
import { analyticsRepository } from '../repositories/analyticsRepository.js'
|
||||
|
||||
const periods = [
|
||||
@@ -25,6 +26,12 @@ export function AnalyticsPage() {
|
||||
|
||||
return (
|
||||
<div className="mx-auto max-w-7xl space-y-6">
|
||||
<FeatureCallout
|
||||
description="Os indicadores, gráficos e rankings desta tela ainda vêm de dados mockados."
|
||||
status="mock"
|
||||
title="Analytics ainda é demonstrativo"
|
||||
/>
|
||||
|
||||
<section className="flex flex-col items-start justify-between gap-4 md:flex-row md:items-center">
|
||||
<div>
|
||||
<h1 className="text-2xl font-bold tracking-tight text-[#f5f5f5]">Relatórios & Analytics</h1>
|
||||
|
||||
@@ -3,6 +3,7 @@ import { useState } from 'react'
|
||||
import { authRepository } from '../repositories/authRepository.js'
|
||||
|
||||
import { BrandLogo } from '../components/Brand.jsx'
|
||||
import { FeatureBadge, FeatureCallout } from '../components/FeatureState.jsx'
|
||||
import loginClinicImage from '../assets/figma/login-clinic.png'
|
||||
|
||||
export function LoginPage({ navigate }) {
|
||||
@@ -163,6 +164,7 @@ export function LoginPage({ navigate }) {
|
||||
type="button"
|
||||
>
|
||||
dev · credenciais
|
||||
<FeatureBadge className="border-white/20 bg-white/10 text-white/70" status="mock" text="mock" />
|
||||
<span aria-hidden="true" className="text-[9px]">
|
||||
^
|
||||
</span>
|
||||
@@ -181,6 +183,12 @@ export function RegisterPage({ navigate }) {
|
||||
description="Crie um acesso mockado para navegar pelo ambiente da clínica."
|
||||
title="Criar acesso"
|
||||
>
|
||||
<FeatureCallout
|
||||
className="mt-6"
|
||||
description="Cadastro ainda é apenas demonstrativo e não cria conta real."
|
||||
status="mock"
|
||||
title="Fluxo mockado"
|
||||
/>
|
||||
<form
|
||||
className="mt-8 grid gap-5"
|
||||
onSubmit={(event) => {
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import loginClinicImage from '../assets/figma/login-clinic.png'
|
||||
import { FeatureBadge, FeatureCallout } from '../components/FeatureState.jsx'
|
||||
import { featurePanelClass } from '../components/featureStateStyles.js'
|
||||
import { homeRepository } from '../repositories/homeRepository.js'
|
||||
|
||||
export function HomePage({ navigate }) {
|
||||
@@ -6,6 +8,12 @@ export function HomePage({ navigate }) {
|
||||
|
||||
return (
|
||||
<div className="mx-auto flex max-w-[1180px] flex-col gap-8 text-[#e5e5e5]">
|
||||
<FeatureCallout
|
||||
description="Painel, métricas, insights e relatórios desta tela ainda usam dados mockados."
|
||||
status="mock"
|
||||
title="Visão geral ainda não está ligada à API"
|
||||
/>
|
||||
|
||||
<section className="flex flex-col gap-4 md:flex-row md:items-center md:justify-between">
|
||||
<div>
|
||||
<h1 className="text-[32px] font-bold leading-8 tracking-[-0.02em] text-[#e5e5e5]">
|
||||
@@ -41,14 +49,17 @@ export function HomePage({ navigate }) {
|
||||
</section>
|
||||
|
||||
<section className="grid gap-6 xl:grid-cols-[1.7fr_0.9fr]">
|
||||
<div className="rounded-2xl border border-[#3b82f6] bg-[#262626] p-5 shadow-[0_1px_3px_rgba(0,0,0,0.2)]">
|
||||
<div className={`rounded-2xl border bg-[#262626] p-5 shadow-[0_1px_3px_rgba(0,0,0,0.2)] ${featurePanelClass('mock')}`}>
|
||||
<div className="flex items-start justify-between gap-4">
|
||||
<div className="flex items-start gap-4">
|
||||
<div className="grid size-12 shrink-0 place-items-center rounded-md bg-[#3b82f6] text-white">
|
||||
<SparkLineIcon className="size-6" />
|
||||
</div>
|
||||
<div>
|
||||
<h2 className="text-base font-bold leading-6 text-[#3b82f6]">Insights de IA</h2>
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
<h2 className="text-base font-bold leading-6 text-[#3b82f6]">Insights de IA</h2>
|
||||
<FeatureBadge status="mock" />
|
||||
</div>
|
||||
<p className="mt-1 text-sm font-medium leading-5 text-[#a3a3a3]">
|
||||
Evolução de absenteísmo e risco da semana
|
||||
</p>
|
||||
@@ -65,8 +76,11 @@ export function HomePage({ navigate }) {
|
||||
</div>
|
||||
|
||||
<div className="grid gap-4">
|
||||
<div className="rounded-2xl border border-[#404040] bg-[#262626] p-5">
|
||||
<h2 className="text-base font-bold text-[#e5e5e5]">Pacientes de hoje</h2>
|
||||
<div className={`rounded-2xl border bg-[#262626] p-5 ${featurePanelClass('mock')}`}>
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
<h2 className="text-base font-bold text-[#e5e5e5]">Pacientes de hoje</h2>
|
||||
<FeatureBadge status="mock" />
|
||||
</div>
|
||||
<div className="mt-4 grid gap-3">
|
||||
{appointmentsToday.map((item) => (
|
||||
<button
|
||||
@@ -85,8 +99,11 @@ export function HomePage({ navigate }) {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="rounded-2xl border border-[#404040] bg-[#262626] p-5">
|
||||
<h2 className="text-base font-bold text-[#e5e5e5]">Alerta preditivo</h2>
|
||||
<div className={`rounded-2xl border bg-[#262626] p-5 ${featurePanelClass('mock')}`}>
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
<h2 className="text-base font-bold text-[#e5e5e5]">Alerta preditivo</h2>
|
||||
<FeatureBadge status="mock" />
|
||||
</div>
|
||||
<p className="mt-3 text-sm leading-6 text-[#a3a3a3]">
|
||||
3 pacientes apresentam risco de falta. Recomenda-se confirmar presença antes das 16h.
|
||||
</p>
|
||||
@@ -102,7 +119,10 @@ export function HomePage({ navigate }) {
|
||||
</section>
|
||||
|
||||
<section className="grid gap-4" id="relatorios">
|
||||
<h2 className="text-base font-bold text-[#e5e5e5]">Relatórios e Análises</h2>
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
<h2 className="text-base font-bold text-[#e5e5e5]">Relatórios e Análises</h2>
|
||||
<FeatureBadge status="mock" />
|
||||
</div>
|
||||
<div className="grid gap-4 lg:grid-cols-2">
|
||||
<button
|
||||
className="relative min-h-[164px] overflow-hidden rounded-2xl border border-[#3b82f6] bg-[#262626] p-5 text-left shadow-[0_1px_3px_rgba(0,0,0,0.2)]"
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { useMemo, useState } from 'react'
|
||||
|
||||
import { FeatureCallout } from '../components/FeatureState.jsx'
|
||||
import { medicalRecordRepository } from '../repositories/medicalRecordRepository.js'
|
||||
|
||||
|
||||
@@ -34,6 +35,12 @@ export function MedicalRecordsPage() {
|
||||
|
||||
return (
|
||||
<div className="mx-auto max-w-7xl space-y-6 text-[#e5e5e5]">
|
||||
<FeatureCallout
|
||||
description="Prontuário, listagem e criação de registros ainda usam dados locais e não persistem na API."
|
||||
status="mock"
|
||||
title="Prontuário ainda é mockado"
|
||||
/>
|
||||
|
||||
<div className="flex flex-col items-start justify-between gap-4 md:flex-row md:items-center">
|
||||
<div>
|
||||
<h1 className="text-2xl font-bold tracking-tight text-[#e5e5e5]">Prontuário Médico</h1>
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { useMemo, useState } from 'react'
|
||||
|
||||
import { FeatureCallout } from '../components/FeatureState.jsx'
|
||||
import { featurePanelClass } from '../components/featureStateStyles.js'
|
||||
import { communicationRepository } from '../repositories/communicationRepository.js'
|
||||
|
||||
const channels = {
|
||||
@@ -155,6 +157,12 @@ export function MessagesPage() {
|
||||
|
||||
return (
|
||||
<div className="mx-auto max-w-7xl space-y-6">
|
||||
<FeatureCallout
|
||||
description="Envio de SMS usa API. Histórico, templates e campanhas ainda são dados locais de demonstração."
|
||||
status="partial"
|
||||
title="Mensageria híbrida"
|
||||
/>
|
||||
|
||||
<div className="flex flex-col items-start justify-between gap-4 md:flex-row md:items-center">
|
||||
<div>
|
||||
<h1 className="text-2xl font-bold tracking-tight text-[#f5f5f5]">Comunicação</h1>
|
||||
@@ -210,7 +218,7 @@ export function MessagesPage() {
|
||||
</div>
|
||||
|
||||
{activeTab === 'historico' ? (
|
||||
<section className={`${cardClass} p-5 md:p-6`} aria-label="Histórico de comunicação">
|
||||
<section className={`${cardClass} ${featurePanelClass('mock')} p-5 md:p-6`} aria-label="Histórico de comunicação">
|
||||
<div className="mb-6 flex flex-col gap-3 md:flex-row">
|
||||
<label className="relative flex-1">
|
||||
<span className="sr-only">Buscar comunicação</span>
|
||||
@@ -279,7 +287,7 @@ export function MessagesPage() {
|
||||
) : null}
|
||||
|
||||
{activeTab === 'templates' ? (
|
||||
<section className="space-y-4" aria-label="Templates de comunicação">
|
||||
<section className={`space-y-4 rounded-2xl p-4 ${featurePanelClass('mock')}`} aria-label="Templates de comunicação">
|
||||
<div className="flex justify-end">
|
||||
<button
|
||||
className="inline-flex h-10 items-center gap-2 rounded-sm bg-[#3b82f6] px-4 text-sm font-semibold text-white transition hover:bg-[#2563eb]"
|
||||
@@ -300,7 +308,7 @@ export function MessagesPage() {
|
||||
) : null}
|
||||
|
||||
{activeTab === 'campanha' ? (
|
||||
<section className={`${cardClass} p-6`} aria-label="Campanhas inteligentes">
|
||||
<section className={`${cardClass} ${featurePanelClass('mock')} p-6`} aria-label="Campanhas inteligentes">
|
||||
<div className="py-8 text-center">
|
||||
<div className="mx-auto mb-4 grid size-16 place-items-center rounded-full bg-[#303030]">
|
||||
<CommIcon className="size-8 text-[#51a2ff]" name="send" />
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { useRef, useState, useEffect } from 'react'
|
||||
|
||||
import { FeatureCallout } from '../components/FeatureState.jsx'
|
||||
import { featurePanelClass } from '../components/featureStateStyles.js'
|
||||
import { profileRepository } from '../repositories/profileRepository.js'
|
||||
import { authRepository } from '../repositories/authRepository.js'
|
||||
|
||||
@@ -59,13 +61,19 @@ export function ProfilePage({ navigate }) {
|
||||
|
||||
return (
|
||||
<div className="mx-auto max-w-6xl space-y-6">
|
||||
<FeatureCallout
|
||||
description="Carregar perfil, avatar e logout usam integração. O botão de salvar preferências desta tela ainda grava só localmente."
|
||||
status="partial"
|
||||
title="Perfil com persistência parcial"
|
||||
/>
|
||||
|
||||
<header>
|
||||
<h1 className="text-2xl font-bold tracking-tight text-[#f5f5f5]">Perfil</h1>
|
||||
<p className="mt-1 text-sm text-[#b8b8b8]">Dados locais do usuário logado e preferências básicas do shell.</p>
|
||||
</header>
|
||||
|
||||
<div className="grid gap-6 lg:grid-cols-[1fr_360px]">
|
||||
<section className={`${cardClass} p-6`}>
|
||||
<section className={`${cardClass} ${featurePanelClass('partial')} p-6`}>
|
||||
<div className="mb-6 flex items-center gap-4">
|
||||
{profile.avatarUrl ? (
|
||||
<img
|
||||
@@ -134,12 +142,12 @@ export function ProfilePage({ navigate }) {
|
||||
<button className="h-10 rounded-sm bg-[#3b82f6] px-4 text-sm font-semibold text-white" type="submit">
|
||||
Salvar alterações
|
||||
</button>
|
||||
{saved ? <span className="rounded bg-emerald-500/20 px-2.5 py-1 text-xs font-bold text-emerald-400">Preferências salvas localmente</span> : null}
|
||||
{saved ? <span className="rounded bg-amber-500/20 px-2.5 py-1 text-xs font-bold text-amber-300">Preferências salvas localmente</span> : null}
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
|
||||
<aside className={`${cardClass} p-6`}>
|
||||
<aside className={`${cardClass} ${featurePanelClass('live')} p-6`}>
|
||||
<h2 className="text-xl font-bold text-[#f5f5f5]">Resumo de acesso</h2>
|
||||
<dl className="mt-5 grid gap-4 text-sm">
|
||||
<Info label="Perfil" value={profile.role} />
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { useEffect, useMemo, useState } from 'react'
|
||||
|
||||
import { FeatureBadge, FeatureCallout } from '../components/FeatureState.jsx'
|
||||
import { featurePanelClass } from '../components/featureStateStyles.js'
|
||||
import { reportRepository } from '../repositories/reportRepository.js'
|
||||
import { patientRepository } from '../repositories/patientRepository.js'
|
||||
|
||||
@@ -186,18 +188,25 @@ export function ReportsPage() {
|
||||
|
||||
return (
|
||||
<div className="mx-auto max-w-7xl space-y-6 text-[#e5e5e5]">
|
||||
<FeatureCallout
|
||||
description="Listagem e salvar laudo usam API. Templates, protocolo de entrega e parte do fluxo editorial ainda são locais."
|
||||
status="partial"
|
||||
title="Laudos com integração parcial"
|
||||
/>
|
||||
|
||||
<div className="flex flex-col items-start justify-between gap-4 md:flex-row md:items-center">
|
||||
<div>
|
||||
<h1 className="text-2xl font-bold tracking-tight text-[#e5e5e5]">Gestão de Laudos</h1>
|
||||
</div>
|
||||
<div className="flex w-full flex-col gap-2 sm:w-auto sm:flex-row sm:items-center">
|
||||
<button
|
||||
className="inline-flex h-10 items-center justify-center gap-2 rounded-lg border border-[#404040] bg-[#262626] px-4 text-sm font-medium text-[#e5e5e5] transition hover:bg-[#2a2a2a]"
|
||||
className={`inline-flex h-10 items-center justify-center gap-2 rounded-lg border px-4 text-sm font-medium text-[#e5e5e5] transition hover:bg-[#2a2a2a] ${featurePanelClass('mock')}`}
|
||||
onClick={() => setTemplatesOpen(true)}
|
||||
type="button"
|
||||
>
|
||||
<ReportIcon className="size-4 text-[#3b82f6]" name="template" />
|
||||
Templates
|
||||
<FeatureBadge status="mock" />
|
||||
</button>
|
||||
<button
|
||||
className="inline-flex h-10 items-center justify-center gap-2 rounded-lg bg-[#3b82f6] px-4 text-sm font-medium text-white transition hover:bg-[#2563eb]"
|
||||
@@ -219,7 +228,7 @@ export function ReportsPage() {
|
||||
))}
|
||||
</section>
|
||||
|
||||
<section className={`${cardClass} p-6`}>
|
||||
<section className={`${cardClass} ${featurePanelClass('live')} p-6`}>
|
||||
<div className="mb-6 flex flex-col gap-4 md:flex-row">
|
||||
<div className="relative flex-1">
|
||||
<ReportIcon className="pointer-events-none absolute left-3 top-1/2 size-4 -translate-y-1/2 text-[#a3a3a3]" name="search" />
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { useState } from 'react'
|
||||
|
||||
import { FeatureCallout } from '../components/FeatureState.jsx'
|
||||
import { settingsRepository } from '../repositories/settingsRepository.js'
|
||||
|
||||
|
||||
@@ -14,6 +15,13 @@ export function SettingsPage() {
|
||||
|
||||
return (
|
||||
<div className="mx-auto max-w-5xl">
|
||||
<FeatureCallout
|
||||
className="mb-6"
|
||||
description="Preferências, integrações e backup ainda são protótipos locais, sem persistência real."
|
||||
status="mock"
|
||||
title="Configurações ainda estão em modo protótipo"
|
||||
/>
|
||||
|
||||
<header className="mb-8">
|
||||
<h1 className="text-2xl font-bold tracking-tight text-[#f5f5f5]">Configurações</h1>
|
||||
<p className="mt-1 text-sm text-[#b8b8b8]">Gerencie preferências, segurança e integrações do MediConnect</p>
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import { useState, useEffect } from 'react'
|
||||
import { FeatureBadge, FeatureCallout } from '../components/FeatureState.jsx'
|
||||
import { featurePanelClass } from '../components/featureStateStyles.js'
|
||||
import { professionalRepository } from '../repositories/professionalRepository.js'
|
||||
|
||||
const cardClass = 'rounded-2xl border border-[#404040] bg-[#262626] shadow-sm'
|
||||
@@ -13,6 +15,12 @@ export function TeamPage({ navigate }) {
|
||||
|
||||
return (
|
||||
<div className="mx-auto max-w-7xl space-y-6">
|
||||
<FeatureCallout
|
||||
description="A listagem de profissionais usa API, mas o mapa de cobertura e parte da disponibilidade ainda são simulados."
|
||||
status="partial"
|
||||
title="Tela híbrida: parte real, parte mockada"
|
||||
/>
|
||||
|
||||
<header className="flex flex-col items-start justify-between gap-4 md:flex-row md:items-center">
|
||||
<div>
|
||||
<h1 className="text-2xl font-bold tracking-tight text-[#f5f5f5]">Profissionais</h1>
|
||||
@@ -29,7 +37,7 @@ export function TeamPage({ navigate }) {
|
||||
|
||||
<section className="grid gap-4 md:grid-cols-2 xl:grid-cols-4" aria-label="Equipe médica">
|
||||
{professionals.map((professional) => (
|
||||
<article className={`${cardClass} p-5`} key={professional.id}>
|
||||
<article className={`${cardClass} ${featurePanelClass('live')} p-5`} key={professional.id}>
|
||||
<div className="flex items-start justify-between gap-3">
|
||||
<div>
|
||||
<div className="grid size-11 place-items-center rounded-full border border-[#3b82f6]/30 bg-[#3b82f6]/10 text-sm font-bold text-[#3b82f6]">
|
||||
@@ -50,10 +58,13 @@ export function TeamPage({ navigate }) {
|
||||
))}
|
||||
</section>
|
||||
|
||||
<section className={`${cardClass} p-5`}>
|
||||
<section className={`${cardClass} ${featurePanelClass('mock')} p-5`}>
|
||||
<div className="flex flex-wrap items-center justify-between gap-3">
|
||||
<div>
|
||||
<h2 className="text-xl font-bold text-[#f5f5f5]">Mapa de cobertura</h2>
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
<h2 className="text-xl font-bold text-[#f5f5f5]">Mapa de cobertura</h2>
|
||||
<FeatureBadge status="mock" />
|
||||
</div>
|
||||
<p className="mt-1 text-sm text-[#a3a3a3]">
|
||||
Matriz simples para preparar o fluxo de agenda, plantão e disponibilidade.
|
||||
</p>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { useMemo, useState } from 'react'
|
||||
|
||||
import { FeatureCallout } from '../components/FeatureState.jsx'
|
||||
import { visitRepository } from '../repositories/visitRepository.js'
|
||||
|
||||
const tabs = [
|
||||
@@ -35,6 +36,12 @@ export function VisitsPage({ navigate }) {
|
||||
|
||||
return (
|
||||
<div className="mx-auto max-w-7xl space-y-6">
|
||||
<FeatureCallout
|
||||
description="Fila, etapas e resumo desta tela ainda são inteiramente mockados."
|
||||
status="mock"
|
||||
title="Consultas ainda não usam backend"
|
||||
/>
|
||||
|
||||
<header className="flex flex-col items-start justify-between gap-4 md:flex-row md:items-center">
|
||||
<div>
|
||||
<h1 className="text-2xl font-bold tracking-tight text-[#f5f5f5]">Consultas</h1>
|
||||
|
||||
Reference in New Issue
Block a user