93 lines
2.9 KiB
JavaScript
93 lines
2.9 KiB
JavaScript
/**
|
|
* Listings Service - Higher-level API for listing operations
|
|
* Wraps directus.js with business logic and convenience methods
|
|
*/
|
|
|
|
import { directus } from './directus.js'
|
|
import { categoriesService } from './categories.js'
|
|
|
|
class ListingsService {
|
|
async getListingsWithFilters(filters = {}) {
|
|
const directusFilter = { status: { _eq: 'published' } }
|
|
|
|
if (filters.category) {
|
|
if (filters.subcategory) {
|
|
directusFilter.category = { slug: { _eq: filters.subcategory } }
|
|
} else {
|
|
const all = await categoriesService.getAll()
|
|
const parent = all.find(c => c.slug === filters.category && !c.parent)
|
|
if (parent) {
|
|
const childSlugs = all
|
|
.filter(c => (c.parent?.id || c.parent) === parent.id)
|
|
.map(c => c.slug)
|
|
directusFilter.category = { slug: { _in: [filters.category, ...childSlugs] } }
|
|
} else {
|
|
directusFilter.category = { slug: { _eq: filters.category } }
|
|
}
|
|
}
|
|
}
|
|
|
|
if (filters.location) {
|
|
directusFilter.location = { _eq: filters.location }
|
|
}
|
|
|
|
if (filters.minPrice != null) {
|
|
directusFilter.price = directusFilter.price || {}
|
|
directusFilter.price._gte = filters.minPrice
|
|
}
|
|
|
|
if (filters.maxPrice != null) {
|
|
directusFilter.price = directusFilter.price || {}
|
|
directusFilter.price._lte = filters.maxPrice
|
|
}
|
|
|
|
if (filters.condition) {
|
|
directusFilter.condition = { _eq: filters.condition }
|
|
}
|
|
|
|
if (filters.shipping === true) {
|
|
directusFilter.shipping = { _eq: true }
|
|
}
|
|
|
|
if (filters.priceType) {
|
|
directusFilter.price_type = { _eq: filters.priceType }
|
|
}
|
|
|
|
const sortMap = {
|
|
'newest': ['-date_created'],
|
|
'oldest': ['date_created'],
|
|
'price_asc': ['price'],
|
|
'price_desc': ['-price'],
|
|
'views': ['-views']
|
|
}
|
|
|
|
return directus.getListings({
|
|
filter: directusFilter,
|
|
sort: sortMap[filters.sort] || ['-date_created'],
|
|
limit: filters.limit || 20,
|
|
page: filters.page || 1,
|
|
search: filters.search
|
|
})
|
|
}
|
|
|
|
isPaidAndActive(listing) {
|
|
return listing.paid_at
|
|
&& listing.expires_at
|
|
&& new Date(listing.expires_at) > new Date()
|
|
}
|
|
|
|
canTogglePublish(listing) {
|
|
return listing.status === 'published' || (listing.status === 'draft' && this.isPaidAndActive(listing))
|
|
}
|
|
|
|
isSoftDeleted(listing) {
|
|
return listing.status === 'deleted'
|
|
}
|
|
|
|
canPublicView(listing) {
|
|
return listing.status === 'published'
|
|
}
|
|
}
|
|
|
|
export const listingsService = new ListingsService()
|