{"version":3,"file":"inertia-BDq0AgXb.js","sources":["../../../app/frontend/components/Modal/index.jsx","../../../app/frontend/utils/index.jsx","../../../app/frontend/components/Cards/AppointmentCard/appointmentDetailsModal.jsx","../../../app/frontend/components/Calendar/index.jsx","../../../app/frontend/components/Sidebar/constants.jsx","../../../app/frontend/components/Sidebar/index.jsx","../../../app/frontend/components/Table/pagination.jsx","../../../app/frontend/components/Table/simplePagination.jsx","../../../app/frontend/components/Table/index.jsx","../../../app/frontend/components/Table/appointmentTable.jsx","../../../app/frontend/contexts/Alert.jsx","../../../app/frontend/components/Pagination/index.jsx","../../../app/frontend/components/AppointmentsComponents/AppointmentsHistory.jsx","../../../app/frontend/components/Cards/AppointmentCard/index.jsx","../../../app/frontend/components/AppointmentsComponents/NextAppointments.jsx","../../../app/frontend/pages/Appointments/Index.jsx","../../../app/frontend/pages/Appointments/Modals/creditCardModal.jsx","../../../app/frontend/pages/Appointments/Modals/pixModal.jsx","../../../app/frontend/pages/Appointments/constants.jsx","../../../app/frontend/pages/Appointments/new.jsx","../../../app/frontend/pages/Appointments/payment.jsx","../../../app/frontend/components/Cards/ExamCard/index.jsx","../../../app/frontend/constants/SelectOptions.jsx","../../../app/frontend/components/Cards/SelectedClinicsCard/index.jsx","../../../app/frontend/pages/Budget/Index.jsx","../../../app/frontend/pages/Budget/List.jsx","../../../app/frontend/pages/Budget/Modals/creditCardModal.jsx","../../../app/frontend/pages/Budget/Modals/pixModal.jsx","../../../app/frontend/components/Cards/SimpleClinicCardButton/index.jsx","../../../app/frontend/pages/Budget/Show.jsx","../../../app/frontend/pages/Budget/constants.jsx","../../../app/frontend/pages/Budget/payment.jsx","../../../app/frontend/pages/Budget/payment_confirm.jsx","../../../app/frontend/pages/Budget/payment_show.jsx","../../../app/frontend/components/Cards/SimpleClinicCard/index.jsx","../../../app/frontend/pages/ClinicExam/Edit.jsx","../../../app/frontend/pages/ClinicExam/Index.jsx","../../../app/frontend/pages/ClinicExam/constants.jsx","../../../app/frontend/components/ConfigurationPagesSidebar/index.jsx","../../../app/frontend/pages/Configuration/Password.jsx","../../../app/frontend/pages/Configuration/constants.jsx","../../../app/frontend/components/Table/historyTable.jsx","../../../app/frontend/pages/Configuration/plan.jsx","../../../app/frontend/components/Table/monthlyIncomeTable.jsx","../../../app/frontend/pages/Doctor/income.jsx","../../../app/frontend/pages/Exams/Details.jsx","../../../app/frontend/pages/Exams/Index.jsx","../../../app/frontend/pages/Exams/constants.jsx","../../../app/frontend/components/HomeSections/FaqSection.jsx","../../../app/frontend/components/HomeSections/HomeDoctorSections/AboutSection.jsx","../../../app/frontend/components/HomeSections/HomeDoctorSections/AppealSection.jsx","../../../app/frontend/components/HomeSections/HomeDoctorSections/BenefitsSection.jsx","../../../app/frontend/components/HomeSections/HomeDoctorSections/HeroSection.jsx","../../../app/frontend/components/HomeSections/HomeDoctorSections/InfoSection.jsx","../../../app/frontend/components/HomeSections/HomePatientSections/SignUpSection.jsx","../../../app/frontend/components/HomeSections/HomeDoctorSections/PaymentSection.jsx","../../../app/frontend/components/WhatsAppButton/index.jsx","../../../app/frontend/pages/Home/HomeDoctor.jsx","../../../app/frontend/components/HomeSections/HomeDoctorSections/SignUpSection.jsx","../../../app/frontend/components/HomeSections/HomePatientSections/AboutSection.jsx","../../../app/frontend/components/HomeSections/HomePatientSections/AppealSection.jsx","../../../app/frontend/components/HomeSections/HomePatientSections/BenefitsSection.jsx","../../../app/frontend/components/HomeSections/HomePatientSections/HeroSection.jsx","../../../app/frontend/components/HomeSections/HomePatientSections/InfoSection.jsx","../../../app/frontend/pages/Home/HomePatient.jsx","../../../app/frontend/components/Cards/AppointmentPatientCard/index.jsx","../../../app/frontend/components/Cards/PatientAppointmentCard/index.jsx","../../../app/frontend/pages/User/modal/AppointmentPatientModal.jsx","../../../app/frontend/pages/Patients/appointments.jsx","../../../app/frontend/components/Cards/ProfessionalCard/index.jsx","../../../app/frontend/pages/Professional/Index.jsx","../../../app/frontend/pages/Professional/constants.jsx","../../../app/frontend/pages/Rating/Index.jsx","../../../app/frontend/pages/Team/Appointments.jsx","../../../app/frontend/pages/Team/Index.jsx","../../../app/frontend/components/SignUpSections/AddressInfo.jsx","../../../app/frontend/components/SignUpSections/FinishSignUp.jsx","../../../app/frontend/components/SignUpSections/PersonalInfo.jsx","../../../app/frontend/components/SignUpSections/ProfessionalInfo.jsx","../../../app/frontend/components/SignUpSections/StartAccount.jsx","../../../app/frontend/pages/Team/New.jsx","../../../app/frontend/pages/User/cards.jsx","../../../app/frontend/components/InputFile/defaultMessage.jsx","../../../app/frontend/components/InputFile/deleteFile.jsx","../../../app/frontend/components/InputFile/fileInfos.jsx","../../../app/frontend/components/InputFile/fileSize.jsx","../../../app/frontend/components/InputFile/index.jsx","../../../app/frontend/components/AddImageModal/index.jsx","../../../app/frontend/components/ProfileSections/EditProfile.jsx","../../../app/frontend/pages/User/profile.jsx","../../../app/frontend/components/SignUpSections/DoctorTypeInfo.jsx","../../../app/frontend/components/SignUpSections/LocationInfo.jsx","../../../app/frontend/components/SignUpSections/UserTypeInfo.jsx","../../../app/frontend/pages/registrations/new.jsx","../../../app/frontend/pages/reset_password/stepFour.jsx","../../../app/frontend/components/ClickBack/index.jsx","../../../app/frontend/pages/reset_password/stepOne.jsx","../../../app/frontend/pages/reset_password/stepThree.jsx","../../../app/frontend/pages/reset_password/stepTwo.jsx","../../../app/frontend/pages/sessions/new.jsx","../../../app/frontend/components/Layout/Footer/index.jsx","../../../app/frontend/components/Layout/Navbar/index.jsx","../../../app/frontend/components/Layout/index.jsx","../../../app/frontend/entrypoints/inertia.jsx"],"sourcesContent":["import \"react-spring-bottom-sheet/dist/style.css\";\n\nimport { XMarkIcon } from \"@heroicons/react/24/solid\";\nimport { Button } from \"@switchdreams/ui\";\nimport React from \"react\";\nimport { BottomSheet } from \"react-spring-bottom-sheet\";\n\nconst Modal = ({\n confirmLabel,\n cancelLabel,\n children,\n onClickCancel,\n onClickConfirm,\n open,\n setOpen,\n cancelOutline = true,\n confirmOutline,\n iconConfirm,\n error,\n padding = true,\n loading = false,\n buttons = true,\n onClose = null,\n}) => {\n const handleClose = () => {\n setOpen(false);\n if (onClose) {\n onClose();\n }\n };\n const handleDismiss = () => {\n handleClose();\n };\n\n return (\n <>\n {\n setOpen(!open);\n if (onClose) {\n onClose();\n }\n }}\n />\n \n
\n {\n setOpen(!open);\n if (onClose) {\n onClose();\n }\n }}\n />\n
{children}
\n {buttons && (\n
\n \n \n
\n )}\n
\n \n {/* Mobile */}\n [maxHeight * 0.75]}\n >\n
\n
{children}
\n {buttons && (\n
\n \n \n
\n )}\n
\n \n \n );\n};\n\nexport default Modal;\n","import axios from \"axios\";\n\nexport const imagePath = (name) => {\n return `/images/${name}`;\n};\n\nexport const cardBrandLogo = (name) => {\n switch (name) {\n case \"VISA\":\n return imagePath(\"visa.svg\");\n case \"MASTERCARD\":\n return imagePath(\"mastercard.svg\");\n default:\n break;\n }\n};\n\nexport const priceOptions = [\n { value: 8000, label: \"R$ 80,00\" },\n { value: 10000, label: \"R$ 100,00\" },\n { value: 12000, label: \"R$ 120,00\" },\n { value: 14000, label: \"R$ 140,00\" },\n { value: 15000, label: \"R$ 150,00\" },\n { value: 16000, label: \"R$ 160,00\" },\n { value: 18000, label: \"R$ 180,00\" },\n { value: 20000, label: \"R$ 200,00\" },\n { value: 22000, label: \"R$ 220,00\" },\n { value: 24000, label: \"R$ 240,00\" },\n];\n\nexport const pixTypeOptions = [\n { value: \"CPF\", label: \"CPF\" },\n { value: \"EMAIL\", label: \"Email\" },\n { value: \"PHONE\", label: \"Telefone\" },\n { value: \"EVP\", label: \"Aleatória\" },\n];\n\nexport const yesOrNotOptions = [\n { value: 'true', label: \"Sim\" },\n { value: 'false', label: \"Não\" },\n];\n\nexport const specialtyType = [\n { value: \"1\", label: \"Laboratório\" },\n { value: \"2\", label: \"Exames Diagnósticos\" },\n { value: \"3\", label: \"Ambos\" },\n];\n\nexport const specialtyClinicMock = [\n {value: 1, label:'Exames de cardiologia' },\n {value: 2, label:'Exames de dermatologia/alergia' },\n {value: 3, label:'Exames de imagem' },\n {value: 4, label:'Exames de laboratório' },\n {value: 5, label:'Exames de neurologia' },\n {value: 6, label:'Exames de nutrição' },\n {value: 7, label:'Exames de odontologia' },\n {value: 8, label:'Exames de oftamologia' },\n {value: 9, label:'Exames de otorrinolaringologia' },\n {value: 10, label:'Exames de patologia' },\n {value: 11, label:'Exames do sono ' },\n {value: 12, label:'Exames de urologia ' },\n {value: 13, label:'Exames Laboratoriais' },\n {value: 14, label:'Exames de outra natureza' },\n]\n\nexport const pixTypeMask = (pixType) => {\n if (pixType === \"CPF\") {\n return \"999.999.999-99\";\n } else if (pixType === \"PHONE\") {\n return \"(99) 99999-9999\";\n }\n};\n\nexport const monthsTranslated = [\n \"Janeiro\",\n \"Fevereiro\",\n \"Março\",\n \"Abril\",\n \"Maio\",\n \"Junho\",\n \"Julho\",\n \"Agosto\",\n \"Setembro\",\n \"Outubro\",\n \"Novembro\",\n \"Dezembro\",\n];\n\nexport const monthsTranslatedAbreviation = [\n \"Jan\",\n \"Fev\",\n \"Mar\",\n \"Abr\",\n \"Mai\",\n \"Jun\",\n \"Jul\",\n \"Ago\",\n \"Set\",\n \"Out\",\n \"Nov\",\n \"Dez\",\n];\n\nexport const weekDaysTranslated = [\n \"Domingo\",\n \"Segunda\",\n \"Terça\",\n \"Quarta\",\n \"Quinta\",\n \"Sexta\",\n \"Sábado\",\n];\n\nexport const currencyStringToInteger = (currency) => {\n return Number(currency.replace(/[^0-9-]+/g, \"\"));\n};\n\nexport const fetchCep = async (data, setData, setError, setLoading) => {\n let latitude = '';\n let longitude = '';\n if (setLoading) setLoading(true);\n axios\n .get(`https://viacep.com.br/ws/${data.address_attributes.cep}/json/`)\n .then(async (response) => {\n if (response.data.erro) {\n setError(true);\n } else {\n const apiKey = \"AIzaSyAoLzTfDNeO5ZBNk8yyvZ6p5CJnWPKM8LU\";\n const url = `https://maps.googleapis.com/maps/api/geocode/json?address=${data.address_attributes.cep}&key=${apiKey}`;\n const responseCoord = await axios.get(url);\n const responseData = responseCoord.data;\n\n if (responseData.results && responseData.results.length > 0) {\n const location = responseData.results[0].geometry.location;\n console.log(location.lat, location.lng);\n latitude = location.lat.toString();\n longitude = location.lng.toString();\n }\n\n setError(false);\n const addressData = {\n cep: data.address_attributes.cep,\n street: response.data.logradouro,\n city: response.data.localidade,\n neighborhood: response.data.bairro,\n complement: response.data.complemento,\n state: response.data.uf,\n latitude: latitude,\n longitude: longitude,\n };\n\n setData({ ...data, address_attributes: addressData });\n }\n if (setLoading) setLoading(false);\n })\n .catch(() => {\n setError(true);\n if (setLoading) setLoading(false);\n });\n};\n\nexport const workAreaOptionsFetch = (setData) => {\n const blank = [{ value: \"\", label: \"Todos\" }];\n\n try {\n axios\n .get(\"/work_areas\")\n .then((response) => {\n const options = response.data.map((specialty) => {\n return {\n value: specialty.id,\n label: specialty.nick_name,\n work_specialities: specialty.work_specialties,\n };\n });\n\n setData(blank.concat(options));\n })\n .catch(() => {\n setData(blank);\n });\n } catch (error) {\n setData(blank);\n }\n};\n\nexport const specialtyOptions = (setData) => {\n const blank = [{ value: \"\", label: \"Todos\" }];\n\n try {\n axios\n .get(\"/work_specialties\")\n .then((response) => {\n const options = response.data.map((specialty) => {\n return {\n value: specialty.id,\n label: specialty.name,\n };\n });\n\n setData(blank.concat(options));\n })\n .catch(() => {\n setData(blank);\n });\n } catch (error) {\n setData(blank);\n }\n};\n\nexport const formatIntegerCurrency = (value) => {\n if (!value) return \"R$ 0,00\";\n\n let stringValue = value.toString();\n while (stringValue.length < 3) stringValue = \"0\" + stringValue;\n\n const wholePart = stringValue.slice(0, -2);\n const decimalPart = stringValue.slice(-2);\n\n const formattedWholePart = wholePart.replace(/\\B(?=(\\d{3})+(?!\\d))/g, \".\");\n\n return `R$ ${formattedWholePart},${decimalPart}`;\n};\n\nexport const extractTime = (date) => {\n const hours = date.getHours().toString().padStart(2, \"0\");\n const minutes = date.getMinutes().toString().padStart(2, \"0\");\n return `${hours}:${minutes}`;\n};\n","import {\n CalendarDaysIcon,\n ClockIcon,\n CurrencyDollarIcon,\n MapPinIcon,\n} from \"@heroicons/react/24/outline\";\nimport { Avatar, Text } from \"@switchdreams/ui\";\nimport React from \"react\";\n\nimport Modal from \"@/components/Modal\";\nimport { formatIntegerCurrency, imagePath } from \"@/utils\";\n\nconst AppointmentModal = ({ appointments, open, setOpen }) => {\n const date = new Date(appointments.date);\n return (\n \n
\n
\n \n
\n \n {appointments.patient_name}\n \n \n {appointments.patient_gender}, {appointments.patient_age} anos\n \n
\n
\n
\n \n {formatIntegerCurrency(appointments.transfer_value_cents)}\n \n \n (Valor sem taxas: {formatIntegerCurrency(appointments.price_cents)})\n \n
\n
\n
\n
\n \n
\n \n {appointments.location}\n \n \n Local\n \n
\n
\n \n
\n
\n \n
\n \n {`${date.getDate()}/${date.getMonth() < 10 ? \"0\" : \"\"}${date.getMonth()}/${date.getFullYear()}`}\n \n \n Data\n \n
\n
\n
\n \n
\n \n {`${date.getHours() < 10 ? \"0\" : \"\"}${date.getHours()}:${date.getMinutes() < 10 ? \"0\" : \"\"}${date.getMinutes()}`}\n \n \n Horário\n \n
\n
\n
\n \n
\n \n {appointments.payment_method == \"pix\" ? \"PIX\" : \"cartão de crédito\"}\n \n \n Método de pagamento\n \n
\n
\n
\n \n Informações adicionais do paciente:\n \n \n {appointments.aditional_info}\n \n
\n
\n );\n};\n\nexport default AppointmentModal;\n","import dayGridPlugin from \"@fullcalendar/daygrid\";\nimport FullCalendar from \"@fullcalendar/react\";\nimport timeGridPlugin from \"@fullcalendar/timegrid\";\nimport { ChevronLeftIcon, ChevronRightIcon } from \"@heroicons/react/24/solid\";\nimport { Button, Text } from \"@switchdreams/ui\";\nimport React, { useEffect, useState } from \"react\";\n\nimport AppointmentModal from \"../Cards/AppointmentCard/appointmentDetailsModal\";\n\nconst renderEventContent = (eventInfo) => {\n let event_border = \"\";\n let event_color = \"\";\n let event_user = \"\";\n\n const start_time = eventInfo.event.extendedProps.approximate_start_time;\n const end_time = eventInfo.event.extendedProps.approximate_end_time;\n\n switch (eventInfo.event.extendedProps.status) {\n case \"completed\":\n event_border = \"border-green-300\";\n event_color = \"bg-green-100\";\n event_user = \"text-green-500\";\n break;\n case \"scheduled\":\n event_border = \"border-yellow-300\";\n event_color = \"bg-yellow-100\";\n event_user = \"text-yellow-500\";\n break;\n case \"cancelled\":\n event_border = \"border-red-300\";\n event_color = \"bg-red-100\";\n event_user = \"text-red-500\";\n break;\n default:\n event_border = \"border-gray-300\";\n event_color = \"bg-gray-100\";\n event_user = \"text-gray-500\";\n break;\n }\n return (\n \n
\n {eventInfo.event.extendedProps.patient_name}\n \n {start_time} - {end_time}\n \n
\n {eventInfo.event.extendedProps.user_name}\n \n );\n};\n\nconst CustomMoreButtonRender = (info) => {\n return (\n \n + {info.num} consultas\n \n );\n};\n\nconst Calendar = ({ events }) => {\n const [open, setOpen] = useState(false);\n const [event, setEvent] = useState(null);\n const calendarRef = React.createRef();\n\n let monthDefault = new Date().getMonth();\n let yearDefault = new Date().getFullYear();\n\n const [selectedYear, setSelectedYear] = useState(yearDefault);\n const [selectedMonth, setSelectedMonth] = useState(monthDefault);\n\n useEffect(() => {\n const calendarApi = calendarRef.current.getApi();\n calendarApi.gotoDate(new Date(selectedYear, selectedMonth));\n }, [selectedMonth]);\n\n const handleNextButtonClick = () => {\n const calendarApi = calendarRef.current.getApi();\n calendarApi.next();\n setSelectedMonth(calendarApi.getDate().getMonth());\n setSelectedYear(calendarApi.getDate().getFullYear());\n };\n const handlePrevButtonClick = () => {\n const calendarApi = calendarRef.current.getApi();\n calendarApi.prev();\n setSelectedMonth(calendarApi.getDate().getMonth());\n setSelectedYear(calendarApi.getDate().getFullYear());\n };\n\n const [screenWidth, setScreenWidth] = useState(window.innerWidth);\n\n useEffect(() => {\n const handleResize = () => {\n setScreenWidth(window.innerWidth);\n };\n\n window.addEventListener(\"resize\", handleResize);\n\n return () => {\n window.removeEventListener(\"resize\", handleResize);\n };\n }, []);\n\n let daysOfWeek = {};\n\n if (screenWidth <= 768) {\n daysOfWeek = {\n Sunday: \"D\",\n Monday: \"S\",\n Tuesday: \"T\",\n Wednesday: \"Q\",\n Thursday: \"Q\",\n Friday: \"S\",\n Saturday: \"S\",\n };\n } else {\n daysOfWeek = {\n Sunday: \"Domingo\",\n Monday: \"Segunda\",\n Tuesday: \"Terça\",\n Wednesday: \"Quarta\",\n Thursday: \"Quinta\",\n Friday: \"Sexta\",\n Saturday: \"Sábado\",\n };\n }\n\n const monthsTranslations = (year) => {\n return {\n 0: `Janeiro de ${year}`,\n 1: `Fevereiro de ${year}`,\n 2: `Março de ${year}`,\n 3: `Abril de ${year}`,\n 4: `Maio de ${year}`,\n 5: `Junho de ${year}`,\n 6: `Julho de ${year}`,\n 7: `Agosto de ${year}`,\n 8: `Setembro de ${year}`,\n 9: `Outubro de ${year}`,\n 10: `Novembro de ${year}`,\n 11: `Dezembro de ${year}`,\n };\n };\n\n const customDayHeaders = ({ date }) => {\n const dayName = date.toLocaleDateString(\"en-US\", { weekday: \"long\", timeZone: \"UTC\" });\n return (\n
\n {daysOfWeek[dayName]}\n
\n );\n };\n\n const changeModal = async (bool) => {\n setOpen(bool);\n };\n\n return (\n <>\n {event && }\n
\n
\n
\n

Calendário de eventos

\n
\n
\n }\n />\n \n {monthsTranslations(selectedYear)[selectedMonth]}\n \n }\n />\n
\n
\n
\n CustomMoreButtonRender(e)}\n eventClick={(e) => {\n setEvent(events.find((obj) => obj.id == e.event._def.publicId));\n changeModal(true);\n }}\n dayMaxEventRows={3}\n />\n
\n
\n \n );\n};\n\nexport default Calendar;\n","export const TimeOptions = [\n { label: \"6:00\", value: \"6:00\" },\n { label: \"6:30\", value: \"6:30\" },\n { label: \"7:00\", value: \"7:00\" },\n { label: \"7:30\", value: \"7:30\" },\n { label: \"8:00\", value: \"8:00\" },\n { label: \"8:30\", value: \"8:30\" },\n { label: \"9:00\", value: \"9:00\" },\n { label: \"9:30\", value: \"9:30\" },\n { label: \"10:00\", value: \"10:00\" },\n { label: \"10:30\", value: \"10:30\" },\n { label: \"11:00\", value: \"11:00\" },\n { label: \"11:30\", value: \"11:30\" },\n { label: \"12:00\", value: \"12:00\" },\n { label: \"12:30\", value: \"12:30\" },\n { label: \"13:00\", value: \"13:00\" },\n { label: \"13:30\", value: \"13:30\" },\n { label: \"14:00\", value: \"14:00\" },\n { label: \"14:30\", value: \"14:30\" },\n { label: \"15:00\", value: \"15:00\" },\n { label: \"15:30\", value: \"15:30\" },\n { label: \"16:00\", value: \"16:00\" },\n { label: \"16:30\", value: \"16:30\" },\n { label: \"17:00\", value: \"17:00\" },\n { label: \"17:30\", value: \"17:30\" },\n { label: \"18:00\", value: \"18:00\" },\n { label: \"18:30\", value: \"18:30\" },\n { label: \"19:00\", value: \"19:00\" },\n { label: \"19:30\", value: \"19:30\" },\n { label: \"20:00\", value: \"20:00\" },\n { label: \"20:30\", value: \"20:30\" },\n { label: \"21:00\", value: \"21:00\" },\n { label: \"21:30\", value: \"21:30\" },\n { label: \"22:00\", value: \"22:00\" },\n];\n","import { ChevronDownIcon, XMarkIcon } from \"@heroicons/react/24/outline\";\nimport { router } from \"@inertiajs/react\";\nimport { Button, CheckBox, Popover, SelectBox, Text } from \"@switchdreams/ui\";\nimport React, { useEffect, useState } from \"react\";\n\nimport { TimeOptions } from \"./constants\";\n\nconst DayAvailability = ({\n index,\n day,\n times,\n setTimes,\n enabled,\n toggleEnabled,\n initialTimes,\n error,\n}) => {\n const [periods, setPeriods] = useState(1);\n\n useEffect(() => {\n if (initialTimes.length > 0) {\n setPeriods(initialTimes.length);\n toggleEnabled(index);\n }\n }, [initialTimes]);\n\n const handleChange = (day, action, value, index) => {\n if (action == \"start\") {\n const newTime = times[day][index]\n ? { startTime: value, endTime: times[day][index].endTime }\n : { startTime: value, endTime: \"\" };\n const newArray = times[day];\n newArray[index] = newTime;\n setTimes({ ...times, [day]: newArray });\n }\n if (action == \"end\") {\n const newTime = times[day][index]\n ? { startTime: times[day][index].startTime, endTime: value }\n : { startTime: \"\", endTime: value };\n const newArray = times[day];\n newArray[index] = newTime;\n setTimes({ ...times, [day]: newArray });\n }\n };\n\n return (\n
\n
\n
\n {\n toggleEnabled(index);\n handleChange(index, \"enable\", !enabled);\n }}\n />\n {day}\n
\n \n \n {periods} período(s)\n \n \n
\n }\n disabled={!enabled}\n >\n
\n {[1, 2, 3, 4].map((period) => (\n
\n 1 ? \"s\" : \"\"}`}\n onClick={() => {\n if (periods > period) {\n setTimes({ ...times, [index]: times[index].slice(0, period) });\n toggleEnabled(index);\n }\n setPeriods(period);\n }}\n disabled={!enabled}\n />\n
\n ))}\n
\n \n
\n {error && Erro: os horários se sobrepõem}\n
\n {Array.from({ length: periods }).map((_, idx) => (\n
\n {idx + 1} período\n
\n
\n handleChange(index, \"start\", e, idx)}\n value={initialTimes[idx]?.startTime.replace(/ /g, \"\")}\n />\n
\n
\n
\n handleChange(index, \"end\", e, idx)}\n defaultValue={initialTimes[idx]?.endTime}\n value={initialTimes[idx]?.endTime.replace(/ /g, \"\")}\n />\n
\n
\n
\n ))}\n
\n
\n );\n};\n\nconst TimeSidebar = ({ open, setOpen, doctorAvailabilities, userId }) => {\n const [times, setTimes] = useState({\n 0: [],\n 1: [],\n 2: [],\n 3: [],\n 4: [],\n 5: [],\n 6: [],\n });\n\n const [errorDays, setErrorDays] = useState({\n 0: false,\n 1: false,\n 2: false,\n 3: false,\n 4: false,\n 5: false,\n 6: false,\n });\n\n const hasTimeOverlaps = (key) => {\n const timeSlots = times[key];\n for (let i = 0; i < timeSlots.length - 1; i++) {\n const slot1 = timeSlots[i];\n for (let j = i + 1; j < timeSlots.length; j++) {\n const slot2 = timeSlots[j];\n if (isOverlapping(slot1.startTime, slot1.endTime, slot2.startTime, slot2.endTime)) {\n return true;\n }\n }\n }\n return false;\n };\n\n useEffect(() => {\n setErrorDays({\n 0: hasTimeOverlaps(0),\n 1: hasTimeOverlaps(1),\n 2: hasTimeOverlaps(2),\n 3: hasTimeOverlaps(3),\n 4: hasTimeOverlaps(4),\n 5: hasTimeOverlaps(5),\n 6: hasTimeOverlaps(6),\n });\n }, [times]);\n\n // console.log(errorDays)\n\n const isOverlapping = (startTime1, endTime1, startTime2, endTime2) => {\n // Helper function to check for overlap between two time ranges\n const start1 = convertTimeStringToNumber(startTime1);\n const end1 = convertTimeStringToNumber(endTime1);\n const start2 = convertTimeStringToNumber(startTime2);\n const end2 = convertTimeStringToNumber(endTime2);\n\n // Overlap exists if:\n // - Start time of one range falls within the other range\n // - End time of one range falls within the other range\n // - One range completely encompasses the other\n return (\n (start1 < end2 && start1 >= start2) ||\n (end1 > start2 && end1 <= end2) ||\n (start1 <= start2 && end1 >= end2)\n );\n };\n\n const convertTimeStringToNumber = (timeString) => {\n // Helper function to convert time string (e.g., \"06:00\") to a number (e.g., 600)\n const [hours, minutes] = timeString.trim().split(\":\");\n return parseInt(hours, 10) * 60 + parseInt(minutes, 10);\n };\n\n const [enabledDays, setEnabledDays] = useState({\n 0: false,\n 1: false,\n 2: false,\n 3: false,\n 4: false,\n 5: false,\n 6: false,\n });\n\n const days = [\"Segunda\", \"Terça\", \"Quarta\", \"Quinta\", \"Sexta\", \"Sábado\", \"Domingo\"];\n\n useEffect(() => {\n if (doctorAvailabilities) {\n const translatedDays = {\n monday: 0,\n tuesday: 1,\n wednesday: 2,\n thursday: 3,\n friday: 4,\n saturday: 5,\n sunday: 6,\n };\n const initialTimes = {\n 0: [],\n 1: [],\n 2: [],\n 3: [],\n 4: [],\n 5: [],\n 6: [],\n };\n Array.from({ length: days.length }).map((_, idx) => {\n const formatedAvailabilities = doctorAvailabilities\n .filter((availability) => translatedDays[availability.day_of_week] == idx)\n .map((availability) => {\n return {\n startTime: availability.start_time,\n endTime: availability.end_time,\n };\n });\n initialTimes[idx] = formatedAvailabilities;\n });\n setTimes(initialTimes);\n }\n }, []);\n\n const toggleEnabled = (day) => {\n setEnabledDays((prev) => ({ ...prev, [day]: !prev[day] }));\n };\n\n const submitAvailability = () => {\n const submitObject = {\n 0: enabledDays[0] && times[0],\n 1: enabledDays[1] && times[1],\n 2: enabledDays[2] && times[2],\n 3: enabledDays[3] && times[3],\n 4: enabledDays[4] && times[4],\n 5: enabledDays[5] && times[5],\n 6: enabledDays[6] && times[6],\n };\n router.post(\"/doctor_availabilities\", { availability: submitObject, user_id: userId });\n setOpen(false);\n };\n\n return (\n <>\n setOpen(!open)}\n />\n \n
\n \n Defina seus horários de atendimento\n \n setOpen(false)} />\n
\n {days.map((day, index) => (\n \n ))}\n
\n setOpen(false)}\n />\n submitAvailability()}\n disabled={Object.values(errorDays).some((value) => Boolean(value))}\n />\n
\n \n \n );\n};\n\nexport default TimeSidebar;\n","import { ArrowLeftIcon, ArrowRightIcon } from \"@heroicons/react/24/outline\";\nimport { router } from \"@inertiajs/react\";\nimport { Text } from \"@switchdreams/ui\";\nimport React from \"react\";\n\n// TODO: Add props to preserve page state on pagination (For filters)?\nconst Pagination = ({ pagy }) => {\n return (\n
\n {\n router.visit(pagy.prev_url, { preserveScroll: true });\n }}\n >\n {}\n Anterior\n \n
\n {pagy.series.map((serie, index) => {\n const classNamePagination = `h-10 w-10 flex justify-center items-center rounded cursor-pointer`;\n\n if (typeof serie == \"number\") {\n const url = pagy.scaffold_url.replace(\"__pagy_page__\", serie);\n return (\n
router.visit(url)}>\n {serie}\n
\n );\n }\n if (pagy.series[0] === \"1\" && serie !== \"gap\") {\n const url = pagy.scaffold_url.replace(\"__pagy_page__\", \"1\");\n return (\n
router.visit(url)}>\n 1\n
\n );\n }\n if (typeof pagy.series[pagy.series.length - 1] === \"string\" && serie !== \"gap\") {\n const url = pagy.scaffold_url.replace(\n \"__pagy_page__\",\n pagy.series[pagy.series.length - 1],\n );\n return (\n
router.visit(url)}>\n {pagy.series[pagy.series.length - 1]}\n
\n );\n } else {\n if (pagy.page.toString() === serie) {\n return (\n
\n {serie}\n
\n );\n } else {\n return (\n
\n ...\n
\n );\n }\n }\n })}\n
\n
\n \n Página\n \n {pagy.page}\n \n de\n \n {pagy.pages}\n \n \n
\n router.visit(pagy.next_url)}\n >\n Próximo\n {}\n \n
\n );\n};\n\nexport default Pagination;\n","import { ArrowLeftIcon, ArrowRightIcon } from \"@heroicons/react/24/outline\";\nimport { router } from \"@inertiajs/react\";\nimport { Text } from \"@switchdreams/ui\";\nimport React from \"react\";\n\nconst SimplePagination = ({ hasMorePages }) => {\n const queryParams = Object.fromEntries(new URLSearchParams(window.location.search));\n\n return (\n
\n {\n router.reload({\n data: { ...queryParams, page: Math.min(Number(queryParams.page || 1) - 1, 1) },\n });\n }}\n disabled={!queryParams.page || queryParams.page === \"1\"}\n >\n {}\n Anterior\n \n
\n \n Página\n \n {queryParams.page || 1}\n \n \n
\n {\n if (hasMorePages)\n router.reload({\n data: { ...queryParams, page: Number(queryParams.page || 1) + 1 },\n });\n }}\n disabled={!hasMorePages}\n >\n Próximo\n {}\n \n
\n );\n};\n\nexport default SimplePagination;\n","import { flexRender, getCoreRowModel, useReactTable } from \"@tanstack/react-table\";\nimport React from \"react\";\nimport InfiniteScroll from \"react-infinite-scroll-component\";\nimport { twMerge } from \"tailwind-merge\";\n\nimport Pagination from \"./pagination\";\nimport SimplePagination from \"./simplePagination\";\n\nconst Table = ({\n data,\n columns,\n defaultMessage,\n classNameCell,\n classNameTable,\n classNameHeader,\n onClickRow,\n pagy,\n simplePagination = false,\n hasMorePages = false,\n infiniteScrollProps,\n selectedIds = [],\n}) => {\n if (!data) {\n return defaultMessage;\n }\n\n const table = useReactTable({\n data,\n columns,\n getCoreRowModel: getCoreRowModel(),\n });\n\n const cellClass = twMerge(\"px-6 py-4 text-sm font-semibold text-primary-600\", classNameCell);\n const tableClass = twMerge(\"w-full overflow-hidden md:rounded-t-md shadow-lg\", classNameTable);\n const headerClass = twMerge(\n \"z-10 top-0 px-6 py-4 font-poppins font-regular text-sm text-coolGray-600 border-b border-gray-100 bg-white\",\n classNameHeader,\n );\n\n const renderTable = () => {\n return (\n \n \n {table.getHeaderGroups().map((headerGroup) => (\n \n {headerGroup.headers.map((header) => (\n \n ))}\n \n ))}\n \n \n {table.getRowModel().rows.map((row) => (\n onClickRow(row.original) })}\n >\n {row.getVisibleCells().map((cell, index) => {\n return (\n \n {flexRender(cell.column.columnDef.cell, cell.getContext())}\n \n );\n })}\n \n ))}\n \n
\n {header.isPlaceholder\n ? null\n : flexRender(header.column.columnDef.header, header.getContext())}\n
\n );\n };\n\n return (\n <>\n {infiniteScrollProps ? (\n {renderTable()}\n ) : (\n
{renderTable()}
\n )}\n {pagy && }\n {!pagy && simplePagination && }\n \n );\n};\n\nexport default Table;\n","import {\n CalendarDaysIcon,\n CheckCircleIcon,\n ChevronRightIcon,\n ClockIcon,\n XCircleIcon,\n} from \"@heroicons/react/24/outline\";\nimport { Avatar, Text } from \"@switchdreams/ui\";\nimport { createColumnHelper } from \"@tanstack/react-table\";\nimport React from \"react\";\n\nimport Table from \"./index\";\n\nconst user = (name) => {\n return (\n
\n \n {name}\n
\n );\n};\n\nconst status = (statusName) => {\n return (\n
\n {statusName == \"completed\" ? (\n <>\n \n Finalizado\n \n ) : (\n <>\n \n Cancelado\n \n )}\n
\n );\n};\n\nconst Timer = (time) => {\n const date = new Date(time);\n return (\n
\n \n {`${date.getHours() < 10 ? \"0\" : \"\"}${date.getHours()}:${date.getMinutes() < 10 ? \"0\" : \"\"}${date.getMinutes()}`}\n
\n );\n};\n\nconst DateFormatter = (day) => {\n const date = new Date(day);\n return (\n
\n \n {`${date.getDate()}/${date.getMonth() < 10 ? \"0\" : \"\"}${date.getMonth()}/${date.getFullYear()}`}\n
\n );\n};\n\nconst columnHelper = createColumnHelper();\n\nconst columns = [\n columnHelper.accessor(\"patient\", {\n header: () => \"Paciente\",\n cell: (info) => user(info.row.original.patient_name),\n }),\n columnHelper.accessor(\"data\", {\n header: () => \"Data de sessão\",\n cell: (info) => DateFormatter(info.row.original.date),\n }),\n columnHelper.accessor(\"hour\", {\n header: () => \"Horário de sessão\",\n cell: (info) => Timer(info.row.original.date),\n }),\n columnHelper.accessor(\"status\", {\n header: () => \"Status\",\n cell: (info) => status(info.row.original.status),\n }),\n columnHelper.accessor(\"options\", {\n header: \"\",\n cell: () => ,\n }),\n];\n\nconst CustomCell = () => {\n return (\n
\n \n
\n );\n};\n\nconst AppointmentTable = ({ info }) => {\n return (\n <>\n {info.length > 0 ? (\n \n ) : (\n
\n Histórico vazio\n \n Seu histórico de consultas está vazio por enquanto.\n \n
\n )}\n \n );\n};\n\nexport default AppointmentTable;\n","import { Transition } from \"@headlessui/react\";\nimport { usePage } from \"@inertiajs/react\";\nimport { Toast } from \"@switchdreams/ui\";\nimport React, { createContext, useEffect, useState } from \"react\";\n\nconst alertContextDefaultValue = {\n showAlert: () => {},\n};\n\nexport const AlertContext = createContext(alertContextDefaultValue);\n\nexport const AlertProvider = ({ children }) => {\n const [content, setContent] = useState({\n title: \"\",\n message: \"\",\n type: \"error\",\n });\n const [isOpen, setIsOpen] = useState(false);\n\n /**\n * Displays an alert with specified message, title, and type.\n * @param {Object} options - Options for displaying the alert.\n * @param {string} options.message - The alert message.\n * @param {?string} options.title - The alert title (optional).\n * @param {(\"primary\"|\"success\"|\"warning\"|\"error\")} [options.type=\"error\"] - The alert type (optional, default: \"error\").\n * @returns {void}\n */\n const showAlert = ({ message, title = null, type = \"error\" }) => {\n setContent({\n title,\n message,\n type,\n });\n if (message !== \"\") {\n setIsOpen(true);\n } else {\n setIsOpen(false);\n }\n };\n\n useEffect(() => {\n if (isOpen) {\n setTimeout(() => {\n setIsOpen(false);\n }, 5000);\n }\n }, [isOpen]);\n\n const { errors } = usePage().props;\n\n useEffect(() => {\n if (errors) showAlert({ message: errors });\n }, [errors]);\n\n return (\n \n \n
\n setIsOpen(false)}\n title={content.title}\n variant=\"tonal\"\n />\n
\n \n {children}\n \n );\n};\n\nexport const useAlert = () => {\n const context = React.useContext(AlertContext);\n if (context === undefined) {\n throw new Error(\"useAlert must be used within a AlertProvider\");\n }\n return context;\n};\n","import { ChevronLeftIcon, ChevronRightIcon } from \"@heroicons/react/24/outline\";\nimport { Button } from \"@switchdreams/ui\";\nimport React from \"react\";\n\nconst Pagination = ({ page, setPage, getData, maxPages }) => {\n return (\n
\n {\n if (page > 1) {\n setPage(page - 1);\n getData(page - 1);\n }\n }}\n disabled={page == 1}\n icon={ChevronLeftIcon}\n iconSide=\"left\"\n />\n {\n if (page > 1) {\n setPage(page - 1);\n getData(page - 1);\n }\n }}\n disabled={page == 1}\n icon={ChevronLeftIcon}\n iconSide=\"left\"\n />\n {Array.from({ length: maxPages + 1 }, (_, i) => i).map((i) => {\n if (i == page && i > 0) {\n return
\n );\n};\n\nexport default Pagination;\n","import { Spinner, Text } from \"@switchdreams/ui\";\nimport axios from \"axios\";\nimport React, { useState } from \"react\";\n\nimport AppointmentTable from \"@/components/Table/appointmentTable\";\nimport { useAlert } from \"@/contexts/Alert\";\n\nimport Pagination from \"../Pagination\";\n\nconst AppointmentsHistory = ({ done_appointments, pagy }) => {\n const [tableInfo, setTableInfo] = useState(done_appointments);\n const [loading, setLoading] = useState(false);\n const { showAlert } = useAlert();\n const [page, setPage] = useState(1);\n const maxPages = pagy.pages;\n\n const getHistoryPage = (current_page) => {\n setLoading(true);\n axios\n .get(`/informacoes_consultas.json?page=${current_page}`)\n .then((response) => {\n setTableInfo(response.data.done_appointments);\n })\n .catch((e) => showAlert({ message: e.message }))\n .finally(() => setLoading(false));\n };\n\n return (\n
\n \n Histórico de consultas\n \n {loading ? (\n
\n \n
\n ) : (\n \n )}\n {tableInfo.length > 0 && (\n \n )}\n
\n );\n};\n\nexport default AppointmentsHistory;\n","import { CalendarDaysIcon, ChevronRightIcon } from \"@heroicons/react/24/outline\";\nimport { Avatar, Button, Text } from \"@switchdreams/ui\";\nimport React, { useState } from \"react\";\n\nimport { monthsTranslated } from \"../../../utils\";\nimport AppointmentModal from \"./appointmentDetailsModal\";\n\nconst AppointmentCard = ({ appointments, idx }) => {\n const [open, setOpen] = useState(false);\n const date = new Date(appointments.date);\n return (\n <>\n \n setOpen(true)}\n >\n
\n
\n \n
\n \n {appointments.patient_name}\n \n \n \n {`${date.getDate()} de ${monthsTranslated[date.getMonth() - 1]}, ${date.getFullYear()} às ${date.getHours() < 10 ? \"0\" : \"\"}${date.getHours()}:${date.getMinutes() < 10 ? \"0\" : \"\"}${date.getMinutes()}`}\n \n
\n
\n \n
\n {idx === 0 && (\n \n )}\n \n \n );\n};\n\nexport default AppointmentCard;\n","import {\n ChevronLeftIcon,\n ChevronRightIcon,\n PencilIcon,\n PlusIcon,\n} from \"@heroicons/react/24/outline\";\nimport { Button, Text } from \"@switchdreams/ui\";\nimport React, { useState } from \"react\";\n\nimport AppointmentCard from \"@/components/Cards/AppointmentCard\";\n\nimport { monthsTranslated } from \"../../utils\";\n\nconst NextAppointments = ({\n pending_appointments,\n doctor_availabilities,\n appointments,\n setSidebarOpen,\n}) => {\n const [currentDayIndex, setCurrentDayIndex] = useState(0);\n const [currentDate, setCurrentDate] = useState(new Date());\n\n const handlePreviousDay = () => {\n if (currentDayIndex > 0) {\n setCurrentDayIndex((prevIndex) => Math.max(prevIndex - 1, 0));\n setCurrentDate((currentDate) => {\n const newDate = new Date();\n newDate.setDate(currentDate.getDate() - 1);\n return newDate;\n });\n }\n };\n\n const handleNextDay = () => {\n if (currentDayIndex < 14) {\n setCurrentDayIndex((prevIndex) => prevIndex + 1);\n setCurrentDate((currentDate) => {\n const newDate = new Date();\n newDate.setDate(currentDate.getDate() + 1);\n return newDate;\n });\n }\n };\n\n const getDayHeader = () => {\n if (currentDayIndex == 0) {\n return \"Hoje\";\n } else if (currentDayIndex == 1) {\n return \"Amanhã\";\n } else {\n return `${currentDate.getDate()} de ${monthsTranslated[currentDate.getMonth()]}`;\n }\n };\n\n const getWeekDay = () => {\n const weekDays = [\"sunday\", \"monday\", \"tuesday\", \"wednesday\", \"thursday\", \"friday\", \"saturday\"];\n return weekDays[currentDate.getDay()];\n };\n\n const buildSchedule = (availabilities, day_appointments) => {\n const schedule = [];\n\n // Generate all time slots from 6:00 to 22:00 in 30-minute intervals\n for (let hour = 6; hour <= 22; hour++) {\n for (let minute = 0; minute <= 30; minute += 30) {\n const time = `${hour.toString().padStart(2, \"0\")}:${minute.toString().padStart(2, \"0\")}`;\n schedule.push({ time, status: \"imposible\" });\n }\n }\n\n // Check each availability range against the schedule\n availabilities.forEach((range) => {\n const startTime = convertTimeToNumber(range.start_time);\n const endTime = convertTimeToNumber(range.end_time);\n for (let i = 0; i < schedule.length; i++) {\n const scheduleTime = convertTimeToNumber(schedule[i].time);\n if (scheduleTime >= startTime && scheduleTime < endTime) {\n schedule[i].status = \"open\"; // Mark overlapping time slots as closed\n }\n }\n });\n\n day_appointments.forEach((appointment) => {\n const startTime = convertTimeToNumber(appointment.approximate_start_time);\n for (let i = 0; i < schedule.length; i++) {\n const scheduleTime = convertTimeToNumber(schedule[i].time);\n if (scheduleTime == startTime) {\n schedule[i].status = \"closed\"; // Mark overlapping time slots as imposible\n }\n }\n });\n\n return schedule;\n };\n\n const convertTimeToNumber = (timeString) => {\n // Helper function to convert \"HH:MM\" string to a number representing minutes since 6:00\n const [hours, minutes] = timeString.split(\":\");\n return parseInt(hours, 10) * 60 + parseInt(minutes, 10);\n };\n\n const isSameDay = (date1, date2) => {\n if (!(date1 instanceof Date) || !(date2 instanceof Date)) {\n return false;\n }\n\n return (\n date1.getFullYear() === date2.getFullYear() &&\n date1.getMonth() === date2.getMonth() &&\n date1.getDate() === date2.getDate()\n );\n };\n\n return (\n <>\n
\n setSidebarOpen(true)}\n />\n \n Próximas consultas\n \n {pending_appointments.length === 0 ? (\n
\n \n Nenhuma consulta por aqui\n \n\n \n Infelizmente você não possui consultas marcadas para os próximos dias\n \n
\n ) : (\n
\n {pending_appointments.slice(0, 3).map((appointment, idx) => (\n \n ))}\n {pending_appointments.length > 3 && (\n \n )}\n
\n )}\n
\n
\n
\n \n Horários marcados\n \n 0 ? \"flex\" : \"hidden\"} w-fit rounded-2xl border border-primary-400 bg-primary-500 px-6 py-2 font-poppins text-sm font-medium text-white duration-500 hover:bg-primary-100 max-md:hidden`}\n iconSide=\"right\"\n icon={PencilIcon}\n onClick={() => setSidebarOpen(true)}\n />\n
\n
\n 0 ? \"flex max-md:flex-col-reverse\" : \"hidden\"} justify-between`}\n >\n
\n
\n
\n Agendado\n
\n
\n
\n Disponível\n
\n
\n
\n Indisponível\n
\n
\n
\n \n \n {getDayHeader()}\n \n \n
\n
\n 0 ? \"grid grid-cols-7 gap-3 max-md:grid-cols-5 max-md:gap-2 max-sm:grid-cols-4\" : \"flex h-96 flex-col items-center justify-center gap-8 bg-coolGray-200\"}`}\n >\n {doctor_availabilities.length > 0 ? (\n buildSchedule(\n doctor_availabilities.filter(\n (availability) => availability.day_of_week == getWeekDay(),\n ),\n appointments.filter((appointment) =>\n isSameDay(new Date(appointment.date), currentDate),\n ),\n ).map((time, idx) => (\n \n \n {time.time}\n \n
\n ))\n ) : (\n <>\n \n Crie a sua agenda e adicione seus horários disponíveis\n \n setSidebarOpen(true)}\n />\n \n )}\n
\n
\n
\n \n );\n};\n\nexport default NextAppointments;\n","import { LockClosedIcon } from \"@heroicons/react/24/outline\";\nimport { Link, usePage } from \"@inertiajs/react\";\nimport { Button, Text } from \"@switchdreams/ui\";\nimport React, { useState } from \"react\";\n\nimport Calendar from \"@/components/Calendar\";\nimport TimeSidebar from \"@/components/Sidebar\";\n\nimport AppointmentsHistory from \"../../components/AppointmentsComponents/AppointmentsHistory\";\nimport NextAppointments from \"../../components/AppointmentsComponents/NextAppointments\";\n\nconst Appointments = ({\n doctor_availabilities,\n appointments,\n pending_appointments,\n done_appointments,\n pagy,\n}) => {\n const { currentUser } = usePage().props;\n const [sidebarOpen, setSidebarOpen] = useState(false);\n\n if (currentUser.active_plan) {\n return (\n <>\n \n
\n
\n \n
\n
\n \n
\n \n
\n \n );\n } else {\n return (\n
\n
\n
\n \n
\n
\n \n Agenda bloqueada\n \n\n \n Para liberar o acesso à agenda é necessário adquirir um plano de assinatura na\n plataforma.\n \n
\n \n \n \n
\n
\n );\n }\n};\n\nexport default Appointments;\n","import { useForm } from \"@inertiajs/react\";\nimport {\n Avatar,\n Button,\n CheckBox,\n RadioButton,\n Spinner,\n Text,\n TextField,\n TextFieldMask,\n} from \"@switchdreams/ui\";\nimport axios from \"axios\";\nimport React, { useState } from \"react\";\n\nimport Modal from \"@/components/Modal\";\nimport { cardBrandLogo, formatIntegerCurrency } from \"@/utils\";\nimport { useAlert } from \"~/contexts/Alert\";\n\nconst CreditCardModal = ({ open, setOpen, user, doctor, date, time, cards }) => {\n const { showAlert } = useAlert();\n const [useSavedCard, setUseSavedCard] = useState(false);\n const [cardId, setCardId] = useState(\"\");\n const [loading, setLoading] = useState(false);\n const [saveCard, setSaveCard] = useState(false);\n\n const formatDate = (date) => {\n const dateTime = new Date(date);\n dateTime.setHours(Number(time.split(\":\")[0]));\n dateTime.setMinutes(Number(time.split(\":\")[1]));\n dateTime.setSeconds(0);\n return dateTime;\n };\n\n const { setData, data, post } = useForm({\n doctor_user_id: doctor.id,\n date: formatDate(date),\n clinic_id: doctor.clinic_id,\n price_cents: doctor.value,\n aditional_info: \"\", // aditionalInfo,\n return_url: window.location.href,\n payment_info: {\n creditCard: {\n holderName: \"\",\n number: \"\",\n expiryMonth: \"\",\n expiryYear: \"\",\n ccv: \"\",\n },\n creditCardHolderInfo: {\n name: user.name,\n email: user.email,\n cpfCnpj: user.cpf,\n postalCode: user.address.cep,\n addressNumber: user.address.number || \"0\",\n phone: user.phone,\n },\n },\n });\n\n const cpfCnpjMask = (v) => {\n v = v.replace(/\\D/g, \"\");\n\n if (v.length <= 11) {\n v = v.replace(/(\\d{3})(\\d)/, \"$1.$2\");\n v = v.replace(/(\\d{3})(\\d)/, \"$1.$2\");\n v = v.replace(/(\\d{3})(\\d{1,2})$/, \"$1-$2\");\n } else {\n v = v.replace(/^(\\d{2})(\\d)/, \"$1.$2\");\n v = v.replace(/^(\\d{2})\\.(\\d{3})(\\d)/, \"$1.$2.$3\");\n v = v.replace(/\\.(\\d{3})(\\d)/, \".$1/$2\");\n v = v.replace(/(\\d{4})(\\d)/, \"$1-$2\");\n }\n\n return v;\n };\n\n const cardTokenization = () => {\n axios.post(\"/credit_cards\", data.payment_info).catch((e) => showAlert({ message: e.message }));\n };\n\n const createAppointment = () => {\n setLoading(true);\n post(`/consultas/credit_card`, {\n onError: (e) => showAlert({ message: e.response.data }),\n onFinish: () => setLoading(false),\n });\n };\n\n return (\n \n
\n Finalize sua compra\n
\n
\n
\n
\n \n \n {user.name}\n \n
\n
\n
\n Total:\n {formatIntegerCurrency(doctor.value)}\n
\n
\n
\n
\n {\n setUseSavedCard(false);\n setCardId(\"\");\n setData(\"payment_info\", {\n creditCard: {\n holderName: \"\",\n number: \"\",\n expiryMonth: \"\",\n expiryYear: \"\",\n ccv: \"\",\n },\n creditCardHolderInfo: {\n name: user.name,\n email: user.email,\n cpfCnpj: user.cpf,\n postalCode: user.address.cep,\n addressNumber: user.address.number || \"0\",\n phone: user.phone,\n },\n });\n }}\n >\n \n Novo cartão\n
\n
setUseSavedCard(true)}>\n \n Usar cartão salvo\n
\n
\n {useSavedCard ? (\n
\n {cards.map((card) => {\n return (\n {\n setCardId(card.id);\n setData(\"payment_info\", { cardId: card.id });\n }}\n key={card.id}\n >\n **** **** **** {card.credit_card_number}\n \n
\n );\n })}\n
\n ) : (\n <>\n {\n setData(\"payment_info\", {\n ...data.payment_info,\n creditCard: { ...data.payment_info.creditCard, holderName: e.target.value },\n });\n }}\n />\n {\n if (e.target.value.length <= 18) {\n const cpfCnpj = cpfCnpjMask(e.target.value);\n setData(\"payment_info\", {\n ...data.payment_info,\n creditCardHolderInfo: {\n ...data.payment_info.creditCardHolderInfo,\n cpfCnpj: cpfCnpj,\n },\n });\n } else {\n setData(\"payment_info\", {\n ...data.payment_info,\n creditCardHolderInfo: {\n ...data.payment_info.creditCardHolderInfo,\n cpfCnpj: e.target.value.slice(0, -1),\n },\n });\n }\n }}\n />\n {\n const cardNumber = e.target.value.replace(/\\s/g, \"\");\n setData(\"payment_info\", {\n ...data.payment_info,\n creditCard: { ...data.payment_info.creditCard, number: cardNumber },\n });\n }}\n />\n
\n {\n const expiryMonth = e.target.value.split(\"/\")[0];\n const expiryYear = e.target.value.split(\"/\")[1];\n setData(\"payment_info\", {\n ...data.payment_info,\n creditCard: {\n ...data.payment_info.creditCard,\n expiryMonth: expiryMonth,\n expiryYear: expiryYear,\n },\n });\n }}\n />\n {\n setData(\"payment_info\", {\n ...data.payment_info,\n creditCard: { ...data.payment_info.creditCard, ccv: e.target.value },\n });\n }}\n />\n
\n
\n {\n setSaveCard(!saveCard);\n }}\n />\n Salvar cartão para uso futuro?\n
\n \n )}\n \n \n
\n {\n setOpen(false);\n }}\n />\n {\n if (saveCard) {\n cardTokenization();\n }\n createAppointment();\n }}\n disabled={loading}\n />\n
\n {loading && (\n
\n \n
\n )}\n
\n );\n};\n\nexport default CreditCardModal;\n","import { useForm } from \"@inertiajs/react\";\nimport { Text } from \"@switchdreams/ui\";\nimport React from \"react\";\n\nimport Modal from \"@/components/Modal\";\nimport { useAlert } from \"@/contexts/Alert\";\nimport { imagePath } from \"@/utils\";\n\nconst PixModal = ({ setOpen, open, date, time, doctor }) => {\n const { showAlert } = useAlert();\n\n const formatDate = (date) => {\n const dateTime = new Date(date);\n dateTime.setHours(Number(time.split(\":\")[0]));\n dateTime.setMinutes(Number(time.split(\":\")[1]));\n dateTime.setSeconds(0);\n return dateTime;\n };\n\n const { post } = useForm({\n doctor_user_id: doctor.id,\n date: formatDate(date),\n clinic_id: doctor.clinic_id,\n price_cents: doctor.value,\n aditional_info: \"\", // aditionalInfo,\n });\n\n const createPixTransaction = () => {\n post(\"/consultas/pix\", {\n onError: (e) => {\n showAlert({ message: e.response.data });\n },\n });\n };\n\n return (\n setOpen(false)}\n onClickConfirm={() => {\n createPixTransaction();\n setOpen(false);\n }}\n >\n
\n
\n \n
\n \n Deseja pagar com Pix?\n \n \n Você será redirecionado à tela de pagamento.\n \n
\n \n );\n};\n\nexport default PixModal;\n","export const appointmentsData = [\n {\n name: \"Ana Luiza\",\n date: \"21 de Abril, 2024 às 18:00\",\n value: \"120,00\",\n image: \"\",\n age: 21,\n gender: \"Mulher\",\n location: \"Consultório José Montenegro\",\n logo: \"\",\n aditionalInfo:\n \"Morem ipsum dolor sit amet, consectetur adipiscing elit. Nunc vulputate libero et velit interdum, ac aliquet odio mattis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Curabitur tempus urna at turpis condimentum \",\n },\n {\n name: \"Luiz Antônio\",\n date: \"21 de Abril, 2024 às 19:00\",\n value: \"120,00\",\n image: \"\",\n age: 23,\n gender: \"Homem\",\n location: \"Consultório José Montenegro\",\n logo: \"\",\n aditionalInfo:\n \"Morem ipsum dolor sit amet, consectetur adipiscing elit. Nunc vulputate libero et velit interdum, ac aliquet odio mattis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Curabitur tempus urna at turpis condimentum \",\n },\n {\n name: \"João Azevedo\",\n date: \"21 de Abril, 2024 às 20:00\",\n value: \"120,00\",\n image: \"\",\n age: 35,\n gender: \"Homem\",\n location: \"Consultório José Montenegro\",\n logo: \"\",\n aditionalInfo:\n \"Morem ipsum dolor sit amet, consectetur adipiscing elit. Nunc vulputate libero et velit interdum, ac aliquet odio mattis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Curabitur tempus urna at turpis condimentum \",\n },\n];\n\nexport const info = [\n {\n patient: \"João Gui\",\n date: \"16/02/2024\",\n hour: \"16:00\",\n status: \"Finalizado\",\n image: \"\",\n },\n {\n patient: \"Júlia Santos\",\n date: \"16/02/2024\",\n hour: \"16:00\",\n status: \"Finalizado\",\n image: \"\",\n },\n {\n patient: \"Jacinto\",\n date: \"16/02/2024\",\n hour: \"16:00\",\n status: \"Finalizado\",\n image: \"\",\n },\n {\n patient: \"Gabriel Silva\",\n date: \"16/02/2024\",\n hour: \"16:00\",\n status: \"Finalizado\",\n image: \"\",\n },\n {\n patient: \"Tierri jamilton\",\n date: \"16/02/2024\",\n hour: \"16:00\",\n status: \"Finalizado\",\n image: \"\",\n },\n {\n patient: \"Tierri jamilton\",\n date: \"16/02/2024\",\n hour: \"16:00\",\n status: \"Finalizado\",\n image: \"\",\n },\n {\n patient: \"Tierri jamilton\",\n date: \"16/02/2024\",\n hour: \"16:00\",\n status: \"Finalizado\",\n image: \"\",\n },\n];\n","import {\n BanknotesIcon,\n CalendarDaysIcon,\n ClockIcon,\n CreditCardIcon,\n LockClosedIcon,\n MapPinIcon,\n} from \"@heroicons/react/24/outline\";\nimport { ChevronRightIcon } from \"@heroicons/react/24/solid\";\nimport { usePage } from \"@inertiajs/react\";\nimport { Avatar, Text } from \"@switchdreams/ui\";\nimport React, { useState } from \"react\";\n\nimport { imagePath } from \"@/utils\";\n\nimport { formatIntegerCurrency, monthsTranslated } from \"../../utils\";\nimport CreditCardModal from \"./Modals/creditCardModal\";\nimport PixModal from \"./Modals/pixModal\";\n\nconst Payments = ({ date, time, doctor, cards }) => {\n const { currentUser } = usePage().props;\n const dateFormated = () => {\n const dateObj = new Date(date);\n return `${dateObj.getDate()} de ${monthsTranslated[dateObj.getMonth()]} de ${dateObj.getFullYear()}`;\n };\n const [openPix, setOpenPix] = useState(false);\n const [openCard, setOpenCard] = useState(false);\n\n return (\n <>\n \n \n
\n
\n
\n \n Método de pagamento\n \n
\n
\n setOpenPix(true)}\n >\n
\n \n Pix\n
\n \n
\n {/*
\n
\n \n Boleto\n
\n \n
*/}\n setOpenCard(true)}\n >\n
\n \n \n Cartão de crédito\n \n
\n \n
\n
\n \n \n Sua transação está protegida com criptografia de ponta.\n \n
\n
\n \n
\n
\n \n
\n
\n \n {doctor.name}\n \n {doctor.verified && \"icone}\n
\n \n {doctor.specialty}\n \n
\n
\n
\n \n
\n \n {dateFormated()}\n \n Data\n
\n
\n
\n \n
\n \n {time}\n \n Horário\n
\n
\n
\n \n
\n \n {doctor.clinic_name}\n \n \n {doctor.clinic_address}\n \n
\n
\n
\n \n
\n \n {formatIntegerCurrency(doctor.value)}\n \n Valor\n
\n
\n \n Você tem o prazo de 48 horas antes da sua consulta para realizar o reagendamento.\n \n
\n \n \n );\n};\n\nexport default Payments;\n","import {\n BanknotesIcon,\n BookmarkIcon,\n CalendarDaysIcon,\n CheckCircleIcon,\n CheckIcon,\n ClockIcon,\n MagnifyingGlassIcon,\n MapPinIcon,\n XCircleIcon,\n XMarkIcon,\n} from \"@heroicons/react/24/outline\";\nimport { Link } from \"@inertiajs/react\";\nimport { Avatar, Badge, Button, Text } from \"@switchdreams/ui\";\n\nimport { extractTime, formatIntegerCurrency, imagePath, monthsTranslated } from \"@/utils\";\n\nconst Payment = ({ appointment, qr_code, doctor }) => {\n const dateFormated = () => {\n const dateObj = new Date(appointment.date);\n return `${dateObj.getDate()} de ${monthsTranslated[dateObj.getMonth()]} de ${dateObj.getFullYear()}`;\n };\n\n const paymentInfo = (payment_status) => {\n if (payment_status === \"pending\") {\n return (\n <>\n
\n
\n \n Valor da consulta\n \n \n {formatIntegerCurrency(appointment.price_cents)}\n \n
\n {qr_code && appointment.payment_method == \"pix\" && (\n \n )}\n
\n
\n \n {appointment.payment_method == \"pix\" ? (\n <>\n \n Escaneie o QR Code ou copie o código PIX\n \n \n Você pode utilizar a câmera do seu celular para ler o QR Code ou copiar o código e\n pagar no aplicativo de seu banco:{\" \"}\n \n navigator.clipboard.writeText(qr_code.payload)}\n />\n \n ) : (\n <>\n \n O pagamento está sendo processado pelo seu cartão de crédito\n \n \n Em caso de dúvida, procure nosso suporte.\n \n \n )}\n
\n \n );\n } else if (payment_status === \"paid\") {\n return (\n <>\n
\n
\n \n Valor da consulta\n \n \n {formatIntegerCurrency(appointment.price_cents)}\n \n
\n \n
\n
\n \n \n Pagamento Aprovado!\n \n \n Esta consulta já foi paga, acesse suas consultas para ver mais detalhes\n \n \n \n \n \n Método de pagamento:{\" \"}\n {appointment.payment_method == \"pix\" ? \"PIX\" : \"Cartão de crédito\"}\n \n
\n \n );\n } else if (payment_status === \"payment_cancelled\") {\n return (\n <>\n
\n
\n \n Valor da consulta\n \n \n {formatIntegerCurrency(appointment.price_cents)}\n \n
\n \n
\n
\n \n \n Pagamento Expirado!\n \n \n Este pagamento expirou, tente agendar a consulta novamente\n \n \n \n \n
\n \n );\n }\n };\n\n return (\n <>\n
\n
\n {paymentInfo(appointment.payment_status)}\n
\n
\n
\n \n
\n
\n \n {doctor.name}\n \n {doctor.verified && \"icone}\n
\n \n {doctor.specialty}\n \n
\n
\n
\n \n
\n \n {dateFormated()}\n \n Data\n
\n
\n
\n \n
\n \n {extractTime(new Date(appointment.date))}\n \n Horário\n
\n
\n
\n \n
\n \n {doctor.clinic_name}\n \n \n {doctor.clinic_address}\n \n
\n
\n
\n \n
\n \n {formatIntegerCurrency(appointment.price_cents)}\n \n Valor\n
\n
\n \n Você tem o prazo de 48 horas antes da sua consulta para realizar o reagendamento.\n \n
\n
\n \n );\n};\n\nexport default Payment;\n","import {\n CalendarDaysIcon,\n FaceSmileIcon,\n HeartIcon,\n StarIcon,\n // StarIcon,\n} from \"@heroicons/react/24/outline\";\nimport { router, usePage } from \"@inertiajs/react\";\nimport { Avatar, Text } from \"@switchdreams/ui\";\nimport React, { useState } from \"react\";\nimport { ErrorBoundary } from \"react-error-boundary\";\n\nimport Modal from \"@/components/Modal\";\nimport { useAlert } from \"@/contexts/Alert\";\nimport { extractTime, imagePath, monthsTranslated, weekDaysTranslated } from \"@/utils\";\n\nconst ExamCard = ({ doctorInfo, selected, onClick, onClickReviews, onClickImages }) => {\n console.log('DADOS DOUTOS', doctorInfo)\n const { currentUser } = usePage().props;\n const { showAlert } = useAlert();\n const [open, setOpen] = useState(false);\n const [selectedDate, setSelectedDate] = useState(null);\n const [selectedTime, setSelectedTime] = useState(\"\");\n const [currentDay, setCurrentDay] = useState(new Date());\n const today = new Date();\n const tomorrow = new Date(today);\n const [openReviews, setOpenReviews] = useState(true);\n tomorrow.setDate(tomorrow.getDate() + 1);\n\n const loadMoreRight = () => {\n const newDay = new Date(currentDay);\n newDay.setDate(newDay.getDate() + 3);\n setCurrentDay(newDay);\n };\n\n const loadMoreLeft = () => {\n const newDay = new Date(currentDay);\n newDay.setDate(newDay.getDate() - 3);\n setCurrentDay(newDay);\n };\n\n const HOUR_LIMIT_TO_SCHEDULE = 2;\n\n // How to returns the next 6 days based on currentDay state\n const calcNextSixDays = () => {\n const nextSixDays = [];\n for (let i = 0; i < 6; i++) {\n const newDay = new Date(currentDay);\n newDay.setDate(newDay.getDate() + i);\n nextSixDays.push(newDay);\n }\n return nextSixDays;\n };\n\n const nextSixDays = calcNextSixDays();\n\n const getWeekDay = (currentDate) => {\n const weekDays = [\"sunday\", \"monday\", \"tuesday\", \"wednesday\", \"thursday\", \"friday\", \"saturday\"];\n return weekDays[currentDate.getDay()];\n };\n\n const buildSchedule = (availabilities, day_appointments, date) => {\n const schedule = [];\n\n const isToday = isSameDay(date, new Date());\n const todayLimitTime =\n convertTimeToNumber(extractTime(new Date())) + 60 * HOUR_LIMIT_TO_SCHEDULE;\n\n // Generate all time slots from 6:00 to 22:00 in 30-minute intervals\n for (let hour = 6; hour <= 22; hour++) {\n for (let minute = 0; minute <= 30; minute += 30) {\n const time = `${hour.toString().padStart(2, \"0\")}:${minute.toString().padStart(2, \"0\")}`;\n schedule.push({ time, status: \"unavailable\" });\n }\n }\n\n // Check each availability range against the schedule\n availabilities.forEach((range) => {\n // if(isToday) {\n // const startTime = convertTimeToNumber(range.start_time);\n // } else {\n // }\n const availabilityStartTime = convertTimeToNumber(range.start_time);\n const availabilityEndTime = convertTimeToNumber(range.end_time);\n schedule.forEach((availability) => {\n const scheduleTime = convertTimeToNumber(availability.time);\n if (scheduleTime >= availabilityStartTime && scheduleTime < availabilityEndTime) {\n // Do not include past times if for today's availabilities\n if (!(isToday && todayLimitTime >= scheduleTime)) {\n availability.status = \"available\";\n }\n }\n });\n });\n\n day_appointments.forEach((appointment) => {\n const startTime = convertTimeToNumber(appointment.approximate_start_time);\n for (let i = 0; i < schedule.length; i++) {\n const scheduleTime = convertTimeToNumber(schedule[i].time);\n if (scheduleTime == startTime) {\n schedule[i].status = \"scheduled\"; // Mark overlapping time slots as scheduled\n }\n }\n });\n\n return schedule;\n };\n\n const convertTimeToNumber = (timeString) => {\n // Helper function to convert \"HH:MM\" string to a number representing minutes since 6:00\n const [hours, minutes] = timeString.split(\":\");\n return parseInt(hours, 10) * 60 + parseInt(minutes, 10);\n };\n\n const isSameDay = (date1, date2) => {\n if (!(date1 instanceof Date) || !(date2 instanceof Date)) {\n return false;\n }\n\n return (\n date1.getFullYear() === date2.getFullYear() &&\n date1.getMonth() === date2.getMonth() &&\n date1.getDate() === date2.getDate()\n );\n };\n\n const getDayHeader = (idx, day) => {\n if (isSameDay(day, today)) {\n return \"Hoje\";\n } else if (isSameDay(day, tomorrow)) {\n return \"Amanhã\";\n } else {\n return weekDaysTranslated[day.getDay()];\n }\n };\n\n const changeSelect = () => {\n usePage().props.handleSelect(\"alou\");\n };\n\n return (\n Aconteceu algum problema para exibir o profissional...}>\n {selectedDate && (\n \n router.get(\"/consultas/new\", {\n date: selectedDate,\n time: selectedTime,\n doctor_id: doctorInfo.id,\n })\n }\n onClickCancel={() => setOpen(false)}\n >\n
\n
\n \n
\n \n Agendar consulta para o dia{\" \"}\n \n {selectedDate.getDate()} de {monthsTranslated[selectedDate.getMonth()]}\n {\" \"}\n às{\" \"}\n \n {selectedTime}\n \n ?\n \n \n Você será direcionado para etapa de checkout.\n \n
\n \n )}\n
\n
\n
\n \n \n
\n
\n \n {doctorInfo.name}\n \n {doctorInfo.verified && (\n \"icone\n )}\n
\n \n {doctorInfo.description}\n \n \n Ver mais fotos\n \n
\n
\n
\n
\n
\n \n \n {doctorInfo.months_registered} meses\n \n no via consultas\n
\n
\n \n \n {doctorInfo.patients_treated} pacientes\n \n atendidos\n
\n \n \n \n {doctorInfo.reviews.length}\n \n Avaliações\n
\n
\n
\n \n {doctorInfo.doctor_description}\n \n
\n {/* \n {formatIntegerCurrency(doctorInfo.value)}\n */}\n\n {/* \n Ver Fotos\n */}\n
\n
\n \n \n
\n
\n\n
\n
\n \n {doctorInfo.address.neighborhood}{\" \"}\n {/* {doctorInfo.address.street},{\" \"}\n {doctorInfo.address.number}, {doctorInfo.address.city} - {doctorInfo.address.state}{\" \"}\n - {doctorInfo.address.cep} */}\n \n
\n
\n \n \n
\n );\n};\n\nexport default ExamCard;\n","export const stateOptions = [\n { label: \"Todos\", value: \"\" },\n { label: \"Acre\", value: \"AC\" },\n { label: \"Alagoas\", value: \"AL\" },\n { label: \"Amapá\", value: \"AP\" },\n { label: \"Amazonas\", value: \"AM\" },\n { label: \"Bahia\", value: \"BA\" },\n { label: \"Ceará\", value: \"CE\" },\n { label: \"Distrito Federal\", value: \"DF\" },\n { label: \"Espírito Santo\", value: \"ES\" },\n { label: \"Goiás\", value: \"GO\" },\n { label: \"Maranhão\", value: \"MA\" },\n { label: \"Mato Grosso\", value: \"MT\" },\n { label: \"Mato Grosso do Sul\", value: \"MS\" },\n { label: \"Minas Gerais\", value: \"MG\" },\n { label: \"Pará\", value: \"PA\" },\n { label: \"Paraíba\", value: \"PB\" },\n { label: \"Paraná\", value: \"PR\" },\n { label: \"Pernambuco\", value: \"PE\" },\n { label: \"Piauí\", value: \"PI\" },\n { label: \"Rio de Janeiro\", value: \"RJ\" },\n { label: \"Rio Grande do Norte\", value: \"RN\" },\n { label: \"Rio Grande do Sul\", value: \"RS\" },\n { label: \"Rondônia\", value: \"RO\" },\n { label: \"Roraima\", value: \"RR\" },\n { label: \"Santa Catarina\", value: \"SC\" },\n { label: \"São Paulo\", value: \"SP\" },\n { label: \"Sergipe\", value: \"SE\" },\n { label: \"Tocantins\", value: \"TO\" },\n];\n\nexport const genderOptions = [\n {\n value: \"male\",\n label: \"Masculino\",\n },\n {\n value: \"female\",\n label: \"Feminino\",\n },\n];\n\nexport const workOptions = [\n {\n value: \"médico\",\n label: \"Médico\",\n },\n {\n value: \"dentista\",\n label: \"Dentista/Odontólogo\",\n },\n {\n value: \"fisioterapeuta\",\n label: \"Fisioterapeuta\",\n },\n {\n value: \"psicólogo\",\n label: \"Psicólogo\",\n },\n {\n value: \"nutricionista\",\n label: \"Nutricionista\",\n },\n {\n value: \"farmacêutico\",\n label: \"Farmacêutico\",\n },\n {\n value: \"biomédico\",\n label: \"Biomédico\",\n },\n {\n value: \"fonoaudiólogo\",\n label: \"Fonoaudiólogo\",\n },\n];\n","import { Link } from \"@inertiajs/react\";\nimport React from \"react\";\n\nconst SelectedClinicsCard = ({ quantity }) => {\n return (\n <>\n \n

{quantity == 0 ? 'Nenhuma' : quantity} Clínica{quantity == 0 ? '' : 's'} Selecionada{quantity == 0 ? '' : 's'} para o orçamento

\n

\n Escolha até 3 clínicas que você deseja enviar seus exames\n para receber um orçamento \n

\n \n \n \n );\n};\n\nexport default SelectedClinicsCard;\n","import { FunnelIcon } from \"@heroicons/react/24/outline\";\nimport { ChevronDownIcon, MagnifyingGlassIcon, MapPinIcon } from \"@heroicons/react/24/solid\";\nimport { Button, Popover, Select, Spinner, Text } from \"@switchdreams/ui\";\nimport axios from \"axios\";\nimport React, { useEffect, useReducer, useRef, useState } from \"react\";\n\nimport ExamCard from \"@/components/Cards/ExamCard\";\nimport { stateOptions } from \"@/constants/SelectOptions\";\nimport { imagePath, specialtyOptions, workAreaOptionsFetch } from \"@/utils\";\nimport SelectedClinicsCard from \"../../components/Cards/SelectedClinicsCard\";\nimport { useAlert } from \"@/contexts/Alert\";\n\nconst ExamsSearch = ({ initial_professionals, pagy }) => {\n const sortOptions = [\n { label: \"Alfabética\", value: \"alphabetical\" },\n { label: \"Número de pacientes atendido\", value: \"patients_count\" },\n { label: \"Tempo no site\", value: \"created_at\" },\n ];\n\n // Params from url\n const workSpecialtyIdFromUrl = parseInt(\n new URLSearchParams(window.location.search).get(\"work_specialty\"),\n );\n const workAreaIdFromUrl = parseInt(new URLSearchParams(window.location.search).get(\"work_area\"));\n\n const [professionals, setProfessionals] = useState(initial_professionals);\n const [sort, setSort] = useState(sortOptions[0]);\n const [countSelected, setCountSelected] = useState(0);\n const [workArea, setWorkArea] = useState(\"\");\n const [specialty, setSpecialty] = useState(null);\n const [state, setState] = useState(null);\n const [isLoading, setIsLoading] = useState(false);\n const [workAreaOptions, setWorkAreaOptions] = useState([]);\n const [specialtiesOptions, setSpecialtiesOptions] = useState([]);\n const { showAlert } = useAlert();\n\n // Pagination\n const [page, setPage] = useState(0);\n const [maxPages, setMaxPages] = useState(pagy.pages);\n const [count, setCount] = useState(pagy.count);\n const [firstLoad, setFirstLoad] = useState(true);\n\n const elementRef = useRef(null);\n\n function onIntersection(entries) {\n const firstEntry = entries[0];\n if (firstEntry.isIntersecting && page <= maxPages) {\n getData(\"add\");\n }\n }\n\n useEffect(() => {\n const observer = new IntersectionObserver(onIntersection);\n if (observer && elementRef.current) {\n observer.observe(elementRef.current);\n }\n\n return () => {\n if (observer) {\n observer.disconnect();\n }\n };\n }, []);\n\n\n const handleSelect = (data) => {\n console.log(data)\n }\n\n\n const getData = (action) => {\n setIsLoading(true);\n let workSpecialityParams;\n if (specialty?.label == \"Todos\") {\n workSpecialityParams = \"\";\n } else {\n workSpecialityParams = specialty?.value || workSpecialtyIdFromUrl || \"\";\n }\n axios\n .get(`/profissionais.json`, {\n params: {\n sort: sort.value,\n page: action == \"add\" ? page + 1 : 1,\n state: state?.value || \"\",\n work_specialty: workSpecialityParams,\n work_area_id: workArea?.value || workAreaIdFromUrl || \"\",\n },\n })\n .then((response) => {\n setMaxPages(response.data.pagy.pages);\n setCount(response.data.pagy.count);\n if (action == \"add\") {\n setProfessionals(professionals.concat(response.data.professionals));\n setPage(page + 1);\n } else if (action == \"substitute\") {\n setProfessionals(response.data.professionals);\n setPage(1);\n }\n })\n .finally(() => setIsLoading(false));\n };\n\n useEffect(() => {\n getData(\"substitute\");\n }, [sort]);\n const [, forceUpdate] = useReducer(x => x + 1, 0);\n\n const selectClinic = (idx) => {\n let allData = professionals;\n allData[idx].selected = !allData[idx].selected;\n \n \n if(allData[idx].selected == true){ \n if(countSelected < 3){\n setCountSelected(countSelected + 1)\n setProfessionals(allData); \n }else{\n allData[idx].selected = !allData[idx].selected;\n showAlert({\n message: \"Você pode selecionar no máximo três clínicas!\",\n type: \"warning\",\n });\n }\n }else{\n setCountSelected(countSelected - 1)\n setProfessionals(allData);\n }\n\n forceUpdate();\n }\n\n\n\n useEffect(() => {\n // TODO: PERFOMANCE Improves to make only one fetch\n // Set select inputs\n workAreaOptionsFetch(setWorkAreaOptions);\n specialtyOptions(setSpecialtiesOptions);\n // Set state\n const state = stateOptions.find(\n (option) => option.value == new URLSearchParams(window.location.search).get(\"state\"),\n );\n setState(state);\n }, []);\n\n // Set work area from URL\n useEffect(() => {\n if (workAreaOptions) {\n const workArea = workAreaOptions.find((option) => option.value == workAreaIdFromUrl);\n if (workArea) {\n setWorkArea(workArea);\n }\n }\n }, [workAreaOptions]);\n\n // Set specialty from URL\n useEffect(() => {\n if (specialtiesOptions) {\n const specialty = specialtiesOptions.find((option) => option.value == workSpecialtyIdFromUrl);\n if (specialty) {\n setSpecialty(specialty);\n }\n }\n }, [specialtiesOptions]);\n\n useEffect(() => {\n if (workArea === \"\") {\n return;\n }\n // find workArea selected\n const selectedWorkArea = workAreaOptions.find((option) => option.value === workArea.value);\n const specialties =\n selectedWorkArea?.work_specialities?.map((specialty) => {\n return {\n value: specialty.id,\n label: specialty.name,\n };\n }) || [];\n setSpecialtiesOptions(specialties);\n }, [workArea]);\n\n useEffect(() => {\n if (firstLoad) {\n setPage(1);\n setFirstLoad(false);\n }\n }, [specialty, sort, state]);\n\n \n \n return (\n <>\n
\n
\n
\n \n Exames de qualidade com as melhores clínicas da sua região!\n \n
\n
\n
\n setWorkArea(e)}\n />\n
\n
\n setSpecialty(e)}\n />\n
\n
\n
\n setState(e)}\n />\n
\n
\n getData(\"substitute\")}\n />\n
\n
\n \n
\n
\n
\n
\n
\n
\n
\n
\n \n Encontramos\n \n \n {count} Clínicas\n \n
\n
\n \n Ordenar por:\n \n \n \n {sort.label}\n \n \n
\n }\n >\n
\n {sortOptions.map((option, key) => {\n return (\n
\n
\n );\n })}\n
\n \n
\n
\n
\n {isLoading ? (\n \n ) : (\n professionals.map((info, idx) => {\n return selectClinic(idx)} selected={info.selected} />;\n })\n )}\n {page < maxPages && (\n
\n \n
\n )}\n
\n \n {/*
\n \n
*/}\n
\n \n Encontre a especialidade que você precisa!\n \n
\n {specialtiesOptions.map((Option, idx) => {\n return (\n {\n window.scroll({ top: 0, behavior: \"smooth\" });\n setSpecialty(Option.value);\n }}\n >\n \n {Option.label}\n \n
\n );\n })}\n
\n
\n
\n
\n \n );\n};\n\nexport default ExamsSearch;\n","import { Link, router } from \"@inertiajs/react\";\nimport React, { useRef, useState } from \"react\";\n\nimport { useAlert } from \"@/contexts/Alert\";\n\nconst List = ({ data, pagy }) => {\n const sortOptions = [\n { label: \"Alfabética\", value: \"alphabetical\" },\n { label: \"Número de pacientes atendido\", value: \"patients_count\" },\n { label: \"Tempo no site\", value: \"created_at\" },\n ];\n\n\n const { showAlert } = useAlert();\n const [open, setOpen] = useState(false);\n\n const elementRef = useRef(null);\n \n\n const openModal = () => {\n setOpen(true);\n }\n\n const redirectExams = () => {\n router.visit('/orcamento/1')\n }\n\n const selectClinic = (item) => {\n setOpen(true)\n }\n\n const formatDate = (date) => {\n const dateTime = new Date(date);\n return dateTime.toLocaleString();\n };\n\n return (\n <> \n
\n
\n
\n
Meus Exames
\n

\n Lista da lista de orçamentos de exames realizados\n

\n
\n {data.map((item, i) => (\n
\n
#{item.id}
\n
Data pedido:
{formatDate(item.sent_at)}
\n
Respostas Recebidas: {item.total_received}/{item.total_sent}
\n
\n \n \n \n
\n
\n ))}\n
\n
\n \n );\n};\n\nexport default List;\n","import { router, useForm, usePage } from \"@inertiajs/react\";\nimport {\n Avatar,\n Button,\n CheckBox,\n RadioButton,\n Spinner,\n Text,\n TextField,\n TextFieldMask,\n} from \"@switchdreams/ui\";\nimport axios from \"axios\";\nimport React, { useState } from \"react\";\n\nimport Modal from \"@/components/Modal\";\nimport { cardBrandLogo, formatIntegerCurrency } from \"@/utils\";\nimport { useAlert } from \"~/contexts/Alert\";\n\nconst CreditCardModal = ({ open, setOpen, dataClinic, cards }) => {\n const { showAlert } = useAlert();\n const [useSavedCard, setUseSavedCard] = useState(false);\n const [cardId, setCardId] = useState(\"\");\n const [loading, setLoading] = useState(false);\n const [saveCard, setSaveCard] = useState(false);\n\n const { currentUser } = usePage().props;\n\n const formatDate = (date) => {\n const dateTime = new Date(date);\n dateTime.setHours(Number(time.split(\":\")[0]));\n dateTime.setMinutes(Number(time.split(\":\")[1]));\n dateTime.setSeconds(0);\n return dateTime;\n };\n\n const { setData, data, post } = useForm({\n // doctor_user_id: doctor.id,\n // date: formatDate(date),\n // clinic_id: doctor.clinic_id,\n // price_cents: doctor.value,\n // aditional_info: \"\", // aditionalInfo,\n // return_url: window.location.href,\n payment_info: {\n credit_card: {\n holder_name: \"\",\n number: \"\",\n expiry_month: \"\",\n expiry_year: \"\",\n ccv: \"\",\n },\n credit_card_holder_info: {\n name: currentUser.name,\n email: currentUser.email,\n cpf_cnpj: currentUser.cpf,\n postal_code: currentUser.address.cep,\n address_number: currentUser.address.number || \"0\",\n phone: currentUser.phone,\n },\n },\n budget_id: dataClinic.budget_id,\n budget_item_id: dataClinic.id,\n });\n\n const cpfCnpjMask = (v) => {\n if(!v) return;\n v = v.replace(/\\D/g, \"\");\n\n if (v.length <= 11) {\n v = v.replace(/(\\d{3})(\\d)/, \"$1.$2\");\n v = v.replace(/(\\d{3})(\\d)/, \"$1.$2\");\n v = v.replace(/(\\d{3})(\\d{1,2})$/, \"$1-$2\");\n } else {\n v = v.replace(/^(\\d{2})(\\d)/, \"$1.$2\");\n v = v.replace(/^(\\d{2})\\.(\\d{3})(\\d)/, \"$1.$2.$3\");\n v = v.replace(/\\.(\\d{3})(\\d)/, \".$1/$2\");\n v = v.replace(/(\\d{4})(\\d)/, \"$1-$2\");\n }\n\n return v;\n };\n\n const cardTokenization = () => {\n axios.post(\"/credit_cards\", data.payment_info).catch((e) => showAlert({ message: e.message }));\n };\n\n const payBudget = () => {\n // setLoading(true);\n router.post(\n `/exams/budgets/${dataClinic.budget_id}/items/${dataClinic.id}/payments/pay_credit_card`,\n data,\n );\n // post(`/consultas/credit_card`, {\n // onError: (e) => showAlert({ message: e.response.data }),\n // onFinish: () => setLoading(false),\n // });\n };\n\n return (\n \n
\n Finalize sua compra\n
\n
\n
\n
\n \n \n {currentUser.name}\n \n
\n
\n
\n Total:\n {dataClinic.formatted_amount}\n
\n
\n
\n
\n {\n setUseSavedCard(false);\n setCardId(\"\");\n setData(\"payment_info\", {\n credit_card: {\n holder_name: \"\",\n number: \"\",\n expiry_month: \"\",\n expiry_year: \"\",\n ccv: \"\",\n },\n credit_card_holder_info: {\n name: currentUser.name,\n email: currentUser.email,\n cpfCnpj: currentUser.cpf,\n postal_code: currentUser.address.cep,\n address_number: currentUser.address.number || \"0\",\n phone: currentUser.phone,\n },\n });\n }}\n >\n \n Novo cartão\n
\n
setUseSavedCard(true)}>\n \n Usar cartão salvo\n
\n
\n {useSavedCard ? (\n
\n {cards.map((card) => {\n return (\n {\n setCardId(card.id);\n setData(\"payment_info\", { cardId: card.id });\n }}\n key={card.id}\n >\n **** **** **** {card.credit_card_number}\n \n
\n );\n })}\n
\n ) : (\n <>\n {\n setData(\"payment_info\", {\n ...data.payment_info,\n credit_card: { ...data.payment_info.credit_card, holder_name: e.target.value },\n });\n }}\n />\n {\n if (e.target.value.length <= 18) {\n const cpfCnpj = cpfCnpjMask(e.target.value);\n setData(\"payment_info\", {\n ...data.payment_info,\n credit_card_holder_info: {\n ...data.payment_info.credit_card_holder_info,\n cpf_cnpj: cpfCnpj,\n },\n });\n } else {\n setData(\"payment_info\", {\n ...data.payment_info,\n credit_card_holder_info: {\n ...data.payment_info.credit_card_holder_info,\n cpf_cnpj: e.target.value.slice(0, -1),\n },\n });\n }\n }}\n />\n {\n const cardNumber = e.target.value.replace(/\\s/g, \"\");\n setData(\"payment_info\", {\n ...data.payment_info,\n credit_card: { ...data.payment_info.credit_card, number: cardNumber },\n });\n }}\n />\n
\n {\n const expiryMonth = e.target.value.split(\"/\")[0];\n const expiryYear = e.target.value.split(\"/\")[1];\n setData(\"payment_info\", {\n ...data.payment_info,\n credit_card: {\n ...data.payment_info.credit_card,\n expiry_month: expiryMonth,\n expiry_year: expiryYear,\n },\n });\n }}\n />\n {\n setData(\"payment_info\", {\n ...data.payment_info,\n credit_card: { ...data.payment_info.credit_card, ccv: e.target.value },\n });\n }}\n />\n
\n
\n {/* {\n setSaveCard(!saveCard);\n }}\n /> */}\n {/* Salvar cartão para uso futuro? */}\n
\n \n )}\n
\n \n
\n {\n setOpen(false);\n }}\n />\n {\n if (saveCard) {\n cardTokenization();\n }\n payBudget();\n }}\n disabled={loading}\n />\n
\n {loading && (\n
\n \n
\n )}\n \n );\n};\n\nexport default CreditCardModal;\n","import { useForm } from \"@inertiajs/react\";\nimport { Text } from \"@switchdreams/ui\";\nimport React from \"react\";\n\nimport Modal from \"@/components/Modal\";\nimport { useAlert } from \"@/contexts/Alert\";\nimport { imagePath } from \"@/utils\";\n\nconst PixModal = ({ setOpen, open, date, time, doctor }) => {\n const { showAlert } = useAlert();\n\n const formatDate = (date) => {\n const dateTime = new Date(date);\n dateTime.setHours(Number(time.split(\":\")[0]));\n dateTime.setMinutes(Number(time.split(\":\")[1]));\n dateTime.setSeconds(0);\n return dateTime;\n };\n\n const { post } = useForm({\n doctor_user_id: doctor.id,\n date: formatDate(date),\n clinic_id: doctor.clinic_id,\n price_cents: doctor.value,\n aditional_info: \"\", // aditionalInfo,\n });\n\n const createPixTransaction = () => {\n post(\"/consultas/pix\", {\n onError: (e) => {\n showAlert({ message: e.response.data });\n },\n });\n };\n\n return (\n setOpen(false)}\n onClickConfirm={() => {\n createPixTransaction();\n setOpen(false);\n }}\n >\n
\n
\n \n
\n \n Deseja pagar com Pix?\n \n \n Você será redirecionado à tela de pagamento.\n \n
\n \n );\n};\n\nexport default PixModal;\n","import React, { useEffect, useState } from \"react\";\nimport { ErrorBoundary } from \"react-error-boundary\";\nimport _ from 'lodash';\nimport { Avatar } from \"@switchdreams/ui\";\nimport { Link } from \"@inertiajs/react\";\n\nconst SimpleClinicCard = ({status,clinic, onClick}) => {\n console.log(clinic)\n const statusList = [\n {status: 'pending', name: 'Aguardando Retorno', color: '#F79009'},\n {status: 'received', name: 'Ver Orçamento Recebido', color: '#38C2B9'},\n {status: 'cancelled', name: 'Cancelado pela Clínica', color: '#850000'},\n {status: 'accepted', name: 'Aceito - Pagamento Realizado', color: '#007AFF'},\n ];\n const [statusOptions, setStatusOptions] = useState(statusList);\n const [actualStatus, setActualStatus] = useState({});\n\n useEffect(() => {\n let findStatus = _.find(statusOptions, {status: status});\n setActualStatus(findStatus)\n }, [])\n\n return (\n Aconteceu algum problema para exibir a clínica...}>\n
\n
\n
\n \n
\n
\n {clinic.clinic.name}\n
\n
\n {clinic.clinic.description}\n
\n
\n
\n
\n
\n \n
\n {actualStatus.name}\n
\n \n
\n
\n\n {status === 'accepted' && (\n
\n
\n

\n A Clínica entrará em contato via e-mail ou Whatsapp o quanto antes para a finalização do processo do seu Exame.\n Fique atento às notificações que serão recebidas ou entre em contato:
\n Telefone: {clinic.clinic.phone}
\n Email: {clinic.clinic.email}

\n \n Sua avaliação é muito importante!
Clique aqui e deixe uma avaliação para a clínica
\n \n

\n
\n
\n )}\n
\n );\n};\n\nexport default SimpleClinicCard;\n","import { Link, router } from \"@inertiajs/react\";\nimport React, { useRef, useState } from \"react\";\n\nimport Modal from \"@/components/Modal\";\nimport { useAlert } from \"@/contexts/Alert\";\nimport SimpleClinicCardButton from \"../../components/Cards/SimpleClinicCardButton\";\nimport { Avatar } from \"@switchdreams/ui\";\n\nconst Show = ({ data, pagy }) => {\n\n const sortOptions = [\n { label: \"Alfabética\", value: \"alphabetical\" },\n { label: \"Número de pacientes atendido\", value: \"patients_count\" },\n { label: \"Tempo no site\", value: \"created_at\" },\n ];\n\n\n const { showAlert } = useAlert();\n const [open, setOpen] = useState(false);\n const [clinic, setClinic] = useState(null);\n\n const elementRef = useRef(null);\n\n const openModal = () => {\n setOpen(true);\n }\n\n const redirectExams = () => {\n router.visit('/orcamento/1')\n }\n\n const selectClinic = (item) => {\n if(item.status == 'received'){\n setOpen(true)\n setClinic(item)\n }\n }\n\n const cancelBudget = () => {\n \n }\n\n return (\n <> \n setOpen(false)}\n >\n {clinic && (\n
\n
\n
\n
\n
\n \n
\n
\n
\n {clinic.clinic.name}\n
\n
\n {clinic.clinic.description}\n
\n
\n
\n
\n
Observações
\n
\n {clinic.additional_description || ''}\n
\n
\n Valor Total {clinic.formatted_amount || ''}\n
\n
\n \n Cancelar\n \n \n \n \n
\n
\n
\n )}\n \n\n
\n
\n
\n
Clínicas Selecionadas
\n

