Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(dashboard): restructure create product flow #7374

Merged
merged 38 commits into from
May 28, 2024
Merged
Show file tree
Hide file tree
Changes from 37 commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
8e7abd6
feat: restructure create product details
fPolic May 20, 2024
049e27c
Merge branch 'develop' into feat/product-create-reorg-v1
fPolic May 21, 2024
234d1eb
feat: auto select variants, align some texts with design, fix tabs sc…
fPolic May 21, 2024
8779420
Merge branch 'develop' into feat/product-create-reorg-v1
fPolic May 21, 2024
8a302f8
feat: manage default variant, inventory kit tab
fPolic May 22, 2024
b06b10c
feat/wip: bulk editor
fPolic May 22, 2024
8dcaa71
fix: basic flow edge cases
fPolic May 22, 2024
6009d01
fix: issues with inventory items appending on tab switch
fPolic May 22, 2024
5493dae
Merge branch 'develop' into feat/product-create-reorg-v1
fPolic May 23, 2024
31aeba3
fix: send correct pricing, render correct pricing on the edit form
fPolic May 23, 2024
ce4118b
fix: manage inventory flag
fPolic May 23, 2024
e5bc4ff
Add admin http product type and update sdk
adrien2p May 23, 2024
948c3c7
fix: merge conflict
fPolic May 23, 2024
ca060bf
resolve conflicts
adrien2p May 23, 2024
50c9884
fix: add missing files
fPolic May 23, 2024
960d111
Merge branch 'feat/product-create-reorg-v1' of github.com:medusajs/me…
adrien2p May 23, 2024
371184f
cleanup
adrien2p May 23, 2024
b87d731
feat: add new bulk editor, fix build issue
fPolic May 23, 2024
38922ee
chore: cleanup
fPolic May 23, 2024
3a20cc2
Merge branch 'develop' into feat/product-create-reorg-v1
fPolic May 23, 2024
a330536
fix: change error toasts
fPolic May 24, 2024
7c38cac
Merge branch 'develop' into feat/product-create-reorg-v1
fPolic May 24, 2024
831cb93
fix: rerendering of the table
fPolic May 24, 2024
35b7304
fix: validations
fPolic May 24, 2024
ee89e3a
Merge branch 'develop' into feat/product-create-reorg-v1
fPolic May 24, 2024
ba08eff
Merge branch 'develop' into feat/product-create-reorg-v1
fPolic May 26, 2024
bbed062
Merge branch 'develop' into feat/product-create-reorg-v1
fPolic May 27, 2024
a7deabb
fix: typo
fPolic May 27, 2024
d79c1f5
fix: prices filed
fPolic May 27, 2024
bcb599d
fix: edit variant prices endpoint
fPolic May 27, 2024
2ecc039
feat: different additional validations, disable deleting single optio…
fPolic May 27, 2024
2bce0bc
Merge branch 'develop' into feat/product-create-reorg-v1
fPolic May 27, 2024
21f8276
feat: filter variants, reponsive fix
fPolic May 27, 2024
2a37748
feat: decorate default values
fPolic May 27, 2024
9b190f0
chore: cleanup
fPolic May 27, 2024
1b3aa63
Merge branch 'develop' into feat/product-create-reorg-v1
fPolic May 27, 2024
647725c
Merge branch 'develop' into feat/product-create-reorg-v1
fPolic May 28, 2024
06e89d1
fix: number defaults, handling errors
fPolic May 28, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { MouseEvent, createContext } from "react"
import { Control, FieldValues, Path, UseFormRegister } from "react-hook-form"
import { CellCoords } from "./types"

type DataGridContextType<TForm extends FieldValues> = {
anchor: CellCoords | null
register: UseFormRegister<TForm>
control: Control<TForm>
onRegisterCell: (coordinates: CellCoords) => void
onUnregisterCell: (coordinates: CellCoords) => void
getMouseDownHandler: (
coordinates: CellCoords
) => (e: MouseEvent<HTMLElement>) => void
getMouseOverHandler: (
coordinates: CellCoords
) => ((e: MouseEvent<HTMLElement>) => void) | undefined
getOnChangeHandler: (field: Path<TForm>) => (next: any, prev: any) => void
}

