LayoutSectionCard.tsx 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. "use client";
  2. import { useState } from "react";
  3. import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
  4. import { Badge } from "@/components/ui/badge";
  5. import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
  6. import { Button } from "@/components/ui/button";
  7. import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@/components/ui/dropdown-menu";
  8. import { MoreVertical, Trash2 } from "lucide-react";
  9. import { DeleteSectionDialog } from "./DeleteSectionDialog";
  10. interface LayoutSection {
  11. id: number;
  12. name: string;
  13. type: string;
  14. sheetName: string;
  15. startingRow?: number | null;
  16. endingRow?: number | null;
  17. tableName: string;
  18. fields: LayoutSectionField[];
  19. }
  20. interface LayoutSectionField {
  21. id: number;
  22. name: string;
  23. dataType: string;
  24. dataTypeFormat: string | null;
  25. cellPosition: string;
  26. importTableColumnName: string;
  27. importColumnOrderNumber: number;
  28. }
  29. interface LayoutSectionCardProps {
  30. section: LayoutSection;
  31. onSectionDeleted?: () => void;
  32. }
  33. export function LayoutSectionCard({ section, onSectionDeleted }: LayoutSectionCardProps) {
  34. const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
  35. const getTypeColor = (type: string) => {
  36. switch (type.toLowerCase()) {
  37. case "properties":
  38. return "bg-blue-100 text-blue-800";
  39. case "grid":
  40. return "bg-green-100 text-green-800";
  41. default:
  42. return "bg-gray-100 text-gray-800";
  43. }
  44. };
  45. const handleCardClick = (e: React.MouseEvent) => {
  46. // Prevent navigation when clicking on the dropdown menu
  47. if ((e.target as HTMLElement).closest('.section-actions')) {
  48. return;
  49. }
  50. window.location.href = `/layout-configurations/sections/${section.id}/fields`;
  51. };
  52. return (
  53. <>
  54. <Card
  55. className="cursor-pointer hover:shadow-lg transition-shadow relative"
  56. onClick={handleCardClick}
  57. >
  58. <CardHeader>
  59. <div className="flex justify-between items-start">
  60. <div>
  61. <CardTitle className="text-lg">{section.name}</CardTitle>
  62. <CardDescription>
  63. Sheet: {section.sheetName} | Table: {section.tableName}
  64. </CardDescription>
  65. </div>
  66. <div className="section-actions flex items-center gap-2">
  67. <Badge className={getTypeColor(section.type)}>
  68. {section.type}
  69. </Badge>
  70. <DropdownMenu>
  71. <DropdownMenuTrigger asChild>
  72. <Button
  73. variant="ghost"
  74. size="sm"
  75. className="h-8 w-8 p-0"
  76. onClick={(e) => e.stopPropagation()}
  77. >
  78. <MoreVertical className="h-4 w-4" />
  79. </Button>
  80. </DropdownMenuTrigger>
  81. <DropdownMenuContent align="end">
  82. <DropdownMenuItem
  83. className="text-destructive"
  84. onClick={(e) => {
  85. e.stopPropagation();
  86. setDeleteDialogOpen(true);
  87. }}
  88. >
  89. <Trash2 className="mr-2 h-4 w-4" />
  90. Delete
  91. </DropdownMenuItem>
  92. </DropdownMenuContent>
  93. </DropdownMenu>
  94. </div>
  95. </div>
  96. </CardHeader>
  97. <CardContent>
  98. <div className="space-y-4">
  99. <div className="flex gap-4 text-sm">
  100. {section.startingRow && (
  101. <span>
  102. <strong>Rows:</strong> {section.startingRow} - {section.endingRow || "end"}
  103. </span>
  104. )}
  105. <span>
  106. <strong>Fields:</strong> {section.fields.length}
  107. </span>
  108. </div>
  109. {section.fields.length > 0 && (
  110. <div>
  111. <h4 className="font-medium mb-2">Fields</h4>
  112. <div className="overflow-x-auto">
  113. <Table>
  114. <TableHeader>
  115. <TableRow>
  116. <TableHead>Name</TableHead>
  117. <TableHead>Type</TableHead>
  118. <TableHead>Position</TableHead>
  119. <TableHead>Column</TableHead>
  120. <TableHead>Order</TableHead>
  121. </TableRow>
  122. </TableHeader>
  123. <TableBody>
  124. {section.fields.map((field) => (
  125. <TableRow key={field.id}>
  126. <TableCell className="font-medium">{field.name}</TableCell>
  127. <TableCell>
  128. <Badge variant="outline" className="text-xs">
  129. {field.dataType}
  130. </Badge>
  131. </TableCell>
  132. <TableCell>{field.cellPosition}</TableCell>
  133. <TableCell>{field.importTableColumnName}</TableCell>
  134. <TableCell>{field.importColumnOrderNumber}</TableCell>
  135. </TableRow>
  136. ))}
  137. </TableBody>
  138. </Table>
  139. </div>
  140. </div>
  141. )}
  142. </div>
  143. </CardContent>
  144. </Card>
  145. <DeleteSectionDialog
  146. open={deleteDialogOpen}
  147. onOpenChange={setDeleteDialogOpen}
  148. section={{ id: section.id, name: section.name }}
  149. onSuccess={onSectionDeleted}
  150. />
  151. </>
  152. );
  153. }