feat: enhance UI components and add accordion functionality

- Updated DraggableWindow.vue to improve shadow effects.
- Refactored AboutWindow.vue for better structure and readability.
- Added chatbot functionality in chatbot.vue with cookie management.
- Improved navigation component for better code clarity.
- Created a new chat history table in the database schema.
- Modified error handling in error.vue to display error messages correctly.
- Integrated ChatbotWindow into the desktop application layout.
- Implemented accordion component in home.vue for Q/A section.
- Enhanced API for chat functionality with improved error handling.
- Removed unused routes for cleaner codebase.
- Added custom animations for accordion components in tailwind.config.js.
- Developed accordion UI components (Accordion, AccordionContent, AccordionItem, AccordionTrigger) for better user interaction.
This commit is contained in:
yuanhau 2025-05-13 09:40:37 +08:00
parent f89e6aaa48
commit 5bf857f3cd
21 changed files with 402 additions and 182 deletions

View file

@ -66,7 +66,7 @@ const stopDrag = () => {
width: props.width || '400px',
height: props.height || '300px',
}"
class="fixed bg-white dark:bg-gray-800 rounded-md shadow-lg overflow-hidden flex flex-col"
class="fixed bg-white dark:bg-gray-800 rounded-md shadow-lg overflow-hidden flex flex-col shadow-lg shadow-xl/30"
>
<div
@mousedown="startDrag"

View file

@ -1,16 +1,25 @@
<template>
<div class="justify-center align-center text-center flex flex-col">
<div class="flex flex-col">
<span class=text-xl>為什麼要做網站</span>
<span>1. 台灣媒體真的很爛要嘛有超多偏見或是比較偏小孩不能看的新聞 (aka 擦邊通過的</span>
<span>2. 這個網站是為了讓大家可以更方便的比較新聞可以分析新聞的偏見</span>
<span>3. <span class="line-through"> TailwindCSS</span></span>
</div>
<hr/>
<div class="flex flex-col">
<span class=text-xl>關於開發者</span>
<span class="text-center align-center justify-center">開發者yh</span>
<span class="text-center align-center justify-center">聯絡信箱<a href="mailto:public+newscompareauthor@yuanhau.com">public@yuanhau.com</a></span>
</div>
<div class="justify-center align-center text-center flex flex-col">
<div class="flex flex-col">
<span class="text-xl">為什麼要做網站</span>
<span
>1. 台灣媒體真的很爛要嘛有超多偏見或是比較偏小孩不能看的新聞 (aka
擦邊通過的</span
>
<span
>2. 這個網站是為了讓大家可以更方便的比較新聞可以分析新聞的偏見</span
>
<span>3. <span class="line-through"> TailwindCSS</span></span>
</div>
<hr />
<div class="flex flex-col">
<span class="text-xl">關於開發者</span>
<span class="text-center align-center justify-center">開發者yh</span>
<span class="text-center align-center justify-center"
>聯絡信箱<a href="mailto:public+newscompareauthor@yuanhau.com"
>public@yuanhau.com</a
></span
>
</div>
</div>
</template>

View file

@ -1,5 +1,13 @@
<script setup lang="ts">
const { t } = useI18n();
const cookie = useCookie("lastChatId");
const lastChatId = cookie.value;
onMounted(() => {
console.log(lastChatId);
if (lastChatId) {
}
});
</script>
<template>
<div class="justify-center align-center text-center flex flex-col">
</div>
</template>
<div class="justify-center align-center text-center flex flex-col">Hi</div>
</template>

View file

@ -20,7 +20,9 @@ const toggleDropdown = () => {
class="fixed top-0 inset-x-0 bg-[#81611a]/70 backdrop-blur-sm h-[55px] flex align-center items-center flex-row text-white pl-4 gap-x-5 justify-between z-50 rounded-3xl m-2"
>
<div class="text-3xl text-bold">
<NuxtLink :to="localePath('home')" ref="title">{{ t("core.sitename") }}</NuxtLink>
<NuxtLink :to="localePath('home')" ref="title">{{
t("core.sitename")
}}</NuxtLink>
</div>
<div
class="text-[0.9em] left-1/2 absolute transform -translate-x-1/2 space-x-4 items-center"

View file

@ -0,0 +1,19 @@
<script setup lang="ts">
import {
AccordionRoot,
type AccordionRootEmits,
type AccordionRootProps,
useForwardPropsEmits,
} from "reka-ui";
const props = defineProps<AccordionRootProps>();
const emits = defineEmits<AccordionRootEmits>();
const forwarded = useForwardPropsEmits(props, emits);
</script>
<template>
<AccordionRoot v-bind="forwarded">
<slot />
</AccordionRoot>
</template>

View file

@ -0,0 +1,26 @@
<script setup lang="ts">
import { cn } from "@/lib/utils";
import { AccordionContent, type AccordionContentProps } from "reka-ui";
import { computed, type HTMLAttributes } from "vue";
const props = defineProps<
AccordionContentProps & { class?: HTMLAttributes["class"] }
>();
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props;
return delegated;
});
</script>
<template>
<AccordionContent
v-bind="delegatedProps"
class="overflow-hidden text-sm data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down"
>
<div :class="cn('pb-4 pt-0', props.class)">
<slot />
</div>
</AccordionContent>
</template>

View file

@ -0,0 +1,27 @@
<script setup lang="ts">
import { cn } from "@/lib/utils";
import {
AccordionItem,
type AccordionItemProps,
useForwardProps,
} from "reka-ui";
import { computed, type HTMLAttributes } from "vue";
const props = defineProps<
AccordionItemProps & { class?: HTMLAttributes["class"] }
>();
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props;
return delegated;
});
const forwardedProps = useForwardProps(delegatedProps);
</script>
<template>
<AccordionItem v-bind="forwardedProps" :class="cn('border-b', props.class)">
<slot />
</AccordionItem>
</template>

View file

@ -0,0 +1,41 @@
<script setup lang="ts">
import { cn } from "@/lib/utils";
import { ChevronDown } from "lucide-vue-next";
import {
AccordionHeader,
AccordionTrigger,
type AccordionTriggerProps,
} from "reka-ui";
import { computed, type HTMLAttributes } from "vue";
const props = defineProps<
AccordionTriggerProps & { class?: HTMLAttributes["class"] }
>();
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props;
return delegated;
});
</script>
<template>
<AccordionHeader class="flex">
<AccordionTrigger
v-bind="delegatedProps"
:class="
cn(
'flex flex-1 items-center justify-between py-4 text-sm font-medium transition-all hover:underline [&[data-state=open]>svg]:rotate-180',
props.class,
)
"
>
<slot />
<slot name="icon">
<ChevronDown
class="h-4 w-4 shrink-0 text-muted-foreground transition-transform duration-200"
/>
</slot>
</AccordionTrigger>
</AccordionHeader>
</template>

View file

@ -0,0 +1,4 @@
export { default as Accordion } from "./Accordion.vue";
export { default as AccordionContent } from "./AccordionContent.vue";
export { default as AccordionItem } from "./AccordionItem.vue";
export { default as AccordionTrigger } from "./AccordionTrigger.vue";