diff --git a/frontend/src/components/RelayDetailCard.tsx b/frontend/src/components/RelayDetailCard.tsx index fb577e3..8a23053 100644 --- a/frontend/src/components/RelayDetailCard.tsx +++ b/frontend/src/components/RelayDetailCard.tsx @@ -2,54 +2,11 @@ import { A } from "@solidjs/router" import { Show, createEffect, createSignal, onCleanup } from "solid-js" import type { Relay, PlanId } from "@/lib/api" import menuDotsIcon from "@/assets/menu-dots-2.svg" +import Field from "@/components/Field" import PricingTable from "@/components/PricingTable" - -function Field(props: { label: string; children: any }) { - return ( -
-
{props.label}
-
{props.children}
-
- ) -} - -function ToggleField(props: { label: string; children: any }) { - return ( -
-
{props.label}
-
{props.children}
-
- ) -} - -function ToggleButton(props: { - enabled: boolean - disabled?: boolean - onToggle?: () => void - onLabel?: string - offLabel?: string -}) { - const label = () => (props.enabled ? (props.onLabel ?? "Enabled") : (props.offLabel ?? "Disabled")) - - return ( -
- - {label()} -
- ) -} +import ToggleButton from "@/components/ToggleButton" +import ToggleField from "@/components/ToggleField" +import { setToastMessage } from "@/components/Toast" function DetailSection(props: { title: string; children: any }) { return ( @@ -116,7 +73,12 @@ export default function RelayDetailCard(props: RelayDetailCardProps) { async function changePlan(plan: PlanId) { setPlan(plan) - props.onUpdatePlan?.(plan) + try { + await props.onUpdatePlan?.(plan) + setToastMessage(`Plan updated to ${plan}`, "success") + } catch { + // error is handled by the caller + } } createEffect(() => { diff --git a/frontend/src/components/RelayListItem.tsx b/frontend/src/components/RelayListItem.tsx new file mode 100644 index 0000000..cef2ebe --- /dev/null +++ b/frontend/src/components/RelayListItem.tsx @@ -0,0 +1,27 @@ +import { A } from "@solidjs/router" +import type { Relay } from "@/lib/api" + +type RelayListItemProps = { + relay: Relay + href: string + showTenant?: boolean +} + +export default function RelayListItem(props: RelayListItemProps) { + return ( +
  • + +
    +
    +

    {props.relay.info_name || props.relay.subdomain}

    +

    {props.relay.subdomain}.spaces.coracle.social

    + {props.showTenant && ( +

    Tenant: {props.relay.tenant}

    + )} +
    +

    {props.relay.status}

    +
    +
    +
  • + ) +} diff --git a/frontend/src/components/SearchInput.tsx b/frontend/src/components/SearchInput.tsx new file mode 100644 index 0000000..82b3ea9 --- /dev/null +++ b/frontend/src/components/SearchInput.tsx @@ -0,0 +1,25 @@ +type SearchInputProps = { + value: string + onInput: (value: string) => void + placeholder?: string +} + +export default function SearchInput(props: SearchInputProps) { + return ( +
    + + + + props.onInput(e.currentTarget.value)} + placeholder={props.placeholder ?? "Search..."} + class="w-full border border-gray-300 rounded-lg py-2 pl-10 pr-3 focus:outline-none focus:ring-2 focus:ring-blue-500" + /> +
    + ) +} diff --git a/frontend/src/components/Toast.tsx b/frontend/src/components/Toast.tsx index 139d507..9155d0a 100644 --- a/frontend/src/components/Toast.tsx +++ b/frontend/src/components/Toast.tsx @@ -1,6 +1,14 @@ import { Show, createEffect, createSignal, onCleanup } from "solid-js" -export const [toastMessage, setToastMessage] = createSignal("") +type ToastVariant = "error" | "success" + +const [toastVariant, setToastVariant] = createSignal("error") +export const [toastMessage, setRawToastMessage] = createSignal("") + +export function setToastMessage(message: string, variant: ToastVariant = "error") { + setToastVariant(variant) + setRawToastMessage(message) +} export default function Toast() { const [visible, setVisible] = createSignal(false) @@ -57,10 +65,12 @@ export default function Toast() {