This commit is contained in:
seb
2026-10-28 21:55:24 +01:00
parent 2e69f49e4d
commit 87ef79bea3
3 changed files with 58 additions and 3 deletions

View File

@@ -120,6 +120,12 @@ function toIndexRecord(article, categoryId) {
? String(categoryId)
: (Array.isArray(article.categoryIds) ? article.categoryIds.join(',') : (article.categories ?? null));
const firstPhoto = Array.isArray(article.photos) && article.photos.length > 0 ? article.photos[0] : null;
const fullHash = article.fullHash ?? firstPhoto?.fullHash ?? null;
const thumbHash = article.thumbHash ?? firstPhoto?.thumbHash ?? null;
const smallThumbBinary = article.smallThumbBinary ?? firstPhoto?.smallThumbBinary ?? null;
const photos = article.photos ?? (fullHash ? [{ fullHash, thumbHash }] : []);
return {
...article,
id: article.id,
@@ -137,6 +143,10 @@ function toIndexRecord(article, categoryId) {
categories,
isParent: Boolean(article.isParent ?? article.is_parent ?? (childCount > 0)),
childCount,
fullHash,
thumbHash,
photos,
smallThumbBinary,
};
}
@@ -377,14 +387,24 @@ export function updateArticleIndexRecord(article) {
let nextItems;
if (existingIndex >= 0) {
const existing = items[existingIndex];
const firstPhoto = Array.isArray(article.photos) && article.photos.length > 0 ? article.photos[0] : null;
const hasPhotosProp = 'photos' in article;
const fullHash = article.fullHash ?? firstPhoto?.fullHash ?? (hasPhotosProp ? null : existing.fullHash);
const thumbHash = article.thumbHash ?? firstPhoto?.thumbHash ?? (hasPhotosProp ? null : existing.thumbHash);
const photos = article.photos ?? (hasPhotosProp ? [] : (existing.photos ?? []));
const smallThumbBinary = article.smallThumbBinary ?? firstPhoto?.smallThumbBinary ?? (hasPhotosProp ? null : existing.smallThumbBinary);
nextItems = [...items];
nextItems[existingIndex] = {
...existing,
...record,
categories: record.categories ?? existing.categories,
smallThumbBinary: article.smallThumbBinary ?? article.photos?.[0]?.smallThumbBinary ?? existing.smallThumbBinary,
brand: article.brand ?? existing.brand,
brandName: article.brand?.name ?? article.brandName ?? existing.brandName,
fullHash,
thumbHash,
photos,
smallThumbBinary,
};
} else {
nextItems = [...items, record];

View File

@@ -352,6 +352,13 @@ export function updateArticleInCategoryViews(article) {
// Update in-place
const existing = item.data.articles[existingIndex];
const updatedArticles = [...item.data.articles];
const firstPhoto = Array.isArray(article.photos) && article.photos.length > 0 ? article.photos[0] : null;
const hasPhotosProp = 'photos' in article;
const fullHash = article.fullHash ?? firstPhoto?.fullHash ?? (hasPhotosProp ? null : existing.fullHash);
const thumbHash = article.thumbHash ?? firstPhoto?.thumbHash ?? (hasPhotosProp ? null : existing.thumbHash);
const photos = article.photos ?? (hasPhotosProp ? [] : (existing.photos ?? []));
const smallThumbBinary = article.smallThumbBinary ?? firstPhoto?.smallThumbBinary ?? (hasPhotosProp ? null : existing.smallThumbBinary);
updatedArticles[existingIndex] = {
...existing,
...article,
@@ -365,6 +372,10 @@ export function updateArticleInCategoryViews(article) {
brandName: article.brand?.name ?? article.brandName ?? existing.brandName,
childCount: article.childCount ?? existing.childCount,
isParent: Boolean(article.childCount > 0 || article.isParent || existing.isParent),
fullHash,
thumbHash,
photos,
smallThumbBinary,
};
categoryViews.key(slug).set({
...item.data,

View File

@@ -22,6 +22,8 @@ import ChevronLeftIcon from '@mui/icons-material/ChevronLeft';
import articleSearchAutomat from '../automats/articleSearchAutomat';
import BackendError from '../components/BackendError';
import { formatPrice, getArticleGross } from '../utils/price';
import { thumb } from '../api';
import { getThumbHashDataUrl } from '../utils/thumbHashCache';
import {
buildSearchUrl,
queryFromParams,
@@ -110,6 +112,15 @@ class ResultRow extends Component {
const showChildBadge = isParent || childCount > 0;
const price = getArticleGross(row, companyAutomat.state.current?.taxrate);
const firstPhoto = Array.isArray(row.photos) && row.photos.length > 0 ? row.photos[0] : null;
const fullHash = row.fullHash ?? firstPhoto?.fullHash ?? null;
const thumbHash = row.thumbHash ?? firstPhoto?.thumbHash ?? null;
const smallThumbBinary = row.smallThumbBinary ?? firstPhoto?.smallThumbBinary ?? null;
const thumbSrc = smallThumbBinary
? `data:image/avif;base64,${smallThumbBinary}`
: (fullHash ? thumb.url(fullHash) : null);
const thumbHashUrl = thumbHash ? getThumbHashDataUrl(thumbHash) : null;
return (
<ListItemButton
type="button"
@@ -127,15 +138,28 @@ class ResultRow extends Component {
borderRadius: 0.5,
overflow: 'hidden',
bgcolor: 'action.hover',
backgroundImage: thumbHashUrl ? `url("${thumbHashUrl}")` : undefined,
backgroundSize: 'cover',
backgroundPosition: 'center',
}}
>
{row.smallThumbBinary && (
{thumbSrc ? (
<Box
component="img"
alt=""
src={`data:image/avif;base64,${row.smallThumbBinary}`}
src={thumbSrc}
loading="lazy"
sx={{ width: '100%', height: '100%', objectFit: 'cover', display: 'block' }}
/>
) : (
thumbHashUrl && (
<Box
component="img"
alt=""
src={thumbHashUrl}
sx={{ width: '100%', height: '100%', objectFit: 'cover', display: 'block' }}
/>
)
)}
</Box>
<Typography