Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -152,22 +152,47 @@ const PartnerOnboardingWizard: React.FC = () => {
query: { meta: { integrationId } },
});

const templates: CredentialTemplate[] = boostsResult?.records?.map((boost: any) => {
const meta = boost.boost?.meta as any;
const credential = boost.boost?.credential;
// Helper to convert a boost record to a CredentialTemplate
// API returns: { uri, name, type, category, meta, status, ... } (credential is NOT included)
const boostToTemplate = (boost: any): CredentialTemplate => {
const meta = boost.meta as any;

return {
id: boost.uri || boost.boost?.id || crypto.randomUUID(),
name: boost.boost?.name || credential?.name || 'Untitled Template',
description: credential?.credentialSubject?.achievement?.description || '',
achievementType: meta?.templateConfig?.achievementType || boost.boost?.type || 'Achievement',
id: boost.uri || crypto.randomUUID(),
name: boost.name || 'Untitled Template',
description: boost.description || '',
achievementType: meta?.templateConfig?.achievementType || boost.type || 'Achievement',
fields: meta?.templateConfig?.fields || [],
imageUrl: boost.boost?.image || credential?.credentialSubject?.achievement?.image?.id,
imageUrl: boost.image,
boostUri: boost.uri,
isNew: false,
isDirty: false,
isMasterTemplate: meta?.isMasterTemplate,
};
}) || [];
};

// First pass: convert all boosts to templates
const allTemplates: CredentialTemplate[] = boostsResult?.records?.map(boostToTemplate) || [];

// Second pass: load children for master templates and reconstruct hierarchy
const templates = await Promise.all(
allTemplates.map(async (template) => {
if (template.isMasterTemplate && template.boostUri) {
try {
const childBoosts = await wallet.invoke.getChildrenBoosts(template.boostUri);
if (childBoosts?.length) {
template.childTemplates = childBoosts.map((child: any) => ({
...boostToTemplate(child),
parentTemplateId: template.id,
}));
}
} catch (err) {
console.warn('Failed to load children for template:', template.boostUri, err);
}
}
return template;
})
);

// Load profile for branding
let branding: BrandingConfig | null = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -531,17 +531,24 @@ export const TemplateBuilderStep: React.FC<TemplateBuilderStepProps> = ({

// PARALLEL: Save all master templates (each saves its children in parallel internally)
// and all standalone templates at the same time
// Track original indices for reliable reconstruction after parallel saves
const masterIndices = masterTemplates.map(t => localTemplates.indexOf(t));
const standaloneIndices = standaloneTemplates.map(t => localTemplates.indexOf(t));

const [savedMasters, savedStandalones] = await Promise.all([
Promise.all(masterTemplates.map(saveMasterWithChildren)),
Promise.all(standaloneTemplates.map(saveStandalone)),
]);

// Reconstruct the saved templates in original order
const savedTemplates = localTemplates.map(template => {
if (template.isMasterTemplate && template.childTemplates?.length) {
return savedMasters.find(m => m.id === template.id || m.boostUri === template.boostUri) || template;
}
return savedStandalones.find(s => s.id === template.id || s.boostUri === template.boostUri) || template;
// Reconstruct the saved templates in original order using indices
const savedTemplates = [...localTemplates] as ExtendedTemplate[];

masterIndices.forEach((originalIdx, i) => {
savedTemplates[originalIdx] = savedMasters[i]!;
});

standaloneIndices.forEach((originalIdx, i) => {
savedTemplates[originalIdx] = savedStandalones[i]!;
});

setLocalTemplates(savedTemplates as ExtendedTemplate[]);
Expand Down
Loading
Loading