import { makeObservable, action, observable, autorun } from 'mobx'; import * as React from 'react'; import { Docs } from '../../../documents/Documents'; import { DocumentType } from '../../../documents/DocumentTypes'; import { ViewBoxAnnotatableComponent } from '../../DocComponent'; import { FieldView, FieldViewProps } from '../FieldView'; import { FormattedTextBox, FormattedTextBoxProps } from './FormattedTextBox'; import { gptAPICall, GPTCallType, gptImageLabel } from '../../../apis/gpt/GPT'; import { RichTextField } from '../../../../fields/RichTextField'; import { TextSelection } from 'prosemirror-state'; export class DailyJournal extends ViewBoxAnnotatableComponent() { @observable journalDate: string; public static LayoutString(fieldStr: string) { return FieldView.LayoutString(DailyJournal, fieldStr); } constructor(props: FormattedTextBoxProps) { super(props); makeObservable(this); this.journalDate = this.getFormattedDate(); } getFormattedDate(): string { const date = new Date().toLocaleDateString(undefined, { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric', }); console.log('getFormattedDate():', date); return date; } @action setDailyTitle() { console.log('setDailyTitle() called...'); console.log('Current title before update:', this.dataDoc.title); if (!this.dataDoc.title || this.dataDoc.title !== this.journalDate) { console.log('Updating title to:', this.journalDate); this.dataDoc.title = this.journalDate; } console.log('New title after update:', this.dataDoc.title); } @action setDailyText() { const placeholderText = 'Start writing here...'; const dateText = `${this.journalDate}\n`; console.log('Checking if dataDoc has text field...'); this.dataDoc[this.fieldKey] = RichTextField.textToRtfFormat( [ { text: 'Journal Entry:', styles: { bold: true, color: 'black', fontSize: 20 } }, { text: dateText, styles: { italic: true, color: 'gray', fontSize: 15 } }, { text: placeholderText, styles: { fontSize: 14, color: 'gray' } }, ], undefined, placeholderText.length ); console.log('Current text field:', this.dataDoc[this.fieldKey]); } componentDidMount(): void { console.log('componentDidMount() triggered...'); console.log("Text: " + (this.Document.text as any)?.Text); const rawText = (this.Document.text as any)?.Text ?? ''; const isTextEmpty = !rawText || rawText === ""; const currentTitle = this.dataDoc.title || ""; const isTitleString = typeof currentTitle === 'string'; const isDefaultTitle = isTitleString && currentTitle.includes("Untitled DailyJournal"); if (isTextEmpty && isDefaultTitle) { console.log('Journal title and text are default. Initializing...'); this.setDailyTitle(); this.setDailyText(); } else { console.log('Journal already has content. Skipping initialization.'); } } @action handleGeneratePrompts = async () => { const rawText = (this.Document.text as any)?.Text ?? ''; console.log('Extracted Journal Text:', rawText); console.log('Before Update:', this.Document.text, 'Type:', typeof this.Document.text); if (!rawText.trim()) { alert('Journal is empty! Write something first.'); return; } try { // Call GPT API to generate prompts const res = await gptAPICall('Generate 1-2 short journal prompts for the following journal entry: ' + rawText, GPTCallType.COMPLETION); if (!res) { console.error('GPT call failed.'); return; } const editorView = this._ref.current?.EditorView; if (!editorView) { console.error('EditorView is not available.'); return; } else { const { state, dispatch } = editorView; const { schema } = state; // Use available marks const boldMark = schema.marks.strong.create(); const italicMark = schema.marks.em.create(); const fontSizeMark = schema.marks.pFontSize.create({ fontSize: "14px" }); const fontColorMark = schema.marks.pFontColor.create({ fontColor: "gray" }); // Create text nodes with formatting const headerText = schema.text('\n\n# Suggested Prompts:\n', [boldMark, italicMark, fontSizeMark, fontColorMark]); const responseText = schema.text(res, [fontSizeMark, fontColorMark]); // Insert formatted text const transaction = state.tr.insert( state.selection.from, headerText).insert( state.selection.from + headerText.nodeSize, responseText); dispatch(transaction); } } catch (err) { console.error('Error calling GPT:', err); } }; _ref = React.createRef(); render() { return (
{/* GPT Button */}
); } } Docs.Prototypes.TemplateMap.set(DocumentType.JOURNAL, { layout: { view: DailyJournal, dataField: 'text' }, options: { acl: '', _height: 35, _xMargin: 10, _yMargin: 10, _layout_autoHeight: true, _layout_nativeDimEditable: true, _layout_reflowVertical: true, _layout_reflowHorizontal: true, defaultDoubleClick: 'ignore', systemIcon: 'BsFileEarmarkTextFill', }, });