.
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 { Toaster, TooltipProvider } from "@repo/shadcn-ui/components";
|
||||||
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
||||||
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
|
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
|
||||||
import { Suspense } from "react";
|
|
||||||
import { I18nextProvider } from "react-i18next";
|
import { I18nextProvider } from "react-i18next";
|
||||||
|
|
||||||
import { createAxiosDataProvider } from "@/lib/axios/create-axios-data-provider";
|
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 { i18n } from "@/locales";
|
||||||
|
|
||||||
import "./App.css";
|
import { AppRoutes } from "./app-routes";
|
||||||
import { Routes } from "./routes";
|
import "./app.css";
|
||||||
|
|
||||||
function App() {
|
export const App = () => {
|
||||||
const queryClient = new QueryClient({
|
const queryClient = new QueryClient({
|
||||||
defaultOptions: {
|
defaultOptions: {
|
||||||
queries: {
|
queries: {
|
||||||
@ -26,22 +24,16 @@ function App() {
|
|||||||
<I18nextProvider i18n={i18n}>
|
<I18nextProvider i18n={i18n}>
|
||||||
<QueryClientProvider client={queryClient}>
|
<QueryClientProvider client={queryClient}>
|
||||||
<DataSourceProvider dataSource={createAxiosDataProvider(import.meta.env.VITE_API_URL)}>
|
<DataSourceProvider dataSource={createAxiosDataProvider(import.meta.env.VITE_API_URL)}>
|
||||||
<ThemeProvider defaultTheme='light' storageKey='vite-ui-theme'>
|
<TooltipProvider delayDuration={0}>
|
||||||
<TooltipProvider delayDuration={0}>
|
<UnsavedWarnProvider>
|
||||||
<UnsavedWarnProvider>
|
<AppRoutes />
|
||||||
<Suspense fallback={<LoadingOverlay />}>
|
</UnsavedWarnProvider>
|
||||||
<Routes />
|
</TooltipProvider>
|
||||||
</Suspense>
|
<Toaster />
|
||||||
</UnsavedWarnProvider>
|
|
||||||
</TooltipProvider>
|
{import.meta.env.MODE === "development" && <ReactQueryDevtools initialIsOpen={false} />}
|
||||||
<Toaster />
|
|
||||||
<TailwindIndicator />
|
|
||||||
{import.meta.env.MODE === "development" && <ReactQueryDevtools initialIsOpen={false} />}
|
|
||||||
</ThemeProvider>
|
|
||||||
</DataSourceProvider>
|
</DataSourceProvider>
|
||||||
</QueryClientProvider>
|
</QueryClientProvider>
|
||||||
</I18nextProvider>
|
</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 { StrictMode } from "react";
|
||||||
import { createRoot } from "react-dom/client";
|
import { createRoot } from "react-dom/client";
|
||||||
import App from "./App.tsx";
|
import { App } from "./app.tsx";
|
||||||
|
|
||||||
import "./global.css";
|
import "./global.css";
|
||||||
|
|
||||||
@ -8,7 +10,10 @@ const rootElement = document.getElementById("factuges");
|
|||||||
if (rootElement) {
|
if (rootElement) {
|
||||||
createRoot(rootElement).render(
|
createRoot(rootElement).render(
|
||||||
<StrictMode>
|
<StrictMode>
|
||||||
<App />
|
<ThemeProvider defaultTheme='light' storageKey='vite-ui-theme'>
|
||||||
|
<App />
|
||||||
|
<TailwindIndicator />
|
||||||
|
</ThemeProvider>
|
||||||
</StrictMode>
|
</StrictMode>
|
||||||
);
|
);
|
||||||
} else {
|
} 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 React, { JSX, ReactNode } from "react";
|
||||||
import { RouteObject } from "react-router-dom";
|
|
||||||
import { ModuleMetadata } from "./types";
|
import { ModuleMetadata } from "./types";
|
||||||
|
|
||||||
export interface ModuleClientMetadata extends ModuleMetadata {
|
export interface ModuleClientMetadata extends ModuleMetadata {
|
||||||
@ -9,7 +8,7 @@ export interface ModuleClientMetadata extends ModuleMetadata {
|
|||||||
|
|
||||||
export interface IModuleClient {
|
export interface IModuleClient {
|
||||||
metadata: ModuleClientMetadata;
|
metadata: ModuleClientMetadata;
|
||||||
routes?: () => RouteObject[];
|
routes?: () => JSX.Element;
|
||||||
component?: React.FC;
|
component?: React.FC;
|
||||||
setup?(): void;
|
setup?(): void;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,7 +18,8 @@
|
|||||||
"ag-grid-community": "^33.3.0",
|
"ag-grid-community": "^33.3.0",
|
||||||
"i18next": "^25.1.1",
|
"i18next": "^25.1.1",
|
||||||
"react": "^18 || ^19",
|
"react": "^18 || ^19",
|
||||||
"react-dom": "^18 || ^19"
|
"react-dom": "^18 || ^19",
|
||||||
|
"react-router-dom": "^6.26.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@biomejs/biome": "1.9.4",
|
"@biomejs/biome": "1.9.4",
|
||||||
|
|||||||
@ -57,8 +57,9 @@ export const InvoicesGrid = () => {
|
|||||||
{
|
{
|
||||||
field: "mission",
|
field: "mission",
|
||||||
filter: true,
|
filter: true,
|
||||||
|
minWidth: 200,
|
||||||
},
|
},
|
||||||
{ field: "company" },
|
{ field: "company", filter: false },
|
||||||
{ field: "location" },
|
{ field: "location" },
|
||||||
{ field: "date" },
|
{ field: "date" },
|
||||||
{
|
{
|
||||||
@ -75,12 +76,17 @@ export const InvoicesGrid = () => {
|
|||||||
const defaultColDef = useMemo<ColDef>(() => {
|
const defaultColDef = useMemo<ColDef>(() => {
|
||||||
return {
|
return {
|
||||||
filter: true,
|
filter: true,
|
||||||
|
sortable: false,
|
||||||
|
resizable: false,
|
||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// Container: Defines the grid's theme & dimensions.
|
// Container: Defines the grid's theme & dimensions.
|
||||||
return (
|
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
|
<AgGridReact
|
||||||
rowData={data}
|
rowData={data}
|
||||||
loading={loading}
|
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 { PropsWithChildren } from "react";
|
||||||
|
|
||||||
import { SectionCards } from "@repo/rdx-ui/components/layout/section-cards";
|
import { SectionCards } from "@repo/rdx-ui/components/layout/section-cards";
|
||||||
@ -11,29 +7,9 @@ export const InvoicesLayout = ({ children }: PropsWithChildren) => {
|
|||||||
const { t } = useTranslation("invoices");
|
const { t } = useTranslation("invoices");
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SidebarProvider
|
<>
|
||||||
style={
|
<SectionCards />
|
||||||
{
|
{children}
|
||||||
"--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>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,8 +1,6 @@
|
|||||||
//import { ProtectedRoute } from "@erp/auth/components";
|
//import { ProtectedRoute } from "@erp/auth/components";
|
||||||
import { LoadingOverlay } from "@repo/rdx-ui/components";
|
import { JSX, lazy } from "react";
|
||||||
import { Suspense, lazy } from "react";
|
import { Route } from "react-router-dom";
|
||||||
import { Outlet, RouteObject } from "react-router-dom";
|
|
||||||
import { InvoicesGrid } from "./components";
|
|
||||||
|
|
||||||
// Lazy load components
|
// Lazy load components
|
||||||
const InvoicesLayout = lazy(() =>
|
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 InvoicesLayout = lazy(() => import("./app").then((m) => ({ default: m.InvoicesLayout })));
|
||||||
const InvoicesList = lazy(() => import("./app").then((m) => ({ default: m.InvoicesList })));*/
|
const InvoicesList = lazy(() => import("./app").then((m) => ({ default: m.InvoicesList })));*/
|
||||||
|
|
||||||
export const InvoiceRoutes = (): RouteObject[] => {
|
export const InvoiceRoutes = (): JSX.Element => {
|
||||||
// Define routes accessible only to authenticated users
|
return (
|
||||||
const privateRoutes: RouteObject[] = [
|
<Route path='/invoices' element={<InvoicesLayout />}>
|
||||||
{
|
<Route index element={<InvoicesList />} />
|
||||||
path: "/invoices",
|
<Route path='list' element={<InvoicesList />} />
|
||||||
element: (
|
|
||||||
<Suspense fallback={<LoadingOverlay />}>
|
|
||||||
<InvoicesLayout>
|
|
||||||
<Outlet />
|
|
||||||
</InvoicesLayout>
|
|
||||||
</Suspense>
|
|
||||||
),
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
index: true,
|
|
||||||
element: <InvoicesGrid />,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
// Define routes accessible only to non-authenticated users
|
{/*<Route path='create' element={<InvoiceCreate />} />
|
||||||
const publicRoutes = [{}];
|
<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;
|
<Route path='*' element={<InvoicesList />} />
|
||||||
|
</Route>
|
||||||
// Provide the router configuration using RouterProvider
|
);
|
||||||
//return <RouterProvider router={router} />;
|
|
||||||
};
|
};
|
||||||
@ -2,7 +2,7 @@ import { IModuleClient } from "@erp/core";
|
|||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
import enResources from "../common/locales/en.json";
|
import enResources from "../common/locales/en.json";
|
||||||
import esResources from "../common/locales/es.json";
|
import esResources from "../common/locales/es.json";
|
||||||
import { InvoiceRoutes } from "./routes";
|
import { InvoiceRoutes } from "./invoice-routes";
|
||||||
|
|
||||||
const MODULE_NAME = "invoices";
|
const MODULE_NAME = "invoices";
|
||||||
const MODULE_VERSION = "1.0.0";
|
const MODULE_VERSION = "1.0.0";
|
||||||
|
|||||||
@ -16,7 +16,8 @@
|
|||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"react": "^18 || ^19",
|
"react": "^18 || ^19",
|
||||||
"react-dom": "^18 || ^19"
|
"react-dom": "^18 || ^19",
|
||||||
|
"react-router": "^6.26.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@biomejs/biome": "1.9.4",
|
"@biomejs/biome": "1.9.4",
|
||||||
@ -49,6 +50,7 @@
|
|||||||
"react-dom": "^19.1.0",
|
"react-dom": "^19.1.0",
|
||||||
"react-i18next": "^15.5.1",
|
"react-i18next": "^15.5.1",
|
||||||
"react-router-dom": "^6.26.0",
|
"react-router-dom": "^6.26.0",
|
||||||
|
"react-router": "^6.26.0",
|
||||||
"recharts": "^2.15.3",
|
"recharts": "^2.15.3",
|
||||||
"sonner": "^2.0.3",
|
"sonner": "^2.0.3",
|
||||||
"zod": "^3.24.4"
|
"zod": "^3.24.4"
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
export * from "./tailwind-indicator.tsx";
|
export * from "./buttons/index.tsx";
|
||||||
export * from "./loading-overlay/index.tsx";
|
|
||||||
export * from "./custom-dialog.tsx";
|
export * from "./custom-dialog.tsx";
|
||||||
export * from "./error-overlay.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 "./app-layout.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";
|
|
||||||
|
|||||||
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))
|
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:
|
ts-jest:
|
||||||
specifier: ^29.2.5
|
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:
|
tsconfig-paths:
|
||||||
specifier: ^4.2.0
|
specifier: ^4.2.0
|
||||||
version: 4.2.0
|
version: 4.2.0
|
||||||
@ -507,6 +507,9 @@ importers:
|
|||||||
react-i18next:
|
react-i18next:
|
||||||
specifier: ^15.5.1
|
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)
|
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:
|
react-router-dom:
|
||||||
specifier: ^6.26.0
|
specifier: ^6.26.0
|
||||||
version: 6.30.0(react-dom@19.1.0(react@19.1.0))(react@19.1.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-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:
|
dependencies:
|
||||||
bs-logger: 0.2.6
|
bs-logger: 0.2.6
|
||||||
ejs: 3.1.10
|
ejs: 3.1.10
|
||||||
@ -11396,6 +11399,7 @@ snapshots:
|
|||||||
'@jest/transform': 29.7.0
|
'@jest/transform': 29.7.0
|
||||||
'@jest/types': 29.6.3
|
'@jest/types': 29.6.3
|
||||||
babel-jest: 29.7.0(@babel/core@7.27.1)
|
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):
|
ts-node@10.9.2(@types/node@22.15.12)(typescript@5.8.3):
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user