Skip to content

Commit cf15286

Browse files
authored
refactor!: use shadcn sidebar (#661)
* refactor!: use shadcn sidebar * chore: cleanup comment * update icons * add `@iconify-json/lucide` to deps * change `<SidebarTrigger />` icon * enspire info dropdown * sidebar blur background * move options * update breadcrumbs * add changeset
1 parent 181c843 commit cf15286

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

76 files changed

+3505
-993
lines changed

.changeset/healthy-houses-remember.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
"enspire": minor
3+
---
4+
<br />
5+
**Welcome to Enspire v1.3.0!**
6+
7+
This version introduces redesign of the sidebar.

app/app.vue

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,15 @@
1-
<script setup lang="ts">
1+
<script setup lang=ts>
2+
import { useFavicon, usePreferredDark } from '@vueuse/core'
23
import { ConfigProvider } from 'radix-vue'
34
import { useClerkProvider } from 'vue-clerk'
5+
46
import '@unocss/reset/tailwind-compat.css'
57
8+
const isDark = usePreferredDark()
9+
const favicon = computed(() => isDark.value ? '/favicon-dark.ico' : '/favicon.ico')
10+
11+
useFavicon(favicon)
12+
613
const { isClerkLoaded } = useClerkProvider()
714
815
const useIdFunction = () => useId()
@@ -19,8 +26,6 @@ useHead({
1926

2027
<template>
2128
<ConfigProvider :use-id="useIdFunction">
22-
<NuxtLoadingIndicator />
23-
<VitePwaManifest />
2429
<div v-if="!isClerkLoaded || isEnspireLoading" class="absolute z-100 h-screen w-screen bg-background">
2530
<div class="h-full w-full flex flex-col items-center justify-center space-y-6">
2631
<div class="flex justify-center space-x-1">
@@ -32,9 +37,13 @@ useHead({
3237
<Icon name="svg-spinners:3-dots-fade" size="2em" />
3338
</div>
3439
</div>
35-
<NuxtLayout class="z-10">
36-
<NuxtPage />
37-
</NuxtLayout>
40+
<div>
41+
<NuxtLayout class="z-10">
42+
<NuxtLoadingIndicator />
43+
<VitePwaManifest />
44+
<NuxtPage />
45+
</NuxtLayout>
46+
</div>
3847
</ConfigProvider>
3948
</template>
4049

@@ -82,6 +91,14 @@ useHead({
8291
/* change to any hsl value you want */
8392
--vis-primary-color: 160 81% 40%;
8493
--vis-text-color: var(--muted-foreground);
94+
--sidebar-background: 0 0% 98%;
95+
--sidebar-foreground: 240 5.3% 26.1%;
96+
--sidebar-primary: 240 5.9% 10%;
97+
--sidebar-primary-foreground: 0 0% 98%;
98+
--sidebar-accent: 240 4.8% 95.9%;
99+
--sidebar-accent-foreground: 240 5.9% 10%;
100+
--sidebar-border: 220 13% 91%;
101+
--sidebar-ring: 217.2 91.2% 59.8%;
85102
}
86103
}
87104
@@ -113,9 +130,16 @@ useHead({
113130
--vis-tooltip-backdrop-filter: none !important;
114131
--vis-tooltip-padding: none !important;
115132
--vis-secondary-color: var(--primary);
116-
/* change to any hsl value you want */
117133
--vis-primary-color: 160 81% 40%;
118134
--vis-text-color: var(--muted-foreground);
135+
--sidebar-background: 240 5.9% 10%;
136+
--sidebar-foreground: 240 4.8% 95.9%;
137+
--sidebar-primary: 224.3 76.3% 48%;
138+
--sidebar-primary-foreground: 0 0% 100%;
139+
--sidebar-accent: 240 3.7% 15.9%;
140+
--sidebar-accent-foreground: 240 4.8% 95.9%;
141+
--sidebar-border: 240 3.7% 15.9%;
142+
--sidebar-ring: 217.2 91.2% 59.8%;
119143
}
120144
}
121145
</style>

app/components/custom/CAS/ClassroomReservation/NewClassroomReservation.vue

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ const { data, suspense } = useQuery<ClassroomData[]>({
1919
queryKey: ['/api/reservation/classroomId'],
2020
})
2121
await suspense()
22+
const sortedClassroomData = ref<ClassroomData[]>()
2223
2324
if (!data.value) {
2425
toast({
@@ -27,7 +28,7 @@ if (!data.value) {
2728
})
2829
}
2930
else {
30-
data.value = data.value.sort((a: any, b: any) => a.name < b.name ? -1 : 1)
31+
sortedClassroomData.value = [...data.value].sort((a: any, b: any) => a.name < b.name ? -1 : 1)
3132
}
3233
3334
const { data: clubs, suspense: clubsSuspense } = useQuery<AllClubs>({
@@ -78,7 +79,7 @@ async function handleSubmit(e: any) {
7879
}
7980
pending.value = true
8081
try {
81-
const { data, error } = await useFetch('/api/reservation/new', {
82+
const { data: submitData, error } = await useFetch('/api/reservation/new', {
8283
method: 'POST',
8384
headers: {
8485
'Content-Type': 'application/json',
@@ -92,7 +93,7 @@ async function handleSubmit(e: any) {
9293
variant: 'destructive',
9394
})
9495
}
95-
else if (data.value?.status === 'SUCCESS') {
96+
else if (submitData.value?.status === 'SUCCESS') {
9697
toast({
9798
title: '创建成功',
9899
description: '已成功创建预约记录,你可以在「管理预约」中查看',
@@ -106,7 +107,7 @@ async function handleSubmit(e: any) {
106107
formData.value.applicant = ''
107108
formData.value.note = ''
108109
}
109-
else if (data.value?.status === 'PRISMA_ERROR') {
110+
else if (submitData.value?.status === 'PRISMA_ERROR') {
110111
toast({
111112
title: '数据错误',
112113
description: '请稍后再试',
@@ -132,15 +133,15 @@ async function handleSubmit(e: any) {
132133
<CardDescription>在此处预约教室</CardDescription>
133134
</CardHeader>
134135
<CardContent>
135-
<form class="space-y-2" @submit="handleSubmit">
136+
<Form class="space-y-2" @submit="handleSubmit">
136137
<FormField name="main">
137138
<FormItem>
138139
<FormLabel>预约时间</FormLabel>
139140
<FormControl>
140-
<div class="flex flex-col sm:flex-row space-y-2 sm:space-y-0 sm:space-x-1 justify-start">
141+
<div class="flex flex-col justify-start sm:flex-row space-y-2 sm:space-x-1 sm:space-y-0">
141142
<!-- This ToggleGroup should be implemented in a better way but anyway it works -->
142-
<ToggleGroup :key="reloadKey" type="multiple" variant="outline">
143-
<div class="text-muted-foreground text-sm text-center w-7">
143+
<ToggleGroup :key="`reloadKey-${reloadKey}`" type="multiple" variant="outline">
144+
<div class="w-7 text-center text-sm text-muted-foreground">
144145
每周
145146
</div>
146147
<ToggleGroupItem value="mon" @click="day[1] = !day[1]">
@@ -164,7 +165,7 @@ async function handleSubmit(e: any) {
164165
<SelectValue placeholder="选择时段" />
165166
</SelectTrigger>
166167
<SelectContent>
167-
<SelectItem v-for="period in enums.periods.values" :key="period" :value="period">
168+
<SelectItem v-for="period in enums.periods.values" :key="`period-${period}`" :value="period">
168169
{{ enums.periods.map[period] }}
169170
</SelectItem>
170171
</SelectContent>
@@ -175,7 +176,7 @@ async function handleSubmit(e: any) {
175176
<div class="py-1" />
176177
<FormItem>
177178
<FormLabel>选择教室</FormLabel>
178-
<div v-if="!clubs || !data">
179+
<div v-if="!clubs || !sortedClassroomData">
179180
<Skeleton class="h-5 p-3 my-3" />
180181
</div>
181182
<FormControl>
@@ -185,7 +186,7 @@ async function handleSubmit(e: any) {
185186
</SelectTrigger>
186187
<!-- Only available classrooms should be filled in the following <SelectContent/> -->
187188
<SelectContent>
188-
<SelectGroup v-for="classroom in data" :key="classroom.id">
189+
<SelectGroup v-for="classroom in sortedClassroomData" :key="`classroom-${classroom.id}`">
189190
<SelectItem :value="classroom.id.toString()">
190191
<span class="inline-block min-w-32 text-left">
191192
<span class="inline-block min-w-14">
@@ -214,23 +215,23 @@ async function handleSubmit(e: any) {
214215
</SelectTrigger>
215216
<SelectContent>
216217
<SelectGroup v-if="clubs?.president && clubs?.president.length">
217-
<SelectItem v-for="club in clubs?.president" :key="club.id" :value="club.id">
218+
<SelectItem v-for="club in clubs?.president" :key="`club-${club.id}`" :value="String(club.id)">
218219
{{ club.name.zh }}
219220
<span class="inline-block text-gray-500">
220221
社长
221222
</span>
222223
</SelectItem>
223224
</SelectGroup>
224225
<SelectGroup v-if="clubs?.vice && clubs?.vice.length">
225-
<SelectItem v-for="club in clubs?.vice" :key="club.id" :value="club.id">
226+
<SelectItem v-for="club in clubs?.vice" :key="`club-${club.id}`" :value="String(club.id)">
226227
{{ club.name.zh }}
227228
<span class="inline-block text-gray-500">
228229
副社
229230
</span>
230231
</SelectItem>
231232
</SelectGroup>
232233
<SelectGroup v-if="clubs?.member && clubs?.member.length">
233-
<SelectItem v-for="club in clubs?.member" :key="club.id" :value="club.id">
234+
<SelectItem v-for="club in clubs?.member" :key="`club-${club.id}`" :value="String(club.id)">
234235
{{ club.name.zh }}
235236
<span class="inline-block text-gray-500">
236237
成员
@@ -260,7 +261,7 @@ async function handleSubmit(e: any) {
260261
<span v-if="!pending">提交预约</span>
261262
<span v-if="pending">处理中...</span>
262263
</Button>
263-
</form>
264+
</Form>
264265
</CardContent>
265266
</Card>
266267
</template>

app/components/custom/breadcrumb.vue

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<script setup lang="ts">
2+
import type { RouteRecordNormalized } from 'vue-router'
3+
4+
const route = useRoute()
5+
const router = useRouter()
6+
const breadcrumbs = ref<RouteRecordNormalized[]>()
7+
8+
watch(() => route.path, () => {
9+
breadcrumbs.value = []
10+
const fullPath = route.path
11+
const requestPath = fullPath.startsWith('/')
12+
? fullPath.substring(1)
13+
: fullPath
14+
const crumbs = requestPath.split('/')
15+
let path = ''
16+
crumbs.forEach((crumb) => {
17+
if (crumb) {
18+
path = `${path}/${crumb}`
19+
const breadcrumb = router.getRoutes().find(r => r.path === path)
20+
if (breadcrumb && breadcrumbs.value) {
21+
breadcrumbs.value.push(breadcrumb)
22+
}
23+
}
24+
})
25+
console.log(breadcrumbs.value)
26+
}, { immediate: true })
27+
</script>
28+
29+
<template>
30+
<Breadcrumb>
31+
<BreadcrumbList>
32+
<BreadcrumbItem class="hidden md:block">
33+
<BreadcrumbLink to="/">
34+
Enspire
35+
</BreadcrumbLink>
36+
</BreadcrumbItem>
37+
<template v-for="(breadcrumb, index) in breadcrumbs" :key="`breadcrumb-${String(index)}`">
38+
<BreadcrumbSeparator class="hidden md:block" />
39+
<BreadcrumbItem class="hidden md:block">
40+
<BreadcrumbLink :href="breadcrumb!.path">
41+
{{ breadcrumb!.meta.breadcrumb ?? breadcrumb.path.split('/').pop() }}
42+
</BreadcrumbLink>
43+
</BreadcrumbItem>
44+
</template>
45+
</BreadcrumbList>
46+
</Breadcrumb>
47+
</template>

0 commit comments

Comments
 (0)