diff --git a/web/apps/admin/src/pages/admins/AdminsPage.tsx b/web/apps/admin/src/pages/admins/AdminsPage.tsx
index 8dfa7fb29..8bc110cec 100644
--- a/web/apps/admin/src/pages/admins/AdminsPage.tsx
+++ b/web/apps/admin/src/pages/admins/AdminsPage.tsx
@@ -1,5 +1,12 @@
import { AdminsView } from "@raystack/frontier/admin";
+import { useNavigate } from "react-router-dom";
export function AdminsPage() {
- return ;
+ const navigate = useNavigate();
+
+ return (
+ navigate(`/organizations/${orgId}`)}
+ />
+ );
}
diff --git a/web/apps/admin/src/pages/plans/PlansPage.tsx b/web/apps/admin/src/pages/plans/PlansPage.tsx
index 9097921d0..a79d074f5 100644
--- a/web/apps/admin/src/pages/plans/PlansPage.tsx
+++ b/web/apps/admin/src/pages/plans/PlansPage.tsx
@@ -9,6 +9,7 @@ export function PlansPage() {
navigate("/plans")}
+ onSelectPlan={(id: string) => navigate(`/plans/${id}`)}
/>
);
}
diff --git a/web/apps/admin/src/pages/preferences/PreferencesPage.tsx b/web/apps/admin/src/pages/preferences/PreferencesPage.tsx
index a6771afa1..49f040800 100644
--- a/web/apps/admin/src/pages/preferences/PreferencesPage.tsx
+++ b/web/apps/admin/src/pages/preferences/PreferencesPage.tsx
@@ -9,6 +9,7 @@ export function PreferencesPage() {
navigate("/preferences")}
+ onSelectPreference={(prefName: string) => navigate(`/preferences/${prefName}`)}
/>
);
}
diff --git a/web/apps/admin/src/pages/users/UsersPage.tsx b/web/apps/admin/src/pages/users/UsersPage.tsx
index 3561b8f6e..31fc92f4d 100644
--- a/web/apps/admin/src/pages/users/UsersPage.tsx
+++ b/web/apps/admin/src/pages/users/UsersPage.tsx
@@ -1,6 +1,6 @@
import { UsersView } from "@raystack/frontier/admin";
import { useCallback } from "react";
-import { useParams, useNavigate } from "react-router-dom";
+import { useParams, useNavigate, useLocation } from "react-router-dom";
import { clients } from "~/connect/clients";
import { exportCsvFromStream } from "~/utils/helper";
@@ -9,6 +9,7 @@ const adminClient = clients.admin({ useBinary: true });
export function UsersPage() {
const { userId } = useParams();
const navigate = useNavigate();
+ const location = useLocation();
const onExportUsers = useCallback(async () => {
await exportCsvFromStream(adminClient.exportUsers, {}, "users.csv");
@@ -27,6 +28,8 @@ export function UsersPage() {
onCloseDetail={() => navigate("/users")}
onExportUsers={onExportUsers}
onNavigateToUser={onNavigateToUser}
+ currentPath={location.pathname}
+ onNavigate={navigate}
/>
);
}
diff --git a/web/pnpm-lock.yaml b/web/pnpm-lock.yaml
index 2167447df..d4ab66f8e 100644
--- a/web/pnpm-lock.yaml
+++ b/web/pnpm-lock.yaml
@@ -263,9 +263,6 @@ importers:
react-image-crop:
specifier: ^10.1.8
version: 10.1.8(react@18.3.1)
- react-router-dom:
- specifier: '>=6.0.0'
- version: 7.13.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
slugify:
specifier: ^1.6.6
version: 1.6.6
diff --git a/web/sdk/admin/views/admins/columns.tsx b/web/sdk/admin/views/admins/columns.tsx
index d45a9019c..400b881ac 100644
--- a/web/sdk/admin/views/admins/columns.tsx
+++ b/web/sdk/admin/views/admins/columns.tsx
@@ -1,11 +1,12 @@
-import type { DataTableColumnDef } from "@raystack/apsara";
+import { Text, type DataTableColumnDef } from "@raystack/apsara";
import type { ServiceUser, User } from "@raystack/proton/frontier";
-import { Link } from "react-router-dom";
-export const getColumns: () => DataTableColumnDef<
+export const getColumns: (options?: {
+ onNavigateToOrg?: (orgId: string) => void;
+}) => DataTableColumnDef<
User | ServiceUser,
unknown
->[] = () => {
+>[] = ({ onNavigateToOrg } = {}) => {
return [
{
header: "Title",
@@ -40,7 +41,12 @@ export const getColumns: () => DataTableColumnDef<
cell: (info) => {
const org_id = info.getValue() as string;
return org_id ? (
- {org_id}
+ onNavigateToOrg?.(org_id)}
+ >
+ {org_id}
+
) : (
"-"
);
diff --git a/web/sdk/admin/views/admins/index.tsx b/web/sdk/admin/views/admins/index.tsx
index c52582aab..c334e61db 100644
--- a/web/sdk/admin/views/admins/index.tsx
+++ b/web/sdk/admin/views/admins/index.tsx
@@ -21,7 +21,11 @@ const NoAdmins = () => {
);
};
-export default function AdminsView() {
+export type AdminsViewProps = {
+ onNavigateToOrg?: (orgId: string) => void;
+};
+
+export default function AdminsView({ onNavigateToOrg }: AdminsViewProps = {}) {
const {
data: platformUsersData,
isLoading,
@@ -31,7 +35,7 @@ export default function AdminsView() {
staleTime: Infinity,
});
- const columns = getColumns();
+ const columns = getColumns({ onNavigateToOrg });
const data = [
...(platformUsersData?.users || []),
...(platformUsersData?.serviceusers || []),
diff --git a/web/sdk/admin/views/plans/columns.tsx b/web/sdk/admin/views/plans/columns.tsx
index 85e6c440e..e2da52e07 100644
--- a/web/sdk/admin/views/plans/columns.tsx
+++ b/web/sdk/admin/views/plans/columns.tsx
@@ -1,20 +1,29 @@
-import { Link } from "react-router-dom";
-import { type DataTableColumnDef } from "@raystack/apsara";
+import { Text, type DataTableColumnDef } from "@raystack/apsara";
import type { Plan } from "@raystack/proton/frontier";
import { timestampToDate, type TimeStamp } from "../../utils/connect-timestamp";
-export const getColumns: () => DataTableColumnDef<
+export const getColumns: (options?: {
+ onSelectPlan?: (planId: string) => void;
+}) => DataTableColumnDef<
Plan,
unknown
->[] = () => {
+>[] = ({ onSelectPlan } = {}) => {
return [
{
header: "ID",
accessorKey: "id",
filterVariant: "text",
- cell: ({ row, getValue }) => (
- {getValue() as string}
- ),
+ cell: ({ getValue }) => {
+ const id = getValue() as string;
+ return (
+ onSelectPlan?.(id)}
+ >
+ {id}
+
+ );
+ },
},
{
header: "Title",
diff --git a/web/sdk/admin/views/plans/index.tsx b/web/sdk/admin/views/plans/index.tsx
index 0e1dfc3c6..a2f5fba43 100644
--- a/web/sdk/admin/views/plans/index.tsx
+++ b/web/sdk/admin/views/plans/index.tsx
@@ -19,12 +19,14 @@ const pageHeader = {
export type PlansViewProps = {
selectedPlanId?: string;
onCloseDetail?: () => void;
+ onSelectPlan?: (planId: string) => void;
appName?: string;
};
export default function PlansView({
selectedPlanId,
onCloseDetail,
+ onSelectPlan,
appName,
}: PlansViewProps = {}) {
const {
@@ -38,7 +40,7 @@ export default function PlansView({
const plans = plansResponse?.plans || [];
const planMapById = reduceByKey(plans ?? [], "id");
- const columns = getColumns();
+ const columns = getColumns({ onSelectPlan });
if (isError) {
console.error("ConnectRPC Error:", error);
diff --git a/web/sdk/admin/views/preferences/PreferencesView.tsx b/web/sdk/admin/views/preferences/PreferencesView.tsx
index eb12c2757..1b5c75595 100644
--- a/web/sdk/admin/views/preferences/PreferencesView.tsx
+++ b/web/sdk/admin/views/preferences/PreferencesView.tsx
@@ -17,11 +17,13 @@ import PreferenceDetails from "./details";
export type PreferencesViewProps = {
selectedPreferenceName?: string;
onCloseDetail?: () => void;
+ onSelectPreference?: (name: string) => void;
};
export default function PreferencesView({
selectedPreferenceName,
onCloseDetail,
+ onSelectPreference,
}: PreferencesViewProps = {}) {
const transport = useTransport();
@@ -80,6 +82,7 @@ export default function PreferencesView({
preferences={preferences}
traits={traits}
isLoading={isLoading}
+ onSelectPreference={onSelectPreference}
/>
);
diff --git a/web/sdk/admin/views/preferences/columns.tsx b/web/sdk/admin/views/preferences/columns.tsx
index d3c17a992..45aa588e0 100644
--- a/web/sdk/admin/views/preferences/columns.tsx
+++ b/web/sdk/admin/views/preferences/columns.tsx
@@ -1,11 +1,11 @@
-import type { DataTableColumnDef } from "@raystack/apsara";
+import { Text, type DataTableColumnDef } from "@raystack/apsara";
import { Preference, PreferenceTrait } from "@raystack/proton/frontier";
-import { Link } from "react-router-dom";
import styles from "./preferences.module.css";
interface getColumnsOptions {
traits: PreferenceTrait[];
preferences: Preference[];
+ onSelectPreference?: (name: string) => void;
}
export const getColumns: (
@@ -13,6 +13,7 @@ export const getColumns: (
) => DataTableColumnDef[] = ({
traits,
preferences,
+ onSelectPreference,
}) => {
return [
{
@@ -25,7 +26,19 @@ export const getColumns: (
{
header: "Action",
accessorKey: "name",
- cell: (info) => Edit,
+ cell: (info) => {
+ const name = info.getValue() as string;
+ return (
+ onSelectPreference?.(name)}
+ >
+ Edit
+
+ );
+ },
footer: (props) => props.column.id,
},
{
diff --git a/web/sdk/admin/views/preferences/index.tsx b/web/sdk/admin/views/preferences/index.tsx
index e1a169eee..28787af11 100644
--- a/web/sdk/admin/views/preferences/index.tsx
+++ b/web/sdk/admin/views/preferences/index.tsx
@@ -14,16 +14,19 @@ export type PreferencesListProps = {
preferences: Preference[];
traits: PreferenceTrait[];
isLoading: boolean;
+ onSelectPreference?: (name: string) => void;
};
export default function PreferencesList({
preferences,
traits,
isLoading,
+ onSelectPreference,
}: PreferencesListProps) {
const columns = getColumns({
traits,
preferences,
+ onSelectPreference,
});
return (
diff --git a/web/sdk/admin/views/users/UsersView.tsx b/web/sdk/admin/views/users/UsersView.tsx
index 2c016e22d..87b27f42a 100644
--- a/web/sdk/admin/views/users/UsersView.tsx
+++ b/web/sdk/admin/views/users/UsersView.tsx
@@ -6,6 +6,8 @@ export type UsersViewProps = {
onCloseDetail?: () => void;
onExportUsers?: () => Promise;
onNavigateToUser?: (userId: string) => void;
+ currentPath?: string;
+ onNavigate?: (path: string) => void;
};
export default function UsersView({
@@ -13,9 +15,11 @@ export default function UsersView({
onCloseDetail,
onExportUsers,
onNavigateToUser,
+ currentPath,
+ onNavigate,
}: UsersViewProps = {}) {
if (selectedUserId) {
- return ;
+ return ;
}
return (
diff --git a/web/sdk/admin/views/users/details/layout/layout.tsx b/web/sdk/admin/views/users/details/layout/layout.tsx
index 06629e08c..57a955a3c 100644
--- a/web/sdk/admin/views/users/details/layout/layout.tsx
+++ b/web/sdk/admin/views/users/details/layout/layout.tsx
@@ -6,9 +6,11 @@ import { UserDetailsNavbar } from "./navbar";
interface UserDetailsLayoutProps {
children: ReactNode;
+ currentPath?: string;
+ onNavigate?: (path: string) => void;
}
-export const UserDetailsLayout = ({ children }: UserDetailsLayoutProps) => {
+export const UserDetailsLayout = ({ children, currentPath, onNavigate }: UserDetailsLayoutProps) => {
const [showSidePanel, setShowSidePanel] = useState(true);
function toggleSidePanel() {
@@ -17,7 +19,7 @@ export const UserDetailsLayout = ({ children }: UserDetailsLayoutProps) => {
return (
-
+
void;
+ currentPath?: string;
+ onNavigate?: (path: string) => void;
}
export const UserDetailsNavbar = ({
toggleSidePanel,
+ currentPath = "",
+ onNavigate,
}: UserDetailsNavbarProps) => {
const { user } = useUser();
@@ -50,18 +53,19 @@ export const UserDetailsNavbar = ({
- {links.map((link, index) => (
-
- {({ isActive }) => (
-
- {link.name}
-
- )}
-
- ))}
+ {links.map((link, index) => {
+ const isActive = currentPath.startsWith(link.path);
+ return (
+ onNavigate?.(link.path)}>
+ {link.name}
+
+ );
+ })}
diff --git a/web/sdk/admin/views/users/details/user-details.tsx b/web/sdk/admin/views/users/details/user-details.tsx
index 8dfb03afc..f3b8deee5 100644
--- a/web/sdk/admin/views/users/details/user-details.tsx
+++ b/web/sdk/admin/views/users/details/user-details.tsx
@@ -11,12 +11,14 @@ import { UserDetailsSecurityContent } from "./security/security";
interface UserDetailContentProps {
user: User;
refetch: () => void;
+ currentPath?: string;
+ onNavigate?: (path: string) => void;
}
-export const UserDetailContent = ({ user, refetch }: UserDetailContentProps) => {
+export const UserDetailContent = ({ user, refetch, currentPath, onNavigate }: UserDetailContentProps) => {
return (
-
+
@@ -25,9 +27,11 @@ export const UserDetailContent = ({ user, refetch }: UserDetailContentProps) =>
interface UserDetailsByUserIdProps {
userId: string;
+ currentPath?: string;
+ onNavigate?: (path: string) => void;
}
-export const UserDetailsByUserId = ({ userId }: UserDetailsByUserIdProps) => {
+export const UserDetailsByUserId = ({ userId, currentPath, onNavigate }: UserDetailsByUserIdProps) => {
const { data, isLoading, refetch } = useQuery(
AdminServiceQueries.searchUsers,
{ query: { search: userId } },
@@ -66,5 +70,5 @@ export const UserDetailsByUserId = ({ userId }: UserDetailsByUserIdProps) => {
);
}
- return ;
+ return ;
};
diff --git a/web/sdk/admin/views/users/list/columns.tsx b/web/sdk/admin/views/users/list/columns.tsx
index 122ea7abb..0083dc7d7 100644
--- a/web/sdk/admin/views/users/list/columns.tsx
+++ b/web/sdk/admin/views/users/list/columns.tsx
@@ -6,7 +6,6 @@ import {
getAvatarColor,
Text,
} from "@raystack/apsara";
-import { Link } from "react-router-dom";
import dayjs from "dayjs";
import styles from "./list.module.css";
import { getUserName, USER_STATES, UserState } from "../util";
@@ -19,10 +18,12 @@ import {
interface getColumnsOptions {
groupCountMap: Record>;
+ onNavigateToUser?: (userId: string) => void;
}
export const getColumns = ({
groupCountMap,
+ onNavigateToUser,
}: getColumnsOptions): DataTableColumnDef[] => {
return [
{
@@ -37,16 +38,19 @@ export const getColumns = ({
const name = getUserName(row.original);
const userId = row.original.id;
return (
-
-
-
- {name}
-
-
+ userId && onNavigateToUser?.(userId)}
+ >
+
+ {name}
+
);
},
enableColumnFilter: true,
diff --git a/web/sdk/admin/views/users/list/list.tsx b/web/sdk/admin/views/users/list/list.tsx
index 96ce9516c..8537b6256 100644
--- a/web/sdk/admin/views/users/list/list.tsx
+++ b/web/sdk/admin/views/users/list/list.tsx
@@ -98,7 +98,7 @@ export const UsersList = ({ onExportUsers, onNavigateToUser }: UsersListProps) =
}
};
- const columns = getColumns({ groupCountMap });
+ const columns = getColumns({ groupCountMap, onNavigateToUser });
const loading = isLoading || isFetchingNextPage;
diff --git a/web/sdk/admin/views/webhooks/webhooks/create/index.tsx b/web/sdk/admin/views/webhooks/webhooks/create/index.tsx
index 7bbe49df2..3db2e6813 100644
--- a/web/sdk/admin/views/webhooks/webhooks/create/index.tsx
+++ b/web/sdk/admin/views/webhooks/webhooks/create/index.tsx
@@ -1,6 +1,5 @@
import { useCallback } from "react";
import { Button, Flex, Sheet } from "@raystack/apsara";
-import { useNavigate } from "react-router-dom";
import { SheetHeader } from "../../../../components/SheetHeader";
import { SheetFooter } from "../../../../components/SheetFooter";
import * as z from "zod";
@@ -36,13 +35,11 @@ export type CreateWebhooksProps = {
};
export default function CreateWebhooks({ onClose: onCloseProp }: CreateWebhooksProps = {}) {
- const navigate = useNavigate();
const { invalidateWebhooksList } = useWebhookQueries();
const onOpenChange = useCallback(() => {
- if (onCloseProp) onCloseProp();
- else navigate("/webhooks");
- }, [navigate, onCloseProp]);
+ onCloseProp?.();
+ }, [onCloseProp]);
const { mutateAsync: createWebhook, isPending: isSubmitting } = useMutation(
AdminServiceQueries.createWebhook,
diff --git a/web/sdk/admin/views/webhooks/webhooks/header.tsx b/web/sdk/admin/views/webhooks/webhooks/header.tsx
index e58bb0556..baeeedfda 100644
--- a/web/sdk/admin/views/webhooks/webhooks/header.tsx
+++ b/web/sdk/admin/views/webhooks/webhooks/header.tsx
@@ -1,7 +1,6 @@
import { PlusIcon } from "@radix-ui/react-icons";
import { Button, Flex, DataTable } from "@raystack/apsara";
-import { useNavigate } from "react-router-dom";
import { PageHeader } from "../../../components/PageHeader";
import styles from "./webhooks.module.css";
@@ -16,8 +15,7 @@ export type WebhooksHeaderProps = {
};
export const WebhooksHeader = ({ header = pageHeader, onOpenCreate }: WebhooksHeaderProps) => {
- const navigate = useNavigate();
- const handleCreate = () => (onOpenCreate ? onOpenCreate() : navigate("/webhooks/create"));
+ const handleCreate = () => onOpenCreate?.();
return (
{
- if (onCloseProp) onCloseProp();
- else navigate("/webhooks");
- }, [navigate, onCloseProp]);
+ onCloseProp?.();
+ }, [onCloseProp]);
const methods = useForm({
resolver: zodResolver(UpdateWebhookSchema),
diff --git a/web/sdk/package.json b/web/sdk/package.json
index c54bca967..ef85465fb 100644
--- a/web/sdk/package.json
+++ b/web/sdk/package.json
@@ -122,8 +122,7 @@
"peerDependencies": {
"@raystack/apsara": ">=0.30.0",
"react": "^18.2.0",
- "react-dom": "^18.2.0",
- "react-router-dom": ">=6.0.0"
+ "react-dom": "^18.2.0"
},
"peerDependenciesMeta": {
"react": {
@@ -132,9 +131,6 @@
"react-dom": {
"optional": true
},
- "react-router-dom": {
- "optional": true
- },
"svelte": {
"optional": true
},