From 5cf7b51686d51d203f1c16787ad02ab2cb7f876d Mon Sep 17 00:00:00 2001 From: aramesh-site deploy Date: Mon, 28 Sep 2026 09:58:49 +0000 Subject: [PATCH] =?UTF-8?q?revert(ui):=20=D8=A8=D8=A7=D8=B2=DA=AF=D8=B1?= =?UTF-8?q?=D8=AF=D8=A7=D9=86=DB=8C=20=D8=AF=DA=A9=D9=85=D9=87=E2=80=8C?= =?UTF-8?q?=D9=87=D8=A7=DB=8C=20=D9=81=D8=B1=D9=85=20=D8=AA=D9=85=D8=A7?= =?UTF-8?q?=D8=B3=D8=8C=20=D8=AE=D8=A8=D8=B1=D9=86=D8=A7=D9=85=D9=87=D8=8C?= =?UTF-8?q?=20=D9=85=D9=82=D8=A7=D9=84=D8=A7=D8=AA=D8=8C=20=D8=AF=D8=A7?= =?UTF-8?q?=D8=B3=D8=AA=D8=A7=D9=86=20=D9=88=20=D8=B5=D9=81=D8=AD=D9=87?= =?UTF-8?q?=D9=94=20=D9=85=D9=82=D8=A7=D9=84=D9=87=20=D8=A8=D9=87=20=D8=B7?= =?UTF-8?q?=D8=B1=D8=AD=20=D9=82=D8=A8=D9=84=DB=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit همه جای Button/PremiumButton جابه‌جا شده بودند؛ به Button/ButtonLink قبلی برگشتند (کامپوننت Button قبلاً بازگردانده شده بود). --- frontend/src/components/ContactSection.tsx | 42 ++++++--------- frontend/src/components/home/Articles.tsx | 9 ++-- frontend/src/components/home/Newsletter.tsx | 33 ++++-------- frontend/src/components/home/Story.tsx | 9 ++-- frontend/src/pages/ArticleDetail.tsx | 59 ++++++--------------- 5 files changed, 53 insertions(+), 99 deletions(-) diff --git a/frontend/src/components/ContactSection.tsx b/frontend/src/components/ContactSection.tsx index 0053917..4c5952e 100644 --- a/frontend/src/components/ContactSection.tsx +++ b/frontend/src/components/ContactSection.tsx @@ -1,21 +1,20 @@ import React, { useState } from 'react' -import { CheckCircle2Icon, MailIcon, MapPinIcon, PhoneIcon } from 'lucide-react' +import { CheckCircle2Icon, MailIcon, MapPinIcon, PhoneIcon, SendIcon } from 'lucide-react' import Swal from 'sweetalert2' import { Reveal } from './Reveal' -import { PremiumButton } from './PremiumButton' +import { Button } from './Button' import { useSite } from '../api' import { useLang } from '../i18n/lang' import { useFieldSaver } from '../admin/AdminContext' import { InlineEdit } from './admin/InlineEdit' import { SingletonPill } from '../admin/Editable' import { API_URL } from '../config' -import { track } from '../analytics' export function ContactSection() { const { brand, contact_section: content } = useSite() const { t } = useLang() const save = useFieldSaver() - const [form, setForm] = useState({ name: '', phone: '', note: '', website: '' }) + const [form, setForm] = useState({ name: '', phone: '', note: '' }) const [sent, setSent] = useState(false) const [sending, setSending] = useState(false) @@ -80,7 +79,7 @@ export function ContactSection() { const res = await fetch(`${API_URL}/api/contact`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ name: nameValue, phone: phoneValue, note: form.note.trim(), website: form.website }), + body: JSON.stringify({ name: nameValue, phone: phoneValue, note: form.note.trim() }), }) if (!res.ok) { @@ -91,7 +90,6 @@ export function ContactSection() { return } - track('contact-submit') setSent(true) } catch { showErrorAlert(t('connectionErrorTitle'), t('connectionErrorText')) @@ -154,7 +152,6 @@ export function ContactSection() { track('phone-click', { from: 'contact-section' })} className="mt-1 block text-sm font-light text-ivory/70 transition-colors hover:text-copper" > saveBrand('phone', v)} /> @@ -197,29 +194,20 @@ export function ContactSection() {

saveContent('success_text', v)} />

