From 24c0adfa8de59397541d38d5ed42fa18e69b2103 Mon Sep 17 00:00:00 2001 From: Sabda Yagra Date: Sat, 4 Oct 2025 22:10:40 +0700 Subject: [PATCH] fix: table user level, navbar show detail profile login --- .../settings/tenant/component/columns.tsx | 283 ++++++ .../tenant/component/table-user-level.tsx | 923 ++++++++++++++++++ .../(admin)/admin/settings/tenant/page.tsx | 665 +------------ components/form/login.tsx | 12 +- components/landing-page/navbar.tsx | 105 +- components/modals/WorkflowModalProvider.tsx | 4 +- components/partials/auth/login-form.tsx | 94 +- components/partials/header/profile-info.tsx | 38 +- hooks/use-auth.ts | 3 +- lib/auth-utils.ts | 2 +- types/auth.ts | 2 + 11 files changed, 1392 insertions(+), 739 deletions(-) create mode 100644 app/[locale]/(admin)/admin/settings/tenant/component/columns.tsx create mode 100644 app/[locale]/(admin)/admin/settings/tenant/component/table-user-level.tsx diff --git a/app/[locale]/(admin)/admin/settings/tenant/component/columns.tsx b/app/[locale]/(admin)/admin/settings/tenant/component/columns.tsx new file mode 100644 index 0000000..44a277d --- /dev/null +++ b/app/[locale]/(admin)/admin/settings/tenant/component/columns.tsx @@ -0,0 +1,283 @@ +"use client"; +import * as React from "react"; +import { ColumnDef } from "@tanstack/react-table"; + +import { Eye, MoreVertical, SquarePen, Trash2 } from "lucide-react"; +import { cn, getCookiesDecrypt } from "@/lib/utils"; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuTrigger, + DropdownMenuItem, +} from "@/components/ui/dropdown-menu"; +import { Button } from "@/components/ui/button"; +import { Badge } from "@/components/ui/badge"; +import { format } from "date-fns"; +import { useRouter } from "next/navigation"; +import { deleteMedia } from "@/service/content/content"; +import { error } from "@/lib/swal"; +import Swal from "sweetalert2"; +import withReactContent from "sweetalert2-react-content"; +import Link from "next/link"; + +const useTableColumns = () => { + const MySwal = withReactContent(Swal); + const userLevelId = getCookiesDecrypt("ulie"); + + const columns: ColumnDef[] = [ + { + accessorKey: "no", + header: "No", + cell: ({ row }) => ( +
+
+

+ {row.getValue("no")} +

+
+
+ ), + }, + { + accessorKey: "aliasName", + header: "Name", + cell: ({ row }) => ( +
+
+

+ {row.getValue("aliasName")} +

+
+
+ ), + }, + { + accessorKey: "group", + header: "Group", + cell: ({ row }) => ( +
+
+

+ {row.getValue("group")} +

+
+
+ ), + }, + { + accessorKey: "parentLevelName", + header: "Parent Level", + cell: ({ row }) => ( +
+
+

+ {row.getValue("parentLevelName")} +

+
+
+ ), + }, + // { + // accessorKey: "createdAt", + // header: "Upload Date", + // cell: ({ row }) => { + // const createdAt = row.getValue("createdAt") as string | number | undefined; + // const formattedDate = + // createdAt && !isNaN(new Date(createdAt).getTime()) + // ? format(new Date(createdAt), "dd-MM-yyyy HH:mm:ss") + // : "-"; + // return {formattedDate}; + // }, + // }, + // { + // accessorKey: "creatorName", + // header: "Creator Group", + // cell: ({ row }) => ( + // + // {row.original.creatorName || row.original.createdByName || "-"} + // + // ), + // }, + // { + // accessorKey: "creatorGroupLevelName", + // header: "Source", + // cell: ({ row }) => ( + // + // {row.getValue("creatorGroupLevelName") || "-"} + // + // ), + // }, + // { + // accessorKey: "publishedOn", + // header: "Published", + // cell: ({ row }) => { + // const isPublish = row.original.isPublish; + // const isPublishOnPolda = row.original.isPublishOnPolda; + // const creatorGroupParentLevelId = row.original.creatorGroupParentLevelId; + + // let displayText = "-"; + // if (isPublish && !isPublishOnPolda) { + // displayText = "Mabes"; + // } else if (isPublish && isPublishOnPolda) { + // if (Number(creatorGroupParentLevelId) === 761) { + // displayText = "Mabes & Satker"; + // } else { + // displayText = "Mabes & Polda"; + // } + // } else if (!isPublish && isPublishOnPolda) { + // if (Number(creatorGroupParentLevelId) === 761) { + // displayText = "Satker"; + // } else { + // displayText = "Polda"; + // } + // } + + // return ( + //
+ // {displayText} + //
+ // ); + // }, + // }, + // { + // accessorKey: "statusName", + // header: "Status", + // cell: ({ row }) => { + // const statusId = Number(row.original?.statusId); + // const reviewedAtLevel = row.original?.reviewedAtLevel || ""; + // const creatorGroupLevelId = Number(row.original?.creatorGroupLevelId); + // const needApprovalFromLevel = Number(row.original?.needApprovalFromLevel); + + // const userHasReviewed = reviewedAtLevel.includes(`:${userLevelId}:`); + // const isCreator = creatorGroupLevelId === Number(userLevelId); + + // const isWaitingForReview = statusId === 2 && !userHasReviewed && !isCreator; + // const isApprovalNeeded = statusId === 1 && needApprovalFromLevel === Number(userLevelId); + + // const label = + // isWaitingForReview || isApprovalNeeded + // ? "Menunggu Review" + // : statusId === 2 + // ? "Diterima" + // : row.original?.statusName; + + // const colors: Record = { + // "Menunggu Review": "bg-orange-100 text-orange-600", + // Diterima: "bg-green-100 text-green-600", + // default: "bg-red-200 text-red-600", + // }; + + // const statusStyles = colors[label] || colors.default; + + // return ( + // + // {label} + // + // ); + // }, + // }, + { + id: "actions", + accessorKey: "action", + header: "Action", + enableHiding: false, + cell: ({ row }) => { + const router = useRouter(); + const MySwal = withReactContent(Swal); + + async function doDelete(id: any) { + const data = { id }; + const response = await deleteMedia(data); + if (response?.error) { + error(response.message); + return false; + } + success(); + } + + function success() { + MySwal.fire({ + title: "Sukses", + icon: "success", + confirmButtonColor: "#3085d6", + confirmButtonText: "OK", + }).then((result) => { + if (result.isConfirmed) { + window.location.reload(); + } + }); + } + + const handleDeleteMedia = (id: any) => { + MySwal.fire({ + title: "Hapus Data", + icon: "warning", + showCancelButton: true, + cancelButtonColor: "#3085d6", + confirmButtonColor: "#d33", + confirmButtonText: "Hapus", + }).then((result) => { + if (result.isConfirmed) { + doDelete(id); + } + }); + }; + + const [isMabesApprover, setIsMabesApprover] = React.useState(false); + const userId = getCookiesDecrypt("uie"); + const userLevelId = getCookiesDecrypt("ulie"); + const roleId = getCookiesDecrypt("urie"); + + React.useEffect(() => { + if (userLevelId !== undefined && roleId !== undefined) { + setIsMabesApprover(Number(userLevelId) === 216 && Number(roleId) === 3); + } + }, [userLevelId, roleId]); + + return ( + + + + + + + + + View + + + {/* {(Number(row.original.uploadedById) === Number(userId) || isMabesApprover) && ( */} + + + + Edit + + + {/* )} */} + handleDeleteMedia(row.original.id)} + className="p-2 border-b text-destructive bg-destructive/30 focus:bg-destructive focus:text-white rounded-none" + > + + Delete + + + + ); + }, + }, + ]; + + return columns; +}; + +export default useTableColumns; diff --git a/app/[locale]/(admin)/admin/settings/tenant/component/table-user-level.tsx b/app/[locale]/(admin)/admin/settings/tenant/component/table-user-level.tsx new file mode 100644 index 0000000..32725cd --- /dev/null +++ b/app/[locale]/(admin)/admin/settings/tenant/component/table-user-level.tsx @@ -0,0 +1,923 @@ +"use client"; +import React, { useState } from "react"; +import { Button } from "@/components/ui/button"; +import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; +import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; +import { + Dialog, + DialogContent, + DialogHeader, + DialogTitle, + DialogTrigger, +} from "@/components/ui/dialog"; +import { + PlusIcon, + SettingsIcon, + UsersIcon, + WorkflowIcon, +} from "@/components/icons"; +import { ApprovalWorkflowForm } from "@/components/form/ApprovalWorkflowForm"; +import { UserLevelsForm } from "@/components/form/UserLevelsForm"; +import { useWorkflowModal } from "@/components/modals/WorkflowModalProvider"; +import { useWorkflowStatusCheck } from "@/hooks/useWorkflowStatusCheck"; +import { + CreateApprovalWorkflowWithClientSettingsRequest, + UserLevelsCreateRequest, + UserLevel, + getUserLevels, + getApprovalWorkflowComprehensiveDetails, + ComprehensiveWorkflowResponse, + createUserLevel, +} from "@/service/approval-workflows"; +import { + Table, + TableBody, + TableCell, + TableHead, + TableHeader, + TableRow, +} from "@/components/ui/table"; +import { + flexRender, + getCoreRowModel, + getFilteredRowModel, + getPaginationRowModel, + getSortedRowModel, + PaginationState, + useReactTable, +} from "@tanstack/react-table"; +import TablePagination from "@/components/table/table-pagination"; +import useTableColumns from "./columns"; + +function TenantSettingsContentTable() { + const [activeTab, setActiveTab] = useState("workflows"); + const [isUserLevelDialogOpen, setIsUserLevelDialogOpen] = useState(false); + const [workflow, setWorkflow] = + useState(null); + const [userLevels, setUserLevels] = useState([]); + const [isLoading, setIsLoading] = useState(false); + const [isEditingWorkflow, setIsEditingWorkflow] = useState(false); + const { checkWorkflowStatus } = useWorkflowStatusCheck(); + const { showWorkflowModal } = useWorkflowModal(); + + React.useEffect(() => { + loadData(); + }, []); + + const loadData = async () => { + setIsLoading(true); + try { + const [comprehensiveWorkflowRes, userLevelsRes] = await Promise.all([ + getApprovalWorkflowComprehensiveDetails(4), + getUserLevels(), + ]); + + if (!comprehensiveWorkflowRes?.error) { + setWorkflow(comprehensiveWorkflowRes?.data?.data || null); + } else { + setWorkflow(null); + } + + if (!userLevelsRes?.error) { + const data = userLevelsRes?.data?.data; + data.forEach((item: any, index: number) => { + item.no = (page - 1) * Number(showData) + index + 1; + item.parentLevelName = + data.length > 0 + ? data.find((ul: any) => ul.id === item.parentLevelId)?.name || + `Level ${item.parentLevelId}` + : `Level ${item.parentLevelId}`; + }); + setUserLevels(data); + console.log("LLL", data); + } + } catch (error) { + console.error("Error loading data:", error); + } finally { + setIsLoading(false); + } + }; + + const handleWorkflowSave = async ( + data: CreateApprovalWorkflowWithClientSettingsRequest + ) => { + setIsEditingWorkflow(false); + await loadData(); + }; + + const handleUserLevelSave = async (data: UserLevelsCreateRequest) => { + try { + const response = await createUserLevel(data); + + if (response?.error) { + console.error("Error creating user level:", response?.message); + } else { + console.log("User level created successfully:", response); + } + } catch (error) { + console.error("Error creating user level:", error); + } + + setIsUserLevelDialogOpen(false); + await loadData(); + }; + + const handleBulkUserLevelSave = async (data: UserLevelsCreateRequest[]) => { + setIsUserLevelDialogOpen(false); + await loadData(); + }; + + const columns = useTableColumns(); + const [showData, setShowData] = React.useState("10"); + const [page, setPage] = React.useState(1); + const [totalPage, setTotalPage] = React.useState(1); + const [totalData, setTotalData] = React.useState(1); + const [pagination, setPagination] = React.useState({ + pageIndex: 0, + pageSize: Number(showData), + }); + + const table = useReactTable({ + data: userLevels, + columns, + // onSortingChange: setSorting, + // onColumnFiltersChange: setColumnFilters, + getCoreRowModel: getCoreRowModel(), + getPaginationRowModel: getPaginationRowModel(), + getSortedRowModel: getSortedRowModel(), + getFilteredRowModel: getFilteredRowModel(), + // onColumnVisibilityChange: setColumnVisibility, + // onRowSelectionChange: setRowSelection, + onPaginationChange: setPagination, + state: { + // sorting, + // columnFilters, + // columnVisibility, + // rowSelection, + pagination, + }, + }); + + return ( +
+
+
+

Tenant Settings

+

+ Manage approval workflows and user levels for your tenant +

+
+
+ + + +
+
+ + + + + + Approval Workflows + + + + User Levels + + + + {/* Approval Workflows Tab */} + +
+

+ Approval Workflow Setup +

+ {workflow && !isEditingWorkflow && ( + + )} +
+ + {isEditingWorkflow ? ( + + + + Setup Approval Workflow + + + + + ({ + stepOrder: step.stepOrder, + stepName: step.stepName, + requiredUserLevelId: step.requiredUserLevelId, + canSkip: step.canSkip, + autoApproveAfterHours: step.autoApproveAfterHours, + isActive: step.isActive, + conditionType: step.conditionType, + conditionValue: step.conditionValue, + })) || [], + clientApprovalSettings: { + approvalExemptCategories: + workflow.clientSettings.exemptCategoriesDetails || + [], + approvalExemptRoles: + workflow.clientSettings.exemptRolesDetails || [], + approvalExemptUsers: + workflow.clientSettings.exemptUsersDetails || [], + autoPublishArticles: + workflow.clientSettings.autoPublishArticles, + isActive: workflow.clientSettings.isActive, + requireApprovalFor: + workflow.clientSettings.requireApprovalFor || [], + requiresApproval: + workflow.clientSettings.requiresApproval, + skipApprovalFor: + workflow.clientSettings.skipApprovalFor || [], + }, + } + : undefined + } + onSave={handleWorkflowSave} + onCancel={() => setIsEditingWorkflow(false)} + /> + + + ) : workflow ? ( + + + + {workflow.workflow.name} +
+ {workflow.workflow.isDefault && ( + + Default + + )} + {workflow.workflow.isActive ? ( + + Active + + ) : ( + + Inactive + + )} +
+
+
+ +

+ {workflow.workflow.description} +

+ +
+
+
+ {workflow.workflow.totalSteps} +
+
Total Steps
+
+ +
+
+ {workflow.workflow.activeSteps} +
+
Active Steps
+
+ +
+
+ {workflow.workflow.requiresApproval ? "Yes" : "No"} +
+
+ Requires Approval +
+
+ +
+
+ {workflow.workflow.autoPublish ? "Yes" : "No"} +
+
Auto Publish
+
+
+ + {/* Workflow Steps Overview */} + {workflow.steps && workflow.steps.length > 0 && ( +
+

Workflow Steps

+
+ {workflow.steps.map((step: any, index: number) => ( +
+
+
+ {step.stepOrder} +
+
+
{step.stepName}
+
+ {step.conditionType && + `Condition: ${step.conditionType}`} + {step.autoApproveAfterHours && + ` • Auto-approve after ${step.autoApproveAfterHours}h`} + {step.requiredUserLevelName && + ` • Required Level: ${step.requiredUserLevelName}`} +
+
+
+
+ {step.canSkip && ( + + Can Skip + + )} + {step.isParallel && ( + + Parallel + + )} + {step.isActive && ( + + Active + + )} + {step.isFirstStep && ( + + First Step + + )} + {step.isLastStep && ( + + Last Step + + )} +
+
+ ))} +
+
+ )} + + {/* Client Settings */} +
+

Client Settings

+
+
+
+ Default Workflow +
+
+ {workflow.clientSettings.defaultWorkflowName} +
+
+
+
+ Auto Publish Articles +
+
+ {workflow.clientSettings.autoPublishArticles + ? "Yes" + : "No"} +
+
+
+
+ Requires Approval +
+
+ {workflow.clientSettings.requiresApproval + ? "Yes" + : "No"} +
+
+
+
+ Settings Active +
+
+ {workflow.clientSettings.isActive ? "Yes" : "No"} +
+
+
+
+ + {/* Statistics */} +
+

+ Workflow Statistics +

+
+
+
+ Total Articles Processed +
+
+ {workflow.statistics.totalArticlesProcessed} +
+
+
+
+ Pending Articles +
+
+ {workflow.statistics.pendingArticles} +
+
+
+
+ Approved Articles +
+
+ {workflow.statistics.approvedArticles} +
+
+
+
+ Rejected Articles +
+
+ {workflow.statistics.rejectedArticles} +
+
+
+
+ Average Processing Time +
+
+ {workflow.statistics.averageProcessingTime}h +
+
+
+
+ Most Active Step +
+
+ {workflow.statistics.mostActiveStep || "N/A"} +
+
+
+
+ + {/* Workflow Metadata */} +
+

+ Workflow Information +

+
+
+
+ Client ID +
+
+ {workflow.workflow.clientId} +
+
+
+
+ Created At +
+
+ {new Date(workflow.workflow.createdAt).toLocaleString()} +
+
+
+
+ Updated At +
+
+ {new Date(workflow.workflow.updatedAt).toLocaleString()} +
+
+
+
+ Workflow ID +
+
+ {workflow.workflow.id} +
+
+
+
+ Has Branches +
+
+ {workflow.workflow.hasBranches ? "Yes" : "No"} +
+
+
+
+ Max Step Order +
+
+ {workflow.workflow.maxStepOrder} +
+
+
+
+
+
+ ) : ( + + +
+ +

+ No Workflow Configured +

+

+ Set up your approval workflow to manage content approval + process +

+ +
+
+
+ )} +
+ + {/* User Levels Tab */} + +
+

