diff --git a/frontend/app/globals.css b/frontend/app/globals.css index a2868cf4..d5389cba 100644 --- a/frontend/app/globals.css +++ b/frontend/app/globals.css @@ -348,8 +348,9 @@ /* Gradient Page Backgrounds - Enhanced visibility */ .gradient-page-bg { - background: linear-gradient(135deg, - rgba(102, 126, 234, 0.12) 0%, + background: linear-gradient( + 135deg, + rgba(102, 126, 234, 0.12) 0%, rgba(240, 242, 255, 0.8) 25%, rgba(255, 240, 245, 0.8) 50%, rgba(245, 240, 255, 0.8) 75%, @@ -359,8 +360,9 @@ } .dark .gradient-page-bg { - background: linear-gradient(135deg, - rgba(76, 81, 191, 0.25) 0%, + background: linear-gradient( + 135deg, + rgba(76, 81, 191, 0.25) 0%, rgba(30, 30, 45, 0.95) 25%, rgba(40, 30, 45, 0.95) 50%, rgba(35, 30, 50, 0.95) 75%, @@ -531,3 +533,183 @@ border-color: rgba(76, 81, 191, 0.5); box-shadow: 0 10px 40px rgba(76, 81, 191, 0.3); } + +/* ======================================== + DATE PICKER CUSTOM STYLING + ======================================== */ + +/* Modern Date Input Styling */ +input[type="date"] { + position: relative; + padding: 0.75rem 1rem; + font-size: 1rem; + font-weight: 500; + line-height: 1.5; + color: var(--foreground); + background: linear-gradient( + 135deg, + rgba(102, 126, 234, 0.05) 0%, + rgba(118, 75, 162, 0.05) 100% + ); + border: 2px solid rgba(102, 126, 234, 0.3); + border-radius: 0.75rem; + transition: all 0.3s ease; + cursor: pointer; + backdrop-filter: blur(10px); + -webkit-backdrop-filter: blur(10px); +} + +input[type="date"]:hover { + background: linear-gradient( + 135deg, + rgba(102, 126, 234, 0.1) 0%, + rgba(118, 75, 162, 0.1) 100% + ); + border-color: rgba(102, 126, 234, 0.5); + box-shadow: 0 4px 12px rgba(102, 126, 234, 0.2); + transform: translateY(-2px); +} + +input[type="date"]:focus { + outline: none; + background: linear-gradient( + 135deg, + rgba(102, 126, 234, 0.15) 0%, + rgba(118, 75, 162, 0.15) 100% + ); + border-color: rgba(102, 126, 234, 0.6); + box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1), + 0 8px 16px rgba(102, 126, 234, 0.25); + transform: translateY(-2px); +} + +/* Dark mode date input */ +.dark input[type="date"] { + background: linear-gradient( + 135deg, + rgba(76, 81, 191, 0.15) 0%, + rgba(85, 60, 154, 0.15) 100% + ); + border-color: rgba(76, 81, 191, 0.4); +} + +.dark input[type="date"]:hover { + background: linear-gradient( + 135deg, + rgba(76, 81, 191, 0.2) 0%, + rgba(85, 60, 154, 0.2) 100% + ); + border-color: rgba(76, 81, 191, 0.6); + box-shadow: 0 4px 12px rgba(76, 81, 191, 0.3); +} + +.dark input[type="date"]:focus { + background: linear-gradient( + 135deg, + rgba(76, 81, 191, 0.25) 0%, + rgba(85, 60, 154, 0.25) 100% + ); + border-color: rgba(76, 81, 191, 0.7); + box-shadow: 0 0 0 3px rgba(76, 81, 191, 0.15), + 0 8px 16px rgba(76, 81, 191, 0.35); +} + +/* Calendar icon styling */ +input[type="date"]::-webkit-calendar-picker-indicator { + cursor: pointer; + opacity: 0.8; + padding: 0.25rem; + border-radius: 0.375rem; + transition: all 0.2s ease; + filter: brightness(0.9); +} + +input[type="date"]::-webkit-calendar-picker-indicator:hover { + opacity: 1; + background: rgba(102, 126, 234, 0.15); + transform: scale(1.1); + filter: brightness(1.1); +} + +.dark input[type="date"]::-webkit-calendar-picker-indicator { + filter: invert(1) brightness(0.9); +} + +.dark input[type="date"]::-webkit-calendar-picker-indicator:hover { + background: rgba(76, 81, 191, 0.25); + filter: invert(1) brightness(1.1); +} + +/* Date input inner elements (webkit) */ +input[type="date"]::-webkit-datetime-edit-fields-wrapper { + padding: 0; +} + +input[type="date"]::-webkit-datetime-edit-text { + padding: 0 0.25rem; + opacity: 0.7; +} + +input[type="date"]::-webkit-datetime-edit-month-field, +input[type="date"]::-webkit-datetime-edit-day-field, +input[type="date"]::-webkit-datetime-edit-year-field { + padding: 0.25rem 0.5rem; + border-radius: 0.375rem; + transition: all 0.2s ease; +} + +input[type="date"]::-webkit-datetime-edit-month-field:hover, +input[type="date"]::-webkit-datetime-edit-day-field:hover, +input[type="date"]::-webkit-datetime-edit-year-field:hover { + background: rgba(102, 126, 234, 0.2); + color: var(--foreground); +} + +input[type="date"]::-webkit-datetime-edit-month-field:focus, +input[type="date"]::-webkit-datetime-edit-day-field:focus, +input[type="date"]::-webkit-datetime-edit-year-field:focus { + background: rgba(102, 126, 234, 0.25); + color: var(--foreground); + outline: none; +} + +.dark input[type="date"]::-webkit-datetime-edit-month-field:hover, +.dark input[type="date"]::-webkit-datetime-edit-day-field:hover, +.dark input[type="date"]::-webkit-datetime-edit-year-field:hover { + background: rgba(76, 81, 191, 0.3); +} + +.dark input[type="date"]::-webkit-datetime-edit-month-field:focus, +.dark input[type="date"]::-webkit-datetime-edit-day-field:focus, +.dark input[type="date"]::-webkit-datetime-edit-year-field:focus { + background: rgba(76, 81, 191, 0.35); +} + +/* Placeholder styling when empty */ +input[type="date"]:invalid::-webkit-datetime-edit { + color: var(--muted-foreground); +} + +/* Animation for date picker open */ +@keyframes datePickerSlide { + from { + opacity: 0; + transform: translateY(-10px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +/* Additional polish */ +input[type="date"]::before { + content: attr(placeholder); + width: 100%; + color: var(--muted-foreground); +} + +input[type="date"]:focus::before, +input[type="date"]:valid::before { + display: none; +} diff --git a/frontend/components/analysis/AnalysisForm.tsx b/frontend/components/analysis/AnalysisForm.tsx index 95493e3f..c4dda477 100644 --- a/frontend/components/analysis/AnalysisForm.tsx +++ b/frontend/components/analysis/AnalysisForm.tsx @@ -58,14 +58,14 @@ const formSchema = z.object({ .url("請輸入有效的 URL") .optional() .or(z.literal("")), - quick_think_api_key: z.string().optional().or(z.literal("")), - deep_think_api_key: z.string().optional().or(z.literal("")), + quick_think_api_key: z.string().min(1, "請輸入快速思維模型 API Key"), + deep_think_api_key: z.string().min(1, "請輸入深層思維模型 API Key"), embedding_base_url: z .string() .url("請輸入有效的 URL") .optional() .or(z.literal("")), - embedding_api_key: z.string().optional().or(z.literal("")), + embedding_api_key: z.string().min(1, "請輸入嵌入模型 API Key"), alpha_vantage_api_key: z.string().min(1, "請輸入 Alpha Vantage API Key"), }); @@ -586,12 +586,12 @@ export function AnalysisForm({ onSubmit, loading = false }: AnalysisFormProps) { name="quick_think_api_key" render={({ field }) => ( - 快速思維模型 API Key + 快速思維模型 API Key * - 該模型的專屬 API Key(若留空則使用預設/環境變數) + 該模型的專屬 API Key(必填) @@ -685,12 +685,12 @@ export function AnalysisForm({ onSubmit, loading = false }: AnalysisFormProps) { name="deep_think_api_key" render={({ field }) => ( - 深層思維模型 API Key + 深層思維模型 API Key * - 該模型的專屬 API Key(若留空則使用預設/環境變數) + 該模型的專屬 API Key(必填) @@ -756,13 +756,11 @@ export function AnalysisForm({ onSubmit, loading = false }: AnalysisFormProps) { name="embedding_api_key" render={({ field }) => ( - 嵌入模型 API Key + 嵌入模型 API Key * - - 該端點的 API Key(若留空則使用環境變數 OPENAI_API_KEY) - + 該端點的 API Key(必填) )}