\n Seus Exames serão enviados para essas clínicas e você receberá o retorno dos orçamentos o quanto antes\n

\n
\n {data.map((item, i) => (\n selectClinic(item)}\n />\n ))}\n
\n
\n \n );\n};\n\nexport default Show;\n","export const DoctorInfo = [\n {\n name: \"Dr. José Montenegro\",\n verified: true,\n img: \"\",\n specility: \"Clínico Geral e Cardiologista\",\n timeOnSite: \"3 meses\",\n patients: 235,\n description:\n \"Formado em Medicina e especializado em Cardiologia pela Unifesp. Com mais de 14 anos de experiência clínica, estou comprometido em oferecer diagnósticos precisos e tratamentos personalizados a todos.\",\n starts: 5,\n evaluations: 36,\n clinicName: \"Consultório José Montenegro\",\n address: \"Praça Santo Agostinho 70, Brasília\",\n logo: \"\",\n dates: [\n {\n day: \"Segunda\",\n times: [\n \"8:00\",\n \"9:00\",\n \"10:00\",\n \"11:00\",\n \"12:00\",\n \"13:00\",\n \"14:00\",\n \"15:00\",\n \"16:00\",\n \"17:00\",\n ],\n },\n {\n day: \"Terça\",\n times: [\n \"8:00\",\n \"9:00\",\n \"10:00\",\n \"11:00\",\n \"12:00\",\n \"13:00\",\n \"14:00\",\n \"15:00\",\n \"16:00\",\n \"17:00\",\n ],\n },\n {\n day: \"Quarta\",\n times: [\n \"8:00\",\n \"9:00\",\n \"10:00\",\n \"11:00\",\n \"12:00\",\n \"13:00\",\n \"14:00\",\n \"15:00\",\n \"16:00\",\n \"17:00\",\n ],\n },\n {\n day: \"Quinta\",\n times: [\n \"8:00\",\n \"9:00\",\n \"10:00\",\n \"11:00\",\n \"12:00\",\n \"13:00\",\n \"14:00\",\n \"15:00\",\n \"16:00\",\n \"17:00\",\n ],\n },\n {\n day: \"Sexta\",\n times: [\n \"8:00\",\n \"9:00\",\n \"10:00\",\n \"11:00\",\n \"12:00\",\n \"13:00\",\n \"14:00\",\n \"15:00\",\n \"16:00\",\n \"17:00\",\n ],\n },\n {\n day: \"Sábado\",\n times: [\"8:00\", \"9:00\", \"10:00\"],\n },\n ],\n },\n {\n name: \"Dra. Maria Silva\",\n verified: true,\n img: \"\",\n specility: \"Pediatra\",\n timeOnSite: \"1 ano\",\n patients: 320,\n description:\n \"Especialista em Pediatria pela USP, com 10 anos de experiência. Apaixonada por cuidar da saúde das crianças, proporcionando um atendimento humanizado e de qualidade.\",\n starts: 5,\n evaluations: 45,\n clinicName: \"Clínica Pediátrica Maria Silva\",\n address: \"Rua das Flores 123, São Paulo\",\n logo: \"\",\n dates: [\n {\n day: \"Segunda\",\n times: [\"9:00\", \"10:00\", \"11:00\", \"13:00\", \"14:00\", \"15:00\", \"16:00\", \"17:00\"],\n },\n {\n day: \"Terça\",\n times: [\"9:00\", \"10:00\", \"11:00\", \"13:00\", \"14:00\", \"15:00\", \"16:00\", \"17:00\"],\n },\n {\n day: \"Quarta\",\n times: [\"9:00\", \"10:00\", \"11:00\", \"13:00\", \"14:00\", \"15:00\", \"16:00\", \"17:00\"],\n },\n {\n day: \"Quinta\",\n times: [\"9:00\", \"10:00\", \"11:00\", \"13:00\", \"14:00\", \"15:00\", \"16:00\", \"17:00\"],\n },\n {\n day: \"Sexta\",\n times: [\"9:00\", \"10:00\", \"11:00\", \"13:00\", \"14:00\", \"15:00\", \"16:00\", \"17:00\"],\n },\n {\n day: \"Sábado\",\n times: [\"9:00\", \"10:00\"],\n },\n ],\n },\n {\n name: \"Dr. Carlos Andrade\",\n verified: true,\n img: \"\",\n specility: \"Dermatologista\",\n timeOnSite: \"6 meses\",\n patients: 180,\n description:\n \"Formado pela UFRJ com especialização em Dermatologia. Experiência de 8 anos no tratamento de doenças de pele, cabelo e unhas, com foco em procedimentos estéticos.\",\n starts: 4,\n evaluations: 27,\n clinicName: \"Clínica Dermatológica Carlos Andrade\",\n address: \"Av. Atlântica 456, Rio de Janeiro\",\n logo: \"\",\n dates: [\n {\n day: \"Segunda\",\n times: [\"10:00\", \"11:00\", \"12:00\", \"13:00\", \"14:00\", \"15:00\", \"16:00\", \"17:00\", \"18:00\"],\n },\n {\n day: \"Terça\",\n times: [\"10:00\", \"11:00\", \"12:00\", \"13:00\", \"14:00\", \"15:00\", \"16:00\", \"17:00\", \"18:00\"],\n },\n {\n day: \"Quarta\",\n times: [\"10:00\", \"11:00\", \"12:00\", \"13:00\", \"14:00\", \"15:00\", \"16:00\", \"17:00\", \"18:00\"],\n },\n {\n day: \"Quinta\",\n times: [\"10:00\", \"11:00\", \"12:00\", \"13:00\", \"14:00\", \"15:00\", \"16:00\", \"17:00\", \"18:00\"],\n },\n {\n day: \"Sexta\",\n times: [\"10:00\", \"11:00\", \"12:00\", \"13:00\", \"14:00\", \"15:00\", \"16:00\", \"17:00\", \"18:00\"],\n },\n {\n day: \"Sábado\",\n times: [\"10:00\", \"11:00\", \"12:00\"],\n },\n ],\n },\n {\n name: \"Dra. Fernanda Costa\",\n verified: true,\n img: \"\",\n specility: \"Ginecologista e Obstetra\",\n timeOnSite: \"2 anos\",\n patients: 410,\n description:\n \"Especialista em Ginecologia e Obstetrícia pela UNICAMP. Com mais de 12 anos de experiência, foco em saúde da mulher, acompanhamento pré-natal e partos humanizados.\",\n starts: 5,\n evaluations: 52,\n clinicName: \"Centro de Saúde da Mulher Fernanda Costa\",\n address: \"Rua dos Pinheiros 789, Campinas\",\n logo: \"\",\n dates: [\n {\n day: \"Segunda\",\n times: [\n \"8:00\",\n \"9:00\",\n \"10:00\",\n \"11:00\",\n \"12:00\",\n \"13:00\",\n \"14:00\",\n \"15:00\",\n \"16:00\",\n \"17:00\",\n ],\n },\n {\n day: \"Terça\",\n times: [\n \"8:00\",\n \"9:00\",\n \"10:00\",\n \"11:00\",\n \"12:00\",\n \"13:00\",\n \"14:00\",\n \"15:00\",\n \"16:00\",\n \"17:00\",\n ],\n },\n {\n day: \"Quarta\",\n times: [\n \"8:00\",\n \"9:00\",\n \"10:00\",\n \"11:00\",\n \"12:00\",\n \"13:00\",\n \"14:00\",\n \"15:00\",\n \"16:00\",\n \"17:00\",\n ],\n },\n {\n day: \"Quinta\",\n times: [\n \"8:00\",\n \"9:00\",\n \"10:00\",\n \"11:00\",\n \"12:00\",\n \"13:00\",\n \"14:00\",\n \"15:00\",\n \"16:00\",\n \"17:00\",\n ],\n },\n {\n day: \"Sexta\",\n times: [\n \"8:00\",\n \"9:00\",\n \"10:00\",\n \"11:00\",\n \"12:00\",\n \"13:00\",\n \"14:00\",\n \"15:00\",\n \"16:00\",\n \"17:00\",\n ],\n },\n {\n day: \"Sábado\",\n times: [\"8:00\", \"9:00\", \"10:00\"],\n },\n ],\n },\n {\n name: \"Dr. Paulo Moreira\",\n verified: true,\n img: \"\",\n specility: \"Ortopedista\",\n timeOnSite: \"9 meses\",\n patients: 290,\n description:\n \"Graduado pela USP com especialização em Ortopedia e Traumatologia. Experiência de 11 anos em tratamentos de fraturas, lesões esportivas e cirurgias ortopédicas.\",\n starts: 4,\n evaluations: 40,\n clinicName: \"Ortopedia Paulo Moreira\",\n address: \"Rua das Palmeiras 250, Belo Horizonte\",\n logo: \"\",\n dates: [\n {\n day: \"Segunda\",\n times: [\n \"7:00\",\n \"8:00\",\n \"9:00\",\n \"10:00\",\n \"11:00\",\n \"12:00\",\n \"13:00\",\n \"14:00\",\n \"15:00\",\n \"16:00\",\n ],\n },\n {\n day: \"Terça\",\n times: [\n \"7:00\",\n \"8:00\",\n \"9:00\",\n \"10:00\",\n \"11:00\",\n \"12:00\",\n \"13:00\",\n \"14:00\",\n \"15:00\",\n \"16:00\",\n ],\n },\n {\n day: \"Quarta\",\n times: [\n \"7:00\",\n \"8:00\",\n \"9:00\",\n \"10:00\",\n \"11:00\",\n \"12:00\",\n \"13:00\",\n \"14:00\",\n \"15:00\",\n \"16:00\",\n ],\n },\n {\n day: \"Quinta\",\n times: [\n \"8:00\",\n \"9:00\",\n \"10:00\",\n \"11:00\",\n \"12:00\",\n \"13:00\",\n \"14:00\",\n \"15:00\",\n \"16:00\",\n \"17:00\",\n ],\n },\n {\n day: \"Sexta\",\n times: [\n \"8:00\",\n \"9:00\",\n \"10:00\",\n \"11:00\",\n \"12:00\",\n \"13:00\",\n \"14:00\",\n \"15:00\",\n \"16:00\",\n \"17:00\",\n ],\n },\n {\n day: \"Sábado\",\n times: [\"8:00\", \"9:00\", \"10:00\"],\n },\n ],\n },\n];\n\nexport const Options = [\n \"Alergia e Imunologia\",\n \"Dermatologista\",\n \"Neurocirurgia\",\n \"Infectiologia\",\n \"Anestesiologia\",\n \"Coloproctologia\",\n \"Neurologia\",\n \"Mastologia\",\n \"Angiologia\",\n \"Cirurgia Torácica\",\n \"Nutrologia\",\n \"Medicina Física e Reabilitação\",\n \"Cancerologia / Oncologia\",\n \"Cirurgia Vascular\",\n \"Oftalmologia\",\n \"Nefrologia\",\n \"Cardiologia\",\n \"Endocrinologia\",\n \"Ortopedia e Traumatologia\",\n \"Neurocirurgia\",\n \"Cirurgia Cardiovascular\",\n \"Gastroenterologia\",\n \"Otorrinolaringologia\",\n \"Neurologia\",\n \"Cirurgia de Mão\",\n \"Genética Médica\",\n \"Pediatria\",\n \"Nutrologia\",\n \"Cirurgia de Cabeça e Pescoço\",\n \"Geriatria\",\n \"Pneumologia\",\n \"Oftalmologia\",\n \"Cirurgia de Aparelho Digestivo\",\n \"Ginecologia e Hemoterapia\",\n \"Psiquiatria\",\n \"Ortopedia e Traumatologia\",\n \"Cirurgia Geral\",\n \"Infectiologia\",\n \"Reumatologia\",\n \"Otorrinolaringologia\",\n \"Cirurgia Pediátrica\",\n \"Mastologia\",\n \"Urologia\",\n \"Cirurgia Plástica\",\n \"Medicina Física e Reabilitação\",\n \"Clínica de Exames Radiológicos\",\n \"Pneumologia\",\n \"Clínica Médica\",\n \"Nefrologia\",\n \"Laboratórios de Análises Clínicas e Patológicas\",\n];\n","import {\n BanknotesIcon,\n BookmarkIcon,\n CalendarDaysIcon,\n CheckCircleIcon,\n CheckIcon,\n ChevronRightIcon,\n ClockIcon,\n CreditCardIcon,\n LockClosedIcon,\n MagnifyingGlassIcon,\n MapPinIcon,\n XCircleIcon,\n XMarkIcon,\n} from \"@heroicons/react/24/outline\";\nimport { Link } from \"@inertiajs/react\";\nimport { Avatar, Badge, Button, Text } from \"@switchdreams/ui\";\n\nimport { formatIntegerCurrency, imagePath, monthsTranslated } from \"@/utils\";\nimport CreditCardModal from \"./Modals/creditCardModal\";\nimport { useState } from \"react\";\n\nconst Payment = ({ data }) => { \n const [openCard, setOpenCard] = useState(false);\n\n return (\n <>\n \n
\n
\n
\n \n Método de pagamento\n \n
\n
\n \n \n
\n \n Pix\n
\n \n
\n \n {/*
\n
\n \n Boleto\n
\n \n
*/}\n \n
\n \n \n Cartão de crédito\n \n
\n \n
\n
\n \n \n Sua transação está protegida com criptografia de ponta.\n \n
\n
\n \n
\n
\n \n
\n
\n \n {data.clinic.name}\n \n {/* {doctor.verified && \"icone} */}\n
\n \n {data.description}\n \n
\n
\n
\n \n
\n \n {data.clinic.name}\n \n \n {data.clinic.address.neighborhood} {data.clinic.address.street},{\" \"}\n {data.clinic.address.number}, {data.clinic.address.city} - {data.clinic.address.state}{\" \"}\n - {data.clinic.address.cep}\n \n
\n
\n
\n \n
\n \n {data.formatted_amount}\n \n Valor\n
\n
\n \n A Clínica entrará em contato com você para orientar sobre os procedimentos necessários.\n \n
\n \n \n );\n};\n\nexport default Payment;\n","import {\n BanknotesIcon,\n BookmarkIcon,\n CalendarDaysIcon,\n CheckCircleIcon,\n CheckIcon,\n ClockIcon,\n MagnifyingGlassIcon,\n MapPinIcon,\n XCircleIcon,\n XMarkIcon,\n} from \"@heroicons/react/24/outline\";\nimport { Link } from \"@inertiajs/react\";\nimport { Avatar, Badge, Button, Text } from \"@switchdreams/ui\";\n\nimport { formatIntegerCurrency, imagePath, monthsTranslated } from \"@/utils\";\n\nconst Payment = ({ data, qr_code, payment }) => {\n console.log(data, qr_code, payment)\n \n\n const paymentInfo = (status) => {\n if (status === \"pending\") {\n return (\n <>\n
\n
\n \n Valor do Exame\n \n \n {data.formatted_amount}\n \n
\n {qr_code && payment.payment_method == \"pix\" && (\n \n )}\n
\n
\n \n {payment.payment_method == \"pix\" ? (\n <>\n \n Escaneie o QR Code ou copie o código PIX\n \n \n Você pode utilizar a câmera do seu celular para ler o QR Code ou copiar o código e\n pagar no aplicativo de seu banco:{\" \"}\n \n navigator.clipboard.writeText(qr_code.payload)}\n />\n \n ) : (\n <>\n \n O pagamento está sendo processado pelo seu cartão de crédito\n \n \n Em caso de dúvida, procure nosso suporte.\n \n \n )}\n
\n \n );\n } else if (status === \"paid\") {\n return (\n <>\n
\n
\n \n Valor do Exame\n \n \n {data.formatted_amount}\n \n
\n \n
\n
\n \n \n Pagamento Aprovado!\n \n \n Este exame já foi pago, acesse seus exames para ver mais detalhes\n \n \n \n \n \n Método de pagamento:{\" \"}\n {payment.payment_method == \"pix\" ? \"PIX\" : \"Cartão de crédito\"}\n \n
\n \n );\n } else if (status === \"expired\") {\n return (\n <>\n
\n
\n \n Valor do Exame\n \n \n {data.formatted_amount}\n \n
\n \n
\n
\n \n \n Pagamento Expirado!\n \n \n Este pagamento expirou, tente agendar a consulta novamente\n \n \n \n \n
\n \n );\n }\n };\n\n return (\n <>\n
\n
\n {paymentInfo(payment.status)}\n
\n
\n
\n {/* */}\n
\n
\n \n {data.clinic.name}\n \n {data.clinic.verified && \"icone}\n
\n \n {data.clinic.description}\n \n
\n
\n
\n \n
\n \n \n Pagar Até\n
\n
\n
\n \n
\n \n {data.clinic.address.neighborhood} {data.clinic.address.street},{\" \"}\n {data.clinic.address.number}, {data.clinic.address.city} - {data.clinic.address.state}{\" \"}\n - {data.clinic.address.cep}\n \n \n Endereço\n \n
\n
\n
\n \n
\n \n {data.formatted_amount}\n \n Valor\n
\n
\n \n A Clínica entrará em contato com você para orientar sobre os procedimentos necessários.\n \n
\n
\n \n );\n};\n\nexport default Payment;\n","import {\n BanknotesIcon,\n BookmarkIcon,\n CalendarDaysIcon,\n CheckCircleIcon,\n CheckIcon,\n ClockIcon,\n MagnifyingGlassIcon,\n MapPinIcon,\n XCircleIcon,\n XMarkIcon,\n} from \"@heroicons/react/24/outline\";\nimport { Link, router } from \"@inertiajs/react\";\nimport { Avatar, Badge, Button, Text } from \"@switchdreams/ui\";\n\nimport { formatIntegerCurrency, imagePath, monthsTranslated } from \"@/utils\";\nimport { useEffect, useState } from \"react\";\n\nconst Payment = ({ data, qr_code, payment }) => {\n const [paymentData, setPaymentData] = useState(payment);\n\n const dateFormated = () => {\n const dateObj = new Date(qr_code.expirationDate);\n return `${dateObj.getDate()} de ${monthsTranslated[dateObj.getMonth()]} de ${dateObj.getFullYear()} às ${dateObj.getHours()}:${dateObj.getMinutes()}`;\n };\n console.log(data, payment)\n \n useEffect(() => {\n // const eventSource = new EventSource(`/exams/budgets/:budget_id/items/:budget_item_id/payments/:payment_id/status`);\n\n // eventSource.onmessage = (event) => {\n // console.log(event.data)\n // };\n\n // eventSource.onerror = (error) => {\n // console.error(\"Erro na conexão SSE:\", error);\n // eventSource.close();\n // };\n\n // return () => {\n // eventSource.close();\n // };\n}, []);\n\n const paymentInfo = (status) => {\n if (status === \"pending\") {\n return (\n <>\n
\n
\n \n Valor do Exame\n \n \n {data.formatted_amount}\n \n
\n {qr_code && paymentData.payment_method == \"pix\" && (\n \n )}\n
\n
\n \n {paymentData.payment_method == \"pix\" ? (\n <>\n \n Escaneie o QR Code ou copie o código PIX\n \n \n Você pode utilizar a câmera do seu celular para ler o QR Code ou copiar o código e\n pagar no aplicativo de seu banco:{\" \"}\n \n navigator.clipboard.writeText(qr_code.payload)}\n />\n \n ) : (\n <>\n \n O pagamento está sendo processado pelo seu cartão de crédito\n \n \n Em caso de dúvida, procure nosso suporte.\n \n \n )}\n
\n \n );\n } else if (status === \"paid\") {\n return (\n <>\n
\n
\n \n Valor do Exame\n \n \n {data.formatted_amount}\n \n
\n \n
\n
\n \n \n Pagamento Aprovado!\n \n \n Este exame já foi pago, acesse seus exames para ver mais detalhes\n \n \n \n \n \n Método de pagamento:{\" \"}\n {paymentData.payment_method == \"pix\" ? \"PIX\" : \"Cartão de crédito\"}\n \n
\n \n );\n } else if (status === \"expired\") {\n return (\n <>\n
\n
\n \n Valor do Exame\n \n \n {data.formatted_amount}\n \n
\n \n
\n
\n \n \n Pagamento Expirado!\n \n \n Este pagamento expirou, tente agendar a consulta novamente\n \n \n \n \n
\n \n );\n }\n };\n\n return (\n <>\n
\n
\n {paymentInfo(paymentData.status)}\n
\n
\n
\n {/* */}\n
\n
\n \n {data.clinic.name}\n \n {data.clinic.verified && (\n \"icone\n )}\n
\n \n {data.clinic.description}\n \n
\n
\n
\n \n
\n \n {dateFormated()}\n \n Pagar Até\n
\n
\n
\n \n
\n \n {data.clinic.address.neighborhood} {data.clinic.address.street},{\" \"}\n {data.clinic.address.number}, {data.clinic.address.city} -{\" \"}\n {data.clinic.address.state} - {data.clinic.address.cep}\n \n Endereço\n
\n
\n
\n \n
\n \n {data.formatted_amount}\n \n Valor\n
\n
\n \n A Clínica entrará em contato com você para orientar sobre os procedimentos necessários.\n \n
\n
\n \n );\n};\n\nexport default Payment;\n","import {\n CalendarDaysIcon,\n ChevronLeftIcon,\n ChevronRightIcon,\n FaceSmileIcon,\n HeartIcon,\n // StarIcon,\n} from \"@heroicons/react/24/outline\";\nimport { router, usePage } from \"@inertiajs/react\";\nimport { Avatar, Text } from \"@switchdreams/ui\";\nimport React, { useState } from \"react\";\nimport { ErrorBoundary } from \"react-error-boundary\";\n\nimport Modal from \"@/components/Modal\";\nimport { useAlert } from \"@/contexts/Alert\";\nimport {\n extractTime,\n formatIntegerCurrency,\n imagePath,\n monthsTranslated,\n monthsTranslatedAbreviation,\n weekDaysTranslated,\n} from \"@/utils\";\n\nconst SimpleClinicCard = (props) => {\n\n return (\n Aconteceu algum problema para exibir a clínica...}>\n
\n
\n
\n
\n \n
\n
\n
\n
\n
{props.name}
\n
\n
{props.specialty}
\n
\n
\n
\n
\n );\n};\n\nexport default SimpleClinicCard;\n","import { router } from \"@inertiajs/react\";\nimport axios from \"axios\";\nimport React, { useEffect, useRef, useState } from \"react\";\n\nimport Modal from \"@/components/Modal\";\nimport SimpleClinicCard from \"@/components/Cards/SimpleClinicCard\";\n\nimport { useAlert } from \"@/contexts/Alert\";\nimport { imagePath } from \"@/utils\";\n\nconst Edit = ({ data }) => {\n const sortOptions = [\n { label: \"Alfabética\", value: \"alphabetical\" },\n { label: \"Número de pacientes atendido\", value: \"patients_count\" },\n { label: \"Tempo no site\", value: \"created_at\" },\n ]; \n console.log(data);\n const { showAlert } = useAlert();\n const [open, setOpen] = useState(false);\n const [clinics, setClinics] = useState([]);\n const [files, setFiles] = useState([]);\n const [description, setDescription] = useState('');\n const [amount, setAmount] = useState(null);\n const elementRef = useRef(null);\n\n useEffect(() => {\n\n }, [])\n \n const redirectExams = () => {\n router.visit('/orcamento/1')\n }\n\n const onFileChange = (event) => {\n setFiles(event.target.files)\n }; \n\n const sendData = async () => {\n const formData = new FormData();\n formData.append('additional_description', description);\n formData.append('amount', amount);\n router.patch('/clinics/exams/budgets/'+data.id, formData)\n }\n\n const responseContent = () => {\n return (<>\n
\n
\n
\n \n
\n
\n Faça o download\n
\n dos arquivos de pedido médico do paciente\n
\n
\n
\n {\n data.attachments.map((item, i) => (\n <>\n Clique Aqui para Baixar Pedido Médico {i +1}
\n \n ))\n }\n
\n
\n
\n
\n Valor do Orçamento (R$)\n
\n
\n setAmount(e.target.value)}\n type=\"number\"\n placeholder=\"Digite o valor do orçamento\"\n className=\"shrink grow basis-0 self-stretch font-['Poppins'] text-base font-normal leading-snug text-[#98a1b2]\"\n />\n
\n
\n Informações adicionais (opcional)\n
\n
\n setDescription(e.target.value)}\n rows=\"5\"\n placeholder=\"Dê uma descrição, escreva informações importantes ou compartilhe qualquer coisa que você achar necessário.\"\n className=\"shrink grow basis-0 self-stretch font-['Poppins'] text-base font-normal leading-snug text-[#98a1b2]\"\n />\n
\n \n
\n )\n }\n\n const formatDate = (date) => {\n const dateTime = new Date(date);\n return dateTime.toLocaleString();\n };\n\n const waitingStatus = () => {\n return (<>\n
\n
\n
\n \n
\n
\n Aguardando Retorno do Orçamento\n
\n
\n O cliente não aceitou o orçamento ainda, mas,
\n ele pode ser aceito a qualquer momento. Aguarde.\n
\n
\n
\n )\n }\n\n const paidStatus = () => {\n return (<>\n
\n
\n
\n \n
\n
\n O orçamento foi aceito e pago pelo cliente!\n
\n
\n Entre em contato com o paciente o quanto antes para
\n informar sobre os horários de atendimento do seu estabelecimento.\n
\n
\n Valor Pago: {data.formatted_amount}\n
\n
\n Dados do paciente\n
\n
\n Nome do paciente: {data.user_name}\n
\n
\n Telefone: {data.user_phone}\n
\n
\n E-mail: {data.user_emai}\n
\n
\n
\n )\n }\n\n return (\n <>\n redirectExams()}\n >\n
\n
\n \"Sucesso\"\n
\n
Orçamentos Enviados com Sucesso
\n
Aguarde a confirmação das clínicas, você será notificado por e-mail
\n
\n \n\n
\n
\n
\n
Responder Orçamento
\n

