feat(29-02): update detail pages and LinkToGlobalItem to use GearImage
Replace object-cover on item detail, global item detail, candidate detail, global items index, and LinkToGlobalItem. Detail pages use dominant color backgrounds. LinkToGlobalItem uses cover mode for 32px thumbnails. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { Link } from "@tanstack/react-router";
|
||||
import { useEffect, useState } from "react";
|
||||
import { GearImage } from "./GearImage";
|
||||
import {
|
||||
useGlobalItem,
|
||||
useGlobalItems,
|
||||
@@ -177,11 +178,13 @@ export function LinkToGlobalItem({
|
||||
className="w-full text-left px-3 py-2 hover:bg-gray-50 transition-colors flex items-center gap-2"
|
||||
>
|
||||
{item.imageUrl ? (
|
||||
<img
|
||||
src={item.imageUrl}
|
||||
alt=""
|
||||
className="w-8 h-8 rounded object-cover shrink-0"
|
||||
/>
|
||||
<div className="w-8 h-8 rounded overflow-hidden shrink-0">
|
||||
<GearImage
|
||||
src={item.imageUrl}
|
||||
alt=""
|
||||
cover
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<div className="w-8 h-8 rounded bg-gray-100 shrink-0" />
|
||||
)}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { createFileRoute, Link } from "@tanstack/react-router";
|
||||
import { GearImage, imageContainerBg } from "../../components/GearImage";
|
||||
import { useAuth } from "../../hooks/useAuth";
|
||||
import { useFormatters } from "../../hooks/useFormatters";
|
||||
import { useGlobalItem } from "../../hooks/useGlobalItems";
|
||||
@@ -62,15 +63,25 @@ function GlobalItemDetail() {
|
||||
</div>
|
||||
|
||||
{/* Image */}
|
||||
<div className="aspect-[16/9] bg-gray-50 rounded-xl overflow-hidden">
|
||||
<div
|
||||
className="aspect-[16/9] rounded-xl overflow-hidden"
|
||||
style={{
|
||||
backgroundColor: item.imageUrl
|
||||
? imageContainerBg(item.dominantColor)
|
||||
: undefined,
|
||||
}}
|
||||
>
|
||||
{item.imageUrl ? (
|
||||
<img
|
||||
<GearImage
|
||||
src={item.imageUrl}
|
||||
alt={`${item.brand} ${item.model}`}
|
||||
className="w-full h-full object-cover"
|
||||
dominantColor={item.dominantColor}
|
||||
cropZoom={item.cropZoom}
|
||||
cropX={item.cropX}
|
||||
cropY={item.cropY}
|
||||
/>
|
||||
) : (
|
||||
<div className="w-full h-full flex flex-col items-center justify-center">
|
||||
<div className="w-full h-full bg-gray-50 flex flex-col items-center justify-center">
|
||||
<svg
|
||||
className="w-16 h-16 text-gray-300"
|
||||
fill="none"
|
||||
|
||||
@@ -2,6 +2,7 @@ import { createFileRoute, Link } from "@tanstack/react-router";
|
||||
import { ArrowLeft, LayoutGrid, LayoutList, X } from "lucide-react";
|
||||
import { useEffect, useMemo, useRef, useState } from "react";
|
||||
import { z } from "zod";
|
||||
import { GearImage } from "../../components/GearImage";
|
||||
import { GlobalItemCard } from "../../components/GlobalItemCard";
|
||||
import { useFormatters } from "../../hooks/useFormatters";
|
||||
import { useGlobalItems } from "../../hooks/useGlobalItems";
|
||||
@@ -537,15 +538,21 @@ function GlobalItemListRow({ item, weight, price }: ListRowProps) {
|
||||
className="bg-white rounded-xl border border-gray-100 flex items-center gap-4 px-4 py-3 hover:border-gray-200 hover:shadow-sm transition-all block"
|
||||
>
|
||||
{/* Thumbnail */}
|
||||
<div className="w-12 h-12 rounded-lg bg-gray-50 shrink-0 overflow-hidden">
|
||||
<div
|
||||
className="w-12 h-12 rounded-lg shrink-0 overflow-hidden"
|
||||
style={{
|
||||
backgroundColor: item.imageUrl
|
||||
? (item.dominantColor as string) || "#f3f4f6"
|
||||
: undefined,
|
||||
}}
|
||||
>
|
||||
{item.imageUrl ? (
|
||||
<img
|
||||
<GearImage
|
||||
src={item.imageUrl}
|
||||
alt={`${item.brand} ${item.model}`}
|
||||
className="w-full h-full object-cover"
|
||||
/>
|
||||
) : (
|
||||
<div className="w-full h-full flex items-center justify-center">
|
||||
<div className="w-full h-full bg-gray-50 flex items-center justify-center">
|
||||
<svg
|
||||
className="w-5 h-5 text-gray-300"
|
||||
fill="none"
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { createFileRoute, Link, useNavigate } from "@tanstack/react-router";
|
||||
import { useState } from "react";
|
||||
import { CategoryPicker } from "../../components/CategoryPicker";
|
||||
import { GearImage, imageContainerBg } from "../../components/GearImage";
|
||||
import { ImageUpload } from "../../components/ImageUpload";
|
||||
import { useFormatters } from "../../hooks/useFormatters";
|
||||
import { useDuplicateItem, useItem, useUpdateItem } from "../../hooks/useItems";
|
||||
@@ -242,15 +243,25 @@ function ItemDetail() {
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<div className="aspect-[4/3] bg-gray-50 rounded-xl overflow-hidden mb-6">
|
||||
<div
|
||||
className="aspect-[4/3] rounded-xl overflow-hidden mb-6"
|
||||
style={{
|
||||
backgroundColor: imageUrl
|
||||
? imageContainerBg(item.dominantColor)
|
||||
: undefined,
|
||||
}}
|
||||
>
|
||||
{imageUrl ? (
|
||||
<img
|
||||
<GearImage
|
||||
src={imageUrl}
|
||||
alt={item.name}
|
||||
className="w-full h-full object-cover"
|
||||
dominantColor={item.dominantColor}
|
||||
cropZoom={item.cropZoom}
|
||||
cropX={item.cropX}
|
||||
cropY={item.cropY}
|
||||
/>
|
||||
) : (
|
||||
<div className="w-full h-full flex flex-col items-center justify-center">
|
||||
<div className="w-full h-full bg-gray-50 flex flex-col items-center justify-center">
|
||||
<LucideIcon
|
||||
name={item.categoryIcon}
|
||||
size={64}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { createFileRoute, Link } from "@tanstack/react-router";
|
||||
import { useState } from "react";
|
||||
import { CategoryPicker } from "../../../../components/CategoryPicker";
|
||||
import { GearImage, imageContainerBg } from "../../../../components/GearImage";
|
||||
import { ImageUpload } from "../../../../components/ImageUpload";
|
||||
import { StatusBadge } from "../../../../components/StatusBadge";
|
||||
import { useUpdateCandidate } from "../../../../hooks/useCandidates";
|
||||
@@ -204,11 +205,19 @@ function CandidateDetailPage() {
|
||||
/>
|
||||
</div>
|
||||
) : imageUrl ? (
|
||||
<div className="aspect-[16/9] bg-gray-50 rounded-xl overflow-hidden mb-6">
|
||||
<img
|
||||
<div
|
||||
className="aspect-[16/9] rounded-xl overflow-hidden mb-6"
|
||||
style={{
|
||||
backgroundColor: imageContainerBg(candidate.dominantColor),
|
||||
}}
|
||||
>
|
||||
<GearImage
|
||||
src={imageUrl}
|
||||
alt={candidate.name}
|
||||
className="w-full h-full object-cover"
|
||||
dominantColor={candidate.dominantColor}
|
||||
cropZoom={candidate.cropZoom}
|
||||
cropX={candidate.cropX}
|
||||
cropY={candidate.cropY}
|
||||
/>
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
Reference in New Issue
Block a user