import { h, Component } from 'preact';
import { SingleListing } from './singleListing';
export class Listings extends Component {
state = {
listings: [],
query: '',
tags: [],
index: null,
category: '',
allCategories: [],
initialFetch: true,
currentUserId: null,
openedListing: null,
slug: null,
page: 0,
showNextPageButt: false,
};
componentWillMount() {
const params = this.getQueryParams();
const t = this;
const algoliaId = document.querySelector("meta[name='algolia-public-id']")
.content;
const algoliaKey = document.querySelector("meta[name='algolia-public-key']")
.content;
const env = document.querySelector("meta[name='environment']").content;
const client = algoliasearch(algoliaId, algoliaKey);
const index = client.initIndex(`ClassifiedListing_${env}`);
const container = document.getElementById('classifieds-index-container')
const category = container.dataset.category || ''
const allCategories = JSON.parse(container.dataset.allcategories || []);
let tags = [];
if (params.t) {
tags = params.t.split(',')
}
const query = params.q || ''
let listings = [];
if (tags.length === 0 && query === '') {
listings = JSON.parse(container.dataset.listings)
}
let openedListing = null;
let slug = null;
if (container.dataset.displayedlisting) {
openedListing = JSON.parse(container.dataset.displayedlisting);
slug = openedListing.slug;
document.body.classList.add('modal-open');
}
t.setState({query, tags, index, category, allCategories, listings, openedListing, slug });
t.listingSearch(query, tags, category, slug);
t.setUser()
document.body.addEventListener('keydown', t.handleKeyDown)
}
componentDidUpdate() {
this.triggerMasonry()
}
componentWillUnmount() {
document.body.removeEventListener('keydown', this.handleKeyDown)
}
addTag = (e, tag) => {
e.preventDefault();
const { query, tags, category } = this.state;
const newTags = tags;
if (newTags.indexOf(tag) === -1) {
newTags.push(tag)
}
this.setState({tags: newTags, page: 0, listings: []})
this.listingSearch(query, newTags, category, null)
window.scroll(0,0)
}
removeTag = (e, tag) => {
e.preventDefault();
const { query, tags, category } = this.state;
const newTags = tags;
const index = newTags.indexOf(tag);
if (newTags.indexOf(tag) > -1) {
newTags.splice(index, 1);
}
this.setState({tags: newTags, page: 0, listings: []})
this.listingSearch(query, newTags, category, null)
}
selectCategory = (e, cat) => {
e.preventDefault();
const { query, tags } = this.state;
this.setState({category: cat, page: 0, listings: []})
this.listingSearch(query, tags, cat, null)
}
handleKeyDown = (e) => {
// Enable Escape key to close an open listing.
if (this.openedListing !== null && e.key === 'Escape') {
this.handleCloseModal()
}
}
handleCloseModal = (e) => {
const { query, tags, category } = this.state;
this.setState({openedListing: null, page: 0})
this.setLocation(query, tags, category, null);
document.body.classList.remove('modal-open');
}
handleOpenModal = (e, listing) => {
e.preventDefault();
this.setState({openedListing: listing});
window.history.replaceState(null, null, `/listings/${listing.category}/${listing.slug}`);
this.setLocation(null, null, listing.category, listing.slug);
document.body.classList.add('modal-open');
}
handleQuery = e => {
const { tags, category } = this.state;
this.setState({query: e.target.value, page: 0, listings: []})
this.listingSearch(e.target.value, tags, category, null)
}
clearQuery = () => {
const { tags, category } = this.state;
document.getElementById('listings-search').value = '';
this.setState({query: '', page: 0, listings: []});
this.listingSearch('', tags, category, null);
}
getQueryParams = () => {
let qs = document.location.search;
qs = qs.split('+').join(' ');
const params = {};
let tokens;
const re = /[?&]?([^=]+)=([^&]*)/g;
// eslint-disable-next-line no-cond-assign
while (tokens = re.exec(qs)) {
params[decodeURIComponent(tokens[1])] = decodeURIComponent(tokens[2]);
}
return params;
}
loadNextPage = () => {
const { query, tags, category, slug, page } = this.state;
this.setState({page: page + 1});
this.listingSearch(query, tags, category, slug);
}
setUser = () => {
const t = this;
setTimeout(function() {
if (window.currentUser && t.state.currentUserId === null) {
t.setState({currentUserId: window.currentUser.id });
}
}, 300)
setTimeout(function() {
if (window.currentUser && t.state.currentUserId === null) {
t.setState({currentUserId: window.currentUser.id });
}
}, 1000)
}
triggerMasonry = () => {
resizeAllMasonryItems();
setTimeout(function() {
resizeAllMasonryItems();
}, 1)
setTimeout(function() {
resizeAllMasonryItems();
}, 3)
}
setLocation = (query, tags, category, slug) => {
let newLocation = ''
if (slug) {
newLocation = `/listings/${category}/${slug}`;
} else if (query.length > 0 && tags.length > 0) {
newLocation = `/listings/${category}?q=${query}&t=${tags}`;
} else if (query.length > 0){
newLocation = `/listings/${category}?q=${query}`;
} else if (tags.length > 0) {
newLocation = `/listings/${category}?t=${tags}`;
} else if (category.length > 0) {
newLocation = `/listings/${category}`;
} else {
newLocation = '/listings'
}
window.history.replaceState(null, null, newLocation);
}
listingSearch(query, tags, category, slug) {
const t = this;
const { index, page, listings } = t.state;
const filterObject = {tagFilters: tags, hitsPerPage: 75, page}
if (category.length > 0) {
filterObject.filters = `category:${category}`
}
index.search(query, filterObject)
.then(function searchDone(content) {
const fullListings = listings;
content.hits.forEach(listing => {
if (!listings.map(l => (l.id)).includes(listing.id)) {
fullListings.push(listing)
}
});
t.setState({listings: fullListings, initialFetch: false, showNextPageButt: content.hits.length === 75});
});
this.setLocation(query, tags, category, slug);
}
render() {
const { listings, query, tags, category, allCategories, currentUserId, openedListing, showNextPageButt, initialFetch } = this.state;
const allListings = listings.map(listing => (