├── src
├── images
│ ├── exemple.png
│ └── segunda-vesao.png
├── components
│ ├── HeadPages.js
│ ├── Title.js
│ ├── CustomButtonOne.js
│ ├── Form
│ │ ├── FormHeader.js
│ │ ├── FormInput.js
│ │ └── Form.js
│ ├── MessagePopup.js
│ ├── ThemeChangeButton.js
│ ├── HeaderComponet.js
│ ├── Loading.js
│ ├── Avatar.js
│ ├── ButtonSendSticker.js
│ ├── Account.js
│ └── MessageList.js
└── Styles
│ └── GlobalStyle.js
├── public
├── images
│ ├── 5549789.gif
│ ├── Frame-2.jpg
│ ├── favicon.ico
│ ├── Frame-Small.jpg
│ ├── Android-Small.jpg
│ ├── Unknown_person.jpg
│ ├── Screenshot (205).png
│ ├── logotipo-github.png
│ ├── send.svg
│ └── trash2.svg
└── Fonts
│ └── Retro-Gaming.ttf
├── services
└── supabase.js
├── pages
├── _app.js
├── index.js
├── 404.js
└── chat.js
├── package.json
├── hooks
└── UserContext
│ └── index.js
├── README.md
├── .gitignore
└── config.json
/src/images/exemple.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/parlandin/Imersao-React-Aluracord/HEAD/src/images/exemple.png
--------------------------------------------------------------------------------
/public/images/5549789.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/parlandin/Imersao-React-Aluracord/HEAD/public/images/5549789.gif
--------------------------------------------------------------------------------
/public/images/Frame-2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/parlandin/Imersao-React-Aluracord/HEAD/public/images/Frame-2.jpg
--------------------------------------------------------------------------------
/public/images/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/parlandin/Imersao-React-Aluracord/HEAD/public/images/favicon.ico
--------------------------------------------------------------------------------
/public/Fonts/Retro-Gaming.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/parlandin/Imersao-React-Aluracord/HEAD/public/Fonts/Retro-Gaming.ttf
--------------------------------------------------------------------------------
/public/images/Frame-Small.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/parlandin/Imersao-React-Aluracord/HEAD/public/images/Frame-Small.jpg
--------------------------------------------------------------------------------
/src/images/segunda-vesao.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/parlandin/Imersao-React-Aluracord/HEAD/src/images/segunda-vesao.png
--------------------------------------------------------------------------------
/public/images/Android-Small.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/parlandin/Imersao-React-Aluracord/HEAD/public/images/Android-Small.jpg
--------------------------------------------------------------------------------
/public/images/Unknown_person.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/parlandin/Imersao-React-Aluracord/HEAD/public/images/Unknown_person.jpg
--------------------------------------------------------------------------------
/public/images/Screenshot (205).png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/parlandin/Imersao-React-Aluracord/HEAD/public/images/Screenshot (205).png
--------------------------------------------------------------------------------
/public/images/logotipo-github.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/parlandin/Imersao-React-Aluracord/HEAD/public/images/logotipo-github.png
--------------------------------------------------------------------------------
/services/supabase.js:
--------------------------------------------------------------------------------
1 | import { createClient } from '@supabase/supabase-js'
2 |
3 |
4 | const baseUrl = process.env.NEXT_PUBLIC_SUPERBASE_URL
5 | const anonKey = process.env.NEXT_PUBLIC_SUPERBASE_ANON_KEY
6 |
7 | const supabase = createClient(baseUrl, anonKey )
8 |
9 | export default supabase
--------------------------------------------------------------------------------
/public/images/send.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/components/HeadPages.js:
--------------------------------------------------------------------------------
1 | import Head from "next/head"
2 |
3 | export default function HeadPage() {
4 | return (
5 | <>
6 |
7 |
8 |
9 |
10 |
11 | >
12 | )
13 | }
--------------------------------------------------------------------------------
/public/images/trash2.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/pages/_app.js:
--------------------------------------------------------------------------------
1 | import GlobalStyle from '../src/Styles/GlobalStyle';
2 | import HeadPage from '../src/components/HeadPages';
3 | import { AuthContextProvider } from '../hooks/UserContext';
4 |
5 | export default function CustomApp({ Component, pageProps }) {
6 | return (
7 | <>
8 |
9 |
10 |
11 |
12 |
13 | >
14 | )
15 | }
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "aluracord",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "dev": "next dev",
8 | "build": "next build",
9 | "start": "next start",
10 | "lint": "next lint"
11 | },
12 | "keywords": [],
13 | "author": "",
14 | "license": "ISC",
15 | "dependencies": {
16 | "@skynexui/components": "^1.23.2",
17 | "@supabase/supabase-js": "^1.29.4",
18 | "next": "^12.0.8",
19 | "react": "^17.0.2",
20 | "react-dom": "^17.0.2"
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/components/Title.js:
--------------------------------------------------------------------------------
1 |
2 |
3 | function Titulo(props) {
4 | const Tag = props.tag || 'h1';
5 |
6 | return (
7 | <>
8 | {props.children}
9 |
18 | >
19 | );
20 | }
21 |
22 |
23 | export default Titulo
--------------------------------------------------------------------------------
/src/components/CustomButtonOne.js:
--------------------------------------------------------------------------------
1 |
2 | function CustomButtonOne( { children , onClick} ) {
3 | return (
4 | <>
5 |
8 |
21 | >
22 | )
23 | }
24 |
25 | export default CustomButtonOne
--------------------------------------------------------------------------------
/hooks/UserContext/index.js:
--------------------------------------------------------------------------------
1 | import React, { createContext, useState , useContext, useEffect} from "react"
2 | import supabase from "../../services/supabase"
3 |
4 | export const AuthContext = createContext({})
5 |
6 | export const AuthContextProvider = ({ children }) => {
7 |
8 | const [user, setUser] = useState()
9 |
10 | useEffect(() => {
11 | const user = supabase.auth.user()
12 | if(user){
13 | setUser(user)
14 | }
15 | })
16 |
17 | return (
18 |
19 | {children}
20 |
21 | )
22 | }
23 |
24 | export function useAuth(){
25 | return useContext(AuthContext)
26 | }
--------------------------------------------------------------------------------
/src/components/Form/FormHeader.js:
--------------------------------------------------------------------------------
1 | import Title from "../Title"
2 |
3 |
4 | function FormHeader(){
5 | return (
6 | <>
7 |
8 |
9 | Bem vindo!
10 |
11 | Discord - Alura Gaming
12 |
13 |
27 |
28 | >
29 | )
30 | }
31 |
32 |
33 | export default FormHeader
--------------------------------------------------------------------------------
/src/components/MessagePopup.js:
--------------------------------------------------------------------------------
1 |
2 |
3 | function MessagePopup({type, message} ){
4 | const cor = type == "error" ? "#c44040" : "#265d2bdb"
5 |
6 | return (
7 | <>
8 |
11 |
12 |
31 | >
32 | )
33 | }
34 |
35 |
36 | export default MessagePopup
--------------------------------------------------------------------------------
/src/components/ThemeChangeButton.js:
--------------------------------------------------------------------------------
1 |
2 | export default function ThemeChangeButton(props) {
3 | const color = props.color
4 | const handerClick = props.event
5 | const theme = props.theme
6 |
7 | return (
8 | <>
9 | handerClick(theme)}>
10 |
30 | >
31 | )
32 | }
33 |
--------------------------------------------------------------------------------
/src/Styles/GlobalStyle.js:
--------------------------------------------------------------------------------
1 | function GlobalStyle() {
2 | return (
3 |
52 | );
53 | }
54 |
55 | export default GlobalStyle
--------------------------------------------------------------------------------
/src/components/HeaderComponet.js:
--------------------------------------------------------------------------------
1 | import { Box, Text, Button } from '@skynexui/components';
2 |
3 | function Header({router, defaultTheme , supabase }) {
4 |
5 | return (
6 | <>
7 |
17 |
18 | Chat
19 |
20 |
31 | >
32 | )
33 | }
34 |
35 | export default Header
--------------------------------------------------------------------------------
/src/components/Loading.js:
--------------------------------------------------------------------------------
1 | function Loading(){
2 | return (
3 | <>
4 | Loading…
5 |
6 |
45 | >
46 | )
47 | }
48 |
49 |
50 | export default Loading
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # AluraCord
2 |
3 |
4 |
5 |
6 |
7 | > Projeto em desenvolvimento.
8 |
9 | ### Ajustes e melhorias
10 |
11 | O projeto ainda está em desenvolvimento e as próximas atualizações serão voltadas nas seguintes tarefas:
12 |
13 | - [x] Criar primeira tela.
14 | - [x] Criar segunda tela.
15 | - [x] Autenticação github.
16 | - [x] Buscar informações no banco de dados.
17 | - [ ] Finalizar projeto.
18 |
19 | ## 💻 Pré-requisitos
20 |
21 | Antes de começar, verifique se você atendeu aos seguintes requisitos:
22 |
23 | * Você instalou a versão mais recente do nodeJs
24 |
25 | ## 🚀 Instalando AluraCord
26 |
27 | Para instalar o AluraCord, siga estas etapas:
28 |
29 |
30 | ```
31 | npm install
32 | ```
33 | ou
34 |
35 | ```
36 | yarn add [package]
37 | ```
38 |
39 |
40 | ## ☕ Usando AluraCord
41 |
42 | Para usar AluraCord, siga estas etapas:
43 |
44 | ```
45 | npm run dev
46 | ```
47 | ou
48 | ```
49 | yarn dev
50 | ```
51 |
52 |
53 | ## 🤝 Colaboradores
54 |
55 | Agradecemos às seguintes pessoas que contribuíram para este projeto:
56 |
57 |
69 |
70 |
71 |
72 | ## 📝 Licença
73 |
74 |
75 |
76 | [⬆ Voltar ao topo](#Imersao-React-Aluracord)
77 |
--------------------------------------------------------------------------------
/src/components/Avatar.js:
--------------------------------------------------------------------------------
1 | import { useEffect, useState } from 'react'
2 | import supabase from '../../services/supabase'
3 |
4 | export default function Avatar({ onUpload }) {
5 | const [uploading, setUploading] = useState(false)
6 |
7 |
8 | async function uploadAvatar(event) {
9 | try {
10 | setUploading(true)
11 |
12 | if (!event.target.files || event.target.files.length === 0) {
13 | throw new Error('You must select an image to upload.')
14 | }
15 |
16 | const file = event.target.files[0]
17 | const fileExt = file.name.split('.').pop()
18 | const fileName = `${Math.random()}.${fileExt}`
19 | const filePath = `${fileName}`
20 |
21 | let { error: uploadError } = await supabase.storage
22 | .from('avatars')
23 | .upload(filePath, file)
24 |
25 | if (uploadError) {
26 | throw uploadError
27 | }
28 |
29 | onUpload(filePath)
30 | } catch (error) {
31 | alert(error.message)
32 | } finally {
33 | setUploading(false)
34 | }
35 | }
36 |
37 | return (
38 | <>
39 |
40 |
43 |
54 |
55 |
56 |
66 | >
67 | )
68 | }
--------------------------------------------------------------------------------
/pages/index.js:
--------------------------------------------------------------------------------
1 | import { Box } from '@skynexui/components'
2 | import appConfig from '../config.json'
3 | import React, { useContext, useState, useEffect } from 'react'
4 | import Head from "next/head"
5 | import Form from "../src/components/Form/Form"
6 | import { useAuth } from '../hooks/UserContext'
7 | import { useRouter } from 'next/router';
8 |
9 |
10 |
11 |
12 | export default function PaginaInicial() {
13 | const [user] = useAuth()
14 | const defaultTheme = appConfig.defaultTheme
15 | const router = useRouter()
16 |
17 | useEffect(()=> {
18 | if(user){
19 | router.push("/chat")
20 | return
21 | }
22 | })
23 |
24 | return (
25 | <>
26 |
27 | Aluracord
28 |
29 |
30 |
31 |
39 |
50 | {/* Formulário */}
51 |
52 | {/* Formulário */}
53 |
54 |
55 |
56 | >
57 | );
58 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | lerna-debug.log*
8 | .pnpm-debug.log*
9 |
10 | # Diagnostic reports (https://nodejs.org/api/report.html)
11 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
12 |
13 | # Runtime data
14 | pids
15 | *.pid
16 | *.seed
17 | *.pid.lock
18 |
19 | # Directory for instrumented libs generated by jscoverage/JSCover
20 | lib-cov
21 |
22 | # Coverage directory used by tools like istanbul
23 | coverage
24 | *.lcov
25 |
26 | # nyc test coverage
27 | .nyc_output
28 |
29 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
30 | .grunt
31 |
32 | # Bower dependency directory (https://bower.io/)
33 | bower_components
34 |
35 | # node-waf configuration
36 | .lock-wscript
37 |
38 | # Compiled binary addons (https://nodejs.org/api/addons.html)
39 | build/Release
40 |
41 | # Dependency directories
42 | node_modules/
43 | jspm_packages/
44 |
45 | # Snowpack dependency directory (https://snowpack.dev/)
46 | web_modules/
47 |
48 | # TypeScript cache
49 | *.tsbuildinfo
50 |
51 | # Optional npm cache directory
52 | .npm
53 |
54 | # Optional eslint cache
55 | .eslintcache
56 |
57 | # Optional stylelint cache
58 | .stylelintcache
59 |
60 | # Microbundle cache
61 | .rpt2_cache/
62 | .rts2_cache_cjs/
63 | .rts2_cache_es/
64 | .rts2_cache_umd/
65 |
66 | # Optional REPL history
67 | .node_repl_history
68 |
69 | # Output of 'npm pack'
70 | *.tgz
71 |
72 | # Yarn Integrity file
73 | .yarn-integrity
74 |
75 | # dotenv environment variable files
76 | .env
77 | .env.development.local
78 | .env.test.local
79 | .env.production.local
80 | .env.local
81 |
82 | # parcel-bundler cache (https://parceljs.org/)
83 | .cache
84 | .parcel-cache
85 |
86 | # Next.js build output
87 | .next
88 | out
89 |
90 | # Nuxt.js build / generate output
91 | .nuxt
92 | dist
93 |
94 | # Gatsby files
95 | .cache/
96 | # Comment in the public line in if your project uses Gatsby and not Next.js
97 | # https://nextjs.org/blog/next-9-1#public-directory-support
98 | # public
99 |
100 | # vuepress build output
101 | .vuepress/dist
102 |
103 | # vuepress v2.x temp and cache directory
104 | .temp
105 | .cache
106 |
107 | # Docusaurus cache and generated files
108 | .docusaurus
109 |
110 | # Serverless directories
111 | .serverless/
112 |
113 | # FuseBox cache
114 | .fusebox/
115 |
116 | # DynamoDB Local files
117 | .dynamodb/
118 |
119 | # TernJS port file
120 | .tern-port
121 |
122 | # Stores VSCode versions used for testing VSCode extensions
123 | .vscode-test
124 |
125 | # yarn v2
126 | .yarn/cache
127 | .yarn/unplugged
128 | .yarn/build-state.yml
129 | .yarn/install-state.gz
130 | .pnp.*
131 |
--------------------------------------------------------------------------------
/src/components/ButtonSendSticker.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Box, Button, Text, Image } from '@skynexui/components';
3 | import appConfig from '../../config.json';
4 |
5 | export function ButtonSendSticker( {onSend} ) {
6 | const [isOpen, setOpenState] = React.useState('');
7 |
8 | return (
9 |
14 |
99 | )
100 | }
--------------------------------------------------------------------------------
/src/components/Account.js:
--------------------------------------------------------------------------------
1 | import { useState, useEffect } from 'react'
2 | import supabase from '../../services/supabase'
3 | import Avatar from './Avatar'
4 | import { useRouter } from 'next/router'
5 |
6 |
7 | export default function Account({ session }) {
8 | const [loading, setLoading] = useState(true)
9 | const [username, setUsername] = useState(null)
10 | const [avatar_url, setAvatarUrl] = useState(null)
11 |
12 | const router = useRouter()
13 |
14 |
15 | useEffect(() => {
16 | getProfile()
17 | }, [session])
18 |
19 |
20 | async function getProfile() {
21 | try {
22 | setLoading(true)
23 | const user = supabase.auth.user()
24 |
25 | let { data, error, status } = await supabase
26 | .from('profiles')
27 | .select(`username, avatar_url`)
28 | .eq('id', user.id)
29 | .single()
30 |
31 | if (error && status !== 406) {
32 | throw error
33 | }
34 |
35 | if (data) {
36 | setUsername(data.username)
37 | setAvatarUrl(data.avatar_url)
38 | }
39 | } catch (error) {
40 | alert(error.message)
41 | } finally {
42 | setLoading(false)
43 | }
44 | }
45 |
46 | async function updateProfile({ username, avatar_url }) {
47 | try {
48 | setLoading(true)
49 | const user = supabase.auth.user()
50 |
51 | const updates = {
52 | id: user.id,
53 | username,
54 | avatar_url,
55 | updated_at: new Date(),
56 | }
57 |
58 | let { error } = await supabase.from('profiles').upsert(updates, {
59 | returning: 'minimal'
60 | })
61 |
62 | if (error) {
63 | throw error
64 | }
65 | router.reload()
66 |
67 | } catch (error) {
68 | alert(error.message)
69 | } finally {
70 | setLoading(false)
71 | }
72 | }
73 |
74 | return (
75 | <>
76 |
77 |
78 |
79 | setUsername(e.target.value)}
84 | />
85 |
86 |
87 |
88 |
{
92 | setAvatarUrl(url)
93 | updateProfile({ username, avatar_url: url })
94 | }}
95 | />
96 |
97 |
98 |
99 |
106 |
107 |
108 |
134 | >
135 | )
136 | }
137 |
--------------------------------------------------------------------------------
/src/components/Form/FormInput.js:
--------------------------------------------------------------------------------
1 | import React, {useState} from "react"
2 |
3 |
4 | function FormInput({type, handleOnSubmit, handleChangeLogin}){
5 | const [values, setValues ] = useState({email: "", senha: ""})
6 |
7 | function handleChange(e){
8 | const name = e.target.name
9 | setValues({...values, [name]: e.target.value})
10 | }
11 |
12 | function handleSubmit(e){
13 | e.preventDefault()
14 | if(values.email < 0|| values.senha < 6){
15 | return alert("dados inválido , revise e tente novamente")
16 | }
17 | handleOnSubmit(values)
18 | }
19 | return (
20 | <>
21 |
45 |
46 |
48 |
49 |
107 | >
108 | )
109 | }
110 |
111 | export default FormInput
--------------------------------------------------------------------------------
/src/components/Form/Form.js:
--------------------------------------------------------------------------------
1 | import FormHeader from "./FormHeader"
2 | import FormInput from "./FormInput"
3 | import React, {useState} from "react"
4 | import supabase from "../../../services/supabase"
5 | import { useAuth } from "../../../hooks/UserContext"
6 | import { useRouter } from "next/router"
7 | import Loading from "../Loading"
8 | import MessagePopup from "../MessagePopup"
9 |
10 |
11 |
12 | function Form(){
13 | const [stateLogin, setStateLogin] = useState({
14 | loading: false,
15 | PopupMessage: false,
16 | message: "",
17 | type: "success"
18 | })
19 |
20 | const router = useRouter()
21 | const [user, setUser] = useAuth()
22 |
23 |
24 | async function handleLogin(date){
25 | setStateLogin({...stateLogin, loading: true})
26 | let { user, error } = await supabase.auth.signIn({
27 | email: date.email,
28 | password: date.senha,
29 | })
30 |
31 | if (error){
32 | setStateLogin({...stateLogin, loading: false})
33 | setStateLogin({...stateLogin, PopupMessage: true, message: error.message, type: "error"})
34 |
35 | const inteval = setTimeout(() => setStateLogin({...stateLogin, PopupMessage: false}), 1500)
36 | return () => clearInterval(inteval)
37 | }
38 | setUser(user)
39 | router.push("/chat")
40 | }
41 |
42 | async function handleRegistre(date){
43 | setStateLogin({...stateLogin, loading: true})
44 | let { user, error } = await supabase.auth.signUp({
45 | email: date.email,
46 | password: date.senha
47 | })
48 |
49 | if (error){
50 | setStateLogin({...stateLogin, loading: false})
51 | setStateLogin({...stateLogin, PopupMessage: true, message: error.message, type: "error"})
52 |
53 | const inteval = setTimeout(() => setStateLogin({...stateLogin, PopupMessage: false}), 1500)
54 | return () => clearInterval(inteval)
55 | }
56 |
57 |
58 | setStateLogin({...stateLogin, loading: false, PopupMessage: true, message: " Confirme seu email para continuar ", type: "success"})
59 |
60 | const inteval = setTimeout(() => setStateLogin({...stateLogin, PopupMessage: false}), 1500)
61 | return () => clearInterval(inteval)
62 | }
63 |
64 |
65 | function handleChangeLogin(){
66 | setStateLogin(!stateLogin)
67 |
68 | }
69 |
70 |
71 | return (
72 | <>
73 | {stateLogin.PopupMessage ? :
74 | stateLogin.loading ? :
75 | user || stateLogin
76 | ?
77 |
78 |
82 |
83 |
84 | :
85 |
86 |
90 |
91 |
92 | }
93 |
94 |
105 | >
106 | )
107 |
108 | }
109 |
110 | export default Form
111 |
112 |
--------------------------------------------------------------------------------
/pages/404.js:
--------------------------------------------------------------------------------
1 | import { Box, Button, Text, Image } from '@skynexui/components';
2 | import Head from "next/head"
3 | import { useRouter } from "next/router"
4 |
5 |
6 |
7 |
8 |
9 |
10 | function Page404() {
11 | //jsx
12 | const roteamento = useRouter()
13 | return (
14 | <>
15 |
16 |
17 |
18 |
19 | 404-Page not found
20 |
21 |
22 |
23 |
35 |
38 |
46 | 404
47 |
48 |
49 |
57 | Você Perdeu o Caminho de Casa
58 |
59 |
60 |
69 | Não se preocupe, você não está só, volte para o inicio.
70 |
71 |
72 |
95 |
96 |
97 |
98 | >
99 | )
100 | }
101 |
102 |
103 |
104 | export default Page404
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
--------------------------------------------------------------------------------
/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Discord - Alura Matrix",
3 | "stickers": [
4 | "http://2.bp.blogspot.com/-d21tffsTIQo/U_H9QjC69gI/AAAAAAAAKqM/wnvOyUr6a_I/s1600/Pikachu%2B2.gif",
5 | "https://media1.giphy.com/media/BdghqxNFV4efm/200.gif",
6 | "https://c.tenor.com/TKpmh4WFEsAAAAAC/alura-gaveta-filmes.gif",
7 | "https://i.pinimg.com/originals/0b/1c/23/0b1c2307c83e1ebdeed72e41b9a058ad.gif",
8 | "https://c.tenor.com/VylWt5lyjBoAAAAC/omg-yes.gif",
9 | "https://i.pinimg.com/originals/96/34/c5/9634c520c9a3cd4e7f23190bb2c96500.gif",
10 | "https://www.alura.com.br/imersao-react-4/assets/figurinhas/Figurinha_1.png",
11 | "https://www.alura.com.br/imersao-react-4/assets/figurinhas/Figurinha_2.png",
12 | "https://www.alura.com.br/imersao-react-4/assets/figurinhas/Figurinha_3.png",
13 | "https://www.alura.com.br/imersao-react-4/assets/figurinhas/Figurinha_4.png",
14 | "https://www.alura.com.br/imersao-react-4/assets/figurinhas/Figurinha_5.png",
15 | "https://www.alura.com.br/imersao-react-4/assets/figurinhas/Figurinha_6.png",
16 | "https://www.alura.com.br/imersao-react-4/assets/figurinhas/Figurinha_7.png",
17 | "https://www.alura.com.br/imersao-react-4/assets/figurinhas/Figurinha_8.png",
18 | "https://www.alura.com.br/imersao-react-4/assets/figurinhas/Figurinha_9.png",
19 | "https://www.alura.com.br/imersao-react-4/assets/figurinhas/Figurinha_10.png",
20 | "https://www.alura.com.br/imersao-react-4/assets/figurinhas/Figurinha_11.png",
21 | "https://www.alura.com.br/imersao-react-4/assets/figurinhas/Figurinha_12.png",
22 | "https://www.alura.com.br/imersao-react-4/assets/figurinhas/Figurinha_13.png",
23 | "https://www.alura.com.br/imersao-react-4/assets/figurinhas/Figurinha_14.png",
24 | "https://www.alura.com.br/imersao-react-4/assets/figurinhas/Figurinha_15.png",
25 | "https://www.alura.com.br/imersao-react-4/assets/figurinhas/Figurinha_16.png",
26 | "https://www.alura.com.br/imersao-react-4/assets/figurinhas/Figurinha_17.png",
27 | "https://www.alura.com.br/imersao-react-4/assets/figurinhas/Figurinha_18.png",
28 | "https://www.alura.com.br/imersao-react-4/assets/figurinhas/Figurinha_19.png",
29 | "https://www.alura.com.br/imersao-react-4/assets/figurinhas/Figurinha_20.png",
30 | "https://www.alura.com.br/imersao-react-4/assets/figurinhas/Figurinha_21.png",
31 | "https://www.alura.com.br/imersao-react-4/assets/figurinhas/Figurinha_22.png",
32 | "https://www.alura.com.br/imersao-react-4/assets/figurinhas/Figurinha_23.png",
33 | "https://www.alura.com.br/imersao-react-4/assets/figurinhas/Figurinha_24.png",
34 | "https://www.alura.com.br/imersao-react-4/assets/figurinhas/Figurinha_25.png",
35 | "https://www.alura.com.br/imersao-react-4/assets/figurinhas/Figurinha_26.png",
36 | "https://www.alura.com.br/imersao-react-4/assets/figurinhas/Figurinha_27.png",
37 | "https://www.alura.com.br/imersao-react-4/assets/figurinhas/Figurinha_28.png",
38 | "https://www.alura.com.br/imersao-react-4/assets/figurinhas/Figurinha_29.png",
39 | "https://www.alura.com.br/imersao-react-4/assets/figurinhas/Figurinha_30.png",
40 | "http://2.bp.blogspot.com/-d21tffsTIQo/U_H9QjC69gI/AAAAAAAAKqM/wnvOyUr6a_I/s1600/Pikachu%2B2.gif",
41 | "https://media1.giphy.com/media/BdghqxNFV4efm/200.gif",
42 | "https://c.tenor.com/TKpmh4WFEsAAAAAC/alura-gaveta-filmes.gif",
43 | "https://i.pinimg.com/originals/0b/1c/23/0b1c2307c83e1ebdeed72e41b9a058ad.gif",
44 | "https://c.tenor.com/VylWt5lyjBoAAAAC/omg-yes.gif",
45 | "https://i.pinimg.com/originals/96/34/c5/9634c520c9a3cd4e7f23190bb2c96500.gif"
46 | ],
47 |
48 | "defaultTheme": {
49 | "name": "Game lofi Tema",
50 | "backgroundImage": "url(https://wallpaperaccess.com/full/5549789.gif)",
51 | "icon": "url(https://i.pinimg.com/564x/22/14/f4/2214f4869398a52b2c512c896f315426.jpg)",
52 | "colors": {
53 | "primary": {
54 | "050": "#E3F9E5",
55 | "100": "#C1EAC5",
56 | "200": "#A3D9A5",
57 | "300": "#7BC47F",
58 | "400": "#57AE5B",
59 | "500": "#000000",
60 | "600": "#2F8132",
61 | "700": "#4d5b684a",
62 | "800": "#0E5814",
63 | "900": "#05400A"
64 | },
65 | "neutrals": {
66 | "000": "#FFFFFF",
67 | "050": "#F5F7FA",
68 | "100": "#E4E7EB",
69 | "200": "#CBD2D9",
70 | "300": "#9AA5B1",
71 | "400": "#52667A",
72 | "500": "#313D49",
73 | "600": "#29333D",
74 | "700": "#40566a70",
75 | "800": "#181f254d",
76 | "900": "#101418",
77 | "999": "#080A0C"
78 | }
79 | }
80 | }
81 | }
--------------------------------------------------------------------------------
/src/components/MessageList.js:
--------------------------------------------------------------------------------
1 | import { Box, Text, Image } from '@skynexui/components';
2 | import React,{memo} from 'react';
3 | import CustomButtonOne from "./CustomButtonOne";
4 |
5 |
6 |
7 | function MessageListTest( props) {
8 | const user = props.user || "anywere"
9 | return (
10 | <>
11 |
27 |
28 | {props.mensagens.map((date) => {
29 |
30 | return (
31 |
32 |
49 |
50 |
59 |
60 |
70 |
71 | {date.userName}
72 |
73 |
81 | {new Date(date.created_at).toLocaleString('pt-BR').substring(0,16)}
82 |
83 |
84 | {
85 | if(user == date.userName){
86 |
87 | props.supabase
88 | .from("mensagens-date")
89 | .delete([date])
90 | .match({ id: `${date.id}` })
91 | .then(() => {})
92 |
93 |
94 |
95 | } else{
96 | alert("Você só pode apagar suas proprias mensagens!!")
97 | }
98 | }
99 | }>
100 | {"/images/trash2.svg"}
101 |
102 |
103 |
104 |
105 | {date.texto.startsWith(":sticker:")
106 | ? (
107 |
112 | )
113 | :
114 | (<>
115 | {date.texto}
116 |
125 | >)
126 | }
127 |
128 |
129 |
130 | )
131 | })}
132 |
133 |
134 | >
135 | )
136 |
137 | }
138 |
139 | const MessageList = memo(MessageListTest)
140 |
141 | export default MessageList
--------------------------------------------------------------------------------
/pages/chat.js:
--------------------------------------------------------------------------------
1 | import { Box, TextField, } from '@skynexui/components';
2 | import React, { useState, useEffect } from 'react';
3 | import Head from "next/head"
4 | import { useRouter } from 'next/router';
5 | import CustomButtonOne from '../src/components/CustomButtonOne';
6 | import { ButtonSendSticker } from "../src/components/ButtonSendSticker"
7 | import appConfig from '../config.json'
8 | import supabase from "../services/supabase"
9 | import { useAuth } from '../hooks/UserContext';
10 | import Account from '../src/components/Account';
11 | import Loading from "../src/components/Loading"
12 | import MessageList from "../src/components/MessageList"
13 | import Header from '../src/components/HeaderComponet';
14 |
15 |
16 |
17 |
18 |
19 | export default function ChatPage() {
20 | const [user, setUser] = useAuth()
21 | const [session, setSession] = useState(supabase.auth.session())
22 | const [userInfo, setUserInfo] = useState({
23 | username: "new_user"
24 |
25 | })
26 |
27 | const [userMensangem, setUserMensagem] = useState([])
28 | const [mensage, setNewMensage] = useState("")
29 |
30 |
31 | const router = useRouter()
32 | const defaultTheme = appConfig.defaultTheme
33 |
34 | const [loading, setLoading] = useState(true)
35 |
36 |
37 | function listenerChange(addNewMensage){
38 | return (
39 | supabase
40 | .from("mensagens-date")
41 | .on('INSERT', async (date) => {
42 | addNewMensage(date.new)
43 | })
44 | .on("DELETE", async ( {old} ) => {
45 | setUserMensagem((valorAtual) => {
46 | const newValue = [...valorAtual].filter((value) => value.id != old.id )
47 | return newValue
48 | })
49 | })
50 | .subscribe()
51 |
52 | )
53 | }
54 |
55 |
56 | useEffect(() => {
57 | if(!user){
58 | router.push("/")
59 | return
60 | }
61 |
62 | supabase
63 | .from("mensagens-date")
64 | .select("*")
65 | .order("id", { ascending:false})
66 | .then( ( { data } ) => {
67 | setUserMensagem(data)
68 | })
69 |
70 | listenerChange((date) => {
71 | setUserMensagem((valorAtual) => {
72 | return [
73 | date,
74 | ...valorAtual,
75 | ]}
76 | )
77 | })
78 | }, [])
79 |
80 |
81 |
82 | useEffect(() => {
83 | supabase.auth.onAuthStateChange((_event, session) => {
84 | setSession(session)
85 | })
86 |
87 | if(session){
88 | getProfile()
89 | }
90 |
91 | }, [user])
92 |
93 |
94 | async function getProfile() {
95 | try {
96 | let { data } = await supabase
97 | .from('profiles')
98 | .select(`username, avatar_url`)
99 | .eq('id', user.id)
100 | .single()
101 |
102 | if(data) {
103 | setUserInfo(data)
104 | setLoading(false)
105 | }
106 | if(user){
107 | return setLoading(false)
108 | }
109 |
110 | }
111 | catch(error){
112 | console.log(error)
113 | }
114 | }
115 |
116 |
117 | function handleNewMessage(date){
118 | const newMensage = {
119 | avatar: userInfo.avatar_url ? "userInfo.avatar_url" : "Unknown_person.jpg",
120 | userName: userInfo.username,
121 | texto: date,
122 | created_at: new Date(),
123 | user_id: user.identities[0].user_id
124 | }
125 | supabase
126 | .from("mensagens-date")
127 | .insert([newMensage])
128 | .then(() => {})
129 |
130 | setNewMensage("")
131 | }
132 |
133 | return (
134 | <>
135 |
136 | Aluracord - Chat
137 |
138 |
139 |
149 |
164 |
165 |
166 |
167 |
181 | {loading ? :}
182 |
183 | {loading
184 | ? < MessageList defaultTheme={defaultTheme} mensagens={userMensangem} />
185 |
186 | : < MessageList defaultTheme={defaultTheme} mensagens={userMensangem} setMensagens={setUserMensagem} supabase={supabase} user={userInfo.username}/>}
187 |
188 |
195 | {
210 | setNewMensage(event.target.value)
211 | }}
212 |
213 | onKeyPress={(event) => {
214 | if (event.key === "Enter"){
215 |
216 | if (mensage.length > 0){
217 | event.preventDefault()
218 | handleNewMessage(mensage)
219 | }
220 | else {
221 | event.preventDefault()
222 | alert("sua mensagem não pode ser vazia")
223 | }
224 | }
225 | }}
226 | />
227 | {
228 | mensage.length > 0 ? handleNewMessage(mensage) : alert("sua mensagem não pode ser vazia")
229 |
230 | }}>
231 | {"/images/send.svg"}
232 |
233 | {
234 |
235 | handleNewMessage(`:sticker:${sticker}`)
236 | }}>
237 |
238 |
239 |
240 |
241 |
242 |
243 | >
244 | )
245 | }
246 |
247 |
--------------------------------------------------------------------------------