commit 22a572792054d38ca64ba41943643fbc2415b4e7 Author: v0 Date: Sun Sep 21 15:28:35 2025 +0000 Initialized repository for project AI scoring application Co-authored-by: 吳佩庭 <190080258+WuPeiTing0919@users.noreply.github.com> diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f650315 --- /dev/null +++ b/.gitignore @@ -0,0 +1,27 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules + +# next.js +/.next/ +/out/ + +# production +/build + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.pnpm-debug.log* + +# env files +.env* + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..1a7cb1c --- /dev/null +++ b/README.md @@ -0,0 +1,30 @@ +# AI scoring application + +*Automatically synced with your [v0.app](https://v0.app) deployments* + +[![Deployed on Vercel](https://img.shields.io/badge/Deployed%20on-Vercel-black?style=for-the-badge&logo=vercel)](https://vercel.com/pettys-projects/v0-ai-scoring-application) +[![Built with v0](https://img.shields.io/badge/Built%20with-v0.app-black?style=for-the-badge)](https://v0.app/chat/projects/0LR55VqrLTi) + +## Overview + +This repository will stay in sync with your deployed chats on [v0.app](https://v0.app). +Any changes you make to your deployed app will be automatically pushed to this repository from [v0.app](https://v0.app). + +## Deployment + +Your project is live at: + +**[https://vercel.com/pettys-projects/v0-ai-scoring-application](https://vercel.com/pettys-projects/v0-ai-scoring-application)** + +## Build your app + +Continue building your app on: + +**[https://v0.app/chat/projects/0LR55VqrLTi](https://v0.app/chat/projects/0LR55VqrLTi)** + +## How It Works + +1. Create and modify your project using [v0.app](https://v0.app) +2. Deploy your chats from the v0 interface +3. Changes are automatically pushed to this repository +4. Vercel deploys the latest version from this repository \ No newline at end of file diff --git a/app/client-layout.tsx b/app/client-layout.tsx new file mode 100644 index 0000000..1e75b21 --- /dev/null +++ b/app/client-layout.tsx @@ -0,0 +1,22 @@ +"use client" + +import type React from "react" + +import { Analytics } from "@vercel/analytics/next" +import { useSearchParams } from "next/navigation" +import { Suspense } from "react" + +export default function ClientLayout({ + children, +}: Readonly<{ + children: React.ReactNode +}>) { + const searchParams = useSearchParams() + + return ( + <> + Loading...}>{children} + + + ) +} diff --git a/app/criteria/page.tsx b/app/criteria/page.tsx new file mode 100644 index 0000000..eafbf0e --- /dev/null +++ b/app/criteria/page.tsx @@ -0,0 +1,293 @@ +"use client" + +import { useState } from "react" +import { Sidebar } from "@/components/sidebar" +import { Button } from "@/components/ui/button" +import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card" +import { Input } from "@/components/ui/input" +import { Label } from "@/components/ui/label" +import { Textarea } from "@/components/ui/textarea" +import { Slider } from "@/components/ui/slider" +import { Badge } from "@/components/ui/badge" +import { Plus, Trash2, Save, RotateCcw, FileText } from "lucide-react" +import { useToast } from "@/hooks/use-toast" + +interface CriteriaItem { + id: string + name: string + description: string + weight: number + maxScore: number +} + +const defaultCriteria: CriteriaItem[] = [ + { + id: "1", + name: "內容品質", + description: "內容的準確性、完整性和專業度", + weight: 25, + maxScore: 10, + }, + { + id: "2", + name: "視覺設計", + description: "版面設計、色彩搭配和視覺效果", + weight: 20, + maxScore: 10, + }, + { + id: "3", + name: "邏輯結構", + description: "內容組織的邏輯性和條理性", + weight: 20, + maxScore: 10, + }, + { + id: "4", + name: "創新性", + description: "創意思維和獨特觀點的展現", + weight: 15, + maxScore: 10, + }, + { + id: "5", + name: "實用性", + description: "內容的實際應用價值和可操作性", + weight: 20, + maxScore: 10, + }, +] + +export default function CriteriaPage() { + const [criteria, setCriteria] = useState(defaultCriteria) + const [templateName, setTemplateName] = useState("預設評分標準") + const { toast } = useToast() + + const addCriteria = () => { + const newCriteria: CriteriaItem = { + id: Date.now().toString(), + name: "", + description: "", + weight: 10, + maxScore: 10, + } + setCriteria([...criteria, newCriteria]) + } + + const removeCriteria = (id: string) => { + setCriteria(criteria.filter((item) => item.id !== id)) + } + + const updateCriteria = (id: string, field: keyof CriteriaItem, value: string | number) => { + setCriteria(criteria.map((item) => (item.id === id ? { ...item, [field]: value } : item))) + } + + const updateWeight = (id: string, weight: number[]) => { + updateCriteria(id, "weight", weight[0]) + } + + const totalWeight = criteria.reduce((sum, item) => sum + item.weight, 0) + + const saveCriteria = () => { + if (totalWeight !== 100) { + toast({ + title: "權重設定錯誤", + description: "所有評分項目的權重總和必須等於 100%", + variant: "destructive", + }) + return + } + + if (criteria.some((item) => !item.name.trim())) { + toast({ + title: "設定不完整", + description: "請填寫所有評分項目的名稱", + variant: "destructive", + }) + return + } + + // 這裡會連接到後端 API 儲存評分標準 + toast({ + title: "儲存成功", + description: "評分標準已成功儲存", + }) + } + + const resetToDefault = () => { + setCriteria(defaultCriteria) + setTemplateName("預設評分標準") + toast({ + title: "已重置", + description: "評分標準已重置為預設值", + }) + } + + return ( +
+ + +
+
+ {/* Header */} +
+

評分標準設定

+

自定義評分項目和權重,建立符合您需求的評審標準

+
+ + {/* Template Name */} + + + + + 標準模板名稱 + + + + setTemplateName(e.target.value)} + placeholder="輸入評分標準名稱" + className="max-w-md" + /> + + + + {/* Weight Summary */} + + +
+ 權重總計 + {totalWeight}% +
+
+
+
+ {totalWeight !== 100 &&

權重總和必須等於 100%

} + + + + {/* Criteria List */} +
+ {criteria.map((item, index) => ( + + +
+ 評分項目 {index + 1} + +
+
+ +
+
+ + updateCriteria(item.id, "name", e.target.value)} + placeholder="例如:內容品質" + /> +
+
+ + updateCriteria(item.id, "maxScore", Number.parseInt(e.target.value) || 10)} + min="1" + max="100" + /> +
+
+ +
+ +