144 lines
4.1 KiB
TypeScript
144 lines
4.1 KiB
TypeScript
import { createOperationKey } from './operation-key.ts';
|
|
export const swotDimensions = {
|
|
strength: 'Forças — internas ao objecto',
|
|
weakness: 'Fraquezas — internas ao objecto',
|
|
opportunity: 'Oportunidades — externas ao objecto',
|
|
threat: 'Ameaças — externas ao objecto',
|
|
} as const;
|
|
export type SwotRow = {
|
|
id: string;
|
|
dimension: keyof typeof swotDimensions;
|
|
text: string;
|
|
reference: string;
|
|
source_key: string | null;
|
|
date: string | null;
|
|
classification: 'documented_fact' | 'hypothesis' | 'unconfirmed';
|
|
};
|
|
export type SwotDraft = {
|
|
sources_snapshot?: unknown;
|
|
snapshot_fingerprint?: string;
|
|
object_key: string;
|
|
scope: string | null;
|
|
rows: SwotRow[];
|
|
source_fingerprint: string;
|
|
review?: { reason: string; at: string } | null;
|
|
actions: {
|
|
id: string;
|
|
title: string;
|
|
kind: string;
|
|
href: string;
|
|
review_version: number;
|
|
}[];
|
|
};
|
|
export type Workspace = {
|
|
historical?: boolean;
|
|
initial_scope?: boolean;
|
|
saved_scopes?: { key: string; label: string; href: string }[];
|
|
case: { id: string; title: string; closed: boolean };
|
|
opportunity: string | null;
|
|
opportunity_label?: string | null;
|
|
version: number;
|
|
apiex: {
|
|
note: string | null;
|
|
additional_documents: string[];
|
|
review: { reason: string; at: string; fingerprint: string } | null;
|
|
exports: { id: string; at: string; context_revision: number }[];
|
|
external: {
|
|
id: string;
|
|
kind: string;
|
|
date: string;
|
|
reference: string;
|
|
proof_document: string;
|
|
related_id?: string;
|
|
export_id: string;
|
|
outcome?: string;
|
|
}[];
|
|
};
|
|
swot: SwotDraft;
|
|
api_state: string;
|
|
api_issues: string[];
|
|
api_fingerprint: string;
|
|
swot_fingerprint: string;
|
|
swot_review_required: boolean;
|
|
can_write: boolean;
|
|
can_review: boolean;
|
|
links: Record<string, string>;
|
|
objects: { key: string; label: string; kind: string }[];
|
|
sources: {
|
|
key: string;
|
|
label: string;
|
|
consulted?: unknown;
|
|
current?: unknown;
|
|
notice?: string;
|
|
}[];
|
|
reused?: Record<string, unknown>;
|
|
context: { revision: number; fields: Record<string, unknown> };
|
|
assessment: {
|
|
requirements: {
|
|
key: string;
|
|
label: string;
|
|
state: string;
|
|
required: boolean;
|
|
available: boolean;
|
|
reason: string;
|
|
document_id: string | null;
|
|
source: { reference: string; url: string };
|
|
}[];
|
|
};
|
|
documents: {
|
|
id: string;
|
|
document_id: string;
|
|
file_name: string;
|
|
available: boolean;
|
|
version_no: number;
|
|
}[];
|
|
history_next?: number | null;
|
|
history: {
|
|
version: number;
|
|
action: string;
|
|
at: string;
|
|
actor: number;
|
|
operation_key?: string;
|
|
}[];
|
|
};
|
|
/** A lost response retains the exact intent; editing fields never mutates a retry. */
|
|
export class PreparationAttempt {
|
|
private value: Record<string, unknown> | null = null;
|
|
start(
|
|
version: number,
|
|
opportunity: string | null,
|
|
action: string,
|
|
data: Record<string, unknown>,
|
|
reason: string,
|
|
) {
|
|
if (this.value)
|
|
throw Error('Resolva a tentativa anterior antes de iniciar outra.');
|
|
this.value = JSON.parse(
|
|
JSON.stringify({
|
|
...data,
|
|
version,
|
|
opportunity,
|
|
action,
|
|
reason,
|
|
operation_key: createOperationKey(),
|
|
}),
|
|
) as Record<string, unknown>;
|
|
return this.current()!;
|
|
}
|
|
current() {
|
|
return this.value ? structuredClone(this.value) : null;
|
|
}
|
|
complete() {
|
|
this.value = null;
|
|
}
|
|
canAdopt(view: Pick<Workspace, 'version' | 'history'>) {
|
|
return (
|
|
!this.value ||
|
|
view.version > Number(this.value.version) ||
|
|
view.history.some(
|
|
(h) => h.operation_key === this.value?.operation_key,
|
|
)
|
|
);
|
|
}
|
|
}
|