forked from syntaxbullet/aurorabot
feat: Implement new settings pages and refactor application layout and navigation with new components and hooks.
This commit is contained in:
141
web/src/pages/settings/Roles.tsx
Normal file
141
web/src/pages/settings/Roles.tsx
Normal file
@@ -0,0 +1,141 @@
|
||||
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>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user