Add toggle for larger item images

This commit is contained in:
Jurgis Sakalauskas
2025-10-18 10:08:32 +03:00
parent 4701eb974d
commit c24a01b282
5 changed files with 42 additions and 17 deletions
@@ -3,13 +3,14 @@ import { useState } from 'react';
interface ItemThumbnailProps {
url: string | null;
alt: string;
size?: 'sm' | 'md';
size?: 'sm' | 'md' | 'lg';
onClick?: () => void;
}
const sizeClassMap: Record<Required<ItemThumbnailProps>['size'], string> = {
sm: 'h-14 w-14',
md: 'h-20 w-20'
md: 'h-20 w-20',
lg: 'h-28 w-28'
};
export function ItemThumbnail({ url, alt, size = 'sm', onClick }: ItemThumbnailProps) {
@@ -13,6 +13,7 @@ interface ProjectItemsDesktopTableProps {
onEditItem: (item: Item) => void;
projectId: string | undefined;
onViewItemImages: (item: Item) => void;
showLargeImages: boolean;
}
export function ProjectItemsDesktopTable({
@@ -22,7 +23,8 @@ export function ProjectItemsDesktopTable({
onTogglePrices,
onEditItem,
projectId,
onViewItemImages
onViewItemImages,
showLargeImages
}: ProjectItemsDesktopTableProps) {
return (
<div className="hidden md:block">
@@ -64,7 +66,7 @@ export function ProjectItemsDesktopTable({
<ItemThumbnail
url={item.defaultImageUrl}
alt={displayName}
size="sm"
size={showLargeImages ? 'md' : 'sm'}
onClick={() => onViewItemImages(item)}
/>
<div className="flex flex-1 flex-col gap-1">
@@ -4,6 +4,8 @@ interface ProjectItemsHeaderProps {
showDifferencesOnly: boolean;
hasAttributeDifferences: boolean;
onToggleDifferences: (value: boolean) => void;
showLargeImages: boolean;
onToggleLargeImages: (value: boolean) => void;
}
export function ProjectItemsHeader({
@@ -11,7 +13,9 @@ export function ProjectItemsHeader({
isLoading,
showDifferencesOnly,
hasAttributeDifferences,
onToggleDifferences
onToggleDifferences,
showLargeImages,
onToggleLargeImages
}: ProjectItemsHeaderProps) {
const subtitle = isLoading
? 'Loading items…'
@@ -25,16 +29,27 @@ export function ProjectItemsHeader({
<h2 className="text-xl font-semibold text-slate-900">Items</h2>
<p className="text-sm text-slate-500">{subtitle}</p>
</div>
<label className="flex items-center gap-2 text-xs font-medium uppercase tracking-wide text-slate-500">
<input
type="checkbox"
className="h-4 w-4 rounded border-slate-300 text-blue-600 focus:ring-blue-500 disabled:cursor-not-allowed disabled:border-slate-200 disabled:text-slate-300"
checked={showDifferencesOnly}
onChange={(event) => onToggleDifferences(event.target.checked)}
disabled={!hasAttributeDifferences}
/>
Show differences only
</label>
<div className="flex flex-col gap-3 text-xs font-medium uppercase tracking-wide text-slate-500 md:flex-row md:items-center md:gap-6">
<label className="flex items-center gap-2">
<input
type="checkbox"
className="h-4 w-4 rounded border-slate-300 text-blue-600 focus:ring-blue-500 disabled:cursor-not-allowed disabled:border-slate-200 disabled:text-slate-300"
checked={showDifferencesOnly}
onChange={(event) => onToggleDifferences(event.target.checked)}
disabled={!hasAttributeDifferences}
/>
Show differences only
</label>
<label className="flex items-center gap-2">
<input
type="checkbox"
className="h-4 w-4 rounded border-slate-300 text-blue-600 focus:ring-blue-500"
checked={showLargeImages}
onChange={(event) => onToggleLargeImages(event.target.checked)}
/>
Larger images
</label>
</div>
</header>
);
}
@@ -12,6 +12,7 @@ interface ProjectItemsMobileListProps {
onEditItem: (item: Item) => void;
projectId: string | undefined;
onViewItemImages: (item: Item) => void;
showLargeImages: boolean;
}
export function ProjectItemsMobileList({
@@ -21,7 +22,8 @@ export function ProjectItemsMobileList({
onTogglePrices,
onEditItem,
projectId,
onViewItemImages
onViewItemImages,
showLargeImages
}: ProjectItemsMobileListProps) {
return (
<div className="space-y-4 md:hidden">
@@ -38,7 +40,7 @@ export function ProjectItemsMobileList({
<ItemThumbnail
url={item.defaultImageUrl}
alt={displayName}
size="md"
size={showLargeImages ? 'lg' : 'md'}
onClick={() => onViewItemImages(item)}
/>
<div className="flex flex-1 flex-col gap-2">
@@ -39,6 +39,7 @@ export function ProjectItemsSection({
}: ProjectItemsSectionProps) {
const [showDifferencesOnly, setShowDifferencesOnly] = useState(false);
const [expandedItemId, setExpandedItemId] = useState<string | null>(null);
const [showLargeImages, setShowLargeImages] = useState(false);
const mismatchedAttributes = useMemo(() => {
const result = new Set<string>();
@@ -117,6 +118,8 @@ export function ProjectItemsSection({
showDifferencesOnly={showDifferencesOnly}
hasAttributeDifferences={hasAttributeDifferences}
onToggleDifferences={(value) => setShowDifferencesOnly(value)}
showLargeImages={showLargeImages}
onToggleLargeImages={(value) => setShowLargeImages(value)}
/>
{error ? (
@@ -137,6 +140,7 @@ export function ProjectItemsSection({
onEditItem={onEditItem}
projectId={projectId}
onViewItemImages={onViewItemImages}
showLargeImages={showLargeImages}
/>
<ProjectItemsMobileList
@@ -147,6 +151,7 @@ export function ProjectItemsSection({
onEditItem={onEditItem}
projectId={projectId}
onViewItemImages={onViewItemImages}
showLargeImages={showLargeImages}
/>
</section>