fix(validation & catalog): disable strict forbidNonWhitelisted in NestJS ValidationPipe and wire full catalog mode & maintenance mode settings to frontend
Some checks failed
Deploy Canina / deploy (push) Failing after 29s

This commit is contained in:
parsa aghaei 2026-08-08 18:38:48 +03:30
parent 9e233bee27
commit 7cc9194827
3 changed files with 44 additions and 16 deletions

View File

@ -61,7 +61,7 @@ async function bootstrap() {
new ValidationPipe({
transform: true,
whitelist: true,
forbidNonWhitelisted: true,
forbidNonWhitelisted: false,
exceptionFactory: (errors) => {
const formattedDetails = errors.map((err) => {
const constraints = err.constraints

View File

@ -13,7 +13,17 @@ export class SettingsService {
constructor(private prisma: PrismaService) {}
async getUiTexts() {
return this.prisma.uiText.findMany();
const [uiTexts, settings] = await Promise.all([
this.prisma.uiText.findMany(),
this.prisma.setting.findMany(),
]);
const merged = [...uiTexts];
settings.forEach((s) => {
merged.push({ key: s.key, value: String(s.value) } as any);
});
return merged;
}
async updateUiText(key: string, value: string) {

View File

@ -32,6 +32,12 @@ function ProductCard({ product }: { product: Product }) {
return { type: "neutral", text: `مناسب برای ${activePet.name}` };
}, [product, activePet]);
const getText = useSettingsStore((state) => state.getText);
const isCatalogOnly = getText('CATALOG_ONLY_MODE', 'false') === 'true';
const showPrices = !isCatalogOnly || getText('CATALOG_SHOW_PRICES', 'true') === 'true';
const allowCart = !isCatalogOnly || getText('CATALOG_ALLOW_CART', 'false') === 'true';
const showPreorderBtn = isCatalogOnly && getText('CATALOG_PREORDER_BTN', 'false') === 'true';
return (
<motion.div
initial={{ opacity: 0, y: 24 }}
@ -72,19 +78,23 @@ function ProductCard({ product }: { product: Product }) {
<div
onClick={(e) => { e.stopPropagation(); router.push(`/shop/${product.slug || product.id}`); }}
className="w-11 h-11 rounded-full bg-white text-canina-blue flex items-center justify-center hover:scale-110 transition-transform shadow-lg cursor-pointer"
title="مشاهده جزئیات"
>
<Eye className="w-5 h-5" />
</div>
<div
onClick={(e) => {
e.stopPropagation();
addItem(product, 1);
toast.success(`${nameFa} به سبد خرید اضافه شد.`);
}}
className="w-11 h-11 rounded-full bg-canina-blue text-white flex items-center justify-center hover:scale-110 transition-transform shadow-lg border border-white/20 cursor-pointer"
>
<ShoppingCart className="w-5 h-5" />
</div>
{allowCart && (
<div
onClick={(e) => {
e.stopPropagation();
addItem(product, 1);
toast.success(`${nameFa} به سبد خرید اضافه شد.`);
}}
className="w-11 h-11 rounded-full bg-canina-blue text-white flex items-center justify-center hover:scale-110 transition-transform shadow-lg border border-white/20 cursor-pointer"
title="افزودن به سبد خرید"
>
<ShoppingCart className="w-5 h-5" />
</div>
)}
</div>
</div>
@ -109,10 +119,18 @@ function ProductCard({ product }: { product: Product }) {
{/* Footer: Price + CTA */}
<div className="flex items-center justify-between pt-3 border-t border-medical-gray-100">
<div className="text-base font-black text-medical-gray-900 font-vazir whitespace-nowrap">{product.price}</div>
<span className="text-[11px] font-black text-canina-blue uppercase tracking-widest border-b-2 border-canina-blue pb-0.5 hover:text-medical-gray-900 hover:border-medical-gray-900 transition-all whitespace-nowrap">
{getText("product_view_details", "مشاهده جزئیات")}
</span>
<div className="text-base font-black text-medical-gray-900 font-vazir whitespace-nowrap">
{showPrices ? product.price : 'تماس بگیرید'}
</div>
{showPreorderBtn ? (
<span className="text-[11px] font-black text-amber-600 bg-amber-50 px-3 py-1 rounded-full border border-amber-200">
ثبت پیشخرید
</span>
) : (
<span className="text-[11px] font-black text-canina-blue uppercase tracking-widest border-b-2 border-canina-blue pb-0.5 hover:text-medical-gray-900 hover:border-medical-gray-900 transition-all whitespace-nowrap">
{getText("product_view_details", "مشاهده جزئیات")}
</span>
)}
</div>
</Link>
</motion.div>