wip: domains

This commit is contained in:
Derock 2024-02-03 21:56:49 -05:00
parent b11c79639a
commit fbbf1772a1
No known key found for this signature in database
4 changed files with 114 additions and 69 deletions

View file

@ -1,30 +1,16 @@
"use client";
import { ArrowRight, PlusIcon } from "lucide-react";
import { PlusIcon } from "lucide-react";
import { useFieldArray } from "react-hook-form";
import { z } from "zod";
import { Button } from "~/components/ui/button";
import {
Form,
FormControl,
FormField,
FormItem,
FormLabel,
FormMessage,
} from "~/components/ui/form";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "~/components/ui/select";
import { Form } from "~/components/ui/form";
import {
FormSubmit,
FormUnsavedChangesIndicator,
SimpleFormField,
useForm,
} from "~/hooks/forms";
import DomainEntry from "./_components/DomainEntry";
const formValidator = z.object({
domains: z.array(
@ -71,55 +57,13 @@ export default function DomainsList(
<h1 className="col-span-2">Domains</h1>
{domainsForm.fields.map((field, index) => (
<div className="flex flex-row gap-4" key={field.id}>
<FormField
control={form.control}
name={`domains.${index}.https`}
render={({ field }) => (
<FormItem>
<FormLabel>Protocol</FormLabel>
<Select
onValueChange={(value) => field.onChange(value === "https")}
defaultValue={field.value ? "https" : "http"}
>
<FormControl>
<SelectTrigger>
<SelectValue />
</SelectTrigger>
</FormControl>
<SelectContent>
<SelectItem value="http">http://</SelectItem>
<SelectItem value="https">https://</SelectItem>
</SelectContent>
</Select>
<FormMessage />
</FormItem>
)}
/>
{/* toggle */}
<SimpleFormField
control={form.control}
name={`domains.${index}.forceSSL`}
friendlyName="Use HTTPS"
render={({ field }) => <Switch {...field} className="block" />}
/>
<SimpleFormField
control={form.control}
name={`domains.${index}.domain`}
friendlyName="Domain"
className="flex-1"
/>
<ArrowRight className="mt-9 flex-shrink-0" />
<SimpleFormField
control={form.control}
name={`domains.${index}.internalPort`}
friendlyName="Internal Port"
className="w-60"
/>
</div>
<DomainEntry
form={form}
domains={domainsForm}
field={field}
index={index}
key={field.id}
/>
))}
<div className="flex flex-row flex-wrap items-center gap-4">
@ -132,7 +76,14 @@ export default function DomainsList(
<Button
variant="secondary"
icon={PlusIcon}
onClick={() => domainsForm.append()}
onClick={() =>
domainsForm.append({
domain: "",
forceSSL: false,
https: false,
internalPort: 8080,
})
}
>
Add Domain
</Button>

View file

@ -0,0 +1,86 @@
"use client";
import { ArrowRight, CogIcon, TrashIcon } from "lucide-react";
import { useState } from "react";
import { type UseFieldArrayReturn, type UseFormReturn } from "react-hook-form";
import { Button } from "~/components/ui/button";
import { Card } from "~/components/ui/card";
import { Switch } from "~/components/ui/switch";
import { SimpleFormField } from "~/hooks/forms";
type FieldData = {
domain: string;
internalPort: number;
https: boolean;
forceSSL: boolean;
};
export default function DomainEntry({
form,
domains,
field,
index,
}: {
form: UseFormReturn<
{
domains: FieldData[];
},
// eslint-disable-next-line @typescript-eslint/no-explicit-any
any,
undefined
>;
domains: UseFieldArrayReturn<
{
domains: FieldData[];
},
"domains",
"id"
>;
field: FieldData;
index: number;
}) {
const isOpen = useState(false);
return (
<Card className="flex flex-row gap-4 p-4">
<SimpleFormField
control={form.control}
name={`domains.${index}.forceSSL`}
friendlyName="HTTPS"
render={({ field }) => (
<div className="pt-2">
<Switch {...field} className="mx-auto block" />
</div>
)}
/>
<SimpleFormField
control={form.control}
name={`domains.${index}.domain`}
friendlyName="Domain"
className="flex-1"
/>
<ArrowRight className="mt-9 flex-shrink-0" />
<SimpleFormField
control={form.control}
name={`domains.${index}.internalPort`}
friendlyName="Internal Port"
className="w-60"
/>
<div className="flex flex-row gap-2 pt-8">
<Button variant="secondary" icon={CogIcon} className="mr-2" />
<Button
variant="destructive"
icon={TrashIcon}
onClick={() => domains.remove(index)}
/>
</div>
</Card>
);
}

View file

@ -0,0 +1,7 @@
"use client";
export function SourcePage() {
return (
)
}

View file

@ -60,6 +60,7 @@ const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
) => {
const Comp = asChild ? Slot : "button";
const Child = asChild ? "span" : React.Fragment;
const iconPadding = children ? " mr-2" : "";
return (
<Comp
@ -73,8 +74,8 @@ const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
disabled={isLoading || props.disabled}
>
<Child>
{isLoading && <CgSpinner className="mr-2 animate-spin" />}
{Icon && !isLoading && <Icon className="mr-2" size={18} />}
{isLoading && <CgSpinner className={"animate-spin" + iconPadding} />}
{Icon && !isLoading && <Icon className={iconPadding} size={18} />}
{children}
</Child>