feat(articles): تاریخ انتشار خودکار توسط سرور در لحظهٔ انتشار

problem: ستون date نمایشی دستی پر می‌شد و از لحظهٔ واقعی انتشار جدا می‌افتاد.
- ستون published_at (timestamptz) + مهاجرت idempotent؛ مقالات منتشرشدهٔ قدیمی
  از updated_at عقب‌گرد پر می‌شوند
- _apply_publish_timestamp در PUT و PATCH: در گذار draft→published مقدار
  published_at ثبت می‌شود؛ ستون date/date_en فقط اگر خالی باشد از آن پر می‌شود
  (تاریخ درستِ موجود را خراب نمی‌کند)
- پنل: فیلد «تاریخ انتشار» فقط‌خواندنی شد (نمایش شمسی؛ پیش از انتشار: «در لحظهٔ
  انتشار ثبت می‌شود»)
- ArticleOut: published_at نمایان شد
This commit is contained in:
aramesh-site deploy
2026-10-25 20:03:23 +00:00
parent aa13d41b6d
commit fb8b8bbd61
5 changed files with 82 additions and 28 deletions
+19 -5
View File
@@ -10,6 +10,7 @@ import { ArticleEditor } from '../components/admin/ArticleEditor'
import { SeoChecklist } from '../components/admin/SeoChecklist'
import { ImageField } from '../components/admin/ImageField'
import { JalaliDatePicker } from '../components/admin/JalaliDatePicker'
import { formatJalali } from '../utils/date'
import { CategorySelect, LuxeTagsSelect } from '../components/admin/LuxeSelect'
import type { CategoryOption } from '../components/admin/LuxeSelect'
import { ARTICLE_CATEGORIES } from './entities'
@@ -391,6 +392,13 @@ export function ArticleWritePage() {
</Link>
<div className="flex items-center gap-4">
<Link
to="/admin/articles"
data-admin-link
className="border border-ivory/20 px-3 py-1.5 text-xs font-light text-ivory/70 transition-colors duration-200 hover:border-copper hover:text-copper"
>
مقاله‌ها
</Link>
<button
type="button"
onClick={() => {
@@ -443,7 +451,7 @@ export function ArticleWritePage() {
</button>
)}
<Link
to={`${editLang === 'en' ? '/en' : ''}/blog/${editLang === 'en' ? draft.slug_en || draft.slug : draft.slug}`}
to={`${editLang === 'en' ? '/en' : ''}/blog/${encodeURIComponent(editLang === 'en' ? draft.slug_en || draft.slug : draft.slug)}`}
data-admin-link
className="flex items-center gap-1.5 border border-ivory/20 px-4 py-2 text-xs font-light text-ivory/70 transition-colors hover:border-copper hover:text-copper"
>
@@ -501,6 +509,7 @@ export function ArticleWritePage() {
<div className="mt-8">
<ImageField
label="تصویر شاخص مقاله"
requireEditMode={false}
value={draft.image}
alt={imageAltField.value}
altFallback={imageAltFallback}
@@ -673,12 +682,17 @@ export function ArticleWritePage() {
<div className="grid grid-cols-1 gap-5 lg:grid-cols-3">
<div>
<label htmlFor="article-date" className="text-xs font-light text-ivory/50">تاریخ انتشار (شمسی)</label>
<label htmlFor="article-date" className="text-xs font-light text-ivory/50">
تاریخ انتشار (خودکار)
</label>
<div className="mt-2">
<JalaliDatePicker
{/* تاریخ را سرور در لحظهٔ انتشار ثبت می‌کند — دستی قابل تغییر نیست */}
<input
id="article-date"
value={draft.date ?? ''}
onChange={(isoDate) => queueSave({ date: isoDate })}
type="text"
disabled
value={draft.date ? formatJalali(draft.date) : 'در لحظهٔ انتشار ثبت می‌شود'}
className="w-full text-sm font-light opacity-70"
/>
</div>
</div>