AddSectionDialog.tsx 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. "use client";
  2. import { useState } from "react";
  3. import { useRouter } from "next/navigation";
  4. import { createLayoutSection } from "@/app/actions/layout-configurations";
  5. import { Button } from "@/components/ui/button";
  6. import {
  7. Dialog,
  8. DialogContent,
  9. DialogDescription,
  10. DialogFooter,
  11. DialogHeader,
  12. DialogTitle,
  13. } from "@/components/ui/dialog";
  14. import { Input } from "@/components/ui/input";
  15. import { Label } from "@/components/ui/label";
  16. import { useToast } from "@/hooks/use-toast";
  17. interface AddSectionDialogProps {
  18. configurationId: number;
  19. open: boolean;
  20. onOpenChange: (open: boolean) => void;
  21. }
  22. export function AddSectionDialog({
  23. configurationId,
  24. open,
  25. onOpenChange,
  26. }: AddSectionDialogProps) {
  27. const router = useRouter();
  28. const { toast } = useToast();
  29. const [isLoading, setIsLoading] = useState(false);
  30. const [formData, setFormData] = useState({
  31. name: "",
  32. type: "table",
  33. sheetName: "",
  34. tableName: "",
  35. startingRow: "",
  36. endingRow: "",
  37. });
  38. const handleSubmit = async (e: React.FormEvent) => {
  39. e.preventDefault();
  40. setIsLoading(true);
  41. try {
  42. const result = await createLayoutSection(configurationId, {
  43. name: formData.name,
  44. type: formData.type,
  45. sheetName: formData.sheetName,
  46. tableName: formData.tableName,
  47. startingRow: formData.startingRow ? parseInt(formData.startingRow) : undefined,
  48. endingRow: formData.endingRow ? parseInt(formData.endingRow) : undefined,
  49. });
  50. if (result.success) {
  51. toast({
  52. title: "Section added successfully",
  53. description: `Section "${formData.name}" has been added to the configuration.`,
  54. });
  55. // Reset form and close dialog
  56. setFormData({
  57. name: "",
  58. type: "table",
  59. sheetName: "",
  60. tableName: "",
  61. startingRow: "",
  62. endingRow: "",
  63. });
  64. onOpenChange(false);
  65. // Refresh the page to show the new section
  66. router.refresh();
  67. } else {
  68. toast({
  69. title: "Error adding section",
  70. description: result.error || "Failed to add section",
  71. variant: "destructive",
  72. });
  73. }
  74. } catch {
  75. toast({
  76. title: "Error",
  77. description: "An unexpected error occurred",
  78. variant: "destructive",
  79. });
  80. } finally {
  81. setIsLoading(false);
  82. }
  83. };
  84. const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
  85. const { name, value } = e.target;
  86. setFormData((prev) => ({ ...prev, [name]: value }));
  87. };
  88. return (
  89. <Dialog open={open} onOpenChange={onOpenChange}>
  90. <DialogContent className="sm:max-w-[500px]">
  91. <DialogHeader>
  92. <DialogTitle>Add New Section</DialogTitle>
  93. <DialogDescription>
  94. Create a new section for this layout configuration
  95. </DialogDescription>
  96. </DialogHeader>
  97. <form onSubmit={handleSubmit}>
  98. <div className="grid gap-4 py-4">
  99. <div className="grid gap-2">
  100. <Label htmlFor="name">Section Name *</Label>
  101. <Input
  102. id="name"
  103. name="name"
  104. value={formData.name}
  105. onChange={handleChange}
  106. placeholder="e.g., Customer Information"
  107. required
  108. />
  109. </div>
  110. <div className="grid gap-2">
  111. <Label htmlFor="type">Section Type *</Label>
  112. <Input
  113. id="type"
  114. name="type"
  115. value={formData.type}
  116. onChange={handleChange}
  117. placeholder="e.g., table, header, footer"
  118. required
  119. />
  120. </div>
  121. <div className="grid gap-2">
  122. <Label htmlFor="sheetName">Sheet Name *</Label>
  123. <Input
  124. id="sheetName"
  125. name="sheetName"
  126. value={formData.sheetName}
  127. onChange={handleChange}
  128. placeholder="e.g., Sheet1"
  129. required
  130. />
  131. </div>
  132. <div className="grid gap-2">
  133. <Label htmlFor="tableName">Table Name *</Label>
  134. <Input
  135. id="tableName"
  136. name="tableName"
  137. value={formData.tableName}
  138. onChange={handleChange}
  139. placeholder="e.g., customers"
  140. required
  141. />
  142. </div>
  143. <div className="grid grid-cols-2 gap-4">
  144. <div className="grid gap-2">
  145. <Label htmlFor="startingRow">Starting Row</Label>
  146. <Input
  147. id="startingRow"
  148. name="startingRow"
  149. type="number"
  150. value={formData.startingRow}
  151. onChange={handleChange}
  152. placeholder="e.g., 2"
  153. min="1"
  154. />
  155. </div>
  156. <div className="grid gap-2">
  157. <Label htmlFor="endingRow">Ending Row</Label>
  158. <Input
  159. id="endingRow"
  160. name="endingRow"
  161. type="number"
  162. value={formData.endingRow}
  163. onChange={handleChange}
  164. placeholder="e.g., 100"
  165. min="1"
  166. />
  167. </div>
  168. </div>
  169. </div>
  170. <DialogFooter>
  171. <Button
  172. type="button"
  173. variant="outline"
  174. onClick={() => onOpenChange(false)}
  175. disabled={isLoading}
  176. >
  177. Cancel
  178. </Button>
  179. <Button type="submit" disabled={isLoading}>
  180. {isLoading ? "Adding..." : "Add Section"}
  181. </Button>
  182. </DialogFooter>
  183. </form>
  184. </DialogContent>
  185. </Dialog>
  186. );
  187. }