mirror of
https://github.com/fccview/cronmaster.git
synced 2025-12-23 22:18:20 -05:00
154 lines
5.1 KiB
TypeScript
154 lines
5.1 KiB
TypeScript
"use client";
|
|
|
|
import { Modal } from "@/app/_components/GlobalComponents/UIElements/Modal";
|
|
import { Button } from "@/app/_components/GlobalComponents/UIElements/Button";
|
|
import { Input } from "@/app/_components/GlobalComponents/FormElements/Input";
|
|
import { BashEditor } from "@/app/_components/FeatureComponents/Scripts/BashEditor";
|
|
import { BashSnippetHelper } from "@/app/_components/FeatureComponents/Scripts/BashSnippetHelper";
|
|
import { showToast } from "@/app/_components/GlobalComponents/UIElements/Toast";
|
|
import { FileText, Code } from "lucide-react";
|
|
|
|
interface ScriptModalProps {
|
|
isOpen: boolean;
|
|
onClose: () => void;
|
|
onSubmit: (
|
|
formData: FormData
|
|
) => Promise<{ success: boolean; message: string }>;
|
|
title: string;
|
|
submitButtonText: string;
|
|
submitButtonIcon: React.ReactNode;
|
|
form: {
|
|
name: string;
|
|
description: string;
|
|
content: string;
|
|
};
|
|
onFormChange: (updates: Partial<ScriptModalProps["form"]>) => void;
|
|
additionalFormData?: Record<string, string>;
|
|
}
|
|
|
|
export const ScriptModal = ({
|
|
isOpen,
|
|
onClose,
|
|
onSubmit,
|
|
title,
|
|
submitButtonText,
|
|
submitButtonIcon,
|
|
form,
|
|
onFormChange,
|
|
additionalFormData = {},
|
|
}: ScriptModalProps) => {
|
|
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
|
|
e.preventDefault();
|
|
|
|
if (!form.name.trim()) {
|
|
showToast("error", "Validation Error", "Script name is required");
|
|
return;
|
|
}
|
|
|
|
if (!form.content.trim()) {
|
|
showToast("error", "Validation Error", "Script content is required");
|
|
return;
|
|
}
|
|
|
|
const formData = new FormData();
|
|
formData.append("name", form.name.trim());
|
|
formData.append("description", form.description.trim());
|
|
formData.append("content", form.content.trim());
|
|
|
|
Object.entries(additionalFormData).forEach(([key, value]) => {
|
|
formData.append(key, value);
|
|
});
|
|
|
|
const result = await onSubmit(formData);
|
|
if (result.success) {
|
|
onClose();
|
|
} else {
|
|
showToast("error", `Failed to ${title.toLowerCase()}`, result.message);
|
|
}
|
|
};
|
|
|
|
const handleInsertSnippet = (snippet: string) => {
|
|
onFormChange({ content: snippet });
|
|
};
|
|
|
|
return (
|
|
<Modal isOpen={isOpen} onClose={onClose} title={title} size="xl">
|
|
<form onSubmit={handleSubmit} className="space-y-6">
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
<div>
|
|
<label className="block text-sm font-medium text-foreground mb-2">
|
|
Script Name <span className="text-red-500">*</span>
|
|
</label>
|
|
<Input
|
|
value={form.name}
|
|
onChange={(e) => onFormChange({ name: e.target.value })}
|
|
placeholder="My Script"
|
|
required
|
|
className={
|
|
!form.name.trim()
|
|
? "border-red-300 focus:border-red-500 focus:ring-red-500"
|
|
: ""
|
|
}
|
|
/>
|
|
</div>
|
|
<div>
|
|
<label className="block text-sm font-medium text-foreground mb-2">
|
|
Description{" "}
|
|
<span className="text-muted-foreground text-xs">(optional)</span>
|
|
</label>
|
|
<Input
|
|
value={form.description}
|
|
onChange={(e) => onFormChange({ description: e.target.value })}
|
|
placeholder="What does this script do?"
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6 h-[500px]">
|
|
<div className="lg:col-span-1 bg-muted/20 rounded-lg p-4 flex flex-col h-full overflow-hidden">
|
|
<div className="flex items-center gap-2 mb-4 flex-shrink-0">
|
|
<Code className="h-4 w-4 text-primary" />
|
|
<h3 className="text-sm font-medium text-foreground">Snippets</h3>
|
|
</div>
|
|
<div className="flex-1 overflow-y-auto min-h-0 !pr-0">
|
|
<BashSnippetHelper onInsertSnippet={handleInsertSnippet} />
|
|
</div>
|
|
</div>
|
|
|
|
<div className="lg:col-span-2 flex flex-col h-full overflow-hidden">
|
|
<div className="flex items-center gap-2 mb-4 flex-shrink-0">
|
|
<FileText className="h-4 w-4 text-primary" />
|
|
<h3 className="text-sm font-medium text-foreground">
|
|
Script Content <span className="text-red-500">*</span>
|
|
</h3>
|
|
</div>
|
|
<div className="flex-1 min-h-0">
|
|
<BashEditor
|
|
value={form.content}
|
|
onChange={(value) => onFormChange({ content: value })}
|
|
placeholder="#!/bin/bash # Your script here echo 'Hello World'"
|
|
className="h-full"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="flex justify-end gap-3 pt-4 border-t border-border/30">
|
|
<Button
|
|
type="button"
|
|
variant="outline"
|
|
onClick={onClose}
|
|
className="btn-outline"
|
|
>
|
|
Cancel
|
|
</Button>
|
|
<Button type="submit" className="btn-primary glow-primary">
|
|
{submitButtonIcon}
|
|
{submitButtonText}
|
|
</Button>
|
|
</div>
|
|
</form>
|
|
</Modal>
|
|
);
|
|
};
|