From 7f07950ada1b64672a7a28f0019c760130cc6d10 Mon Sep 17 00:00:00 2001 From: pedrofedericoo Date: Wed, 10 Sep 2025 14:26:48 -0300 Subject: [PATCH] =?UTF-8?q?feat:=20Cria=C3=A7=C3=A3o=20da=20p=C3=A1gina=20?= =?UTF-8?q?in=C3=ADcio=20e=20melhoria=20na=20navega=C3=A7=C3=A3o?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package-lock.json | 144 +++++++++++++++----------- package.json | 7 +- src/App.js | 102 ++++++------------ src/components/Sidebar.js | 4 +- src/data/sidebar-items.json | 6 ++ src/horizontal-menu-items.json | 4 +- src/pages/Agendamentos.jsx | 12 +++ src/pages/Inicio.css | 182 +++++++++++++++++++++++++++++++++ src/pages/Inicio.jsx | 137 +++++++++++++++++++++++++ 9 files changed, 463 insertions(+), 135 deletions(-) create mode 100644 src/pages/Agendamentos.jsx create mode 100644 src/pages/Inicio.css create mode 100644 src/pages/Inicio.jsx diff --git a/package-lock.json b/package-lock.json index 3a03d4c..24acd1e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,6 +19,7 @@ "bootstrap": "^5.3.8", "bootstrap-icons": "^1.13.1", "flatpickr": "^4.6.13", + "lucide-react": "^0.543.0", "perfect-scrollbar": "^1.5.6", "quill": "^2.0.3", "rater-js": "^1.0.1", @@ -27,6 +28,7 @@ "react-bootstrap": "^2.10.10", "react-dom": "^18.2.0", "react-flatpickr": "^4.0.11", + "react-icons": "^5.5.0", "react-input-mask": "^2.0.4", "react-quill": "^2.0.0", "react-scripts": "5.0.1", @@ -36,8 +38,11 @@ "web-vitals": "^2.1.4" }, "devDependencies": { + "autoprefixer": "^10.4.21", + "postcss": "^8.5.6", "sass": "^1.91.0", - "sass-loader": "^16.0.5" + "sass-loader": "^16.0.5", + "tailwindcss": "^4.1.13" } }, "node_modules/@adobe/css-tools": { @@ -16228,9 +16233,9 @@ } }, "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.0.tgz", - "integrity": "sha512-TKY5pyBkHyADOPYlRT9Lx6F544mPl0vS5Ew7BJ45hA08Q+t3GjbueLliBWN3sMICk6+y7HdyxSzC4bWS8baBdg==", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", "license": "MIT", "engines": { "node": ">=12" @@ -16240,9 +16245,9 @@ } }, "node_modules/@isaacs/cliui/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", "license": "MIT", "engines": { "node": ">=12" @@ -16269,9 +16274,9 @@ } }, "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", "license": "MIT", "dependencies": { "ansi-regex": "^6.0.1" @@ -26833,6 +26838,15 @@ "yallist": "^3.0.2" } }, + "node_modules/lucide-react": { + "version": "0.543.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.543.0.tgz", + "integrity": "sha512-fpVfuOQO0V3HBaOA1stIiP/A2fPCXHIleRZL16Mx3HmjTYwNSbimhnFBygs2CAfU1geexMX5ItUcWBGUaqw5CA==", + "license": "ISC", + "peerDependencies": { + "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/lz-string": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", @@ -30537,6 +30551,15 @@ "react": ">= 16 <= 19" } }, + "node_modules/react-icons": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.5.0.tgz", + "integrity": "sha512-MEFcXdkP3dLo8uumGI5xN3lDFNsRtrjbOEKDLD7yv76v4wpnEq2Lt2qeHaQOr34I/wPN3s3+N08WkQ+CW37Xiw==", + "license": "MIT", + "peerDependencies": { + "react": "*" + } + }, "node_modules/react-input-mask": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/react-input-mask/-/react-input-mask-2.0.4.tgz", @@ -30730,6 +30753,18 @@ } } }, + "node_modules/react-scripts/node_modules/lilconfig": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", + "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, "node_modules/react-scripts/node_modules/sass-loader": { "version": "12.6.0", "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-12.6.0.tgz", @@ -30768,6 +30803,43 @@ } } }, + "node_modules/react-scripts/node_modules/tailwindcss": { + "version": "3.4.17", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.17.tgz", + "integrity": "sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==", + "license": "MIT", + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "arg": "^5.0.2", + "chokidar": "^3.6.0", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.3.2", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "jiti": "^1.21.6", + "lilconfig": "^3.1.3", + "micromatch": "^4.0.8", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.1.1", + "postcss": "^8.4.47", + "postcss-import": "^15.1.0", + "postcss-js": "^4.0.1", + "postcss-load-config": "^4.0.2", + "postcss-nested": "^6.2.0", + "postcss-selector-parser": "^6.1.2", + "resolve": "^1.22.8", + "sucrase": "^3.35.0" + }, + "bin": { + "tailwind": "lib/cli.js", + "tailwindcss": "lib/cli.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/react-transition-group": { "version": "4.4.5", "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", @@ -32944,53 +33016,11 @@ "license": "MIT" }, "node_modules/tailwindcss": { - "version": "3.4.17", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.17.tgz", - "integrity": "sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==", - "license": "MIT", - "dependencies": { - "@alloc/quick-lru": "^5.2.0", - "arg": "^5.0.2", - "chokidar": "^3.6.0", - "didyoumean": "^1.2.2", - "dlv": "^1.1.3", - "fast-glob": "^3.3.2", - "glob-parent": "^6.0.2", - "is-glob": "^4.0.3", - "jiti": "^1.21.6", - "lilconfig": "^3.1.3", - "micromatch": "^4.0.8", - "normalize-path": "^3.0.0", - "object-hash": "^3.0.0", - "picocolors": "^1.1.1", - "postcss": "^8.4.47", - "postcss-import": "^15.1.0", - "postcss-js": "^4.0.1", - "postcss-load-config": "^4.0.2", - "postcss-nested": "^6.2.0", - "postcss-selector-parser": "^6.1.2", - "resolve": "^1.22.8", - "sucrase": "^3.35.0" - }, - "bin": { - "tailwind": "lib/cli.js", - "tailwindcss": "lib/cli.js" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/tailwindcss/node_modules/lilconfig": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", - "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", - "license": "MIT", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/antonk52" - } + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.13.tgz", + "integrity": "sha512-i+zidfmTqtwquj4hMEwdjshYYgMbOrPzb9a0M3ZgNa0JMoZeFC6bxZvO8yr8ozS6ix2SDz0+mvryPeBs2TFE+w==", + "dev": true, + "license": "MIT" }, "node_modules/tapable": { "version": "2.2.3", diff --git a/package.json b/package.json index 2ee1efb..0c2e858 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "bootstrap": "^5.3.8", "bootstrap-icons": "^1.13.1", "flatpickr": "^4.6.13", + "lucide-react": "^0.543.0", "perfect-scrollbar": "^1.5.6", "quill": "^2.0.3", "rater-js": "^1.0.1", @@ -22,6 +23,7 @@ "react-bootstrap": "^2.10.10", "react-dom": "^18.2.0", "react-flatpickr": "^4.0.11", + "react-icons": "^5.5.0", "react-input-mask": "^2.0.4", "react-quill": "^2.0.0", "react-scripts": "5.0.1", @@ -55,7 +57,10 @@ ] }, "devDependencies": { + "autoprefixer": "^10.4.21", + "postcss": "^8.5.6", "sass": "^1.91.0", - "sass-loader": "^16.0.5" + "sass-loader": "^16.0.5", + "tailwindcss": "^4.1.13" } } diff --git a/src/App.js b/src/App.js index 165f091..a82292a 100644 --- a/src/App.js +++ b/src/App.js @@ -1,94 +1,50 @@ -import React, { useState, useEffect } from 'react'; +import React, { useState } from 'react'; import Sidebar from './components/Sidebar'; import Header from './components/Header'; -import Table from "./pages/Table"; // <-- ADIÇÃO AQUI +import Table from "./pages/Table"; import DataTable from "./pages/DataTable"; import Files from "./pages/files"; import EmailApp from "./pages/EmailApp"; -//import ChatApp from "./pages/ChatApp"; import GalleryApp from "./pages/GalleryApp"; import FormLayout from './pages/FormLayout'; import EditPage from './pages/EditPage'; -import PatientForm from "./components/patients/PatientForm"; +import PatientForm from "./components/patients/PatientForm"; import Details from './pages/Details'; -//import DoctorEditPage from './components/doctors/DoctorEditPage'; import DoctorTable from './pages/DoctorTable'; import DoctorFormLayout from './pages/DoctorFormLayout'; +import Inicio from './pages/Inicio'; +import Agendamentos from './pages/Agendamentos'; function App() { const [isSidebarActive, setIsSidebarActive] = useState(true); - const [currentPage, setCurrentPage] = useState('table '); - - const [patientID, setPatientID] = useState(null) - - - + const [currentPage, setCurrentPage] = useState('Inicio'); + const [patientID, setPatientID] = useState(null); const toggleSidebar = () => { setIsSidebarActive(!isSidebarActive); }; -const renderPageContent = () => { - if (currentPage === 'form-layout') { - return ; - } - else if(currentPage === 'doctor-form-layout'){ - return - } - else if (currentPage === 'table') { - return ; - } - else if(currentPage === 'doctor-table'){ - return - } - else if (currentPage === 'data-table') { - return ; - } - else if (currentPage === 'files') { - return ; - } - else if (currentPage === 'email-app') { - return ; - } - //else if (currentPage === 'chat-app') { - // return ; - //} - else if (currentPage === 'gallery-app') { - return ; - } - else if(currentPage === 'edit-page-paciente'){ - return - } - // else if(currentPage === 'doctor-form-layout'){ - // return - //} - else if(currentPage === 'details-page-paciente'){ - return
; - } - - - // Dashboard por padrão - return ( - <> -
-

