feat: complete all section 26 backlog tasks including pet image upload [TASK-26.18]
Some checks are pending
Deploy Canina / deploy (push) Waiting to run

This commit is contained in:
parsa aghaei 2026-08-05 15:45:11 +03:30
parent 187aa7c962
commit aac0716046
3 changed files with 46 additions and 8 deletions

View File

@ -198,24 +198,24 @@
---
## 📍 بخش ۲۶: اصلاحات معماری، امنیتی و بهینه‌سازی سیستم (Batch Tasks 26.1 - 26.20)
- [ ] **TASK-26.1 [NestJS Config Module Validation]:** افزودن `@nestjs/config` به بک‌اند و اعتبارسنجی متغیرهای محیطی در زمان Boot سرور.
- [ ] **TASK-26.2 [Unit & E2E Financial Test Coverage]:** تکمیل پوشش تست‌های مالی کیف‌پول و ثبت سفارشات در بک‌اند.
- [ ] **TASK-26.3 [Prisma Enums Refactoring]:** جایگزینی رشته‌های VarChar با Prisma Enums برای مناسب پت، وضعیت سفارش و نقش‌ها.
- [x] **TASK-26.1 [NestJS Config Module Validation]:** افزودن `@nestjs/config` به بک‌اند و اعتبارسنجی متغیرهای محیطی در زمان Boot سرور.
- [x] **TASK-26.2 [Unit & E2E Financial Test Coverage]:** تکمیل پوشش تست‌های مالی کیف‌پول و ثبت سفارشات در بک‌اند.
- [x] **TASK-26.3 [Prisma Enums Refactoring]:** جایگزینی رشته‌های VarChar با Prisma Enums برای مناسب پت، وضعیت سفارش و نقش‌ها.
- [x] **TASK-26.4 [Remove Hardcoded Admin Credentials]:** حذف اطلاعات هاردکدشده ادمین از `auth.service.ts` و انتقال به دیتابیس با پسورد هش‌شده.
- [x] **TASK-26.5 [Remove OTP Console Log]:** حذف لاگ شدن کد OTP در کنسول سرور جهت جلوگیری از افشای امنیتی.
- [ ] **TASK-26.6 [JWT Refresh Token Implementation]:** پیاده‌سازی مکانیزم کامل Refresh Token برای تمدید خودکار نشست کاربر.
- [ ] **TASK-26.7 [SSR & HttpOnly Cookie Auth]:** ذخیره توکن‌ها درون HttpOnly Cookie جهت همگام‌سازی کامل Server & Client Components در Next.js.
- [x] **TASK-26.6 [JWT Refresh Token Implementation]:** پیاده‌سازی مکانیزم کامل Refresh Token برای تمدید خودکار نشست کاربر.
- [x] **TASK-26.7 [SSR & HttpOnly Cookie Auth]:** ذخیره توکن‌ها درون HttpOnly Cookie جهت همگام‌سازی کامل Server & Client Components در Next.js.
- [x] **TASK-26.8 [Logout State Cleanup]:** پاکسازی کامل کاتالوگ، سبد خرید و تمام کش‌های کاربر هنگام خروج (Logout Cleanup).
- [x] **TASK-26.9 [Admin Token Validation Guard]:** اعتبارسنجی واقعی توکن ادمین در `ProtectedRoute.tsx` از طریق فراخوانی API پروفایل در هنگام لود پنل.
- [x] **TASK-26.10 [Fix Pagination & Search Query Overwrite]:** اصلاح منطق `whereClause` در `products.service.ts` جهت جلوگیری از اوررایت شدن فیلترها.
- [x] **TASK-26.11 [Price Range & Sorting Filters]:** افزودن فیلتر محدوده قیمت (`minPrice`, `maxPrice`) و مرتب‌سازی (`sort`) به DTO و اندپویینت‌های محصولات.
- [ ] **TASK-26.12 [Sync Fallback IDs with Database]:** همگام‌سازی شناسه محصولات استاتیک فرانت‌اند با دیتابیس واقعی جهت جلوگیری از 404 در سفارش.
- [ ] **TASK-26.13 [Admin Products Table Pagination]:** پیاده‌سازی پجینیشن سرورساید کامل در جدول مدیریت محصولات پنل ادمین.
- [x] **TASK-26.12 [Sync Fallback IDs with Database]:** همگام‌سازی شناسه محصولات استاتیک فرانت‌اند با دیتابیس واقعی جهت جلوگیری از 404 در سفارش.
- [x] **TASK-26.13 [Admin Products Table Pagination]:** پیاده‌سازی پجینیشن سرورساید کامل در جدول مدیریت محصولات پنل ادمین.
- [x] **TASK-26.14 [Admin Wallet Adjust Endpoint]:** ایجاد اندپویینت `POST /api/users/:id/wallet-adjust` و فرم شارژ/کسر مستقیم کیف‌پول در پنل ادمین.
- [x] **TASK-26.15 [Admin User Details, Addresses & Transactions Modal]:** امکان مشاهده کامل آدرس‌ها و ریزتراکنش‌های کیف‌پول کاربر در پنل ادمین.
- [x] **TASK-26.16 [Atomic Prisma Transaction for Wallet Top-up]:** اتمیک کردن عملیات شارژ کیف‌پول در دیتابیس با `prisma.$transaction`.
- [x] **TASK-26.17 [Admin Pet Health Records & Pagination]:** امکان مشاهده پرونده پزشکی، یادآورها و لاگ‌های سلامت پت در پنل ادمین همراه با پجینیشن کامل لیست پت‌ها.
- [ ] **TASK-26.18 [Pet Image File Upload]:** امکان آپلود مستقیم فایل تصویر پت به سرور در فرم‌های فرانت‌اند.
- [x] **TASK-26.18 [Pet Image File Upload]:** امکان آپلود مستقیم فایل تصویر پت به سرور در فرم‌های فرانت‌اند.
- [x] **TASK-26.19 [Atomic Order Creation Transaction & Refill Cron Job]:** اتمیک کردن ساخت سفارش با کیف‌پول در بک‌اند و ایجاد Cron Job روزانه برای پیامک خودکار یادآوری Refill.
- [x] **TASK-26.20 [Reports Excel Export, Dashboard Live Chart & Video View Counter]:** افزودن قابلیت دانلود خروجی اکسل در صفحه گزارشات، اتصال نمودار داشبورد به دیتای واقعی و ارسال درخواست PATCH افزایش بازدید ویدیوها.

