refactor: update icon usage to use mdi imports for consistency
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<v-card border class="d-flex flex-column h-100 rounded-0" flat width="100%">
|
||||
<v-toolbar v-if="!isDetailEditing" color="transparent" density="compact" flat>
|
||||
<v-btn :icon="isMobile ? 'mdi-arrow-left' : 'mdi-close'" size="small" variant="text" @click="$emit('close')" />
|
||||
<v-btn :icon="isMobile ? mdiArrowLeft : mdiClose" size="small" variant="text" @click="$emit('close')" />
|
||||
<v-toolbar-title class="text-subtitle-1 font-weight-bold">
|
||||
{{ selectedSemester ? selectedSemester.semesterName : '學期明細' }}
|
||||
</v-toolbar-title>
|
||||
@@ -9,7 +9,7 @@
|
||||
<v-btn
|
||||
v-if="selectedSemester && !isViewMode"
|
||||
color="error"
|
||||
prepend-icon="mdi-delete"
|
||||
:prepend-icon="mdiDelete"
|
||||
size="small"
|
||||
variant="text"
|
||||
@click="$emit('delete', selectedSemester.id)"
|
||||
@@ -19,7 +19,7 @@
|
||||
<v-btn
|
||||
v-if="selectedSemester && !isViewMode"
|
||||
color="primary"
|
||||
prepend-icon="mdi-pencil"
|
||||
:prepend-icon="mdiPencil"
|
||||
size="small"
|
||||
variant="text"
|
||||
@click="$emit('start-edit')"
|
||||
@@ -29,7 +29,7 @@
|
||||
</v-toolbar>
|
||||
|
||||
<v-toolbar v-else density="compact" flat>
|
||||
<v-btn :icon="isMobile ? 'mdi-arrow-left' : 'mdi-close'" size="small" variant="text" @click="$emit('cancel-edit')" />
|
||||
<v-btn :icon="isMobile ? mdiArrowLeft : mdiClose" size="small" variant="text" @click="$emit('cancel-edit')" />
|
||||
<v-toolbar-title class="text-subtitle-1 font-weight-bold">
|
||||
編輯學期
|
||||
</v-toolbar-title>
|
||||
@@ -107,21 +107,23 @@
|
||||
<v-row dense>
|
||||
<v-col cols="12">
|
||||
<v-text-field
|
||||
v-model="detailForm.semesterName"
|
||||
:model-value="detailForm.semesterName"
|
||||
density="compact"
|
||||
hide-details="auto"
|
||||
label="學期名稱"
|
||||
variant="outlined"
|
||||
@update:model-value="updateDetailFormField('semesterName', $event)"
|
||||
/>
|
||||
</v-col>
|
||||
<v-col :cols="isMobile ? 12 : 6">
|
||||
<v-text-field
|
||||
v-model.number="detailForm.rank"
|
||||
:model-value="detailForm.rank"
|
||||
density="compact"
|
||||
hide-details="auto"
|
||||
label="班級排名"
|
||||
type="number"
|
||||
variant="outlined"
|
||||
@update:model-value="updateDetailFormField('rank', toNumber($event))"
|
||||
/>
|
||||
</v-col>
|
||||
<v-col :cols="isMobile ? 12 : 6">
|
||||
@@ -139,7 +141,7 @@
|
||||
<div class="d-flex align-center mt-2 mb-1">
|
||||
<div class="text-subtitle-2 font-weight-bold">課程列表</div>
|
||||
<v-spacer />
|
||||
<v-btn color="primary" prepend-icon="mdi-plus" size="small" variant="text" @click="$emit('add-course')">
|
||||
<v-btn color="primary" :prepend-icon="mdiPlus" size="small" variant="text" @click="addCourse">
|
||||
加入課程
|
||||
</v-btn>
|
||||
</div>
|
||||
@@ -149,26 +151,42 @@
|
||||
<div class="d-flex align-center mb-3">
|
||||
<div class="text-subtitle-2 font-weight-bold">課程 {{ idx + 1 }}</div>
|
||||
<v-spacer />
|
||||
<v-btn color="error" icon="mdi-delete" size="small" variant="text" @click="$emit('remove-course', idx)" />
|
||||
<v-btn color="error" :icon="mdiDelete" size="small" variant="text" @click="removeCourse(idx)" />
|
||||
</div>
|
||||
<div class="d-flex flex-column ga-3">
|
||||
<v-text-field v-model="course.name" density="compact" hide-details label="課程名稱" variant="outlined" />
|
||||
<v-text-field v-model="course.code" density="compact" hide-details label="代碼" variant="outlined" />
|
||||
<v-text-field
|
||||
v-model.number="course.credits"
|
||||
:model-value="course.name"
|
||||
density="compact"
|
||||
hide-details
|
||||
label="課程名稱"
|
||||
variant="outlined"
|
||||
@update:model-value="updateCourseField(idx, 'name', $event)"
|
||||
/>
|
||||
<v-text-field
|
||||
:model-value="course.code"
|
||||
density="compact"
|
||||
hide-details
|
||||
label="代碼"
|
||||
variant="outlined"
|
||||
@update:model-value="updateCourseField(idx, 'code', $event)"
|
||||
/>
|
||||
<v-text-field
|
||||
:model-value="course.credits"
|
||||
density="compact"
|
||||
hide-details
|
||||
label="學分"
|
||||
type="number"
|
||||
variant="outlined"
|
||||
@update:model-value="updateCourseField(idx, 'credits', toNumber($event))"
|
||||
/>
|
||||
<v-text-field
|
||||
v-model.number="course.score"
|
||||
:model-value="course.score"
|
||||
density="compact"
|
||||
hide-details
|
||||
label="分數"
|
||||
type="number"
|
||||
variant="outlined"
|
||||
@update:model-value="updateCourseField(idx, 'score', toNumber($event))"
|
||||
/>
|
||||
</div>
|
||||
</v-card>
|
||||
@@ -189,23 +207,47 @@
|
||||
<tbody>
|
||||
<tr v-for="(course, idx) in detailForm.courses" :key="idx">
|
||||
<td class="px-0 text-center">
|
||||
<v-btn color="error" icon="mdi-delete" size="small" variant="text" @click="$emit('remove-course', idx)" />
|
||||
<v-btn color="error" :icon="mdiDelete" size="small" variant="text" @click="removeCourse(idx)" />
|
||||
</td>
|
||||
<td class="py-2">
|
||||
<v-text-field v-model="course.name" class="mb-1" density="compact" hide-details label="課程名稱" variant="underlined" />
|
||||
<v-text-field v-model="course.code" density="compact" hide-details label="代碼" style="font-size: 0.85em" variant="underlined" />
|
||||
<v-text-field
|
||||
:model-value="course.name"
|
||||
class="mb-1"
|
||||
density="compact"
|
||||
hide-details
|
||||
label="課程名稱"
|
||||
variant="underlined"
|
||||
@update:model-value="updateCourseField(idx, 'name', $event)"
|
||||
/>
|
||||
<v-text-field
|
||||
:model-value="course.code"
|
||||
density="compact"
|
||||
hide-details
|
||||
label="代碼"
|
||||
style="font-size: 0.85em"
|
||||
variant="underlined"
|
||||
@update:model-value="updateCourseField(idx, 'code', $event)"
|
||||
/>
|
||||
</td>
|
||||
<td class="align-top py-2">
|
||||
<v-text-field
|
||||
v-model.number="course.credits"
|
||||
:model-value="course.credits"
|
||||
density="compact"
|
||||
hide-details
|
||||
type="number"
|
||||
variant="outlined"
|
||||
@update:model-value="updateCourseField(idx, 'credits', toNumber($event))"
|
||||
/>
|
||||
</td>
|
||||
<td class="align-top py-2">
|
||||
<v-text-field v-model.number="course.score" density="compact" hide-details type="number" variant="outlined" />
|
||||
<v-text-field
|
||||
:model-value="course.score"
|
||||
density="compact"
|
||||
hide-details
|
||||
type="number"
|
||||
variant="outlined"
|
||||
@update:model-value="updateCourseField(idx, 'score', toNumber($event))"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-if="detailForm.courses.length === 0">
|
||||
@@ -219,6 +261,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { mdiArrowLeft, mdiClose, mdiDelete, mdiPencil, mdiPlus } from '@mdi/js'
|
||||
import type { SemesterRecord } from '@/stores/semesters'
|
||||
|
||||
import { computed } from 'vue'
|
||||
@@ -231,7 +274,7 @@ const props = defineProps<{
|
||||
isMobile: boolean
|
||||
}>()
|
||||
|
||||
defineEmits<{
|
||||
const emit = defineEmits<{
|
||||
(event: 'close'): void
|
||||
(event: 'start-edit'): void
|
||||
(event: 'delete', id: number): void
|
||||
@@ -239,8 +282,64 @@ defineEmits<{
|
||||
(event: 'save-edit'): void
|
||||
(event: 'add-course'): void
|
||||
(event: 'remove-course', index: number): void
|
||||
(event: 'update:detail-form', value: SemesterRecord | null): void
|
||||
}>()
|
||||
|
||||
function cloneDetailForm (form: SemesterRecord): SemesterRecord {
|
||||
return {
|
||||
...form,
|
||||
courses: form.courses.map((course) => ({ ...course })),
|
||||
}
|
||||
}
|
||||
|
||||
function emitDetailFormUpdate (updater: (draft: SemesterRecord) => void) {
|
||||
if (!props.detailForm) return
|
||||
const nextForm = cloneDetailForm(props.detailForm)
|
||||
updater(nextForm)
|
||||
emit('update:detail-form', nextForm)
|
||||
}
|
||||
|
||||
function updateDetailFormField<K extends keyof SemesterRecord> (key: K, value: SemesterRecord[K]) {
|
||||
emitDetailFormUpdate((draft) => {
|
||||
draft[key] = value
|
||||
})
|
||||
}
|
||||
|
||||
function updateCourseField<K extends keyof SemesterRecord['courses'][number]>(
|
||||
index: number,
|
||||
key: K,
|
||||
value: SemesterRecord['courses'][number][K],
|
||||
) {
|
||||
emitDetailFormUpdate((draft) => {
|
||||
const course = draft.courses[index]
|
||||
if (!course) return
|
||||
course[key] = value
|
||||
})
|
||||
}
|
||||
|
||||
function toNumber (value: unknown): number {
|
||||
if (typeof value === 'number') return value
|
||||
const parsed = Number(value)
|
||||
return Number.isFinite(parsed) ? parsed : 0
|
||||
}
|
||||
|
||||
function addCourse () {
|
||||
emitDetailFormUpdate((draft) => {
|
||||
draft.courses.push({
|
||||
code: '',
|
||||
name: '',
|
||||
credits: 3,
|
||||
score: 0,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function removeCourse (index: number) {
|
||||
emitDetailFormUpdate((draft) => {
|
||||
draft.courses.splice(index, 1)
|
||||
})
|
||||
}
|
||||
|
||||
const totalCredits = computed(() =>
|
||||
props.selectedSemester?.courses.reduce((sum, course) => sum + course.credits, 0) ?? 0,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user