From f5f276b8c91ef65c4dbf3119a91977fe76cfb164 Mon Sep 17 00:00:00 2001 From: AldemirLucas Date: Fri, 12 Jan 2024 20:08:23 -0300 Subject: [PATCH 1/6] wip change profile photo --- next/components/molecules/ImgCrop.js | 13 ++ next/package-lock.json | 9 ++ next/package.json | 1 + next/pages/precos.js | 1 - next/pages/user/[username].js | 204 ++++++++++++++++++++++----- next/pages/user/login.js | 4 + 6 files changed, 195 insertions(+), 37 deletions(-) create mode 100644 next/components/molecules/ImgCrop.js diff --git a/next/components/molecules/ImgCrop.js b/next/components/molecules/ImgCrop.js new file mode 100644 index 00000000..6f249617 --- /dev/null +++ b/next/components/molecules/ImgCrop.js @@ -0,0 +1,13 @@ +import { useState } from 'react'; +import ReactCrop from 'react-image-crop'; +import 'react-image-crop/dist/ReactCrop.css'; + +export default function CropImage ({src}) { + const [crop, setCrop] = useState() + + return ( + setCrop(c)}> + + + ) +} diff --git a/next/package-lock.json b/next/package-lock.json index 54f8a603..5edc89d3 100644 --- a/next/package-lock.json +++ b/next/package-lock.json @@ -21,6 +21,7 @@ "next": "^12.3.4", "react": "^17.0.2", "react-dom": "^17.0.2", + "react-image-crop": "^11.0.4", "react-latex-next": "^2.2.0", "react-paginate": "^8.2.0", "react-query": "^3.39.2", @@ -2293,6 +2294,14 @@ "react": "^16.8.0 || ^17.0.0" } }, + "node_modules/react-image-crop": { + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/react-image-crop/-/react-image-crop-11.0.4.tgz", + "integrity": "sha512-FO6N0oJIs+T/kw9wHZ1sjLYURUBv7BOKamjwkiQ0lI4D2Vp5OZFDNhrSJW41K0V9oCsbHtEymbOT/8eF28OOhg==", + "peerDependencies": { + "react": ">=16.13.1" + } + }, "node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", diff --git a/next/package.json b/next/package.json index 3a4f086f..ccad18e9 100644 --- a/next/package.json +++ b/next/package.json @@ -24,6 +24,7 @@ "next": "^12.3.4", "react": "^17.0.2", "react-dom": "^17.0.2", + "react-image-crop": "^11.0.4", "react-latex-next": "^2.2.0", "react-paginate": "^8.2.0", "react-query": "^3.39.2", diff --git a/next/pages/precos.js b/next/pages/precos.js index 84a6a704..590ba9b8 100644 --- a/next/pages/precos.js +++ b/next/pages/precos.js @@ -464,7 +464,6 @@ export default function Price() { ]} button={{ text: `${userData?.proSubscription === "bd_pro" ? "Plano atual" : "Iniciar teste grátis"}`, - onClick: userData?.proSubscription === "bd_pro" ? () => {} : () => setPlan({plan: "BD Pro"}), styles: userData?.proSubscription === "bd_pro" && { color: "#252A32", diff --git a/next/pages/user/[username].js b/next/pages/user/[username].js index a18af85c..b7d245b3 100644 --- a/next/pages/user/[username].js +++ b/next/pages/user/[username].js @@ -3,6 +3,7 @@ import { Box, Text, Divider, + Input, FormControl, FormLabel, FormErrorMessage, @@ -25,7 +26,12 @@ import { GridItem, Skeleton, SkeletonCircle, - SkeletonText + SkeletonText, + Popover, + PopoverTrigger, + PopoverContent, + PopoverBody, + PopoverArrow } from "@chakra-ui/react"; import { useState, useEffect } from "react"; import { useRouter } from "next/router"; @@ -43,6 +49,7 @@ import BodyText from "../../components/atoms/BodyText"; import { CardPrice } from "../precos"; import PaymentSystem from "../../components/organisms/PaymentSystem"; import { getUserDataJson, checkUserInfo, cleanUserInfo } from "../../utils"; +import ImageCrop from "../../components/molecules/ImgCrop"; import { getUser, @@ -201,6 +208,10 @@ const ProfileConfiguration = ({ userInfo }) => { const [isLoading, setIsLoading] = useState(true) const [formData, setFormData] = useState({}) const [errors, setErrors] = useState({}) + const menuAvatar = useDisclosure() + const pictureModal = useDisclosure() + const [picture, setPicture] = useState(null) + const [fileInputKey, setFileInputKey] = useState(Date.now()) useEffect(() => { if(Object.keys(userInfo).length === 0) return null @@ -256,6 +267,30 @@ const ProfileConfiguration = ({ userInfo }) => { setIsLoading(false) } + const handleImageChange = (event) => { + const input = event.target + + if (input.files && input.files[0]) { + const fileType = input.files[0].type + if (fileType === 'image/png' || fileType === 'image/jpeg' || fileType === 'image/jpg') { + const reader = new FileReader() + reader.onload = function (e) { + setPicture(e.target.result) + } + pictureModal.onOpen() + reader.readAsDataURL(input.files[0]) + } else { + setPicture(null) + input.value = "" + } + } + } + + useEffect(() => { + setPicture(null) + setFileInputKey(Date.now()) + }, [pictureModal.isOpen === false]) + return ( { spacing={0} gap={isMobileMod() ? "40px" : "80px"} > + + <> + + + {!!picture && } + + + + pictureModal.onClose()} + > + Cancelar + + + Salvar + + + + @@ -462,43 +537,92 @@ const ProfileConfiguration = ({ userInfo }) => { > - - + { menuAvatar.onOpen() }} + > + + + + + + - - - + + + + Atualizar a foto + + + + Remover foto + + + @@ -673,6 +797,10 @@ instruções enviadas no e-mail para completar a alteração. { Date: Mon, 15 Jan 2024 18:05:42 -0300 Subject: [PATCH 2/6] img crop save img --- next/components/molecules/ImgCrop.js | 163 ++++++++++++++++++++++++++- next/pages/user/[username].js | 40 +------ 2 files changed, 161 insertions(+), 42 deletions(-) diff --git a/next/components/molecules/ImgCrop.js b/next/components/molecules/ImgCrop.js index 6f249617..76f042da 100644 --- a/next/components/molecules/ImgCrop.js +++ b/next/components/molecules/ImgCrop.js @@ -1,13 +1,166 @@ -import { useState } from 'react'; +import { + Stack, + Modal, + ModalOverlay, + ModalContent, + ModalHeader, + ModalBody, + ModalFooter, + ModalCloseButton +} from '@chakra-ui/react'; +import { useState, useEffect, useRef } from 'react'; import ReactCrop from 'react-image-crop'; +import { isMobileMod } from '../../hooks/useCheckMobile.hook'; +import SectionTitle from '../atoms/SectionTitle'; +import RoundedButton from '../atoms/RoundedButton'; import 'react-image-crop/dist/ReactCrop.css'; -export default function CropImage ({src}) { +export default function CropImage ({ + isOpen, + onClose, + src, +}) { + const imgRef = useRef(null) + const blobUrlRef = useRef(null) + const hiddenAnchorRef = useRef(null) + + const [completedCrop, setCompletedCrop] = useState() const [crop, setCrop] = useState() + useEffect(() => { + setCrop() + setCompletedCrop() + }, [!!isOpen]) + + async function onDownloadCropClick() { + const image = imgRef.current + + if (!image || !completedCrop) return null + + const scaleX = image.naturalWidth / image.width; + const scaleY = image.naturalHeight / image.height; + + const offscreen = new OffscreenCanvas( + completedCrop.width * scaleX, + completedCrop.height * scaleY, + ) + + const ctx = offscreen.getContext("2d") + + if (!ctx) { + throw new Error("No 2d context") + } + + ctx.drawImage( + image, + completedCrop.x * scaleX, + completedCrop.y * scaleY, + completedCrop.width * scaleX, + completedCrop.height * scaleY, + 0, + 0, + offscreen.width, + offscreen.height, + ) + + const blob = await offscreen.convertToBlob({ + type: "image/png", + }) + + if (blobUrlRef.current) { + URL.revokeObjectURL(blobUrlRef.current); + } + blobUrlRef.current = URL.createObjectURL(blob) + hiddenAnchorRef.current.href = blobUrlRef.current + hiddenAnchorRef.current.click() + } + return ( - setCrop(c)}> - - + + + + + + Corte sua nova foto de perfil + + + + + + + {!!src && + setCrop(c)} + onComplete={(c) => setCompletedCrop(c)} + aspect={1 / 1} + keepSelection={true} + circularCrop + > + + + } + + + + + + + Cancelar + + onDownloadCropClick()} + > + Salvar + + + Hidden download + + + + + ) } diff --git a/next/pages/user/[username].js b/next/pages/user/[username].js index b7d245b3..520f9a40 100644 --- a/next/pages/user/[username].js +++ b/next/pages/user/[username].js @@ -298,45 +298,11 @@ const ProfileConfiguration = ({ userInfo }) => { spacing={0} gap={isMobileMod() ? "40px" : "80px"} > - - <> - - - {!!picture && } - - - - pictureModal.onClose()} - > - Cancelar - - - Salvar - - - + src={picture} + /> From 73e5543896489ec50dcf9f33deecaf2cb3a8d0d4 Mon Sep 17 00:00:00 2001 From: AldemirLucas Date: Mon, 15 Jan 2024 19:29:05 -0300 Subject: [PATCH 3/6] update of picture --- next/components/molecules/ImgCrop.js | 42 +++++++++--------- next/pages/api/user/index.js | 2 + next/pages/api/user/updatePictureProfile.js | 49 +++++++++++++++++++++ next/pages/user/[username].js | 2 + 4 files changed, 75 insertions(+), 20 deletions(-) create mode 100644 next/pages/api/user/updatePictureProfile.js diff --git a/next/components/molecules/ImgCrop.js b/next/components/molecules/ImgCrop.js index 76f042da..60207281 100644 --- a/next/components/molecules/ImgCrop.js +++ b/next/components/molecules/ImgCrop.js @@ -11,6 +11,11 @@ import { import { useState, useEffect, useRef } from 'react'; import ReactCrop from 'react-image-crop'; import { isMobileMod } from '../../hooks/useCheckMobile.hook'; + +import { + updatePictureProfile +} from '../../pages/api/user' + import SectionTitle from '../atoms/SectionTitle'; import RoundedButton from '../atoms/RoundedButton'; import 'react-image-crop/dist/ReactCrop.css'; @@ -19,11 +24,10 @@ export default function CropImage ({ isOpen, onClose, src, + id, + username }) { const imgRef = useRef(null) - const blobUrlRef = useRef(null) - const hiddenAnchorRef = useRef(null) - const [completedCrop, setCompletedCrop] = useState() const [crop, setCrop] = useState() @@ -32,7 +36,7 @@ export default function CropImage ({ setCompletedCrop() }, [!!isOpen]) - async function onDownloadCropClick() { + async function handlerUpdatePicture() { const image = imgRef.current if (!image || !completedCrop) return null @@ -63,16 +67,21 @@ export default function CropImage ({ offscreen.height, ) - const blob = await offscreen.convertToBlob({ - type: "image/png", + const picture = await new Promise((resolve) => { + offscreen.convertToBlob({ + type: "image/png", + }).then((pic) => { + resolve(pic) + }) }) - if (blobUrlRef.current) { - URL.revokeObjectURL(blobUrlRef.current); - } - blobUrlRef.current = URL.createObjectURL(blob) - hiddenAnchorRef.current.href = blobUrlRef.current - hiddenAnchorRef.current.click() + const filePic = new File([picture], `${username}.png`, {type: "image/png"}) + + const reg = new RegExp("(?<=:).*") + const [ uid ] = reg.exec(id) + + const res = await updatePictureProfile(uid, filePic) + if(res?.status === 200) window.location.reload() } return ( @@ -147,17 +156,10 @@ export default function CropImage ({ marginTop="16px" borderRadius="30px" _hover={{transform: "none", opacity: 0.8}} - onClick={() => onDownloadCropClick()} + onClick={() => handlerUpdatePicture()} > Salvar - - Hidden download - diff --git a/next/pages/api/user/index.js b/next/pages/api/user/index.js index f14bee9c..b329f8cb 100644 --- a/next/pages/api/user/index.js +++ b/next/pages/api/user/index.js @@ -11,6 +11,7 @@ import updateUser from "./updateUser"; import updatePassword from "./updatePassword"; import activeAccount from "./activeAccount"; import deleteAccount from "./deleteAccount"; +import updatePictureProfile from "./updatePictureProfile" export { getToken, @@ -26,4 +27,5 @@ export { updatePassword, activeAccount, deleteAccount, + updatePictureProfile } diff --git a/next/pages/api/user/updatePictureProfile.js b/next/pages/api/user/updatePictureProfile.js new file mode 100644 index 00000000..5bde2041 --- /dev/null +++ b/next/pages/api/user/updatePictureProfile.js @@ -0,0 +1,49 @@ +import axios from "axios"; +import cookies from "js-cookie"; + +const API_URL= `${process.env.NEXT_PUBLIC_API_URL}/api/v1/graphql` + +export default async function updatePictureProfile( + id, + file, +) { + let token = cookies.get("token") || "" + + const formData = new FormData() + + formData.append('operations', JSON.stringify({ + query: ` + mutation ($file: Upload!) { + CreateUpdateAccount(input: {id: ${id} , picture: $file}) { + account { + email + } + } + } + `, + variables: { + file: null, + }, + })) + formData.append('map', JSON.stringify({ + '0': ['variables.file'], + })) + formData.append('0', file); + + try { + const res = await axios({ + url: API_URL, + method: "POST", + headers: { + Authorization: `Bearer ${token}`, + 'Content-Type': 'multipart/form-data' + }, + data: formData + }) + const data = res + return data + } catch (error) { + console.error(error) + return error + } +} diff --git a/next/pages/user/[username].js b/next/pages/user/[username].js index 520f9a40..a6476fbd 100644 --- a/next/pages/user/[username].js +++ b/next/pages/user/[username].js @@ -302,6 +302,8 @@ const ProfileConfiguration = ({ userInfo }) => { isOpen={pictureModal.isOpen} onClose={pictureModal.onClose} src={picture} + id={userInfo.id} + username={userInfo.username} /> From 3ea17e08e15b4d420d6106203d0b8a30474f1d47 Mon Sep 17 00:00:00 2001 From: AldemirLucas Date: Fri, 19 Jan 2024 01:08:53 -0300 Subject: [PATCH 4/6] crop img and updatePicture completed and functional --- next/components/molecules/ImgCrop.js | 44 ++++++++++++++++++--- next/pages/api/user/deleteAccount.js | 2 +- next/pages/api/user/deletePictureProfile.js | 30 ++++++++++++++ next/pages/api/user/index.js | 6 ++- next/pages/api/user/updatePictureProfile.js | 1 - next/pages/user/[username].js | 22 ++++++++++- next/styles/imgCrop.module.css | 3 ++ 7 files changed, 96 insertions(+), 12 deletions(-) create mode 100644 next/pages/api/user/deletePictureProfile.js create mode 100644 next/styles/imgCrop.module.css diff --git a/next/components/molecules/ImgCrop.js b/next/components/molecules/ImgCrop.js index 60207281..52cb7c27 100644 --- a/next/components/molecules/ImgCrop.js +++ b/next/components/molecules/ImgCrop.js @@ -10,22 +10,26 @@ import { } from '@chakra-ui/react'; import { useState, useEffect, useRef } from 'react'; import ReactCrop from 'react-image-crop'; +import cookies from 'js-cookie'; import { isMobileMod } from '../../hooks/useCheckMobile.hook'; import { + getUser, updatePictureProfile } from '../../pages/api/user' import SectionTitle from '../atoms/SectionTitle'; import RoundedButton from '../atoms/RoundedButton'; import 'react-image-crop/dist/ReactCrop.css'; +import styles from "../../styles/imgCrop.module.css"; export default function CropImage ({ isOpen, onClose, src, id, - username + username, + email }) { const imgRef = useRef(null) const [completedCrop, setCompletedCrop] = useState() @@ -67,21 +71,47 @@ export default function CropImage ({ offscreen.height, ) + const maxSizeKB = 1000 + let quality = 1.0 + const maxIterations = 10 + + for (let i = 0; i < maxIterations; i++) { + const tempCanvas = document.createElement('canvas') + tempCanvas.width = offscreen.width + tempCanvas.height = offscreen.height + const tempCtx = tempCanvas.getContext('2d') + tempCtx.drawImage(offscreen, 0, 0) + + const compressedDataUrl = tempCanvas.toDataURL("image/jpeg", quality) + const sizeKB = compressedDataUrl.length / 1024 + + if (sizeKB <= maxSizeKB) { + break; + } + + quality -= 0.1 + } + const picture = await new Promise((resolve) => { offscreen.convertToBlob({ - type: "image/png", + type: "image/jpeg", + quality }).then((pic) => { resolve(pic) }) }) - const filePic = new File([picture], `${username}.png`, {type: "image/png"}) + const filePic = new File([picture], `${username}.jpeg`, {type: "image/jpeg"}) const reg = new RegExp("(?<=:).*") const [ uid ] = reg.exec(id) const res = await updatePictureProfile(uid, filePic) - if(res?.status === 200) window.location.reload() + if(res?.status === 200) { + const userData = await getUser(email) + cookies.set('userBD', JSON.stringify(userData)) + window.location.reload() + } } return ( @@ -105,6 +135,7 @@ export default function CropImage ({ lineHeight="40px" >Corte sua nova foto de perfil @@ -144,8 +176,8 @@ export default function CropImage ({ { } } + async function hanlderRemovePicture() { + const reg = new RegExp("(?<=:).*") + const [ id ] = reg.exec(userInfo.id) + + const res = await deletePictureProfile(id) + + if(res?.ok === true) { + const userData = await getUser(userInfo.email) + cookies.set('userBD', JSON.stringify(userData)) + window.location.reload() + } + } + useEffect(() => { setPicture(null) setFileInputKey(Date.now()) @@ -304,6 +319,7 @@ const ProfileConfiguration = ({ userInfo }) => { src={picture} id={userInfo.id} username={userInfo.username} + email={userInfo.email} /> @@ -580,6 +596,7 @@ const ProfileConfiguration = ({ userInfo }) => { { fontWeight="400" color="#252A32" _hover={{ color: "#42B0FF" }} + onClick={() => hanlderRemovePicture()} >Remover foto @@ -648,7 +666,7 @@ const Account = ({ userInfo }) => { const result = await deleteAccount(id) - if(result?.errors?.length === 0) { + if(result?.ok === true) { cookies.remove('userBD', { path: '/' }) cookies.remove('token', { path: '/' }) return window.open("/", "_self") diff --git a/next/styles/imgCrop.module.css b/next/styles/imgCrop.module.css new file mode 100644 index 00000000..1cdb226c --- /dev/null +++ b/next/styles/imgCrop.module.css @@ -0,0 +1,3 @@ +.containerImageCroped :global(.ReactCrop__child-wrapper img) { + min-width: 100%; +} \ No newline at end of file From badb2232bb712107a36417c74b539d9405cb72a9 Mon Sep 17 00:00:00 2001 From: AldemirLucas Date: Fri, 19 Jan 2024 03:28:11 -0300 Subject: [PATCH 5/6] wip page for privacy policy and terms of service --- next/components/molecules/Footer.js | 3 + next/components/molecules/Menu.js | 1 + next/content/privacyPolicy.js | 108 +++++++++++ .../{serviceTermsBDPro.js => serviceTerms.js} | 2 +- next/pages/perguntas-frequentes.js | 1 - next/pages/precos.js | 28 +-- next/pages/termos_e_politicas.js | 167 ++++++++++++++++++ next/pages/user/password-recovery.js | 1 - 8 files changed, 285 insertions(+), 26 deletions(-) create mode 100644 next/content/privacyPolicy.js rename next/content/{serviceTermsBDPro.js => serviceTerms.js} (99%) create mode 100644 next/pages/termos_e_politicas.js diff --git a/next/components/molecules/Footer.js b/next/components/molecules/Footer.js index b134d480..f3cd62db 100644 --- a/next/components/molecules/Footer.js +++ b/next/components/molecules/Footer.js @@ -176,6 +176,9 @@ export default function Footer({ pages, ocult = false }) { Perguntas frequentes + + Termos e Políticas + Apoie o projeto diff --git a/next/components/molecules/Menu.js b/next/components/molecules/Menu.js index a69afaa9..b5c8a8df 100644 --- a/next/components/molecules/Menu.js +++ b/next/components/molecules/Menu.js @@ -834,6 +834,7 @@ export default function MenuNav({ simpleTemplate = false, userTemplate = false } {name: "Newsletter", href: "https://info.basedosdados.org/newsletter"}, {name: "Carreiras", href: "https://info.basedosdados.org/carreiras"}, {name: "Perguntas frequentes", href: "/perguntas-frequentes"}, + {name: "Termos e Políticas", href: "/termos_e_politicas"}, ], Contato: "/contato", Button: [] diff --git a/next/content/privacyPolicy.js b/next/content/privacyPolicy.js new file mode 100644 index 00000000..9eb3925d --- /dev/null +++ b/next/content/privacyPolicy.js @@ -0,0 +1,108 @@ + +import { + VStack, + Box +} from "@chakra-ui/react"; +import BodyText from "../components/atoms/BodyText"; +import SectionText from "../components/atoms/SectionText"; + +export default function PrivacyPolicy() { + + return ( + + Bem-vindo à Base dos Dados ("Nós", "Nosso" ou "Nossos"). Comprometemo-nos a proteger e respeitar sua privacidade e cumprir todas as obrigações estabelecidas na Lei Geral de Proteção de Dados ("LGPD"). + Esta Política de Privacidade descreve como coletamos, usamos, compartilhamos e protegemos suas informações pessoais. Ao acessar ou usar nossos serviços, você concorda com os termos e práticas descritos nesta Política de Privacidade. + + + 1. Informações que Coletamos + + 1.1. Coletamos informações pessoais que você nos fornece diretamente ao usar nossos serviços. Isso pode incluir seu nome, endereço de e-mail, informações de pagamento e outras informações que você escolher compartilhar conosco. + 1.2. Também coletamos informações de forma automática, incluindo dados de uso, endereço IP, tipo de navegador, e informações sobre o dispositivo que você usa para acessar nossos serviços. + + + + + 2. Uso das Informações + + 2.1. Utilizamos suas informações pessoais para fornecer e melhorar nossos serviços, incluindo o processamento de pagamentos, o fornecimento de suporte ao cliente e a personalização da experiência do usuário. + 2.2. Não venderemos, alugaremos ou compartilharemos suas informações pessoais com terceiros não afiliados sem o seu consentimento explícito. + + + + + 3. Cookies e Tecnologias Semelhantes + 3.1. Utilizamos cookies e outras tecnologias semelhantes para coletar informações de uso e facilitar sua experiência de navegação em nossos serviços. Você pode gerenciar suas preferências de cookies nas configurações do seu navegador. + + + + 4. Segurança das Informações + 4.1. Implementamos medidas de segurança técnicas e organizacionais para proteger suas informações pessoais contra acesso não autorizado e uso indevido. + + + + 5. Seus Direitos + 5.1. De acordo com a LGPD, você tem direito de acessar, retificar, excluir ou portar seus dados pessoais. Se você deseja exercer esses direitos ou tiver alguma dúvida sobre como suas informações estão sendo tratadas, entre em contato conosco através do endereço de e-mail contato@basedosdados.org. + + + + 6. Alterações nesta Política de Privacidade + 6.1. Reservamo-nos o direito de atualizar esta Política de Privacidade periodicamente. As alterações serão publicadas em nosso site, e a data da última atualização será revisada. Recomendamos que você revise esta Política regularmente para se manter informado sobre nossas práticas de privacidade. + + + + 7. Contato + 7.1. Para quaisquer perguntas ou preocupações relacionadas à nossa Política de Privacidade, entre em contato conosco através do endereço de e-mail contato@basedosdados.org. + + + Esta Política de Privacidade foi elaborada de acordo com as disposições da LGPD e visa garantir que suas informações pessoais sejam tratadas com o devido respeito e cuidado. + + ) +} \ No newline at end of file diff --git a/next/content/serviceTermsBDPro.js b/next/content/serviceTerms.js similarity index 99% rename from next/content/serviceTermsBDPro.js rename to next/content/serviceTerms.js index 11650d70..8f133f8f 100644 --- a/next/content/serviceTermsBDPro.js +++ b/next/content/serviceTerms.js @@ -6,7 +6,7 @@ import { import BodyText from "../components/atoms/BodyText"; import SectionText from "../components/atoms/SectionText"; -export default function ServiceTermsBDPro() { +export default function ServiceTerms() { return ( { - function handlerClick(elm) { if(elm === categorySelected) { setCategorySelected("") diff --git a/next/pages/precos.js b/next/pages/precos.js index 590ba9b8..b9d8690e 100644 --- a/next/pages/precos.js +++ b/next/pages/precos.js @@ -21,7 +21,7 @@ import BodyText from "../components/atoms/BodyText"; import RoundedButton from "../components/atoms/RoundedButton"; import { MainPageTemplate } from "../components/templates/main"; import { isMobileMod } from "../hooks/useCheckMobile.hook"; -import ServiceTermsBDPro from "../content/serviceTermsBDPro"; +import ServiceTerms from "../content/serviceTerms"; import { getUserDataJson } from "../utils" import CheckIcon from "../public/img/icons/checkIcon"; @@ -78,7 +78,7 @@ export const CardPrice = ({ Termos de serviço - + @@ -147,7 +147,6 @@ export const CardPrice = ({ flexDirection="row" height="50px" alignItems="center" - // marginBottom="24px" marginBottom="40px" > /mês - {/* inclui {nubmerOfPerson} pessoa{nubmerOfPerson >= 2 && "s"} */} - + {personConfig.text && <> @@ -463,16 +453,8 @@ export default function Price() { {name: "Dezenas de bases de alta frequência atualizadas"}, ]} button={{ - text: `${userData?.proSubscription === "bd_pro" ? "Plano atual" : "Iniciar teste grátis"}`, - styles: - userData?.proSubscription === "bd_pro" && { - color: "#252A32", - backgroundColor: "#FFF", - boxShadow: "none", - cursor: "default", - _hover: {transform: "none"}, - fontWeight: "400" - } + text: `Iniciar teste grátis`, + href: "https://buy.stripe.com/8wM01TeVQ3kg0mIeV4?locale=pt" }} hasServiceTerms /> diff --git a/next/pages/termos_e_politicas.js b/next/pages/termos_e_politicas.js new file mode 100644 index 00000000..4f5c8b91 --- /dev/null +++ b/next/pages/termos_e_politicas.js @@ -0,0 +1,167 @@ +import { + Box, + VStack, + Stack, + Text, +} from "@chakra-ui/react"; +import Head from "next/head"; +import { useState } from "react"; +import { isMobileMod, useCheckMobile } from "../hooks/useCheckMobile.hook"; +import Display from "../components/atoms/Display"; +import { MainPageTemplate } from "../components/templates/main"; +import ServiceTerms from "../content/serviceTerms"; +import PrivacyPolicy from "../content/privacyPolicy"; + +export default function TermsAndPolitics() { + const [sectionSelected, setSectionSelected] = useState("") + + const SectionText = ({ section }) => { + function handlerClick(elm) { + if(elm === sectionSelected) { + setSectionSelected("") + window.scrollTo({top: 1}) + } else { + setSectionSelected(elm) + const targetElement = document.getElementById(elm) + + if (targetElement) { + if(targetElement.id === "Termos de serviço") { + window.scrollTo({ + top: useCheckMobile() ? 210 : 80, + behavior: 'smooth', + }) + } else { + window.scrollTo({ + top: targetElement.offsetTop+120, + behavior: 'smooth', + }) + } + } + } + } + + return ( + handlerClick(section)} + > + {section} + + ) + } + + return ( + + + Termos e Políticas – Base dos Dados + + {/* */} + + + + + Termos e Políticas + + + + + + + + + + + + Termos de serviço + + + + + Políticas de privacidade + + + + + Cookies + + + + + + + + ) +} \ No newline at end of file diff --git a/next/pages/user/password-recovery.js b/next/pages/user/password-recovery.js index 97b9d466..b8096cec 100644 --- a/next/pages/user/password-recovery.js +++ b/next/pages/user/password-recovery.js @@ -133,7 +133,6 @@ export default function PasswordRecovery({ confirmed, uid, confirmToken }) { } if(Object.keys(regexPassword).length > 0) validationErrors.regexPassword = regexPassword - console.log(validationErrors) if(formData.password === "") { validationErrors.password = "Por favor, insira a senha." From cff5aefc2c544df525cd213a3b2c72f52f74c85a Mon Sep 17 00:00:00 2001 From: AldemirLucas Date: Fri, 19 Jan 2024 17:19:09 -0300 Subject: [PATCH 6/6] wip cookies modal --- next/components/molecules/Cookies.js | 83 +++++++++++++++++++ next/components/molecules/Footer.js | 4 +- next/components/molecules/Menu.js | 1 - next/components/templates/main.js | 2 + next/pages/contato.js | 2 +- next/pages/estudos-de-caso/[id].js | 1 + next/pages/estudos-de-caso/index.js | 2 +- next/pages/perguntas-frequentes.js | 2 +- next/pages/quem-somos.js | 2 +- ...e_politicas.js => termos-e-privacidade.js} | 64 +++++++++++--- next/pages/user/[username].js | 21 ++--- next/pages/user/activate-account.js | 58 +++++++++---- next/pages/user/login.js | 16 +++- next/pages/user/register.js | 2 +- 14 files changed, 213 insertions(+), 47 deletions(-) create mode 100644 next/components/molecules/Cookies.js rename next/pages/{termos_e_politicas.js => termos-e-privacidade.js} (51%) diff --git a/next/components/molecules/Cookies.js b/next/components/molecules/Cookies.js new file mode 100644 index 00000000..03f26445 --- /dev/null +++ b/next/components/molecules/Cookies.js @@ -0,0 +1,83 @@ +import { + Box, + Text, + CloseButton, + HStack +} from "@chakra-ui/react"; +import { useState, useEffect } from "react"; +import cookies from "js-cookie"; +import RoundedButton from "../atoms/RoundedButton"; +import Link from "../atoms/Link"; +import { useCheckMobile } from "../../hooks/useCheckMobile.hook"; + +export default function ConfirmCookies() { + const [isOpen, setIsOpen] = useState(false) + + useEffect(() => { + const res = cookies.get("cookieAccepted") + + if(res === undefined) setIsOpen(true) + }, []) + + const handleClose = () => { + setIsOpen(false) + } + + const handleConfirm = () => { + cookies.set("cookieAccepted", "true",{ expires: 366 }) + setIsOpen(false) + } + + if(!isOpen) return null + + return ( + + + Nossos Cookies + + handleClose()} + /> + + + + Os cookies são essenciais para a funcionalidade completa de nossa plataforma. Ao continuar, você concorda com o uso desses cookies para garantir uma experiência de usuário eficaz. Veja mais sobre nossas Política de Cookies + + + + handleConfirm()} + marginLeft="auto" + > + Concordo + + + + ) +} diff --git a/next/components/molecules/Footer.js b/next/components/molecules/Footer.js index f3cd62db..83a5169a 100644 --- a/next/components/molecules/Footer.js +++ b/next/components/molecules/Footer.js @@ -176,8 +176,8 @@ export default function Footer({ pages, ocult = false }) { Perguntas frequentes - - Termos e Políticas + + Termos e Privacidade Apoie o projeto diff --git a/next/components/molecules/Menu.js b/next/components/molecules/Menu.js index b5c8a8df..a69afaa9 100644 --- a/next/components/molecules/Menu.js +++ b/next/components/molecules/Menu.js @@ -834,7 +834,6 @@ export default function MenuNav({ simpleTemplate = false, userTemplate = false } {name: "Newsletter", href: "https://info.basedosdados.org/newsletter"}, {name: "Carreiras", href: "https://info.basedosdados.org/carreiras"}, {name: "Perguntas frequentes", href: "/perguntas-frequentes"}, - {name: "Termos e Políticas", href: "/termos_e_politicas"}, ], Contato: "/contato", Button: [] diff --git a/next/components/templates/main.js b/next/components/templates/main.js index d43099dd..01979f38 100644 --- a/next/components/templates/main.js +++ b/next/components/templates/main.js @@ -5,6 +5,7 @@ import UserContext from "../../context/user"; import SiteHead from "../atoms/SiteHead"; import Footer from "../molecules/Footer"; import Menu from "../molecules/Menu"; +import Cookies from "../molecules/Cookies" export function MainPageTemplate({ pages, @@ -25,6 +26,7 @@ export function MainPageTemplate({ {children}