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