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:
Alireza Hassani
2026-08-03 00:06:44 +03:30
co-authored by Cursor
parent 66004a0fba
commit 672091d1f5
113 changed files with 4154 additions and 1451 deletions
+24 -9
View File
@@ -1,8 +1,10 @@
import { useEffect, useState } from 'react'
import { Link, useParams } from 'react-router-dom'
import { CalendarDays, User } from 'lucide-react'
import { useLocale } from '@meshkee/dashboard-ui'
import { Breadcrumbs } from '../components/Breadcrumbs'
import { BlogCommentsSection } from '../components/BlogCommentsSection'
import { useT } from '../i18n/useT'
import { ApiError } from '../lib/api'
import {
formatBlogAuthor,
@@ -16,6 +18,8 @@ import pageStyles from '../components/PageContent.module.css'
import styles from './BlogDetailsPage.module.css'
export function BlogDetailsPage() {
const t = useT()
const { locale } = useLocale()
const { id } = useParams()
const [blog, setBlog] = useState<BlogDetail | null>(null)
const [isLoading, setIsLoading] = useState(true)
@@ -38,7 +42,7 @@ export function BlogDetailsPage() {
if (err instanceof ApiError) {
setError(err.message)
} else {
setError('Unable to load blog post.')
setError(t('blog.details.errorLoad'))
}
setBlog(null)
} finally {
@@ -53,7 +57,7 @@ export function BlogDetailsPage() {
if (isLoading) {
return (
<main className={pageStyles.content}>
<p className={styles.status}>Loading blog post...</p>
<p className={styles.status}>{t('blog.details.loading')}</p>
</main>
)
}
@@ -61,17 +65,28 @@ export function BlogDetailsPage() {
if (error || !blog || !id) {
return (
<main className={pageStyles.content}>
<p className={styles.error}>{error || 'Blog post not found.'}</p>
<p className={styles.error}>{error || t('blog.details.notFound')}</p>
<Link to="/blog/list" className={styles.backLink}>
Back to My Blogs
{t('blog.details.back')}
</Link>
</main>
)
}
const displayDate = formatBlogDate(blog.publishedAt ?? blog.createdAt)
const typeLabel =
BLOG_TYPE_OPTIONS.find((option) => option.value === blog.type)?.label ?? blog.type
const displayDate = formatBlogDate(
blog.publishedAt ?? blog.createdAt,
locale === 'fa' ? 'fa' : 'en',
)
const typeValue = BLOG_TYPE_OPTIONS.find((option) => option.value === blog.type)?.value
const typeLabel = typeValue
? t(
typeValue === 'news'
? 'blog.form.type.news'
: typeValue === 'article'
? 'blog.form.type.article'
: 'blog.form.type.blog',
)
: blog.type
const titleLocale = textLocaleAttrs(blog.title)
const abstractLocale = textLocaleAttrs(blog.abstract)
const contentLocale = textLocaleAttrs(
@@ -155,13 +170,13 @@ export function BlogDetailsPage() {
/>
) : (
<p className={styles.content} lang="en" dir="ltr">
No content yet.
{t('blog.details.noContent')}
</p>
)}
<div className={styles.authorRow}>
<User size={16} />
<span className={styles.authorLabel}>Author</span>
<span className={styles.authorLabel}>{t('blog.details.author')}</span>
<span className={styles.authorName}>{formatBlogAuthor(blog.author)}</span>
</div>
</div>