feat(catalog/maintenance): add granular sub-settings for Catalog Mode and Maintenance Page redirect [TASK-17.1]

This commit is contained in:
parsa aghaei 2026-08-03 11:49:38 +03:30
parent ce36d7ab38
commit 2f37d0a92c
4 changed files with 67 additions and 4 deletions

View File

@ -14,6 +14,9 @@ const PAGE_TABS = [
];
const GROUPS: Record<string, string[]> = {
"تنظیمات کاتالوگ‌مود و حالت صیانت": [
"maintenance_mode", "catalog_mode", "catalog_hide_prices", "catalog_disable_cart", "catalog_disable_checkout",
],
"هدر و ناوبری": [
"shipping_notice", "brand_name_fa", "brand_subtitle",
"nav_solutions", "nav_products", "nav_wiki", "nav_blog", "nav_pet_profiles",

View File

@ -15,6 +15,8 @@ import { useUserStore } from "../lib/store/userStore";
import { useSettingsStore } from "../lib/store/settingsStore";
import { useUIStore } from "../lib/store/uiStore";
import MaintenancePage from "../components/MaintenancePage";
export default function ClientLayout({ children }: { children: React.ReactNode }) {
const {
isCartOpen, isLoginModalOpen, isB2BPortalOpen, advisorData,
@ -24,8 +26,9 @@ export default function ClientLayout({ children }: { children: React.ReactNode }
const pathname = usePathname();
const router = useRouter();
const { fetchProfile } = useUserStore();
const { fetchProfile, role } = useUserStore();
const fetchSettings = useSettingsStore(state => state.fetchSettings);
const getText = useSettingsStore(state => state.getText);
const isInitialized = useSettingsStore(state => state.isInitialized);
useEffect(() => {
@ -38,7 +41,13 @@ export default function ClientLayout({ children }: { children: React.ReactNode }
}
}, [fetchProfile, fetchSettings]);
// Remove full-page blocking screen to allow immediate render
// Check Maintenance Mode (Admin / Partner bypass)
const isMaintenanceMode = getText('maintenance_mode', 'false') === 'true';
const isAdmin = role === 'User_Partner' || localStorage.getItem('adminToken');
if (isMaintenanceMode && !isAdmin) {
return <MaintenancePage />;
}
// Derived currentView from pathname for Header
let currentView = "home";

View File

@ -162,8 +162,12 @@ const ArchiveProductCard: React.FC<{ product: Product }> = ({ product }) => {
</div>
<div className="mt-auto flex items-center justify-between pt-4 border-t border-medical-gray-50 gap-2">
<span className="font-black text-medical-gray-900 font-vazir text-sm sm:text-base">{product.price}</span>
{(() => {
{!useSettingsStore.getState().getText("catalog_hide_prices", "false").includes("true") ? (
<span className="font-black text-medical-gray-900 font-vazir text-sm sm:text-base">{product.price}</span>
) : (
<span className="text-xs font-bold text-amber-600 bg-amber-50 px-2 py-1 rounded-md">تماس جهت استعلام قیمت</span>
)}
{!useSettingsStore.getState().getText("catalog_disable_cart", "false").includes("true") && (() => {
const cartItem = useCartStore.getState().items.find(i => i.product.id === product.id);
if (cartItem && cartItem.quantity > 0) {
return (

View File

@ -0,0 +1,47 @@
"use client";
import React from "react";
import { Wrench, ShieldCheck, Phone, ArrowRight } from "lucide-react";
import Link from "next/link";
export default function MaintenancePage() {
return (
<div className="min-h-screen bg-medical-gray-900 text-white flex flex-col items-center justify-center p-6 text-center font-vazir relative overflow-hidden" dir="rtl">
{/* Glow Effects */}
<div className="absolute top-1/4 left-1/2 -translate-x-1/2 -translate-y-1/2 w-96 h-96 bg-canina-blue/20 rounded-full blur-3xl pointer-events-none" />
<div className="absolute bottom-10 right-10 w-80 h-80 bg-canina-gold/10 rounded-full blur-3xl pointer-events-none" />
<div className="relative z-10 max-w-xl mx-auto space-y-6">
<div className="w-24 h-24 bg-white/10 border border-white/20 rounded-3xl mx-auto flex items-center justify-center text-canina-gold shadow-2xl backdrop-blur-md">
<Wrench className="w-12 h-12 animate-bounce" />
</div>
<span className="inline-block px-4 py-1.5 bg-canina-gold/20 text-canina-gold border border-canina-gold/30 rounded-full text-xs font-black tracking-widest uppercase">
سامانه در حال بهروزرسانی و ارتقا
</span>
<h1 className="text-3xl sm:text-5xl font-black tracking-tight leading-tight">
بهزودی با خدمات کاملتر بازمیگردیم
</h1>
<p className="text-sm sm:text-base text-medical-gray-300 leading-relaxed">
وبسایت کانینا ایران جهت ارتقای زیرساختها و ارائه خدمات بهتر به شما سرپرستان و دامپزشکان محترم به صورت موقت در دست بهروزرسانی است. از شکیبایی شما سپاسگزاریم.
</p>
<div className="pt-4 flex flex-col sm:flex-row items-center justify-center gap-4">
<a
href="tel:0218888"
className="w-full sm:w-auto px-6 py-3.5 bg-canina-blue hover:bg-canina-dark text-white font-black text-xs rounded-xl flex items-center justify-center gap-2 shadow-lg transition-all"
>
<Phone className="w-4 h-4" />
<span>پشتیبانی اضطراری: ۰۲۱-۸۸۸۸</span>
</a>
</div>
</div>
<div className="absolute bottom-6 text-xs text-medical-gray-500 font-bold flex items-center gap-2">
<ShieldCheck className="w-4 h-4 text-canina-gold" />
<span>CANINA PHARMA GMBH GERMANY نماینده رسمی ایران</span>
</div>
</div>
);
}