fix: groups input + entity feature id UI

This commit is contained in:
John Yeo
2025-10-20 08:31:39 +01:00
parent 458e3ca4ce
commit d5ee00d4f0
7 changed files with 41 additions and 13 deletions

View File

@@ -33,7 +33,7 @@ const productDetailsSame = (prod1: Product, prod2: UpdateProduct) => {
return false;
}
if (notNullish(prod2.group) && prod1.group !== prod2.group) {
if (prod2.group !== undefined && prod1.group !== prod2.group) {
return false;
}
@@ -223,6 +223,7 @@ export const handleUpdateProductDetails = async ({
}
// 2. Update product
console.log("New group:", newProduct.group);
await ProductService.updateByInternalId({
db,
@@ -230,7 +231,10 @@ export const handleUpdateProductDetails = async ({
update: {
id: newProduct.id,
name: newProduct.name,
group: newProduct.group,
group:
newProduct.group === "" || newProduct.group === null
? ""
: newProduct.group,
is_add_on: newProduct.is_add_on,
is_default: newProduct.is_default,
archived: newProduct.archived,

View File

@@ -35,7 +35,7 @@ export const UpdateProductV2ParamsSchema = z.object({
is_add_on: z.boolean().optional(),
is_default: z.boolean().optional(),
version: z.number().optional(),
group: z.string().nullish(),
group: z.string().nonempty().nullable(),
archived: z.boolean().optional(),
items: z.array(CreateProductItemParamsSchema).optional(),

View File

@@ -11,7 +11,7 @@ export const ProductV2Schema = z.object({
is_add_on: z.boolean(),
is_default: z.boolean(),
version: z.number().default(1),
group: z.string(),
group: z.string().nullable(),
env: z.nativeEnum(AppEnv),
free_trial: FreeTrialSchema.nullish(),

View File

@@ -85,7 +85,7 @@ export const mapToProductV2 = ({
is_add_on: product.is_add_on,
is_default: product.is_default,
version: product.version,
group: product.group,
group: product.group || null,
free_trial: product.free_trial,
created_at: product.created_at,
env: product.env,

View File

@@ -1,13 +1,7 @@
import type { z } from "zod/v4";
import type { ProductV2 } from "../../models/productV2Models/productV2Models.js";
import type { PlanResponseSchema } from "../../models/productV3Models/productV3Response.js";
import { productV2ToBasePrice } from "./productItemUtils/productV3ItemUtils.js";
export function mapToProductV3({
product,
}: {
product: ProductV2;
}): z.infer<typeof PlanResponseSchema> {
export function mapToProductV3({ product }: { product: ProductV2 }) {
const productV3 = {
id: product.id,
name: product.name,

View File

@@ -1,4 +1,5 @@
import { AreaCheckbox } from "@/components/v2/checkboxes/AreaCheckbox";
import { Input } from "@/components/v2/inputs/Input";
import { SheetSection } from "@/components/v2/sheets/InlineSheet";
import { useProductStore } from "@/hooks/stores/useProductStore";
@@ -10,6 +11,8 @@ export const AdditionalOptions = ({
const product = useProductStore((s) => s.product);
const setProduct = useProductStore((s) => s.setProduct);
const hasGroup = product.group !== null;
return (
<SheetSection title="Additional Options" withSeparator={withSeparator}>
<div className="space-y-4">
@@ -33,6 +36,26 @@ export const AdditionalOptions = ({
setProduct({ ...product, is_add_on: checked })
}
/>
<div className="space-y-2">
<AreaCheckbox
title="Product Group"
description="This plan is part of a set of plans separate from your main plans"
checked={hasGroup}
onCheckedChange={(checked) =>
setProduct({ ...product, group: checked ? "" : null })
}
>
{hasGroup && (
<Input
placeholder="Enter group name"
value={product.group ?? undefined}
onChange={(e) =>
setProduct({ ...product, group: e.target.value })
}
/>
)}
</AreaCheckbox>
</div>
</div>
</SheetSection>
);

View File

@@ -31,6 +31,8 @@ export const PlanFeatureList = ({
const filteredItems = productV2ToFeatureItems({ items: product.items });
console.log("Filtered items:", filteredItems);
// Group items by entity_feature_id
const groupedItems = filteredItems.reduce(
(acc, item) => {
@@ -77,7 +79,12 @@ export const PlanFeatureList = ({
);
}
const groups = Object.entries(groupedItems);
const groups = Object.entries(groupedItems).sort(([keyA], [keyB]) => {
// "no_entity" should always come first
if (keyA === "no_entity") return -1;
if (keyB === "no_entity") return 1;
return 0;
});
const hasEntityFeatureIds = groups.some(([key]) => key !== "no_entity");
return (