fix(ui): refine mobile product details alignment, search overlay, remove full page loading, toast close button and dosage calculator layout
This commit is contained in:
parent
19c86c9955
commit
1c93aec1c9
@ -35,17 +35,7 @@ export default function ClientLayout({ children }: { children: React.ReactNode }
|
||||
}
|
||||
}, [fetchProfile, fetchSettings]);
|
||||
|
||||
if (!isInitialized) {
|
||||
return (
|
||||
<div className="min-h-screen bg-medical-gray-50 flex flex-col items-center justify-center font-sans" dir="rtl">
|
||||
<div className="flex flex-col items-center gap-4 text-center">
|
||||
<div className="w-12 h-12 border-4 border-canina-blue border-t-transparent rounded-full animate-spin" />
|
||||
<h2 className="text-xl font-black text-medical-gray-900 font-lalezar tracking-wide">در حال بارگذاری اطلاعات سایت...</h2>
|
||||
<p className="text-sm text-medical-gray-500 font-shabnam">لطفاً شکیبا باشید</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
// Remove full-page blocking screen to allow immediate render
|
||||
|
||||
// Derived currentView from pathname for Header
|
||||
let currentView = "home";
|
||||
@ -114,7 +104,7 @@ export default function ClientLayout({ children }: { children: React.ReactNode }
|
||||
petName={advisorData?.name}
|
||||
isAdvisorContext={!!advisorData}
|
||||
/>
|
||||
<Toaster position="top-center" expand={true} richColors />
|
||||
<Toaster position="top-center" expand={true} richColors closeButton />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@ -247,15 +247,17 @@ export default function Header({
|
||||
<div className="flex items-center gap-2 sm:gap-4 flex-shrink-0 justify-end h-auto md:h-16 pl-1 sm:pl-2">
|
||||
|
||||
{/* Elastic Search */}
|
||||
<div className="relative flex items-center justify-end z-20">
|
||||
{/* Elastic Search */}
|
||||
<div className="relative flex items-center justify-end z-30">
|
||||
<AnimatePresence>
|
||||
{isSearchFocused && (
|
||||
<motion.div
|
||||
initial={{ width: 0, opacity: 0 }}
|
||||
animate={{ width: 260, opacity: 1 }}
|
||||
animate={{ width: 220, opacity: 1 }}
|
||||
exit={{ width: 0, opacity: 0 }}
|
||||
transition={{ type: "spring", damping: 25, stiffness: 220 }}
|
||||
className="absolute right-0 top-1/2 -translate-y-1/2 bg-white border border-canina-blue/30 border-l rounded-2xl shadow-xl shadow-canina-blue/5 overflow-hidden h-10 sm:h-12 flex items-center pr-10 pl-3 z-25"
|
||||
className="absolute left-full sm:right-0 top-1/2 -translate-y-1/2 bg-white border border-canina-blue/30 rounded-2xl shadow-2xl overflow-hidden h-10 sm:h-12 flex items-center pr-10 pl-3 z-30"
|
||||
style={{ transformOrigin: "right center" }}
|
||||
>
|
||||
<form onSubmit={handleSearch} className="w-full flex items-center">
|
||||
<input
|
||||
|
||||
@ -161,14 +161,28 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
|
||||
setItemQuantity(suggestedQty);
|
||||
}, [calculation?.duration]);
|
||||
|
||||
if (isLoading) return <div className="min-h-screen flex items-center justify-center">Loading...</div>;
|
||||
if (isLoading) return (
|
||||
<div className="min-h-screen bg-medical-gray-50 p-6 max-w-7xl mx-auto font-vazir" dir="rtl">
|
||||
<div className="animate-pulse space-y-6">
|
||||
<div className="h-8 bg-medical-gray-200 rounded-2xl w-48" />
|
||||
<div className="grid md:grid-cols-12 gap-8">
|
||||
<div className="md:col-span-5 h-80 bg-white border border-medical-gray-200 rounded-[2.5rem]" />
|
||||
<div className="md:col-span-7 space-y-4">
|
||||
<div className="h-10 bg-medical-gray-200 rounded-2xl w-3/4" />
|
||||
<div className="h-6 bg-medical-gray-100 rounded-xl w-1/2" />
|
||||
<div className="h-24 bg-medical-gray-100 rounded-2xl w-full" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
if (!product || !fullProduct || !calculation) return <div className="min-h-screen flex items-center justify-center">محصول یافت نشد</div>;
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-medical-gray-50 pt-2 pb-20 px-4 md:px-0" dir="rtl">
|
||||
<div className="min-h-screen bg-medical-gray-50 pt-2 pb-32 sm:pb-20 px-4 md:px-0" dir="rtl">
|
||||
<div className="max-w-7xl mx-auto">
|
||||
{/* Breadcrumbs for Mobile and Desktop */}
|
||||
<nav className="flex items-center gap-2 text-xs md:text-sm font-semibold text-medical-gray-600 mb-6 md:mb-10 overflow-x-auto whitespace-nowrap py-3 border-b border-medical-gray-100 font-vazir" dir="rtl">
|
||||
<nav className="flex items-center gap-2 text-xs md:text-sm font-semibold text-medical-gray-600 mb-6 md:mb-10 overflow-x-auto whitespace-nowrap py-3 border-b border-medical-gray-100 font-vazir scrollbar-thin scrollbar-thumb-medical-gray-200 scrollbar-track-transparent pr-1" dir="rtl">
|
||||
<button
|
||||
onClick={() => router.push('/')}
|
||||
className="hover:text-canina-blue transition-colors font-vazir cursor-pointer"
|
||||
@ -193,20 +207,20 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
|
||||
<div className="lg:col-span-8 space-y-12">
|
||||
|
||||
{/* Above the Fold Grid */}
|
||||
<div className="grid md:grid-cols-12 gap-12 items-start">
|
||||
<div className="grid md:grid-cols-12 gap-8 md:gap-12 items-center md:items-start text-center md:text-right font-vazir" dir="rtl">
|
||||
{/* Right Column: Product Image Frame (md:col-span-5) */}
|
||||
<div className="md:col-span-5 w-full">
|
||||
<div className="md:col-span-5 w-full mx-auto max-w-sm md:max-w-none">
|
||||
<motion.div
|
||||
initial={{ opacity: 0, scale: 0.95 }}
|
||||
animate={{ opacity: 1, scale: 1 }}
|
||||
className="bg-white rounded-[2.5rem] border border-medical-gray-200 shadow-xl relative group overflow-hidden h-[380px] flex items-center justify-center p-8"
|
||||
className="bg-white rounded-[2.5rem] border border-medical-gray-200 shadow-xl relative group overflow-hidden h-[300px] sm:h-[380px] flex items-center justify-center p-6 sm:p-8"
|
||||
>
|
||||
<div className="absolute top-6 left-6 flex flex-col gap-2 z-10">
|
||||
<div className="px-3 py-1 bg-green-500 text-white rounded-full text-[10px] font-black uppercase tracking-widest flex items-center gap-1 font-vazir shadow-sm">
|
||||
<div className="absolute top-4 left-4 sm:top-6 sm:left-6 flex flex-col gap-1.5 sm:gap-2 z-10 items-start">
|
||||
<div className="px-2.5 py-1 bg-green-500 text-white rounded-full text-[9px] sm:text-[10px] font-black uppercase tracking-widest flex items-center gap-1 font-vazir shadow-sm">
|
||||
<CheckCircle2 className="w-3 h-3" />
|
||||
موجود در انبار
|
||||
</div>
|
||||
<div className="px-3 py-1 bg-canina-blue text-white rounded-full text-[10px] font-black uppercase tracking-widest font-vazir whitespace-nowrap shadow-sm">
|
||||
<div className="px-2.5 py-1 bg-canina-blue text-white rounded-full text-[9px] sm:text-[10px] font-black uppercase tracking-widest font-vazir whitespace-nowrap shadow-sm">
|
||||
گرید دارویی اختصاصی
|
||||
</div>
|
||||
</div>
|
||||
@ -214,15 +228,15 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
|
||||
src={product.image}
|
||||
alt={product.name}
|
||||
className="w-full h-full"
|
||||
imgClassName="max-h-[300px] w-auto object-contain drop-shadow-2xl group-hover:scale-105 transition-transform duration-700 mx-auto my-auto"
|
||||
imgClassName="max-h-[240px] sm:max-h-[300px] w-auto object-contain drop-shadow-2xl group-hover:scale-105 transition-transform duration-700 mx-auto my-auto"
|
||||
/>
|
||||
</motion.div>
|
||||
</div>
|
||||
|
||||
{/* Left Column: Product Title & Description (md:col-span-7) */}
|
||||
<div className="md:col-span-7 space-y-6">
|
||||
<div>
|
||||
<div className="flex flex-wrap items-center gap-3 mb-4">
|
||||
<div className="md:col-span-7 space-y-4 sm:space-y-6 flex flex-col items-center md:items-start">
|
||||
<div className="w-full flex flex-col items-center md:items-start">
|
||||
<div className="flex flex-wrap justify-center md:justify-start items-center gap-2 sm:gap-3 mb-3 sm:mb-4">
|
||||
<div className="px-3 py-1 bg-canina-blue text-white rounded-full text-[10px] font-black uppercase tracking-widest font-vazir whitespace-nowrap shadow-sm">
|
||||
استاندارد صنعتی آلمان
|
||||
</div>
|
||||
@ -232,17 +246,17 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex flex-col gap-2 mb-4">
|
||||
<h1 dir="rtl" className="text-2xl md:text-3xl lg:text-4xl font-black text-medical-gray-900 leading-tight font-vazir text-right">
|
||||
<div className="flex flex-col gap-1.5 mb-4 text-center md:text-right w-full">
|
||||
<h1 dir="rtl" className="text-xl sm:text-2xl md:text-3xl lg:text-4xl font-black text-medical-gray-900 leading-tight font-vazir">
|
||||
{product.nameFa || product.name}
|
||||
</h1>
|
||||
{product.nameEn && (
|
||||
<h2 dir="ltr" className="text-base md:text-lg text-slate-400 font-bold italic font-sans text-left">
|
||||
<h2 dir="ltr" className="text-xs sm:text-base text-slate-400 font-bold italic font-sans text-center md:text-left">
|
||||
{product.nameEn}
|
||||
</h2>
|
||||
)}
|
||||
</div>
|
||||
<p className="text-xl text-canina-blue font-bold italic opacity-70 leading-relaxed max-w-2xl font-vazir mb-6 text-right" dir="rtl">
|
||||
<p className="text-base sm:text-xl text-canina-blue font-bold italic opacity-80 leading-relaxed max-w-2xl font-vazir mb-4 text-center md:text-right" dir="rtl">
|
||||
{isMounted && pets.length > 0 ? (
|
||||
product.optimisticTemplate?.replace("[PetName]", activePet?.name || "").replace("[OnSet]", product.onSetOfAction || "به زودی")
|
||||
) : (
|
||||
@ -250,7 +264,7 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
|
||||
)}
|
||||
</p>
|
||||
{fullProduct.shortDescription && (
|
||||
<p className="text-lg text-medical-gray-600 font-bold leading-relaxed max-w-3xl font-vazir border-r-4 border-canina-blue pr-6 py-2 bg-canina-blue/5 rounded-l-2xl">
|
||||
<p className="text-sm sm:text-lg text-medical-gray-600 font-bold leading-relaxed max-w-3xl font-vazir border-r-4 border-canina-blue pr-4 sm:pr-6 py-2 bg-canina-blue/5 rounded-l-2xl text-right w-full">
|
||||
{fullProduct.shortDescription}
|
||||
</p>
|
||||
)}
|
||||
@ -365,8 +379,8 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
|
||||
<Clock className="w-6 h-6" />
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-2xl font-black text-medical-gray-900 italic font-vazir">ماشین حساب هوشمند مصرف</h3>
|
||||
<p className="text-xs text-medical-gray-400 font-bold font-vazir mt-1">تخمین دقیق دوز روزانه و ماندگاری هر بسته بر اساس مشخصات پت شما</p>
|
||||
<h3 className="text-lg sm:text-2xl font-black text-medical-gray-900 italic font-vazir whitespace-nowrap">ماشین حساب هوشمند مصرف</h3>
|
||||
<p className="text-[11px] sm:text-xs text-medical-gray-400 font-bold font-vazir mt-0.5 sm:mt-1">تخمین دقیق دوز روزانه و ماندگاری هر بسته بر اساس مشخصات پت شما</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@ -128,51 +128,57 @@ export default function SmartAdvisor({ onComplete, rules = [] }: SmartAdvisorPro
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
className="grid md:grid-cols-3 gap-6 mb-12"
|
||||
className="grid grid-cols-1 md:grid-cols-3 gap-4 sm:gap-6 mb-8 sm:mb-12"
|
||||
>
|
||||
<div className="bg-white p-6 rounded-[2.5rem] border border-medical-gray-200/80 shadow-lg hover:shadow-xl transition-all group flex flex-col justify-between">
|
||||
<div className="bg-white p-4 sm:p-6 rounded-2xl sm:rounded-[2.5rem] border border-medical-gray-200/80 shadow-md sm:shadow-lg hover:shadow-xl transition-all group flex flex-col justify-between">
|
||||
<div>
|
||||
<div className="w-12 h-12 bg-canina-blue/10 rounded-2xl flex items-center justify-center text-canina-blue mb-4 group-hover:bg-canina-blue group-hover:text-white transition-all shadow-sm">
|
||||
<Pill className="w-6 h-6" />
|
||||
<div className="flex items-center gap-3 sm:block mb-2 sm:mb-0">
|
||||
<div className="w-9 h-9 sm:w-12 sm:h-12 bg-canina-blue/10 rounded-xl sm:rounded-2xl flex items-center justify-center text-canina-blue sm:mb-4 group-hover:bg-canina-blue group-hover:text-white transition-all shadow-sm flex-shrink-0">
|
||||
<Pill className="w-5 h-5 sm:w-6 sm:h-6" />
|
||||
</div>
|
||||
<h3 className="text-base sm:text-lg font-black text-medical-gray-900 sm:mb-2 font-vazir">چرا ثبت شناسنامه؟</h3>
|
||||
</div>
|
||||
<h3 className="text-lg font-black text-medical-gray-900 mb-2 font-vazir">چرا ثبت شناسنامه؟</h3>
|
||||
<p className="text-xs text-medical-gray-500 font-medium leading-relaxed font-vazir">
|
||||
مکملهای دارویی کانینا غلیظ و تخصصی هستند؛ الگوریتم هوشمند ما بر اساس سن، وزن و جثه پت شما، دوز دقیق مصرفی روزانه را محاسبه میکند تا حداکثر اثرگذاری ایجاد شود.
|
||||
مکملهای دارویی کانینا غلیظ و تخصصی هستند؛ الگوریتم هوشمند ما بر اساس سن، وزن و جثه پت شما، دوز دقیق مصرفی روزانه را محاسبه میکند.
|
||||
</p>
|
||||
</div>
|
||||
<div className="mt-4 pt-4 border-t border-medical-gray-100 text-[10px] font-black text-canina-blue flex items-center gap-1 font-vazir">
|
||||
<div className="mt-3 sm:mt-4 pt-3 sm:pt-4 border-t border-medical-gray-100 text-[10px] font-black text-canina-blue flex items-center gap-1 font-vazir">
|
||||
<Check className="w-3.5 h-3.5" />
|
||||
تضمین ایمنی و عدم اوردوز
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="bg-white p-6 rounded-[2.5rem] border border-medical-gray-200/80 shadow-lg hover:shadow-xl transition-all group flex flex-col justify-between">
|
||||
<div className="bg-white p-4 sm:p-6 rounded-2xl sm:rounded-[2.5rem] border border-medical-gray-200/80 shadow-md sm:shadow-lg hover:shadow-xl transition-all group flex flex-col justify-between">
|
||||
<div>
|
||||
<div className="w-12 h-12 bg-canina-blue/10 rounded-2xl flex items-center justify-center text-canina-blue mb-4 group-hover:bg-canina-blue group-hover:text-white transition-all shadow-sm">
|
||||
<Activity className="w-6 h-6" />
|
||||
<div className="flex items-center gap-3 sm:block mb-2 sm:mb-0">
|
||||
<div className="w-9 h-9 sm:w-12 sm:h-12 bg-canina-blue/10 rounded-xl sm:rounded-2xl flex items-center justify-center text-canina-blue sm:mb-4 group-hover:bg-canina-blue group-hover:text-white transition-all shadow-sm flex-shrink-0">
|
||||
<Activity className="w-5 h-5 sm:w-6 sm:h-6" />
|
||||
</div>
|
||||
<h3 className="text-base sm:text-lg font-black text-medical-gray-900 sm:mb-2 font-vazir">تطبیق علائم بالینی</h3>
|
||||
</div>
|
||||
<h3 className="text-lg font-black text-medical-gray-900 mb-2 font-vazir">تطبیق علائم بالینی</h3>
|
||||
<p className="text-xs text-medical-gray-500 font-medium leading-relaxed font-vazir">
|
||||
با انتخاب علائمی مثل لنگیدن، ریزش مو، یا اسهال، موتور هوشمند ما دقیقترین راهکار مکمل آلمانی مرتبط را به همراه دلایل علمی به شما پیشنهاد میدهد.
|
||||
با انتخاب علائمی مثل لنگیدن یا ریزش مو، دقیقترین راهکار مکمل آلمانی به همراه دلایل علمی به شما پیشنهاد میشود.
|
||||
</p>
|
||||
</div>
|
||||
<div className="mt-4 pt-4 border-t border-medical-gray-100 text-[10px] font-black text-canina-blue flex items-center gap-1 font-vazir">
|
||||
<div className="mt-3 sm:mt-4 pt-3 sm:pt-4 border-t border-medical-gray-100 text-[10px] font-black text-canina-blue flex items-center gap-1 font-vazir">
|
||||
<Check className="w-3.5 h-3.5" />
|
||||
پیشنهاد هدفمند و تخصصی
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="bg-white p-6 rounded-[2.5rem] border border-medical-gray-200/80 shadow-lg hover:shadow-xl transition-all group flex flex-col justify-between">
|
||||
<div className="bg-white p-4 sm:p-6 rounded-2xl sm:rounded-[2.5rem] border border-medical-gray-200/80 shadow-md sm:shadow-lg hover:shadow-xl transition-all group flex flex-col justify-between">
|
||||
<div>
|
||||
<div className="w-12 h-12 bg-canina-blue/10 rounded-2xl flex items-center justify-center text-canina-blue mb-4 group-hover:bg-canina-blue group-hover:text-white transition-all shadow-sm">
|
||||
<ShieldCheck className="w-6 h-6" />
|
||||
<div className="flex items-center gap-3 sm:block mb-2 sm:mb-0">
|
||||
<div className="w-9 h-9 sm:w-12 sm:h-12 bg-canina-blue/10 rounded-xl sm:rounded-2xl flex items-center justify-center text-canina-blue sm:mb-4 group-hover:bg-canina-blue group-hover:text-white transition-all shadow-sm flex-shrink-0">
|
||||
<ShieldCheck className="w-5 h-5 sm:w-6 sm:h-6" />
|
||||
</div>
|
||||
<h3 className="text-base sm:text-lg font-black text-medical-gray-900 sm:mb-2 font-vazir">پایش موجودی و یادآور</h3>
|
||||
</div>
|
||||
<h3 className="text-lg font-black text-medical-gray-900 mb-2 font-vazir">پایش موجودی و یادآور</h3>
|
||||
<p className="text-xs text-medical-gray-500 font-medium leading-relaxed font-vazir">
|
||||
پس از ایجاد شناسنامه، زمانهای مصرف مکملها تنظیم شده و سیستم قبل از اتمام دوره درمانی، پیام هشدار شارژ مجدد به شما ارسال خواهد کرد.
|
||||
زمانهای مصرف مکملها تنظیم شده و سیستم قبل از اتمام دوره درمانی، هشدار شارژ مجدد ارسال خواهد کرد.
|
||||
</p>
|
||||
</div>
|
||||
<div className="mt-4 pt-4 border-t border-medical-gray-100 text-[10px] font-black text-canina-blue flex items-center gap-1 font-vazir">
|
||||
<div className="mt-3 sm:mt-4 pt-3 sm:pt-4 border-t border-medical-gray-100 text-[10px] font-black text-canina-blue flex items-center gap-1 font-vazir">
|
||||
<Check className="w-3.5 h-3.5" />
|
||||
تکمیل منظم دوره درمان
|
||||
</div>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user