User Levels

+ + + + + + + Create New User Level + + setIsUserLevelDialogOpen(false)} + /> + + +
+ + {/* User Levels Summary */} + {userLevels.length > 0 && ( +
+
+
+ {userLevels.length} +
+
Total User Levels
+
+ +
+
+ {userLevels.filter((ul) => ul.isActive).length} +
+
Active Levels
+
+ +
+
+ {userLevels.filter((ul) => ul.isApprovalActive).length} +
+
Approval Active
+
+ +
+
+ {userLevels.filter((ul) => ul.parentLevelId).length} +
+
Child Levels
+
+
+ )} + + {/* User Levels Hierarchy */} + {userLevels.length > 0 && ( + + + + + User Levels Hierarchy + + + +
+ {userLevels + .filter((ul) => !ul.parentLevelId) // Root levels + .sort((a, b) => a.levelNumber - b.levelNumber) + .map((rootLevel) => ( +
+ {/* Root Level */} +
+
+ {rootLevel.levelNumber} +
+
+
{rootLevel.name}
+
+ {rootLevel.aliasName} •{" "} + {rootLevel.group || "No group"} +
+
+
+ {rootLevel.isActive && ( + + Active + + )} + {rootLevel.isApprovalActive && ( + + Approval Active + + )} +
+
+ + {/* Child Levels */} + {userLevels + .filter((ul) => ul.parentLevelId === rootLevel.id) + .sort((a, b) => a.levelNumber - b.levelNumber) + .map((childLevel) => ( +
+
+ {childLevel.levelNumber} +
+
+
+ {childLevel.name} +
+
+ {childLevel.aliasName} •{" "} + {childLevel.group || "No group"} +
+
+
+ {childLevel.isActive && ( + + Active + + )} + {childLevel.isApprovalActive && ( + + Approval + + )} +
+
+ ))} +
+ ))} +
+
+
+ )} + + + + {table.getHeaderGroups().map((headerGroup) => ( + + {headerGroup.headers.map((header) => ( + + {header.isPlaceholder + ? null + : flexRender( + header.column.columnDef.header, + header.getContext() + )} + + ))} + + ))} + + + {table.getRowModel().rows?.length ? ( + table.getRowModel().rows.map((row) => ( + + {row.getVisibleCells().map((cell) => ( + + {flexRender( + cell.column.columnDef.cell, + cell.getContext() + )} + + ))} + + )) + ) : ( + + + No results. + + + )} + +
+ + + {/*
+ {userLevels.length > 0 ? userLevels.map((userLevel) => ( + + + + {userLevel.name} +
+ + Level {userLevel.levelNumber} + + {userLevel.isActive ? ( + + Active + + ) : ( + + Inactive + + )} +
+
+
+ +
+
+ Alias: + + {userLevel.aliasName} + +
+ + {userLevel.group && ( +
+ Group: + {userLevel.group} +
+ )} + +
+ Approval Active: + + {userLevel.isApprovalActive ? 'Yes' : 'No'} + +
+ + {userLevel.parentLevelId && ( +
+ Parent Level: + + { userLevels.length > 0 ? userLevels.find(ul => ul.id === userLevel.parentLevelId)?.name || `Level ${userLevel.parentLevelId}` : `Level ${userLevel.parentLevelId}`} + +
+ )} + + {userLevel.provinceId && ( +
+ Province: + Province {userLevel.provinceId} +
+ )} + +
+ Created: + + {userLevel.createdAt ? new Date(userLevel.createdAt).toLocaleDateString() : 'N/A'} + +
+
+ +
+ + +
+
+
+ )) : ''} +
*/} + + {userLevels.length === 0 && !isLoading && ( + + +
+ +

+ No User Levels Found +

+

+ Create your first user level to define approval hierarchy +

+ +
+
+
+ )} +
+
+
+ ); +} + +export default function TenantSettingsPageTable() { + return ; +} diff --git a/app/[locale]/(admin)/admin/settings/tenant/page.tsx b/app/[locale]/(admin)/admin/settings/tenant/page.tsx index a3d7682..4cd19bc 100644 --- a/app/[locale]/(admin)/admin/settings/tenant/page.tsx +++ b/app/[locale]/(admin)/admin/settings/tenant/page.tsx @@ -3,8 +3,19 @@ import React, { useState } from "react"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; -import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog"; -import { PlusIcon, SettingsIcon, UsersIcon, WorkflowIcon } from "@/components/icons"; +import { + Dialog, + DialogContent, + DialogHeader, + DialogTitle, + DialogTrigger, +} from "@/components/ui/dialog"; +import { + PlusIcon, + SettingsIcon, + UsersIcon, + WorkflowIcon, +} from "@/components/icons"; import { ApprovalWorkflowForm } from "@/components/form/ApprovalWorkflowForm"; import { UserLevelsForm } from "@/components/form/UserLevelsForm"; import { useWorkflowModal } from "@/components/modals/WorkflowModalProvider"; @@ -18,637 +29,29 @@ import { ComprehensiveWorkflowResponse, createUserLevel, } from "@/service/approval-workflows"; +import { + Table, + TableBody, + TableCell, + TableHead, + TableHeader, + TableRow, +} from "@/components/ui/table"; +import { + flexRender, + getCoreRowModel, + getFilteredRowModel, + getPaginationRowModel, + getSortedRowModel, + PaginationState, + useReactTable, +} from "@tanstack/react-table"; +import useTableColumns from "./component/columns"; +import TablePagination from "@/components/table/table-pagination"; +import TenantSettingsPageTable from "./component/table-user-level"; -function TenantSettingsContent() { - const [activeTab, setActiveTab] = useState("workflows"); - const [isUserLevelDialogOpen, setIsUserLevelDialogOpen] = useState(false); - const [workflow, setWorkflow] = useState(null); - const [userLevels, setUserLevels] = useState([]); - const [isLoading, setIsLoading] = useState(false); - const [isEditingWorkflow, setIsEditingWorkflow] = useState(false); - const { checkWorkflowStatus } = useWorkflowStatusCheck(); - const { showWorkflowModal } = useWorkflowModal(); - React.useEffect(() => { - loadData(); - }, []); - - const loadData = async () => { - setIsLoading(true); - try { - const [comprehensiveWorkflowRes, userLevelsRes] = await Promise.all([ - getApprovalWorkflowComprehensiveDetails(4), - getUserLevels(), - ]); - - if (!comprehensiveWorkflowRes?.error) { - setWorkflow(comprehensiveWorkflowRes?.data?.data || null); - } else { - setWorkflow(null); - } - - if (!userLevelsRes?.error) { - setUserLevels(userLevelsRes?.data?.data || []); - } - } catch (error) { - console.error("Error loading data:", error); - } finally { - setIsLoading(false); - } - }; - - const handleWorkflowSave = async (data: CreateApprovalWorkflowWithClientSettingsRequest) => { - setIsEditingWorkflow(false); - await loadData(); - }; - - const handleUserLevelSave = async (data: UserLevelsCreateRequest) => { - try { - const response = await createUserLevel(data); - - if (response?.error) { - console.error("Error creating user level:", response?.message); - } else { - console.log("User level created successfully:", response); - } - } catch (error) { - console.error("Error creating user level:", error); - } - - setIsUserLevelDialogOpen(false); - await loadData(); - }; - - const handleBulkUserLevelSave = async (data: UserLevelsCreateRequest[]) => { - setIsUserLevelDialogOpen(false); - await loadData(); - }; - - return ( -
-
-
-