\n Analise o pedido médico e responda o mais rápido o possível.\n O paciente será notificado via E-mail.\n

\n
\n \n
Informações do Orçamento
\n
{'Código: ' + data.id}
\n
{'Recebido Em: ' + formatDate(data.sent_at)}
\n
{'Descrição: ' + data.description}
\n
\n\n
\n
\n
\n
\n Resposta do Orçamento\n
\n
\n
\n {data.status === 'pending' && responseContent()}\n {data.status === 'received' && waitingStatus()}\n {data.status === 'accepted' && paidStatus()}\n
\n
\n
\n
\n \n );\n};\n\nexport default Edit;\n","import { Link, router } from \"@inertiajs/react\";\nimport React, { useRef, useState } from \"react\";\n\nimport { useAlert } from \"@/contexts/Alert\";\n\nconst List = ({ data, pagy }) => {\n const sortOptions = [\n { label: \"Alfabética\", value: \"alphabetical\" },\n { label: \"Número de pacientes atendido\", value: \"patients_count\" },\n { label: \"Tempo no site\", value: \"created_at\" },\n ];\n\n\n const { showAlert } = useAlert();\n const [open, setOpen] = useState(false);\n\n const elementRef = useRef(null);\n \n\n const openModal = () => {\n setOpen(true);\n }\n\n const redirectExams = () => {\n router.visit('/orcamento/1')\n }\n\n const selectClinic = (item) => {\n setOpen(true)\n }\n\n const formatDate = (date) => {\n const dateTime = new Date(date);\n return dateTime.toLocaleString();\n };\n\n return (\n <> \n
\n
\n
\n
Pedidos Recebidos
\n

