From 7e231dbdd8aaf864e8dacf3aa9fdd16a9747c5df Mon Sep 17 00:00:00 2001 From: Kirill Date: Fri, 15 May 2026 20:24:19 +0500 Subject: [PATCH] feat: use WebP original for full-screen product image viewer --- client/src/pages/product/ui/ProductPage.tsx | 3 ++- client/src/shared/lib/get-original-webp-url.ts | 14 ++++++++++++++ client/src/shared/ui/OptimizedImage.tsx | 8 -------- .../shared/ui/__tests__/OptimizedImage.test.tsx | 3 ++- 4 files changed, 18 insertions(+), 10 deletions(-) create mode 100644 client/src/shared/lib/get-original-webp-url.ts diff --git a/client/src/pages/product/ui/ProductPage.tsx b/client/src/pages/product/ui/ProductPage.tsx index fc04f90..0cc428e 100644 --- a/client/src/pages/product/ui/ProductPage.tsx +++ b/client/src/pages/product/ui/ProductPage.tsx @@ -22,6 +22,7 @@ import { fetchPublicProduct } from '@/entities/product/api/product-api' import { fetchPublicProductReviews } from '@/entities/product/api/reviews-api' import { ToggleCartIcon } from '@/features/cart/toggle-cart-icon' import { formatPriceRub } from '@/shared/lib/format-price' +import { getOriginalWebpUrl } from '@/shared/lib/get-original-webp-url' import { reviewsCountRu } from '@/shared/lib/reviews-count-ru' import { $user } from '@/shared/model/auth' import { OptimizedImage } from '@/shared/ui/OptimizedImage' @@ -282,7 +283,7 @@ export function ProductPage() { diff --git a/client/src/shared/lib/get-original-webp-url.ts b/client/src/shared/lib/get-original-webp-url.ts new file mode 100644 index 0000000..0060f1c --- /dev/null +++ b/client/src/shared/lib/get-original-webp-url.ts @@ -0,0 +1,14 @@ +/** Extract UUID and subdir from a /uploads/... URL */ +function parseUploadUrl(src: string): { uuid: string; ext: string; subdir: string } | null { + const match = src.match(/^\/uploads(?:\/(reviews))?\/([^.\\/]+)\.(png|jpe?g|webp)/i) + if (!match) return null + return { subdir: match[1] || '', uuid: match[2], ext: match[3].toLowerCase() } +} + +/** Get the original WebP URL for full-screen display (no resize) */ +export function getOriginalWebpUrl(src: string): string { + const parsed = parseUploadUrl(src) + if (!parsed) return src + const pathPrefix = parsed.subdir ? `${parsed.subdir}/` : '' + return `/uploads/${pathPrefix}${parsed.uuid}.webp` +} diff --git a/client/src/shared/ui/OptimizedImage.tsx b/client/src/shared/ui/OptimizedImage.tsx index 8f2b708..85da53a 100644 --- a/client/src/shared/ui/OptimizedImage.tsx +++ b/client/src/shared/ui/OptimizedImage.tsx @@ -35,14 +35,6 @@ function buildFallbackSrc(src: string, width: number): string { return `/uploads-resized/${pathPrefix}${parsed.uuid}.webp?w=${width}` } -/** Get the original WebP URL for full-screen display (no resize) */ -export function getOriginalWebpUrl(src: string): string { - const parsed = parseUploadUrl(src) - if (!parsed) return src - const pathPrefix = parsed.subdir ? `${parsed.subdir}/` : '' - return `/uploads/${pathPrefix}${parsed.uuid}.webp` -} - export function OptimizedImage({ src, alt, diff --git a/client/src/shared/ui/__tests__/OptimizedImage.test.tsx b/client/src/shared/ui/__tests__/OptimizedImage.test.tsx index 6ff8cdd..2df8f23 100644 --- a/client/src/shared/ui/__tests__/OptimizedImage.test.tsx +++ b/client/src/shared/ui/__tests__/OptimizedImage.test.tsx @@ -1,6 +1,7 @@ import { render, screen } from '@testing-library/react' import { describe, it, expect } from 'vitest' -import { OptimizedImage, getOriginalWebpUrl } from '@/shared/ui/OptimizedImage' +import { getOriginalWebpUrl } from '@/shared/lib/get-original-webp-url' +import { OptimizedImage } from '@/shared/ui/OptimizedImage' describe('OptimizedImage', () => { it('renders a plain img for non-upload URLs', () => {