Skip to content

Commit

Permalink
Demo: Add 'FinalFormRangeInput' to handmade 'ProductForm' (#2593)
Browse files Browse the repository at this point in the history
A `FinalFormRangeInput` field is added to the handmade `ProductForm`.
This is done in preparation to add the range input field to the admin
generator.

A new field has been added to `product.entity` in context to this:
`priceRange`

```
@ObjectType()
@inputType("ProductPriceRangeInput")
export class ProductPriceRange {
    @field()
    @IsNumber()
    min: number;

    @field()
    @IsNumber()
    max: number;
}
```
  • Loading branch information
andrearutrecht authored Oct 8, 2024
1 parent fb24b79 commit fb7dc52
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 2 deletions.
4 changes: 4 additions & 0 deletions demo/admin/src/products/ProductForm.gql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ export const productFormFragment = gql`
id
title
}
priceRange {
min
max
}
}
${finalFormFileUploadFragment}
`;
Expand Down
14 changes: 13 additions & 1 deletion demo/admin/src/products/ProductForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
Field,
filterByFragment,
FinalForm,
FinalFormRangeInput,
FinalFormSubmitEvent,
Loading,
MainContent,
Expand All @@ -24,7 +25,7 @@ import {
resolveHasSaveConflict,
useFormSaveConflict,
} from "@comet/cms-admin";
import { MenuItem } from "@mui/material";
import { InputAdornment, MenuItem } from "@mui/material";
import { GQLProductType } from "@src/graphql.generated";
import {
GQLManufacturerCountriesQuery,
Expand All @@ -35,6 +36,7 @@ import {
import { FormApi } from "final-form";
import isEqual from "lodash.isequal";
import { useMemo } from "react";
import * as React from "react";
import { FormattedMessage } from "react-intl";

import {
Expand Down Expand Up @@ -177,6 +179,16 @@ export function ProductForm({ id }: FormProps) {
<TextField required fullWidth name="title" label={<FormattedMessage id="product.title" defaultMessage="Title" />} />
<TextField required fullWidth name="slug" label={<FormattedMessage id="product.slug" defaultMessage="Slug" />} />

<Field
name="priceRange"
label={<FormattedMessage id="product.priceRange" defaultMessage="Price range" />}
fullWidth
component={FinalFormRangeInput}
min={5}
max={100}
startAdornment={<InputAdornment position="start"></InputAdornment>}
disableSlider
/>
<TextAreaField
required
fullWidth
Expand Down
13 changes: 13 additions & 0 deletions demo/api/schema.gql
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,11 @@ type ProductDimensions {
depth: Float!
}

type ProductPriceRange {
min: Float!
max: Float!
}

type Product {
id: ID!
title: String!
Expand All @@ -538,6 +543,7 @@ type Product {
type: ProductType!
additionalTypes: [ProductType!]!
price: Float
priceRange: ProductPriceRange
inStock: Boolean!
soldCount: Int
availableSince: Date
Expand Down Expand Up @@ -729,6 +735,11 @@ input ProductDimensionsInput {
depth: Float!
}

input ProductPriceRangeInput {
min: Float!
max: Float!
}

input RedirectScopeInput {
domain: String!
}
Expand Down Expand Up @@ -1403,6 +1414,7 @@ input ProductInput {
type: ProductType!
additionalTypes: [ProductType!]! = []
price: Float = null
priceRange: ProductPriceRangeInput
inStock: Boolean! = true
availableSince: Date = null
lastCheckedAt: DateTime = null
Expand Down Expand Up @@ -1442,6 +1454,7 @@ input ProductUpdateInput {
type: ProductType
additionalTypes: [ProductType!]
price: Float
priceRange: ProductPriceRangeInput
inStock: Boolean
availableSince: Date
lastCheckedAt: DateTime
Expand Down
7 changes: 7 additions & 0 deletions demo/api/src/db/migrations/Migration20241004111520.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { Migration } from "@mikro-orm/migrations";

export class Migration20241004111520 extends Migration {
async up(): Promise<void> {
this.addSql('alter table "Product" add column "priceRange" jsonb null;');
}
}
16 changes: 16 additions & 0 deletions demo/api/src/products/entities/product.entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,18 @@ export class ProductDimensions {
depth: number;
}

@ObjectType()
@InputType("ProductPriceRangeInput")
export class ProductPriceRange {
@Field()
@IsNumber()
min: number;

@Field()
@IsNumber()
max: number;
}

@ObjectType()
@Entity()
@RootBlockEntity<Product>({ isVisible: (product) => product.status === ProductStatus.Published })
Expand Down Expand Up @@ -109,6 +121,10 @@ export class Product extends BaseEntity<Product, "id"> {
@Field({ nullable: true })
price?: number = undefined;

@Property({ type: "json", nullable: true })
@Field(() => ProductPriceRange, { nullable: true })
priceRange?: ProductPriceRange = undefined;

// eslint-disable-next-line @typescript-eslint/no-inferrable-types
@Property({ type: types.boolean })
@Field()
Expand Down
8 changes: 7 additions & 1 deletion demo/api/src/products/generated/dto/product.input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { Transform, Type } from "class-transformer";
import { IsArray, IsBoolean, IsDate, IsEnum, IsNotEmpty, IsNumber, IsString, IsUUID, ValidateNested } from "class-validator";
import { GraphQLDate } from "graphql-scalars";

import { ProductDimensions, ProductDiscounts, ProductStatus } from "../../entities/product.entity";
import { ProductDimensions, ProductDiscounts, ProductPriceRange, ProductStatus } from "../../entities/product.entity";
import { ProductType } from "../../entities/product-type.enum";
import { ProductNestedProductColorInput } from "./product-nested-product-color.input";
import { ProductNestedProductStatisticsInput } from "./product-nested-product-statistics.input";
Expand Down Expand Up @@ -50,6 +50,12 @@ export class ProductInput {
@Field({ nullable: true, defaultValue: null })
price?: number;

@IsNullable()
@ValidateNested()
@Type(() => ProductPriceRange)
@Field(() => ProductPriceRange, { nullable: true })
priceRange?: ProductPriceRange;

@IsNotEmpty()
@IsBoolean()
@Field({ defaultValue: true })
Expand Down

0 comments on commit fb7dc52

Please sign in to comment.