docbrown/app/javascript/listings/listingDashboard.jsx
Mario See fda048dc12 Listing Drafts and Deletion (#3540)
* wip init handle draft class and styling

* add draft button

* start splitting up listing row into multile files

* separate tag links

* split location

* fix location

* separate listing row action buttons

* update listing row proptypes to describe listing object

* contact via connect to jsx

* fix default checked

* init draft creation and first publish charge

* fix first publish logic and credit charging

* handle drafts in dashboard filtering

* adjust isDraft bool statement

* hide drafts from main listings feed

* fix expired and draft bools in listing row

* adjust create listing org credits

* internally handle drafts

* adjust listing row

* break down update method

* remove unnecessary logic and shorten lines

* fix logic again woops

* convert input hidden value + submit into one form button submit with corresponding name and value

also adds clear message that drafts do not cost credits

* handle insufficient org credits on first publish

- uses user credits to publish
- similar to bump implementation

* fix sorting for personal and all orgs

* space out some elements

* don't spend original users credit for them

* add delete buttons and delete_confirm and destroy methods

* remove notification removal since listings dont trigger notifications

* move draft message and add draft_params to tests

* Update classified_listings_controller.rb

* update tests

* update snapshot

* add del tests

* add guard preventing free draft publish

* fix draft filter

* update from master and resolve merge conflict in listing preact

* Revert "update from master and resolve merge conflict in listing preact"

This reverts commit 0a34fccf334a2ca0902644b486cb26ead6bef664.

* update column spec

instead of setting and saving

* separate two expectations into their own tests

* split more tests into single expectations

* change to unless bumped_at? instead of if nil

* Fix listing draft edge cases and styling

* Add title tags to listings pages
2019-09-01 13:54:54 -04:00

186 lines
5.5 KiB
JavaScript

import { h, Component } from 'preact';
import { ListingRow } from './dashboard/listingRow';
export class ListingDashboard extends Component {
state = {
listings: [],
orgListings: [],
orgs: [],
userCredits: 0,
selectedListings: 'user',
filter: 'All',
sort: 'created_at',
};
componentDidMount() {
const t = this;
const container = document.getElementById('classifieds-listings-dashboard');
let listings = [];
let orgs = [];
let orgListings = [];
listings = JSON.parse(container.dataset.listings).sort((a,b) => (a.created_at > b.created_at) ? -1 : 1);
orgs = JSON.parse(container.dataset.orgs);
orgListings = JSON.parse(container.dataset.orglistings);
const userCredits = container.dataset.usercredits;
t.setState({ listings, orgListings, orgs, userCredits });
}
render() {
const {
listings,
orgListings,
userCredits,
orgs,
selectedListings,
filter,
sort
} = this.state;
const isExpired = (listing) => listing.bumped_at && (!listing.published) ? ((Date.now() - new Date(listing.bumped_at.toString()).getTime()) / (1000 * 60 * 60 * 24)) > 30 : false;
const isDraft = (listing) => listing.bumped_at ? !isExpired(listing) && (!listing.published) : true;
const filterListings = (listingsToFilter, selectedFilter) => {
if (selectedFilter === "Draft") {
return listingsToFilter.filter(listing => isDraft(listing))
} if (selectedFilter === "Expired") {
return listingsToFilter.filter(listing => isExpired(listing))
} if (selectedFilter === "Active") {
return listingsToFilter.filter(listing => listing.published === true)
}
return listingsToFilter
}
const customSort = (a,b) => {
if (a[sort] === null) {
return 1
}
if (b[sort] === null) {
return -1
}
if (a[sort] > b[sort]) {
return -1
}
return 1
}
const showListings = (selected, userListings, organizationListings, selectedFilter) => {
let displayedListings;
if (selected === 'user') {
displayedListings = filterListings(userListings, selectedFilter).sort(customSort)
return displayedListings.map(listing => <ListingRow listing={listing} />)
}
displayedListings = filterListings(organizationListings, selectedFilter).sort(customSort)
return displayedListings.map(listing =>
listing.organization_id === selected ? (
<ListingRow listing={listing} />
) : (
''
),
);
};
const filters = ["All", "Active", "Draft", "Expired"];
const filterButtons = filters.map(f => (
<span
onClick={(event) => {this.setState( {filter:event.target.textContent} )}}
className={`rounded-btn ${filter === f ? 'active' : ''}`}
role="button"
tabIndex="0">
{f}
</span>
))
const sortingDropdown = (
<div class="dashboard-listings-actions">
<div className="listings-dashboard-filter-buttons">
{filterButtons}
</div>
<select onChange={(event) => {this.setState({sort: event.target.value})}}>
<option value="created_at" selected="selected">Recently Created</option>
<option value="bumped_at">Recently Bumped</option>
</select>
</div>
);
const orgButtons = orgs.map(org => (
<span
onClick={() => this.setState({ selectedListings: org.id })}
className={`rounded-btn ${selectedListings === org.id ? 'active' : ''}`}
role="button"
tabIndex="0"
>
{org.name}
</span>
));
const listingLength = (selected, userListings, organizationListings) => {
return selected === 'user' ? (
<h4>
Listings Made:
{' '}
{userListings.length}
</h4>
) : (
<h4>
Listings Made:
{' '}
{
organizationListings.filter(
listing => listing.organization_id === selected,
).length
}
</h4>
);
};
const creditCount = (selected, userCreds, organizations) => {
return selected === 'user' ? (
<h4>
Credits Available:
{' '}
{userCreds}
</h4>
) : (
<h4>
Credits Available:
{' '}
{organizations.find(org => org.id === selected).unspent_credits_count}
</h4>
);
};
return (
<div className="dashboard-listings-container">
<span
onClick={() => this.setState({ selectedListings: 'user' })}
className={`rounded-btn ${
selectedListings === 'user' ? 'active' : ''
}`}
role="button"
tabIndex="0"
>
Personal
</span>
{orgButtons}
<div className="dashboard-listings-header-wrapper">
<div className="dashboard-listings-header">
<h3>Listings</h3>
{listingLength(selectedListings, listings, orgListings)}
<a href="/listings/new">Create a Listing</a>
</div>
<div className="dashboard-listings-header">
<h3>Credits</h3>
{creditCount(selectedListings, userCredits, orgs)}
<a href="/credits/purchase" data-no-instant>
Buy Credits
</a>
</div>
</div>
{sortingDropdown}
<div className="dashboard-listings-view">
{showListings(selectedListings, listings, orgListings, filter)}
</div>
</div>
);
}
}