feat: add Environment admin UI page
All checks were successful
CI / cleanup-branch (push) Has been skipped
CI / build (push) Successful in 1m19s
CI / docker (push) Successful in 1m6s
CI / deploy-feature (push) Has been skipped
CI / deploy (push) Successful in 41s

SplitPane with create/edit/delete, production flag toggle,
enabled/disabled toggle. Follows existing admin page patterns.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
hsiegeln
2026-04-08 11:19:05 +02:00
parent 2e006051bc
commit 9af0043915
4 changed files with 365 additions and 0 deletions

View File

@@ -0,0 +1,63 @@
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { adminFetch } from './admin-api';
export interface Environment {
id: string;
slug: string;
displayName: string;
production: boolean;
enabled: boolean;
createdAt: string;
}
export interface CreateEnvironmentRequest {
slug: string;
displayName: string;
production: boolean;
}
export interface UpdateEnvironmentRequest {
displayName: string;
production: boolean;
enabled: boolean;
}
export function useEnvironments() {
return useQuery({
queryKey: ['admin', 'environments'],
queryFn: () => adminFetch<Environment[]>('/environments'),
});
}
export function useCreateEnvironment() {
const qc = useQueryClient();
return useMutation({
mutationFn: (req: CreateEnvironmentRequest) =>
adminFetch<Environment>('/environments', {
method: 'POST',
body: JSON.stringify(req),
}),
onSuccess: () => qc.invalidateQueries({ queryKey: ['admin', 'environments'] }),
});
}
export function useUpdateEnvironment() {
const qc = useQueryClient();
return useMutation({
mutationFn: ({ id, ...req }: UpdateEnvironmentRequest & { id: string }) =>
adminFetch<Environment>(`/environments/${id}`, {
method: 'PUT',
body: JSON.stringify(req),
}),
onSuccess: () => qc.invalidateQueries({ queryKey: ['admin', 'environments'] }),
});
}
export function useDeleteEnvironment() {
const qc = useQueryClient();
return useMutation({
mutationFn: (id: string) =>
adminFetch<void>(`/environments/${id}`, { method: 'DELETE' }),
onSuccess: () => qc.invalidateQueries({ queryKey: ['admin', 'environments'] }),
});
}