feat: TASK-111 - add prescription and household supplement filters to ArchivePage

This commit is contained in:
parsa aghaei 2026-07-26 15:19:54 +03:30
parent db3c18a433
commit 72c126b9ca
4 changed files with 49 additions and 5 deletions

View File

@ -138,5 +138,19 @@
"به‌روزرسانی sitemap.ts برای شامل شدن تمام slugs واقعی محصولات دیتابیس", "به‌روزرسانی sitemap.ts برای شامل شدن تمام slugs واقعی محصولات دیتابیس",
"اعتبارسنجی فایل robots.ts برای موتورهای جستجو" "اعتبارسنجی فایل robots.ts برای موتورهای جستجو"
] ]
},
{
"id": "TASK-111",
"title": "افزودن فیلتر محصولات در صفحه لیست مکمل‌ها بر اساس نسخه دامپزشکی و گروه‌بندی تخصصی",
"priority": "HIGH",
"assigned_role": "05_dev_frontend",
"status": "pending",
"max_file_count": 3,
"estimated_minutes": 15,
"dependency_task_ids": [],
"acceptance_criteria": [
"افزودن فیلتر محصولات نیازمند نسخه در ArchivePage و SearchResultsPage",
"امکان فیلتر سریع مکمل‌های خانگی بدون نسخه در کنار مکمل‌های تجویزی"
]
} }
] ]

View File

@ -1,11 +1,11 @@
{ {
"project_name": "Canina Veterinary E-Commerce", "project_name": "Canina Veterinary E-Commerce",
"project_mode": "BROWNFIELD", "project_mode": "BROWNFIELD",
"status": "COMPLETED", "status": "IN_PROGRESS",
"checkpoint": { "checkpoint": {
"stage": "DEEP_ENGINEERING_PHASE_COMPLETED", "stage": "TASK_EXECUTION",
"active_agent": "06_qa_engineer", "active_agent": "05_dev_frontend",
"current_ticket_id": null, "current_ticket_id": "TASK-111",
"sub_step_index": 10, "sub_step_index": 10,
"total_sub_steps": 10 "total_sub_steps": 10
}, },

View File

@ -229,6 +229,7 @@ export default function ArchivePage({
initialSymptoms?: string initialSymptoms?: string
}) { }) {
const router = useRouter(); const router = useRouter();
const [prescriptionFilter, setPrescriptionFilter] = useState<"all" | "prescription" | "otc">("all");
const [selectedCategory, setSelectedCategory] = useState(initialCategory); const [selectedCategory, setSelectedCategory] = useState(initialCategory);
const [selectedPet, setSelectedPet] = useState<PetType | "all">(initialPetType as any); const [selectedPet, setSelectedPet] = useState<PetType | "all">(initialPetType as any);
const [activeSymptoms, setActiveSymptoms] = useState<string[]>(initialSymptoms ? initialSymptoms.split(',') : []); const [activeSymptoms, setActiveSymptoms] = useState<string[]>(initialSymptoms ? initialSymptoms.split(',') : []);
@ -343,6 +344,13 @@ export default function ArchivePage({
result = result.filter(p => p.symptoms && p.symptoms.some(s => activeSymptoms.includes(s))); result = result.filter(p => p.symptoms && p.symptoms.some(s => activeSymptoms.includes(s)));
} }
// Filter by prescription requirement (OTC vs Prescription)
if (prescriptionFilter === "prescription") {
result = result.filter(p => p.requiresRx || p.category === "special-care");
} else if (prescriptionFilter === "otc") {
result = result.filter(p => !p.requiresRx && p.category !== "special-care");
}
setFilteredProducts(result); setFilteredProducts(result);
setMeta(res.meta); setMeta(res.meta);
} catch (error) { } catch (error) {
@ -355,7 +363,7 @@ export default function ArchivePage({
useEffect(() => { useEffect(() => {
fetchProducts(); fetchProducts();
}, [selectedCategory, selectedPet, searchQuery, activeSymptoms]); }, [selectedCategory, selectedPet, searchQuery, activeSymptoms, prescriptionFilter]);
const toggleSymptom = (s: string) => { const toggleSymptom = (s: string) => {
setActiveSymptoms(prev => prev.includes(s) ? prev.filter(item => item !== s) : [...prev, s]); setActiveSymptoms(prev => prev.includes(s) ? prev.filter(item => item !== s) : [...prev, s]);
@ -418,6 +426,27 @@ export default function ArchivePage({
</div> </div>
<div className="space-y-6"> <div className="space-y-6">
{/* Prescription / Household Filter */}
<div>
<span className="text-[10px] font-black text-medical-gray-400 uppercase tracking-widest block mb-3">نوع دسترسی و نسخه</span>
<div className="flex flex-col gap-2">
{[
{ id: "all", label: "همه داروها و مکمل‌ها" },
{ id: "otc", label: "مکمل‌های خانگی (بدون نیاز به نسخه)" },
{ id: "prescription", label: "داروها و مکمل‌های تخصصی (با نسخه)" },
].map(type => (
<button
key={type.id}
onClick={() => setPrescriptionFilter(type.id as any)}
className={`w-full py-2 px-3 rounded-xl text-xs font-bold border transition-all text-right flex items-center justify-between ${prescriptionFilter === type.id ? 'bg-canina-blue border-canina-blue text-white shadow-md' : 'bg-white border-medical-gray-200 text-medical-gray-600 hover:bg-medical-gray-50'}`}
>
<span>{type.label}</span>
{prescriptionFilter === type.id && <Sparkles className="w-3.5 h-3.5 text-amber-300" />}
</button>
))}
</div>
</div>
{/* Pet Type */} {/* Pet Type */}
<div> <div>
<span className="text-[10px] font-black text-medical-gray-400 uppercase tracking-widest block mb-3">نوع پت</span> <span className="text-[10px] font-black text-medical-gray-400 uppercase tracking-widest block mb-3">نوع پت</span>

View File

@ -50,6 +50,7 @@ export interface Product {
symptoms: string[]; symptoms: string[];
suitableFor: PetType; suitableFor: PetType;
specialBadge?: string; specialBadge?: string;
requiresRx?: boolean;
contraindications?: string[]; contraindications?: string[];
onSetOfAction?: string; onSetOfAction?: string;
expectedResults?: { icon: string; text: string }[]; expectedResults?: { icon: string; text: string }[];