85 lines
1.9 KiB
TypeScript
85 lines
1.9 KiB
TypeScript
import { usePermission } from '@/hooks/usePermission';
|
|
import { ReactNode } from 'react';
|
|
|
|
interface CanProps {
|
|
permission: string | string[];
|
|
children: ReactNode;
|
|
fallback?: ReactNode;
|
|
}
|
|
|
|
/**
|
|
* 權限判斷元件 - 類似 Blade 的 @can 指令
|
|
*
|
|
* @example
|
|
* ```tsx
|
|
* <Can permission="products.create">
|
|
* <button>新增商品</button>
|
|
* </Can>
|
|
*
|
|
* <Can permission={['products.edit', 'products.delete']}>
|
|
* <div>管理操作</div>
|
|
* </Can>
|
|
* ```
|
|
*/
|
|
export function Can({ permission, children, fallback = null }: CanProps) {
|
|
const { can, canAny } = usePermission();
|
|
|
|
const hasPermission = Array.isArray(permission)
|
|
? canAny(permission)
|
|
: can(permission);
|
|
|
|
return hasPermission ? <>{children}</> : <>{fallback}</>;
|
|
}
|
|
|
|
interface HasRoleProps {
|
|
role: string | string[];
|
|
children: ReactNode;
|
|
fallback?: ReactNode;
|
|
}
|
|
|
|
/**
|
|
* 角色判斷元件 - 類似 Blade 的 @role 指令
|
|
*
|
|
* @example
|
|
* ```tsx
|
|
* <HasRole role="admin">
|
|
* <Link href="/admin">管理後台</Link>
|
|
* </HasRole>
|
|
*
|
|
* <HasRole role={['admin', 'manager']}>
|
|
* <button>管理選項</button>
|
|
* </HasRole>
|
|
* ```
|
|
*/
|
|
export function HasRole({ role, children, fallback = null }: HasRoleProps) {
|
|
const { hasRole, hasAnyRole } = usePermission();
|
|
|
|
const hasRequiredRole = Array.isArray(role)
|
|
? hasAnyRole(role)
|
|
: hasRole(role);
|
|
|
|
return hasRequiredRole ? <>{children}</> : <>{fallback}</>;
|
|
}
|
|
|
|
interface CanAllProps {
|
|
permissions: string[];
|
|
children: ReactNode;
|
|
fallback?: ReactNode;
|
|
}
|
|
|
|
/**
|
|
* 檢查是否擁有所有權限
|
|
*
|
|
* @example
|
|
* ```tsx
|
|
* <CanAll permissions={['products.edit', 'products.delete']}>
|
|
* <button>完整管理</button>
|
|
* </CanAll>
|
|
* ```
|
|
*/
|
|
export function CanAll({ permissions, children, fallback = null }: CanAllProps) {
|
|
const { canAll } = usePermission();
|
|
|
|
return canAll(permissions) ? <>{children}</> : <>{fallback}</>;
|
|
}
|