This commit is contained in:
2026-09-13 06:53:33 +01:00
parent 75670e4d5c
commit e7e63bc491
45 changed files with 2117 additions and 22 deletions
@@ -0,0 +1,108 @@
import type { Dispatch, ReactNode, SetStateAction } from "react";
import { X } from "lucide-react";
import Modal from "@/src/components/twui/elements/Modal";
import Input from "@/src/components/twui/form/Input";
import AdminButton from "@/src/components/general/admin-button";
type Props = {
open: boolean;
setOpen: Dispatch<SetStateAction<boolean>>;
};
type FormFieldProps = {
label: string;
htmlFor: string;
children: ReactNode;
};
function FormField({ label, htmlFor, children }: FormFieldProps) {
return (
<div className="flex flex-col gap-1.5">
<label
htmlFor={htmlFor}
className="text-[11.5px] font-semibold uppercase tracking-[0.08em] text-foreground-light/50 dark:text-foreground-dark/50"
>
{label}
</label>
{children}
</div>
);
}
export default function ClientFormModal({ open, setOpen }: Props) {
return (
<Modal
open={open}
setOpen={setOpen}
no_cancel_button
className="p-6"
>
<div className="flex items-start justify-between gap-4 mb-6">
<div>
<h3 className="text-lg font-bold text-foreground-light dark:text-foreground-dark">
Add client
</h3>
<p className="text-xs text-foreground-light/50 dark:text-foreground-dark/50 mt-1">
A WireGuard config will be generated on save
</p>
</div>
<button
type="button"
aria-label="Close"
onClick={() => setOpen(false)}
className="p-1 cursor-pointer text-foreground-light/60 dark:text-foreground-dark/60 hover:text-foreground-light dark:hover:text-foreground-dark transition-colors"
>
<X size={18} />
</button>
</div>
<form
className="flex flex-col gap-4"
onSubmit={(e) => {
e.preventDefault();
setOpen(false);
}}
>
<FormField label="Client name" htmlFor="client_name">
<Input
name="client_name"
id="client_name"
placeholder="e.g. MacBook Pro"
required
/>
</FormField>
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
<FormField label="Tunnel IP" htmlFor="tunnel_ip">
<Input
name="tunnel_ip"
id="tunnel_ip"
placeholder="10.0.0.10 · auto-assigned"
/>
</FormField>
<FormField label="Allowed IPs" htmlFor="allowed_ips">
<Input
name="allowed_ips"
id="allowed_ips"
placeholder="10.0.0.10/32"
/>
</FormField>
</div>
<FormField label="Notes" htmlFor="client_notes">
<Input
name="client_notes"
id="client_notes"
istextarea
placeholder="Optional description for this client"
/>
</FormField>
<div className="flex justify-end gap-2 mt-2">
<AdminButton onClick={() => setOpen(false)}>
Cancel
</AdminButton>
<AdminButton variant="primary" type="submit">
Add client
</AdminButton>
</div>
</form>
</Modal>
);
}