Commit 1a440237 authored by Administrator's avatar Administrator
Browse files

feat(task): add "only incomplete" filter



Adds a checkbox to the TaskView filter panel that, when checked,
attaches completion_percent_lte=99 to the /api/tasks/ query — i.e.
tasks with completion_percent < 100% (not_started + in_progress).

Bug fix: TaskView.fetchTasks built its query inline and bypassed
useTaskFilters.toApiParams(), so any future field added to the
composable's params mapping would silently no-op. Route the call
through toApiParams() to make the composable the single source of
truth.

Coverage: extend useTaskFilters.spec toApiParams suite with both
branches of onlyIncomplete.
Co-Authored-By: default avatarClaude <noreply@anthropic.com>
parent efd558d6
......@@ -200,4 +200,21 @@ describe('toApiParams', () => {
story_id: null,
})
})
it('attaches completion_percent_lte=99 when onlyIncomplete is set', () => {
const f = useTaskFilters(refs)
f.filters.value.onlyIncomplete = true
expect(f.toApiParams()).toEqual({
student_id: null,
subject_id: null,
term_id: null,
story_id: null,
completion_percent_lte: 99,
})
})
it('omits completion_percent_lte when onlyIncomplete is false', () => {
const f = useTaskFilters(refs)
expect(f.toApiParams()).not.toHaveProperty('completion_percent_lte')
})
})
......@@ -27,6 +27,7 @@ const emit = defineEmits([
'update:subject-id',
'update:term-id',
'update:story-id',
'update:only-incomplete',
])
const { t } = useI18n() // available as $t in template; used here for consistency.
......@@ -114,6 +115,22 @@ const { t } = useI18n() // available as $t in template; used here for consistenc
/>
</v-col>
<v-col cols="12">
<v-checkbox
:model-value="filters.onlyIncomplete"
:label="t('task.filters.onlyIncomplete')"
density="compact"
hide-details
color="primary"
@update:model-value="
(v) => {
emit('update:only-incomplete', v)
emit('apply')
}
"
/>
</v-col>
<v-col cols="12">
<v-btn
color="primary"
......
......@@ -25,6 +25,8 @@ export function useTaskFilters({ students, subjects, terms, stories }) {
subjectId: null,
termId: null,
storyId: null,
// 只看未完成:completion_percent < 100%(覆盖 not_started + in_progress)
onlyIncomplete: false,
})
// 横屏(width > height)时默认收起 filter panel,避免 304px 高的 panel 把
......@@ -79,16 +81,22 @@ export function useTaskFilters({ students, subjects, terms, stories }) {
subjectId: null,
termId: null,
storyId: null,
onlyIncomplete: false,
}
}
function toApiParams() {
return {
const params = {
student_id: filters.value.studentId,
subject_id: filters.value.subjectId,
term_id: filters.value.termId,
story_id: filters.value.storyId,
}
// 只看未完成:completion_percent < 100%(兼容后端 status 枚举推导规则)
if (filters.value.onlyIncomplete) {
params.completion_percent_lte = 99
}
return params
}
// Cascade: 学生变了 → 重置学期和系列任务。
......
......@@ -66,6 +66,7 @@ export default {
expand: 'Expand Filter Panel',
collapse: 'Collapse Filter Panel',
expandToReselect: 'Click to Expand and Reselect',
onlyIncomplete: 'Only incomplete',
},
edit: {
title: 'Edit Task',
......
......@@ -66,6 +66,7 @@ export default {
expand: '展开筛选面板',
collapse: '收起筛选面板',
expandToReselect: '点击展开重新选择',
onlyIncomplete: '只看未完成',
},
edit: {
title: '编辑作业',
......
......@@ -90,12 +90,7 @@ async function fetchTasks(filterParams = null) {
isLoading.value = true
clearError()
try {
const params = filterParams || {
student_id: filterPanel.filters.value.studentId,
subject_id: filterPanel.filters.value.subjectId,
term_id: filterPanel.filters.value.termId,
story_id: filterPanel.filters.value.storyId,
}
const params = filterParams || filterPanel.toApiParams()
const response = await getTasks(params)
tasks.value = Array.isArray(response) ? response : []
} catch (e) {
......@@ -134,6 +129,9 @@ function onUpdateTermId(value) {
function onUpdateStoryId(value) {
filterPanel.filters.value.storyId = value
}
function onUpdateOnlyIncomplete(value) {
filterPanel.filters.value.onlyIncomplete = value
}
// ─── Edit dialog open / close ───────────────────────────────────────
function openEditForTask(taskId) {
......@@ -255,6 +253,7 @@ onUnmounted(() => {
@update:subject-id="onUpdateSubjectId"
@update:term-id="onUpdateTermId"
@update:story-id="onUpdateStoryId"
@update:only-incomplete="onUpdateOnlyIncomplete"
/>
<TaskCalendar
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment