├── next.config.js ├── .eslintrc.json ├── src ├── services │ ├── api.ts │ ├── queryClient.ts │ ├── integration.ts │ ├── hooks │ │ ├── useAuth.ts │ │ ├── useUsers.ts │ │ └── useRoom.ts │ ├── stripe-js.ts │ ├── stripe.ts │ ├── firebase.ts │ ├── api │ │ ├── subscribe.ts │ │ └── webhooks.ts │ └── mirage │ │ └── index.ts ├── styles │ ├── chatButton.css │ ├── star.css │ └── theme.ts ├── components │ ├── Header │ │ ├── Logo.tsx │ │ ├── SearchBox.tsx │ │ ├── index.tsx │ │ ├── NotificationsNav.tsx │ │ └── Profile.tsx │ ├── Sidebar │ │ ├── NavSection.tsx │ │ ├── NavLink.tsx │ │ ├── SidebarNav.tsx │ │ └── index.tsx │ ├── Pagination │ │ ├── PaginationItem.tsx │ │ └── index.tsx │ ├── ActiveLink.tsx │ ├── Form │ │ ├── Input.tsx │ │ └── TextArea.tsx │ ├── DevItem │ │ └── index.tsx │ ├── Cookie │ │ └── index.tsx │ ├── SubscribeButton │ │ └── index.tsx │ ├── DevForm │ │ └── index.tsx │ ├── Footer │ │ └── index.tsx │ ├── Table │ │ └── index.tsx │ ├── AboutUs │ │ └── index.tsx │ └── Navigator │ │ └── index.tsx ├── contexts │ ├── SidebarDrawerContext.tsx │ └── AuthContext.tsx └── pages │ ├── 404.tsx │ ├── _app.tsx │ ├── _ │ └── _ │ │ └── policy │ │ ├── use-of-cookies.tsx │ │ ├── privacy-policy.tsx │ │ └── terms-of-service.tsx │ ├── _document.tsx │ ├── registration │ └── index.tsx │ ├── avaliar │ └── [id].tsx │ ├── forms.tsx │ ├── dashboard.tsx │ ├── users │ ├── index.tsx │ └── create.tsx │ ├── list.tsx │ ├── login.tsx │ └── index.tsx ├── next-env.d.ts ├── .gitignore ├── tsconfig.json ├── README.md └── package.json /next.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | reactStrictMode: true, 3 | ignoreDuringBuilds: true, 4 | } 5 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "next/core-web-vitals", 3 | "rules": {"react/no-unescaped-entities": 0} 4 | } 5 | -------------------------------------------------------------------------------- /src/services/api.ts: -------------------------------------------------------------------------------- 1 | import axios from 'axios' 2 | 3 | export const api = axios.create({ 4 | baseURL: '/api' 5 | }) -------------------------------------------------------------------------------- /src/services/queryClient.ts: -------------------------------------------------------------------------------- 1 | import { QueryClient } from 'react-query' 2 | 3 | 4 | export const queryClient = new QueryClient() -------------------------------------------------------------------------------- /src/services/integration.ts: -------------------------------------------------------------------------------- 1 | import axios from 'axios' 2 | 3 | export const api = axios.create({ 4 | baseURL: 'https://fif7o4.sse.codesandbox.io' 5 | }) -------------------------------------------------------------------------------- /src/services/hooks/useAuth.ts: -------------------------------------------------------------------------------- 1 | import { useContext } from "react"; 2 | import { AuthContext } from "../../contexts/AuthContext"; 3 | 4 | export function useAuth() { 5 | const value = useContext(AuthContext); 6 | return value; 7 | } -------------------------------------------------------------------------------- /src/services/stripe-js.ts: -------------------------------------------------------------------------------- 1 | import { loadStripe } from '@stripe/stripe-js' 2 | 3 | export async function getStripeJs(){ 4 | const stripeJs = await loadStripe(process.env.NEXT_PUBLIC_STRIPE_PUBLIC_KEY) 5 | 6 | return stripeJs 7 | } -------------------------------------------------------------------------------- /next-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | /// 4 | 5 | // NOTE: This file should not be edited 6 | // see https://nextjs.org/docs/basic-features/typescript for more information. 7 | -------------------------------------------------------------------------------- /src/styles/chatButton.css: -------------------------------------------------------------------------------- 1 | df-messenger { 2 | --df-messenger-bot-message: #D53F8C; 3 | --df-messenger-button-titlebar-color: #D53F8C; 4 | --df-messenger-chat-background-color: #fafafa; 5 | --df-messenger-font-color: white; 6 | --df-messenger-send-icon: #D53F8C; 7 | --df-messenger-user-message: #1F2029; 8 | } -------------------------------------------------------------------------------- /src/styles/star.css: -------------------------------------------------------------------------------- 1 | .estrelas input[type=radio] { 2 | display: none; 3 | } 4 | .estrelas label i.fa:before { 5 | content:'\f005'; 6 | color: #FC0; 7 | margin: 0 0.5rem; 8 | cursor: pointer; 9 | } 10 | .estrelas input[type=radio]:checked ~ label i.fa:before { 11 | color: #CCC; 12 | } -------------------------------------------------------------------------------- /src/services/stripe.ts: -------------------------------------------------------------------------------- 1 | import Stripe from 'stripe' 2 | // import { version } from '../../package.json' 3 | 4 | export const stripe = new Stripe( 5 | process.env.STRIPE_API_KEY, 6 | { 7 | apiVersion: '2020-08-27', 8 | appInfo: { 9 | name: 'SW', 10 | version: "0.1.0" 11 | } 12 | } 13 | ) -------------------------------------------------------------------------------- /src/components/Header/Logo.tsx: -------------------------------------------------------------------------------- 1 | import { Text } from '@chakra-ui/react' 2 | 3 | export function Logo() { 4 | return ( 5 | 6 | Safe Woman 7 | . 8 | 9 | ) 10 | } -------------------------------------------------------------------------------- /src/components/Sidebar/NavSection.tsx: -------------------------------------------------------------------------------- 1 | import { Box, Stack, Text } from "@chakra-ui/react"; 2 | import { ReactNode } from "react"; 3 | 4 | interface NavSectionProps{ 5 | title: string; 6 | children: ReactNode; 7 | } 8 | 9 | export function NavSection({title, children}: NavSectionProps){ 10 | return( 11 | 12 | {title} 13 | 14 | {children} 15 | 16 | 17 | ) 18 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # next.js 12 | /.next/ 13 | /out/ 14 | 15 | # production 16 | /build 17 | 18 | # misc 19 | .DS_Store 20 | *.pem 21 | 22 | # debug 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | 27 | # local env files 28 | .env.local 29 | .env.development.local 30 | .env.test.local 31 | .env.production.local 32 | 33 | # vercel 34 | .vercel 35 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "dom", 6 | "dom.iterable", 7 | "esnext" 8 | ], 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "strict": false, 12 | "forceConsistentCasingInFileNames": true, 13 | "noEmit": true, 14 | "esModuleInterop": true, 15 | "module": "esnext", 16 | "moduleResolution": "node", 17 | "resolveJsonModule": true, 18 | "isolatedModules": true, 19 | "jsx": "preserve" 20 | }, 21 | "include": [ 22 | "next-env.d.ts", 23 | "**/*.ts", 24 | "**/*.tsx" 25 | ], 26 | "exclude": [ 27 | "node_modules" 28 | ] 29 | } 30 | -------------------------------------------------------------------------------- /src/styles/theme.ts: -------------------------------------------------------------------------------- 1 | import { extendTheme } from '@chakra-ui/react' 2 | 3 | export const theme = extendTheme({ 4 | colors:{ 5 | gray: { 6 | "900": "#181B23", 7 | "800": "#1F2029", 8 | "700": "#353646", 9 | "600": "#4B4D63", 10 | "500": "#616480", 11 | "400": "#797D9A", 12 | "300": "#9699B0", 13 | "200": "#B3B5C6", 14 | "100": "#D1D2DC", 15 | "50": "#EEEEF2", 16 | } 17 | }, 18 | fonts: { 19 | heading: 'Roboto', 20 | body: 'Roboto', 21 | }, 22 | styles: { 23 | global: { 24 | body: { 25 | bg: 'gray.900', 26 | color: 'gray.50' 27 | } 28 | } 29 | } 30 | }) -------------------------------------------------------------------------------- /src/components/Sidebar/NavLink.tsx: -------------------------------------------------------------------------------- 1 | import { Text, Link as ChakraLink, Icon, LinkProps as ChakraLinkProps } from "@chakra-ui/react"; 2 | import { ElementType } from 'react' 3 | import { ActiveLink } from "../ActiveLink"; 4 | 5 | interface NavLinkProps extends ChakraLinkProps{ 6 | icon: ElementType; 7 | children: string; 8 | href: string; 9 | } 10 | 11 | export function NavLink({icon, children, href, ...rest}:NavLinkProps){ 12 | return( 13 | 14 | 15 | 16 | {children} 17 | 18 | 19 | ) 20 | } -------------------------------------------------------------------------------- /src/services/firebase.ts: -------------------------------------------------------------------------------- 1 | import { initializeApp } from "firebase/app"; 2 | import { getDatabase } from "firebase/database"; 3 | import { getAuth } from "firebase/auth"; 4 | 5 | const firebaseConfig = { 6 | apiKey: "AIzaSyBl_xXu8vkF_z_Qs1pTYCAcOYUE2z_RO88", 7 | authDomain: "safewoman22.firebaseapp.com", 8 | databaseURL: "https://safewoman22-default-rtdb.firebaseio.com", 9 | projectId: "safewoman22", 10 | storageBucket: "safewoman22.appspot.com", 11 | messagingSenderId: "880829612224", 12 | appId: "1:880829612224:web:731b048d16e8c787da6d25", 13 | measurementId: "G-R9NTPGP9KC" 14 | }; 15 | 16 | const app = initializeApp(firebaseConfig); 17 | const database = getDatabase(app); 18 | const auth = getAuth(app) 19 | 20 | 21 | export { database, auth }; -------------------------------------------------------------------------------- /src/components/Pagination/PaginationItem.tsx: -------------------------------------------------------------------------------- 1 | import { Button } from '@chakra-ui/button' 2 | 3 | interface PaginationItemProps{ 4 | number: number; 5 | isCurrent?: boolean; 6 | onPageChange: (page: number) => void; 7 | } 8 | 9 | export function PaginationItem({isCurrent = false, onPageChange, number}:PaginationItemProps) { 10 | if(isCurrent) { 11 | return( 12 | 16 | ) 17 | } 18 | return( 19 | 24 | ) 25 | } -------------------------------------------------------------------------------- /src/components/Header/SearchBox.tsx: -------------------------------------------------------------------------------- 1 | import { Flex, Input, Icon } from '@chakra-ui/react' 2 | import { useRef } from 'react' 3 | import { RiSearchLine } from 'react-icons/ri' 4 | import { api } from '../../services/integration' 5 | 6 | export function SearchBox() { 7 | const searchInputRef = useRef(null) 8 | // console.log(searchInputRef.current?.focus()) 9 | return ( 10 | 11 | 14 | 15 | 16 | ) 17 | } -------------------------------------------------------------------------------- /src/components/ActiveLink.tsx: -------------------------------------------------------------------------------- 1 | import Link, { LinkProps } from 'next/link' 2 | import { useRouter } from 'next/router' 3 | import { cloneElement, ReactElement } from 'react' 4 | 5 | interface ActiveLinkProps extends LinkProps{ 6 | children: ReactElement; 7 | shoulMatchExactHref?: boolean; 8 | } 9 | 10 | export function ActiveLink({children, shoulMatchExactHref = false, ...rest}:ActiveLinkProps){ 11 | const { asPath } = useRouter() 12 | let isActive = false 13 | 14 | if(shoulMatchExactHref && (asPath === rest.href || asPath === rest.as)){ 15 | isActive = true 16 | } 17 | 18 | if(!shoulMatchExactHref && (asPath.startsWith(String(rest.href)) || asPath.startsWith(String(rest.as)))){ 19 | isActive = true 20 | } 21 | 22 | return( 23 | 24 | {cloneElement(children, { 25 | color: isActive ? 'pink.400' : 'gray.50' 26 | })} 27 | 28 | ) 29 | } -------------------------------------------------------------------------------- /src/contexts/SidebarDrawerContext.tsx: -------------------------------------------------------------------------------- 1 | import { useDisclosure, UseDisclosureReturn } from "@chakra-ui/react"; 2 | import { useRouter } from "next/router"; 3 | import { createContext, ReactNode, useContext, useEffect } from "react"; 4 | 5 | interface SidebarDrawerProviderProps{ 6 | children: ReactNode; 7 | } 8 | 9 | type SidebarDrawerContextData = UseDisclosureReturn 10 | 11 | const SidebarDrawerContext = createContext({} as SidebarDrawerContextData) 12 | 13 | export function SidebarDrawerProvider({children}: SidebarDrawerProviderProps){ 14 | const disclosure = useDisclosure() 15 | const router = useRouter() 16 | 17 | useEffect(()=>{ 18 | disclosure.onClose() 19 | }, [router.asPath]) 20 | 21 | return( 22 | 23 | {children} 24 | 25 | ) 26 | } 27 | 28 | export const useSidebarDrawer = () => useContext(SidebarDrawerContext) -------------------------------------------------------------------------------- /src/components/Sidebar/SidebarNav.tsx: -------------------------------------------------------------------------------- 1 | import { Stack } from "@chakra-ui/react"; 2 | import { RiSmartphoneLine, RiInputMethodLine, RiListCheck2, RiContactsLine, RiDashboardLine } from "react-icons/ri"; 3 | import { NavSection } from "./NavSection"; 4 | import { NavLink } from "./NavLink"; 5 | 6 | export function SidebarNav(){ 7 | return( 8 | 9 | 10 | Dashboard 11 | Usuários 12 | 13 | 14 | Aplicativo 15 | Formulários 16 | Relatos 17 | 18 | 19 | ) 20 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Safe Woman 2 |

