Enviroment

This commit is contained in:
2026-01-01 07:10:27 +01:00
parent a574aeb48f
commit f9f808f327
9 changed files with 386 additions and 30 deletions
+106
View File
@@ -0,0 +1,106 @@
"use client";
import * as React from "react";
import { Button } from "@/components/ui/button";
import {
Dialog,
DialogContent,
DialogHeader,
DialogTitle,
DialogDescription,
DialogFooter,
DialogTrigger,
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Checkbox } from "@/components/ui/checkbox";
import { Plus } from "lucide-react";
import { Env, EnvVariable } from "@/lib/types";
interface Props {
selectedApp: string;
currentGroup: Env;
setEnvGroups: React.Dispatch<React.SetStateAction<Record<string, Env>>>;
}
export function AddVariableDialog({
selectedApp,
currentGroup,
setEnvGroups,
}: Props) {
const [open, setOpen] = React.useState(false);
const [key, setKey] = React.useState("");
const [value, setValue] = React.useState("");
const [secret, setSecret] = React.useState(false);
const handleAdd = () => {
if (!key) return;
const newVariable: EnvVariable = { key, value, secret };
setEnvGroups((env) => ({
...env,
[selectedApp]: {
...currentGroup,
variables: [...currentGroup.variables, newVariable],
},
}));
setKey("");
setValue("");
setSecret(false);
setOpen(false);
};
return (
<Dialog open={open} onOpenChange={setOpen}>
<DialogTrigger asChild>
<Button variant="outline" size="sm" className="gap-2">
<Plus className="w-4 h-4" />
<span className="hidden sm:inline">Add Variable</span>
</Button>
</DialogTrigger>
<DialogContent className="sm:max-w-md">
<DialogHeader>
<DialogTitle>Add Environment Variable</DialogTitle>
<DialogDescription>
Enter the variable name, value, and whether it should be secret.
</DialogDescription>
</DialogHeader>
<div className="grid gap-4 py-4">
<div className="grid gap-1">
<label className="text-sm font-medium">Variable Name</label>
<Input
placeholder="PORT"
value={key}
onChange={(e) => setKey(e.target.value)}
/>
</div>
<div className="grid gap-1">
<label className="text-sm font-medium">Value</label>
<Input
placeholder="3000"
value={value}
onChange={(e) => setValue(e.target.value)}
/>
</div>
<div className="flex items-center space-x-2">
<Checkbox
id="secret"
checked={secret}
onCheckedChange={(checked) => setSecret(!!checked)}
/>
<label htmlFor="secret" className="text-sm font-medium">
Secret
</label>
</div>
</div>
<DialogFooter>
<Button onClick={handleAdd}>Add Variable</Button>
</DialogFooter>
</DialogContent>
</Dialog>
);
}
+32
View File
@@ -0,0 +1,32 @@
"use client"
import * as React from "react"
import * as CheckboxPrimitive from "@radix-ui/react-checkbox"
import { CheckIcon } from "lucide-react"
import { cn } from "@/lib/utils"
function Checkbox({
className,
...props
}: React.ComponentProps<typeof CheckboxPrimitive.Root>) {
return (
<CheckboxPrimitive.Root
data-slot="checkbox"
className={cn(
"peer border-input dark:bg-input/30 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground dark:data-[state=checked]:bg-primary data-[state=checked]:border-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive size-4 shrink-0 rounded-[4px] border shadow-xs transition-shadow outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50",
className
)}
{...props}
>
<CheckboxPrimitive.Indicator
data-slot="checkbox-indicator"
className="grid place-content-center text-current transition-none"
>
<CheckIcon className="size-3.5" />
</CheckboxPrimitive.Indicator>
</CheckboxPrimitive.Root>
)
}
export { Checkbox }