diff --git a/app/src/plugins/tm@_components/z-datepicker.vue b/app/src/plugins/tm@_components/z-datepicker.vue
new file mode 100644
index 0000000..c2e1573
--- /dev/null
+++ b/app/src/plugins/tm@_components/z-datepicker.vue
@@ -0,0 +1,331 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/plugins/tm@modal/_mixins/vuetify-fix-focus.ts b/app/src/plugins/tm@modal/_mixins/vuetify-fix-focus.ts
index a3b544d..c48f2d3 100644
--- a/app/src/plugins/tm@modal/_mixins/vuetify-fix-focus.ts
+++ b/app/src/plugins/tm@modal/_mixins/vuetify-fix-focus.ts
@@ -9,9 +9,20 @@ export default {
methods: {
setFocusEvent() {
- document.querySelectorAll('.v-autocomplete input').forEach((input) => {
+ const inputs = document.querySelectorAll('.v-autocomplete input');
+ console.log(
+ '🟢 [VuetifyFixFocusMixin] setFocusEvent - Found',
+ inputs.length,
+ 'autocomplete inputs',
+ );
+ inputs.forEach((input) => {
input.addEventListener('focus', this.onInputFocus);
});
+ console.log(
+ '🟢 [VuetifyFixFocusMixin] Attached focus listeners to',
+ inputs.length,
+ 'inputs',
+ );
},
onDateFocus($event) {
@@ -21,31 +32,69 @@ export default {
},
onDateOpen($event) {
+ console.log(
+ '🟢 [VuetifyFixFocusMixin] onDateOpen called at:',
+ new Date().toISOString(),
+ 'with event:',
+ $event,
+ );
// $event should be the element reference (or any truthy value to trigger saving)
if ($event) {
// Find the scrollable modal container
const modalContent = document.querySelector('.v-dialog .modal-content');
if (modalContent) {
this.savedScrollPosition = modalContent.scrollTop;
+ console.log(
+ '🟢 [VuetifyFixFocusMixin] Saved scroll position:',
+ this.savedScrollPosition,
+ );
+ } else {
+ console.log('🟢 [VuetifyFixFocusMixin] Modal content not found');
}
this.preventInputFocus = true;
+ console.log(
+ '🟢 [VuetifyFixFocusMixin] preventInputFocus set to:',
+ this.preventInputFocus,
+ );
// Reset after datepicker is opened
setTimeout(() => {
this.preventInputFocus = false;
this.savedScrollPosition = null;
+ console.log(
+ '🟢 [VuetifyFixFocusMixin] Reset preventInputFocus and savedScrollPosition after 500ms',
+ );
}, 500);
}
},
onInputFocus($event) {
+ const target = $event.target;
+ console.log('🟢 [VuetifyFixFocusMixin] onInputFocus triggered on:', {
+ tagName: target.tagName,
+ type: target.type,
+ id: target.id,
+ className: target.className,
+ preventInputFocus: this.preventInputFocus,
+ savedScrollPosition: this.savedScrollPosition,
+ });
+
// If we have a saved scroll position and an unwanted focus happened
if (this.preventInputFocus && this.savedScrollPosition !== null) {
const target = $event.target;
// Only intercept text input focus (autocomplete fields)
if (target.tagName === 'INPUT' && target.type === 'text') {
+ console.log('🟢 [VuetifyFixFocusMixin] PREVENTING FOCUS on:', target);
+ const scrollBefore = document.querySelector(
+ '.v-dialog .modal-content',
+ )?.scrollTop;
+ console.log(
+ '🟢 [VuetifyFixFocusMixin] Scroll position before:',
+ scrollBefore,
+ );
+
// Blur the focused element
setTimeout(() => {
target.blur();
@@ -55,9 +104,26 @@ export default {
);
if (modalContent && this.savedScrollPosition !== null) {
modalContent.scrollTop = this.savedScrollPosition;
+ const scrollAfter = modalContent.scrollTop;
+ console.log(
+ '🟢 [VuetifyFixFocusMixin] Scroll position restored to:',
+ scrollAfter,
+ );
}
}, 0);
+ } else {
+ console.log(
+ '🟢 [VuetifyFixFocusMixin] Not a text input, skipping prevention',
+ );
}
+ } else {
+ console.log(
+ '🟢 [VuetifyFixFocusMixin] Focus allowed (preventInputFocus:',
+ this.preventInputFocus,
+ ', savedScrollPosition:',
+ this.savedScrollPosition,
+ ')',
+ );
}
},
},
diff --git a/app/src/plugins/tm@modal/master-task/z-master-task-modal.vue b/app/src/plugins/tm@modal/master-task/z-master-task-modal.vue
index e0f4425..093018e 100644
--- a/app/src/plugins/tm@modal/master-task/z-master-task-modal.vue
+++ b/app/src/plugins/tm@modal/master-task/z-master-task-modal.vue
@@ -57,24 +57,22 @@