Merge pull request 'Align goal status and delete buttons in goals tab' (#4) from feature/android-upload-hint into master
Reviewed-on: #4
This commit was merged in pull request #4.
This commit is contained in:
+56
-39
@@ -1341,6 +1341,26 @@ function goalMatchesFilter(goal, filter) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const GOALS_TABLE_COLGROUP = `
|
||||
<colgroup>
|
||||
<col class="col-goal-item">
|
||||
<col class="col-goal-progress">
|
||||
<col class="col-goal-status">
|
||||
<col class="col-goal-actions">
|
||||
</colgroup>`;
|
||||
|
||||
function goalsTableHead() {
|
||||
return `
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="col-goal-item">${esc(t("goals.item"))}</th>
|
||||
<th class="col-goal-progress">${esc(t("goals.progress"))}</th>
|
||||
<th class="col-goal-status">${esc(t("goals.status"))}</th>
|
||||
<th class="col-goal-actions">${esc(t("goals.actions"))}</th>
|
||||
</tr>
|
||||
</thead>`;
|
||||
}
|
||||
|
||||
function renderGoalRow(goal) {
|
||||
const done = !!goal.completed_at;
|
||||
const isSkill = goal.goal_type === "skill";
|
||||
@@ -1359,14 +1379,14 @@ function renderGoalRow(goal) {
|
||||
: "";
|
||||
const deleteBtn = `<button type="button" class="goal-delete-btn" data-goal-id="${goal.id}">${esc(t("goals.delete"))}</button>`;
|
||||
return `<tr>
|
||||
<td>${typeBadge}${esc(goal.item_name)}</td>
|
||||
<td>
|
||||
<td class="col-goal-item">${typeBadge}${esc(goal.item_name)}</td>
|
||||
<td class="col-goal-progress">
|
||||
<div class="goal-progress-text">${progressText} ${modeHint}</div>
|
||||
<div class="progress-bar"><div class="progress-fill" style="width:${goal.progress_pct}%"></div></div>
|
||||
${missing}${eta}
|
||||
</td>
|
||||
<td><span class="badge ${done ? "badge-success" : "badge-warning"}">${esc(done ? t("goals.done") : t("goals.open"))}</span></td>
|
||||
<td class="goal-actions-cell">${deleteBtn}</td>
|
||||
<td class="col-goal-status"><span class="badge ${done ? "badge-success" : "badge-warning"}">${esc(done ? t("goals.done") : t("goals.open"))}</span></td>
|
||||
<td class="col-goal-actions goal-actions-cell">${deleteBtn}</td>
|
||||
</tr>`;
|
||||
}
|
||||
|
||||
@@ -1464,7 +1484,7 @@ function renderGoals() {
|
||||
const filter = g.filter;
|
||||
const data = g.data || { groups: [], ungrouped: [] };
|
||||
|
||||
const groupSections = data.groups.map((group) => {
|
||||
const groupRows = data.groups.map((group) => {
|
||||
const goals = (group.goals || []).filter((goal) => goalMatchesFilter(goal, filter));
|
||||
if (!goals.length && filter !== "all") return "";
|
||||
const completed = goals.filter((goal) => goal.completed_at).length;
|
||||
@@ -1491,43 +1511,40 @@ function renderGoals() {
|
||||
: `<tr class="goal-item-row ${expanded ? "" : "collapsed"}" data-group="${sectionKey}"><td colspan="4" class="empty-state">${esc(t("goals.empty"))}</td></tr>`;
|
||||
|
||||
return `
|
||||
<div class="card goals-group-card">
|
||||
<table class="goals-table">
|
||||
<tbody>
|
||||
<tr class="inv-group-row goal-group-header">
|
||||
<td colspan="4">
|
||||
<button type="button" class="inv-group-toggle goal-group-toggle" data-group="${sectionKey}" aria-expanded="${expanded}">
|
||||
<span class="inv-group-title">${esc(group.name)}</span>
|
||||
<span class="inv-group-meta">${esc(t("goals.groupProgress", { completed, total }))}</span>
|
||||
</button>
|
||||
<span class="goal-group-actions">${headerActions}</span>
|
||||
${missingSummary}
|
||||
</td>
|
||||
</tr>
|
||||
${rows}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>`;
|
||||
<tr class="inv-group-row goal-group-header">
|
||||
<td colspan="4">
|
||||
<button type="button" class="inv-group-toggle goal-group-toggle" data-group="${sectionKey}" aria-expanded="${expanded}">
|
||||
<span class="inv-group-title">${esc(group.name)}</span>
|
||||
<span class="inv-group-meta">${esc(t("goals.groupProgress", { completed, total }))}</span>
|
||||
</button>
|
||||
<span class="goal-group-actions">${headerActions}</span>
|
||||
${missingSummary}
|
||||
</td>
|
||||
</tr>
|
||||
${rows}`;
|
||||
}).join("");
|
||||
|
||||
const ungrouped = (data.ungrouped || []).filter((goal) => goalMatchesFilter(goal, filter));
|
||||
const ungroupedSection = (filter === "all" || ungrouped.length) ? `
|
||||
<div class="card goals-group-card">
|
||||
<h3 class="goals-ungrouped-title">${esc(t("goals.ungrouped"))}</h3>
|
||||
<table class="goals-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>${esc(t("goals.item"))}</th>
|
||||
<th>${esc(t("goals.progress"))}</th>
|
||||
<th>${esc(t("goals.status"))}</th>
|
||||
<th>${esc(t("goals.actions"))}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>${renderGoalsTableBody(ungrouped)}</tbody>
|
||||
</table>
|
||||
</div>` : "";
|
||||
const showUngrouped = filter === "all" || ungrouped.length;
|
||||
const ungroupedRows = showUngrouped
|
||||
? `<tr class="goal-section-header">
|
||||
<td colspan="4" class="goals-ungrouped-title">${esc(t("goals.ungrouped"))}</td>
|
||||
</tr>
|
||||
${renderGoalsTableBody(ungrouped)}`
|
||||
: "";
|
||||
|
||||
const hasAny = groupSections || ungrouped.length || filter === "all";
|
||||
const hasAny = groupRows || ungrouped.length || filter === "all";
|
||||
const goalsTable = hasAny ? `
|
||||
<div class="card goals-group-card">
|
||||
<table class="goals-table">
|
||||
${GOALS_TABLE_COLGROUP}
|
||||
${goalsTableHead()}
|
||||
<tbody>
|
||||
${groupRows}
|
||||
${ungroupedRows}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>` : `<div class="card"><p class="empty-state">${esc(t("goals.empty"))}</p></div>`;
|
||||
|
||||
const overview = state.goalsOverview;
|
||||
const overviewHtml = overview ? `
|
||||
@@ -1547,7 +1564,7 @@ function renderGoals() {
|
||||
</select>
|
||||
<button type="button" class="upload-btn" id="goals-create-group">${esc(t("goals.createGroup"))}</button>
|
||||
</div>
|
||||
${hasAny ? groupSections + ungroupedSection : `<div class="card"><p class="empty-state">${esc(t("goals.empty"))}</p></div>`}`;
|
||||
${goalsTable}`;
|
||||
|
||||
document.getElementById("goals-filter").addEventListener("change", (e) => {
|
||||
state.goals.filter = e.target.value;
|
||||
|
||||
+20
-2
@@ -1057,12 +1057,30 @@ body.inv-chart-modal-open {
|
||||
/* Goals */
|
||||
.goals-toolbar { gap: 12px; flex-wrap: wrap; }
|
||||
.goals-group-card { margin-bottom: 16px; }
|
||||
.goals-ungrouped-title { margin: 0 0 12px; font-size: 1rem; }
|
||||
.goals-table { width: 100%; border-collapse: collapse; }
|
||||
.goals-ungrouped-title {
|
||||
margin: 0;
|
||||
padding: 10px 10px 6px;
|
||||
font-size: 1rem;
|
||||
font-weight: 600;
|
||||
border-bottom: 1px solid var(--border);
|
||||
background: var(--bg);
|
||||
}
|
||||
.goal-section-header td {
|
||||
padding: 0;
|
||||
border-bottom: none;
|
||||
border-top: 1px solid var(--border);
|
||||
}
|
||||
.goal-section-header + tr td { border-top: none; }
|
||||
.goals-table { width: 100%; border-collapse: collapse; table-layout: fixed; }
|
||||
.goals-table th,
|
||||
.goals-table td { padding: 8px 10px; text-align: left; border-bottom: 1px solid var(--border); vertical-align: middle; }
|
||||
.goals-table .col-goal-item { width: 22%; }
|
||||
.goals-table .col-goal-progress { width: auto; }
|
||||
.goals-table .col-goal-status { width: 96px; text-align: center; }
|
||||
.goals-table .col-goal-actions { width: 88px; text-align: right; }
|
||||
.goal-progress-text { font-size: 0.85rem; margin-bottom: 4px; }
|
||||
.goal-actions-cell { white-space: nowrap; }
|
||||
.goal-actions-cell .goal-delete-btn { margin-left: 0; }
|
||||
.goal-delete-btn,
|
||||
.goal-group-delete,
|
||||
.goal-clear-completed {
|
||||
|
||||
Reference in New Issue
Block a user