CreateImportDialog.tsx 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. 'use client';
  2. import { useState, useEffect } from 'react';
  3. import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from '@/components/ui/dialog';
  4. import { Button } from '@/components/ui/button';
  5. import { Input } from '@/components/ui/input';
  6. import { Label } from '@/components/ui/label';
  7. import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
  8. import { useToast } from '@/hooks/use-toast';
  9. import { createImport, getLayoutConfigurations } from '@/app/actions/imports';
  10. interface LayoutConfiguration {
  11. id: number;
  12. name: string;
  13. }
  14. interface CreateImportDialogProps {
  15. open: boolean;
  16. onOpenChange: (open: boolean) => void;
  17. onSuccess?: () => void;
  18. }
  19. export function CreateImportDialog({ open, onOpenChange, onSuccess }: CreateImportDialogProps) {
  20. const [name, setName] = useState('');
  21. const [layoutId, setLayoutId] = useState<string>('');
  22. const [loading, setLoading] = useState(false);
  23. const [layouts, setLayouts] = useState<LayoutConfiguration[]>([]);
  24. const [loadingLayouts, setLoadingLayouts] = useState(true);
  25. const { toast } = useToast();
  26. useEffect(() => {
  27. async function loadLayouts() {
  28. try {
  29. const result = await getLayoutConfigurations();
  30. if (result.success && result.data) {
  31. setLayouts(result.data);
  32. }
  33. } catch {
  34. toast({
  35. title: 'Error',
  36. description: 'Failed to load layout configurations',
  37. variant: 'destructive',
  38. });
  39. } finally {
  40. setLoadingLayouts(false);
  41. }
  42. }
  43. if (open) {
  44. loadLayouts();
  45. }
  46. }, [open, toast]);
  47. async function handleSubmit(e: React.FormEvent) {
  48. e.preventDefault();
  49. if (!name.trim()) {
  50. toast({
  51. title: 'Error',
  52. description: 'Please enter an import name',
  53. variant: 'destructive',
  54. });
  55. return;
  56. }
  57. if (!layoutId) {
  58. toast({
  59. title: 'Error',
  60. description: 'Please select a layout configuration',
  61. variant: 'destructive',
  62. });
  63. return;
  64. }
  65. setLoading(true);
  66. try {
  67. const result = await createImport({
  68. name: name.trim(),
  69. layoutId: parseInt(layoutId),
  70. });
  71. if (result.success) {
  72. toast({
  73. title: 'Success',
  74. description: 'Import created successfully',
  75. });
  76. setName('');
  77. setLayoutId('');
  78. onOpenChange(false);
  79. onSuccess?.();
  80. } else {
  81. toast({
  82. title: 'Error',
  83. description: result.error || 'Failed to create import',
  84. variant: 'destructive',
  85. });
  86. }
  87. } catch {
  88. toast({
  89. title: 'Error',
  90. description: 'Failed to create import',
  91. variant: 'destructive',
  92. });
  93. } finally {
  94. setLoading(false);
  95. }
  96. }
  97. return (
  98. <Dialog open={open} onOpenChange={onOpenChange}>
  99. <DialogContent className="sm:max-w-[425px]">
  100. <DialogHeader>
  101. <DialogTitle>Create New Import</DialogTitle>
  102. <DialogDescription>
  103. Create a new import with a layout configuration and file name.
  104. </DialogDescription>
  105. </DialogHeader>
  106. <form onSubmit={handleSubmit}>
  107. <div className="grid gap-4 py-4">
  108. <div className="grid gap-2">
  109. <Label htmlFor="name">Import Name</Label>
  110. <Input
  111. id="name"
  112. value={name}
  113. onChange={(e) => setName(e.target.value)}
  114. placeholder="Enter import name"
  115. disabled={loading}
  116. />
  117. </div>
  118. <div className="grid gap-2">
  119. <Label htmlFor="layout">Layout Configuration</Label>
  120. <Select value={layoutId} onValueChange={setLayoutId} disabled={loadingLayouts || loading}>
  121. <SelectTrigger>
  122. <SelectValue placeholder="Select a layout configuration" />
  123. </SelectTrigger>
  124. <SelectContent>
  125. {layouts.map((layout) => (
  126. <SelectItem key={layout.id} value={layout.id.toString()}>
  127. {layout.name}
  128. </SelectItem>
  129. ))}
  130. </SelectContent>
  131. </Select>
  132. </div>
  133. </div>
  134. <DialogFooter>
  135. <Button type="button" variant="outline" onClick={() => onOpenChange(false)} disabled={loading}>
  136. Cancel
  137. </Button>
  138. <Button type="submit" disabled={loading || !name || !layoutId}>
  139. {loading ? 'Creating...' : 'Create Import'}
  140. </Button>
  141. </DialogFooter>
  142. </form>
  143. </DialogContent>
  144. </Dialog>
  145. );
  146. }