Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion web/apps/admin/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
import { Flex } from "@raystack/apsara";
import { Suspense } from "react";
import { Outlet } from "react-router-dom";
import "@raystack/apsara/normalize.css";
import "@raystack/apsara/style.css";
import "./App.css";
import IAMSidebar from "./components/Sidebar";
import LoadingState from "./components/states/Loading";

function App() {
return (
<div style={{ display: "flex", height: "100vh", overflow: "hidden" }}>
<IAMSidebar />
<Flex style={{ flexGrow: "1", overflow: "auto" }}>
<Outlet />
{/* Boundary for the lazily-loaded route pages. Sits inside the layout
so the sidebar stays mounted while a route chunk loads. */}
<Suspense fallback={<LoadingState />}>
<Outlet />
</Suspense>
</Flex>
</div>
);
Expand Down
2 changes: 1 addition & 1 deletion web/apps/admin/src/pages/admins/AdminsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { AdminsView, useAdminPaths } from "@raystack/frontier/admin";
import { useNavigate } from "react-router-dom";
import AdminsIcon from "~/assets/icons/admins.svg?react";

export function AdminsPage() {
export default function AdminsPage() {
const navigate = useNavigate();
const paths = useAdminPaths();

Expand Down
2 changes: 1 addition & 1 deletion web/apps/admin/src/pages/audit-logs/AuditLogsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import type { RQLExportRequest, RQLRequest } from "@raystack/proton/frontier";

const adminClient = clients.admin({ useBinary: true });

export function AuditLogsPage() {
export default function AuditLogsPage() {
const navigate = useNavigate();
const onExportCsv = useCallback(async (query: RQLRequest) => {
await exportCsvFromStream(
Expand Down
2 changes: 1 addition & 1 deletion web/apps/admin/src/pages/invoices/InvoicesPage.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { InvoicesView } from "@raystack/frontier/admin";

export function InvoicesPage() {
export default function InvoicesPage() {
return <InvoicesView />;
}
2 changes: 1 addition & 1 deletion web/apps/admin/src/pages/organizations/details/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ async function loadCountries(): Promise<string[]> {
return (data.default as { name: string }[]).map((c) => c.name);
}

export function OrganizationDetailsPage() {
export default function OrganizationDetailsPage() {
const { organizationId } = useParams<{ organizationId: string }>();
const location = useLocation();
const navigate = useNavigate();
Expand Down
2 changes: 1 addition & 1 deletion web/apps/admin/src/pages/organizations/list/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ async function loadCountries(): Promise<string[]> {
return (data.default as { name: string }[]).map((c) => c.name);
}

export function OrganizationListPage() {
export default function OrganizationListPage() {
const navigate = useNavigate();
const { config } = useContext(AppContext);
const paths = useAdminPaths();
Expand Down
2 changes: 1 addition & 1 deletion web/apps/admin/src/pages/plans/PlansPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { PlansView } from "@raystack/frontier/admin";
import { useNavigate, useParams } from "react-router-dom";
import PlansIcon from "~/assets/icons/plans.svg?react";

export function PlansPage() {
export default function PlansPage() {
const { planId } = useParams();
const navigate = useNavigate();

Expand Down
2 changes: 1 addition & 1 deletion web/apps/admin/src/pages/preferences/PreferencesPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { useParams, useNavigate } from "react-router-dom";
import { PreferencesView } from "@raystack/frontier/admin";
import PreferencesIcon from "~/assets/icons/preferences.svg?react";

export function PreferencesPage() {
export default function PreferencesPage() {
const { name } = useParams();
const navigate = useNavigate();

Expand Down
2 changes: 1 addition & 1 deletion web/apps/admin/src/pages/products/ProductPricesPage.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ProductPricesView } from "@raystack/frontier/admin";
import { useParams, useNavigate } from "react-router-dom";

export function ProductPricesPage() {
export default function ProductPricesPage() {
const { productId } = useParams();
const navigate = useNavigate();

Expand Down
2 changes: 1 addition & 1 deletion web/apps/admin/src/pages/products/ProductsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { ProductsView } from "@raystack/frontier/admin";
import { useParams, useNavigate } from "react-router-dom";
import ProductsIcon from "~/assets/icons/products.svg?react";

export function ProductsPage() {
export default function ProductsPage() {
const { productId } = useParams();
const navigate = useNavigate();

Expand Down
2 changes: 1 addition & 1 deletion web/apps/admin/src/pages/roles/RolesPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { RolesView } from "@raystack/frontier/admin";
import { useParams, useNavigate } from "react-router-dom";
import RolesIcon from "~/assets/icons/roles.svg?react";

export function RolesPage() {
export default function RolesPage() {
const { roleId } = useParams();
const navigate = useNavigate();

Expand Down
2 changes: 1 addition & 1 deletion web/apps/admin/src/pages/users/UsersPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { exportCsvFromStream } from "~/utils/helper";

const adminClient = clients.admin({ useBinary: true });

export function UsersPage() {
export default function UsersPage() {
const { userId } = useParams();
const navigate = useNavigate();
const location = useLocation();
Expand Down
2 changes: 1 addition & 1 deletion web/apps/admin/src/pages/webhooks/WebhooksPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { WebhooksView } from "@raystack/frontier/admin";
import { AppContext } from "~/contexts/App";
import WebhooksIcon from "~/assets/icons/webhooks.svg?react";

export function WebhooksPage() {
export default function WebhooksPage() {
const { config } = useContext(AppContext);
const { webhookId } = useParams();
const navigate = useNavigate();
Expand Down
45 changes: 26 additions & 19 deletions web/apps/admin/src/routes.tsx
Original file line number Diff line number Diff line change
@@ -1,43 +1,50 @@
import * as R from "ramda";
import { memo, useContext } from "react";
import { lazy, memo, useContext } from "react";
import { Navigate, Route, Routes } from "react-router-dom";

import LoadingState from "./components/states/Loading";
import UnauthorizedState from "./components/states/Unauthorized";

// Eager: the app shell and the unauthenticated flow. Keeping these in the
// initial bundle means the login screen paints instantly.
import App from "./App";
import { PlansPage } from "./pages/plans/PlansPage";
import Login from "./containers/login";
import MagicLink from "./containers/magiclink";

import { PreferencesPage } from "./pages/preferences/PreferencesPage";
import { ProductsPage } from "./pages/products/ProductsPage";
import { ProductPricesPage } from "./pages/products/ProductPricesPage";

import { RolesPage } from "./pages/roles/RolesPage";

import { AppContext } from "./contexts/App";
import { AdminsPage } from "./pages/admins/AdminsPage";
import { WebhooksPage } from "./pages/webhooks/WebhooksPage";
import AuthLayout from "./layout/auth";

import { OrganizationListPage } from "./pages/organizations/list";
import { OrganizationDetailsPage } from "./pages/organizations/details";
import { AppContext } from "./contexts/App";
// Static imports from the SDK barrel. `useAdminPaths` is a hook used during
// render. The organization-detail child views are imported eagerly too: they
// come from the `@raystack/frontier/admin` barrel, which is already pinned into
// the initial chunk (the app shell imports from it), so wrapping them in
// React.lazy produced no separate chunk — only Suspense churn. Lazy loading is
// kept on the app-owned page files below, which DO split into their own chunks.
import {
useAdminPaths,
OrganizationSecurity,
OrganizationMembersView,
OrganizationProjectsView,
OrganizationInvoicesView,
OrganizationTokensView,
OrganizationApisView,
OrganizationPatView,
useAdminPaths,
} from "@raystack/frontier/admin";

import { UsersPage } from "./pages/users/UsersPage";

import { InvoicesPage } from "./pages/invoices/InvoicesPage";
import { AuditLogsPage } from "./pages/audit-logs/AuditLogsPage";
// Lazily-loaded route pages — each becomes its own async chunk, so the heavy
// admin code stays out of the initial/unauthenticated bundle. The pages are
// default exports, so React.lazy imports them directly (per the React docs).
const PlansPage = lazy(() => import("./pages/plans/PlansPage"));
const PreferencesPage = lazy(() => import("./pages/preferences/PreferencesPage"));
const ProductsPage = lazy(() => import("./pages/products/ProductsPage"));
const ProductPricesPage = lazy(() => import("./pages/products/ProductPricesPage"));
const RolesPage = lazy(() => import("./pages/roles/RolesPage"));
const AdminsPage = lazy(() => import("./pages/admins/AdminsPage"));
const WebhooksPage = lazy(() => import("./pages/webhooks/WebhooksPage"));
const OrganizationListPage = lazy(() => import("./pages/organizations/list"));
const OrganizationDetailsPage = lazy(() => import("./pages/organizations/details"));
const UsersPage = lazy(() => import("./pages/users/UsersPage"));
const InvoicesPage = lazy(() => import("./pages/invoices/InvoicesPage"));
const AuditLogsPage = lazy(() => import("./pages/audit-logs/AuditLogsPage"));

export default memo(function AppRoutes() {
const { isAdmin, isLoading, user } = useContext(AppContext);
Expand Down
Loading