chore: codify React component style
This commit is contained in:
@@ -2,7 +2,7 @@ import { MantineProvider } from "@mantine/core";
|
||||
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
||||
import { renderHook, waitFor } from "@testing-library/react";
|
||||
import { HttpResponse, http } from "msw";
|
||||
import type { ReactNode } from "react";
|
||||
import type { FC, PropsWithChildren } from "react";
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import { server } from "@/test/server";
|
||||
import { useAuthenticatedQuery } from "./authenticated-query";
|
||||
@@ -10,11 +10,17 @@ import { apiQueryClient, configureAuthClient } from "./client";
|
||||
|
||||
function createWrapper() {
|
||||
const client = new QueryClient();
|
||||
return ({ children }: { children: ReactNode }) => (
|
||||
<MantineProvider>
|
||||
<QueryClientProvider client={client}>{children}</QueryClientProvider>
|
||||
</MantineProvider>
|
||||
);
|
||||
const TestWrapper: FC<PropsWithChildren> = (props) => {
|
||||
const { children } = props;
|
||||
|
||||
return (
|
||||
<MantineProvider>
|
||||
<QueryClientProvider client={client}>{children}</QueryClientProvider>
|
||||
</MantineProvider>
|
||||
);
|
||||
};
|
||||
|
||||
return TestWrapper;
|
||||
}
|
||||
|
||||
describe("useAuthenticatedQuery", () => {
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
subscribeAuthenticatedSession,
|
||||
} from "./client";
|
||||
|
||||
export function useAuthenticatedQuery<
|
||||
function useAuthenticatedQuery<
|
||||
TQueryFnData = unknown,
|
||||
TError = Error,
|
||||
TData = TQueryFnData,
|
||||
@@ -32,3 +32,5 @@ export function useAuthenticatedQuery<
|
||||
(typeof enabled === "function" ? enabled(query) : (enabled ?? true)),
|
||||
});
|
||||
}
|
||||
|
||||
export { useAuthenticatedQuery };
|
||||
|
||||
@@ -21,16 +21,16 @@ function setAuthenticatedSession(next: boolean) {
|
||||
for (const listener of authSessionListeners) listener();
|
||||
}
|
||||
|
||||
export function configureAuthClient(handlers: AuthHandlers | null) {
|
||||
function configureAuthClient(handlers: AuthHandlers | null) {
|
||||
auth = handlers;
|
||||
setAuthenticatedSession(Boolean(auth?.accessToken()));
|
||||
}
|
||||
|
||||
export function getAuthenticatedSessionSnapshot() {
|
||||
function getAuthenticatedSessionSnapshot() {
|
||||
return hasAuthenticatedSession;
|
||||
}
|
||||
|
||||
export function subscribeAuthenticatedSession(listener: () => void) {
|
||||
function subscribeAuthenticatedSession(listener: () => void) {
|
||||
authSessionListeners.add(listener);
|
||||
return () => authSessionListeners.delete(listener);
|
||||
}
|
||||
@@ -71,10 +71,18 @@ async function authenticatedFetch(request: Request): Promise<Response> {
|
||||
: response;
|
||||
}
|
||||
|
||||
export const apiClient = createClient<paths>({
|
||||
const apiClient = createClient<paths>({
|
||||
baseUrl: apiBaseUrl,
|
||||
credentials: "include",
|
||||
fetch: authenticatedFetch,
|
||||
});
|
||||
|
||||
export const apiQueryClient = createQueryClient(apiClient);
|
||||
const apiQueryClient = createQueryClient(apiClient);
|
||||
|
||||
export {
|
||||
apiClient,
|
||||
apiQueryClient,
|
||||
configureAuthClient,
|
||||
getAuthenticatedSessionSnapshot,
|
||||
subscribeAuthenticatedSession,
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export const ru = {
|
||||
const ru = {
|
||||
translation: {
|
||||
appName: "WealthLedger",
|
||||
navigation: { accounts: "Счета", settings: "Настройки" },
|
||||
@@ -167,3 +167,5 @@ export const ru = {
|
||||
},
|
||||
},
|
||||
} as const;
|
||||
|
||||
export { ru };
|
||||
|
||||
@@ -2,8 +2,10 @@ import type { ParseKeys } from "i18next";
|
||||
|
||||
import { i18n } from "./i18n";
|
||||
|
||||
export function validationMessage(
|
||||
function validationMessage(
|
||||
key: ParseKeys,
|
||||
): (_value: unknown) => { message: string } {
|
||||
return () => ({ message: i18n.t(key) });
|
||||
}
|
||||
|
||||
export { validationMessage };
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
import { AppShell as MantineAppShell, NavLink, Text } from "@mantine/core";
|
||||
import type { ReactNode } from "react";
|
||||
import type { FC, ReactNode } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Outlet, NavLink as RouterNavLink, useLocation } from "react-router";
|
||||
|
||||
export function AppShell({
|
||||
contentAboveOutlet,
|
||||
}: {
|
||||
type AppShellProps = {
|
||||
contentAboveOutlet?: ReactNode;
|
||||
}) {
|
||||
};
|
||||
|
||||
const AppShell: FC<AppShellProps> = (props) => {
|
||||
const { contentAboveOutlet } = props;
|
||||
const { t } = useTranslation();
|
||||
const { pathname } = useLocation();
|
||||
const items = [
|
||||
@@ -52,4 +53,6 @@ export function AppShell({
|
||||
</nav>
|
||||
</MantineAppShell>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export { AppShell };
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Button, Loader, Paper, Stack, Text, Title } from "@mantine/core";
|
||||
import type { ReactNode } from "react";
|
||||
import type { FC, ReactNode } from "react";
|
||||
|
||||
type StateViewProps = {
|
||||
title: string;
|
||||
@@ -9,13 +9,8 @@ type StateViewProps = {
|
||||
error?: boolean;
|
||||
};
|
||||
|
||||
export function StateView({
|
||||
title,
|
||||
text,
|
||||
action,
|
||||
loading = false,
|
||||
error = false,
|
||||
}: StateViewProps) {
|
||||
const StateView: FC<StateViewProps> = (props) => {
|
||||
const { title, text, action, loading = false, error = false } = props;
|
||||
const role = loading ? "status" : error ? "alert" : undefined;
|
||||
|
||||
return (
|
||||
@@ -28,6 +23,6 @@ export function StateView({
|
||||
</Stack>
|
||||
</Paper>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export { Button };
|
||||
export { Button, StateView };
|
||||
|
||||
Reference in New Issue
Block a user