Advertisement
Diogovski

Untitled

Jun 9th, 2022
295
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import { useState, useEffect } from "react";
  2. import { supabase } from "../api/auth/supabaseClient";
  3. import Dropzone, { useDropzone } from "React-dropzone";
  4. import {
  5.   Button,
  6.   Flex,
  7.   FormControl,
  8.   FormLabel,
  9.   Heading,
  10.   Input,
  11.   Stack,
  12.   useColorModeValue,
  13.   HStack,
  14.   Avatar,
  15.   AvatarBadge,
  16.   IconButton,
  17.   Center,
  18.   Container,
  19.   useBreakpointValue,
  20.   Text,
  21.   useDisclosure,
  22.   Icon,
  23.   Square,
  24.   VStack
  25. } from '@chakra-ui/react';
  26. import { SmallCloseIcon } from "@chakra-ui/icons";
  27. import toast from "react-hot-toast";
  28. import { FiUploadCloud } from "react-icons/fi";
  29.  
  30. export default function Account({ session }) {
  31.   const {
  32.     isOpen: isLoading,
  33.     onOpen: startLoading,
  34.     onClose: stopLoading
  35.   } = useDisclosure();
  36.  
  37.   const [username, setUsername] = useState(null);
  38.   const [avatar_url, setAvatarUrl] = useState(null);
  39.   const [uploading, setUploading] = useState(false)
  40.  
  41.   useEffect(() => {
  42.     getProfile()
  43.   }, [session])
  44.  
  45.   function Comprimento(username) {
  46.     if (username.length < 3) {
  47.       toast.error("O nome de utilizador deve ter pelo menos 3 caracteres")
  48.     }
  49.     else {
  50.       updateProfile()
  51.     }
  52.   }
  53.  
  54.   async function getProfile() {
  55.     try {
  56.       isLoading
  57.       const user = supabase.auth.user();
  58.       let { data, error, status } = await supabase
  59.         .from("profiles")
  60.         .select(`username, avatar_url`)
  61.         .eq("id", user.id)
  62.         .single();
  63.       if (error && status !== 406) throw error;
  64.       if (data) {
  65.         setUsername(data.username);
  66.         setAvatarUrl(data.avatar_url);
  67.         if (data.avatar_url !== null) {
  68.           downloadImage(data.avatar_url);
  69.         }
  70.       }
  71.     } catch (error) {
  72.       toast.error(error.message);
  73.     }
  74.     finally {
  75.       stopLoading;
  76.     }
  77.   }
  78.   async function updateProfile() {
  79.     try {
  80.       isLoading;
  81.       const user = supabase.auth.user();
  82.  
  83.       const updates = {
  84.         id: user.id,
  85.         username,
  86.         avatar_url,
  87.         updated_at: new Date(),
  88.       };
  89.  
  90.       let { error } = await supabase.from("profiles").upsert(updates, {
  91.         returning: "minimal",
  92.       });
  93.  
  94.       if (error) throw error;
  95.       toast.success("Perfil atualizado com sucesso!");
  96.     } catch (error) {
  97.       toast.error("Nome de utilizador já existe!");
  98.     } finally {
  99.       stopLoading
  100.       getProfile
  101.     }
  102.   }
  103.  
  104.   async function downloadImage(path) {
  105.     try {
  106.       const { data, error } = await supabase.storage.from('avatars').download(path)
  107.       if (error) {
  108.         throw error
  109.       }
  110.       const url = URL.createObjectURL(data)
  111.       setAvatarUrl(url)
  112.     } catch (error) {
  113.       console.log('Erro ao baixar a imagem: ', error.message)
  114.     }
  115.   }
  116.  
  117.   async function uploadAvatar(event) {
  118.     try {
  119.       setUploading(true)
  120.  
  121.       if (!event.target.files || event.target.files.length === 0) {
  122.         throw new Error('Tens de escolher um Avatar')
  123.       }
  124.  
  125.       const file = event.target.files[0]
  126.       const fileExt = file.name.split('.').pop()
  127.       const fileName = `${Math.random()}.${fileExt}`
  128.       const filePath = `${fileName}`
  129.  
  130.       let { error: uploadError } = await supabase.storage
  131.         .from('avatars')
  132.         .upload(filePath, file)
  133.  
  134.       if (uploadError) {
  135.         throw uploadError
  136.       }
  137.       setAvatarUrl(fileName)
  138.     } catch (error) {
  139.       alert(error.message)
  140.     }
  141.   }
  142.  
  143.   return (
  144.     <>
  145.       <Container
  146.         maxW="lg"
  147.         py={{ base: "12", md: "24" }}
  148.         px={{ base: "0", sm: "8" }}
  149.       >
  150.         <Stack spacing="8">
  151.           <Stack spacing="6">
  152.             <Stack spacing={{ base: "2", md: "3" }} textAlign="center">
  153.               <Heading size={useBreakpointValue({ base: "xs", md: "sm" })}>
  154.                 Perfil
  155.               </Heading>
  156.               <HStack spacing="1" justify="center">
  157.                 <Text color="muted">
  158.                   Escolhe uma imagem de perfil e um nome de utilizador
  159.                 </Text>
  160.               </HStack>
  161.             </Stack>
  162.           </Stack>
  163.           <Stack
  164.             spacing="10"
  165.             py={{ base: "0", sm: "8" }}
  166.             px={{ base: "4", sm: "10" }}
  167.             bg={useBreakpointValue({ base: "transparent", sm: "bg-surface" })}
  168.             boxShadow={{ base: "none", sm: useColorModeValue("md", "md-dark") }}
  169.             borderRadius={{ base: "none", sm: "xl" }}
  170.           >
  171.             <FormControl id="userName" isRequired>
  172.               <Stack direction={["column", "row"]} spacing={6}>
  173.                 <Center>
  174.                   <Avatar size="xl" src={avatar_url}>
  175.                     <AvatarBadge
  176.                       as={IconButton}
  177.                       size="sm"
  178.                       rounded="full"
  179.                       top="-10px"
  180.                       colorScheme="red"
  181.                       aria-label="remove Image"
  182.                       icon={<SmallCloseIcon />}
  183.                     >
  184.                     </AvatarBadge>
  185.                   </Avatar>
  186.                 </Center>
  187.                 <Center w="full">
  188.                   <VStack spacing="3">
  189.                     <VStack>
  190.                       <Square size="10" bg="bg-subtle" borderRadius="lg">
  191.                         <Icon as={FiUploadCloud} boxSize="5" _hover={{ textDecor: 'none' }} color="muted" />
  192.                       </Square>
  193.                       <VStack spacing="1">
  194.                         <HStack spacing="1" whiteSpace="nowrap">
  195.                           {/** <Button variant="link" colorScheme="blue" size="sm">Clique</Button> */}
  196.                           <Input type="file" variant="link" colorScheme="blue" size="sm" onChange={uploadAvatar}>
  197.                           </Input>
  198.                           <Text fontSize="sm" color="muted">
  199.                             ou arrasta e larga
  200.                           </Text>
  201.                         </HStack>
  202.                         <Text fontSize="xs" color="muted">
  203.                           PNG, JPG ou GIF até 2MB
  204.                         </Text>
  205.                       </VStack>
  206.                     </VStack>
  207.                   </VStack>
  208.                 </Center>
  209.               </Stack>
  210.             </FormControl>
  211.             <FormControl id="userName">
  212.               <FormLabel>Nome de Utilizador</FormLabel>
  213.               <Input
  214.                 _placeholder={{ color: "gray.500" }}
  215.                 type="text"
  216.                 defaultValue={username}
  217.                 onChange={(e) => setUsername(e.target.value)}
  218.               />
  219.             </FormControl>
  220.             <br />
  221.             <Stack spacing={6} direction={["column", "row"]}>
  222.               <Button
  223.                 isLoading={isLoading}
  224.                 onClick={() => { startLoading; Comprimento(username); }}
  225.                 variant="primary"
  226.                 w="full"
  227.               >
  228.                 Guardar
  229.               </Button>
  230.             </Stack>
  231.           </Stack>
  232.         </Stack>
  233.       </Container>
  234.     </>
  235.   );
  236. }
  237.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement