Browse Source

feat: add pilgrim testimonials settings tab with multi-language support and management CRUD functionality

develop
Muhammad Amin Ghorbani 16 hours ago
parent
commit
a2a790aaee
  1. 6
      src/config/navigation.ts
  2. 7
      src/features/settings/SettingsPage.tsx
  3. 1029
      src/features/settings/components/TestimonialsSettingsTab.tsx
  4. 72
      src/features/settings/services/settings-api.ts
  5. 55
      src/features/settings/types.ts
  6. 39
      src/locales/ar.json
  7. 39
      src/locales/en.json
  8. 39
      src/locales/fa.json

6
src/config/navigation.ts

@ -159,6 +159,12 @@ export function getNavigationConfig(t: (key: string) => string): NavGroupConfig[
to: '/settings/notifications', to: '/settings/notifications',
icon: 'bell', icon: 'bell',
}, },
{
title: t('navigation.settingsTestimonials'),
titleKey: 'navigation.settingsTestimonials',
to: '/settings/testimonials',
icon: 'star',
},
], ],
}, },
], ],

7
src/features/settings/SettingsPage.tsx

@ -6,6 +6,7 @@ import { Ic } from '@/icons'
import { AdminManagementTab } from './components/AdminManagementTab' import { AdminManagementTab } from './components/AdminManagementTab'
import { NotificationsTab } from './components/NotificationsTab' import { NotificationsTab } from './components/NotificationsTab'
import { SocialMediaSettingsTab } from './components/SocialMediaSettingsTab' import { SocialMediaSettingsTab } from './components/SocialMediaSettingsTab'
import { TestimonialsSettingsTab } from './components/TestimonialsSettingsTab'
export default function SettingsPage() { export default function SettingsPage() {
const { t } = useTranslation() const { t } = useTranslation()
@ -13,12 +14,12 @@ export default function SettingsPage() {
const navigate = useNavigate() const navigate = useNavigate()
React.useEffect(() => { React.useEffect(() => {
if (!section || !['admins', 'social', 'notifications'].includes(section)) {
if (!section || !['admins', 'social', 'notifications', 'testimonials'].includes(section)) {
navigate('/settings/admins', { replace: true }) navigate('/settings/admins', { replace: true })
} }
}, [section, navigate]) }, [section, navigate])
const activeSection = section && ['admins', 'social', 'notifications'].includes(section)
const activeSection = section && ['admins', 'social', 'notifications', 'testimonials'].includes(section)
? section ? section
: 'admins' : 'admins'
@ -54,6 +55,8 @@ export default function SettingsPage() {
<AdminManagementTab /> <AdminManagementTab />
) : activeSection === 'social' ? ( ) : activeSection === 'social' ? (
<SocialMediaSettingsTab /> <SocialMediaSettingsTab />
) : activeSection === 'testimonials' ? (
<TestimonialsSettingsTab />
) : ( ) : (
<NotificationsTab /> <NotificationsTab />
)} )}

1029
src/features/settings/components/TestimonialsSettingsTab.tsx
File diff suppressed because it is too large
View File

72
src/features/settings/services/settings-api.ts

@ -131,3 +131,75 @@ export async function saveSocialMediaSettings(
}) })
} }
/**
* دریافت تنظیمات سربرگ بخش نظرات زائران
*/
export async function fetchTestimonialSectionSettings(): Promise<import('../types').TestimonialSectionConfigData> {
return apiFetch<import('../types').TestimonialSectionConfigData>('home/settings/testimonials/section/')
}
/**
* ذخیره تنظیمات سربرگ بخش نظرات زائران
*/
export async function saveTestimonialSectionSettings(
payload: Partial<import('../types').TestimonialSectionConfigData>
): Promise<import('../types').TestimonialSectionConfigData> {
return apiFetch<import('../types').TestimonialSectionConfigData>('home/settings/testimonials/section/', {
method: 'POST',
body: payload,
})
}
/**
* دریافت فهرست مدیریت نظرات زائران
*/
export async function fetchAdminTestimonials(params?: {
search?: string
is_active?: string
rating?: string
}): Promise<import('../types').AdminTestimonialItem[]> {
const query = new URLSearchParams()
if (params?.search && params.search.trim()) query.set('search', params.search.trim())
if (params?.is_active && params.is_active !== 'all') query.set('is_active', params.is_active)
if (params?.rating && params.rating !== 'all') query.set('rating', params.rating)
const qs = query.toString()
return apiFetch<import('../types').AdminTestimonialItem[]>(
qs ? `home/settings/testimonials/?${qs}` : 'home/settings/testimonials/'
)
}
/**
* ایجاد یک نظر جدید زائر
*/
export async function createAdminTestimonial(
body: FormData | import('../types').CreateOrUpdateTestimonialPayload
): Promise<import('../types').AdminTestimonialItem> {
return apiFetch<import('../types').AdminTestimonialItem>('home/settings/testimonials/', {
method: 'POST',
body,
})
}
/**
* ویرایش نظر زائر
*/
export async function updateAdminTestimonial(
id: number,
body: FormData | Partial<import('../types').CreateOrUpdateTestimonialPayload>
): Promise<import('../types').AdminTestimonialItem> {
return apiFetch<import('../types').AdminTestimonialItem>(`home/settings/testimonials/${id}/`, {
method: 'PATCH',
body,
})
}
/**
* حذف نظر زائر
*/
export async function deleteAdminTestimonial(id: number): Promise<{ success: boolean; detail?: string }> {
return apiFetch<{ success: boolean; detail?: string }>(`home/settings/testimonials/${id}/`, {
method: 'DELETE',
})
}

