Skip to content

Commit

Permalink
Merge branch 'dev' into Vxrcel-clean
Browse files Browse the repository at this point in the history
  • Loading branch information
kleenpulse authored Jul 30, 2024
2 parents bbc90cc + 3ba7094 commit 201f842
Showing 1 changed file with 129 additions and 65 deletions.
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
"use client";

import { useState } from "react";
import { useEffect, useState } from "react";

import CustomButton from "~/components/common/common-button/common-button";
import RoleCreationModal from "~/components/common/modals/role-creation";
import LoadingSpinner from "~/components/miscellaneous/loading-spinner";
import { useToast } from "~/components/ui/use-toast";
import { getApiUrl } from "~/utils/getApiUrl";

type Role = {
id: number;
Expand All @@ -12,75 +15,116 @@ type Role = {
};

type Permission = {
name: string;
enabled: boolean;
};

const rolesData: Role[] = [
{ id: 1, name: "Administrator", description: "Full access, control" },
{ id: 2, name: "Guest", description: "Read-only access" },
{ id: 3, name: "User", description: "Read, write, update" },
{ id: 4, name: "Manager", description: "Read, write, approve" },
{ id: 5, name: "Project Lead", description: "Manage, coordinate, oversee" },
];

const permissionsData: { [key: number]: Permission[] } = {
1: [
{ name: "Can view transactions", enabled: true },
{ name: "Can view refunds", enabled: false },
{ name: "Can log refunds", enabled: true },
],
2: [
{ name: "Can view users", enabled: true },
{ name: "Can create users", enabled: false },
{ name: "Can edit users", enabled: true },
{ name: "Can blacklist/whitelist users", enabled: true },
],
3: [
{ name: "Can view users", enabled: true },
{ name: "Can create users", enabled: true },
{ name: "Can edit users", enabled: false },
{ name: "Can blacklist/whitelist users", enabled: true },
],
4: [
{ name: "Can view transactions", enabled: true },
{ name: "Can view refunds", enabled: true },
{ name: "Can log refunds", enabled: true },
{ name: "Can view users", enabled: true },
{ name: "Can create users", enabled: true },
{ name: "Can edit users", enabled: true },
{ name: "Can blacklist/whitelist users", enabled: true },
],
5: [
{ name: "Can view transactions", enabled: true },
{ name: "Can view refunds", enabled: true },
{ name: "Can log refunds", enabled: true },
{ name: "Can view users", enabled: true },
{ name: "Can create users", enabled: true },
{ name: "Can edit users", enabled: true },
{ name: "Can blacklist/whitelist users", enabled: true },
],
[key: string]: boolean;
};

const RolesAndPermission = () => {
const [selectedRoleId, setSelectedRoleId] = useState<number | undefined>();
const [permissions, setPermissions] = useState<Permission[]>([]);
const [permissions, setPermissions] = useState<Permission>({});
const [isModalOpen, setIsModalOpen] = useState(false);
const [roles, setRoles] = useState<Role[]>([]);
const [apiUrl, setApiUrl] = useState("");
const { toast } = useToast();
const [loadingRoles, setLoadingRoles] = useState<boolean>(true);
const [loadingPermissions, setLoadingPermissions] = useState<boolean>(false);
const [loadingRequest, setLoadingRequest] = useState<boolean>(false);
const org_id = "9ca4512c-f665-4901-ba63-0b6492e47d32";

useEffect(() => {
setLoadingRoles(true);
const fetchData = async () => {
try {
const url = await getApiUrl();
setApiUrl(url);
const response = await fetch(`${url}/organisations/${org_id}/roles`);
const data = await response.json();
setRoles(data);
setLoadingRoles(false);
} catch (error: unknown) {
toast({
title: "Error occurred",
description:
error instanceof Error ? error.message : "Error fetching data",
variant: "destructive",
});
setLoadingRoles(false);
}
};
fetchData();
}, [toast]);

useEffect(() => {
const fetchPermissions = async () => {
if (selectedRoleId) {
setLoadingPermissions(true);
try {
const response = await fetch(
`${apiUrl}/organisations/${org_id}/roles/${selectedRoleId}`,
);
const permissionsData = await response.json();
setPermissions(permissionsData.permission_list);
setLoadingPermissions(false);
} catch {
toast({
title: "An error occurred",
description: "Error fetching permissions",
variant: "destructive",
});
setLoadingPermissions(false);
}
}
};
fetchPermissions();
}, [selectedRoleId, apiUrl, org_id, toast]);

const handleRoleClick = (roleId: number) => {
setSelectedRoleId(roleId);
setPermissions([...permissionsData[roleId]]);
};

const handleToggle = (index: number) => {
setPermissions((previous) => {
const newPermissions = [...previous];
newPermissions[index].enabled = !newPermissions[index].enabled;
permissionsData[selectedRoleId!] = newPermissions;
return newPermissions;
const handleToggle = (permission: string, value: boolean) => {
setPermissions({
...permissions,
[permission]: value,
});
};

const handleSave = async () => {
setLoadingRequest(true);
try {
const response = await fetch(
`${apiUrl}/organisations/${org_id}/${selectedRoleId}/permissions`,
{
method: "PUT",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ permission_list: permissions }),
},
);

if (response.ok) {
toast({
title: "Success",
description: "Permissions updated successfully",
variant: "default",
});
} else {
toast({
title: "Error",
description: "Failed to update permissions",
variant: "destructive",
});
}
} catch {
toast({
title: "Error",
description: "Failed to update permissions",
variant: "destructive",
});
}
setLoadingRequest(false);
};

const handleModalOpen = () => {
setIsModalOpen(true);
};
Expand All @@ -95,7 +139,12 @@ const RolesAndPermission = () => {
<div className="w-1/4">
<h2 className="mb-10 text-xl font-medium">Roles</h2>
<ul className="rounded-md border border-[#CBD5E1] p-3">
{rolesData.map((role) => (
{loadingRoles && (
<div className="flex justify-center py-8">
<LoadingSpinner className="size-4 animate-spin stroke-orange-500 sm:size-5" />
</div>
)}
{roles.map((role) => (
<li
key={role.id}
className={`mb-2 cursor-pointer border-[#CBD5E1] p-2 ${
Expand Down Expand Up @@ -143,30 +192,45 @@ const RolesAndPermission = () => {
Click on a role to view permissions
</p>
</div>
) : loadingPermissions ? (
<div className="item-center flex justify-center py-48">
<LoadingSpinner className="size-4 animate-spin stroke-orange-500 sm:size-5" />
</div>
) : (
<div className="mt-6">
{permissions.map((permission, index) => (
{Object.keys(permissions).map((permission) => (
<div
key={permission.name}
key={permission}
className="mb-4 flex items-center justify-between"
>
<span className="text-sm font-normal text-[#525252]">
{permission.name}
{permission
.replaceAll("_", " ")
.replaceAll(/\b\w/g, (l) => l.toUpperCase())}
</span>
<label className="relative inline-flex cursor-pointer items-center">
<input
type="checkbox"
className="peer sr-only"
checked={permission.enabled}
onChange={() => handleToggle(index)}
checked={permissions[permission]}
onChange={(event) =>
handleToggle(permission, event.target.checked)
}
/>
<div className="peer h-6 w-11 rounded-full bg-gray-200 after:absolute after:left-[2px] after:top-[2px] after:h-5 after:w-5 after:rounded-full after:border after:border-gray-300 after:bg-white after:transition-all after:content-[''] peer-checked:bg-orange-600 peer-checked:after:translate-x-full peer-checked:after:border-white peer-focus:ring-4 peer-focus:ring-orange-300 dark:border-gray-600 dark:bg-gray-700 dark:peer-focus:ring-orange-800"></div>
</label>
</div>
))}
<div className="mt-16 flex justify-center">
<button className="rounded border border-[#E2E8F0] bg-[#F1F5F9] px-4 py-2 text-sm font-medium text-[#0F172A] hover:bg-[#c1c9d2]">
Save Preferences
<button
className="w-40 rounded border border-[#E2E8F0] bg-[#F1F5F9] px-4 py-2 text-sm font-medium text-[#0F172A] hover:bg-[#c1c9d2]"
onClick={handleSave}
>
{loadingRequest ? (
<LoadingSpinner className="mx-auto size-4 animate-spin sm:size-5" />
) : (
"Save Preferences"
)}
</button>
</div>
</div>
Expand Down

0 comments on commit 201f842

Please sign in to comment.