fix(address): show saved address in record detail when street1 is null (#21033)
## Fixes #20084 ### Problem A saved address is visible in the **table view** but shows **"Empty"** in the **record detail page** when `addressStreet1` is `null`. This reproduces with the default seed data out of the box — e.g. **Google** (city "Mountain View", no street), **Microsoft** (Redmond), **Meta** (Menlo Park) — which is why several users reported hitting it immediately. ### Root cause The frontend zod schema required `addressStreet1` to be a **non-null** string: ```ts // isFieldAddressValue.ts export const addressSchema = z.object({ addressStreet1: z.string(), // ← required non-null addressStreet2: z.string().nullable(), ... }); ``` …but the backend composite type marks it `isRequired: false` (`address.composite-type.ts`), and the DB column is nullable. So the API legitimately returns `addressStreet1: null` when only other subfields are filled. The two views diverge on how they render: - **Record detail** gates the value behind `useIsFieldEmpty()` → `isFieldValueEmpty()`, which for addresses calls `isFieldAddressValue()`. With `addressStreet1: null` the `safeParse` **fails**, so `isFieldValueEmpty` returns `true` and the `"Empty"` placeholder is shown (`RecordInlineCellDisplayMode`). - **Table view** (`RecordTableCellDisplayMode`) renders `AddressFieldDisplay` directly with **no** empty check, so the address stays visible. This was a latent mismatch since the address guard was introduced. ### Fix Make `addressStreet1` nullable to match the backend and the other subfields: - `addressSchema` → `addressStreet1: z.string().nullable()` - `FieldAddressValue.addressStreet1` → `string | null` - `FieldAddressDraftValue.addressStreet1` → `string | null` (keeps the input/draft type consistent; the text input already renders `?? ''`) The change is strictly more permissive — persisting and the settings default-value form still accept string values; they now also accept `null`. ### Tests - `isFieldAddressValue.test.ts` — guard returns `true` for `addressStreet1: null` with other subfields filled. - `isFieldValueEmpty.test.ts` — new address coverage: empty address is empty; **`street1: null` + city filled is NOT empty**; normal address is not empty. (Added an `addressFieldDefinition` mock.) Both new assertions were confirmed to **fail before the fix** and pass after. ### Verification - `npx jest isFieldValueEmpty isFieldAddressValue normalize-address-field-value-for-persist` → 17 passed - `npx nx typecheck twenty-front` → pass - `npx nx lint:diff-with-main twenty-front` → 0 warnings, 0 errors
This commit is contained in:
+4
-6
@@ -1,10 +1,8 @@
|
||||
import { Separator } from '@/settings/components/Separator';
|
||||
import { Controller, useFormContext } from 'react-hook-form';
|
||||
|
||||
import {
|
||||
addressSchema as addressFieldDefaultValueSchema,
|
||||
addressSettingsSchema,
|
||||
} from '@/object-record/record-field/ui/types/guards/isFieldAddressValue';
|
||||
import { addressFieldSettingsSchema } from '@/object-record/record-field/ui/validation-schemas/addressFieldSettingsSchema';
|
||||
import { addressFieldValueSchema } from '@/object-record/record-field/ui/validation-schemas/addressFieldValueSchema';
|
||||
import { SettingsOptionCardContentSelect } from '@/settings/components/SettingsOptions/SettingsOptionCardContentSelect';
|
||||
import { MultiSelectAddressFields } from '@/settings/data-model/fields/forms/address/components/MultiSelectAddressFields';
|
||||
import { DEFAULT_SELECTION_ADDRESS_WITH_MESSAGES } from '@/settings/data-model/fields/forms/address/constants/DefaultSelectionAddressWithMessages';
|
||||
@@ -33,8 +31,8 @@ type SettingsDataModelFieldAddressFormProps = {
|
||||
};
|
||||
|
||||
export const settingsDataModelFieldAddressFormSchema = z.object({
|
||||
defaultValue: addressFieldDefaultValueSchema,
|
||||
settings: addressSettingsSchema,
|
||||
defaultValue: addressFieldValueSchema,
|
||||
settings: addressFieldSettingsSchema,
|
||||
});
|
||||
|
||||
export type SettingsDataModelFieldTextFormValues = z.infer<
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
import { Controller, useFormContext } from 'react-hook-form';
|
||||
|
||||
import { useFieldMetadataItemById } from '@/object-metadata/hooks/useFieldMetadataItemById';
|
||||
import { phonesSchema as phonesFieldDefaultValueSchema } from '@/object-record/record-field/ui/types/guards/isFieldPhonesValue';
|
||||
import { phonesFieldValueSchema } from '@/object-record/record-field/ui/validation-schemas/phonesFieldValueSchema';
|
||||
import { SettingsOptionCardContentSelect } from '@/settings/components/SettingsOptions/SettingsOptionCardContentSelect';
|
||||
import { mergeSettingsSchemas } from '@/settings/data-model/fields/forms/utils/mergeSettingsSchema';
|
||||
import { settingsDataModelFieldMaxValuesSchema } from '@/settings/data-model/fields/forms/utils/settingsDataModelFieldMaxValuesSchema';
|
||||
@@ -28,7 +28,7 @@ type SettingsDataModelFieldPhonesFormProps = {
|
||||
|
||||
export const settingsDataModelFieldPhonesFormSchema = z
|
||||
.object({
|
||||
defaultValue: phonesFieldDefaultValueSchema,
|
||||
defaultValue: phonesFieldValueSchema,
|
||||
})
|
||||
.merge(
|
||||
mergeSettingsSchemas(
|
||||
|
||||
Reference in New Issue
Block a user