[STYLE] 商品管理與分類管理 UI 標準化,補全多語系翻譯
All checks were successful
star-cloud-deploy-demo / deploy-demo (push) Successful in 50s
All checks were successful
star-cloud-deploy-demo / deploy-demo (push) Successful in 50s
This commit is contained in:
@@ -131,7 +131,7 @@ class MachineController extends AdminController
|
|||||||
*/
|
*/
|
||||||
public function slotsAjax(Machine $machine)
|
public function slotsAjax(Machine $machine)
|
||||||
{
|
{
|
||||||
$slots = $machine->slots()->with('product:id,name,image')->orderByRaw('CAST(slot_no AS UNSIGNED) ASC')->get();
|
$slots = $machine->slots()->with('product:id,name,image_url')->orderByRaw('CAST(slot_no AS UNSIGNED) ASC')->get();
|
||||||
|
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'success' => true,
|
'success' => true,
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ class PermissionController extends Controller
|
|||||||
// 篩選:公司名稱 (僅限系統管理員)
|
// 篩選:公司名稱 (僅限系統管理員)
|
||||||
if ($user->isSystemAdmin() && request()->filled('company_id')) {
|
if ($user->isSystemAdmin() && request()->filled('company_id')) {
|
||||||
if (request()->company_id === 'system') {
|
if (request()->company_id === 'system') {
|
||||||
$query->where('is_system', true);
|
$query->whereNull('company_id');
|
||||||
} else {
|
} else {
|
||||||
$query->where('company_id', request()->company_id);
|
$query->where('company_id', request()->company_id);
|
||||||
}
|
}
|
||||||
@@ -36,7 +36,9 @@ class PermissionController extends Controller
|
|||||||
$roles = $query->latest()->paginate($per_page)->withQueryString();
|
$roles = $query->latest()->paginate($per_page)->withQueryString();
|
||||||
$companies = $user->isSystemAdmin() ? \App\Models\System\Company::all() : collect();
|
$companies = $user->isSystemAdmin() ? \App\Models\System\Company::all() : collect();
|
||||||
|
|
||||||
// 權限遞迴約束:租戶管理員只能看到並指派自己擁有的權限
|
// 權限分組邏輯中的標題與過濾
|
||||||
|
$isSubAccountRoles = request()->routeIs('*.sub-account-roles');
|
||||||
|
$title = $isSubAccountRoles ? __('Sub Account Roles') : __('Role Settings');
|
||||||
$permissionQuery = \Spatie\Permission\Models\Permission::query();
|
$permissionQuery = \Spatie\Permission\Models\Permission::query();
|
||||||
if (!$user->isSystemAdmin()) {
|
if (!$user->isSystemAdmin()) {
|
||||||
$permissionQuery->whereIn('name', $user->getAllPermissions()->pluck('name'));
|
$permissionQuery->whereIn('name', $user->getAllPermissions()->pluck('name'));
|
||||||
@@ -44,17 +46,13 @@ class PermissionController extends Controller
|
|||||||
|
|
||||||
// 權限分組邏輯
|
// 權限分組邏輯
|
||||||
$all_permissions = $permissionQuery->get()
|
$all_permissions = $permissionQuery->get()
|
||||||
|
->reject(fn($p) => $p->name === 'menu.data-config.sub-account-roles')
|
||||||
->groupBy(function($perm) {
|
->groupBy(function($perm) {
|
||||||
if (str_starts_with($perm->name, 'menu.')) {
|
if (str_starts_with($perm->name, 'menu.')) {
|
||||||
// 主選單權限:menu.xxx (兩段)
|
|
||||||
// 子選單權限:menu.xxx.yyy (三段)
|
|
||||||
return 'menu';
|
return 'menu';
|
||||||
}
|
}
|
||||||
return 'other';
|
return 'other';
|
||||||
});
|
});
|
||||||
|
|
||||||
// 根據路由決定標題
|
|
||||||
$title = request()->routeIs('*.sub-account-roles') ? __('Sub Account Roles') : __('Role Settings');
|
|
||||||
|
|
||||||
$currentUserRoleIds = $user->roles->pluck('id')->toArray();
|
$currentUserRoleIds = $user->roles->pluck('id')->toArray();
|
||||||
return view('admin.permission.roles', compact('roles', 'all_permissions', 'title', 'currentUserRoleIds', 'companies'));
|
return view('admin.permission.roles', compact('roles', 'all_permissions', 'title', 'currentUserRoleIds', 'companies'));
|
||||||
@@ -77,7 +75,9 @@ class PermissionController extends Controller
|
|||||||
$all_permissions = $permissionQuery->get()->groupBy(fn($p) => str_starts_with($p->name, 'menu.') ? 'menu' : 'other');
|
$all_permissions = $permissionQuery->get()->groupBy(fn($p) => str_starts_with($p->name, 'menu.') ? 'menu' : 'other');
|
||||||
|
|
||||||
$title = request()->routeIs('*.sub-account-roles.create') ? __('Create Sub Account Role') : __('Create New Role');
|
$title = request()->routeIs('*.sub-account-roles.create') ? __('Create Sub Account Role') : __('Create New Role');
|
||||||
$back_url = request()->routeIs('*.sub-account-roles.create') ? route('admin.data-config.sub-account-roles') : route('admin.permission.roles');
|
$back_url = request()->routeIs('*.sub-account-roles.create')
|
||||||
|
? route('admin.data-config.sub-accounts', ['tab' => 'roles'])
|
||||||
|
: route('admin.permission.roles');
|
||||||
|
|
||||||
return view('admin.permission.roles-edit', compact('role', 'all_permissions', 'title', 'back_url'));
|
return view('admin.permission.roles-edit', compact('role', 'all_permissions', 'title', 'back_url'));
|
||||||
}
|
}
|
||||||
@@ -98,6 +98,7 @@ class PermissionController extends Controller
|
|||||||
|
|
||||||
// 權限分組邏輯
|
// 權限分組邏輯
|
||||||
$all_permissions = $permissionQuery->get()
|
$all_permissions = $permissionQuery->get()
|
||||||
|
->reject(fn($p) => $p->name === 'menu.data-config.sub-account-roles')
|
||||||
->groupBy(function($perm) {
|
->groupBy(function($perm) {
|
||||||
if (str_starts_with($perm->name, 'menu.')) {
|
if (str_starts_with($perm->name, 'menu.')) {
|
||||||
return 'menu';
|
return 'menu';
|
||||||
@@ -109,7 +110,9 @@ class PermissionController extends Controller
|
|||||||
$title = request()->routeIs('*.sub-account-roles.edit') ? __('Edit Sub Account Role') : __('Edit Role Permissions');
|
$title = request()->routeIs('*.sub-account-roles.edit') ? __('Edit Sub Account Role') : __('Edit Role Permissions');
|
||||||
|
|
||||||
// 麵包屑/返回路徑
|
// 麵包屑/返回路徑
|
||||||
$back_url = request()->routeIs('*.sub-account-roles.edit') ? route('admin.data-config.sub-account-roles') : route('admin.permission.roles');
|
$back_url = request()->routeIs('*.sub-account-roles.edit')
|
||||||
|
? route('admin.data-config.sub-accounts', ['tab' => 'roles'])
|
||||||
|
: route('admin.permission.roles');
|
||||||
|
|
||||||
return view('admin.permission.roles-edit', compact('role', 'all_permissions', 'title', 'back_url'));
|
return view('admin.permission.roles-edit', compact('role', 'all_permissions', 'title', 'back_url'));
|
||||||
}
|
}
|
||||||
@@ -158,8 +161,8 @@ class PermissionController extends Controller
|
|||||||
$role->syncPermissions($perms);
|
$role->syncPermissions($perms);
|
||||||
}
|
}
|
||||||
|
|
||||||
$target_route = request()->routeIs('*.sub-account-roles.*') ? 'admin.data-config.sub-account-roles' : 'admin.permission.roles';
|
$target_route = request()->routeIs('*.sub-account-roles.*') ? route('admin.data-config.sub-accounts', ['tab' => 'roles']) : route('admin.permission.roles');
|
||||||
return redirect()->route($target_route)->with('success', __('Role created successfully.'));
|
return redirect()->to($target_route)->with('success', __('Role created successfully.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -219,8 +222,8 @@ class PermissionController extends Controller
|
|||||||
}
|
}
|
||||||
$role->syncPermissions($perms);
|
$role->syncPermissions($perms);
|
||||||
|
|
||||||
$target_route = request()->routeIs('*.sub-account-roles.*') ? 'admin.data-config.sub-account-roles' : 'admin.permission.roles';
|
$target_route = request()->routeIs('*.sub-account-roles.*') ? route('admin.data-config.sub-accounts', ['tab' => 'roles']) : route('admin.permission.roles');
|
||||||
return redirect()->route($target_route)->with('success', __('Role updated successfully.'));
|
return redirect()->to($target_route)->with('success', __('Role updated successfully.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -244,46 +247,95 @@ class PermissionController extends Controller
|
|||||||
|
|
||||||
$role->delete();
|
$role->delete();
|
||||||
|
|
||||||
|
if (request()->routeIs('*.sub-account-roles.*')) {
|
||||||
|
return redirect()->route('admin.data-config.sub-accounts', ['tab' => 'roles'])->with('success', __('Role deleted successfully.'));
|
||||||
|
}
|
||||||
|
|
||||||
return redirect()->back()->with('success', __('Role deleted successfully.'));
|
return redirect()->back()->with('success', __('Role deleted successfully.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 帳號管理
|
// 帳號管理
|
||||||
public function accounts(Request $request)
|
public function accounts(Request $request)
|
||||||
{
|
{
|
||||||
$query = \App\Models\System\User::query()->with(['company', 'roles', 'machines']);
|
$user = auth()->user();
|
||||||
|
$isSubAccountRoute = $request->routeIs('admin.data-config.sub-accounts');
|
||||||
|
$tab = $request->input('tab', 'accounts');
|
||||||
|
|
||||||
// 租戶隔離:如果不是系統管理員,則只看自己公司的成員
|
// 初始化變數
|
||||||
if (!auth()->user()->isSystemAdmin()) {
|
$users = collect();
|
||||||
$query->where('company_id', auth()->user()->company_id);
|
$roles = collect();
|
||||||
|
$paginated_roles = collect();
|
||||||
|
$all_permissions = collect();
|
||||||
|
$currentUserRoleIds = $user->roles->pluck('id')->toArray();
|
||||||
|
$companies = $user->isSystemAdmin() ? \App\Models\System\Company::all() : collect();
|
||||||
|
|
||||||
|
if ($isSubAccountRoute && $tab === 'roles') {
|
||||||
|
// 處理角色分頁邏輯 (移植自 roles())
|
||||||
|
$per_page = $request->input('per_page', 10);
|
||||||
|
$roles_query = \App\Models\System\Role::query()->with(['permissions', 'users', 'company']);
|
||||||
|
|
||||||
|
if (!$user->isSystemAdmin()) {
|
||||||
|
$roles_query->where('company_id', $user->company_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($search = $request->input('search')) {
|
||||||
|
$roles_query->where('name', 'like', "%{$search}%");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($user->isSystemAdmin() && $request->filled('company_id')) {
|
||||||
|
if ($request->company_id === 'system') {
|
||||||
|
$roles_query->where('is_system', true);
|
||||||
|
} else {
|
||||||
|
$roles_query->where('company_id', $request->company_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$paginated_roles = $roles_query->latest()->paginate($per_page)->withQueryString();
|
||||||
|
|
||||||
|
// 權限分組邏輯
|
||||||
|
$permissionQuery = \Spatie\Permission\Models\Permission::query();
|
||||||
|
if (!$user->isSystemAdmin()) {
|
||||||
|
$permissionQuery->whereIn('name', $user->getAllPermissions()->pluck('name'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$all_permissions = $permissionQuery->get()
|
||||||
|
->reject(fn($p) => $p->name === 'menu.data-config.sub-account-roles')
|
||||||
|
->groupBy(fn($p) => str_starts_with($p->name, 'menu.') ? 'menu' : 'other');
|
||||||
|
} else {
|
||||||
|
// 處理帳號名單邏輯
|
||||||
|
$query = \App\Models\System\User::query()->with(['company', 'roles', 'machines']);
|
||||||
|
|
||||||
|
if (!$user->isSystemAdmin()) {
|
||||||
|
$query->where('company_id', $user->company_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($search = $request->input('search')) {
|
||||||
|
$query->where(function($q) use ($search) {
|
||||||
|
$q->where('name', 'like', "%{$search}%")
|
||||||
|
->orWhere('username', 'like', "%{$search}%")
|
||||||
|
->orWhere('email', 'like', "%{$search}%");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($user->isSystemAdmin() && $request->filled('company_id')) {
|
||||||
|
$query->where('company_id', $request->company_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
$per_page = $request->input('per_page', 10);
|
||||||
|
$users = $query->latest()->paginate($per_page)->withQueryString();
|
||||||
|
|
||||||
|
$roles_query = \App\Models\System\Role::query();
|
||||||
|
if (!$user->isSystemAdmin()) {
|
||||||
|
$roles_query->forCompany($user->company_id);
|
||||||
|
}
|
||||||
|
$roles = $roles_query->get();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 搜尋
|
$title = $isSubAccountRoute ? __('Sub Account Management') : __('Account Management');
|
||||||
if ($search = $request->input('search')) {
|
|
||||||
$query->where(function($q) use ($search) {
|
|
||||||
$q->where('name', 'like', "%{$search}%")
|
|
||||||
->orWhere('username', 'like', "%{$search}%")
|
|
||||||
->orWhere('email', 'like', "%{$search}%");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 公司篩選 (僅限 super-admin)
|
return view('admin.data-config.accounts', compact(
|
||||||
if (auth()->user()->isSystemAdmin() && $request->filled('company_id')) {
|
'users', 'companies', 'roles', 'paginated_roles', 'all_permissions', 'title', 'tab', 'currentUserRoleIds'
|
||||||
$query->where('company_id', $request->company_id);
|
));
|
||||||
}
|
|
||||||
|
|
||||||
$per_page = $request->input('per_page', 10);
|
|
||||||
$users = $query->latest()->paginate($per_page)->withQueryString();
|
|
||||||
$companies = auth()->user()->isSystemAdmin() ? \App\Models\System\Company::all() : collect();
|
|
||||||
$roles_query = \App\Models\System\Role::query();
|
|
||||||
if (!auth()->user()->isSystemAdmin()) {
|
|
||||||
$roles_query->forCompany(auth()->user()->company_id);
|
|
||||||
}
|
|
||||||
$roles = $roles_query->get();
|
|
||||||
|
|
||||||
// 根據路由決定標題
|
|
||||||
$title = request()->routeIs('*.sub-accounts') ? __('Sub Account Management') : __('Account Management');
|
|
||||||
|
|
||||||
return view('admin.data-config.accounts', compact('users', 'companies', 'roles', 'title'));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
// 1. 取得權限 ID
|
||||||
|
$permission = DB::table('permissions')
|
||||||
|
->where('name', 'menu.data-config.sub-account-roles')
|
||||||
|
->first();
|
||||||
|
|
||||||
|
if ($permission) {
|
||||||
|
// 2. 移除角色與該權限的關聯 (雖然 Spatie 通常會處理,但手動確保清理乾淨)
|
||||||
|
DB::table('role_has_permissions')
|
||||||
|
->where('permission_id', $permission->id)
|
||||||
|
->delete();
|
||||||
|
|
||||||
|
// 3. 移除權限本身
|
||||||
|
DB::table('permissions')
|
||||||
|
->where('id', $permission->id)
|
||||||
|
->delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 清理權限快取 (如果有的話)
|
||||||
|
try {
|
||||||
|
app()[\Spatie\Permission\PermissionRegistrar::class]->forgetCachedPermissions();
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
// 忽略快取清理失敗(例如在沒有 Redis 的環境中)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
// 由於是要永久拿掉,down 邏輯通常不需要重建,
|
||||||
|
// 若真要復原,應透過重跑 Seeder 或手動新增。
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -34,7 +34,6 @@ class RoleSeeder extends Seeder
|
|||||||
'menu.data-config.products',
|
'menu.data-config.products',
|
||||||
'menu.data-config.advertisements',
|
'menu.data-config.advertisements',
|
||||||
'menu.data-config.sub-accounts',
|
'menu.data-config.sub-accounts',
|
||||||
'menu.data-config.sub-account-roles',
|
|
||||||
'menu.data-config.points',
|
'menu.data-config.points',
|
||||||
'menu.data-config.badges',
|
'menu.data-config.badges',
|
||||||
'menu.remote',
|
'menu.remote',
|
||||||
@@ -81,7 +80,6 @@ class RoleSeeder extends Seeder
|
|||||||
'menu.data-config.products',
|
'menu.data-config.products',
|
||||||
'menu.data-config.advertisements',
|
'menu.data-config.advertisements',
|
||||||
'menu.data-config.sub-accounts',
|
'menu.data-config.sub-accounts',
|
||||||
'menu.data-config.sub-account-roles',
|
|
||||||
'menu.data-config.points',
|
'menu.data-config.points',
|
||||||
'menu.data-config.badges',
|
'menu.data-config.badges',
|
||||||
'menu.remote',
|
'menu.remote',
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
"Account": "Account",
|
"Account": "Account",
|
||||||
"Account :name status has been changed to :status.": "Account :name status has been changed to :status.",
|
"Account :name status has been changed to :status.": "Account :name status has been changed to :status.",
|
||||||
"Account Info": "Account Info",
|
"Account Info": "Account Info",
|
||||||
|
"Account List": "Account List",
|
||||||
"Account Management": "Account Management",
|
"Account Management": "Account Management",
|
||||||
"Account Name": "Account Name",
|
"Account Name": "Account Name",
|
||||||
"Account Settings": "Account Settings",
|
"Account Settings": "Account Settings",
|
||||||
@@ -429,6 +430,7 @@
|
|||||||
"No matching machines": "No matching machines",
|
"No matching machines": "No matching machines",
|
||||||
"No permissions": "No permissions",
|
"No permissions": "No permissions",
|
||||||
"No roles found.": "No roles found.",
|
"No roles found.": "No roles found.",
|
||||||
|
"No roles available": "No roles available",
|
||||||
"No slots found": "No slots found",
|
"No slots found": "No slots found",
|
||||||
"No users found": "No users found",
|
"No users found": "No users found",
|
||||||
"None": "None",
|
"None": "None",
|
||||||
@@ -559,7 +561,7 @@
|
|||||||
"Risk": "Risk",
|
"Risk": "Risk",
|
||||||
"Role": "Role",
|
"Role": "Role",
|
||||||
"Role Identification": "Role Identification",
|
"Role Identification": "Role Identification",
|
||||||
"Role Management": "Role Permission Management",
|
"Role Management": "Role Management",
|
||||||
"Role Name": "Role Name",
|
"Role Name": "Role Name",
|
||||||
"Role Permissions": "Role Permissions",
|
"Role Permissions": "Role Permissions",
|
||||||
"Role Settings": "Role Permissions",
|
"Role Settings": "Role Permissions",
|
||||||
@@ -777,7 +779,6 @@
|
|||||||
"menu.data-config.badges": "Badge Settings",
|
"menu.data-config.badges": "Badge Settings",
|
||||||
"menu.data-config.points": "Point Settings",
|
"menu.data-config.points": "Point Settings",
|
||||||
"menu.data-config.products": "Product Management",
|
"menu.data-config.products": "Product Management",
|
||||||
"menu.data-config.sub-account-roles": "Sub Account Roles",
|
|
||||||
"menu.data-config.sub-accounts": "Sub Account Management",
|
"menu.data-config.sub-accounts": "Sub Account Management",
|
||||||
"menu.line": "Line Management",
|
"menu.line": "Line Management",
|
||||||
"menu.machines": "Machine Management",
|
"menu.machines": "Machine Management",
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
"Account": "帳號",
|
"Account": "帳號",
|
||||||
"Account :name status has been changed to :status.": "アカウント :name のステータスが :status に変更されました。",
|
"Account :name status has been changed to :status.": "アカウント :name のステータスが :status に変更されました。",
|
||||||
"Account Management": "アカウント管理",
|
"Account Management": "アカウント管理",
|
||||||
|
"Account List": "アカウント一覧",
|
||||||
"Account Name": "帳號姓名",
|
"Account Name": "帳號姓名",
|
||||||
"Account Settings": "アカウント設定",
|
"Account Settings": "アカウント設定",
|
||||||
"Account Status": "アカウント狀態",
|
"Account Status": "アカウント狀態",
|
||||||
@@ -424,6 +425,7 @@
|
|||||||
"No matching machines": "一致する機台がありません",
|
"No matching machines": "一致する機台がありません",
|
||||||
"No permissions": "権限項目なし",
|
"No permissions": "権限項目なし",
|
||||||
"No roles found.": "ロールが見つかりませんでした。",
|
"No roles found.": "ロールが見つかりませんでした。",
|
||||||
|
"No roles available": "利用可能なロールがありません",
|
||||||
"No slots found": "未找到貨道資訊",
|
"No slots found": "未找到貨道資訊",
|
||||||
"No users found": "ユーザーが見つかりません",
|
"No users found": "ユーザーが見つかりません",
|
||||||
"None": "なし",
|
"None": "なし",
|
||||||
@@ -557,7 +559,7 @@
|
|||||||
"Risk": "リスク",
|
"Risk": "リスク",
|
||||||
"Role": "ロール",
|
"Role": "ロール",
|
||||||
"Role Identification": "ロール識別情報",
|
"Role Identification": "ロール識別情報",
|
||||||
"Role Management": "ロール權限管理",
|
"Role Management": "ロール管理",
|
||||||
"Role Name": "ロール名",
|
"Role Name": "ロール名",
|
||||||
"Role Permissions": "ロール權限",
|
"Role Permissions": "ロール權限",
|
||||||
"Role Settings": "ロール權限",
|
"Role Settings": "ロール權限",
|
||||||
@@ -777,7 +779,6 @@
|
|||||||
"menu.data-config.badges": "バッジ設定",
|
"menu.data-config.badges": "バッジ設定",
|
||||||
"menu.data-config.points": "ポイント設定",
|
"menu.data-config.points": "ポイント設定",
|
||||||
"menu.data-config.products": "商品管理",
|
"menu.data-config.products": "商品管理",
|
||||||
"menu.data-config.sub-account-roles": "サブアカウントロール",
|
|
||||||
"menu.data-config.sub-accounts": "サブアカウント管理",
|
"menu.data-config.sub-accounts": "サブアカウント管理",
|
||||||
"menu.line": "LINE 設定",
|
"menu.line": "LINE 設定",
|
||||||
"menu.machines": "機台管理",
|
"menu.machines": "機台管理",
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
"Account": "帳號",
|
"Account": "帳號",
|
||||||
"Account :name status has been changed to :status.": "帳號 :name 的狀態已變更為 :status。",
|
"Account :name status has been changed to :status.": "帳號 :name 的狀態已變更為 :status。",
|
||||||
"Account Info": "帳號資訊",
|
"Account Info": "帳號資訊",
|
||||||
|
"Account List": "帳號列表",
|
||||||
"Account Management": "帳號管理",
|
"Account Management": "帳號管理",
|
||||||
"Account Name": "帳號名稱",
|
"Account Name": "帳號名稱",
|
||||||
"Account Settings": "帳戶設定",
|
"Account Settings": "帳戶設定",
|
||||||
@@ -439,6 +440,7 @@
|
|||||||
"No matching machines": "查無匹配機台",
|
"No matching machines": "查無匹配機台",
|
||||||
"No permissions": "無權限項目",
|
"No permissions": "無權限項目",
|
||||||
"No roles found.": "找不到角色資料。",
|
"No roles found.": "找不到角色資料。",
|
||||||
|
"No roles available": "目前沒有角色資料。",
|
||||||
"No slots found": "未找到貨道資訊",
|
"No slots found": "未找到貨道資訊",
|
||||||
"No users found": "找不到用戶資料",
|
"No users found": "找不到用戶資料",
|
||||||
"None": "無",
|
"None": "無",
|
||||||
@@ -806,7 +808,6 @@
|
|||||||
"menu.data-config.badges": "徽章設定",
|
"menu.data-config.badges": "徽章設定",
|
||||||
"menu.data-config.points": "點數設定",
|
"menu.data-config.points": "點數設定",
|
||||||
"menu.data-config.products": "商品管理",
|
"menu.data-config.products": "商品管理",
|
||||||
"menu.data-config.sub-account-roles": "子帳號角色",
|
|
||||||
"menu.data-config.sub-accounts": "子帳號管理",
|
"menu.data-config.sub-accounts": "子帳號管理",
|
||||||
"menu.line": "LINE 配置",
|
"menu.line": "LINE 配置",
|
||||||
"menu.machines": "機台管理",
|
"menu.machines": "機台管理",
|
||||||
@@ -912,5 +913,6 @@
|
|||||||
"System Default (All Companies)": "系統預設 (所有公司)",
|
"System Default (All Companies)": "系統預設 (所有公司)",
|
||||||
"No materials available": "沒有可用的素材",
|
"No materials available": "沒有可用的素材",
|
||||||
"Search...": "搜尋...",
|
"Search...": "搜尋...",
|
||||||
|
"Category Name": "分類名稱",
|
||||||
"Category Management": "分類管理"
|
"Category Management": "分類管理"
|
||||||
}
|
}
|
||||||
@@ -297,7 +297,7 @@
|
|||||||
<td class="px-6 py-6 cursor-pointer" @click='openDetail({{ $machine->toJson() }}, {{ $machine->id }}, "{{ $machine->serial_no }}")'>
|
<td class="px-6 py-6 cursor-pointer" @click='openDetail({{ $machine->toJson() }}, {{ $machine->id }}, "{{ $machine->serial_no }}")'>
|
||||||
<div class="flex items-center gap-4">
|
<div class="flex items-center gap-4">
|
||||||
<div
|
<div
|
||||||
class="w-10 h-10 rounded-xl bg-slate-100 dark:bg-slate-800 flex items-center justify-center text-slate-400 border border-slate-200 dark:border-slate-700 group-hover:bg-cyan-500 group-hover:text-white transition-all duration-300 overflow-hidden">
|
class="w-10 h-10 rounded-xl bg-slate-100 dark:bg-slate-800 flex items-center justify-center text-slate-400 border border-slate-200 dark:border-slate-700 group-hover:bg-cyan-500 group-hover:text-white group-hover:border-cyan-500 shadow-sm group-hover:shadow-cyan-500/50 transition-all duration-300 overflow-hidden">
|
||||||
@if(isset($machine->image_urls[0]))
|
@if(isset($machine->image_urls[0]))
|
||||||
<img src="{{ $machine->image_urls[0] }}" class="w-full h-full object-cover">
|
<img src="{{ $machine->image_urls[0] }}" class="w-full h-full object-cover">
|
||||||
@else
|
@else
|
||||||
@@ -437,7 +437,7 @@
|
|||||||
<td class="px-6 py-6 font-display text-left">
|
<td class="px-6 py-6 font-display text-left">
|
||||||
<div class="flex items-center gap-4 text-left">
|
<div class="flex items-center gap-4 text-left">
|
||||||
<div
|
<div
|
||||||
class="w-10 h-10 rounded-xl bg-slate-100 dark:bg-slate-800 flex items-center justify-center text-slate-400 border border-slate-200 dark:border-slate-700">
|
class="w-10 h-10 rounded-xl bg-slate-100 dark:bg-slate-800 flex items-center justify-center text-slate-400 border border-slate-200 dark:border-slate-700 group-hover:bg-cyan-500 group-hover:text-white group-hover:border-cyan-500 shadow-sm group-hover:shadow-cyan-500/50 transition-all duration-300">
|
||||||
<svg class="size-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
<svg class="size-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2.5"
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2.5"
|
||||||
d="M15.75 6a3.75 3.75 0 1 1-7.5 0 3.75 3.75 0 0 1 7.5 0ZM4.501 20.118a7.5 7.5 0 0 1 14.998 0A17.933 17.933 0 0 1 12 21.75c-2.676 0-5.216-.584-7.499-1.632Z" />
|
d="M15.75 6a3.75 3.75 0 1 1-7.5 0 3.75 3.75 0 0 1 7.5 0ZM4.501 20.118a7.5 7.5 0 0 1 14.998 0A17.933 17.933 0 0 1 12 21.75c-2.676 0-5.216-.584-7.499-1.632Z" />
|
||||||
@@ -540,7 +540,7 @@
|
|||||||
<td class="px-6 py-6">
|
<td class="px-6 py-6">
|
||||||
<div class="flex items-center gap-x-3">
|
<div class="flex items-center gap-x-3">
|
||||||
<div
|
<div
|
||||||
class="flex-shrink-0 w-10 h-10 rounded-xl bg-slate-100 dark:bg-slate-800 flex items-center justify-center text-slate-400 border border-slate-200 dark:border-slate-700 group-hover:bg-cyan-500 group-hover:text-white transition-all duration-300">
|
class="flex-shrink-0 w-10 h-10 rounded-xl bg-slate-100 dark:bg-slate-800 flex items-center justify-center text-slate-400 border border-slate-200 dark:border-slate-700 group-hover:bg-cyan-500 group-hover:text-white group-hover:border-cyan-500 shadow-sm group-hover:shadow-cyan-500/50 transition-all duration-300">
|
||||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"
|
||||||
stroke-width="2">
|
stroke-width="2">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round"
|
<path stroke-linecap="round" stroke-linejoin="round"
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ $roleSelectConfig = [
|
|||||||
@endphp
|
@endphp
|
||||||
|
|
||||||
@section('content')
|
@section('content')
|
||||||
<div class="space-y-6 pb-20" x-data="accountManager({
|
<div class="space-y-2 pb-20" x-data="accountManager({
|
||||||
roles: @js($roles),
|
roles: @js($roles),
|
||||||
errors: @js($errors->any()),
|
errors: @js($errors->any()),
|
||||||
oldValues: {
|
oldValues: {
|
||||||
@@ -42,212 +42,338 @@ $roleSelectConfig = [
|
|||||||
<div>
|
<div>
|
||||||
<h1 class="text-3xl font-black text-slate-800 dark:text-white font-display tracking-tight">{{ $title }}</h1>
|
<h1 class="text-3xl font-black text-slate-800 dark:text-white font-display tracking-tight">{{ $title }}</h1>
|
||||||
<p class="text-sm font-bold text-slate-500 dark:text-slate-400 mt-1 uppercase tracking-widest">
|
<p class="text-sm font-bold text-slate-500 dark:text-slate-400 mt-1 uppercase tracking-widest">
|
||||||
{{ __('Manage administrative and tenant accounts') }}
|
{{ $tab === 'roles' ? __('Define and manage security roles and permissions.') : __('Manage administrative and tenant accounts') }}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-center gap-3">
|
<div class="flex items-center gap-3">
|
||||||
<button @click="openCreateModal()" class="btn-luxury-primary">
|
@if($tab === 'roles')
|
||||||
<svg class="size-4" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2.5">
|
<a href="{{ route('admin.data-config.sub-account-roles.create') }}" class="btn-luxury-primary">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" d="M12 4.5v15m7.5-7.5h-15" />
|
<svg class="size-4" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2.5">
|
||||||
</svg>
|
<path stroke-linecap="round" stroke-linejoin="round" d="M12 4.5v15m7.5-7.5h-15" />
|
||||||
<span>{{ __('Add Account') }}</span>
|
</svg>
|
||||||
</button>
|
<span>{{ __('Add Role') }}</span>
|
||||||
|
</a>
|
||||||
|
@else
|
||||||
|
<button @click="openCreateModal()" class="btn-luxury-primary">
|
||||||
|
<svg class="size-4" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2.5">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" d="M12 4.5v15m7.5-7.5h-15" />
|
||||||
|
</svg>
|
||||||
|
<span>{{ __('Add Account') }}</span>
|
||||||
|
</button>
|
||||||
|
@endif
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@if(request()->routeIs('admin.data-config.sub-accounts') && auth()->user()->can('menu.data-config.sub-accounts'))
|
||||||
|
<!-- Tabs Navigation (Pills Style) -->
|
||||||
|
<div class="flex items-center gap-1 p-1.5 bg-slate-100 dark:bg-slate-900/50 rounded-2xl w-fit border border-slate-200/50 dark:border-slate-800/50" aria-label="Tabs">
|
||||||
|
<button type="button"
|
||||||
|
@click="switchTab('accounts')"
|
||||||
|
:class="tab === 'accounts' ? 'bg-white dark:bg-slate-800 text-cyan-600 dark:text-cyan-400 shadow-sm shadow-cyan-500/10' : 'text-slate-400 hover:text-slate-600 dark:hover:text-slate-200'"
|
||||||
|
class="px-8 py-3 rounded-xl text-sm font-black uppercase tracking-widest transition-all duration-300">
|
||||||
|
{{ __('Account List') }}
|
||||||
|
</button>
|
||||||
|
<button type="button"
|
||||||
|
@click="switchTab('roles')"
|
||||||
|
:class="tab === 'roles' ? 'bg-white dark:bg-slate-800 text-cyan-600 dark:text-cyan-400 shadow-sm shadow-cyan-500/10' : 'text-slate-400 hover:text-slate-600 dark:hover:text-slate-200'"
|
||||||
|
class="px-8 py-3 rounded-xl text-sm font-black uppercase tracking-widest transition-all duration-300">
|
||||||
|
{{ __('Role Management') }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
<!-- Accounts Content (Integrated Card) -->
|
<!-- Accounts Content (Integrated Card) -->
|
||||||
<div class="luxury-card rounded-3xl p-8 animate-luxury-in">
|
<div class="luxury-card rounded-3xl p-8 animate-luxury-in mt-6">
|
||||||
<!-- Filters & Search -->
|
@if($tab === 'roles')
|
||||||
<form action="{{ route($baseRoute) }}" method="GET"
|
<!-- Role Filters & Search -->
|
||||||
class="flex flex-col md:flex-row md:items-center gap-4 mb-10">
|
<form action="{{ route($baseRoute) }}" method="GET" class="flex flex-col md:flex-row md:items-center gap-4 mb-10">
|
||||||
<div class="relative group">
|
<input type="hidden" name="tab" value="roles">
|
||||||
<span class="absolute inset-y-0 left-0 flex items-center pl-4 pointer-events-none z-10">
|
<div class="relative group">
|
||||||
<svg class="h-4 w-4 text-slate-400 group-focus-within:text-cyan-500 transition-colors"
|
<span class="absolute inset-y-0 left-0 flex items-center pl-4 pointer-events-none z-10">
|
||||||
viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
|
<svg class="h-4 w-4 text-slate-400 group-focus-within:text-cyan-500 transition-colors" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||||
stroke-linejoin="round">
|
<circle cx="11" cy="11" r="8"></circle>
|
||||||
<circle cx="11" cy="11" r="8"></circle>
|
<line x1="21" y1="21" x2="16.65" y2="16.65"></line>
|
||||||
<line x1="21" y1="21" x2="16.65" y2="16.65"></line>
|
</svg>
|
||||||
</svg>
|
</span>
|
||||||
</span>
|
<input type="text" name="search" value="{{ request('search') }}" class="py-2.5 pl-12 pr-6 block w-full md:w-80 luxury-input" placeholder="{{ __('Search roles...') }}">
|
||||||
<input type="text" name="search" value="{{ request('search') }}"
|
</div>
|
||||||
class="py-2.5 pl-12 pr-6 block w-full md:w-80 luxury-input"
|
|
||||||
placeholder="{{ __('Search users...') }}">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@if(auth()->user()->isSystemAdmin())
|
@if(auth()->user()->isSystemAdmin())
|
||||||
<div class="relative">
|
<div class="relative">
|
||||||
<x-searchable-select name="company_id" :options="$companies" :selected="request('company_id')"
|
<x-searchable-select name="company_id" :options="$companies" :selected="request('company_id')" placeholder="{{ __('All Affiliations') }}" class="w-full md:w-auto min-w-[280px]" onchange="this.form.submit()">
|
||||||
:placeholder="__('All Affiliations')" class="w-full md:w-auto min-w-[280px]"
|
<option value="system" {{ request('company_id') === 'system' ? 'selected' : '' }} data-title="{{ __('System Level') }}">{{ __('System Level') }}</option>
|
||||||
onchange="this.form.submit()" />
|
</x-searchable-select>
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
<input type="hidden" name="per_page" value="{{ request('per_page', 10) }}">
|
<input type="hidden" name="per_page" value="{{ request('per_page', 10) }}">
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<div class="overflow-x-auto">
|
<div class="overflow-x-auto">
|
||||||
<table class="w-full text-left border-separate border-spacing-y-0">
|
<table class="w-full text-left border-separate border-spacing-y-0">
|
||||||
<thead>
|
<thead>
|
||||||
<tr class="bg-slate-50/50 dark:bg-slate-900/10">
|
<tr class="bg-slate-50/50 dark:bg-slate-900/10">
|
||||||
<th
|
<th class="px-6 py-4 text-xs font-bold text-slate-500 dark:text-slate-400 uppercase tracking-[0.15em] border-b border-slate-100 dark:border-slate-800">{{ __('Role Name') }}</th>
|
||||||
class="px-6 py-4 text-xs font-bold text-slate-500 dark:text-slate-400 uppercase tracking-[0.15em] border-b border-slate-100 dark:border-slate-800">
|
<th class="px-6 py-4 text-xs font-bold text-slate-500 dark:text-slate-400 uppercase tracking-[0.15em] border-b border-slate-100 dark:border-slate-800">{{ __('Affiliation') }}</th>
|
||||||
{{ __('User Info') }}</th>
|
<th class="px-6 py-4 text-xs font-bold text-slate-500 dark:text-slate-400 uppercase tracking-[0.15em] border-b border-slate-100 dark:border-slate-800">{{ __('Permissions') }}</th>
|
||||||
<th
|
<th class="px-6 py-4 text-xs font-bold text-slate-500 dark:text-slate-400 uppercase tracking-[0.15em] border-b border-slate-100 dark:border-slate-800 text-center">{{ __('Users') }}</th>
|
||||||
class="px-6 py-4 text-xs font-bold text-slate-500 dark:text-slate-400 uppercase tracking-[0.15em] border-b border-slate-100 dark:border-slate-800">
|
<th class="px-6 py-4 text-xs font-bold text-slate-500 dark:text-slate-400 uppercase tracking-[0.15em] border-b border-slate-100 dark:border-slate-800 text-right">{{ __('Actions') }}</th>
|
||||||
{{ __('Contact Info') }}</th>
|
</tr>
|
||||||
@if(auth()->user()->isSystemAdmin())
|
</thead>
|
||||||
<th
|
<tbody class="divide-y divide-slate-50 dark:divide-slate-800/80">
|
||||||
class="px-6 py-4 text-xs font-bold text-slate-500 dark:text-slate-400 uppercase tracking-[0.15em] border-b border-slate-100 dark:border-slate-800">
|
@forelse($paginated_roles as $role)
|
||||||
{{ __('Affiliation') }}</th>
|
<tr class="group hover:bg-slate-50/80 dark:hover:bg-slate-800/40 transition-all duration-300">
|
||||||
@endif
|
<td class="px-6 py-6">
|
||||||
<th
|
<div class="flex items-center gap-3">
|
||||||
class="px-6 py-4 text-xs font-bold text-slate-500 dark:text-slate-400 uppercase tracking-[0.15em] border-b border-slate-100 dark:border-slate-800 text-center">
|
<div class="w-10 h-10 rounded-2xl bg-slate-100 dark:bg-slate-800 flex items-center justify-center text-slate-400 border border-slate-200 dark:border-slate-700 group-hover:bg-cyan-500 group-hover:text-white transition-all duration-300">
|
||||||
{{ __('Role') }}</th>
|
<svg xmlns="http://www.w3.org/2000/svg" class="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z" /></svg>
|
||||||
<th
|
</div>
|
||||||
class="px-6 py-4 text-xs font-bold text-slate-500 dark:text-slate-400 uppercase tracking-[0.15em] border-b border-slate-100 dark:border-slate-800 text-center">
|
<span class="text-base font-extrabold text-slate-800 dark:text-slate-100 group-hover:text-cyan-600 dark:group-hover:text-cyan-400 transition-colors">{{ $role->name }}</span>
|
||||||
{{ __('Status') }}</th>
|
@if($role->is_system)
|
||||||
<th
|
<span class="p-1.5 bg-cyan-50 dark:bg-cyan-900/30 text-cyan-600 dark:text-cyan-400 rounded-lg tooltip" title="{{ __('System Role') }}">
|
||||||
class="px-6 py-4 text-xs font-bold text-slate-500 dark:text-slate-400 uppercase tracking-[0.15em] border-b border-slate-100 dark:border-slate-800 text-right">
|
<svg xmlns="http://www.w3.org/2000/svg" class="w-3.5 h-3.5" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="18" height="11" x="3" y="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg>
|
||||||
{{ __('Actions') }}</th>
|
</span>
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody class="divide-y divide-slate-50 dark:divide-slate-800/80">
|
|
||||||
@forelse($users as $user)
|
|
||||||
<tr class="group hover:bg-slate-50/80 dark:hover:bg-slate-800/40 transition-all duration-300">
|
|
||||||
<td class="px-6 py-6">
|
|
||||||
<div class="flex items-center gap-x-4">
|
|
||||||
<div
|
|
||||||
class="w-10 h-10 rounded-xl bg-slate-100 dark:bg-slate-800 flex items-center justify-center text-slate-400 group-hover:bg-cyan-500 group-hover:text-white transition-all overflow-hidden shadow-sm">
|
|
||||||
@if($user->avatar)
|
|
||||||
<img src="{{ Storage::url($user->avatar) }}" class="w-full h-full object-cover">
|
|
||||||
@else
|
|
||||||
<svg class="size-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"
|
|
||||||
stroke-width="2.5">
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round"
|
|
||||||
d="M15.75 6a3.75 3.75 0 1 1-7.5 0 3.75 3.75 0 0 1 7.5 0ZM4.501 20.118a7.5 7.5 0 0 1 14.998 0A17.933 17.933 0 0 1 12 21.75c-2.676 0-5.216-.584-7.499-1.632Z" />
|
|
||||||
</svg>
|
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col">
|
</td>
|
||||||
<span
|
<td class="px-6 py-6">
|
||||||
class="text-base font-extrabold text-slate-800 dark:text-slate-100 group-hover:text-cyan-600 dark:group-hover:text-cyan-400 transition-colors">{{ $user->name }}</span>
|
@if($role->is_system)
|
||||||
<span
|
<span class="px-2.5 py-1 rounded-lg text-xs font-bold bg-cyan-500/10 text-cyan-600 dark:text-cyan-400 uppercase tracking-widest">
|
||||||
class="text-xs font-bold text-slate-500 dark:text-slate-400 mt-0.5 tracking-widest uppercase"><span
|
{{ __('System Level') }}
|
||||||
class="font-mono">{{ $user->username }}</span></span>
|
</span>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td class="px-6 py-6 font-display">
|
|
||||||
<div class="flex flex-col">
|
|
||||||
@if($user->phone)
|
|
||||||
<span class="text-xs font-bold text-slate-500 dark:text-slate-400 tracking-widest">{{ $user->phone }}</span>
|
|
||||||
@endif
|
|
||||||
<span class="text-xs font-bold text-slate-400 dark:text-slate-500 @if($user->phone) mt-1 @endif tracking-widest">{{ $user->email ?? '-' }}</span>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
@if(auth()->user()->isSystemAdmin())
|
|
||||||
<td class="px-6 py-6">
|
|
||||||
@if($user->company)
|
|
||||||
<span
|
|
||||||
class="text-xs font-bold text-slate-500 dark:text-slate-400 tracking-widest uppercase">{{ $user->company->name }}</span>
|
|
||||||
@else
|
|
||||||
<span
|
|
||||||
class="px-2.5 py-1 rounded-lg text-xs font-bold bg-cyan-500/10 text-cyan-600 dark:text-cyan-400 uppercase tracking-widest">{{ __('SYSTEM') }}</span>
|
|
||||||
@endif
|
|
||||||
</td>
|
|
||||||
@endif
|
|
||||||
<td class="px-6 py-6 text-center">
|
|
||||||
@foreach($user->roles as $role)
|
|
||||||
<span
|
|
||||||
class="inline-flex items-center px-2.5 py-1 rounded-lg text-xs font-bold bg-slate-100 dark:bg-slate-800 text-slate-600 dark:text-slate-300 border border-slate-200 dark:border-slate-700 uppercase tracking-widest">
|
|
||||||
{{ $role->name }}
|
|
||||||
</span>
|
|
||||||
@endforeach
|
|
||||||
</td>
|
|
||||||
<td class="px-6 py-6 text-center">
|
|
||||||
@if($user->status)
|
|
||||||
<span
|
|
||||||
class="inline-flex items-center px-2.5 py-1 rounded-lg text-xs font-bold bg-emerald-500/10 text-emerald-600 dark:text-emerald-400 border border-emerald-500/20 tracking-widest uppercase">
|
|
||||||
{{ __('Active') }}
|
|
||||||
</span>
|
|
||||||
@else
|
|
||||||
<span
|
|
||||||
class="inline-flex items-center px-2.5 py-1 rounded-lg text-xs font-bold bg-rose-500/10 text-rose-600 dark:text-rose-400 border border-rose-500/20 tracking-widest uppercase">
|
|
||||||
{{ __('Disabled') }}
|
|
||||||
</span>
|
|
||||||
@endif
|
|
||||||
</td>
|
|
||||||
<td class="px-6 py-6 text-right">
|
|
||||||
<div class="flex justify-end items-center gap-2">
|
|
||||||
@if(!$user->hasRole('super-admin') || auth()->user()->hasRole('super-admin'))
|
|
||||||
@if($user->status)
|
|
||||||
<button type="button"
|
|
||||||
@click="toggleFormAction = '{{ route($baseRoute . '.status.toggle', $user->id) }}'; statusToggleSource = 'list'; isStatusConfirmOpen = true"
|
|
||||||
class="p-2 rounded-lg bg-slate-50 dark:bg-slate-800 text-slate-400 hover:text-amber-500 hover:bg-amber-500/5 transition-all border border-transparent hover:border-amber-500/20"
|
|
||||||
title="{{ __('Disable') }}">
|
|
||||||
<svg class="size-4" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2.5">
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" d="M15.75 5.25v13.5m-7.5-13.5v13.5" />
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
@else
|
|
||||||
<button type="button"
|
|
||||||
@click="toggleFormAction = '{{ route($baseRoute . '.status.toggle', $user->id) }}'; $nextTick(() => $refs.statusToggleForm.submit())"
|
|
||||||
class="p-2 rounded-lg bg-slate-50 dark:bg-slate-800 text-slate-400 hover:text-emerald-500 hover:bg-emerald-500/5 transition-all border border-transparent hover:border-emerald-500/20"
|
|
||||||
title="{{ __('Enable') }}">
|
|
||||||
<svg class="size-4" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2.5">
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" d="M5.25 5.653c0-.856.917-1.398 1.667-.986l11.54 6.348a1.125 1.125 0 010 1.971l-11.54 6.347c-.75.412-1.667-.13-1.667-.986V5.653z" />
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
@endif
|
|
||||||
<button @click="openEditModal(@js($user))"
|
|
||||||
class="p-2 rounded-lg bg-slate-50 dark:bg-slate-800 text-slate-400 hover:text-cyan-500 hover:bg-cyan-500/5 transition-all border border-transparent hover:border-cyan-500/20"
|
|
||||||
title="{{ __('Edit') }}">
|
|
||||||
<svg class="size-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"
|
|
||||||
stroke-width="2.5">
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round"
|
|
||||||
d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1-2.652 2.652L10.582 16.07a4.5 4.5 0 0 1-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 0 1 1.13-1.897l8.932-8.931Zm0 0L19.5 7.125M18 14v4.75A2.25 2.25 0 0 1 15.75 21H5.25A2.25 2.25 0 0 1 3 18.75V8.25A2.25 2.25 0 0 1 5.25 6H10" />
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
<form action="{{ route($baseRoute . '.destroy', $user->id) }}" method="POST"
|
|
||||||
class="inline-block">
|
|
||||||
@csrf
|
|
||||||
@method('DELETE')
|
|
||||||
<button type="button"
|
|
||||||
@click="confirmDelete('{{ route($baseRoute . '.destroy', $user->id) }}')"
|
|
||||||
class="p-2 rounded-xl bg-slate-50 dark:bg-slate-800 text-slate-400 hover:text-rose-500 dark:hover:text-rose-400 hover:bg-rose-500/5 dark:hover:bg-rose-500/10 border border-transparent hover:border-rose-500/20 transition-all group/btn"
|
|
||||||
title="{{ __('Delete Account') }}">
|
|
||||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2.5"
|
|
||||||
d="M14.74 9l-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 01-2.244 2.077H8.084a2.25 2.25 0 01-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 00-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 013.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 00-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 00-7.5 0" />
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
@else
|
@else
|
||||||
<span
|
<span class="text-xs font-bold text-slate-500 dark:text-slate-400 tracking-widest uppercase">
|
||||||
class="text-[10px] font-black text-slate-300 dark:text-slate-600 uppercase tracking-[0.15em] px-2">{{ __('Protected') }}</span>
|
{{ $role->company->name ?? __('Company Level') }}
|
||||||
|
</span>
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</td>
|
||||||
</td>
|
<td class="px-6 py-6" width="30%">
|
||||||
</tr>
|
<div class="flex flex-wrap gap-1 max-w-xs">
|
||||||
@empty
|
@forelse($role->permissions->take(6) as $permission)
|
||||||
<tr>
|
<span class="px-2 py-0.5 text-xs bg-slate-100 dark:bg-slate-800 text-slate-600 dark:text-slate-300 rounded border border-slate-200 dark:border-slate-700 uppercase font-bold tracking-widest">{{ __($permission->name) }}</span>
|
||||||
<td colspan="{{ auth()->user()->isSystemAdmin() ? 6 : 5 }}" class="px-6 py-24 text-center">
|
@empty
|
||||||
<div class="flex flex-col items-center gap-3 opacity-20">
|
<span class="text-xs font-bold text-slate-500 dark:text-slate-400 tracking-widest">{{ __('No permissions') }}</span>
|
||||||
<svg class="size-16" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
@endforelse
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"
|
@if($role->permissions->count() > 6)
|
||||||
d="M17 21v-2a4 4 0 00-4-4H5a4 4 0 00-4 4v2m16-10a4 4 0 11-8 0 4 4 0 018 0zM23 21v-2a4 4 0 00-3-3.87m-4-12a4 4 0 010 7.75" />
|
<span class="px-2 py-0.5 text-xs bg-slate-100 dark:bg-slate-800 text-slate-500 dark:text-slate-400 rounded border border-slate-200 dark:border-slate-700 uppercase font-bold tracking-widest">+{{ $role->permissions->count() - 6 }}</span>
|
||||||
</svg>
|
@endif
|
||||||
<p class="text-slate-400 font-extrabold tracking-widest uppercase text-xs">{{ __('No accounts found') }}</p>
|
</div>
|
||||||
</div>
|
</td>
|
||||||
</td>
|
<td class="px-6 py-6 text-center">
|
||||||
</tr>
|
<span class="text-sm font-extrabold text-slate-700 dark:text-slate-300">{{ $role->users()->count() }}</span>
|
||||||
@endforelse
|
</td>
|
||||||
</tbody>
|
<td class="px-6 py-6 text-right">
|
||||||
</table>
|
<div class="flex items-center justify-end gap-2">
|
||||||
</div>
|
<a href="{{ route('admin.data-config.sub-account-roles.edit', $role->id) }}" class="p-2 rounded-lg bg-slate-50 dark:bg-slate-800 text-slate-400 hover:text-cyan-500 hover:bg-cyan-500/5 transition-all border border-transparent hover:border-cyan-500/20 tooltip" title="{{ __('Edit') }}">
|
||||||
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2.5"><path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L10.582 16.07a4.5 4.5 0 0 1-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 0 1 1.13-1.897l8.932-8.931Zm0 0L19.5 7.125M18 14v4.75A2.25 2.25 0 0 1 15.75 21H5.25A2.25 2.25 0 0 1 3 18.75V8.25A2.25 2.25 0 0 1 5.25 6H10"/></svg>
|
||||||
|
</a>
|
||||||
|
@if($role->name !== 'super-admin' && (auth()->user()->isSystemAdmin() || !$role->is_system))
|
||||||
|
<form action="{{ route('admin.data-config.sub-account-roles.destroy', $role->id) }}" method="POST" @submit.prevent="if({{ $role->users()->count() }} > 0) { triggerDeleteWarning('{{ __('Cannot delete role with active users.') }}'); return; } confirmDelete('{{ route('admin.data-config.sub-account-roles.destroy', $role->id) }}')" class="inline text-slate-400">
|
||||||
|
@csrf
|
||||||
|
@method('DELETE')
|
||||||
|
<button type="submit" class="p-2 rounded-lg bg-slate-50 dark:bg-slate-800 text-slate-400 hover:text-rose-500 hover:bg-rose-500/5 transition-all border border-transparent hover:border-rose-500/20 tooltip" title="{{ __('Delete') }}">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" class="w-4 h-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M3 6h18"/><path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"/><path d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"/><line x1="10" x2="10" y1="11" y2="17"/><line x1="14" x2="14" y1="11" y2="17"/></svg>
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
@empty
|
||||||
|
<tr>
|
||||||
|
<td colspan="5" class="px-6 py-20 text-center">
|
||||||
|
<div class="flex flex-col items-center justify-center gap-4 text-slate-400">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" class="w-16 h-16 opacity-20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1" stroke-linecap="round" stroke-linejoin="round"><rect width="18" height="18" x="3" y="3" rx="2"/><path d="M12 8v8"/><path d="M8 12h8"/></svg>
|
||||||
|
<p class="text-lg font-bold">{{ __('No roles found.') }}</p>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
@endforelse
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="mt-8 border-t border-slate-100/50 dark:border-slate-800/50 pt-6">
|
<div class="mt-8 border-t border-slate-100 dark:border-slate-800 pt-6">
|
||||||
{{ $users->links('vendor.pagination.luxury') }}
|
{{ $paginated_roles->links('vendor.pagination.luxury') }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@else
|
||||||
|
<!-- Accounts Filters & Search -->
|
||||||
|
<form action="{{ route($baseRoute) }}" method="GET" class="flex flex-col md:flex-row md:items-center gap-4 mb-10">
|
||||||
|
<input type="hidden" name="tab" value="accounts">
|
||||||
|
<div class="relative group">
|
||||||
|
<span class="absolute inset-y-0 left-0 flex items-center pl-4 pointer-events-none z-10">
|
||||||
|
<svg class="h-4 w-4 text-slate-400 group-focus-within:text-cyan-500 transition-colors"
|
||||||
|
viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
|
||||||
|
stroke-linejoin="round">
|
||||||
|
<circle cx="11" cy="11" r="8"></circle>
|
||||||
|
<line x1="21" y1="21" x2="16.65" y2="16.65"></line>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
<input type="text" name="search" value="{{ request('search') }}"
|
||||||
|
class="py-2.5 pl-12 pr-6 block w-full md:w-80 luxury-input"
|
||||||
|
placeholder="{{ __('Search users...') }}">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@if(auth()->user()->isSystemAdmin())
|
||||||
|
<div class="relative">
|
||||||
|
<x-searchable-select name="company_id" :options="$companies" :selected="request('company_id')"
|
||||||
|
:placeholder="__('All Affiliations')" class="w-full md:w-auto min-w-[280px]"
|
||||||
|
onchange="this.form.submit()" />
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
<input type="hidden" name="per_page" value="{{ request('per_page', 10) }}">
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<div class="overflow-x-auto">
|
||||||
|
<table class="w-full text-left border-separate border-spacing-y-0">
|
||||||
|
<thead>
|
||||||
|
<tr class="bg-slate-50/50 dark:bg-slate-900/10">
|
||||||
|
<th class="px-6 py-4 text-xs font-bold text-slate-500 dark:text-slate-400 uppercase tracking-[0.15em] border-b border-slate-100 dark:border-slate-800">
|
||||||
|
{{ __('User Info') }}</th>
|
||||||
|
<th class="px-6 py-4 text-xs font-bold text-slate-500 dark:text-slate-400 uppercase tracking-[0.15em] border-b border-slate-100 dark:border-slate-800">
|
||||||
|
{{ __('Contact Info') }}</th>
|
||||||
|
@if(auth()->user()->isSystemAdmin())
|
||||||
|
<th class="px-6 py-4 text-xs font-bold text-slate-500 dark:text-slate-400 uppercase tracking-[0.15em] border-b border-slate-100 dark:border-slate-800">
|
||||||
|
{{ __('Affiliation') }}</th>
|
||||||
|
@endif
|
||||||
|
<th class="px-6 py-4 text-xs font-bold text-slate-500 dark:text-slate-400 uppercase tracking-[0.15em] border-b border-slate-100 dark:border-slate-800 text-center">
|
||||||
|
{{ __('Role') }}</th>
|
||||||
|
<th class="px-6 py-4 text-xs font-bold text-slate-500 dark:text-slate-400 uppercase tracking-[0.15em] border-b border-slate-100 dark:border-slate-800 text-center">
|
||||||
|
{{ __('Status') }}</th>
|
||||||
|
<th class="px-6 py-4 text-xs font-bold text-slate-500 dark:text-slate-400 uppercase tracking-[0.15em] border-b border-slate-100 dark:border-slate-800 text-right">
|
||||||
|
{{ __('Actions') }}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody class="divide-y divide-slate-50 dark:divide-slate-800/80">
|
||||||
|
@forelse($users as $user)
|
||||||
|
<tr class="group hover:bg-slate-50/80 dark:hover:bg-slate-800/40 transition-all duration-300">
|
||||||
|
<td class="px-6 py-6">
|
||||||
|
<div class="flex items-center gap-x-4">
|
||||||
|
<div class="w-10 h-10 rounded-xl bg-slate-100 dark:bg-slate-800 flex items-center justify-center text-slate-400 group-hover:bg-cyan-500 group-hover:text-white transition-all overflow-hidden shadow-sm">
|
||||||
|
@if($user->avatar)
|
||||||
|
<img src="{{ Storage::url($user->avatar) }}" class="w-full h-full object-cover">
|
||||||
|
@else
|
||||||
|
<svg class="size-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"
|
||||||
|
stroke-width="2.5">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round"
|
||||||
|
d="M15.75 6a3.75 3.75 0 1 1-7.5 0 3.75 3.75 0 0 1 7.5 0ZM4.501 20.118a7.5 7.5 0 0 1 14.998 0A17.933 17.933 0 0 1 12 21.75c-2.676 0-5.216-.584-7.499-1.632Z" />
|
||||||
|
</svg>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col">
|
||||||
|
<span class="text-base font-extrabold text-slate-800 dark:text-slate-100 group-hover:text-cyan-600 dark:group-hover:text-cyan-400 transition-colors">{{ $user->name }}</span>
|
||||||
|
<span class="text-xs font-bold text-slate-500 dark:text-slate-400 mt-0.5 tracking-widest uppercase"><span class="font-mono">{{ $user->username }}</span></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td class="px-6 py-6 font-display">
|
||||||
|
<div class="flex flex-col">
|
||||||
|
@if($user->phone)
|
||||||
|
<span class="text-xs font-bold text-slate-500 dark:text-slate-400 tracking-widest">{{ $user->phone }}</span>
|
||||||
|
@endif
|
||||||
|
<span class="text-xs font-bold text-slate-400 dark:text-slate-500 @if($user->phone) mt-1 @endif tracking-widest">{{ $user->email ?? '-' }}</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
@if(auth()->user()->isSystemAdmin())
|
||||||
|
<td class="px-6 py-6">
|
||||||
|
@if($user->company)
|
||||||
|
<span class="text-xs font-bold text-slate-500 dark:text-slate-400 tracking-widest uppercase">{{ $user->company->name }}</span>
|
||||||
|
@else
|
||||||
|
<span class="px-2.5 py-1 rounded-lg text-xs font-bold bg-cyan-500/10 text-cyan-600 dark:text-cyan-400 uppercase tracking-widest">{{ __('SYSTEM') }}</span>
|
||||||
|
@endif
|
||||||
|
</td>
|
||||||
|
@endif
|
||||||
|
<td class="px-6 py-6 text-center">
|
||||||
|
@foreach($user->roles as $role)
|
||||||
|
<span class="inline-flex items-center px-2.5 py-1 rounded-lg text-xs font-bold bg-slate-100 dark:bg-slate-800 text-slate-600 dark:text-slate-300 border border-slate-200 dark:border-slate-700 uppercase tracking-widest">
|
||||||
|
{{ $role->name }}
|
||||||
|
</span>
|
||||||
|
@endforeach
|
||||||
|
</td>
|
||||||
|
<td class="px-6 py-6 text-center">
|
||||||
|
@if($user->status)
|
||||||
|
<span class="inline-flex items-center px-2.5 py-1 rounded-lg text-xs font-bold bg-emerald-500/10 text-emerald-600 dark:text-emerald-400 border border-emerald-500/20 tracking-widest uppercase">
|
||||||
|
{{ __('Active') }}
|
||||||
|
</span>
|
||||||
|
@else
|
||||||
|
<span class="inline-flex items-center px-2.5 py-1 rounded-lg text-xs font-bold bg-rose-500/10 text-rose-600 dark:text-rose-400 border border-rose-500/20 tracking-widest uppercase">
|
||||||
|
{{ __('Disabled') }}
|
||||||
|
</span>
|
||||||
|
@endif
|
||||||
|
</td>
|
||||||
|
<td class="px-6 py-6 text-right">
|
||||||
|
<div class="flex justify-end items-center gap-2">
|
||||||
|
@if(!$user->hasRole('super-admin') || auth()->user()->hasRole('super-admin'))
|
||||||
|
@if($user->status)
|
||||||
|
<button type="button"
|
||||||
|
@click="toggleFormAction = '{{ route($baseRoute . '.status.toggle', $user->id) }}'; statusToggleSource = 'list'; isStatusConfirmOpen = true"
|
||||||
|
class="p-2 rounded-lg bg-slate-50 dark:bg-slate-800 text-slate-400 hover:text-amber-500 hover:bg-amber-500/5 transition-all border border-transparent hover:border-amber-500/20"
|
||||||
|
title="{{ __('Disable') }}">
|
||||||
|
<svg class="size-4" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2.5">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" d="M15.75 5.25v13.5m-7.5-13.5v13.5" />
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
@else
|
||||||
|
<button type="button"
|
||||||
|
@click="toggleFormAction = '{{ route($baseRoute . '.status.toggle', $user->id) }}'; $nextTick(() => $refs.statusToggleForm.submit())"
|
||||||
|
class="p-2 rounded-lg bg-slate-50 dark:bg-slate-800 text-slate-400 hover:text-emerald-500 hover:bg-emerald-500/5 transition-all border border-transparent hover:border-emerald-500/20"
|
||||||
|
title="{{ __('Enable') }}">
|
||||||
|
<svg class="size-4" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2.5">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" d="M5.25 5.653c0-.856.917-1.398 1.667-.986l11.54 6.348a1.125 1.125 0 010 1.971l-11.54 6.347c-.75.412-1.667-.13-1.667-.986V5.653z" />
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
@endif
|
||||||
|
<button @click="openEditModal(@js($user))"
|
||||||
|
class="p-2 rounded-lg bg-slate-50 dark:bg-slate-800 text-slate-400 hover:text-cyan-500 hover:bg-cyan-500/5 transition-all border border-transparent hover:border-cyan-500/20"
|
||||||
|
title="{{ __('Edit') }}">
|
||||||
|
<svg class="size-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"
|
||||||
|
stroke-width="2.5">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round"
|
||||||
|
d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1-2.652 2.652L10.582 16.07a4.5 4.5 0 0 1-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 0 1 1.13-1.897l8.932-8.931Zm0 0L19.5 7.125M18 14v4.75A2.25 2.25 0 0 1 15.75 21H5.25A2.25 2.25 0 0 1 3 18.75V8.25A2.25 2.25 0 0 1 5.25 6H10" />
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<form action="{{ route($baseRoute . '.destroy', $user->id) }}" method="POST"
|
||||||
|
class="inline-block">
|
||||||
|
@csrf
|
||||||
|
@method('DELETE')
|
||||||
|
<button type="button"
|
||||||
|
@click="confirmDelete('{{ route($baseRoute . '.destroy', $user->id) }}')"
|
||||||
|
class="p-2 rounded-xl bg-slate-50 dark:bg-slate-800 text-slate-400 hover:text-rose-500 dark:hover:text-rose-400 hover:bg-rose-500/5 dark:hover:bg-rose-500/10 border border-transparent hover:border-rose-500/20 transition-all group/btn"
|
||||||
|
title="{{ __('Delete Account') }}">
|
||||||
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2.5"
|
||||||
|
d="M14.74 9l-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 01-2.244 2.077H8.084a2.25 2.25 0 01-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 00-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 013.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 00-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 00-7.5 0" />
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
@else
|
||||||
|
<span
|
||||||
|
class="text-[10px] font-black text-slate-300 dark:text-slate-600 uppercase tracking-[0.15em] px-2">{{ __('Protected') }}</span>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
@empty
|
||||||
|
<tr>
|
||||||
|
<td colspan="{{ auth()->user()->isSystemAdmin() ? 6 : 5 }}" class="px-6 py-24 text-center">
|
||||||
|
<div class="flex flex-col items-center gap-3 opacity-20">
|
||||||
|
<svg class="size-16" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"
|
||||||
|
d="M17 21v-2a4 4 0 00-4-4H5a4 4 0 00-4 4v2m16-10a4 4 0 11-8 0 4 4 0 018 0zM23 21v-2a4 4 0 00-3-3.87m-4-12a4 4 0 010 7.75" />
|
||||||
|
</svg>
|
||||||
|
<p class="text-slate-400 font-extrabold tracking-widest uppercase text-xs">{{ __('No accounts found') }}</p>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
@endforelse
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-8 border-t border-slate-100/50 dark:border-slate-800/50 pt-6">
|
||||||
|
{{ $users->links('vendor.pagination.luxury') }}
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- User Modal -->
|
<!-- User Modal -->
|
||||||
@@ -403,6 +529,49 @@ $roleSelectConfig = [
|
|||||||
@csrf
|
@csrf
|
||||||
@method('PATCH')
|
@method('PATCH')
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
<!-- Global Delete Warning Modal -->
|
||||||
|
<div x-show="isWarningModalOpen" class="fixed inset-0 z-[200] overflow-y-auto" x-cloak>
|
||||||
|
<div class="flex items-center justify-center min-h-screen px-4 pt-4 pb-20 text-center sm:block sm:p-0">
|
||||||
|
<div x-show="isWarningModalOpen" x-transition:enter="ease-out duration-300"
|
||||||
|
x-transition:enter-start="opacity-0" x-transition:enter-end="opacity-100"
|
||||||
|
x-transition:leave="ease-in duration-200" x-transition:leave-start="opacity-100"
|
||||||
|
x-transition:leave-end="opacity-0" class="fixed inset-0 transition-opacity bg-slate-900/60 backdrop-blur-sm"
|
||||||
|
@click="isWarningModalOpen = false"></div>
|
||||||
|
|
||||||
|
<span class="hidden sm:inline-block sm:align-middle sm:h-screen">​</span>
|
||||||
|
|
||||||
|
<div x-show="isWarningModalOpen" x-transition:enter="ease-out duration-300"
|
||||||
|
x-transition:enter-start="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
|
||||||
|
x-transition:enter-end="opacity-100 translate-y-0 sm:scale-100" x-transition:leave="ease-in duration-200"
|
||||||
|
x-transition:leave-start="opacity-100 translate-y-0 sm:scale-100"
|
||||||
|
x-transition:leave-end="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
|
||||||
|
class="inline-block px-4 pt-5 pb-4 overflow-hidden text-left align-bottom transition-all transform bg-white dark:bg-slate-900 rounded-3xl shadow-2xl sm:my-8 sm:align-middle sm:max-w-lg sm:w-full sm:p-8 border border-slate-100 dark:border-slate-800">
|
||||||
|
|
||||||
|
<div class="sm:flex sm:items-start">
|
||||||
|
<div class="flex items-center justify-center flex-shrink-0 w-12 h-12 mx-auto bg-rose-100 dark:bg-rose-500/10 rounded-2xl sm:mx-0 sm:h-12 sm:w-12 text-rose-600 dark:text-rose-400">
|
||||||
|
<svg class="w-6 h-6" fill="none" viewBox="0 0 24 24" stroke-width="2.5" stroke="currentColor">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126zM12 15.75h.007v.008H12v-.008z" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<div class="mt-3 text-center sm:mt-0 sm:ml-6 sm:text-left">
|
||||||
|
<h3 class="text-xl font-black text-slate-800 dark:text-white leading-6 tracking-tight outfit-font">
|
||||||
|
{{ __('Cannot Delete Role') }}
|
||||||
|
</h3>
|
||||||
|
<div class="mt-4">
|
||||||
|
<p class="text-sm font-bold text-slate-500 dark:text-slate-400 leading-relaxed" x-text="deleteWarningMsg"></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="mt-8 sm:mt-10 sm:flex sm:flex-row-reverse">
|
||||||
|
<button type="button" @click="isWarningModalOpen = false"
|
||||||
|
class="inline-flex justify-center w-full px-8 py-3 text-sm font-black text-white transition-all bg-slate-800 dark:bg-slate-700 rounded-xl hover:bg-slate-900 dark:hover:bg-slate-600 sm:w-auto tracking-widest uppercase">
|
||||||
|
{{ __('Got it') }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@endsection
|
@endsection
|
||||||
|
|
||||||
@@ -423,6 +592,7 @@ $roleSelectConfig = [
|
|||||||
role: initData.oldValues.role || '',
|
role: initData.oldValues.role || '',
|
||||||
status: initData.oldValues.status || 1
|
status: initData.oldValues.status || 1
|
||||||
},
|
},
|
||||||
|
tab: initData.tab || 'accounts',
|
||||||
roleSelectConfig: initData.roleSelectConfig,
|
roleSelectConfig: initData.roleSelectConfig,
|
||||||
isDeleteConfirmOpen: false,
|
isDeleteConfirmOpen: false,
|
||||||
deleteFormAction: '',
|
deleteFormAction: '',
|
||||||
@@ -430,6 +600,20 @@ $roleSelectConfig = [
|
|||||||
toggleFormAction: '',
|
toggleFormAction: '',
|
||||||
statusToggleSource: 'list',
|
statusToggleSource: 'list',
|
||||||
|
|
||||||
|
isWarningModalOpen: false,
|
||||||
|
deleteWarningMsg: '',
|
||||||
|
triggerDeleteWarning(msg) {
|
||||||
|
this.deleteWarningMsg = msg;
|
||||||
|
this.isWarningModalOpen = true;
|
||||||
|
},
|
||||||
|
|
||||||
|
switchTab(newTab) {
|
||||||
|
const url = new URL(window.location.href);
|
||||||
|
url.searchParams.set('tab', newTab);
|
||||||
|
// Clear search and filters when switching tabs if desired, but here we just go to the URL
|
||||||
|
window.location.href = url.toString();
|
||||||
|
},
|
||||||
|
|
||||||
confirmDelete(action) {
|
confirmDelete(action) {
|
||||||
this.deleteFormAction = action;
|
this.deleteFormAction = action;
|
||||||
this.isDeleteConfirmOpen = true;
|
this.isDeleteConfirmOpen = true;
|
||||||
|
|||||||
@@ -398,20 +398,17 @@ window.machineApp = function(initialTab) {
|
|||||||
<div class="flex items-center gap-4 cursor-pointer group/info"
|
<div class="flex items-center gap-4 cursor-pointer group/info"
|
||||||
@click="openCabinet('{{ $machine->id }}')">
|
@click="openCabinet('{{ $machine->id }}')">
|
||||||
<div
|
<div
|
||||||
class="w-12 h-12 rounded-2xl bg-slate-100 dark:bg-slate-800 flex items-center justify-center text-slate-400 border border-slate-200 dark:border-slate-700 overflow-hidden group-hover/info:border-cyan-500/50 group-hover/info:shadow-lg group-hover/info:shadow-cyan-500/10 transition-all duration-300 shadow-sm relative">
|
class="w-12 h-12 rounded-2xl bg-slate-100 dark:bg-slate-800 flex items-center justify-center text-slate-400 border border-slate-200 dark:border-slate-700 overflow-hidden group-hover/info:bg-cyan-500 group-hover/info:text-white transition-all duration-300 shadow-sm relative">
|
||||||
@if(isset($machine->image_urls[0]))
|
@if(isset($machine->image_urls[0]))
|
||||||
<img src="{{ $machine->image_urls[0] }}"
|
<img src="{{ $machine->image_urls[0] }}"
|
||||||
class="w-full h-full object-cover group-hover/info:scale-110 transition-transform duration-500">
|
class="w-full h-full object-cover group-hover/info:scale-110 transition-transform duration-500">
|
||||||
@else
|
@else
|
||||||
<svg class="w-6 h-6 stroke-[1.5]" fill="none" stroke="currentColor"
|
<svg class="w-6 h-6 stroke-[2.5]" fill="none" stroke="currentColor"
|
||||||
viewBox="0 0 24 24">
|
viewBox="0 0 24 24">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round"
|
<path stroke-linecap="round" stroke-linejoin="round"
|
||||||
d="M21 7.5l-9-5.25L3 7.5m18 0l-9 5.25m9-5.25v9l-9 5.25M3 7.5l9 5.25M3 7.5v9l9 5.25m0-5.25v9" />
|
d="M21 7.5l-9-5.25L3 7.5m18 0l-9 5.25m9-5.25v9l-9 5.25M3 7.5l9 5.25M3 7.5v9l9 5.25m0-5.25v9" />
|
||||||
</svg>
|
</svg>
|
||||||
@endif
|
@endif
|
||||||
<div
|
|
||||||
class="absolute inset-0 bg-cyan-500/0 group-hover/info:bg-cyan-500/10 transition-colors duration-300">
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
@@ -548,10 +545,10 @@ window.machineApp = function(initialTab) {
|
|||||||
<!-- Product Image/Icon -->
|
<!-- Product Image/Icon -->
|
||||||
<div
|
<div
|
||||||
class="w-12 h-12 sm:w-16 sm:h-16 rounded-2xl bg-white/10 flex items-center justify-center p-2 mb-2 overflow-hidden backdrop-blur-md">
|
class="w-12 h-12 sm:w-16 sm:h-16 rounded-2xl bg-white/10 flex items-center justify-center p-2 mb-2 overflow-hidden backdrop-blur-md">
|
||||||
<template x-if="slot.product && slot.product.image">
|
<template x-if="slot.product && slot.product.image_url">
|
||||||
<img :src="slot.product.image" class="w-full h-full object-contain">
|
<img :src="slot.product.image_url" class="w-full h-full object-contain">
|
||||||
</template>
|
</template>
|
||||||
<template x-if="!slot.product || !slot.product.image">
|
<template x-if="!slot.product || !slot.product.image_url">
|
||||||
<svg class="w-6 h-6 stroke-[1.5]" fill="none" stroke="currentColor"
|
<svg class="w-6 h-6 stroke-[1.5]" fill="none" stroke="currentColor"
|
||||||
viewBox="0 0 24 24">
|
viewBox="0 0 24 24">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round"
|
<path stroke-linecap="round" stroke-linejoin="round"
|
||||||
@@ -918,10 +915,12 @@ window.machineApp = function(initialTab) {
|
|||||||
<!-- Slot Header Info -->
|
<!-- Slot Header Info -->
|
||||||
<div
|
<div
|
||||||
class="flex items-center gap-4 p-4 rounded-2xl bg-slate-50 dark:bg-slate-800/50 border border-slate-100 dark:border-slate-800">
|
class="flex items-center gap-4 p-4 rounded-2xl bg-slate-50 dark:bg-slate-800/50 border border-slate-100 dark:border-slate-800">
|
||||||
<div
|
<div class="flex-shrink-0 w-16 h-16 rounded-xl bg-slate-100 dark:bg-slate-800 flex items-center justify-center p-2 overflow-hidden">
|
||||||
class="w-16 h-16 rounded-xl bg-white dark:bg-slate-800 p-2 border border-slate-200 dark:border-slate-700 shadow-sm overflow-hidden">
|
<template x-if="selectedSlot.product && selectedSlot.product.image_url">
|
||||||
<template x-if="selectedSlot.product && selectedSlot.product.image">
|
<img :src="selectedSlot.product.image_url" class="w-full h-full object-contain">
|
||||||
<img :src="selectedSlot.product.image" class="w-full h-full object-contain">
|
</template>
|
||||||
|
<template x-if="!selectedSlot.product || !selectedSlot.product.image_url">
|
||||||
|
<svg class="w-8 h-8 text-slate-300 dark:text-slate-600" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z" /></svg>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
@@ -140,7 +140,7 @@
|
|||||||
<td class="px-6 py-6 font-display">
|
<td class="px-6 py-6 font-display">
|
||||||
<div class="flex items-center gap-4">
|
<div class="flex items-center gap-4">
|
||||||
<div
|
<div
|
||||||
class="w-10 h-10 rounded-xl bg-slate-100 dark:bg-slate-800 flex items-center justify-center text-slate-400 border border-slate-200 dark:border-slate-700">
|
class="w-10 h-10 rounded-xl bg-slate-100 dark:bg-slate-800 flex items-center justify-center text-slate-400 border border-slate-200 dark:border-slate-700 group-hover:bg-cyan-500 group-hover:text-white transition-all duration-300 shadow-sm overflow-hidden">
|
||||||
<svg class="size-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
<svg class="size-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2.5"
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2.5"
|
||||||
d="M15.75 6a3.75 3.75 0 1 1-7.5 0 3.75 3.75 0 0 1 7.5 0ZM4.501 20.118a7.5 7.5 0 0 1 14.998 0A17.933 17.933 0 0 1 12 21.75c-2.676 0-5.216-.584-7.499-1.632Z" />
|
d="M15.75 6a3.75 3.75 0 1 1-7.5 0 3.75 3.75 0 0 1 7.5 0ZM4.501 20.118a7.5 7.5 0 0 1 14.998 0A17.933 17.933 0 0 1 12 21.75c-2.676 0-5.216-.584-7.499-1.632Z" />
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ $roleSelectConfig = [
|
|||||||
<tr class="group hover:bg-slate-50/80 dark:hover:bg-slate-800/40 transition-all duration-300">
|
<tr class="group hover:bg-slate-50/80 dark:hover:bg-slate-800/40 transition-all duration-300">
|
||||||
<td class="px-6 py-6">
|
<td class="px-6 py-6">
|
||||||
<div class="flex items-center gap-x-4">
|
<div class="flex items-center gap-x-4">
|
||||||
<div class="w-10 h-10 rounded-xl bg-slate-100 dark:bg-slate-800 flex items-center justify-center text-slate-400 group-hover:bg-cyan-500 group-hover:text-white transition-all overflow-hidden shadow-sm">
|
<div class="w-10 h-10 rounded-xl bg-slate-100 dark:bg-slate-800 flex items-center justify-center text-slate-400 border border-slate-200 dark:border-slate-700 group-hover:bg-cyan-500 group-hover:text-white group-hover:border-cyan-500 shadow-sm group-hover:shadow-cyan-500/50 transition-all duration-300 overflow-hidden">
|
||||||
@if($product->image_url)
|
@if($product->image_url)
|
||||||
<img src="{{ $product->image_url }}" class="w-full h-full object-cover">
|
<img src="{{ $product->image_url }}" class="w-full h-full object-cover">
|
||||||
@else
|
@else
|
||||||
@@ -125,7 +125,7 @@ $roleSelectConfig = [
|
|||||||
@php
|
@php
|
||||||
$catName = $product->category->localized_name ?? __('Uncategorized');
|
$catName = $product->category->localized_name ?? __('Uncategorized');
|
||||||
@endphp
|
@endphp
|
||||||
<span class="text-[10px] font-bold text-slate-400 dark:text-slate-500 uppercase tracking-widest bg-slate-100 dark:bg-slate-800 px-1.5 py-0.5 rounded transition-colors group-hover:text-slate-600 dark:group-hover:text-slate-300">{{ $catName }}</span>
|
<span class="text-[10px] font-bold text-slate-500 dark:text-slate-400 uppercase tracking-widest bg-slate-100 dark:bg-slate-800 px-1.5 py-0.5 rounded transition-colors group-hover:text-slate-600 dark:group-hover:text-slate-300">{{ $catName }}</span>
|
||||||
@if(($companySettings['enable_material_code'] ?? false) && isset($product->metadata['material_code']))
|
@if(($companySettings['enable_material_code'] ?? false) && isset($product->metadata['material_code']))
|
||||||
<span class="text-[10px] font-bold text-emerald-500/80 uppercase tracking-widest bg-emerald-500/10 px-1.5 py-0.5 rounded border border-emerald-500/20">#{{ $product->metadata['material_code'] }}</span>
|
<span class="text-[10px] font-bold text-emerald-500/80 uppercase tracking-widest bg-emerald-500/10 px-1.5 py-0.5 rounded border border-emerald-500/20">#{{ $product->metadata['material_code'] }}</span>
|
||||||
@endif
|
@endif
|
||||||
@@ -217,13 +217,21 @@ $roleSelectConfig = [
|
|||||||
@forelse($categories as $category)
|
@forelse($categories as $category)
|
||||||
<tr class="group hover:bg-slate-50/80 dark:hover:bg-slate-800/40 transition-all duration-300">
|
<tr class="group hover:bg-slate-50/80 dark:hover:bg-slate-800/40 transition-all duration-300">
|
||||||
<td class="px-6 py-6">
|
<td class="px-6 py-6">
|
||||||
<span class="text-base font-extrabold text-slate-800 dark:text-slate-100 transition-colors group-hover:text-cyan-600">
|
<div class="flex items-center gap-x-4">
|
||||||
{{ $category->localized_name }}
|
<div class="w-10 h-10 rounded-xl bg-slate-100 dark:bg-slate-800 flex items-center justify-center text-slate-400 border border-slate-200 dark:border-slate-700 group-hover:bg-cyan-500 group-hover:text-white group-hover:border-cyan-500 shadow-sm group-hover:shadow-cyan-500/50 transition-all duration-300">
|
||||||
</span>
|
<svg class="size-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2.5">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" d="M9.568 3H5.25A2.25 2.25 0 003 5.25v13.5A2.25 2.25 0 005.25 21h13.5A2.25 2.25 0 0021 18.75V9.432a2.25 2.25 0 00-.659-1.591l-4.182-4.182A2.25 2.25 0 0014.568 3h-5z" />
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" d="M15 12h-6m6 4h-6m6-8h-6" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<span class="text-base font-extrabold text-slate-800 dark:text-slate-100 transition-colors group-hover:text-cyan-600 dark:group-hover:text-cyan-400">
|
||||||
|
{{ $category->localized_name }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
</td>
|
</td>
|
||||||
@if(auth()->user()->isSystemAdmin())
|
@if(auth()->user()->isSystemAdmin())
|
||||||
<td class="px-6 py-6 text-center">
|
<td class="px-6 py-6 text-center">
|
||||||
<span class="text-xs font-bold text-slate-600 dark:text-slate-400">{{ $category->company->name ?? __('System Default') }}</span>
|
<span class="text-xs font-bold text-slate-500 dark:text-slate-400">{{ $category->company->name ?? __('System Default') }}</span>
|
||||||
</td>
|
</td>
|
||||||
@endif
|
@endif
|
||||||
<td class="px-6 py-6 text-right">
|
<td class="px-6 py-6 text-right">
|
||||||
|
|||||||
@@ -229,13 +229,6 @@
|
|||||||
</a></li>
|
</a></li>
|
||||||
@endcan
|
@endcan
|
||||||
|
|
||||||
@can('menu.data-config.sub-account-roles')
|
|
||||||
<li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm transition-colors rounded-lg {{ request()->routeIs('admin.data-config.sub-account-roles') ? 'text-slate-900 dark:text-white bg-slate-100 dark:bg-white/5' : 'text-slate-500 dark:text-slate-400 hover:text-slate-900 dark:hover:text-white' }}" href="{{ route('admin.data-config.sub-account-roles') }}">
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" class="w-4 h-4 shrink-0 transition-colors" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z" /></svg>
|
|
||||||
{{ __('Sub Account Roles') }}
|
|
||||||
</a></li>
|
|
||||||
@endcan
|
|
||||||
|
|
||||||
@can('menu.data-config.points')
|
@can('menu.data-config.points')
|
||||||
<li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm transition-colors rounded-lg {{ request()->routeIs('admin.data-config.points') ? 'text-slate-900 dark:text-white bg-slate-100 dark:bg-white/5' : 'text-slate-500 dark:text-slate-400 hover:text-slate-900 dark:hover:text-white' }}" href="{{ route('admin.data-config.points') }}">
|
<li><a class="flex items-center gap-x-3.5 py-2 px-2.5 text-sm transition-colors rounded-lg {{ request()->routeIs('admin.data-config.points') ? 'text-slate-900 dark:text-white bg-slate-100 dark:bg-white/5' : 'text-slate-500 dark:text-slate-400 hover:text-slate-900 dark:hover:text-white' }}" href="{{ route('admin.data-config.points') }}">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" class="w-4 h-4 shrink-0 transition-colors" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M12 8c-1.657 0-3 .895-3 2s1.343 2 3 2 3 .895 3 2-1.343 2-3 2m0-8c1.11 0 2.08.402 2.599 1M12 8V7m0 1v8m0 0v1m0-1c-1.11 0-2.08-.402-2.599-1M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" class="w-4 h-4 shrink-0 transition-colors" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M12 8c-1.657 0-3 .895-3 2s1.343 2 3 2 3 .895 3 2-1.343 2-3 2m0-8c1.11 0 2.08.402 2.599 1M12 8V7m0 1v8m0 0v1m0-1c-1.11 0-2.08-.402-2.599-1M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>
|
||||||
|
|||||||
@@ -130,12 +130,14 @@ Route::middleware(['auth', 'verified', 'tenant.access'])->prefix('admin')->name(
|
|||||||
Route::post('/sub-accounts', [App\Http\Controllers\Admin\PermissionController::class, 'storeAccount'])->name('sub-accounts.store')->middleware('can:menu.data-config.sub-accounts');
|
Route::post('/sub-accounts', [App\Http\Controllers\Admin\PermissionController::class, 'storeAccount'])->name('sub-accounts.store')->middleware('can:menu.data-config.sub-accounts');
|
||||||
Route::put('/sub-accounts/{id}', [App\Http\Controllers\Admin\PermissionController::class, 'updateAccount'])->name('sub-accounts.update')->middleware('can:menu.data-config.sub-accounts');
|
Route::put('/sub-accounts/{id}', [App\Http\Controllers\Admin\PermissionController::class, 'updateAccount'])->name('sub-accounts.update')->middleware('can:menu.data-config.sub-accounts');
|
||||||
Route::delete('/sub-accounts/{id}', [App\Http\Controllers\Admin\PermissionController::class, 'destroyAccount'])->name('sub-accounts.destroy')->middleware('can:menu.data-config.sub-accounts');
|
Route::delete('/sub-accounts/{id}', [App\Http\Controllers\Admin\PermissionController::class, 'destroyAccount'])->name('sub-accounts.destroy')->middleware('can:menu.data-config.sub-accounts');
|
||||||
Route::get('/sub-account-roles', [App\Http\Controllers\Admin\PermissionController::class, 'roles'])->name('sub-account-roles')->middleware('can:menu.data-config.sub-account-roles');
|
Route::get('/sub-account-roles', function() {
|
||||||
Route::get('/sub-account-roles/create', [App\Http\Controllers\Admin\PermissionController::class, 'createRole'])->name('sub-account-roles.create')->middleware('can:menu.data-config.sub-account-roles');
|
return redirect()->route('admin.data-config.sub-accounts', ['tab' => 'roles']);
|
||||||
Route::get('/sub-account-roles/{id}/edit', [App\Http\Controllers\Admin\PermissionController::class, 'editRole'])->name('sub-account-roles.edit')->middleware('can:menu.data-config.sub-account-roles');
|
})->name('sub-account-roles')->middleware('can:menu.data-config.sub-accounts');
|
||||||
Route::post('/sub-account-roles', [App\Http\Controllers\Admin\PermissionController::class, 'storeRole'])->name('sub-account-roles.store')->middleware('can:menu.data-config.sub-account-roles');
|
Route::get('/sub-account-roles/create', [App\Http\Controllers\Admin\PermissionController::class, 'createRole'])->name('sub-account-roles.create')->middleware('can:menu.data-config.sub-accounts');
|
||||||
Route::put('/sub-account-roles/{id}', [App\Http\Controllers\Admin\PermissionController::class, 'updateRole'])->name('sub-account-roles.update')->middleware('can:menu.data-config.sub-account-roles');
|
Route::get('/sub-account-roles/{id}/edit', [App\Http\Controllers\Admin\PermissionController::class, 'editRole'])->name('sub-account-roles.edit')->middleware('can:menu.data-config.sub-accounts');
|
||||||
Route::delete('/sub-account-roles/{id}', [App\Http\Controllers\Admin\PermissionController::class, 'destroyRole'])->name('sub-account-roles.destroy')->middleware('can:menu.data-config.sub-account-roles');
|
Route::post('/sub-account-roles', [App\Http\Controllers\Admin\PermissionController::class, 'storeRole'])->name('sub-account-roles.store')->middleware('can:menu.data-config.sub-accounts');
|
||||||
|
Route::put('/sub-account-roles/{id}', [App\Http\Controllers\Admin\PermissionController::class, 'updateRole'])->name('sub-account-roles.update')->middleware('can:menu.data-config.sub-accounts');
|
||||||
|
Route::delete('/sub-account-roles/{id}', [App\Http\Controllers\Admin\PermissionController::class, 'destroyRole'])->name('sub-account-roles.destroy')->middleware('can:menu.data-config.sub-accounts');
|
||||||
Route::get('/points', [App\Http\Controllers\Admin\DataConfigController::class, 'points'])->name('points');
|
Route::get('/points', [App\Http\Controllers\Admin\DataConfigController::class, 'points'])->name('points');
|
||||||
Route::get('/badges', [App\Http\Controllers\Admin\DataConfigController::class, 'badges'])->name('badges');
|
Route::get('/badges', [App\Http\Controllers\Admin\DataConfigController::class, 'badges'])->name('badges');
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user