diff --git a/src/BackOffice/Pages/Content/Components/AboutSettingsEditor.razor b/src/BackOffice/Pages/Content/Components/AboutSettingsEditor.razor new file mode 100644 index 0000000..762f208 --- /dev/null +++ b/src/BackOffice/Pages/Content/Components/AboutSettingsEditor.razor @@ -0,0 +1,66 @@ +@using BackOffice.Pages.Content.Components.SettingsModels + + + + @* ── Vision ── *@ + + + + + + + + + @* ── Mission ── *@ + + + + + + + + + @* ── Section Titles ── *@ + + + + + + + + @* ── Hint ── *@ + + آیتم‌های ارزش‌ها و اعضای تیم از بخش «مدیریت تصاویر» قابل ویرایش هستند. + + + + +@code { + [Parameter] public AboutSettingsModel Model { get; set; } = new(); +} diff --git a/src/BackOffice/Pages/Content/Components/ContactSettingsEditor.razor b/src/BackOffice/Pages/Content/Components/ContactSettingsEditor.razor new file mode 100644 index 0000000..15a2bb3 --- /dev/null +++ b/src/BackOffice/Pages/Content/Components/ContactSettingsEditor.razor @@ -0,0 +1,68 @@ +@using BackOffice.Pages.Content.Components.SettingsModels + + + + @* ── Contact Info ── *@ + + + + + + + + + + + + + + + + @* ── Social Media ── *@ + + + + + + + + + + + +@code { + [Parameter] public ContactSettingsModel Model { get; set; } = new(); +} diff --git a/src/BackOffice/Pages/Content/Components/LandingSettingsEditor.razor b/src/BackOffice/Pages/Content/Components/LandingSettingsEditor.razor new file mode 100644 index 0000000..12bd702 --- /dev/null +++ b/src/BackOffice/Pages/Content/Components/LandingSettingsEditor.razor @@ -0,0 +1,332 @@ +@using BackOffice.Pages.Content.Components.SettingsModels + + + + @* ── Hero Buttons ── *@ + + + + + + + + @* ── Trust Badges ── *@ + + + @for (var i = 0; i < Model.TrustBadges.Count; i++) + { + var index = i; + + + @(index + 1) + + + + + + } + + افزودن نشان + + + + + @* ── Steps ── *@ + + + + @for (var i = 0; i < Model.Steps.Count; i++) + { + var index = i; + + + + + @(index + 1) + + + + + + + + } + + افزودن مرحله + + + + + @* ── Features ── *@ + + + + @for (var i = 0; i < Model.Features.Count; i++) + { + var index = i; + + + + @(index + 1) + + + + + + + + } + + افزودن ویژگی + + + + + @* ── Stats ── *@ + + + + @for (var i = 0; i < Model.Stats.Count; i++) + { + var index = i; + + + @(index + 1) + + + + + آبی + بنفش + سبز + زرد + قرمز + آبی روشن + + + + + } + + افزودن آمار + + + + + @* ── Testimonials ── *@ + + + + @for (var i = 0; i < Model.Testimonials.Count; i++) + { + var index = i; + + + + @(index + 1) + + + + + + + + } + + افزودن نظر + + + + + @* ── FAQs ── *@ + + + + @for (var i = 0; i < Model.Faqs.Count; i++) + { + var index = i; + + + + @(index + 1) + + + + + + + } + + افزودن سوال + + + + + @* ── CTA Section ── *@ + + + + + + + + + @* ── Blog Section ── *@ + + + + + نمایش آخرین مطالب بلاگ + + + + + + +@code { + [Parameter] public LandingSettingsModel Model { get; set; } = new(); + + private bool _featuredBlogEnabled + { + get => Model.FeaturedBlogEnabled ?? true; + set => Model.FeaturedBlogEnabled = value; + } +} diff --git a/src/BackOffice/Pages/Content/Components/LicensesSettingsEditor.razor b/src/BackOffice/Pages/Content/Components/LicensesSettingsEditor.razor new file mode 100644 index 0000000..7426aa1 --- /dev/null +++ b/src/BackOffice/Pages/Content/Components/LicensesSettingsEditor.razor @@ -0,0 +1,32 @@ +@using BackOffice.Pages.Content.Components.SettingsModels + + + + @* ── Page Settings ── *@ + + + + + گرید (Grid) + لیست (List) + اسلایدر (Carousel) + + + + + @* ── Hint ── *@ + + تصاویر مجوزها از بخش «مدیریت تصاویر» قابل افزودن و ویرایش هستند. + + + + +@code { + [Parameter] public LicensesSettingsModel Model { get; set; } = new(); +} diff --git a/src/BackOffice/Pages/Content/Components/PageSettingsEditDialog.razor b/src/BackOffice/Pages/Content/Components/PageSettingsEditDialog.razor index 899e7be..8ab2e3b 100644 --- a/src/BackOffice/Pages/Content/Components/PageSettingsEditDialog.razor +++ b/src/BackOffice/Pages/Content/Components/PageSettingsEditDialog.razor @@ -1,4 +1,5 @@ @using BackOffice.Services.Content +@using BackOffice.Pages.Content.Components.SettingsModels @using Microsoft.AspNetCore.Components.Forms @using BackOffice.Common.BaseComponents @@ -63,12 +64,34 @@ - تنظیمات اختصاصی (JSON) - + + + تنظیمات اختصاصی «@PageTitle» + + + @* ── Typed Settings Editors ── *@ + @switch (Model.PageKey) + { + case "landing": + + break; + case "about": + + break; + case "contact": + + break; + case "licenses": + + break; + default: + + break; + } diff --git a/src/BackOffice/Pages/Content/Components/PageSettingsEditDialog.razor.cs b/src/BackOffice/Pages/Content/Components/PageSettingsEditDialog.razor.cs index 028a351..9095065 100644 --- a/src/BackOffice/Pages/Content/Components/PageSettingsEditDialog.razor.cs +++ b/src/BackOffice/Pages/Content/Components/PageSettingsEditDialog.razor.cs @@ -1,3 +1,5 @@ +using System.Text.Json; +using BackOffice.Pages.Content.Components.SettingsModels; using BackOffice.Services.Content; using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components.Forms; @@ -23,6 +25,70 @@ public partial class PageSettingsEditDialog private string? _imagePreview; private readonly long _maxAllowedSize = (1024 * 1024) * 5; + // ── Typed settings models ── + private LandingSettingsModel _landingSettings = new(); + private AboutSettingsModel _aboutSettings = new(); + private ContactSettingsModel _contactSettings = new(); + private LicensesSettingsModel _licensesSettings = new(); + + private static readonly JsonSerializerOptions JsonOptions = new() + { + PropertyNameCaseInsensitive = true, + WriteIndented = true, + PropertyNamingPolicy = JsonNamingPolicy.CamelCase + }; + + protected override void OnParametersSet() + { + DeserializeSettings(); + } + + /// + /// Parse existing SettingsJson into the typed model based on PageKey + /// + private void DeserializeSettings() + { + if (string.IsNullOrWhiteSpace(Model.SettingsJson)) return; + + try + { + switch (Model.PageKey) + { + case "landing": + _landingSettings = JsonSerializer.Deserialize(Model.SettingsJson, JsonOptions) ?? new(); + break; + case "about": + _aboutSettings = JsonSerializer.Deserialize(Model.SettingsJson, JsonOptions) ?? new(); + break; + case "contact": + _contactSettings = JsonSerializer.Deserialize(Model.SettingsJson, JsonOptions) ?? new(); + break; + case "licenses": + _licensesSettings = JsonSerializer.Deserialize(Model.SettingsJson, JsonOptions) ?? new(); + break; + } + } + catch + { + // If JSON is malformed, start with empty model + } + } + + /// + /// Serialize the typed model back to JSON before saving + /// + private void SerializeSettings() + { + Model.SettingsJson = Model.PageKey switch + { + "landing" => JsonSerializer.Serialize(_landingSettings, JsonOptions), + "about" => JsonSerializer.Serialize(_aboutSettings, JsonOptions), + "contact" => JsonSerializer.Serialize(_contactSettings, JsonOptions), + "licenses" => JsonSerializer.Serialize(_licensesSettings, JsonOptions), + _ => Model.SettingsJson // keep raw JSON for unknown pages + }; + } + private async Task OnImageSelected(IBrowserFile? file) { _imageFile = file; @@ -46,6 +112,9 @@ public partial class PageSettingsEditDialog _loading = true; + // Serialize typed model → JSON before saving + SerializeSettings(); + if (_imageFile != null && _imageBuffer != null) { Model.ImageFile = _imageBuffer; diff --git a/src/BackOffice/Pages/Content/Components/SettingsModels/PageSettingsModels.cs b/src/BackOffice/Pages/Content/Components/SettingsModels/PageSettingsModels.cs new file mode 100644 index 0000000..a5f2ae2 --- /dev/null +++ b/src/BackOffice/Pages/Content/Components/SettingsModels/PageSettingsModels.cs @@ -0,0 +1,108 @@ +namespace BackOffice.Pages.Content.Components.SettingsModels; + +// ══════════════════════════════════════════════════════════════ +// LANDING PAGE +// ══════════════════════════════════════════════════════════════ + +public class LandingSettingsModel +{ + public string? HeroButtonPrimaryText { get; set; } + public string? HeroButtonSecondaryText { get; set; } + public List TrustBadges { get; set; } = new(); + public string? StepsTitle { get; set; } + public List Steps { get; set; } = new(); + public string? FeaturesTitle { get; set; } + public List Features { get; set; } = new(); + public string? StatsTitle { get; set; } + public List Stats { get; set; } = new(); + public string? TestimonialsTitle { get; set; } + public List Testimonials { get; set; } = new(); + public string? FaqTitle { get; set; } + public List Faqs { get; set; } = new(); + public string? CtaTitle { get; set; } + public string? CtaDescription { get; set; } + public string? CtaButtonText { get; set; } + public bool? FeaturedBlogEnabled { get; set; } +} + +public class TrustBadgeModel +{ + public string? IconName { get; set; } + public string? Text { get; set; } +} + +public class StepModel +{ + public string? Title { get; set; } + public string? Description { get; set; } +} + +public class FeatureModel +{ + public string? IconName { get; set; } + public string? Title { get; set; } + public string? Description { get; set; } +} + +public class StatModel +{ + public string? Label { get; set; } + public double Value { get; set; } + public string? Suffix { get; set; } + public string? Color { get; set; } +} + +public class TestimonialModel +{ + public string? Quote { get; set; } + public string? Name { get; set; } + public string? Role { get; set; } +} + +public class FaqModel +{ + public string? Question { get; set; } + public string? Answer { get; set; } +} + +// ══════════════════════════════════════════════════════════════ +// ABOUT PAGE +// ══════════════════════════════════════════════════════════════ + +public class AboutSettingsModel +{ + public string? VisionTitle { get; set; } + public string? VisionText { get; set; } + public string? VisionIcon { get; set; } + public string? MissionTitle { get; set; } + public string? MissionText { get; set; } + public string? MissionIcon { get; set; } + public string? ValuesTitle { get; set; } + public string? TeamTitle { get; set; } +} + +// ══════════════════════════════════════════════════════════════ +// CONTACT PAGE +// ══════════════════════════════════════════════════════════════ + +public class ContactSettingsModel +{ + public string? Address { get; set; } + public string? Phone { get; set; } + public string? Email { get; set; } + public string? WorkingHours { get; set; } + public string? TelegramUrl { get; set; } + public string? InstagramUrl { get; set; } + public string? LinkedinUrl { get; set; } + public string? WhatsappUrl { get; set; } +} + +// ══════════════════════════════════════════════════════════════ +// LICENSES PAGE +// ══════════════════════════════════════════════════════════════ + +public class LicensesSettingsModel +{ + public string? PageDescription { get; set; } + public string? DisplayStyle { get; set; } +}