refactor(hr): move Custom Roles from Settings into the HR section
CI/CD / CI · API (dotnet build + test) (push) Successful in 42s
CI/CD / CI · Admin API (dotnet build) (push) Successful in 29s
CI/CD / CI · Dashboard (tsc) (push) Successful in 1m8s
CI/CD / CI · Admin Web (tsc) (push) Successful in 39s
CI/CD / CI · Website (tsc) (push) Successful in 45s
CI/CD / CI · Koja (tsc) (push) Successful in 50s
CI/CD / Deploy · all services (push) Successful in 2m47s

Custom roles is staff governance, so it belongs with the team — added a "Roles &
permissions" tab to the HR screen (owner-only) rendering the existing
CustomRolesPanel, and removed the Settings → Team → Custom Roles leaf/group.
fa/en/ar label added.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
soroush.asadi
2026-06-25 09:38:55 +03:30
parent eaf911e12c
commit aede5bfd97
6 changed files with 19 additions and 27 deletions
+2 -1
View File
@@ -438,7 +438,8 @@
"payroll": "الرواتب",
"access": "صلاحيات الفروع",
"credentials": "بيانات الدخول",
"team": "الموظفون"
"team": "الموظفون",
"roles": "الأدوار والصلاحيات"
},
"myAttendance": "حضوري",
"clockIn": "تسجيل دخول",
+2 -1
View File
@@ -457,7 +457,8 @@
"payroll": "Payroll",
"access": "Branch access",
"credentials": "Login credentials",
"team": "Team"
"team": "Team",
"roles": "Roles & permissions"
},
"myAttendance": "My attendance",
"clockIn": "Clock in",
+2 -1
View File
@@ -457,7 +457,8 @@
"payroll": "حقوق",
"access": "دسترسی شعب",
"credentials": "رمز ورود",
"team": "کارکنان"
"team": "کارکنان",
"roles": "نقش‌ها و دسترسی‌ها"
},
"myAttendance": "حضور من",
"clockIn": "ورود",
+10 -3
View File
@@ -14,6 +14,7 @@ import { Badge } from "@/components/ui/badge";
import { BranchAccessPanel } from "@/components/hr/branch-access-panel";
import { EmployeeCredentialsPanel } from "@/components/hr/employee-credentials-panel";
import { AddEmployeeForm } from "@/components/hr/add-employee-form";
import { CustomRolesPanel } from "@/components/settings/custom-roles-panel";
import { UserPlus } from "lucide-react";
interface Employee {
@@ -50,7 +51,7 @@ interface Salary {
isPaid: boolean;
}
type Tab = "team" | "attendance" | "leave" | "payroll" | "access" | "credentials";
type Tab = "team" | "attendance" | "leave" | "payroll" | "access" | "credentials" | "roles";
export function HrScreen() {
const t = useTranslations("hr");
@@ -58,6 +59,7 @@ export function HrScreen() {
const userId = useAuthStore((s) => s.user?.userId);
const role = useAuthStore((s) => s.user?.role);
const canManageAccess = role === "Owner" || role === "Manager";
const canManageRoles = role === "Owner";
const queryClient = useQueryClient();
const [tab, setTab] = useState<Tab>("team");
const [addingEmployee, setAddingEmployee] = useState(false);
@@ -126,8 +128,11 @@ export function HrScreen() {
<h2 className="text-xl font-bold">{t("title")}</h2>
<div className="flex flex-wrap gap-2">
{((["team", "attendance", "leave", "payroll", "access", "credentials"] as Tab[]).filter(
(key) => (key !== "access" && key !== "credentials") || canManageAccess
{((["team", "attendance", "leave", "payroll", "access", "credentials", "roles"] as Tab[]).filter(
(key) =>
key === "roles"
? canManageRoles
: (key !== "access" && key !== "credentials") || canManageAccess
)).map((key) => (
<Button
key={key}
@@ -282,6 +287,8 @@ export function HrScreen() {
{tab === "credentials" && canManageAccess && (
<EmployeeCredentialsPanel cafeId={cafeId} employees={employees} />
)}
{tab === "roles" && canManageRoles && <CustomRolesPanel cafeId={cafeId} />}
</div>
);
}
@@ -14,7 +14,6 @@ import { SettingsTerminalsPanel } from "@/components/settings/settings-terminals
import { SettingsPrinterPanel } from "@/components/settings/settings-printer-panel";
import { SettingsStationsPanel } from "@/components/settings/settings-stations-panel";
import { SettingsPrintTestPanel } from "@/components/settings/settings-print-test-panel";
import { CustomRolesPanel } from "@/components/settings/custom-roles-panel";
import {
DEFAULT_SETTINGS_LEAF,
groupForLeaf,
@@ -30,7 +29,6 @@ const LEAF_PAGE_TITLE: Record<SettingsLeafId, string> = {
"printer-config": "nav.printerSettings",
"printer-stations": "nav.printerStations",
"print-test": "nav.printTest",
"team-custom-roles": "nav.customRoles",
};
export function SettingsScreen() {
@@ -46,10 +44,7 @@ export function SettingsScreen() {
const toggleGroup = (group: SettingsGroupId) => {
setExpandedGroup((prev) => (prev === group ? prev : group));
const firstChild =
group === "shop" ? "shop-general" :
group === "team" ? "team-custom-roles" :
"printer-config";
const firstChild = group === "shop" ? "shop-general" : "printer-config";
if (groupForLeaf(activeLeaf) !== group) {
selectLeaf(firstChild);
}
@@ -115,10 +110,6 @@ export function SettingsScreen() {
onOpenPrinterSettings={() => selectLeaf("printer-config")}
/>
) : null}
{activeLeaf === "team-custom-roles" ? (
<CustomRolesPanel cafeId={cafeId} />
) : null}
</div>
</div>
</div>
@@ -1,4 +1,4 @@
export type SettingsGroupId = "shop" | "printer" | "team";
export type SettingsGroupId = "shop" | "printer";
export type SettingsLeafId =
| "shop-general"
@@ -7,8 +7,7 @@ export type SettingsLeafId =
| "shop-discover"
| "printer-config"
| "printer-stations"
| "print-test"
| "team-custom-roles";
| "print-test";
export type SettingsNavGroup = {
id: SettingsGroupId;
@@ -36,13 +35,6 @@ export const SETTINGS_NAV: SettingsNavGroup[] = [
{ id: "print-test", labelKey: "nav.printTest" },
],
},
{
id: "team",
labelKey: "nav.team",
children: [
{ id: "team-custom-roles", labelKey: "nav.customRoles" },
],
},
];
export const DEFAULT_SETTINGS_LEAF: SettingsLeafId = "shop-general";
@@ -50,6 +42,5 @@ export const DEFAULT_SETTINGS_LEAF: SettingsLeafId = "shop-general";
export function groupForLeaf(leaf: SettingsLeafId): SettingsGroupId {
if (leaf === "printer-config" || leaf === "printer-stations" || leaf === "print-test")
return "printer";
if (leaf === "team-custom-roles") return "team";
return "shop";
}