export const DataGridContext = createContext<DataGridContextType<any> | null>(
null
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { Checkbox } from "@medusajs/ui"
import { Controller } from "react-hook-form"
import { useDataGridCell } from "../hooks"
import { DataGridCellProps } from "../types"
import { DataGridCellContainer } from "./data-grid-cell-container"

export const DataGridBooleanCell = <TData, TValue = any>({
field,
context,
disabled,
}: DataGridCellProps<TData, TValue> & { disabled?: boolean }) => {
const { control, attributes, container, onChange } = useDataGridCell({
field,
context,
})

return (
<Controller
control={control}
name={field}
render={({ field: { value, onChange: _, ...field } }) => {
return (
<DataGridCellContainer {...container}>
<Checkbox
checked={value}
onCheckedChange={(next) => onChange(next, value)}
{...field}
{...attributes}
disabled={disabled}
/>
</DataGridCellContainer>
)
}}
/>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { PropsWithChildren } from "react"
import { DataGridCellContainerProps } from "../types"

type ContainerProps = PropsWithChildren<DataGridCellContainerProps>

export const DataGridCellContainer = ({
isAnchor,
placeholder,
overlay,
wrapper,
children,
}: ContainerProps) => {
return (
<div className="static size-full">
<div className="flex size-full items-start outline-none" tabIndex={-1}>
<div {...wrapper} className="relative size-full min-w-0 flex-1">
<div className="relative z-[1] flex size-full items-center justify-center">
<RenderChildren isAnchor={isAnchor} placeholder={placeholder}>
{children}
</RenderChildren>
</div>
{!isAnchor && (
<div
{...overlay}
tabIndex={-1}
className="absolute inset-0 z-[2] size-full"
/>
)}
</div>
</div>
{/* {showDragHandle && (
<div className="bg-ui-bg-interactive absolute -bottom-[1.5px] -right-[1.5px] size-[3px]" />
)} */}
</div>
)
}

const RenderChildren = ({
isAnchor,
placeholder,
children,
}: PropsWithChildren<
Pick<DataGridCellContainerProps, "isAnchor" | "placeholder">
>) => {
if (!isAnchor && placeholder) {
return placeholder
}

return children
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import { TrianglesMini } from "@medusajs/icons"
import { clx } from "@medusajs/ui"
import { ComponentPropsWithoutRef, forwardRef, memo } from "react"
import { Controller } from "react-hook-form"

import { countries } from "../../../lib/countries"
import { useDataGridCell } from "../hooks"
import { DataGridCellProps } from "../types"
import { DataGridCellContainer } from "./data-grid-cell-container"

export const DataGridCountrySelectCell = <TData, TValue = any>({
field,
context,
}: DataGridCellProps<TData, TValue>) => {
const { control, attributes, container, onChange } = useDataGridCell({
field,
context,
})

return (
<Controller
control={control}
name={field}
render={({ field: { value, onChange: _, disabled, ...field } }) => {
return (
<DataGridCellContainer
{...container}
placeholder={
<DataGridCountryCellPlaceholder
value={value}
disabled={disabled}
attributes={attributes}
/>
}
>
<MemoizedDataGridCountryCell
value={value}
onChange={(e) => onChange(e.target.value, value)}
disabled={disabled}
{...attributes}
{...field}
/>
</DataGridCellContainer>
)
}}
/>
)
}

const DataGridCountryCellPlaceholder = ({
value,
disabled,
attributes,
}: {
value?: string
disabled?: boolean
attributes: Record<string, any>
}) => {
const country = countries.find((c) => c.iso_2 === value)

return (
<div className="relative flex size-full" {...attributes}>
<TrianglesMini
className={clx(
"text-ui-fg-muted transition-fg pointer-events-none absolute right-4 top-1/2 -translate-y-1/2",
{
"text-ui-fg-disabled": disabled,
}
)}
/>
<div
className={clx(
"txt-compact-small w-full appearance-none bg-transparent px-4 py-2.5 outline-none"
)}
>
{country?.display_name}
</div>
</div>
)
}

const DataGridCountryCellImpl = forwardRef<
HTMLSelectElement,
ComponentPropsWithoutRef<"select">
>(({ disabled, className, ...props }, ref) => {
return (
<div className="relative flex size-full">
<TrianglesMini
className={clx(
"text-ui-fg-muted transition-fg pointer-events-none absolute right-4 top-1/2 -translate-y-1/2",
{
"text-ui-fg-disabled": disabled,
}
)}
/>
<select
{...props}
ref={ref}
className={clx(
"txt-compact-small w-full appearance-none bg-transparent px-4 py-2.5 outline-none",
className
)}
>
<option value=""></option>
{countries.map((country) => (
<option key={country.iso_2} value={country.iso_2}>
{country.display_name}
</option>
))}
</select>
</div>
)
})
DataGridCountryCellImpl.displayName = "DataGridCountryCell"

const MemoizedDataGridCountryCell = memo(DataGridCountryCellImpl)
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import CurrencyInput from "react-currency-input-field"
import { Controller } from "react-hook-form"

import { currencies } from "../../../lib/currencies"
import { useDataGridCell } from "../hooks"
import { DataGridCellProps } from "../types"
import { DataGridCellContainer } from "./data-grid-cell-container"

interface DataGridCurrencyCellProps<TData, TValue = any>
extends DataGridCellProps<TData, TValue> {
code: string
}

export const DataGridCurrencyCell = <TData, TValue = any>({
field,
context,
code,
}: DataGridCurrencyCellProps<TData, TValue>) => {
const { control, attributes, container } = useDataGridCell({
field,
context,
})

const currency = currencies[code.toUpperCase()]

return (
<Controller
control={control}
name={field}
render={({ field: { value, onChange, ...field } }) => {
return (
<DataGridCellContainer {...container}>
<div className="flex size-full items-center gap-2 px-4 py-2.5">
<span className="txt-compact-small text-ui-fg-muted" aria-hidden>
{currency.symbol_native}
</span>
<CurrencyInput
{...field}
{...attributes}
className="txt-compact-small flex-1 appearance-none bg-transparent text-right outline-none"
value={value}
onValueChange={(_value, _name, values) =>
onChange(values?.value)
}
decimalScale={currency.decimal_digits}
decimalsLimit={currency.decimal_digits}
/>
</div>
</DataGridCellContainer>
)
}}
/>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { useDataGridCell } from "../hooks"
import { DataGridCellProps } from "../types"
import { DataGridCellContainer } from "./data-grid-cell-container"

export const DataGridNumberCell = <TData, TValue = any>({
field,
context,
}: DataGridCellProps<TData, TValue>) => {
const { register, attributes, container } = useDataGridCell({
field,
context,
})

return (
<DataGridCellContainer {...container}>
<input
{...attributes}
type="number"
{...register(field, {
valueAsNumber: true,
})}
/>
</DataGridCellContainer>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { PropsWithChildren } from "react"

type DataGridReadOnlyCellProps = PropsWithChildren

export const DataGridReadOnlyCell = ({
children,
}: DataGridReadOnlyCellProps) => {
return (
<div className="bg-ui-bg-subtle txt-compact-small text-ui-fg-subtle flex size-full cursor-not-allowed items-center px-4 py-2.5 outline-none">
<span>{children}</span>
</div>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { Select, clx } from "@medusajs/ui"
import { Controller } from "react-hook-form"
import { useDataGridCell } from "../hooks"
import { DataGridCellProps } from "../types"
import { DataGridCellContainer } from "./data-grid-cell-container"

interface DataGridSelectCellProps<TData, TValue = any>
extends DataGridCellProps<TData, TValue> {
options: { label: string; value: string }[]
}

export const DataGridSelectCell = <TData, TValue = any>({
context,
options,
field,
}: DataGridSelectCellProps<TData, TValue>) => {
const { control, attributes, container } = useDataGridCell({
field,
context,
})

return (
<Controller
control={control}
name={field}
render={({ field: { onChange, ref, ...field } }) => {
return (
<DataGridCellContainer {...container}>
<Select {...field} onValueChange={onChange}>
<Select.Trigger
{...attributes}
ref={ref}
className={clx(
"h-full w-full rounded-none bg-transparent px-4 py-2.5 shadow-none",
"hover:bg-transparent focus:shadow-none data-[state=open]:!shadow-none"
)}
>
<Select.Value />
</Select.Trigger>
<Select.Content>
{options.map((option) => (
<Select.Item key={option.value} value={option.value}>
{option.label}
</Select.Item>
))}
</Select.Content>
</Select>
</DataGridCellContainer>
)
}}
/>
)
}
Loading
Loading