diff --git a/src/webcomponents/HabitCounter/HabitCounter.types.ts b/src/webcomponents/HabitCounter/HabitCounter.types.ts index f10cb80..b8b1a79 100644 --- a/src/webcomponents/HabitCounter/HabitCounter.types.ts +++ b/src/webcomponents/HabitCounter/HabitCounter.types.ts @@ -1,6 +1,6 @@ //? Expected structure returned by the data service fetch method. export interface HabitRecord { - value: number; + value: number; //? Service should SELECT 'actual_value_col AS value' } //? Base arguments for identifying a habit entry, now includes column names. diff --git a/src/webcomponents/HabitCounter/dom/uiUpdaters.ts b/src/webcomponents/HabitCounter/dom/uiUpdaters.ts index 70101c4..620ceaa 100644 --- a/src/webcomponents/HabitCounter/dom/uiUpdaters.ts +++ b/src/webcomponents/HabitCounter/dom/uiUpdaters.ts @@ -9,7 +9,6 @@ export interface HabitCounterUIElements { /** Updates the text content of the value display. */ export function updateDisplayValue(elements: HabitCounterUIElements, newValue: number | string): void { - //& console.log(`[HabitCounterUI] updateDisplayValue called with: ${newValue}`); if (elements.valueDisplay) { elements.valueDisplay.textContent = String(newValue); } else { @@ -20,7 +19,6 @@ export function updateDisplayValue(elements: HabitCounterUIElements, newValue: n export function updateStaticUI(elements: HabitCounterUIElements, emoji: string, habitKey: string): void { if (elements.labelElement) { const newLabelText = `${emoji} ${habitKey}:`; - console.log(`[HabitCounterUI] DEBUG: Attempting to set label textContent to: "${newLabelText}"`); elements.labelElement.textContent = newLabelText; } else { console.error("[HabitCounterUI] updateStaticUI: labelElement was null."); @@ -35,7 +33,6 @@ export function updateStaticUI(elements: HabitCounterUIElements, emoji: string, /** Sets the component to visually indicate an error state. */ export function setComponentErrorState(elements: HabitCounterUIElements, message: string = "Error"): void { - //& console.warn(`[HabitCounterUI] setComponentErrorState called with message: "${message}"`); updateDisplayValue(elements, "ERR"); if (elements.wrapper) { elements.wrapper.style.borderColor = "var(--text-error)"; @@ -46,7 +43,6 @@ export function setComponentErrorState(elements: HabitCounterUIElements, message /** Clears any visual error indication. */ export function clearComponentErrorState(elements: HabitCounterUIElements): void { - //& console.log(`[HabitCounterUI] clearComponentErrorState called.`); //? Only reset if actually in error state (check border color) if (elements.wrapper && elements.wrapper.style.borderColor !== "transparent") { elements.wrapper.style.borderColor = "transparent"; diff --git a/src/webcomponents/HabitCounter/registerHabitCounter.ts b/src/webcomponents/HabitCounter/registerHabitCounter.ts index d8af13e..5f0e546 100644 --- a/src/webcomponents/HabitCounter/registerHabitCounter.ts +++ b/src/webcomponents/HabitCounter/registerHabitCounter.ts @@ -1,4 +1,3 @@ -// src/webcomponents/registration.ts import { DBService } from "../../DBService"; import { HabitCounter } from "./HabitCounter"; @@ -36,7 +35,7 @@ export const registerHabitCounter = (el: HTMLElement, dbService: DBService) => { const component = document.createElement("habit-counter") as HabitCounter; //^ Set attributes that the component will read later - component.setAttribute("habit", habitKey); // Set 'habit' attribute + component.setAttribute("habit", habitKey); component.setAttribute("table", table); if (date) component.setAttribute("date", date); else component.setAttribute("date", "@date"); diff --git a/src/webcomponents/HabitCounter/services/HabitDataService.ts b/src/webcomponents/HabitCounter/services/HabitDataService.ts index ed6a98c..dcc3ffe 100644 --- a/src/webcomponents/HabitCounter/services/HabitDataService.ts +++ b/src/webcomponents/HabitCounter/services/HabitDataService.ts @@ -3,6 +3,8 @@ import { HabitRecord, HabitDataArgs, UpdateHabitDataArgs } from "../HabitCounter import { quoteSqlIdentifier } from "./utils/quoteSqlIdentifier"; import { validateFetchArgs, validateUpdateArgs } from "./utils/validateHabitArgs"; +interface UuidResult { uuid: string; } + export class HabitDataService { private dbService: DBService; @@ -48,15 +50,27 @@ export class HabitDataService { const safeValueCol = quoteSqlIdentifier(args.valueCol); const safeDateCol = quoteSqlIdentifier(args.dateCol); - //^ Use specified columns in INSERT, ON CONFLICT target, and UPDATE SET - const sql = ` - INSERT INTO ${safeTable} (${safeHabitIdCol}, ${safeDateCol}, ${safeValueCol}) VALUES (?, ?, ?) - ON CONFLICT(${safeHabitIdCol}, ${safeDateCol}) DO UPDATE SET ${safeValueCol} = excluded.${safeValueCol}; - `; - //! Requires UNIQUE constraint on the specified (habitIdCol, dateCol) - const params = [args.habitKey, args.date, args.newValue]; + //? Attempt to fetch existing UUID + const fetchUuidSql = `SELECT uuid FROM ${safeTable} WHERE ${safeHabitIdCol} = ? AND ${safeDateCol} = ?`; + const fetchUuidParams = [args.habitKey, args.date]; + const uuidResult = await this.dbService.getQuery(fetchUuidSql, fetchUuidParams); + const existingUuid = uuidResult?.[0]?.uuid; - await this.dbService.runQuery(sql, params); + + if (existingUuid && typeof existingUuid === 'string') { + const updateSql = `UPDATE ${safeTable} SET ${safeValueCol} = ? WHERE uuid = ?`; + const updateParams = [args.newValue, existingUuid]; + await this.dbService.runQuery(updateSql, updateParams); + } else { + //^ Use specified columns in INSERT, ON CONFLICT target, and UPDATE SET without uuid + const sql = ` + INSERT INTO ${safeTable} (${safeHabitIdCol}, ${safeDateCol}, ${safeValueCol}) VALUES (?, ?, ?) + ON CONFLICT(${safeHabitIdCol}, ${safeDateCol}) DO UPDATE SET ${safeValueCol} = excluded.${safeValueCol}; + `; + //! Requires UNIQUE constraint on the specified (habitIdCol, dateCol) + const params = [args.habitKey, args.date, args.newValue]; + await this.dbService.runQuery(sql, params); + } } catch (error) { console.error(`[HabitDataService] Error in updateHabitValue for ${args.habitKey}:`, error);