Ctrl K
ComunidadGuías…

src/components/certifications/certifications-page-content.tsx

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
"use client";

import { useCallback, useState } from "react";
import { useAuthGuard } from "@/hooks/useAuthGuard";
import { useInfiniteResource } from "@/hooks/useInfiniteResource";
import { useDeleteResource } from "@/hooks/useDeleteResource";
import { useSavedElsewhere } from "@/hooks/useSavedElsewhere";
import { certificationsAPI, Certification } from "@/lib/api/certifications";
import { CertificationsPageFrame } from "@/components/certifications/certifications-page-frame";
import { CertificationCard } from "@/components/certifications/certification-card";
import { ConfirmDialog } from "@/components/ui/confirm-dialog";
import { PageSpinner } from "@/components/ui/page-spinner";
import { CertificationDialog } from "@/components/certifications/certification-dialog";
import { CertificationViewDialog } from "@/components/certifications/certification-view-dialog";

export function CertificationsPageContent() {
  const { user, isAuthenticated, isLoading: isAuthLoading } = useAuthGuard();

  // `null` = the dialog is closed; a certification = editing it; `undefined` = creating.
  const [editing, setEditing] = useState<Certification | null | undefined>(
    null,
  );
  const [viewing, setViewing] = useState<Certification | null>(null);

  const fetchCertifications = useCallback(
    (page: number, perPage: number) =>
      certificationsAPI.getCertifications(page, perPage),
    [],
  );

  const {
    items: certifications,
    isLoading,
    isLoadingMore,
    totalCount,
    itemsPerPage,
    hasMore,
    loadFailed,
    loadMore,
    removeItem,
    applySaved,
  } = useInfiniteResource<Certification>(fetchCertifications, {
    keyOf: (certification) => certification.uuid,
    enabled: !!user,
    errorMessage: "Failed to load certifications. Please try again.",
  });

  useSavedElsewhere("certification", ({ certification }) =>
    applySaved(certification),
  );

  const {
    deletingId,
    pendingId,
    confirmMessage,
    requestDelete,
    cancelDelete,
    confirmDelete,
  } = useDeleteResource(certificationsAPI.deleteCertification, {
    confirmMessage:
      "Are you sure you want to delete this certification? The card images stored with it are permanently deleted too.",
    successMessage: "Certification deleted successfully.",
    errorMessage: "Failed to delete certification. Please try again.",
    // The card goes locally rather than by re-reading the pages around it: a
    // diver who has scrolled several pages in should not have the list
    // collapse back to the first one under them.
    onDeleted: removeItem,
  });

  if (isAuthLoading || !isAuthenticated) {
    return <PageSpinner variant="inset" />;
  }

  return (
    <>
      <CertificationsPageFrame
        isLoading={isLoading}
        totalCount={totalCount}
        itemsPerPage={itemsPerPage}
        isLoadingMore={isLoadingMore}
        loadFailed={loadFailed}
        hasMore={hasMore}
        onLoadMore={loadMore}
        onNew={() => setEditing(undefined)}
        cards={certifications.map((certification) => (
          <CertificationCard
            key={certification.uuid}
            certification={certification}
            onView={() => setViewing(certification)}
            onEdit={() => setEditing(certification)}
            onDelete={() => requestDelete(certification.uuid)}
            isDeleting={deletingId === certification.uuid}
          />
        ))}
      />

      {user && (
        <CertificationDialog
          open={editing !== null}
          onOpenChange={(open) => !open && setEditing(null)}
          certification={editing}
          // The card images ride on that dialog's own save, so the certification
          // it hands back already carries whatever landed.
          onSaved={applySaved}
        />
      )}

      <CertificationViewDialog
        certification={viewing}
        onOpenChange={(open) => !open && setViewing(null)}
      />

      <ConfirmDialog
        open={pendingId !== null}
        onOpenChange={(open) => !open && cancelDelete()}
        title="Delete certification"
        description={confirmMessage}
        confirmText="Delete"
        isLoading={deletingId === pendingId}
        onConfirm={confirmDelete}
      />
    </>
  );
}