# Image Usage - Quick Reference Card

## 🎯 At a Glance

| Item | Status | Details |
|------|--------|---------|
| **HTML `<img>` Tags** | ✅ 0 found | All replaced with next/image |
| **next/image Used** | ✅ 8 files | Proper implementation across app |
| **Image Components** | ✅ 3 specialized | Gallery, Lightbox, Upload |
| **Configuration** | ✅ Configured | remotePatterns + CSP headers |
| **Accessibility** | ✅ Full support | Alt text, keyboard nav, ARIA |
| **Security** | ✅ HTTPS only | CSP configured, blob URLs for preview |

---

## 📁 Where Images Are Used

### **Core Image Components**
```
components/listings/image-gallery.tsx      ← Main gallery viewer
components/listings/image-lightbox.tsx     ← Fullscreen view
components/listings/image-upload.tsx       ← Upload with preview
```

### **Components That Display Images**
```
components/search/property-card.tsx        → Thumbnail in search results
components/agents/agent-profile-client.tsx → Avatar + agent's listings
components/comparison/comparison-table.tsx → Comparison images
components/listings/listing-detail-client.tsx → Integrates ImageGallery
```

### **Page Components**
```
app/[locale]/(public)/listings/[id]/page.tsx       → Listing detail (uses ImageGallery)
app/[locale]/(public)/search/page.tsx              → Search results (uses PropertyCard)
app/[locale]/(public)/agents/[id]/page.tsx         → Agent profile
app/[locale]/(dashboard)/listings/page.tsx         → Dashboard listings
app/[locale]/(dashboard)/listings/new/page.tsx     → Upload new listing
```

---

## 🔧 Configuration

### **next.config.js**
```javascript
images: {
  remotePatterns: [
    {
      protocol: 'https',
      hostname: '**',
    },
  ],
}
```

### **CSP Headers**
```
img-src 'self' data: blob: https://*.mapbox.com https://*.tiles.mapbox.com https:
```
- ✅ Allows blob: (file preview)
- ✅ Allows data: (inline images)
- ✅ Allows all HTTPS

---

## 📊 Image Component Details

### ImageGallery
```typescript
<ImageGallery 
  media={propertyMedia}  // PropertyMedia[]
  className="w-full"
/>
```
**Features:** Main + thumbnails, navigation, counter, lightbox integration

### ImageLightbox
```typescript
<ImageLightbox 
  images={images}
  initialIndex={0}
  open={isOpen}
  onClose={() => setIsOpen(false)}
/>
```
**Features:** Keyboard nav, swipe, preloading, focus trap

### ImageUpload
```typescript
<ImageUpload 
  images={uploadedImages}
  onChange={setUploadedImages}
  maxFiles={20}
/>
```
**Features:** Drag-drop, validation (JPEG/PNG/WebP), preview, cleanup

---

## 🎨 Image Data Types

```typescript
interface PropertyMedia {
  id: string;
  url: string;              // Image URL
  type: 'image' | 'video';  // Media type
  order: number;            // Display order
  caption?: string;         // Optional caption
}

interface ImageFile {
  file: File;               // Browser File
  preview: string;          // blob: URL
}
```

---

## ⚡ Performance Features

| Feature | Status |
|---------|--------|
| Responsive sizing (`sizes` prop) | ✅ Implemented |
| Priority loading for above-fold | ✅ Implemented |
| Image preloading in lightbox | ✅ Implemented |
| Blob URL cleanup (memory) | ✅ Implemented |
| Skeleton placeholders | ⚠️ Not implemented |
| Image compression on upload | ⚠️ Not implemented |

---

## ♿ Accessibility Features

| Feature | Status |
|---------|--------|
| Alt text on images | ✅ Vietnamese |
| ARIA labels | ✅ Implemented |
| Keyboard navigation | ✅ Arrow keys + Escape |
| Focus trap in modal | ✅ Implemented |
| Tab trapping | ✅ Implemented |

---

## 🔒 Security Checklist

- ✅ HTTPS-only remote patterns
- ✅ CSP headers configured
- ✅ blob: URLs only for client-side preview
- ⚠️ API image URL validation - **TO DO**
- ⚠️ User upload scanning - **TO DO**

---

## 📝 Common Tasks

### Adding Images to a Component
```tsx
import Image from 'next/image';

<Image
  src={imageUrl}
  alt="Descriptive text in Vietnamese"
  fill
  sizes="(max-width: 768px) 100vw, 50vw"
  className="object-cover"
/>
```

### Showing Image Gallery
```tsx
import { ImageGallery } from '@/components/listings/image-gallery';

<ImageGallery 
  media={property.media}
/>
```

### File Upload
```tsx
import { ImageUpload } from '@/components/listings/image-upload';

const [images, setImages] = useState<ImageFile[]>([]);

<ImageUpload 
  images={images}
  onChange={setImages}
  maxFiles={20}
/>
```

---

## 🚨 Important Notes

1. **Never use HTML `<img>` tags** - Use `next/image` instead
2. **Exception:** Blob URL preview in image-upload is OK
3. **Always provide alt text** - Use Vietnamese text
4. **Use `sizes` prop** - For responsive images
5. **Set `priority`** - For above-fold images
6. **Revoke blob URLs** - On unmount to prevent memory leaks
7. **Validate image URLs** - At API layer before returning

---

## 📞 Questions?

See `IMAGE_AUDIT_REPORT.md` for complete details and recommendations.
