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 { interface ItemThumbnailProps {
url: string | null; url: string | null;
alt: string; alt: string;
size?: 'sm' | 'md'; size?: 'sm' | 'md' | 'lg';
onClick?: () => void; onClick?: () => void;
} }
const sizeClassMap: Record<Required<ItemThumbnailProps>['size'], string> = { const sizeClassMap: Record<Required<ItemThumbnailProps>['size'], string> = {
sm: 'h-14 w-14', 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) { export function ItemThumbnail({ url, alt, size = 'sm', onClick }: ItemThumbnailProps) {
@@ -13,6 +13,7 @@ interface ProjectItemsDesktopTableProps {
onEditItem: (item: Item) => void; onEditItem: (item: Item) => void;
projectId: string | undefined; projectId: string | undefined;
onViewItemImages: (item: Item) => void; onViewItemImages: (item: Item) => void;
showLargeImages: boolean;
} }
export function ProjectItemsDesktopTable({ export function ProjectItemsDesktopTable({
@@ -22,7 +23,8 @@ export function ProjectItemsDesktopTable({
onTogglePrices, onTogglePrices,
onEditItem, onEditItem,
projectId, projectId,
onViewItemImages onViewItemImages,
showLargeImages
}: ProjectItemsDesktopTableProps) { }: ProjectItemsDesktopTableProps) {
return ( return (
<div className="hidden md:block"> <div className="hidden md:block">
@@ -64,7 +66,7 @@ export function ProjectItemsDesktopTable({
<ItemThumbnail <ItemThumbnail
url={item.defaultImageUrl} url={item.defaultImageUrl}
alt={displayName} alt={displayName}
size="sm" size={showLargeImages ? 'md' : 'sm'}
onClick={() => onViewItemImages(item)} onClick={() => onViewItemImages(item)}
/> />
<div className="flex flex-1 flex-col gap-1"> <div className="flex flex-1 flex-col gap-1">
@@ -4,6 +4,8 @@ interface ProjectItemsHeaderProps {
showDifferencesOnly: boolean; showDifferencesOnly: boolean;
hasAttributeDifferences: boolean; hasAttributeDifferences: boolean;
onToggleDifferences: (value: boolean) => void; onToggleDifferences: (value: boolean) => void;
showLargeImages: boolean;
onToggleLargeImages: (value: boolean) => void;
} }
export function ProjectItemsHeader({ export function ProjectItemsHeader({
@@ -11,7 +13,9 @@ export function ProjectItemsHeader({
isLoading, isLoading,
showDifferencesOnly, showDifferencesOnly,
hasAttributeDifferences, hasAttributeDifferences,
onToggleDifferences onToggleDifferences,
showLargeImages,
onToggleLargeImages
}: ProjectItemsHeaderProps) { }: ProjectItemsHeaderProps) {
const subtitle = isLoading const subtitle = isLoading
? 'Loading items…' ? 'Loading items…'
@@ -25,16 +29,27 @@ export function ProjectItemsHeader({
<h2 className="text-xl font-semibold text-slate-900">Items</h2> <h2 className="text-xl font-semibold text-slate-900">Items</h2>
<p className="text-sm text-slate-500">{subtitle}</p> <p className="text-sm text-slate-500">{subtitle}</p>
</div> </div>
<label className="flex items-center gap-2 text-xs font-medium uppercase tracking-wide text-slate-500"> <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">
<input <label className="flex items-center gap-2">
type="checkbox" <input
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" type="checkbox"
checked={showDifferencesOnly} 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"
onChange={(event) => onToggleDifferences(event.target.checked)} checked={showDifferencesOnly}
disabled={!hasAttributeDifferences} onChange={(event) => onToggleDifferences(event.target.checked)}
/> disabled={!hasAttributeDifferences}
Show differences only />
</label> 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> </header>
); );
} }
@@ -12,6 +12,7 @@ interface ProjectItemsMobileListProps {
onEditItem: (item: Item) => void; onEditItem: (item: Item) => void;
projectId: string | undefined; projectId: string | undefined;
onViewItemImages: (item: Item) => void; onViewItemImages: (item: Item) => void;
showLargeImages: boolean;
} }
export function ProjectItemsMobileList({ export function ProjectItemsMobileList({
@@ -21,7 +22,8 @@ export function ProjectItemsMobileList({
onTogglePrices, onTogglePrices,
onEditItem, onEditItem,
projectId, projectId,
onViewItemImages onViewItemImages,
showLargeImages
}: ProjectItemsMobileListProps) { }: ProjectItemsMobileListProps) {
return ( return (
<div className="space-y-4 md:hidden"> <div className="space-y-4 md:hidden">
@@ -38,7 +40,7 @@ export function ProjectItemsMobileList({
<ItemThumbnail <ItemThumbnail
url={item.defaultImageUrl} url={item.defaultImageUrl}
alt={displayName} alt={displayName}
size="md" size={showLargeImages ? 'lg' : 'md'}
onClick={() => onViewItemImages(item)} onClick={() => onViewItemImages(item)}
/> />
<div className="flex flex-1 flex-col gap-2"> <div className="flex flex-1 flex-col gap-2">
@@ -39,6 +39,7 @@ export function ProjectItemsSection({
}: ProjectItemsSectionProps) { }: ProjectItemsSectionProps) {
const [showDifferencesOnly, setShowDifferencesOnly] = useState(false); const [showDifferencesOnly, setShowDifferencesOnly] = useState(false);
const [expandedItemId, setExpandedItemId] = useState<string | null>(null); const [expandedItemId, setExpandedItemId] = useState<string | null>(null);
const [showLargeImages, setShowLargeImages] = useState(false);
const mismatchedAttributes = useMemo(() => { const mismatchedAttributes = useMemo(() => {
const result = new Set<string>(); const result = new Set<string>();
@@ -117,6 +118,8 @@ export function ProjectItemsSection({
showDifferencesOnly={showDifferencesOnly} showDifferencesOnly={showDifferencesOnly}
hasAttributeDifferences={hasAttributeDifferences} hasAttributeDifferences={hasAttributeDifferences}
onToggleDifferences={(value) => setShowDifferencesOnly(value)} onToggleDifferences={(value) => setShowDifferencesOnly(value)}
showLargeImages={showLargeImages}
onToggleLargeImages={(value) => setShowLargeImages(value)}
/> />
{error ? ( {error ? (
@@ -137,6 +140,7 @@ export function ProjectItemsSection({
onEditItem={onEditItem} onEditItem={onEditItem}
projectId={projectId} projectId={projectId}
onViewItemImages={onViewItemImages} onViewItemImages={onViewItemImages}
showLargeImages={showLargeImages}
/> />
<ProjectItemsMobileList <ProjectItemsMobileList
@@ -147,6 +151,7 @@ export function ProjectItemsSection({
onEditItem={onEditItem} onEditItem={onEditItem}
projectId={projectId} projectId={projectId}
onViewItemImages={onViewItemImages} onViewItemImages={onViewItemImages}
showLargeImages={showLargeImages}
/> />
</section> </section>