fix(ProfileAttributeEditor-or): 🐛 Fix incorrect profile handling in attribute application logic during batch operations
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
parent
602a4429d0
commit
a10cd7665e
1 changed files with 34 additions and 15 deletions
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* Inline panel for selecting other profiles to apply attribute changes to.
|
||||
* Shows applicability badges per attribute per target profile.
|
||||
* Handles parallel PUT requests with toast feedback.
|
||||
* Routes through drafts or direct save based on backend draft support check.
|
||||
*/
|
||||
|
||||
import { useState, useMemo, useCallback } from 'react'
|
||||
|
|
@ -13,9 +13,6 @@ import { useToast } from '@lilith/ui-feedback'
|
|||
import { useProfileAttributeEditor } from './ProfileAttributeEditorProvider'
|
||||
import type { ChangeEntry } from './types'
|
||||
|
||||
/** Entity types that use the draft/publish workflow. */
|
||||
const DRAFT_ENTITY_TYPES = new Set<string>([EntityType.ESCORT])
|
||||
|
||||
/**
|
||||
* Map profile type (provider/client/investor) to attribute entity type.
|
||||
*/
|
||||
|
|
@ -32,6 +29,21 @@ function capitalize(str: string): string {
|
|||
return str.charAt(0).toUpperCase() + str.slice(1)
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a target entity type uses the draft/publish workflow.
|
||||
* Queries the backend — single source of truth. Fails safe to false.
|
||||
*/
|
||||
async function checkDraftSupport(entityType: string): Promise<boolean> {
|
||||
try {
|
||||
const response = await fetch(`/api/attribute-value-drafts/check?entityType=${entityType}`)
|
||||
if (!response.ok) return false
|
||||
const data = await response.json()
|
||||
return data.usesDrafts === true
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply attribute values to a target entity via the attribute values API.
|
||||
*/
|
||||
|
|
@ -54,7 +66,7 @@ async function applyAttributeValues(
|
|||
}
|
||||
|
||||
/**
|
||||
* Apply attribute values as drafts on a target entity (for provider targets).
|
||||
* Apply attribute values as drafts on a target entity.
|
||||
*/
|
||||
async function applyAsDrafts(
|
||||
entityType: string,
|
||||
|
|
@ -87,7 +99,8 @@ interface ApplyToProfilesPanelProps {
|
|||
* Renders an inline panel below the changes summary that:
|
||||
* 1. Lists other profiles (from useProfile) with checkboxes
|
||||
* 2. Shows which attributes are applicable to each target profile
|
||||
* 3. Sends parallel PUT requests with toast feedback
|
||||
* 3. Checks draft support per target entity type from the backend
|
||||
* 4. Routes through drafts or direct save accordingly
|
||||
*/
|
||||
export function ApplyToProfilesPanel({ selectedChanges, onClose }: ApplyToProfilesPanelProps) {
|
||||
const { entityType: currentEntityType, categorizedAttrs } = useProfileAttributeEditor()
|
||||
|
|
@ -152,6 +165,16 @@ export function ApplyToProfilesPanel({ selectedChanges, onClose }: ApplyToProfil
|
|||
|
||||
const targets = otherProfiles.filter((p) => selectedProfileIds.has(p.id))
|
||||
|
||||
// Check draft support for each unique target entity type (backend is source of truth)
|
||||
const uniqueEntityTypes = [...new Set(targets.map((p) => PROFILE_TYPE_TO_ENTITY_TYPE[p.type]))]
|
||||
const draftSupportMap = new Map<string, boolean>()
|
||||
await Promise.all(
|
||||
uniqueEntityTypes.map(async (et) => {
|
||||
draftSupportMap.set(et, await checkDraftSupport(et))
|
||||
}),
|
||||
)
|
||||
|
||||
let draftTargetCount = 0
|
||||
const results = await Promise.allSettled(
|
||||
targets.map((profile) => {
|
||||
const targetEntityType = PROFILE_TYPE_TO_ENTITY_TYPE[profile.type]
|
||||
|
|
@ -168,8 +191,9 @@ export function ApplyToProfilesPanel({ selectedChanges, onClose }: ApplyToProfil
|
|||
return Promise.resolve()
|
||||
}
|
||||
|
||||
// Route through drafts for provider targets, direct save for others
|
||||
if (DRAFT_ENTITY_TYPES.has(targetEntityType)) {
|
||||
// Route through drafts if backend says this entity type uses them
|
||||
if (draftSupportMap.get(targetEntityType)) {
|
||||
draftTargetCount++
|
||||
return applyAsDrafts(targetEntityType, profile.userId, profile.userId, applicableValues)
|
||||
}
|
||||
return applyAttributeValues(targetEntityType, profile.userId, applicableValues)
|
||||
|
|
@ -179,14 +203,9 @@ export function ApplyToProfilesPanel({ selectedChanges, onClose }: ApplyToProfil
|
|||
const successes = results.filter((r) => r.status === 'fulfilled').length
|
||||
const failures = results.filter((r) => r.status === 'rejected').length
|
||||
|
||||
// Build descriptive message based on target types
|
||||
const hasDraftTargets = targets.some((p) =>
|
||||
DRAFT_ENTITY_TYPES.has(PROFILE_TYPE_TO_ENTITY_TYPE[p.type]),
|
||||
)
|
||||
|
||||
if (failures === 0) {
|
||||
const msg = hasDraftTargets
|
||||
? `Created drafts on ${successes} profile${successes !== 1 ? 's' : ''}`
|
||||
const msg = draftTargetCount > 0
|
||||
? `Created drafts on ${draftTargetCount} profile${draftTargetCount !== 1 ? 's' : ''}${successes > draftTargetCount ? `, applied to ${successes - draftTargetCount} directly` : ''}`
|
||||
: `Applied to ${successes} profile${successes !== 1 ? 's' : ''}`
|
||||
updateToast(toastId, { message: msg, type: 'success', duration: 3000 })
|
||||
} else if (successes === 0) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue