11<script setup lang="ts">
2+ import type { AllClubs } from ' @@/types/api/user/all_clubs'
3+ import type { MyRecords } from ' @@/types/api/cas/record/my'
24import Announcements from ' @/components/custom/Index/announcements.vue'
5+ import { Card , CardContent , CardDescription , CardHeader , CardTitle } from ' @/components/ui/card'
6+ import { Skeleton } from ' @/components/ui/skeleton'
7+ import { useUser } from ' vue-clerk'
38
49definePageMeta ({
510 middleware: [' auth' ],
@@ -10,26 +15,181 @@ useHead({
1015 title: ' Home | Enspire' ,
1116})
1217
18+ const { user } = useUser ()
1319const now = new Date ().getHours ()
20+
21+ // Get user's clubs
22+ const { data : clubs } = useQuery <AllClubs >({
23+ queryKey: [' /api/user/all_clubs' ],
24+ })
25+
26+ // Track total CAS hours
27+ const isLoading = ref (true )
28+ const totalCASHours = ref (0 )
29+
30+ watch (clubs , async () => {
31+ isLoading .value = true
32+ if (clubs .value ?.president ?.length || clubs .value ?.vice ?.length ) {
33+ let total = 0
34+ for (const club of [... (clubs .value .president || []), ... (clubs .value .vice || [])]) {
35+ const { data } = await useFetch <MyRecords >(` /api/cas/record/my?club=${club .id } ` )
36+ if (data .value ) {
37+ total += data .value .data .reduce ((sum , record ) => {
38+ return sum + record .cTime + record .aTime + record .sTime
39+ }, 0 )
40+ }
41+ }
42+ totalCASHours .value = total
43+ }
44+ isLoading .value = false
45+ }, { immediate: true })
1446 </script >
1547
1648<template >
17- <div class =" text-3xl font-bold" >
18- {{
19- now < 5 ? '晚上好!'
20- : now < 12 ? '早上好!'
21- : now < 13 ? '中午好!'
22- : now < 18 ? '下午好!' : '晚上好!'
23- }}
24- </div >
25- <div class =" text-muted-foreground" >
26- Welcome to Enspire!
27- </div >
28- <div class =" mt-7 space-y-2" >
29- <Announcements />
30- </div >
31- </template >
49+ <div class =" space-y-6" >
50+
51+ <!-- Welcome Section -->
52+ <div >
53+ <div class =" text-3xl font-bold" >
54+ {{
55+ now < 5 ? '晚上好!'
56+ : now < 12 ? '早上好!'
57+ : now < 13 ? '中午好!'
58+ : now < 18 ? '下午好!' : '晚上好!'
59+ }}
60+ </div >
61+ <div class =" text-muted-foreground" >
62+ Welcome to Enspire!
63+ </div >
64+ </div >
3265
33- <style scoped>
66+ <!-- Quick Stats -->
67+ <div class =" grid gap-4 md:grid-cols-2 lg:grid-cols-3" >
68+ <Card class =" transition-all hover:shadow-md hover:bg-muted/50" >
69+ <CardHeader >
70+ <CardTitle class =" flex items-center gap-2" >
71+ <Icon name =" lucide:users" class =" h-5 w-5 text-primary" />
72+ 我的社团
73+ </CardTitle >
74+ </CardHeader >
75+ <CardContent >
76+ <div v-if =" isLoading" class =" space-y-2" >
77+ <Skeleton class =" h-8 w-16" />
78+ <Skeleton class =" h-4 w-32" />
79+ </div >
80+ <div v-else >
81+ <div class =" text-2xl font-bold" >
82+ {{ (clubs?.president?.length || 0) + (clubs?.vice?.length || 0) + (clubs?.member?.length || 0) }}
83+ </div >
84+ <p class =" mt-1 text-xs text-muted-foreground" >总计参与社团数量</p >
85+ </div >
86+ </CardContent >
87+ </Card >
3488
35- </style >
89+ <Card class =" transition-all hover:shadow-md hover:bg-muted/50" >
90+ <CardHeader >
91+ <CardTitle class =" flex items-center gap-2" >
92+ <Icon name =" lucide:star" class =" h-5 w-5 text-primary" />
93+ 管理社团
94+ </CardTitle >
95+ </CardHeader >
96+ <CardContent >
97+ <div v-if =" isLoading" class =" space-y-2" >
98+ <Skeleton class =" h-8 w-16" />
99+ <Skeleton class =" h-4 w-32" />
100+ </div >
101+ <div v-else >
102+ <div class =" text-2xl font-bold" >
103+ {{ (clubs?.president?.length || 0) + (clubs?.vice?.length || 0) }}
104+ </div >
105+ <p class =" mt-1 text-xs text-muted-foreground" >担任社长或副社长的社团数量</p >
106+ </div >
107+ </CardContent >
108+ </Card >
109+
110+ <Card class =" transition-all hover:shadow-md hover:bg-muted/50" >
111+ <CardHeader >
112+ <CardTitle class =" flex items-center gap-2" >
113+ <Icon name =" lucide:clock" class =" h-5 w-5 text-primary" />
114+ 活动记录时间
115+ </CardTitle >
116+ </CardHeader >
117+ <CardContent >
118+ <div v-if =" isLoading" class =" space-y-2" >
119+ <Skeleton class =" h-8 w-16" />
120+ <Skeleton class =" h-4 w-32" />
121+ </div >
122+ <div v-else >
123+ <div class =" text-2xl font-bold" >
124+ {{ totalCASHours }}
125+ </div >
126+ <p class =" mt-1 text-xs text-muted-foreground" >总计活动时间(小时)</p >
127+ </div >
128+ </CardContent >
129+ </Card >
130+ </div >
131+
132+ <!-- Quick Actions -->
133+ <div >
134+ <h2 class =" mb-4 text-lg font-semibold flex items-center gap-2" >
135+ <Icon name =" lucide:zap" class =" h-5 w-5" />
136+ 快捷操作
137+ </h2 >
138+ <div class =" grid gap-4 md:grid-cols-2 lg:grid-cols-3" >
139+ <NuxtLink to =" /cas/clubs" class =" group" >
140+ <Card class =" transition-all hover:bg-muted/50 hover:shadow-md" >
141+ <CardHeader >
142+ <CardTitle class =" flex items-center gap-2" >
143+ <Icon name =" lucide:map" class =" h-5 w-5" />
144+ 浏览社团
145+ </CardTitle >
146+ <CardDescription class =" flex items-center" >
147+ 查看所有社团信息
148+ <Icon name =" lucide:arrow-right" class =" ml-1 h-4 w-4 transition-transform group-hover:translate-x-1" />
149+ </CardDescription >
150+ </CardHeader >
151+ </Card >
152+ </NuxtLink >
153+
154+ <NuxtLink to =" /forms" class =" group" >
155+ <Card class =" transition-all hover:bg-muted/50 hover:shadow-md" >
156+ <CardHeader >
157+ <CardTitle class =" flex items-center gap-2" >
158+ <Icon name =" lucide:clipboard" class =" h-5 w-5" />
159+ 填写表单
160+ </CardTitle >
161+ <CardDescription class =" flex items-center" >
162+ 查看待填写的表单
163+ <Icon name =" lucide:arrow-right" class =" ml-1 h-4 w-4 transition-transform group-hover:translate-x-1" />
164+ </CardDescription >
165+ </CardHeader >
166+ </Card >
167+ </NuxtLink >
168+
169+ <NuxtLink to =" /manage/statuses" class =" group" >
170+ <Card class =" transition-all hover:bg-muted/50 hover:shadow-md" >
171+ <CardHeader >
172+ <CardTitle class =" flex items-center gap-2" >
173+ <Icon name =" lucide:door-open" class =" h-5 w-5" />
174+ 教室状态
175+ </CardTitle >
176+ <CardDescription class =" flex items-center" >
177+ 查看教室预约状态
178+ <Icon name =" lucide:arrow-right" class =" ml-1 h-4 w-4 transition-transform group-hover:translate-x-1" />
179+ </CardDescription >
180+ </CardHeader >
181+ </Card >
182+ </NuxtLink >
183+ </div >
184+ </div >
185+
186+ <!-- Announcements Section -->
187+ <div >
188+ <h2 class =" mb-4 text-lg font-semibold flex items-center gap-2" >
189+ <Icon name =" lucide:megaphone" class =" h-5 w-5" />
190+ 公告
191+ </h2 >
192+ <Announcements />
193+ </div >
194+ </div >
195+ </template >
0 commit comments