Files
habit-tracker/app/templates/partials/habit_item.html
T
shinalokandClaude Sonnet 5 d212451fe0 add habit goal-period difficulty and habit formation research notes
Ground the 21-day habit myth in actual research (Lally et al. 2010) and let
users pick a target period (21/66/254 days or unlimited) matching that
study's easy/median/hard automaticity timelines when creating a habit,
with progress shown on the habits list.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-19 10:12:17 +09:00

113 lines
4.3 KiB
HTML

<div
data-habit-id="{{ habit.id }}"
x-data="{
editing: false,
mask: {{ habit.weekdays_mask }},
difficulty: '{{ habit.difficulty.value }}',
alarmOn: {{ 'true' if habit.reminder_time else 'false' }},
days: ['월', '화', '수', '목', '금', '토', '일'],
}"
>
<div class="habit-item" x-show="!editing">
<div class="habit-item-main">
<span class="drag-handle" aria-hidden="true"></span>
<div>
<div class="habit-item-name">{{ habit.name }}</div>
{% if habit.condition_text %}<div class="habit-item-condition">{{ habit.condition_text }}</div>{% endif %}
<div class="habit-item-meta">
{{ weekday_label(habit.weekdays_mask) }}
{% if habit.reminder_time %}· 알람 {{ habit.reminder_time.strftime("%H:%M") }}{% endif %}
</div>
{% set progress = goal_progress(habit) %}
<div class="goal-progress-badge">
{% if progress %}
목표 {{ difficulty_label(habit.difficulty) }} · {{ progress.elapsed }}/{{ progress.target }}일차{% if progress.reached %} · 목표 기간 달성!{% else %} (D-{{ progress.remaining }}){% endif %}
{% else %}
{{ difficulty_label(habit.difficulty) }}
{% endif %}
</div>
{% set stats = stats_map[habit.id] %}
{% if stats.scheduled_days > 0 %}
<div class="habit-item-stats">
<span class="badge">완료율 {{ stats.completion_rate }}%</span>
{% if stats.current_streak > 0 %}
<span class="badge{{ ' badge-milestone' if is_milestone_streak(stats.current_streak) }}">
{{ '🏆' if is_milestone_streak(stats.current_streak) else '🔥' }} 연속 {{ stats.current_streak }}일
</span>
{% endif %}
</div>
{% endif %}
</div>
</div>
<div class="habit-item-actions">
<button type="button" class="btn btn-secondary" @click="editing = true">수정</button>
{% if habit.status.value == "active" %}
<button
type="button"
class="btn btn-secondary"
hx-post="/habits/{{ habit.id }}/complete"
hx-target="body"
hx-swap="none"
hx-confirm="'{{ habit.name }}' 습관을 완료 처리할까요?"
>완료 처리</button>
<button
type="button"
class="btn btn-secondary"
hx-post="/habits/{{ habit.id }}/abandon"
hx-target="body"
hx-swap="none"
hx-confirm="'{{ habit.name }}' 습관을 포기할까요?"
>포기</button>
{% else %}
<button
type="button"
class="btn btn-secondary"
hx-post="/habits/{{ habit.id }}/reactivate"
hx-target="body"
hx-swap="none"
>다시 진행</button>
{% endif %}
<button
type="button"
class="btn btn-danger-ghost"
hx-delete="/habits/{{ habit.id }}/delete"
hx-target="body"
hx-swap="none"
hx-confirm="'{{ habit.name }}' 습관을 삭제할까요? 기록도 함께 삭제됩니다."
>삭제</button>
</div>
</div>
<form
x-show="editing"
x-cloak
style="padding: 12px 4px; border-bottom: 1px solid var(--color-border);"
hx-post="/habits/{{ habit.id }}/edit"
hx-target="#habit-edit-error-{{ habit.id }}"
hx-swap="innerHTML"
>
<input type="hidden" name="weekdays_mask" :value="mask" />
<input type="hidden" name="difficulty" :value="difficulty" />
<div class="field">
<label for="edit-name-{{ habit.id }}">습관 이름</label>
<input type="text" id="edit-name-{{ habit.id }}" name="name" required value="{{ habit.name }}" />
</div>
<div class="field">
<label for="edit-condition-{{ habit.id }}">달성 조건 (선택)</label>
<input type="text" id="edit-condition-{{ habit.id }}" name="condition_text" value="{{ habit.condition_text or '' }}" />
</div>
{% set reminder_value = habit.reminder_time.strftime("%H:%M") if habit.reminder_time else "" %}
{% include "partials/_weekday_alarm_fields.html" %}
<div id="habit-edit-error-{{ habit.id }}" class="form-error-text"></div>
<div style="display:flex; gap:8px;">
<button type="submit" class="btn btn-primary" style="flex:1;">저장</button>
<button type="button" class="btn btn-secondary" @click="editing = false">취소</button>
</div>
</form>
</div>