Overhaul of the frontend on waiters, orders, and payment events
Manager Dashboard: product reorder/bulk actions, preference sub-choices UI, expanded reports with DateInput component, waiter management updates, order detail improvements, Docker config and backend dockerignore added. Backend: table groups, auto-numbering, has_active_order flag, expanded reporting endpoints, waiter zone management, user schema updates, system router additions, table router fixes. Waiter PWA: TableDetailPage order/payment event improvements. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
79
manager_dashboard/src/components/DateInput.jsx
Normal file
79
manager_dashboard/src/components/DateInput.jsx
Normal file
@@ -0,0 +1,79 @@
|
||||
/**
|
||||
* DateInput / DateTimeInput
|
||||
*
|
||||
* Native date pickers display in the OS/browser locale (MM/DD/YYYY on en-US).
|
||||
* These wrappers overlay the native input with a visible DD/MM/YYYY display
|
||||
* while keeping the full native picker UX (click, keyboard, mobile wheel).
|
||||
*
|
||||
* Props mirror a plain <input>: value (YYYY-MM-DD or YYYY-MM-DDTHH:MM),
|
||||
* onChange (receives the same synthetic event), className.
|
||||
*/
|
||||
import { useRef } from 'react'
|
||||
|
||||
function formatDateGR(value) {
|
||||
// value is "YYYY-MM-DD"
|
||||
if (!value) return ''
|
||||
const [y, m, d] = value.split('-')
|
||||
if (!y || !m || !d) return value
|
||||
return `${d}/${m}/${y}`
|
||||
}
|
||||
|
||||
function formatDateTimeGR(value) {
|
||||
// value is "YYYY-MM-DDTHH:MM"
|
||||
if (!value) return ''
|
||||
const [datePart, timePart] = value.split('T')
|
||||
if (!datePart) return value
|
||||
const [y, m, d] = datePart.split('-')
|
||||
if (!y || !m || !d) return value
|
||||
return `${d}/${m}/${y}${timePart ? ' ' + timePart : ''}`
|
||||
}
|
||||
|
||||
export function DateInput({ value, onChange, className = '', ...rest }) {
|
||||
const ref = useRef(null)
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`relative cursor-pointer ${className}`}
|
||||
onClick={() => ref.current?.showPicker?.()}
|
||||
>
|
||||
{/* Visible display */}
|
||||
<div className="absolute inset-0 flex items-center px-3 pointer-events-none z-10 bg-white rounded-lg text-sm text-gray-800">
|
||||
{value ? formatDateGR(value) : <span className="text-gray-400">ΗΗ/ΜΜ/ΕΕΕΕ</span>}
|
||||
</div>
|
||||
{/* Native input — invisible but functional (provides the picker) */}
|
||||
<input
|
||||
ref={ref}
|
||||
type="date"
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
className="opacity-0 w-full h-full absolute inset-0 cursor-pointer"
|
||||
tabIndex={0}
|
||||
{...rest}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export function DateTimeInput({ value, onChange, className = '', ...rest }) {
|
||||
const ref = useRef(null)
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`relative cursor-pointer ${className}`}
|
||||
onClick={() => ref.current?.showPicker?.()}
|
||||
>
|
||||
<div className="absolute inset-0 flex items-center px-3 pointer-events-none z-10 bg-white rounded-lg text-sm text-gray-800">
|
||||
{value ? formatDateTimeGR(value) : <span className="text-gray-400">ΗΗ/ΜΜ/ΕΕΕΕ ΩΩ:ΛΛ</span>}
|
||||
</div>
|
||||
<input
|
||||
ref={ref}
|
||||
type="datetime-local"
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
className="opacity-0 w-full h-full absolute inset-0 cursor-pointer"
|
||||
tabIndex={0}
|
||||
{...rest}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user