fix conflict

This commit is contained in:
hagiye
2026-05-30 11:30:39 +03:00
27 changed files with 1929 additions and 1970 deletions

View File

@@ -11,6 +11,8 @@ import PermissionsPage from "./pages/dashboard/user-management/PermissionsPage";
import RolesPage from "./pages/dashboard/user-management/RolesPage";
import UserManagementPage from "./pages/dashboard/user-management/UserManagementPage";
import LoadingScreen from "./components/LoadingScreen";
import DemoUser1Page from "./pages/dashboard/demo/DemoUser1Page";
import DemoUser2Page from "./pages/dashboard/demo/DemoUser2Page";
import { RuleEnginePage } from "./pages/ruleEngine/RuleEngine";
// Create a QueryClient instance
@@ -56,11 +58,74 @@ const sidebarItems: SidebarItem[] = [
},
];
const hasPermission = (
user: ReturnType<typeof useAuth>["user"],
key: string,
) => {
if (!user) return false;
if (user.permissions?.some((p) => p.key === key)) return true;
return (user.employee ?? []).some((emp) =>
(emp.positions ?? []).some((pos) =>
(pos.permissions ?? []).some((p) => p.key === key),
),
);
};
const DashboardShell = () => {
const navigate = useNavigate();
const location = useLocation();
const { user, logout } = useAuth();
const sidebarItems: SidebarItem[] = [
{
label: "Overview",
href: "/dashboard/overview",
icon: <LayoutDashboard />,
},
{
label: "User management",
href: "/dashboard/user-management",
icon: <Network />,
children: [
{
label: "Employees",
href: "/dashboard/user-management/employees",
},
{
label: "Permissions",
href: "/dashboard/user-management/permissions",
},
{
label: "Roles",
href: "/dashboard/user-management/roles",
},
],
},
{
label: "Rule Engine",
href: "/dashboard/rule-engine",
icon: <Settings />,
},
...(hasPermission(user, "can:demo:user1")
? ([
{
label: "User1",
href: "/dashboard/user1",
icon: <Settings />,
},
] as SidebarItem[])
: []),
...(hasPermission(user, "can:demo:user2")
? ([
{
label: "User2",
href: "/dashboard/user2",
icon: <Settings />,
},
] as SidebarItem[])
: []),
];
const displayName = user?.name?.en || user?.username || user?.email || "User";
return (
@@ -99,7 +164,7 @@ const App = () => {
return (
<QueryClientProvider client={queryClient}>
<Routes>
{/* <Routes>
<Route path="/" element={<Navigate to="/dashboard/overview" replace />} />
<Route path="/dashboard" element={<Navigate to="/dashboard/overview" replace />} />
<Route path="/dashboard" element={<DashboardShell />}>
@@ -114,6 +179,24 @@ const App = () => {
</Route>
<Route path="*" element={<Navigate to="/dashboard/overview" replace />} />
</Routes>
======= */}
<Routes>
<Route path="/" element={<Navigate to="/dashboard/overview" replace />} />
<Route path="/dashboard" element={<Navigate to="/dashboard/overview" replace />} />
<Route path="/dashboard" element={<DashboardShell />}>
<Route path="overview" element={<OverviewPage />} />
<Route path="user-management" element={<UserManagementPage />} />
<Route path="rule-engine" element={<RuleEnginePage />} />
<Route path="user-management/employees" element={<EmployeesPage />} />
<Route path="user-management/permissions" element={<PermissionsPage />} />
<Route path="user-management/roles" element={<RolesPage />} />
<Route path="user1" element={<DemoUser1Page />} />
<Route path="user2" element={<DemoUser2Page />} />
<Route path="org-structure" element={<Navigate to="/dashboard/user-management" replace />} />
<Route path="org-structure/*" element={<Navigate to="/dashboard/user-management" replace />} />
</Route>
<Route path="*" element={<Navigate to="/dashboard/overview" replace />} />
</Routes>
</QueryClientProvider>
);
};

View File

@@ -0,0 +1,67 @@
import { useEffect, useState } from "react";
import { api } from "@/auth/http";
const DemoUser1Page = () => {
const [data, setData] = useState<unknown>(null);
const [error, setError] = useState<string | null>(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
let cancelled = false;
const run = async () => {
setLoading(true);
setError(null);
try {
const response = await api.get("/test_user1");
if (cancelled) return;
setData(response.data);
} catch (e: any) {
if (cancelled) return;
const message =
e?.response?.data?.message ||
e?.response?.data?.error ||
e?.message ||
"Request failed";
setError(String(message));
} finally {
if (!cancelled) setLoading(false);
}
};
void run();
return () => {
cancelled = true;
};
}, []);
return (
<div className="p-6">
<div className="rounded-2xl border border-border bg-card p-6">
<h1 className="text-lg font-semibold text-foreground">User1 Demo</h1>
<p className="mt-1 text-sm text-muted-foreground">
Calls <code className="font-mono">GET /api/test_user1</code> (requires{' '}
<code className="font-mono">can:demo:user1</code>).
</p>
<div className="mt-4">
{loading ? <p className="text-sm text-muted-foreground">Loading...</p> : null}
{error ? (
<div className="rounded-xl border border-red-200 bg-red-50 px-4 py-3 text-sm text-red-700">
{error}
</div>
) : null}
{!loading && !error ? (
<pre className="mt-3 overflow-auto rounded-xl border border-border bg-background p-4 text-xs text-foreground">
{JSON.stringify(data, null, 2)}
</pre>
) : null}
</div>
</div>
</div>
);
};
export default DemoUser1Page;

View File

@@ -0,0 +1,67 @@
import { useEffect, useState } from "react";
import { api } from "@/auth/http";
const DemoUser2Page = () => {
const [data, setData] = useState<unknown>(null);
const [error, setError] = useState<string | null>(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
let cancelled = false;
const run = async () => {
setLoading(true);
setError(null);
try {
const response = await api.get("/test_user2");
if (cancelled) return;
setData(response.data);
} catch (e: any) {
if (cancelled) return;
const message =
e?.response?.data?.message ||
e?.response?.data?.error ||
e?.message ||
"Request failed";
setError(String(message));
} finally {
if (!cancelled) setLoading(false);
}
};
void run();
return () => {
cancelled = true;
};
}, []);
return (
<div className="p-6">
<div className="rounded-2xl border border-border bg-card p-6">
<h1 className="text-lg font-semibold text-foreground">User2 Demo</h1>
<p className="mt-1 text-sm text-muted-foreground">
Calls <code className="font-mono">GET /api/test_user2</code> (requires{' '}
<code className="font-mono">can:demo:user2</code>).
</p>
<div className="mt-4">
{loading ? <p className="text-sm text-muted-foreground">Loading...</p> : null}
{error ? (
<div className="rounded-xl border border-red-200 bg-red-50 px-4 py-3 text-sm text-red-700">
{error}
</div>
) : null}
{!loading && !error ? (
<pre className="mt-3 overflow-auto rounded-xl border border-border bg-background p-4 text-xs text-foreground">
{JSON.stringify(data, null, 2)}
</pre>
) : null}
</div>
</div>
</div>
);
};
export default DemoUser2Page;