1. 新增機台異常日誌手動解除功能,包含資料庫欄位更新與 UI 操作按鈕。 2. 實作機台庫存變動紀錄系統 (Machine Stock Movements),支援追蹤補貨與銷售產生的庫存異動。 3. 重構取貨碼 (Pickup Code) 與通行碼 (Pass Code) 管理介面,採用極簡奢華風 UI 並拆分 Partial Views 提升可維護性。 4. 優化取貨操作日誌,明確區分「取貨成功」與「取貨失敗」,並加入顏色標籤增強辨識度。 5. 擴充多語系支援 (繁中、英文、日文),確保所有新功能與操作狀態均有對應翻譯。 6. 更新 IoT API 規格文件與相關 Service 邏輯,加強指令確認 (ACK) 處理機制。
550 lines
16 KiB
CSS
550 lines
16 KiB
CSS
@import 'flatpickr/dist/flatpickr.min.css';
|
|
|
|
@tailwind base;
|
|
@tailwind components;
|
|
@tailwind utilities;
|
|
|
|
@layer base {
|
|
:root {
|
|
--font-sans: 'Plus Jakarta Sans', ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
|
--font-display: 'Outfit', var(--font-sans);
|
|
--color-luxury-deep: #0f172a;
|
|
--color-luxury-card: #1e293b;
|
|
--color-accent: #06b6d4;
|
|
/* Cyan 500 */
|
|
}
|
|
|
|
html {
|
|
font-family: var(--font-sans);
|
|
}
|
|
|
|
h1,
|
|
h2,
|
|
h3,
|
|
h4,
|
|
h5,
|
|
h6,
|
|
.font-display {
|
|
font-family: var(--font-display);
|
|
letter-spacing: -0.02em;
|
|
}
|
|
|
|
/* Luxury Cards */
|
|
.luxury-card {
|
|
@apply bg-white dark:bg-[#1e293b] border-0 rounded-2xl;
|
|
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.05), 0 2px 4px -2px rgba(0, 0, 0, 0.05);
|
|
transition: transform 0.2s cubic-bezier(0.4, 0, 0.2, 1), box-shadow 0.2s cubic-bezier(0.4, 0, 0.2, 1);
|
|
}
|
|
|
|
.luxury-card:hover {
|
|
transform: translateY(-2px);
|
|
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.08), 0 8px 10px -6px rgba(0, 0, 0, 0.08);
|
|
}
|
|
|
|
/* Luxury Gradient Accents */
|
|
.bg-luxury-gradient {
|
|
background: linear-gradient(135deg, var(--color-accent), #6366f1);
|
|
}
|
|
|
|
/* Animations */
|
|
@keyframes fadeUp {
|
|
from {
|
|
opacity: 0;
|
|
transform: translateY(15px);
|
|
}
|
|
|
|
to {
|
|
opacity: 1;
|
|
transform: translateY(0);
|
|
}
|
|
}
|
|
|
|
.animate-luxury-in {
|
|
animation: fadeUp 0.6s cubic-bezier(0.34, 1.56, 0.64, 1) forwards;
|
|
}
|
|
|
|
/* Additional Loading Animations */
|
|
@keyframes fadeInRight {
|
|
from {
|
|
opacity: 0;
|
|
transform: translateX(-10px);
|
|
}
|
|
to {
|
|
opacity: 1;
|
|
transform: translateX(0);
|
|
}
|
|
}
|
|
|
|
.animate-fade-in-right {
|
|
animation: fadeInRight 0.8s ease-out forwards;
|
|
}
|
|
|
|
@keyframes trickle {
|
|
0% { width: 0%; opacity: 1; }
|
|
20% { width: 30%; }
|
|
50% { width: 70%; }
|
|
80% { width: 90%; }
|
|
95% { width: 95%; }
|
|
100% { width: 95%; }
|
|
}
|
|
|
|
.animate-trickle {
|
|
animation: trickle 10s cubic-bezier(0.1, 0.5, 0.5, 1) forwards;
|
|
}
|
|
|
|
/* Top Progress Bar (Trickle Style) */
|
|
.top-loading-bar {
|
|
@apply fixed top-0 left-0 right-0 h-0.5 z-[99999] bg-gradient-to-r from-cyan-500 to-blue-500 opacity-0 transition-opacity duration-300;
|
|
width: 0%;
|
|
}
|
|
|
|
.top-loading-bar.loading {
|
|
@apply opacity-100;
|
|
animation: trickle 12s cubic-bezier(0.1, 0.5, 0.5, 1) forwards;
|
|
}
|
|
|
|
@keyframes loadingPulse {
|
|
0% { opacity: 1; }
|
|
50% { opacity: 0.6; }
|
|
100% { opacity: 1; }
|
|
}
|
|
|
|
/* Skeleton Loading Utilities (Option C) */
|
|
.skeleton {
|
|
@apply bg-slate-100 dark:bg-slate-800 animate-pulse-subtle rounded-lg overflow-hidden relative border-none !text-transparent selection:bg-transparent pointer-events-none;
|
|
}
|
|
|
|
@keyframes pulse-subtle {
|
|
0%, 100% { opacity: 1; }
|
|
50% { opacity: 0.5; }
|
|
}
|
|
|
|
.animate-pulse-subtle {
|
|
animation: pulse-subtle 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
|
|
}
|
|
|
|
/* Custom Scrollbar - Minimal & Elegant */
|
|
::-webkit-scrollbar {
|
|
width: 6px;
|
|
height: 6px;
|
|
}
|
|
|
|
::-webkit-scrollbar-track {
|
|
background: transparent;
|
|
}
|
|
|
|
::-webkit-scrollbar-thumb {
|
|
background: #94a3b8;
|
|
border-radius: 10px;
|
|
}
|
|
|
|
.dark ::-webkit-scrollbar-thumb {
|
|
background: #334155;
|
|
}
|
|
|
|
::-webkit-scrollbar-thumb:hover {
|
|
background: #64748b;
|
|
}
|
|
|
|
/* Firefox */
|
|
* {
|
|
scrollbar-width: thin;
|
|
scrollbar-color: #94a3b8 transparent;
|
|
}
|
|
}
|
|
|
|
@layer utilities {
|
|
[x-cloak] {
|
|
display: none !important;
|
|
}
|
|
|
|
/* Hide scrollbar for Chrome, Safari and Opera */
|
|
.hide-scrollbar::-webkit-scrollbar {
|
|
display: none;
|
|
}
|
|
|
|
/* Hide scrollbar for IE, Edge and Firefox */
|
|
.hide-scrollbar {
|
|
-ms-overflow-style: none; /* IE and Edge */
|
|
scrollbar-width: none; /* Firefox */
|
|
}
|
|
}
|
|
|
|
@layer components {
|
|
.luxury-nav-item {
|
|
@apply flex items-center gap-x-3.5 py-2.5 px-4 text-sm font-semibold rounded-xl transition-all duration-200 overflow-hidden;
|
|
@apply text-slate-600 hover:text-slate-900 hover:bg-slate-100;
|
|
@apply dark:text-slate-300 dark:hover:text-white dark:hover:bg-white/5;
|
|
}
|
|
|
|
.luxury-nav-item.active {
|
|
@apply bg-slate-100 text-slate-900;
|
|
@apply dark:bg-white/10 dark:text-white;
|
|
position: relative;
|
|
}
|
|
|
|
.luxury-nav-item.active::before {
|
|
content: "";
|
|
@apply absolute left-0 w-1 h-5 bg-cyan-500 rounded-full;
|
|
box-shadow: 0 0 8px rgba(6, 182, 212, 0.5);
|
|
}
|
|
|
|
/* Submenu styling */
|
|
.luxury-submenu {
|
|
@apply mt-2 space-y-1 ps-4 border-l border-slate-200 ms-4;
|
|
@apply dark:border-white/10;
|
|
}
|
|
|
|
/* Luxury Buttons */
|
|
.btn-luxury-primary {
|
|
@apply inline-flex items-center justify-center gap-x-2 px-4 py-2.5 text-sm font-semibold rounded-xl text-white transition-all duration-200;
|
|
background: linear-gradient(135deg, #06b6d4, #3b82f6);
|
|
box-shadow: 0 4px 12px -2px rgba(6, 182, 212, 0.3);
|
|
}
|
|
|
|
.btn-luxury-primary:hover {
|
|
@apply -translate-y-0.5;
|
|
box-shadow: 0 8px 20px -4px rgba(6, 182, 212, 0.4);
|
|
filter: brightness(1.1);
|
|
}
|
|
|
|
.btn-luxury-primary:active {
|
|
@apply translate-y-0 scale-[0.98];
|
|
}
|
|
|
|
.btn-luxury-rose {
|
|
@apply inline-flex items-center justify-center gap-x-2 px-4 py-2.5 text-sm font-semibold rounded-xl text-white transition-all duration-300;
|
|
background: linear-gradient(135deg, #f43f5e, #e11d48);
|
|
box-shadow: 0 4px 12px -2px rgba(225, 29, 72, 0.3), 0 0 0 1px rgba(225, 29, 72, 0.1);
|
|
}
|
|
|
|
.btn-luxury-rose:hover {
|
|
@apply -translate-y-0.5;
|
|
box-shadow: 0 10px 25px -5px rgba(225, 29, 72, 0.5), 0 0 15px rgba(225, 29, 72, 0.2);
|
|
filter: brightness(1.1);
|
|
}
|
|
|
|
.btn-luxury-rose:active {
|
|
@apply translate-y-0 scale-[0.97];
|
|
}
|
|
|
|
.btn-luxury-secondary {
|
|
@apply inline-flex items-center justify-center gap-x-2 px-3 py-2 text-sm font-semibold rounded-xl transition-all duration-200;
|
|
@apply bg-white text-slate-700 border border-slate-200 shadow-sm;
|
|
@apply dark:bg-slate-800 dark:text-white dark:border-slate-700;
|
|
}
|
|
|
|
.btn-luxury-secondary:hover {
|
|
@apply bg-slate-50 border-slate-300 -translate-y-0.5 shadow-md;
|
|
@apply dark:bg-slate-700/50 dark:border-slate-600;
|
|
}
|
|
|
|
.btn-luxury-ghost {
|
|
@apply inline-flex items-center justify-center gap-x-2 px-4 py-2 text-sm font-bold rounded-xl transition-all duration-200;
|
|
@apply text-slate-500 hover:bg-slate-100 hover:text-slate-900;
|
|
@apply dark:text-slate-300 dark:hover:bg-white/10 dark:hover:text-cyan-400;
|
|
}
|
|
|
|
/* Luxury Form Elements */
|
|
.luxury-input, .luxury-select {
|
|
@apply py-3 px-5 block w-full border-slate-200 rounded-xl text-sm font-bold text-slate-700 placeholder-slate-400 transition-all duration-200 outline-none border;
|
|
@apply dark:bg-slate-900/40 dark:border-slate-700 dark:text-slate-200 dark:placeholder-slate-500;
|
|
backdrop-filter: blur(4px);
|
|
}
|
|
|
|
.luxury-input:focus, .luxury-select:focus {
|
|
@apply ring-4 ring-cyan-500/10 border-cyan-500;
|
|
@apply dark:ring-cyan-500/20 dark:border-cyan-400/50;
|
|
}
|
|
|
|
/* Input Icon Optimization (Date/Time) */
|
|
.luxury-input[type="date"]::-webkit-calendar-picker-indicator,
|
|
.luxury-input[type="time"]::-webkit-calendar-picker-indicator,
|
|
.luxury-input[type="datetime-local"]::-webkit-calendar-picker-indicator {
|
|
@apply cursor-pointer transition-opacity hover:opacity-100;
|
|
opacity: 0.6;
|
|
}
|
|
|
|
.dark .luxury-input[type="date"]::-webkit-calendar-picker-indicator,
|
|
.dark .luxury-input[type="time"]::-webkit-calendar-picker-indicator,
|
|
.dark .luxury-input[type="datetime-local"]::-webkit-calendar-picker-indicator {
|
|
filter: invert(1);
|
|
}
|
|
|
|
.luxury-select {
|
|
@apply appearance-none pr-10;
|
|
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%2364748b' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e");
|
|
background-position: right 0.85rem center;
|
|
background-repeat: no-repeat;
|
|
background-size: 1.25em 1.25em;
|
|
}
|
|
|
|
/* Preline Searchable Select Customizations */
|
|
.hs-select-toggle.luxury-select-toggle {
|
|
@apply luxury-input pr-10 cursor-pointer text-start flex items-center justify-between relative;
|
|
}
|
|
|
|
.hs-select-toggle.luxury-select-toggle::after {
|
|
content: "";
|
|
@apply absolute right-3 top-1/2 -translate-y-1/2 w-4 h-4 transition-transform duration-300 pointer-events-none;
|
|
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke='%2394a3b8' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='m6 9 6 6 6-6'/%3e%3c/svg%3e");
|
|
background-repeat: no-repeat;
|
|
background-size: contain;
|
|
}
|
|
|
|
/* 當選單開啟時旋轉箭頭 */
|
|
.hs-select.active .hs-select-toggle::after,
|
|
.hs-select-toggle.active::after,
|
|
.hs-select-toggle[aria-expanded="true"]::after {
|
|
@apply rotate-180;
|
|
}
|
|
|
|
.hs-select-menu {
|
|
@apply mt-2 max-h-72 p-2 space-y-0.5 z-50 bg-white border border-slate-200 rounded-2xl shadow-2xl overflow-y-auto;
|
|
@apply dark:bg-slate-900 dark:border-slate-800;
|
|
}
|
|
|
|
.hs-select-option {
|
|
@apply py-2.5 px-4 w-full text-sm font-bold text-slate-700 cursor-pointer hover:bg-slate-50 rounded-xl transition-colors;
|
|
@apply dark:text-slate-200 dark:hover:bg-slate-800;
|
|
}
|
|
|
|
.hs-selected.hs-select-option {
|
|
@apply bg-cyan-50 text-cyan-600;
|
|
@apply dark:bg-cyan-500/10 dark:text-cyan-400;
|
|
}
|
|
|
|
.hs-select-search-wrapper {
|
|
@apply p-2 sticky top-0 bg-white/80 dark:bg-slate-900/80 backdrop-blur-md z-10 mb-1 border-b border-slate-100 dark:border-slate-800;
|
|
}
|
|
|
|
.hs-select-search-input {
|
|
@apply luxury-input py-2 px-3 text-xs border-slate-100 dark:border-slate-800;
|
|
}
|
|
|
|
/* Small variants for filter bars */
|
|
.luxury-input-sm {
|
|
@apply py-2 text-sm !important;
|
|
}
|
|
|
|
.luxury-select-sm .hs-select-toggle {
|
|
@apply py-2 text-sm !important;
|
|
}
|
|
}
|
|
/* Flatpickr Luxury Theme Overrides */
|
|
.flatpickr-calendar {
|
|
border: 1px solid #e2e8f0 !important;
|
|
border-radius: 1.25rem !important;
|
|
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25) !important;
|
|
background: #ffffff !important;
|
|
padding: 4px !important;
|
|
}
|
|
|
|
.dark .flatpickr-calendar {
|
|
background: #1e293b !important;
|
|
border-color: #334155 !important;
|
|
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.5) !important;
|
|
}
|
|
|
|
.flatpickr-day {
|
|
color: #475569 !important;
|
|
border-radius: 12px !important;
|
|
font-weight: 500 !important;
|
|
}
|
|
|
|
.dark .flatpickr-day {
|
|
color: #cbd5e1 !important;
|
|
}
|
|
|
|
.flatpickr-day.prevMonthDay,
|
|
.flatpickr-day.nextMonthDay {
|
|
color: #cbd5e1 !important;
|
|
opacity: 0.3;
|
|
}
|
|
|
|
.dark .flatpickr-day.prevMonthDay,
|
|
.dark .flatpickr-day.nextMonthDay {
|
|
color: #475569 !important;
|
|
opacity: 0.8;
|
|
}
|
|
|
|
.flatpickr-day.today {
|
|
border-color: #06b6d4 !important;
|
|
color: #06b6d4 !important;
|
|
}
|
|
|
|
.flatpickr-day.selected,
|
|
.flatpickr-day.startRange,
|
|
.flatpickr-day.endRange {
|
|
background: linear-gradient(135deg, #06b6d4, #3b82f6) !important;
|
|
border-color: transparent !important;
|
|
color: white !important;
|
|
box-shadow: 0 8px 15px -3px rgba(6, 182, 212, 0.4) !important;
|
|
z-index: 10;
|
|
}
|
|
|
|
.flatpickr-day.inRange {
|
|
background: #ecfeff !important;
|
|
border-color: transparent !important;
|
|
box-shadow: -5px 0 0 #ecfeff, 5px 0 0 #ecfeff !important;
|
|
color: #0891b2 !important;
|
|
}
|
|
|
|
.dark .flatpickr-day.inRange {
|
|
background: rgba(6, 182, 212, 0.15) !important;
|
|
box-shadow: -5px 0 0 rgba(6, 182, 212, 0.15), 5px 0 0 rgba(6, 182, 212, 0.15) !important;
|
|
color: #22d3ee !important;
|
|
}
|
|
|
|
.flatpickr-day:not(.selected):hover {
|
|
background: #f1f5f9 !important;
|
|
}
|
|
|
|
.dark .flatpickr-day:not(.selected):hover {
|
|
background: #334155 !important;
|
|
}
|
|
|
|
/* Weekdays & Header */
|
|
.flatpickr-weekday {
|
|
color: #94a3b8 !important;
|
|
font-weight: 800 !important;
|
|
font-size: 11px !important;
|
|
}
|
|
|
|
.dark .flatpickr-weekday {
|
|
color: #475569 !important;
|
|
}
|
|
|
|
.flatpickr-months .flatpickr-month {
|
|
color: #1e293b !important;
|
|
fill: currentColor !important;
|
|
}
|
|
|
|
.dark .flatpickr-months .flatpickr-month {
|
|
color: #f8fafc !important;
|
|
}
|
|
|
|
.flatpickr-prev-month,
|
|
.flatpickr-next-month {
|
|
color: #1e293b !important;
|
|
fill: currentColor !important;
|
|
@apply transition-colors duration-200 !important;
|
|
}
|
|
|
|
.dark .flatpickr-prev-month,
|
|
.dark .flatpickr-next-month {
|
|
color: #cbd5e1 !important;
|
|
}
|
|
|
|
.flatpickr-prev-month:hover,
|
|
.flatpickr-next-month:hover {
|
|
color: #06b6d4 !important;
|
|
}
|
|
|
|
.flatpickr-current-month .flatpickr-monthDropdown-months {
|
|
font-weight: 800 !important;
|
|
@apply bg-transparent dark:bg-slate-800 text-slate-900 dark:text-slate-100 !important;
|
|
border: none !important;
|
|
border-radius: 6px !important;
|
|
padding: 2px 4px !important;
|
|
cursor: pointer !important;
|
|
}
|
|
|
|
.flatpickr-monthDropdown-month {
|
|
@apply bg-white dark:bg-slate-800 text-slate-900 dark:text-slate-100 !important;
|
|
}
|
|
|
|
/* Time Section */
|
|
.flatpickr-time {
|
|
border-top: 1px solid #f1f5f9 !important;
|
|
margin-top: 8px !important;
|
|
padding-top: 8px !important;
|
|
}
|
|
|
|
.dark .flatpickr-time {
|
|
border-top-color: #334155 !important;
|
|
}
|
|
|
|
.flatpickr-time input {
|
|
color: #1e293b !important;
|
|
font-weight: 800 !important;
|
|
border-radius: 8px !important;
|
|
}
|
|
|
|
.dark .flatpickr-time input {
|
|
color: #f8fafc !important;
|
|
}
|
|
|
|
.flatpickr-time input:hover,
|
|
.flatpickr-time input:focus {
|
|
background: #f1f5f9 !important;
|
|
}
|
|
|
|
.dark .flatpickr-time input:hover,
|
|
.dark .flatpickr-time input:focus {
|
|
background: #334155 !important;
|
|
}
|
|
|
|
.dark .flatpickr-time .flatpickr-am-pm {
|
|
color: #f8fafc !important;
|
|
}
|
|
|
|
/* Time Stepper Arrows & Separator */
|
|
.flatpickr-time .numInputWrapper span.arrowUp:after {
|
|
border-bottom-color: #94a3b8 !important;
|
|
}
|
|
|
|
.flatpickr-time .numInputWrapper span.arrowUp:hover:after {
|
|
border-bottom-color: #06b6d4 !important;
|
|
}
|
|
|
|
.flatpickr-time .numInputWrapper span.arrowDown:after {
|
|
border-top-color: #94a3b8 !important;
|
|
}
|
|
|
|
.flatpickr-time .numInputWrapper span.arrowDown:hover:after {
|
|
border-top-color: #06b6d4 !important;
|
|
}
|
|
|
|
.dark .flatpickr-time .numInputWrapper span.arrowUp:after {
|
|
border-bottom-color: #64748b !important;
|
|
}
|
|
|
|
.dark .flatpickr-time .numInputWrapper span.arrowUp:hover:after {
|
|
border-bottom-color: #06b6d4 !important;
|
|
}
|
|
|
|
.dark .flatpickr-time .numInputWrapper span.arrowDown:after {
|
|
border-top-color: #64748b !important;
|
|
}
|
|
|
|
.dark .flatpickr-time .numInputWrapper span.arrowDown:hover:after {
|
|
border-top-color: #06b6d4 !important;
|
|
}
|
|
|
|
.flatpickr-time .numInputWrapper span {
|
|
border-color: #f1f5f9 !important;
|
|
}
|
|
|
|
.dark .flatpickr-time .numInputWrapper span {
|
|
border-color: #334155 !important;
|
|
background: transparent !important;
|
|
}
|
|
|
|
.dark .flatpickr-time .numInputWrapper span:hover {
|
|
background: #334155 !important;
|
|
}
|
|
|
|
.flatpickr-time .flatpickr-time-separator {
|
|
color: #94a3b8 !important;
|
|
}
|
|
|
|
.dark .flatpickr-time .flatpickr-time-separator {
|
|
color: #64748b !important;
|
|
}
|
|
|
|
.flatpickr-weekdays {
|
|
background: transparent !important;
|
|
}
|
|
|