Skip to content

Image Gallery

The image gallery is a feature of the front-end application that allows users to upload, view, and select images for use in various parts of the application, such as client logos, brand images, etc.

Overview

The image gallery system consists of several components:

  1. Backend API: Handles image uploads, storage, and retrieval
  2. Database: Stores image metadata
  3. Frontend Components: Displays images and provides selection functionality

Implementation Details

Backend

Images are stored in the filesystem under the /static/images/ directory. The backend API provides endpoints for:

  • Uploading images
  • Retrieving images
  • Deleting images

The image metadata is stored in the database, including:

  • Original filename
  • Storage filename (UUID-based)
  • MIME type
  • Size
  • Dimensions (width and height)
  • URL path

Frontend Components

The frontend includes several components for working with images:

ImageGallery.tsx

The ImageGallery.tsx component displays a grid of images with upload functionality. It includes:

  • A grid layout for displaying images
  • An upload button for adding new images
  • Pagination controls for navigating through large collections of images
  • Hover effects for image selection
  • Delete functionality for removing images

ImageSelectionModal.tsx

The ImageSelectionModal.tsx component is a modal dialog for selecting images to use in forms. It includes:

  • A grid layout for displaying images
  • Search functionality for finding specific images
  • Selection functionality for choosing an image
  • A preview of the selected image
  • Confirmation and cancel buttons

URL Handling for Static Files

Important: Static file URLs (like image paths) should not have trailing slashes added to them. The API client has special handling to skip adding trailing slashes to URLs that start with /static/.

This is critical because:

  1. Static file URLs like /static/images/filename.png must be preserved exactly as they are
  2. Adding a trailing slash would result in /static/images/filename.png/ which is invalid

Usage in Forms

To use images in forms (like client or brand forms):

  1. Click the "Gallery" button next to the image upload field
  2. Select an image from the gallery
  3. The selected image will be used as the logo/image for the entity

The implementation follows these steps:

  1. The form component includes an image field with a file input and a gallery button
  2. When the gallery button is clicked, the ImageSelectionModal is opened
  3. When an image is selected in the modal, the modal is closed and the selected image is set as the value of the image field
  4. The form submission includes the selected image's ID or URL

Troubleshooting

If images are not appearing in the gallery or selection modals:

  1. Check that the image files exist in the /static/images/ directory
  2. Verify that the image records exist in the database
  3. Ensure the API client is not modifying static file URLs (no trailing slashes should be added)
  4. Check browser network requests for any 404 errors when loading images
  5. Verify that the static files directory is properly mounted and accessible

Adding New Image Features

When adding new features that use images:

  1. Use the existing ImageSelectionModal component for image selection
  2. Follow the pattern in ClientForm.tsx or BrandForm.tsx for implementation
  3. Make sure to handle both file uploads and gallery selection

Example implementation:

import { useState } from "react";
import { ImageSelectionModal } from "@/components/images/ImageSelectionModal";

const MyForm = () => {
  const [selectedImage, setSelectedImage] = useState<string | null>(null);
  const [isGalleryOpen, setIsGalleryOpen] = useState(false);

  const handleImageSelect = (imageUrl: string) => {
    setSelectedImage(imageUrl);
    setIsGalleryOpen(false);
  };

  return (
    <form>
      {/* Other form fields */}

      <div className="form-group">
        <label>Image</label>
        <div className="flex items-center">
          {selectedImage && (
            <img
              src={selectedImage}
              alt="Selected"
              className="w-16 h-16 object-cover mr-2"
            />
          )}
          <input
            type="file"
            accept="image/*"
            onChange={(e) => {
              // Handle file upload
            }}
          />
          <button
            type="button"
            onClick={() => setIsGalleryOpen(true)}
            className="ml-2 px-3 py-1 bg-blue-500 text-white rounded"
          >
            Gallery
          </button>
        </div>
      </div>

      {/* Other form fields */}

      {isGalleryOpen && (
        <ImageSelectionModal
          onSelect={handleImageSelect}
          onClose={() => setIsGalleryOpen(false)}
        />
      )}
    </form>
  );
};

Future Improvements

Potential improvements to the image gallery include:

  1. Image Editing: Add basic image editing functionality (crop, resize, rotate)
  2. Categories: Allow users to categorize images for easier organization
  3. Bulk Upload: Support uploading multiple images at once
  4. Drag and Drop: Add drag and drop support for image uploads
  5. Image Optimization: Automatically optimize images for web use