style: course
This commit is contained in:
@@ -164,13 +164,18 @@
|
||||
|
||||
<!-- 運動時間建議:對應 doc/運動時間建議.png -->
|
||||
<v-card class="rounded-lg elevation-1 mt-4 overflow-hidden">
|
||||
<v-card-title class="text-title-medium font-weight-bold text-primary d-flex align-center">
|
||||
<v-expansion-panels v-model="durationTablePanel" flat variant="accordion">
|
||||
<v-expansion-panel value="duration">
|
||||
<v-expansion-panel-title
|
||||
class="course-table-panel-title text-title-medium font-weight-bold text-primary"
|
||||
>
|
||||
<v-icon class="mr-2" color="primary" icon="mdi-timer-outline" size="20" />
|
||||
運動時間建議
|
||||
</v-card-title>
|
||||
</v-expansion-panel-title>
|
||||
|
||||
<v-divider />
|
||||
|
||||
<v-expansion-panel-text class="pa-0">
|
||||
<v-table class="course-table" density="comfortable">
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -198,9 +203,24 @@
|
||||
</tr>
|
||||
</tbody>
|
||||
</v-table>
|
||||
</v-expansion-panel-text>
|
||||
</v-expansion-panel>
|
||||
</v-expansion-panels>
|
||||
</v-card>
|
||||
|
||||
<v-card class="rounded-lg elevation-1 mt-4 overflow-hidden">
|
||||
<v-expansion-panels v-model="scheduleTablePanel" flat variant="accordion">
|
||||
<v-expansion-panel value="schedule">
|
||||
<v-expansion-panel-title
|
||||
class="course-table-panel-title text-title-medium font-weight-bold text-primary"
|
||||
>
|
||||
<v-icon class="mr-2" color="primary" icon="mdi-timer-outline" size="20" />
|
||||
運動課表
|
||||
</v-expansion-panel-title>
|
||||
|
||||
<v-divider />
|
||||
|
||||
<v-expansion-panel-text class="pa-0">
|
||||
<v-table class="course-table" density="comfortable">
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -247,6 +267,9 @@
|
||||
</tr>
|
||||
</tbody>
|
||||
</v-table>
|
||||
</v-expansion-panel-text>
|
||||
</v-expansion-panel>
|
||||
</v-expansion-panels>
|
||||
</v-card>
|
||||
|
||||
<v-card class="rounded-lg elevation-1 mt-4 overflow-hidden">
|
||||
@@ -275,6 +298,10 @@ const detail = computed(() => COURSE_DETAIL[store.group])
|
||||
// 課程說明預設只展開第一個面板(族群特徵)
|
||||
const openPanels = ref([0])
|
||||
|
||||
// 兩張表格預設展開,使用者可分別收合以減少頁面長度。
|
||||
const durationTablePanel = ref<string | null>('duration')
|
||||
const scheduleTablePanel = ref<string | null>('schedule')
|
||||
|
||||
const GROUP_ILLUSTRATIONS: Record<FitnessGroup, string> = {
|
||||
low: lowIllustration,
|
||||
medium: mediumIllustration,
|
||||
@@ -291,7 +318,7 @@ const DAY_NAMES = ['一', '二', '三', '四', '五', '六', '日']
|
||||
// 課表小卡:檔名為「星期-時段」,逐一匯入 21 張圖並依 day/slot 查表取用
|
||||
const scheduleCardModules = import.meta.glob<{ default: string }>(
|
||||
'../assets/course/schedule/*.png',
|
||||
{ eager: true }
|
||||
{ eager: true },
|
||||
)
|
||||
|
||||
const SCHEDULE_CARD_DAY_KEYS = [
|
||||
@@ -313,7 +340,7 @@ const SCHEDULE_CARDS: Record<string, string> = Object.fromEntries(
|
||||
Object.entries(scheduleCardModules).map(([path, module]) => [
|
||||
path.replace(/^.*\/|\.png$/g, ''),
|
||||
module.default,
|
||||
])
|
||||
]),
|
||||
)
|
||||
|
||||
function scheduleCardImage (day: number, slot: TimeSlot): string {
|
||||
@@ -321,14 +348,14 @@ function scheduleCardImage(day: number, slot: TimeSlot): string {
|
||||
return SCHEDULE_CARDS[key]
|
||||
}
|
||||
|
||||
const SLOTS: { key: TimeSlot; label: string; icon: string; headerClass: string }[] = [
|
||||
const SLOTS: { key: TimeSlot, label: string, icon: string, headerClass: string }[] = [
|
||||
{ key: 'morning', label: '早上', icon: 'mdi-weather-sunset-up', headerClass: 'bg-deep-orange' },
|
||||
{ key: 'noon', label: '中午', icon: 'mdi-white-balance-sunny', headerClass: 'bg-amber-darken-2' },
|
||||
{ key: 'night', label: '晚上', icon: 'mdi-weather-night', headerClass: 'bg-deep-purple' },
|
||||
]
|
||||
|
||||
// 依目前選取的時段決定表格要顯示哪幾欄,順序固定為早上/中午/晚上
|
||||
const visibleSlots = computed(() => SLOTS.filter((slot) => store.selectedSlots.includes(slot.key)))
|
||||
const visibleSlots = computed(() => SLOTS.filter(slot => store.selectedSlots.includes(slot.key)))
|
||||
|
||||
// 今天對應的星期幾,換算成與 CourseRow.day 相同的規則(1 = 週一 … 7 = 週日)
|
||||
const todayDay = computed(() => {
|
||||
@@ -339,7 +366,7 @@ const todayDay = computed(() => {
|
||||
// v-btn-toggle 以陣列表達勾選狀態,store 則以 Y/N 保存,兩者在此橋接
|
||||
const selectedSlots = computed<TimeSlot[]>({
|
||||
get: () => store.selectedSlots,
|
||||
set: (value) => {
|
||||
set: value => {
|
||||
for (const slot of SLOTS) {
|
||||
const next: YesNo = value.includes(slot.key) ? 'Y' : 'N'
|
||||
store.setSlot(slot.key, next)
|
||||
@@ -359,6 +386,11 @@ onMounted(() => {
|
||||
table-layout: fixed;
|
||||
}
|
||||
|
||||
.course-table-panel-title {
|
||||
min-height: 40px;
|
||||
padding: 8px 16px;
|
||||
}
|
||||
|
||||
.day-col {
|
||||
width: 15%;
|
||||
}
|
||||
|
||||
@@ -14,17 +14,17 @@ import 'vuetify/styles'
|
||||
const HPTheme: ThemeDefinition = {
|
||||
dark: false,
|
||||
colors: {
|
||||
background: '#F0F9F6', // 頁面背景
|
||||
surface: '#FFFFFF', // 卡片與白底區塊
|
||||
primary: '#1D7063', // 主要品牌色
|
||||
'background': '#F0F9F6', // 頁面背景
|
||||
'surface': '#FFFFFF', // 卡片與白底區塊
|
||||
'primary': '#1D7063', // 主要品牌色
|
||||
'primary-darken-1': '#145248',
|
||||
secondary: '#dc5349', // CTA 按鈕
|
||||
'secondary': '#dc5349', // CTA 按鈕
|
||||
'secondary-darken-1': '#ab4c3d',
|
||||
accent: '#47C2A6', // 標籤與強調
|
||||
error: '#B00020',
|
||||
info: '#2196F3',
|
||||
success: '#4CAF50',
|
||||
warning: '#FB8C00',
|
||||
'accent': '#47C2A6', // 標籤與強調
|
||||
'error': '#B00020',
|
||||
'info': '#2196F3',
|
||||
'success': '#4CAF50',
|
||||
'warning': '#FB8C00',
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user