\n Lista de pedidos de exames recebidos\n

\n
\n {data.map((item, i) => (\n
\n
Código:
#{item.id}
\n
Paciente:
{item.user_name}
\n
Data recebimento:
{formatDate(item.sent_at)}
\n
\n \n \n \n
\n
\n ))}\n
\n
\n \n );\n};\n\nexport default List;\n","export const DoctorInfo = [\n {\n name: \"Dr. José Montenegro\",\n verified: true,\n img: \"\",\n specility: \"Clínico Geral e Cardiologista\",\n timeOnSite: \"3 meses\",\n patients: 235,\n description:\n \"Formado em Medicina e especializado em Cardiologia pela Unifesp. Com mais de 14 anos de experiência clínica, estou comprometido em oferecer diagnósticos precisos e tratamentos personalizados a todos.\",\n starts: 5,\n evaluations: 36,\n clinicName: \"Consultório José Montenegro\",\n address: \"Praça Santo Agostinho 70, Brasília\",\n logo: \"\",\n dates: [\n {\n day: \"Segunda\",\n times: [\n \"8:00\",\n \"9:00\",\n \"10:00\",\n \"11:00\",\n \"12:00\",\n \"13:00\",\n \"14:00\",\n \"15:00\",\n \"16:00\",\n \"17:00\",\n ],\n },\n {\n day: \"Terça\",\n times: [\n \"8:00\",\n \"9:00\",\n \"10:00\",\n \"11:00\",\n \"12:00\",\n \"13:00\",\n \"14:00\",\n \"15:00\",\n \"16:00\",\n \"17:00\",\n ],\n },\n {\n day: \"Quarta\",\n times: [\n \"8:00\",\n \"9:00\",\n \"10:00\",\n \"11:00\",\n \"12:00\",\n \"13:00\",\n \"14:00\",\n \"15:00\",\n \"16:00\",\n \"17:00\",\n ],\n },\n {\n day: \"Quinta\",\n times: [\n \"8:00\",\n \"9:00\",\n \"10:00\",\n \"11:00\",\n \"12:00\",\n \"13:00\",\n \"14:00\",\n \"15:00\",\n \"16:00\",\n \"17:00\",\n ],\n },\n {\n day: \"Sexta\",\n times: [\n \"8:00\",\n \"9:00\",\n \"10:00\",\n \"11:00\",\n \"12:00\",\n \"13:00\",\n \"14:00\",\n \"15:00\",\n \"16:00\",\n \"17:00\",\n ],\n },\n {\n day: \"Sábado\",\n times: [\"8:00\", \"9:00\", \"10:00\"],\n },\n ],\n },\n {\n name: \"Dra. Maria Silva\",\n verified: true,\n img: \"\",\n specility: \"Pediatra\",\n timeOnSite: \"1 ano\",\n patients: 320,\n description:\n \"Especialista em Pediatria pela USP, com 10 anos de experiência. Apaixonada por cuidar da saúde das crianças, proporcionando um atendimento humanizado e de qualidade.\",\n starts: 5,\n evaluations: 45,\n clinicName: \"Clínica Pediátrica Maria Silva\",\n address: \"Rua das Flores 123, São Paulo\",\n logo: \"\",\n dates: [\n {\n day: \"Segunda\",\n times: [\"9:00\", \"10:00\", \"11:00\", \"13:00\", \"14:00\", \"15:00\", \"16:00\", \"17:00\"],\n },\n {\n day: \"Terça\",\n times: [\"9:00\", \"10:00\", \"11:00\", \"13:00\", \"14:00\", \"15:00\", \"16:00\", \"17:00\"],\n },\n {\n day: \"Quarta\",\n times: [\"9:00\", \"10:00\", \"11:00\", \"13:00\", \"14:00\", \"15:00\", \"16:00\", \"17:00\"],\n },\n {\n day: \"Quinta\",\n times: [\"9:00\", \"10:00\", \"11:00\", \"13:00\", \"14:00\", \"15:00\", \"16:00\", \"17:00\"],\n },\n {\n day: \"Sexta\",\n times: [\"9:00\", \"10:00\", \"11:00\", \"13:00\", \"14:00\", \"15:00\", \"16:00\", \"17:00\"],\n },\n {\n day: \"Sábado\",\n times: [\"9:00\", \"10:00\"],\n },\n ],\n },\n {\n name: \"Dr. Carlos Andrade\",\n verified: true,\n img: \"\",\n specility: \"Dermatologista\",\n timeOnSite: \"6 meses\",\n patients: 180,\n description:\n \"Formado pela UFRJ com especialização em Dermatologia. Experiência de 8 anos no tratamento de doenças de pele, cabelo e unhas, com foco em procedimentos estéticos.\",\n starts: 4,\n evaluations: 27,\n clinicName: \"Clínica Dermatológica Carlos Andrade\",\n address: \"Av. Atlântica 456, Rio de Janeiro\",\n logo: \"\",\n dates: [\n {\n day: \"Segunda\",\n times: [\"10:00\", \"11:00\", \"12:00\", \"13:00\", \"14:00\", \"15:00\", \"16:00\", \"17:00\", \"18:00\"],\n },\n {\n day: \"Terça\",\n times: [\"10:00\", \"11:00\", \"12:00\", \"13:00\", \"14:00\", \"15:00\", \"16:00\", \"17:00\", \"18:00\"],\n },\n {\n day: \"Quarta\",\n times: [\"10:00\", \"11:00\", \"12:00\", \"13:00\", \"14:00\", \"15:00\", \"16:00\", \"17:00\", \"18:00\"],\n },\n {\n day: \"Quinta\",\n times: [\"10:00\", \"11:00\", \"12:00\", \"13:00\", \"14:00\", \"15:00\", \"16:00\", \"17:00\", \"18:00\"],\n },\n {\n day: \"Sexta\",\n times: [\"10:00\", \"11:00\", \"12:00\", \"13:00\", \"14:00\", \"15:00\", \"16:00\", \"17:00\", \"18:00\"],\n },\n {\n day: \"Sábado\",\n times: [\"10:00\", \"11:00\", \"12:00\"],\n },\n ],\n },\n {\n name: \"Dra. Fernanda Costa\",\n verified: true,\n img: \"\",\n specility: \"Ginecologista e Obstetra\",\n timeOnSite: \"2 anos\",\n patients: 410,\n description:\n \"Especialista em Ginecologia e Obstetrícia pela UNICAMP. Com mais de 12 anos de experiência, foco em saúde da mulher, acompanhamento pré-natal e partos humanizados.\",\n starts: 5,\n evaluations: 52,\n clinicName: \"Centro de Saúde da Mulher Fernanda Costa\",\n address: \"Rua dos Pinheiros 789, Campinas\",\n logo: \"\",\n dates: [\n {\n day: \"Segunda\",\n times: [\n \"8:00\",\n \"9:00\",\n \"10:00\",\n \"11:00\",\n \"12:00\",\n \"13:00\",\n \"14:00\",\n \"15:00\",\n \"16:00\",\n \"17:00\",\n ],\n },\n {\n day: \"Terça\",\n times: [\n \"8:00\",\n \"9:00\",\n \"10:00\",\n \"11:00\",\n \"12:00\",\n \"13:00\",\n \"14:00\",\n \"15:00\",\n \"16:00\",\n \"17:00\",\n ],\n },\n {\n day: \"Quarta\",\n times: [\n \"8:00\",\n \"9:00\",\n \"10:00\",\n \"11:00\",\n \"12:00\",\n \"13:00\",\n \"14:00\",\n \"15:00\",\n \"16:00\",\n \"17:00\",\n ],\n },\n {\n day: \"Quinta\",\n times: [\n \"8:00\",\n \"9:00\",\n \"10:00\",\n \"11:00\",\n \"12:00\",\n \"13:00\",\n \"14:00\",\n \"15:00\",\n \"16:00\",\n \"17:00\",\n ],\n },\n {\n day: \"Sexta\",\n times: [\n \"8:00\",\n \"9:00\",\n \"10:00\",\n \"11:00\",\n \"12:00\",\n \"13:00\",\n \"14:00\",\n \"15:00\",\n \"16:00\",\n \"17:00\",\n ],\n },\n {\n day: \"Sábado\",\n times: [\"8:00\", \"9:00\", \"10:00\"],\n },\n ],\n },\n {\n name: \"Dr. Paulo Moreira\",\n verified: true,\n img: \"\",\n specility: \"Ortopedista\",\n timeOnSite: \"9 meses\",\n patients: 290,\n description:\n \"Graduado pela USP com especialização em Ortopedia e Traumatologia. Experiência de 11 anos em tratamentos de fraturas, lesões esportivas e cirurgias ortopédicas.\",\n starts: 4,\n evaluations: 40,\n clinicName: \"Ortopedia Paulo Moreira\",\n address: \"Rua das Palmeiras 250, Belo Horizonte\",\n logo: \"\",\n dates: [\n {\n day: \"Segunda\",\n times: [\n \"7:00\",\n \"8:00\",\n \"9:00\",\n \"10:00\",\n \"11:00\",\n \"12:00\",\n \"13:00\",\n \"14:00\",\n \"15:00\",\n \"16:00\",\n ],\n },\n {\n day: \"Terça\",\n times: [\n \"7:00\",\n \"8:00\",\n \"9:00\",\n \"10:00\",\n \"11:00\",\n \"12:00\",\n \"13:00\",\n \"14:00\",\n \"15:00\",\n \"16:00\",\n ],\n },\n {\n day: \"Quarta\",\n times: [\n \"7:00\",\n \"8:00\",\n \"9:00\",\n \"10:00\",\n \"11:00\",\n \"12:00\",\n \"13:00\",\n \"14:00\",\n \"15:00\",\n \"16:00\",\n ],\n },\n {\n day: \"Quinta\",\n times: [\n \"8:00\",\n \"9:00\",\n \"10:00\",\n \"11:00\",\n \"12:00\",\n \"13:00\",\n \"14:00\",\n \"15:00\",\n \"16:00\",\n \"17:00\",\n ],\n },\n {\n day: \"Sexta\",\n times: [\n \"8:00\",\n \"9:00\",\n \"10:00\",\n \"11:00\",\n \"12:00\",\n \"13:00\",\n \"14:00\",\n \"15:00\",\n \"16:00\",\n \"17:00\",\n ],\n },\n {\n day: \"Sábado\",\n times: [\"8:00\", \"9:00\", \"10:00\"],\n },\n ],\n },\n];\n\nexport const Options = [\n \"Alergia e Imunologia\",\n \"Dermatologista\",\n \"Neurocirurgia\",\n \"Infectiologia\",\n \"Anestesiologia\",\n \"Coloproctologia\",\n \"Neurologia\",\n \"Mastologia\",\n \"Angiologia\",\n \"Cirurgia Torácica\",\n \"Nutrologia\",\n \"Medicina Física e Reabilitação\",\n \"Cancerologia / Oncologia\",\n \"Cirurgia Vascular\",\n \"Oftalmologia\",\n \"Nefrologia\",\n \"Cardiologia\",\n \"Endocrinologia\",\n \"Ortopedia e Traumatologia\",\n \"Neurocirurgia\",\n \"Cirurgia Cardiovascular\",\n \"Gastroenterologia\",\n \"Otorrinolaringologia\",\n \"Neurologia\",\n \"Cirurgia de Mão\",\n \"Genética Médica\",\n \"Pediatria\",\n \"Nutrologia\",\n \"Cirurgia de Cabeça e Pescoço\",\n \"Geriatria\",\n \"Pneumologia\",\n \"Oftalmologia\",\n \"Cirurgia de Aparelho Digestivo\",\n \"Ginecologia e Hemoterapia\",\n \"Psiquiatria\",\n \"Ortopedia e Traumatologia\",\n \"Cirurgia Geral\",\n \"Infectiologia\",\n \"Reumatologia\",\n \"Otorrinolaringologia\",\n \"Cirurgia Pediátrica\",\n \"Mastologia\",\n \"Urologia\",\n \"Cirurgia Plástica\",\n \"Medicina Física e Reabilitação\",\n \"Clínica de Exames Radiológicos\",\n \"Pneumologia\",\n \"Clínica Médica\",\n \"Nefrologia\",\n \"Laboratórios de Análises Clínicas e Patológicas\",\n];\n","import { Link, router } from \"@inertiajs/react\";\nimport { SelectBox, Text } from \"@switchdreams/ui\";\nimport React from \"react\";\n\nconst ConfigurationSidebar = ({ page_name }) => {\n const elementColor = (requested_page) => {\n if (requested_page === page_name) {\n return \"text-secondary-950 bg-secondary-25\";\n } else {\n return \"text-gray-600\";\n }\n };\n\n const renderSelectOption = (value, label) => {\n return (\n
\n
\n {label}\n
\n
\n );\n };\n\n const renderOption = (option) => {\n return (\n \n {option.word}\n \n );\n };\n\n const Options = [\n // {\n // value: \"plan\",\n // word: \"Planos de Assinatura\",\n // label: renderSelectOption(\"advanced\", \"Opções avançadas\"),\n // },\n {\n value: \"password\",\n word: \"Alterar Senha\",\n label: renderSelectOption(\"advanced\", \"Opções avançadas\"),\n },\n ];\n\n return (\n <>\n
\n {Options.map(renderOption)}\n
\n
\n
\n {\n router.get(`/configurations/${e}`);\n }}\n />\n
\n
\n \n );\n};\n\nexport default ConfigurationSidebar;\n","import { EyeIcon, EyeSlashIcon, KeyIcon } from \"@heroicons/react/24/outline\";\nimport { useForm, usePage } from \"@inertiajs/react\";\nimport { Button, CheckBox, Spinner, Text, TextField } from \"@switchdreams/ui\";\nimport React, { useState } from \"react\";\n\nimport ConfigurationsSidebar from \"@/components/ConfigurationPagesSidebar\";\nimport { useAlert } from \"@/contexts/Alert\";\n\nexport const Password = ({ type }) => {\n const { currentUser } = usePage().props;\n const [showCurrentPassword, setShowCurrentPassword] = useState(false);\n const [showNewPassword, setShowNewPassword] = useState(false);\n const [showConfirmNewPassword, setShowConfirmShowNewPassword] = useState(false);\n const { setData, data, patch, processing } = useForm({\n current_password: \"\",\n new_password: \"\",\n confirm_new_password: \"\",\n end_sessions: false,\n });\n const { showAlert } = useAlert();\n\n const updatePassword = () => {\n patch(\"/configurations/password\", {\n onError: (e) => {\n showAlert({ message: e });\n },\n onSuccess: () => {\n showAlert({ message: \"Senha trocada com sucesso!\", type: \"success\" });\n },\n });\n };\n\n return (\n
\n \n
\n
\n \n \n TROCAR SENHA\n \n
\n
\n {\n event.preventDefault();\n updatePassword();\n }}\n >\n setShowCurrentPassword(!showCurrentPassword)}\n value={data.current_password}\n onChange={(e) => setData(\"current_password\", e.target.value)}\n />\n
\n
\n setShowNewPassword(!showNewPassword)}\n value={data.new_password}\n onChange={(e) => setData(\"new_password\", e.target.value)}\n required\n />\n
\n
\n setShowConfirmShowNewPassword(!showConfirmNewPassword)}\n value={data.confirm_new_password}\n onChange={(e) => setData(\"confirm_new_password\", e.target.value)}\n required\n />\n
\n
\n
\n setData(\"end_sessions\", e.target.checked)}\n />\n
\n \n Encerrar todas as sessões ativas\n \n
\n
\n \n \n {processing && (\n
\n \n
\n )}\n updatePassword()}\n disabled={processing}\n />\n
\n
\n
\n );\n};\n\nexport default Password;\n","export const infos = [\n {\n plan: \"Mensal\",\n value: \"R$ 150,00\",\n profissionalNumber: 1,\n paymentDate: \"10/05/2021\",\n planLimit: \"10/05/2021\",\n status: \"Ativo\",\n }, \n {\n plan: \"Mensal\",\n value: \"R$ 150,00\",\n profissionalNumber: 1,\n paymentDate: \"10/05/2021\",\n planLimit: \"10/05/2021\",\n status: \"Ativo\",\n }, \n {\n plan: \"Mensal\",\n value: \"R$ 150,00\",\n profissionalNumber: 1,\n paymentDate: \"10/05/2021\",\n planLimit: \"10/05/2021\",\n status: \"Ativo\",\n }, \n];\n","import { CalendarDaysIcon, CheckCircleIcon, UsersIcon } from \"@heroicons/react/24/outline\";\nimport { Text } from \"@switchdreams/ui\";\nimport { createColumnHelper } from \"@tanstack/react-table\";\nimport React from \"react\";\n\nimport Table from \"./index\";\n\nconst planFormatter = (name) => {\n return {name};\n};\n\nconst status = (statusName) => {\n return (\n
\n \n {statusName}\n
\n );\n};\n\nconst ProfessionalNumberFormatter = (number) => {\n return (\n
\n \n {number}\n
\n );\n};\n\nconst DateFormatter = (date) => {\n return (\n
\n \n {date}\n
\n );\n};\n\nconst valueFormatter = (value) => {\n return {value};\n};\n\nconst columnHelper = createColumnHelper();\n\nconst columns = [\n columnHelper.accessor(\"plan\", {\n header: () => \"Plano\",\n cell: (info) => planFormatter(info.row.original.plan),\n }),\n columnHelper.accessor(\"profissionalNumber\", {\n header: () => \"Profissionais\",\n cell: (info) => ProfessionalNumberFormatter(info.row.original.profissionalNumber),\n }),\n columnHelper.accessor(\"paymentDate\", {\n header: () => \"Data do Pagamento\",\n cell: (info) => DateFormatter(info.row.original.paymentDate),\n }),\n columnHelper.accessor(\"planLimit\", {\n header: () => \"Vencimento do plano\",\n cell: (info) => DateFormatter(info.row.original.planLimit),\n }),\n columnHelper.accessor(\"value\", {\n header: () => \"Valor\",\n cell: (info) => valueFormatter(info.row.original.value),\n }),\n columnHelper.accessor(\"Status\", {\n header: () => \"Status\",\n cell: (info) => status(info.row.original.status),\n }),\n];\n\nconst HistoryTable = ({ info }) => {\n return (\n \n );\n};\n\nexport default HistoryTable;\n","import { ArrowsRightLeftIcon } from \"@heroicons/react/24/outline\";\nimport { AccordionMenu, Button, RadioButton, Text } from \"@switchdreams/ui\";\nimport React, { useState } from \"react\";\n\nimport ConfigurationSidebar from \"@/components/ConfigurationPagesSidebar\";\nimport HistoryTable from \"@/components/Table/historyTable\";\nimport { imagePath } from \"@/utils\";\n\nimport { infos } from \"./constants\";\n\nconst Options = [\n {\n time: 1,\n title: \"Mensal\",\n parcelas: \"\",\n descripition: \"Plano Padrão\",\n }\n // },\n // {\n // time: 3,\n // title: \"Trimestral\",\n // parcelas: \"3x\",\n // descripition: \"Três meses com taxa reduzida.\",\n // },\n // {\n // time: 6,\n // title: \"Semestral\",\n // parcelas: \"6x\",\n // descripition: \"Plano ideal e mais popular.\",\n // },\n // {\n // time: 12,\n // title: \"Anual\",\n // parcelas: \"12x\",\n // descripition: \"Compromisso anual com excelência.\",\n // },\n];\n\nconst calculateValue = (type, number) => {\n const prices = {\n Mensal: [\"150,00\", \"150,00\", \"150,00\", \"150,00\"],\n Trimestral: [\"150,00\", \"140,00\", \"130,00\", \"120,00\"],\n Semestral: [\"125,00\", \"115,00\", \"110,00\", \"105,00\"],\n Anual: [\"100,00\", \"95,00\", \"90,00\", \"80,00\"],\n };\n const index = Math.min(number, prices[type].length - 1);\n return prices[type][index];\n};\n\nconst plan = ({ currentUser }) => {\n const activePlan = currentUser.active_plan;\n const [number, setNumber] = useState(0);\n\n return (\n
\n
\n \n
\n {activePlan && (\n <>\n \n Meu plano atual\n \n
\n
\n
\n
\n \n
\n
\n \n {currentUser.active_plan}\n \n
\n \n 3 profissionais adicionados\n \n
\n
\n
\n
\n \n R$ 450,00\n \n \n por mês\n \n
\n
\n
\n \n Renovação em 19.08.2024\n \n
\n
\n \n )}\n {activePlan ? (\n \n
\n {/* \n Quantidade de profissionais na clínica:\n \n
\n {[0, 1, 2, 3].map((count) => (\n setNumber(count)}\n />\n ))}\n
*/}\n
\n {Options.map((option, idx) => {\n return (\n \n
\n
\n \n {option.time}\n \n
\n
\n
\n \n {option.title}\n \n
\n \n {option.parcelas ? `até ${option.parcelas} de` : \"\"}{\" \"}\n \n R$ {calculateValue(option.title, number)}\n {\" \"}\n por profissional\n \n
\n \n {option.descripition}\n \n
\n
\n \n
\n );\n })}\n
\n
\n \n ) : (\n <>\n \n Plano de assinatura\n \n \n Quantidade de profissionais na clínica:\n \n
\n {[0, 1, 2, 3].map((count) => (\n setNumber(count)}\n />\n ))}\n
\n
\n {Options.map((option, idx) => {\n return (\n \n
\n
\n \n {option.time}\n \n
\n
\n
\n \n {option.title}\n \n
\n \n {option.parcelas ? `até ${option.parcelas} de` : \"\"}{\" \"}\n \n R$ {calculateValue(option.title, number)}\n {\" \"}\n por profissional\n \n
\n \n {option.descripition}\n \n
\n
\n \n
\n );\n })}\n
\n \n )}\n \n
\n \n
\n \n
\n
\n
\n );\n};\n\nexport default plan;\n","import {\n CalendarDaysIcon,\n CheckCircleIcon,\n ChevronRightIcon,\n ClockIcon,\n XCircleIcon,\n} from \"@heroicons/react/24/outline\";\nimport { Avatar, Badge, Text } from \"@switchdreams/ui\";\nimport { createColumnHelper } from \"@tanstack/react-table\";\nimport React from \"react\";\n\nimport { formatIntegerCurrency } from \"../../utils\";\nimport Table from \"./index\";\n\nconst user = (name, image) => {\n return (\n
\n \n {name}\n
\n );\n};\n\nconst status = (paymentStatus, transferStatus, updatedAt) => {\n const statusTranslate = () => {\n if (paymentStatus == \"pending\" && transferStatus == \"waiting\") {\n return {\n label: \"Aguardando pagamento\",\n type: \"warning\",\n };\n } else if (paymentStatus == \"paid\" && transferStatus == \"waiting\") {\n const paymentDate = new Date(updatedAt);\n paymentDate.setDate(paymentDate.getDate() + 30);\n const today = new Date();\n const days = Math.trunc((paymentDate - today) / (1000 * 60 * 60 * 24));\n return {\n label: `Pagamento em aproximadamente ${days} dias`,\n type: \"warning\",\n };\n } else if (paymentStatus == \"paid\" && transferStatus == \"success\") {\n return {\n label: \"Pago\",\n type: \"success\",\n };\n } else {\n return {\n label: \"Erro\",\n type: \"error\",\n };\n }\n };\n return (\n
\n \n
\n );\n};\n\nconst Timer = (time) => {\n return (\n
\n \n {time}\n
\n );\n};\n\nconst DateFormatter = (dateObj) => {\n const date = new Date(dateObj);\n return (\n
\n \n {`${date.getDate()}/${date.getMonth() + 1}/${date.getFullYear()}`}\n
\n );\n};\n\nconst ValueFormatter = (value) => {\n return (\n
\n {formatIntegerCurrency(value)}\n
\n );\n};\n\nconst columnHelper = createColumnHelper();\n\nconst columns = [\n columnHelper.accessor(\"pacient\", {\n header: () => \"Paciente\",\n cell: (info) => user(info.row.original.patient_name, info.row.original.patient_image),\n }),\n columnHelper.accessor(\"data\", {\n header: () => \"Data de sessão\",\n cell: (info) => DateFormatter(info.row.original.date),\n }),\n columnHelper.accessor(\"hour\", {\n header: () => \"Horário de sessão\",\n cell: (info) => Timer(info.row.original.approximate_start_time),\n }),\n columnHelper.accessor(\"status\", {\n header: () => \"Status\",\n cell: (info) =>\n status(\n info.row.original.payment_status,\n info.row.original.transfer_status,\n info.row.original.updated_at,\n ),\n }),\n columnHelper.accessor(\"value\", {\n header: () => \"Valor\",\n cell: (info) => ValueFormatter(info.row.original.transfer_value_cents),\n }),\n columnHelper.accessor(\"options\", {\n header: \"\",\n cell: () => ,\n }),\n];\n\nconst CustomCell = () => {\n return (\n
\n \n
\n );\n};\n\nconst MonthlyIncomeTable = ({ info }) => {\n return (\n \n );\n};\n\nexport default MonthlyIncomeTable;\n","import { ArrowDownIcon, ArrowUpIcon, ChevronDownIcon } from \"@heroicons/react/24/solid\";\nimport { Badge, Button, Popover, Spinner, Text } from \"@switchdreams/ui\";\nimport axios from \"axios\";\nimport React, { useEffect, useRef, useState } from \"react\";\n\nimport MonthlyIncomeTable from \"@/components/Table/monthlyIncomeTable\";\n\nimport { formatIntegerCurrency, monthsTranslated } from \"../../utils\";\n\nconst monthlyIncome = ({ professional, initial_appointments, pagy, initial_month_info }) => {\n const today = new Date();\n const [selectedDate, setSelectedDate] = useState(new Date());\n const [monthlyData, setMonthlyData] = useState(initial_month_info);\n const [appointments, setAppointments] = useState(initial_appointments);\n const [page, setPage] = useState(2);\n const maxPages = pagy.pages;\n\n const elementRef = useRef(null);\n\n function onIntersection(entries) {\n const firstEntry = entries[0];\n if (firstEntry.isIntersecting && page <= maxPages) {\n getAppointments();\n }\n }\n\n const getAppointments = () => {\n axios.get(`/rendimento.json?page=${page}`).then((response) => {\n setAppointments(appointments.concat(response.data));\n setPage(page + 1);\n });\n };\n\n useEffect(() => {\n const observer = new IntersectionObserver(onIntersection);\n if (observer && elementRef.current) {\n observer.observe(elementRef.current);\n }\n\n return () => {\n if (observer) {\n observer.disconnect();\n }\n };\n });\n\n const monthOptions = () => {\n const startDate = new Date(professional.created_at);\n const months = [];\n\n // Loop through months until reaching today's year and month\n while (\n startDate.getFullYear() < today.getFullYear() ||\n (startDate.getFullYear() === today.getFullYear() && startDate.getMonth() <= today.getMonth())\n ) {\n const thisDate = new Date(startDate);\n const year = startDate.getFullYear().toString();\n const month = startDate.getMonth();\n\n months.push({ label: `${monthsTranslated[month]}, ${year}`, date: thisDate }); // Push month/year string\n\n // Move to the next month\n startDate.setMonth(startDate.getMonth() + 1);\n }\n\n return months;\n };\n\n const ratioBadge = (lastMonthValue, thisMonthValue) => {\n if (lastMonthValue == 0 || thisMonthValue == 0) {\n return \"\";\n }\n const ratio = thisMonthValue / lastMonthValue;\n if (ratio > 1) {\n return (\n
\n \n \n do mês anterior\n \n
\n );\n } else {\n return (\n
\n \n \n do mês anterior\n \n
\n );\n }\n };\n\n useEffect(() => {\n axios.get(`/rendimento.json?date=${selectedDate}`).then((response) => {\n setMonthlyData(response.data);\n });\n }, [selectedDate]);\n\n return (\n
\n
\n
\n
\n
\n \n Rendimento mensal\n \n \n São exibidas somente as consultas finalizadas\n \n
\n \n \n {`${monthsTranslated[selectedDate.getMonth()]}, ${selectedDate.getFullYear()}`}\n \n \n
\n }\n >\n {monthOptions().map((month, idx) => {\n return (\n
\n
\n );\n })}\n \n
\n
\n
\n \n Valor total recebido\n \n
\n {true && ratioBadge(monthlyData.last_income, monthlyData.monthly_income)}\n
\n \n {formatIntegerCurrency(monthlyData.monthly_income)}\n \n
\n
\n
\n
\n \n Valor total a receber\n \n
\n {true &&\n ratioBadge(monthlyData.last_pending_income, monthlyData.monthly_pending_income)}\n
\n \n {formatIntegerCurrency(monthlyData.monthly_pending_income)}\n \n
\n
\n
\n
\n \n Consultas realizadas\n \n
\n {selectedDate.getMonth() != new Date(professional.created_at).getMonth() &&\n ratioBadge(monthlyData.last_appointments, monthlyData.monthly_appointments)}\n
\n \n {monthlyData.monthly_appointments}\n \n
\n
\n
\n
\n \n Novos pacientes\n \n
\n {selectedDate.getMonth() != new Date(professional.created_at).getMonth() &&\n ratioBadge(monthlyData.last_new_patients, monthlyData.monthly_new_patients)}\n
\n \n {monthlyData.monthly_new_patients}\n \n
\n
\n
\n
\n
\n \n Histórico de consultas\n \n
\n \n {page <= maxPages && (\n
\n \n
\n )}\n
\n
\n \n );\n};\n\nexport default monthlyIncome;\n","import { router, usePage } from \"@inertiajs/react\";\nimport React, { useEffect, useRef, useState } from \"react\";\n\nimport Modal from \"@/components/Modal\";\nimport { useAlert } from \"@/contexts/Alert\";\nimport { imagePath } from \"@/utils\";\nimport SimpleClinicCard from \"../../components/Cards/SimpleClinicCard\";\n\nconst ExamDetails = () => {\n const sortOptions = [\n { label: \"Alfabética\", value: \"alphabetical\" },\n { label: \"Número de pacientes atendido\", value: \"patients_count\" },\n { label: \"Tempo no site\", value: \"created_at\" },\n ];\n\n\n const { showAlert } = useAlert();\n const [open, setOpen] = useState(false);\n const [clinics, setClinics] = useState([]);\n const [files, setFiles] = useState([]);\n const [description, setDescription] = useState('');\n const { data } = usePage().props;\n const elementRef = useRef(null);\n\n\n useEffect(() => {\n let data = localStorage.getItem(\"clinics\");\n data = JSON.parse(data);\n\n setClinics(data);\n }, [])\n\n useEffect(() => {\n if(data !== undefined){\n setOpen(true)\n }\n }, [data])\n\n const redirectExams = () => {\n router.visit(`/exams/budgets/${data.id}`)\n }\n\n const onFileChange = (event) => {\n setFiles(event.target.files)\n };\n\n const sendData = async () => {\n if(Object.keys(files).length == 0){\n showAlert({ message: 'Você deve enviar pelo menos 1 exame' });\n return;\n }\n const formData = new FormData();\n formData.append('description', description);\n clinics.map((item) => {\n formData.append('clinic_ids[]', item.id);\n })\n\n Object.keys(files).map((item) => {\n formData.append('attachments[]', files[item]);\n })\n\n router.post('/exams/budgets', formData)\n }\n\n\n return (\n <>\n {redirectExams()}}\n >\n
\n
\n
\n \n
\n
Orçamentos Enviados com Sucesso
\n
Aguarde a confirmação das clínicas, você será notificado por e-mail
\n
\n
\n \n
\n
\n
\n
Clínicas Selecionadas
\n

\n Seus Exames serão enviados para essas clínicas e você receberá o retorno dos\n orçamentos o quanto antes\n

