export type FillGroup = { id: string; title: string; hint: string; fields: string[]; }; const definitions: Omit[] = [ { id: 'idea', title: 'Ideia e actividade', hint: 'Identifique o investimento e descreva a necessidade que pretende responder.', }, { id: 'people', title: 'Promotor e contactos', hint: 'Reutilize os contactos guardados e escolha o que pode ser divulgado.', }, { id: 'territory', title: 'Localização e enquadramento', hint: 'Indique o território conhecido e as associações documentadas que se aplicam.', }, { id: 'operation', title: 'Actividade e impacto', hint: 'Complete os produtos, recursos, mercados e impactos relevantes para esta oportunidade.', }, { id: 'finance', title: 'Investimento e financiamento', hint: 'Preencha os valores conhecidos. O rascunho pode continuar incompleto.', }, { id: 'evidence', title: 'Documentos e imagens', hint: 'Reutilize os recursos guardados na mesma oportunidade.', }, { id: 'specific', title: 'Dados específicos', hint: 'Preencha os detalhes aplicáveis à modalidade escolhida.', }, { id: 'review', title: 'Revisão e divulgação', hint: 'Reveja riscos, condições e visibilidade antes das acções autorizadas de submissão.', }, ]; const fields: Record = { idea: [ 'official_title', 'sector_id', 'subsector_id', 'economic_activity_id', 'executive_summary', 'demand_statement', 'opportunity_type', 'maturity_stage', 'enterprise_size', ], people: [ 'promoter_type', 'internal_contact_id', 'publish_contact', 'public_contact_id', ], territory: [ 'location_mode', 'geographic_scope', 'multi_district_rationale', 'locations', 'relations', ], operation: [ 'investment_modalities', 'investor_profiles', 'products', 'assets', 'inputs', 'markets', 'competitive_advantage', 'employment', 'impact_indicators', ], finance: [ 'total_investment', 'currency', 'investment_breakdown', 'secured_financing', 'funding_sought', 'financial_indicators', ], evidence: ['documents', 'evidences', 'images'], review: [ 'publication_languages', 'visibility', 'review_due_date', 'truth_declaration', 'milestones', 'licenses', 'environmental_social', 'risks', ], }; /** Presentation groups only: retain every applicable field exactly once, including future schema keys. */ export function opportunityFillGroups(available: string[]): FillGroup[] { const unique = [...new Set(available)]; return definitions .map((group) => ({ ...group, fields: unique.filter((field) => { const owner = Object.keys(fields).find((key) => fields[key].includes(field), ) ?? 'specific'; return owner === group.id; }), })) .filter((group) => group.fields.length > 0); } export function opportunityErrorGroup( groups: FillGroup[], errors: Record, ): string | undefined { return groups.find((group) => group.fields.some((field) => Object.keys(errors).some( (path) => path === `canonical.${field}` || path.startsWith(`canonical.${field}.`), ), ), )?.id; } export function opportunityMissingGroups( groups: FillGroup[], paths: string[], ): FillGroup[] { return groups.filter((group) => group.fields.some((field) => paths.some((path) => { const normalized = path.replace(/^canonical\./, ''); return ( normalized === field || normalized.startsWith(`${field}.`) ); }), ), ); }