diff --git a/src/PagesMedico/DoctorAgendamentoManager.jsx b/src/PagesMedico/DoctorAgendamentoManager.jsx index 25a8cae..d89a68f 100644 --- a/src/PagesMedico/DoctorAgendamentoManager.jsx +++ b/src/PagesMedico/DoctorAgendamentoManager.jsx @@ -10,50 +10,50 @@ import isBetween from 'dayjs/plugin/isBetween'; import localeData from 'dayjs/plugin/localeData'; import { Search, ChevronLeft, ChevronRight, Edit, Trash2, CheckCircle } from 'lucide-react'; import "../pages/style/Agendamento.css"; -import '../pages/style/FilaEspera.css'; -import Spinner from '../components/Spinner.jsx'; +import "../pages/style/FilaEspera.css"; +import Spinner from "../components/Spinner.jsx"; - -dayjs.locale('pt-br'); +dayjs.locale("pt-br"); dayjs.extend(isBetween); dayjs.extend(localeData); - const Agendamento = () => { - const navigate = useNavigate(); - const { getAuthorizationHeader, user } = useAuth(); - const authHeader = getAuthorizationHeader(); + const navigate = useNavigate(); + const { getAuthorizationHeader, user } = useAuth(); + const authHeader = getAuthorizationHeader(); const ID_MEDICO_ESPECIFICO = "078d2a67-b4c1-43c8-ae32-c1e75bb5b3df"; - const [listaTodosAgendamentos, setListaTodosAgendamentos] = useState([]); - const [selectedID, setSelectedId] = useState('0'); - const [filaEsperaData, setFilaEsperaData] = useState([]); - const [FiladeEspera, setFiladeEspera] = useState(false); - const [PageNovaConsulta, setPageConsulta] = useState(false); - const [DictAgendamentosOrganizados, setAgendamentosOrganizados] = useState({}); - const [showDeleteModal, setShowDeleteModal] = useState(false); - const [ListaDeMedicos, setListaDeMedicos] = useState([]); - const [FiltredTodosMedicos, setFiltredTodosMedicos] = useState([]); - const [searchTermDoctor, setSearchTermDoctor] = useState(''); - const [MedicoFiltrado, setMedicoFiltrado] = useState({ id: "vazio" }); - const [motivoCancelamento, setMotivoCancelamento] = useState(""); - const [showSpinner, setShowSpinner] = useState(true); - const [waitlistSearch, setWaitlistSearch] = useState(''); - const [waitSortKey, setWaitSortKey] = useState(null); - const [waitSortDir, setWaitSortDir] = useState('asc'); - const [waitPage, setWaitPage] = useState(1); - const [waitPerPage, setWaitPerPage] = useState(10); - const [cacheMedicos, setCacheMedicos] = useState({}); - const [cachePacientes, setCachePacientes] = useState({}); - const [currentDate, setCurrentDate] = useState(dayjs()); - const [selectedDay, setSelectedDay] = useState(dayjs()); - const [agendamentoParaEdicao, setAgendamentoParaEdicao] = useState(null); - const [quickJump, setQuickJump] = useState({ - month: currentDate.month(), - year: currentDate.year() - }); + const [listaTodosAgendamentos, setListaTodosAgendamentos] = useState([]); + const [selectedID, setSelectedId] = useState("0"); + const [filaEsperaData, setFilaEsperaData] = useState([]); + const [FiladeEspera, setFiladeEspera] = useState(false); + const [PageNovaConsulta, setPageConsulta] = useState(false); + const [DictAgendamentosOrganizados, setAgendamentosOrganizados] = useState( + {} + ); + const [showDeleteModal, setShowDeleteModal] = useState(false); + const [ListaDeMedicos, setListaDeMedicos] = useState([]); + const [FiltredTodosMedicos, setFiltredTodosMedicos] = useState([]); + const [searchTermDoctor, setSearchTermDoctor] = useState(""); + const [MedicoFiltrado, setMedicoFiltrado] = useState({ id: "vazio" }); + const [motivoCancelamento, setMotivoCancelamento] = useState(""); + const [showSpinner, setShowSpinner] = useState(true); + const [waitlistSearch, setWaitlistSearch] = useState(""); + const [waitSortKey, setWaitSortKey] = useState(null); + const [waitSortDir, setWaitSortDir] = useState("asc"); + const [waitPage, setWaitPage] = useState(1); + const [waitPerPage, setWaitPerPage] = useState(10); + const [cacheMedicos, setCacheMedicos] = useState({}); + const [cachePacientes, setCachePacientes] = useState({}); + const [currentDate, setCurrentDate] = useState(dayjs()); + const [selectedDay, setSelectedDay] = useState(dayjs()); + const [agendamentoParaEdicao, setAgendamentoParaEdicao] = useState(null); + const [quickJump, setQuickJump] = useState({ + month: currentDate.month(), + year: currentDate.year(), + }); const fetchAppointments = useCallback(async () => { @@ -67,65 +67,89 @@ const Agendamento = () => { const apiUrl = `https://yuanqfswhberkoevtmfr.supabase.co/rest/v1/appointments?doctor_id=eq.${ID_MEDICO_ESPECIFICO}&select=*`; - try { - const res = await fetch(apiUrl, requestOptions); - const data = await res.json(); - setListaTodosAgendamentos(data || []); - } catch (err) { - console.error('Erro ao buscar agendamentos', err); - setListaTodosAgendamentos([]); - } finally { - setShowSpinner(false); - } - }, [authHeader, ID_MEDICO_ESPECIFICO]); + try { + const res = await fetch(apiUrl, requestOptions); + const data = await res.json(); + setListaTodosAgendamentos(data || []); + } catch (err) { + console.error("Erro ao buscar agendamentos", err); + setListaTodosAgendamentos([]); + } finally { + setShowSpinner(false); + } + }, [authHeader, ID_MEDICO_ESPECIFICO]); - - const updateAppointmentStatus = useCallback(async (id, updates) => { - setShowSpinner(true); - const myHeaders = new Headers(); - myHeaders.append("Authorization", authHeader); - myHeaders.append("apikey", API_KEY); - myHeaders.append("Content-Type", "application/json"); - myHeaders.append("Prefer", "return=representation"); - const requestOptions = { method: 'PATCH', headers: myHeaders, body: JSON.stringify(updates) }; - try { - const response = await fetch(`https://yuanqfswhberkoevtmfr.supabase.co/rest/v1/appointments?id=eq.${id}`, requestOptions); - if (response.ok) { - await fetchAppointments(); - return true; - } else { - console.error('Erro ao atualizar agendamento:', await response.text()); - return false; - } - } catch (error) { - console.error('Erro de rede/servidor:', error); - return false; - } finally { - setShowSpinner(false); - } - }, [authHeader, fetchAppointments]); - - - const deleteConsulta = useCallback(async (id) => { - const success = await updateAppointmentStatus(id, { status: "cancelled", cancellation_reason: motivoCancelamento, updated_at: new Date().toISOString() }); - if (success) { - setShowDeleteModal(false); - setMotivoCancelamento(""); - setSelectedId('0'); + const updateAppointmentStatus = useCallback( + async (id, updates) => { + setShowSpinner(true); + const myHeaders = new Headers(); + myHeaders.append("Authorization", authHeader); + myHeaders.append("apikey", API_KEY); + myHeaders.append("Content-Type", "application/json"); + myHeaders.append("Prefer", "return=representation"); + const requestOptions = { + method: "PATCH", + headers: myHeaders, + body: JSON.stringify(updates), + }; + try { + const response = await fetch( + `https://yuanqfswhberkoevtmfr.supabase.co/rest/v1/appointments?id=eq.${id}`, + requestOptions + ); + if (response.ok) { + await fetchAppointments(); + return true; } else { - alert("Falha ao cancelar a consulta."); + console.error( + "Erro ao atualizar agendamento:", + await response.text() + ); + return false; } - }, [motivoCancelamento, updateAppointmentStatus]); + } catch (error) { + console.error("Erro de rede/servidor:", error); + return false; + } finally { + setShowSpinner(false); + } + }, + [authHeader, fetchAppointments] + ); + const deleteConsulta = useCallback( + async (id) => { + const success = await updateAppointmentStatus(id, { + status: "cancelled", + cancellation_reason: motivoCancelamento, + updated_at: new Date().toISOString(), + }); + if (success) { + setShowDeleteModal(false); + setMotivoCancelamento(""); + setSelectedId("0"); + } else { + alert("Falha ao cancelar a consulta."); + } + }, + [motivoCancelamento, updateAppointmentStatus] + ); - const confirmConsulta = useCallback(async (id) => { - const success = await updateAppointmentStatus(id, { status: "agendado", cancellation_reason: null, updated_at: new Date().toISOString() }); - if (success) { - setSelectedId('0'); - } else { - alert("Falha ao reverter o cancelamento."); - } - }, [updateAppointmentStatus]); + const confirmConsulta = useCallback( + async (id) => { + const success = await updateAppointmentStatus(id, { + status: "agendado", + cancellation_reason: null, + updated_at: new Date().toISOString(), + }); + if (success) { + setSelectedId("0"); + } else { + alert("Falha ao reverter o cancelamento."); + } + }, + [updateAppointmentStatus] + ); useEffect(() => { if(authHeader) { @@ -150,24 +174,24 @@ const Agendamento = () => { return; } - setShowSpinner(true); + setShowSpinner(true); const appointmentsToShow = listaTodosAgendamentos; - const patientIdsToFetch = new Set(); - const doctorIdsToFetch = new Set(); + const patientIdsToFetch = new Set(); + const doctorIdsToFetch = new Set(); - appointmentsToShow.forEach(ag => { - if (ag.patient_id && !cachePacientes[ag.patient_id]) { - patientIdsToFetch.add(ag.patient_id); - } - if (ag.doctor_id && !cacheMedicos[ag.doctor_id]) { - doctorIdsToFetch.add(ag.doctor_id); - } - }); + appointmentsToShow.forEach((ag) => { + if (ag.patient_id && !cachePacientes[ag.patient_id]) { + patientIdsToFetch.add(ag.patient_id); + } + if (ag.doctor_id && !cacheMedicos[ag.doctor_id]) { + doctorIdsToFetch.add(ag.doctor_id); + } + }); - const fetchPromises = []; + const fetchPromises = []; if (patientIdsToFetch.size > 0) { const query = `id=in.(${Array.from(patientIdsToFetch).join(',')})`; @@ -180,95 +204,106 @@ const Agendamento = () => { fetchPromises.push(Promise.resolve(null)); } - if (doctorIdsToFetch.size > 0) { - const query = `id=in.(${Array.from(doctorIdsToFetch).join(',')})`; - fetchPromises.push( - fetch(`https://yuanqfswhberkoevtmfr.supabase.co/rest/v1/doctors?${query}&select=id,full_name`, { - headers: { apikey: API_KEY, Authorization: authHeader } - }).then(res => res.json()) - ); - } else { - fetchPromises.push(Promise.resolve(null)); + if (doctorIdsToFetch.size > 0) { + const query = `id=in.(${Array.from(doctorIdsToFetch).join(",")})`; + fetchPromises.push( + fetch( + `https://yuanqfswhberkoevtmfr.supabase.co/rest/v1/doctors?${query}&select=id,full_name`, + { + headers: { apikey: API_KEY, Authorization: authHeader }, } - - const [newPatients, newDoctors] = await Promise.all(fetchPromises); + ).then((res) => res.json()) + ); + } else { + fetchPromises.push(Promise.resolve(null)); + } - const updatedPatientCache = { ...cachePacientes }; - if (newPatients) newPatients.forEach(p => updatedPatientCache[p.id] = p); + const [newPatients, newDoctors] = await Promise.all(fetchPromises); - const updatedDoctorCache = { ...cacheMedicos }; - if (newDoctors) newDoctors.forEach(d => updatedDoctorCache[d.id] = d); - - setCachePacientes(updatedPatientCache); - setCacheMedicos(updatedDoctorCache); + const updatedPatientCache = { ...cachePacientes }; + if (newPatients) + newPatients.forEach((p) => (updatedPatientCache[p.id] = p)); - const newDict = {}; - const newFila = []; + const updatedDoctorCache = { ...cacheMedicos }; + if (newDoctors) newDoctors.forEach((d) => (updatedDoctorCache[d.id] = d)); - for (const agendamento of appointmentsToShow) { - const medico = updatedDoctorCache[agendamento.doctor_id]; - const paciente = updatedPatientCache[agendamento.patient_id]; + setCachePacientes(updatedPatientCache); + setCacheMedicos(updatedDoctorCache); - if (!medico || !paciente) continue; + const newDict = {}; + const newFila = []; - const agendamentoMelhorado = { - ...agendamento, - medico_nome: medico.full_name || 'N/A', - paciente_nome: paciente.full_name || 'N/A', - paciente_cpf: paciente.cpf || 'N/A' - }; + for (const agendamento of appointmentsToShow) { + const medico = updatedDoctorCache[agendamento.doctor_id]; + const paciente = updatedPatientCache[agendamento.patient_id]; - if (agendamento.status === "requested") { - newFila.push({ agendamento: agendamentoMelhorado, Infos: agendamentoMelhorado }); - } else { - const DiaAgendamento = dayjs(agendamento.scheduled_at).format("YYYY-MM-DD"); - if (!newDict[DiaAgendamento]) newDict[DiaAgendamento] = []; - newDict[DiaAgendamento].push(agendamentoMelhorado); - } - } + if (!medico || !paciente) continue; - for (const key in newDict) { - newDict[key].sort((a, b) => new Date(a.scheduled_at) - new Date(b.scheduled_at)); - } - - setAgendamentosOrganizados(newDict); - setFilaEsperaData(newFila); - setShowSpinner(false); + const agendamentoMelhorado = { + ...agendamento, + medico_nome: medico.full_name || "N/A", + paciente_nome: paciente.full_name || "N/A", + paciente_cpf: paciente.cpf || "N/A", }; + if (agendamento.status === "requested") { + newFila.push({ + agendamento: agendamentoMelhorado, + Infos: agendamentoMelhorado, + }); + } else { + const DiaAgendamento = dayjs(agendamento.scheduled_at).format( + "YYYY-MM-DD" + ); + if (!newDict[DiaAgendamento]) newDict[DiaAgendamento] = []; + newDict[DiaAgendamento].push(agendamentoMelhorado); + } + } + + for (const key in newDict) { + newDict[key].sort( + (a, b) => new Date(a.scheduled_at) - new Date(b.scheduled_at) + ); + } + + setAgendamentosOrganizados(newDict); + setFilaEsperaData(newFila); + setShowSpinner(false); + }; + processData(); }, [listaTodosAgendamentos, authHeader]); - const handleEditConsulta = (agendamento) => { - setAgendamentoParaEdicao(agendamento); - setPageConsulta(true); - }; + const handleEditConsulta = (agendamento) => { + setAgendamentoParaEdicao(agendamento); + setPageConsulta(true); + }; - const handleSearchMedicos = (term) => { - setSearchTermDoctor(term); - if (term.trim()) { - const filtered = ListaDeMedicos.filter(medico => - medico.nomeMedico.toLowerCase().includes(term.toLowerCase()) - ); - setFiltredTodosMedicos(filtered); - } else { - setFiltredTodosMedicos([]); - setMedicoFiltrado({ id: "vazio" }); - } - }; - - const generateDateGrid = () => { - const grid = []; - const startOfMonth = currentDate.startOf('month'); - let currentDay = startOfMonth.subtract(startOfMonth.day(), 'day'); - for (let i = 0; i < 42; i++) { - grid.push(currentDay); - currentDay = currentDay.add(1, 'day'); - } - return grid; - }; + const handleSearchMedicos = (term) => { + setSearchTermDoctor(term); + if (term.trim()) { + const filtered = ListaDeMedicos.filter((medico) => + medico.nomeMedico.toLowerCase().includes(term.toLowerCase()) + ); + setFiltredTodosMedicos(filtered); + } else { + setFiltredTodosMedicos([]); + setMedicoFiltrado({ id: "vazio" }); + } + }; + + const generateDateGrid = () => { + const grid = []; + const startOfMonth = currentDate.startOf("month"); + let currentDay = startOfMonth.subtract(startOfMonth.day(), "day"); + for (let i = 0; i < 42; i++) { + grid.push(currentDay); + currentDay = currentDay.add(1, "day"); + } + return grid; + }; const dateGrid = useMemo(() => generateDateGrid(), [currentDate]); const weekDays = ['Dom', 'Seg', 'Ter', 'Qua', 'Qui', 'Sex', 'Sáb']; @@ -293,68 +328,86 @@ const DeleteModal = () => ( -); + ); + useEffect(() => { + setQuickJump({ + month: currentDate.month(), + year: currentDate.year(), + }); + }, [currentDate]); - useEffect(() => { - setQuickJump({ - month: currentDate.month(), - year: currentDate.year() - }); - }, [currentDate]); - - const filaEsperaFiltrada = useMemo(() => { - if (!waitlistSearch.trim()) return filaEsperaData; - const term = waitlistSearch.toLowerCase(); - return filaEsperaData.filter(item => - (item?.Infos?.paciente_nome?.toLowerCase() || '').includes(term) || - (item?.Infos?.paciente_cpf?.toLowerCase() || '').includes(term) || - (item?.Infos?.medico_nome?.toLowerCase() || '').includes(term) - ); - }, [waitlistSearch, filaEsperaData]); + const filaEsperaFiltrada = useMemo(() => { + if (!waitlistSearch.trim()) return filaEsperaData; + const term = waitlistSearch.toLowerCase(); + return filaEsperaData.filter( + (item) => + (item?.Infos?.paciente_nome?.toLowerCase() || "").includes(term) || + (item?.Infos?.paciente_cpf?.toLowerCase() || "").includes(term) || + (item?.Infos?.medico_nome?.toLowerCase() || "").includes(term) + ); + }, [waitlistSearch, filaEsperaData]); - const applySortingWaitlist = useCallback((arr) => { - if (!Array.isArray(arr) || !waitSortKey) return arr; - const copy = [...arr]; - const key = waitSortKey; - const dir = waitSortDir === 'asc' ? 1 : -1; - copy.sort((a, b) => { - const valA = key === 'data' ? new Date(a.agendamento.scheduled_at) : (a.Infos?.[`${key}_nome`] || ''); - const valB = key === 'data' ? new Date(b.agendamento.scheduled_at) : (b.Infos?.[`${key}_nome`] || ''); - if (valA < valB) return -1 * dir; - if (valA > valB) return 1 * dir; - return 0; - }); - return copy; - }, [waitSortKey, waitSortDir]); + const applySortingWaitlist = useCallback( + (arr) => { + if (!Array.isArray(arr) || !waitSortKey) return arr; + const copy = [...arr]; + const key = waitSortKey; + const dir = waitSortDir === "asc" ? 1 : -1; + copy.sort((a, b) => { + const valA = + key === "data" + ? new Date(a.agendamento.scheduled_at) + : a.Infos?.[`${key}_nome`] || ""; + const valB = + key === "data" + ? new Date(b.agendamento.scheduled_at) + : b.Infos?.[`${key}_nome`] || ""; + if (valA < valB) return -1 * dir; + if (valA > valB) return 1 * dir; + return 0; + }); + return copy; + }, + [waitSortKey, waitSortDir] + ); - const filaEsperaOrdenada = useMemo(() => applySortingWaitlist(filaEsperaFiltrada), [filaEsperaFiltrada, applySortingWaitlist]); - const waitTotalPages = Math.ceil(filaEsperaOrdenada.length / waitPerPage) || 1; - const waitIndiceInicial = (waitPage - 1) * waitPerPage; - const waitIndiceFinal = waitIndiceInicial + waitPerPage; - const filaEsperaPaginada = filaEsperaOrdenada.slice(waitIndiceInicial, waitIndiceFinal); + const filaEsperaOrdenada = useMemo( + () => applySortingWaitlist(filaEsperaFiltrada), + [filaEsperaFiltrada, applySortingWaitlist] + ); + const waitTotalPages = + Math.ceil(filaEsperaOrdenada.length / waitPerPage) || 1; + const waitIndiceInicial = (waitPage - 1) * waitPerPage; + const waitIndiceFinal = waitIndiceInicial + waitPerPage; + const filaEsperaPaginada = filaEsperaOrdenada.slice( + waitIndiceInicial, + waitIndiceFinal + ); - const gerarNumerosWaitPages = () => { - const paginas = []; - const paginasParaMostrar = 5; - let inicio = Math.max(1, waitPage - Math.floor(paginasParaMostrar / 2)); - let fim = Math.min(waitTotalPages, inicio + paginasParaMostrar - 1); - inicio = Math.max(1, fim - paginasParaMostrar + 1); - for (let i = inicio; i <= fim; i++) paginas.push(i); - return paginas; - }; + const gerarNumerosWaitPages = () => { + const paginas = []; + const paginasParaMostrar = 5; + let inicio = Math.max(1, waitPage - Math.floor(paginasParaMostrar / 2)); + let fim = Math.min(waitTotalPages, inicio + paginasParaMostrar - 1); + inicio = Math.max(1, fim - paginasParaMostrar + 1); + for (let i = inicio; i <= fim; i++) paginas.push(i); + return paginas; + }; - useEffect(() => { setWaitPage(1); }, [waitlistSearch, waitSortKey, waitSortDir]); + useEffect(() => { + setWaitPage(1); + }, [waitlistSearch, waitSortKey, waitSortDir]); - const handleQuickJumpChange = (type, value) => { - setQuickJump(prev => ({ ...prev, [type]: Number(value) })); - }; + const handleQuickJumpChange = (type, value) => { + setQuickJump((prev) => ({ ...prev, [type]: Number(value) })); + }; - const applyQuickJump = () => { - let newDate = dayjs().year(quickJump.year).month(quickJump.month).date(1); - setCurrentDate(newDate); - setSelectedDay(newDate); - }; + const applyQuickJump = () => { + let newDate = dayjs().year(quickJump.year).month(quickJump.month).date(1); + setCurrentDate(newDate); + setSelectedDay(newDate); + }; return (
diff --git a/src/pages/FinanceiroDashboard.jsx b/src/pages/FinanceiroDashboard.jsx index b3768ce..d2bf772 100644 --- a/src/pages/FinanceiroDashboard.jsx +++ b/src/pages/FinanceiroDashboard.jsx @@ -86,7 +86,7 @@ function mockFetchPagamentos() { { id: "PAY-001", paciente: { nome: "Sarah Oliveira", convenio: "Unimed" }, - valor: 20000, + valor: 20000, forma_pagamento: "Cartão", data_vencimento: "2025-09-30", status: "pendente", @@ -96,7 +96,7 @@ function mockFetchPagamentos() { { id: "PAY-002", paciente: { nome: "Laissa Marquetti", convenio: "Bradesco Saúde" }, - valor: 15000, + valor: 15000, forma_pagamento: "Dinheiro", data_vencimento: "2025-09-15", status: "pago", @@ -106,14 +106,14 @@ function mockFetchPagamentos() { { id: "PAY-003", paciente: { nome: "Vera Santos", convenio: "Particular" }, - valor: 30000, + valor: 30000, forma_pagamento: "Pix", data_vencimento: "2025-09-20", - status: "vencido", + status: "vencido", desconto: 0, observacoes: "Não respondeu ao contato" }, - { + { id: "PAY-004", paciente: { nome: "Carlos Almeida", convenio: "Particular" }, valor: 10000, @@ -169,7 +169,7 @@ export default function FinanceiroDashboard() { recebido += valorLiquido; descontos += p.desconto; } else { - aReceber += p.valor; + aReceber += valorLiquido; } }); @@ -244,8 +244,7 @@ export default function FinanceiroDashboard() {
@@ -416,15 +415,14 @@ export default function FinanceiroDashboard() {
-
@@ -432,4 +430,4 @@ export default function FinanceiroDashboard() { )} ); -} +} \ No newline at end of file diff --git a/src/pages/style/Agendamento.css b/src/pages/style/Agendamento.css index 6a4964f..806e78c 100644 --- a/src/pages/style/Agendamento.css +++ b/src/pages/style/Agendamento.css @@ -273,6 +273,7 @@ justify-content: space-between; align-items: center; margin: 15px 0 20px; + color: #fff; } .tabs-agenda-fila { diff --git a/src/pages/style/FinanceiroDashboard.css b/src/pages/style/FinanceiroDashboard.css index d9caac7..2d9fb6a 100644 --- a/src/pages/style/FinanceiroDashboard.css +++ b/src/pages/style/FinanceiroDashboard.css @@ -39,6 +39,7 @@ margin: 0 0 8px 0; font-size: 14px; font-weight: 500; + color: #fff; opacity: 0.9; } @@ -107,35 +108,79 @@ } /* Botões de ação */ -.action-group { - display: flex; - gap: 8px; - align-items: center; + +.btn-view { + background-color: #E6F2FF !important; + color: #004085 !important; + border: 1px solid #B8D4F0 !important; + padding: 0.375rem 0.75rem; + font-size: 0.875rem; + border-radius: 6px; + cursor: pointer; + transition: all 0.15s ease-in-out; + text-decoration: none; + display: inline-block; + text-align: center; } -.action-btn { - cursor: pointer; - padding: 6px 12px; - border-radius: 6px; - border: 1px solid #d7e6fb; - background: #fff; - transition: all 0.2s ease; - font-size: 13px; +.btn-view:hover { + background-color: #D1E7FF !important; + border-color: #9EC5FE !important; } -.action-btn:hover { - background: #f6f9fc; - border-color: #93c5fd; +.btn-edit { + background-color: #FFF3CD !important; + color: #856404 !important; + border: 1px solid #FFEAA7 !important; + padding: 0.375rem 0.75rem; + font-size: 0.875rem; + border-radius: 6px; + cursor: pointer; + transition: all 0.15s ease-in-out; + text-decoration: none; + display: inline-block; + text-align: center; } -.action-btn.delete { - border-color: #fca5a5; - color: #b91c1c; +.btn-edit:hover { + background-color: #FFEEBA !important; + border-color: #FFE087 !important; } -.action-btn.delete:hover { - background: #fee2e2; - border-color: #ef4444; +.btn-delete:hover { + background-color: #F1B0B7 !important; + border-color: #ED969E !important; +} +.btn-delete { + background-color: #F8D7DA !important; + color: #721C24 !important; + border: 1px solid #F5C6CB !important; + padding: 0.375rem 0.75rem; + font-size: 0.875rem; + border-radius: 6px; + cursor: pointer; + transition: all 0.15s ease-in-out; + text-decoration: none; + display: inline-block; + text-align: center; +} + +html[data-bs-theme="dark"] .btn-view { + background-color: #1e3a8a !important; + color: #e0e0e0 !important; + border-color: #374151 !important; +} + +html[data-bs-theme="dark"] .btn-edit { + background-color: #78350f !important; + color: #fef3c7 !important; + border-color: #374151 !important; +} + +html[data-bs-theme="dark"] .btn-delete { + background-color: #7f1d1d !important; + color: #fee2e2 !important; + border-color: #374151 !important; } /* Badges de status */ @@ -182,8 +227,8 @@ padding: 24px; width: 100%; max-width: 550px; - max-height: 90vh; - overflow-y: auto; + max-height: 85vh; + overflow-y: auto; box-sizing: border-box; box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgba(0, 0, 0, 0.1); } @@ -208,6 +253,12 @@ gap: 16px; } +.modal-card .input-field, +.modal-card .select-field, +.modal-card textarea { + width: 100%; +} + .form-group { display: flex; flex-direction: column; @@ -241,12 +292,23 @@ gap: 10px; margin-top: 24px; } +.input-field, +.select-field, +textarea { + padding: 10px 12px; + border: 1px solid #d1d5db; + border-radius: 8px; + box-sizing: border-box; + font-size: 14px; + transition: border-color 0.2s, box-shadow 0.2s; + background-color: #fff; +} + /* Inputs e selects */ .input-field, .select-field, textarea { - width: 100%; padding: 10px 12px; border: 1px solid #d1d5db; border-radius: 8px; @@ -269,6 +331,18 @@ textarea { min-height: 80px; } +.financeiro-wrap .input-field:not(.modal-card *), +.financeiro-wrap .select-field:not(.modal-card *), +.financeiro-wrap textarea:not(.modal-card *) { + width: 30%; +} + +.modal-card .input-field, +.modal-card .select-field, +.modal-card textarea { + width: 100%; +} + /* Mensagem quando não há pagamentos */ .empty { text-align: center; @@ -366,4 +440,4 @@ html[data-bs-theme="dark"] textarea:focus { border-color: #3b82f6; box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.25); outline: none; -} \ No newline at end of file +} diff --git a/src/pages/style/Inicio.css b/src/pages/style/Inicio.css index 21e4058..a7da5d5 100644 --- a/src/pages/style/Inicio.css +++ b/src/pages/style/Inicio.css @@ -70,10 +70,10 @@ } /* 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; } +.stat-icon-wrapper.blue { background-color: #1D3B88; } +.stat-icon-wrapper.green { background-color: #399CE5; } +.stat-icon-wrapper.purple { background-color: #5F5DF2; } +.stat-icon-wrapper.orange { background-color: #051AFF; } /* Seção de Ações Rápidas */ .quick-actions h2 {