3 | Logo 4 |

5 | 6 | Quem somos? 7 | 8 | A Safe Woman é uma startup de segurança brasileira focada em entregar o melhor valor a seus clientes. Nós começamos a operar em Abril de 2022 com os melhores profissionais do país. Nossa especialidade é no desenvolvimento e aprimoração da segurança feminina utilizando as melhores tecnologias. 9 | 10 | A Safe Woman segue uma filosofia simples de Oss: dedicar seu talento e tecnologia à criação de produtos e serviços superiores que contribuam para uma sociedade global melhor. 11 | 12 | ## Acesso: 13 | 14 | Para ter acesso basta acessar nosso [site](https://safe-woman.vercel.app). 15 | 16 | ## Funções: 17 | 18 | - Análise 19 | - Desenvolvimento 20 | - Design 21 | - Gestão 22 | - Teste 23 | - Marketing 24 | - Negócios 25 | - Suporte 26 | -------------------------------------------------------------------------------- /src/components/Form/Input.tsx: -------------------------------------------------------------------------------- 1 | import { Input as ChakraInput, FormLabel, FormControl, InputProps as ChakraInputProps, FormErrorMessage } from '@chakra-ui/react' 2 | import { forwardRef, ForwardRefRenderFunction } from 'react'; 3 | import { FieldError } from 'react-hook-form' 4 | 5 | interface InputProps extends ChakraInputProps{ 6 | name: string; 7 | label?: string; 8 | error?: FieldError; 9 | } 10 | 11 | 12 | 13 | const InputBase: ForwardRefRenderFunction = ({name, label, error = null, ...rest}, ref) => { 14 | return ( 15 | 16 | {!!label && {label}} 17 | 21 | {!!error && ( 22 | 23 | {error.message} 24 | )} 25 | 26 | ); 27 | } 28 | 29 | export const Input = forwardRef(InputBase) -------------------------------------------------------------------------------- /src/services/api/subscribe.ts: -------------------------------------------------------------------------------- 1 | import { NextApiRequest, NextApiResponse } from "next"; 2 | import { stripe } from "../../services/stripe"; 3 | 4 | export default async (req: NextApiRequest, res: NextApiResponse) => { 5 | if(req.method === 'POST'){ 6 | const stripeCustomer = await stripe.customers.create({ 7 | email: "safewoman22@gmail.com" 8 | }) 9 | 10 | const stripeCheckoutSession = await stripe.checkout.sessions.create({ 11 | customer: stripeCustomer.id, 12 | payment_method_types: ['card'], 13 | billing_address_collection: 'required', 14 | line_items: [ 15 | {price: 'price_1KtJK8GnuxSAi5xdYIau8PDR', 16 | quantity: 1}, 17 | ], 18 | mode: 'payment', 19 | allow_promotion_codes: true, 20 | success_url: process.env.STRIPE_SUCCESS_URL, 21 | cancel_url: process.env.STRIPE_CANCEL_URL, 22 | }) 23 | 24 | console.log('oi') 25 | 26 | return res.status(200).json({sessionId: stripeCheckoutSession.id}) 27 | }else{ 28 | res.setHeader('Allow', 'POST') 29 | res.status(405).end('Method not allowed') 30 | } 31 | } -------------------------------------------------------------------------------- /src/components/Form/TextArea.tsx: -------------------------------------------------------------------------------- 1 | import { Textarea as ChakraTextArea, FormLabel, FormControl, TextareaProps as ChakraTextareaProps, FormErrorMessage } from '@chakra-ui/react' 2 | import { forwardRef, ForwardRefRenderFunction } from 'react'; 3 | import { FieldError } from 'react-hook-form' 4 | 5 | interface TextareaProps extends ChakraTextareaProps{ 6 | name: string; 7 | label?: string; 8 | error?: FieldError; 9 | } 10 | 11 | 12 | const TextAreaBase: ForwardRefRenderFunction = ({name, label, error = null, ...rest}, ref) => { 13 | return ( 14 | 15 | {!!label && {label}} 16 | 20 | {!!error && ( 21 | 22 | {error.message} 23 | )} 24 | 25 | ); 26 | } 27 | 28 | export const TextArea = forwardRef(TextAreaBase) -------------------------------------------------------------------------------- /src/pages/404.tsx: -------------------------------------------------------------------------------- 1 | import { 2 | Box, 3 | Flex, 4 | Text, 5 | Heading, 6 | Center, 7 | Divider, 8 | VStack, 9 | HStack, 10 | Button, 11 | Img, 12 | useBreakpointValue, 13 | } from "@chakra-ui/react"; 14 | import Link from "next/link"; 15 | import Head from "next/head"; 16 | import { theme } from "../styles/theme"; 17 | 18 | export default function NotFound() { 19 | const isWideVersion = useBreakpointValue({ 20 | base: false, 21 | md: true 22 | }) 23 | 24 | return ( 25 | 26 | 27 | Safe Woman 28 | 29 | 37 | Página não encontrada! 42 | Safe Woman 43 | 44 | 45 | ); 46 | } 47 | -------------------------------------------------------------------------------- /src/components/Header/index.tsx: -------------------------------------------------------------------------------- 1 | import { Flex, useBreakpointValue, IconButton, Icon } from '@chakra-ui/react' 2 | import { Profile } from './Profile' 3 | import { NotificationsNav } from './NotificationsNav' 4 | import { SearchBox } from './SearchBox' 5 | import { Logo } from './Logo' 6 | import { useSidebarDrawer } from '../../contexts/SidebarDrawerContext' 7 | import { RiMenuLine } from 'react-icons/ri' 8 | 9 | export function Header() { 10 | const { onOpen } = useSidebarDrawer() 11 | 12 | const isWideVersion = useBreakpointValue({ 13 | base: false, 14 | lg: true 15 | }) 16 | 17 | return( 18 | 19 | { !isWideVersion && ( 20 | } fontSize="24" variant="unstyled" onClick={onOpen} aria-label="Open Navigation" mr="2"> 21 | 22 | 23 | ) } 24 | 25 | 26 | {/* { isWideVersion && } */} 27 | {/* */} 28 | 29 | 30 | 31 | ); 32 | } -------------------------------------------------------------------------------- /src/components/DevItem/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { 3 | Box, 4 | Flex, 5 | Text, 6 | Heading, 7 | Center, 8 | Divider, 9 | VStack, 10 | HStack, 11 | Button, 12 | Img, 13 | useBreakpointValue, 14 | List, 15 | ListItem, 16 | ListIcon, 17 | OrderedList, 18 | UnorderedList, 19 | } from "@chakra-ui/react"; 20 | import Link from "next/link"; 21 | 22 | 23 | export default function DevItem({ dev }) { 24 | return ( 25 | 31 | 32 | {dev.github_username} 33 | 34 | {dev.techs.join(', ')} 35 | {dev.name} 36 | 37 | 38 | {dev.bio} 42 | Abrir WhatsApp 45 | 46 | ); 47 | } 48 | -------------------------------------------------------------------------------- /src/pages/_app.tsx: -------------------------------------------------------------------------------- 1 | import { AppProps } from 'next/app' 2 | import { ChakraProvider } from '@chakra-ui/react' 3 | import { Toaster } from "react-hot-toast"; 4 | import { theme } from '../styles/theme' 5 | import { SidebarDrawerProvider } from '../contexts/SidebarDrawerContext' 6 | // import { makeServer } from '../services/mirage' 7 | import { QueryClientProvider } from 'react-query' 8 | import { ReactQueryDevtools } from 'react-query/devtools' 9 | import { queryClient } from '../services/queryClient' 10 | import { AuthContextProvider } from "../contexts/AuthContext"; 11 | import Script from 'next/script' 12 | import '../styles/chatButton.css' 13 | import '../styles/star.css' 14 | 15 | 16 | 17 | // if(process.env.NODE_ENV === 'production'){ 18 | // makeServer() 19 | // } 20 | 21 | function MyApp({ Component, pageProps }: AppProps) { 22 | return ( 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | ) 36 | } 37 | 38 | export default MyApp 39 | -------------------------------------------------------------------------------- /src/components/Sidebar/index.tsx: -------------------------------------------------------------------------------- 1 | import { Box, Drawer, DrawerOverlay, DrawerContent, DrawerCloseButton, DrawerHeader, DrawerBody, useBreakpointValue } from "@chakra-ui/react"; 2 | import { useSidebarDrawer } from "../../contexts/SidebarDrawerContext"; 3 | import { theme } from "../../styles/theme"; 4 | import { SidebarNav } from "./SidebarNav"; 5 | 6 | export function Sidebar() { 7 | const { isOpen, onClose } = useSidebarDrawer() 8 | 9 | const isDrawerSidebar = useBreakpointValue({ 10 | base: true, 11 | lg: false, 12 | }) 13 | 14 | if(isDrawerSidebar) { 15 | return( 16 | 17 | 18 | 19 | 20 | Navegação 21 | 34 | 35 | 36 | 37 | 38 | 39 | ) 40 | } 41 | 42 | return ( 43 | 44 | 45 | 46 | ); 47 | } 48 | -------------------------------------------------------------------------------- /src/services/hooks/useUsers.ts: -------------------------------------------------------------------------------- 1 | import { useQuery, UseQueryOptions } from 'react-query' 2 | import { api } from "../../services/api"; 3 | 4 | type User = { 5 | id: string; 6 | name: string; 7 | email: string; 8 | createdAt: string; 9 | sendAt: string; 10 | local: string; 11 | description: string; 12 | } 13 | 14 | type GetUsersResponse = { 15 | totalCount: number; 16 | users: User[]; 17 | } 18 | 19 | export async function getUsers (page: number): Promise { 20 | const { data, headers } = await api.get('users', { 21 | params: { 22 | page, 23 | } 24 | }) 25 | 26 | const totalCount = Number(headers['x-total-count']) 27 | 28 | const users = data.users.map(user => { 29 | return{ 30 | id: user.id, 31 | name: user.name, 32 | email: user.email, 33 | local: user.local, 34 | description: user.description, 35 | sendAt: new Date(user.created_at).toLocaleDateString('pt-BR', { 36 | day: '2-digit', 37 | month: '2-digit', 38 | year: 'numeric', 39 | }), 40 | createdAt: new Date(user.created_at).toLocaleDateString('pt-BR', { 41 | day: '2-digit', 42 | month: 'long', 43 | year: 'numeric', 44 | }) 45 | } 46 | }); 47 | return {users, totalCount}; 48 | } 49 | 50 | export function useUsers(page: number, options: UseQueryOptions){ 51 | return useQuery(['users', page], () => getUsers(page), { 52 | staleTime: 1000 * 60 * 10, 53 | ...options, 54 | }) 55 | } -------------------------------------------------------------------------------- /src/components/Cookie/index.tsx: -------------------------------------------------------------------------------- 1 | import { 2 | Box, 3 | Flex, 4 | Text, 5 | Heading, 6 | Center, 7 | Divider, 8 | VStack, 9 | HStack, 10 | Button, 11 | Img, 12 | useBreakpointValue, 13 | List, 14 | ListItem, 15 | Input, 16 | ListIcon, 17 | OrderedList, 18 | UnorderedList, 19 | } from "@chakra-ui/react"; 20 | import {theme} from '../../styles/theme' 21 | import nookies from 'nookies' 22 | import { useState } from "react"; 23 | 24 | export function Cookie(){ 25 | const [cookie, setCookie] = useState(false) 26 | 27 | return( 28 | <> 29 | {!cookie && 30 | Aviso 31 | Nós e os terceiros selecionados usamos cookies ou tecnologias similares para finalidades técnicas e, com seu consentimento, para outras finalidades. Negá-los poderá tornar os recursos relacionados indisponíveis. 32 | 33 |

