frontend fully integreated with the backend

This commit is contained in:
Kalana B. Thilakarathna
2026-08-25 23:47:33 +05:30
parent 1bee5f91c6
commit 83d3272784
151 changed files with 10724 additions and 573 deletions
+71 -9
View File
@@ -7,7 +7,64 @@ import { cn } from "@/lib/utils"
import { HugeiconsIcon } from "@hugeicons/react"
import { UnfoldMoreIcon, Tick02Icon, ArrowUp01Icon, ArrowDown01Icon } from "@hugeicons/core-free-icons"
const Select = SelectPrimitive.Root
function collectSelectItems(children: React.ReactNode): Array<{ value: unknown; label: string }> {
const items: Array<{ value: unknown; label: string }> = []
React.Children.forEach(children, (child) => {
if (!React.isValidElement<{ value?: unknown; label?: string; children?: React.ReactNode }>(child)) {
return
}
if ("value" in child.props) {
items.push({
value: child.props.value ?? null,
label: child.props.label ?? getItemLabel(child.props.children) ?? String(child.props.value ?? ""),
})
}
if (child.props.children) {
items.push(...collectSelectItems(child.props.children))
}
})
return items
}
function Select<Value, Multiple extends boolean | undefined = false>({
children,
items,
...props
}: SelectPrimitive.Root.Props<Value, Multiple>) {
const derivedItems = React.useMemo(
() => (items == null ? collectSelectItems(children) : items),
[children, items]
)
return (
<SelectPrimitive.Root {...props} items={derivedItems}>
{children}
</SelectPrimitive.Root>
)
}
function getItemLabel(children: React.ReactNode): string | undefined {
if (typeof children === "string" || typeof children === "number") {
return String(children)
}
if (Array.isArray(children)) {
const parts = children
.map(getItemLabel)
.filter((part): part is string => Boolean(part))
return parts.length > 0 ? parts.join(" ") : undefined
}
if (React.isValidElement<{ children?: React.ReactNode }>(children)) {
return getItemLabel(children.props.children)
}
return undefined
}
function SelectGroup({ className, ...props }: SelectPrimitive.Group.Props) {
return (
@@ -64,12 +121,13 @@ function SelectContent({
sideOffset = 4,
align = "center",
alignOffset = 0,
alignItemWithTrigger = true,
alignItemWithTrigger = false,
collisionAvoidance = { side: "shift", align: "shift", fallbackAxisSide: "none" },
...props
}: SelectPrimitive.Popup.Props &
Pick<
SelectPrimitive.Positioner.Props,
"align" | "alignOffset" | "side" | "sideOffset" | "alignItemWithTrigger"
"align" | "alignOffset" | "side" | "sideOffset" | "alignItemWithTrigger" | "collisionAvoidance"
>) {
return (
<SelectPrimitive.Portal>
@@ -79,6 +137,7 @@ function SelectContent({
align={align}
alignOffset={alignOffset}
alignItemWithTrigger={alignItemWithTrigger}
collisionAvoidance={collisionAvoidance}
className="isolate z-50"
>
<SelectPrimitive.Popup
@@ -114,25 +173,28 @@ function SelectItem({
children,
...props
}: SelectPrimitive.Item.Props) {
const label = props.label ?? getItemLabel(children)
return (
<SelectPrimitive.Item
{...props}
data-slot="select-item"
label={label}
className={cn(
"relative flex min-h-7 w-full cursor-default items-center gap-2 rounded-xl py-1.5 pr-8 pl-2 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2",
"relative flex min-h-7 w-full items-center gap-2 rounded-xl py-1.5 pr-8 pl-2 text-sm text-popover-foreground outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
className
)}
{...props}
>
<SelectPrimitive.ItemText className="flex flex-1 shrink-0 gap-2 whitespace-nowrap">
{children}
</SelectPrimitive.ItemText>
<SelectPrimitive.ItemIndicator
render={
<span className="pointer-events-none absolute right-2 flex size-4 items-center justify-center" />
<span className="pointer-events-none flex size-4 shrink-0 items-center justify-center" />
}
>
<HugeiconsIcon icon={Tick02Icon} strokeWidth={2} className="pointer-events-none" />
</SelectPrimitive.ItemIndicator>
<SelectPrimitive.ItemText className="block flex-1 whitespace-nowrap text-popover-foreground">
{children}
</SelectPrimitive.ItemText>
</SelectPrimitive.Item>
)
}