Tenant Settings

-

- Manage approval workflows and user levels for your tenant -

-
-
- - - -
-
- - - - - - Approval Workflows - - - - User Levels - - - - {/* Approval Workflows Tab */} - -
-

Approval Workflow Setup

- {workflow && !isEditingWorkflow && ( - - )} -
- - {isEditingWorkflow ? ( - - - - Setup Approval Workflow - - - - - ({ - stepOrder: step.stepOrder, - stepName: step.stepName, - requiredUserLevelId: step.requiredUserLevelId, - canSkip: step.canSkip, - autoApproveAfterHours: step.autoApproveAfterHours, - isActive: step.isActive, - conditionType: step.conditionType, - conditionValue: step.conditionValue, - })) || [], - clientApprovalSettings: { - approvalExemptCategories: workflow.clientSettings.exemptCategoriesDetails || [], - approvalExemptRoles: workflow.clientSettings.exemptRolesDetails || [], - approvalExemptUsers: workflow.clientSettings.exemptUsersDetails || [], - autoPublishArticles: workflow.clientSettings.autoPublishArticles, - isActive: workflow.clientSettings.isActive, - requireApprovalFor: workflow.clientSettings.requireApprovalFor || [], - requiresApproval: workflow.clientSettings.requiresApproval, - skipApprovalFor: workflow.clientSettings.skipApprovalFor || [] - } - } : undefined} - onSave={handleWorkflowSave} - onCancel={() => setIsEditingWorkflow(false)} - /> - - - ) : workflow ? ( - - - - {workflow.workflow.name} -
- {workflow.workflow.isDefault && ( - - Default - - )} - {workflow.workflow.isActive ? ( - - Active - - ) : ( - - Inactive - - )} -
-
-
- -

- {workflow.workflow.description} -

- -
-
-
{workflow.workflow.totalSteps}
-
Total Steps
-
- -
-
{workflow.workflow.activeSteps}
-
Active Steps
-
- -
-
- {workflow.workflow.requiresApproval ? 'Yes' : 'No'} -
-
Requires Approval
-
- -
-
- {workflow.workflow.autoPublish ? 'Yes' : 'No'} -
-
Auto Publish
-
-
- - {/* Workflow Steps Overview */} - {workflow.steps && workflow.steps.length > 0 && ( -
-

Workflow Steps

-
- {workflow.steps.map((step: any, index: number) => ( -
-
-
- {step.stepOrder} -
-
-
{step.stepName}
-
- {step.conditionType && `Condition: ${step.conditionType}`} - {step.autoApproveAfterHours && ` • Auto-approve after ${step.autoApproveAfterHours}h`} - {step.requiredUserLevelName && ` • Required Level: ${step.requiredUserLevelName}`} -
-
-
-
- {step.canSkip && ( - - Can Skip - - )} - {step.isParallel && ( - - Parallel - - )} - {step.isActive && ( - - Active - - )} - {step.isFirstStep && ( - - First Step - - )} - {step.isLastStep && ( - - Last Step - - )} -
-
- ))} -
-
- )} - - {/* Client Settings */} -
-

Client Settings

-
-
-
Default Workflow
-
{workflow.clientSettings.defaultWorkflowName}
-
-
-
Auto Publish Articles
-
- {workflow.clientSettings.autoPublishArticles ? 'Yes' : 'No'} -
-
-
-
Requires Approval
-
- {workflow.clientSettings.requiresApproval ? 'Yes' : 'No'} -
-
-
-
Settings Active
-
- {workflow.clientSettings.isActive ? 'Yes' : 'No'} -
-
-
-
- - {/* Statistics */} -
-

Workflow Statistics

-
-
-
Total Articles Processed
-
{workflow.statistics.totalArticlesProcessed}
-
-
-
Pending Articles
-
{workflow.statistics.pendingArticles}
-
-
-
Approved Articles
-
{workflow.statistics.approvedArticles}
-
-
-
Rejected Articles
-
{workflow.statistics.rejectedArticles}
-
-
-
Average Processing Time
-
{workflow.statistics.averageProcessingTime}h
-
-
-
Most Active Step
-
{workflow.statistics.mostActiveStep || 'N/A'}
-
-
-
- - {/* Workflow Metadata */} -
-

Workflow Information

-
-
-
Client ID
-
{workflow.workflow.clientId}
-
-
-
Created At
-
- {new Date(workflow.workflow.createdAt).toLocaleString()} -
-
-
-
Updated At
-
- {new Date(workflow.workflow.updatedAt).toLocaleString()} -
-
-
-
Workflow ID
-
{workflow.workflow.id}
-
-
-
Has Branches
-
- {workflow.workflow.hasBranches ? 'Yes' : 'No'} -
-
-
-
Max Step Order
-
{workflow.workflow.maxStepOrder}
-
-
-
-
-
- ) : ( - - -
- -

No Workflow Configured

-

- Set up your approval workflow to manage content approval process -

- -
-
-
- )} -
- - {/* User Levels Tab */} - -
-

