feat: enhance import/export functionality with detailed results dialog and improved data handling

This commit is contained in:
2026-05-15 11:34:23 +04:00
parent fcbba6247d
commit 54d11f01b4
18 changed files with 312 additions and 59 deletions
@@ -141,9 +141,20 @@ export function AppSidebar({ navGroups, logo, user, ...props }: AppSidebarProps)
)
}
function isPathActive(pathname: string, href: string): boolean {
if (href === '/') return pathname === '/'
return pathname === href || pathname.startsWith(href + '/')
}
function isItemActive(pathname: string, item: { href: string; matchPath?: string; isActive?: boolean }): boolean {
if (item.isActive !== undefined) return item.isActive
if (item.matchPath) return isPathActive(pathname, item.matchPath)
return isPathActive(pathname, item.href)
}
function SimpleNavItem({ item, isCollapsed }: { item: NavItem; isCollapsed: boolean }) {
const pathname = usePathname()
const isActive = item.isActive ?? pathname === item.href
const isActive = isItemActive(pathname, item)
return (
<SidebarMenuItem>
@@ -169,8 +180,8 @@ function SimpleNavItem({ item, isCollapsed }: { item: NavItem; isCollapsed: bool
function CollapsibleNavItem({ item, isCollapsed }: { item: NavItem; isCollapsed: boolean }) {
const pathname = usePathname()
const isChildActive = item.items?.some((sub) => pathname === sub.href)
const isActive = item.isActive ?? (pathname === item.href || isChildActive === true)
const isChildActive = item.items?.some((sub) => isItemActive(pathname, sub))
const isActive = item.isActive ?? (isItemActive(pathname, item) || isChildActive === true)
// Collapsed sidebar → flyout dropdown with sub-items
if (isCollapsed) {
@@ -210,7 +221,7 @@ function CollapsibleNavItem({ item, isCollapsed }: { item: NavItem; isCollapsed:
</DropdownMenuLabel>
<DropdownMenuSeparator />
{item.items?.map((sub) => {
const isSubActive = sub.isActive ?? pathname === sub.href
const isSubActive = isItemActive(pathname, sub)
return (
<DropdownMenuItem key={sub.href} asChild>
<Link
@@ -272,7 +283,7 @@ function CollapsibleNavItem({ item, isCollapsed }: { item: NavItem; isCollapsed:
<CollapsibleContent className="overflow-hidden py-2 data-[state=open]:animate-collapsible-down data-[state=closed]:animate-collapsible-up">
<SidebarMenuSub>
{item.items?.map((sub) => {
const isSubActive = sub.isActive ?? pathname === sub.href
const isSubActive = isItemActive(pathname, sub)
return (
<SidebarMenuSubItem key={sub.href}>
<SidebarMenuSubButton asChild isActive={isSubActive} className="dashboard-nav-sub-item my-0.5">
@@ -68,14 +68,22 @@ export default function DashboardDetailsPageLayout({
</Button>
)}
{(avatarSrc || avatarFallback) && (
<a rel="preload" target="_blank" href={avatarSrc} >
<Avatar className="size-14">
{avatarSrc && <AvatarImage src={avatarSrc} alt={title} />}
<AvatarFallback>
{avatarFallback ?? title.charAt(0).toUpperCase()}
</AvatarFallback>
</Avatar>
</a>
avatarSrc ? (
<a target="_blank" rel="noopener noreferrer" href={avatarSrc}>
<Avatar className="size-14">
<AvatarImage src={avatarSrc} alt={title} />
<AvatarFallback>
{avatarFallback ?? title.charAt(0).toUpperCase()}
</AvatarFallback>
</Avatar>
</a>
) : (
<Avatar className="size-14">
<AvatarFallback>
{avatarFallback ?? title.charAt(0).toUpperCase()}
</AvatarFallback>
</Avatar>
)
)}
{!avatarSrc && !avatarFallback && icon && (
<div className="flex items-center justify-center size-10 rounded-full bg-muted text-muted-foreground">
+7
View File
@@ -6,6 +6,12 @@ export type NavItem = {
href: string
icon?: ReactNode
isActive?: boolean
/**
* Optional prefix used to decide active state when the link target
* differs from the page's URL pattern (e.g. `/calendar/appointment/list`
* is the link, but the item should stay active on `/calendar/appointment/{id}`).
*/
matchPath?: string
badge?: string | number
items?: NavSubItem[]
}
@@ -15,6 +21,7 @@ export type NavSubItem = {
href: string
icon?: ReactNode
isActive?: boolean
matchPath?: string
}
export type NavGroup = {