Typesafe routing and CM line height issue

This commit is contained in:
Gregory Schier
2023-03-20 16:47:36 -07:00
parent c5ca3daab3
commit f855d8ab16
20 changed files with 202 additions and 77 deletions

View File

@@ -1,6 +1,7 @@
import { useParams } from 'react-router-dom';
import type { RouteParamsRequest } from './useRoutes';
export function useActiveRequestId(): string | null {
const { requestId } = useParams<{ requestId?: string }>();
const { requestId } = useParams<RouteParamsRequest>();
return requestId ?? null;
}

View File

@@ -1,6 +1,7 @@
import { useParams } from 'react-router-dom';
import type { RouteParamsWorkspace } from './useRoutes';
export function useActiveWorkspaceId(): string | null {
const { workspaceId } = useParams<{ workspaceId?: string }>();
const { workspaceId } = useParams<RouteParamsWorkspace>();
return workspaceId ?? null;
}

View File

@@ -1,17 +1,17 @@
import { useMutation } from '@tanstack/react-query';
import { invoke } from '@tauri-apps/api';
import { useNavigate } from 'react-router-dom';
import type { Workspace } from '../lib/models';
import { useRoutes } from './useRoutes';
export function useCreateWorkspace({ navigateAfter }: { navigateAfter: boolean }) {
const navigate = useNavigate();
const routes = useRoutes();
return useMutation<string, unknown, Pick<Workspace, 'name'>>({
mutationFn: (patch) => {
return invoke('create_workspace', patch);
},
onSuccess: async (workspaceId) => {
if (navigateAfter) {
navigate(`/workspaces/${workspaceId}`);
routes.navigate('workspace', { workspaceId });
}
},
});

View File

@@ -0,0 +1,11 @@
import { useMutation } from '@tanstack/react-query';
import { invoke } from '@tauri-apps/api';
export function useDeleteResponse(id: string | null) {
return useMutation({
mutationFn: async () => {
if (id === null) return;
await invoke('delete_response', { id: id });
},
});
}

View File

@@ -9,9 +9,9 @@ export function useDeleteResponses(requestId?: string) {
if (!requestId) return;
await invoke('delete_all_responses', { requestId });
},
onSuccess: () => {
onSuccess: async () => {
if (!requestId) return;
queryClient.setQueryData(responsesQueryKey(requestId), []);
await queryClient.invalidateQueries(responsesQueryKey(requestId));
},
});
}

View File

@@ -0,0 +1,25 @@
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { invoke } from '@tauri-apps/api';
import { useNavigate } from 'react-router-dom';
import { useActiveWorkspaceId } from './useActiveWorkspaceId';
import { useRoutes } from './useRoutes';
import { workspacesQueryKey } from './useWorkspaces';
export function useDeleteWorkspace(id: string | null) {
const queryClient = useQueryClient();
const activeWorkspaceId = useActiveWorkspaceId();
const routes = useRoutes();
return useMutation<void, string>({
mutationFn: async () => {
if (id === null) return;
await invoke('delete_workspace', { id });
},
onSuccess: async () => {
if (id === null) return;
await queryClient.invalidateQueries(workspacesQueryKey());
if (id === activeWorkspaceId) {
routes.navigate('workspace', { workspaceId: id });
}
},
});
}

View File

@@ -1,21 +0,0 @@
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { invoke } from '@tauri-apps/api';
import type { HttpResponse } from '../lib/models';
import { responsesQueryKey } from './useResponses';
export function useDeleteResponse(response: HttpResponse | null) {
const queryClient = useQueryClient();
return useMutation({
mutationFn: async () => {
if (response === null) return;
await invoke('delete_response', { id: response.id });
},
onSuccess: () => {
if (response === null) return;
queryClient.setQueryData(
responsesQueryKey(response.requestId),
(responses: HttpResponse[] = []) => responses.filter((r) => r.id !== response.id),
);
},
});
}

View File

@@ -0,0 +1,39 @@
export type RouteParamsWorkspace = {
workspaceId: string;
};
export type RouteParamsRequest = RouteParamsWorkspace & {
requestId: string;
};
export const routePaths = {
workspaces() {
return '/workspaces';
},
workspace({ workspaceId } = { workspaceId: ':workspaceId' } as RouteParamsWorkspace) {
return `/workspaces/${workspaceId}`;
},
request(
{ workspaceId, requestId } = {
workspaceId: ':workspaceId',
requestId: ':requestId',
} as RouteParamsRequest,
) {
return `${this.workspace({ workspaceId })}/requests/${requestId}`;
},
};
export function useRoutes() {
return {
navigate<T extends keyof typeof routePaths>(
path: T,
params: Parameters<(typeof routePaths)[T]>[0],
) {
// Not sure how to make TS work here, but it's good from the
// outside caller perspective.
// eslint-disable-next-line @typescript-eslint/no-explicit-any
routePaths[path](params as any);
},
paths: routePaths,
};
}