Skip to content

Commit 166cc24

Browse files
committed
refactor(habits-widget): implement per-widget habit item state management
- Change habit item and history IDs from number to string type - Replace global habitItems array with widgetId-keyed record for item storage - Add setHabitItems and getHabitItems functions to manage state by widget instance - Generate unique IDs for items without ID when setting habit items - Pass widgetId as parameter in widget utils functions to isolate widget data - Adjust widget rendering to fetch and update items per widgetId - Update event handlers and DOM updates to use widget-scoped habit items - Modify progress bar updates to target multiple elements by class for each item - Remove default hardcoded habit items, rely on passed or stored items per widget - Fix modal rendering and consumption list to reflect per-widget habit data - Ensure UI updates and tracking counts correspond to the correct widget instance
1 parent c59f8fd commit 166cc24

File tree

3 files changed

+147
-174
lines changed

3 files changed

+147
-174
lines changed

web/src/server/widgets/habits-widget.ts

Lines changed: 17 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@ import { FormlyFieldConfig } from '@ngx-formly/core';
33
import { of, tap } from 'rxjs';
44
import { z } from 'zod';
55

6-
import { linkFunctionsToWindow } from './habits-widget.utils';
6+
import {
7+
getHabitItems,
8+
linkFunctionsToWindow,
9+
setHabitItems,
10+
} from './habits-widget.utils';
711
import {
812
WidgetRender,
913
WidgetRenderInitFunctionOptions,
@@ -13,7 +17,7 @@ import {
1317
// Define the habit item structure
1418

1519
export const HabitsWidgetItemSchema = z.object({
16-
id: z.string().optional().nullish(),
20+
id: z.string(),
1721
name: z.string().min(1, { message: 'Name cannot be empty' }),
1822
icon: z.string(),
1923
color: z.string(),
@@ -23,7 +27,7 @@ export const HabitsWidgetItemSchema = z.object({
2327
history: z
2428
.array(
2529
z.object({
26-
id: z.number(),
30+
id: z.string(),
2731
time: z.string(),
2832
})
2933
)
@@ -244,57 +248,15 @@ export class HabitsWidgetRender implements WidgetRender<HabitsWidgetType> {
244248
) {
245249
const render = (): string => {
246250
// Default items if none provided
247-
const items =
248-
widget.options.items && widget.options.items.length > 0
249-
? widget.options.items
250-
: [
251-
{
252-
id: 'water',
253-
name: 'Water',
254-
icon: 'droplet',
255-
color: 'blue',
256-
minValue: 0,
257-
maxValue: 8,
258-
currentValue: 0,
259-
history: [],
260-
},
261-
{
262-
id: 'food',
263-
name: 'Food',
264-
icon: 'utensils',
265-
color: 'orange',
266-
minValue: 0,
267-
maxValue: 5,
268-
currentValue: 0,
269-
history: [],
270-
},
271-
{
272-
id: 'medication',
273-
name: 'Medication',
274-
icon: 'pill',
275-
color: 'purple',
276-
minValue: 0,
277-
maxValue: 5,
278-
currentValue: 0,
279-
history: [],
280-
},
281-
{
282-
id: 'exercise',
283-
name: 'Exercise',
284-
icon: 'dumbbell',
285-
color: 'green',
286-
minValue: 0,
287-
maxValue: 3,
288-
currentValue: 0,
289-
history: [],
290-
},
291-
];
251+
const items = widget.options.items || [];
292252

293253
// Generate unique IDs for this widget instance
294254
const modalId = `habits-modal-${widget.id}`;
295255

256+
setHabitItems(widget.id, items);
257+
296258
return `
297-
<div class="bg-white p-6 rounded-2xl long-shadow group transition-all duration-300 relative overflow-hidden h-40 flex flex-col justify-between border-l-4 border-pastel-green" onclick="showHabitsModal('${modalId}')">
259+
<div class="bg-white p-6 rounded-2xl long-shadow group transition-all duration-300 relative overflow-hidden h-40 flex flex-col justify-between border-l-4 border-pastel-green" onclick="showHabitsModal('${widget.id}','${modalId}')">
298260
<button class="absolute top-2 right-2 text-gray-400 hover:text-pastel-blue opacity-0 group-hover:opacity-100 transition-opacity p-2 rounded-full bg-white/70 backdrop-blur-sm">
299261
<i data-lucide="pencil" class="w-5 h-5"></i>
300262
</button>
@@ -304,7 +266,7 @@ export class HabitsWidgetRender implements WidgetRender<HabitsWidgetType> {
304266
</div>
305267
<div id="habits-widget-content">
306268
<!-- Dynamic content will be inserted here -->
307-
${renderWidgetContent(items)}
269+
${renderWidgetContent(widget.id)}
308270
</div>
309271
</div>
310272
@@ -355,8 +317,10 @@ export class HabitsWidgetRender implements WidgetRender<HabitsWidgetType> {
355317
};
356318

357319
// Helper function to render widget content
358-
function renderWidgetContent(items: HabitsWidgetItemType[]): string {
359-
if (items.length === 0) {
320+
function renderWidgetContent(widgetId: string): string {
321+
const items = getHabitItems(widgetId);
322+
console.log({ items });
323+
if (items?.length === 0) {
360324
return '<p class="text-gray-500 text-sm">No habits configured</p>';
361325
}
362326

@@ -380,7 +344,7 @@ export class HabitsWidgetRender implements WidgetRender<HabitsWidgetType> {
380344
</div>
381345
<p class="text-xs text-gray-500 text-center">${item.name}</p>
382346
<div class="w-full bg-gray-200 rounded-full h-1.5 mt-1">
383-
<div id="habit-${item.id}-progress" class="h-1.5 rounded-full ${progressBarColor} transition-all duration-500" style="width: ${percentage}%"></div>
347+
<div class="habit-${item.id}-progress h-1.5 rounded-full ${progressBarColor} transition-all duration-500" style="width: ${percentage}%"></div>
384348
</div>
385349
</div>
386350
`;

0 commit comments

Comments
 (0)