feat(admin-ui): Filter reservations (#4115)
* initial filter * clenaup * reser filters correctly * filter reservations * ensure reset works * update types * add adjustment icon * pr prep * update filtering with proper description handling * location filter updates and search removal * removed greyed out dates + add created_by filtering * update filtering with proper ordering * filter out selected users * fix array issues * update spacing for searchable queries * fix deselection bug for inventory item search * update date filter; * rename const a to initialFilters * fix re-render issue * ui updates * update inventory filter to remove selected items * fix width * fix truncation for button text if desired * add span classes * add "go to reservations" popover * add tooltip if location text is truncated * fix long items * typing * minor fix for select value * fix reservation quantity field updates * add pb * Update packages/admin-ui/ui/src/components/templates/reservations-table/index.tsx Co-authored-by: Oliver Windall Juhl <59018053+olivermrbl@users.noreply.github.com> * feedback * add changeset --------- Co-authored-by: Oliver Windall Juhl <59018053+olivermrbl@users.noreply.github.com>
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import * as RadixPopover from "@radix-ui/react-popover"
|
||||
|
||||
import React, {
|
||||
PropsWithChildren,
|
||||
ReactNode,
|
||||
@@ -6,8 +7,9 @@ import React, {
|
||||
useRef,
|
||||
useState,
|
||||
} from "react"
|
||||
import { useWindowDimensions } from "../../../hooks/use-window-dimensions"
|
||||
|
||||
import Button from "../../fundamentals/button"
|
||||
import { useWindowDimensions } from "../../../hooks/use-window-dimensions"
|
||||
|
||||
type FilterDropdownContainerProps = {
|
||||
submitFilters: () => void
|
||||
@@ -52,13 +54,25 @@ const FilterDropdownContainer = ({
|
||||
<RadixPopover.Content
|
||||
sideOffset={8}
|
||||
style={heightStyle}
|
||||
className="bg-grey-0 rounded-rounded shadow-dropdown z-40 max-w-[272px] overflow-y-auto py-4"
|
||||
className="bg-grey-0 rounded-rounded shadow-dropdown z-40 max-w-[320px] overflow-y-auto pt-1"
|
||||
>
|
||||
<div className="border-grey-20 flex border-b px-4 pb-4">
|
||||
{React.Children.toArray(children)
|
||||
.filter(Boolean)
|
||||
.map((child, idx) => {
|
||||
return (
|
||||
<div
|
||||
key={idx}
|
||||
className="border-grey-20 border-b last:border-0 last:pb-0"
|
||||
>
|
||||
{child}
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
<div className="border-grey-20 gap-x-small flex grid grid-cols-2 border-b px-3 py-2.5">
|
||||
<Button
|
||||
size="small"
|
||||
tabIndex={-1}
|
||||
className="border-grey-20 mr-2 border"
|
||||
className="border-grey-20 mr-2 w-full border"
|
||||
variant="ghost"
|
||||
onClick={() => onClear()}
|
||||
>
|
||||
@@ -67,20 +81,13 @@ const FilterDropdownContainer = ({
|
||||
<Button
|
||||
tabIndex={-1}
|
||||
variant="primary"
|
||||
className="w-44 justify-center"
|
||||
className="w-full justify-center"
|
||||
size="small"
|
||||
onClick={() => onSubmit()}
|
||||
>
|
||||
Apply
|
||||
</Button>
|
||||
</div>
|
||||
{React.Children.toArray(children).filter(Boolean).map((child) => {
|
||||
return (
|
||||
<div className="border-grey-20 border-b py-2 px-4 last:border-0 last:pb-0">
|
||||
{child}
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</RadixPopover.Content>
|
||||
</RadixPopover.Root>
|
||||
)
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
import * as RadixCollapsible from "@radix-ui/react-collapsible"
|
||||
import * as RadixPopover from "@radix-ui/react-popover"
|
||||
import clsx from "clsx"
|
||||
import moment from "moment"
|
||||
import { useEffect, useMemo, useState } from "react"
|
||||
import { DateFilters } from "../../../utils/filters"
|
||||
|
||||
import { addHours, atMidnight, dateToUnixTimestamp } from "../../../utils/time"
|
||||
import { CalendarComponent } from "../../atoms/date-picker/date-picker"
|
||||
import Spinner from "../../atoms/spinner"
|
||||
import { useEffect, useMemo, useState } from "react"
|
||||
|
||||
import ArrowRightIcon from "../../fundamentals/icons/arrow-right-icon"
|
||||
import { CalendarComponent } from "../../atoms/date-picker/date-picker"
|
||||
import CheckIcon from "../../fundamentals/icons/check-icon"
|
||||
import ChevronUpIcon from "../../fundamentals/icons/chevron-up"
|
||||
import { DateFilters } from "../../../utils/filters"
|
||||
import InputField from "../input"
|
||||
import Spinner from "../../atoms/spinner"
|
||||
import clsx from "clsx"
|
||||
import moment from "moment"
|
||||
|
||||
const DAY_IN_SECONDS = 86400
|
||||
|
||||
@@ -84,7 +86,7 @@ const FilterDropdownItem = ({
|
||||
|
||||
return (
|
||||
<div
|
||||
className={clsx("w-full cursor-pointer", {
|
||||
className={clsx("w-full cursor-pointer py-2 px-4 ", {
|
||||
"inter-small-semibold": open,
|
||||
"inter-small-regular": !open,
|
||||
})}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { useEffect, useMemo } from "react"
|
||||
import { useAdminStockLocations } from "medusa-react"
|
||||
|
||||
import { NextSelect } from "../select/next-select"
|
||||
import { StockLocationDTO } from "@medusajs/types"
|
||||
import { useAdminStockLocations } from "medusa-react"
|
||||
|
||||
const LocationDropdown = ({
|
||||
selectedLocation,
|
||||
@@ -19,7 +21,10 @@ const LocationDropdown = ({
|
||||
|
||||
const selectedLocObj = useMemo(() => {
|
||||
if (!isLoading && locations) {
|
||||
return locations.find((l) => l.id === selectedLocation) ?? locations[0]
|
||||
return (
|
||||
locations.find((l: StockLocationDTO) => l.id === selectedLocation) ??
|
||||
locations[0]
|
||||
)
|
||||
}
|
||||
}, [selectedLocation, locations, isLoading])
|
||||
|
||||
@@ -33,7 +38,7 @@ const LocationDropdown = ({
|
||||
onChange={(loc) => {
|
||||
onChange(loc!.value)
|
||||
}}
|
||||
options={locations.map((l) => ({
|
||||
options={locations.map((l: StockLocationDTO) => ({
|
||||
label: l.name,
|
||||
value: l.id,
|
||||
}))}
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import clsx from "clsx"
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from "react"
|
||||
import {
|
||||
ActionMeta,
|
||||
CX,
|
||||
@@ -12,11 +10,14 @@ import {
|
||||
OptionsOrGroups,
|
||||
PropsValue,
|
||||
} from "react-select"
|
||||
import { hasPrefix, hasSuffix, optionIsDisabled } from "../utils"
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from "react"
|
||||
|
||||
import Button from "../../../../fundamentals/button"
|
||||
import CheckIcon from "../../../../fundamentals/icons/check-icon"
|
||||
import ListArrowIcon from "../../../../fundamentals/icons/list-arrow-icon"
|
||||
import { hasPrefix, hasSuffix, optionIsDisabled } from "../utils"
|
||||
import SelectPrimitives from "./select-primitives"
|
||||
import clsx from "clsx"
|
||||
|
||||
const Menu = <
|
||||
Option,
|
||||
@@ -279,7 +280,7 @@ export const Option = <
|
||||
},
|
||||
{
|
||||
"h-xlarge": size === "sm",
|
||||
"h-10": size === "md" || !size,
|
||||
"min-h-10": size === "md" || !size,
|
||||
},
|
||||
className
|
||||
)
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import clsx from "clsx"
|
||||
import { GroupBase, SingleValueProps } from "react-select"
|
||||
|
||||
import Tooltip from "../../../../atoms/tooltip"
|
||||
import clsx from "clsx"
|
||||
import { hasPrefix } from "../utils"
|
||||
import { useRef } from "react"
|
||||
|
||||
const SingleValue = <
|
||||
Option,
|
||||
@@ -13,28 +16,58 @@ const SingleValue = <
|
||||
className,
|
||||
isDisabled,
|
||||
data,
|
||||
getValue,
|
||||
}: SingleValueProps<Option, IsMulti, Group>) => {
|
||||
const prefix = hasPrefix(data) ? data.prefix : null
|
||||
|
||||
const isEllipsisActive = (e: HTMLDivElement | null) => {
|
||||
if (!e || !(e.offsetParent as HTMLDivElement)?.offsetWidth) {
|
||||
return false
|
||||
}
|
||||
|
||||
return (e.offsetParent as HTMLDivElement).offsetWidth < e.scrollWidth
|
||||
}
|
||||
|
||||
const getToolTipValue = () => {
|
||||
const values = getValue()
|
||||
if (!values.length) {
|
||||
return null
|
||||
}
|
||||
|
||||
const value = values[0] as { label: string } // option with label
|
||||
return value.label ?? null
|
||||
}
|
||||
|
||||
const toolTip = getToolTipValue()
|
||||
|
||||
const ref = useRef(null)
|
||||
|
||||
return (
|
||||
<div
|
||||
{...innerProps}
|
||||
className={cx(
|
||||
{
|
||||
"single-value": true,
|
||||
"single-value--is-disabled": isDisabled,
|
||||
},
|
||||
clsx(
|
||||
"absolute top-1/2 -translate-y-1/2 overflow-hidden overflow-ellipsis whitespace-nowrap",
|
||||
className
|
||||
)
|
||||
)}
|
||||
<Tooltip
|
||||
className={clsx({ hidden: !isEllipsisActive(ref.current) || !toolTip })}
|
||||
delayDuration={1000}
|
||||
content={<div>{toolTip}</div>}
|
||||
>
|
||||
<div className="gap-x-xsmall inter-base-regular flex items-center">
|
||||
{prefix && <span className="inter-base-semibold">{prefix}</span>}
|
||||
{children}
|
||||
<div
|
||||
{...innerProps}
|
||||
ref={ref}
|
||||
className={cx(
|
||||
{
|
||||
"single-value": true,
|
||||
"single-value--is-disabled": isDisabled,
|
||||
},
|
||||
clsx(
|
||||
"absolute top-1/2 -translate-y-1/2 overflow-hidden overflow-ellipsis whitespace-nowrap",
|
||||
className
|
||||
)
|
||||
)}
|
||||
>
|
||||
<div className="gap-x-xsmall inter-base-regular flex items-center">
|
||||
{prefix && <span className="inter-base-semibold">{prefix}</span>}
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user