.
This commit is contained in:
parent
ff6a546d8a
commit
87eb51a44b
64
apps/web/src/app-routes.tsx
Normal file
64
apps/web/src/app-routes.tsx
Normal file
@ -0,0 +1,64 @@
|
||||
import { AppLayout, LoadingOverlay, ScrollToTop } from "@repo/rdx-ui/components";
|
||||
import { JSX, Suspense } from "react";
|
||||
import { Route, BrowserRouter as Router, Routes } from "react-router-dom";
|
||||
import { ErrorPage } from "./pages";
|
||||
import { modules } from "./register-modules"; // Aquí ca
|
||||
|
||||
// Lazy load components
|
||||
//const ErrorPage = lazy(() => import("./pages").then((m) => ({ default: m.ErrorPage })));
|
||||
|
||||
//const LogoutPage = lazy(() => import("./app").then((m) => ({ default: m.LogoutPage })));
|
||||
|
||||
/*const DealerLayout = lazy(() => import("./app").then((m) => ({ default: m.DealerLayout })));
|
||||
const DealersList = lazy(() => import("./app").then((m) => ({ default: m.DealersList })));
|
||||
|
||||
const LoginPageWithLanguageSelector = lazy(() =>
|
||||
import("./app").then((m) => ({ default: m.LoginPageWithLanguageSelector }))
|
||||
);
|
||||
|
||||
const QuoteCreate = lazy(() => import("./app").then((m) => ({ default: m.QuoteCreate })));
|
||||
const QuoteEdit = lazy(() => import("./app").then((m) => ({ default: m.QuoteEdit })));
|
||||
const SettingsEditor = lazy(() => import("./app").then((m) => ({ default: m.SettingsEditor })));
|
||||
const SettingsLayout = lazy(() => import("./app").then((m) => ({ default: m.SettingsLayout })));
|
||||
const CatalogLayout = lazy(() => import("./app").then((m) => ({ default: m.CatalogLayout })));
|
||||
const CatalogList = lazy(() => import("./app").then((m) => ({ default: m.CatalogList })));
|
||||
const DashboardPage = lazy(() => import("./app").then((m) => ({ default: m.DashboardPage })));
|
||||
const QuotesLayout = lazy(() => import("./app").then((m) => ({ default: m.QuotesLayout })));
|
||||
const QuotesList = lazy(() => import("./app").then((m) => ({ default: m.QuotesList })));*/
|
||||
|
||||
export const AppRoutes = (): JSX.Element => {
|
||||
return (
|
||||
<Router>
|
||||
<ScrollToTop />
|
||||
|
||||
<Suspense fallback={<LoadingOverlay />}>
|
||||
<Routes>
|
||||
<Route element={<AppLayout />}>
|
||||
{/* Main Layout */}
|
||||
<Route index element={<ErrorPage />} />
|
||||
<Route path='/dashboard' element={<ErrorPage />} />
|
||||
<Route path='/settings' element={<ErrorPage />} />
|
||||
<Route path='/catalog' element={<ErrorPage />} />
|
||||
<Route path='/quotes' element={<ErrorPage />} />
|
||||
|
||||
{/* Dynamic Module Routes */}
|
||||
|
||||
{modules.map((module) => {
|
||||
if (module.routes) {
|
||||
return module.routes();
|
||||
}
|
||||
return null;
|
||||
})}
|
||||
</Route>
|
||||
|
||||
{/* Auth Layout */}
|
||||
{/*<Route path="/signin" element={<SignIn />} />
|
||||
<Route path="/signup" element={<SignUp />} />*/}
|
||||
|
||||
{/* Fallback Route */}
|
||||
<Route path='*' element={<ErrorPage />} />
|
||||
</Routes>
|
||||
</Suspense>
|
||||
</Router>
|
||||
);
|
||||
};
|
||||
@ -1,18 +1,16 @@
|
||||
import { LoadingOverlay, TailwindIndicator } from "@repo/rdx-ui/components";
|
||||
import { Toaster, TooltipProvider } from "@repo/shadcn-ui/components";
|
||||
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
||||
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
|
||||
import { Suspense } from "react";
|
||||
import { I18nextProvider } from "react-i18next";
|
||||
|
||||
import { createAxiosDataProvider } from "@/lib/axios/create-axios-data-provider";
|
||||
import { DataSourceProvider, ThemeProvider, UnsavedWarnProvider } from "@/lib/hooks";
|
||||
import { DataSourceProvider, UnsavedWarnProvider } from "@/lib/hooks";
|
||||
import { i18n } from "@/locales";
|
||||
|
||||
import "./App.css";
|
||||
import { Routes } from "./routes";
|
||||
import { AppRoutes } from "./app-routes";
|
||||
import "./app.css";
|
||||
|
||||
function App() {
|
||||
export const App = () => {
|
||||
const queryClient = new QueryClient({
|
||||
defaultOptions: {
|
||||
queries: {
|
||||
@ -26,22 +24,16 @@ function App() {
|
||||
<I18nextProvider i18n={i18n}>
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<DataSourceProvider dataSource={createAxiosDataProvider(import.meta.env.VITE_API_URL)}>
|
||||
<ThemeProvider defaultTheme='light' storageKey='vite-ui-theme'>
|
||||
<TooltipProvider delayDuration={0}>
|
||||
<UnsavedWarnProvider>
|
||||
<Suspense fallback={<LoadingOverlay />}>
|
||||
<Routes />
|
||||
</Suspense>
|
||||
</UnsavedWarnProvider>
|
||||
</TooltipProvider>
|
||||
<Toaster />
|
||||
<TailwindIndicator />
|
||||
{import.meta.env.MODE === "development" && <ReactQueryDevtools initialIsOpen={false} />}
|
||||
</ThemeProvider>
|
||||
<TooltipProvider delayDuration={0}>
|
||||
<UnsavedWarnProvider>
|
||||
<AppRoutes />
|
||||
</UnsavedWarnProvider>
|
||||
</TooltipProvider>
|
||||
<Toaster />
|
||||
|
||||
{import.meta.env.MODE === "development" && <ReactQueryDevtools initialIsOpen={false} />}
|
||||
</DataSourceProvider>
|
||||
</QueryClientProvider>
|
||||
</I18nextProvider>
|
||||
);
|
||||
}
|
||||
|
||||
export default App;
|
||||
};
|
||||
@ -1,6 +1,8 @@
|
||||
import { ThemeProvider } from "@/lib/hooks";
|
||||
import { TailwindIndicator } from "@repo/rdx-ui/components";
|
||||
import { StrictMode } from "react";
|
||||
import { createRoot } from "react-dom/client";
|
||||
import App from "./App.tsx";
|
||||
import { App } from "./app.tsx";
|
||||
|
||||
import "./global.css";
|
||||
|
||||
@ -8,7 +10,10 @@ const rootElement = document.getElementById("factuges");
|
||||
if (rootElement) {
|
||||
createRoot(rootElement).render(
|
||||
<StrictMode>
|
||||
<App />
|
||||
<ThemeProvider defaultTheme='light' storageKey='vite-ui-theme'>
|
||||
<App />
|
||||
<TailwindIndicator />
|
||||
</ThemeProvider>
|
||||
</StrictMode>
|
||||
);
|
||||
} else {
|
||||
|
||||
@ -1,197 +0,0 @@
|
||||
import { LoadingOverlay } from "@repo/rdx-ui/components";
|
||||
import { Suspense, lazy } from "react";
|
||||
import { RouteObject, RouterProvider, createBrowserRouter } from "react-router-dom";
|
||||
import { modules } from "./register-modules"; // Aquí ca
|
||||
|
||||
// Lazy load components
|
||||
const ErrorPage = lazy(() => import("./pages").then((m) => ({ default: m.ErrorPage })));
|
||||
|
||||
//const LogoutPage = lazy(() => import("./app").then((m) => ({ default: m.LogoutPage })));
|
||||
|
||||
/*const DealerLayout = lazy(() => import("./app").then((m) => ({ default: m.DealerLayout })));
|
||||
const DealersList = lazy(() => import("./app").then((m) => ({ default: m.DealersList })));
|
||||
|
||||
const LoginPageWithLanguageSelector = lazy(() =>
|
||||
import("./app").then((m) => ({ default: m.LoginPageWithLanguageSelector }))
|
||||
);
|
||||
|
||||
const QuoteCreate = lazy(() => import("./app").then((m) => ({ default: m.QuoteCreate })));
|
||||
const QuoteEdit = lazy(() => import("./app").then((m) => ({ default: m.QuoteEdit })));
|
||||
const SettingsEditor = lazy(() => import("./app").then((m) => ({ default: m.SettingsEditor })));
|
||||
const SettingsLayout = lazy(() => import("./app").then((m) => ({ default: m.SettingsLayout })));
|
||||
const CatalogLayout = lazy(() => import("./app").then((m) => ({ default: m.CatalogLayout })));
|
||||
const CatalogList = lazy(() => import("./app").then((m) => ({ default: m.CatalogList })));
|
||||
const DashboardPage = lazy(() => import("./app").then((m) => ({ default: m.DashboardPage })));
|
||||
const QuotesLayout = lazy(() => import("./app").then((m) => ({ default: m.QuotesLayout })));
|
||||
const QuotesList = lazy(() => import("./app").then((m) => ({ default: m.QuotesList })));*/
|
||||
|
||||
export const Routes = () => {
|
||||
const routesForErrors = [
|
||||
{
|
||||
path: "*",
|
||||
Element: (
|
||||
<Suspense fallback={<LoadingOverlay />}>
|
||||
<ErrorPage />
|
||||
</Suspense>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
const routesForModules: RouteObject[] = [];
|
||||
|
||||
modules.map((module) => {
|
||||
if (module.routes) {
|
||||
routesForModules.push(...module.routes());
|
||||
}
|
||||
});
|
||||
|
||||
// Define routes accessible only to authenticated users
|
||||
/*const routesForAuthenticatedOnly = [
|
||||
{
|
||||
path: "/",
|
||||
element: (
|
||||
<ProtectedRoute>
|
||||
<Navigate to='/quotes' replace={true} />
|
||||
</ProtectedRoute>
|
||||
),
|
||||
},
|
||||
{
|
||||
path: "/home",
|
||||
element: (
|
||||
<ProtectedRoute>
|
||||
<Suspense fallback={<LoadingOverlay />}>
|
||||
<DashboardPage />
|
||||
</Suspense>
|
||||
</ProtectedRoute>
|
||||
),
|
||||
},
|
||||
{
|
||||
path: "/catalog",
|
||||
element: (
|
||||
<Suspense fallback={<LoadingOverlay />}>
|
||||
<CatalogLayout>
|
||||
<Outlet />
|
||||
</CatalogLayout>
|
||||
</Suspense>
|
||||
),
|
||||
children: [
|
||||
{
|
||||
index: true,
|
||||
element: (
|
||||
<Suspense fallback={<LoadingOverlay />}>
|
||||
<CatalogList />
|
||||
</Suspense>
|
||||
),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: "/dealers",
|
||||
element: (
|
||||
<Suspense fallback={<LoadingOverlay />}>
|
||||
<DealerLayout>
|
||||
<Outlet />
|
||||
</DealerLayout>
|
||||
</Suspense>
|
||||
),
|
||||
children: [
|
||||
{
|
||||
index: true,
|
||||
element: (
|
||||
<Suspense fallback={<LoadingOverlay />}>
|
||||
<DealersList />
|
||||
</Suspense>
|
||||
),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: "/quotes",
|
||||
element: (
|
||||
<Suspense fallback={<LoadingOverlay />}>
|
||||
<QuotesLayout>
|
||||
<Outlet />
|
||||
</QuotesLayout>
|
||||
</Suspense>
|
||||
),
|
||||
children: [
|
||||
{
|
||||
index: true,
|
||||
element: (
|
||||
<Suspense fallback={<LoadingOverlay />}>
|
||||
<QuotesList />
|
||||
</Suspense>
|
||||
),
|
||||
},
|
||||
{
|
||||
path: "add",
|
||||
element: (
|
||||
<Suspense fallback={<LoadingOverlay />}>
|
||||
<QuoteCreate />
|
||||
</Suspense>
|
||||
),
|
||||
},
|
||||
{
|
||||
path: "edit/:id",
|
||||
element: (
|
||||
<Suspense fallback={<LoadingOverlay />}>
|
||||
<QuoteEdit />
|
||||
</Suspense>
|
||||
),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: "/settings",
|
||||
element: (
|
||||
<Suspense fallback={<LoadingOverlay />}>
|
||||
<SettingsLayout>
|
||||
<Outlet />
|
||||
</SettingsLayout>
|
||||
</Suspense>
|
||||
),
|
||||
children: [
|
||||
{
|
||||
index: true,
|
||||
element: (
|
||||
<Suspense fallback={<LoadingOverlay />}>
|
||||
<SettingsEditor />
|
||||
</Suspense>
|
||||
),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: "/logout",
|
||||
element: <LogoutPage />,
|
||||
},
|
||||
];
|
||||
|
||||
// Define routes accessible only to non-authenticated users
|
||||
const routesForNotAuthenticatedOnly = [
|
||||
{
|
||||
path: "/login",
|
||||
element: (
|
||||
<Suspense fallback={<LoadingOverlay />}>
|
||||
<LoginPageWithLanguageSelector />
|
||||
</Suspense>
|
||||
),
|
||||
},
|
||||
];*/
|
||||
|
||||
// Combine and conditionally include routes based on authentication status
|
||||
const router = createBrowserRouter(
|
||||
[
|
||||
//...routesForAuthenticatedOnly,
|
||||
//...routesForNotAuthenticatedOnly,
|
||||
...routesForErrors,
|
||||
...routesForModules,
|
||||
],
|
||||
{
|
||||
//basename: "/app",
|
||||
}
|
||||
);
|
||||
|
||||
// Provide the router configuration using RouterProvider
|
||||
return <RouterProvider router={router} />;
|
||||
};
|
||||
@ -1,5 +1,4 @@
|
||||
import React, { ReactNode } from "react";
|
||||
import { RouteObject } from "react-router-dom";
|
||||
import React, { JSX, ReactNode } from "react";
|
||||
import { ModuleMetadata } from "./types";
|
||||
|
||||
export interface ModuleClientMetadata extends ModuleMetadata {
|
||||
@ -9,7 +8,7 @@ export interface ModuleClientMetadata extends ModuleMetadata {
|
||||
|
||||
export interface IModuleClient {
|
||||
metadata: ModuleClientMetadata;
|
||||
routes?: () => RouteObject[];
|
||||
routes?: () => JSX.Element;
|
||||
component?: React.FC;
|
||||
setup?(): void;
|
||||
}
|
||||
|
||||
@ -18,7 +18,8 @@
|
||||
"ag-grid-community": "^33.3.0",
|
||||
"i18next": "^25.1.1",
|
||||
"react": "^18 || ^19",
|
||||
"react-dom": "^18 || ^19"
|
||||
"react-dom": "^18 || ^19",
|
||||
"react-router-dom": "^6.26.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@biomejs/biome": "1.9.4",
|
||||
|
||||
@ -57,8 +57,9 @@ export const InvoicesGrid = () => {
|
||||
{
|
||||
field: "mission",
|
||||
filter: true,
|
||||
minWidth: 200,
|
||||
},
|
||||
{ field: "company" },
|
||||
{ field: "company", filter: false },
|
||||
{ field: "location" },
|
||||
{ field: "date" },
|
||||
{
|
||||
@ -75,12 +76,17 @@ export const InvoicesGrid = () => {
|
||||
const defaultColDef = useMemo<ColDef>(() => {
|
||||
return {
|
||||
filter: true,
|
||||
sortable: false,
|
||||
resizable: false,
|
||||
};
|
||||
}, []);
|
||||
|
||||
// Container: Defines the grid's theme & dimensions.
|
||||
return (
|
||||
<div style={{ height: 1500 }}>
|
||||
<div
|
||||
style={{ height: 1500 }}
|
||||
className='*:data-[slot=card]:shadow-xs @xl/main:grid-cols-2 @5xl/main:grid-cols-4 grid grid-cols-1 gap-4 px-4 *:data-[slot=card]:bg-gradient-to-t *:data-[slot=card]:from-primary/5 *:data-[slot=card]:to-card dark:*:data-[slot=card]:bg-card lg:px-6'
|
||||
>
|
||||
<AgGridReact
|
||||
rowData={data}
|
||||
loading={loading}
|
||||
|
||||
@ -1,7 +1,3 @@
|
||||
import { AppSidebar } from "@repo/rdx-ui/components/layout/app-sidebar";
|
||||
import { ChartAreaInteractive } from "@repo/rdx-ui/components/layout/chart-area-interactive";
|
||||
import { SiteHeader } from "@repo/rdx-ui/components/layout/site-header";
|
||||
import { SidebarInset, SidebarProvider } from "@repo/shadcn-ui/components";
|
||||
import { PropsWithChildren } from "react";
|
||||
|
||||
import { SectionCards } from "@repo/rdx-ui/components/layout/section-cards";
|
||||
@ -11,29 +7,9 @@ export const InvoicesLayout = ({ children }: PropsWithChildren) => {
|
||||
const { t } = useTranslation("invoices");
|
||||
|
||||
return (
|
||||
<SidebarProvider
|
||||
style={
|
||||
{
|
||||
"--sidebar-width": "calc(var(--spacing) * 72)",
|
||||
"--header-height": "calc(var(--spacing) * 12)",
|
||||
} as React.CSSProperties
|
||||
}
|
||||
>
|
||||
<AppSidebar variant='inset' />
|
||||
<SidebarInset>
|
||||
<SiteHeader title={t("invoices.title")} />
|
||||
<div className='flex flex-1 flex-col'>
|
||||
<div className='@container/main flex flex-1 flex-col gap-2'>
|
||||
<div className='flex flex-col gap-4 py-4 md:gap-6 md:py-6'>
|
||||
<SectionCards />
|
||||
<div className='px-4 lg:px-6'>
|
||||
<ChartAreaInteractive />
|
||||
</div>
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</SidebarInset>
|
||||
</SidebarProvider>
|
||||
<>
|
||||
<SectionCards />
|
||||
{children}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
//import { ProtectedRoute } from "@erp/auth/components";
|
||||
import { LoadingOverlay } from "@repo/rdx-ui/components";
|
||||
import { Suspense, lazy } from "react";
|
||||
import { Outlet, RouteObject } from "react-router-dom";
|
||||
import { InvoicesGrid } from "./components";
|
||||
import { JSX, lazy } from "react";
|
||||
import { Route } from "react-router-dom";
|
||||
|
||||
// Lazy load components
|
||||
const InvoicesLayout = lazy(() =>
|
||||
@ -29,32 +27,24 @@ const DashboardPage = lazy(() => import("./app").then((m) => ({ default: m.Dashb
|
||||
const InvoicesLayout = lazy(() => import("./app").then((m) => ({ default: m.InvoicesLayout })));
|
||||
const InvoicesList = lazy(() => import("./app").then((m) => ({ default: m.InvoicesList })));*/
|
||||
|
||||
export const InvoiceRoutes = (): RouteObject[] => {
|
||||
// Define routes accessible only to authenticated users
|
||||
const privateRoutes: RouteObject[] = [
|
||||
{
|
||||
path: "/invoices",
|
||||
element: (
|
||||
<Suspense fallback={<LoadingOverlay />}>
|
||||
<InvoicesLayout>
|
||||
<Outlet />
|
||||
</InvoicesLayout>
|
||||
</Suspense>
|
||||
),
|
||||
children: [
|
||||
{
|
||||
index: true,
|
||||
element: <InvoicesGrid />,
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
export const InvoiceRoutes = (): JSX.Element => {
|
||||
return (
|
||||
<Route path='/invoices' element={<InvoicesLayout />}>
|
||||
<Route index element={<InvoicesList />} />
|
||||
<Route path='list' element={<InvoicesList />} />
|
||||
|
||||
// Define routes accessible only to non-authenticated users
|
||||
const publicRoutes = [{}];
|
||||
{/*<Route path='create' element={<InvoiceCreate />} />
|
||||
<Route path=':id' element={<InvoicesList />} />
|
||||
<Route path=':id/edit' element={<InvoicesList />} />
|
||||
<Route path=':id/delete' element={<InvoicesList />} />
|
||||
<Route path=':id/view' element={<InvoicesList />} />
|
||||
<Route path=':id/print' element={<InvoicesList />} />
|
||||
<Route path=':id/email' element={<InvoicesList />} />
|
||||
<Route path=':id/download' element={<InvoicesList />} />
|
||||
<Route path=':id/duplicate' element={<InvoicesList />} />
|
||||
<Route path=':id/preview' element={<InvoicesList />} />*/}
|
||||
|
||||
return privateRoutes;
|
||||
|
||||
// Provide the router configuration using RouterProvider
|
||||
//return <RouterProvider router={router} />;
|
||||
<Route path='*' element={<InvoicesList />} />
|
||||
</Route>
|
||||
);
|
||||
};
|
||||
@ -2,7 +2,7 @@ import { IModuleClient } from "@erp/core";
|
||||
import i18next from "i18next";
|
||||
import enResources from "../common/locales/en.json";
|
||||
import esResources from "../common/locales/es.json";
|
||||
import { InvoiceRoutes } from "./routes";
|
||||
import { InvoiceRoutes } from "./invoice-routes";
|
||||
|
||||
const MODULE_NAME = "invoices";
|
||||
const MODULE_VERSION = "1.0.0";
|
||||
|
||||
@ -16,7 +16,8 @@
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^18 || ^19",
|
||||
"react-dom": "^18 || ^19"
|
||||
"react-dom": "^18 || ^19",
|
||||
"react-router": "^6.26.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@biomejs/biome": "1.9.4",
|
||||
@ -49,6 +50,7 @@
|
||||
"react-dom": "^19.1.0",
|
||||
"react-i18next": "^15.5.1",
|
||||
"react-router-dom": "^6.26.0",
|
||||
"react-router": "^6.26.0",
|
||||
"recharts": "^2.15.3",
|
||||
"sonner": "^2.0.3",
|
||||
"zod": "^3.24.4"
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
export * from "./tailwind-indicator.tsx";
|
||||
export * from "./loading-overlay/index.tsx";
|
||||
export * from "./buttons/index.tsx";
|
||||
export * from "./custom-dialog.tsx";
|
||||
export * from "./error-overlay.tsx";
|
||||
export * from "./buttons/index.tsx";
|
||||
export * from "./layout/index.tsx";
|
||||
export * from "./loading-overlay/index.tsx";
|
||||
export * from "./scroll-to-top.tsx";
|
||||
export * from "./tailwind-indicator.tsx";
|
||||
|
||||
30
packages/rdx-ui/src/components/layout/app-layout.tsx
Normal file
30
packages/rdx-ui/src/components/layout/app-layout.tsx
Normal file
@ -0,0 +1,30 @@
|
||||
import { SidebarInset, SidebarProvider } from "@repo/shadcn-ui/components";
|
||||
import { Outlet } from "react-router";
|
||||
import { AppSidebar } from "./app-sidebar.tsx";
|
||||
import { SiteHeader } from "./site-header.tsx";
|
||||
|
||||
export const AppLayout: React.FC = () => {
|
||||
return (
|
||||
<SidebarProvider
|
||||
style={
|
||||
{
|
||||
"--sidebar-width": "calc(var(--spacing) * 72)",
|
||||
"--header-height": "calc(var(--spacing) * 12)",
|
||||
} as React.CSSProperties
|
||||
}
|
||||
>
|
||||
<AppSidebar variant='inset' />
|
||||
<SidebarInset>
|
||||
<SiteHeader title={"Título"} />
|
||||
|
||||
<div className='flex flex-1 flex-col'>
|
||||
<div className='@container/main flex flex-1 flex-col gap-2'>
|
||||
<div className='flex flex-col gap-4 py-4 md:gap-6 md:py-6'>
|
||||
<Outlet />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</SidebarInset>
|
||||
</SidebarProvider>
|
||||
);
|
||||
};
|
||||
@ -1,9 +1 @@
|
||||
export * from "./app-sidebar.tsx";
|
||||
export * from "./chart-area-interactive.tsx";
|
||||
export * from "./data-table.tsx";
|
||||
export * from "./nav-documents.tsx";
|
||||
export * from "./nav-main.tsx";
|
||||
export * from "./nav-secondary.tsx";
|
||||
export * from "./nav-user.tsx";
|
||||
export * from "./section-cards.tsx";
|
||||
export * from "./site-header.tsx";
|
||||
export * from "./app-layout.tsx";
|
||||
|
||||
17
packages/rdx-ui/src/components/scroll-to-top.tsx
Normal file
17
packages/rdx-ui/src/components/scroll-to-top.tsx
Normal file
@ -0,0 +1,17 @@
|
||||
import { useEffect } from "react";
|
||||
import { useLocation } from "react-router";
|
||||
|
||||
export function ScrollToTop() {
|
||||
const { pathname } = useLocation();
|
||||
|
||||
// biome-ignore lint/correctness/useExhaustiveDependencies: <explanation>
|
||||
useEffect(() => {
|
||||
window.scrollTo({
|
||||
top: 0,
|
||||
left: 0,
|
||||
behavior: "smooth",
|
||||
});
|
||||
}, [pathname]);
|
||||
|
||||
return null;
|
||||
}
|
||||
@ -170,7 +170,7 @@ importers:
|
||||
version: 29.7.0(@types/node@22.15.12)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.15.12)(typescript@5.8.3))
|
||||
ts-jest:
|
||||
specifier: ^29.2.5
|
||||
version: 29.3.2(@babel/core@7.27.1)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.27.1))(jest@29.7.0(@types/node@22.15.12)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.15.12)(typescript@5.8.3)))(typescript@5.8.3)
|
||||
version: 29.3.2(@babel/core@7.27.1)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.27.1))(esbuild@0.25.4)(jest@29.7.0(@types/node@22.15.12)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.15.12)(typescript@5.8.3)))(typescript@5.8.3)
|
||||
tsconfig-paths:
|
||||
specifier: ^4.2.0
|
||||
version: 4.2.0
|
||||
@ -507,6 +507,9 @@ importers:
|
||||
react-i18next:
|
||||
specifier: ^15.5.1
|
||||
version: 15.5.1(i18next@25.1.1(typescript@5.8.3))(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(typescript@5.8.3)
|
||||
react-router:
|
||||
specifier: ^6.26.0
|
||||
version: 6.30.0(react@19.1.0)
|
||||
react-router-dom:
|
||||
specifier: ^6.26.0
|
||||
version: 6.30.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
@ -11377,7 +11380,7 @@ snapshots:
|
||||
|
||||
ts-interface-checker@0.1.13: {}
|
||||
|
||||
ts-jest@29.3.2(@babel/core@7.27.1)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.27.1))(jest@29.7.0(@types/node@22.15.12)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.15.12)(typescript@5.8.3)))(typescript@5.8.3):
|
||||
ts-jest@29.3.2(@babel/core@7.27.1)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.27.1))(esbuild@0.25.4)(jest@29.7.0(@types/node@22.15.12)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.15.12)(typescript@5.8.3)))(typescript@5.8.3):
|
||||
dependencies:
|
||||
bs-logger: 0.2.6
|
||||
ejs: 3.1.10
|
||||
@ -11396,6 +11399,7 @@ snapshots:
|
||||
'@jest/transform': 29.7.0
|
||||
'@jest/types': 29.6.3
|
||||
babel-jest: 29.7.0(@babel/core@7.27.1)
|
||||
esbuild: 0.25.4
|
||||
|
||||
ts-node@10.9.2(@types/node@22.15.12)(typescript@5.8.3):
|
||||
dependencies:
|
||||
|
||||
Loading…
Reference in New Issue
Block a user