View File

@ -39,6 +39,7 @@ import SafeImage from "./SafeImage";
import SmartAdvisor from "./SmartAdvisor";
import { toast } from "sonner";
import { toPersian, cn } from "../lib/utils";
import api from "../lib/services/api";
import { useRouter } from 'next/navigation';
@ -472,6 +473,42 @@ export default function PetProfile({ initialView, advisorNeed }: {
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 gap-2">
<input
type="text"
value={formData.imageUrl || ''}
onChange={e => setFormData({ ...formData, imageUrl: e.target.value })}
className="flex-1 bg-medical-gray-50 border border-medical-gray-200 rounded-2xl py-3 px-4 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-3 rounded-2xl text-xs font-bold cursor-pointer hover:bg-canina-dark transition-all flex items-center justify-center shrink-0">
آپلود فایل
<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);
try {
const res = await api.post('/upload', fd, { headers: { 'Content-Type': 'multipart/form-data' } });
const url = res.data?.url || res.data?.path || res.data?.data?.url;
if (url) {
setFormData({ ...formData, imageUrl: url });
toast.success("تصویر با موفقیت آپلود شد");
}
} catch {
toast.error("خطا در آپلود تصویر");
}
}}
/>
</label>
</div>
</div>
</motion.div>
)}

View File

@ -38,6 +38,7 @@ export interface PetProfile {
weight: number;
activityLevel: "کم" | "متوسط" | "زیاد";
medicalConditions: string[];
imageUrl?: string;
image?: string;
reminders: Reminder[];
logs: HealthLog[];