- { setSent(false) - setForm({ name: '', phone: '', note: '', website: '' }) + setForm({ name: '', phone: '', note: '' }) }} - className="mt-8 font-light" > saveContent('success_button_label', v)} /> - + ) : (
- {/* honeypot — خارج از دید؛ فقط ربات‌ها آن را پر می‌کنند */} - setForm({ ...form, website: e.target.value })} - tabIndex={-1} - autoComplete="off" - aria-hidden="true" - className="pointer-events-none absolute -left-[9999px] h-0 w-0 opacity-0" - />
- {sending ? ( content.sending_label ) : ( - saveContent('submit_label', v)} /> + <> + saveContent('submit_label', v)} /> + + )} - +
)} diff --git a/frontend/src/components/home/Articles.tsx b/frontend/src/components/home/Articles.tsx index e4c03ad..636ddde 100644 --- a/frontend/src/components/home/Articles.tsx +++ b/frontend/src/components/home/Articles.tsx @@ -1,7 +1,7 @@ import React from 'react'; - +import { ArrowLeftIcon } from 'lucide-react'; import { Reveal } from '../Reveal'; -import { PremiumButton } from '../PremiumButton'; +import { ButtonLink } from '../Button'; import { ArticleCard } from '../ArticleCard'; import { useSectionHeading, useSite } from '../../api'; import { useLang } from '../../i18n/lang'; @@ -53,9 +53,10 @@ export function Articles() { {heading.cta_label && heading.cta_href && (
- + saveHeading('cta_label', v)} /> - + +
)} diff --git a/frontend/src/components/home/Newsletter.tsx b/frontend/src/components/home/Newsletter.tsx index 0af6af9..64d6ca1 100644 --- a/frontend/src/components/home/Newsletter.tsx +++ b/frontend/src/components/home/Newsletter.tsx @@ -1,22 +1,20 @@ import React, { useState } from 'react' -import { CheckIcon } from 'lucide-react' +import { CheckIcon, SendIcon } from 'lucide-react' import Swal from 'sweetalert2' import { Reveal } from '../Reveal' -import { PremiumButton } from '../PremiumButton' +import { Button } from '../Button' import { useSite } from '../../api' import { useLang } from '../../i18n/lang' import { useFieldSaver } from '../../admin/AdminContext' import { InlineEdit } from '../admin/InlineEdit' import { SingletonPill } from '../../admin/Editable' import { API_URL } from '../../config' -import { track } from '../../analytics' export function Newsletter() { const { newsletter } = useSite() const { t } = useLang() const save = useFieldSaver() const [email, setEmail] = useState('') - const [website, setWebsite] = useState('') const [status, setStatus] = useState<'idle' | 'error' | 'done'>('idle') const [sending, setSending] = useState(false) @@ -77,7 +75,7 @@ export function Newsletter() { const res = await fetch(`${API_URL}/api/newsletter`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ email: emailValue, website }), + body: JSON.stringify({ email: emailValue }), }) if (!res.ok) { @@ -89,7 +87,6 @@ export function Newsletter() { return } - track('newsletter-signup') setStatus('done') setEmail('') } catch { @@ -101,7 +98,7 @@ export function Newsletter() { } return ( -
+
{/* هاله نور پس‌زمینه برای عمق بصری */} @@ -120,17 +117,6 @@ export function Newsletter() {
- {/* honeypot — خارج از دید؛ فقط ربات‌ها آن را پر می‌کنند */} - setWebsite(e.target.value)} - tabIndex={-1} - autoComplete="off" - aria-hidden="true" - className="pointer-events-none absolute -left-[9999px] h-0 w-0 opacity-0" - />
- +
diff --git a/frontend/src/components/home/Story.tsx b/frontend/src/components/home/Story.tsx index f5b241e..f12ec49 100644 --- a/frontend/src/components/home/Story.tsx +++ b/frontend/src/components/home/Story.tsx @@ -1,7 +1,7 @@ import React from 'react' - +import { ArrowLeftIcon } from 'lucide-react' import { Reveal } from '../Reveal' -import { PremiumButton } from '../PremiumButton' +import { ButtonLink } from '../Button' import { useSite } from '../../api' import { useLang } from '../../i18n/lang' import { useFieldSaver } from '../../admin/AdminContext' @@ -89,9 +89,10 @@ export function Story({ showLink = true, showLabel = true, showQuote = false, al {showLink && ( - + saveStory('link_label', v)} /> - + + )} diff --git a/frontend/src/pages/ArticleDetail.tsx b/frontend/src/pages/ArticleDetail.tsx index 67698e1..543489f 100644 --- a/frontend/src/pages/ArticleDetail.tsx +++ b/frontend/src/pages/ArticleDetail.tsx @@ -1,12 +1,11 @@ import React from 'react'; import { Link, useParams } from 'react-router-dom'; -import { ChevronLeftIcon, ChevronRightIcon } from 'lucide-react'; +import { ArrowLeftIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-react'; import { renderToHTMLString } from '@tiptap/static-renderer'; import { Reveal } from '../components/Reveal'; -import { PremiumButton } from '../components/PremiumButton'; +import { ButtonLink } from '../components/Button'; import { ArticleCard } from '../components/ArticleCard'; import { ArticleMeta } from '../components/ArticleMeta'; -import { ArticleFaq } from '../components/ArticleFaq'; import { TableOfContents, extractToc, type TocItem } from '../components/TableOfContents'; import { Newsletter } from '../components/home/Newsletter'; import { useSite } from '../api'; @@ -48,35 +47,6 @@ export function ArticleDetail() { // عنوان تب، توضیح متا، OG و JSON-LD از خود مقاله useEffect(() => { if (!article) return; - let jsonLd: Record | Record[] = { - '@context': 'https://schema.org', - '@type': 'Article', - headline: article.title, - description: article.meta_description || article.excerpt, - image: article.image ? new URL(article.image, window.location.origin).href : undefined, - inLanguage: lang, - author: { '@type': 'Organization', name: article.author?.trim() || brand.name }, - publisher: { '@type': 'Organization', name: brand.name }, - mainEntityOfPage: new URL(href(`/blog/${article.slug}`), window.location.origin).href, - }; - // پرسش‌وپاسخ مقاله → اسکیمای FAQPage در همان بلوک (آرایه‌ای از دو اسکیما) - const articleFaqs = article.faqs ?? []; - if (articleFaqs.length) { - jsonLd = [ - jsonLd, - { - '@context': 'https://schema.org', - '@type': 'FAQPage', - mainEntity: articleFaqs - .filter((f) => f.question.trim()) - .map((f) => ({ - '@type': 'Question', - name: f.question, - acceptedAnswer: { '@type': 'Answer', text: f.answer }, - })), - }, - ]; - } applySeo({ title: `${article.title} | ${brand.name}`, // توضیحات سئوی اختصاصی در اولویت است؛ در نبود آن، چکیده @@ -85,7 +55,17 @@ export function ArticleDetail() { image: article.image, type: 'article', lang, - jsonLd, + jsonLd: { + '@context': 'https://schema.org', + '@type': 'Article', + headline: article.title, + description: article.meta_description || article.excerpt, + image: article.image ? new URL(article.image, window.location.origin).href : undefined, + inLanguage: lang, + author: { '@type': 'Organization', name: article.author?.trim() || brand.name }, + publisher: { '@type': 'Organization', name: brand }, + mainEntityOfPage: new URL(href(`/blog/${article.slug}`), window.location.origin).href, + }, }); }, [article?.id, lang, href]); @@ -94,9 +74,10 @@ export function ArticleDetail() {

{t('articleNotFound')}

{t('articleNotFoundText')}

- + {t('backToBlog')} - + +
); } @@ -190,14 +171,6 @@ export function ArticleDetail() { - {/* پرسش‌وپاسخ‌های پایان مقاله — همان ظاهر آکاردئونی FAQ سایت */} -
-
-

{t('fallbackFaqTitle')}

- -
-
-

{t('relatedArticles')}