fixed urgency-date connection and added urgency-date guidance. fixed password extension break. fixed template saving.
This commit is contained in:
+28
-92
@@ -2,6 +2,7 @@ import { createStore, reconcile, produce } from "solid-js/store";
|
||||
import { createSignal, createEffect, createRoot } from "solid-js";
|
||||
import { pb, TASGRID_COLLECTION } from "@/lib/pocketbase";
|
||||
import { toast } from "solid-sonner";
|
||||
import { URGENCY_HOURS } from "@/lib/constants";
|
||||
|
||||
const getStorageKey = () => {
|
||||
const userId = pb.authStore.model?.id;
|
||||
@@ -117,25 +118,31 @@ export const calculateUrgencyScore = (dueDateStr: string): number => {
|
||||
const due = new Date(dueDateStr).getTime();
|
||||
const diffHours = (due - now()) / (1000 * 60 * 60);
|
||||
|
||||
// Geometric formulation
|
||||
// Base is derived so that urgency 1 ~ matrixScaleDays
|
||||
const base = Math.pow(Math.max(1, store.matrixScaleDays), 1 / 9);
|
||||
if (diffHours <= URGENCY_HOURS[10]) return 10;
|
||||
if (diffHours >= URGENCY_HOURS[1]) return 1;
|
||||
|
||||
// Reverse formula: Level = 10 - (ln(hours/24) / ln(base))
|
||||
// If hours <= 24, log(<=1) is negative or 0, so Level >= 10.
|
||||
if (diffHours <= 24) return 10;
|
||||
// Linear interpolation between breakpoints
|
||||
const levels = Object.keys(URGENCY_HOURS).map(Number).sort((a, b) => b - a); // 10, 9, 8...
|
||||
for (let i = 0; i < levels.length - 1; i++) {
|
||||
const highLevel = levels[i];
|
||||
const lowLevel = levels[i + 1];
|
||||
const highHours = URGENCY_HOURS[highLevel];
|
||||
const lowHours = URGENCY_HOURS[lowLevel];
|
||||
|
||||
const level = 10 - (Math.log(diffHours / 24) / Math.log(base));
|
||||
return Math.max(1, Math.min(10, level));
|
||||
if (diffHours >= highHours && diffHours <= lowHours) {
|
||||
// Level decreases as hours increase
|
||||
const range = lowHours - highHours;
|
||||
const progress = (diffHours - highHours) / range;
|
||||
return highLevel - progress * (highLevel - lowLevel);
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
};
|
||||
|
||||
export const calculateDateFromUrgency = (level: number): string => {
|
||||
// Inverse of above
|
||||
if (level >= 10) {
|
||||
return new Date(now() + 24 * 60 * 60 * 1000).toISOString();
|
||||
}
|
||||
const base = Math.pow(Math.max(1, store.matrixScaleDays), 1 / 9);
|
||||
const hours = 24 * Math.pow(base, 10 - level);
|
||||
const roundedLevel = Math.max(1, Math.min(10, Math.round(level)));
|
||||
const hours = URGENCY_HOURS[roundedLevel] || 24;
|
||||
return new Date(now() + hours * 60 * 60 * 1000).toISOString();
|
||||
};
|
||||
|
||||
@@ -400,24 +407,7 @@ export const updateTaskField = (id: string, field: keyof Task, value: any) => {
|
||||
|
||||
export const setMatrixScaleDays = async (days: number) => {
|
||||
setStore("matrixScaleDays", days);
|
||||
|
||||
// Sync to users collection
|
||||
if (store.prefId) {
|
||||
try {
|
||||
const prefs = {
|
||||
pWeight: store.pWeight,
|
||||
uWeight: store.uWeight,
|
||||
matrixScaleDays: days
|
||||
};
|
||||
|
||||
await pb.collection('users').update(store.prefId, {
|
||||
Taskgrid_pref: prefs
|
||||
});
|
||||
|
||||
} catch (err) {
|
||||
console.error("Failed to update preferences", err);
|
||||
}
|
||||
}
|
||||
await syncPreferences();
|
||||
};
|
||||
|
||||
export const toggleTask = (id: string) => {
|
||||
@@ -491,27 +481,7 @@ export const upsertMultipleTagDefinitions = async (updates: Record<string, numbe
|
||||
setStore("tagDefinitions", (defs) => ({ ...(defs || {}), ...updates }));
|
||||
|
||||
// Persist
|
||||
const map = { ...store.tagDefinitions };
|
||||
const userId = pb.authStore.model?.id;
|
||||
if (userId) {
|
||||
try {
|
||||
const prefs = {
|
||||
pWeight: store.pWeight,
|
||||
uWeight: store.uWeight,
|
||||
matrixScaleDays: store.matrixScaleDays,
|
||||
tagDefinitions: map
|
||||
};
|
||||
|
||||
await pb.collection('users').update(userId, {
|
||||
Taskgrid_pref: prefs
|
||||
}, { requestKey: null });
|
||||
} catch (e: any) {
|
||||
// Ignore abort errors
|
||||
if (e.isAbort) return;
|
||||
console.error("Failed to persist tag definitions", e);
|
||||
toast.error("Failed to save tag definitions");
|
||||
}
|
||||
}
|
||||
await syncPreferences();
|
||||
};
|
||||
|
||||
export const removeTagDefinition = async (name: string) => {
|
||||
@@ -528,25 +498,8 @@ export const removeTagDefinition = async (name: string) => {
|
||||
}));
|
||||
|
||||
// 3. Persist
|
||||
const map = { ...store.tagDefinitions };
|
||||
const userId = pb.authStore.model?.id;
|
||||
if (userId) {
|
||||
try {
|
||||
const prefs = {
|
||||
pWeight: store.pWeight,
|
||||
uWeight: store.uWeight,
|
||||
matrixScaleDays: store.matrixScaleDays,
|
||||
tagDefinitions: map
|
||||
};
|
||||
await pb.collection('users').update(userId, {
|
||||
Taskgrid_pref: prefs
|
||||
});
|
||||
toast.success(`Tag "${name}" deleted`);
|
||||
} catch (e) {
|
||||
console.error("Failed to delete tag definition", e);
|
||||
toast.error("Failed to delete tag");
|
||||
}
|
||||
}
|
||||
await syncPreferences();
|
||||
toast.success(`Tag "${name}" deleted`);
|
||||
};
|
||||
|
||||
export const renameTagDefinition = async (oldName: string, newName: string) => {
|
||||
@@ -574,31 +527,13 @@ export const renameTagDefinition = async (oldName: string, newName: string) => {
|
||||
}));
|
||||
|
||||
// 4. Persist
|
||||
const map = { ...store.tagDefinitions };
|
||||
const userId = pb.authStore.model?.id;
|
||||
if (userId) {
|
||||
try {
|
||||
const prefs = {
|
||||
pWeight: store.pWeight,
|
||||
uWeight: store.uWeight,
|
||||
matrixScaleDays: store.matrixScaleDays,
|
||||
tagDefinitions: map
|
||||
};
|
||||
await pb.collection('users').update(userId, {
|
||||
Taskgrid_pref: prefs
|
||||
});
|
||||
toast.success(`Tag renamed to "${finalName}"`);
|
||||
} catch (e) {
|
||||
console.error("Failed to rename tag", e);
|
||||
toast.error("Failed to rename tag");
|
||||
}
|
||||
}
|
||||
await syncPreferences();
|
||||
};
|
||||
|
||||
|
||||
// -- Templates --
|
||||
|
||||
const syncPreferences = async () => {
|
||||
export const syncPreferences = async () => {
|
||||
const userId = pb.authStore.model?.id;
|
||||
if (!userId) return;
|
||||
|
||||
@@ -617,6 +552,7 @@ const syncPreferences = async () => {
|
||||
} catch (e: any) {
|
||||
if (e.isAbort) return;
|
||||
console.error("Failed to sync preferences", e);
|
||||
// We could toast here, but many of these are background syncs
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user