Files
discord-rpg-concept/web/src/pages/settings/Roles.tsx

142 lines
8.3 KiB
TypeScript

import React from "react";
import { useSettingsForm } from "./SettingsLayout";
import { FormField, FormItem, FormLabel, FormControl, FormDescription } from "@/components/ui/form";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Switch } from "@/components/ui/switch";
import { ScrollArea } from "@/components/ui/scroll-area";
import { Badge } from "@/components/ui/badge";
import { Palette, Users } from "lucide-react";
import { fromSelectValue, toSelectValue } from "@/hooks/use-settings";
export function RolesSettings() {
const { form, meta } = useSettingsForm();
return (
<div className="space-y-8 animate-in fade-in slide-up duration-500">
<div className="space-y-4">
<div className="flex items-center gap-2 mb-4">
<Badge variant="outline" className="bg-primary/5 text-primary border-primary/20">
<Users className="w-3 h-3 mr-1" /> System Roles
</Badge>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<FormField
control={form.control}
name="studentRole"
render={({ field }) => (
<FormItem className="glass-card p-5 rounded-xl border border-border/50">
<FormLabel className="font-bold">Student Role</FormLabel>
<Select onValueChange={v => field.onChange(fromSelectValue(v))} value={toSelectValue(field.value || null)}>
<FormControl>
<SelectTrigger className="bg-background/50">
<SelectValue placeholder="Select role" />
</SelectTrigger>
</FormControl>
<SelectContent>
{meta?.roles.map(r => (
<SelectItem key={r.id} value={r.id}>
<span className="flex items-center gap-2">
<span className="w-3 h-3 rounded-full" style={{ background: r.color }} />
{r.name}
</span>
</SelectItem>
))}
</SelectContent>
</Select>
<FormDescription className="text-xs">Default role for new members/students.</FormDescription>
</FormItem>
)}
/>
<FormField
control={form.control}
name="visitorRole"
render={({ field }) => (
<FormItem className="glass-card p-5 rounded-xl border border-border/50">
<FormLabel className="font-bold">Visitor Role</FormLabel>
<Select onValueChange={v => field.onChange(fromSelectValue(v))} value={toSelectValue(field.value || null)}>
<FormControl>
<SelectTrigger className="bg-background/50">
<SelectValue placeholder="Select role" />
</SelectTrigger>
</FormControl>
<SelectContent>
{meta?.roles.map(r => (
<SelectItem key={r.id} value={r.id}>
<span className="flex items-center gap-2">
<span className="w-3 h-3 rounded-full" style={{ background: r.color }} />
{r.name}
</span>
</SelectItem>
))}
</SelectContent>
</Select>
<FormDescription className="text-xs">Role for visitors/guests.</FormDescription>
</FormItem>
)}
/>
</div>
</div>
<div className="space-y-4">
<div className="flex items-center gap-2 mb-4">
<Badge variant="outline" className="bg-primary/5 text-primary border-primary/20">
<Palette className="w-3 h-3 mr-1" /> Color Roles
</Badge>
</div>
<div className="glass-card p-6 rounded-xl border border-border/50 bg-card/30">
<div className="mb-4">
<FormDescription className="text-sm">
Select roles that users can choose from to set their name color in the bot.
</FormDescription>
</div>
<ScrollArea className="h-[400px] pr-4">
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-3">
{meta?.roles.map((role) => (
<FormField
key={role.id}
control={form.control}
name="colorRoles"
render={({ field }) => {
const isSelected = field.value?.includes(role.id);
return (
<FormItem
key={role.id}
className={`flex flex-row items-center space-x-3 space-y-0 p-3 rounded-lg border transition-all cursor-pointer ${
isSelected
? 'bg-primary/10 border-primary/30 ring-1 ring-primary/20'
: 'hover:bg-muted/50 border-transparent'
}`}
>
<FormControl>
<Switch
checked={isSelected}
onCheckedChange={(checked) => {
return checked
? field.onChange([...(field.value || []), role.id])
: field.onChange(
field.value?.filter(
(value: string) => value !== role.id
)
)
}}
/>
</FormControl>
<FormLabel className="font-medium flex items-center gap-2 cursor-pointer w-full text-foreground text-sm">
<span className="w-3 h-3 rounded-full shadow-sm" style={{ background: role.color }} />
{role.name}
</FormLabel>
</FormItem>
)
}}
/>
))}
</div>
</ScrollArea>
</div>
</div>
</div>
);
}