Profile Statistics

-
-
-
-
-
- -
-
-
-
-
- -
-
-
- - ); + const renderPageContent = () => { + switch (currentPage) { + case 'Inicio': + return ; + case 'Agendamentos': + return ; + case 'form-layout': + return ; + case 'doctor-form-layout': + return ; + case 'table': + return
; + case 'doctor-table': + return ; + case 'details-page-paciente': + return
; + case 'edit-page-paciente': + return ; + default: + return ; + } }; return ( @@ -102,4 +58,4 @@ const renderPageContent = () => { ); } -export default App; +export default App; \ No newline at end of file diff --git a/src/components/Sidebar.js b/src/components/Sidebar.js index 23bb80b..4177d27 100644 --- a/src/components/Sidebar.js +++ b/src/components/Sidebar.js @@ -48,12 +48,12 @@ function Sidebar(props) {
- {/* Logo volta pro Dashboard */} + {/* Logo volta pro Início */} { e.preventDefault(); - props.setCurrentPage('dashboard'); + props.setCurrentPage('Inicio'); }} > MediConnect diff --git a/src/data/sidebar-items.json b/src/data/sidebar-items.json index 9d39584..7927ac5 100644 --- a/src/data/sidebar-items.json +++ b/src/data/sidebar-items.json @@ -4,6 +4,12 @@ "isTitle": true }, + { + "name":"Início", + "url": "Inicio", + "icon": "house" + }, + { "name": "Cadastro de Pacientes", "url": "form-layout", diff --git a/src/horizontal-menu-items.json b/src/horizontal-menu-items.json index a18ae52..de3aad9 100644 --- a/src/horizontal-menu-items.json +++ b/src/horizontal-menu-items.json @@ -1,7 +1,7 @@ [ { - "name": "Dashboard", - "url": "dashboard", + "name": "Início", + "url": "Inicio", "icon": "grid-fill" }, { diff --git a/src/pages/Agendamentos.jsx b/src/pages/Agendamentos.jsx new file mode 100644 index 0000000..537d8da --- /dev/null +++ b/src/pages/Agendamentos.jsx @@ -0,0 +1,12 @@ +import React from 'react'; + +function Agendamentos() { + return ( +
+

Página de Agendamentos

+ +
+ ); +} + +export default Agendamentos; \ No newline at end of file diff --git a/src/pages/Inicio.css b/src/pages/Inicio.css new file mode 100644 index 0000000..c7eb6a3 --- /dev/null +++ b/src/pages/Inicio.css @@ -0,0 +1,182 @@ +/* Container Principal */ +.dashboard-container { + padding: 2rem; + background-color: #f7f9fc; + flex-grow: 1; /* Permite que o container ocupe o espaço restante */ +} + +/* Header */ +.dashboard-header h1 { + font-size: 1.8rem; + font-weight: 600; + color: #333; + margin-bottom: 0.25rem; +} + +.dashboard-header p { + font-size: 0.9rem; + color: #666; + margin-bottom: 2rem; +} + +/* Seção de Estatísticas (Cartões) */ +.stats-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); + gap: 1.5rem; + margin-bottom: 2.5rem; +} + +.stat-card { + background-color: #fff; + border-radius: 12px; + padding: 1.5rem; + display: flex; + justify-content: space-between; + align-items: center; + box-shadow: 0 4px 10px rgba(0, 0, 0, 0.05); +} + +.stat-info { + display: flex; + flex-direction: column; +} + +.stat-label { + font-size: 0.8rem; + font-weight: 500; + color: #888; + margin-bottom: 0.25rem; +} + +.stat-value { + font-size: 2rem; + font-weight: 700; + color: #444; +} + +.stat-icon-wrapper { + width: 50px; + height: 50px; + border-radius: 50%; + display: flex; + justify-content: center; + align-items: center; +} + +.stat-icon { + font-size: 1.25rem; + color: #fff; +} + +/* Cores dos ícones */ +.stat-icon-wrapper.blue { background-color: #5d5dff; } +.stat-icon-wrapper.green { background-color: #30d158; } +.stat-icon-wrapper.purple { background-color: #a272ff; } +.stat-icon-wrapper.orange { background-color: #f1952e; } + +/* Seção de Ações Rápidas */ +.quick-actions h2 { + font-size: 1.2rem; + font-weight: 600; + color: #333; + margin-bottom: 1.5rem; +} + +.actions-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); + gap: 1.5rem; + margin-bottom: 2.5rem; +} + +.action-button { + background-color: #fff; + border-radius: 12px; + padding: 1.5rem; + display: flex; + align-items: center; + cursor: pointer; + transition: all 0.2s ease-in-out; + box-shadow: 0 4px 10px rgba(0, 0, 0, 0.05); +} + +.action-button:hover { + transform: translateY(-5px); + box-shadow: 0 6px 15px rgba(0, 0, 0, 0.1); +} + +.action-icon { + font-size: 2.25rem; + margin-right: 1rem; + color: #a272ff; /* Cor padrão para os ícones das ações */ +} + +.action-info { + display: flex; + flex-direction: column; +} + +.action-title { + font-size: 1rem; + font-weight: 600; + color: #444; +} + +.action-desc { + font-size: 0.8rem; + color: #888; +} + +/* Seção de Próximos Agendamentos */ +.appointments-section { + background-color: #fff; + border-radius: 12px; + padding: 2rem; + box-shadow: 0 4px 10px rgba(0, 0, 0, 0.05); +} + +.appointments-section h2 { + font-size: 1.2rem; + font-weight: 600; + color: #333; + margin-bottom: 1.5rem; +} + +.no-appointments-content { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + text-align: center; + height: 100%; + padding: 2rem 0; +} + +.no-appointments-icon { + font-size: 3rem; + color: #bbb; + margin-bottom: 1rem; +} + +.no-appointments-content p { + font-size: 1rem; + color: #666; + margin-bottom: 1.5rem; +} + +.manage-button { + background-color: #5d5dff; + color: #fff; + border: none; + border-radius: 8px; + padding: 0.75rem 1.5rem; + font-size: 0.9rem; + font-weight: 500; + cursor: pointer; + transition: background-color 0.2s ease; +} + +.manage-button:hover { + background-color: #4444ff; +} \ No newline at end of file diff --git a/src/pages/Inicio.jsx b/src/pages/Inicio.jsx new file mode 100644 index 0000000..feaca74 --- /dev/null +++ b/src/pages/Inicio.jsx @@ -0,0 +1,137 @@ +import React, { useState, useEffect } from 'react'; +import { FaUser, FaUserPlus, FaCalendarAlt, FaCalendarCheck } from 'react-icons/fa'; +import './Inicio.css'; + +function Inicio({ setCurrentPage }) { + const [pacientes, setPacientes] = useState([]); + const [agendamentos, setAgendamentos] = useState([]); + + useEffect(() => { + const fetchPacientes = async () => { + try { + const res = await fetch("https://mock.apidog.com/m1/1053378-0-default/pacientes"); + const data = await res.json(); + setPacientes(data.data); + } catch (error) { + console.error("Erro ao buscar pacientes:", error); + } + }; + + const fetchAgendamentos = async () => { + try { + const res = await fetch("SUA_URL_DA_API_DE_AGENDAMENTOS"); + const data = await res.json(); + setAgendamentos(data.data); + } catch (error) { + console.error("Erro ao buscar agendamentos:", error); + } + }; + + fetchPacientes(); + fetchAgendamentos(); + }, []); + + const totalPacientes = pacientes.length; + const novosEsseMes = pacientes.filter(p => p.createdAt && new Date(p.createdAt).getMonth() === new Date().getMonth()).length; + + const hoje = new Date(); + const agendamentosDoDia = agendamentos.filter( + a => a.data && new Date(a.data).getDate() === hoje.getDate() + ); + const agendamentosHoje = agendamentosDoDia.length; + + return ( +
+
+ +

Bem-vindo ao MediConnect



+ +
+ +
+
+
+ TOTAL DE PACIENTES + {totalPacientes} +
+
+
+ +
+
+ NOVOS ESTE MÊS + {novosEsseMes} +
+
+
+ +
+
+ AGENDAMENTOS HOJE + {agendamentosHoje} +
+
+
+ +
+
+ PENDÊNCIAS + 0 +
+
+
+
+ +
+

Ações Rápidas

+
+
setCurrentPage('form-layout')}> + +
+ Novo Paciente + Cadastrar um novo paciente +
+
+
setCurrentPage('table')}> + +
+ Lista de Pacientes + Ver todos os pacientes +
+
+
setCurrentPage('Agendamentos')}> + +
+ Agendamentos + Gerenciar consultas +
+
+
+
+ +
+

Próximos Agendamentos

+ {agendamentosHoje > 0 ? ( +
+ {agendamentosDoDia.map(agendamento => ( +
+

{agendamento.nomePaciente}

+

{new Date(agendamento.data).toLocaleTimeString()}

+
+ ))} +
+ ) : ( +
+ +

Nenhum agendamento para hoje

+ +
+ )} +
+
+ ); +} + +export default Inicio; \ No newline at end of file