diff --git a/components/tiptap-editor.tsx b/components/tiptap-editor.tsx
index ef2441f..cbb54ab 100644
--- a/components/tiptap-editor.tsx
+++ b/components/tiptap-editor.tsx
@@ -14,14 +14,21 @@ import {
TooltipProvider,
TooltipTrigger,
} from '@/components/ui/tooltip'
+import { cn } from "@/lib/utils"
interface TipTapEditorProps {
content: string
onChange: (content: string) => void
className?: string
+ minimal?: boolean
}
-export function TipTapEditor({ content, onChange, className = '' }: TipTapEditorProps) {
+const getEditorClassNames = (minimal: boolean) => cn(
+ 'prose prose-sm dark:prose-invert focus:outline-none max-w-none',
+ minimal ? 'p-2' : 'p-4 min-h-[200px]'
+);
+
+export function TipTapEditor({ content, onChange, className = '', minimal = false }: TipTapEditorProps) {
const [isFocused, setIsFocused] = React.useState(false);
const [isRawMode, setIsRawMode] = React.useState(false);
const [rawMarkdown, setRawMarkdown] = React.useState(content || '');
@@ -53,7 +60,7 @@ export function TipTapEditor({ content, onChange, className = '' }: TipTapEditor
},
editorProps: {
attributes: {
- class: 'prose prose-sm dark:prose-invert focus:outline-none max-w-none p-4 min-h-[200px]'
+ class: getEditorClassNames(minimal)
}
},
onFocus: () => setIsFocused(true),
@@ -173,35 +180,42 @@ export function TipTapEditor({ content, onChange, className = '' }: TipTapEditor
];
return (
-
-
-
- {tools
- .filter(tool => isRawMode ? tool.showInRawMode : true)
- .map((Tool) => (
-
-
-
-
- {Tool.title}
-
- ))}
-
-
+
+ {!minimal && (
+
+
+ {tools
+ .filter(tool => isRawMode ? tool.showInRawMode : true)
+ .map((Tool) => (
+
+
+
+
+ {Tool.title}
+
+ ))}
+
+
+ )}
{isRawMode ? (
) : (
diff --git a/components/workflow/WorkflowAccordion.tsx b/components/workflow/WorkflowAccordion.tsx
index 629d971..7b8d2a1 100644
--- a/components/workflow/WorkflowAccordion.tsx
+++ b/components/workflow/WorkflowAccordion.tsx
@@ -90,6 +90,7 @@ export default function WorkflowAccordion({
removeStakeholder,
updateStakeholders,
publishDecision,
+ updateDecisionNotes,
} = useDecision(decisionId, organisationId)
const {
@@ -457,25 +458,42 @@ export default function WorkflowAccordion({
if (step.key === 'choose' && decision) {
return (
+
+
Notes
+ updateDecisionNotes(content)}
+ />
+
+
-
-
Decision
- updateDecisionContent(content)}
- />
-
-
-
+
+
+
+
Decision
+
+ - state your decision concisely in 1-2 sentences
+
+
+
+ updateDecisionContent(content)}
+ className="prose-sm min-h-[4rem] max-h-[8rem] overflow-y-auto"
+ minimal
+ />
+
+
)
}
diff --git a/hooks/useDecisions.ts b/hooks/useDecisions.ts
index 3b5ce70..fb91393 100644
--- a/hooks/useDecisions.ts
+++ b/hooks/useDecisions.ts
@@ -225,6 +225,23 @@ export function useDecision(decisionId: string, organisationId: string) {
}
};
+ /**
+ * Updates the notes associated with a decision
+ * @param decisionNotes - The new notes content in HTML format
+ * @throws {Error} If the update fails or if no decision is loaded
+ */
+ const updateDecisionNotes = async (decisionNotes: string) => {
+ try {
+ if (!decision) return;
+ await decisionsRepository.update(
+ decision.with({ decisionNotes }),
+ );
+ } catch (error) {
+ setError(error as Error);
+ throw error;
+ }
+ };
+
return {
decision,
loading,
@@ -243,5 +260,6 @@ export function useDecision(decisionId: string, organisationId: string) {
addSupportingMaterial,
removeSupportingMaterial,
publishDecision,
+ updateDecisionNotes,
};
}
diff --git a/lib/domain/Decision.ts b/lib/domain/Decision.ts
index 5f85324..64398ef 100644
--- a/lib/domain/Decision.ts
+++ b/lib/domain/Decision.ts
@@ -115,6 +115,7 @@ export type DecisionProps = {
teamIds: string[];
projectIds: string[];
relationships?: DecisionRelationshipMap;
+ decisionNotes?: string;
};
export class Decision {
@@ -175,6 +176,10 @@ export class Decision {
@IsOptional()
readonly relationships?: DecisionRelationshipMap;
+ @IsOptional()
+ @IsString()
+ readonly decisionNotes?: string;
+
toDocumentReference(): DocumentReference {
return {
id: this.id,
@@ -368,6 +373,7 @@ export class Decision {
this.teamIds = props.teamIds || [];
this.projectIds = props.projectIds || [];
this.relationships = props.relationships;
+ this.decisionNotes = props.decisionNotes;
this.validate();
}
diff --git a/lib/infrastructure/firestoreDecisionsRepository.ts b/lib/infrastructure/firestoreDecisionsRepository.ts
index f2f4494..478228b 100644
--- a/lib/infrastructure/firestoreDecisionsRepository.ts
+++ b/lib/infrastructure/firestoreDecisionsRepository.ts
@@ -55,6 +55,7 @@ export class FirestoreDecisionsRepository implements DecisionsRepository {
teamIds: data.teamIds || [],
projectIds: data.projectIds || [],
relationships: data.relationships || {},
+ decisionNotes: data.decisionNotes || '',
};
return Decision.create(props);
}
@@ -94,10 +95,10 @@ export class FirestoreDecisionsRepository implements DecisionsRepository {
return this.decisionFromFirestore(docSnap)
}
- async create(initialData: Partial>, scope: DecisionScope): Promise {
+ async create(scope: DecisionScope, initialData: Partial = {}): Promise {
const docRef = doc(collection(db, this.getDecisionPath(scope)))
- const createData: Record | DecisionStakeholderRole[] | SupportingMaterial[]> = {
+ const data: Record | DecisionStakeholderRole[] | SupportingMaterial[]> = {
title: initialData.title ?? '',
description: initialData.description ?? '',
cost: initialData.cost ?? 'low',
@@ -110,16 +111,17 @@ export class FirestoreDecisionsRepository implements DecisionsRepository {
organisationId: scope.organisationId,
teamIds: initialData.teamIds ?? [],
projectIds: initialData.projectIds ?? [],
+ decisionNotes: initialData.decisionNotes ?? '',
createdAt: serverTimestamp(),
updatedAt: serverTimestamp(),
}
// Filter out any undefined values
- const filteredCreateData = Object.fromEntries(
- Object.entries(createData).filter(([, value]) => value !== undefined)
+ const filteredData = Object.fromEntries(
+ Object.entries(data).filter(([, value]) => value !== undefined)
);
- await setDoc(docRef, filteredCreateData)
+ await setDoc(docRef, filteredData)
return this.getById(docRef.id, scope)
}
@@ -131,7 +133,7 @@ export class FirestoreDecisionsRepository implements DecisionsRepository {
const docRef = doc(db, this.getDecisionPath(scope), decision.id)
- const updateData: Record | undefined> = {
+ const data: Record | undefined> = {
title: decision.title,
description: decision.description,
cost: decision.cost,
@@ -145,15 +147,16 @@ export class FirestoreDecisionsRepository implements DecisionsRepository {
teamIds: decision.teamIds,
projectIds: decision.projectIds,
publishDate: decision.publishDate,
+ decisionNotes: decision.decisionNotes,
updatedAt: serverTimestamp()
}
// Filter out any undefined values
- const filteredUpdateData = Object.fromEntries(
- Object.entries(updateData).filter(([, value]) => value !== undefined)
+ const filteredData = Object.fromEntries(
+ Object.entries(data).filter(([, value]) => value !== undefined)
);
- await updateDoc(docRef, filteredUpdateData)
+ await updateDoc(docRef, filteredData)
}
async delete(id: string, scope: DecisionScope): Promise {