File size: 2,572 Bytes
0b9dc2e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
import { CircleAlert, Loader2, PlusCircle } from 'lucide-react';
import { useState, type ReactNode } from 'react';

import { Button } from '@/components/ui/button';
import {
	Dialog,
	DialogContent,
	DialogDescription,
	DialogFooter,
	DialogHeader,
	DialogTitle,
	DialogTrigger,
} from '@/components/ui/dialog';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { useTranslation } from '@/i18n/useI18n';

interface AddSkillDialogProps {
	children: ReactNode;
	onAdd: (skillPath: string) => Promise<void>;
}

export function AddSkillDialog({ children, onAdd }: AddSkillDialogProps) {
	const { t } = useTranslation();
	const [open, setOpen] = useState(false);
	const [skillPath, setSkillPath] = useState('');
	const [loading, setLoading] = useState(false);
	const [error, setError] = useState<string | null>(null);

	const handleSubmit = async () => {
		if (!skillPath.trim()) return;
		setLoading(true);
		setError(null);
		try {
			await onAdd(skillPath.trim());
			setSkillPath('');
			setOpen(false);
		} catch (e) {
			setError((e as Error).message);
		} finally {
			setLoading(false);
		}
	};

	return (
		<Dialog open={open} onOpenChange={setOpen}>

			<DialogTrigger asChild>{children}</DialogTrigger>

			<DialogContent className="!w-[500px] !max-w-[500px]">

				<DialogHeader>

					<DialogTitle>{t('dialog-skill-add.title')}</DialogTitle>

					<DialogDescription>{t('dialog-skill-add.description')}</DialogDescription>

				</DialogHeader>

				<div className="flex flex-col gap-y-2">

					<Label htmlFor="skill-path">{t('dialog-skill-add.pathLabel')}</Label>

					<Input

						id="skill-path"

						placeholder={t('dialog-skill-add.pathPlaceholder')}

						value={skillPath}

						onChange={(e) => setSkillPath(e.target.value)}

						onKeyDown={(e) => {

							if (e.key === 'Enter') handleSubmit();

						}}

					/>

					{error && <p className="text-destructive text-sm">{error}</p>}

				</div>

				<DialogFooter>

					<Button variant="ghost" onClick={() => setOpen(false)} disabled={loading}>

						<CircleAlert className="size-3.5" />

						{t('common.cancel')}

					</Button>

					<Button onClick={handleSubmit} disabled={loading || !skillPath.trim()}>

						{loading ? (

							<Loader2 className="size-3.5 animate-spin" />

						) : (

							<PlusCircle className="size-3.5" />

						)}

						{loading ? t('dialog-mcp-create.adding') : t('common.add')}

					</Button>

				</DialogFooter>

			</DialogContent>

		</Dialog>
	);
}