mirror of
https://github.com/chillpadclub/bedolaga-cabinet.git
synced 2026-07-29 18:13:47 +00:00
feat: add granular user permissions (balance, subscription, promo_group, referral, send_offer)
Split users:edit into fine-grained permissions. Guard UI sections with hasPermission checks so moderators only see what they can do.
This commit is contained in:
@@ -2618,7 +2618,12 @@
|
||||
"manage": "Manage",
|
||||
"ban": "Ban",
|
||||
"unban": "Unban",
|
||||
"assign": "Assign"
|
||||
"assign": "Assign",
|
||||
"promo_group": "Promo group",
|
||||
"balance": "Balance",
|
||||
"subscription": "Subscription",
|
||||
"send_offer": "Send offer",
|
||||
"referral": "Referral %"
|
||||
},
|
||||
"toggleSection": "Toggle all {{section}} permissions",
|
||||
"selectedPermissions_one": "{{count}} permission selected",
|
||||
|
||||
@@ -2407,7 +2407,12 @@
|
||||
"manage": "مدیریت",
|
||||
"ban": "مسدود کردن",
|
||||
"unban": "رفع مسدودیت",
|
||||
"assign": "اختصاص"
|
||||
"assign": "اختصاص",
|
||||
"promo_group": "گروه تبلیغاتی",
|
||||
"balance": "موجودی",
|
||||
"subscription": "اشتراک",
|
||||
"send_offer": "ارسال پیشنهاد",
|
||||
"referral": "درصد ارجاع"
|
||||
},
|
||||
"toggleSection": "تغییر وضعیت تمام مجوزهای {{section}}",
|
||||
"selectedPermissions_other": "{{count}} مجوز انتخاب شده",
|
||||
|
||||
@@ -3166,7 +3166,12 @@
|
||||
"manage": "Управление",
|
||||
"ban": "Бан",
|
||||
"unban": "Разбан",
|
||||
"assign": "Назначение"
|
||||
"assign": "Назначение",
|
||||
"promo_group": "Промо-группа",
|
||||
"balance": "Баланс",
|
||||
"subscription": "Подписка",
|
||||
"send_offer": "Промо-предложение",
|
||||
"referral": "Реф. процент"
|
||||
},
|
||||
"toggleSection": "Переключить все права {{section}}",
|
||||
"selectedPermissions_one": "{{count}} разрешение выбрано",
|
||||
|
||||
@@ -2406,7 +2406,12 @@
|
||||
"manage": "管理",
|
||||
"ban": "封禁",
|
||||
"unban": "解封",
|
||||
"assign": "分配"
|
||||
"assign": "分配",
|
||||
"promo_group": "促销组",
|
||||
"balance": "余额",
|
||||
"subscription": "订阅",
|
||||
"send_offer": "发送优惠",
|
||||
"referral": "推荐佣金"
|
||||
},
|
||||
"toggleSection": "切换所有 {{section}} 权限",
|
||||
"selectedPermissions_other": "已选择 {{count}} 个权限",
|
||||
|
||||
@@ -386,7 +386,7 @@ export default function AdminUserDetail() {
|
||||
useEffect(() => {
|
||||
if (activeTab === 'info') {
|
||||
loadReferrals();
|
||||
if (hasPermission('promo_groups:read')) loadPromoGroups();
|
||||
if (hasPermission('users:promo_group')) loadPromoGroups();
|
||||
}
|
||||
if (activeTab === 'sync' && hasPermission('users:sync')) loadSyncStatus();
|
||||
if (activeTab === 'subscription') {
|
||||
@@ -935,7 +935,7 @@ export default function AdminUserDetail() {
|
||||
<div className="rounded-xl bg-dark-800/50 p-3">
|
||||
<div className="mb-1 flex items-center justify-between">
|
||||
<span className="text-xs text-dark-500">{t('admin.users.detail.promoGroup')}</span>
|
||||
{hasPermission('promo_groups:read') && (
|
||||
{hasPermission('users:promo_group') && (
|
||||
<button
|
||||
onClick={() => setEditingPromoGroup(!editingPromoGroup)}
|
||||
className="text-xs text-accent-400 transition-colors hover:text-accent-300"
|
||||
@@ -989,6 +989,7 @@ export default function AdminUserDetail() {
|
||||
<span className="text-sm font-medium text-dark-200">
|
||||
{t('admin.users.detail.referral.title')}
|
||||
</span>
|
||||
{hasPermission('users:referral') && (
|
||||
<button
|
||||
onClick={() => {
|
||||
if (!editingReferralCommission) {
|
||||
@@ -1000,6 +1001,7 @@ export default function AdminUserDetail() {
|
||||
>
|
||||
{editingReferralCommission ? t('common.cancel') : t('common.edit')}
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
<div className="grid grid-cols-3 gap-3 text-center">
|
||||
<div>
|
||||
@@ -1358,6 +1360,7 @@ export default function AdminUserDetail() {
|
||||
)}
|
||||
|
||||
{/* Actions */}
|
||||
{hasPermission('users:subscription') && (
|
||||
<div className="rounded-xl bg-dark-800/50 p-4">
|
||||
<div className="mb-3 font-medium text-dark-200">
|
||||
{t('admin.users.detail.subscription.actions')}
|
||||
@@ -1368,11 +1371,15 @@ export default function AdminUserDetail() {
|
||||
onChange={(e) => setSubAction(e.target.value)}
|
||||
className="input"
|
||||
>
|
||||
<option value="extend">{t('admin.users.detail.subscription.extend')}</option>
|
||||
<option value="extend">
|
||||
{t('admin.users.detail.subscription.extend')}
|
||||
</option>
|
||||
<option value="change_tariff">
|
||||
{t('admin.users.detail.subscription.changeTariff')}
|
||||
</option>
|
||||
<option value="cancel">{t('admin.users.detail.subscription.cancel')}</option>
|
||||
<option value="cancel">
|
||||
{t('admin.users.detail.subscription.cancel')}
|
||||
</option>
|
||||
<option value="activate">
|
||||
{t('admin.users.detail.subscription.activate')}
|
||||
</option>
|
||||
@@ -1422,8 +1429,9 @@ export default function AdminUserDetail() {
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
) : hasPermission('users:subscription') ? (
|
||||
<div className="rounded-xl bg-dark-800/50 p-4">
|
||||
<div className="mb-4 text-center text-dark-400">
|
||||
{t('admin.users.detail.subscription.noActive')}
|
||||
@@ -1463,6 +1471,12 @@ export default function AdminUserDetail() {
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="rounded-xl bg-dark-800/50 p-4">
|
||||
<div className="text-center text-dark-400">
|
||||
{t('admin.users.detail.subscription.noActive')}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Panel Info */}
|
||||
@@ -1788,6 +1802,7 @@ export default function AdminUserDetail() {
|
||||
</div>
|
||||
|
||||
{/* Add/subtract form */}
|
||||
{hasPermission('users:balance') && (
|
||||
<div className="space-y-3 rounded-xl bg-dark-800/50 p-4">
|
||||
<input
|
||||
type="number"
|
||||
@@ -1821,6 +1836,7 @@ export default function AdminUserDetail() {
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Active promo offer */}
|
||||
{user.promo_offer_discount_percent > 0 && (
|
||||
@@ -1869,6 +1885,7 @@ export default function AdminUserDetail() {
|
||||
)}
|
||||
|
||||
{/* Send promo offer */}
|
||||
{hasPermission('users:send_offer') && (
|
||||
<div className="rounded-xl bg-dark-800/50 p-4">
|
||||
<div className="mb-3 text-sm font-medium text-dark-200">
|
||||
{t('admin.users.detail.sendOffer')}
|
||||
@@ -1901,6 +1918,7 @@ export default function AdminUserDetail() {
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Recent transactions */}
|
||||
{user.recent_transactions.length > 0 && (
|
||||
|
||||
Reference in New Issue
Block a user