aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/client/views/nodes/TaskBox.scss8
-rw-r--r--src/client/views/nodes/TaskBox.tsx55
2 files changed, 62 insertions, 1 deletions
diff --git a/src/client/views/nodes/TaskBox.scss b/src/client/views/nodes/TaskBox.scss
index cc04f7973..071fe1f7c 100644
--- a/src/client/views/nodes/TaskBox.scss
+++ b/src/client/views/nodes/TaskBox.scss
@@ -92,10 +92,16 @@ input[type='datetime-local'] {
white-space: nowrap;
transition: background-color 0.2s ease;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
-
+
&:hover {
background-color: #4773b0; // darker shade of your base blue
color: white;
transform: scale(1.01); // subtle hover feel without real size change
}
+
+ &:disabled {
+ opacity: 0.5;
+ cursor: not-allowed;
+ pointer-events: none;
+ }
}
diff --git a/src/client/views/nodes/TaskBox.tsx b/src/client/views/nodes/TaskBox.tsx
index 7df3876c3..82c22057e 100644
--- a/src/client/views/nodes/TaskBox.tsx
+++ b/src/client/views/nodes/TaskBox.tsx
@@ -23,6 +23,23 @@ interface TaskBoxProps {
*/
@observer
export class TaskBox extends React.Component<TaskBoxProps> {
+ // contains the last synced task information
+ lastSyncedTask: {
+ title: string;
+ text: string;
+ due?: string;
+ completed: boolean;
+ } = {
+ title: '',
+ text: '',
+ due: '',
+ completed: false,
+ };
+
+ state = {
+ needsSync: false,
+ };
+
/**
* Method to reuturn the
* @param fieldStr
@@ -234,6 +251,34 @@ export class TaskBox extends React.Component<TaskBoxProps> {
}
}
);
+
+ this._googleTaskCreateDisposer = reaction(
+ () => {
+ const { title, text, $task_completed, $task_dateRange, $task_startTime, $task_endTime, $task_allDay } = doc;
+
+ const completed = !!$task_completed;
+ let due: string | undefined;
+
+ if ($task_allDay && typeof $task_dateRange === 'string') {
+ const datePart = $task_dateRange.split('|')[0];
+ if (datePart && !isNaN(new Date(datePart).getTime())) {
+ due = new Date(datePart + 'T00:00:00Z').toISOString();
+ }
+ } else if ($task_endTime && $task_endTime instanceof DateField && $task_endTime.date) {
+ due = $task_endTime.date.toISOString();
+ } else if ($task_startTime && $task_startTime instanceof DateField && $task_startTime.date) {
+ due = $task_startTime.date.toISOString();
+ }
+
+ return { title, text, completed, due };
+ },
+ current => {
+ const hasChanged = current.title !== this.lastSyncedTask.title || current.text !== this.lastSyncedTask.text || current.due !== this.lastSyncedTask.due || current.completed !== this.lastSyncedTask.completed;
+
+ this.setState({ needsSync: hasChanged });
+ },
+ { fireImmediately: true }
+ );
}
componentWillUnmount() {
@@ -350,6 +395,15 @@ export class TaskBox extends React.Component<TaskBoxProps> {
if (result?.id) {
alert('✅ Task synced with Google Tasks!');
+ if (result?.id) {
+ this.lastSyncedTask = {
+ title: taskTitle,
+ text: taskDesc,
+ due,
+ completed: isCompleted,
+ };
+ this.setState({ needsSync: false });
+ }
} else {
alert(`❌ Failed: ${result?.error?.message || 'Unknown error'}`);
}
@@ -402,6 +456,7 @@ export class TaskBox extends React.Component<TaskBoxProps> {
<button
className="task-manager-google"
+ disabled={!this.state.needsSync}
onClick={event => {
event.preventDefault();
handleGoogleTaskSync();