Files
Mace-AIO-Discord-Bot---With…/dashboard/components/dashboard/leveling-form.tsx
TheOnlyMace b4110c3d66
Some checks failed
CI / Bot (Python) (push) Failing after 49s
CI / Dashboard (Next.js) (push) Failing after 11s
Update project configuration files, and API routes accordingly. Add SQLite runtime file ignores to .gitignore for better file management.
2026-07-21 17:11:38 +02:00

195 lines
8.4 KiB
TypeScript

/**
* ╔══════════════════════════════════════════════════════════════════╗
* ║ ║
* ║ +-+-+-+-+-+-+-+-+ ║
* ║ |H|e|x|a|H|o|s|t| ║
* ║ +-+-+-+-+-+-+-+-+ ║
* ║ ║
* ║ © 2026 HexaHost — All Rights Reserved ║
* ║ ║
* ║ discord ── https://discord.gg/hexahost ║
* ║ github ── https://github.com/theoneandonlymace ║
* ║ ║
* ╚══════════════════════════════════════════════════════════════════╝
*/
"use client";
import React, { useState } from "react";
import {
Save,
RefreshCcw,
Zap,
Clock,
Hash,
Palette,
Layout,
Info
} from "lucide-react";
import { toast } from "sonner";
import { api } from "@/lib/api";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Switch } from "@/components/ui/switch";
import { LevelingConfig } from "@/types/api";
interface LevelingFormProps {
initialConfig: LevelingConfig;
guildId: string;
}
export function LevelingForm({ initialConfig, guildId }: LevelingFormProps) {
const [config, setConfig] = useState<LevelingConfig>(initialConfig);
const [saving, setSaving] = useState(false);
const handleSave = async (e: React.FormEvent) => {
e.preventDefault();
setSaving(true);
const promise = api.updateLeveling(guildId, {
enabled: config.enabled,
xp_per_message: config.xp_per_message,
cooldown: config.cooldown,
level_up_channel: config.level_up_channel,
embed_color: config.embed_style.color
});
toast.promise(promise, {
loading: 'Saving leveling settings...',
success: 'Leveling settings updated successfully!',
error: 'Failed to update leveling settings',
});
try {
await promise;
} catch (err: any) {
console.error(err);
} finally {
setSaving(false);
}
};
return (
<form onSubmit={handleSave} className="grid grid-cols-1 lg:grid-cols-3 gap-8 pb-20">
<div className="lg:col-span-2 space-y-6">
<div className="bg-[#141B2D] border border-slate-800 rounded-3xl overflow-hidden shadow-xl shadow-black/20">
<div className="p-8 space-y-8">
<div className="flex items-center justify-between mb-4 border-b border-slate-800 pb-4">
<span className="text-sm font-bold text-slate-300">Social Economy Status</span>
<Switch
checked={config.enabled}
onCheckedChange={() => setConfig({...config, enabled: !config.enabled})}
/>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-8">
<div className="space-y-2">
<label className="text-xs font-black uppercase text-slate-500 tracking-widest flex items-center gap-2">
<Zap className="h-3 w-3" />
XP Weight
</label>
<Input
type="number"
value={config.xp_per_message}
onChange={(e) => setConfig({...config, xp_per_message: parseInt(e.target.value) || 0})}
placeholder="20"
disabled={!config.enabled}
className="py-6 text-lg font-bold"
/>
</div>
<div className="space-y-2">
<label className="text-xs font-black uppercase text-slate-500 tracking-widest flex items-center gap-2">
<Clock className="h-3 w-3" />
Cooldown
</label>
<div className="relative">
<Input
type="number"
value={config.cooldown}
onChange={(e) => setConfig({...config, cooldown: parseInt(e.target.value) || 0})}
placeholder="60"
disabled={!config.enabled}
className="py-6 text-lg font-bold pr-12"
/>
<span className="absolute right-4 top-1/2 -translate-y-1/2 text-xs font-bold text-slate-700">SEC</span>
</div>
</div>
</div>
<div className="space-y-2">
<label className="text-xs font-black uppercase text-slate-500 tracking-widest flex items-center gap-2">
<Hash className="h-3 w-3" />
Level Up Channel
</label>
<Input
value={config.level_up_channel || ""}
onChange={(e) => setConfig({...config, level_up_channel: e.target.value ? parseInt(e.target.value.replace(/\D/g, "")) : null})}
placeholder="Discord Channel ID"
disabled={!config.enabled}
className="py-6 font-mono"
/>
</div>
<Button
type="submit"
disabled={saving}
className="w-full h-14 text-base font-bold gap-2"
>
{saving ? <RefreshCcw className="h-5 w-5 animate-spin" /> : <Save className="h-5 w-5" />}
{saving ? "Updating System..." : "Update Leveling Engine"}
</Button>
</div>
</div>
<div className="bg-[#141B2D] border border-slate-800 rounded-3xl p-8 relative overflow-hidden group">
<div className="absolute right-0 top-0 h-full w-1 bg-primary/20" />
<h3 className="text-sm font-black uppercase text-slate-500 tracking-widest mb-6 flex items-center gap-2">
<Palette className="h-4 w-4" />
Cosmetic Defaults
</h3>
<div className="grid grid-cols-1 sm:grid-cols-2 gap-6 relative z-10">
<div className="space-y-2">
<p className="text-xs text-slate-500 font-bold px-1">Rank Card Color</p>
<div className="flex items-center gap-3">
<div className="h-10 w-10 rounded-xl border border-slate-700 shadow-inner" style={{ backgroundColor: config.embed_style.color }} />
<Input
value={config.embed_style.color}
onChange={(e) => setConfig({...config, embed_style: {...config.embed_style, color: e.target.value}})}
className="font-mono h-10"
disabled={!config.enabled}
/>
</div>
</div>
<div className="flex items-center justify-between p-4 bg-slate-900/40 rounded-2xl border border-slate-800">
<div className="flex items-center gap-3">
<Layout className="h-4 w-4 text-slate-500" />
<span className="text-sm font-bold text-slate-300">Thumbnail</span>
</div>
<Switch
checked={config.embed_style.thumbnail}
onCheckedChange={(val) => setConfig({...config, embed_style: {...config.embed_style, thumbnail: val}})}
disabled={!config.enabled}
/>
</div>
</div>
</div>
</div>
<div className="space-y-6">
<div className="bg-[#141B2D] border border-slate-800 rounded-3xl p-6 relative overflow-hidden group shadow-lg">
<div className="absolute -right-4 -top-4 opacity-[0.03] group-hover:scale-110 transition-transform">
<Info className="h-32 w-32 text-white" />
</div>
<h3 className="text-xs font-black uppercase text-slate-500 tracking-widest mb-4">Leveling Logic</h3>
<div className="space-y-4 text-sm leading-relaxed text-slate-400">
<p>Members earn <span className="text-white font-bold italic">XP</span> by chatting.</p>
<div className="p-4 bg-primary/5 rounded-2xl border border-primary/10 text-[10px] font-mono">
5 * (level ^ 2) + (50 * level) + 100
</div>
</div>
</div>
</div>
</form>
);
}