import { h, Component } from 'preact'; export class ReadingList extends Component { state = { readingListItems: [], query: '', index: '', availableTags: [], selectedTags: [], itemsLoaded: false, archiving: false, statusView: document.getElementById('reading-list').dataset.view, }; componentDidMount() { const algoliaId = document.querySelector("meta[name='algolia-public-id']") .content; const algoliaKey = document.getElementById('reading-list').dataset.algolia; const env = document.querySelector("meta[name='environment']").content; const client = algoliasearch(algoliaId, algoliaKey); const index = client.initIndex(`SecuredReactions_${env}`); const t = this; index .search('', { hitsPerPage: 64, filters: `status:${t.state.statusView}` }) .then(content => { t.setState({ readingListItems: content.hits, index, itemsLoaded: true, }); }); const waitingOnUser = setInterval(() => { if (window.currentUser) { t.setState({ availableTags: window.currentUser.followed_tag_names }); clearInterval(waitingOnUser); } }, 1); } handleTyping = e => { const query = e.target.value; const { selectedTags, statusView } = this.state; this.listSearch(query, selectedTags, statusView); }; toggleTag = (e, tag) => { e.preventDefault(); const { query, selectedTags, statusView } = this.state; const newTags = selectedTags; if (newTags.indexOf(tag) === -1) { newTags.push(tag); } else { newTags.splice(newTags.indexOf(tag), 1); } this.setState({ selectedTags: newTags }); this.listSearch(query, newTags, statusView); }; toggleStatusView = e => { e.preventDefault(); const { statusView, query, selectedTags } = this.state; if (statusView === 'valid') { this.setState({ statusView: 'archived' }); this.listSearch(query, selectedTags, 'archived'); window.history.replaceState(null, null, '/readinglist/archive'); } else { this.setState({ statusView: 'valid' }); this.listSearch(query, selectedTags, 'valid'); window.history.replaceState(null, null, '/readinglist'); } }; archive = (e, item) => { e.preventDefault(); const { statusView, readingListItems } = this.state; const t = this; window.fetch(`/reading_list_items/${item.id}`, { method: 'PUT', headers: { 'X-CSRF-Token': window.csrfToken, 'Content-Type': 'application/json', }, body: JSON.stringify({ current_status: statusView }), credentials: 'same-origin', }); const newItems = readingListItems; newItems.splice(newItems.indexOf(item), 1); t.setState({ archiving: true, readingListItems: newItems }); setTimeout(() => { t.setState({ archiving: false }); }, 1800); }; listSearch(query, tags, statusView) { const t = this; const { index } = this.state; const filters = { hitsPerPage: 256, filters: `status:${statusView}` }; if (tags.length > 0) { filters.tagFilters = tags; } index.search(query, filters).then(content => { t.setState({ readingListItems: content.hits, query }); }); } render() { const { readingListItems, availableTags, selectedTags, itemsLoaded, query, statusView, archiving, } = this.state; let allItems = readingListItems.map(item => (
{item.searchable_reactable_title}
Profile Pic {item.reactable_user.name}・{item.reactable_published_date}・ {item.reading_time} min read・ {item.reactable_tags.map(tag => ( #{tag} ))}
)); if (readingListItems.length === 0 && itemsLoaded) { if (statusView === 'valid') { allItems = (

{selectedTags.length === 0 && query.length === 0 ? 'Your Reading List is Lonely' : 'Nothing with this filter 🤔'}

Hit the SAVE or Bookmark 🔖 to start your Collection

); } else { allItems = (

{selectedTags.length === 0 && query.length === 0 ? 'Your Archive List is Lonely' : 'Nothing with this filter 🤔'}

); } } const allTags = availableTags.map(tag => ( -1 ? 'selected' : '' }`} href={`/t/${tag}`} data-no-instant onClick={e => this.toggleTag(e, tag)} > #{tag} )); const snackBar = archiving ? (
{statusView === 'valid' ? 'Archiving' : 'Unarchiving'} (async)
) : ( '' ); return (
{allTags}
this.toggleStatusView(e)} data-no-instant > {statusView === 'valid' ? 'View Archive' : 'View Reading List'}
{statusView === 'valid' ? 'Reading List' : 'Archive'}
{allItems}
{snackBar}
); } }