Untitled
unknown
javascript
2 years ago
7.4 kB
5
Indexable
/* eslint-disable no-nested-ternary */ import { Link } from 'react-router-dom'; import { useState, useEffect, useMemo, useCallback } from 'react'; import { Loader } from '../../components/Loader'; import { Error } from '../../components/Error'; import { Modal } from '../../components/Modal'; import ContactsService from '../../services/ContactsService'; import formatPhone from '../../utils/formatPhone'; import toast from '../../utils/toast'; import APIError from '../../errors/APIError'; import arrowIcon from '../../assets/icons/arrow.svg'; import editIcon from '../../assets/icons/edit.svg'; import deleteIcon from '../../assets/icons/delete.svg'; import sadIcon from '../../assets/icons/sad.svg'; import emptyBoxIcon from '../../assets/icons/empty-box.svg'; import magnifierQuestionIcon from '../../assets/icons/magnifier-question.svg'; import { Container, InputSearchBarContainer, ListHeader, Divider, EmptyContainer, SearchEmptyContainer, ListContainer, Card } from './styles'; export function Home() { const [contacts, setContacts] = useState([]); const [orderByName, setOrderByName] = useState('ASC'); const [searchTerm, setSearchTerm] = useState(''); const [isLoading, setIsLoading] = useState(true); const [hasError, setHasError] = useState(false); const [isVisibleModalDeleteContact, setIsVisibleModalDeleteContact] = useState(false); const [contactBeingDelete, setContactBeingDelete] = useState(null); const [isLoadingDeleteContact, setIsLoadingDeleteContact] = useState(false); const filteredContacts = useMemo( () => contacts.filter((contact) => contact.name.toLowerCase().includes(searchTerm.toLowerCase()) ), [contacts, searchTerm] ); const loadContacts = useCallback(async () => { try { setIsLoading(true); const result = await ContactsService.listContacts(orderByName); const formattedContacts = result.map((contact) => ({ ...contact, phoneFormatted: contact.telephone && formatPhone(contact.telephone) })); setHasError(false); setContacts(formattedContacts); } catch (error) { if (error instanceof APIError) { // MOSTRAR ALGO PARA USUÁRIO RELACIONADO ALGUM ERRO DA API console.log(error); } else { // MOSTRAR ALGO PARA USUÁRIO RELACIONADO ALGUM ERRO NO CÓDIGO/JAVASCRIPT NO FRONT-END console.log(error); } setHasError(error.name); } finally { setIsLoading(false); } }, [orderByName]); useEffect(() => { loadContacts(); }, [loadContacts]); function handleChangeSearchTerm(e) { setSearchTerm(e.target.value); } function handleToggleOrderByName() { setOrderByName((state) => (state === 'ASC' ? 'DESC' : 'ASC')); } function handleLoadContacts() { loadContacts(); } function handleDeleteContact(contact) { setIsVisibleModalDeleteContact(true); setContactBeingDelete(contact); } function handleCloseDeleteModal() { setIsVisibleModalDeleteContact(false); setContactBeingDelete(null); } async function handleConfirmDeleteContact() { try { setIsLoadingDeleteContact(true); await ContactsService.deleteContactById(contactBeingDelete.id); setContacts((state) => state.filter((contact) => contact.id !== contactBeingDelete.id) ); setIsLoadingDeleteContact(false); handleCloseDeleteModal(); toast({ type: 'success', text: 'Contato deletado com sucesso!' }); } catch (error) { toast({ type: 'danger', text: 'Ocorreu um erro ao deletar o contato' }); } } return ( <Container> <Loader isLoading={isLoading} /> <Modal isLoading={isLoadingDeleteContact} isVisible={isVisibleModalDeleteContact} title={`Tem certeza que deseja remover o contato ”${contactBeingDelete?.name}”?`} subtitle="Esta ação não poderá ser desfeita!" confirmLabel="Deletar" danger onCancel={handleCloseDeleteModal} onConfirm={handleConfirmDeleteContact} /> {!hasError && contacts.length > 0 && ( <InputSearchBarContainer> <input value={searchTerm} type="text" placeholder="Pesquisar contato..." onChange={(e) => handleChangeSearchTerm(e)} /> </InputSearchBarContainer> )} <ListHeader hasError={hasError} justifyContent={ hasError ? 'flex-end' : contacts.length > 0 ? 'space-between' : 'center' } > {!hasError && contacts.length > 0 && ( <strong> {filteredContacts.length}{' '} {filteredContacts.length === 1 ? 'contato' : 'contatos'} </strong> )} <Link to="/new">Novo Contato</Link> </ListHeader> <Divider /> {hasError && ( <Error icon={{ src: sadIcon, alt: 'sad' }} message="Ocorreu um erro ao obter os seus contatos!" onCLick={() => handleLoadContacts} /> )} {contacts.length === 0 && !isLoading && !hasError && ( <EmptyContainer> <img src={emptyBoxIcon} alt="Empty box" /> <span> Você ainda não tem nenhum contato cadastrado! <br /> Clique no botão<strong> ”Novo contato” </strong>à cima para cadastrar o seu primeiro! </span> </EmptyContainer> )} {!hasError && contacts.length > 0 && filteredContacts.length < 1 && ( <SearchEmptyContainer> <img src={magnifierQuestionIcon} alt="Magnifier question" /> <span> Nenhum resultado foi encontrado para <b> ”{searchTerm}”</b>. </span> </SearchEmptyContainer> )} {!hasError && ( <ListContainer orderByName={orderByName}> {filteredContacts.length > 0 && ( <header> <button type="button" onClick={handleToggleOrderByName}> <span>Nome</span> <img src={arrowIcon} alt="Arrow" /> </button> </header> )} {filteredContacts.map((contact) => ( <Card key={contact.id}> <div className="info"> <div className="info-header"> <strong>{contact.name}</strong> {contact.category.name && ( <small>{contact.category.name}</small> )} </div> <span>{contact.email}</span> <span>{contact.phoneFormatted}</span> </div> <div className="actions"> <Link to={`/edit/${contact.id}`}> <img src={editIcon} alt="Edit" /> </Link> <button type="button" onClick={() => handleDeleteContact(contact)} > <img src={deleteIcon} alt="Delete" /> </button> </div> </Card> ))} </ListContainer> )} </Container> ); }
Editor is loading...