Initial
This commit is contained in:
139
DirectoryListingItem.js
Normal file
139
DirectoryListingItem.js
Normal file
@ -0,0 +1,139 @@
|
||||
import { useState, useEffect } from '@wordpress/element';
|
||||
|
||||
function isOpenNow(operatingHours = []) {
|
||||
if (!operatingHours.length) return null;
|
||||
|
||||
const now = new Date();
|
||||
const dayNames = ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'];
|
||||
const today = dayNames[now.getDay()];
|
||||
const todaysHours = operatingHours.filter(h => h.day === today);
|
||||
if (!todaysHours.length) return null;
|
||||
|
||||
for (let h of todaysHours) {
|
||||
if (h.closed) continue;
|
||||
if (h.open_24_hours) return true;
|
||||
if (!h.opening_time || !h.closing_time) continue;
|
||||
|
||||
const [openH, openM] = h.opening_time.split(':').map(Number);
|
||||
const [closeH, closeM] = h.closing_time.split(':').map(Number);
|
||||
|
||||
const openDate = new Date(now);
|
||||
openDate.setHours(openH, openM, 0, 0);
|
||||
const closeDate = new Date(now);
|
||||
closeDate.setHours(closeH, closeM, 0, 0);
|
||||
|
||||
if (now >= openDate && now <= closeDate) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
export default function DirectoryListingItem({
|
||||
post,
|
||||
imageSrc = '',
|
||||
imageMediaID = null,
|
||||
restRoot = '', // must pass multisite REST root from View.js
|
||||
onQuickView,
|
||||
style = 'hero',
|
||||
displayCategoryTitle = '',
|
||||
displayCategoryURL = '#',
|
||||
operatingHours = [],
|
||||
titleTag,
|
||||
postDescription,
|
||||
}) {
|
||||
const [finalImageSrc, setFinalImageSrc] = useState(imageSrc);
|
||||
const [isOpen, setIsOpen] = useState(null);
|
||||
const TitleTag = titleTag || 'h3';
|
||||
|
||||
useEffect(() => {
|
||||
setIsOpen(isOpenNow(operatingHours));
|
||||
}, [operatingHours]);
|
||||
|
||||
// Fetch image URL if imageMediaID is provided
|
||||
useEffect(() => {
|
||||
if (!imageMediaID) return;
|
||||
if (!restRoot) {
|
||||
console.error('DirectoryListingItem: restRoot is required for multisite media fetch.');
|
||||
return;
|
||||
}
|
||||
|
||||
let isMounted = true;
|
||||
const url = `${restRoot}wp/v2/media/${imageMediaID}`;
|
||||
console.log('Fetching media URL:', url);
|
||||
|
||||
fetch(url)
|
||||
.then(res => {
|
||||
if (!res.ok) throw new Error(`Media fetch failed: ${res.status}`);
|
||||
return res.json();
|
||||
})
|
||||
.then(data => {
|
||||
if (isMounted && data?.source_url) {
|
||||
setFinalImageSrc(data.source_url);
|
||||
}
|
||||
})
|
||||
.catch(err => console.error('Failed to fetch media:', err));
|
||||
|
||||
return () => { isMounted = false; };
|
||||
}, [imageMediaID, restRoot]);
|
||||
|
||||
const heroStyle = style === 'hero' && finalImageSrc ? { backgroundImage: `url(${finalImageSrc})` } : {};
|
||||
|
||||
const content = (
|
||||
<>
|
||||
{style !== 'hero' && (
|
||||
<div className="listing-left">
|
||||
{finalImageSrc ? (
|
||||
<img src={finalImageSrc} alt={post.title?.rendered || 'Post image'} />
|
||||
) : (
|
||||
<div className="placeholder-image">No Image</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="listing-right">
|
||||
{displayCategoryTitle && (
|
||||
<a
|
||||
className="listing-category-button"
|
||||
href={displayCategoryURL}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
{displayCategoryTitle}
|
||||
</a>
|
||||
)}
|
||||
|
||||
<TitleTag>
|
||||
{post.title?.rendered ? (
|
||||
<a href={post.link} dangerouslySetInnerHTML={{ __html: post.title.rendered }} />
|
||||
) : (
|
||||
<span>No title</span>
|
||||
)}
|
||||
</TitleTag>
|
||||
|
||||
{postDescription ? (
|
||||
<p dangerouslySetInnerHTML={{ __html: postDescription }} />
|
||||
) : null}
|
||||
|
||||
{isOpen !== null && (
|
||||
<span className={`open-status ${isOpen ? 'open' : 'closed'}`}>
|
||||
{isOpen ? 'Open' : 'Closed'}
|
||||
</span>
|
||||
)}
|
||||
|
||||
<button className="quickview-button" onClick={() => onQuickView(post)}>
|
||||
QuickView
|
||||
</button>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
||||
return style === 'hero' ? (
|
||||
<a href={post.link} className={`directory-listing ${style}`} style={heroStyle}>
|
||||
{content}
|
||||
</a>
|
||||
) : (
|
||||
<article className={`directory-listing ${style}`} style={heroStyle}>
|
||||
{content}
|
||||
</article>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user