34 | Você poderá livremente conceder, negar ou cancelar sua permissão a qualquer momento. 35 |

36 | Você poderá consentir o uso de tais tecnologias ao usar o botão “Aceitar”.
37 | 38 |
} 39 | 40 | ) 41 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "dashgo", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "next dev", 7 | "build": "next build", 8 | "start": "next start", 9 | "lint": "next lint" 10 | }, 11 | "dependencies": { 12 | "@chakra-ui/core": "^0.8.0", 13 | "@chakra-ui/icons": "^2.0.0", 14 | "@chakra-ui/react": "^1.6.9", 15 | "@emotion/react": "^11.4.1", 16 | "@emotion/styled": "^11.3.0", 17 | "@hookform/resolvers": "^2.8.3", 18 | "@stripe/stripe-js": "^1.29.0", 19 | "animate.css": "^4.1.1", 20 | "apexcharts": "^3.29.0", 21 | "axios": "^0.24.0", 22 | "faunadb": "4.3.0", 23 | "firebase": "^9.6.11", 24 | "framer-motion": "^4.1.17", 25 | "jquery": "^3.6.0", 26 | "next": "11.1.2", 27 | "next-auth": "^4.3.3", 28 | "nookies": "^2.5.2", 29 | "react": "17.0.2", 30 | "react-apexcharts": "^1.3.9", 31 | "react-dom": "17.0.2", 32 | "react-hook-form": "^7.20.5", 33 | "react-hot-toast": "^2.2.0", 34 | "react-icons": "^4.3.1", 35 | "react-modal": "^3.14.4", 36 | "react-query": "^3.34.0", 37 | "react-slick": "^0.29.0", 38 | "slick-carousel": "^1.8.1", 39 | "stripe": "8.165.0", 40 | "sweetalert2": "^11.4.14", 41 | "yup": "^0.32.11" 42 | }, 43 | "devDependencies": { 44 | "@types/faker": "^5.5.9", 45 | "@types/jquery": "^3.5.14", 46 | "@types/node": "^16.10.3", 47 | "@types/react": "^17.0.27", 48 | "eslint": "7.32.0", 49 | "eslint-config-next": "11.1.2", 50 | "faker": "^5.5.3", 51 | "miragejs": "^0.1.43", 52 | "typescript": "^4.4.3" 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/components/Header/NotificationsNav.tsx: -------------------------------------------------------------------------------- 1 | import { Icon, HStack, Link as ChakraLink, LinkProps as ChakraLinkProps} from '@chakra-ui/react' 2 | import { RiLogoutBoxRLine, RiUserAddLine } from 'react-icons/ri' 3 | import { ElementType } from 'react' 4 | import { ActiveLink } from "../ActiveLink"; 5 | import { auth } from '../../services/firebase' 6 | import { signOut } from "firebase/auth"; 7 | import toast, { Toaster } from 'react-hot-toast'; 8 | import { useRouter } from 'next/router'; 9 | 10 | 11 | interface IconLinkProps extends ChakraLinkProps{ 12 | icon: ElementType; 13 | href: string; 14 | } 15 | 16 | export function NotificationsNav({icon, href, ...rest}:IconLinkProps) { 17 | const router = useRouter() 18 | function logOut(){ 19 | signOut(auth).then(() => { 20 | toast.success('Desconectado'); 21 | router.push('/') 22 | // Sign-out successful. 23 | }).catch((error) => { 24 | toast.error('Erro'); 25 | // An error happened. 26 | }); 27 | } 28 | return ( 29 | 30 | {/* */} 31 | 32 | {auth.currentUser?.uid ? : ''} 33 | 34 | {/* */} 35 | 36 | 37 | 38 | 39 | 40 | 41 | ) 42 | } -------------------------------------------------------------------------------- /src/components/SubscribeButton/index.tsx: -------------------------------------------------------------------------------- 1 | // import { signIn, useSession } from 'next-auth/client' 2 | import { useRouter } from 'next/router' 3 | import { api } from '../../services/api' 4 | import { getStripeJs } from '../../services/stripe-js' 5 | import { Box, Flex, Text, Heading, Divider, VStack, HStack, Button, Img } from "@chakra-ui/react"; 6 | // import styles from './styles.module.scss' 7 | 8 | export function SubscribeButton(){ 9 | // const [session] = useSession() 10 | const router = useRouter() 11 | 12 | async function handleSubscribe(){ 13 | // if(!session){ 14 | // signIn('github') 15 | // return 16 | // } 17 | 18 | // if(session.activeSubscription){ 19 | // router.push('/posts') 20 | // return 21 | // } 22 | router.push('https://buy.stripe.com/test_dR6eWq2oX4lJaf68wU') 23 | 24 | // try{ 25 | // const response = await api.post('/subscribe') 26 | 27 | // const { sessionId } = response.data 28 | 29 | // const stripe = await getStripeJs() 30 | 31 | // await stripe.redirectToCheckout({sessionId}) 32 | 33 | // }catch(err){ 34 | // alert(err.message) 35 | // } 36 | 37 | } 38 | 39 | return ( 40 | 61 | ) 62 | } -------------------------------------------------------------------------------- /src/pages/_/_/policy/use-of-cookies.tsx: -------------------------------------------------------------------------------- 1 | import { Box, Text } from '@chakra-ui/react' 2 | import Head from 'next/head' 3 | import { theme } from '../../../../styles/theme' 4 | 5 | export default function useOfCookies(){ 6 | return( 7 | 20 | 21 | Uso de Cookies | SW 22 | 23 | Uso de Cookies 24 | Utilizamos cookies de funcionalidade para nos permitir relembrar as preferências do usuário. Por exemplo, os cookies evitam digitar o nome do utilizador cada vez que este acede ao site. Também usamos cookies de funcionalidade para fornecer serviços avançados ao usuário, como por exemplo efetuar comentários a um artigo. Em resumo, os cookies de funcionalidade guardam as preferências do usuário relativamente à utilização do site, de forma que não seja necessário voltar a configurar o site cada vez que o visita. 25 |

26 |

27 | Alguns cookies são essenciais para acessar a áreas específicas do nosso site. Permitem a navegação no site e a utilização das suas aplicações, tal como acessar áreas seguras do site através de login. Sem estes cookies, os serviços que o exijam não podem ser prestados.
28 |
29 | ) 30 | } -------------------------------------------------------------------------------- /src/pages/_document.tsx: -------------------------------------------------------------------------------- 1 | import Document, { Head, Html, Main, NextScript } from 'next/document'; 2 | 3 | export default class MyDocument extends Document { 4 | render(){ 5 | return( 6 | 7 | 8 | 9 | 10 | 11 | {/* 12 | */} 13 | 14 | {/* */} 15 | 16 | 17 | 18 |
26 | ` }} /> 27 | 28 | 29 |
30 | 31 | 32 | 33 | ); 34 | } 35 | } -------------------------------------------------------------------------------- /src/services/mirage/index.ts: -------------------------------------------------------------------------------- 1 | import { createServer, Factory, Model, Response, ActiveModelSerializer } from 'miragejs' 2 | import faker from 'faker' 3 | 4 | type User = { 5 | name: string; 6 | email: string; 7 | created_at: string; 8 | local: string; 9 | description: string; 10 | } 11 | 12 | export function makeServer(){ 13 | const server = createServer({ 14 | serializers: { 15 | application: ActiveModelSerializer, 16 | }, 17 | models: { 18 | user: Model.extend>({}) 19 | }, 20 | 21 | factories: { 22 | user: Factory.extend({ 23 | name(){ 24 | // return `User ${i + 1 }` 25 | return faker.name.firstName() 26 | }, 27 | email(){ 28 | return faker.internet.email().toLowerCase() 29 | }, 30 | createdAt(){ 31 | return faker.date.recent(100) 32 | }, 33 | local(){ 34 | return faker.address.city() 35 | }, 36 | description(){ 37 | return faker.lorem.text() 38 | } 39 | }) 40 | }, 41 | 42 | seeds(server){ 43 | server.createList('user', 200) 44 | }, 45 | routes(){ 46 | this.namespace = 'api' 47 | this.timing = 750 48 | 49 | this.get('/users', function(schema, request){ 50 | const { page = 1, per_page = 10 } = request.queryParams 51 | const total = schema.all('user').length 52 | const pageStart = (Number(page) - 1) * Number(per_page) 53 | const pageEnd = pageStart + Number(per_page) 54 | const users = this.serialize(schema.all('user')).users.sort((a, b) => a.createdAt - b.createdAt).slice(pageStart, pageEnd) 55 | 56 | return new Response( 57 | 200, 58 | { 'x-total-count': String(total) }, 59 | { users } 60 | ) 61 | }) 62 | this.get('/users/:id') 63 | this.post('/users') 64 | 65 | this.namespace = '' 66 | this.passthrough() 67 | } 68 | }) 69 | return server 70 | } -------------------------------------------------------------------------------- /src/contexts/AuthContext.tsx: -------------------------------------------------------------------------------- 1 | import { createContext , ReactNode, useState, useEffect } from 'react' 2 | import { auth } from '../services/firebase' 3 | import { GoogleAuthProvider, signInWithPopup, onAuthStateChanged } from "firebase/auth"; 4 | 5 | 6 | 7 | type User = { 8 | id: string; 9 | name: string; 10 | avatar: string; 11 | } 12 | 13 | type AuthContextType = { 14 | user: User | undefined; 15 | signInWithGoogle: () => Promise; 16 | } 17 | 18 | type AuthContextProviderProps = { 19 | children: ReactNode; 20 | } 21 | 22 | export const AuthContext = createContext({} as AuthContextType); 23 | 24 | export function AuthContextProvider(props: AuthContextProviderProps) { 25 | const [ user, setUser] = useState() 26 | 27 | useEffect(() => { 28 | const unsubscribe = onAuthStateChanged(auth, (user) => { 29 | if(user) { 30 | const { displayName, photoURL, uid } = user 31 | 32 | // if(!displayName || !photoURL){ 33 | // throw new Error('Missing Information from Google Account.') 34 | // } 35 | 36 | setUser({ 37 | id: uid, 38 | name: displayName, 39 | avatar: photoURL 40 | }) 41 | } 42 | }) 43 | return () => { 44 | unsubscribe(); 45 | } 46 | }, [ ] ) 47 | 48 | async function signInWithGoogle() { 49 | const provider = new GoogleAuthProvider() 50 | const result = await signInWithPopup(auth, provider) 51 | 52 | if(result.user){ 53 | const { displayName, photoURL, uid } = result.user 54 | 55 | if(!displayName || !photoURL){ 56 | throw new Error('Missing Information from Google Account.') 57 | } 58 | 59 | setUser({ 60 | id: uid, 61 | name: displayName, 62 | avatar: photoURL 63 | }) 64 | } 65 | } 66 | 67 | return ( 68 | 69 | {props.children} 70 | 71 | ); 72 | } -------------------------------------------------------------------------------- /src/pages/registration/index.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from 'react'; 2 | import { 3 | Box, 4 | Flex, 5 | Text, 6 | Heading, 7 | Center, 8 | Divider, 9 | VStack, 10 | HStack, 11 | Button, 12 | Img, 13 | useBreakpointValue, 14 | List, 15 | ListItem, 16 | ListIcon, 17 | OrderedList, 18 | UnorderedList, 19 | } from "@chakra-ui/react"; 20 | import Head from 'next/head' 21 | 22 | import {api} from '../../services/integration'; 23 | 24 | import DevForm from '../../components/DevForm' 25 | import DevItem from '../../components/DevItem'; 26 | 27 | import { auth } from "../../services/firebase"; 28 | 29 | export default function Registration() { 30 | const [devs, setDevs] = useState([]); 31 | 32 | const isWideVersion = useBreakpointValue({ 33 | base: false, 34 | md: true 35 | }) 36 | 37 | useEffect(() => { 38 | async function loadDevs() { 39 | const response = await api.get('/devs'); 40 | 41 | setDevs(response.data); 42 | } 43 | 44 | loadDevs(); 45 | }, []); 46 | 47 | async function handleAddDev(data) { 48 | const response = await api.post('/devs', data) 49 | 50 | setDevs([...devs, response.data]); 51 | } 52 | 53 | return ( 54 | 55 | 56 | Cadastro | SW 57 | 58 | 59 | Cadastrar 60 | 61 | 62 | 63 | {auth.currentUser?.uid === 'ONhO5k9W2tcymSb39KTTBKkWZi32' && 64 | 65 | {devs.map(dev => ( 66 | 67 | ))} 68 | 69 | } 70 | 71 | ); 72 | } -------------------------------------------------------------------------------- /src/components/Pagination/index.tsx: -------------------------------------------------------------------------------- 1 | import { Stack, Button, Box, Text } from "@chakra-ui/react"; 2 | import { PaginationItem } from "./PaginationItem"; 3 | 4 | interface PaginationProps{ 5 | totalCountOfRegisters: number; 6 | registersPerPage?: number; 7 | currentPage?: number; 8 | onPageChange: (page: number) => void; 9 | } 10 | 11 | const siblingsCount = 1 12 | 13 | function generatePagesArray(from: number, to: number){ 14 | return [...new Array(to - from)].map((_, index) => { 15 | return from + index + 1 16 | }).filter(page => page > 0) 17 | } 18 | 19 | export default function Pagination({ totalCountOfRegisters, registersPerPage = 10, currentPage = 1, onPageChange }: PaginationProps){ 20 | const lastPage = Math.floor(totalCountOfRegisters / registersPerPage); 21 | const previousPages = currentPage > 1 ? generatePagesArray(currentPage - 1 - siblingsCount, currentPage - 1) : [] 22 | 23 | const nextPages = currentPage < lastPage ? generatePagesArray(currentPage, Math.min(currentPage + siblingsCount, lastPage)) : [] 24 | 25 | return( 26 | 27 | 28 | {/* 0 - 10 de 100 */} 29 | 30 | 31 | 32 | { currentPage > (1 + siblingsCount) && ( 33 | <> 34 | 35 | { currentPage > (2 + siblingsCount) && ( 36 | ... 37 | )} 38 | 39 | ) } 40 | 41 | { previousPages.length > 0 && previousPages.map(page => { 42 | return 43 | }) } 44 | 45 | 46 | 47 | { nextPages.length > 0 && nextPages.map(page => { 48 | return 49 | }) } 50 | 51 | { (currentPage + siblingsCount) < lastPage && ( 52 | <> 53 | { (currentPage + 1 + siblingsCount) < lastPage && ( 54 | ... 55 | )} 56 | 57 | 58 | ) } 59 | 60 | 61 | 62 | ); 63 | } -------------------------------------------------------------------------------- /src/services/api/webhooks.ts: -------------------------------------------------------------------------------- 1 | import { NextApiRequest, NextApiResponse } from "next"; 2 | import { Readable } from 'stream' 3 | import Stripe from "stripe"; 4 | import { stripe } from "../../services/stripe"; 5 | // import { saveSubscription } from "./_lib/manageSubscription"; 6 | 7 | // async function buffer(readable: Readable){ 8 | // const chunks = []; 9 | 10 | // for await (const chunk of readable) { 11 | // chunks.push( 12 | // typeof chunk === "string" ? Buffer.from(chunk) : chunk 13 | // ) 14 | // } 15 | 16 | // return Buffer.concat(chunks) 17 | // } 18 | 19 | // export const config = { 20 | // api: { 21 | // bodyParser: false 22 | // } 23 | // } 24 | 25 | // const relevantEvents = new Set([ 26 | // 'checkout.session.completed', 27 | // 'customer.subscription.updated', 28 | // 'customer.subscription.deleted' 29 | // ]) 30 | 31 | 32 | // eslint-disable-next-line import/no-anonymous-default-export 33 | // export default async (req: NextApiRequest, res: NextApiResponse)=>{ 34 | // if(req.method === 'POST'){ 35 | // const buf = await buffer(req) 36 | // const secret = req.headers['stripe-signature'] 37 | 38 | 39 | // let event: Stripe.Event 40 | 41 | // try{ 42 | 43 | // event = stripe.webhooks.constructEvent(buf, secret, process.env.STRIPE_WEBHOOK_SECRET) 44 | 45 | // }catch (err){ 46 | // return res.status(400).send(`Webhoook error: ${err.message}`) 47 | // } 48 | 49 | // const {type} = event 50 | 51 | // if(relevantEvents.has(type)){ 52 | // console.log('evento relevant', event) 53 | // try{ 54 | // switch(type){ 55 | // case 'customer.subscription.updated': 56 | // case 'customer.subscription.deleted': 57 | 58 | // const subscription = event.data.object as Stripe.Subscription 59 | 60 | // // await saveSubscription( 61 | // // subscription.id, 62 | // // subscription.customer.toString(), 63 | // // false 64 | // // ) 65 | // break 66 | // case 'checkout.session.completed': 67 | // const checkoutSession = event.data.object as Stripe.Checkout.Session 68 | 69 | // // await saveSubscription( 70 | // // checkoutSession.subscription.toString(), 71 | // // checkoutSession.customer.toString(), 72 | // // true 73 | // // ) 74 | // break; 75 | // default: 76 | // throw new Error('Unhandled event.') 77 | // } 78 | // }catch(err){ 79 | // return res.json({ error: 'Webhoook handler failed.' }) 80 | // } 81 | // } 82 | 83 | // res.json({received: true}) 84 | // }else{ 85 | // res.setHeader('Allow', 'POST') 86 | // res.status(405).end('Method not allowed') 87 | // } 88 | // } -------------------------------------------------------------------------------- /src/pages/avaliar/[id].tsx: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from 'react'; 2 | import { 3 | Box, 4 | Flex, 5 | Text, 6 | Heading, 7 | Center, 8 | Divider, 9 | VStack, 10 | HStack, 11 | Button, 12 | Img, 13 | useBreakpointValue, 14 | List, 15 | ListItem, 16 | ListIcon, 17 | OrderedList, 18 | UnorderedList, 19 | } from "@chakra-ui/react"; 20 | import Head from 'next/head' 21 | import toast from 'react-hot-toast'; 22 | // import '../../styles/star.css' 23 | 24 | import {api} from '../../services/integration'; 25 | 26 | export default function Avaliar() { 27 | const isWideVersion = useBreakpointValue({ 28 | base: false, 29 | md: true 30 | }) 31 | 32 | const [ loading, setLoading ] = useState(false) 33 | 34 | function Loading(){ 35 | setLoading(true) 36 | new Promise(() => setTimeout(() => {setLoading(false), toast.success('Obrigado por sua avaliação!', { 37 | duration: 4000, 38 | });}, 2000)) 39 | } 40 | 41 | return ( 42 | 43 | 44 | Avaliar | SW 45 | 46 | 47 | Avaliação 48 | 49 | {/* */} 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 77 | 78 | 79 | ); 80 | } -------------------------------------------------------------------------------- /src/services/hooks/useRoom.ts: -------------------------------------------------------------------------------- 1 | import { database } from "../firebase"; 2 | import { ref, child, onValue } from "firebase/database"; 3 | 4 | import Router from "next/router"; 5 | import { useState, useEffect } from "react"; 6 | import { toast } from "react-hot-toast"; 7 | 8 | type QuestionType = { 9 | username: string; 10 | message: string; 11 | email: string; 12 | date: string; 13 | tel: string; 14 | id: string; 15 | } 16 | 17 | type FirebaseQuestions = Record< 18 | string, 19 | { 20 | username: string; 21 | message: string; 22 | email: string; 23 | date: string; 24 | tel: string; 25 | } 26 | >; 27 | 28 | export default function useRoom(roomId: string) { 29 | const [questions, setQuestions] = useState([]); 30 | const [title, setTitle] = useState(""); 31 | 32 | useEffect(() => { 33 | const roomRef = ref(database, 'feedback/') 34 | console.log('amore', roomRef) 35 | 36 | 37 | onValue(roomRef, (room) => { 38 | 39 | const databaseRoom = room.val(); 40 | 41 | // if(databaseRoom?.closedAt && (user?.id !== databaseRoom?.authorId)) { 42 | // toast.error("Sala foi encerrada pelo admin", { 43 | // style: { 44 | // background: "#F56565", 45 | // color: "#FFF", 46 | // }, 47 | // iconTheme: { 48 | // primary: "#FFF", 49 | // secondary: "#F56565", 50 | // }, 51 | // }); 52 | 53 | // Router.push("/"); 54 | 55 | // return () => { 56 | // roomRef.off("value"); 57 | // }; 58 | // } 59 | 60 | const firebaseQuestions: FirebaseQuestions = 61 | databaseRoom?.feedback ?? {}; 62 | 63 | room.forEach((data) => { 64 | console.log('EU', data.val()) 65 | const user = { 66 | id: data.key, 67 | message: data.val().message, 68 | username: data.val().username, 69 | email: data.val().email, 70 | date: data.val().date, 71 | tel: data.val().tel 72 | } 73 | setQuestions(user) 74 | }) 75 | 76 | const parsedQuestions = Object.entries(firebaseQuestions).map( 77 | ([key, value]) => { 78 | return { 79 | id: key, 80 | message: value.message, 81 | username: value.username, 82 | email: value.email, 83 | date: value.date, 84 | tel: value.tel, 85 | }; 86 | } 87 | ); 88 | // console.log('Tamanho', parsedQuestions) 89 | 90 | // const orderQuestionsByLikeCount = parsedQuestions.sort((roomA, roomB) => 91 | // roomA.type < roomB.type ? -1 : roomA.type > roomB.type ? 1 : 0 92 | // ); 93 | 94 | // const orderQuestionByNotAnswer = orderQuestionsByLikeCount.sort((roomA, roomB) => 95 | // roomA.isAnswered > roomB.isAnswered ? 1 : roomA.isAnswered < roomB.isAnswered ? -1 : 0 96 | // ); 97 | 98 | // setTitle(databaseRoom?.title); 99 | setQuestions(databaseRoom?.form); 100 | }); 101 | 102 | // return () => { 103 | // roomRef.off("value"); 104 | // }; 105 | }, []); 106 | // console.log('q', questions) 107 | 108 | return { questions, title }; 109 | } -------------------------------------------------------------------------------- /src/components/Header/Profile.tsx: -------------------------------------------------------------------------------- 1 | import { Flex, Text, Box, Avatar, AvatarBadge, Menu, 2 | MenuButton, 3 | MenuList, 4 | MenuItem, 5 | MenuDivider, 6 | Center, 7 | Button } from '@chakra-ui/react' 8 | import { auth } from '../../services/firebase' 9 | import { signOut } from "firebase/auth"; 10 | import toast, { Toaster } from 'react-hot-toast'; 11 | import { useRouter } from 'next/router'; 12 | 13 | 14 | interface ProfileProps{ 15 | showProfileData?: boolean; 16 | } 17 | 18 | export function Profile({showProfileData = true}: ProfileProps) { 19 | const router = useRouter() 20 | function logOut(){ 21 | signOut(auth).then(() => { 22 | toast.success('Desconectado'); 23 | router.push('/login') 24 | // Sign-out successful. 25 | }).catch((error) => { 26 | toast.error('Erro'); 27 | // An error happened. 28 | }); 29 | } 30 | return ( 31 | 32 | {/* { showProfileData && ( 33 | 34 | {auth.currentUser?.displayName ? auth.currentUser?.displayName : auth.currentUser?.email.split('@')[0]} 35 | {auth.currentUser?.email ? auth.currentUser?.email : ''} 36 | 37 | )} */} 38 | {/* {auth.currentUser?.email ? 39 | 40 | : 41 | 42 | } */} 43 | 44 | { auth.currentUser?.email ? 45 | 46 | 52 | 53 | 54 | 55 | 56 | 57 |
58 |
59 | 63 |
64 |
65 |
66 | {auth.currentUser?.displayName ? auth.currentUser?.displayName : auth.currentUser?.email.split('@')[0]} 67 | 68 |
69 |
70 |
71 | {auth.currentUser?.email} 72 |
73 |
74 | 75 | {/* Configurações */} 76 | Sair 77 |
78 |
79 | : 80 | 81 | 82 | 83 | } 84 | 85 | 86 |
87 | ) 88 | } -------------------------------------------------------------------------------- /src/pages/forms.tsx: -------------------------------------------------------------------------------- 1 | import { Box, Flex, Heading, Divider, VStack, HStack, Button } from "@chakra-ui/react"; 2 | import { Header } from "./../components/Header"; 3 | import { Sidebar } from "./../components/Sidebar"; 4 | import { Input } from "./../components/Form/Input"; 5 | import { TextArea } from "./../components/Form/TextArea"; 6 | import Link from 'next/link' 7 | import Head from 'next/head' 8 | import { push, child, ref, set } from "firebase/database"; 9 | import { theme } from "../styles/theme"; 10 | import toast, { Toaster } from 'react-hot-toast'; 11 | import { useState } from "react"; 12 | import { auth, database } from "../services/firebase"; 13 | 14 | export default function CreateUser(){ 15 | const [ username, setUsername ] = useState('') 16 | const [ local, setLocal ] = useState('') 17 | // const [ date, setDate ] = useState('') 18 | const [ email, setEmail ] = useState('') 19 | const [ description, setDescription ] = useState('') 20 | 21 | async function handleSubmit(event){ 22 | event.preventDefault 23 | 24 | const newPostKey = push(child(ref(database), 'forms')).key; 25 | 26 | await set(ref(database, `forms/${newPostKey}`), { 27 | username: username, 28 | local: local, 29 | date: new Intl.DateTimeFormat('pt-BR', { 30 | year: '2-digit', month: '2-digit', day: '2-digit' 31 | }).format(new Date()), 32 | email: email, 33 | description: description, 34 | }); 35 | 36 | } 37 | 38 | return( 39 | 52 | 53 | Formulário | SW 54 | 55 |
56 | 57 | 58 | 59 | Formulário 60 | 61 | 62 | setUsername(event.target.value)} css={{'&::selection': {background: theme.colors.pink[500]}}}/> 63 | setEmail(event.target.value)} css={{'&::selection': {background: theme.colors.pink[500]}}}/> 64 | setLocal(event.target.value)} css={{'&::selection': {background: theme.colors.pink[500]}}}/> 65 |