\n
\n {\n clinics.map((item) => (\n <>\n \n \n ))\n }\n
\n\n
\n
\n
\n
\n
\n Solicite um Orçamento\n
\n
\n
\n
\n
\n \n
\n
\n Clique aqui para fazer o envio do\n
\n seu pedido médico. (.jpg, .pdf, .png)\n
\n
\n \n
\n {\n Object.keys(files).map((item) => (\n <>\n {files[item].name}
\n \n ))\n }\n
\n
\n
\n
\n Informações adicionais (opcional)\n
\n
\n setDescription(e.target.value)}\n rows=\"5\"\n placeholder=\"Dê uma descrição, escreva informações importantes ou compartilhe qualquer coisa que você achar necessário.\"\n className=\"shrink grow basis-0 self-stretch font-['Poppins'] text-base font-normal leading-snug text-[#98a1b2]\"\n />\n
\n \n
\n
\n
\n
\n\n
\n \n );\n};\n\nexport default ExamDetails;\n","import { ChevronDownIcon, MagnifyingGlassIcon, MapPinIcon } from \"@heroicons/react/24/solid\";\nimport { Link } from \"@inertiajs/react\";\nimport { Button, Popover, Select, Spinner, Text } from \"@switchdreams/ui\";\nimport React, { useEffect, useReducer, useRef, useState } from \"react\";\nimport Modal from \"react-modal\";\n\nimport ExamCard from \"@/components/Cards/ExamCard\";\nimport { stateOptions } from \"@/constants/SelectOptions\";\nimport { useAlert } from \"@/contexts/Alert\";\nimport { imagePath, specialtyOptions, workAreaOptionsFetch } from \"@/utils\";\n\nimport SelectedClinicsCard from \"../../components/Cards/SelectedClinicsCard\";\n\nconst ExamsSearch = ({\n clinics,\n specialties_options,\n states_options,\n cities_by_state_options,\n pagy,\n}) => {\n const sortOptions = [\n { label: \"Alfabética\", value: \"alphabetical\" },\n { label: \"Número de pacientes atendido\", value: \"patients_count\" },\n { label: \"Tempo no site\", value: \"created_at\" },\n ];\n console.log(clinics)\n\n // Params from url\n const workSpecialtyIdFromUrl = parseInt(\n new URLSearchParams(window.location.search).get(\"work_specialty_id\"),\n );\n const workAreaIdFromUrl = parseInt(\n new URLSearchParams(window.location.search).get(\"work_specialty_id\"),\n );\n\n const [professionals, setProfessionals] = useState(clinics);\n const [sort, setSort] = useState(sortOptions[0]);\n const [countSelected, setCountSelected] = useState(0);\n const [workAreaClinic, setWorkAreaClinic] = useState(\"\");\n const [specialty, setSpecialty] = useState(null);\n const [state, setState] = useState(null);\n const [city, setCity] = useState([]);\n const [cityOptions, setCityOptions] = useState([]);\n const [allStates, setAllStates] = useState([]);\n const [isLoading, setIsLoading] = useState(false);\n const [workAreaOptions, setWorkAreaOptions] = useState([]);\n const [specialtiesOptions, setSpecialtiesOptions] = useState([]);\n const { showAlert } = useAlert();\n const [openReviews, setOpenReviews] = useState(false);\n const [openImages, setOpenImages] = useState(false);\n const [reviews, setReviews] = useState([]);\n const [images, setImages] = useState([]);\n // Pagination\n const [page, setPage] = useState(0);\n const [maxPages, setMaxPages] = useState(pagy.pages);\n const [count, setCount] = useState(pagy.count);\n const [firstLoad, setFirstLoad] = useState(true);\n\n const elementRef = useRef(null);\n\n function onIntersection(entries) {\n const firstEntry = entries[0];\n if (firstEntry.isIntersecting && page <= maxPages) {\n getData(\"add\");\n }\n }\n\n useEffect(() => {\n let statesArr = states_options.map((item) => ({\n value: item.state,\n label: item.state,\n }));\n setAllStates(statesArr);\n }, []);\n\n const selectState = (selectedState) => {\n let citiesData = cities_by_state_options[selectedState.value].map((item) => ({\n value: item,\n label: item,\n }));\n setCityOptions(citiesData);\n setState(selectedState);\n };\n\n useEffect(() => {\n const observer = new IntersectionObserver(onIntersection);\n if (observer && elementRef.current) {\n observer.observe(elementRef.current);\n }\n\n return () => {\n if (observer) {\n observer.disconnect();\n }\n };\n }, []);\n\n const openReviewsModal = (reviewData) => {\n if (reviewData.reviews.length > 0) {\n setOpenReviews(true);\n setReviews(reviewData.reviews);\n }\n };\n\n const openImagesModal = (imageData) => {\n if (imageData.user_media.length > 0) {\n setOpenImages(true);\n setImages(imageData.user_media);\n }\n };\n\n const [, forceUpdate] = useReducer((x) => x + 1, 0);\n\n const selectClinic = (idx, data) => {\n let allData = professionals;\n allData[idx].selected = !allData[idx].selected;\n\n if (allData[idx].selected == true) {\n if (countSelected < 3) {\n setCountSelected(countSelected + 1);\n setProfessionals(allData);\n } else {\n allData[idx].selected = !allData[idx].selected;\n showAlert({\n message: \"Você pode selecionar no máximo três clínicas!\",\n type: \"warning\",\n });\n }\n } else {\n setCountSelected(countSelected - 1);\n setProfessionals(allData);\n }\n\n forceUpdate();\n\n let arr = [];\n allData.map((item) => {\n if (item.selected == true) {\n arr.push(item);\n }\n });\n localStorage.setItem(\"clinics\", JSON.stringify(arr));\n };\n\n const formatDate = (date) => {\n const dateTime = new Date(date);\n return dateTime.toLocaleString();\n };\n\n useEffect(() => {\n // TODO: PERFOMANCE Improves to make only one fetch\n // Set select inputs\n workAreaOptionsFetch(setWorkAreaOptions);\n specialtyOptions(setSpecialtiesOptions);\n // Set state\n const state = states_options.find(\n (option) => option.state == new URLSearchParams(window.location.search).get(\"state\"),\n );\n const getCity = new URLSearchParams(window.location.search).get(\"city\");\n if (state) {\n selectState({ value: state.state, label: state.state });\n }\n setCity({ value: getCity, label: getCity });\n }, []);\n\n // Set work area from URL\n useEffect(() => {\n if (workAreaOptions) {\n const specialty = specialties_options.find((option) => option.value == workAreaIdFromUrl);\n if (specialty) {\n setWorkAreaClinic(specialty);\n }\n }\n }, [workAreaOptions]);\n\n // Set specialty from URL\n useEffect(() => {\n if (specialtiesOptions) {\n const specialty = specialtiesOptions.find((option) => option.value == workSpecialtyIdFromUrl);\n if (specialty) {\n setSpecialty(specialty);\n }\n }\n }, [specialtiesOptions]);\n\n useEffect(() => {\n if (workAreaClinic === \"\") {\n return;\n }\n\n // find workArea selected\n const selectedWorkArea = workAreaOptions.find(\n (option) => option.value === workAreaClinic.value,\n );\n const specialties =\n selectedWorkArea?.work_specialities?.map((specialty) => {\n return {\n value: specialty.id,\n label: specialty.name,\n };\n }) || [];\n setSpecialtiesOptions(specialties);\n }, [workAreaClinic]);\n\n useEffect(() => {\n if (firstLoad) {\n setPage(1);\n setFirstLoad(false);\n }\n }, [specialty, sort, state]);\n\n return (\n <>\n setOpenImages(false)}\n className=\"mx-auto my-6 w-full max-w-4xl rounded-lg bg-white shadow-2xl\"\n overlayClassName=\"fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center\"\n >\n
\n
\n setOpenImages(false)}\n className=\"absolute right-2 top-2 text-gray-600 hover:text-gray-800\"\n aria-label=\"Fechar\"\n >\n ×\n \n

Imagens

\n
\n
\n
\n
\n {images.map((item, i) => (\n
\n \n
\n ))}\n
\n
\n \n setOpenReviews(false)}\n className=\"mx-auto my-6 w-full max-w-lg rounded-lg bg-white shadow-2xl \"\n overlayClassName=\"fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center\"\n >\n
\n
\n setOpenReviews(false)}\n className=\"absolute right-2 top-2 text-gray-600 hover:text-gray-800\"\n aria-label=\"Fechar\"\n >\n ×\n \n

Avaliações

\n
\n
\n
\n {\" \"}\n {/* Usar espaço vertical entre as avaliações */}\n {reviews.map((review, index) => (\n
\n {\" \"}\n {/* Estilo melhorado */}\n
\n {formatDate(review?.created_at)}\n
\n
\n {\"Avaliação\"}\n
\n
\n {[1, 2, 3, 4, 5].map((star) => (\n = star ? \"text-yellow-500\" : \"text-gray-300\"\n }`}\n >\n ★\n \n ))}\n
\n
\n {review?.description || \"Nenhuma descrição fornecida.\"}\n
\n
\n ))}\n
\n \n
\n
\n
\n \n Exames de qualidade com as melhores clínicas da sua região!\n \n
\n
\n
\n setWorkAreaClinic(e)}\n />\n
\n
\n
\n
\n selectState(e)}\n />\n
\n
\n setCity(e)}\n />\n
\n
\n \n \n \n
\n
\n \n
\n
\n
\n
\n
\n
\n
\n
\n \n Encontramos\n \n \n {count} Clínicas\n \n
\n
\n \n Ordenar por:\n \n \n \n {sort.label}\n \n \n
\n }\n >\n
\n {sortOptions.map((option, key) => {\n return (\n
\n
\n );\n })}\n
\n \n
\n
\n
\n {isLoading ? (\n \n ) : (\n professionals.map((info, idx) => {\n return (\n selectClinic(idx, info)}\n onClickReviews={() => openReviewsModal(info)}\n onClickImages={() => openImagesModal(info)}\n selected={info.selected}\n />\n );\n })\n )}\n {page < maxPages && (\n
\n \n
\n )}\n
\n \n {/*
\n \n
*/}\n
\n \n Encontre a especialidade que você precisa!\n \n
\n {specialtiesOptions.map((Option, idx) => {\n return (\n {\n window.scroll({ top: 0, behavior: \"smooth\" });\n setSpecialty(Option.value);\n }}\n >\n \n {Option.label}\n \n
\n );\n })}\n
\n
\n
\n
\n \n );\n};\n\nexport default ExamsSearch;\n","export const DoctorInfo = [\n {\n name: \"Dr. José Montenegro\",\n verified: true,\n img: \"\",\n specility: \"Clínico Geral e Cardiologista\",\n timeOnSite: \"3 meses\",\n patients: 235,\n description:\n \"Formado em Medicina e especializado em Cardiologia pela Unifesp. Com mais de 14 anos de experiência clínica, estou comprometido em oferecer diagnósticos precisos e tratamentos personalizados a todos.\",\n starts: 5,\n evaluations: 36,\n clinicName: \"Consultório José Montenegro\",\n address: \"Praça Santo Agostinho 70, Brasília\",\n logo: \"\",\n dates: [\n {\n day: \"Segunda\",\n times: [\n \"8:00\",\n \"9:00\",\n \"10:00\",\n \"11:00\",\n \"12:00\",\n \"13:00\",\n \"14:00\",\n \"15:00\",\n \"16:00\",\n \"17:00\",\n ],\n },\n {\n day: \"Terça\",\n times: [\n \"8:00\",\n \"9:00\",\n \"10:00\",\n \"11:00\",\n \"12:00\",\n \"13:00\",\n \"14:00\",\n \"15:00\",\n \"16:00\",\n \"17:00\",\n ],\n },\n {\n day: \"Quarta\",\n times: [\n \"8:00\",\n \"9:00\",\n \"10:00\",\n \"11:00\",\n \"12:00\",\n \"13:00\",\n \"14:00\",\n \"15:00\",\n \"16:00\",\n \"17:00\",\n ],\n },\n {\n day: \"Quinta\",\n times: [\n \"8:00\",\n \"9:00\",\n \"10:00\",\n \"11:00\",\n \"12:00\",\n \"13:00\",\n \"14:00\",\n \"15:00\",\n \"16:00\",\n \"17:00\",\n ],\n },\n {\n day: \"Sexta\",\n times: [\n \"8:00\",\n \"9:00\",\n \"10:00\",\n \"11:00\",\n \"12:00\",\n \"13:00\",\n \"14:00\",\n \"15:00\",\n \"16:00\",\n \"17:00\",\n ],\n },\n {\n day: \"Sábado\",\n times: [\"8:00\", \"9:00\", \"10:00\"],\n },\n ],\n },\n {\n name: \"Dra. Maria Silva\",\n verified: true,\n img: \"\",\n specility: \"Pediatra\",\n timeOnSite: \"1 ano\",\n patients: 320,\n description:\n \"Especialista em Pediatria pela USP, com 10 anos de experiência. Apaixonada por cuidar da saúde das crianças, proporcionando um atendimento humanizado e de qualidade.\",\n starts: 5,\n evaluations: 45,\n clinicName: \"Clínica Pediátrica Maria Silva\",\n address: \"Rua das Flores 123, São Paulo\",\n logo: \"\",\n dates: [\n {\n day: \"Segunda\",\n times: [\"9:00\", \"10:00\", \"11:00\", \"13:00\", \"14:00\", \"15:00\", \"16:00\", \"17:00\"],\n },\n {\n day: \"Terça\",\n times: [\"9:00\", \"10:00\", \"11:00\", \"13:00\", \"14:00\", \"15:00\", \"16:00\", \"17:00\"],\n },\n {\n day: \"Quarta\",\n times: [\"9:00\", \"10:00\", \"11:00\", \"13:00\", \"14:00\", \"15:00\", \"16:00\", \"17:00\"],\n },\n {\n day: \"Quinta\",\n times: [\"9:00\", \"10:00\", \"11:00\", \"13:00\", \"14:00\", \"15:00\", \"16:00\", \"17:00\"],\n },\n {\n day: \"Sexta\",\n times: [\"9:00\", \"10:00\", \"11:00\", \"13:00\", \"14:00\", \"15:00\", \"16:00\", \"17:00\"],\n },\n {\n day: \"Sábado\",\n times: [\"9:00\", \"10:00\"],\n },\n ],\n },\n {\n name: \"Dr. Carlos Andrade\",\n verified: true,\n img: \"\",\n specility: \"Dermatologista\",\n timeOnSite: \"6 meses\",\n patients: 180,\n description:\n \"Formado pela UFRJ com especialização em Dermatologia. Experiência de 8 anos no tratamento de doenças de pele, cabelo e unhas, com foco em procedimentos estéticos.\",\n starts: 4,\n evaluations: 27,\n clinicName: \"Clínica Dermatológica Carlos Andrade\",\n address: \"Av. Atlântica 456, Rio de Janeiro\",\n logo: \"\",\n dates: [\n {\n day: \"Segunda\",\n times: [\"10:00\", \"11:00\", \"12:00\", \"13:00\", \"14:00\", \"15:00\", \"16:00\", \"17:00\", \"18:00\"],\n },\n {\n day: \"Terça\",\n times: [\"10:00\", \"11:00\", \"12:00\", \"13:00\", \"14:00\", \"15:00\", \"16:00\", \"17:00\", \"18:00\"],\n },\n {\n day: \"Quarta\",\n times: [\"10:00\", \"11:00\", \"12:00\", \"13:00\", \"14:00\", \"15:00\", \"16:00\", \"17:00\", \"18:00\"],\n },\n {\n day: \"Quinta\",\n times: [\"10:00\", \"11:00\", \"12:00\", \"13:00\", \"14:00\", \"15:00\", \"16:00\", \"17:00\", \"18:00\"],\n },\n {\n day: \"Sexta\",\n times: [\"10:00\", \"11:00\", \"12:00\", \"13:00\", \"14:00\", \"15:00\", \"16:00\", \"17:00\", \"18:00\"],\n },\n {\n day: \"Sábado\",\n times: [\"10:00\", \"11:00\", \"12:00\"],\n },\n ],\n },\n {\n name: \"Dra. Fernanda Costa\",\n verified: true,\n img: \"\",\n specility: \"Ginecologista e Obstetra\",\n timeOnSite: \"2 anos\",\n patients: 410,\n description:\n \"Especialista em Ginecologia e Obstetrícia pela UNICAMP. Com mais de 12 anos de experiência, foco em saúde da mulher, acompanhamento pré-natal e partos humanizados.\",\n starts: 5,\n evaluations: 52,\n clinicName: \"Centro de Saúde da Mulher Fernanda Costa\",\n address: \"Rua dos Pinheiros 789, Campinas\",\n logo: \"\",\n dates: [\n {\n day: \"Segunda\",\n times: [\n \"8:00\",\n \"9:00\",\n \"10:00\",\n \"11:00\",\n \"12:00\",\n \"13:00\",\n \"14:00\",\n \"15:00\",\n \"16:00\",\n \"17:00\",\n ],\n },\n {\n day: \"Terça\",\n times: [\n \"8:00\",\n \"9:00\",\n \"10:00\",\n \"11:00\",\n \"12:00\",\n \"13:00\",\n \"14:00\",\n \"15:00\",\n \"16:00\",\n \"17:00\",\n ],\n },\n {\n day: \"Quarta\",\n times: [\n \"8:00\",\n \"9:00\",\n \"10:00\",\n \"11:00\",\n \"12:00\",\n \"13:00\",\n \"14:00\",\n \"15:00\",\n \"16:00\",\n \"17:00\",\n ],\n },\n {\n day: \"Quinta\",\n times: [\n \"8:00\",\n \"9:00\",\n \"10:00\",\n \"11:00\",\n \"12:00\",\n \"13:00\",\n \"14:00\",\n \"15:00\",\n \"16:00\",\n \"17:00\",\n ],\n },\n {\n day: \"Sexta\",\n times: [\n \"8:00\",\n \"9:00\",\n \"10:00\",\n \"11:00\",\n \"12:00\",\n \"13:00\",\n \"14:00\",\n \"15:00\",\n \"16:00\",\n \"17:00\",\n ],\n },\n {\n day: \"Sábado\",\n times: [\"8:00\", \"9:00\", \"10:00\"],\n },\n ],\n },\n {\n name: \"Dr. Paulo Moreira\",\n verified: true,\n img: \"\",\n specility: \"Ortopedista\",\n timeOnSite: \"9 meses\",\n patients: 290,\n description:\n \"Graduado pela USP com especialização em Ortopedia e Traumatologia. Experiência de 11 anos em tratamentos de fraturas, lesões esportivas e cirurgias ortopédicas.\",\n starts: 4,\n evaluations: 40,\n clinicName: \"Ortopedia Paulo Moreira\",\n address: \"Rua das Palmeiras 250, Belo Horizonte\",\n logo: \"\",\n dates: [\n {\n day: \"Segunda\",\n times: [\n \"7:00\",\n \"8:00\",\n \"9:00\",\n \"10:00\",\n \"11:00\",\n \"12:00\",\n \"13:00\",\n \"14:00\",\n \"15:00\",\n \"16:00\",\n ],\n },\n {\n day: \"Terça\",\n times: [\n \"7:00\",\n \"8:00\",\n \"9:00\",\n \"10:00\",\n \"11:00\",\n \"12:00\",\n \"13:00\",\n \"14:00\",\n \"15:00\",\n \"16:00\",\n ],\n },\n {\n day: \"Quarta\",\n times: [\n \"7:00\",\n \"8:00\",\n \"9:00\",\n \"10:00\",\n \"11:00\",\n \"12:00\",\n \"13:00\",\n \"14:00\",\n \"15:00\",\n \"16:00\",\n ],\n },\n {\n day: \"Quinta\",\n times: [\n \"8:00\",\n \"9:00\",\n \"10:00\",\n \"11:00\",\n \"12:00\",\n \"13:00\",\n \"14:00\",\n \"15:00\",\n \"16:00\",\n \"17:00\",\n ],\n },\n {\n day: \"Sexta\",\n times: [\n \"8:00\",\n \"9:00\",\n \"10:00\",\n \"11:00\",\n \"12:00\",\n \"13:00\",\n \"14:00\",\n \"15:00\",\n \"16:00\",\n \"17:00\",\n ],\n },\n {\n day: \"Sábado\",\n times: [\"8:00\", \"9:00\", \"10:00\"],\n },\n ],\n },\n];\n\nexport const Options = [\n \"Alergia e Imunologia\",\n \"Dermatologista\",\n \"Neurocirurgia\",\n \"Infectiologia\",\n \"Anestesiologia\",\n \"Coloproctologia\",\n \"Neurologia\",\n \"Mastologia\",\n \"Angiologia\",\n \"Cirurgia Torácica\",\n \"Nutrologia\",\n \"Medicina Física e Reabilitação\",\n \"Cancerologia / Oncologia\",\n \"Cirurgia Vascular\",\n \"Oftalmologia\",\n \"Nefrologia\",\n \"Cardiologia\",\n \"Endocrinologia\",\n \"Ortopedia e Traumatologia\",\n \"Neurocirurgia\",\n \"Cirurgia Cardiovascular\",\n \"Gastroenterologia\",\n \"Otorrinolaringologia\",\n \"Neurologia\",\n \"Cirurgia de Mão\",\n \"Genética Médica\",\n \"Pediatria\",\n \"Nutrologia\",\n \"Cirurgia de Cabeça e Pescoço\",\n \"Geriatria\",\n \"Pneumologia\",\n \"Oftalmologia\",\n \"Cirurgia de Aparelho Digestivo\",\n \"Ginecologia e Hemoterapia\",\n \"Psiquiatria\",\n \"Ortopedia e Traumatologia\",\n \"Cirurgia Geral\",\n \"Infectiologia\",\n \"Reumatologia\",\n \"Otorrinolaringologia\",\n \"Cirurgia Pediátrica\",\n \"Mastologia\",\n \"Urologia\",\n \"Cirurgia Plástica\",\n \"Medicina Física e Reabilitação\",\n \"Clínica de Exames Radiológicos\",\n \"Pneumologia\",\n \"Clínica Médica\",\n \"Nefrologia\",\n \"Laboratórios de Análises Clínicas e Patológicas\",\n];\n","import { AccordionMenu, Text } from \"@switchdreams/ui\";\nimport React from \"react\";\n\nconst FaqSection = () => {\n return (\n
\n
\n \n PERGUNTAS FREQUENTES (FAQ)\n \n \n Tire suas dúvidas\n \n \n Bem-vindo à nossa seção de Perguntas Frequentes (FAQ)! Aqui, reunimos as dúvidas mais\n comuns dos nossos usuários para oferecer respostas claras e abrangentes. Se você tem\n perguntas sobre como funciona o viaconsultas, como se cadastrar, ou qualquer outro\n aspecto relacionado à nossa plataforma, você está no lugar certo! Explore as perguntas\n abaixo para encontrar as respostas que você precisa:\n \n
\n \n \n Ao se cadastrar no viaconsultas, você terá acesso a uma série de benefícios\n exclusivos, incluindo maior visibilidade para sua clínica, prospecção ativa de pacientes,\n independência dos planos de saúde, facilidade no faturamento, redução do absenteísmo e\n cancelamentos de consultas, flexibilidade na agenda.\n \n \n \n \n O processo de agendamento de consultas é simples e intuitivo para os pacientes. Eles podem\n acessar nossa plataforma, encontrar sua clínica ou consultório, verificar sua\n disponibilidade de horários e agendar uma consulta diretamente, sem complicações. Isso\n proporciona uma experiência conveniente e eficiente para os pacientes, aumentando as\n chances de agendamentos bem-sucedidos.\n \n \n \n \n No viaconsultas, levamos a segurança e privacidade dos dados muito a sério.\n Implementamos medidas robustas de proteção de dados para garantir a segurança tanto dos\n profissionais cadastrados quanto dos pacientes. Além disso, seguimos estritamente as\n regulamentações de proteção de dados, proporcionando tranquilidade e confiança a todos os\n usuários da nossa plataforma.\n \n \n \n \n Estamos aqui para ajudar! Caso você tenha alguma dúvida ou problema técnico, nossa equipe\n de suporte está disponível para fornecer assistência rápida e eficiente. Você pode entrar\n em contato conosco através dos nossos canais de atendimento, garantindo uma experiência\n tranquila e satisfatória com o viaconsultas.\n \n \n
\n );\n};\n\nexport default FaqSection;\n","import { Text } from \"@switchdreams/ui\";\nimport React from \"react\";\n\nconst AboutSection = () => {\n return (\n \n
\n
\n APRESENTAÇÃO\n \n Conheça as soluções da nossa plataforma!\n \n \n Descubra como o viaconsultas pode transformar sua clínica ou consultório,\n proporcionando uma alta captação de pacientes particulares de maneira acessível, rápida e\n conveniente. Assista ao nosso vídeo institucional e mergulhe em uma visão detalhada de\n como nossa plataforma pode impulsionar o crescimento e a visibilidade do seu negócio na\n área da saúde.\n \n
\n \n
\n );\n};\n\nexport default AboutSection;\n","import { ArrowLongRightIcon } from \"@heroicons/react/24/outline\";\nimport { Link } from \"@inertiajs/react\";\nimport { Button, Text } from \"@switchdreams/ui\";\nimport React from \"react\";\n\nimport { imagePath } from \"../../../utils\";\n\nconst AppealSection = () => {\n return (\n
\n
\n \n Consultas e exames ao alcance de todos\n \n \n \n \n
\n
\n
\n \n
\n
\n Para o\n \n paciente\n \n
\n \n atendimento de qualidade, em tempo hábil e com valores mais acessíveis.\n \n
\n
\n
\n
\n \"Ícone\n
\n
\n Para os\n \n profissionais\n \n
\n \n Promovemos suas Clínicas ampliando o número de pacientes para completar suas agendas.\n \n
\n
\n
\n
\n \n
\n
\n Para a\n \n sociedade\n \n
\n \n facilitar o acesso aos profissionais de saúde, proporcionando maior qualidade de vida\n \n
\n
\n
\n \n \n \n
\n );\n};\n\nexport default AppealSection;\n","import {\n CalendarDaysIcon,\n CursorArrowRippleIcon,\n TvIcon,\n WrenchScrewdriverIcon,\n} from \"@heroicons/react/24/outline\";\nimport { Text } from \"@switchdreams/ui\";\nimport React from \"react\";\n\nconst Cells = [\n {\n icon: ,\n name: \"Maior Visibilidade Profissional\",\n description:\n \"Potencialize sua visibilidade e influência profissional. Atraia uma ampla base de pacientes em busca de assistência médica e reduza as taxas de absenteísmo em sua clínica.\",\n },\n {\n icon: ,\n name: \"Flexibilidade de Agenda\",\n description:\n \"Aprimore sua prática médica com um gerenciamento de agenda flexível e personalizado. Cadastre sua clínica e ajuste seus horários de acordo com sua disponibilidade e preferência, simplificando o agendamento para você e seus pacientes\",\n },\n {\n icon: ,\n name: \"Fácil e Intuitiva\",\n description:\n \"Uma plataforma intuitiva e fácil de usar, automatizando as operações de agendamento, tanto para os profissionais como para os pacientes.\",\n },\n {\n icon: ,\n name: \"Suporte Profissional\",\n description:\n \"Conte com o apoio da nossa equipe de profissionais sempre prontos para prestar o melhor atendimento de suporte e facilitar as etapas.\",\n },\n];\n\nconst BenefitsSection = () => {\n return (\n
\n
\n \n BENEFÍCIOS\n \n \n Descubra os Benefícios do viaconsultas\n \n \n Junte-se à nossa comunidade e experimente uma nova forma de cuidados de saúde. Com o\n viaconsultas, você desfrutará de:\n \n
\n
\n {Cells.map((cardCell, idx) => {\n return (\n \n
\n {cardCell.icon}\n
\n \n {cardCell.name}\n \n \n {cardCell.description}\n \n
\n );\n })}\n
\n
\n );\n};\n\nexport default BenefitsSection;\n","import { PlayCircleIcon } from \"@heroicons/react/24/solid\";\nimport { Link } from \"@inertiajs/react\";\nimport { Button, Text } from \"@switchdreams/ui\";\nimport React from \"react\";\n\nimport { imagePath } from \"../../../utils\";\n\nconst HeroSection = () => {\n return (\n
\n
\n \n VIACONSULTAS\n \n \n Mais pacientes particulares com menos burocracia.\n \n
\n \n Não dependa de Planos de Saúde.\n \n \n Tenha mais pacientes particulares na sua Clínica, com agendamentos e pagamentos\n totalmente automatizados.\n \n
\n
\n \n \n \n \n \n \n
\n
\n \n
\n );\n};\n\nexport default HeroSection;\n","import { Link } from \"@inertiajs/react\";\nimport { Button, Text } from \"@switchdreams/ui\";\nimport React from \"react\";\n\nimport { imagePath } from \"../../../utils\";\n\nconst InfoSection = () => {\n return (\n
\n
\n
\n \n
\n SOBRE\n \n Oportunidade Para Médicos e Demais Profissionais de Saúde!\n \n
\n \n a plataforma viaconsultas está em sua fase inicial de cadastro de médicos e demais\n profissionais de saúde! Este é o momento ideal para se juntar a nós e garantir sua\n presença desde o início nesta jornada rumo à excelência em atendimento particular.\n \n \n Mas aqui vai um segredo que você não pode perder: logo em seguida, iniciaremos a\n prospecção e cadastro dos pacientes em nossa plataforma! Isso mesmo, uma oportunidade\n única de se posicionar à frente da concorrência e assegurar uma maior visibilidade\n para sua clínica ou consultório\n \n \n Não perca tempo! Ao se cadastrar agora, você estará na vanguarda dessa revolução na\n prestação de serviços de saúde, alcançando novos pacientes e expandindo sua prática de\n forma estratégica e eficaz.\n \n
\n \n \n \n
\n
\n
\n );\n};\n\nexport default InfoSection;\n","import { Link } from \"@inertiajs/react\";\nimport { Button, Text } from \"@switchdreams/ui\";\nimport React from \"react\";\n\nimport { imagePath } from \"../../../utils\";\n\nconst SignUpSection = () => {\n return (\n
\n
\n
\n \n Precisa de atendimento?\n \n \n Cuide da sua saúde de forma conveniente e acessível. Junte-se ao viaconsultas e dê o\n primeiro passo para uma vida mais saudável.\n \n \n \n \n
\n \n
\n \n
\n
\n
\n );\n};\n\nexport default SignUpSection;\n","import { Link } from \"@inertiajs/react\";\nimport { Button, Text } from \"@switchdreams/ui\";\nimport React from \"react\";\n\nconst pricingData = [\n {\n type: \"Mensal\",\n name: \"ideal para iniciar\",\n tax: \"7.5%\",\n },\n {\n type: \"Trimestral\",\n name: \"Três meses com taxa reduzida\",\n tax: \"5%\",\n installments: \"Até 3x de\",\n },\n {\n type: \"Semestral\",\n name: \"Plano Ideal + Popular\",\n tax: \"5%\",\n installments: \"Até 6x de\",\n },\n {\n type: \"Anual\",\n name: \"Compromisso anual com excelência\",\n tax: \"5%\",\n installments: \"Até 12x de\",\n },\n];\n\nconst calculateValue = (type, number) => {\n const prices = {\n Mensal: [\"150,00\", \"150,00\", \"150,00\", \"150,00\"],\n Trimestral: [\"150,00\", \"140,00\", \"130,00\", \"120,00\"],\n Semestral: [\"125,00\", \"115,00\", \"110,00\", \"105,00\"],\n Anual: [\"100,00\", \"95,00\", \"90,00\", \"80,00\"],\n };\n const index = Math.min(number, prices[type].length - 1);\n return prices[type][index];\n};\n\nconst handlePlanClick = (plan, count) => {\n const message = `Olá, tenho interesse no plano ${plan.type}, ${professionalCount(count)} profissionais`;\n const whatsappURL = `https://wa.me//61996652148?text=${encodeURIComponent(message)}`;\n window.location.href = whatsappURL;\n};\n\nconst professionalCount = (count) => {\n switch (count) {\n case 0:\n return \"para até 05\";\n case 1:\n return \"para até 10\";\n case 2:\n return \"para até 25\";\n case 3:\n return \"para até 50\";\n default:\n return \"para até 05\";\n }\n};\n\nconst PaymentSection = () => {\n const number = 0;\n\n return (\n
\n
\n {/* \n PLANOS DE PAGAMENTO\n */}\n {/* \n Escolha o plano ideal para as suas necessidades profissionais\n */}\n \n Como funciona?\n \n \n O viaconsultas não cobra taxa de adesão, nem mensalidades.\n \n \n Será aplicada apenas uma taxa de operação da plataforma, de 10% sobre cada aquisição de serviço pelo usuário. \n \n \n Esta taxa será debitada automaticamente no ato do pagamento pelo usuário. Ou seja, a Clínica ou profissional receberá 90% líquido do valor pago pelo usuário. \n Esta taxa tem como função a manutenção dos custos operacionais da plataforma, como marketing e outros serviços.\n \n
\n
\n \n {/* {pricingData.map((pricing, idx) => (\n \n
\n \n {pricing.type}\n \n \n {pricing.name}\n \n
\n
\n
\n \n {pricing.installments}\n \n
\n \n R$\n \n \n {pricing.value || calculateValue(pricing.type, number)}\n \n
\n \n Por profissional\n \n
\n
\n handlePlanClick(pricing, number)}\n label={`Escolher ${pricing.type}`}\n className={`flex max-w-60 rounded-2xl font-poppins ${pricing.type === \"Semestral\" ? \"bg-primary-25 text-primary-500\" : \"bg-primary-500 text-white\"} px-6 py-2 text-sm font-medium duration-500 hover:bg-primary-100`}\n />\n \n +Taxa de operação de {pricing.tax} sobre o valor de cada atendimento\n \n
\n
\n {pricing.type === \"Semestral\" && (\n
\n Popular\n
\n )}\n
\n ))} */}\n\n
\n \n Cadastre-se e conheça tudo que o Viaconsultas tem a oferecer!\n \n \n \n \n \n Taxa de operação de 10% sobre o valor de cada atendimento\n \n
\n
\n
\n );\n};\n\nexport default PaymentSection;\n","import { useForm } from \"@inertiajs/react\";\nimport { Button, Text, TextField, TextFieldMask } from \"@switchdreams/ui\";\nimport axios from \"axios\";\nimport React, { useState } from \"react\";\n\nimport { useAlert } from \"@/contexts/Alert\";\nimport { imagePath } from \"@/utils\";\n\nconst whatsAppButton = () => {\n const { showAlert } = useAlert();\n const [open, setOpen] = useState(false);\n const { data, setData } = useForm({\n name: \"\",\n phone: \"\",\n email: \"\",\n });\n\n const handleSubmit = () => {\n if (!data.name || !data.phone || !data.email) {\n showAlert({ message: \"Preecha todos os campos para entrar em contato\", type: \"warning\" });\n } else {\n axios\n .post(\"/contacting_users\", data)\n .then(() => {\n window.location.href = `https://wa.me//61996652148`;\n })\n .catch((response) => showAlert({ message: response.response.data }));\n }\n };\n\n return (\n <>\n setOpen(!open)}\n >\n \"ícone\n
\n {open && (\n
\n
\n Entre em contato conosco\n \n Mas primeiro, preencha as seguintes informações.\n \n
\n
\n setData(\"name\", e.target.value)}\n />\n setData(\"email\", e.target.value)}\n />\n setData(\"phone\", e.target.value)}\n mask=\"(99) 99999-9999\"\n />\n
\n handleSubmit()}\n />\n
\n )}\n \n );\n};\n\nexport default whatsAppButton;\n","import React from \"react\";\n\nimport FaqSection from \"@/components/HomeSections/FaqSection\";\nimport AboutSection from \"@/components/HomeSections/HomeDoctorSections/AboutSection\";\nimport AppealSection from \"@/components/HomeSections/HomeDoctorSections/AppealSection\";\nimport BenefitsSection from \"@/components/HomeSections/HomeDoctorSections/BenefitsSection\";\nimport HeroSection from \"@/components/HomeSections/HomeDoctorSections/HeroSection\";\nimport InfoSection from \"@/components/HomeSections/HomeDoctorSections/InfoSection\";\nimport SignUpSection from \"@/components/HomeSections/HomePatientSections/SignUpSection\";\nimport PaymentSection from \"~/components/HomeSections/HomeDoctorSections/PaymentSection\";\n\nimport WhatsAppButton from \"../../components/WhatsAppButton\";\n\nconst HomeDoctor = () => {\n return (\n <>\n \n \n \n \n \n \n \n \n \n \n );\n};\n\nexport default HomeDoctor;\n","import { Link } from \"@inertiajs/react\";\nimport { Button, Text } from \"@switchdreams/ui\";\nimport React from \"react\";\n\nimport { imagePath } from \"../../../utils\";\n\nconst SignUpSection = () => {\n return (\n
\n
\n
\n \n É profissional da saúde?\n \n \n Seja nosso parceiro\n \n \n Não perca esta oportunidade de fazer a diferença na vida dos pacientes e elevar sua\n prática a novos patamares. Cadastre-se hoje mesmo no viaconsultas e faça parte da\n revolução da saúde digital!\n \n \n \n \n
\n \n
\n \n
\n
\n
\n );\n};\n\nexport default SignUpSection;\n","import { Text } from \"@switchdreams/ui\";\nimport React from \"react\";\n\nconst AboutSection = () => {\n return (\n \n
\n
\n
\n \n APRESENTAÇÃO\n \n \n Conheça as soluções da nossa plataforma!\n \n \n Descubra como o viaconsultas pode transformar sua clínica ou consultório,\n proporcionando uma alta captação de pacientes particulares de maneira acessível, rápida\n e conveniente. Assista ao nosso vídeo institucional e mergulhe em uma visão detalhada de\n como nossa plataforma pode impulsionar o crescimento e a visibilidade do seu negócio na\n área da saúde.\n \n
\n \n
\n
\n );\n};\n\nexport default AboutSection;\n","import { ArrowLongRightIcon } from \"@heroicons/react/24/outline\";\nimport { Link } from \"@inertiajs/react\";\nimport { Button, Text } from \"@switchdreams/ui\";\nimport React from \"react\";\n\nimport { imagePath } from \"../../../utils\";\n\nconst Options = [\n {\n label: \"Clínica geral\",\n img: imagePath(\"Stethoscope.svg\"),\n },\n {\n label: \"Pediatria\",\n img: imagePath(\"doctorWithKid.svg\"),\n },\n {\n label: \"Ortopedia\",\n img: imagePath(\"bones.svg\"),\n },\n {\n label: \"Cardiologia\",\n img: imagePath(\"hearth.svg\"),\n },\n {\n label: \"Ginecologia\",\n img: imagePath(\"femaleGender.svg\"),\n },\n {\n label: \"Psiquiatria\",\n img: imagePath(\"Brain.svg\"),\n },\n {\n label: \"Dermatologia\",\n img: imagePath(\"skincare.svg\"),\n },\n {\n label: \"Odontologia\",\n img: imagePath(\"Tooth.svg\"),\n },\n {\n label: \"Fisioterapia\",\n img: imagePath(\"terapy.svg\"),\n },\n {\n label: \"Psicologia\",\n img: imagePath(\"think.svg\"),\n },\n {\n label: \"Nutrição\",\n img: imagePath(\"apple.svg\"),\n },\n];\n\nconst AppealSection = () => {\n return (\n
\n
\n
\n \n ESPECIALIDADES\n \n
\n \n As especialidades mais procuradas\n \n \n \n \n
\n \n Oferecemos uma ampla variedade de especialidades médicas para atender às suas\n necessidades de saúde.\n \n
\n
\n {Options.map((option, idx) => {\n return (\n
\n \n \n {option.label}\n \n
\n );\n })}\n
\n \n \n \n
\n
\n );\n};\n\nexport default AppealSection;\n","import {\n BoltIcon,\n CheckBadgeIcon,\n ClipboardIcon,\n CursorArrowRippleIcon,\n} from \"@heroicons/react/24/outline\";\nimport { Text } from \"@switchdreams/ui\";\nimport React from \"react\";\n\nconst Cells = [\n {\n icon: ,\n name: \"Acesso prático e rápido\",\n description:\n \"Marque consultas médicas de onde estiver, sem a necessidade de deslocamentos. Agende seus horários de consulta com facilidade e rapidez.\",\n },\n {\n icon: ,\n name: \"Valores Acessíveis\",\n description:\n \"Acesse cuidados médicos de qualidade a valores acessíveis. Nossa plataforma oferece transparência, sem surpresas no momento do pagamento.\",\n },\n {\n icon: ,\n name: \"Fácil e Intuitiva\",\n description:\n \"Uma plataforma intuitiva e fácil de usar, projetada para simplificar o processo de agendamento, tanto para os profissionais como para os pacientes.\",\n },\n {\n icon: ,\n name: \"Especialidades Médicasl\",\n description:\n \"Explore uma diversidade de especialidades médicas e encontre o profissional certo para atender às suas necessidades específicas de saúde.\",\n },\n];\n\nconst BenefitsSection = () => {\n return (\n
\n
\n \n BENEFÍCIOS\n \n \n Descubra os Benefícios do viaconsultas\n \n \n Junte-se à nossa comunidade e experimente uma nova forma de cuidados de saúde. Com o\n viaconsultas, você desfrutará de:\n \n
\n
\n {Cells.map((cardCell, idx) => {\n return (\n \n
\n {cardCell.icon}\n
\n \n {cardCell.name}\n \n \n {cardCell.description}\n \n
\n );\n })}\n
\n
\n );\n};\n\nexport default BenefitsSection;\n","import { FunnelIcon } from \"@heroicons/react/24/outline\";\nimport { MagnifyingGlassIcon, MapPinIcon } from \"@heroicons/react/24/solid\";\nimport { Link } from \"@inertiajs/react\";\nimport { Badge, Button, Select, Text } from \"@switchdreams/ui\";\nimport React, { useEffect, useState } from \"react\";\n\nimport { stateOptions } from \"@/constants/SelectOptions\";\nimport { imagePath, specialtyOptions, workAreaOptionsFetch } from \"@/utils\";\n\nconst HeroSection = ({ clinicSpecialtiesOptions, states_options, cities_by_state }) => {\n const [selected, setSelected] = useState(\"consulta\");\n const [workArea, setWorkArea] = useState(\"\");\n const [workAreaClinic, setWorkAreaClinic] = useState(\"\");\n const [specialty, setSpecialty] = useState(\"\");\n const [state, setState] = useState(\"\");\n const [city, setCity] = useState([]);\n const [latitude, setLatitude] = useState(null)\n const [longitude, setLongitude] = useState(null)\n const [cityOptions, setCityOptions] = useState([]);\n const [allStates, setAllStates] = useState([]);\n const [workAreaOptions, setWorkAreaOptions] = useState([]);\n const [specialtiesOptions, setSpecialtiesOptions] = useState([]);\n useEffect(() => {\n // TODO: PERFOMANCE Improves to make only one fetch\n workAreaOptionsFetch(setWorkAreaOptions);\n specialtyOptions(setSpecialtiesOptions);\n\n getLocation()\n }, []);\n\n const getLocation = () => {\n if (navigator.geolocation) {\n navigator.geolocation.getCurrentPosition(success, error);\n } else {\n console.log(\"Geolocation not supported\");\n }\n }\n const success = (position) => {\n setLatitude(position.coords.latitude);\n setLongitude(position.coords.longitude);\n console.log(`Latitude: ${latitude}, Longitude: ${longitude}`);\n }\n \n const error = () => {\n console.log(\"Unable to retrieve your location\");\n }\n\n useEffect(() => {\n let statesArr = states_options.map((item) => ({\n value: item.state,\n label: item.state,\n }));\n setAllStates(statesArr);\n }, []);\n\n const selectState = (selectedState) => {\n let citiesData = cities_by_state[selectedState.value].map((item) => ({\n value: item,\n label: item,\n }));\n setCityOptions(citiesData);\n setState(selectedState);\n getLocation();\n };\n\n // Filter specialtiesOptions when workArea is selected\n useEffect(() => {\n if (workArea === \"\") {\n return;\n }\n // find workArea selected\n const selectedWorkArea = workAreaOptions.find((option) => option.value === workArea.value);\n const specialties =\n selectedWorkArea?.work_specialities?.map((specialty) => {\n return {\n value: specialty.id,\n label: specialty.name,\n };\n }) || [];\n setSpecialtiesOptions(specialties);\n }, [workArea]);\n\n return (\n
\n
\n
\n \n VIACONSULTAS\n \n \n Consultas e exames com profissionais à sua escolha!\n \n
\n \n Encontre os melhores profissionais de saúde, com valores acessíveis e agendamento\n rápido\n \n
\n
\n setSelected(\"consulta\")}\n />\n setSelected(\"exame\")}\n />\n {/* \n setSelected(\"telemedicina\")}\n /> \n */}\n
\n\n
\n
\n {selected == \"exame\" ? (\n
\n setWorkAreaClinic(e)}\n />\n
\n ) : null}\n {selected !== \"exame\" ? (\n <>\n
\n setWorkArea(e)}\n />\n
\n
\n setSpecialty(e)}\n />\n
\n \n ) : null}\n\n
\n
\n selectState(e)}\n />\n
\n
\n setCity(e)}\n />\n
\n
\n \n \n \n
\n
\n \n
\n
\n );\n};\n\nexport default HeroSection;\n","import { Link } from \"@inertiajs/react\";\nimport { Button, Text } from \"@switchdreams/ui\";\nimport React from \"react\";\n\nimport { imagePath } from \"../../../utils\";\n\nconst InfoSection = () => {\n return (\n
\n
\n
\n \n
\n SOBRE\n \n Mas, o que nós fazemos?\n \n
\n \n No viaconsultas, estamos comprometidos em revolucionar o acesso à saúde,\n conectando pacientes e profissionais de forma inovadora e eficiente. Somos uma\n plataforma dedicada a proporcionar uma experiência de atendimento particular de alta\n qualidade em diversas especialidades, eliminando as barreiras tradicionais e\n oferecendo soluções acessíveis e convenientes para todos.\n \n \n O que Fazemos:\n
Nossa missão é simples: facilitar o encontro entre pacientes em busca de\n atendimento particular e médicos e profissionais de saúde excepcionais. Através de\n nossa plataforma intuitiva e abrangente, pacientes podem encontrar os melhores\n especialistas, agendar consultas com facilidade e desfrutar de atendimento\n personalizado e de excelência.\n
\n \n Para os profissionais de saúde, oferecemos uma oportunidade única de expandir sua base\n de pacientes particulares, aumentar sua visibilidade e independência em relação aos\n planos de saúde, e proporcionar uma experiência de atendimento diferenciado, onde a\n qualidade e a acessibilidade caminham juntas.\n \n \n Em resumo, no viaconsultas, estamos redefinindo os padrões de cuidados de saúde,\n unindo tecnologia e humanidade para criar um futuro onde todos tenham acesso a um\n atendimento de qualidade, quando e onde precisarem. Junte-se a nós nessa jornada rumo\n a uma saúde mais acessível, eficiente e humana.\n \n
\n \n \n \n
\n
\n
\n );\n};\n\nexport default InfoSection;\n","import React from \"react\";\n\nimport FaqSection from \"@/components/HomeSections/FaqSection\";\nimport SignUpSection from \"@/components/HomeSections/HomeDoctorSections/SignUpSection\";\nimport AboutSection from \"@/components/HomeSections/HomePatientSections/AboutSection\";\nimport AppealSection from \"@/components/HomeSections/HomePatientSections/AppealSection\";\nimport BenefitsSection from \"@/components/HomeSections/HomePatientSections/BenefitsSection\";\nimport ClubSection from \"@/components/HomeSections/HomePatientSections/clubSection\";\nimport HeroSection from \"@/components/HomeSections/HomePatientSections/HeroSection\";\nimport InfoSection from \"@/components/HomeSections/HomePatientSections/InfoSection\";\n\nimport WhatsAppButton from \"../../components/WhatsAppButton\";\n\nconst HomePatient = ({ specialties_options, states_options, cities_by_state_options }) => { \n return (\n <>\n \n \n \n \n \n {/* */}\n \n \n \n \n );\n};\n\nexport default HomePatient;\n","import {\n ArrowLongRightIcon,\n CalendarDaysIcon,\n ClockIcon,\n MapIcon,\n MapPinIcon,\n} from \"@heroicons/react/24/outline\";\nimport { Avatar, Button, Text } from \"@switchdreams/ui\";\nimport React from \"react\";\n\nimport { monthsTranslated } from \"../../../utils\";\n\nconst AppointmentPatientCard = ({ info, setOpen, setAppointment }) => {\n const date = info && new Date(info.date);\n return (\n
\n {info ? (\n <>\n
\n
\n \n \n
\n
\n \n {info.doctor_name}\n \n
\n \n {info.doctor_specialty}\n \n
\n
\n {\n setOpen(true), setAppointment(info);\n }}\n />\n
\n
\n
\n \n
\n \n {info.location}\n \n \n Local\n \n
\n
\n window.open(`http://maps.google.com/?q=${info.location}`)}\n />\n
\n
\n \n
\n \n {`${date.getDate()} de ${monthsTranslated[date.getMonth()]} de ${date.getFullYear()}`}\n \n \n Data\n \n
\n
\n
\n \n
\n \n {info.approximate_start_time}\n \n \n Horário\n \n
\n
\n \n ) : (\n
\n \n Você não possui próximas consultas\n \n \n Suas próximas consultas agendadas aparecerão aqui!\n \n
\n )}\n
\n );\n};\n\nexport default AppointmentPatientCard;\n","import {\n ArrowLongRightIcon,\n CalendarDaysIcon,\n ClockIcon,\n XMarkIcon,\n} from \"@heroicons/react/24/outline\";\nimport { Link } from \"@inertiajs/react\";\nimport { Avatar, Badge, Button, Text } from \"@switchdreams/ui\";\nimport React from \"react\";\n\nimport { monthsTranslated } from \"@/utils\";\n\nconst PatientAppointmentCard = ({ appointment, setAppointment, setOpen }) => {\n const date = new Date(appointment.date);\n\n const renderButton = () => {\n if (\n appointment.payment_status === \"pending\" ||\n appointment.payment_status === \"payment_cancelled\"\n ) {\n return (\n \n \n \n );\n } else {\n return (\n {\n setAppointment(appointment);\n setOpen(true);\n }}\n />\n );\n }\n };\n\n const renderBadge = () => {\n if (appointment.payment_status === \"pending\") {\n return ;\n } else if (\n appointment.payment_status === \"payment_cancelled\" ||\n appointment.status === \"cancelled\"\n ) {\n return ;\n }\n };\n return (\n
\n
\n \n
\n
\n \n {appointment.doctor_name}\n \n
\n
\n \n \n {`${date.getDate()} de ${monthsTranslated[date.getMonth()]} de ${date.getFullYear()} às ${appointment.approximate_start_time}`}\n \n
\n
\n
\n {renderBadge()}\n
{renderButton()}
\n
\n );\n};\n\nexport default PatientAppointmentCard;\n","import {\n CalendarDaysIcon,\n ClockIcon,\n CurrencyDollarIcon,\n MapPinIcon,\n} from \"@heroicons/react/24/outline\";\nimport { Avatar, Text } from \"@switchdreams/ui\";\nimport React from \"react\";\n\nimport Modal from \"@/components/Modal\";\nimport { imagePath } from \"@/utils\";\n\nimport { formatIntegerCurrency, monthsTranslated } from \"../../../utils\";\nimport { Link } from \"@inertiajs/react\";\n\nconst AppointmentPatientModal = ({ info, open, setOpen }) => {\n const date = new Date(info.date);\n return (\n \n
\n
\n \n
\n \n {info?.doctor_name || \"\"}\n \n \n {info?.doctor_gender || \"\"}, {info?.doctor_age || \"\"} anos\n \n
\n
\n \n {formatIntegerCurrency(info?.price_cents) || \"\"}\n \n
\n
\n
\n \n
\n \n {info?.location || \"\"}\n \n \n Local\n \n
\n
\n \n
\n
\n \n
\n \n {`${date.getDate()} de ${monthsTranslated[date.getMonth()]} de ${date.getFullYear()}`}\n \n \n Data\n \n
\n
\n
\n \n
\n \n {info?.approximate_start_time}\n \n \n Horário\n \n
\n
\n
\n \n
\n \n {info?.payment_method == \"pix\" ? \"PIX\" : \"cartão de crédito\"}\n \n \n Método de pagamento\n \n
\n
\n
\n
\n \n \n Sua avaliação é muito importante!
Clique aqui e deixe uma avaliação para a clínica
\n \n
\n
\n
\n
\n );\n};\n\nexport default AppointmentPatientModal;\n","import { Spinner, Text } from \"@switchdreams/ui\";\nimport axios from \"axios\";\nimport React, { useEffect, useRef, useState } from \"react\";\n\nimport AppointmentPatientCard from \"@/components/Cards/AppointmentPatientCard\";\n\nimport PatientAppointmentCard from \"../../components/Cards/PatientAppointmentCard\";\nimport AppointmentPatientModal from \"../User/modal/AppointmentPatientModal\";\n\nconst Appointment = ({ appointment_history, next_appointments, pagy }) => {\n const [appointment, setAppointment] = useState({\n name: \"\",\n image: \"\",\n gender: \"\",\n age: \"\",\n value: \"\",\n location: \"\",\n date: \"\",\n });\n const [open, setOpen] = useState(false);\n const [nextPage, setNextPage] = useState(2);\n const [appointments, setAppointments] = useState(appointment_history);\n const maxPages = pagy.pages;\n\n const getMoreAppointments = () => {\n axios\n .get(`/minhas_consultas.json?page=${nextPage}`)\n .then((response) => setAppointments(appointments.concat(response.data)))\n .finally(() => setNextPage(nextPage + 1));\n };\n\n const elementRef = useRef(null);\n\n function onIntersection(entries) {\n const firstEntry = entries[0];\n if (firstEntry.isIntersecting && nextPage <= maxPages) {\n getMoreAppointments();\n }\n }\n\n useEffect(() => {\n const observer = new IntersectionObserver(onIntersection);\n if (observer && elementRef.current) {\n observer.observe(elementRef.current);\n }\n\n return () => {\n if (observer) {\n observer.disconnect();\n }\n };\n });\n\n return (\n <>\n \n
\n
\n \n Próxima consulta\n \n \n\n {next_appointments.length > 1 && (\n <>\n \n Próximas Consultas\n \n
\n {next_appointments.slice(1).map((info, idx) => {\n return (\n \n );\n })}\n
\n \n )}\n\n \n Histórico de consultas\n \n
\n {appointments.map((info, idx) => {\n return (\n \n );\n })}\n {nextPage <= maxPages && (\n
\n \n
\n )}\n
\n
\n
\n \n );\n};\n\nexport default Appointment;\n","import {\n CalendarDaysIcon,\n ChevronLeftIcon,\n ChevronRightIcon,\n FaceSmileIcon,\n HeartIcon,\n // StarIcon,\n} from \"@heroicons/react/24/outline\";\nimport { router, usePage } from \"@inertiajs/react\";\nimport { Avatar, Text } from \"@switchdreams/ui\";\nimport React, { useState } from \"react\";\nimport { ErrorBoundary } from \"react-error-boundary\";\n\nimport Modal from \"@/components/Modal\";\nimport { useAlert } from \"@/contexts/Alert\";\nimport {\n extractTime,\n formatIntegerCurrency,\n imagePath,\n monthsTranslated,\n monthsTranslatedAbreviation,\n weekDaysTranslated,\n} from \"@/utils\";\nimport { StarIcon } from \"@heroicons/react/24/solid\";\n\nconst ProfessionalCard = ({ doctorInfo, onClickReviews, onClickImages }) => {\n const { currentUser } = usePage().props;\n const { showAlert } = useAlert();\n const [open, setOpen] = useState(false);\n const [selectedDate, setSelectedDate] = useState(null);\n const [selectedTime, setSelectedTime] = useState(\"\");\n const [currentDay, setCurrentDay] = useState(new Date());\n\n const today = new Date();\n const tomorrow = new Date(today);\n tomorrow.setDate(tomorrow.getDate() + 1);\n\n const loadMoreRight = () => {\n const newDay = new Date(currentDay);\n newDay.setDate(newDay.getDate() + 3);\n setCurrentDay(newDay);\n };\n\n const loadMoreLeft = () => {\n const newDay = new Date(currentDay);\n newDay.setDate(newDay.getDate() - 3);\n setCurrentDay(newDay);\n };\n\n const HOUR_LIMIT_TO_SCHEDULE = 2;\n\n // How to returns the next 6 days based on currentDay state\n const calcNextSixDays = () => {\n const nextSixDays = [];\n for (let i = 0; i < 6; i++) {\n const newDay = new Date(currentDay);\n newDay.setDate(newDay.getDate() + i);\n nextSixDays.push(newDay);\n }\n return nextSixDays;\n };\n\n const nextSixDays = calcNextSixDays();\n\n const getWeekDay = (currentDate) => {\n const weekDays = [\"sunday\", \"monday\", \"tuesday\", \"wednesday\", \"thursday\", \"friday\", \"saturday\"];\n return weekDays[currentDate.getDay()];\n };\n\n const buildSchedule = (availabilities, day_appointments, date) => {\n const schedule = [];\n\n const isToday = isSameDay(date, new Date());\n const todayLimitTime =\n convertTimeToNumber(extractTime(new Date())) + 60 * HOUR_LIMIT_TO_SCHEDULE;\n\n // Generate all time slots from 6:00 to 22:00 in 30-minute intervals\n for (let hour = 6; hour <= 22; hour++) {\n for (let minute = 0; minute <= 30; minute += 30) {\n const time = `${hour.toString().padStart(2, \"0\")}:${minute.toString().padStart(2, \"0\")}`;\n schedule.push({ time, status: \"unavailable\" });\n }\n }\n\n // Check each availability range against the schedule\n availabilities.forEach((range) => {\n // if(isToday) {\n // const startTime = convertTimeToNumber(range.start_time);\n // } else {\n // }\n const availabilityStartTime = convertTimeToNumber(range.start_time);\n const availabilityEndTime = convertTimeToNumber(range.end_time);\n schedule.forEach((availability) => {\n const scheduleTime = convertTimeToNumber(availability.time);\n if (scheduleTime >= availabilityStartTime && scheduleTime < availabilityEndTime) {\n // Do not include past times if for today's availabilities\n if (!(isToday && todayLimitTime >= scheduleTime)) {\n availability.status = \"available\";\n }\n }\n });\n });\n\n day_appointments.forEach((appointment) => {\n const startTime = convertTimeToNumber(appointment.approximate_start_time);\n for (let i = 0; i < schedule.length; i++) {\n const scheduleTime = convertTimeToNumber(schedule[i].time);\n if (scheduleTime == startTime) {\n schedule[i].status = \"scheduled\"; // Mark overlapping time slots as scheduled\n }\n }\n });\n\n return schedule;\n };\n\n const convertTimeToNumber = (timeString) => {\n // Helper function to convert \"HH:MM\" string to a number representing minutes since 6:00\n const [hours, minutes] = timeString.split(\":\");\n return parseInt(hours, 10) * 60 + parseInt(minutes, 10);\n };\n\n const isSameDay = (date1, date2) => {\n if (!(date1 instanceof Date) || !(date2 instanceof Date)) {\n return false;\n }\n\n return (\n date1.getFullYear() === date2.getFullYear() &&\n date1.getMonth() === date2.getMonth() &&\n date1.getDate() === date2.getDate()\n );\n };\n\n const getDayHeader = (idx, day) => {\n if (isSameDay(day, today)) {\n return \"Hoje\";\n } else if (isSameDay(day, tomorrow)) {\n return \"Amanhã\";\n } else {\n return weekDaysTranslated[day.getDay()];\n }\n };\n\n return (\n Aconteceu algum problema para exibir o profissional...
}>\n {selectedDate && (\n \n router.get(\"/consultas/new\", {\n date: selectedDate,\n time: selectedTime,\n doctor_id: doctorInfo.id,\n })\n }\n onClickCancel={() => setOpen(false)}\n >\n
\n
\n \n
\n \n Agendar consulta para o dia{\" \"}\n \n {selectedDate.getDate()} de {monthsTranslated[selectedDate.getMonth()]}\n {\" \"}\n às{\" \"}\n \n {selectedTime}\n \n ?\n \n \n Você será direcionado para etapa de checkout.\n \n
\n \n )}\n
\n
\n
\n {/* */}\n
\n
\n \n {doctorInfo.name}\n \n {doctorInfo.verified && (\n \"icone\n )}\n
\n \n {doctorInfo.specialty}\n \n
\n
\n
\n
\n
\n \n \n {doctorInfo.registered_since}\n \n no via consultas\n
\n
\n \n \n {doctorInfo.patients} pacientes\n \n atendidos\n
\n
\n
\n \n \n \n {doctorInfo.reviews.length}\n \n Avaliações\n
\n
\n
\n \n {doctorInfo.doctor_description}\n \n
\n \n {formatIntegerCurrency(doctorInfo.value)}\n \n \n / consulta\n \n
\n
\n {/*
\n
\n \n
\n
*/}\n
\n \n {doctorInfo.clinic_name}\n \n \n {doctorInfo.clinic_address}\n \n
\n
\n
\n
\n loadMoreLeft()} />\n\n loadMoreRight()}\n />\n\n
\n {nextSixDays.map((day, idx) => (\n 2 ? \"hidden md:flex\" : \"\")\n }\n key={idx}\n >\n \n {day.getDate()} {monthsTranslatedAbreviation[day.getMonth()]}\n \n \n {getDayHeader(idx, day)}\n \n
\n ))}\n {nextSixDays.map((date, index) => {\n return (\n 2 ? \"hidden md:flex\" : \"\")\n }\n >\n {buildSchedule(\n doctorInfo.availabilities.filter(\n (availability) => availability.day_of_week == getWeekDay(date),\n ),\n doctorInfo.appointments.filter((appointment) =>\n isSameDay(new Date(appointment.date), date),\n ),\n date,\n ).map((time, idx) => {\n return (\n {\n if (time.status === \"available\") {\n setSelectedDate(date);\n setSelectedTime(time.time);\n if (currentUser && currentUser.role == \"patient\") {\n setOpen(true);\n } else {\n showAlert({\n message: `É necessário estar logado ${currentUser && currentUser.role == \"doctor\" ? \"como paciente\" : \"\"} para agendar uma consulta`,\n });\n }\n }\n }}\n >\n \n {time.time}\n \n
\n );\n })}\n
\n );\n })}\n
\n \n \n \n );\n};\n\nexport default ProfessionalCard;\n","import { FunnelIcon } from \"@heroicons/react/24/outline\";\nimport { ChevronDownIcon, MagnifyingGlassIcon, MapPinIcon } from \"@heroicons/react/24/solid\";\nimport { Link } from \"@inertiajs/react\";\nimport { Button, Popover, Select, Spinner, Text } from \"@switchdreams/ui\";\nimport axios from \"axios\";\nimport React, { useEffect, useRef, useState } from \"react\";\n// import Modal from \"@/components/Modal\";\nimport ProfessionalCard from \"@/components/Cards/ProfessionalCard\";\nimport { specialtyOptions, workAreaOptionsFetch } from \"@/utils\";\nimport Modal from 'react-modal';\n\nconst ProfessionalSearch = ({\n initial_professionals,\n states_options,\n cities_by_state_options,\n pagy,\n}) => {\n const sortOptions = [\n { label: \"Alfabética\", value: \"alphabetical\" },\n { label: \"Número de pacientes atendido\", value: \"patients_count\" },\n { label: \"Tempo no site\", value: \"created_at\" },\n ];\n\n // Params from url\n const workSpecialtyIdFromUrl = parseInt(\n new URLSearchParams(window.location.search).get(\"work_specialty\"),\n );\n const workAreaIdFromUrl = parseInt(new URLSearchParams(window.location.search).get(\"work_area\"));\n\n const [professionals, setProfessionals] = useState(initial_professionals);\n const [sort, setSort] = useState(sortOptions[0]);\n const [workArea, setWorkArea] = useState(\"\");\n const [specialty, setSpecialty] = useState(null);\n const [state, setState] = useState(null);\n const [city, setCity] = useState([]);\n const [cityOptions, setCityOptions] = useState([]);\n const [allStates, setAllStates] = useState([]);\n const [isLoading, setIsLoading] = useState(false);\n const [workAreaOptions, setWorkAreaOptions] = useState([]);\n const [specialtiesOptions, setSpecialtiesOptions] = useState([]);\n const [openReviews, setOpenReviews] = useState(false);\n const [reviews, setReviews] = useState([]);\n // Pagination\n const [page, setPage] = useState(0);\n const [maxPages, setMaxPages] = useState(pagy.pages);\n const [count, setCount] = useState(pagy.count);\n const [firstLoad, setFirstLoad] = useState(true);\n\n const elementRef = useRef(null);\n\n const formatDate = (date) => {\n const dateTime = new Date(date);\n return dateTime.toLocaleString();\n };\n\n const openReviewsModal = (reviewData) => {\n if (reviewData.reviews.length > 0) {\n setOpenReviews(true);\n setReviews(reviewData.reviews);\n }\n };\n\n useEffect(() => {\n let statesArr = states_options.map((item) => ({\n value: item.state,\n label: item.state,\n }));\n setAllStates(statesArr);\n }, []);\n\n const selectState = (selectedState) => {\n let citiesData = cities_by_state_options[selectedState.value].map((item) => ({\n value: item,\n label: item,\n }));\n setCityOptions(citiesData);\n setState(selectedState);\n };\n\n\n useEffect(() => {\n // TODO: PERFOMANCE Improves to make only one fetch\n // Set select inputs\n workAreaOptionsFetch(setWorkAreaOptions);\n specialtyOptions(setSpecialtiesOptions);\n // Set state\n const state = states_options.find(\n (option) => option.state == new URLSearchParams(window.location.search).get(\"state\"),\n );\n const getCity = new URLSearchParams(window.location.search).get(\"city\");\n if (state) {\n selectState({ value: state.state, label: state.state });\n }\n setCity({ value: getCity, label: getCity });\n }, []);\n\n // Set work area from URL\n useEffect(() => {\n if (workAreaOptions) {\n const workArea = workAreaOptions.find((option) => option.value == workAreaIdFromUrl);\n if (workArea) {\n setWorkArea(workArea);\n }\n }\n }, [workAreaOptions]);\n\n // Set specialty from URL\n useEffect(() => {\n if (specialtiesOptions) {\n const specialty = specialtiesOptions.find((option) => option.value == workSpecialtyIdFromUrl);\n if (specialty) {\n setSpecialty(specialty);\n }\n }\n }, [specialtiesOptions]);\n\n useEffect(() => {\n if (workArea === \"\") {\n return;\n }\n // find workArea selected\n const selectedWorkArea = workAreaOptions.find((option) => option.value === workArea.value);\n const specialties =\n selectedWorkArea?.work_specialities?.map((specialty) => {\n return {\n value: specialty.id,\n label: specialty.name,\n };\n }) || [];\n setSpecialtiesOptions(specialties);\n }, [workArea]);\n\n useEffect(() => {\n if (firstLoad) {\n setPage(1);\n setFirstLoad(false);\n }\n }, [specialty, sort, state]);\n\n return (\n <>\n setOpenReviews(false)}\n className=\"w-full max-w-lg mx-auto my-6 bg-white rounded-lg shadow-2xl \"\n overlayClassName=\"fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center\"\n >\n
\n
\n setOpenReviews(false)}\n className=\"absolute top-2 right-2 text-gray-600 hover:text-gray-800\"\n aria-label=\"Fechar\"\n >\n ×\n \n

