ui: unnest dashboard detail routes and stabilize form hooks

This commit is contained in:
Syahdan 2026-04-29 19:20:27 +07:00
parent 41fff32f60
commit 8e9acd5006
5 changed files with 219 additions and 157 deletions

View file

@ -17,14 +17,14 @@ import { Route as DashboardServicesRouteImport } from './routes/dashboard.servic
import { Route as DashboardServersRouteImport } from './routes/dashboard.servers' import { Route as DashboardServersRouteImport } from './routes/dashboard.servers'
import { Route as DashboardNotesRouteImport } from './routes/dashboard.notes' import { Route as DashboardNotesRouteImport } from './routes/dashboard.notes'
import { Route as DashboardDomainsRouteImport } from './routes/dashboard.domains' import { Route as DashboardDomainsRouteImport } from './routes/dashboard.domains'
import { Route as DashboardServicesServiceIdRouteImport } from './routes/dashboard.services_.$serviceId'
import { Route as DashboardServicesNewRouteImport } from './routes/dashboard.services.new' import { Route as DashboardServicesNewRouteImport } from './routes/dashboard.services.new'
import { Route as DashboardServicesServiceIdRouteImport } from './routes/dashboard.services.$serviceId' import { Route as DashboardServersServerIdRouteImport } from './routes/dashboard.servers_.$serverId'
import { Route as DashboardServersNewRouteImport } from './routes/dashboard.servers.new' import { Route as DashboardServersNewRouteImport } from './routes/dashboard.servers.new'
import { Route as DashboardServersServerIdRouteImport } from './routes/dashboard.servers.$serverId' import { Route as DashboardNotesNoteIdRouteImport } from './routes/dashboard.notes_.$noteId'
import { Route as DashboardNotesNewRouteImport } from './routes/dashboard.notes.new' import { Route as DashboardNotesNewRouteImport } from './routes/dashboard.notes.new'
import { Route as DashboardNotesNoteIdRouteImport } from './routes/dashboard.notes.$noteId' import { Route as DashboardDomainsDomainIdRouteImport } from './routes/dashboard.domains_.$domainId'
import { Route as DashboardDomainsNewRouteImport } from './routes/dashboard.domains.new' import { Route as DashboardDomainsNewRouteImport } from './routes/dashboard.domains.new'
import { Route as DashboardDomainsDomainIdRouteImport } from './routes/dashboard.domains.$domainId'
const LoginRoute = LoginRouteImport.update({ const LoginRoute = LoginRouteImport.update({
id: '/login', id: '/login',
@ -66,49 +66,49 @@ const DashboardDomainsRoute = DashboardDomainsRouteImport.update({
path: '/domains', path: '/domains',
getParentRoute: () => DashboardRoute, getParentRoute: () => DashboardRoute,
} as any) } as any)
const DashboardServicesServiceIdRoute =
DashboardServicesServiceIdRouteImport.update({
id: '/services_/$serviceId',
path: '/services/$serviceId',
getParentRoute: () => DashboardRoute,
} as any)
const DashboardServicesNewRoute = DashboardServicesNewRouteImport.update({ const DashboardServicesNewRoute = DashboardServicesNewRouteImport.update({
id: '/new', id: '/new',
path: '/new', path: '/new',
getParentRoute: () => DashboardServicesRoute, getParentRoute: () => DashboardServicesRoute,
} as any) } as any)
const DashboardServicesServiceIdRoute = const DashboardServersServerIdRoute =
DashboardServicesServiceIdRouteImport.update({ DashboardServersServerIdRouteImport.update({
id: '/$serviceId', id: '/servers_/$serverId',
path: '/$serviceId', path: '/servers/$serverId',
getParentRoute: () => DashboardServicesRoute, getParentRoute: () => DashboardRoute,
} as any) } as any)
const DashboardServersNewRoute = DashboardServersNewRouteImport.update({ const DashboardServersNewRoute = DashboardServersNewRouteImport.update({
id: '/new', id: '/new',
path: '/new', path: '/new',
getParentRoute: () => DashboardServersRoute, getParentRoute: () => DashboardServersRoute,
} as any) } as any)
const DashboardServersServerIdRoute = const DashboardNotesNoteIdRoute = DashboardNotesNoteIdRouteImport.update({
DashboardServersServerIdRouteImport.update({ id: '/notes_/$noteId',
id: '/$serverId', path: '/notes/$noteId',
path: '/$serverId', getParentRoute: () => DashboardRoute,
getParentRoute: () => DashboardServersRoute, } as any)
} as any)
const DashboardNotesNewRoute = DashboardNotesNewRouteImport.update({ const DashboardNotesNewRoute = DashboardNotesNewRouteImport.update({
id: '/new', id: '/new',
path: '/new', path: '/new',
getParentRoute: () => DashboardNotesRoute, getParentRoute: () => DashboardNotesRoute,
} as any) } as any)
const DashboardNotesNoteIdRoute = DashboardNotesNoteIdRouteImport.update({ const DashboardDomainsDomainIdRoute =
id: '/$noteId', DashboardDomainsDomainIdRouteImport.update({
path: '/$noteId', id: '/domains_/$domainId',
getParentRoute: () => DashboardNotesRoute, path: '/domains/$domainId',
} as any) getParentRoute: () => DashboardRoute,
} as any)
const DashboardDomainsNewRoute = DashboardDomainsNewRouteImport.update({ const DashboardDomainsNewRoute = DashboardDomainsNewRouteImport.update({
id: '/new', id: '/new',
path: '/new', path: '/new',
getParentRoute: () => DashboardDomainsRoute, getParentRoute: () => DashboardDomainsRoute,
} as any) } as any)
const DashboardDomainsDomainIdRoute =
DashboardDomainsDomainIdRouteImport.update({
id: '/$domainId',
path: '/$domainId',
getParentRoute: () => DashboardDomainsRoute,
} as any)
export interface FileRoutesByFullPath { export interface FileRoutesByFullPath {
'/': typeof IndexRoute '/': typeof IndexRoute
@ -119,14 +119,14 @@ export interface FileRoutesByFullPath {
'/dashboard/servers': typeof DashboardServersRouteWithChildren '/dashboard/servers': typeof DashboardServersRouteWithChildren
'/dashboard/services': typeof DashboardServicesRouteWithChildren '/dashboard/services': typeof DashboardServicesRouteWithChildren
'/dashboard/': typeof DashboardIndexRoute '/dashboard/': typeof DashboardIndexRoute
'/dashboard/domains/$domainId': typeof DashboardDomainsDomainIdRoute
'/dashboard/domains/new': typeof DashboardDomainsNewRoute '/dashboard/domains/new': typeof DashboardDomainsNewRoute
'/dashboard/notes/$noteId': typeof DashboardNotesNoteIdRoute '/dashboard/domains/$domainId': typeof DashboardDomainsDomainIdRoute
'/dashboard/notes/new': typeof DashboardNotesNewRoute '/dashboard/notes/new': typeof DashboardNotesNewRoute
'/dashboard/servers/$serverId': typeof DashboardServersServerIdRoute '/dashboard/notes/$noteId': typeof DashboardNotesNoteIdRoute
'/dashboard/servers/new': typeof DashboardServersNewRoute '/dashboard/servers/new': typeof DashboardServersNewRoute
'/dashboard/services/$serviceId': typeof DashboardServicesServiceIdRoute '/dashboard/servers/$serverId': typeof DashboardServersServerIdRoute
'/dashboard/services/new': typeof DashboardServicesNewRoute '/dashboard/services/new': typeof DashboardServicesNewRoute
'/dashboard/services/$serviceId': typeof DashboardServicesServiceIdRoute
} }
export interface FileRoutesByTo { export interface FileRoutesByTo {
'/': typeof IndexRoute '/': typeof IndexRoute
@ -136,14 +136,14 @@ export interface FileRoutesByTo {
'/dashboard/servers': typeof DashboardServersRouteWithChildren '/dashboard/servers': typeof DashboardServersRouteWithChildren
'/dashboard/services': typeof DashboardServicesRouteWithChildren '/dashboard/services': typeof DashboardServicesRouteWithChildren
'/dashboard': typeof DashboardIndexRoute '/dashboard': typeof DashboardIndexRoute
'/dashboard/domains/$domainId': typeof DashboardDomainsDomainIdRoute
'/dashboard/domains/new': typeof DashboardDomainsNewRoute '/dashboard/domains/new': typeof DashboardDomainsNewRoute
'/dashboard/notes/$noteId': typeof DashboardNotesNoteIdRoute '/dashboard/domains/$domainId': typeof DashboardDomainsDomainIdRoute
'/dashboard/notes/new': typeof DashboardNotesNewRoute '/dashboard/notes/new': typeof DashboardNotesNewRoute
'/dashboard/servers/$serverId': typeof DashboardServersServerIdRoute '/dashboard/notes/$noteId': typeof DashboardNotesNoteIdRoute
'/dashboard/servers/new': typeof DashboardServersNewRoute '/dashboard/servers/new': typeof DashboardServersNewRoute
'/dashboard/services/$serviceId': typeof DashboardServicesServiceIdRoute '/dashboard/servers/$serverId': typeof DashboardServersServerIdRoute
'/dashboard/services/new': typeof DashboardServicesNewRoute '/dashboard/services/new': typeof DashboardServicesNewRoute
'/dashboard/services/$serviceId': typeof DashboardServicesServiceIdRoute
} }
export interface FileRoutesById { export interface FileRoutesById {
__root__: typeof rootRouteImport __root__: typeof rootRouteImport
@ -155,14 +155,14 @@ export interface FileRoutesById {
'/dashboard/servers': typeof DashboardServersRouteWithChildren '/dashboard/servers': typeof DashboardServersRouteWithChildren
'/dashboard/services': typeof DashboardServicesRouteWithChildren '/dashboard/services': typeof DashboardServicesRouteWithChildren
'/dashboard/': typeof DashboardIndexRoute '/dashboard/': typeof DashboardIndexRoute
'/dashboard/domains/$domainId': typeof DashboardDomainsDomainIdRoute
'/dashboard/domains/new': typeof DashboardDomainsNewRoute '/dashboard/domains/new': typeof DashboardDomainsNewRoute
'/dashboard/notes/$noteId': typeof DashboardNotesNoteIdRoute '/dashboard/domains_/$domainId': typeof DashboardDomainsDomainIdRoute
'/dashboard/notes/new': typeof DashboardNotesNewRoute '/dashboard/notes/new': typeof DashboardNotesNewRoute
'/dashboard/servers/$serverId': typeof DashboardServersServerIdRoute '/dashboard/notes_/$noteId': typeof DashboardNotesNoteIdRoute
'/dashboard/servers/new': typeof DashboardServersNewRoute '/dashboard/servers/new': typeof DashboardServersNewRoute
'/dashboard/services/$serviceId': typeof DashboardServicesServiceIdRoute '/dashboard/servers_/$serverId': typeof DashboardServersServerIdRoute
'/dashboard/services/new': typeof DashboardServicesNewRoute '/dashboard/services/new': typeof DashboardServicesNewRoute
'/dashboard/services_/$serviceId': typeof DashboardServicesServiceIdRoute
} }
export interface FileRouteTypes { export interface FileRouteTypes {
fileRoutesByFullPath: FileRoutesByFullPath fileRoutesByFullPath: FileRoutesByFullPath
@ -175,14 +175,14 @@ export interface FileRouteTypes {
| '/dashboard/servers' | '/dashboard/servers'
| '/dashboard/services' | '/dashboard/services'
| '/dashboard/' | '/dashboard/'
| '/dashboard/domains/$domainId'
| '/dashboard/domains/new' | '/dashboard/domains/new'
| '/dashboard/notes/$noteId' | '/dashboard/domains/$domainId'
| '/dashboard/notes/new' | '/dashboard/notes/new'
| '/dashboard/servers/$serverId' | '/dashboard/notes/$noteId'
| '/dashboard/servers/new' | '/dashboard/servers/new'
| '/dashboard/services/$serviceId' | '/dashboard/servers/$serverId'
| '/dashboard/services/new' | '/dashboard/services/new'
| '/dashboard/services/$serviceId'
fileRoutesByTo: FileRoutesByTo fileRoutesByTo: FileRoutesByTo
to: to:
| '/' | '/'
@ -192,14 +192,14 @@ export interface FileRouteTypes {
| '/dashboard/servers' | '/dashboard/servers'
| '/dashboard/services' | '/dashboard/services'
| '/dashboard' | '/dashboard'
| '/dashboard/domains/$domainId'
| '/dashboard/domains/new' | '/dashboard/domains/new'
| '/dashboard/notes/$noteId' | '/dashboard/domains/$domainId'
| '/dashboard/notes/new' | '/dashboard/notes/new'
| '/dashboard/servers/$serverId' | '/dashboard/notes/$noteId'
| '/dashboard/servers/new' | '/dashboard/servers/new'
| '/dashboard/services/$serviceId' | '/dashboard/servers/$serverId'
| '/dashboard/services/new' | '/dashboard/services/new'
| '/dashboard/services/$serviceId'
id: id:
| '__root__' | '__root__'
| '/' | '/'
@ -210,14 +210,14 @@ export interface FileRouteTypes {
| '/dashboard/servers' | '/dashboard/servers'
| '/dashboard/services' | '/dashboard/services'
| '/dashboard/' | '/dashboard/'
| '/dashboard/domains/$domainId'
| '/dashboard/domains/new' | '/dashboard/domains/new'
| '/dashboard/notes/$noteId' | '/dashboard/domains_/$domainId'
| '/dashboard/notes/new' | '/dashboard/notes/new'
| '/dashboard/servers/$serverId' | '/dashboard/notes_/$noteId'
| '/dashboard/servers/new' | '/dashboard/servers/new'
| '/dashboard/services/$serviceId' | '/dashboard/servers_/$serverId'
| '/dashboard/services/new' | '/dashboard/services/new'
| '/dashboard/services_/$serviceId'
fileRoutesById: FileRoutesById fileRoutesById: FileRoutesById
} }
export interface RootRouteChildren { export interface RootRouteChildren {
@ -284,6 +284,13 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof DashboardDomainsRouteImport preLoaderRoute: typeof DashboardDomainsRouteImport
parentRoute: typeof DashboardRoute parentRoute: typeof DashboardRoute
} }
'/dashboard/services_/$serviceId': {
id: '/dashboard/services_/$serviceId'
path: '/services/$serviceId'
fullPath: '/dashboard/services/$serviceId'
preLoaderRoute: typeof DashboardServicesServiceIdRouteImport
parentRoute: typeof DashboardRoute
}
'/dashboard/services/new': { '/dashboard/services/new': {
id: '/dashboard/services/new' id: '/dashboard/services/new'
path: '/new' path: '/new'
@ -291,12 +298,12 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof DashboardServicesNewRouteImport preLoaderRoute: typeof DashboardServicesNewRouteImport
parentRoute: typeof DashboardServicesRoute parentRoute: typeof DashboardServicesRoute
} }
'/dashboard/services/$serviceId': { '/dashboard/servers_/$serverId': {
id: '/dashboard/services/$serviceId' id: '/dashboard/servers_/$serverId'
path: '/$serviceId' path: '/servers/$serverId'
fullPath: '/dashboard/services/$serviceId' fullPath: '/dashboard/servers/$serverId'
preLoaderRoute: typeof DashboardServicesServiceIdRouteImport preLoaderRoute: typeof DashboardServersServerIdRouteImport
parentRoute: typeof DashboardServicesRoute parentRoute: typeof DashboardRoute
} }
'/dashboard/servers/new': { '/dashboard/servers/new': {
id: '/dashboard/servers/new' id: '/dashboard/servers/new'
@ -305,12 +312,12 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof DashboardServersNewRouteImport preLoaderRoute: typeof DashboardServersNewRouteImport
parentRoute: typeof DashboardServersRoute parentRoute: typeof DashboardServersRoute
} }
'/dashboard/servers/$serverId': { '/dashboard/notes_/$noteId': {
id: '/dashboard/servers/$serverId' id: '/dashboard/notes_/$noteId'
path: '/$serverId' path: '/notes/$noteId'
fullPath: '/dashboard/servers/$serverId' fullPath: '/dashboard/notes/$noteId'
preLoaderRoute: typeof DashboardServersServerIdRouteImport preLoaderRoute: typeof DashboardNotesNoteIdRouteImport
parentRoute: typeof DashboardServersRoute parentRoute: typeof DashboardRoute
} }
'/dashboard/notes/new': { '/dashboard/notes/new': {
id: '/dashboard/notes/new' id: '/dashboard/notes/new'
@ -319,12 +326,12 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof DashboardNotesNewRouteImport preLoaderRoute: typeof DashboardNotesNewRouteImport
parentRoute: typeof DashboardNotesRoute parentRoute: typeof DashboardNotesRoute
} }
'/dashboard/notes/$noteId': { '/dashboard/domains_/$domainId': {
id: '/dashboard/notes/$noteId' id: '/dashboard/domains_/$domainId'
path: '/$noteId' path: '/domains/$domainId'
fullPath: '/dashboard/notes/$noteId' fullPath: '/dashboard/domains/$domainId'
preLoaderRoute: typeof DashboardNotesNoteIdRouteImport preLoaderRoute: typeof DashboardDomainsDomainIdRouteImport
parentRoute: typeof DashboardNotesRoute parentRoute: typeof DashboardRoute
} }
'/dashboard/domains/new': { '/dashboard/domains/new': {
id: '/dashboard/domains/new' id: '/dashboard/domains/new'
@ -333,23 +340,14 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof DashboardDomainsNewRouteImport preLoaderRoute: typeof DashboardDomainsNewRouteImport
parentRoute: typeof DashboardDomainsRoute parentRoute: typeof DashboardDomainsRoute
} }
'/dashboard/domains/$domainId': {
id: '/dashboard/domains/$domainId'
path: '/$domainId'
fullPath: '/dashboard/domains/$domainId'
preLoaderRoute: typeof DashboardDomainsDomainIdRouteImport
parentRoute: typeof DashboardDomainsRoute
}
} }
} }
interface DashboardDomainsRouteChildren { interface DashboardDomainsRouteChildren {
DashboardDomainsDomainIdRoute: typeof DashboardDomainsDomainIdRoute
DashboardDomainsNewRoute: typeof DashboardDomainsNewRoute DashboardDomainsNewRoute: typeof DashboardDomainsNewRoute
} }
const DashboardDomainsRouteChildren: DashboardDomainsRouteChildren = { const DashboardDomainsRouteChildren: DashboardDomainsRouteChildren = {
DashboardDomainsDomainIdRoute: DashboardDomainsDomainIdRoute,
DashboardDomainsNewRoute: DashboardDomainsNewRoute, DashboardDomainsNewRoute: DashboardDomainsNewRoute,
} }
@ -357,12 +355,10 @@ const DashboardDomainsRouteWithChildren =
DashboardDomainsRoute._addFileChildren(DashboardDomainsRouteChildren) DashboardDomainsRoute._addFileChildren(DashboardDomainsRouteChildren)
interface DashboardNotesRouteChildren { interface DashboardNotesRouteChildren {
DashboardNotesNoteIdRoute: typeof DashboardNotesNoteIdRoute
DashboardNotesNewRoute: typeof DashboardNotesNewRoute DashboardNotesNewRoute: typeof DashboardNotesNewRoute
} }
const DashboardNotesRouteChildren: DashboardNotesRouteChildren = { const DashboardNotesRouteChildren: DashboardNotesRouteChildren = {
DashboardNotesNoteIdRoute: DashboardNotesNoteIdRoute,
DashboardNotesNewRoute: DashboardNotesNewRoute, DashboardNotesNewRoute: DashboardNotesNewRoute,
} }
@ -371,12 +367,10 @@ const DashboardNotesRouteWithChildren = DashboardNotesRoute._addFileChildren(
) )
interface DashboardServersRouteChildren { interface DashboardServersRouteChildren {
DashboardServersServerIdRoute: typeof DashboardServersServerIdRoute
DashboardServersNewRoute: typeof DashboardServersNewRoute DashboardServersNewRoute: typeof DashboardServersNewRoute
} }
const DashboardServersRouteChildren: DashboardServersRouteChildren = { const DashboardServersRouteChildren: DashboardServersRouteChildren = {
DashboardServersServerIdRoute: DashboardServersServerIdRoute,
DashboardServersNewRoute: DashboardServersNewRoute, DashboardServersNewRoute: DashboardServersNewRoute,
} }
@ -384,12 +378,10 @@ const DashboardServersRouteWithChildren =
DashboardServersRoute._addFileChildren(DashboardServersRouteChildren) DashboardServersRoute._addFileChildren(DashboardServersRouteChildren)
interface DashboardServicesRouteChildren { interface DashboardServicesRouteChildren {
DashboardServicesServiceIdRoute: typeof DashboardServicesServiceIdRoute
DashboardServicesNewRoute: typeof DashboardServicesNewRoute DashboardServicesNewRoute: typeof DashboardServicesNewRoute
} }
const DashboardServicesRouteChildren: DashboardServicesRouteChildren = { const DashboardServicesRouteChildren: DashboardServicesRouteChildren = {
DashboardServicesServiceIdRoute: DashboardServicesServiceIdRoute,
DashboardServicesNewRoute: DashboardServicesNewRoute, DashboardServicesNewRoute: DashboardServicesNewRoute,
} }
@ -402,6 +394,10 @@ interface DashboardRouteChildren {
DashboardServersRoute: typeof DashboardServersRouteWithChildren DashboardServersRoute: typeof DashboardServersRouteWithChildren
DashboardServicesRoute: typeof DashboardServicesRouteWithChildren DashboardServicesRoute: typeof DashboardServicesRouteWithChildren
DashboardIndexRoute: typeof DashboardIndexRoute DashboardIndexRoute: typeof DashboardIndexRoute
DashboardDomainsDomainIdRoute: typeof DashboardDomainsDomainIdRoute
DashboardNotesNoteIdRoute: typeof DashboardNotesNoteIdRoute
DashboardServersServerIdRoute: typeof DashboardServersServerIdRoute
DashboardServicesServiceIdRoute: typeof DashboardServicesServiceIdRoute
} }
const DashboardRouteChildren: DashboardRouteChildren = { const DashboardRouteChildren: DashboardRouteChildren = {
@ -410,6 +406,10 @@ const DashboardRouteChildren: DashboardRouteChildren = {
DashboardServersRoute: DashboardServersRouteWithChildren, DashboardServersRoute: DashboardServersRouteWithChildren,
DashboardServicesRoute: DashboardServicesRouteWithChildren, DashboardServicesRoute: DashboardServicesRouteWithChildren,
DashboardIndexRoute: DashboardIndexRoute, DashboardIndexRoute: DashboardIndexRoute,
DashboardDomainsDomainIdRoute: DashboardDomainsDomainIdRoute,
DashboardNotesNoteIdRoute: DashboardNotesNoteIdRoute,
DashboardServersServerIdRoute: DashboardServersServerIdRoute,
DashboardServicesServiceIdRoute: DashboardServicesServiceIdRoute,
} }
const DashboardRouteWithChildren = DashboardRoute._addFileChildren( const DashboardRouteWithChildren = DashboardRoute._addFileChildren(

View file

@ -1,13 +1,14 @@
import { DetailCard, FormCard, PageSection, QueryStateCard, TextAreaField, TextField } from "@/components/dashboard-ui";
import { queryClient, trpc, trpcClient } from "@/utils/trpc";
import { Button } from "@minmon/ui/components/button"; import { Button } from "@minmon/ui/components/button";
import { StatusBadge } from "@minmon/ui/components/status-badge"; import { StatusBadge } from "@minmon/ui/components/status-badge";
import { useForm } from "@tanstack/react-form"; import { useForm } from "@tanstack/react-form";
import { useMutation, useQuery } from "@tanstack/react-query"; import { useMutation, useQuery } from "@tanstack/react-query";
import { createFileRoute, useNavigate } from "@tanstack/react-router"; import { createFileRoute, useNavigate } from "@tanstack/react-router";
import { useEffect } from "react";
import { toast } from "sonner"; import { toast } from "sonner";
import { DetailCard, FormCard, PageSection, QueryStateCard, TextAreaField, TextField } from "@/components/dashboard-ui";
import { queryClient, trpc, trpcClient } from "@/utils/trpc";
export const Route = createFileRoute("/dashboard/domains/$domainId")({ export const Route = createFileRoute("/dashboard/domains_/$domainId")({
component: RouteComponent, component: RouteComponent,
}); });
@ -54,6 +55,31 @@ function RouteComponent() {
onError: (error) => toast.error(error.message), onError: (error) => toast.error(error.message),
}); });
const form = useForm({
defaultValues: {
serviceId: "",
name: "",
expectedServerIp: "",
remarks: "",
} satisfies DomainFormValues,
onSubmit: async ({ value }) => {
await updateDomain.mutateAsync(value);
},
});
useEffect(() => {
if (!domain.data) {
return;
}
form.reset({
serviceId: domain.data.serviceId,
name: domain.data.name,
expectedServerIp: domain.data.expectedServerIp,
remarks: domain.data.remarks ?? "",
});
}, [domain.data, form]);
if (domain.isLoading || services.isLoading) { if (domain.isLoading || services.isLoading) {
return <QueryStateCard title="Loading domain" description="Fetching the selected domain details." />; return <QueryStateCard title="Loading domain" description="Fetching the selected domain details." />;
} }
@ -62,20 +88,6 @@ function RouteComponent() {
return <QueryStateCard title="Domain unavailable" description="The requested domain could not be loaded." />; return <QueryStateCard title="Domain unavailable" description="The requested domain could not be loaded." />;
} }
const defaultValues: DomainFormValues = {
serviceId: domain.data.serviceId,
name: domain.data.name,
expectedServerIp: domain.data.expectedServerIp,
remarks: domain.data.remarks ?? "",
};
const form = useForm({
defaultValues,
onSubmit: async ({ value }) => {
await updateDomain.mutateAsync(value);
},
});
return ( return (
<div className="grid gap-6"> <div className="grid gap-6">
<PageSection title={domain.data.name} description="View DNS check results and edit this domain record."> <PageSection title={domain.data.name} description="View DNS check results and edit this domain record.">
@ -122,16 +134,16 @@ function RouteComponent() {
> >
<form.Field name="serviceId"> <form.Field name="serviceId">
{(field) => ( {(field) => (
<TextField <TextField
label="Service ID" label="Service ID"
name={field.name} name={field.name}
value={field.state.value} value={field.state.value}
onBlur={field.handleBlur} onBlur={field.handleBlur}
onChange={(e) => field.handleChange(e.target.value)} onChange={(e) => field.handleChange(e.target.value)}
description={`Available: ${services.data.map((item) => `${item.name} (${item.id})`).join(", ")}`} description={`Available: ${services.data.map((item) => `${item.name} (${item.id})`).join(", ")}`}
/> />
)} )}
</form.Field> </form.Field>
<div className="grid gap-4 md:grid-cols-2"> <div className="grid gap-4 md:grid-cols-2">
<form.Field name="name">{(field) => <TextField label="Domain name" name={field.name} value={field.state.value} onBlur={field.handleBlur} onChange={(e) => field.handleChange(e.target.value)} />}</form.Field> <form.Field name="name">{(field) => <TextField label="Domain name" name={field.name} value={field.state.value} onBlur={field.handleBlur} onChange={(e) => field.handleChange(e.target.value)} />}</form.Field>
<form.Field name="expectedServerIp">{(field) => <TextField label="Expected server IP" name={field.name} value={field.state.value} onBlur={field.handleBlur} onChange={(e) => field.handleChange(e.target.value)} />}</form.Field> <form.Field name="expectedServerIp">{(field) => <TextField label="Expected server IP" name={field.name} value={field.state.value} onBlur={field.handleBlur} onChange={(e) => field.handleChange(e.target.value)} />}</form.Field>

View file

@ -2,11 +2,12 @@ import { Button } from "@minmon/ui/components/button";
import { useForm } from "@tanstack/react-form"; import { useForm } from "@tanstack/react-form";
import { useMutation, useQuery } from "@tanstack/react-query"; import { useMutation, useQuery } from "@tanstack/react-query";
import { createFileRoute, useNavigate } from "@tanstack/react-router"; import { createFileRoute, useNavigate } from "@tanstack/react-router";
import { useEffect } from "react";
import { toast } from "sonner"; import { toast } from "sonner";
import { DetailCard, FormCard, PageSection, QueryStateCard, TextAreaField, TextField } from "@/components/dashboard-ui"; import { DetailCard, FormCard, PageSection, QueryStateCard, TextAreaField, TextField } from "@/components/dashboard-ui";
import { queryClient, trpc, trpcClient } from "@/utils/trpc"; import { queryClient, trpc, trpcClient } from "@/utils/trpc";
export const Route = createFileRoute("/dashboard/notes/$noteId")({ export const Route = createFileRoute("/dashboard/notes_/$noteId")({
component: RouteComponent, component: RouteComponent,
}); });
@ -39,19 +40,11 @@ function RouteComponent() {
onError: (error) => toast.error(error.message), onError: (error) => toast.error(error.message),
}); });
if (note.isLoading || servers.isLoading) {
return <QueryStateCard title="Loading note" description="Fetching the selected note details." />;
}
if (note.isError || servers.isError || !note.data || !servers.data) {
return <QueryStateCard title="Note unavailable" description="The requested note could not be loaded." />;
}
const defaultValues: NoteFormValues = { const defaultValues: NoteFormValues = {
serverId: note.data.serverId, serverId: "",
title: note.data.title, title: "",
category: note.data.category ?? "", category: "",
content: note.data.content, content: "",
}; };
const form = useForm({ const form = useForm({
@ -61,6 +54,27 @@ function RouteComponent() {
}, },
}); });
useEffect(() => {
if (!note.data) {
return;
}
form.reset({
serverId: note.data.serverId,
title: note.data.title,
category: note.data.category ?? "",
content: note.data.content,
});
}, [note.data, form]);
if (note.isLoading || servers.isLoading) {
return <QueryStateCard title="Loading note" description="Fetching the selected note details." />;
}
if (note.isError || servers.isError || !note.data || !servers.data) {
return <QueryStateCard title="Note unavailable" description="The requested note could not be loaded." />;
}
return ( return (
<div className="grid gap-6"> <div className="grid gap-6">
<PageSection title={note.data.title} description="View and edit this note."> <PageSection title={note.data.title} description="View and edit this note.">

View file

@ -3,11 +3,12 @@ import { StatusBadge } from "@minmon/ui/components/status-badge";
import { useForm } from "@tanstack/react-form"; import { useForm } from "@tanstack/react-form";
import { useMutation, useQuery } from "@tanstack/react-query"; import { useMutation, useQuery } from "@tanstack/react-query";
import { createFileRoute, useNavigate } from "@tanstack/react-router"; import { createFileRoute, useNavigate } from "@tanstack/react-router";
import { useEffect } from "react";
import { toast } from "sonner"; import { toast } from "sonner";
import { DetailCard, FormCard, PageSection, QueryStateCard, TextAreaField, TextField } from "@/components/dashboard-ui"; import { DetailCard, FormCard, PageSection, QueryStateCard, TextAreaField, TextField } from "@/components/dashboard-ui";
import { queryClient, trpc, trpcClient } from "@/utils/trpc"; import { queryClient, trpc, trpcClient } from "@/utils/trpc";
export const Route = createFileRoute("/dashboard/servers/$serverId")({ export const Route = createFileRoute("/dashboard/servers_/$serverId")({
component: RouteComponent, component: RouteComponent,
}); });
@ -45,23 +46,15 @@ function RouteComponent() {
onError: (error) => toast.error(error.message), onError: (error) => toast.error(error.message),
}); });
if (server.isLoading) {
return <QueryStateCard title="Loading server" description="Fetching the selected server details." />;
}
if (server.isError || !server.data) {
return <QueryStateCard title="Server unavailable" description="The requested server could not be loaded." />;
}
const defaultValues: ServerFormValues = { const defaultValues: ServerFormValues = {
name: server.data.name, name: "",
primaryIpAddress: server.data.primaryIpAddress, primaryIpAddress: "",
secondaryIpAddress: server.data.secondaryIpAddress ?? "", secondaryIpAddress: "",
operatingSystem: server.data.operatingSystem ?? "", operatingSystem: "",
location: server.data.location ?? "", location: "",
provider: server.data.provider ?? "", provider: "",
description: server.data.description ?? "", description: "",
status: server.data.status, status: "active",
}; };
const form = useForm({ const form = useForm({
@ -71,6 +64,31 @@ function RouteComponent() {
}, },
}); });
useEffect(() => {
if (!server.data) {
return;
}
form.reset({
name: server.data.name,
primaryIpAddress: server.data.primaryIpAddress,
secondaryIpAddress: server.data.secondaryIpAddress ?? "",
operatingSystem: server.data.operatingSystem ?? "",
location: server.data.location ?? "",
provider: server.data.provider ?? "",
description: server.data.description ?? "",
status: server.data.status,
});
}, [server.data, form]);
if (server.isLoading) {
return <QueryStateCard title="Loading server" description="Fetching the selected server details." />;
}
if (server.isError || !server.data) {
return <QueryStateCard title="Server unavailable" description="The requested server could not be loaded." />;
}
return ( return (
<div className="grid gap-6"> <div className="grid gap-6">
<PageSection title={server.data.name} description="View and edit the selected server."> <PageSection title={server.data.name} description="View and edit the selected server.">

View file

@ -3,11 +3,12 @@ import { StatusBadge } from "@minmon/ui/components/status-badge";
import { useForm } from "@tanstack/react-form"; import { useForm } from "@tanstack/react-form";
import { useMutation, useQuery } from "@tanstack/react-query"; import { useMutation, useQuery } from "@tanstack/react-query";
import { createFileRoute, useNavigate } from "@tanstack/react-router"; import { createFileRoute, useNavigate } from "@tanstack/react-router";
import { useEffect } from "react";
import { toast } from "sonner"; import { toast } from "sonner";
import { DetailCard, FormCard, PageSection, QueryStateCard, TextAreaField, TextField } from "@/components/dashboard-ui"; import { DetailCard, FormCard, PageSection, QueryStateCard, TextAreaField, TextField } from "@/components/dashboard-ui";
import { queryClient, trpc, trpcClient } from "@/utils/trpc"; import { queryClient, trpc, trpcClient } from "@/utils/trpc";
export const Route = createFileRoute("/dashboard/services/$serviceId")({ export const Route = createFileRoute("/dashboard/services_/$serviceId")({
component: RouteComponent, component: RouteComponent,
}); });
@ -48,23 +49,15 @@ function RouteComponent() {
onError: (error) => toast.error(error.message), onError: (error) => toast.error(error.message),
}); });
if (service.isLoading || servers.isLoading) {
return <QueryStateCard title="Loading service" description="Fetching the selected service details." />;
}
if (service.isError || servers.isError || !service.data || !servers.data) {
return <QueryStateCard title="Service unavailable" description="The requested service could not be loaded." />;
}
const defaultValues: ServiceFormValues = { const defaultValues: ServiceFormValues = {
serverId: service.data.serverId, serverId: "",
name: service.data.name, name: "",
type: service.data.type, type: "web_app",
internalPort: service.data.internalPort?.toString() ?? "", internalPort: "",
externalPort: service.data.externalPort?.toString() ?? "", externalPort: "",
protocol: service.data.protocol, protocol: "http",
status: service.data.status, status: "active",
description: service.data.description ?? "", description: "",
}; };
const form = useForm({ const form = useForm({
@ -74,6 +67,31 @@ function RouteComponent() {
}, },
}); });
useEffect(() => {
if (!service.data) {
return;
}
form.reset({
serverId: service.data.serverId,
name: service.data.name,
type: service.data.type,
internalPort: service.data.internalPort?.toString() ?? "",
externalPort: service.data.externalPort?.toString() ?? "",
protocol: service.data.protocol,
status: service.data.status,
description: service.data.description ?? "",
});
}, [service.data, form]);
if (service.isLoading || servers.isLoading) {
return <QueryStateCard title="Loading service" description="Fetching the selected service details." />;
}
if (service.isError || servers.isError || !service.data || !servers.data) {
return <QueryStateCard title="Service unavailable" description="The requested service could not be loaded." />;
}
return ( return (
<div className="grid gap-6"> <div className="grid gap-6">
<PageSection title={service.data.name} description="View and edit the selected service."> <PageSection title={service.data.name} description="View and edit the selected service.">