Browse Source

refactor(imports): optimize react hooks and improve code structure

- Refactor useEffect hooks to use useCallback for better performance
- Move async functions inside useEffect to prevent unnecessary re-renders
- Add proper dependency arrays to useEffect hooks
- Improve type safety with RawImportData interface
- Fix whitespace and formatting issues
vidane 6 months ago
parent
commit
a3db31b6f7

+ 19 - 19
app/components/imports/CreateImportDialog.tsx

@@ -29,31 +29,31 @@ export function CreateImportDialog({ open, onOpenChange, onSuccess }: CreateImpo
   const { toast } = useToast();
 
   useEffect(() => {
-    if (open) {
-      loadLayouts();
+    async function loadLayouts() {
+      try {
+        const result = await getLayoutConfigurations();
+        if (result.success && result.data) {
+          setLayouts(result.data);
+        }
+      } catch {
+        toast({
+          title: 'Error',
+          description: 'Failed to load layout configurations',
+          variant: 'destructive',
+        });
+      } finally {
+        setLoadingLayouts(false);
+      }
     }
-  }, [open, loadLayouts]);
 
-  async function loadLayouts() {
-    try {
-      const result = await getLayoutConfigurations();
-      if (result.success && result.data) {
-        setLayouts(result.data);
-      }
-    } catch {
-      toast({
-        title: 'Error',
-        description: 'Failed to load layout configurations',
-        variant: 'destructive',
-      });
-    } finally {
-      setLoadingLayouts(false);
+    if (open) {
+      loadLayouts();
     }
-  }
+  }, [open, toast]);
 
   async function handleSubmit(e: React.FormEvent) {
     e.preventDefault();
-    
+
     if (!name.trim()) {
       toast({
         title: 'Error',

+ 11 - 11
app/components/imports/ImportDetailDialog.tsx

@@ -1,6 +1,6 @@
 'use client';
 
-import { useState, useEffect } from 'react';
+import { useState, useEffect, useCallback } from 'react';
 import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from '@/components/ui/dialog';
 import { Button } from '@/components/ui/button';
 import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
@@ -59,13 +59,7 @@ export function ImportDetailDialog({ open, onOpenChange, importId }: ImportDetai
   const [calculating, setCalculating] = useState(false);
   const { toast } = useToast();
 
-  useEffect(() => {
-    if (open && importId) {
-      loadImportDetail();
-    }
-  }, [open, importId]);
-
-  async function loadImportDetail() {
+  const loadImportDetail = useCallback(async () => {
     try {
       const result = await getImportById(importId);
       if (result.success && result.data) {
@@ -88,7 +82,13 @@ export function ImportDetailDialog({ open, onOpenChange, importId }: ImportDetai
     } finally {
       setLoading(false);
     }
-  }
+  }, [importId, toast]);
+
+  useEffect(() => {
+    if (open && importId) {
+      loadImportDetail();
+    }
+  }, [open, importId, loadImportDetail]);
 
   async function handleCalculateSummaries() {
     setCalculating(true);
@@ -195,8 +195,8 @@ export function ImportDetailDialog({ open, onOpenChange, importId }: ImportDetai
             <CardHeader>
               <div className="flex justify-between items-center">
                 <CardTitle>Cintas Summaries</CardTitle>
-                <Button 
-                  onClick={handleCalculateSummaries} 
+                <Button
+                  onClick={handleCalculateSummaries}
                   disabled={calculating}
                   size="sm"
                 >

+ 19 - 8
app/imports/page.tsx

@@ -1,6 +1,6 @@
 'use client';
 
-import { useState, useEffect } from 'react';
+import { useState, useEffect, useCallback } from 'react';
 import { Plus, FileText, Calendar, Trash2, Edit } from 'lucide-react';
 import { Button } from '@/components/ui/button';
 import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
@@ -23,6 +23,17 @@ interface Import {
   };
 }
 
+interface RawImportData {
+  id: number;
+  name: string;
+  importDate: Date | string;
+  layoutId: number;
+  layout: {
+    id: number;
+    name: string;
+  };
+}
+
 export default function ImportsPage() {
   const [imports, setImports] = useState<Import[]>([]);
   const [loading, setLoading] = useState(true);
@@ -32,16 +43,12 @@ export default function ImportsPage() {
   const [selectedImport, setSelectedImport] = useState<Import | null>(null);
   const { toast } = useToast();
 
-  useEffect(() => {
-    loadImports();
-  }, []);
-
-  async function loadImports() {
+  const loadImports = useCallback(async () => {
     try {
       const result = await getImports();
       if (result.success && result.data) {
         // Transform the data to match our Import interface
-        const transformedImports = result.data.map(item => ({
+        const transformedImports = result.data.map((item: RawImportData) => ({
           id: item.id,
           name: item.name,
           importDate: item.importDate instanceof Date
@@ -71,7 +78,11 @@ export default function ImportsPage() {
     } finally {
       setLoading(false);
     }
-  }
+  }, [toast]);
+
+  useEffect(() => {
+    loadImports();
+  }, [loadImports]);
 
   async function handleDeleteImport(id: number) {
     if (!confirm('Are you sure you want to delete this import?')) return;