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:
Philip Korsholm
2023-06-08 17:57:39 +02:00
committed by GitHub
parent f7376f09fe
commit 79cca2ab80
22 changed files with 1412 additions and 358 deletions

View File

@@ -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>
)

View File

@@ -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,
})}

View File

@@ -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,
}))}

View File

@@ -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
)

View File

@@ -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>
)
}