Polish business FA layout and wire special-group keys plus SSL sync.
RTL carousels/FABs, special key+title fields, slider gallery fixes, and dashboard SSL sync agent for super-admin. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
co-authored by
Cursor
parent
66004a0fba
commit
672091d1f5
@@ -1,9 +1,11 @@
|
||||
import { useEffect, useMemo, useState } from 'react'
|
||||
import { Link, useParams } from 'react-router-dom'
|
||||
import { CalendarDays } from 'lucide-react'
|
||||
import { useLocale } from '@meshkee/dashboard-ui'
|
||||
import { Breadcrumbs } from '../components/Breadcrumbs'
|
||||
import { ImageLightbox } from '../components/ImageLightbox'
|
||||
import { PortfolioCommentsSection } from '../components/PortfolioCommentsSection'
|
||||
import { useT } from '../i18n/useT'
|
||||
import { ApiError } from '../lib/api'
|
||||
import { formatPortfolioDate, getPortfolioDetail } from '../services/portfolioService'
|
||||
import type { PortfolioDetail } from '../types/portfolio'
|
||||
@@ -11,6 +13,8 @@ import pageStyles from '../components/PageContent.module.css'
|
||||
import styles from './PortfolioDetailsPage.module.css'
|
||||
|
||||
export function PortfolioDetailsPage() {
|
||||
const t = useT()
|
||||
const { locale } = useLocale()
|
||||
const { id } = useParams()
|
||||
const [portfolio, setPortfolio] = useState<PortfolioDetail | null>(null)
|
||||
const [isLoading, setIsLoading] = useState(true)
|
||||
@@ -35,7 +39,7 @@ export function PortfolioDetailsPage() {
|
||||
if (err instanceof ApiError) {
|
||||
setError(err.message)
|
||||
} else {
|
||||
setError('Unable to load portfolio.')
|
||||
setError(t('portfolio.details.errorLoad'))
|
||||
}
|
||||
setPortfolio(null)
|
||||
} finally {
|
||||
@@ -60,7 +64,7 @@ export function PortfolioDetailsPage() {
|
||||
if (isLoading) {
|
||||
return (
|
||||
<main className={pageStyles.content}>
|
||||
<p className={styles.status}>Loading portfolio...</p>
|
||||
<p className={styles.status}>{t('portfolio.details.loading')}</p>
|
||||
</main>
|
||||
)
|
||||
}
|
||||
@@ -68,15 +72,18 @@ export function PortfolioDetailsPage() {
|
||||
if (error || !portfolio || !id) {
|
||||
return (
|
||||
<main className={pageStyles.content}>
|
||||
<p className={styles.error}>{error || 'Portfolio not found.'}</p>
|
||||
<p className={styles.error}>{error || t('portfolio.details.notFound')}</p>
|
||||
<Link to="/portfolios/list" className={styles.backLink}>
|
||||
Back to My Portfolios
|
||||
{t('portfolio.details.back')}
|
||||
</Link>
|
||||
</main>
|
||||
)
|
||||
}
|
||||
|
||||
const displayDate = formatPortfolioDate(portfolio.publishedAt ?? portfolio.createdAt)
|
||||
const displayDate = formatPortfolioDate(
|
||||
portfolio.publishedAt ?? portfolio.createdAt,
|
||||
locale === 'fa' ? 'fa' : 'en',
|
||||
)
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -145,16 +152,16 @@ export function PortfolioDetailsPage() {
|
||||
dangerouslySetInnerHTML={{ __html: portfolio.mainTextHtml }}
|
||||
/>
|
||||
) : (
|
||||
<p className={styles.content}>No content yet.</p>
|
||||
<p className={styles.content}>{t('portfolio.details.noContent')}</p>
|
||||
)}
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
|
||||
{galleryImages.length > 0 && (
|
||||
<section className={styles.galleryBand} aria-label="Portfolio gallery">
|
||||
<section className={styles.galleryBand} aria-label={t('portfolio.details.gallery')}>
|
||||
<div className={styles.galleryInner}>
|
||||
<h3 className={styles.galleryTitle}>Gallery</h3>
|
||||
<h3 className={styles.galleryTitle}>{t('portfolio.details.gallery')}</h3>
|
||||
<div className={styles.galleryGrid}>
|
||||
{galleryImages.map((src, index) => (
|
||||
<button
|
||||
@@ -162,7 +169,7 @@ export function PortfolioDetailsPage() {
|
||||
type="button"
|
||||
className={styles.galleryItem}
|
||||
onClick={() => openLightbox(index)}
|
||||
aria-label={`View gallery image ${index + 1}`}
|
||||
aria-label={t('portfolio.details.galleryImage', { index: index + 1 })}
|
||||
>
|
||||
<img src={src} alt={`${portfolio.title} gallery ${index + 1}`} loading="lazy" />
|
||||
</button>
|
||||
|
||||
Reference in New Issue
Block a user