Dashboard Redesign (#48)

* feat: add user_template setting

* style: header

* style: page padding

* style: header

* feat: header now time

* style: login page

* feat: nav indicator

* style: button inset shadow

* style: footer text size

* feat: header show login_ip

* fix: error toast

* fix: frontend_templates setting

* fix: lint

* feat: pr auto format

* chore: auto-fix linting and formatting issues

---------

Co-authored-by: hamster1963 <hamster1963@users.noreply.github.com>
This commit is contained in:
仓鼠
2024-12-13 23:51:33 +08:00
committed by GitHub
co-authored by hamster1963
parent 811835ffe5
commit 540bb0185d
132 changed files with 13241 additions and 12877 deletions
+84 -97
View File
@@ -1,9 +1,5 @@
"use client"
import * as React from "react"
import { Check, ChevronDown } from "lucide-react"
import { cn } from "@/lib/utils"
import { Button } from "@/components/ui/button"
import {
Command,
@@ -13,106 +9,97 @@ import {
CommandItem,
CommandList,
} from "@/components/ui/command"
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover"
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover"
import { cn } from "@/lib/utils"
import { Check, ChevronDown } from "lucide-react"
import * as React from "react"
interface ComboboxProps
extends React.ButtonHTMLAttributes<HTMLButtonElement> {
interface ComboboxProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
options: {
label: string,
value: string,
}[];
label: string
value: string
}[]
placeholder?: string;
defaultValue?: string;
className?: string;
onValueChange: (value: string) => void;
placeholder?: string
defaultValue?: string
className?: string
onValueChange: (value: string) => void
}
export const Combobox = React.forwardRef<
HTMLButtonElement,
ComboboxProps
>(({
options,
placeholder,
defaultValue,
className,
onValueChange,
...props
}, ref) => {
const [open, setOpen] = React.useState(false)
const [value, setValue] = React.useState(defaultValue)
export const Combobox = React.forwardRef<HTMLButtonElement, ComboboxProps>(
({ options, placeholder, defaultValue, className, onValueChange, ...props }, ref) => {
const [open, setOpen] = React.useState(false)
const [value, setValue] = React.useState(defaultValue)
return (
<Popover open={open} onOpenChange={setOpen}>
<PopoverTrigger asChild>
<Button
ref={ref}
{...props}
role="combobox"
variant="outline"
aria-expanded={open}
className={cn(
"flex w-full justify-between hover:bg-inherit",
className
)}
>
{value
? (() => {
const val = options.find((option) => option.value === value)?.label
return (
val ? (
return (
<Popover open={open} onOpenChange={setOpen}>
<PopoverTrigger asChild>
<Button
ref={ref}
{...props}
role="combobox"
variant="outline"
aria-expanded={open}
className={cn("flex w-full justify-between hover:bg-inherit", className)}
>
{value ? (
(() => {
const val = options.find((option) => option.value === value)?.label
return val ? (
<div>{val}</div>
) : (
<div className="text-muted-foreground">{placeholder}</div>
)
)
})()
: <div className="text-muted-foreground">{placeholder}</div>}
<ChevronDown className="ml-auto opacity-50" />
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto p-0" align="start">
<Command
filter={(value, search, keywords = []) => {
const extendValue = value + " " + keywords.join(" ");
if (extendValue.toLowerCase().includes(search.toLowerCase())) {
return 1;
}
return 0;
}}
>
<CommandInput placeholder={placeholder} className="h-9" />
<CommandList>
<CommandEmpty>No result found.</CommandEmpty>
<CommandGroup>
{options.map((option) => (
<CommandItem
key={option.value}
value={option.value}
keywords={[option.label]}
onSelect={(currentValue) => {
setValue(currentValue === value ? "" : currentValue)
onValueChange(currentValue === value ? "" : currentValue)
setOpen(false)
}}
>
<Check
className={cn(
"justify-start",
value === option.value ? "opacity-100" : "opacity-0"
)}
/>
<span>{option.label}</span>
</CommandItem>
))}
</CommandGroup>
</CommandList>
</Command>
</PopoverContent>
</Popover>
)
});
})()
) : (
<div className="text-muted-foreground">{placeholder}</div>
)}
<ChevronDown className="ml-auto opacity-50" />
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto p-0" align="start">
<Command
filter={(value, search, keywords = []) => {
const extendValue = value + " " + keywords.join(" ")
if (extendValue.toLowerCase().includes(search.toLowerCase())) {
return 1
}
return 0
}}
>
<CommandInput placeholder={placeholder} className="h-9" />
<CommandList>
<CommandEmpty>No result found.</CommandEmpty>
<CommandGroup>
{options.map((option) => (
<CommandItem
key={option.value}
value={option.value}
keywords={[option.label]}
onSelect={(currentValue) => {
setValue(currentValue === value ? "" : currentValue)
onValueChange(
currentValue === value ? "" : currentValue,
)
setOpen(false)
}}
>
<Check
className={cn(
"justify-start",
value === option.value
? "opacity-100"
: "opacity-0",
)}
/>
<span>{option.label}</span>
</CommandItem>
))}
</CommandGroup>
</CommandList>
</Command>
</PopoverContent>
</Popover>
)
},
)