From 03a5f4d646d849426b70ecffdff848421f01c98d Mon Sep 17 00:00:00 2001 From: pedrofedericoo Date: Thu, 9 Oct 2025 11:48:50 -0300 Subject: [PATCH] =?UTF-8?q?Salva=20altera=C3=A7=C3=B5es=20antes=20de=20tro?= =?UTF-8?q?car=20de=20branch?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/assets/scss/components/_responsive.scss | 271 ++++++++++++++ src/assets/scss/components/_sidebar.scss | 204 ++++++++++- .../scss/components/_tables-responsive.scss | 338 ++++++++++++++++++ src/assets/scss/layouts/main.scss | 80 ++++- src/assets/scss/main.scss | 2 + src/assets/scss/pages/auth.scss | 112 +++++- src/components/MobileMenuToggle.jsx | 86 +++++ src/components/Sidebar.jsx | 290 ++++++++------- src/pages/Login.jsx | 252 ++++++------- src/pages/style/LandingPage.css | 193 +++++++++- 10 files changed, 1553 insertions(+), 275 deletions(-) create mode 100644 src/assets/scss/components/_responsive.scss create mode 100644 src/assets/scss/components/_tables-responsive.scss create mode 100644 src/components/MobileMenuToggle.jsx diff --git a/src/assets/scss/components/_responsive.scss b/src/assets/scss/components/_responsive.scss new file mode 100644 index 0000000..f7514c7 --- /dev/null +++ b/src/assets/scss/components/_responsive.scss @@ -0,0 +1,271 @@ +/* Utilitários responsivos para melhorar a experiência em diferentes dispositivos */ + +/* Breakpoints personalizados */ +$mobile: 576px; +$tablet: 768px; +$desktop-small: 992px; +$desktop: 1200px; +$desktop-large: 1400px; + +/* Utilitários de texto responsivo */ +.text-responsive { + @media screen and (max-width: $tablet - 1) { + font-size: 0.9rem !important; + } + + @media screen and (max-width: $mobile - 1) { + font-size: 0.85rem !important; + } +} + +.heading-responsive { + @media screen and (max-width: $desktop - 1) { + font-size: 1.5rem !important; + } + + @media screen and (max-width: $tablet - 1) { + font-size: 1.3rem !important; + } + + @media screen and (max-width: $mobile - 1) { + font-size: 1.1rem !important; + } +} + +/* Cards responsivos */ +.card-responsive { + @media screen and (max-width: $tablet - 1) { + margin-bottom: 1rem; + } + + .card-body { + @media screen and (max-width: $tablet - 1) { + padding: 1rem; + } + + @media screen and (max-width: $mobile - 1) { + padding: 0.75rem; + } + } +} + +/* Botões responsivos */ +.btn-responsive { + @media screen and (max-width: $tablet - 1) { + padding: 0.5rem 1rem; + font-size: 0.9rem; + } + + @media screen and (max-width: $mobile - 1) { + padding: 0.6rem 1.2rem; + font-size: 0.85rem; + width: 100%; + max-width: 200px; + } +} + +/* Tabelas responsivas */ +.table-responsive-custom { + @media screen and (max-width: $desktop - 1) { + font-size: 0.9rem; + } + + @media screen and (max-width: $tablet - 1) { + font-size: 0.8rem; + + th, td { + padding: 0.5rem !important; + } + } + + @media screen and (max-width: $mobile - 1) { + font-size: 0.75rem; + + th, td { + padding: 0.3rem !important; + } + } +} + +/* Formulários responsivos */ +.form-responsive { + .form-control { + @media screen and (max-width: $tablet - 1) { + font-size: 0.9rem; + padding: 0.5rem 0.75rem; + } + + @media screen and (max-width: $mobile - 1) { + font-size: 0.85rem; + padding: 0.6rem 0.8rem; + } + } + + .form-label { + @media screen and (max-width: $tablet - 1) { + font-size: 0.9rem; + margin-bottom: 0.3rem; + } + + @media screen and (max-width: $mobile - 1) { + font-size: 0.85rem; + margin-bottom: 0.25rem; + } + } +} + +/* Navegação responsiva */ +.nav-responsive { + @media screen and (max-width: $tablet - 1) { + .nav-link { + padding: 0.5rem 0.75rem; + font-size: 0.9rem; + } + } + + @media screen and (max-width: $mobile - 1) { + .nav-link { + padding: 0.6rem 0.8rem; + font-size: 0.85rem; + } + } +} + +/* Modais responsivos */ +.modal-responsive { + @media screen and (max-width: $tablet - 1) { + .modal-dialog { + margin: 1rem; + max-width: calc(100% - 2rem); + } + + .modal-header { + padding: 1rem; + + .modal-title { + font-size: 1.1rem; + } + } + + .modal-body { + padding: 1rem; + font-size: 0.9rem; + } + + .modal-footer { + padding: 0.75rem 1rem; + } + } + + @media screen and (max-width: $mobile - 1) { + .modal-dialog { + margin: 0.5rem; + max-width: calc(100% - 1rem); + } + + .modal-header { + padding: 0.75rem; + + .modal-title { + font-size: 1rem; + } + } + + .modal-body { + padding: 0.75rem; + font-size: 0.85rem; + } + + .modal-footer { + padding: 0.5rem 0.75rem; + } + } +} + +/* Utilitários de espaçamento responsivo */ +.spacing-responsive { + @media screen and (max-width: $desktop - 1) { + margin: 1.5rem 0 !important; + } + + @media screen and (max-width: $tablet - 1) { + margin: 1rem 0 !important; + } + + @media screen and (max-width: $mobile - 1) { + margin: 0.75rem 0 !important; + } +} + +/* Container responsivo personalizado */ +.container-responsive { + @media screen and (min-width: $desktop-large) { + max-width: 1320px; + } + + @media screen and (min-width: $desktop) and (max-width: $desktop-large - 1) { + max-width: 1140px; + } + + @media screen and (min-width: $desktop-small) and (max-width: $desktop - 1) { + max-width: 960px; + } + + @media screen and (min-width: $tablet) and (max-width: $desktop-small - 1) { + max-width: 720px; + } + + @media screen and (max-width: $tablet - 1) { + padding: 0 1rem; + } + + @media screen and (max-width: $mobile - 1) { + padding: 0 0.5rem; + } +} + +/* Ocultar/mostrar elementos por breakpoint */ +.hide-mobile { + @media screen and (max-width: $tablet - 1) { + display: none !important; + } +} + +.hide-tablet { + @media screen and (min-width: $tablet) and (max-width: $desktop - 1) { + display: none !important; + } +} + +.hide-desktop { + @media screen and (min-width: $desktop) { + display: none !important; + } +} + +.show-mobile-only { + display: none !important; + + @media screen and (max-width: $tablet - 1) { + display: block !important; + } +} + +.show-tablet-only { + display: none !important; + + @media screen and (min-width: $tablet) and (max-width: $desktop - 1) { + display: block !important; + } +} + +/* Ajustes específicos para touch devices */ +@media (hover: none) and (pointer: coarse) { + .btn, .sidebar-link, .nav-link { + min-height: 44px; /* Tamanho mínimo recomendado para touch */ + } + + .form-control { + min-height: 44px; + } +} diff --git a/src/assets/scss/components/_sidebar.scss b/src/assets/scss/components/_sidebar.scss index e809752..cf66428 100644 --- a/src/assets/scss/components/_sidebar.scss +++ b/src/assets/scss/components/_sidebar.scss @@ -1,9 +1,10 @@ -@mixin sidebar-active { +@mixin sidebar-active($sidebar-width: 300px) { .sidebar-wrapper { left: 0; + width: $sidebar-width; } & ~ #main { - margin-left: 300px; + margin-left: $sidebar-width; } } @mixin sidebar-inactive { @@ -17,9 +18,37 @@ #sidebar { @include sidebar-inactive(); - - @media screen and (min-width: 1200px) { - @include sidebar-active(); + + // Desktop grande (1920px+) + @media screen and (min-width: 1400px) { + @include sidebar-active(300px); + } + + // Desktop padrão (1200px-1399px) + @media screen and (min-width: 1200px) and (max-width: 1399px) { + @include sidebar-active(280px); + } + + // Tablet grande (992px-1199px) + @media screen and (min-width: 992px) and (max-width: 1199px) { + @include sidebar-active(260px); + } + + // Tablet (768px-991px) - sidebar colapsada por padrão + @media screen and (min-width: 768px) and (max-width: 991px) { + @include sidebar-inactive(); + + &.active { + .sidebar-wrapper { + left: 0; + width: 280px; + z-index: 1050; + box-shadow: 0 0 20px rgba(0, 0, 0, 0.3); + } + & ~ #main { + margin-left: 0; + } + } } &.inactive { @@ -31,7 +60,7 @@ left: 0; } } - + } .sidebar-wrapper { width: 300px; @@ -42,21 +71,56 @@ overflow-y: auto; background-color: $sidebar-bg; bottom: 0; - transition: left .7s cubic-bezier(0.22, 1, 0.36, 1); + transition: left .7s cubic-bezier(0.22, 1, 0.36, 1), width .3s ease; + + // Responsividade da largura + @media screen and (min-width: 1200px) and (max-width: 1399px) { + width: 280px; + } + + @media screen and (min-width: 992px) and (max-width: 1199px) { + width: 260px; + } + + @media screen and (max-width: 991px) { + width: 280px; + z-index: 1050; + } + .sidebar-header { - padding: 2rem 2rem 1rem; - font-size: 2rem; + padding: 2rem 1.5rem 1rem; + font-size: 1.8rem; font-weight: bold; + // Responsividade do header + @media screen and (max-width: 1199px) { + padding: 1.5rem 1rem 0.5rem; + font-size: 1.6rem; + } + + @media screen and (max-width: 767px) { + padding: 1rem 1rem 0.5rem; + font-size: 1.4rem; + } + img { height: 1.2rem; + + @media screen and (max-width: 767px) { + height: 1rem; + } } } .sidebar-toggler.x { position: absolute; right: 1.75rem; top: .25rem; - display:none; + display: none; + + @media screen and (max-width: 991px) { + right: 1rem; + top: 0.5rem; + } } .menu { @@ -64,6 +128,18 @@ margin-top: 2rem; padding: 0 2rem; font-weight: 600; + + // Responsividade do menu + @media screen and (max-width: 1199px) { + padding: 0 1.5rem; + margin-top: 1.5rem; + } + + @media screen and (max-width: 767px) { + padding: 0 1rem; + margin-top: 1rem; + } + .sidebar-title { padding: 0 1rem; margin: 1.5rem 0 1rem; @@ -71,8 +147,20 @@ list-style: none; font-weight: 600; color: $sidebar-link-color; + + @media screen and (max-width: 1199px) { + margin: 1rem 0 0.5rem; + font-size: 0.9rem; + padding: 0 0.5rem; + } + + @media screen and (max-width: 767px) { + margin: 0.8rem 0 0.4rem; + font-size: 0.85rem; + padding: 0 0.3rem; + } } - + .sidebar-link { display: block; padding: .7rem 1rem; @@ -83,14 +171,39 @@ transition: all .5s; text-decoration: none; color: $sidebar-link-color; + + // Responsividade dos links + @media screen and (max-width: 1199px) { + padding: 0.6rem 0.8rem; + font-size: 0.9rem; + } + + @media screen and (max-width: 767px) { + padding: 0.8rem 0.6rem; + font-size: 0.85rem; + } + svg,i { color:#7c8db5; + flex-shrink: 0; + + @media screen and (max-width: 767px) { + font-size: 1.1em; + } } i:before { vertical-align: top; } span { margin-left: 1rem; + + @media screen and (max-width: 1199px) { + margin-left: 0.8rem; + } + + @media screen and (max-width: 767px) { + margin-left: 0.6rem; + } } &:hover { background-color: $sidebar-link-hover-bg; @@ -192,15 +305,80 @@ background-color: rgba(0, 0, 0, 0.5); z-index: 9; } +// Media queries para diferentes dispositivos @media screen and (max-width: 1199px) { .sidebar-wrapper { position: fixed; left: -300px; .sidebar-toggler.x { - display:block; + display: block; } } } + +// Tablet específico +@media screen and (min-width: 768px) and (max-width: 991px) { + .sidebar-wrapper { + left: -280px; + + .menu { + .sidebar-link { + padding: 0.7rem 0.8rem; + } + } + } + + #sidebar.active ~ #main { + margin-left: 0 !important; + } +} + +// Mobile específico +@media screen and (max-width: 767px) { + .sidebar-wrapper { + left: -280px; + width: 280px !important; + + .sidebar-header { + .logo h1 { + font-size: 1.3rem; + } + } + + .menu { + .sidebar-link { + padding: 0.9rem 0.7rem; + + span { + font-size: 0.9rem; + } + } + + .submenu { + .submenu-item a { + padding: 0.6rem 1.5rem; + font-size: 0.8rem; + } + } + } + } + + #sidebar.active ~ #main { + margin-left: 0 !important; + } + + // Backdrop para mobile + #sidebar.active::before { + content: ''; + position: fixed; + top: 0; + left: 0; + width: 100vw; + height: 100vh; + background-color: rgba(0, 0, 0, 0.5); + z-index: 1040; + } +} @keyframes slideDown { from { max-height: 0; @@ -264,4 +442,4 @@ html[data-bs-theme="dark"] { .sidebar-backdrop { background-color: rgba(0, 0, 0, 0.7) !important; } -} \ No newline at end of file +} diff --git a/src/assets/scss/components/_tables-responsive.scss b/src/assets/scss/components/_tables-responsive.scss new file mode 100644 index 0000000..e569e73 --- /dev/null +++ b/src/assets/scss/components/_tables-responsive.scss @@ -0,0 +1,338 @@ +/* Melhorias de responsividade para tabelas e componentes de dados */ + +/* Tabelas responsivas melhoradas */ +.table-responsive-enhanced { + @media screen and (max-width: 1199px) { + font-size: 0.9rem; + + th, td { + padding: 0.6rem 0.5rem !important; + } + } + + @media screen and (max-width: 991px) { + font-size: 0.85rem; + + th, td { + padding: 0.5rem 0.4rem !important; + } + + /* Ocultar colunas menos importantes em tablet */ + .hide-tablet { + display: none !important; + } + } + + @media screen and (max-width: 767px) { + font-size: 0.8rem; + + th, td { + padding: 0.4rem 0.3rem !important; + } + + /* Ocultar mais colunas em mobile */ + .hide-mobile { + display: none !important; + } + + /* Estilo de card para mobile */ + &.table-card-mobile { + thead { + display: none; + } + + tbody tr { + display: block; + border: 1px solid #dee2e6; + border-radius: 0.375rem; + margin-bottom: 1rem; + padding: 0.75rem; + background: white; + box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075); + } + + tbody td { + display: block; + border: none; + padding: 0.25rem 0 !important; + text-align: left !important; + + &:before { + content: attr(data-label) ": "; + font-weight: bold; + color: #495057; + } + + &:last-child { + border-bottom: none; + } + } + } + } + + @media screen and (max-width: 576px) { + font-size: 0.75rem; + + th, td { + padding: 0.3rem 0.2rem !important; + } + } +} + +/* Cards responsivos para dados */ +.data-card-responsive { + @media screen and (max-width: 991px) { + margin-bottom: 1rem; + + .card-header { + padding: 0.75rem 1rem; + + h5, h6 { + font-size: 1rem; + margin-bottom: 0; + } + } + + .card-body { + padding: 1rem; + } + } + + @media screen and (max-width: 767px) { + .card-header { + padding: 0.5rem 0.75rem; + + h5, h6 { + font-size: 0.9rem; + } + } + + .card-body { + padding: 0.75rem; + font-size: 0.9rem; + } + } + + @media screen and (max-width: 576px) { + .card-header { + padding: 0.5rem; + + h5, h6 { + font-size: 0.85rem; + } + } + + .card-body { + padding: 0.5rem; + font-size: 0.85rem; + } + } +} + +/* Paginação responsiva */ +.pagination-responsive { + @media screen and (max-width: 767px) { + .page-item { + &:not(.active):not(.disabled) { + &:nth-child(n+4):nth-last-child(n+4) { + display: none; + } + } + } + + .page-link { + padding: 0.5rem 0.75rem; + font-size: 0.875rem; + } + } + + @media screen and (max-width: 576px) { + justify-content: center; + + .page-item { + &:not(.active):not(.disabled) { + &:nth-child(n+3):nth-last-child(n+3) { + display: none; + } + } + } + + .page-link { + padding: 0.4rem 0.6rem; + font-size: 0.8rem; + } + } +} + +/* Filtros e controles responsivos */ +.filters-responsive { + @media screen and (max-width: 991px) { + .row { + margin-bottom: 1rem; + } + + .col-md-3, .col-md-4, .col-md-6 { + margin-bottom: 0.5rem; + } + } + + @media screen and (max-width: 767px) { + .form-control, .form-select { + font-size: 0.9rem; + padding: 0.5rem 0.75rem; + } + + .btn { + font-size: 0.9rem; + padding: 0.5rem 1rem; + width: 100%; + margin-bottom: 0.5rem; + } + } + + @media screen and (max-width: 576px) { + .form-control, .form-select { + font-size: 0.85rem; + padding: 0.6rem 0.8rem; + } + + .btn { + font-size: 0.85rem; + padding: 0.6rem 1rem; + } + } +} + +/* Stats cards responsivos */ +.stats-card-responsive { + @media screen and (max-width: 1199px) { + .card-body { + padding: 1.25rem 1rem; + } + + h3, h4 { + font-size: 1.5rem; + } + + .stats-icon { + width: 3rem; + height: 3rem; + } + } + + @media screen and (max-width: 991px) { + margin-bottom: 1rem; + + .card-body { + padding: 1rem 0.75rem; + } + + h3, h4 { + font-size: 1.3rem; + } + + .stats-icon { + width: 2.5rem; + height: 2.5rem; + } + } + + @media screen and (max-width: 767px) { + .card-body { + padding: 0.75rem; + text-align: center; + } + + h3, h4 { + font-size: 1.2rem; + } + + .stats-icon { + width: 2rem; + height: 2rem; + margin: 0 auto 0.5rem; + } + + p, small { + font-size: 0.85rem; + } + } + + @media screen and (max-width: 576px) { + .card-body { + padding: 0.5rem; + } + + h3, h4 { + font-size: 1.1rem; + } + + .stats-icon { + width: 1.8rem; + height: 1.8rem; + } + + p, small { + font-size: 0.8rem; + } + } +} + +/* Breadcrumb responsivo */ +.breadcrumb-responsive { + @media screen and (max-width: 767px) { + font-size: 0.85rem; + padding: 0.5rem 0; + + .breadcrumb-item { + &:not(:last-child) { + &:nth-child(n+2):nth-last-child(n+2) { + display: none; + } + + &:nth-last-child(2):before { + content: "... / "; + } + } + } + } + + @media screen and (max-width: 576px) { + font-size: 0.8rem; + + .breadcrumb-item { + &:not(:last-child):not(:first-child) { + display: none; + } + + &:first-child:not(:last-child):after { + content: " / ..."; + } + } + } +} + +/* Alertas responsivos */ +.alert-responsive { + @media screen and (max-width: 767px) { + padding: 0.75rem; + font-size: 0.9rem; + + .alert-heading { + font-size: 1.1rem; + } + } + + @media screen and (max-width: 576px) { + padding: 0.5rem; + font-size: 0.85rem; + + .alert-heading { + font-size: 1rem; + } + + .btn-close { + padding: 0.25rem; + } + } +} diff --git a/src/assets/scss/layouts/main.scss b/src/assets/scss/layouts/main.scss index 33aff3b..236ef39 100644 --- a/src/assets/scss/layouts/main.scss +++ b/src/assets/scss/layouts/main.scss @@ -2,12 +2,41 @@ margin-left: 300px; padding: 2rem; min-height: 100vh; - @media screen and (max-width: 1199px) { - margin-left: 0; + transition: margin-left .7s cubic-bezier(0.22, 1, 0.36, 1); + + // Responsividade do layout principal + @media screen and (min-width: 1400px) { + margin-left: 300px; + padding: 2rem; } + + @media screen and (min-width: 1200px) and (max-width: 1399px) { + margin-left: 280px; + padding: 1.5rem; + } + + @media screen and (min-width: 992px) and (max-width: 1199px) { + margin-left: 260px; + padding: 1.5rem; + } + + @media screen and (min-width: 768px) and (max-width: 991px) { + margin-left: 0; + padding: 1rem; + } + + @media screen and (max-width: 767px) { + margin-left: 0; + padding: 1rem 0.5rem; + } + &.layout-navbar { padding: 0; - transition: margin-left .7s cubic-bezier(0.22, 1, 0.36, 1) + transition: margin-left .7s cubic-bezier(0.22, 1, 0.36, 1); + + @media screen and (max-width: 767px) { + padding: 0; + } } &.layout-horizontal { padding: 0; @@ -15,6 +44,14 @@ } #main-content { padding: 2rem; + + @media screen and (max-width: 1199px) { + padding: 1.5rem; + } + + @media screen and (max-width: 767px) { + padding: 1rem; + } } } #main, #main-content { @@ -25,9 +62,26 @@ flex-grow: 1; } .page-heading { - margin: 0 0 2rem; + margin: 0 0 2rem; + + @media screen and (max-width: 1199px) { + margin: 0 0 1.5rem; + } + + @media screen and (max-width: 767px) { + margin: 0 0 1rem; + } + h3 { font-weight: bold; + + @media screen and (max-width: 1199px) { + font-size: 1.5rem; + } + + @media screen and (max-width: 767px) { + font-size: 1.3rem; + } } } .page-title-headings { @@ -35,14 +89,30 @@ align-items: center; justify-content: space-between; margin-bottom: .5rem; + + @media screen and (max-width: 767px) { + flex-direction: column; + align-items: flex-start; + gap: 0.5rem; + } + h3 { margin-bottom: 0; margin-right: 1rem; + + @media screen and (max-width: 767px) { + margin-right: 0; + font-size: 1.2rem; + } } .breadcrumb { margin-bottom: 0; + + @media screen and (max-width: 767px) { + font-size: 0.85rem; + } } } a { text-decoration: none; -} \ No newline at end of file +} diff --git a/src/assets/scss/main.scss b/src/assets/scss/main.scss index e41b0ed..8b4474f 100644 --- a/src/assets/scss/main.scss +++ b/src/assets/scss/main.scss @@ -38,6 +38,8 @@ @import 'components/progress'; @import 'components/sidebar'; @import 'components/table'; +@import 'components/responsive'; +@import 'components/tables-responsive'; // Layout (se tiver arquivos, mas você mencionou que só tem main.scss aqui) @import 'layouts/main'; diff --git a/src/assets/scss/pages/auth.scss b/src/assets/scss/pages/auth.scss index 7e20eb2..4348916 100644 --- a/src/assets/scss/pages/auth.scss +++ b/src/assets/scss/pages/auth.scss @@ -13,7 +13,7 @@ body { } #auth-left { padding: 5rem; - + .auth-title { font-size: 4rem; margin-bottom: 1rem; @@ -30,13 +30,60 @@ body { } } @media screen and (max-width: 1399.9px) { - padding: 3rem ; + padding: 3rem; + + .auth-title { + font-size: 3rem; + } + .auth-subtitle { + font-size: 1.4rem; + line-height: 2rem; + } + .auth-logo { + margin-bottom: 5rem; + } + } + @media screen and (max-width: 991px) { + padding: 2.5rem; + + .auth-title { + font-size: 2.5rem; + } + .auth-subtitle { + font-size: 1.2rem; + line-height: 1.8rem; + } + .auth-logo { + margin-bottom: 3rem; + } } @media screen and (max-width: 767px) { - padding: 5rem ; + padding: 2rem; + + .auth-title { + font-size: 2rem; + } + .auth-subtitle { + font-size: 1rem; + line-height: 1.5rem; + } + .auth-logo { + margin-bottom: 2rem; + } } @media screen and (max-width: 576px) { - padding: 5rem 3rem; + padding: 1.5rem 1rem; + + .auth-title { + font-size: 1.8rem; + } + .auth-subtitle { + font-size: 0.9rem; + line-height: 1.4rem; + } + .auth-logo { + margin-bottom: 1.5rem; + } } } } @@ -61,3 +108,60 @@ html[data-bs-theme="dark"] { } } } + +/* Melhorias específicas para responsividade do login */ +.card-position { + display: flex; + justify-content: center; + align-items: center; + min-height: 100vh; + padding: 1rem; + + @media screen and (max-width: 768px) { + padding: 0.5rem; + align-items: flex-start; + padding-top: 2rem; + } + + @media screen and (max-width: 576px) { + padding: 0.25rem; + padding-top: 1rem; + } + + .card { + width: 100%; + max-width: 500px; + + @media screen and (max-width: 576px) { + margin: 0; + border-radius: 0.5rem; + } + } +} + +/* Melhorias para formulários de autenticação */ +.form-control-xl { + @media screen and (max-width: 768px) { + padding: 0.75rem 1rem; + font-size: 1rem; + } + + @media screen and (max-width: 576px) { + padding: 0.8rem 1rem; + font-size: 0.9rem; + } +} + +.btn-block { + @media screen and (max-width: 576px) { + padding: 0.8rem 1rem; + font-size: 1rem; + } +} + +/* Ajustes para ícones em campos de formulário */ +.form-control-icon { + @media screen and (max-width: 576px) { + left: 0.8rem; + } +} diff --git a/src/components/MobileMenuToggle.jsx b/src/components/MobileMenuToggle.jsx new file mode 100644 index 0000000..c9a90a0 --- /dev/null +++ b/src/components/MobileMenuToggle.jsx @@ -0,0 +1,86 @@ +import React from 'react'; + +const MobileMenuToggle = ({ isOpen, onToggle, className = '' }) => { + return ( + + ); +}; + +export default MobileMenuToggle; diff --git a/src/components/Sidebar.jsx b/src/components/Sidebar.jsx index e1cc85a..35abe99 100644 --- a/src/components/Sidebar.jsx +++ b/src/components/Sidebar.jsx @@ -1,138 +1,184 @@ -import React, { useState } from "react"; +import React, { useState, useEffect } from "react"; import { Link } from "react-router-dom"; import menuItems from "../data/sidebar-items-medico.json"; // Use "sidebar-items-secretaria.json" para secretaria e "sidebar-items-adm.json" para ADM -import TrocardePerfis from "./TrocardePerfis"; - +import TrocardePerfis from "./TrocardePerfis"; +import MobileMenuToggle from "./MobileMenuToggle"; // 1. Recebe 'menuItems' e 'onLogout' como props -function Sidebar({ menuItems, onLogout }) { - const [isActive, setIsActive] = useState(true); - const [openSubmenu, setOpenSubmenu] = useState(null); +function Sidebar({ menuItems, onLogout }) { + const [isActive, setIsActive] = useState(true); + const [openSubmenu, setOpenSubmenu] = useState(null); + const [isMobile, setIsMobile] = useState(false); - const toggleSidebar = () => { - setIsActive(!isActive); - }; + // Detectar se é mobile/tablet + useEffect(() => { + const checkScreenSize = () => { + setIsMobile(window.innerWidth < 992); + // Em mobile/tablet, sidebar começa fechada + if (window.innerWidth < 992) { + setIsActive(false); + } else { + setIsActive(true); + } + }; - const handleSubmenuClick = (submenuName) => { - setOpenSubmenu(openSubmenu === submenuName ? null : submenuName); - }; + checkScreenSize(); + window.addEventListener("resize", checkScreenSize); - const renderLink = (item) => { - // Links internos (rotas do React Router) - if (item.url && item.url.startsWith("/")) { - return ( - - {item.icon && } - {item.name} - - ); - } + return () => window.removeEventListener("resize", checkScreenSize); + }, []); + + const toggleSidebar = () => { + setIsActive(!isActive); + }; + + const handleSubmenuClick = (submenuName) => { + setOpenSubmenu(openSubmenu === submenuName ? null : submenuName); + }; + + const renderLink = (item) => { + // Links internos (rotas do React Router) + if (item.url && item.url.startsWith("/")) { + return ( + + {item.icon && } + {item.name} + + ); + } + + // Links externos + return ( + + {item.icon && } + {item.name} + + ); + }; - // Links externos return ( - - {item.icon && } - {item.name} - - ); - }; + <> + {/* Botão toggle para mobile */} + {isMobile && ( + + )} - return ( - - - ); + if (item.submenu) { + return ( +
  • + {/* ... Lógica de Submenu ... */} + +
      + {item.submenu.map((subItem, subIndex) => ( +
    • + {renderLink(subItem)} +
    • + ))} +
    +
  • + ); + } + + return ( +
  • + {renderLink(item)} +
  • + ); + })} + {/* 3. Adiciona o botão de logout no final do menu */} +
  • + +
  • + + + + + + + + + + ); } -export default Sidebar; \ No newline at end of file +export default Sidebar; diff --git a/src/pages/Login.jsx b/src/pages/Login.jsx index a71df6f..9275a93 100644 --- a/src/pages/Login.jsx +++ b/src/pages/Login.jsx @@ -1,19 +1,19 @@ -import React, { useState, useEffect, use } from 'react'; -import {Link, useNavigate } from "react-router-dom"; -import { useAuth } from '../components/utils/AuthProvider'; -import API_KEY from '../components/utils/apiKeys'; -import { UserInfos } from '../components/utils/Functions-Endpoints/General'; +import React, { useState, useEffect, use } from "react"; +import { Link, useNavigate } from "react-router-dom"; +import { useAuth } from "../components/utils/AuthProvider"; +import API_KEY from "../components/utils/apiKeys"; +import { UserInfos } from "../components/utils/Functions-Endpoints/General"; function Login({ onEnterSystem }) { - const {setAuthTokens } = useAuth(); - const navigate = useNavigate(); - const [form, setForm] = useState({ - username: "", - password: "" - }); - const [alert, setAlert] = useState(""); - const [showPassword, setShowPassword] = useState(false); -/* + const { setAuthTokens } = useAuth(); + const navigate = useNavigate(); + const [form, setForm] = useState({ + username: "", + password: "", + }); + const [alert, setAlert] = useState(""); + const [showPassword, setShowPassword] = useState(false); + /* useEffect(async () => { var myHeaders = new Headers(); @@ -64,7 +64,7 @@ function Login({ onEnterSystem }) { .then(result => console.log(result)) .catch(error => console.log('error', error));*/ - /* var myHeaders = new Headers(); + /* var myHeaders = new Headers(); myHeaders.append("Authorization", `Bearer ${data.access_token}`); myHeaders.append("apikey", API_KEY); var requestOptions = { @@ -80,83 +80,82 @@ function Login({ onEnterSystem }) { } }, []);*/ - const handleChange = (e) => { - setForm({ ...form, [e.target.name]: e.target.value }); - }; + const handleChange = (e) => { + setForm({ ...form, [e.target.name]: e.target.value }); + }; - const handleLogin = async (e) => { - e.preventDefault(); - console.log("Tentando logar com:", form); - if (form.username && form.password) { - var myHeaders = new Headers(); - myHeaders.append("apikey", API_KEY); - myHeaders.append("Content-Type", "application/json"); - - var raw = JSON.stringify({ - "email": form.username, - "password": form.password - }); - - var requestOptions = { - method: 'POST', - headers: myHeaders, - body: raw, - - redirect: 'follow' - }; + const handleLogin = async (e) => { + e.preventDefault(); + console.log("Tentando logar com:", form); + if (form.username && form.password) { + var myHeaders = new Headers(); + myHeaders.append("apikey", API_KEY); + myHeaders.append("Content-Type", "application/json"); - const response = await fetch("https://yuanqfswhberkoevtmfr.supabase.co/auth/v1/token?grant_type=password", requestOptions); - const data = await response.json(); - setAuthTokens(data); - console.log(data); + var raw = JSON.stringify({ + email: form.username, + password: form.password, + }); - - if (data.access_token){ - + var requestOptions = { + method: "POST", + headers: myHeaders, + body: raw, - const UserData = await UserInfos(`bearer ${data.access_token}`); - console.log(UserData, 'Dados do usuário'); + redirect: "follow", + }; - if(UserData?.roles?.includes('admin')){ - navigate(`/admin/`); - } else if(UserData?.roles?.includes('secretaria')){ - navigate(`/secretaria/`); - } else if(UserData?.roles?.includes('medico')){ - navigate(`/medico/`); - } else if(UserData?.roles?.includes('financeiro')){ - navigate(`/financeiro/`); - } + const response = await fetch( + "https://yuanqfswhberkoevtmfr.supabase.co/auth/v1/token?grant_type=password", + requestOptions + ); + const data = await response.json(); + setAuthTokens(data); + console.log(data); + + if (data.access_token) { + const UserData = await UserInfos(`bearer ${data.access_token}`); + console.log(UserData, "Dados do usuário"); + + if (UserData?.roles?.includes("admin")) { + navigate(`/admin/`); + } else if (UserData?.roles?.includes("secretaria")) { + navigate(`/secretaria/`); + } else if (UserData?.roles?.includes("medico")) { + navigate(`/medico/`); + } else if (UserData?.roles?.includes("financeiro")) { + navigate(`/financeiro/`); } + } + } else { + setAlert("Preencha todos os campos!"); + } + }; - } else { - setAlert("Preencha todos os campos!"); - } - }; - - return ( + return ( <> -
    -
    -
    -
    -
    -
    - -

    MediConnect

    - -
    -

    Entrar

    -

    +

    +
    +
    +
    +
    +
    + +

    MediConnect

    + +
    +

    Entrar

    +

    Entre com os dados que você inseriu durante o registro. -

    - {alert && ( -
    - {alert} -
    - )} -
    +

    + {alert && ( +
    + {alert} +
    + )} +
    - -
    + /> +
    -
    +
    - -
    + /> +
    -
    - +
    +
    - -
    - - -
    + +

    - Não tem uma conta? - + Não tem uma conta? + Cadastre-se - - . + + .

    - + Esqueceu a senha? - - . + + .

    -
    +
    -
    +
    +
    -
    -
    +
    - ); + ); } -export default Login; \ No newline at end of file +export default Login; diff --git a/src/pages/style/LandingPage.css b/src/pages/style/LandingPage.css index fc56b0c..989db84 100644 --- a/src/pages/style/LandingPage.css +++ b/src/pages/style/LandingPage.css @@ -21,15 +21,72 @@ z-index: 1000; } +/* Responsividade do cabeçalho */ +@media screen and (max-width: 1199px) { + .landing-header { + padding: 12px 30px; + } +} + +@media screen and (max-width: 768px) { + .landing-header { + padding: 10px 20px; + flex-wrap: wrap; + gap: 10px; + } +} + +@media screen and (max-width: 576px) { + .landing-header { + padding: 8px 15px; + flex-direction: column; + gap: 15px; + position: relative; + padding-bottom: 15px; + } +} + /* Estilo para a logo DENTRO do cabeçalho da Landing Page */ .landing-header .logo h1 { font-size: 1.8em; - color: #25396f; + color: #25396f; font-weight: 700; margin: 0; /* Remove margem que pode quebrar o layout */ padding: 0; /* Remove padding */ } +@media screen and (max-width: 768px) { + .landing-header .logo h1 { + font-size: 1.5em; + } +} + +@media screen and (max-width: 576px) { + .landing-header .logo h1 { + font-size: 1.3em; + } +} + +.nav-menu { + display: flex; + align-items: center; + flex-wrap: wrap; + gap: 10px; +} + +@media screen and (max-width: 768px) { + .nav-menu { + gap: 15px; + } +} + +@media screen and (max-width: 576px) { + .nav-menu { + justify-content: center; + width: 100%; + } +} + .nav-menu a { text-decoration: none; color: #333; @@ -38,6 +95,19 @@ transition: color 0.2s; } +@media screen and (max-width: 768px) { + .nav-menu a { + margin-left: 0; + font-size: 0.9em; + } +} + +@media screen and (max-width: 576px) { + .nav-menu a { + font-size: 0.85em; + } +} + .nav-menu a:hover { color: #5b56f8; } @@ -56,6 +126,21 @@ font-weight: 600; } +@media screen and (max-width: 768px) { + .access-button { + margin-left: 0; + padding: 8px 15px; + font-size: 0.9em; + } +} + +@media screen and (max-width: 576px) { + .access-button { + padding: 10px 20px; + font-size: 0.85em; + } +} + /* --- Área de Destaque (Hero Section) --- */ .hero-section { display: flex; @@ -65,31 +150,101 @@ background: linear-gradient(rgba(0, 0, 0, 0.6), rgba(0, 0, 0, 0.6)), url('https://picsum.photos/1200/600?random=4') center/cover; color: white; min-height: 600px; - padding-top: 100px; + padding-top: 100px; +} + +/* Responsividade da hero section */ +@media screen and (max-width: 1199px) { + .hero-section { + padding: 80px 30px; + min-height: 500px; + padding-top: 80px; + } +} + +@media screen and (max-width: 768px) { + .hero-section { + padding: 60px 20px; + min-height: 400px; + padding-top: 80px; + justify-content: center; + text-align: center; + } +} + +@media screen and (max-width: 576px) { + .hero-section { + padding: 40px 15px; + min-height: 350px; + padding-top: 100px; + } } .hero-content { - max-width: 700px; - text-align: left; + max-width: 700px; + text-align: left; +} + +@media screen and (max-width: 768px) { + .hero-content { + max-width: 100%; + text-align: center; + } } /* Título Branco e Legível */ -.hero-content .hero-title { - font-size: 3.5em; +.hero-content .hero-title { + font-size: 3.5em; font-weight: 700; margin-bottom: 20px; - color: #ffffff; - text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5); + color: #ffffff; + text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5); +} + +@media screen and (max-width: 1199px) { + .hero-content .hero-title { + font-size: 3em; + } +} + +@media screen and (max-width: 768px) { + .hero-content .hero-title { + font-size: 2.5em; + margin-bottom: 15px; + } +} + +@media screen and (max-width: 576px) { + .hero-content .hero-title { + font-size: 2em; + margin-bottom: 12px; + line-height: 1.2; + } } .hero-content p { - font-size: 1.2em; + font-size: 1.2em; margin-bottom: 30px; color: #ddd; } +@media screen and (max-width: 768px) { + .hero-content p { + font-size: 1.1em; + margin-bottom: 25px; + } +} + +@media screen and (max-width: 576px) { + .hero-content p { + font-size: 1em; + margin-bottom: 20px; + line-height: 1.4; + } +} + .main-action-button { - background-color: #5b56f8; + background-color: #5b56f8; color: white; border: none; padding: 15px 30px; @@ -100,6 +255,22 @@ transition: background-color 0.3s; } +@media screen and (max-width: 768px) { + .main-action-button { + padding: 12px 25px; + font-size: 1em; + } +} + +@media screen and (max-width: 576px) { + .main-action-button { + padding: 12px 20px; + font-size: 0.9em; + width: 100%; + max-width: 250px; + } +} + .main-action-button:hover { background-color: #4540d6; } @@ -156,4 +327,4 @@ html[data-bs-theme="dark"] .main-action-button { html[data-bs-theme="dark"] .main-action-button:hover { background-color: #5b56f8; color: #fff; -} \ No newline at end of file +}