refactor: frontend improvements
This commit is contained in:
2
ai
2
ai
Submodule ai updated: 008fd7a292...761b842553
@@ -11,7 +11,7 @@
|
||||
"enumMembers",
|
||||
"duplicates"
|
||||
],
|
||||
"ignore": ["ai/**", "others/**"],
|
||||
"ignore": ["ai/**", "others/**", ".trigger/**"],
|
||||
"ignoreWorkspaces": [
|
||||
"packages/atmn",
|
||||
"packages/autumn-js",
|
||||
|
||||
@@ -14,7 +14,7 @@ import {
|
||||
DropdownMenuLabel,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/components/ui/dropdown-menu";
|
||||
} from "@/components/v2/dropdowns/DropdownMenu";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
const providers = {
|
||||
|
||||
@@ -417,8 +417,8 @@ export const PromptInputActionAddAttachments = ({
|
||||
return (
|
||||
<DropdownMenuItem
|
||||
{...props}
|
||||
onSelect={(e) => {
|
||||
e.preventDefault();
|
||||
closeOnClick={false}
|
||||
onClick={() => {
|
||||
attachments.openFileDialog();
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -29,6 +29,7 @@ function ColumnCheckboxItem<T>({ column }: { column: Column<T> }) {
|
||||
return (
|
||||
<DropdownMenuItem
|
||||
key={column.id}
|
||||
closeOnClick={false}
|
||||
onClick={() => {
|
||||
column.toggleVisibility(!isVisible);
|
||||
}}
|
||||
|
||||
@@ -4,7 +4,7 @@ import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/components/ui/dropdown-menu";
|
||||
} from "@/components/v2/dropdowns/DropdownMenu";
|
||||
|
||||
export function TableDropdownMenuCell({
|
||||
children,
|
||||
|
||||
@@ -1,308 +0,0 @@
|
||||
"use client";
|
||||
|
||||
import { Menu as MenuPrimitive } from "@base-ui/react/menu";
|
||||
import { Check, ChevronRight, Circle } from "lucide-react";
|
||||
import * as React from "react";
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
import SmallSpinner from "../general/SmallSpinner";
|
||||
|
||||
function DropdownMenu({
|
||||
...props
|
||||
}: MenuPrimitive.Root.Props) {
|
||||
return <MenuPrimitive.Root data-slot="dropdown-menu" {...props} />;
|
||||
}
|
||||
|
||||
const DropdownMenuTrigger = React.forwardRef<
|
||||
HTMLButtonElement,
|
||||
MenuPrimitive.Trigger.Props & { asChild?: boolean }
|
||||
>(({ asChild, children, ...props }, ref) => {
|
||||
if (asChild && React.isValidElement(children)) {
|
||||
return (
|
||||
<MenuPrimitive.Trigger
|
||||
ref={ref}
|
||||
data-slot="dropdown-menu-trigger"
|
||||
render={children}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<MenuPrimitive.Trigger ref={ref} data-slot="dropdown-menu-trigger" {...props}>
|
||||
{children}
|
||||
</MenuPrimitive.Trigger>
|
||||
);
|
||||
});
|
||||
DropdownMenuTrigger.displayName = "DropdownMenuTrigger";
|
||||
|
||||
function DropdownMenuGroup({
|
||||
...props
|
||||
}: MenuPrimitive.Group.Props) {
|
||||
return <MenuPrimitive.Group data-slot="dropdown-menu-group" {...props} />;
|
||||
}
|
||||
|
||||
function DropdownMenuPortal({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
return <>{children}</>;
|
||||
}
|
||||
|
||||
function DropdownMenuSub({
|
||||
...props
|
||||
}: MenuPrimitive.SubmenuRoot.Props) {
|
||||
return <MenuPrimitive.SubmenuRoot data-slot="dropdown-menu-sub" {...props} />;
|
||||
}
|
||||
|
||||
function DropdownMenuRadioGroup({
|
||||
...props
|
||||
}: MenuPrimitive.RadioGroup.Props) {
|
||||
return (
|
||||
<MenuPrimitive.RadioGroup
|
||||
data-slot="dropdown-menu-radio-group"
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
const DropdownMenuSubTrigger = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
MenuPrimitive.SubmenuTrigger.Props & {
|
||||
inset?: boolean;
|
||||
withIcon?: boolean;
|
||||
}
|
||||
>(({ className, inset, children, withIcon = true, ...props }, ref) => (
|
||||
<MenuPrimitive.SubmenuTrigger
|
||||
ref={ref}
|
||||
data-slot="dropdown-menu-sub-trigger"
|
||||
className={cn(
|
||||
"flex cursor-pointer gap-2 select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-zinc-100 data-popup-open:bg-zinc-100 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 dark:focus:bg-zinc-800 dark:data-popup-open:bg-zinc-800",
|
||||
inset && "pl-8",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
{withIcon && <ChevronRight className="ml-auto text-t3" />}
|
||||
</MenuPrimitive.SubmenuTrigger>
|
||||
));
|
||||
DropdownMenuSubTrigger.displayName = "DropdownMenuSubTrigger";
|
||||
|
||||
const DropdownMenuSubContent = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
MenuPrimitive.Popup.Props & {
|
||||
sideOffset?: number;
|
||||
}
|
||||
>(({ className, sideOffset = 0, ...props }, ref) => (
|
||||
<MenuPrimitive.Portal>
|
||||
<MenuPrimitive.Positioner
|
||||
sideOffset={sideOffset}
|
||||
positionMethod="fixed"
|
||||
className="isolate z-[160]"
|
||||
>
|
||||
<MenuPrimitive.Popup
|
||||
ref={ref}
|
||||
data-slot="dropdown-menu-sub-content"
|
||||
className={cn(
|
||||
"z-[160] min-w-[8rem] overflow-hidden rounded-md border border-zinc-200 bg-white p-1 shadow-lg data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 dark:border-zinc-800 dark:bg-zinc-950 dark:text-zinc-50 text-zinc-800 font-regular",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
</MenuPrimitive.Positioner>
|
||||
</MenuPrimitive.Portal>
|
||||
));
|
||||
DropdownMenuSubContent.displayName = "DropdownMenuSubContent";
|
||||
|
||||
const DropdownMenuContent = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
MenuPrimitive.Popup.Props & {
|
||||
sideOffset?: number;
|
||||
side?: "top" | "bottom" | "left" | "right";
|
||||
align?: "start" | "center" | "end";
|
||||
onCloseAutoFocus?: (e: any) => void;
|
||||
}
|
||||
>(({ className, sideOffset = 4, side = "bottom", align = "start", onCloseAutoFocus: _onCloseAutoFocus, ...props }, ref) => (
|
||||
<MenuPrimitive.Portal>
|
||||
<MenuPrimitive.Positioner
|
||||
sideOffset={sideOffset}
|
||||
side={side}
|
||||
align={align}
|
||||
positionMethod="fixed"
|
||||
className="isolate z-[160] outline-none"
|
||||
>
|
||||
<MenuPrimitive.Popup
|
||||
ref={ref}
|
||||
data-slot="dropdown-menu-content"
|
||||
className={cn(
|
||||
"z-[160] min-w-[8rem] overflow-hidden rounded-md border border-zinc-200 bg-white p-1 text-zinc-950 shadow-md dark:border-zinc-800 dark:bg-zinc-950 dark:text-zinc-50",
|
||||
"data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
</MenuPrimitive.Positioner>
|
||||
</MenuPrimitive.Portal>
|
||||
));
|
||||
DropdownMenuContent.displayName = "DropdownMenuContent";
|
||||
|
||||
const DropdownMenuItem = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
MenuPrimitive.Item.Props & {
|
||||
inset?: boolean;
|
||||
isLoading?: boolean;
|
||||
shimmer?: boolean;
|
||||
asChild?: boolean;
|
||||
}
|
||||
>(({ className, inset, shimmer = false, isLoading, children, asChild, ...props }, ref) => {
|
||||
if (asChild && React.isValidElement(children)) {
|
||||
return (
|
||||
<MenuPrimitive.Item
|
||||
ref={ref}
|
||||
data-slot="dropdown-menu-item"
|
||||
closeOnClick={false}
|
||||
render={children}
|
||||
className={cn(
|
||||
"relative flex cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50 [&>svg]:size-4 [&>svg]:shrink-0",
|
||||
shimmer && "shimmer",
|
||||
inset && "pl-8",
|
||||
className,
|
||||
)}
|
||||
disabled={shimmer || isLoading}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<MenuPrimitive.Item
|
||||
ref={ref}
|
||||
data-slot="dropdown-menu-item"
|
||||
closeOnClick={false}
|
||||
className={cn(
|
||||
"relative flex cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50 [&>svg]:size-4 [&>svg]:shrink-0",
|
||||
shimmer && "shimmer",
|
||||
inset && "pl-8",
|
||||
className,
|
||||
)}
|
||||
disabled={shimmer || isLoading}
|
||||
{...props}
|
||||
>
|
||||
{isLoading ? (
|
||||
<>
|
||||
{children}
|
||||
<SmallSpinner />
|
||||
</>
|
||||
) : (
|
||||
children
|
||||
)}
|
||||
</MenuPrimitive.Item>
|
||||
);
|
||||
});
|
||||
DropdownMenuItem.displayName = "DropdownMenuItem";
|
||||
|
||||
const DropdownMenuCheckboxItem = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
MenuPrimitive.CheckboxItem.Props
|
||||
>(({ className, children, checked, ...props }, ref) => (
|
||||
<MenuPrimitive.CheckboxItem
|
||||
ref={ref}
|
||||
data-slot="dropdown-menu-checkbox-item"
|
||||
className={cn(
|
||||
"relative flex cursor-pointer select-none items-center rounded-sm py-1.5 pl-1 pr-2 text-sm outline-none transition-colors focus:bg-zinc-100 focus:text-zinc-900 data-disabled:pointer-events-none data-disabled:opacity-50 dark:focus:bg-zinc-800 dark:focus:text-zinc-50",
|
||||
className,
|
||||
)}
|
||||
checked={checked}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
<span className="absolute right-2 flex h-3.5 w-3.5 items-center justify-center">
|
||||
<MenuPrimitive.CheckboxItemIndicator>
|
||||
<Check className="h-4 w-4 text-t3" />
|
||||
</MenuPrimitive.CheckboxItemIndicator>
|
||||
</span>
|
||||
</MenuPrimitive.CheckboxItem>
|
||||
));
|
||||
DropdownMenuCheckboxItem.displayName = "DropdownMenuCheckboxItem";
|
||||
|
||||
const DropdownMenuRadioItem = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
MenuPrimitive.RadioItem.Props
|
||||
>(({ className, children, ...props }, ref) => (
|
||||
<MenuPrimitive.RadioItem
|
||||
ref={ref}
|
||||
data-slot="dropdown-menu-radio-item"
|
||||
className={cn(
|
||||
"relative flex cursor-pointer select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-zinc-100 focus:text-zinc-900 data-disabled:pointer-events-none data-disabled:opacity-50 dark:focus:bg-zinc-800 dark:focus:text-zinc-50",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
|
||||
<MenuPrimitive.RadioItemIndicator>
|
||||
<Circle className="h-2 w-2 fill-current" />
|
||||
</MenuPrimitive.RadioItemIndicator>
|
||||
</span>
|
||||
{children}
|
||||
</MenuPrimitive.RadioItem>
|
||||
));
|
||||
DropdownMenuRadioItem.displayName = "DropdownMenuRadioItem";
|
||||
|
||||
const DropdownMenuLabel = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
MenuPrimitive.GroupLabel.Props & {
|
||||
inset?: boolean;
|
||||
}
|
||||
>(({ className, inset, ...props }, ref) => (
|
||||
<MenuPrimitive.GroupLabel
|
||||
ref={ref}
|
||||
data-slot="dropdown-menu-label"
|
||||
className={cn(
|
||||
"px-2 py-1.5 text-sm font-semibold",
|
||||
inset && "pl-8",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
DropdownMenuLabel.displayName = "DropdownMenuLabel";
|
||||
|
||||
const DropdownMenuSeparator = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
MenuPrimitive.Separator.Props
|
||||
>(({ className, ...props }, ref) => (
|
||||
<MenuPrimitive.Separator
|
||||
ref={ref}
|
||||
data-slot="dropdown-menu-separator"
|
||||
className={cn("-mx-1 my-1 h-px bg-zinc-100 dark:bg-zinc-800", className)}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
DropdownMenuSeparator.displayName = "DropdownMenuSeparator";
|
||||
|
||||
const DropdownMenuShortcut = ({
|
||||
className,
|
||||
...props
|
||||
}: React.HTMLAttributes<HTMLSpanElement>) => {
|
||||
return (
|
||||
<span
|
||||
className={cn("ml-auto text-xs tracking-widest opacity-60", className)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
};
|
||||
DropdownMenuShortcut.displayName = "DropdownMenuShortcut";
|
||||
|
||||
export {
|
||||
DropdownMenu,
|
||||
DropdownMenuTrigger,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuLabel,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuGroup,
|
||||
DropdownMenuPortal,
|
||||
DropdownMenuSub,
|
||||
DropdownMenuSubContent,
|
||||
DropdownMenuSubTrigger,
|
||||
};
|
||||
@@ -88,8 +88,7 @@ const DialogContent = React.forwardRef<
|
||||
ref={ref}
|
||||
data-slot="dialog-content"
|
||||
className={cn(
|
||||
"data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 fixed top-[40%] left-[50%] z-[180] grid translate-x-[-50%] translate-y-[-50%] rounded-lg border shadow-lg duration-200",
|
||||
|
||||
"data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 fixed top-[40%] left-[50%] z-[180] grid translate-x-[-50%] translate-y-[-50%] rounded-lg shadow-lg ring-1 ring-foreground/10 duration-200",
|
||||
"w-full max-w-md gap-3 bg-background",
|
||||
"p-4",
|
||||
className,
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import { Menu as MenuPrimitive } from "@base-ui/react/menu";
|
||||
import { cva, type VariantProps } from "class-variance-authority";
|
||||
import { Check, ChevronRight, Circle } from "lucide-react";
|
||||
import { Check, ChevronRight } from "lucide-react";
|
||||
import * as React from "react";
|
||||
import { useHotkeys } from "react-hotkeys-hook";
|
||||
|
||||
@@ -14,16 +14,17 @@ const DropdownMenuContext = React.createContext<{ isOpen: boolean }>({
|
||||
});
|
||||
|
||||
const dropdownMenuItemVariants = cva(
|
||||
"relative flex cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm text-t2 outline-hidden transition-colors data-disabled:pointer-events-none data-disabled:opacity-50 [&>svg]:size-4 [&>svg]:shrink-0",
|
||||
"group/dropdown-menu-item relative flex cursor-default select-none items-center gap-1.5 rounded-md px-1.5 py-1 text-sm text-t2 outline-hidden data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
default: "hover:bg-accent focus:bg-accent",
|
||||
default:
|
||||
"focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground",
|
||||
destructive:
|
||||
"hover:bg-destructive/10 focus:bg-destructive/10 text-destructive",
|
||||
"text-destructive focus:bg-destructive/10 focus:text-destructive dark:focus:bg-destructive/20",
|
||||
},
|
||||
inset: {
|
||||
true: "pl-8",
|
||||
true: "pl-7",
|
||||
false: "",
|
||||
},
|
||||
},
|
||||
@@ -38,9 +39,7 @@ type DropdownMenuItemVariantProps = VariantProps<
|
||||
typeof dropdownMenuItemVariants
|
||||
>;
|
||||
|
||||
function DropdownMenu(
|
||||
props: MenuPrimitive.Root.Props,
|
||||
) {
|
||||
function DropdownMenu(props: MenuPrimitive.Root.Props) {
|
||||
const isOpen = props.open ?? false;
|
||||
return (
|
||||
<DropdownMenuContext.Provider value={{ isOpen }}>
|
||||
@@ -74,31 +73,19 @@ const DropdownMenuTrigger = React.forwardRef<
|
||||
);
|
||||
});
|
||||
|
||||
function DropdownMenuGroup(
|
||||
props: MenuPrimitive.Group.Props,
|
||||
) {
|
||||
return (
|
||||
<MenuPrimitive.Group data-slot="dropdown-menu-group" {...props} />
|
||||
);
|
||||
function DropdownMenuGroup(props: MenuPrimitive.Group.Props) {
|
||||
return <MenuPrimitive.Group data-slot="dropdown-menu-group" {...props} />;
|
||||
}
|
||||
|
||||
function DropdownMenuPortal({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
function DropdownMenuPortal({ children }: { children: React.ReactNode }) {
|
||||
return <>{children}</>;
|
||||
}
|
||||
|
||||
function DropdownMenuSub(
|
||||
props: MenuPrimitive.SubmenuRoot.Props,
|
||||
) {
|
||||
function DropdownMenuSub(props: MenuPrimitive.SubmenuRoot.Props) {
|
||||
return <MenuPrimitive.SubmenuRoot data-slot="dropdown-menu-sub" {...props} />;
|
||||
}
|
||||
|
||||
function DropdownMenuRadioGroup(
|
||||
props: MenuPrimitive.RadioGroup.Props,
|
||||
) {
|
||||
function DropdownMenuRadioGroup(props: MenuPrimitive.RadioGroup.Props) {
|
||||
return (
|
||||
<MenuPrimitive.RadioGroup
|
||||
data-slot="dropdown-menu-radio-group"
|
||||
@@ -122,35 +109,39 @@ const DropdownMenuSubTrigger = React.forwardRef<
|
||||
ref={ref}
|
||||
data-slot="dropdown-menu-sub-trigger"
|
||||
className={cn(
|
||||
"flex cursor-pointer gap-2 select-none items-center rounded-sm px-2 py-1.5 text-sm text-t2 outline-hidden hover:bg-accent focus:bg-accent data-popup-open:bg-accent [&>svg]:pointer-events-none [&>svg]:size-4 [&>svg]:shrink-0",
|
||||
inset && "pl-8",
|
||||
"flex cursor-default gap-1.5 select-none items-center rounded-md px-1.5 py-1 text-sm text-t2 outline-hidden focus:bg-accent focus:text-accent-foreground data-popup-open:bg-accent data-popup-open:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
||||
inset && "pl-7",
|
||||
className,
|
||||
)}
|
||||
{...rest}
|
||||
>
|
||||
{children}
|
||||
{withIcon && <ChevronRight className="ml-auto text-t3" />}
|
||||
{withIcon && <ChevronRight className="ml-auto size-3.5 text-t3" />}
|
||||
</MenuPrimitive.SubmenuTrigger>
|
||||
);
|
||||
});
|
||||
|
||||
const DropdownMenuSubContent = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
MenuPrimitive.Popup.Props & { sideOffset?: number }
|
||||
MenuPrimitive.Popup.Props & {
|
||||
sideOffset?: number;
|
||||
alignOffset?: number;
|
||||
}
|
||||
>(function DropdownMenuSubContent(props, ref) {
|
||||
const { className, sideOffset = 0, ...rest } = props;
|
||||
const { className, sideOffset = 6, alignOffset = -4, ...rest } = props;
|
||||
return (
|
||||
<MenuPrimitive.Portal>
|
||||
<MenuPrimitive.Positioner
|
||||
sideOffset={sideOffset}
|
||||
alignOffset={alignOffset}
|
||||
positionMethod="fixed"
|
||||
className="isolate z-[200]"
|
||||
className="isolate z-[300] outline-none"
|
||||
>
|
||||
<MenuPrimitive.Popup
|
||||
ref={ref}
|
||||
data-slot="dropdown-menu-sub-content"
|
||||
className={cn(
|
||||
"bg-interactive-secondary text-t2 min-w-[8rem] overflow-hidden rounded-lg border p-1 shadow-md",
|
||||
"min-w-[8rem] overflow-x-hidden overflow-y-auto rounded-lg bg-interactive-secondary p-1 text-t2 shadow-lg ring-1 ring-foreground/10 duration-100 origin-(--transform-origin)",
|
||||
"data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
||||
className,
|
||||
)}
|
||||
@@ -172,7 +163,14 @@ const DropdownMenuContent = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
DropdownMenuContentProps
|
||||
>(function DropdownMenuContent(props, ref) {
|
||||
const { className, sideOffset = 4, side = "bottom", align = "start", onCloseAutoFocus: _onCloseAutoFocus, ...rest } = props;
|
||||
const {
|
||||
className,
|
||||
sideOffset = 4,
|
||||
side = "bottom",
|
||||
align = "start",
|
||||
onCloseAutoFocus: _onCloseAutoFocus,
|
||||
...rest
|
||||
} = props;
|
||||
return (
|
||||
<MenuPrimitive.Portal>
|
||||
<MenuPrimitive.Positioner
|
||||
@@ -180,13 +178,13 @@ const DropdownMenuContent = React.forwardRef<
|
||||
side={side}
|
||||
align={align}
|
||||
positionMethod="fixed"
|
||||
className="isolate z-[200] outline-none"
|
||||
className="isolate z-[300] outline-none"
|
||||
>
|
||||
<MenuPrimitive.Popup
|
||||
ref={ref}
|
||||
data-slot="dropdown-menu-content"
|
||||
className={cn(
|
||||
"bg-interactive-secondary text-t2 min-w-[8rem] overflow-hidden rounded-lg border p-1 shadow-md",
|
||||
"max-h-(--available-height) min-w-32 overflow-x-hidden overflow-y-auto rounded-lg bg-interactive-secondary p-1 text-t2 shadow-md ring-1 ring-foreground/10 duration-100 origin-(--transform-origin)",
|
||||
"data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
||||
className,
|
||||
)}
|
||||
@@ -202,6 +200,8 @@ type DropdownMenuItemProps = MenuPrimitive.Item.Props &
|
||||
isLoading?: boolean;
|
||||
shimmer?: boolean;
|
||||
shortcut?: string;
|
||||
asChild?: boolean;
|
||||
closeOnClick?: boolean;
|
||||
};
|
||||
|
||||
const DropdownMenuItem = React.forwardRef<
|
||||
@@ -214,6 +214,8 @@ const DropdownMenuItem = React.forwardRef<
|
||||
shimmer = false,
|
||||
isLoading,
|
||||
shortcut,
|
||||
asChild,
|
||||
closeOnClick,
|
||||
className,
|
||||
children,
|
||||
onClick,
|
||||
@@ -233,11 +235,30 @@ const DropdownMenuItem = React.forwardRef<
|
||||
},
|
||||
);
|
||||
|
||||
if (asChild && React.isValidElement(children)) {
|
||||
return (
|
||||
<MenuPrimitive.Item
|
||||
ref={ref}
|
||||
data-slot="dropdown-menu-item"
|
||||
render={children}
|
||||
closeOnClick={closeOnClick}
|
||||
className={cn(
|
||||
dropdownMenuItemVariants({ variant, inset }),
|
||||
shimmer && "shimmer",
|
||||
className,
|
||||
)}
|
||||
disabled={shimmer || isLoading}
|
||||
onClick={onClick}
|
||||
{...rest}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<MenuPrimitive.Item
|
||||
ref={ref}
|
||||
data-slot="dropdown-menu-item"
|
||||
closeOnClick={false}
|
||||
closeOnClick={closeOnClick}
|
||||
className={cn(
|
||||
dropdownMenuItemVariants({ variant, inset }),
|
||||
shimmer && "shimmer",
|
||||
@@ -261,23 +282,25 @@ const DropdownMenuItem = React.forwardRef<
|
||||
|
||||
const DropdownMenuCheckboxItem = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
MenuPrimitive.CheckboxItem.Props
|
||||
MenuPrimitive.CheckboxItem.Props & { inset?: boolean }
|
||||
>(function DropdownMenuCheckboxItem(props, ref) {
|
||||
const { className, children, ...rest } = props;
|
||||
const { className, children, inset, ...rest } = props;
|
||||
return (
|
||||
<MenuPrimitive.CheckboxItem
|
||||
ref={ref}
|
||||
data-slot="dropdown-menu-checkbox-item"
|
||||
data-inset={inset}
|
||||
closeOnClick={false}
|
||||
className={cn(
|
||||
"relative flex cursor-pointer select-none items-center rounded-sm py-1.5 pl-1 pr-2 text-sm text-t2 outline-hidden transition-colors hover:bg-accent focus:bg-accent data-disabled:pointer-events-none data-disabled:opacity-50",
|
||||
"relative flex cursor-default select-none items-center gap-1.5 rounded-md py-1 pr-8 pl-1.5 text-sm outline-hidden focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground data-inset:pl-7 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
||||
className,
|
||||
)}
|
||||
{...rest}
|
||||
>
|
||||
{children}
|
||||
<span className="absolute right-2 flex size-3.5 items-center justify-center">
|
||||
<span className="pointer-events-none absolute right-2 flex items-center justify-center">
|
||||
<MenuPrimitive.CheckboxItemIndicator>
|
||||
<Check className="size-4 text-t3" />
|
||||
<Check className="size-4" />
|
||||
</MenuPrimitive.CheckboxItemIndicator>
|
||||
</span>
|
||||
</MenuPrimitive.CheckboxItem>
|
||||
@@ -286,22 +309,23 @@ const DropdownMenuCheckboxItem = React.forwardRef<
|
||||
|
||||
const DropdownMenuRadioItem = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
MenuPrimitive.RadioItem.Props
|
||||
MenuPrimitive.RadioItem.Props & { inset?: boolean }
|
||||
>(function DropdownMenuRadioItem(props, ref) {
|
||||
const { className, children, ...rest } = props;
|
||||
const { className, children, inset, ...rest } = props;
|
||||
return (
|
||||
<MenuPrimitive.RadioItem
|
||||
ref={ref}
|
||||
data-slot="dropdown-menu-radio-item"
|
||||
data-inset={inset}
|
||||
className={cn(
|
||||
"relative flex cursor-pointer select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm text-t2 outline-hidden transition-colors hover:bg-accent focus:bg-accent data-disabled:pointer-events-none data-disabled:opacity-50",
|
||||
"relative flex cursor-default select-none items-center gap-1.5 rounded-md py-1 pr-8 pl-1.5 text-sm outline-hidden focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground data-inset:pl-7 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
||||
className,
|
||||
)}
|
||||
{...rest}
|
||||
>
|
||||
<span className="absolute left-2 flex size-3.5 items-center justify-center">
|
||||
<span className="pointer-events-none absolute right-2 flex items-center justify-center">
|
||||
<MenuPrimitive.RadioItemIndicator>
|
||||
<Circle className="size-2 fill-current" />
|
||||
<Check className="size-4" />
|
||||
</MenuPrimitive.RadioItemIndicator>
|
||||
</span>
|
||||
{children}
|
||||
@@ -322,9 +346,9 @@ const DropdownMenuLabel = React.forwardRef<
|
||||
<MenuPrimitive.GroupLabel
|
||||
ref={ref}
|
||||
data-slot="dropdown-menu-label"
|
||||
data-inset={inset}
|
||||
className={cn(
|
||||
"px-2 py-1.5 text-sm font-semibold",
|
||||
inset && "pl-8",
|
||||
"px-1.5 py-1 text-xs font-medium text-muted-foreground data-inset:pl-7",
|
||||
className,
|
||||
)}
|
||||
{...rest}
|
||||
@@ -354,7 +378,10 @@ function DropdownMenuShortcut(props: DropdownMenuShortcutProps) {
|
||||
return (
|
||||
<span
|
||||
data-slot="dropdown-menu-shortcut"
|
||||
className={cn("ml-auto text-xs tracking-widest text-t4", className)}
|
||||
className={cn(
|
||||
"ml-auto text-xs tracking-widest text-muted-foreground group-focus/dropdown-menu-item:text-accent-foreground",
|
||||
className,
|
||||
)}
|
||||
{...rest}
|
||||
/>
|
||||
);
|
||||
@@ -367,7 +394,11 @@ export {
|
||||
DropdownMenuGroup,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuLabel,
|
||||
DropdownMenuPortal,
|
||||
DropdownMenuRadioGroup,
|
||||
DropdownMenuRadioItem,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuShortcut,
|
||||
DropdownMenuSub,
|
||||
DropdownMenuSubContent,
|
||||
DropdownMenuSubTrigger,
|
||||
|
||||
@@ -1,21 +1,6 @@
|
||||
import { Check, ChevronsUpDown } from "lucide-react";
|
||||
import { useState } from "react";
|
||||
import {
|
||||
Command,
|
||||
CommandEmpty,
|
||||
CommandGroup,
|
||||
CommandInput,
|
||||
CommandItem,
|
||||
CommandList,
|
||||
} from "@/components/ui/command";
|
||||
import {
|
||||
Popover,
|
||||
PopoverContent,
|
||||
PopoverTrigger,
|
||||
} from "@/components/ui/popover";
|
||||
import { Button } from "@/components/v2/buttons/Button";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { stripeCurrencyCodes } from "@/utils/constants/stripeCurrencyCodes";
|
||||
import { SearchableSelect } from "./SearchableSelect";
|
||||
|
||||
export const CurrencySelect = ({
|
||||
defaultCurrency,
|
||||
@@ -28,54 +13,19 @@ export const CurrencySelect = ({
|
||||
className?: string;
|
||||
disabled?: boolean;
|
||||
}) => {
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
return (
|
||||
<Popover open={open} onOpenChange={setOpen}>
|
||||
<PopoverTrigger asChild>
|
||||
<Button
|
||||
variant="secondary"
|
||||
role="combobox"
|
||||
aria-expanded={open}
|
||||
className={cn("w-full justify-between", className)}
|
||||
disabled={disabled}
|
||||
disableActive
|
||||
>
|
||||
{defaultCurrency ? defaultCurrency : "Select currency..."}
|
||||
<ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="p-0 w-[var(--anchor-width)]">
|
||||
<Command className="p-0">
|
||||
<CommandInput placeholder="Search currency..." />
|
||||
<CommandEmpty>No currency found.</CommandEmpty>
|
||||
<CommandList className="p-0">
|
||||
<CommandGroup className="p-0">
|
||||
{stripeCurrencyCodes.map((currency) => (
|
||||
<CommandItem
|
||||
key={currency.code}
|
||||
value={currency.code}
|
||||
onSelect={(value) => {
|
||||
setDefaultCurrency(value.toUpperCase());
|
||||
setOpen(false);
|
||||
}}
|
||||
className="p-2 flex items-center justify-between"
|
||||
>
|
||||
{currency.currency} - {currency.code}
|
||||
<Check
|
||||
className={cn(
|
||||
"mr-2 h-4 w-4",
|
||||
defaultCurrency === currency.code
|
||||
? "opacity-100"
|
||||
: "opacity-0",
|
||||
)}
|
||||
/>
|
||||
</CommandItem>
|
||||
))}
|
||||
</CommandGroup>
|
||||
</CommandList>
|
||||
</Command>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
<SearchableSelect
|
||||
value={defaultCurrency}
|
||||
onValueChange={(value) => setDefaultCurrency(value.toUpperCase())}
|
||||
options={stripeCurrencyCodes}
|
||||
getOptionValue={(currency) => currency.code}
|
||||
getOptionLabel={(currency) => `${currency.currency} - ${currency.code}`}
|
||||
searchable
|
||||
searchPlaceholder="Search currency..."
|
||||
placeholder="Select currency..."
|
||||
emptyText="No currency found."
|
||||
disabled={disabled}
|
||||
triggerClassName={cn("w-full", className)}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -93,12 +93,12 @@ function SelectContent({
|
||||
side={side}
|
||||
alignItemWithTrigger={false}
|
||||
positionMethod="fixed"
|
||||
className="isolate z-[160]"
|
||||
className="isolate z-[300] outline-none"
|
||||
>
|
||||
<SelectPrimitive.Popup
|
||||
data-slot="select-content"
|
||||
className={cn(
|
||||
"bg-interactive-secondary text-popover-foreground relative max-h-[var(--available-height)] min-w-[var(--anchor-width)] overflow-x-hidden overflow-y-auto rounded-md border shadow-md p-1",
|
||||
"bg-interactive-secondary text-t2 relative max-h-[var(--available-height)] min-w-[var(--anchor-width)] overflow-x-hidden overflow-y-auto rounded-lg shadow-md ring-1 ring-foreground/10 p-1",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
@@ -132,12 +132,12 @@ function SelectItem({
|
||||
<SelectPrimitive.Item
|
||||
data-slot="select-item"
|
||||
className={cn(
|
||||
"focus:bg-accent focus:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex w-full cursor-pointer items-center gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm outline-hidden select-none 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",
|
||||
"data-highlighted:bg-accent data-highlighted:text-accent-foreground data-highlighted:**:text-accent-foreground focus:bg-accent focus:text-accent-foreground relative flex w-full cursor-default items-center gap-1.5 rounded-md py-1 pr-8 pl-1.5 text-sm outline-hidden select-none 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",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
<span className="absolute right-2 flex size-3.5 items-center justify-center">
|
||||
<span className="pointer-events-none absolute right-2 flex items-center justify-center">
|
||||
<SelectPrimitive.ItemIndicator>
|
||||
<CheckIcon className="size-4" />
|
||||
</SelectPrimitive.ItemIndicator>
|
||||
|
||||
@@ -46,15 +46,16 @@ export const FilterStatusSubMenu = () => {
|
||||
{statuses.map((status: any) => {
|
||||
const isActive = selectedStatuses.includes(status);
|
||||
return (
|
||||
<DropdownMenuItem
|
||||
key={status}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
toggleStatus(status);
|
||||
}}
|
||||
onSelect={(e) => e.preventDefault()}
|
||||
className="flex items-center gap-2 cursor-pointer text-sm"
|
||||
>
|
||||
<DropdownMenuItem
|
||||
key={status}
|
||||
closeOnClick={false}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
toggleStatus(status);
|
||||
}}
|
||||
className="flex items-center gap-2 cursor-pointer text-sm"
|
||||
>
|
||||
<Checkbox checked={isActive} className="border-border" />
|
||||
{keyToTitle(status)}
|
||||
</DropdownMenuItem>
|
||||
|
||||
@@ -70,11 +70,11 @@ export const ProcessorSubMenu = () => {
|
||||
return (
|
||||
<DropdownMenuItem
|
||||
key={value}
|
||||
closeOnClick={false}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
toggleProcessor(value);
|
||||
}}
|
||||
onSelect={(e) => e.preventDefault()}
|
||||
className="flex items-center gap-2 cursor-pointer text-sm"
|
||||
>
|
||||
<Checkbox checked={isActive} className="border-border" />
|
||||
|
||||
@@ -192,11 +192,11 @@ export const ProductsSubMenu = () => {
|
||||
{versionCount === 1 ? (
|
||||
// Single version - show just one button for the product
|
||||
<DropdownMenuItem
|
||||
closeOnClick={false}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
toggleVersion(product.id, "1");
|
||||
}}
|
||||
onSelect={(e) => e.preventDefault()}
|
||||
className="flex items-center gap-2 cursor-pointer font-medium"
|
||||
>
|
||||
<Checkbox
|
||||
@@ -232,11 +232,11 @@ export const ProductsSubMenu = () => {
|
||||
</DropdownMenuSubTrigger>
|
||||
<DropdownMenuSubContent>
|
||||
<DropdownMenuItem
|
||||
closeOnClick={false}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
toggleProduct(product);
|
||||
}}
|
||||
onSelect={(e) => e.preventDefault()}
|
||||
className="flex items-center gap-2 cursor-pointer font-medium"
|
||||
>
|
||||
<Checkbox
|
||||
@@ -257,11 +257,11 @@ export const ProductsSubMenu = () => {
|
||||
return (
|
||||
<DropdownMenuItem
|
||||
key={versionKey}
|
||||
closeOnClick={false}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
toggleVersion(product.id, version.toString());
|
||||
}}
|
||||
onSelect={(e) => e.preventDefault()}
|
||||
className="flex items-center gap-2 cursor-pointer text-sm"
|
||||
>
|
||||
<Checkbox
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
import { Button } from "@/components/v2/buttons/Button";
|
||||
import { Input } from "@/components/v2/inputs/Input";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
import { useAxiosInstance } from "@/services/useAxiosInstance";
|
||||
import { getBackendErr } from "@/utils/genUtils";
|
||||
import { useSavedViewsQuery } from "../../hooks/useSavedViewsQuery";
|
||||
@@ -63,17 +64,16 @@ export const SaveViewPopover = ({ onClose }: SaveViewPopoverProps) => {
|
||||
return (
|
||||
<Popover open={open} onOpenChange={setOpen}>
|
||||
<PopoverTrigger asChild>
|
||||
<Button
|
||||
variant="skeleton"
|
||||
size="sm"
|
||||
<button
|
||||
type="button"
|
||||
className={cn(
|
||||
"w-full !h-full text-t3 text-sm hover:bg-accent hover:text-t2 rounded-none gap-0",
|
||||
"flex-1 flex items-center justify-center gap-1.5 rounded-br-lg px-2 py-1.5 text-xs text-t3 hover:text-t2 hover:bg-accent cursor-default",
|
||||
open && "bg-accent text-t1",
|
||||
)}
|
||||
>
|
||||
<Pin size={12} className="mr-2" />
|
||||
<Pin size={10} />
|
||||
Save
|
||||
</Button>
|
||||
</button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent
|
||||
sideOffset={2}
|
||||
|
||||
@@ -2,17 +2,17 @@ import { TrashIcon } from "@phosphor-icons/react";
|
||||
import { useState } from "react";
|
||||
import { toast } from "sonner";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
DropdownMenuGroup,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuLabel,
|
||||
DropdownMenuSeparator,
|
||||
} from "@/components/ui/dropdown-menu";
|
||||
import {
|
||||
Popover,
|
||||
PopoverContent,
|
||||
PopoverTrigger,
|
||||
} from "@/components/ui/popover";
|
||||
import {
|
||||
DropdownMenuGroup,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuLabel,
|
||||
DropdownMenuSeparator,
|
||||
} from "@/components/v2/dropdowns/DropdownMenu";
|
||||
import { useAxiosInstance } from "@/services/useAxiosInstance";
|
||||
import { getBackendErr } from "@/utils/genUtils";
|
||||
import { useCustomerFilters } from "../../hooks/useCustomerFilters";
|
||||
@@ -54,7 +54,9 @@ export const SavedViews = ({
|
||||
status: statusParam ? statusParam.split(",").filter(Boolean) : [],
|
||||
version: versionParam ? versionParam.split(",").filter(Boolean) : [],
|
||||
none: noneParam === "true",
|
||||
processor: processorParam ? processorParam.split(",").filter(Boolean) : [],
|
||||
processor: processorParam
|
||||
? processorParam.split(",").filter(Boolean)
|
||||
: [],
|
||||
});
|
||||
|
||||
toast.success(`Applied filters from ${view.name} view`);
|
||||
|
||||
@@ -181,13 +181,12 @@ export const SelectFeatureDropdown = () => {
|
||||
{filteredOptions.map((option) => {
|
||||
const featureLabel = formatFeatureLabel(option.linkedFeatures);
|
||||
return (
|
||||
<DropdownMenuCheckboxItem
|
||||
key={option.eventName}
|
||||
checked={option.selected}
|
||||
onCheckedChange={() => handleToggleItem(option)}
|
||||
onSelect={(e) => e.preventDefault()}
|
||||
className="pl-2"
|
||||
>
|
||||
<DropdownMenuCheckboxItem
|
||||
key={option.eventName}
|
||||
checked={option.selected}
|
||||
onCheckedChange={() => handleToggleItem(option)}
|
||||
className="pl-2"
|
||||
>
|
||||
<div className="flex items-center gap-1.5 min-w-0">
|
||||
<span className="text-xs truncate">
|
||||
{option.eventName}
|
||||
|
||||
@@ -10,6 +10,7 @@ import { IconButton } from "@/components/v2/buttons/IconButton";
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuGroup,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuLabel,
|
||||
DropdownMenuSeparator,
|
||||
@@ -133,6 +134,7 @@ export const SelectGroupByDropdown = ({
|
||||
|
||||
<div className="max-h-[300px] overflow-y-auto pt-1">
|
||||
<DropdownMenuItem
|
||||
closeOnClick={false}
|
||||
onClick={() => handleSelect({ property: null })}
|
||||
className="flex items-center justify-between"
|
||||
>
|
||||
@@ -144,6 +146,7 @@ export const SelectGroupByDropdown = ({
|
||||
<DropdownMenuSeparator />
|
||||
{showCustomerIdOption && (
|
||||
<DropdownMenuItem
|
||||
closeOnClick={false}
|
||||
onClick={() => handleSelect({ property: "customer_id" })}
|
||||
className="flex items-center justify-between"
|
||||
>
|
||||
@@ -154,6 +157,7 @@ export const SelectGroupByDropdown = ({
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
<DropdownMenuItem
|
||||
closeOnClick={false}
|
||||
onClick={() => handleSelect({ property: "entity_id" })}
|
||||
className="flex items-center justify-between"
|
||||
>
|
||||
@@ -174,6 +178,7 @@ export const SelectGroupByDropdown = ({
|
||||
{filteredOptions.map((property) => (
|
||||
<DropdownMenuItem
|
||||
key={property}
|
||||
closeOnClick={false}
|
||||
onClick={() => handleSelect({ property })}
|
||||
className="flex items-center justify-between"
|
||||
>
|
||||
@@ -233,10 +238,12 @@ export const SelectGroupByDropdown = ({
|
||||
{currentGroupBy && availableGroupValues.length > 0 && (
|
||||
<>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuGroup>
|
||||
<DropdownMenuLabel className="text-xs text-t4 font-normal">
|
||||
Filter by value
|
||||
</DropdownMenuLabel>
|
||||
<DropdownMenuItem
|
||||
closeOnClick={false}
|
||||
onClick={() => setGroupFilter(null)}
|
||||
className="flex items-center justify-between"
|
||||
>
|
||||
@@ -255,6 +262,7 @@ export const SelectGroupByDropdown = ({
|
||||
return (
|
||||
<DropdownMenuItem
|
||||
key={value}
|
||||
closeOnClick={false}
|
||||
onClick={() => setGroupFilter(value)}
|
||||
className="flex items-center justify-between"
|
||||
>
|
||||
@@ -267,6 +275,7 @@ export const SelectGroupByDropdown = ({
|
||||
</DropdownMenuItem>
|
||||
);
|
||||
})}
|
||||
</DropdownMenuGroup>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -2,10 +2,12 @@ import type { CreateCustomer, Customer } from "@autumn/shared";
|
||||
import { useState } from "react";
|
||||
import { useNavigate } from "react-router";
|
||||
import { toast } from "sonner";
|
||||
import { Button } from "@/components/v2/buttons/Button";
|
||||
import { ShortcutButton } from "@/components/v2/buttons/ShortcutButton";
|
||||
import {
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from "@/components/v2/dialogs/Dialog";
|
||||
import { FormLabel as FieldLabel } from "@/components/v2/form/FormLabel";
|
||||
@@ -76,7 +78,12 @@ const UpdateCustomerDialog = ({
|
||||
|
||||
return (
|
||||
<DialogContent className="w-md bg-card">
|
||||
<DialogTitle>Update Customer</DialogTitle>
|
||||
<DialogHeader>
|
||||
<DialogTitle>Update Customer</DialogTitle>
|
||||
<DialogDescription>
|
||||
Edit customer details and billing configuration.
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
|
||||
<CustomerConfig
|
||||
customer={customer}
|
||||
@@ -102,13 +109,15 @@ const UpdateCustomerDialog = ({
|
||||
)}
|
||||
|
||||
<DialogFooter>
|
||||
<Button
|
||||
<ShortcutButton
|
||||
variant="primary"
|
||||
onClick={() => handleAddClicked()}
|
||||
isLoading={loading}
|
||||
metaShortcut="enter"
|
||||
className="w-full"
|
||||
>
|
||||
Update
|
||||
</Button>
|
||||
Update Customer
|
||||
</ShortcutButton>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
);
|
||||
|
||||
@@ -30,7 +30,7 @@ import {
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/components/ui/dropdown-menu";
|
||||
} from "@/components/v2/dropdowns/DropdownMenu";
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
|
||||
@@ -4,9 +4,11 @@ import { useNavigate } from "react-router";
|
||||
import { toast } from "sonner";
|
||||
import { useQueryClient } from "@tanstack/react-query";
|
||||
import { Button } from "@/components/v2/buttons/Button";
|
||||
import { ShortcutButton } from "@/components/v2/buttons/ShortcutButton";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
@@ -79,14 +81,6 @@ export function CustomerListCreateButton() {
|
||||
{ enableOnFormTags: false },
|
||||
);
|
||||
|
||||
useHotkeys(
|
||||
"meta+enter",
|
||||
(event) => {
|
||||
event.preventDefault();
|
||||
handleCreate();
|
||||
},
|
||||
{ enableOnFormTags: true },
|
||||
);
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
@@ -113,12 +107,16 @@ export function CustomerListCreateButton() {
|
||||
<DialogContent className="w-[400px] bg-card">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Create Customer</DialogTitle>
|
||||
<DialogDescription>
|
||||
Add a new customer to your workspace.
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<div className="flex gap-2">
|
||||
<div className="flex-1">
|
||||
<FieldLabel>Name</FieldLabel>
|
||||
<Input
|
||||
ref={nameInputRef}
|
||||
placeholder="John Doe"
|
||||
value={fields.name}
|
||||
onChange={(e) => setFields({ ...fields, name: e.target.value })}
|
||||
/>
|
||||
@@ -126,6 +124,7 @@ export function CustomerListCreateButton() {
|
||||
<div className="flex-1">
|
||||
<FieldLabel>ID</FieldLabel>
|
||||
<Input
|
||||
placeholder="cus_123"
|
||||
value={fields.id}
|
||||
onChange={(e) => setFields({ ...fields, id: e.target.value })}
|
||||
/>
|
||||
@@ -135,19 +134,21 @@ export function CustomerListCreateButton() {
|
||||
<FieldLabel>Email</FieldLabel>
|
||||
<Input
|
||||
value={fields.email}
|
||||
placeholder="optional"
|
||||
placeholder="jane@example.com"
|
||||
onChange={(e) => setFields({ ...fields, email: e.target.value })}
|
||||
/>
|
||||
</div>
|
||||
<DialogFooter>
|
||||
<Button
|
||||
<ShortcutButton
|
||||
onClick={handleCreate}
|
||||
isLoading={isLoading}
|
||||
variant="primary"
|
||||
metaShortcut="enter"
|
||||
disabled={!fields.id.trim() && !fields.email.trim()}
|
||||
className="w-full"
|
||||
>
|
||||
Create
|
||||
</Button>
|
||||
Create Customer
|
||||
</ShortcutButton>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
||||
@@ -6,7 +6,6 @@ import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuGroup,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/components/v2/dropdowns/DropdownMenu";
|
||||
@@ -72,18 +71,16 @@ export function CustomerListFilterButton() {
|
||||
setDropdownOpen={setOpen}
|
||||
/>
|
||||
)}
|
||||
<div className="flex h-9 items-stretch justify-between">
|
||||
<DropdownMenuItem
|
||||
onClick={() => clearFilters()}
|
||||
className="cursor-pointer justify-center gap-0 flex-1"
|
||||
<div className="flex items-stretch">
|
||||
<button
|
||||
type="button"
|
||||
onClick={clearFilters}
|
||||
className="flex-1 flex items-center justify-center gap-1.5 rounded-bl-lg px-2 py-1.5 text-xs text-t3 hover:text-t2 hover:bg-accent cursor-default"
|
||||
>
|
||||
<X size={12} className="mr-2 text-t3" />
|
||||
<p className="text-t3">Clear</p>
|
||||
</DropdownMenuItem>
|
||||
|
||||
<div className="flex-1">
|
||||
<SaveViewPopover onClose={closeFilterModal} />
|
||||
</div>
|
||||
<X size={10} />
|
||||
Clear
|
||||
</button>
|
||||
<SaveViewPopover onClose={closeFilterModal} />
|
||||
</div>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/components/ui/dropdown-menu";
|
||||
} from "@/components/v2/dropdowns/DropdownMenu";
|
||||
import { DeleteCustomerDialog } from "@/views/customers/customer/components/DeleteCustomerDialog";
|
||||
import type { CustomerWithProducts } from "./CustomerListColumns";
|
||||
|
||||
@@ -26,9 +26,14 @@ export const CustomerListRowToolbar = ({
|
||||
setOpen={setDeleteOpen}
|
||||
/>
|
||||
<DropdownMenu open={dropdownOpen} onOpenChange={setDropdownOpen}>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<ToolbarButton />
|
||||
</DropdownMenuTrigger>
|
||||
<div
|
||||
onClick={(e) => { e.preventDefault(); e.stopPropagation(); }}
|
||||
onMouseDown={(e) => { e.preventDefault(); e.stopPropagation(); }}
|
||||
>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<ToolbarButton />
|
||||
</DropdownMenuTrigger>
|
||||
</div>
|
||||
<DropdownMenuContent
|
||||
className="text-t2"
|
||||
align="end"
|
||||
|
||||
@@ -3,7 +3,7 @@ import { FlaskIcon, PencilIcon } from "@phosphor-icons/react";
|
||||
import type { Row, Table } from "@tanstack/react-table";
|
||||
import { ArrowRightLeft, Delete, RotateCcw } from "lucide-react";
|
||||
import { TableDropdownMenuCell } from "@/components/general/table/table-dropdown-menu-cell";
|
||||
import { DropdownMenuItem } from "@/components/ui/dropdown-menu";
|
||||
import { DropdownMenuItem } from "@/components/v2/dropdowns/DropdownMenu";
|
||||
import { createDateTimeColumn } from "@/views/customers2/utils/ColumnHelpers";
|
||||
import { AdminHover } from "../../../../../components/general/AdminHover";
|
||||
import { getCusProductHoverTexts } from "../../../../admin/adminUtils";
|
||||
|
||||
@@ -2,10 +2,11 @@ import type { Reward } from "@autumn/shared";
|
||||
import { RewardType } from "@autumn/shared";
|
||||
import { useState } from "react";
|
||||
import { toast } from "sonner";
|
||||
import { Button } from "@/components/v2/buttons/Button";
|
||||
import { ShortcutButton } from "@/components/v2/buttons/ShortcutButton";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
@@ -105,6 +106,9 @@ export const AddCouponDialog = ({
|
||||
<DialogContent className="w-[400px] bg-card">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Add Reward</DialogTitle>
|
||||
<DialogDescription>
|
||||
Apply a reward or coupon to this customer.
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
{getExistingCoupon() && (
|
||||
<InfoBox variant="warning">
|
||||
@@ -177,7 +181,7 @@ export const AddCouponDialog = ({
|
||||
)}
|
||||
</div>
|
||||
<DialogFooter>
|
||||
<Button
|
||||
<ShortcutButton
|
||||
variant="primary"
|
||||
onClick={handleAddClicked}
|
||||
disabled={
|
||||
@@ -186,9 +190,11 @@ export const AddCouponDialog = ({
|
||||
!promoCodeSelected)
|
||||
}
|
||||
isLoading={loading}
|
||||
metaShortcut="enter"
|
||||
className="w-full"
|
||||
>
|
||||
Add Reward
|
||||
</Button>
|
||||
</ShortcutButton>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
||||
@@ -3,10 +3,11 @@ import { FeatureUsageType } from "@autumn/shared";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useLocation, useNavigate } from "react-router";
|
||||
import { toast } from "sonner";
|
||||
import { Button } from "@/components/v2/buttons/Button";
|
||||
import { ShortcutButton } from "@/components/v2/buttons/ShortcutButton";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
@@ -111,6 +112,9 @@ export const CreateEntity = ({
|
||||
<DialogContent className="w-[400px] bg-card">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Create Entity</DialogTitle>
|
||||
<DialogDescription>
|
||||
Create a new entity for this customer to track usage separately.
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<div className="flex flex-col gap-4">
|
||||
<div className="flex gap-2">
|
||||
@@ -138,9 +142,9 @@ export const CreateEntity = ({
|
||||
}
|
||||
items={Object.fromEntries(continuousFeatures.map((feature: Feature) => [feature.id, feature.name]))}
|
||||
>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="Select feature" />
|
||||
</SelectTrigger>
|
||||
<SelectTrigger className="w-full">
|
||||
<SelectValue placeholder="Select feature" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{continuousFeatures.map((feature: Feature) => (
|
||||
<SelectItem key={feature.id} value={feature.id}>
|
||||
@@ -153,13 +157,15 @@ export const CreateEntity = ({
|
||||
</div>
|
||||
|
||||
<DialogFooter>
|
||||
<Button
|
||||
<ShortcutButton
|
||||
onClick={handleCreateClicked}
|
||||
isLoading={isLoading}
|
||||
variant="primary"
|
||||
metaShortcut="enter"
|
||||
className="w-full"
|
||||
>
|
||||
Create
|
||||
</Button>
|
||||
Create Entity
|
||||
</ShortcutButton>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/components/ui/dropdown-menu";
|
||||
} from "@/components/v2/dropdowns/DropdownMenu";
|
||||
import { DeleteApiKeyDialog } from "./DeleteApiKeyDialog";
|
||||
|
||||
const APIKeyToolbarItems = ({
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/components/ui/dropdown-menu";
|
||||
} from "@/components/v2/dropdowns/DropdownMenu";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { keyToTitle } from "@/utils/formatUtils/formatTextUtils";
|
||||
import { pushPage } from "@/utils/genUtils";
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
} from "@/components/ui/dropdown-menu";
|
||||
} from "@/components/v2/dropdowns/DropdownMenu";
|
||||
import { useOrg } from "@/hooks/common/useOrg";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { envToPath } from "@/utils/genUtils";
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
DropdownMenuItem,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/components/ui/dropdown-menu";
|
||||
} from "@/components/v2/dropdowns/DropdownMenu";
|
||||
import { useEnv } from "@/utils/envUtils";
|
||||
import { useOnboardingVisibility } from "@/views/onboarding4/hooks/useOnboardingProgress";
|
||||
import { NavButton } from "./NavButton";
|
||||
|
||||
@@ -5,7 +5,7 @@ import { toast } from "sonner";
|
||||
import {
|
||||
DropdownMenuItem,
|
||||
DropdownMenuSeparator,
|
||||
} from "@/components/ui/dropdown-menu";
|
||||
} from "@/components/v2/dropdowns/DropdownMenu";
|
||||
import { authClient, useSession } from "@/lib/auth-client";
|
||||
import { useEnv } from "@/utils/envUtils";
|
||||
import { getBackendErr, notNullish } from "@/utils/genUtils";
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
import { useState } from "react";
|
||||
import { useNavigate } from "react-router";
|
||||
import { toast } from "sonner";
|
||||
import FieldLabel from "@/components/general/modal-components/FieldLabel";
|
||||
import { Button } from "@/components/v2/buttons/Button";
|
||||
import { ShortcutButton } from "@/components/v2/buttons/ShortcutButton";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from "@/components/v2/dialogs/Dialog";
|
||||
import { FormLabel as FieldLabel } from "@/components/v2/form/FormLabel";
|
||||
import { Input } from "@/components/v2/inputs/Input";
|
||||
import { useOrg } from "@/hooks/common/useOrg";
|
||||
import { authClient } from "@/lib/auth-client";
|
||||
@@ -63,45 +64,50 @@ export const CreateNewOrg = ({
|
||||
if (!open) setDialogType(null);
|
||||
}}
|
||||
>
|
||||
<DialogContent className="gap-0 p-0 rounded-xs min-w-[400px]">
|
||||
<div className="p-6 flex flex-col gap-4">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Create New Organization</DialogTitle>
|
||||
</DialogHeader>
|
||||
<div className="flex gap-4">
|
||||
<div>
|
||||
<FieldLabel>Name</FieldLabel>
|
||||
<Input
|
||||
value={name}
|
||||
onChange={(e) => {
|
||||
setName(e.target.value);
|
||||
if (!slugChanged) {
|
||||
setSlug(slugify(e.target.value));
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<FieldLabel>Slug</FieldLabel>
|
||||
<Input
|
||||
value={slug}
|
||||
onChange={(e) => {
|
||||
if (!slugChanged) {
|
||||
setSlug(slugify(e.target.value));
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<DialogContent className="w-[400px] bg-card">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Create Organization</DialogTitle>
|
||||
<DialogDescription>
|
||||
Set up a new organization workspace.
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<div className="flex gap-2">
|
||||
<div className="flex-1">
|
||||
<FieldLabel>Name</FieldLabel>
|
||||
<Input
|
||||
placeholder="Acme Inc"
|
||||
value={name}
|
||||
onChange={(e) => {
|
||||
setName(e.target.value);
|
||||
if (!slugChanged) {
|
||||
setSlug(slugify(e.target.value));
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<FieldLabel>Slug</FieldLabel>
|
||||
<Input
|
||||
placeholder="acme-inc"
|
||||
value={slug}
|
||||
onChange={(e) => {
|
||||
if (!slugChanged) {
|
||||
setSlug(slugify(e.target.value));
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<DialogFooter className="px-4 pb-4">
|
||||
<Button
|
||||
<DialogFooter>
|
||||
<ShortcutButton
|
||||
variant="primary"
|
||||
onClick={handleCreate}
|
||||
isLoading={isLoading}
|
||||
metaShortcut="enter"
|
||||
className="w-full"
|
||||
>
|
||||
Create
|
||||
</Button>
|
||||
Create Organization
|
||||
</ShortcutButton>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { LogOut } from "lucide-react";
|
||||
import React from "react";
|
||||
import { DropdownMenuItem } from "@/components/ui/dropdown-menu";
|
||||
import { DropdownMenuItem } from "@/components/v2/dropdowns/DropdownMenu";
|
||||
import { authClient } from "@/lib/auth-client";
|
||||
|
||||
export const LogOutItem = () => {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { DropdownMenuGroup } from "@/components/v2/dropdowns/DropdownMenu";
|
||||
import { useQueryClient } from "@tanstack/react-query";
|
||||
import {
|
||||
ChevronDown,
|
||||
@@ -14,9 +13,11 @@ import { useNavigate } from "react-router";
|
||||
import { toast } from "sonner";
|
||||
import { AdminHover } from "@/components/general/AdminHover";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Skeleton } from "@/components/ui/skeleton";
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuGroup,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuPortal,
|
||||
DropdownMenuSeparator,
|
||||
@@ -24,8 +25,7 @@ import {
|
||||
DropdownMenuSubContent,
|
||||
DropdownMenuSubTrigger,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/components/ui/dropdown-menu";
|
||||
import { Skeleton } from "@/components/ui/skeleton";
|
||||
} from "@/components/v2/dropdowns/DropdownMenu";
|
||||
import { useTheme } from "@/contexts/ThemeProvider";
|
||||
import { setLastSwitchedOrgId, useOrg } from "@/hooks/common/useOrg";
|
||||
import {
|
||||
@@ -122,7 +122,7 @@ export const OrgDropdown = () => {
|
||||
</AdminHover>
|
||||
<DropdownMenuContent
|
||||
align="start"
|
||||
className="border-1 border-zinc-200 shadow-sm w-48"
|
||||
className="w-48"
|
||||
>
|
||||
<AdminDropdownItems />
|
||||
<DropdownMenuItem className="flex justify-between w-full items-center gap-2 text-t2">
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { AppEnv } from "@autumn/shared";
|
||||
import { ChevronDown, FlaskConical, Sailboat } from "lucide-react";
|
||||
import { DropdownMenuTrigger } from "@/components/ui/dropdown-menu";
|
||||
import { DropdownMenuTrigger } from "@/components/v2/dropdowns/DropdownMenu";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { useEnv } from "@/utils/envUtils";
|
||||
import { useSidebarContext } from "../SidebarContext";
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/components/ui/dropdown-menu";
|
||||
} from "@/components/v2/dropdowns/DropdownMenu";
|
||||
import { IconButton } from "@/components/v2/buttons/IconButton";
|
||||
import { useProductsQueryState } from "@/views/products/hooks/useProductsQueryState";
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/components/ui/dropdown-menu";
|
||||
} from "@/components/v2/dropdowns/DropdownMenu";
|
||||
import UpdateFeatureSheet from "../components/UpdateFeatureSheet";
|
||||
import UpdateCreditSystemSheet from "../credit-systems/components/UpdateCreditSystemSheet";
|
||||
import { DeleteFeatureDialog } from "../feature-row-toolbar/DeleteFeatureDialog";
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/components/ui/dropdown-menu";
|
||||
} from "@/components/v2/dropdowns/DropdownMenu";
|
||||
import { IconButton } from "@/components/v2/buttons/IconButton";
|
||||
import { useProductStore } from "@/hooks/stores/useProductStore";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
@@ -45,7 +45,7 @@ function CreateProductSheet({
|
||||
|
||||
const axiosInstance = useAxiosInstance();
|
||||
const navigate = useNavigate();
|
||||
const { invalidate } = useProductsQuery();
|
||||
const { invalidate, products } = useProductsQuery();
|
||||
|
||||
const handleCreateClicked = async () => {
|
||||
const productName = product.name?.trim() || "";
|
||||
@@ -80,13 +80,18 @@ function CreateProductSheet({
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
// Reset product state when sheet opens/closes
|
||||
const isFirstPlan = !products || products.length === 0;
|
||||
|
||||
useEffect(() => {
|
||||
if (open) {
|
||||
reset();
|
||||
setProduct({ ...DEFAULT_PRODUCT, is_add_on: isAddOn });
|
||||
setProduct({
|
||||
...DEFAULT_PRODUCT,
|
||||
is_add_on: isAddOn,
|
||||
is_default: isFirstPlan && !isAddOn,
|
||||
});
|
||||
}
|
||||
}, [open, reset, setProduct, isAddOn]);
|
||||
}, [open, reset, setProduct, isAddOn, isFirstPlan]);
|
||||
|
||||
return (
|
||||
<Sheet open={open} onOpenChange={setOpen}>
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/components/ui/dropdown-menu";
|
||||
} from "@/components/v2/dropdowns/DropdownMenu";
|
||||
import { IconButton } from "@/components/v2/buttons/IconButton";
|
||||
import { useProductsQueryState } from "@/views/products/hooks/useProductsQueryState";
|
||||
|
||||
|
||||
@@ -51,9 +51,14 @@ export const ProductListRowToolbar = ({
|
||||
/>
|
||||
|
||||
<DropdownMenu open={dropdownOpen} onOpenChange={setDropdownOpen}>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<ToolbarButton />
|
||||
</DropdownMenuTrigger>
|
||||
<div
|
||||
onClick={(e) => { e.preventDefault(); e.stopPropagation(); }}
|
||||
onMouseDown={(e) => { e.preventDefault(); e.stopPropagation(); }}
|
||||
>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<ToolbarButton />
|
||||
</DropdownMenuTrigger>
|
||||
</div>
|
||||
<DropdownMenuContent align="end">
|
||||
<DropdownMenuSub>
|
||||
<DropdownMenuSubTrigger className="flex gap-2">
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/components/ui/dropdown-menu";
|
||||
} from "@/components/v2/dropdowns/DropdownMenu";
|
||||
import { useOrgStripeQuery } from "@/hooks/queries/useOrgStripeQuery";
|
||||
import { useRewardsQuery } from "@/hooks/queries/useRewardsQuery";
|
||||
import { RewardService } from "@/services/products/RewardService";
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/components/ui/dropdown-menu";
|
||||
} from "@/components/v2/dropdowns/DropdownMenu";
|
||||
import { useRewardsQuery } from "@/hooks/queries/useRewardsQuery";
|
||||
import { useAxiosInstance } from "@/services/useAxiosInstance";
|
||||
import { getBackendErr } from "@/utils/genUtils";
|
||||
|
||||
Reference in New Issue
Block a user