Fix identity trait add and persistence bugs

Remove Key from UpsertTraitRequest body (comes from URL route). Emit 'updated' event from IdentityDetail on trait mutations and sync parent. Reload segment data on tab activation and dialog open.
This commit is contained in:
2026-06-17 12:45:45 -07:00
parent 5506151f19
commit 5dcd39f564
3 changed files with 22 additions and 1 deletions

View File

@@ -320,6 +320,7 @@ const props = defineProps<Props>();
const emit = defineEmits<{ const emit = defineEmits<{
'update:modelValue': [value: boolean]; 'update:modelValue': [value: boolean];
deleted: [identityId: number]; deleted: [identityId: number];
updated: [identity: IdentityResponse];
}>(); }>();
const contextStore = useContextStore(); const contextStore = useContextStore();
@@ -420,6 +421,10 @@ watch(
{ immediate: true }, { immediate: true },
); );
watch(activeTab, (tab) => {
if (tab === 'segments') loadSegmentsData();
});
async function onToggleOverride(override: FeatureStateResponse, enabled: boolean | null): Promise<void> { async function onToggleOverride(override: FeatureStateResponse, enabled: boolean | null): Promise<void> {
if (enabled === null || !props.identity) return; if (enabled === null || !props.identity) return;
const envApiKey = contextStore.currentEnvironment?.apiKey; const envApiKey = contextStore.currentEnvironment?.apiKey;
@@ -489,6 +494,12 @@ async function onAddOverride(): Promise<void> {
} }
} }
function emitTraitsUpdated(): void {
if (props.identity) {
emit('updated', { ...props.identity, traits: [...editedTraits.value] });
}
}
async function onSaveTrait(key: string, value: string): Promise<void> { async function onSaveTrait(key: string, value: string): Promise<void> {
if (!props.identity) return; if (!props.identity) return;
const envApiKey = contextStore.currentEnvironment?.apiKey; const envApiKey = contextStore.currentEnvironment?.apiKey;
@@ -499,6 +510,7 @@ async function onSaveTrait(key: string, value: string): Promise<void> {
await upsertIdentityTrait(envApiKey, props.identity.id, key, { value }); await upsertIdentityTrait(envApiKey, props.identity.id, key, { value });
const idx = editedTraits.value.findIndex((t: TraitResponse) => t.key === key); const idx = editedTraits.value.findIndex((t: TraitResponse) => t.key === key);
if (idx >= 0) editedTraits.value[idx] = { key, value }; if (idx >= 0) editedTraits.value[idx] = { key, value };
emitTraitsUpdated();
} catch { } catch {
traitsError.value = 'Failed to save trait. Please try again.'; traitsError.value = 'Failed to save trait. Please try again.';
} finally { } finally {
@@ -515,6 +527,7 @@ async function onDeleteTrait(key: string): Promise<void> {
try { try {
await deleteIdentityTrait(envApiKey, props.identity.id, key); await deleteIdentityTrait(envApiKey, props.identity.id, key);
editedTraits.value = editedTraits.value.filter((t: TraitResponse) => t.key !== key); editedTraits.value = editedTraits.value.filter((t: TraitResponse) => t.key !== key);
emitTraitsUpdated();
} catch { } catch {
traitsError.value = 'Failed to delete trait. Please try again.'; traitsError.value = 'Failed to delete trait. Please try again.';
} finally { } finally {
@@ -540,6 +553,7 @@ async function onAddTrait(): Promise<void> {
} }
newTraitKey.value = ''; newTraitKey.value = '';
newTraitValue.value = ''; newTraitValue.value = '';
emitTraitsUpdated();
} catch { } catch {
traitsError.value = 'Failed to add trait. Please try again.'; traitsError.value = 'Failed to add trait. Please try again.';
} finally { } finally {

View File

@@ -91,6 +91,7 @@
v-model="showDetail" v-model="showDetail"
:identity="selectedIdentity" :identity="selectedIdentity"
@deleted="onIdentityDeleted" @deleted="onIdentityDeleted"
@updated="onIdentityUpdated"
/> />
<!-- Create identity dialog --> <!-- Create identity dialog -->
@@ -246,6 +247,12 @@ function onCreateDialogClosed(): void {
createError.value = null; createError.value = null;
} }
function onIdentityUpdated(updated: IdentityResponse): void {
const idx = identities.value.findIndex((i) => i.id === updated.id);
if (idx >= 0) identities.value[idx] = updated;
selectedIdentity.value = updated;
}
function onIdentityDeleted(identityId: number): void { function onIdentityDeleted(identityId: number): void {
identities.value = identities.value.filter((i) => i.id !== identityId); identities.value = identities.value.filter((i) => i.id !== identityId);
showDetail.value = false; showDetail.value = false;

View File

@@ -1,3 +1,3 @@
namespace MicCheck.Api.Identities; namespace MicCheck.Api.Identities;
public record UpsertTraitRequest(string Key, string Value); public record UpsertTraitRequest(string Value);