diff --git a/frontend/src/components/RelayForm.tsx b/frontend/src/components/RelayForm.tsx
new file mode 100644
index 0000000..474927c
--- /dev/null
+++ b/frontend/src/components/RelayForm.tsx
@@ -0,0 +1,86 @@
+type RelayFormProps = {
+ name: string
+ setName: (value: string) => void
+ subdomain: string
+ setSubdomain: (value: string) => void
+ icon: string
+ setIcon: (value: string) => void
+ description: string
+ setDescription: (value: string) => void
+ plan: string
+ setPlan: (value: string) => void
+ plans: readonly string[]
+ onSubmit: (e: Event) => void
+ submitting: boolean
+ error?: string
+ submitLabel: string
+ submittingLabel: string
+}
+
+export default function RelayForm(props: RelayFormProps) {
+ return (
+
+ )
+}
diff --git a/frontend/src/lib/relayPlans.ts b/frontend/src/lib/relayPlans.ts
new file mode 100644
index 0000000..a175e89
--- /dev/null
+++ b/frontend/src/lib/relayPlans.ts
@@ -0,0 +1,3 @@
+export const RELAY_PLAN_IDS = ["free", "basic", "growth"] as const
+
+export type RelayPlanId = (typeof RELAY_PLAN_IDS)[number]
diff --git a/frontend/src/lib/slugify.ts b/frontend/src/lib/slugify.ts
new file mode 100644
index 0000000..71680b2
--- /dev/null
+++ b/frontend/src/lib/slugify.ts
@@ -0,0 +1,9 @@
+export function slugify(value: string) {
+ return value
+ .toLowerCase()
+ .trim()
+ .normalize("NFD")
+ .replace(/[\u0300-\u036f]/g, "")
+ .replace(/[^a-z0-9]+/g, "-")
+ .replace(/^-+|-+$/g, "")
+}
diff --git a/frontend/src/pages/admin/AdminRelayEdit.tsx b/frontend/src/pages/admin/AdminRelayEdit.tsx
index 4bdc03a..c305613 100644
--- a/frontend/src/pages/admin/AdminRelayEdit.tsx
+++ b/frontend/src/pages/admin/AdminRelayEdit.tsx
@@ -1,19 +1,9 @@
import { A, useNavigate, useParams } from "@solidjs/router"
import { Show, createEffect, createResource, createSignal } from "solid-js"
import { adminGetRelay, adminUpdateRelay } from "../../lib/api"
-
-const PLANS = ["free", "basic", "growth"] as const
-type PlanId = (typeof PLANS)[number]
-
-function slugify(s: string) {
- return s
- .toLowerCase()
- .trim()
- .normalize("NFD")
- .replace(/[\u0300-\u036f]/g, "")
- .replace(/[^a-z0-9]+/g, "-")
- .replace(/^-+|-+$/g, "")
-}
+import RelayForm from "../../components/RelayForm"
+import { RELAY_PLAN_IDS, type RelayPlanId } from "../../lib/relayPlans"
+import { slugify } from "../../lib/slugify"
export default function AdminRelayEdit() {
const navigate = useNavigate()
@@ -25,7 +15,7 @@ export default function AdminRelayEdit() {
const [subdomain, setSubdomain] = createSignal("")
const [icon, setIcon] = createSignal("")
const [description, setDescription] = createSignal("")
- const [plan, setPlan] = createSignal("free")
+ const [plan, setPlan] = createSignal("free")
const [error, setError] = createSignal("")
const [submitting, setSubmitting] = createSignal(false)
@@ -36,7 +26,7 @@ export default function AdminRelayEdit() {
setSubdomain(data.subdomain)
setIcon(data.icon)
setDescription(data.description)
- setPlan(PLANS.includes(data.plan as PlanId) ? (data.plan as PlanId) : "free")
+ setPlan(RELAY_PLAN_IDS.includes(data.plan as RelayPlanId) ? (data.plan as RelayPlanId) : "free")
})
async function handleSubmit(e: Event) {
@@ -74,71 +64,24 @@ export default function AdminRelayEdit() {
-
+
)
diff --git a/frontend/src/pages/relays/RelayEdit.tsx b/frontend/src/pages/relays/RelayEdit.tsx
index 269d12a..98071f7 100644
--- a/frontend/src/pages/relays/RelayEdit.tsx
+++ b/frontend/src/pages/relays/RelayEdit.tsx
@@ -1,19 +1,9 @@
import { A, useNavigate, useParams } from "@solidjs/router"
import { Show, createEffect, createResource, createSignal } from "solid-js"
import { getTenantRelay, updateTenantRelay } from "../../lib/api"
-
-const PLANS = ["free", "basic", "growth"] as const
-type PlanId = (typeof PLANS)[number]
-
-function slugify(s: string) {
- return s
- .toLowerCase()
- .trim()
- .normalize("NFD")
- .replace(/[\u0300-\u036f]/g, "")
- .replace(/[^a-z0-9]+/g, "-")
- .replace(/^-+|-+$/g, "")
-}
+import RelayForm from "../../components/RelayForm"
+import { RELAY_PLAN_IDS, type RelayPlanId } from "../../lib/relayPlans"
+import { slugify } from "../../lib/slugify"
export default function RelayEdit() {
const navigate = useNavigate()
@@ -25,7 +15,7 @@ export default function RelayEdit() {
const [subdomain, setSubdomain] = createSignal("")
const [icon, setIcon] = createSignal("")
const [description, setDescription] = createSignal("")
- const [plan, setPlan] = createSignal("free")
+ const [plan, setPlan] = createSignal("free")
const [error, setError] = createSignal("")
const [submitting, setSubmitting] = createSignal(false)
@@ -36,7 +26,7 @@ export default function RelayEdit() {
setSubdomain(data.subdomain)
setIcon(data.icon)
setDescription(data.description)
- setPlan(PLANS.includes(data.plan as PlanId) ? (data.plan as PlanId) : "free")
+ setPlan(RELAY_PLAN_IDS.includes(data.plan as RelayPlanId) ? (data.plan as RelayPlanId) : "free")
})
async function handleSubmit(e: Event) {
@@ -74,71 +64,24 @@ export default function RelayEdit() {
-
+
)
diff --git a/frontend/src/pages/relays/RelayNew.tsx b/frontend/src/pages/relays/RelayNew.tsx
index f923225..7c4f901 100644
--- a/frontend/src/pages/relays/RelayNew.tsx
+++ b/frontend/src/pages/relays/RelayNew.tsx
@@ -1,6 +1,7 @@
import { Show, createSignal } from "solid-js"
import { useNavigate } from "@solidjs/router"
import { createTenantRelay } from "../../lib/api"
+import { slugify } from "../../lib/slugify"
const PLANS = [
{ id: "free", label: "Free", price: 0, members: "Up to 10", blossom: false, livekit: false },
@@ -10,16 +11,6 @@ const PLANS = [
type PlanId = (typeof PLANS)[number]["id"]
-function slugify(s: string) {
- return s
- .toLowerCase()
- .trim()
- .normalize("NFD")
- .replace(/[\u0300-\u036f]/g, "")
- .replace(/[^a-z0-9]+/g, "-")
- .replace(/^-+|-+$/g, "")
-}
-
export default function RelayNew() {
const navigate = useNavigate()
const [name, setName] = createSignal("")