User Levels

- - - - - - - Create New User Level - - setIsUserLevelDialogOpen(false)} - /> - - -
- - {/* User Levels Summary */} - {userLevels.length > 0 && ( -
-
-
{userLevels.length}
-
Total User Levels
-
- -
-
- {userLevels.filter(ul => ul.isActive).length} -
-
Active Levels
-
- -
-
- {userLevels.filter(ul => ul.isApprovalActive).length} -
-
Approval Active
-
- -
-
- {userLevels.filter(ul => ul.parentLevelId).length} -
-
Child Levels
-
-
- )} - - {/* User Levels Hierarchy */} - {userLevels.length > 0 && ( - - - - - User Levels Hierarchy - - - -
- {userLevels - .filter(ul => !ul.parentLevelId) // Root levels - .sort((a, b) => a.levelNumber - b.levelNumber) - .map(rootLevel => ( -
- {/* Root Level */} -
-
- {rootLevel.levelNumber} -
-
-
{rootLevel.name}
-
- {rootLevel.aliasName} • {rootLevel.group || 'No group'} -
-
-
- {rootLevel.isActive && ( - - Active - - )} - {rootLevel.isApprovalActive && ( - - Approval Active - - )} -
-
- - {/* Child Levels */} - {userLevels - .filter(ul => ul.parentLevelId === rootLevel.id) - .sort((a, b) => a.levelNumber - b.levelNumber) - .map(childLevel => ( -
-
- {childLevel.levelNumber} -
-
-
{childLevel.name}
-
- {childLevel.aliasName} • {childLevel.group || 'No group'} -
-
-
- {childLevel.isActive && ( - - Active - - )} - {childLevel.isApprovalActive && ( - - Approval - - )} -
-
- ))} -
- ))} -
-
-
- )} - -
- {userLevels.length > 0 ? userLevels.map((userLevel) => ( - - - - {userLevel.name} -
- - Level {userLevel.levelNumber} - - {userLevel.isActive ? ( - - Active - - ) : ( - - Inactive - - )} -
-
-
- -
-
- Alias: - - {userLevel.aliasName} - -
- - {userLevel.group && ( -
- Group: - {userLevel.group} -
- )} - -
- Approval Active: - - {userLevel.isApprovalActive ? 'Yes' : 'No'} - -
- - {userLevel.parentLevelId && ( -
- Parent Level: - - { userLevels.length > 0 ? userLevels.find(ul => ul.id === userLevel.parentLevelId)?.name || `Level ${userLevel.parentLevelId}` : `Level ${userLevel.parentLevelId}`} - -
- )} - - {userLevel.provinceId && ( -
- Province: - Province {userLevel.provinceId} -
- )} - -
- Created: - - {userLevel.createdAt ? new Date(userLevel.createdAt).toLocaleDateString() : 'N/A'} - -
-
- -
- - -
-
-
- )) : ''} -
- - {userLevels.length === 0 && !isLoading && ( - - -
- -

No User Levels Found

-

- Create your first user level to define approval hierarchy -

- -
-
-
- )} -
-
-
- ); -} export default function TenantSettingsPage() { - return ; + return ; } diff --git a/components/form/login.tsx b/components/form/login.tsx index 589610b..1a16e19 100644 --- a/components/form/login.tsx +++ b/components/form/login.tsx @@ -96,9 +96,15 @@ export default function Login() { Cookies.set("username", profile?.data?.data?.username, { expires: 1, }); - Cookies.set("urie", profile?.data?.data?.roleId, { + Cookies.set("urie", profile?.data?.data?.userRoleId, { expires: 1, }); + console.log( + "RRR", + profile?.data?.data?.role.id, + "TTTT", + profile?.data?.data?.roleId + ); Cookies.set("roleName", profile?.data?.data?.roleName, { expires: 1, }); @@ -114,7 +120,9 @@ export default function Login() { Cookies.set("email", profile?.data?.data?.email, { expires: 1, }); - router.push("/admin/dashboard"); + // router.push("/admin/dashboard"); + console.log("OOO", profile?.data?.data); + Cookies.set("status", "login", { expires: 1, }); diff --git a/components/landing-page/navbar.tsx b/components/landing-page/navbar.tsx index 0ed976e..bb9b32b 100644 --- a/components/landing-page/navbar.tsx +++ b/components/landing-page/navbar.tsx @@ -28,51 +28,61 @@ const PUBLIKASI_SUBMENU = [ export default function Navbar() { const [isSidebarOpen, setIsSidebarOpen] = useState(false); - const [user, setUser] = useState<{ - id: number; - name: string; - avatar: string; - } | null>(null); + // const [user, setUser] = useState<{ + // id: number; + // name: string; + // avatar: string; + // } | null>(null); const [isDropdownOpen, setDropdownOpen] = useState(false); const [showProfileMenu, setShowProfileMenu] = useState(false); const pathname = usePathname(); - useEffect(() => { - const roleId = getCookiesDecrypt("urie"); - console.log("roleId", roleId); - switch (roleId) { - case "3": - setUser({ - id: 3, - name: "Mabes Polri - Approver", - avatar: "/contributor.png", - }); - break; - case "7": - setUser({ - id: 7, - name: "DivHumas - RoMulmed - BagDise", - avatar: "/contributor.png", - }); - break; + // useEffect(() => { + // const roleId = getCookiesDecrypt("urie"); + // console.log("roleId", roleId); - case "6": - setUser({ - id: 11, - name: "jurnalis-kompas1", - avatar: "/contributor.png", - }); - break; + // switch (roleId) { + // case "1": + // setUser({ + // id: 1, + // name: "User Test", + // avatar: "/contributor.png", + // }); + // break; + // case "3": + // setUser({ + // id: 3, + // name: "Mabes Polri - Approver", + // avatar: "/contributor.png", + // }); + // break; - default: - setUser(null); - } - }, []); + // case "7": + // setUser({ + // id: 7, + // name: "DivHumas - RoMulmed - BagDise", + // avatar: "/contributor.png", + // }); + // break; - const isLoggedIn = user !== null; + // case "6": + // setUser({ + // id: 11, + // name: "jurnalis-kompas1", + // avatar: "/contributor.png", + // }); + // break; + + // default: + // setUser(null); + // } + // }, []); + + const roleId = getCookiesDecrypt("urie"); + const isLoggedIn = roleId !== null; const filteredNavItems = isLoggedIn ? NAV_ITEMS.filter((item) => item.label !== "Mengikuti") @@ -85,10 +95,27 @@ export default function Navbar() { window.location.href = "/"; - setUser(null); + // setUser(null); setShowProfileMenu(false); }; + const username = Cookies.get("username"); + const fullname = Cookies.get("ufne"); + // const router = useRouter(); + // const [detail, setDetail] = useState(); + + // const onLogout = () => { + // Object.keys(Cookies.get()).forEach((cookieName) => { + // Cookies.remove(cookieName); + // }); + + // router.push("/"); + // }; + const [isLogin, setIsLogin] = useState(false); + useEffect(() => { + setIsLogin(fullname ? true : false); + }, [fullname]); + return (
@@ -188,15 +215,15 @@ export default function Navbar() { >
{user.name}
- {user.name} + {fullname} diff --git a/components/modals/WorkflowModalProvider.tsx b/components/modals/WorkflowModalProvider.tsx index e53fb71..1eb132e 100644 --- a/components/modals/WorkflowModalProvider.tsx +++ b/components/modals/WorkflowModalProvider.tsx @@ -113,12 +113,12 @@ export function WorkflowModalProvider({ children }: WorkflowModalProviderProps) return ( {children} - + /> */} ); } diff --git a/components/partials/auth/login-form.tsx b/components/partials/auth/login-form.tsx index c83e0a1..f77d80f 100644 --- a/components/partials/auth/login-form.tsx +++ b/components/partials/auth/login-form.tsx @@ -171,7 +171,8 @@ const LoginForm = () => { setCookiesEncrypt("uie", profile?.data?.data?.id, { expires: 1, }); - setCookiesEncrypt("urie", profile?.data?.data?.roleId, { + console.log("QQQ", profile?.data?.data?.role.id, "LLL", profile?.data?.data?.roleId,) + setCookiesEncrypt("urie", profile?.data?.data?.userRoleId, { expires: 1, }); setCookiesEncrypt("urne", profile?.data?.data?.role?.name, { @@ -203,50 +204,53 @@ const LoginForm = () => { setCookiesEncrypt("uinse", profile?.data?.data?.instituteId, { expires: 1, }); - console.log("ssaddd", profile?.data?.data?.roleId); - if ( - Number(profile?.data?.data?.roleId) == 2 || - Number(profile?.data?.data?.roleId) == 3 || - Number(profile?.data?.data?.roleId) == 4 || - Number(profile?.data?.data?.roleId) == 9 || - Number(profile?.data?.data?.roleId) == 10 || - Number(profile?.data?.data?.roleId) == 11 || - Number(profile?.data?.data?.roleId) == 12 || - Number(profile?.data?.data?.roleId) == 18 || - Number(profile?.data?.data?.roleId) == 19 - ) { - if (profile?.data?.data?.roleId === 18) { - window.location.href = "/in/dashboard/executive-data"; - // router.push('/admin/dashboard'); - Cookies.set("status", "login", { - expires: 1, - }); - } else if (profile?.data?.data?.roleId === 2) { - window.location.href = "/in/dashboard/executive"; - Cookies.set("status", "login", { - expires: 1, - }); - } else if ( - profile?.data?.data?.userLevel?.id == 794 || - profile?.data?.data?.userLevel?.parentLevelId == 761 - ) { - window.location.href = "/in/dashboard"; - Cookies.set("status", "login", { - expires: 1, - }); - } else { - window.location.href = "/in/dashboard"; - // router.push('/admin/dashboard'); - Cookies.set("status", "login", { - expires: 1, - }); - } - } else { - window.location.href = "/"; - Cookies.set("status", "login", { - expires: 1, - }); - } + setCookiesEncrypt("username", profile?.data?.data?.username, { + expires: 1, + }); + console.log("KKKK", profile?.data?.data) + // if ( + // Number(profile?.data?.data?.roleId) == 2 || + // Number(profile?.data?.data?.roleId) == 3 || + // Number(profile?.data?.data?.roleId) == 4 || + // Number(profile?.data?.data?.roleId) == 9 || + // Number(profile?.data?.data?.roleId) == 10 || + // Number(profile?.data?.data?.roleId) == 11 || + // Number(profile?.data?.data?.roleId) == 12 || + // Number(profile?.data?.data?.roleId) == 18 || + // Number(profile?.data?.data?.roleId) == 19 + // ) { + // if (profile?.data?.data?.roleId === 18) { + // window.location.href = "/in/dashboard/executive-data"; + // // router.push('/admin/dashboard'); + // Cookies.set("status", "login", { + // expires: 1, + // }); + // } else if (profile?.data?.data?.roleId === 2) { + // window.location.href = "/in/dashboard/executive"; + // Cookies.set("status", "login", { + // expires: 1, + // }); + // } else if ( + // profile?.data?.data?.userLevel?.id == 794 || + // profile?.data?.data?.userLevel?.parentLevelId == 761 + // ) { + // window.location.href = "/in/dashboard"; + // Cookies.set("status", "login", { + // expires: 1, + // }); + // } else { + // window.location.href = "/in/dashboard"; + // // router.push('/admin/dashboard'); + // Cookies.set("status", "login", { + // expires: 1, + // }); + // } + // } else { + // window.location.href = "/"; + // Cookies.set("status", "login", { + // expires: 1, + // }); + // } } } catch (err: any) { toast.error(err.message || "An unexpected error occurred."); diff --git a/components/partials/header/profile-info.tsx b/components/partials/header/profile-info.tsx index 2f460d3..2d2fe4f 100644 --- a/components/partials/header/profile-info.tsx +++ b/components/partials/header/profile-info.tsx @@ -20,6 +20,7 @@ import Cookies from "js-cookie"; import { useEffect, useState } from "react"; import { useRouter } from "@/components/navigation"; import { getInfoProfile } from "@/service/auth"; +import { getCookiesDecrypt } from "@/lib/utils"; type Detail = { id: number; @@ -35,10 +36,11 @@ type Detail = { }; const ProfileInfo = () => { - const username = Cookies.get("access_token"); + const username = Cookies.get("username"); + const fullname = Cookies.get("ufne"); const picture = Cookies.get("profile_picture"); const router = useRouter(); - const [detail, setDetail] = useState(); + // const [detail, setDetail] = useState(); const onLogout = () => { Object.keys(Cookies.get()).forEach((cookieName) => { @@ -49,28 +51,28 @@ const ProfileInfo = () => { }; useEffect(() => { - if (!username) { + if (!fullname) { router.push("/auth"); } - }, [username]); + }, [fullname]); - useEffect(() => { - async function initState() { - const response = await getInfoProfile(); - const details = response?.data?.data; + // useEffect(() => { + // async function initState() { + // const response = await getInfoProfile(); + // const details = response?.data?.data; - setDetail(details); - console.log("data", details); - } + // setDetail(details); + // console.log("data", details); + // } - initState(); - }, []); + // initState(); + // }, []); return (
- {detail !== undefined ? ( + {/* {detail !== undefined ? ( */}
{ />
- {detail?.fullname} + {fullname}
-

({detail?.username})

+

({username})

- ) : ( + {/* ) : ( "" - )} + )} */}
{/* diff --git a/hooks/use-auth.ts b/hooks/use-auth.ts index 7a9cb24..4c5f4c2 100644 --- a/hooks/use-auth.ts +++ b/hooks/use-auth.ts @@ -33,6 +33,7 @@ import { AUTH_CONSTANTS, } from "@/lib/auth-utils"; import { warning } from "@/lib/swal"; +import { setCookiesEncrypt } from "@/lib/utils"; export const useAuth = (): AuthContextType => { const router = useRouter(); @@ -154,7 +155,7 @@ export const useAuth = (): AuthContextType => { Cookies.set("username", profile?.username, { expires: 1, }); - Cookies.set("urie", profile?.roleId, { + setCookiesEncrypt("urie", profile?.userRoleId, { expires: 1, }); Cookies.set("roleName", profile?.roleName, { diff --git a/lib/auth-utils.ts b/lib/auth-utils.ts index 524662c..7421f79 100644 --- a/lib/auth-utils.ts +++ b/lib/auth-utils.ts @@ -42,7 +42,7 @@ export const setProfileCookies = (profile: ProfileData): void => { Cookies.set("state-prov", profile.userLevel?.province?.provName || "", { expires: 1 }); setCookiesEncrypt("uie", profile.id, { expires: 1 }); - setCookiesEncrypt("urie", profile.roleId.toString(), { expires: 1 }); + setCookiesEncrypt("urie", profile.userRoleId.toString(), { expires: 1 }); setCookiesEncrypt("urne", profile.role?.name || "", { expires: 1 }); setCookiesEncrypt("ulie", profile.userLevel?.id.toString() || "", { expires: 1 }); setCookiesEncrypt("uplie", profile.userLevel?.parentLevelId?.toString() || "", { expires: 1 }); diff --git a/types/auth.ts b/types/auth.ts index 6b0aa2f..f3f1c36 100644 --- a/types/auth.ts +++ b/types/auth.ts @@ -53,6 +53,7 @@ export interface ProfileData { fullname: string; email: string; roleId: number; + userRoleId:number; role: { name: string; }; @@ -169,4 +170,5 @@ export interface AuthCookies { ulnae: string; // user level name encrypted uinse: string; // user institute id encrypted status: string; + username: string; } \ No newline at end of file