Files
Card-data-sorting/templates/expenses/expense_list.html

123 lines
3.9 KiB
HTML

{% extends 'base.html' %}
{% block title %}明細編集{% endblock %}
{% block content %}
<section>
<h2>明細編集</h2>
{% if imported %}
<p>取込件数: {{ imported }} / 重複件数: {{ duplicated }} / 文字コード: {{ encoding }}</p>
{% endif %}
<form>
{% csrf_token %}
</form>
<table>
<thead>
<tr>
<th>利用日</th>
<th>利用先</th>
<th>金額</th>
<th>店舗区分</th>
<th>経費区分</th>
<th>区分</th>
<th>備考</th>
</tr>
</thead>
<tbody>
{% for expense in expenses %}
<tr data-expense-id="{{ expense.id }}">
<td>{{ expense.use_date }}</td>
<td>{{ expense.description }}</td>
<td>{{ expense.amount }}</td>
<td>
<select class="js-expense-field" data-field="store_id">
<option value="">未設定</option>
{% for store in stores %}
<option value="{{ store.id }}" {% if expense.store_id == store.id %}selected{% endif %}>
{{ store.name }}
</option>
{% endfor %}
</select>
</td>
<td>
<select class="js-expense-field" data-field="expense_category_id">
<option value="">未設定</option>
{% for category in categories %}
<option value="{{ category.id }}" {% if expense.expense_category_id == category.id %}selected{% endif %}>
{{ category.name }}
</option>
{% endfor %}
</select>
</td>
<td>
<select class="js-expense-field" data-field="owner_type">
<option value="pending" {% if expense.owner_type == "pending" %}selected{% endif %}>
未設定
</option>
<option value="company" {% if expense.owner_type == "company" %}selected{% endif %}>
会社
</option>
<option value="personal" {% if expense.owner_type == "personal" %}selected{% endif %}>
家計
</option>
</select>
</td>
<td>
<input
class="js-expense-field"
data-field="note"
type="text"
value="{{ expense.note }}"
>
</td>
</tr>
{% empty %}
<tr>
<td colspan="7">データがありません。</td>
</tr>
{% endfor %}
</tbody>
</table>
<script>
const csrfToken = document.querySelector('[name=csrfmiddlewaretoken]')?.value;
async function saveExpense(expenseId, payload) {
const response = await fetch(`/expenses/${expenseId}/update/`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': csrfToken,
},
body: JSON.stringify(payload),
});
if (!response.ok) {
throw new Error('保存に失敗しました');
}
return response.json();
}
function coerceValue(field, value) {
return value;
}
document.querySelectorAll('.js-expense-field').forEach((element) => {
const eventName = element.tagName === 'INPUT' ? 'change' : 'change';
element.addEventListener(eventName, async (event) => {
const row = event.target.closest('tr');
if (!row) {
return;
}
const expenseId = row.dataset.expenseId;
const field = event.target.dataset.field;
const value = coerceValue(field, event.target.value);
try {
await saveExpense(expenseId, { [field]: value });
} catch (error) {
alert(error.message);
}
});
});
</script>
</section>
{% endblock %}