Avaliações

\n
\n
\n
{/* Usar espaço vertical entre as avaliações */}\n {reviews.map((review, index) => (\n
{/* Estilo melhorado */}\n
\n {formatDate(review?.created_at)}\n
\n
\n {'Avaliação'}\n
\n
\n {[1, 2, 3, 4, 5].map((star) => (\n = star ? 'text-yellow-500' : 'text-gray-300'\n }`}\n >\n ★\n \n ))}\n
\n
\n {review?.description || 'Nenhuma descrição fornecida.'}\n
\n
\n ))}\n
\n \n
\n
\n
\n {/*MARK: HEADER TITLE */}\n \n Consultas de qualidade com os melhores profissionais da sua região!\n \n\n {/*MARK: SEARCH BAR */}\n
\n
\n
\n setWorkArea(e)}\n />\n
\n
\n setSpecialty(e)}\n />\n
\n
\n
\n selectState(e)}\n />\n
\n
\n setCity(e)}\n />\n
\n
\n \n \n \n
\n
\n\n {/* */}\n
\n
\n
\n
\n
\n
\n
\n {/*MARK: HEADER DOS RESULTADOS DA PESQUISA */}\n
\n \n Encontramos\n \n \n {count} especialistas\n \n
\n
\n \n Ordenar por:\n \n \n \n {sort.label}\n \n \n
\n }\n >\n
\n {/*MARK: POPUP DE OPÇÕES DE ORDENAÇÃO */}\n {sortOptions.map((option, key) => {\n return (\n
\n
\n );\n })}\n
\n \n
\n
\n
\n {/*MARK: RESULTADOS DA PESQUISA */}\n {isLoading ? (\n \n ) : (\n professionals.map((info, idx) => {\n return openReviewsModal(info)} />;\n })\n )}\n {page < maxPages && (\n
\n \n
\n )}\n
\n {/*
\n \n
*/}\n\n {/*MARK: ESPECIALIDADES */}\n
\n \n Encontre a especialidade que você precisa!\n \n
\n {specialtiesOptions.map((Option, idx) => {\n return (\n {\n window.scroll({ top: 0, behavior: \"smooth\" });\n setSpecialty(Option.value);\n }}\n >\n \n {Option.label}\n \n
\n );\n })}\n
\n
\n
\n
\n \n );\n};\n\nexport default ProfessionalSearch;\n","export const DoctorInfo = [\n {\n name: \"Dr. José Montenegro\",\n verified: true,\n img: \"\",\n specility: \"Clínico Geral e Cardiologista\",\n timeOnSite: \"3 meses\",\n patients: 235,\n description:\n \"Formado em Medicina e especializado em Cardiologia pela Unifesp. Com mais de 14 anos de experiência clínica, estou comprometido em oferecer diagnósticos precisos e tratamentos personalizados a todos.\",\n starts: 5,\n evaluations: 36,\n clinicName: \"Consultório José Montenegro\",\n address: \"Praça Santo Agostinho 70, Brasília\",\n logo: \"\",\n dates: [\n {\n day: \"Segunda\",\n times: [\n \"8:00\",\n \"9:00\",\n \"10:00\",\n \"11:00\",\n \"12:00\",\n \"13:00\",\n \"14:00\",\n \"15:00\",\n \"16:00\",\n \"17:00\",\n ],\n },\n {\n day: \"Terça\",\n times: [\n \"8:00\",\n \"9:00\",\n \"10:00\",\n \"11:00\",\n \"12:00\",\n \"13:00\",\n \"14:00\",\n \"15:00\",\n \"16:00\",\n \"17:00\",\n ],\n },\n {\n day: \"Quarta\",\n times: [\n \"8:00\",\n \"9:00\",\n \"10:00\",\n \"11:00\",\n \"12:00\",\n \"13:00\",\n \"14:00\",\n \"15:00\",\n \"16:00\",\n \"17:00\",\n ],\n },\n {\n day: \"Quinta\",\n times: [\n \"8:00\",\n \"9:00\",\n \"10:00\",\n \"11:00\",\n \"12:00\",\n \"13:00\",\n \"14:00\",\n \"15:00\",\n \"16:00\",\n \"17:00\",\n ],\n },\n {\n day: \"Sexta\",\n times: [\n \"8:00\",\n \"9:00\",\n \"10:00\",\n \"11:00\",\n \"12:00\",\n \"13:00\",\n \"14:00\",\n \"15:00\",\n \"16:00\",\n \"17:00\",\n ],\n },\n {\n day: \"Sábado\",\n times: [\"8:00\", \"9:00\", \"10:00\"],\n },\n ],\n },\n {\n name: \"Dra. Maria Silva\",\n verified: true,\n img: \"\",\n specility: \"Pediatra\",\n timeOnSite: \"1 ano\",\n patients: 320,\n description:\n \"Especialista em Pediatria pela USP, com 10 anos de experiência. Apaixonada por cuidar da saúde das crianças, proporcionando um atendimento humanizado e de qualidade.\",\n starts: 5,\n evaluations: 45,\n clinicName: \"Clínica Pediátrica Maria Silva\",\n address: \"Rua das Flores 123, São Paulo\",\n logo: \"\",\n dates: [\n {\n day: \"Segunda\",\n times: [\"9:00\", \"10:00\", \"11:00\", \"13:00\", \"14:00\", \"15:00\", \"16:00\", \"17:00\"],\n },\n {\n day: \"Terça\",\n times: [\"9:00\", \"10:00\", \"11:00\", \"13:00\", \"14:00\", \"15:00\", \"16:00\", \"17:00\"],\n },\n {\n day: \"Quarta\",\n times: [\"9:00\", \"10:00\", \"11:00\", \"13:00\", \"14:00\", \"15:00\", \"16:00\", \"17:00\"],\n },\n {\n day: \"Quinta\",\n times: [\"9:00\", \"10:00\", \"11:00\", \"13:00\", \"14:00\", \"15:00\", \"16:00\", \"17:00\"],\n },\n {\n day: \"Sexta\",\n times: [\"9:00\", \"10:00\", \"11:00\", \"13:00\", \"14:00\", \"15:00\", \"16:00\", \"17:00\"],\n },\n {\n day: \"Sábado\",\n times: [\"9:00\", \"10:00\"],\n },\n ],\n },\n {\n name: \"Dr. Carlos Andrade\",\n verified: true,\n img: \"\",\n specility: \"Dermatologista\",\n timeOnSite: \"6 meses\",\n patients: 180,\n description:\n \"Formado pela UFRJ com especialização em Dermatologia. Experiência de 8 anos no tratamento de doenças de pele, cabelo e unhas, com foco em procedimentos estéticos.\",\n starts: 4,\n evaluations: 27,\n clinicName: \"Clínica Dermatológica Carlos Andrade\",\n address: \"Av. Atlântica 456, Rio de Janeiro\",\n logo: \"\",\n dates: [\n {\n day: \"Segunda\",\n times: [\"10:00\", \"11:00\", \"12:00\", \"13:00\", \"14:00\", \"15:00\", \"16:00\", \"17:00\", \"18:00\"],\n },\n {\n day: \"Terça\",\n times: [\"10:00\", \"11:00\", \"12:00\", \"13:00\", \"14:00\", \"15:00\", \"16:00\", \"17:00\", \"18:00\"],\n },\n {\n day: \"Quarta\",\n times: [\"10:00\", \"11:00\", \"12:00\", \"13:00\", \"14:00\", \"15:00\", \"16:00\", \"17:00\", \"18:00\"],\n },\n {\n day: \"Quinta\",\n times: [\"10:00\", \"11:00\", \"12:00\", \"13:00\", \"14:00\", \"15:00\", \"16:00\", \"17:00\", \"18:00\"],\n },\n {\n day: \"Sexta\",\n times: [\"10:00\", \"11:00\", \"12:00\", \"13:00\", \"14:00\", \"15:00\", \"16:00\", \"17:00\", \"18:00\"],\n },\n {\n day: \"Sábado\",\n times: [\"10:00\", \"11:00\", \"12:00\"],\n },\n ],\n },\n {\n name: \"Dra. Fernanda Costa\",\n verified: true,\n img: \"\",\n specility: \"Ginecologista e Obstetra\",\n timeOnSite: \"2 anos\",\n patients: 410,\n description:\n \"Especialista em Ginecologia e Obstetrícia pela UNICAMP. Com mais de 12 anos de experiência, foco em saúde da mulher, acompanhamento pré-natal e partos humanizados.\",\n starts: 5,\n evaluations: 52,\n clinicName: \"Centro de Saúde da Mulher Fernanda Costa\",\n address: \"Rua dos Pinheiros 789, Campinas\",\n logo: \"\",\n dates: [\n {\n day: \"Segunda\",\n times: [\n \"8:00\",\n \"9:00\",\n \"10:00\",\n \"11:00\",\n \"12:00\",\n \"13:00\",\n \"14:00\",\n \"15:00\",\n \"16:00\",\n \"17:00\",\n ],\n },\n {\n day: \"Terça\",\n times: [\n \"8:00\",\n \"9:00\",\n \"10:00\",\n \"11:00\",\n \"12:00\",\n \"13:00\",\n \"14:00\",\n \"15:00\",\n \"16:00\",\n \"17:00\",\n ],\n },\n {\n day: \"Quarta\",\n times: [\n \"8:00\",\n \"9:00\",\n \"10:00\",\n \"11:00\",\n \"12:00\",\n \"13:00\",\n \"14:00\",\n \"15:00\",\n \"16:00\",\n \"17:00\",\n ],\n },\n {\n day: \"Quinta\",\n times: [\n \"8:00\",\n \"9:00\",\n \"10:00\",\n \"11:00\",\n \"12:00\",\n \"13:00\",\n \"14:00\",\n \"15:00\",\n \"16:00\",\n \"17:00\",\n ],\n },\n {\n day: \"Sexta\",\n times: [\n \"8:00\",\n \"9:00\",\n \"10:00\",\n \"11:00\",\n \"12:00\",\n \"13:00\",\n \"14:00\",\n \"15:00\",\n \"16:00\",\n \"17:00\",\n ],\n },\n {\n day: \"Sábado\",\n times: [\"8:00\", \"9:00\", \"10:00\"],\n },\n ],\n },\n {\n name: \"Dr. Paulo Moreira\",\n verified: true,\n img: \"\",\n specility: \"Ortopedista\",\n timeOnSite: \"9 meses\",\n patients: 290,\n description:\n \"Graduado pela USP com especialização em Ortopedia e Traumatologia. Experiência de 11 anos em tratamentos de fraturas, lesões esportivas e cirurgias ortopédicas.\",\n starts: 4,\n evaluations: 40,\n clinicName: \"Ortopedia Paulo Moreira\",\n address: \"Rua das Palmeiras 250, Belo Horizonte\",\n logo: \"\",\n dates: [\n {\n day: \"Segunda\",\n times: [\n \"7:00\",\n \"8:00\",\n \"9:00\",\n \"10:00\",\n \"11:00\",\n \"12:00\",\n \"13:00\",\n \"14:00\",\n \"15:00\",\n \"16:00\",\n ],\n },\n {\n day: \"Terça\",\n times: [\n \"7:00\",\n \"8:00\",\n \"9:00\",\n \"10:00\",\n \"11:00\",\n \"12:00\",\n \"13:00\",\n \"14:00\",\n \"15:00\",\n \"16:00\",\n ],\n },\n {\n day: \"Quarta\",\n times: [\n \"7:00\",\n \"8:00\",\n \"9:00\",\n \"10:00\",\n \"11:00\",\n \"12:00\",\n \"13:00\",\n \"14:00\",\n \"15:00\",\n \"16:00\",\n ],\n },\n {\n day: \"Quinta\",\n times: [\n \"8:00\",\n \"9:00\",\n \"10:00\",\n \"11:00\",\n \"12:00\",\n \"13:00\",\n \"14:00\",\n \"15:00\",\n \"16:00\",\n \"17:00\",\n ],\n },\n {\n day: \"Sexta\",\n times: [\n \"8:00\",\n \"9:00\",\n \"10:00\",\n \"11:00\",\n \"12:00\",\n \"13:00\",\n \"14:00\",\n \"15:00\",\n \"16:00\",\n \"17:00\",\n ],\n },\n {\n day: \"Sábado\",\n times: [\"8:00\", \"9:00\", \"10:00\"],\n },\n ],\n },\n];\n\nexport const Options = [\n \"Alergia e Imunologia\",\n \"Dermatologista\",\n \"Neurocirurgia\",\n \"Infectiologia\",\n \"Anestesiologia\",\n \"Coloproctologia\",\n \"Neurologia\",\n \"Mastologia\",\n \"Angiologia\",\n \"Cirurgia Torácica\",\n \"Nutrologia\",\n \"Medicina Física e Reabilitação\",\n \"Cancerologia / Oncologia\",\n \"Cirurgia Vascular\",\n \"Oftalmologia\",\n \"Nefrologia\",\n \"Cardiologia\",\n \"Endocrinologia\",\n \"Ortopedia e Traumatologia\",\n \"Neurocirurgia\",\n \"Cirurgia Cardiovascular\",\n \"Gastroenterologia\",\n \"Otorrinolaringologia\",\n \"Neurologia\",\n \"Cirurgia de Mão\",\n \"Genética Médica\",\n \"Pediatria\",\n \"Nutrologia\",\n \"Cirurgia de Cabeça e Pescoço\",\n \"Geriatria\",\n \"Pneumologia\",\n \"Oftalmologia\",\n \"Cirurgia de Aparelho Digestivo\",\n \"Ginecologia e Hemoterapia\",\n \"Psiquiatria\",\n \"Ortopedia e Traumatologia\",\n \"Cirurgia Geral\",\n \"Infectiologia\",\n \"Reumatologia\",\n \"Otorrinolaringologia\",\n \"Cirurgia Pediátrica\",\n \"Mastologia\",\n \"Urologia\",\n \"Cirurgia Plástica\",\n \"Medicina Física e Reabilitação\",\n \"Clínica de Exames Radiológicos\",\n \"Pneumologia\",\n \"Clínica Médica\",\n \"Nefrologia\",\n \"Laboratórios de Análises Clínicas e Patológicas\",\n];\n","import React, { useState } from \"react\";\nimport { imagePath } from \"@/utils\";\nimport { router } from \"@inertiajs/react\";\n\nconst RatingPage = ({ data }) => {\n const [rating, setRating] = useState(0)\n const [description, setDescription] = useState('')\n const ratingComments = [\n 'Péssimo',\n 'Ruim',\n 'Razoável',\n 'Bom',\n 'Ótimo!'\n ];\n\n const sendRating = () => {\n const query = new URLSearchParams(location.search)\n \n const formData = new FormData();\n formData.append('rating', rating);\n formData.append('description', description);\n formData.append('reviewable_id', query.get('reviewable_id'));\n formData.append('reviewable_type', query.get('reviewable_type'));\n router.post('/reviews', formData)\n }\n\n return (\n <>\n
\n
\n
\n
\n
\n
\n
\n Envie uma Avaliação\n
\n
\n
\n
\n
\n Como você avalia
\n o atendimento recebido?\n
\n
\n
\n {[1, 2, 3, 4, 5].map((star) => {\n return ( \n = star ? 'gold' : 'gray',\n fontSize: `35px`,\n }}\n onClick={() => {\n setRating(star)\n }}\n >\n {' '}\n ★{' '}\n \n )\n })}\n
\n
\n
\n {ratingComments[rating - 1]}\n
\n
\n
\n Adicione um comentário\n
\n
\n setDescription(e.target.value)}\n rows=\"5\"\n placeholder=\"Dê uma descrição, escreva informações importantes ou compartilhe qualquer coisa que você achar necessário.\"\n className=\"shrink grow basis-0 self-stretch font-['Poppins'] text-base font-normal leading-snug text-[#98a1b2]\"\n />\n
\n \n
\n <>Enviar Avaliação\n
\n \n
\n
\n
\n
\n
\n
\n \n );\n};\n\nexport default RatingPage;\n","import { LockClosedIcon } from \"@heroicons/react/24/outline\";\nimport { Link, router, usePage } from \"@inertiajs/react\";\nimport { Avatar, Button, SelectBox, Text } from \"@switchdreams/ui\";\nimport React, { useState } from \"react\";\n\nimport AppointmentsHistory from \"@/components/AppointmentsComponents/AppointmentsHistory\";\nimport NextAppointments from \"@/components/AppointmentsComponents/NextAppointments\";\nimport Calendar from \"@/components/Calendar\";\nimport TimeSidebar from \"@/components/Sidebar\";\n\nconst Appointments = ({\n doctor,\n doctor_options,\n doctor_availabilities,\n appointments,\n pending_appointments,\n done_appointments,\n pagy,\n}) => {\n const { currentUser } = usePage().props;\n const [sidebarOpen, setSidebarOpen] = useState(false);\n\n if (currentUser.active_plan) {\n return (\n <>\n \n
\n
\n
\n \n
\n
\n \n {doctor.name}\n \n
\n \n {doctor.specialty}\n \n
\n
\n
\n router.get(`/clinica/informacoes_consultas/${e}`)}\n value={doctor.id}\n />\n
\n
\n
\n \n
\n
\n \n
\n \n
\n \n );\n } else {\n return (\n
\n
\n
\n \n
\n
\n \n Agenda bloqueada\n \n\n \n Para liberar o acesso à agenda é necessário adquirir um plano de assinatura na\n plataforma.\n \n
\n \n \n \n
\n
\n );\n }\n};\n\nexport default Appointments;\n","import {\n ArrowDownIcon,\n ArrowUpIcon,\n CalendarDaysIcon,\n ChevronDownIcon,\n PlusIcon,\n} from \"@heroicons/react/24/solid\";\nimport { Link, router } from \"@inertiajs/react\";\nimport { Avatar, Badge, Button, Popover, Text } from \"@switchdreams/ui\";\nimport axios from \"axios\";\nimport React, { useEffect, useState } from \"react\";\n\nimport { formatIntegerCurrency, monthsTranslated } from \"../../utils\";\n\nconst team = ({ clinic }) => {\n const today = new Date();\n const [selectedDate, setSelectedDate] = useState(new Date());\n const [monthlyData, setMonthlyData] = useState({\n monthly_appointments: clinic.monthly_appointment,\n monthly_income: clinic.monthly_income,\n monthly_new_patients: clinic.monthly_new_patients,\n last_appointments: clinic.last_appointment,\n last_income: clinic.last_income,\n last_new_patients: clinic.last_new_patients,\n });\n\n const getDayLabel = (date) => {\n const tomorrow = new Date();\n tomorrow.setDate(tomorrow.getDate() + 1);\n if (\n date.getDate() == today.getDate() &&\n date.getMonth() == today.getMonth() &&\n date.getFullYear() == today.getFullYear()\n ) {\n return \"Hoje\";\n } else if (\n date.getDate() == tomorrow.getDate() &&\n date.getMonth() == tomorrow.getMonth() &&\n date.getFullYear() == tomorrow.getFullYear()\n ) {\n return \"Amanhã\";\n } else {\n return `${date.getDate()}/${date.getMonth()}`;\n }\n };\n const monthOptions = () => {\n const startDate = new Date(clinic.created_at);\n const months = [];\n\n // Loop through months until reaching today's year and month\n while (\n startDate.getFullYear() < today.getFullYear() ||\n (startDate.getFullYear() === today.getFullYear() && startDate.getMonth() <= today.getMonth())\n ) {\n const thisDate = new Date(startDate);\n const year = startDate.getFullYear().toString();\n const month = startDate.getMonth();\n\n months.push({ label: `${monthsTranslated[month]}, ${year}`, date: thisDate }); // Push month/year string\n\n // Move to the next month\n startDate.setMonth(startDate.getMonth() + 1);\n }\n\n return months;\n };\n\n const ratioBadge = (lastMonthValue, thisMonthValue) => {\n if (lastMonthValue == 0 || thisMonthValue == 0) {\n return \"\";\n }\n const ratio = thisMonthValue / lastMonthValue;\n if (ratio > 1) {\n return (\n
\n \n \n do mês anterior\n \n
\n );\n } else {\n return (\n
\n \n \n do mês anterior\n \n
\n );\n }\n };\n\n useEffect(() => {\n axios\n .get(`/clinica.json?date=${selectedDate}`)\n .then((response) => setMonthlyData(response.data));\n }, [selectedDate]);\n\n return (\n
\n
\n
\n \n
\n \n {clinic.name}\n \n \n {clinic.description}\n \n
\n \n \n \n
\n
\n
\n \n Rendimento mensal\n \n \n \n {`${monthsTranslated[selectedDate.getMonth()]}, ${selectedDate.getFullYear()}`}\n \n \n
\n }\n >\n
\n {monthOptions().map((month, idx) => {\n return (\n
\n
\n );\n })}\n
\n \n
\n
\n
\n \n Valor total recebido\n \n
\n
\n \n {formatIntegerCurrency(monthlyData.monthly_income)}\n \n
\n {selectedDate.getMonth() != new Date(clinic.created_at).getMonth() &&\n ratioBadge(monthlyData.last_income, monthlyData.monthly_income)}\n
\n
\n
\n \n Consultas realizadas\n \n
\n
\n \n {monthlyData.monthly_appointments}\n \n
\n {selectedDate.getMonth() != new Date(clinic.created_at).getMonth() &&\n ratioBadge(monthlyData.last_appointments, monthlyData.monthly_appointments)}\n
\n
\n
\n \n Novos pacientes\n \n
\n
\n \n {monthlyData.monthly_new_patients}\n \n
\n {selectedDate.getMonth() != new Date(clinic.created_at).getMonth() &&\n ratioBadge(monthlyData.last_new_patients, monthlyData.monthly_new_patients)}\n
\n
\n
\n
\n
\n \n Equipe\n \n \n ({clinic.doctors.length})\n \n
\n router.get(\"/clinica/new_doctor\")}\n />\n
\n
\n
\n {clinic.doctors.map((doctor, idx) => {\n const date = new Date(doctor.state);\n\n return (\n
\n
\n \n
\n
\n \n {doctor.name}\n \n
\n \n {doctor.specialty}\n \n
\n
\n
\n \n Próxima consulta:\n \n {doctor.state === \"working\" ? (\n \n ) : doctor.state === null ? (\n \n ) : (\n \n )}\n
\n
\n );\n })}\n
\n
\n
\n
\n
\n );\n};\n\nexport default team;\n","import { ArrowLongLeftIcon } from \"@heroicons/react/24/outline\";\nimport { Button, SelectBox, Spinner, Text, TextField, TextFieldMask } from \"@switchdreams/ui\";\nimport axios from \"axios\";\nimport React, { useState } from \"react\";\n\nimport { stateOptions } from \"@/constants/SelectOptions\";\nimport { useAlert } from \"@/contexts/Alert\";\nimport { fetchCep } from \"@/utils\";\n\nconst AddressInfo = ({ setSection, data, setData, submitSignUpData, processing }) => {\n const { showAlert } = useAlert();\n\n const [cepError, setCepError] = useState(false);\n const [loading, setLoading] = useState(false);\n\n const nextStep = (e) => {\n e.preventDefault();\n if (\n data.address_attributes.cep === \"\" ||\n data.address_attributes.state === \"\" ||\n data.address_attributes.city === \"\" ||\n data.address_attributes.street === \"\" ||\n data.address_attributes.latitude === \"\" ||\n data.address_attributes.longitude === \"\" ||\n data.address_attributes.neighborhood === \"\"\n ) {\n showAlert({ message: \"Preencha todos os campos!\", type: \"warning\" });\n } else {\n submitSignUpData();\n }\n };\n\n const getCoordinates = async () => {\n const apiKey = \"AIzaSyAoLzTfDNeO5ZBNk8yyvZ6p5CJnWPKM8LU\";\n const url = `https://maps.googleapis.com/maps/api/geocode/json?address=${data.address_attributes.cep}&key=${apiKey}`;\n \n setLoading(true); // Inicia o carregamento\n \n try {\n const response = await axios.get(url);\n const responseData = response.data; // Renomeado para evitar conflitos\n \n if (responseData.results && responseData.results.length > 0) {\n const location = responseData.results[0].geometry.location;\n console.log(location.lat, location.lng);\n \n setData((data) => ({\n ...data,\n address_attributes: {\n ...data.address_attributes,\n latitude: location.lat.toString(),\n longitude: location.lng.toString(),\n },\n }));\n console.log(data)\n return location; // Retorna latitude e longitude\n } else {\n throw new Error(\"Endereço não encontrado para o CEP fornecido\");\n }\n } catch (error) {\n console.error(\"Erro ao buscar dados de geolocalização:\", error);\n showAlert({ message: \"Erro ao buscar localização. Verifique o CEP e tente novamente.\", type: \"error\" });\n } finally {\n setLoading(false); // Finaliza o carregamento\n }\n };\n\n return (\n <>\n setSection(({ step, role }) => ({ step: step - 1, role }))}\n />\n
\n \n Finalize o cadastro\n \n Insira sua localização.\n
\n
nextStep(e)} className=\"mx-auto flex max-w-xl flex-col gap-2\">\n {loading && (\n \n )}\n {\n setLoading(true);\n await fetchCep(data, setData, setCepError, setLoading);\n getCoordinates();\n }}\n mask=\"99999-999\"\n label=\"CEP\"\n className=\"rounded-xl\"\n placeholder=\"Digite seu CEP\"\n error={cepError}\n errorMsg=\"Por favor insira um CEP válido\"\n value={data.address_attributes.cep}\n onChange={(e) =>\n setData((data) => ({\n ...data,\n address_attributes: {\n ...data.address_attributes,\n cep: e.target.value,\n },\n }))\n }\n />\n \n setData((data) => ({\n ...data,\n address_attributes: {\n ...data.address_attributes,\n state: e,\n },\n }))\n }\n />\n \n setData((data) => ({\n ...data,\n address_attributes: {\n ...data.address_attributes,\n city: e.target.value,\n },\n }))\n }\n />\n \n setData((data) => ({\n ...data,\n address_attributes: {\n ...data.address_attributes,\n neighborhood: e.target.value,\n },\n }))\n }\n />\n
\n
\n \n setData((data) => ({\n ...data,\n address_attributes: {\n ...data.address_attributes,\n street: e.target.value,\n },\n }))\n }\n />\n
\n
\n \n setData((data) => ({\n ...data,\n address_attributes: {\n ...data.address_attributes,\n number: e.target.value,\n },\n }))\n }\n />\n
\n
\n {processing ? (\n
\n \n
\n ) : (\n \n )}\n \n \n );\n};\n\nexport default AddressInfo;\n","import { Link } from \"@inertiajs/react\";\nimport { Button, Text } from \"@switchdreams/ui\";\nimport React from \"react\";\n\nimport { imagePath } from \"../../utils\";\n\nconst AddressInfo = ({ clinic }) => {\n return (\n <>\n
\n \n \n Cadastro finalizado!\n \n \n Parabéns pelo sucesso do seu cadastro!\n \n \n Bem-vindo à família viaconsultas!\n \n \n \n \n
\n \n );\n};\n\nexport default AddressInfo;\n","import { ArrowLongLeftIcon } from \"@heroicons/react/24/outline\";\nimport { Button, SelectBox, Text, TextField, TextFieldMask } from \"@switchdreams/ui\";\nimport React, { useState } from \"react\";\n\nimport { genderOptions } from \"@/constants/SelectOptions\";\nimport { useAlert } from \"@/contexts/Alert\";\n\nconst PersonalInfo = ({ setSection, data, setData }) => {\n const { showAlert } = useAlert();\n const [cpfError, setCpfError] = useState(\"\");\n const [ageError, setAgeError] = useState(\"\");\n\n const nextStep = (e) => {\n e.preventDefault();\n if (data.cpf === \"\" || data.gender === \"\" || data.birthdate === \"\") {\n showAlert({ message: \"Preencha todos os campos!\", type: \"warning\" });\n } else if (ageCheck(data.birthdate)) {\n setSection(({ step, role }) => ({ step: step + 1, role }));\n } else {\n showAlert({ message: \"Você deve ter pelo menos 18 anos para prosseguir!\", type: \"warning\" });\n }\n };\n\n const ageCheck = (birthdate) => {\n const today = new Date();\n const birthDate = new Date(birthdate);\n const age = today.getFullYear() - birthDate.getFullYear();\n const monthDiff = today.getMonth() - birthDate.getMonth();\n\n if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birthDate.getDate())) {\n if (age < 18) {\n setAgeError(\"Você deve ter no mínimo 18 anos de idade\");\n }\n return age >= 18;\n }\n if (age < 18) {\n setAgeError(\"Você deve ter no mínimo 18 anos de idade\");\n }\n return age >= 18;\n };\n\n const handleCPFBlur = () => {\n const cpfRegex = /^\\d{3}\\.\\d{3}\\.\\d{3}-\\d{2}$/;\n if (!cpfRegex.test(data.cpf)) {\n setCpfError(\"O CPF deve estar no formato 999.999.999-99.\");\n } else {\n setCpfError(\"\");\n }\n };\n\n return (\n <>\n setSection(({ step, role }) => ({ step: step - 1, role }))}\n />\n
\n \n Continue seu cadastro\n \n Insira seus dados pessoais.\n
\n
nextStep(e)} className=\"flex w-[28rem] flex-col gap-4 max-sm:w-full\">\n setData(\"cpf\", e.target.value)}\n onBlur={() => handleCPFBlur()}\n />\n setData(\"gender\", e)}\n />\n setData(\"birthdate\", e.target.value)}\n name=\"birthdate\"\n />\n\n \n \n \n );\n};\n\nexport default PersonalInfo;\n","import { ArrowLongLeftIcon } from \"@heroicons/react/24/outline\";\nimport { Button, SelectBox, Text, TextField } from \"@switchdreams/ui\";\nimport axios from \"axios\";\nimport React from \"react\";\n\nimport { useAlert } from \"@/contexts/Alert\";\nimport { priceOptions } from \"@/utils\";\n\nconst ProfessionalInfo = ({\n setSection,\n data,\n setData,\n areaOptions,\n specialtyOptions,\n setSpecialtyOptions,\n}) => {\n const { showAlert } = useAlert();\n\n const getSpecialties = (id) => {\n axios\n .get(`/work_specialties/${id}.json`)\n .then((response) => setSpecialtyOptions(response.data))\n .catch(() =>\n showAlert({\n message: \"Não foi possível carregar as áreas de especialidade\",\n type: \"warning\",\n }),\n );\n };\n\n const nextStep = (e) => {\n e.preventDefault();\n if (\n data.doctor_attributes.council === \"\" ||\n data.doctor_attributes.work_area_id === \"\" ||\n data.doctor_attributes.work_specialty_id === null ||\n data.doctor_attributes.price_cents === \"\"\n ) {\n showAlert({ message: \"Preencha todos os campos!\", type: \"warning\" });\n } else {\n setSection(({ step, role }) => ({ step: step + 1, role }));\n }\n };\n\n return (\n <>\n {\n setSection(({ step, role }) => ({ step: step - 1, role }));\n }}\n />\n
\n \n Continue seu cadastro\n \n \n Insira seus dados profissionais.\n \n
\n
nextStep(e)} className=\"flex w-[28rem] flex-col gap-4 max-sm:w-full\">\n {\n setData((data) => ({\n ...data,\n doctor_attributes: {\n ...data.doctor_attributes,\n work_area_id: e,\n work_specialty_id: null,\n },\n }));\n getSpecialties(e);\n }}\n />\n \n setData((data) => ({\n ...data,\n doctor_attributes: {\n ...data.doctor_attributes,\n work_specialty_id: e,\n },\n }))\n }\n disabled={specialtyOptions.length < 1}\n />\n \n setData((data) => ({\n ...data,\n doctor_attributes: {\n ...data.doctor_attributes,\n council: e.target.value,\n },\n }))\n }\n />\n {\n setData((data) => ({\n ...data,\n doctor_attributes: {\n ...data.doctor_attributes,\n price_cents: e,\n },\n }));\n }}\n />\n \n \n \n );\n};\n\nexport default ProfessionalInfo;\n","import { ArrowLongLeftIcon, EyeIcon, EyeSlashIcon } from \"@heroicons/react/24/outline\";\nimport { router } from \"@inertiajs/react\";\nimport { Button, CheckBox, Text, TextField, TextFieldMask } from \"@switchdreams/ui\";\nimport React, { useState } from \"react\";\n\nimport { useAlert } from \"@/contexts/Alert\";\n\nconst StartAccount = ({ setSection, data, setData, terms, setTerms, clinic = null }) => {\n const [passwordError, setPasswordError] = useState();\n const [showPassword, setShowPassword] = useState(false);\n const [emailError, setEmailError] = useState();\n const [phoneError, setPhoneError] = useState();\n const { showAlert } = useAlert();\n\n const nextStep = (e) => {\n e.preventDefault();\n if (data.email === \"\" || data.password === \"\" || data.phone === \"\" || data.name === \"\") {\n showAlert({ message: \"Preencha todos os campos!\", type: \"warning\" });\n } else if (passwordError || emailError || phoneError) {\n showAlert({ message: \"Corrija o erro nos campos!\", type: \"warning\" });\n } else if (terms !== true) {\n showAlert({\n message:\n \"Você esqueceu de aceitar os termos de uso e política de privacidade. Por favor, marque a caixa antes de prosseguir.\",\n type: \"warning\",\n });\n } else {\n setSection(({ step, role }) => ({ step: step + 1, role }));\n }\n };\n\n const showPasswordIcon = () => {\n setShowPassword(!showPassword);\n };\n\n const handlePasswordBlur = () => {\n if (data.password.length < 6) {\n setPasswordError(\"A senha deve ter no mínimo 6 caracteres.\");\n } else {\n setPasswordError();\n }\n };\n\n const handleEmailBlur = () => {\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n\n if (!emailRegex.test(data.email)) {\n setEmailError(\"Por favor, insira um email válido.\");\n } else {\n setEmailError();\n }\n };\n\n const handlePhoneBlur = () => {\n const phoneRegex = /^\\(\\d{2}\\) \\d{5}-\\d{4}$/;\n if (!phoneRegex.test(data.phone)) {\n setPhoneError(\"O telefone deve ter no mínimo 11 caracteres.\");\n } else {\n setPhoneError();\n }\n };\n\n return (\n <>\n {\n if (clinic) {\n router.get(\"/clinica\");\n } else {\n setSection(({ step, role }) => ({ step: step - 1, role }));\n }\n }}\n />\n
\n Crie sua conta\n Insira seus dados de login.\n
\n
nextStep(e)} className=\"w-full max-w-screen-big\">\n setData(\"name\", e.target.value)}\n />\n setData(\"phone\", e.target.value)}\n onBlur={() => {\n handlePhoneBlur();\n }}\n />\n setData(\"email\", e.target.value)}\n onBlur={handleEmailBlur}\n error={emailError && true}\n errorMsg={emailError}\n />\n setData(\"password\", e.target.value)}\n onBlur={handlePasswordBlur}\n error={passwordError && true}\n errorMsg={passwordError}\n className=\"rounded-xl\"\n />\n
\n setTerms(!terms)} checked={terms} />\n \n Aceito os\n \n {\" \"}\n Termos de uso{\" \"}\n \n e\n \n {\" \"}\n Política de privacidade{\" \"}\n \n do viaconsultas\n \n
\n \n \n \n );\n};\n\nexport default StartAccount;\n","import { useForm } from \"@inertiajs/react\";\nimport { Text } from \"@switchdreams/ui\";\nimport axios from \"axios\";\nimport React, { useState } from \"react\";\n\nimport AddressInfo from \"@/components/SignUpSections/AddressInfo\";\nimport FinishSignUp from \"@/components/SignUpSections/FinishSignUp\";\nimport PersonalInfo from \"@/components/SignUpSections/PersonalInfo\";\nimport ProfessionalInfo from \"@/components/SignUpSections/ProfessionalInfo\";\nimport StartAccount from \"@/components/SignUpSections/StartAccount\";\nimport { useAlert } from \"@/contexts/Alert\";\n\nimport { imagePath } from \"../../utils\";\n\nconst SignUpDoctor = ({ area_options, clinic }) => {\n const { showAlert } = useAlert();\n const [currentSection, setCurrentSection] = useState({ step: 0, role: \"doctor\" });\n const [loading, setLoading] = useState(false);\n const [specialtyOptions, setSpecialtyOptions] = useState([]);\n const [terms, setTerms] = useState(false);\n const { setData, data } = useForm({\n role: \"doctor\",\n name: \"\",\n phone: \"\",\n email: \"\",\n password: \"\",\n cpf: \"\",\n gender: \"\",\n birthdate: \"\",\n address_attributes: {\n cep: \"\",\n city: \"\",\n state: \"\",\n neighborhood: \"\",\n street: \"\",\n number: \"\",\n latitude: \"\",\n longitude: \"\",\n },\n doctor_attributes: {\n work_area_id: \"\",\n work_specialty_id: \"\",\n council: \"\",\n },\n clinic_ids: [clinic.id],\n });\n\n const submitSignUpData = () => {\n setLoading(true);\n axios\n .post(\"/clinica/new_doctor\", data)\n .then(() => setCurrentSection(({ step, role }) => ({ step: step + 1, role })))\n .catch((response) => {\n showAlert({ message: response.response.data });\n })\n .finally(() => setLoading(false));\n };\n\n const sectionConfig = {\n doctor: {\n 0: (props) => ,\n 1: (props) => ,\n 2: (props) => (\n \n ),\n 3: (props) => (\n \n ),\n 4: () => ,\n },\n };\n\n const renderCurrentSection = () => {\n const sectionRenderer = sectionConfig[currentSection.role]?.[currentSection.step];\n\n if (sectionRenderer) {\n return sectionRenderer({\n setSection: setCurrentSection,\n setData,\n data,\n terms,\n setTerms,\n submitSignUpData,\n loading,\n area_options,\n specialtyOptions,\n setSpecialtyOptions,\n });\n }\n\n return null;\n };\n\n const renderProgressDots = () => {\n if (currentSection.role === \"doctor\" && currentSection.step >= 4) {\n return null;\n }\n\n // Desconsidera a primeira e a ultima seção para a contagem\n const totalSections = Object.keys(sectionConfig[currentSection.role]).length;\n const relevantSectionsStart = 2;\n const currentSectionNumber = currentSection.step + 1;\n\n if (currentSectionNumber > 0) {\n const dots = [];\n for (let i = 1; i <= totalSections - relevantSectionsStart + 1; i++) {\n dots.push(\n = i ? \"border-primary-400\" : \"border-primary-100\"\n }`}\n />,\n );\n if (i < totalSections - relevantSectionsStart + 1) {\n dots.push(\n i ? \"bg-primary-100\" : \"bg-coolGray-400\"\n }`}\n />,\n );\n }\n }\n return (\n
\n {dots}\n
\n );\n }\n return null;\n };\n\n const sectionWidthStyle = () => {\n if (currentSection.step === 0 || currentSection.step === 1) {\n return \"\";\n } else {\n return \"md:max-w-[450px] max-w-screen-0.5sm\";\n }\n };\n\n return (\n
\n \n
\n \n \n {clinic.name}\n \n
\n {renderCurrentSection()}\n {renderProgressDots()}\n
\n \n );\n};\n\nexport default SignUpDoctor;\n","import { MinusIcon, PlusIcon } from \"@heroicons/react/24/outline\";\nimport { router, useForm, usePage } from \"@inertiajs/react\";\nimport { Button, Text, TextField, TextFieldMask } from \"@switchdreams/ui\";\nimport axios from \"axios\";\nimport React, { useState } from \"react\";\n\nimport { useAlert } from \"@/contexts/Alert\";\nimport { cardBrandLogo } from \"@/utils\";\n\nconst CreditCards = ({ cards }) => {\n const { showAlert } = useAlert();\n const [showForm, setShowForm] = useState(false);\n const { currentUser } = usePage().props;\n const { setData, data, reset } = useForm({\n creditCard: {\n holderName: \"\",\n number: \"\",\n expiryMonth: \"\",\n expiryYear: \"\",\n ccv: \"\",\n },\n creditCardHolderInfo: {\n name: currentUser.name,\n email: currentUser.email,\n cpfCnpj: currentUser.cpf,\n postalCode: currentUser.address.cep,\n addressNumber: currentUser.address.number || \"0\",\n phone: currentUser.phone,\n },\n });\n\n const cpfCnpjMask = (v) => {\n v = v.replace(/\\D/g, \"\");\n\n if (v.length <= 11) {\n v = v.replace(/(\\d{3})(\\d)/, \"$1.$2\");\n v = v.replace(/(\\d{3})(\\d)/, \"$1.$2\");\n v = v.replace(/(\\d{3})(\\d{1,2})$/, \"$1-$2\");\n } else {\n v = v.replace(/^(\\d{2})(\\d)/, \"$1.$2\");\n v = v.replace(/^(\\d{2})\\.(\\d{3})(\\d)/, \"$1.$2.$3\");\n v = v.replace(/\\.(\\d{3})(\\d)/, \".$1/$2\");\n v = v.replace(/(\\d{4})(\\d)/, \"$1-$2\");\n }\n\n return v;\n };\n\n const tokenizeCard = () => {\n axios\n .post(\"/credit_cards\", data)\n .then(() => {\n router.reload({ only: [\"cards\"] });\n setShowForm(false);\n reset();\n showAlert({ message: \"Cartão salvo com sucesso\", type: \"success\" });\n })\n .catch((e) => showAlert(e));\n };\n\n return (\n
\n Pagamento Recorrente\n
\n {cards.map((card) => {\n return (\n \n **** **** **** {card.credit_card_number}\n \n
\n );\n })}\n
\n
\n setShowForm(!showForm)}\n />\n
\n {showForm && (\n
\n {\n setData({\n ...data,\n creditCard: { ...data.creditCard, holderName: e.target.value },\n });\n }}\n />\n {\n if (e.target.value.length <= 18) {\n const cpfCnpj = cpfCnpjMask(e.target.value);\n setData({\n ...data,\n creditCardHolderInfo: {\n ...data.creditCardHolderInfo,\n cpfCnpj: cpfCnpj,\n },\n });\n } else {\n setData({\n ...data,\n creditCardHolderInfo: {\n ...data.creditCardHolderInfo,\n cpfCnpj: e.target.value.slice(0, -1),\n },\n });\n }\n }}\n />\n {\n const cardNumber = e.target.value.replace(/\\s/g, \"\");\n setData({\n ...data,\n creditCard: { ...data.creditCard, number: cardNumber },\n });\n }}\n />\n {\n const expiryMonth = e.target.value.split(\"/\")[0];\n const expiryYear = e.target.value.split(\"/\")[1];\n setData({\n ...data,\n creditCard: {\n ...data.creditCard,\n expiryMonth: expiryMonth,\n expiryYear: expiryYear,\n },\n });\n }}\n />\n {\n setData({\n ...data,\n creditCard: { ...data.creditCard, ccv: e.target.value },\n });\n }}\n />\n tokenizeCard()}\n />\n
\n )}\n \n );\n};\n\nexport default CreditCards;\n","import { Text } from \"@switchdreams/ui\";\nimport React from \"react\";\n\nimport { imagePath } from \"@/utils\";\n\nconst DefaultMessage = ({ isDragActive, type, currentImage }) => {\n const textClassName = (isDragActive) => {\n if (isDragActive) return \"text-secondary-400 font-semibold\";\n };\n\n const currentImagePath = () => {\n if (currentImage) {\n return currentImage;\n } else {\n return isDragActive ? imagePath(\"img_icon_blue.svg\") : imagePath(\"img_icon.svg\");\n }\n };\n\n return (\n <>\n {type != \"img\" ? (\n \n ) : (\n \"img_icon\"\n )}\n \n Adicione uma imagem\n \n \n Selecione o arquivo ou arraste e solte aqui\n \n \n );\n};\n\nexport default DefaultMessage;\n","import { XMarkIcon } from \"@heroicons/react/24/outline\";\nimport React from \"react\";\n\nconst DeleteFile = ({ setSelectedFile }) => {\n const handleRemoveFile = (event) => {\n event.preventDefault();\n setSelectedFile(null);\n };\n\n return (\n <>\n
\n {\n e.stopPropagation();\n handleRemoveFile(e);\n }}\n className=\"size-5 border-none bg-transparent p-0 text-primary-800\"\n >\n \n \n
\n \n );\n};\n\nexport default DeleteFile;\n","import { Text } from \"@switchdreams/ui\";\nimport React from \"react\";\n\nimport { imagePath } from \"@/utils\";\n\nconst FileInfos = ({ type, selectedFile }) => {\n if (!!selectedFile && !Array.isArray(selectedFile)) selectedFile = [selectedFile];\n\n return (\n <>\n {/*TODO: display selected images if input is multiple*/}\n {type != \"img\" ? (\n <>\n \"pdf_icon\"\n {selectedFile.map((file, index) => {\n return (\n \n {file.path}\n \n );\n })}\n \n ) : (\n
\n \n
\n )}\n \n );\n};\n\nexport default FileInfos;\n","import { Text } from \"@switchdreams/ui\";\nimport React from \"react\";\n\nconst FileSize = ({ type, selectedFile }) => {\n if (!!selectedFile && !Array.isArray(selectedFile)) selectedFile = [selectedFile];\n\n const bytesToMegabytes = (bytes) => {\n return (bytes / (1024 * 1024)).toFixed(2);\n };\n\n return (\n <>\n {selectedFile && type !== \"img\" && (\n \n {bytesToMegabytes(selectedFile[0].size) + \"MB\"}\n \n )}\n \n );\n};\n\nexport default FileSize;\n","import React, { useCallback, useEffect, useState } from \"react\";\nimport { useDropzone } from \"react-dropzone\";\n\nimport DefaultMessage from \"./defaultMessage\";\nimport DeleteFile from \"./deleteFile\";\nimport FileInfos from \"./fileInfos\";\nimport FileSize from \"./fileSize\";\n\nconst InputFile = ({\n type = \"doc\",\n initialValue = null,\n dataAttribute,\n setData,\n multiple = false,\n currentImage,\n ...rest\n}) => {\n const [selectedFile, setSelectedFile] = useState(initialValue);\n\n useEffect(() => {\n if (setData) setData(dataAttribute, selectedFile);\n }, [selectedFile]);\n\n const onDrop = useCallback((acceptedFiles) => {\n setSelectedFile(multiple ? acceptedFiles : acceptedFiles[0]);\n }, []);\n\n const { getRootProps, getInputProps, isDragActive } = useDropzone({ onDrop });\n\n const componentPaddingClassName = () => {\n if (selectedFile && type != \"img\") return \"px-3 py-16\";\n if (selectedFile == null || selectedFile.length == 0) return \"px-3 py-16\";\n };\n\n const componentBackgroundClassName = () => {\n if (isDragActive) return \"border-secondary-400 bg-secondary-50\";\n else return \"border-primary-100 hover:bg-primary-50\";\n };\n\n const input_params = () => {\n if (type == \"img\") {\n return { accept: \"image/*\" };\n } else {\n return {};\n }\n };\n\n return (\n \n \n\n {selectedFile == null || selectedFile.length == 0 ? (\n \n ) : (\n <>\n \n \n \n \n )}\n \n );\n};\n\nexport default InputFile;\n","import React from \"react\";\n\nimport InputFile from \"../InputFile/index\";\nimport Modal from \"../Modal\";\n\nconst AddImageModal = ({ open, setOpen, currentImage, onClickConfirm, fileForm }) => {\n return (\n setOpen(false)}\n cancelLabel=\"Cancelar\"\n confirmLabel=\"Editar\"\n onClickConfirm={() => onClickConfirm()}\n >\n
\n \n
\n \n );\n};\n\nexport default AddImageModal;\n","import {\n BriefcaseIcon,\n CameraIcon,\n MapPinIcon,\n PlusIcon,\n UserCircleIcon,\n XMarkIcon,\n} from \"@heroicons/react/24/outline\";\nimport { CogIcon } from \"@heroicons/react/24/solid\";\nimport { router, useForm } from \"@inertiajs/react\";\nimport {\n Avatar,\n Button,\n SelectBox,\n Text,\n TextArea,\n TextField,\n TextFieldMask,\n} from \"@switchdreams/ui\";\nimport axios from \"axios\";\nimport React, { useEffect, useReducer, useState } from \"react\";\nimport { imagePath } from \"@/utils\";\nimport { fetchCep } from \"@/utils\";\n\nimport { genderOptions, stateOptions } from \"@/constants/SelectOptions\";\nimport { useAlert } from \"@/contexts/Alert\";\nimport {\n monthsTranslated,\n pixTypeMask,\n pixTypeOptions,\n priceOptions,\n yesOrNotOptions,\n} from \"@/utils\";\n\nimport AddImageModal from \"../AddImageModal\";\n\nconst EditProfile = ({ user, data, setData, areaOptions, clinic }) => {\n console.log('DATA USER', user)\n const [open, setOpen] = useState(false);\n const [selectedSpecialty, setSelectedSpecialty] = useState(null);\n const [specialtyArr, setSpecialtyArr] = useState([]);\n const [openClinicModal, setOpenClinicModal] = useState(false);\n const { showAlert } = useAlert();\n const fileForm = useForm({ image: null });\n const [files, setFiles] = useState([]);\n const fileFormClinic = useForm({ image: null });\n const [cepError, setCepError] = useState(false);\n const [loading, setLoading] = useState(false);\n\n const onFileChange = (event) => {\n const formData = new FormData();\n formData.append('id', user.id);\n // Object.keys(event.target.files).map((item) => {\n // console.log(event.target.files[item])\n // formData.append('images[]', event.target.files[item]);\n // })\n formData.append('images[]', ...event.target.files);\n\n router.post('/image_upload', formData, {\n forceFormData: true, // Força o uso do FormData, necessário para Inertia com arquivos\n onSuccess: () => {\n console.log(\"Upload concluído com sucesso!\");\n },\n onError: (errors) => {\n console.error(\"Erro durante o upload:\", errors);\n }\n });\n };\n const removeImage = (id) => {\n router.post('/remove_image', {id});\n }\n useEffect(() => {\n console.log(files)\n // setData('user_media', files)\n }, [files])\n\n useEffect(() => {\n let arr = [];\n\n if (clinic !== null) {\n clinic.work_specialties.map((item) => {\n arr.push({ value: item.id, label: item.name });\n });\n setSpecialtyArr(arr);\n }\n }, []);\n\n const formatDateOfRegister = () => {\n const date = user.registered_since.split(\"/\");\n return `${date[0]} de ${monthsTranslated[Number(date[1]) - 1]} de ${date[2]}`;\n };\n\n const [specialtyOptions, setSpecialtyOptions] = useState([]);\n\n const getCoordinates = async () => {\n const apiKey = \"AIzaSyAoLzTfDNeO5ZBNk8yyvZ6p5CJnWPKM8LU\";\n const url = `https://maps.googleapis.com/maps/api/geocode/json?address=${data.address_attributes.cep}&key=${apiKey}`;\n \n setLoading(true); // Inicia o carregamento\n \n try {\n const response = await axios.get(url);\n const responseData = response.data; // Renomeado para evitar conflitos\n \n if (responseData.results && responseData.results.length > 0) {\n const location = responseData.results[0].geometry.location;\n console.log(location.lat, location.lng);\n \n setData((data) => ({\n ...data,\n address_attributes: {\n ...data.address_attributes,\n latitude: location.lat.toString(),\n longitude: location.lng.toString(),\n },\n }));\n console.log(data)\n return location; // Retorna latitude e longitude\n } else {\n throw new Error(\"Endereço não encontrado para o CEP fornecido\");\n }\n } catch (error) {\n console.error(\"Erro ao buscar dados de geolocalização:\", error);\n showAlert({ message: \"Erro ao buscar localização. Verifique o CEP e tente novamente.\", type: \"error\" });\n } finally {\n setLoading(false); // Finaliza o carregamento\n }\n };\n \n const getSpecialties = (id) => {\n axios\n .get(`/work_specialties/${id}`)\n .then((response) => setSpecialtyOptions(response.data))\n .catch(() => showAlert({ message: \"Ocorreu um erro. Tente novamente\", type: \"warning\" }));\n };\n\n const updateUserImage = () => {\n fileForm.patch(`/users/${user.id}/attach_image`, {\n onError: (e) => {\n showAlert({ message: e });\n },\n onSuccess: () => {\n showAlert({ message: \"Dados de usuário editados com sucesso!\", type: \"success\" });\n },\n });\n setOpen(false);\n };\n const [, forceUpdate] = useReducer((x) => x + 1, 0);\n\n const updateClinicImage = () => {\n fileFormClinic.patch(\"/clinica/attach_image\", {\n onError: (e) => {\n showAlert({ message: e });\n },\n onSuccess: () => {\n showAlert({ message: \"Dados da clinica editados com sucesso!\", type: \"success\" });\n },\n });\n setOpenClinicModal(false);\n };\n\n useEffect(() => {\n getSpecialties(data.doctor_attributes.work_area_id);\n }, []);\n\n const addSpecialty = () => {\n let arr = specialtyArr;\n let idsArr = [];\n data.work_specialties_options.map((item) => {\n if (item.value == selectedSpecialty) {\n arr.push(item);\n idsArr.push(item.value);\n }\n });\n\n arr = arr.filter(function (item, pos) {\n return arr.indexOf(item) == pos;\n });\n\n setSpecialtyArr(arr);\n forceUpdate();\n setSpecialtyArrIds(idsArr);\n };\n\n const setSpecialtyArrIds = (idsArr) => {\n specialtyArr.map((item) => {\n idsArr.push(item.value);\n });\n\n idsArr = idsArr.filter(function (item, pos) {\n return idsArr.indexOf(item) == pos;\n });\n\n setData((data) => ({\n ...data,\n clinic_attributes: {\n ...data.clinic_attributes,\n work_specialty_ids: idsArr,\n },\n }));\n forceUpdate();\n };\n\n return (\n
\n \n
\n setOpen(true)}\n >\n \n \n \n
\n \n
\n
\n
\n \n {user.name}\n \n \n {user?.doctor?.work_specialty?.name}\n \n
\n Cadastrado desde\n {formatDateOfRegister()}\n
\n
\n
\n
\n
\n\n
\n
\n {\n user.role !== \"patient\" ? (\n
\n
A partir da sua primeira consulta ou exame uma conta ficará disponível no site do https://www.asaas.com/
\n
\n
Você receberá um E-mail da plataforma Asaas para o primeiro acesso e definição da sua senha, no endereço cadastrado no viaconsultas
\n
\n
O Asaas é a plataforma de pagamento onde ficarão disponíveis todos os valores recebidos através das suas consultas no Viaconsultas
\n
\n ) : null\n }\n\n
\n \n Pessoal\n
\n
\n
\n
\n setData(\"name\", e.target.value)}\n />\n
\n
\n setData(\"cpf\", e.target.value)}\n />\n
\n
\n
\n
\n setData(\"gender\", e)}\n />\n
\n
\n setData(\"phone\", e.target.value)}\n />\n
\n
\n
\n setData(\"birthdate\", e.target.value)}\n />\n
\n
\n\n {user.role === \"doctor\" && (\n <>\n
\n \n \n Profissional\n \n
\n
\n
\n
\n {\n setData((data) => ({\n ...data,\n doctor_attributes: {\n ...data.doctor_attributes,\n work_area_id: e,\n work_specialty_id: null,\n },\n }));\n getSpecialties(e);\n }}\n />\n
\n
\n {\n setData((data) => ({\n ...data,\n doctor_attributes: {\n ...data.doctor_attributes,\n council: e.target.value,\n },\n }));\n }}\n />\n
\n
\n
\n {\n setData((data) => ({\n ...data,\n doctor_attributes: {\n ...data.doctor_attributes,\n work_specialty_id: e,\n },\n }));\n }}\n />\n
\n
\n \n )}\n
\n \n Imagens\n
\n\n
\n
\n
\n {[...user.user_media].map((item) => (\n
\n \n removeImage(item.id)}\n className=\"absolute top-2 right-2 bg-red-500 text-white rounded-full p-1 hover:bg-red-600 transition duration-200\"\n >\n \n \n \n \n
\n ))}\n
\n
\n
\n
\n
\n \n \n
\n
\n
\n \n Endereço\n
\n
\n
\n
\n {\n await fetchCep(data, setData, setCepError, setLoading);\n getCoordinates();\n }}\n onChange={(e) => {\n setData((data) => ({\n ...data,\n address_attributes: {\n ...data.address_attributes,\n cep: e.target.value,\n },\n }));\n }}\n />\n
\n
\n {\n setData((data) => ({\n ...data,\n address_attributes: {\n ...data.address_attributes,\n state: e,\n },\n }));\n }}\n />\n
\n
\n
\n
\n {\n setData((data) => ({\n ...data,\n address_attributes: {\n ...data.address_attributes,\n city: e.target.value,\n },\n }));\n }}\n />\n
\n
\n {\n setData((data) => ({\n ...data,\n address_attributes: {\n ...data.address_attributes,\n neighborhood: e.target.value,\n },\n }));\n }}\n />\n
\n
\n
\n
\n {\n setData((data) => ({\n ...data,\n address_attributes: {\n ...data.address_attributes,\n street: e.target.value,\n },\n }));\n }}\n />\n
\n
\n {\n setData((data) => ({\n ...data,\n address_attributes: {\n ...data.address_attributes,\n number: e.target.value,\n },\n }));\n }}\n />\n
\n
\n
\n
\n\n {clinic && (\n
\n
\n \n
\n \n Escolha aqui as áreas de atuação da Clínica\n \n
\n
\n\n
\n
\n \n setData((data) => ({\n ...data,\n clinic_attributes: {\n ...data.clinic_attributes,\n exam_enabled: e,\n },\n }))\n }\n />\n
\n\n {/*
\n \n
*/}\n
\n\n
\n
\n {\n setSelectedSpecialty(e);\n }}\n />\n
\n
\n\n
\n
\n \n
\n
\n\n
\n
\n

