add habit tracking page with grid layout\
\ - Add HabitGrid component with a responsive calendar-style layout\\ - Support variable habit durations with period-based cell rendering\ - Add skeleton loading states for better UX during data fetching - Add CounterHabitButton component for cells with increment/decrement interactions\ - Create HabitCellContextMenu for period-based actions (reset, set values, fail) - Add HabitCreationForm for creating new habits\ - Add HabitActionMenu component for additional operations on habits (archive, delete, edit)\ - Add SetValueDialog component for editing the value of a cell
This commit is contained in:
@@ -0,0 +1,76 @@
|
||||
<script lang="ts">
|
||||
import * as ContextMenu from '$lib/components/ui/context-menu';
|
||||
import { RotateCcw, SquarePen, CircleX } from '@lucide/svelte';
|
||||
import SetValueDialog from './SetValueDialog.svelte';
|
||||
import type { HabitWithCompletions } from '$lib/context/habits.svelte';
|
||||
|
||||
let {
|
||||
habit,
|
||||
cell,
|
||||
children,
|
||||
onResetPeriod,
|
||||
onSetValue,
|
||||
onToggleFailed
|
||||
}: {
|
||||
habit: HabitWithCompletions;
|
||||
cell: {
|
||||
value: number;
|
||||
date: string;
|
||||
span: number;
|
||||
gridColumn: number;
|
||||
isFailed: boolean;
|
||||
isEmpty: boolean;
|
||||
periodDates: string[];
|
||||
};
|
||||
children: import('svelte').Snippet;
|
||||
onResetPeriod: () => Promise<void>;
|
||||
onSetValue: (totalValue: number, dailyValues?: Record<string, number>) => Promise<void>;
|
||||
onToggleFailed: () => Promise<void>;
|
||||
} = $props();
|
||||
|
||||
let showSetValueDialog = $state(false);
|
||||
|
||||
async function handleResetPeriod() {
|
||||
await onResetPeriod();
|
||||
}
|
||||
|
||||
async function handleSetValue(totalValue: number, dailyValues?: Record<string, number>) {
|
||||
await onSetValue(totalValue, dailyValues);
|
||||
showSetValueDialog = false;
|
||||
}
|
||||
|
||||
async function handleToggleFailed() {
|
||||
await onToggleFailed();
|
||||
}
|
||||
</script>
|
||||
|
||||
<ContextMenu.Root>
|
||||
<ContextMenu.Trigger class="w-full">
|
||||
{@render children()}
|
||||
</ContextMenu.Trigger>
|
||||
<ContextMenu.Content class="w-48">
|
||||
<ContextMenu.Item onclick={handleResetPeriod} class="gap-2">
|
||||
<RotateCcw class="h-4 w-4" />
|
||||
Reset period
|
||||
</ContextMenu.Item>
|
||||
|
||||
<ContextMenu.Item onclick={() => showSetValueDialog = true} class="gap-2">
|
||||
<SquarePen class="h-4 w-4" />
|
||||
Set value...
|
||||
</ContextMenu.Item>
|
||||
|
||||
<ContextMenu.Separator />
|
||||
|
||||
<ContextMenu.Item onclick={handleToggleFailed} class="gap-2">
|
||||
<CircleX class="h-4 w-4" />
|
||||
{cell.isFailed ? 'Mark as unfailed' : 'Mark as failed'}
|
||||
</ContextMenu.Item>
|
||||
</ContextMenu.Content>
|
||||
</ContextMenu.Root>
|
||||
|
||||
<SetValueDialog
|
||||
bind:open={showSetValueDialog}
|
||||
{habit}
|
||||
{cell}
|
||||
onSetValue={handleSetValue}
|
||||
/>
|
||||
Reference in New Issue
Block a user