From e882bcb0488be48a7123faedf02afa5efdbc71bf Mon Sep 17 00:00:00 2001 From: Charlie Lamb Date: Thu, 14 May 2026 11:14:30 +0100 Subject: [PATCH] refactor: frontend improvements --- ai | 2 +- knip.json | 2 +- .../components/ai-elements/open-in-chat.tsx | 2 +- .../components/ai-elements/prompt-input.tsx | 4 +- .../general/table/table-column-visibility.tsx | 1 + .../table/table-dropdown-menu-cell.tsx | 2 +- vite/src/components/ui/dropdown-menu.tsx | 308 ------------------ vite/src/components/v2/dialogs/Dialog.tsx | 3 +- .../components/v2/dropdowns/DropdownMenu.tsx | 129 +++++--- .../components/v2/selects/CurrencySelect.tsx | 78 +---- vite/src/components/v2/selects/Select.tsx | 8 +- .../filter-dropdown/FilterStatusSubMenu.tsx | 19 +- .../filter-dropdown/ProcessorSubMenu.tsx | 2 +- .../filter-dropdown/ProductsSubMenu.tsx | 6 +- .../filter-dropdown/SavedViewPopover.tsx | 12 +- .../components/filter-dropdown/SavedViews.tsx | 16 +- .../components/SelectFeatureDropdown.tsx | 13 +- .../components/SelectGroupByDropdown.tsx | 9 + .../components/UpdateCustomerDialog.tsx | 19 +- .../CustomerBalanceTableColumns.tsx | 2 +- .../CustomerListCreateButton.tsx | 25 +- .../CustomerListFilterButton.tsx | 21 +- .../customer-list/CustomerListRowToolbar.tsx | 13 +- .../CustomerProductsColumns.tsx | 2 +- .../customer/components/AddCouponDialog.tsx | 12 +- .../customer/components/CreateEntity.tsx | 20 +- .../api-keys/components/APIKeyToolbar.tsx | 2 +- .../main-sidebar/CollapsibleNavGroup.tsx | 2 +- vite/src/views/main-sidebar/EnvDropdown.tsx | 2 +- .../src/views/main-sidebar/SidebarContact.tsx | 2 +- .../components/AdminDropdownItems.tsx | 2 +- .../main-sidebar/components/CreateNewOrg.tsx | 76 +++-- .../main-sidebar/components/LogOutItem.tsx | 2 +- .../main-sidebar/components/OrgDropdown.tsx | 8 +- .../env-dropdown/ExpandedEnvTrigger.tsx | 2 +- .../feature-list/FeatureListMenuButton.tsx | 2 +- .../feature-list/FeatureListRowToolbar.tsx | 2 +- .../products/plan/components/PlanToolbar.tsx | 2 +- .../components/CreateProductSheet.tsx | 13 +- .../product-list/ProductListMenuButton.tsx | 2 +- .../product-list/ProductListRowToolbar.tsx | 11 +- .../rewards/components/RewardRowToolbar.tsx | 2 +- .../RewardProgramRowToolbar.tsx | 2 +- 43 files changed, 294 insertions(+), 570 deletions(-) delete mode 100644 vite/src/components/ui/dropdown-menu.tsx diff --git a/ai b/ai index 008fd7a29..761b84255 160000 --- a/ai +++ b/ai @@ -1 +1 @@ -Subproject commit 008fd7a292eae7088e874ea86df4f251165e1f59 +Subproject commit 761b842553d890355b77e618c3aa703dddb661c1 diff --git a/knip.json b/knip.json index 1371dbcf1..06e5e760a 100644 --- a/knip.json +++ b/knip.json @@ -11,7 +11,7 @@ "enumMembers", "duplicates" ], - "ignore": ["ai/**", "others/**"], + "ignore": ["ai/**", "others/**", ".trigger/**"], "ignoreWorkspaces": [ "packages/atmn", "packages/autumn-js", diff --git a/vite/src/components/ai-elements/open-in-chat.tsx b/vite/src/components/ai-elements/open-in-chat.tsx index acc6b1d3d..cf2a86d72 100644 --- a/vite/src/components/ai-elements/open-in-chat.tsx +++ b/vite/src/components/ai-elements/open-in-chat.tsx @@ -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 = { diff --git a/vite/src/components/ai-elements/prompt-input.tsx b/vite/src/components/ai-elements/prompt-input.tsx index 5bac0358e..34d25a797 100644 --- a/vite/src/components/ai-elements/prompt-input.tsx +++ b/vite/src/components/ai-elements/prompt-input.tsx @@ -417,8 +417,8 @@ export const PromptInputActionAddAttachments = ({ return ( { - e.preventDefault(); + closeOnClick={false} + onClick={() => { attachments.openFileDialog(); }} > diff --git a/vite/src/components/general/table/table-column-visibility.tsx b/vite/src/components/general/table/table-column-visibility.tsx index d280977a6..10d07b4d4 100644 --- a/vite/src/components/general/table/table-column-visibility.tsx +++ b/vite/src/components/general/table/table-column-visibility.tsx @@ -29,6 +29,7 @@ function ColumnCheckboxItem({ column }: { column: Column }) { return ( { column.toggleVisibility(!isVisible); }} diff --git a/vite/src/components/general/table/table-dropdown-menu-cell.tsx b/vite/src/components/general/table/table-dropdown-menu-cell.tsx index 7f54d0bcf..d0adf5394 100644 --- a/vite/src/components/general/table/table-dropdown-menu-cell.tsx +++ b/vite/src/components/general/table/table-dropdown-menu-cell.tsx @@ -4,7 +4,7 @@ import { DropdownMenu, DropdownMenuContent, DropdownMenuTrigger, -} from "@/components/ui/dropdown-menu"; +} from "@/components/v2/dropdowns/DropdownMenu"; export function TableDropdownMenuCell({ children, diff --git a/vite/src/components/ui/dropdown-menu.tsx b/vite/src/components/ui/dropdown-menu.tsx deleted file mode 100644 index a8eb8d251..000000000 --- a/vite/src/components/ui/dropdown-menu.tsx +++ /dev/null @@ -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 ; -} - -const DropdownMenuTrigger = React.forwardRef< - HTMLButtonElement, - MenuPrimitive.Trigger.Props & { asChild?: boolean } ->(({ asChild, children, ...props }, ref) => { - if (asChild && React.isValidElement(children)) { - return ( - - ); - } - return ( - - {children} - - ); -}); -DropdownMenuTrigger.displayName = "DropdownMenuTrigger"; - -function DropdownMenuGroup({ - ...props -}: MenuPrimitive.Group.Props) { - return ; -} - -function DropdownMenuPortal({ - children, -}: { - children: React.ReactNode; -}) { - return <>{children}; -} - -function DropdownMenuSub({ - ...props -}: MenuPrimitive.SubmenuRoot.Props) { - return ; -} - -function DropdownMenuRadioGroup({ - ...props -}: MenuPrimitive.RadioGroup.Props) { - return ( - - ); -} - -const DropdownMenuSubTrigger = React.forwardRef< - HTMLDivElement, - MenuPrimitive.SubmenuTrigger.Props & { - inset?: boolean; - withIcon?: boolean; - } ->(({ className, inset, children, withIcon = true, ...props }, ref) => ( - - {children} - {withIcon && } - -)); -DropdownMenuSubTrigger.displayName = "DropdownMenuSubTrigger"; - -const DropdownMenuSubContent = React.forwardRef< - HTMLDivElement, - MenuPrimitive.Popup.Props & { - sideOffset?: number; - } ->(({ className, sideOffset = 0, ...props }, ref) => ( - - - - - -)); -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) => ( - - - - - -)); -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 ( - svg]:size-4 [&>svg]:shrink-0", - shimmer && "shimmer", - inset && "pl-8", - className, - )} - disabled={shimmer || isLoading} - {...props} - /> - ); - } - return ( - svg]:size-4 [&>svg]:shrink-0", - shimmer && "shimmer", - inset && "pl-8", - className, - )} - disabled={shimmer || isLoading} - {...props} - > - {isLoading ? ( - <> - {children} - - - ) : ( - children - )} - - ); -}); -DropdownMenuItem.displayName = "DropdownMenuItem"; - -const DropdownMenuCheckboxItem = React.forwardRef< - HTMLDivElement, - MenuPrimitive.CheckboxItem.Props ->(({ className, children, checked, ...props }, ref) => ( - - {children} - - - - - - -)); -DropdownMenuCheckboxItem.displayName = "DropdownMenuCheckboxItem"; - -const DropdownMenuRadioItem = React.forwardRef< - HTMLDivElement, - MenuPrimitive.RadioItem.Props ->(({ className, children, ...props }, ref) => ( - - - - - - - {children} - -)); -DropdownMenuRadioItem.displayName = "DropdownMenuRadioItem"; - -const DropdownMenuLabel = React.forwardRef< - HTMLDivElement, - MenuPrimitive.GroupLabel.Props & { - inset?: boolean; - } ->(({ className, inset, ...props }, ref) => ( - -)); -DropdownMenuLabel.displayName = "DropdownMenuLabel"; - -const DropdownMenuSeparator = React.forwardRef< - HTMLDivElement, - MenuPrimitive.Separator.Props ->(({ className, ...props }, ref) => ( - -)); -DropdownMenuSeparator.displayName = "DropdownMenuSeparator"; - -const DropdownMenuShortcut = ({ - className, - ...props -}: React.HTMLAttributes) => { - return ( - - ); -}; -DropdownMenuShortcut.displayName = "DropdownMenuShortcut"; - -export { - DropdownMenu, - DropdownMenuTrigger, - DropdownMenuContent, - DropdownMenuItem, - DropdownMenuLabel, - DropdownMenuSeparator, - DropdownMenuGroup, - DropdownMenuPortal, - DropdownMenuSub, - DropdownMenuSubContent, - DropdownMenuSubTrigger, -}; diff --git a/vite/src/components/v2/dialogs/Dialog.tsx b/vite/src/components/v2/dialogs/Dialog.tsx index eaa8960e9..3b0d7c9b1 100644 --- a/vite/src/components/v2/dialogs/Dialog.tsx +++ b/vite/src/components/v2/dialogs/Dialog.tsx @@ -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, diff --git a/vite/src/components/v2/dropdowns/DropdownMenu.tsx b/vite/src/components/v2/dropdowns/DropdownMenu.tsx index f180f4fc3..243042295 100644 --- a/vite/src/components/v2/dropdowns/DropdownMenu.tsx +++ b/vite/src/components/v2/dropdowns/DropdownMenu.tsx @@ -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 ( @@ -74,31 +73,19 @@ const DropdownMenuTrigger = React.forwardRef< ); }); -function DropdownMenuGroup( - props: MenuPrimitive.Group.Props, -) { - return ( - - ); +function DropdownMenuGroup(props: MenuPrimitive.Group.Props) { + return ; } -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 ; } -function DropdownMenuRadioGroup( - props: MenuPrimitive.RadioGroup.Props, -) { +function DropdownMenuRadioGroup(props: MenuPrimitive.RadioGroup.Props) { return ( 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 && } + {withIcon && } ); }); 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 ( (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 ( (function DropdownMenuCheckboxItem(props, ref) { - const { className, children, ...rest } = props; + const { className, children, inset, ...rest } = props; return ( {children} - + - + @@ -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 ( - + - + {children} @@ -322,9 +346,9 @@ const DropdownMenuLabel = React.forwardRef< ); @@ -367,7 +394,11 @@ export { DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, + DropdownMenuPortal, + DropdownMenuRadioGroup, + DropdownMenuRadioItem, DropdownMenuSeparator, + DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, diff --git a/vite/src/components/v2/selects/CurrencySelect.tsx b/vite/src/components/v2/selects/CurrencySelect.tsx index 45f50ded4..b325878fc 100644 --- a/vite/src/components/v2/selects/CurrencySelect.tsx +++ b/vite/src/components/v2/selects/CurrencySelect.tsx @@ -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 ( - - - - - - - - No currency found. - - - {stripeCurrencyCodes.map((currency) => ( - { - setDefaultCurrency(value.toUpperCase()); - setOpen(false); - }} - className="p-2 flex items-center justify-between" - > - {currency.currency} - {currency.code} - - - ))} - - - - - + 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)} + /> ); }; diff --git a/vite/src/components/v2/selects/Select.tsx b/vite/src/components/v2/selects/Select.tsx index c0789a676..cd18b6797 100644 --- a/vite/src/components/v2/selects/Select.tsx +++ b/vite/src/components/v2/selects/Select.tsx @@ -93,12 +93,12 @@ function SelectContent({ side={side} alignItemWithTrigger={false} positionMethod="fixed" - className="isolate z-[160]" + className="isolate z-[300] outline-none" > - + diff --git a/vite/src/views/customers/components/filter-dropdown/FilterStatusSubMenu.tsx b/vite/src/views/customers/components/filter-dropdown/FilterStatusSubMenu.tsx index e9afc65b0..c7f664614 100644 --- a/vite/src/views/customers/components/filter-dropdown/FilterStatusSubMenu.tsx +++ b/vite/src/views/customers/components/filter-dropdown/FilterStatusSubMenu.tsx @@ -46,15 +46,16 @@ export const FilterStatusSubMenu = () => { {statuses.map((status: any) => { const isActive = selectedStatuses.includes(status); return ( - { - e.preventDefault(); - toggleStatus(status); - }} - onSelect={(e) => e.preventDefault()} - className="flex items-center gap-2 cursor-pointer text-sm" - > + { + e.preventDefault(); + e.stopPropagation(); + toggleStatus(status); + }} + className="flex items-center gap-2 cursor-pointer text-sm" + > {keyToTitle(status)} diff --git a/vite/src/views/customers/components/filter-dropdown/ProcessorSubMenu.tsx b/vite/src/views/customers/components/filter-dropdown/ProcessorSubMenu.tsx index 5a1db0c8c..fd0dc1a6e 100644 --- a/vite/src/views/customers/components/filter-dropdown/ProcessorSubMenu.tsx +++ b/vite/src/views/customers/components/filter-dropdown/ProcessorSubMenu.tsx @@ -70,11 +70,11 @@ export const ProcessorSubMenu = () => { return ( { e.preventDefault(); toggleProcessor(value); }} - onSelect={(e) => e.preventDefault()} className="flex items-center gap-2 cursor-pointer text-sm" > diff --git a/vite/src/views/customers/components/filter-dropdown/ProductsSubMenu.tsx b/vite/src/views/customers/components/filter-dropdown/ProductsSubMenu.tsx index 833edd3ed..03b4a7e52 100644 --- a/vite/src/views/customers/components/filter-dropdown/ProductsSubMenu.tsx +++ b/vite/src/views/customers/components/filter-dropdown/ProductsSubMenu.tsx @@ -192,11 +192,11 @@ export const ProductsSubMenu = () => { {versionCount === 1 ? ( // Single version - show just one button for the product { e.preventDefault(); toggleVersion(product.id, "1"); }} - onSelect={(e) => e.preventDefault()} className="flex items-center gap-2 cursor-pointer font-medium" > { { e.preventDefault(); toggleProduct(product); }} - onSelect={(e) => e.preventDefault()} className="flex items-center gap-2 cursor-pointer font-medium" > { return ( { e.preventDefault(); toggleVersion(product.id, version.toString()); }} - onSelect={(e) => e.preventDefault()} className="flex items-center gap-2 cursor-pointer text-sm" > { return ( - + { {filteredOptions.map((option) => { const featureLabel = formatFeatureLabel(option.linkedFeatures); return ( - handleToggleItem(option)} - onSelect={(e) => e.preventDefault()} - className="pl-2" - > + handleToggleItem(option)} + className="pl-2" + >
{option.eventName} diff --git a/vite/src/views/customers/customer/analytics/components/SelectGroupByDropdown.tsx b/vite/src/views/customers/customer/analytics/components/SelectGroupByDropdown.tsx index 421b5f7d1..0f766ed90 100644 --- a/vite/src/views/customers/customer/analytics/components/SelectGroupByDropdown.tsx +++ b/vite/src/views/customers/customer/analytics/components/SelectGroupByDropdown.tsx @@ -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 = ({
handleSelect({ property: null })} className="flex items-center justify-between" > @@ -144,6 +146,7 @@ export const SelectGroupByDropdown = ({ {showCustomerIdOption && ( handleSelect({ property: "customer_id" })} className="flex items-center justify-between" > @@ -154,6 +157,7 @@ export const SelectGroupByDropdown = ({ )} handleSelect({ property: "entity_id" })} className="flex items-center justify-between" > @@ -174,6 +178,7 @@ export const SelectGroupByDropdown = ({ {filteredOptions.map((property) => ( handleSelect({ property })} className="flex items-center justify-between" > @@ -233,10 +238,12 @@ export const SelectGroupByDropdown = ({ {currentGroupBy && availableGroupValues.length > 0 && ( <> + Filter by value setGroupFilter(null)} className="flex items-center justify-between" > @@ -255,6 +262,7 @@ export const SelectGroupByDropdown = ({ return ( setGroupFilter(value)} className="flex items-center justify-between" > @@ -267,6 +275,7 @@ export const SelectGroupByDropdown = ({ ); })} + )}
diff --git a/vite/src/views/customers/customer/components/UpdateCustomerDialog.tsx b/vite/src/views/customers/customer/components/UpdateCustomerDialog.tsx index 1c8843468..1e4d62a0f 100644 --- a/vite/src/views/customers/customer/components/UpdateCustomerDialog.tsx +++ b/vite/src/views/customers/customer/components/UpdateCustomerDialog.tsx @@ -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 ( - Update Customer + + Update Customer + + Edit customer details and billing configuration. + + - + Update Customer + ); diff --git a/vite/src/views/customers2/components/table/customer-balance/CustomerBalanceTableColumns.tsx b/vite/src/views/customers2/components/table/customer-balance/CustomerBalanceTableColumns.tsx index 5e8fb616c..c662bfc47 100644 --- a/vite/src/views/customers2/components/table/customer-balance/CustomerBalanceTableColumns.tsx +++ b/vite/src/views/customers2/components/table/customer-balance/CustomerBalanceTableColumns.tsx @@ -30,7 +30,7 @@ import { DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, -} from "@/components/ui/dropdown-menu"; +} from "@/components/v2/dropdowns/DropdownMenu"; import { Tooltip, TooltipContent, diff --git a/vite/src/views/customers2/components/table/customer-list/CustomerListCreateButton.tsx b/vite/src/views/customers2/components/table/customer-list/CustomerListCreateButton.tsx index 4e6482450..78f3c9234 100644 --- a/vite/src/views/customers2/components/table/customer-list/CustomerListCreateButton.tsx +++ b/vite/src/views/customers2/components/table/customer-list/CustomerListCreateButton.tsx @@ -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 ( Create Customer + + Add a new customer to your workspace. +
Name setFields({ ...fields, name: e.target.value })} /> @@ -126,6 +124,7 @@ export function CustomerListCreateButton() {
ID setFields({ ...fields, id: e.target.value })} /> @@ -135,19 +134,21 @@ export function CustomerListCreateButton() { Email setFields({ ...fields, email: e.target.value })} />
- + Create Customer +
diff --git a/vite/src/views/customers2/components/table/customer-list/CustomerListFilterButton.tsx b/vite/src/views/customers2/components/table/customer-list/CustomerListFilterButton.tsx index 2926ecad8..c0725de3f 100644 --- a/vite/src/views/customers2/components/table/customer-list/CustomerListFilterButton.tsx +++ b/vite/src/views/customers2/components/table/customer-list/CustomerListFilterButton.tsx @@ -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} /> )} -
- clearFilters()} - className="cursor-pointer justify-center gap-0 flex-1" +
+ +
diff --git a/vite/src/views/customers2/components/table/customer-list/CustomerListRowToolbar.tsx b/vite/src/views/customers2/components/table/customer-list/CustomerListRowToolbar.tsx index de69f53f4..6ce7c5e77 100644 --- a/vite/src/views/customers2/components/table/customer-list/CustomerListRowToolbar.tsx +++ b/vite/src/views/customers2/components/table/customer-list/CustomerListRowToolbar.tsx @@ -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} /> - - - +
{ e.preventDefault(); e.stopPropagation(); }} + onMouseDown={(e) => { e.preventDefault(); e.stopPropagation(); }} + > + + + +
Add Reward + + Apply a reward or coupon to this customer. + {getExistingCoupon() && ( @@ -177,7 +181,7 @@ export const AddCouponDialog = ({ )}
- + diff --git a/vite/src/views/customers2/customer/components/CreateEntity.tsx b/vite/src/views/customers2/customer/components/CreateEntity.tsx index 80718fd8b..cabcfaa60 100644 --- a/vite/src/views/customers2/customer/components/CreateEntity.tsx +++ b/vite/src/views/customers2/customer/components/CreateEntity.tsx @@ -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 = ({ Create Entity + + Create a new entity for this customer to track usage separately. +
@@ -138,9 +142,9 @@ export const CreateEntity = ({ } items={Object.fromEntries(continuousFeatures.map((feature: Feature) => [feature.id, feature.name]))} > - - - + + + {continuousFeatures.map((feature: Feature) => ( @@ -153,13 +157,15 @@ export const CreateEntity = ({
- + Create Entity + diff --git a/vite/src/views/developer/api-keys/components/APIKeyToolbar.tsx b/vite/src/views/developer/api-keys/components/APIKeyToolbar.tsx index 4727a3f48..d1af76dcb 100644 --- a/vite/src/views/developer/api-keys/components/APIKeyToolbar.tsx +++ b/vite/src/views/developer/api-keys/components/APIKeyToolbar.tsx @@ -7,7 +7,7 @@ import { DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, -} from "@/components/ui/dropdown-menu"; +} from "@/components/v2/dropdowns/DropdownMenu"; import { DeleteApiKeyDialog } from "./DeleteApiKeyDialog"; const APIKeyToolbarItems = ({ diff --git a/vite/src/views/main-sidebar/CollapsibleNavGroup.tsx b/vite/src/views/main-sidebar/CollapsibleNavGroup.tsx index a1dffad1d..f9cdcce95 100644 --- a/vite/src/views/main-sidebar/CollapsibleNavGroup.tsx +++ b/vite/src/views/main-sidebar/CollapsibleNavGroup.tsx @@ -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"; diff --git a/vite/src/views/main-sidebar/EnvDropdown.tsx b/vite/src/views/main-sidebar/EnvDropdown.tsx index 2356b7f97..15cd1ec03 100644 --- a/vite/src/views/main-sidebar/EnvDropdown.tsx +++ b/vite/src/views/main-sidebar/EnvDropdown.tsx @@ -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"; diff --git a/vite/src/views/main-sidebar/SidebarContact.tsx b/vite/src/views/main-sidebar/SidebarContact.tsx index 9071c1baa..b38041449 100644 --- a/vite/src/views/main-sidebar/SidebarContact.tsx +++ b/vite/src/views/main-sidebar/SidebarContact.tsx @@ -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"; diff --git a/vite/src/views/main-sidebar/components/AdminDropdownItems.tsx b/vite/src/views/main-sidebar/components/AdminDropdownItems.tsx index 02f391f86..c6d2ecec1 100644 --- a/vite/src/views/main-sidebar/components/AdminDropdownItems.tsx +++ b/vite/src/views/main-sidebar/components/AdminDropdownItems.tsx @@ -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"; diff --git a/vite/src/views/main-sidebar/components/CreateNewOrg.tsx b/vite/src/views/main-sidebar/components/CreateNewOrg.tsx index b7d613eb0..b575567d2 100644 --- a/vite/src/views/main-sidebar/components/CreateNewOrg.tsx +++ b/vite/src/views/main-sidebar/components/CreateNewOrg.tsx @@ -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); }} > - -
- - Create New Organization - -
-
- Name - { - setName(e.target.value); - if (!slugChanged) { - setSlug(slugify(e.target.value)); - } - }} - /> -
-
- Slug - { - if (!slugChanged) { - setSlug(slugify(e.target.value)); - } - }} - /> -
+ + + Create Organization + + Set up a new organization workspace. + + +
+
+ Name + { + setName(e.target.value); + if (!slugChanged) { + setSlug(slugify(e.target.value)); + } + }} + /> +
+
+ Slug + { + if (!slugChanged) { + setSlug(slugify(e.target.value)); + } + }} + />
- - + Create Organization +
diff --git a/vite/src/views/main-sidebar/components/LogOutItem.tsx b/vite/src/views/main-sidebar/components/LogOutItem.tsx index 93d0da389..f08a48d7c 100644 --- a/vite/src/views/main-sidebar/components/LogOutItem.tsx +++ b/vite/src/views/main-sidebar/components/LogOutItem.tsx @@ -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 = () => { diff --git a/vite/src/views/main-sidebar/components/OrgDropdown.tsx b/vite/src/views/main-sidebar/components/OrgDropdown.tsx index afd0360e2..07ec162dc 100644 --- a/vite/src/views/main-sidebar/components/OrgDropdown.tsx +++ b/vite/src/views/main-sidebar/components/OrgDropdown.tsx @@ -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 = () => { diff --git a/vite/src/views/main-sidebar/env-dropdown/ExpandedEnvTrigger.tsx b/vite/src/views/main-sidebar/env-dropdown/ExpandedEnvTrigger.tsx index 9b188ff90..2edc288c9 100644 --- a/vite/src/views/main-sidebar/env-dropdown/ExpandedEnvTrigger.tsx +++ b/vite/src/views/main-sidebar/env-dropdown/ExpandedEnvTrigger.tsx @@ -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"; diff --git a/vite/src/views/products/features/feature-list/FeatureListMenuButton.tsx b/vite/src/views/products/features/feature-list/FeatureListMenuButton.tsx index 585df1c3b..10aebf322 100644 --- a/vite/src/views/products/features/feature-list/FeatureListMenuButton.tsx +++ b/vite/src/views/products/features/feature-list/FeatureListMenuButton.tsx @@ -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"; diff --git a/vite/src/views/products/features/feature-list/FeatureListRowToolbar.tsx b/vite/src/views/products/features/feature-list/FeatureListRowToolbar.tsx index 4a1ff5eb4..997f572d1 100644 --- a/vite/src/views/products/features/feature-list/FeatureListRowToolbar.tsx +++ b/vite/src/views/products/features/feature-list/FeatureListRowToolbar.tsx @@ -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"; diff --git a/vite/src/views/products/plan/components/PlanToolbar.tsx b/vite/src/views/products/plan/components/PlanToolbar.tsx index 56e048d6b..6f01ef5bf 100644 --- a/vite/src/views/products/plan/components/PlanToolbar.tsx +++ b/vite/src/views/products/plan/components/PlanToolbar.tsx @@ -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"; diff --git a/vite/src/views/products/products/components/CreateProductSheet.tsx b/vite/src/views/products/products/components/CreateProductSheet.tsx index 7255b3eb9..fbc0be283 100644 --- a/vite/src/views/products/products/components/CreateProductSheet.tsx +++ b/vite/src/views/products/products/components/CreateProductSheet.tsx @@ -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 ( diff --git a/vite/src/views/products/products/components/product-list/ProductListMenuButton.tsx b/vite/src/views/products/products/components/product-list/ProductListMenuButton.tsx index 01e516780..2c34deb05 100644 --- a/vite/src/views/products/products/components/product-list/ProductListMenuButton.tsx +++ b/vite/src/views/products/products/components/product-list/ProductListMenuButton.tsx @@ -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"; diff --git a/vite/src/views/products/products/components/product-list/ProductListRowToolbar.tsx b/vite/src/views/products/products/components/product-list/ProductListRowToolbar.tsx index b350a788b..f97d70ada 100644 --- a/vite/src/views/products/products/components/product-list/ProductListRowToolbar.tsx +++ b/vite/src/views/products/products/components/product-list/ProductListRowToolbar.tsx @@ -51,9 +51,14 @@ export const ProductListRowToolbar = ({ /> - - - +
{ e.preventDefault(); e.stopPropagation(); }} + onMouseDown={(e) => { e.preventDefault(); e.stopPropagation(); }} + > + + + +
diff --git a/vite/src/views/products/rewards/components/RewardRowToolbar.tsx b/vite/src/views/products/rewards/components/RewardRowToolbar.tsx index 83a714945..67354a191 100644 --- a/vite/src/views/products/rewards/components/RewardRowToolbar.tsx +++ b/vite/src/views/products/rewards/components/RewardRowToolbar.tsx @@ -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"; diff --git a/vite/src/views/products/rewards/reward-programs/RewardProgramRowToolbar.tsx b/vite/src/views/products/rewards/reward-programs/RewardProgramRowToolbar.tsx index 44325b9b4..702538298 100644 --- a/vite/src/views/products/rewards/reward-programs/RewardProgramRowToolbar.tsx +++ b/vite/src/views/products/rewards/reward-programs/RewardProgramRowToolbar.tsx @@ -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";