55
src/features/settings/types.ts

@ -68,3 +68,58 @@ export interface SaveSocialMediaPayload {
contactus?: SocialMediaContactUs contactus?: SocialMediaContactUs
} }
export interface TestimonialTranslationItem {
author_name?: string
location?: string
tour_title?: string
content?: string
}
export type TestimonialTranslations = Record<string, TestimonialTranslationItem>
export interface SectionTranslations {
[lang: string]: {
title?: string
subtitle?: string
}
}
export interface TestimonialSectionConfigData {
id?: number
key: string
is_active: boolean
title?: string
subtitle?: string
translations: SectionTranslations
updated_at?: string
}
export interface AdminTestimonialItem {
id: number
slug: string
avatar?: string | null
avatar_url?: string
rating: number
order: number
is_active: boolean
author_name: string
location: string
tour_title: string
meta: string
content: string
translations: TestimonialTranslations
created_at: string
updated_at: string
}
export interface CreateOrUpdateTestimonialPayload {
slug?: string
avatar_url?: string
rating?: number
order?: number
is_active?: boolean
remove_avatar?: boolean
translations: TestimonialTranslations
}

39
src/locales/ar.json

@ -43,7 +43,8 @@
"logout": "تسجيل الخروج", "logout": "تسجيل الخروج",
"soon": "قريباً", "soon": "قريباً",
"comingSoon": "قريباً", "comingSoon": "قريباً",
"adminRole": "مدير النظام العام"
"adminRole": "مدير النظام العام",
"settingsTestimonials": "تجارب وآراء الزوار"
}, },
"topbar": { "topbar": {
"serverOnline": "الخادم متصل", "serverOnline": "الخادم متصل",
@ -556,7 +557,41 @@
"notificationsUpcomingFeaturesTitle": "الميزات قيد التنفيذ لهذا القسم:", "notificationsUpcomingFeaturesTitle": "الميزات قيد التنفيذ لهذا القسم:",
"notificationsFeature1": "إرسال إشعارات مخصصة لمستخدمي التطبيق والويب مصنفة حسب اللغة", "notificationsFeature1": "إرسال إشعارات مخصصة لمستخدمي التطبيق والويب مصنفة حسب اللغة",
"notificationsFeature2": "جدولة تلقائية للتذكير بالرحلات والجولات والمدفوعات المعلقة", "notificationsFeature2": "جدولة تلقائية للتذكير بالرحلات والجولات والمدفوعات المعلقة",
"notificationsFeature3": "تقارير تحليلية لمعدلات المشاهدة والنقر والتسليم الناجح"
"notificationsFeature3": "تقارير تحليلية لمعدلات المشاهدة والنقر والتسليم الناجح",
"tabTestimonials": "تجارب وآراء الزوار",
"badgeTestimonials": "قسم الآراء والملاحظات",
"testimonialsDescription": "إدارة آراء وتجارب الزوار المعنوية في الصفحة الرئيسية وصفحة من نحن",
"sectionHeaderCard": "إعدادات ترويسة قسم الآراء",
"sectionHeaderCardDesc": "ضبط العنوان والعنوان الفرعي لهذا القسم بمختلف اللغات وحالة العرض في الموقع",
"testimonialsListTitle": "قائمة آراء الزوار",
"addTestimonial": "إضافة رأي جديد",
"editTestimonial": "تعديل رأي الزائر",
"deleteTestimonial": "حذف الرأي",
"deleteTestimonialConfirm": "هل أنت متأكد من حذف رأي هذا الزائر؟ لا يمكن التراجع عن هذا الإجراء.",
"authorName": "اسم الزائر",
"location": "بلد وإقامة الزائر",
"tourTitle": "عنوان الرحلة / الجولة",
"rating": "التقييم (النجوم)",
"displayOrder": "ترتيب العرض",
"avatarImage": "الصورة الشخصية (الأفاتار)",
"uploadAvatar": "تحميل صورة جديدة",
"avatarUrlOptional": "رابط الصورة (اختياري)",
"testimonialContent": "نص وتجربة الزائر",
"sectionActive": "تفعيل عرض القسم بالموقع",
"testimonialActive": "الحالة نشطة",
"totalTestimonials": "إجمالي الآراء المسجلة",
"activeTestimonials": "الآراء النشطة",
"averageRating": "متوسط التقييمات",
"saveSettingsSuccess": "تم حفظ الإعدادات بنجاح.",
"testimonialSavedSuccess": "تم حفظ رأي الزائر بنجاح.",
"testimonialDeletedSuccess": "تم حذف الرأي بنجاح.",
"noTestimonialsFound": "لم يتم العثور على أي آراء.",
"searchTestimonialPlaceholder": "البحث في اسم الزائر، المدينة، عنوان الرحلة أو النص...",
"filterAllRatings": "جميع التقييمات",
"starsCount": "نجوم",
"slugLabel": "المعرف الفريد (الرابط المختصر)",
"sectionTitleLabel": "عنوان القسم",
"sectionSubtitleLabel": "العنوان الفرعي ووصف القسم"
}, },
"customTrip": { "customTrip": {
"title": "إدارة الرحلات المخصصة", "title": "إدارة الرحلات المخصصة",

39
src/locales/en.json

@ -43,7 +43,8 @@
"logout": "Logout", "logout": "Logout",
"soon": "Soon", "soon": "Soon",
"comingSoon": "Coming Soon", "comingSoon": "Coming Soon",
"adminRole": "System Administrator"
"adminRole": "System Administrator",
"settingsTestimonials": "Pilgrim Testimonials"
}, },
"topbar": { "topbar": {
"serverOnline": "Server is Online", "serverOnline": "Server is Online",
@ -556,7 +557,41 @@
"notificationsUpcomingFeaturesTitle": "Features under development for this section:", "notificationsUpcomingFeaturesTitle": "Features under development for this section:",
"notificationsFeature1": "Send targeted notifications to app and web users segmented by language", "notificationsFeature1": "Send targeted notifications to app and web users segmented by language",
"notificationsFeature2": "Automated scheduling for trip reminders, tours, and pending payments", "notificationsFeature2": "Automated scheduling for trip reminders, tours, and pending payments",
"notificationsFeature3": "Analytics reports on impressions, open rates, and successful delivery"
"notificationsFeature3": "Analytics reports on impressions, open rates, and successful delivery",
"tabTestimonials": "Pilgrim Testimonials",
"badgeTestimonials": "Testimonials & Reviews",
"testimonialsDescription": "Manage pilgrim reviews, feedback, and spiritual reflections on home and about pages",
"sectionHeaderCard": "Section Header Settings",
"sectionHeaderCardDesc": "Configure multi-language title, subtitle, and visibility on the website",
"testimonialsListTitle": "Pilgrim Testimonials List",
"addTestimonial": "Add New Testimonial",
"editTestimonial": "Edit Pilgrim Testimonial",
"deleteTestimonial": "Delete Testimonial",
"deleteTestimonialConfirm": "Are you sure you want to delete this pilgrim testimonial? This action cannot be undone.",
"authorName": "Pilgrim Name",
"location": "Country / City",
"tourTitle": "Tour / Pilgrimage Title",
"rating": "Rating (Stars)",
"displayOrder": "Display Order",
"avatarImage": "Avatar Photo",
"uploadAvatar": "Upload New Photo",
"avatarUrlOptional": "Image URL (Optional)",
"testimonialContent": "Testimonial Content",
"sectionActive": "Show Section on Site",
"testimonialActive": "Active Status",
"totalTestimonials": "Total Testimonials",
"activeTestimonials": "Active Testimonials",
"averageRating": "Average Rating",
"saveSettingsSuccess": "Settings saved successfully.",
"testimonialSavedSuccess": "Pilgrim testimonial saved successfully.",
"testimonialDeletedSuccess": "Testimonial deleted successfully.",
"noTestimonialsFound": "No testimonials found.",
"searchTestimonialPlaceholder": "Search by pilgrim name, city, tour, or text...",
"filterAllRatings": "All Ratings",
"starsCount": "Stars",
"slugLabel": "Unique Slug",
"sectionTitleLabel": "Section Title",
"sectionSubtitleLabel": "Section Subtitle & Description"
}, },
"customTrip": { "customTrip": {
"title": "Custom Trip Management", "title": "Custom Trip Management",

39
src/locales/fa.json

@ -43,7 +43,8 @@
"logout": "خروج از سیستم", "logout": "خروج از سیستم",
"soon": "به‌زودی", "soon": "به‌زودی",
"comingSoon": "به‌زودی", "comingSoon": "به‌زودی",
"adminRole": "مدیر کل سیستم"
"adminRole": "مدیر کل سیستم",
"settingsTestimonials": "تجارب و نظرات زائران"
}, },
"topbar": { "topbar": {
"serverOnline": "سرور متصل است", "serverOnline": "سرور متصل است",
@ -556,7 +557,41 @@
"notificationsUpcomingFeaturesTitle": "قابلیت‌های در دست پیاده‌سازی این بخش:", "notificationsUpcomingFeaturesTitle": "قابلیت‌های در دست پیاده‌سازی این بخش:",
"notificationsFeature1": "ارسال اعلان اختصاصی به کاربران اپلیکیشن و وب با تفکیک زبان", "notificationsFeature1": "ارسال اعلان اختصاصی به کاربران اپلیکیشن و وب با تفکیک زبان",
"notificationsFeature2": "زمان‌بندی خودکار یادآورهای سفر، تور و پرداخت‌های مالی", "notificationsFeature2": "زمان‌بندی خودکار یادآورهای سفر، تور و پرداخت‌های مالی",
"notificationsFeature3": "گزارش‌های تحلیلی نرخ مشاهده، کلیک و تحویل موفق پیام‌ها"
"notificationsFeature3": "گزارش‌های تحلیلی نرخ مشاهده، کلیک و تحویل موفق پیام‌ها",
"tabTestimonials": "تجارب و دیدگاه‌های زائران",
"badgeTestimonials": "بخش نظرات و بازخوردها",
"testimonialsDescription": "مدیریت نظرات، بازخوردها و تجربیات معنوی زائران در صفحه اصلی و درباره ما",
"sectionHeaderCard": "تنظیمات سربرگ بخش نظرات",
"sectionHeaderCardDesc": "تنظیم عنوان و زیرعنوان این بخش در زبان‌های مختلف و وضعیت نمایش در سایت",
"testimonialsListTitle": "فهرست نظرات زائران",
"addTestimonial": "افزودن نظر جدید",
"editTestimonial": "ویرایش نظر زائر",
"deleteTestimonial": "حذف نظر",
"deleteTestimonialConfirm": "آیا از حذف این نظر زائر اطمینان دارید؟ این عملیات قابل بازگشت نیست.",
"authorName": "نام زائر",
"location": "محل سکونت / کشور و شهر",
"tourTitle": "عنوان تور / سفر زیارتی",
"rating": "امتیاز (ستاره)",
"displayOrder": "ترتیب نمایش",
"avatarImage": "تصویر چهره (آواتار)",
"uploadAvatar": "بارگذاری تصویر جدید",
"avatarUrlOptional": "آدرس اینترنتی تصویر (اختیاری)",
"testimonialContent": "متن بازخورد و تجربه زائر",
"sectionActive": "نمایش بخش در سایت",
"testimonialActive": "وضعیت فعال",
"totalTestimonials": "کل نظرات ثبت‌شده",
"activeTestimonials": "نظرات فعال",
"averageRating": "میانگین امتیازات",
"saveSettingsSuccess": "تنظیمات با موفقیت ذخیره شد.",
"testimonialSavedSuccess": "نظر زائر با موفقیت ذخیره شد.",
"testimonialDeletedSuccess": "نظر با موفقیت حذف شد.",
"noTestimonialsFound": "هیچ نظری یافت نشد.",
"searchTestimonialPlaceholder": "جستجو در نام زائر، شهر، عنوان تور یا متن...",
"filterAllRatings": "همه امتیازها",
"starsCount": "ستاره",
"slugLabel": "شناسه یکتا (اسلاگ)",
"sectionTitleLabel": "عنوان بخش",
"sectionSubtitleLabel": "زیرعنوان و توضیحات بخش"
}, },
"customTrip": { "customTrip": {
"title": "مدیریت سفرهای اختصاصی", "title": "مدیریت سفرهای اختصاصی",

Loading…
Cancel
Save