refactor(cms): separate dashboard data and editor components with focused UX fixes
This commit is contained in:
1 parent
3ae4f21217
commit
e17346ab9f
11 files changed
+1212
-1118
No files matched your search
+3
-120
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,56 @@
|
|||||||
|
"use client";
|
||||||
|
import { cn } from "@/lib/utils";
|
||||||
|
/* ─── Helpers ────────────────────────────────────────────── */
|
||||||
|
|
||||||
|
export function categorizePerms(keys: string[]) {
|
||||||
|
const commands: string[] = [];
|
||||||
|
const account: string[] = [];
|
||||||
|
const other: string[] = [];
|
||||||
|
for (const key of keys.sort()) {
|
||||||
|
if (key.startsWith("cmd_") || key === "kiss_cmd") commands.push(key);
|
||||||
|
else if (key.startsWith("acc_")) account.push(key);
|
||||||
|
else other.push(key);
|
||||||
|
}
|
||||||
|
return { commands, account, other };
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ─── Tri-state Toggle ───────────────────────────────────── */
|
||||||
|
|
||||||
|
export function PermToggle({
|
||||||
|
value,
|
||||||
|
maxValue,
|
||||||
|
onChange,
|
||||||
|
}: {
|
||||||
|
value: string;
|
||||||
|
maxValue: number;
|
||||||
|
onChange: (v: string) => void;
|
||||||
|
}) {
|
||||||
|
const values = Array.from({ length: Math.max(1, maxValue) + 1 }, (_, i) =>
|
||||||
|
String(i),
|
||||||
|
);
|
||||||
|
return (
|
||||||
|
<div className="flex gap-0.5 shrink-0">
|
||||||
|
{values.map((v) => (
|
||||||
|
<button
|
||||||
|
key={v}
|
||||||
|
type="button"
|
||||||
|
aria-pressed={v === value}
|
||||||
|
aria-label={`Permission value ${v}`}
|
||||||
|
onClick={() => onChange(v)}
|
||||||
|
className={cn(
|
||||||
|
"w-7 h-6 text-[11px] font-mono rounded transition-all font-medium",
|
||||||
|
v === value
|
||||||
|
? v === "0"
|
||||||
|
? "bg-[var(--admin-text-muted)] text-[var(--color-surface-text-readable)] shadow-sm"
|
||||||
|
: v === "1"
|
||||||
|
? "bg-[var(--admin-success)] text-[var(--admin-success-foreground)] shadow-sm"
|
||||||
|
: "bg-[var(--admin-warning)] text-[var(--admin-warning-foreground)] shadow-sm"
|
||||||
|
: "bg-muted/60 text-muted-foreground/40 hover:bg-muted hover:text-muted-foreground",
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{v}
|
||||||
|
</button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,41 @@
|
|||||||
|
interface RankData {
|
||||||
|
id: number;
|
||||||
|
rank_name: string;
|
||||||
|
badge: string;
|
||||||
|
level: number;
|
||||||
|
prefix: string;
|
||||||
|
prefix_color: string;
|
||||||
|
hidden_rank: string;
|
||||||
|
log_commands: string;
|
||||||
|
room_effect: number;
|
||||||
|
auto_credits_amount: number;
|
||||||
|
auto_pixels_amount: number;
|
||||||
|
auto_gotw_amount: number;
|
||||||
|
auto_points_amount: number;
|
||||||
|
permissions: Record<string, string>;
|
||||||
|
permissionMaxValues: Record<string, number>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface RankUser {
|
||||||
|
id: number;
|
||||||
|
username: string;
|
||||||
|
look: string;
|
||||||
|
}
|
||||||
|
interface CmsRoleData {
|
||||||
|
id: number;
|
||||||
|
slug: string;
|
||||||
|
title: string;
|
||||||
|
permissionSlugs: string[];
|
||||||
|
}
|
||||||
|
interface CmsPermission {
|
||||||
|
id: number;
|
||||||
|
slug: string;
|
||||||
|
title: string;
|
||||||
|
}
|
||||||
|
export interface RankEditorProps {
|
||||||
|
rank: RankData;
|
||||||
|
users: RankUser[];
|
||||||
|
totalUsers: number;
|
||||||
|
cmsRole: CmsRoleData | null;
|
||||||
|
allCmsPermissions: CmsPermission[];
|
||||||
|
}
|
||||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,77 @@
|
|||||||
|
export interface UserPrefix {
|
||||||
|
id: number;
|
||||||
|
user_id: number;
|
||||||
|
text: string;
|
||||||
|
color: string;
|
||||||
|
icon: string;
|
||||||
|
effect: string;
|
||||||
|
active: boolean;
|
||||||
|
created_at: string;
|
||||||
|
username?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface BlacklistWord {
|
||||||
|
id: number;
|
||||||
|
word: string;
|
||||||
|
created_at: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PrefixSettings {
|
||||||
|
max_length: string;
|
||||||
|
min_rank_to_buy: string;
|
||||||
|
price_credits: string;
|
||||||
|
price_points: string;
|
||||||
|
points_type: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PrefixFormData {
|
||||||
|
username: string;
|
||||||
|
text: string;
|
||||||
|
color: string;
|
||||||
|
icon: string;
|
||||||
|
effect: string;
|
||||||
|
active: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const PRESET_EFFECTS = [
|
||||||
|
{ id: "", label: "None" },
|
||||||
|
{ id: "glow", label: "✨ Glow" },
|
||||||
|
{ id: "shadow", label: "🌑 Shadow" },
|
||||||
|
{ id: "italic", label: "𝑰 Italic" },
|
||||||
|
{ id: "outline", label: "🔲 Outline" },
|
||||||
|
{ id: "pulse", label: "💫 Pulse" },
|
||||||
|
{ id: "bold-glow", label: "💡 Neon" },
|
||||||
|
];
|
||||||
|
|
||||||
|
export const PRESET_ICONS = [
|
||||||
|
{ emoji: "", label: "None" },
|
||||||
|
{ emoji: "👑", label: "Crown" },
|
||||||
|
{ emoji: "⭐", label: "Star" },
|
||||||
|
{ emoji: "❤️", label: "Heart" },
|
||||||
|
{ emoji: "💎", label: "Diamond" },
|
||||||
|
{ emoji: "🔥", label: "Fire" },
|
||||||
|
{ emoji: "⚡", label: "Lightning" },
|
||||||
|
{ emoji: "🛡️", label: "Shield" },
|
||||||
|
{ emoji: "💀", label: "Skull" },
|
||||||
|
{ emoji: "🎵", label: "Music" },
|
||||||
|
{ emoji: "💠", label: "Gem" },
|
||||||
|
{ emoji: "⚔️", label: "Swords" },
|
||||||
|
{ emoji: "🏆", label: "Trophy" },
|
||||||
|
{ emoji: "🚀", label: "Rocket" },
|
||||||
|
{ emoji: "👻", label: "Ghost" },
|
||||||
|
{ emoji: "🐾", label: "Paw" },
|
||||||
|
{ emoji: "🍃", label: "Leaf" },
|
||||||
|
{ emoji: "😎", label: "Cool" },
|
||||||
|
{ emoji: "🐺", label: "Wolf" },
|
||||||
|
{ emoji: "🦁", label: "Lion" },
|
||||||
|
{ emoji: "🐉", label: "Dragon" },
|
||||||
|
{ emoji: "🦄", label: "Unicorn" },
|
||||||
|
{ emoji: "🌙", label: "Moon" },
|
||||||
|
{ emoji: "☀️", label: "Sun" },
|
||||||
|
{ emoji: "❄️", label: "Snow" },
|
||||||
|
{ emoji: "🌹", label: "Rose" },
|
||||||
|
{ emoji: "🎮", label: "Controller" },
|
||||||
|
{ emoji: "💰", label: "Money" },
|
||||||
|
{ emoji: "🔮", label: "Orb" },
|
||||||
|
{ emoji: "🏴☠️", label: "Pirate" },
|
||||||
|
];
|
||||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user