Skip to content

Shadow is broken #410

@kopyl

Description

@kopyl
Image

Here is how i use it:

"use client"

import { useState, useEffect } from "react"
import { Card, CardContent } from "@/components/ui/card"
import { Button } from "@/components/ui/button"
import { ChevronLeft, ChevronRight, Loader2, Copy } from "lucide-react"
import Image from "next/image"
import styles from './inspection-items-viewer.module.sass'
import toast, { Toaster } from 'react-hot-toast';

const notifyAboutCopying = () => toast.success('Copied to clipboard!');

interface InspectionItem {
  car_inspection_item_id: number
  reviewer_note: string
  car_make: string
  car_model: string
  car_color: string
  car_plate_number: string
  driver_name: string
  file_path: string
  inspection_item_type_description: string
  inspection_item_type_name: string
}

export function InspectionItemsViewer() {
  const [items, setItems] = useState<InspectionItem[]>([])
  const [loading, setLoading] = useState(true)
  const [currentPage, setCurrentPage] = useState(1)
  const [totalPages, setTotalPages] = useState(0)
  const [error, setError] = useState<string | null>(null)

  const fetchItems = async (page: number) => {
    setLoading(true)
    setError(null)

    try {
      const response = await fetch(`/api/inspection-items?page=${page}`)
      if (!response.ok) {
        throw new Error("Failed to fetch inspection items")
      }

      const data = await response.json()
      setItems(data.items)
      setTotalPages(data.totalPages)
    } catch (err) {
      setError(err instanceof Error ? err.message : "An error occurred")
    } finally {
      setLoading(false)
    }
  }

  useEffect(() => {
    fetchItems(currentPage)
  }, [currentPage])

  const handlePrevPage = () => {
    if (currentPage > 1) {
      setCurrentPage(currentPage - 1)
    }
  }

  const handleNextPage = () => {
    if (currentPage < totalPages) {
      setCurrentPage(currentPage + 1)
    }
  }

  if (error) {
    return (
      <div className={styles.errorContainer}>
        <p className={styles.errorText}>Error: {error}</p>
        <Button onClick={() => fetchItems(currentPage)} className={styles.retryButton}>
          Retry
        </Button>
      </div>
    )
  }

  return (
    <div className={styles.wrapper}>
      {/* Pagination Controls */}
      <div className={styles.paginationControls}>
        <Button onClick={handlePrevPage} disabled={currentPage === 1 || loading} variant="outline">
          <ChevronLeft className={`${styles.icon} ${styles.iconLeft}`} />
          Previous
        </Button>

        <span className={styles.pageInfo}>
          Page {currentPage} of {totalPages}
        </span>

        <Button onClick={handleNextPage} disabled={currentPage === totalPages || loading} variant="outline">
          Next
          <ChevronRight className={`${styles.icon} ${styles.iconRight}`} />
        </Button>
      </div>

      {/* Loading State */}
      {loading && (
        <div className={styles.loadingContainer}>
          <Loader2 className={styles.spinner} />
        </div>
      )}

      {/* Inspection Items Grid */}
      {!loading && (
        <div className={styles.itemsGrid}>
          {items.map((item) => (
            <Card key={item.car_inspection_item_id} className={styles.card}>
              <div className={styles.imageContainer}>
                <Image
                  src={`/api/images/${item.file_path}`}
                  alt={`Inspection item ${item.car_inspection_item_id}`}
                  fill
                  className={styles.image}
                  sizes="1319px"
                />
              </div>

              <CardContent className={styles.cardContent}>
                <div className={styles.itemId}>
                  <Copy className={styles.copyIcon} onClick={() => {
                    navigator.clipboard.writeText(item.car_inspection_item_id.toString())
                    notifyAboutCopying()
                  }} />
                  <p className={styles.itemId}>{item.car_inspection_item_id}</p>
                  <Toaster position="top-center" reverseOrder={false} />
                </div>

                <div className={styles.itemType}>
                  {item.inspection_item_type_description}{" "}
                  <span className={styles.typeName}>({item.inspection_item_type_name})</span>
                </div>

                <div className={styles.reviewerNote}>{item.reviewer_note}</div>

                <div className={styles.carDetails}>
                  <div className={styles.carModel}>
                    {item.car_make} {item.car_model}
                  </div>
                  <div className={styles.carInfo}>Color: {item.car_color}</div>
                  <div className={styles.carInfo}>Plate: {item.car_plate_number}</div>
                  <div className={styles.carInfo}>Driver: {item.driver_name}</div>
                </div>
              </CardContent>
            </Card>
          ))}
        </div>
      )}

      {/* Empty State */}
      {!loading && items.length === 0 && (
        <div className={styles.emptyState}>
          <p className={styles.emptyText}>No inspection items found.</p>
        </div>
      )}
    </div>
  )
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions