UNPKG

@diagramers/admin

Version:

Diagramers Admin Template - React starter for admin dashboards.

238 lines (216 loc) 9.68 kB
import React, { useEffect, useState } from 'react'; import { useSelector, useDispatch } from 'react-redux'; import Fuse from 'fuse.js'; import { useWindowSize } from 'hooks/useWindowSize'; import { Row, Col, Button, ButtonGroup, Dropdown, OverlayTrigger, Tooltip } from 'react-bootstrap'; import HtmlHead from 'components/html-head/HtmlHead'; import BreadcrumbList from 'components/breadcrumb-list/BreadcrumbList'; import CsLineIcons from 'cs-line-icons/CsLineIcons'; import ComposeMail from './components/ComposeMail'; import EmailList from './components/EmailList'; import MenuModal from './components/MenuModal'; import MenuContent from './components/MenuContent'; import SearchInput from './components/SearchInput'; import CheckAll from './components/CheckAll'; import EmailCorrespondence from './components/EmailCorrespondence'; import { getMailbox, setSelectedMails, setViewingMail } from './mailboxSlice'; const MailboxApp = () => { const title = 'Mailbox'; const description = 'Very basic email application that contains a list page rendering, new&reply layouts and a static details page.'; const breadcrumbs = [ { to: '', text: 'Home' }, { to: 'apps', title: 'Apps' }, ]; const dispatch = useDispatch(); const { mailbox, showSettings, loading, selectedItems, viewingMail } = useSelector((state) => state.mailbox); const { themeValues } = useSelector((state) => state.settings); const lgBreakpoint = parseInt(themeValues.lg.replace('px', ''), 10); const { width } = useWindowSize(); const [listingItems, setListingItems] = useState(mailbox); const [filteredMailbox, setFilteredMailbox] = useState([]); const [isLgScreen, setIsLgScreen] = useState(false); const [isOpenMenuModal, setIsOpenMenuModal] = useState(false); const [isOpenCompose, setIsOpenCompose] = useState(false); useEffect(() => { if (width) { if (width >= lgBreakpoint) { if (!isLgScreen) setIsLgScreen(true); if (isOpenMenuModal) setIsOpenMenuModal(false); } else if (isLgScreen) setIsLgScreen(false); } return () => {}; // eslint-disable-next-line }, [width]); useEffect(() => { dispatch(getMailbox()); return () => {}; // eslint-disable-next-line }, []); useEffect(() => { setListingItems(mailbox); return () => {}; }, [mailbox]); const escapeRegexCharacters = (str) => { return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); }; const onChangeSearchTerm = (value) => { if (value === '') { setListingItems(filteredMailbox); } else { const escapedValue = escapeRegexCharacters(value.trim()); const fuse = new Fuse(filteredMailbox, { includeScore: true, keys: ['title', 'from', 'detail'], threshold: 0.4, }); const results = fuse.search(escapedValue).map((result) => { return result.item; }); setListingItems(results); } dispatch(setSelectedMails([])); }; const toggleSelectAll = (checked) => { if (checked) { dispatch(setSelectedMails(listingItems)); } else { dispatch(setSelectedMails([])); } }; useEffect(() => { if (mailbox) { const { folder, starred, important, tags } = showSettings; let filteringMailbox = mailbox; if (folder !== 'All') filteringMailbox = filteringMailbox.filter((x) => x.folder === folder); if (starred !== 'All') filteringMailbox = filteringMailbox.filter((x) => x.starred === starred); if (important !== 'All') filteringMailbox = filteringMailbox.filter((x) => x.important === important); if (tags !== 'All') filteringMailbox = filteringMailbox.filter((x) => x.tags.find((y) => y.title === tags)); setFilteredMailbox(filteringMailbox); setListingItems(filteringMailbox); } return () => {}; }, [mailbox, showSettings]); const onClickCompose = () => { setIsOpenCompose(true); }; const submitMail = (submitedMail) => { console.log('submitted...', submitedMail); }; return ( <> <HtmlHead title={title} description={description} /> {loading ? ( <div className="loading">Loading...</div> ) : ( <> <div className="page-title-container"> <Row className="g-0"> <Col xs="auto" className="mb-2 mb-lg-0 me-auto"> <div className="w-auto sw-md-25"> <h1 className="mb-0 pb-0 display-4">{title}</h1> <BreadcrumbList items={breadcrumbs} /> </div> </Col> <Col xs="auto" className="d-flex d-lg-none align-items-start mb-2 mb-lg-0 order-lg-1"> <Button variant="primary" id="emailMenuButton" className="btn-icon btn-icon-only ms-1" onClick={() => setIsOpenMenuModal(true)}> <CsLineIcons icon="menu-left" /> </Button> </Col> <div className="w-100 d-none d-md-block d-lg-none" /> <Col xs="12" md="6" lg className="d-flex align-items-start justify-content-start order-3 order-md-2"> {viewingMail === null && ( <Dropdown drop="down" as={ButtonGroup} className="me-1 check-all-container-checkbox-click" align="start"> <CheckAll allItems={listingItems} selectedItems={selectedItems} onToggle={toggleSelectAll} inputClassName="form-check" className="btn btn-outline-primary btn-custom-control p-0 ps-3 pe-2" /> <Dropdown.Toggle split as={Button} variant="outline-primary" /> <Dropdown.Menu popperConfig={{ modifiers: [ { name: 'offset', options: { offset: [0, 3], }, }, { name: 'computeStyles', options: { gpuAcceleration: false, }, }, ], }} > <Dropdown.Item>Mark as read</Dropdown.Item> <Dropdown.Item>Mark as unread</Dropdown.Item> <Dropdown.Item>Mute</Dropdown.Item> <Dropdown.Item>Star</Dropdown.Item> <Dropdown.Item>Pin</Dropdown.Item> </Dropdown.Menu> </Dropdown> )} {viewingMail && ( <OverlayTrigger delay={{ show: 1000, hide: 0 }} overlay={<Tooltip>Back</Tooltip>} placement="bottom"> <Button variant="outline-primary" className="btn-icon btn-icon-only me-1" onClick={() => { dispatch(setViewingMail(null)); }} > <CsLineIcons icon="arrow-left" /> </Button> </OverlayTrigger> )} <OverlayTrigger delay={{ show: 1000, hide: 0 }} overlay={<Tooltip>Tag</Tooltip>} placement="bottom"> <Button variant="outline-primary" className="btn-icon btn-icon-only me-1 disabled" onClick={() => {}}> <CsLineIcons icon="tag" /> </Button> </OverlayTrigger> <OverlayTrigger delay={{ show: 1000, hide: 0 }} overlay={<Tooltip>Spam</Tooltip>} placement="bottom"> <Button variant="outline-primary" className="btn-icon btn-icon-only me-1 disabled" onClick={() => {}}> <CsLineIcons icon="close" /> </Button> </OverlayTrigger> <OverlayTrigger delay={{ show: 1000, hide: 0 }} overlay={<Tooltip>Delete</Tooltip>} placement="bottom"> <Button variant="outline-primary" className="btn-icon btn-icon-only me-1 disabled me-lg-auto" onClick={() => {}}> <CsLineIcons icon="bin" /> </Button> </OverlayTrigger> </Col> <Col xs="12" md="6" lg className="d-flex align-items-start justify-content-end mb-2 mb-md-0 order-md-3"> <div className="w-100 w-md-auto search-input-container border border-separator"> <SearchInput onChange={onChangeSearchTerm} /> </div> <Button variant="outline-primary" className="btn-icon btn-icon-start ms-1" onClick={onClickCompose}> <CsLineIcons icon="plus" /> <span>Compose</span> </Button> </Col> </Row> </div> <Row className="g-0"> {isLgScreen && ( <Col xs="auto" className="d-lg-flex"> <div className="nav flex-column sw-25 mt-n2"> <MenuContent /> </div> </Col> )} <Col> {viewingMail === null && <EmailList items={listingItems} />} {viewingMail && <EmailCorrespondence mail={viewingMail} />} </Col> </Row> {isLgScreen === false && <MenuModal show={isOpenMenuModal} onHide={() => setIsOpenMenuModal(false)} />} {isOpenCompose && <ComposeMail show={isOpenCompose} onHide={() => setIsOpenCompose(false)} submitMail={submitMail} />} </> )} </> ); }; export default MailboxApp;