canina/frontend/application/components/PetProfile.tsx
parsa aghaei 204350eff8
Some checks failed
E2E Playwright Tests / Run Full E2E & Security Suites (push) Waiting to run
Deploy Canina / deploy (push) Has been cancelled
feat(financial): add enable/disable toggle for shelter animal charity and round-up donation
2026-09-13 09:41:56 +03:30

1565 lines
82 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client";
import React, { useState, useMemo, useEffect } from "react";
import { Product } from "../lib/data/products";
import { productService } from "../lib/services/productService";
import { isSpeciesCompatible, matchesMedicalSymptom } from "../lib/petCompatibility";
import { motion, AnimatePresence } from "motion/react";
import { PetProfileSkeleton } from "./Skeleton";
import SafeImage from "./SafeImage";
import {
Dog,
Cat,
ChevronRight,
ChevronLeft,
Heart,
Activity,
Weight,
Calendar,
ShieldCheck,
Stethoscope,
Plus,
Clock,
ClipboardList,
Package,
Star,
Edit3,
Trash2,
AlertTriangle,
TrendingUp,
Check
} from "lucide-react";
import { usePetStore, PetProfile as GlobalPetProfile, Reminder, HealthLog } from "../lib/store/usePetStore";
import { useCartStore } from "../lib/store/cartStore";
import { useSettingsStore } from "../lib/store/settingsStore";
import SmartAdvisor from "./SmartAdvisor";
import OrderDetailsModal from "./OrderDetailsModal";
import { toast } from "sonner";
import { toPersian, cn } from "../lib/utils";
import api, { BASE_DOMAIN } from "../lib/services/api";
import { useRouter, useSearchParams } from 'next/navigation';
export default function PetProfile({ initialView, advisorNeed, embedded = false }: {
initialView?: "index" | "detail" | "add" | "edit",
advisorNeed?: string | null,
embedded?: boolean
}) {
const router = useRouter();
const searchParams = useSearchParams();
const { pets, addPet, removePet, setActivePet, getActivePet, updatePet, addReminder, toggleReminder, addHealthLog } = usePetStore();
const { orders } = useCartStore();
const isCharityEnabled = useSettingsStore(
(state) =>
state.getBoolean("CHARITY_DONATION_ENABLED", true) &&
state.getBoolean("charity_donation_enabled", true) &&
state.getBoolean("charityDonationEnabled", true)
);
const activePet = getActivePet();
const [isLoading, setIsLoading] = useState(true);
const [products, setProducts] = useState<Product[]>([]);
const [prescriptions, setPrescriptions] = useState<any[]>([]);
const [selectedInvoiceOrder, setSelectedInvoiceOrder] = useState<any | null>(null);
useEffect(() => {
productService.getProducts({ limit: 999 })
.then(res => setProducts(res.data))
.catch(err => console.error("Error fetching products in PetProfile:", err));
if (typeof window !== 'undefined' && localStorage.getItem('accessToken')) {
api.get("/prescriptions")
.then(res => {
const data = Array.isArray(res.data) ? res.data : (res.data?.data || []);
setPrescriptions(data);
})
.catch(() => {});
}
}, []);
useEffect(() => {
const timer = setTimeout(() => setIsLoading(false), 800);
return () => clearTimeout(timer);
}, []);
const [view, setView] = useState<"index" | "detail" | "add" | "edit">(initialView || (pets.length > 0 ? "index" : "add"));
useEffect(() => {
if (initialView) {
Promise.resolve().then(() => setView(initialView));
}
}, [initialView]);
const [uploadProgress, setUploadProgress] = useState<number | null>(null);
const [activePetTab, setActivePetTab] = useState<"health" | "orders" | "prescriptions">("health");
// URL query param retention for pet and tab
useEffect(() => {
const petParam = searchParams.get('pet');
if (petParam && pets.length > 0) {
const matchedPet = pets.find(p => p.id === petParam || p.name === petParam);
if (matchedPet && matchedPet.id !== activePet?.id) {
setActivePet(matchedPet.id);
}
}
}, [searchParams, pets, activePet?.id, setActivePet]);
// URL query param retention for tab
useEffect(() => {
const tabParam = searchParams.get('tab');
if (tabParam && ['health', 'orders', 'prescriptions'].includes(tabParam)) {
setActivePetTab(tabParam as "health" | "orders" | "prescriptions");
}
}, [searchParams]);
const [petToDelete, setPetToDelete] = useState<GlobalPetProfile | null>(null);
// Modal states
const [isAddingReminder, setIsAddingReminder] = useState(false);
const [isAddingHealthLog, setIsAddingHealthLog] = useState(false);
// New Reminder form state
const [reminderForm, setReminderForm] = useState<Omit<Reminder, "id" | "completedDates">>({
title: "",
time: "08:00",
frequency: "روزانه",
productId: ""
});
// Health log form state
const [logForm, setLogForm] = useState<Omit<HealthLog, "id" | "date">>({
appetite: "عالی",
energy: "نرمال",
digestion: "نرمال",
note: ""
});
const petOrders = useMemo(() => {
if (!activePet) return [];
return orders.filter(o => o.petId === activePet.id);
}, [activePet, orders]);
const petPrescriptions = useMemo(() => {
if (!activePet) return [];
return prescriptions.filter(rx => rx.petId === activePet.id || rx.pet?.id === activePet.id || rx.petName === activePet.name);
}, [activePet, prescriptions]);
const petCharityTotal = useMemo(() => {
return petOrders.reduce((sum, o) => sum + (Number(o.charityDonation) || 0), 0);
}, [petOrders]);
const allCharityTotal = useMemo(() => {
return orders.reduce((sum, o) => sum + (Number(o.charityDonation) || 0), 0);
}, [orders]);
const [step, setStep] = useState(1);
const [formData, setFormData] = useState<Omit<GlobalPetProfile, "id">>({
name: "",
type: "سگ",
breed: "",
age: 0,
weight: 0,
activityLevel: "متوسط",
medicalConditions: [],
reminders: [],
logs: [],
consumptions: []
});
const recommendedProducts = useMemo(() => {
if (!activePet || products.length === 0) return [];
const picks: { product: Product, reason?: string }[] = [];
// Priority 1: Match activePet.medicalConditions directly against product.symptoms
if (activePet.medicalConditions && activePet.medicalConditions.length > 0) {
products.forEach(p => {
if (!isSpeciesCompatible(p.suitableFor, activePet.type)) return;
const matchedCondition = matchesMedicalSymptom(activePet.medicalConditions, p.symptoms, p.benefits);
if (matchedCondition && !picks.some(x => x.product.id === p.id)) {
picks.push({
product: p,
reason: `پیشنهاد هوشمند برای تسکین ${matchedCondition}`
});
}
});
}
// Priority 2: Biological & Life-stage factors
if (activePet.age >= 7) {
const seniorSupplements = products.filter(p =>
(p.id === "herz-vital" || p.slug?.includes("herz") || p.name.includes("قلب") || p.benefits?.includes("مسن")) &&
isSpeciesCompatible(p.suitableFor, activePet.type)
);
seniorSupplements.forEach(p => {
if (!picks.some(x => x.product.id === p.id)) {
picks.push({ product: p, reason: "محافظت از قلب و مفاصل در سنین بالا" });
}
});
} else if (activePet.age > 0 && activePet.age <= 1) {
const growthSupplements = products.filter(p =>
(p.name.includes("رشد") || p.benefits?.includes("تغذیه توله") || p.benefits?.includes("کلسیم")) &&
isSpeciesCompatible(p.suitableFor, activePet.type)
);
growthSupplements.forEach(p => {
if (!picks.some(x => x.product.id === p.id)) {
picks.push({ product: p, reason: "تغذیه متوازن و تقویت اسکلت در دوره رشد" });
}
});
}
if (activePet.activityLevel === "زیاد") {
const performanceSupplements = products.filter(p =>
(p.name.includes("انرژی") || p.benefits?.includes("عضله") || p.benefits?.includes("مفصل")) &&
isSpeciesCompatible(p.suitableFor, activePet.type)
);
performanceSupplements.forEach(p => {
if (!picks.some(x => x.product.id === p.id)) {
picks.push({ product: p, reason: "تقویت مفاصل و ریکاوری برای سطح فعالیت بالا" });
}
});
}
return picks;
}, [activePet, products]);
const handleNext = () => setStep(s => s + 1);
const handleBackStep = () => setStep(s => s - 1);
const handleSubmit = () => {
const cleanedConditions = (formData.medicalConditions || []).filter(c => !c.includes("هیچ‌کدام"));
const cleanedData = {
...formData,
medicalConditions: cleanedConditions
};
if (view === "edit" && activePet) {
updatePet(activePet.id, cleanedData);
toast.success("اطلاعات شناسنامه با موفقیت بروزرسانی شد");
setView("detail");
} else {
addPet(cleanedData);
toast.success("شناسنامه جدید با موفقیت صادر شد");
setView("detail");
}
setStep(1);
};
const handleHealthLogSubmit = () => {
if (activePet) {
addHealthLog(activePet.id, logForm);
toast.success("گزارش سلامت با موفقیت ثبت شد");
setIsAddingHealthLog(false);
setLogForm({
appetite: "عالی",
energy: "نرمال",
digestion: "نرمال",
note: ""
});
}
};
const handleReminderSubmit = () => {
if (activePet) {
if (!reminderForm.title) {
toast.error("لطفاً عنوان یادآور را وارد کنید");
return;
}
addReminder(activePet.id, reminderForm);
toast.success("یادآور با موفقیت ثبت شد");
setIsAddingReminder(false);
setReminderForm({
title: "",
time: "08:00",
frequency: "روزانه",
productId: ""
});
}
};
const handleToggleReminder = (reminder: Reminder) => {
if (activePet) {
const today = new Date().toISOString().split('T')[0];
toggleReminder(activePet.id, reminder.id, today);
const isCompleting = !reminder.completedDates.includes(today);
if (isCompleting) {
toast.success(`دوز ${reminder.title} تایید شد`);
}
}
};
const startEdit = () => {
if (activePet) {
setFormData({
name: activePet.name,
type: activePet.type,
breed: activePet.breed,
age: activePet.age,
weight: activePet.weight,
activityLevel: activePet.activityLevel,
medicalConditions: activePet.medicalConditions,
reminders: activePet.reminders || [],
logs: activePet.logs || [],
consumptions: activePet.consumptions || []
});
setView("edit");
setStep(1);
}
};
const confirmDelete = (pet: GlobalPetProfile) => {
setPetToDelete(pet);
};
const handlePetDelete = () => {
if (petToDelete) {
removePet(petToDelete.id);
toast.error(`شناسنامه ${petToDelete.name} حذف شد`);
setPetToDelete(null);
if (pets.length <= 1) {
setView("add");
} else {
setView("index");
}
}
};
if (isLoading && view === "detail" && activePet) {
return (
<div className="max-w-6xl mx-auto px-4 py-20" dir="rtl">
<PetProfileSkeleton />
</div>
);
}
// 1. Pet Index Page
if (view === "index") {
return (
<div className={cn(embedded ? "w-full font-vazir" : "min-h-screen bg-medical-gray-50 py-12 sm:py-20 px-2 sm:px-4 font-vazir")} dir="rtl">
<div className="max-w-6xl mx-auto">
<div className="flex flex-col md:flex-row justify-between items-center mb-12 gap-6">
<div>
<h1 className="text-4xl font-black text-medical-gray-900 italic">همدمهای من</h1>
<p className="text-medical-gray-500 mt-2 font-bold">مدیریت شناسنامههای سلامت و سوابق درمانی</p>
</div>
<button
onClick={() => {
setFormData({
name: "",
type: "سگ",
breed: "",
age: 0,
weight: 0,
activityLevel: "متوسط",
medicalConditions: [],
reminders: [],
logs: [],
consumptions: []
});
setView("add");
setStep(1);
}}
className="bg-canina-blue text-white px-8 py-4 rounded-[2rem] font-black shadow-xl shadow-canina-blue/20 hover:scale-105 transition-all flex items-center gap-3"
>
<Plus className="w-5 h-5" />
صدور شناسنامه جدید
</button>
</div>
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-8">
{pets.map(pet => (
<motion.div
key={pet.id}
whileHover={{ y: -5 }}
className="bg-white rounded-[3rem] border border-medical-gray-200 p-8 shadow-sm hover:shadow-2xl transition-all relative group"
>
<div className="w-24 h-24 bg-medical-gray-50 rounded-[2rem] flex items-center justify-center text-canina-blue mb-6 group-hover:bg-canina-blue group-hover:text-white transition-all shadow-inner">
{pet.type === "سگ" ? <Dog className="w-12 h-12" /> : <Cat className="w-12 h-12" />}
</div>
<h3 className="text-2xl font-black text-medical-gray-900 mb-1">{pet.name}</h3>
<p className="text-sm font-bold text-medical-gray-400 mb-6">{pet.breed}</p>
<div className="grid grid-cols-2 gap-4 mb-8">
<div className="bg-medical-gray-50 p-4 rounded-2xl flex flex-col items-center">
<span className="text-[10px] font-black text-medical-gray-400 uppercase tracking-widest">وزن</span>
<span className="text-lg font-black text-medical-gray-900">{toPersian(pet.weight)} <span className="text-xs">کیلوگرم</span></span>
</div>
<div className="bg-medical-gray-50 p-4 rounded-2xl flex flex-col items-center">
<span className="text-[10px] font-black text-medical-gray-400 uppercase tracking-widest">سن</span>
<span className="text-lg font-black text-medical-gray-900">{toPersian(pet.age)} <span className="text-xs">سال</span></span>
</div>
</div>
<button
onClick={() => {
setActivePet(pet.id);
setView("detail");
if (typeof window !== 'undefined') {
const url = new URL(window.location.href);
url.searchParams.set('pet', pet.id);
window.history.replaceState({}, '', url.toString());
}
}}
className="w-full py-4 bg-medical-gray-900 text-white rounded-2xl font-black hover:bg-canina-blue transition-all flex items-center justify-center gap-2 group-hover:shadow-lg"
>
مشاهده شناسنامه سلامت
<ChevronLeft className="w-4 h-4" />
</button>
<button
onClick={() => confirmDelete(pet)}
className="absolute top-8 left-8 text-medical-gray-300 hover:text-red-500 transition-colors"
>
<Trash2 className="w-5 h-5" />
</button>
</motion.div>
))}
</div>
</div>
{/* Delete Confirmation Modal */}
<AnimatePresence>
{petToDelete && (
<div className="fixed inset-0 z-[100] flex items-center justify-center p-4">
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
className="absolute inset-0 bg-medical-gray-900/60 backdrop-blur-sm"
onClick={() => setPetToDelete(null)}
/>
<motion.div
initial={{ scale: 0.9, opacity: 0 }}
animate={{ scale: 1, opacity: 1 }}
exit={{ scale: 0.9, opacity: 0 }}
className="relative bg-white rounded-[3rem] p-10 max-w-md w-full shadow-2xl text-center"
>
<div className="w-16 h-16 bg-red-50 text-red-500 rounded-2xl flex items-center justify-center mx-auto mb-6">
<AlertTriangle className="w-8 h-8" />
</div>
<h3 className="text-2xl font-black text-medical-gray-900 mb-4">حذف شناسنامه {petToDelete.name}؟</h3>
<p className="text-medical-gray-500 font-medium mb-10 leading-relaxed italic">
آیا از حذف شناسنامه {petToDelete.name} اطمینان دارید؟ این عمل غیرقابل بازگشت است و تمام سوابق سلامت او حذف خواهد شد.
</p>
<div className="flex gap-4">
<button
onClick={() => setPetToDelete(null)}
className="flex-1 py-4 bg-medical-gray-100 text-medical-gray-900 rounded-2xl font-black hover:bg-medical-gray-200 transition-all"
>
انصراف
</button>
<button
onClick={handlePetDelete}
className="flex-1 py-4 bg-red-500 text-white rounded-2xl font-black hover:bg-red-600 transition-all shadow-lg shadow-red-500/20"
>
حذف نهایی
</button>
</div>
</motion.div>
</div>
)}
</AnimatePresence>
</div>
);
}
// 2. Add / Edit Pet Steps
if (view === "add" || view === "edit") {
if (view === "add" && pets.length === 0) {
return (
<div className={cn(embedded ? "w-full font-vazir" : "min-h-screen bg-medical-gray-50 py-8 px-2 sm:px-4 font-vazir")} dir="rtl">
<div className="max-w-5xl mx-auto space-y-6">
{/* Render SmartAdvisor directly without redundant top banner */}
<SmartAdvisor
onComplete={(data) => {
const newPet = { ...data, id: Date.now().toString(), reminders: [], logs: [], consumptions: [] } as unknown as GlobalPetProfile;
addPet(newPet);
setActivePet(newPet.id);
toast.success(`شناسنامه سلامت ${data.name} با موفقیت صادر شد`);
setView("detail");
}}
/>
</div>
</div>
);
}
return (
<div className={cn(embedded ? "w-full font-vazir" : "min-h-screen bg-medical-gray-50 py-12 sm:py-20 px-2 sm:px-4 font-vazir")} dir="rtl">
<div className="max-w-2xl mx-auto">
<div className="bg-white rounded-[2rem] sm:rounded-[3rem] p-6 sm:p-12 border border-medical-gray-200 shadow-2xl relative overflow-hidden">
{/* Progress Bar */}
<div className="absolute top-0 left-0 w-full h-1.5 bg-medical-gray-100 font-vazir">
<motion.div
className="h-full bg-canina-blue"
initial={{ width: "0%" }}
animate={{ width: `${(step / 3) * 100}%` }}
/>
</div>
<div className="mb-10 flex items-center justify-between">
<div>
<h2 className="text-3xl font-black text-medical-gray-900">{view === "edit" ? "ویرایش شناسنامه" : "صدور شناسنامه سلامت"}</h2>
<p className="text-medical-gray-500 mt-2 font-medium">مرحله {toPersian(step)} از {toPersian(3)}: بروزرسانی اطلاعات تخصصی</p>
</div>
<div className="w-16 h-16 bg-canina-blue/10 rounded-2xl flex items-center justify-center text-canina-blue">
<ClipboardList className="w-8 h-8" />
</div>
</div>
<AnimatePresence mode="wait">
{step === 1 && (
<motion.div
key="step1"
initial={{ opacity: 0, x: 20 }}
animate={{ opacity: 1, x: 0 }}
exit={{ opacity: 0, x: -20 }}
className="space-y-6"
>
<div>
<label className="block text-[10px] font-black text-medical-gray-400 uppercase tracking-widest mb-3 pr-2">نام همدم</label>
<input
autoFocus
type="text"
value={formData.name}
onChange={e => setFormData({ ...formData, name: e.target.value })}
className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-2xl py-4 px-6 focus:ring-2 focus:ring-canina-blue/20 outline-none font-black text-lg"
placeholder="مثلاً: لوسی"
/>
</div>
<div>
<label className="block text-[10px] font-black text-medical-gray-400 uppercase tracking-widest mb-3 pr-2">گونه جانوری</label>
<div className="grid grid-cols-2 gap-4">
<button
onClick={() => setFormData({ ...formData, type: "سگ" })}
className={`flex items-center justify-center gap-3 py-4 border-2 rounded-2xl transition-all ${formData.type === "سگ" ? 'border-canina-blue bg-canina-blue/5 text-canina-blue font-black' : 'border-medical-gray-200 text-medical-gray-400 font-bold'}`}
>
<Dog className="w-6 h-6" />
سگ
</button>
<button
onClick={() => setFormData({ ...formData, type: "گربه" })}
className={`flex items-center justify-center gap-3 py-4 border-2 rounded-2xl transition-all ${formData.type === "گربه" ? 'border-canina-blue bg-canina-blue/5 text-canina-blue font-black' : 'border-medical-gray-200 text-medical-gray-400 font-bold'}`}
>
<Cat className="w-6 h-6" />
گربه
</button>
</div>
</div>
<div>
<label className="block text-[10px] font-black text-medical-gray-400 uppercase tracking-widest mb-3 pr-2">نژاد دقیق</label>
<input
type="text"
value={formData.breed}
onChange={e => setFormData({ ...formData, breed: e.target.value })}
className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-2xl py-4 px-6 focus:ring-2 focus:ring-canina-blue/20 outline-none font-bold"
placeholder="آلمانی، پرشین، میکس و..."
/>
</div>
<div>
<label className="block text-[10px] font-black text-medical-gray-400 uppercase tracking-widest mb-3 pr-2">تصویر یا عکس پت</label>
<div className="flex flex-col sm:flex-row items-center gap-4 bg-medical-gray-50 p-4 rounded-2xl border border-medical-gray-200">
{/* Photo preview container */}
<div className="relative w-20 h-20 rounded-2xl overflow-hidden bg-medical-gray-200 border-2 border-dashed border-medical-gray-300 flex items-center justify-center shrink-0">
{formData.imageUrl ? (
<SafeImage
src={formData.imageUrl.startsWith('http') ? formData.imageUrl : `${BASE_DOMAIN}${formData.imageUrl}`}
alt="عکس پت"
className="w-full h-full"
imgClassName="w-full h-full object-cover"
/>
) : (
<Dog className="w-8 h-8 text-medical-gray-400" />
)}
{uploadProgress !== null && (
<div className="absolute inset-0 bg-black/60 backdrop-blur-xs flex flex-col items-center justify-center text-white">
<div className="relative w-10 h-10 flex items-center justify-center">
<svg className="w-full h-full -rotate-90" viewBox="0 0 36 36">
<path
className="text-white/20"
strokeWidth="3"
stroke="currentColor"
fill="none"
d="M18 2.0845 a 15.9155 15.9155 0 0 1 0 31.831 a 15.9155 15.9155 0 0 1 0 -31.831"
/>
<path
className="text-canina-blue"
strokeDasharray={`${uploadProgress}, 100`}
strokeWidth="3"
strokeLinecap="round"
stroke="currentColor"
fill="none"
d="M18 2.0845 a 15.9155 15.9155 0 0 1 0 31.831 a 15.9155 15.9155 0 0 1 0 -31.831"
/>
</svg>
<span className="absolute text-[9px] font-black">{toPersian(uploadProgress)}%</span>
</div>
</div>
)}
</div>
<div className="flex-1 w-full space-y-2">
<div className="flex gap-2">
<input
type="text"
value={formData.imageUrl || ''}
onChange={e => setFormData({ ...formData, imageUrl: e.target.value })}
className="flex-1 bg-white border border-medical-gray-200 rounded-xl py-2.5 px-3 focus:ring-2 focus:ring-canina-blue/20 outline-none text-xs font-mono"
placeholder="آدرس اینترنتی تصویر..."
/>
<label className="bg-canina-blue text-white px-4 py-2.5 rounded-xl text-xs font-black cursor-pointer hover:bg-canina-dark transition-all flex items-center justify-center shrink-0 shadow-xs">
انتخاب تصویر
<input
type="file"
accept="image/*"
className="hidden"
onChange={async (e) => {
const file = e.target.files?.[0];
if (!file) return;
const fd = new FormData();
fd.append('file', file);
setUploadProgress(10);
try {
const res = await api.post('/pets/upload-image', fd, {
headers: { 'Content-Type': 'multipart/form-data' },
onUploadProgress: (progressEvent) => {
const total = progressEvent.total || file.size;
const percent = Math.round((progressEvent.loaded * 100) / total);
setUploadProgress(percent);
}
});
const url = res.data?.url || res.data?.path || res.data?.data?.url;
if (url) {
setFormData({ ...formData, imageUrl: url });
toast.success("تصویر با موفقیت آپلود شد");
}
} catch (err) {
console.error("Pet image upload error:", err);
toast.error("خطا در آپلود تصویر");
} finally {
setTimeout(() => setUploadProgress(null), 500);
}
}}
/>
</label>
</div>
<p className="text-[10px] text-medical-gray-400 font-bold">فرمتهای مجاز: JPG, PNG (حداکثر ۱۰ مگابایت)</p>
</div>
</div>
</div>
</motion.div>
)}
{step === 2 && (
<motion.div
key="step2"
initial={{ opacity: 0, x: 20 }}
animate={{ opacity: 1, x: 0 }}
exit={{ opacity: 0, x: -20 }}
className="space-y-6"
>
<div className="grid md:grid-cols-2 gap-6">
<div>
<label className="block text-[10px] font-black text-medical-gray-400 uppercase tracking-widest mb-3 pr-2">سن (سال)</label>
<input
type="number"
value={formData.age || ""}
onChange={e => setFormData({ ...formData, age: parseInt(e.target.value) })}
className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-2xl py-4 px-6 focus:ring-2 focus:ring-canina-blue/20 outline-none font-black text-lg"
placeholder="۳"
/>
</div>
<div>
<label className="block text-[10px] font-black text-medical-gray-400 uppercase tracking-widest mb-3 pr-2">وزن نهایی (کیلوگرم)</label>
<div className="relative">
<input
type="number"
value={formData.weight || ""}
onChange={e => setFormData({ ...formData, weight: parseFloat(e.target.value) })}
className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-2xl py-4 pr-6 pl-12 focus:ring-2 focus:ring-canina-blue/20 outline-none font-black text-lg"
/>
<Weight className="absolute left-4 top-1/2 -translate-y-1/2 w-5 h-5 text-medical-gray-400" />
</div>
</div>
</div>
<div>
<label className="block text-[10px] font-black text-medical-gray-400 uppercase tracking-widest mb-3 pr-2">سطح فعالیت روزانه</label>
<div className="grid grid-cols-3 gap-3">
{["کم", "متوسط", "زیاد"].map(level => (
<button
key={level}
onClick={() => setFormData({ ...formData, activityLevel: level as "کم" | "متوسط" | "زیاد" })}
className={`py-4 border-2 rounded-2xl transition-all text-sm font-black italic ${formData.activityLevel === level ? 'border-canina-blue bg-canina-blue/5 text-canina-blue shadow-lg shadow-canina-blue/10' : 'border-medical-gray-100 text-medical-gray-400'}`}
>
{level}
</button>
))}
</div>
</div>
</motion.div>
)}
{step === 3 && (
<motion.div
key="step3"
initial={{ opacity: 0, x: 20 }}
animate={{ opacity: 1, x: 0 }}
exit={{ opacity: 0, x: -20 }}
className="space-y-6"
>
<label className="block text-[10px] font-black text-medical-gray-400 uppercase tracking-widest mb-3 pr-2">سوابق درمانی و موارد خاص</label>
<div className="grid grid-cols-1 gap-3">
{[
"هیچ‌کدام (سلامت کامل و بدون سابقه بیماری)",
"جراحی مفاصل",
"زایمان اخیر",
"بارداری",
"مشکلات گوارشی",
"ریزش موی شدید",
"بی‌اشتهایی"
].map(condition => {
const isNone = condition.includes("هیچ‌کدام");
const isSelected = isNone
? (formData.medicalConditions.length === 0 || formData.medicalConditions.includes(condition))
: formData.medicalConditions.includes(condition);
return (
<button
key={condition}
type="button"
onClick={() => {
if (isNone) {
setFormData({
...formData,
medicalConditions: ["هیچ‌کدام (سلامت کامل و بدون سابقه بیماری)"]
});
} else {
const filtered = formData.medicalConditions.filter(c => !c.includes("هیچ‌کدام"));
const updated = filtered.includes(condition)
? filtered.filter(c => c !== condition)
: [...filtered, condition];
setFormData({
...formData,
medicalConditions: updated.length === 0 ? ["هیچ‌کدام (سلامت کامل و بدون سابقه بیماری)"] : updated
});
}
}}
className={`flex items-center gap-4 p-4 border-2 rounded-2xl transition-all ${isSelected ? 'border-canina-blue bg-canina-blue/5 text-canina-blue' : 'border-medical-gray-50 text-medical-gray-500'}`}
>
<div className={`w-6 h-6 rounded-lg flex items-center justify-center border ${isSelected ? 'bg-canina-blue border-canina-blue text-white' : 'border-medical-gray-200'}`}>
{isSelected && <ShieldCheck className="w-3.5 h-3.5" />}
</div>
<span className="font-black text-sm italic">{condition}</span>
</button>
);
})}
<div className="pt-2">
<label className="block text-[10px] font-black text-medical-gray-400 uppercase tracking-widest mb-2 pr-2">
توضیحات و سوابق تکمیلی (اختیاری)
</label>
<textarea
rows={3}
value={formData.extraNotes || formData.notes || ""}
onChange={e => setFormData({ ...formData, extraNotes: e.target.value, notes: e.target.value })}
placeholder="سابقه جراحی، حساسیت دارویی، رژیم غذایی یا هر نکته دیگری که پزشکان کنینا باید بدانند..."
className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-2xl p-4 text-xs font-medium text-medical-gray-900 focus:ring-2 focus:ring-canina-blue/20 outline-none resize-none leading-relaxed"
/>
</div>
</div>
</motion.div>
)}
</AnimatePresence>
<div className="mt-12 flex gap-4">
<button
onClick={() => {
if (view === "edit") setView("detail");
else if (pets.length > 0) setView("index");
else router.back();
}}
className="absolute top-8 left-8 text-medical-gray-400 hover:text-canina-blue transition-colors text-[10px] font-black uppercase tracking-widest"
>
انصراف
</button>
{step > 1 && (
<button
onClick={handleBackStep}
className="flex-1 bg-medical-gray-50 text-medical-gray-500 py-4 rounded-2xl font-black flex items-center justify-center gap-2 hover:bg-medical-gray-100 transition-all"
>
<ChevronRight className="w-5 h-5" />
قبلی
</button>
)}
<button
onClick={step === 3 ? handleSubmit : handleNext}
disabled={step === 1 && (!formData.name || !formData.type)}
className="flex-[2] bg-medical-gray-900 text-white py-4 rounded-2xl font-black flex items-center justify-center gap-2 disabled:opacity-50 hover:bg-canina-blue transition-all"
>
{step === 3 ? (view === "edit" ? "ذخیره تغییرات" : "مشاهده پرونده سلامت") : "گام بعدی"}
<ChevronLeft className="w-5 h-5" />
</button>
</div>
</div>
</div>
</div>
);
}
// 3. Detailed Dashboard View
if (!activePet) {
if (pets.length > 0) {
return (
<div className="max-w-6xl mx-auto px-4 py-20" dir="rtl">
<PetProfileSkeleton />
</div>
);
}
return (
<div className={cn(embedded ? "w-full font-vazir" : "min-h-screen bg-medical-gray-50 py-8 px-2 sm:px-4 font-vazir")} dir="rtl">
<div className="max-w-5xl mx-auto space-y-6">
<SmartAdvisor
onComplete={async (data) => {
const newPet = { ...data, id: Date.now().toString(), reminders: [], logs: [], consumptions: [] } as unknown as GlobalPetProfile;
await addPet(newPet);
setActivePet(newPet.id);
toast.success(`شناسنامه سلامت ${data.name} با موفقیت صادر شد`);
setView("detail");
}}
/>
</div>
</div>
);
}
return (
<div className={cn(embedded ? "w-full font-vazir" : "min-h-screen bg-medical-gray-50 py-8 sm:py-12 px-2 sm:px-4 font-vazir")} dir="rtl">
<div className="max-w-7xl mx-auto space-y-10">
{/* Navigation Bar */}
<div className="flex flex-col md:flex-row justify-between items-start md:items-center gap-6">
<div className="flex items-center gap-2 text-[10px] font-black text-medical-gray-400 uppercase tracking-widest">
<span className="cursor-pointer hover:text-canina-blue" onClick={() => setView("index")}>همدمهای من</span>
<ChevronLeft className="w-3 h-3" />
<span className="text-canina-blue">پرونده سلامت {activePet?.name}</span>
</div>
<div className="flex gap-3">
<button
onClick={startEdit}
className="px-6 py-2.5 bg-canina-blue text-white rounded-xl text-xs font-black shadow-lg shadow-canina-blue/20 hover:scale-105 transition-all flex items-center gap-2"
>
<Edit3 className="w-3.5 h-3.5" />
<span>ویرایش پرونده</span>
</button>
<button
onClick={() => setView("index")}
className="px-6 py-2.5 bg-white border border-medical-gray-200 rounded-xl text-xs font-black text-medical-gray-700 hover:border-canina-blue hover:text-canina-blue transition-all flex items-center gap-1.5"
>
<span>بازگشت به لیست</span>
<ChevronLeft className="w-3.5 h-3.5" />
</button>
</div>
</div>
{/* Profile Card */}
<section className={cn("grid gap-8", isCharityEnabled ? "lg:grid-cols-3" : "lg:grid-cols-3")}>
<div className="lg:col-span-2 bg-white rounded-[3.5rem] p-10 border border-medical-gray-200 shadow-xl flex flex-col md:flex-row gap-10 items-center relative overflow-hidden">
<div className="absolute top-0 left-0 w-32 h-32 bg-canina-blue/5 rounded-full blur-[60px] -translate-x-1/2 -translate-y-1/2" />
<div className="w-44 h-44 rounded-[2.5rem] bg-gradient-to-tr from-canina-blue to-blue-400 p-1 flex-shrink-0 shadow-2xl">
<div className="w-full h-full bg-white rounded-[2.2rem] flex items-center justify-center text-canina-blue">
{activePet.type === "سگ" ? <Dog className="w-24 h-24" /> : <Cat className="w-24 h-24" />}
</div>
</div>
<div className="flex-1 text-center md:text-right relative z-10">
<div className="flex flex-col md:flex-row md:items-end gap-3 mb-6">
<h2 className="text-5xl font-black text-medical-gray-900 italic leading-none">{activePet.name}</h2>
<span className="text-sm font-bold text-medical-gray-400 mb-1">{activePet.breed}</span>
</div>
<div className="grid grid-cols-2 sm:grid-cols-4 gap-4 mb-8">
{[
{ icon: <Weight className="w-3.5 h-3.5" />, label: "وزن", value: `${toPersian(activePet.weight)} کیلوگرم` },
{ icon: <Calendar className="w-3.5 h-3.5" />, label: "سن", value: `${toPersian(activePet.age)} سال` },
{ icon: <Activity className="w-3.5 h-3.5" />, label: "فعالیت", value: activePet.activityLevel },
{ icon: <ShieldCheck className="w-3.5 h-3.5" />, label: "وضعیت", value: "نرمال" },
].map((item, idx) => (
<div key={idx} className="bg-medical-gray-50 border border-medical-gray-100 p-3 rounded-2xl">
<div className="flex items-center gap-1.5 text-[8px] font-black text-medical-gray-400 uppercase tracking-widest mb-1">
{item.icon}
{item.label}
</div>
<div className="text-[12px] font-black text-medical-gray-900">{item.value}</div>
</div>
))}
</div>
<div className="flex flex-wrap gap-2">
{activePet.medicalConditions.map(c => (
<div key={c} className="bg-canina-blue text-white px-4 py-2 rounded-xl text-[10px] font-bold border border-white/10 flex items-center gap-2 shadow-sm">
<Stethoscope className="w-3 h-3" />
{c}
</div>
))}
</div>
</div>
</div>
<div className={cn("bg-canina-blue rounded-[3.5rem] p-10 text-white flex flex-col justify-between relative overflow-hidden shadow-2xl group", !isCharityEnabled && "lg:col-span-1")}>
<div className="absolute top-0 right-0 p-8 opacity-20 group-hover:rotate-12 transition-transform duration-700">
<Activity className="w-16 h-16 text-white" />
</div>
<div className="mt-16 relative z-10">
<div className="text-[10px] font-black uppercase tracking-[0.3em] text-white/70 mb-2">امتیاز سلامت پایش شده</div>
<div className="text-7xl font-black italic text-white flex items-baseline gap-2">
{toPersian(88)}
<span className="text-2xl not-italic text-white/50">/۱۰۰</span>
</div>
</div>
<div className="mt-10 relative z-10">
<div className="h-2 w-full bg-white/10 rounded-full overflow-hidden border border-white/10 mb-3">
<motion.div initial={{ width: 0 }} animate={{ width: "88%" }} className="h-full bg-white" />
</div>
<p className="text-[10px] text-white font-bold italic leading-relaxed">
بر اساس پایش هوشمند، وضعیت {activePet.name} در سطح «ایدهآل» قرار دارد.
</p>
</div>
</div>
{/* Kindness Footprint Widget for Pet */}
{isCharityEnabled && (
<div className="bg-pink-50 rounded-[3.5rem] p-10 border border-pink-100 relative overflow-hidden flex flex-col justify-between">
<div className="absolute -bottom-8 -left-8 opacity-5">
<Heart className="w-48 h-48 fill-pink-500" />
</div>
<div className="flex items-center gap-4 mb-6">
<div className="w-12 h-12 bg-pink-500 rounded-2xl flex items-center justify-center text-white shadow-lg shadow-pink-100">
<Heart className="w-6 h-6 fill-white" />
</div>
<div>
<h3 className="text-xl font-black text-medical-gray-900 italic">ردپای مهربانی {activePet.name}</h3>
<p className="text-[10px] font-black text-pink-500 uppercase tracking-widest mt-1">سفیر مهربانی: {activePet.name}</p>
</div>
</div>
<div className="space-y-4 relative z-10">
<div className="bg-white/90 backdrop-blur-sm rounded-2xl p-4 border border-pink-100 space-y-2.5">
<div className="flex items-center justify-between">
<span className="text-xs font-bold text-medical-gray-500">کمک اهدایی با نام {activePet.name}:</span>
<span className="text-sm font-black text-pink-600 font-mono">
{toPersian(petCharityTotal.toLocaleString())} <span className="text-[10px] font-normal">تومان</span>
</span>
</div>
{allCharityTotal > 0 && (
<div className="flex items-center justify-between text-[11px] font-bold text-medical-gray-400 pt-2 border-t border-pink-50">
<span>مجموع مهربانی کل حساب:</span>
<span>{toPersian(allCharityTotal.toLocaleString())} تومان</span>
</div>
)}
</div>
<p className="text-xs text-medical-gray-600 font-medium leading-relaxed">
{petCharityTotal > 0 ? (
<>«{activePet.name}» با خریدهای مکمل خود تا کنون <strong className="text-pink-600">{toPersian(petCharityTotal.toLocaleString())} تومان</strong> به درمان و تغذیه حیوانات نیازمند پناهگاهی کمک کرده است.</>
) : (
<>با هر خرید برای «{activePet.name}» میتوانید با انتخاب گزینه ردپای مهربانی، مبلغی را به نام او به پناهگاههای حیوانات اختصاص دهید.</>
)}
</p>
</div>
</div>
)}
</section>
{/* Refill & Stock Tracking */}
<section className="bg-white rounded-[3.5rem] p-10 border border-medical-gray-200 shadow-sm relative overflow-hidden">
<div className="absolute top-0 left-0 w-full h-1 bg-gradient-to-r from-canina-blue to-blue-300" />
<div className="flex items-center justify-between mb-8">
<div className="flex items-center gap-3">
<Package className="w-8 h-8 text-canina-blue" />
<h3 className="text-2xl font-black text-medical-gray-900 italic">پایش موجودی مکملها</h3>
</div>
<div className="text-[10px] font-black text-medical-gray-400 uppercase tracking-widest hidden md:block">بروزرسانی لحظهای بر اساس مصرف</div>
</div>
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-6">
{(activePet?.consumptions || []).length === 0 ? (
<div className="col-span-full py-12 text-center bg-medical-gray-50 rounded-[2.5rem] border border-dashed border-medical-gray-200 p-6 space-y-4">
<div>
<p className="text-medical-gray-700 font-black text-sm">هنوز محصولی برای پایش موجودی این پت ثبت نشده است.</p>
<p className="text-xs text-medical-gray-500 mt-1">با ثبت سفارش جدید، الگوریتم پایش هوشمند کالا به صورت خودکار فعال میشود. همچنین میتوانید محصول مورد مصرف فعلی را انتخاب کنید:</p>
</div>
<div className="flex flex-wrap justify-center gap-2 max-w-xl mx-auto pt-2">
{products.slice(0, 5).map(p => (
<button
key={p.id}
onClick={() => {
const newConsumptions = [...(activePet.consumptions || []), {
productId: p.id,
packageSize: p.packageSize || 60,
remaining: p.packageSize || 60
}];
updatePet(activePet.id, { consumptions: newConsumptions });
toast.success(`مکمل ${p.name} به لیست پایش اضافه شد`);
}}
className="px-3.5 py-2 bg-white border border-medical-gray-200 hover:border-canina-blue hover:bg-canina-blue/5 text-medical-gray-800 text-xs font-bold rounded-xl transition-all flex items-center gap-1.5 shadow-xs"
>
<span>+ افزودن {p.name}</span>
</button>
))}
</div>
</div>
) : (
activePet.consumptions.map((consumption) => {
const product = products.find(p => p.id === consumption.productId);
if (!product) return null;
const percentage = (consumption.remaining / (consumption.packageSize || 1)) * 100;
const isLow = percentage < 25;
return (
<div key={consumption.productId} className="bg-medical-gray-50 p-6 rounded-3xl border border-medical-gray-100 group">
<div className="flex justify-between items-start mb-4">
<div>
<h4 className="text-sm font-black text-medical-gray-900 mb-1">{product.name}</h4>
<p className="text-[10px] text-medical-gray-400 font-bold">باقیمانده: {toPersian(consumption.remaining)} واحد</p>
</div>
<div className={cn(
"w-12 h-12 rounded-2xl flex items-center justify-center font-black text-xs",
isLow ? "bg-red-50 text-red-500 animate-pulse" : "bg-white text-canina-blue shadow-inner"
)}>
{toPersian(Math.round(percentage))}%
</div>
</div>
<div className="h-2 w-full bg-medical-gray-200 rounded-full overflow-hidden mb-4">
<motion.div
initial={{ width: 0 }}
animate={{ width: `${Math.min(100, Math.max(0, percentage))}%` }}
className={cn("h-full", isLow ? "bg-red-500" : "bg-canina-blue")}
/>
</div>
{isLow && (
<button
onClick={() => router.push(`/shop/${product.id}`)}
className="w-full py-2 bg-red-500 text-white rounded-xl text-[10px] font-black uppercase tracking-widest hover:bg-red-600 transition-all flex items-center justify-center gap-2"
>
<Package className="w-3.5 h-3.5" />
سفارش مجدد (Refill)
</button>
)}
</div>
);
})
)}
</div>
</section>
{/* Tab Selection */}
<div className="flex border-b border-medical-gray-200 gap-8 px-4">
{[
{ id: "health", label: "داشبورد سلامت و یادآوری‌ها", icon: <Heart className="w-4 h-4" /> },
{ id: "orders", label: "سوابق خرید و فاکتورها", icon: <Package className="w-4 h-4" /> },
{ id: "prescriptions", label: "نسخه‌های پزشکی این همدم", icon: <Stethoscope className="w-4 h-4" /> },
].map(tab => (
<button
key={tab.id}
onClick={() => setActivePetTab(tab.id as "health" | "orders" | "prescriptions")}
className={`pb-4 flex items-center gap-2 text-sm font-black transition-all relative cursor-pointer ${activePetTab === tab.id ? "text-canina-blue" : "text-medical-gray-400 hover:text-medical-gray-600"}`}
>
{tab.icon}
{tab.label}
{activePetTab === tab.id && <motion.div layoutId="petTab" className="absolute bottom-0 left-0 right-0 h-1 bg-canina-blue rounded-full" />}
</button>
))}
</div>
{activePetTab === "health" ? (
<>
{/* Personalized Recommendations */}
<section>
<div className="flex items-center justify-between mb-8 px-4">
<div className="flex items-center gap-4">
<div className="w-12 h-12 bg-white rounded-2xl flex items-center justify-center text-canina-blue shadow-lg border border-medical-gray-100">
<Star className="w-6 h-6" />
</div>
<h3 className="text-3xl font-black text-medical-gray-900 italic">توصیههای درمانی هوشمند</h3>
</div>
<p className="text-[10px] font-black text-medical-gray-400 uppercase tracking-wider">کاتالوگ رسمی کنینا آلمان</p>
</div>
{recommendedProducts.length === 0 ? (
<div className="p-8 bg-medical-gray-50/70 border border-dashed border-medical-gray-200 rounded-3xl text-center">
<p className="text-xs font-bold text-medical-gray-500">
بر اساس آخرین وضعیت پایش شده، نیاز درمانی فعالی برای {activePet.name} ثبت نشده است. جهت حفظ سلامتی عمومی میتوانید از کاتالوگ محصولات دیدن فرمایید.
</p>
</div>
) : (
<div className="grid md:grid-cols-2 lg:grid-cols-4 gap-6">
{recommendedProducts.map(({ product: p, reason }) => (
<motion.div
key={p.id}
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
onClick={() => router.push(`/shop/${p.slug || p.id}`)}
className="bg-white rounded-[2.5rem] p-6 border border-medical-gray-200 hover:shadow-2xl transition-all cursor-pointer group flex flex-col justify-between relative overflow-hidden"
>
{reason && (
<div className="absolute top-0 left-0 right-0 bg-canina-blue/10 py-2 px-4 text-[9px] font-black text-canina-blue text-center border-b border-canina-blue/10">
{reason}
</div>
)}
<div className={cn("aspect-square bg-medical-gray-50 rounded-[1.5rem] p-6 mb-6 flex items-center justify-center overflow-hidden", reason ? "mt-8" : "")}>
<SafeImage src={p.image} alt={p.name} className="w-full h-full group-hover:scale-110 transition-transform duration-500" imgClassName="object-contain" />
</div>
<div>
<h4 className="text-lg font-black text-medical-gray-900 group-hover:text-canina-blue transition-colors mb-2 italic">{p.name}</h4>
<p className="text-xs text-medical-gray-400 line-clamp-2 leading-relaxed mb-6 font-medium">{p.benefits}</p>
<button className="w-full py-3.5 bg-medical-gray-900 text-white rounded-xl text-[10px] font-black uppercase tracking-widest group-hover:bg-canina-blue transition-colors flex items-center justify-center gap-2">
بررسی تخصصی
<ChevronLeft className="w-3.5 h-3.5" />
</button>
</div>
</motion.div>
))}
</div>
)}
</section>
<div className="grid lg:grid-cols-2 gap-10">
{/* Reminders */}
<div className="bg-white rounded-[3rem] border border-medical-gray-200 p-10 shadow-sm">
<div className="flex items-center justify-between mb-10">
<div className="flex items-center gap-3">
<Clock className="w-8 h-8 text-canina-blue" />
<h3 className="text-2xl font-black text-medical-gray-900 italic">یادآورهای فعال</h3>
</div>
<TrendingUp className="w-6 h-6 text-green-500" />
</div>
<div className="space-y-4">
{(activePet?.reminders || []).length === 0 ? (
<div className="text-center py-10 bg-medical-gray-50 rounded-2xl border border-dashed border-medical-gray-200">
<p className="text-sm font-bold text-medical-gray-400 italic">هنوز یادآوری ثبت نشده است</p>
</div>
) : (
(activePet?.reminders || []).map((reminder) => {
const today = new Date().toISOString().split('T')[0];
const isCompleted = reminder.completedDates.includes(today);
return (
<div
key={reminder.id}
className={cn(
"flex items-center justify-between p-5 rounded-2xl border transition-all group",
isCompleted ? "bg-green-50 border-green-200" : "bg-medical-gray-50 border-medical-gray-100 hover:border-canina-blue/30"
)}
>
<div className="flex items-center gap-4">
<button
onClick={() => handleToggleReminder(reminder)}
className={cn(
"w-10 h-10 rounded-xl flex items-center justify-center shadow-inner transition-colors",
isCompleted ? "bg-green-500 text-white" : "bg-white text-medical-gray-300 hover:text-canina-blue"
)}
>
{isCompleted ? <Check className="w-5 h-5" /> : <Clock className="w-5 h-5" />}
</button>
<div>
<h5 className={cn("text-[12px] font-black italic", isCompleted ? "text-green-700" : "text-medical-gray-900")}>{reminder.title}</h5>
<p className="text-[10px] text-medical-gray-400 font-bold">{toPersian(reminder.time)} - {reminder.frequency}</p>
</div>
</div>
</div>
);
})
)}
</div>
<button
onClick={() => setIsAddingReminder(true)}
className="w-full mt-8 py-5 border-2 border-dashed border-medical-gray-200 rounded-2xl text-medical-gray-400 font-black hover:border-canina-blue hover:text-canina-blue transition-all flex items-center justify-center gap-2"
>
<Plus className="w-5 h-5" />
تعریف یادآور درمانی جدید
</button>
</div>
{/* Health Logs */}
<div className="bg-white rounded-[3rem] border border-medical-gray-200 p-10 shadow-sm">
<div className="flex items-center justify-between mb-10">
<div className="flex items-center gap-3">
<Activity className="w-8 h-8 text-canina-blue" />
<h3 className="text-2xl font-black text-medical-gray-900 italic">گزارشات سلامت</h3>
</div>
<ClipboardList className="w-6 h-6 text-canina-blue" />
</div>
<div className="space-y-4">
{(activePet?.logs || []).length === 0 ? (
<div className="text-center py-10 bg-medical-gray-50 rounded-2xl border border-dashed border-medical-gray-200">
<p className="text-sm font-bold text-medical-gray-400 italic">هنوز گزارشی ثبت نشده است</p>
</div>
) : (
(activePet?.logs || []).slice(0, 3).map((log) => (
<div key={log.id} className="p-5 bg-medical-gray-50 rounded-2xl border border-medical-gray-100 flex items-center justify-between">
<div>
<div className="flex items-center gap-2 mb-1">
<span className="text-[10px] font-black bg-white px-2 py-0.5 rounded-md border border-medical-gray-200 text-medical-gray-600">
{toPersian(new Date(log.date).toLocaleDateString("fa-IR"))}
</span>
<span className="text-xs font-black text-medical-gray-900">اشتها: {log.appetite} | انرژی: {log.energy}</span>
</div>
{log.note && <p className="text-[11px] text-medical-gray-500 line-clamp-1">{log.note}</p>}
</div>
</div>
))
)}
</div>
<button
onClick={() => setIsAddingHealthLog(true)}
className="w-full mt-8 py-5 bg-canina-blue text-white rounded-2xl font-black hover:bg-medical-gray-900 transition-all shadow-xl shadow-canina-blue/20"
>
ثبت گزارش روزانه جدید
</button>
</div>
</div>
</>
) : activePetTab === "orders" ? (
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
className="bg-white rounded-[4rem] border border-medical-gray-200 p-12 min-h-[500px] shadow-sm"
>
<div className="flex items-center justify-between mb-12">
<div className="flex items-center gap-4">
<div className="w-14 h-14 bg-medical-gray-900 text-white rounded-[1.5rem] flex items-center justify-center shadow-xl">
<Package className="w-7 h-7" />
</div>
<div>
<h3 className="text-3xl font-black text-medical-gray-900 italic">تاریخچه خرید {activePet.name}</h3>
<p className="text-xs font-bold text-medical-gray-400 mt-1">برای مشاهده جزئیات کامل فاکتور و پیگیری، روی هر سفارش کلیک کنید</p>
</div>
</div>
<div className="text-left">
<div className="text-[10px] font-black text-medical-gray-400 uppercase tracking-widest">مجموع هزینه درمانی</div>
<div className="text-2xl font-black text-canina-blue">{toPersian(petOrders.reduce((a, b) => a + b.total, 0).toLocaleString())} <span className="text-xs italic">تومان</span></div>
</div>
</div>
{petOrders.length === 0 ? (
<div className="py-24 text-center space-y-6">
<div className="w-24 h-24 bg-medical-gray-50 rounded-full flex items-center justify-center mx-auto text-medical-gray-200 shadow-inner">
<Package className="w-12 h-12" />
</div>
<p className="text-medical-gray-400 font-black text-xl italic">هنوز سفارشی برای {activePet.name} ثبت نکردهاید.</p>
<button onClick={() => router.push('/shop')} className="bg-canina-blue text-white px-10 py-4 rounded-2xl font-black hover:scale-105 transition-all cursor-pointer">شروع اولین خرید</button>
</div>
) : (
<div className="space-y-5">
{petOrders.map(order => (
<motion.div
key={order.id}
initial={{ opacity: 0, x: 20 }}
animate={{ opacity: 1, x: 0 }}
whileHover={{ x: -6 }}
onClick={() => setSelectedInvoiceOrder(order)}
className="p-6 bg-white rounded-[2.5rem] border border-medical-gray-200 hover:border-canina-blue/50 flex flex-col sm:flex-row items-start sm:items-center justify-between gap-6 transition-all cursor-pointer group shadow-sm hover:shadow-xl"
>
<div className="flex-1 text-right">
<div className="flex items-center gap-2 mb-2">
<span className="text-xs font-black text-medical-gray-900">سفارش #{toPersian(order.id.slice(-6))}</span>
<span className="text-[10px] font-black px-2.5 py-0.5 rounded-full bg-green-50 text-green-600">
{toPersian(order.items.length)} قلم کالا
</span>
</div>
<div className="flex flex-wrap gap-x-6 gap-y-2 items-center text-xs text-medical-gray-500 font-bold">
<div className="flex items-center gap-1.5">
<Calendar className="w-4 h-4 text-canina-blue/40" />
{toPersian(new Date(order.date).toLocaleDateString("fa-IR", { year: 'numeric', month: 'long', day: 'numeric' }))}
</div>
<div className="text-canina-blue font-black">
مبلغ کل: {toPersian(order.total.toLocaleString())} تومان
</div>
</div>
</div>
<div className="flex items-center gap-2 shrink-0">
{order.items.slice(0, 3).map((item, idx) => (
<div key={idx} className="w-14 h-14 bg-medical-gray-50 rounded-2xl p-2 flex items-center justify-center border border-medical-gray-100 overflow-hidden">
<SafeImage src={item.product.image} alt={item.product.name} className="w-full h-full" imgClassName="object-contain" />
</div>
))}
<div className="px-4 py-2 bg-canina-blue/10 text-canina-blue text-xs font-black rounded-xl group-hover:bg-canina-blue group-hover:text-white transition-colors">
مشاهده فاکتور
</div>
</div>
</motion.div>
))}
</div>
)}
</motion.div>
) : (
/* Prescriptions Tab */
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
className="bg-white rounded-[4rem] border border-medical-gray-200 p-12 min-h-[500px] shadow-sm"
>
<div className="flex items-center justify-between mb-12">
<div className="flex items-center gap-4">
<div className="w-14 h-14 bg-canina-blue text-white rounded-[1.5rem] flex items-center justify-center shadow-xl">
<Stethoscope className="w-7 h-7" />
</div>
<div>
<h3 className="text-3xl font-black text-medical-gray-900 italic">نسخههای پزشکی {activePet.name}</h3>
<p className="text-xs font-bold text-medical-gray-400 mt-1">پرونده نسخههای بارگذاری شده و نظرات تخصصی پزشکان کنینا</p>
</div>
</div>
</div>
{petPrescriptions.length === 0 ? (
<div className="py-24 text-center space-y-6">
<div className="w-24 h-24 bg-medical-gray-50 rounded-full flex items-center justify-center mx-auto text-medical-gray-200 shadow-inner">
<Stethoscope className="w-12 h-12" />
</div>
<p className="text-medical-gray-400 font-black text-xl italic">هنوز نسخه پزشکی برای {activePet.name} ثبت نشده است.</p>
</div>
) : (
<div className="space-y-6">
{petPrescriptions.map((rx: any) => (
<div
key={rx.id}
className="p-6 bg-medical-gray-50/70 rounded-[2.5rem] border border-medical-gray-200 flex flex-col md:flex-row items-start md:items-center justify-between gap-6"
>
<div className="space-y-2 flex-1">
<div className="flex items-center gap-2">
<span className="text-xs font-black text-medical-gray-900">نسخه شماره #{rx.id.slice(0, 8)}</span>
<span className={`text-[10px] font-black px-2.5 py-0.5 rounded-full ${
rx.status === 'APPROVED' ? 'bg-green-100 text-green-700' : rx.status === 'REJECTED' ? 'bg-red-100 text-red-700' : 'bg-amber-100 text-amber-700'
}`}>
{rx.status === 'APPROVED' ? 'تایید شده توسط پزشک' : rx.status === 'REJECTED' ? 'عدم تایید' : 'در حال بررسی تخصصی'}
</span>
</div>
<div className="text-xs text-medical-gray-500 font-bold flex items-center gap-2">
<Calendar className="w-4 h-4 text-canina-blue" />
<span>تاریخ ثبت: {toPersian(new Date(rx.createdAt).toLocaleDateString("fa-IR", { year: 'numeric', month: 'long', day: 'numeric', hour: '2-digit', minute: '2-digit' }))}</span>
</div>
{rx.notes && (
<p className="text-xs text-medical-gray-600 bg-white p-3 rounded-xl border border-medical-gray-200">
<strong className="text-medical-gray-800 block mb-0.5">یادداشت شما:</strong>
{rx.notes}
</p>
)}
{rx.adminNotes && (
<p className="text-xs text-canina-blue bg-canina-blue/5 p-3 rounded-xl border border-canina-blue/10 font-bold">
<strong className="text-canina-dark block mb-0.5">پاسخ و دستور مصرف پزشک کنینا:</strong>
{rx.adminNotes.split('__PRESCRIBED_PRODUCTS__:')[0]}
</p>
)}
</div>
<div className="shrink-0 flex items-center gap-3">
<a
href={rx.fileUrl.startsWith('http') ? rx.fileUrl : `${BASE_DOMAIN}${rx.fileUrl}`}
target="_blank"
rel="noreferrer"
className="px-4 py-2.5 bg-white text-canina-blue border border-canina-blue/20 rounded-xl text-xs font-black hover:bg-canina-blue hover:text-white transition-all shadow-xs"
>
مشاهده فایل نسخه
</a>
</div>
</div>
))}
</div>
)}
</motion.div>
)}
{/* Seal of Authenticity */}
<div className="p-16 border-4 border-double border-medical-gray-200 rounded-[5rem] text-center max-w-4xl mx-auto opacity-40 grayscale hover:opacity-100 hover:grayscale-0 transition-all duration-1000">
<div className="flex justify-center mb-8">
<div className="w-20 h-20 border-4 border-canina-blue rounded-full flex items-center justify-center text-canina-blue font-black text-2xl rotate-12 shadow-2xl">آلمان</div>
</div>
<h4 className="text-2xl font-black text-medical-gray-900 mb-4 italic">ضمانت اصالت و سلامت کنینا آلمان</h4>
<p className="text-sm text-medical-gray-500 font-medium leading-relaxed max-w-2xl mx-auto italic">
این گزارش توسط سیستم هوش مصنوعی کنینا و با انطباق کامل بر پروتکلهای درمانی Canina Pharma GmbH آلمان تولید شده است. تمامی مکملهای پیشنهادی دارای استاندارد دارویی (Pharmaceutical Grade) میباشند.
</p>
</div>
{/* Add Reminder Modal */}
<AnimatePresence>
{isAddingReminder && (
<div className="fixed inset-0 z-[100] flex items-center justify-center p-4">
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
className="absolute inset-0 bg-medical-gray-900/60 backdrop-blur-sm"
onClick={() => setIsAddingReminder(false)}
/>
<motion.div
initial={{ y: 50, opacity: 0, scale: 0.95 }}
animate={{ y: 0, opacity: 1, scale: 1 }}
exit={{ y: 50, opacity: 0, scale: 0.95 }}
className="relative bg-white rounded-[3rem] p-10 max-w-md w-full shadow-2xl"
>
<div className="flex items-center justify-between mb-8">
<h3 className="text-2xl font-black text-medical-gray-900 italic font-vazir">افزودن یادآور جدید</h3>
<button onClick={() => setIsAddingReminder(false)} className="text-medical-gray-400 hover:text-red-500"><Plus className="w-6 h-6 rotate-45" /></button>
</div>
<div className="space-y-6">
<div>
<label className="block text-[10px] font-black text-medical-gray-400 uppercase tracking-widest mb-2 pr-2">عنوان یادآور</label>
<input
autoFocus
type="text"
value={reminderForm.title}
onChange={e => setReminderForm({ ...reminderForm, title: e.target.value })}
placeholder="مثلاً: قرص مفاصل، کانهیدروکس"
className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-2xl py-4 px-6 focus:ring-2 focus:ring-canina-blue/20 outline-none font-bold"
/>
</div>
<div className="grid grid-cols-2 gap-4">
<div>
<label className="block text-[10px] font-black text-medical-gray-400 uppercase tracking-widest mb-2 pr-2">زمان (ساعت)</label>
<input
type="time"
value={reminderForm.time}
onChange={e => setReminderForm({ ...reminderForm, time: e.target.value })}
className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-2xl py-4 px-6 focus:ring-2 focus:ring-canina-blue/20 outline-none font-black"
/>
</div>
<div>
<label className="block text-[10px] font-black text-medical-gray-400 uppercase tracking-widest mb-2 pr-2">دوره تکرار</label>
<select
value={reminderForm.frequency}
onChange={e => setReminderForm({ ...reminderForm, frequency: e.target.value as "روزانه" | "هفتگی" })}
className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-2xl py-4 px-6 focus:ring-2 focus:ring-canina-blue/20 outline-none font-black text-sm"
>
<option value="روزانه">روزانه</option>
<option value="هفتگی">هفتگی</option>
</select>
</div>
</div>
<div>
<label className="block text-[10px] font-black text-medical-gray-400 uppercase tracking-widest mb-2 pr-2">متصل به محصول (اختیاری)</label>
<select
value={reminderForm.productId}
onChange={e => setReminderForm({ ...reminderForm, productId: e.target.value })}
className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-2xl py-4 px-6 focus:ring-2 focus:ring-canina-blue/20 outline-none font-black text-sm"
>
<option value="">هیچکدام</option>
{recommendedProducts.map(p => (
<option key={p.product.id} value={p.product.id}>{p.product.name}</option>
))}
</select>
</div>
<button
onClick={handleReminderSubmit}
className="w-full py-5 bg-canina-blue text-white rounded-2xl font-black hover:bg-medical-gray-900 transition-all shadow-xl shadow-canina-blue/20 mt-4"
>
ثبت نهایی یادآور
</button>
</div>
</motion.div>
</div>
)}
</AnimatePresence>
{/* Add Health Log Modal */}
<AnimatePresence>
{isAddingHealthLog && (
<div className="fixed inset-0 z-[100] flex items-center justify-center p-4">
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
className="absolute inset-0 bg-medical-gray-900/60 backdrop-blur-sm transition-all"
onClick={() => setIsAddingHealthLog(false)}
/>
<motion.div
initial={{ y: 50, opacity: 0, scale: 0.95 }}
animate={{ y: 0, opacity: 1, scale: 1 }}
exit={{ y: 50, opacity: 0, scale: 0.95 }}
className="relative bg-white rounded-[3rem] p-10 max-w-lg w-full shadow-2xl"
>
<div className="flex items-center justify-between mb-8">
<h3 className="text-2xl font-black text-medical-gray-900 italic">ثبت گزارش روزانه سلامت</h3>
<button onClick={() => setIsAddingHealthLog(false)} className="text-medical-gray-400 hover:text-red-500"><Plus className="w-6 h-6 rotate-45" /></button>
</div>
<div className="space-y-6">
<div>
<label className="block text-[10px] font-black text-medical-gray-400 uppercase tracking-widest mb-4 pr-2">میزان اشتها و جذب غذا</label>
<div className="grid grid-cols-3 gap-3">
{["عالی", "متوسط", "کم"].map(opt => (
<button
key={opt}
onClick={() => setLogForm({ ...logForm, appetite: opt as "عالی" | "متوسط" | "کم" })}
className={cn(
"py-3 border-2 rounded-xl text-xs font-black transition-all",
logForm.appetite === opt ? "border-canina-blue bg-canina-blue/10 text-canina-blue" : "border-medical-gray-100 text-medical-gray-400"
)}
>
{opt}
</button>
))}
</div>
</div>
<div>
<label className="block text-[10px] font-black text-medical-gray-400 uppercase tracking-widest mb-4 pr-2">سطح انرژی و فعالیت</label>
<div className="grid grid-cols-3 gap-3">
{["زیاد", "نرمال", "بی‌حال"].map(opt => (
<button
key={opt}
onClick={() => setLogForm({ ...logForm, energy: opt as "زیاد" | "نرمال" | "بی‌حال" })}
className={cn(
"py-3 border-2 rounded-xl text-xs font-black transition-all",
logForm.energy === opt ? "border-green-500 bg-green-500/10 text-green-500" : "border-medical-gray-100 text-medical-gray-400"
)}
>
{opt}
</button>
))}
</div>
</div>
<div>
<label className="block text-[10px] font-black text-medical-gray-400 uppercase tracking-widest mb-2 pr-2">یادداشتهای تخصصی (تغییرات رفتاری، دفع و...)</label>
<textarea
rows={4}
value={logForm.note}
onChange={e => setLogForm({ ...logForm, note: e.target.value })}
placeholder="مشاهدات خود را برای بررسی دکتر سیستم اینجا بنویسید..."
className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-2xl py-4 px-6 focus:ring-2 focus:ring-canina-blue/20 outline-none font-bold text-sm resize-none"
/>
</div>
<button
onClick={handleHealthLogSubmit}
className="w-full py-5 bg-medical-gray-900 text-white rounded-2xl font-black hover:bg-canina-blue transition-all shadow-xl mt-2"
>
ثبت نهایی گزارش
</button>
</div>
</motion.div>
</div>
)}
</AnimatePresence>
{/* Invoice Modal for Pet Purchase History */}
<OrderDetailsModal
isOpen={!!selectedInvoiceOrder}
order={selectedInvoiceOrder}
onClose={() => setSelectedInvoiceOrder(null)}
/>
</div>
</div>
);
}