// Dependencies import { horFlexClasses, notEmpty } from '@freesewing/utils' // Hooks import React, { useState, useEffect, Fragment, useContext } from 'react' import { useBackend } from '@freesewing/react/hooks/useBackend' // Context import { LoadingStatusContext } from '@freesewing/react/context/LoadingStatus' import { ModalContext } from '@freesewing/react/context/Modal' // Components import { BookmarkIcon, PlusIcon, TrashIcon } from '@freesewing/react/components/Icon' import { Link as WebLink } from '@freesewing/react/components/Link' import { ModalWrapper } from '@freesewing/react/components/Modal' import { StringInput } from '@freesewing/react/components/Input' /* * Various bookmark types */ const types = { design: 'Designs', pattern: 'Patterns', set: 'Measurements Sets', cset: 'Curated Measurements Sets', doc: 'Documentation', custom: 'Custom Bookmarks', } /** * A component to manage the user's bookmarks * * @component * @returns {JSX.Element} */ export const Bookmarks = () => { // Hooks & Context const backend = useBackend() const { setModal } = useContext(ModalContext) const { setLoadingStatus, LoadingProgress } = useContext(LoadingStatusContext) // State const [bookmarks, setBookmarks] = useState([]) const [selected, setSelected] = useState({}) const [refresh, setRefresh] = useState(0) // Helper var to see how many are selected const selCount = Object.keys(selected).length // Effects useEffect(() => { const getBookmarks = async () => { const [status, body] = await backend.getBookmarks() if (status === 200 && body.result === 'success') setBookmarks(body.bookmarks) } getBookmarks() }, [refresh]) // Helper method to toggle single selection const toggleSelect = (id) => { const newSelected = { ...selected } if (newSelected[id]) delete newSelected[id] else newSelected[id] = 1 setSelected(newSelected) } // Helper method to toggle select all const toggleSelectAll = () => { if (selCount === bookmarks.length) setSelected({}) else { const newSelected = {} for (const bookmark of bookmarks) newSelected[bookmark.id] = 1 setSelected(newSelected) } } // Helper to delete one or more bookmarks const removeSelectedBookmarks = async () => { let i = 0 for (const id in selected) { i++ await backend.removeBookmark(id) setLoadingStatus([ true, , ]) } setSelected({}) setRefresh(refresh + 1) setLoadingStatus([true, 'Nailed it', true, true]) } const perType = {} for (const type in types) perType[type] = bookmarks.filter((b) => b.type === type) return (

{bookmarks.length > 0 ? ( ) : null} {Object.entries(types).map(([type, title]) => perType[type].length > 0 ? (

{title}

{bookmarks .filter((bookmark) => bookmark.type === type) .map((bookmark, i) => ( ))}
Title Location
toggleSelect(bookmark.id)} /> {bookmark.title} {bookmark.url.length > 30 ? bookmark.url.slice(0, 30) + '...' : bookmark.url}
) : null )}
) } /* * Component to create a new bookmark * * @param {object} props - All the React props * @param {function} onCreated - An optional method to call when the bookmark is created */ const NewBookmark = ({ onCreated = false }) => { // Hooks const { setLoadingStatus } = useContext(LoadingStatusContext) const { clearModal } = useContext(ModalContext) const backend = useBackend() // State const [title, setTitle] = useState('') const [url, setUrl] = useState('') // This method will create the bookmark const createBookmark = async () => { setLoadingStatus([true, 'Processing update']) const [status] = await backend.createBookmark({ title, url, type: 'custom', }) if (status === 201) setLoadingStatus([true, 'Bookmark created', true, true]) else setLoadingStatus([ true, 'An error occured, the bookmark was not created. Please report this.', true, false, ]) if (typeof onCreated === 'function') onCreated() clearModal() } // Render the form return (
val.length > 0} placeholder="Bookmark title" /> val.length > 0} placeholder={'https://freesewing.org/account'} />
) } /** * Component to add a bookmark to the user's account * * @component * @param {object} props - All component props * @param {string} props.slug - The bookmark slug/href * @param {string} props.title - The bookmark title * @param {string} props.type - The bookmark type, one of design, pattern, set, cset, doc, or custom * @returns {JSX.Element} */ export const BookmarkButton = ({ slug, type, title }) => { const { setModal } = useContext(ModalContext) const typeTitles = { docs: 'page' } return ( ) } /* * A component to create a bookmark, preloaded with props * * @component * @param {object} props - All component props * @param {string} props.href - The bookmark href * @param {string} props.title - The bookmark title * @param {string} props.type - The bookmark type * @returns {JSX.Element} */ const CreateBookmark = ({ type, title, slug }) => { const backend = useBackend() const [name, setName] = useState(title) const { setLoadingStatus } = useContext(LoadingStatusContext) const { setModal } = useContext(ModalContext) const url = slug.toLowerCase().slice(0, 4) === 'http' ? slug : `/${slug}` const bookmark = async (evt) => { evt.stopPropagation() setLoadingStatus([true, 'Contacting backend']) let title = name const [status] = await backend.createBookmark({ type, title, url }) if (status === 201) { setLoadingStatus([true, 'Bookmark created', true, true]) setModal(false) } else setLoadingStatus([ true, 'Something unexpected happened, failed to create a bookmark', true, false, ]) } return (

New bookmark

) }