Skip to content

Commit

Permalink
feat(dashboard,types,js-sdk,ui): Add missing Price List features (#7856)
Browse files Browse the repository at this point in the history
**What**
- Adds missing features to Price List domain
- Adds `StackedFocusModal` and `StackedDrawer` components that should replace SplitView across the project.
- Add Footer to FocusModal
- Adds missing js-sdk functions and types

**Note**
The DatePickers in the PriceLists forms do not work as intended atm. The component is broken, and needs to be fixed. I am working on a fix, but choose to move that work into a separate branch, to prevent this PR from getting bigger then it already is. Will update once the fixes have been merged.
  • Loading branch information
kasperkristensen committed Jun 28, 2024
1 parent 9f39983 commit c174021
Show file tree
Hide file tree
Showing 295 changed files with 4,490 additions and 2,352 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { PropsWithChildren, createContext } from "react"

type ConditionOperator =
| "eq"
| "ne"
| "gt"
| "lt"
| "gte"
| "lte"
| "in"
| "nin"

type ConditionBlockValue<TValue> = {
attribute: string
operator: ConditionOperator
value: TValue
}

type ConditionBlockState<TValue> = {
defaultValue?: ConditionBlockValue<TValue>
value?: ConditionBlockValue<TValue>
onChange: (value: ConditionBlockValue<TValue>) => void
}

const ConditionBlockContext = createContext<ConditionBlockState<any> | null>(
null
)

const useConditionBlock = () => {
const context = ConditionBlockContext

if (!context) {
throw new Error("useConditionBlock must be used within a ConditionBlock")
}

return context
}

type ConditionBlockProps<TValue> = PropsWithChildren<
ConditionBlockState<TValue>
>

const Root = <TValue,>({ children, ...props }: ConditionBlockProps<TValue>) => {
return (
<ConditionBlockContext.Provider value={props}>
{children}
</ConditionBlockContext.Provider>
)
}

const Divider = () => {}

const Operator = () => {}

const Item = () => {}

export const ConditionBlock = Object.assign(Root, {
Divider,
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { Text, clx } from "@medusajs/ui"
import { useTranslation } from "react-i18next"
import { useDate } from "../../../hooks/use-date"

type DateRangeDisplayProps = {
startsAt?: Date | string | null
endsAt?: Date | string | null
showTime?: boolean
}

export const DateRangeDisplay = ({
startsAt,
endsAt,
showTime = false,
}: DateRangeDisplayProps) => {
const startDate = startsAt ? new Date(startsAt) : null
const endDate = endsAt ? new Date(endsAt) : null

const { t } = useTranslation()
const { getFullDate } = useDate()

return (
<div className="grid gap-3 md:grid-cols-2">
<div className="shadow-elevation-card-rest bg-ui-bg-component text-ui-fg-subtle flex items-center gap-x-3 rounded-md px-3 py-1.5">
<Bar date={startDate} />
<div>
<Text weight="plus" size="small">
{t("fields.startDate")}
</Text>
<Text size="small">
{startDate
? getFullDate({
date: startDate,
includeTime: showTime,
})
: "-"}
</Text>
</div>
</div>

<div className="shadow-elevation-card-rest bg-ui-bg-component text-ui-fg-subtle flex items-center gap-x-3 rounded-md px-3 py-1.5">
<Bar date={endDate} />
<div>
<Text size="small" weight="plus">
{t("fields.endDate")}
</Text>
<Text size="small">
{endDate
? getFullDate({
date: endDate,
includeTime: showTime,
})
: "-"}
</Text>
</div>
</div>
</div>
)
}

const Bar = ({ date }: { date: Date | null }) => {
const now = new Date()

const isDateInFuture = date && date > now

return (
<div
className={clx("bg-ui-tag-neutral-icon h-8 w-1 rounded-full", {
"bg-ui-tag-orange-icon": isDateInFuture,
})}
/>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./date-range-display"
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ import {
useState,
} from "react"

import { Adjustments } from "@medusajs/icons"
import { Button, DropdownMenu, clx } from "@medusajs/ui"
import {
CellContext,
ColumnDef,
OnChangeFn,
Row,
VisibilityState,
flexRender,
Expand Down Expand Up @@ -41,7 +41,7 @@ interface DataGridRootProps<
data?: TData[]
columns: ColumnDef<TData>[]
state: UseFormReturn<TFieldValues>
getSubRows?: (row: TData) => TData[]
getSubRows?: (row: TData) => TData[] | undefined
}

const ARROW_KEYS = ["ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight"]
Expand Down Expand Up @@ -93,13 +93,6 @@ export const DataGridRoot = <

const [columnVisibility, setColumnVisibility] = useState<VisibilityState>({})

const onColumnVisibilityChange: OnChangeFn<VisibilityState> = useCallback(
(next) => {
const update = typeof next === "function" ? next(columnVisibility) : next
},
[columnVisibility]
)

const grid = useReactTable({
data: data,
columns,
Expand Down Expand Up @@ -663,7 +656,8 @@ export const DataGridRoot = <
<DropdownMenu>
<DropdownMenu.Trigger asChild>
<Button size="small" variant="secondary">
Columns
<Adjustments />
Edit columns
</Button>
</DropdownMenu.Trigger>
<DropdownMenu.Content>
Expand Down Expand Up @@ -799,6 +793,7 @@ export const DataGridRoot = <
{flexRender(cell.column.columnDef.cell, {
...cell.getContext(),
columnIndex,
rowIndex: virtualRow.index,
} as CellContext<TData, any>)}
{isAnchor && (
<div
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,14 @@ export const useDataGridCell = <TData, TValue>({
field,
context,
}: UseDataGridCellProps<TData, TValue>) => {
const { row, columnIndex } = context as DataGridCellContext<TData, TValue>
const { rowIndex, columnIndex } = context as DataGridCellContext<
TData,
TValue
>

const coords: CellCoords = useMemo(
() => ({ row: row.index, col: columnIndex }),
[row, columnIndex]
() => ({ row: rowIndex, col: columnIndex }),
[rowIndex, columnIndex]
)
const id = generateCellId(coords)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ export interface DataGridCellContext<TData = unknown, TValue = any>
* The index of the column in the grid.
*/
columnIndex: number
/**
* The index of the row in the grid.
*/
rowIndex: number
}

export interface DataGridCellContainerProps {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,8 +150,8 @@ const useCoreRoutes = (): Omit<NavItemProps, "pathname">[] => {
},
{
icon: <CurrencyDollar />,
label: t("pricing.domain"),
to: "/pricing",
label: t("priceLists.domain"),
to: "/price-lists",
},
]
}
Expand Down
7 changes: 7 additions & 0 deletions packages/admin-next/dashboard/src/components/modals/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export { RouteDrawer } from "./route-drawer"
export { RouteFocusModal } from "./route-focus-modal"
export { useRouteModal } from "./route-modal-provider"

export { StackedDrawer } from "./stacked-drawer"
export { StackedFocusModal } from "./stacked-focus-modal"
export { useStackedModal } from "./stacked-modal-provider"
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { Drawer } from "@medusajs/ui"
import { Drawer, clx } from "@medusajs/ui"
import { PropsWithChildren, useEffect, useState } from "react"
import { useNavigate } from "react-router-dom"
import { RouteForm } from "../route-form"
import { RouteModalForm } from "../route-modal-form"
import { RouteModalProvider } from "../route-modal-provider/route-provider"
import { StackedModalProvider } from "../stacked-modal-provider"

type RouteDrawerProps = PropsWithChildren<{
prev?: string
Expand All @@ -11,13 +12,19 @@ type RouteDrawerProps = PropsWithChildren<{
const Root = ({ prev = "..", children }: RouteDrawerProps) => {
const navigate = useNavigate()
const [open, setOpen] = useState(false)
const [stackedModalOpen, onStackedModalOpen] = useState(false)

/**
* Open the modal when the component mounts. This
* ensures that the entry animation is played.
*/
useEffect(() => {
setOpen(true)

return () => {
setOpen(false)
onStackedModalOpen(false)
}
}, [])

const handleOpenChange = (open: boolean) => {
Expand All @@ -33,17 +40,27 @@ const Root = ({ prev = "..", children }: RouteDrawerProps) => {
return (
<Drawer open={open} onOpenChange={handleOpenChange}>
<RouteModalProvider prev={prev}>
<Drawer.Content>{children}</Drawer.Content>
<StackedModalProvider onOpenChange={onStackedModalOpen}>
<Drawer.Content
className={clx({
"!bg-ui-bg-disabled !inset-y-5 !right-5": stackedModalOpen,
})}
>
{children}
</Drawer.Content>
</StackedModalProvider>
</RouteModalProvider>
</Drawer>
)
}

const Header = Drawer.Header
const Title = Drawer.Title
const Description = Drawer.Description
const Body = Drawer.Body
const Footer = Drawer.Footer
const Close = Drawer.Close
const Form = RouteForm
const Form = RouteModalForm

/**
* Drawer that is used to render a form on a separate route.
Expand All @@ -52,7 +69,9 @@ const Form = RouteForm
*/
export const RouteDrawer = Object.assign(Root, {
Header,
Title,
Body,
Description,
Footer,
Close,
Form,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { FocusModal } from "@medusajs/ui"
import { FocusModal, clx } from "@medusajs/ui"
import { PropsWithChildren, useEffect, useState } from "react"
import { useNavigate } from "react-router-dom"
import { RouteForm } from "../route-form"
import { RouteModalForm } from "../route-modal-form"
import { RouteModalProvider } from "../route-modal-provider/route-provider"
import { StackedModalProvider } from "../stacked-modal-provider"

type RouteFocusModalProps = PropsWithChildren<{
prev?: string
Expand All @@ -11,13 +12,19 @@ type RouteFocusModalProps = PropsWithChildren<{
const Root = ({ prev = "..", children }: RouteFocusModalProps) => {
const navigate = useNavigate()
const [open, setOpen] = useState(false)
const [stackedModalOpen, onStackedModalOpen] = useState(false)

/**
* Open the modal when the component mounts. This
* ensures that the entry animation is played.
*/
useEffect(() => {
setOpen(true)

return () => {
setOpen(false)
onStackedModalOpen(false)
}
}, [])

const handleOpenChange = (open: boolean) => {
Expand All @@ -33,16 +40,27 @@ const Root = ({ prev = "..", children }: RouteFocusModalProps) => {
return (
<FocusModal open={open} onOpenChange={handleOpenChange}>
<RouteModalProvider prev={prev}>
<FocusModal.Content>{children}</FocusModal.Content>
<StackedModalProvider onOpenChange={onStackedModalOpen}>
<FocusModal.Content
className={clx({
"!bg-ui-bg-disabled !inset-x-5 !inset-y-3": stackedModalOpen,
})}
>
{children}
</FocusModal.Content>
</StackedModalProvider>
</RouteModalProvider>
</FocusModal>
)
}

const Header = FocusModal.Header
const Title = FocusModal.Title
const Description = FocusModal.Description
const Footer = FocusModal.Footer
const Body = FocusModal.Body
const Close = FocusModal.Close
const Form = RouteForm
const Form = RouteModalForm

/**
* FocusModal that is used to render a form on a separate route.
Expand All @@ -52,7 +70,10 @@ const Form = RouteForm
*/
export const RouteFocusModal = Object.assign(Root, {
Header,
Title,
Body,
Description,
Footer,
Close,
Form,
})
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./route-modal-form"
Loading

0 comments on commit c174021

Please sign in to comment.