Áreas de Atuação Selecionadas:

\n {specialtyArr.map((item) => (\n \n {item.label}\n \n ))}\n
\n
\n\n
\n \n
\n \n Dados da Clínica\n \n
\n
\n\n
\n updateClinicImage()}\n fileForm={fileFormClinic}\n />\n setOpenClinicModal(true)}\n >\n \n
\n \n
\n
\n
\n\n
\n
\n \n setData((data) => ({\n ...data,\n clinic_attributes: {\n ...data.clinic_attributes,\n name: e.target.value,\n },\n }))\n }\n />\n
\n
\n \n setData((data) => ({\n ...data,\n clinic_attributes: {\n ...data.clinic_attributes,\n cnpj: e.target.value,\n },\n }))\n }\n />\n
\n
\n\n
\n
\n
\n \n setData((data) => ({\n ...data,\n clinic_attributes: {\n ...data.clinic_attributes,\n description: e.target.value,\n },\n }))\n }\n />\n
\n
\n
\n\n
\n
\n {\n setData((data) => ({\n ...data,\n clinic_attributes: {\n ...data.clinic_attributes,\n pix_type: e,\n },\n }));\n }}\n />\n
\n
\n \n setData((data) => ({\n ...data,\n clinic_attributes: {\n ...data.clinic_attributes,\n pix_key: e.target.value,\n },\n }))\n }\n />\n
\n
\n
\n )}\n\n {user.role === \"doctor\" && (\n
\n
\n \n
\n \n Meu Perfil\n \n \n Essas informações aparecerão para os pacientes usuários da plataforma.\n \n
\n
\n\n
\n
\n
\n \n setData((data) => ({\n ...data,\n doctor_attributes: {\n ...data.doctor_attributes,\n description: e.target.value,\n },\n }))\n }\n />\n
\n
\n
\n\n
\n
\n
\n {\n setData((data) => ({\n ...data,\n doctor_attributes: {\n ...data.doctor_attributes,\n price_cents: e,\n },\n }));\n }}\n />\n
\n
\n
\n\n
\n \n Experiências Profissionais\n \n {data.doctor_attributes.professional_experiences.map((experience, index) => (\n
\n
\n {\n let dataCopy = data.doctor_attributes.professional_experiences;\n dataCopy[index] = e.target.value;\n setData((data) => ({\n ...data,\n doctor_attributes: {\n ...data.doctor_attributes,\n professional_experiences: dataCopy,\n },\n }));\n }}\n />\n
\n
\n {\n if (data.doctor_attributes.professional_experiences.length > 1) {\n const new_array = data.doctor_attributes.professional_experiences;\n new_array.splice(index, 1);\n setData((data) => ({\n ...data,\n doctor_attributes: {\n ...data.doctor_attributes,\n professional_experiences: new_array,\n },\n }));\n }\n }}\n />\n
\n
\n ))}\n {\n setData((data) => ({\n ...data,\n doctor_attributes: {\n ...data.doctor_attributes,\n professional_experiences: [\n ...data.doctor_attributes.professional_experiences,\n \"\",\n ],\n },\n }));\n }}\n icon={PlusIcon}\n iconSide=\"left\"\n className=\"text-md transition-500 mt-3 rounded-2xl border border-primary-500 font-poppins font-medium text-primary-500 transition-all hover:bg-primary-50 lg:w-60\"\n label={\"Adicionar Experiência\"}\n />\n
\n\n
\n \n Formações Acadêmicas\n \n {data.doctor_attributes.educational_history.map((experience, index) => (\n
\n
\n {\n let dataCopy = data.doctor_attributes.educational_history;\n dataCopy[index] = e.target.value;\n setData((data) => ({\n ...data,\n doctor_attributes: {\n ...data.doctor_attributes,\n educational_history: dataCopy,\n },\n }));\n }}\n />\n
\n
\n {\n if (data.doctor_attributes.educational_history.length > 1) {\n const new_array = data.doctor_attributes.educational_history;\n new_array.splice(index, 1);\n setData((data) => ({\n ...data,\n doctor_attributes: {\n ...data.doctor_attributes,\n educational_history: new_array,\n },\n }));\n }\n }}\n />\n
\n
\n ))}\n {\n setData((data) => ({\n ...data,\n doctor_attributes: {\n ...data.doctor_attributes,\n educational_history: [...data.doctor_attributes.educational_history, \"\"],\n },\n }));\n }}\n icon={PlusIcon}\n iconSide=\"left\"\n className=\"text-md transition-500 mt-3 rounded-2xl border border-primary-500 font-poppins font-medium text-primary-500 transition-all hover:bg-primary-50 lg:w-60\"\n label={\"Adicionar Formação\"}\n />\n
\n
\n )}\n \n \n );\n};\n\nexport default EditProfile;\n","import { useForm, usePage } from \"@inertiajs/react\";\nimport { Button, Text } from \"@switchdreams/ui\";\nimport React from \"react\";\n\nimport EditProfile from \"@/components/ProfileSections/EditProfile\";\nimport { useAlert } from \"@/contexts/Alert\";\n\nconst Profile = ({ area_options, clinic, work_specialties_options }) => {\n const { showAlert } = useAlert();\n const { currentUser } = usePage().props;\n const { setData, data, patch } = useForm({\n work_specialties_options: work_specialties_options,\n name: currentUser.name,\n cpf: currentUser.cpf,\n gender: currentUser.gender,\n phone: currentUser.phone,\n birthdate: currentUser.birthdate,\n doctor_attributes:\n currentUser.role === \"doctor\"\n ? {\n id: currentUser.doctor.id,\n price_cents: currentUser.doctor.price_cents,\n work_area_id: currentUser.doctor.work_area.id,\n work_specialty_id: currentUser.doctor.work_specialty.id,\n council: currentUser.doctor.council,\n description: currentUser.doctor.description,\n professional_experiences: currentUser.doctor.professional_experiences,\n educational_history: currentUser.doctor.educational_history,\n }\n : {},\n address_attributes: {\n cep: currentUser.address.cep,\n city: currentUser.address.city,\n state: currentUser.address.state,\n neighborhood: currentUser.address.neighborhood,\n street: currentUser.address.street,\n number: currentUser.address.number,\n latitude: currentUser.address.latitude,\n longitude: currentUser.address.longitude,\n },\n clinic_attributes: clinic,\n });\n\n const updateUser = () => {\n patch(\"perfil\", {\n onSuccess: () => {\n showAlert({ message: \"Dados atualizados com sucesso\", type: \"success\" });\n },\n onError: (e) => {\n showAlert({ message: e, type: \"warning\" });\n },\n });\n };\n\n return (\n <>\n
\n \n
\n
\n \n Salvar alterações?\n \n
\n updateUser()}\n />\n
\n
\n \n );\n};\n\nexport default Profile;\n","import {\n ArrowLongLeftIcon,\n ChevronRightIcon,\n MapPinIcon,\n UserIcon,\n} from \"@heroicons/react/24/outline\";\nimport { Button, Text } from \"@switchdreams/ui\";\nimport React from \"react\";\n\nconst DoctorType = ({ setData, setSection }) => {\n return (\n <>\n {\n setSection(({ step, role }) => ({ step: step - 1, role }));\n }}\n />\n
\n \n Em qual perfil você se encaixa?\n \n
\n
\n {\n setData((oldData) => {\n return {\n ...oldData,\n role: \"manager\",\n clinics_attributes: {\n name: \"\",\n cnpj: \"\",\n description: \"\",\n pix_key: \"\",\n pix_type: \"\",\n },\n };\n });\n setSection((oldSection) => ({ step: oldSection.step + 1, role: \"manager\" }));\n }}\n className=\"flex w-96 cursor-pointer flex-col justify-start gap-6 rounded-3xl border border-primary-25 p-6 transition-all duration-500 hover:scale-105 max-md:w-full\"\n >\n
\n \n
\n
\n \n Clínica Privada\n \n \n Possuo uma clínica com um time de profissionais da saúde e quero integrá-los no\n viaconsultas.\n \n
\n
\n \n
\n
\n {\n setData((oldData) => {\n return {\n ...oldData,\n role: \"doctor\",\n doctor_attributes: {\n council: \"\",\n work_area_id: \"\",\n work_specialty_id: \"\",\n },\n clinics_attributes: {\n name: \"\",\n cnpj: \"\",\n description: \"\",\n pix_key: \"\",\n pix_type: \"\",\n },\n };\n });\n setSection((oldSection) => ({ step: oldSection.step + 1, role: \"doctor\" }));\n }}\n className=\"flex w-96 cursor-pointer flex-col justify-start gap-6 rounded-3xl border border-primary-25 p-6 transition-all duration-500 hover:scale-105 max-md:w-full\"\n >\n
\n \n
\n
\n \n Consultório autônomo\n \n \n Sou profissional autônomo e possuo um consultório próprio para atender meus pacientes.\n \n
\n
\n \n
\n \n \n \n );\n};\n\nexport default DoctorType;\n","import { ArrowLongLeftIcon } from \"@heroicons/react/24/outline\";\nimport { Button, SelectBox, Text, TextArea, TextField, TextFieldMask } from \"@switchdreams/ui\";\nimport React from \"react\";\n\nimport { useAlert } from \"@/contexts/Alert\";\nimport { pixTypeMask, pixTypeOptions, yesOrNotOptions } from \"@/utils\";\n\nconst LocationInfo = ({ setSection, data, setData }) => {\n const { showAlert } = useAlert();\n\n const nextStep = (e) => {\n e.preventDefault();\n if (\n (data.locationName === \"\" ||\n data.cnpj === \"\" ||\n data.locationDescription === \"\" ||\n data.pix_key === \"\",\n data.pix_type === \"\")\n ) {\n showAlert({ message: \"Preencha todos os campos!\", type: \"warning\" });\n } else {\n setSection(({ step, role }) => ({ step: step + 1, role }));\n }\n };\n\n return (\n <>\n {\n setSection(({ step, role }) => ({ step: step - 1, role }));\n }}\n />\n
\n \n Continue seu cadastro\n \n \n {data.doctorType === \"autonomy\"\n ? \"Insira informações sobre o seu consultório.\"\n : \"Insira informações sobre o sua clínica\"}\n \n
\n
nextStep(e)} className=\"flex w-[28rem] flex-col gap-4 max-sm:w-full\">\n \n setData({\n ...data,\n clinics_attributes: { ...data.clinics_attributes, name: e.target.value },\n })\n }\n type=\"text\"\n />\n \n setData({\n ...data,\n clinics_attributes: { ...data.clinics_attributes, cnpj: e.target.value },\n })\n }\n type=\"text\"\n />\n \n setData((data) => ({\n ...data,\n clinics_attributes: {\n ...data.clinics_attributes,\n exam_enabled: e,\n },\n }))\n }\n />\n {\n setData((data) => ({\n ...data,\n clinics_attributes: {\n ...data.clinics_attributes,\n pix_type: e,\n },\n }));\n }}\n type=\"text\"\n />\n \n setData({\n ...data,\n clinics_attributes: { ...data.clinics_attributes, pix_key: e.target.value },\n })\n }\n type=\"text\"\n />\n \n setData({\n ...data,\n clinics_attributes: { ...data.clinics_attributes, description: e.target.value },\n })\n }\n />\n \n \n \n );\n};\n\nexport default LocationInfo;\n","import {\n ArrowLongLeftIcon,\n ChevronRightIcon,\n PlusCircleIcon,\n UserIcon,\n} from \"@heroicons/react/24/outline\";\nimport { Link } from \"@inertiajs/react\";\nimport { Button, Text } from \"@switchdreams/ui\";\nimport React from \"react\";\n\nconst UserType = ({ setSection, setData }) => {\n return (\n <>\n \n \n \n
\n \n Selecione seu objetivo no viaconsultas\n \n
\n
\n {\n setData(\"role\", \"patient\");\n setSection((oldSection) => ({ step: oldSection.step + 1, role: \"patient\" }));\n }}\n className=\"flex w-96 cursor-pointer flex-col justify-start gap-6 rounded-3xl border border-primary-25 p-6 transition-all duration-500 hover:scale-105 max-md:w-full\"\n >\n
\n \n
\n
\n \n Sou paciente\n \n \n Quero ser atendido pelos melhores especialistas da minha região.\n \n
\n
\n \n
\n
\n {\n setData(\"role\", \"doctor\");\n setSection((oldSection) => ({ step: oldSection.step + 1, role: \"doctor\" }));\n }}\n className=\"flex w-96 cursor-pointer flex-col justify-start gap-6 rounded-3xl border border-primary-25 p-6 transition-all duration-500 hover:scale-105 max-md:w-full\"\n >\n
\n \n
\n
\n \n Sou profissional da saúde\n \n \n Trabalho na área da saúde e quero atender mais pacientes de forma simplificada.\n \n
\n
\n \n
\n \n \n \n );\n};\n\nexport default UserType;\n","import { useForm } from \"@inertiajs/react\";\nimport axios from \"axios\";\nimport React, { useState } from \"react\";\n\nimport AddressInfo from \"@/components/SignUpSections/AddressInfo\";\nimport DoctorTypeInfo from \"@/components/SignUpSections/DoctorTypeInfo\";\nimport FinishSignUp from \"@/components/SignUpSections/FinishSignUp\";\nimport LocationInfo from \"@/components/SignUpSections/LocationInfo\";\nimport PersonalInfo from \"@/components/SignUpSections/PersonalInfo\";\nimport ProfessionalInfo from \"@/components/SignUpSections/ProfessionalInfo\";\nimport StartAccount from \"@/components/SignUpSections/StartAccount\";\nimport UserTypeInfo from \"@/components/SignUpSections/UserTypeInfo\";\nimport { useAlert } from \"@/contexts/Alert\";\n\nconst SignUp = ({ area_options }) => {\n const { showAlert } = useAlert();\n const [currentSection, setCurrentSection] = useState({ step: 0, role: \"patient\" });\n const [loading, setLoading] = useState(false);\n const [specialtyOptions, setSpecialtyOptions] = useState([]);\n const [terms, setTerms] = useState(false);\n const { setData, data } = useForm({\n role: \"\",\n name: \"\",\n phone: \"\",\n email: \"\",\n password: \"\",\n cpf: \"\",\n gender: \"\",\n type: \"\",\n doctorType: \"\",\n birthdate: \"\",\n address_attributes: {\n cep: \"\",\n city: \"\",\n state: \"\",\n neighborhood: \"\",\n street: \"\",\n number: \"\",\n latitude: \"\",\n longitude: \"\",\n },\n });\n\n const submitSignUpData = () => {\n setLoading(true);\n axios\n .post(\"/sign_up\", data)\n .then(() => setCurrentSection(({ step, role }) => ({ step: step + 1, role })))\n .catch((response) => {\n showAlert({ message: response.response.data });\n })\n .finally(() => setLoading(false));\n };\n\n const sectionConfig = {\n patient: {\n 0: (props) => ,\n 1: (props) => ,\n 2: (props) => ,\n 3: (props) => (\n \n ),\n 4: () => ,\n },\n doctor: {\n 0: (props) => ,\n 1: (props) => ,\n 2: (props) => ,\n 3: (props) => ,\n 4: (props) => (\n \n ),\n 5: (props) => ,\n 6: (props) => (\n \n ),\n 7: () => ,\n },\n manager: {\n 0: (props) => ,\n 1: (props) => ,\n 2: (props) => ,\n 3: (props) => ,\n 4: (props) => ,\n 5: (props) => (\n \n ),\n 6: () => ,\n },\n };\n\n const renderCurrentSection = () => {\n const sectionRenderer = sectionConfig[currentSection.role]?.[currentSection.step];\n\n if (sectionRenderer) {\n return sectionRenderer({\n setSection: setCurrentSection,\n setData,\n data,\n terms,\n setTerms,\n submitSignUpData,\n loading,\n area_options,\n specialtyOptions,\n setSpecialtyOptions,\n });\n }\n\n return null;\n };\n\n const renderProgressDots = () => {\n if (\n (currentSection.role === \"doctor\" &&\n (currentSection.step === 1 || currentSection.step >= 7)) ||\n (currentSection.role === \"manager\" &&\n (currentSection.step === 1 || currentSection.step >= 6)) ||\n (currentSection.role === \"patient\" && currentSection.step >= 4)\n ) {\n // Não renderiza dots nas telas de DoctorTypeInfo e FinishSignUp para doctors\n // e na tela de FinishSignUp para patients\n return null;\n }\n\n // Desconsidera a primeira e a ultima seção para a contagem\n const totalSections = Object.keys(sectionConfig[currentSection.role]).length - 2;\n const relevantSectionsStart =\n currentSection.role === \"doctor\" || currentSection.role === \"manager\" ? 2 : 1;\n const currentSectionNumber =\n currentSection.step >= relevantSectionsStart\n ? currentSection.step - relevantSectionsStart + 1\n : 0;\n\n if (currentSectionNumber > 0) {\n const dots = [];\n for (let i = 1; i <= totalSections - relevantSectionsStart + 1; i++) {\n dots.push(\n = i ? \"border-primary-400\" : \"border-primary-100\"\n }`}\n />,\n );\n if (i < totalSections - relevantSectionsStart + 1) {\n dots.push(\n i ? \"bg-primary-100\" : \"bg-coolGray-400\"\n }`}\n />,\n );\n }\n }\n return (\n
\n {dots}\n
\n );\n }\n return null;\n };\n\n const sectionWidthStyle = () => {\n if (\n currentSection.step === 0 ||\n (currentSection.step === 1 && (data.role === \"doctor\" || data.role === \"manager\"))\n ) {\n return \"\";\n } else {\n return \"md:max-w-[450px] max-w-screen-0.5sm\";\n }\n };\n\n return (\n
\n \n {renderCurrentSection()}\n {renderProgressDots()}\n
\n \n );\n};\n\nexport default SignUp;\n","import { CheckIcon } from \"@heroicons/react/24/outline\";\nimport { router } from \"@inertiajs/react\";\nimport { Button, Text } from \"@switchdreams/ui\";\nimport React from \"react\";\n\nconst StepFour = () => {\n return (\n
\n
\n
\n \n
\n \n Sucesso!\n \n \n Você trocou sua senha com êxito.\n \n router.visit(\"/login\")}\n />\n
\n
\n );\n};\n\nexport default StepFour;\n","import { ArrowLongLeftIcon } from \"@heroicons/react/24/outline\";\nimport React from \"react\";\n\nconst ClickBack = ({ onClickBack }) => {\n return (\n
\n \n \n
\n \n );\n};\n\nexport default ClickBack;\n","import { router, useForm } from \"@inertiajs/react\";\nimport { Button, Text, TextField } from \"@switchdreams/ui\";\nimport React from \"react\";\n\nimport ClickBack from \"@/components/ClickBack\";\nimport { useAlert } from \"@/contexts/Alert\";\n\nconst StepOne = () => {\n const { showAlert } = useAlert();\n const { setData, data, post } = useForm({\n email: \"\",\n });\n\n const submitStepOneData = (e) => {\n e.preventDefault();\n if (data.email === \"\") {\n showAlert({ message: \"Preecha todos os campos!\", type: \"warning\" });\n } else {\n post(\"/reset_password\", {\n onError: (e) => {\n alert(e);\n },\n });\n }\n };\n\n return (\n
\n
\n router.visit(\"/login\")} />\n
\n
\n
\n \n Esqueceu sua senha?\n \n
\n \n Qual é o seu\n \n \n email?\n \n
\n setData(\"email\", e.target.value)}\n placeholder=\"Insira seu Email\"\n type=\"email\"\n supportText=\"Enviaremos um código para o seu e-mail.\"\n required\n />\n \n
\n
\n
\n
\n
\n
\n
\n
\n );\n};\n\nexport default StepOne;\n","import { EyeIcon, EyeSlashIcon } from \"@heroicons/react/24/outline\";\nimport { Link, useForm } from \"@inertiajs/react\";\nimport { Button, Text, TextField } from \"@switchdreams/ui\";\nimport React, { useState } from \"react\";\n\nimport ClickBack from \"@/components/ClickBack\";\n\nconst StepThree = ({ sid, code }) => {\n const [showPassword, setShowPassword] = useState(false);\n const [showConfirmationPassword, setShowConfirmationPassword] = useState(false);\n\n const showPasswordIcon = () => {\n setShowPassword(!showPassword);\n };\n\n const showConfirmationPasswordIcon = () => {\n setShowConfirmationPassword(!showConfirmationPassword);\n };\n\n const { data, setData, patch } = useForm({\n password: \"\",\n passwordConfirmation: \"\",\n sid: sid,\n code: parseInt(code),\n });\n\n const submitStepThreeData = (e) => {\n e.preventDefault();\n\n if (data.password !== data.passwordConfirmation) {\n alert(\"As senhas devem ser idênticas!\");\n return;\n }\n\n patch(\"/reset_password\", {\n onError: (e) => {\n alert(e);\n },\n });\n };\n\n return (\n
\n \n \n \n
\n
\n \n Esqueceu sua senha?\n \n
\n \n Crie uma\n \n \n nova senha\n \n
\n setData(\"password\", e.target.value)}\n required\n className=\"rounded-xl\"\n />\n setData(\"passwordConfirmation\", e.target.value)}\n required\n className=\"rounded-xl\"\n />\n \n
\n
\n
\n
\n
\n
\n
\n
\n );\n};\n\nexport default StepThree;\n","import { Link, router } from \"@inertiajs/react\";\nimport { Button, Text } from \"@switchdreams/ui\";\nimport React, { useRef } from \"react\";\n\nimport ClickBack from \"@/components/ClickBack\";\n\nconst StepTwo = ({ sid }) => {\n const inputs = useRef([]);\n\n const handleInput = (index, event) => {\n const inputElement = event.target;\n const value = inputElement.value;\n\n if (value.length === 1) {\n inputs.current[index + 1]?.focus();\n }\n };\n\n const handleBackspace = (index, event) => {\n const inputElement = event.target;\n if (event.keyCode === 8 && !inputElement.value) {\n inputs.current[index - 1]?.focus();\n }\n };\n\n const submitStepTwoData = (e) => {\n e.preventDefault();\n\n let code = \"\";\n inputs.current.forEach((input) => {\n code = code + input.value;\n });\n\n router.post(\"/reset_password/check_code\", {\n sid: sid,\n code: parseInt(code),\n });\n };\n\n return (\n
\n \n \n \n
\n
\n \n Esqueceu sua senha?\n \n
\n \n Insira o\n \n \n código\n \n
\n
\n {[...Array(6)].map((_, index) => (\n (inputs.current[index] = el)}\n onInput={(e) => handleInput(index, e)}\n onKeyDown={(e) => {\n if (e.key === \"Backspace\") {\n handleBackspace(index, e);\n }\n }}\n />\n ))}\n
\n \n Digite o código de 6 dígitos enviado para\n \n \n
\n
\n
\n
\n
\n
\n
\n
\n );\n};\n\nexport default StepTwo;\n","import { ArrowLongLeftIcon, EyeIcon, EyeSlashIcon } from \"@heroicons/react/24/outline\";\nimport { Link, useForm } from \"@inertiajs/react\";\nimport { Button, CheckBox, Text, TextField } from \"@switchdreams/ui\";\nimport React, { useState } from \"react\";\n\nimport { useAlert } from \"@/contexts/Alert\";\nimport { imagePath } from \"@/utils\";\n\nconst Login = () => {\n const { showAlert } = useAlert();\n const [showPassword, setShowPassword] = useState(false);\n const { setData, data, post } = useForm({\n email: \"\",\n password: \"\",\n remember: false,\n });\n\n const showPasswordIcon = () => {\n setShowPassword(!showPassword);\n };\n\n const handleLogin = (e) => {\n e.preventDefault();\n if (data.email === \"\" || data.password === \"\") {\n showAlert({ message: \"Preecha todos os campos!\", type: \"warning\" });\n } else {\n post(\"/login\", {\n onError: (error) => {\n showAlert({ message: error });\n },\n onSuccess: () => {\n showAlert({ message: \"Login realizado com sucesso\", type: \"success\" });\n },\n });\n }\n };\n\n return (\n
\n
\n \n \n \n
\n \n Entre na sua conta\n \n Seja bem-vindo de volta!\n
\n
handleLogin(e)}>\n setData(\"email\", e.target.value)}\n />\n setData(\"password\", e.target.value)}\n className=\"rounded-xl\"\n />\n
\n
\n setData(\"remember\", !data.remember)} />\n Mantenha-me conectado\n
\n \n Esqueci minha senha\n \n
\n \n \n Não possui uma conta?\n \n Cadastre-se aqui\n \n \n \n
\n
\n \n \n \n \n \n \n Seja bem-vindo de volta!\n \n
\n
\n );\n};\n\nexport default Login;\n","import { EnvelopeIcon, PhoneIcon } from \"@heroicons/react/24/solid\";\nimport { Link } from \"@inertiajs/react\";\nimport { Text } from \"@switchdreams/ui\";\nimport React from \"react\";\n\nimport { imagePath } from \"../../../utils\";\n\nconst Footer = () => {\n const links = [{ name: \"Vantagens\", href: \"#benefits\" }];\n\n const renderLinks = () => {\n return (\n <>\n \n \n Entre em contato\n \n \n \n \n Política de privacidade\n \n \n \n \n Termos de uso\n \n \n {links.map((link, index) => {\n return (\n \n \n {link.name}\n \n \n );\n })}\n \n );\n };\n\n return (\n
\n
\n \"Logo\n
{renderLinks()}
\n
\n \n \n \n \n \n \n \n \n \n
\n
\n
\n
\n {renderLinks()}\n
\n
\n \n © 2024 viaconsultas. Todos os direitos reservados\n \n
\n \n
\n \n contato@viaconsultas.com.br\n
\n
\n
\n \n © 2024 viaconsultas. Todos os direitos reservados\n \n
\n );\n};\n\nexport default Footer;\n","import {\n ArrowLongRightIcon,\n Bars3Icon,\n ChevronDownIcon,\n ChevronRightIcon,\n InformationCircleIcon,\n} from \"@heroicons/react/24/outline\";\nimport { Link, router, usePage } from \"@inertiajs/react\";\nimport { Avatar, Button, Popover, Text } from \"@switchdreams/ui\";\nimport React, { useState } from \"react\";\n\nimport { useAlert } from \"@/contexts/Alert\";\nimport { imagePath } from \"@/utils\";\n\nconst Navbar = ({ currentUser }) => {\n const { showAlert } = useAlert();\n const { url } = usePage();\n const [open, setOpen] = useState(false);\n\n const Links = currentUser\n ? [\n {\n name: \"Minha agenda\",\n href: \"/consultas\",\n userType: \"doctor\",\n },\n {\n name: \"Rendimento mensal\",\n href: \"/rendimento\",\n userType: \"doctor\",\n },\n {\n name: \"Buscar Profissionais\",\n href: \"/profissionais\",\n userType: \"patient\",\n },\n {\n name: \"Minhas consultas\",\n href: \"/minhas_consultas\",\n userType: \"patient\",\n },\n {\n name: \"Meus Exames\",\n href: \"/exams/budgets\",\n userType: \"patient\",\n },\n {\n name: \"Pedidos Recebidos\",\n href: \"/clinics/exams/budgets\",\n userType: \"manager\",\n },\n {\n name: \"Minha clinica\",\n href: \"/clinica\",\n userType: \"manager\",\n },\n {\n name: \"Meu Perfil\",\n href: \"/profiles\",\n userType: null,\n },\n ]\n : [\n {\n name: \"Quem somos\",\n href: \"#about\",\n userType: null,\n },\n {\n name: url === \"/home_profissionais\" ? \"Sou paciente\" : \"Sou profissional de saúde\",\n href: url === \"/home_profissionais\" ? \"/\" : \"/home_profissionais\",\n userType: null,\n },\n ];\n\n const HeaderLinksDesktop = () => {\n return (\n <>\n
\n {currentUser ? (\n Links.map((link, idx) => {\n if (link.userType === currentUser.role || link.userType === null) {\n return (\n \n \n {link.name}\n \n \n );\n }\n })\n ) : (\n <>\n (window.location.href = \"https://wa.me/61996652148\")}\n >\n Contato\n \n {Links.map((link, idx) => (\n \n \n {link.name}\n \n \n ))}\n \n )}\n
\n
\n
\n {currentUser ? (\n <>\n {/*
\n \n
*/}\n \n \n \n \n }\n >\n
\n \n \n Configurações\n \n \n {\n showAlert({\n message: \"O usuário foi deslogado com sucesso\",\n type: \"success\",\n });\n }}\n >\n Sair\n \n
\n \n \n ) : (\n <>\n \n \n Entrar\n \n \n \n setOpen(false)}\n label=\"Cadastre-se\"\n size=\"lg\"\n className=\"flex rounded-2xl bg-primary-500 px-6 py-2 text-sm font-medium text-white duration-500 hover:bg-primary-600\"\n />\n \n \n )}\n
\n
\n \n );\n };\n\n const HeaderLinksMobile = () => {\n return (\n <>\n
\n {currentUser ? (\n <>\n {Links.map((link, idx) => {\n if (link.userType === currentUser.role || link.userType === null) {\n return (\n setOpen(false)}\n >\n \n {link.name}\n \n \n );\n }\n })}\n setOpen(false)}\n >\n \n Configurações\n \n \n \n ) : (\n <>\n {\n setOpen(false);\n window.location.href = `https://wa.me//61996652148`;\n }}\n >\n Contato\n \n
\n {Links.map((link, idx) => (\n setOpen(false)}\n >\n
\n \n {link.name}\n \n \n
\n \n ))}\n \n )}\n {!currentUser && (\n setOpen(false)}\n >\n
\n Entrar\n \n
\n \n )}\n
\n
\n {currentUser ? (\n {\n showAlert({\n message: \"O usuário foi deslogado com sucesso\",\n type: \"success\",\n });\n }}\n >\n Sair\n \n \n ) : (\n setOpen(false)}>\n setOpen(false)}\n className=\"flex rounded-2xl bg-primary-500 px-6 py-2 text-sm font-medium text-white duration-500 hover:bg-primary-600\"\n />\n \n )}\n
\n \n );\n };\n\n return (\n <>\n
\n {currentUser && !currentUser?.active_plan && (\n
\n
\n \n \n Vimos que você ainda não possui um plano ativo. Conheça nossos planos e desfrute de\n todos os recursos da plataforma.\n \n
\n \n
\n )}\n
\n
\n {url === \"/\" ? (\n <>\n router.visit(\"/\")}\n alt=\"logo\"\n />\n router.visit(\"/\")}\n alt=\"logo\"\n />\n \n ) : (\n router.visit(\"/\")}\n alt=\"logo\"\n />\n )}\n
\n {currentUser ? (\n
\n \n \n \n {\n setOpen(!open);\n }}\n />\n
\n ) : (\n {\n setOpen(!open);\n }}\n />\n )}\n
\n {HeaderLinksDesktop()}\n
\n
\n
\n\n {\n setOpen(!open);\n }}\n />\n \n {HeaderLinksMobile()}\n
\n \n );\n};\n\nexport default Navbar;\n","import { usePage } from \"@inertiajs/react\";\nimport React from \"react\";\n\nimport { AlertProvider } from \"@/contexts/Alert\";\n\nimport Footer from \"./Footer\";\nimport Navbar from \"./Navbar\";\n\nconst DefaultLayout = ({ children }) => {\n const { currentUser } = usePage().props;\n return (\n <>\n \n \n \n {children}\n
\n