Repository navigation
Expand file tree
/
Copy pathcaffeine_logs.html
More file actions
175 lines (151 loc) · 6.49 KB
/
Copy pathcaffeine_logs.html
File metadata and controls
175 lines (151 loc) · 6.49 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>[섭취기록] 화면</title>
</head>
<body>
<h1>[섭취기록] 화면</h1>
<nav>
<a href="/testpages/index.html">홈</a> |
<a href="/testpages/signup.html">회원가입</a> |
<a href="/testpages/login.html">로그인</a> |
<a href="/testpages/drinks.html">내 음료</a> |
<a href="/testpages/presets.html">프리셋</a> |
<a href="/testpages/caffeine_logs.html">섭취기록</a> |
<a href="/testpages/sleep_logs.html">수면기록</a> |
<a href="/testpages/profile.html">프로필</a> |
<a href="/testpages/feed_status.html">피드계산</a> |
<a href="/testpages/night_session.html">밤샘모드</a> |
<button onclick="doLogout()">로그아웃</button>
[<span id="auth-status">확인중...</span>]
</nav>
<hr>
<p>로그인 필요(IsAuthenticated). 먼저 로그인 화면에서 로그인하세요.</p>
<h2>1) 한잔 기록 (POST /caffeine-logs/ · drink_id)</h2>
<p><small>등록된 내 음료를 골라 기록합니다. caffeine_mg/name은 서버가 해당 음료에서 박제하므로 여기서 입력하지 않습니다.</small></p>
<label>음료
<select id="drink-select"><option value="">-- 로딩중 --</option></select>
</label>
<button onclick="logFromDrink()">한잔 기록</button>
<pre id="drink-log-result">(아직 요청 없음)</pre>
<hr>
<h2>2) 커스텀 기록 (POST /caffeine-logs/ · 직접 입력)</h2>
<p><small>등록 안 된 음료를 이름과 카페인량으로 직접 기록합니다.</small></p>
<label>이름 <input type="text" id="custom-name" placeholder="예: 편의점 캔커피"></label>
<label>카페인(mg) <input type="number" id="custom-caffeine" min="1" max="1000"></label>
<button onclick="logCustom()">커스텀 기록</button>
<pre id="custom-log-result">(아직 요청 없음)</pre>
<hr>
<h2>3) 목록 조회 (GET /caffeine-logs/)</h2>
<label>start_date <input type="date" id="filter-start"></label>
<label>end_date <input type="date" id="filter-end"></label>
<label>page <input type="number" id="filter-page" min="1" value="1" style="width:5em"></label>
<label>page_size <input type="number" id="filter-page-size" min="1" value="20" style="width:5em"></label>
<button onclick="loadList()">조회</button>
<h3>기록 (수정/삭제)</h3>
<ul id="log-items">(조회 후 생성됨)</ul>
<h3>원본 응답</h3>
<pre id="list-result">(아직 요청 없음)</pre>
<script src="common.js"></script>
<script>
initNav();
// 한잔 기록용: 내 음료 목록을 드롭다운에 채운다.
async function loadDrinkOptions() {
const result = await apiFetch("/users/me/drinks/");
const select = document.getElementById("drink-select");
const list = Array.isArray(result.data) ? result.data : [];
select.innerHTML = '<option value="">-- 음료 선택 --</option>';
if (list.length === 0) {
select.innerHTML = '<option value="">(등록된 음료 없음 - 내 음료에서 추가)</option>';
return;
}
list.forEach((d) => {
const opt = document.createElement("option");
opt.value = d.id;
opt.textContent = "#" + d.id + " " + d.name + " (" + (d.size || "-") + ", " + d.caffeine_mg + "mg)";
select.appendChild(opt);
});
}
async function logFromDrink() {
const drinkId = document.getElementById("drink-select").value;
if (!drinkId) { alert("음료를 선택하세요."); return; }
const result = await apiFetch("/caffeine-logs/", "POST", { drink_id: Number(drinkId) });
renderResult("drink-log-result", result);
if (result.ok) loadList();
}
async function logCustom() {
const name = document.getElementById("custom-name").value.trim();
const caffeine = Number(document.getElementById("custom-caffeine").value);
if (!name) { alert("이름을 입력하세요."); return; }
if (!caffeine) { alert("카페인량을 입력하세요."); return; }
const result = await apiFetch("/caffeine-logs/", "POST", { name, caffeine_mg: caffeine });
renderResult("custom-log-result", result);
if (result.ok) {
document.getElementById("custom-name").value = "";
document.getElementById("custom-caffeine").value = "";
loadList();
}
}
function buildListQuery() {
const params = new URLSearchParams();
const start = document.getElementById("filter-start").value;
const end = document.getElementById("filter-end").value;
const page = document.getElementById("filter-page").value;
const pageSize = document.getElementById("filter-page-size").value;
if (start) params.set("start_date", start);
if (end) params.set("end_date", end);
if (page) params.set("page", page);
if (pageSize) params.set("page_size", pageSize);
const qs = params.toString();
return "/caffeine-logs/" + (qs ? "?" + qs : "");
}
async function loadList() {
const result = await apiFetch(buildListQuery());
renderResult("list-result", result);
const ul = document.getElementById("log-items");
ul.innerHTML = "";
const results = result.data && Array.isArray(result.data.results) ? result.data.results : [];
if (results.length === 0) {
ul.innerHTML = "<li>(기록 없음)</li>";
return;
}
results.forEach((log) => {
const li = document.createElement("li");
const kind = log.drink_id ? "한잔#" + log.drink_id : "커스텀";
li.textContent =
"#" + log.id + " " + log.name + " / " + log.caffeine_mg + "mg / " +
kind + " / " + log.created_at + " ";
const editBtn = document.createElement("button");
editBtn.textContent = "mg 수정";
editBtn.addEventListener("click", () => editLog(log));
li.appendChild(editBtn);
const delBtn = document.createElement("button");
delBtn.textContent = "삭제";
delBtn.addEventListener("click", () => deleteLog(log.id));
li.appendChild(delBtn);
ul.appendChild(li);
});
}
async function editLog(log) {
const input = prompt("새 카페인량(mg)", log.caffeine_mg);
if (input === null) return;
const caffeine = Number(input);
if (!caffeine) { alert("숫자를 입력하세요."); return; }
const result = await apiFetch("/caffeine-logs/" + log.id + "/", "PATCH", { caffeine_mg: caffeine });
if (!result.ok) alert("PATCH 실패\nHTTP " + result.status + "\n" + JSON.stringify(result.data));
loadList();
}
async function deleteLog(id) {
if (!confirm("#" + id + " 기록을 삭제할까요?")) return;
const result = await apiFetch("/caffeine-logs/" + id + "/", "DELETE");
if (!result.ok) alert("DELETE 실패\nHTTP " + result.status + "\n" + JSON.stringify(result.data));
loadList();
}
window.addEventListener("DOMContentLoaded", () => {
loadDrinkOptions();
loadList();
});
</script>
</body>
</html>