vat_wms/resources/js/Pages/PdaView.tsx
2025-06-02 07:36:24 +02:00

186 lines
7.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React from 'react'
import axios from 'axios'
import { Head, usePage } from '@inertiajs/react'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import {
faArrowLeft,
faQuestionCircle,
faBoxOpen,
faClipboardList,
faCubes,
faPlus,
} from '@fortawesome/free-solid-svg-icons'
import { toast, Toaster } from 'react-hot-toast'
import Tile from '../Components/Tile'
import TileLayout from '../Components/TileLayout'
import ModalPDA from '../Components/ModalPDA'
// your extracted modal forms:
import SetStockModal from '../Components/modals/SetStockModal'
import OtherReplacementModal from '../Components/modals/OtherReplacementModal'
import CountStockModal from '../Components/modals/CountStockModal'
type Role = 'Expedice' | 'Skladnik'
// actions per role
const roleActions: Record<Role, string[]> = {
Expedice: ['stockSectionScanned', 'labelScanned'],
Skladnik: ['batchScan', 'stockScan'],
}
// configuration for each tile: either opens a modal (modalKey),
// or performs an API call (onClick)
type TileConfig = {
title: string
icon: any
modalKey?: ModalKey
onClick?: () => void
}
const tilesConfig: Record<Role, Record<string, TileConfig[]>> = {
Expedice: {
stockSectionScanned: [
{ title: 'Not Present', icon: faBoxOpen, onClick: () => toast('Not Present clicked') },
{ title: 'Na pozici je jiny ovladac', icon: faBoxOpen, onClick: () => toast('Not Present clicked') },
{
title: 'Present but Shouldnt',
icon: faClipboardList,
onClick: async () => {
// example direct axios call
try {
await axios.post('/api/presence-error', {}, { withCredentials: true })
toast.success('Reported!')
} catch {
toast.error('Failed to report')
}
},
},
{ title: 'Other Replacement (na test/one time)', icon: faPlus, modalKey: 'otherReplacement' },
{ title: 'Pridej vazbu na jiny ovladac', icon: faPlus, onClick: () => toast('Batch Info clicked') },
{ title: 'Pridej docasnou vazbu (nez prijde jine zbozi, i casove omezene, nejnizsi priorita)', icon: faPlus, onClick: () => toast('Batch Info clicked') },
{ title: 'Doplnit zbozi / dej vic kusu', icon: faPlus, onClick: () => toast('Batch Info clicked') },
{ title: 'Report - chci zmenit pozici(bliz / dal od expedice)', icon: faPlus, onClick: () => toast('Batch Info clicked') },
{ title: 'Pultovy prodej', icon: faPlus, onClick: () => toast('- naskenuju na webu / naskenuju na skladovem miste, obj. se udela automaticky, zakaznik si muze v rohu na PC vyplnit osobni udaje na special formulari - pak customera prida obsluha do obj') },
],
labelScanned: [
{ title: 'Info', icon: faClipboardList, onClick: () => toast('Batch Info clicked') },
]
},
Skladnik: {
batchScan: [
{ title: 'Batch Info', icon: faClipboardList, onClick: () => toast('Batch Info clicked') },
{ title: 'Set Stock', icon: faCubes, modalKey: 'setStock' },
{ title: 'Count Stock', icon: faPlus, modalKey: 'countStock' },
{ title: 'Stitkovani (male stitky)', icon: faClipboardList, onClick: () => toast('Stitkovani (male stitky)') },
{ title: 'Batch Info', icon: faClipboardList, onClick: () => toast('Batch Info clicked') },
{ title: 'Tisk QR kod na krabice', icon: faClipboardList, onClick: () => toast('Batch Info clicked') },
],
stockScan: [
{ title: 'Info', icon: faClipboardList, onClick: () => toast('Batch Info clicked') },
{ title: 'Zmena skladoveho mista (i presun jen casti kusu)', icon: faClipboardList, onClick: () => toast('Batch Info clicked') },
{ title: 'Uprava skladoveho mista (mene sekci, apod)', icon: faClipboardList, onClick: () => toast('Batch Info clicked') },
{ title: 'Zmena poctu', icon: faClipboardList, onClick: () => toast('Batch Info clicked') },
{ title: 'Discard (odebrat ze skladoveho mista / posilame zpet)', icon: faClipboardList, onClick: () => toast('Batch Info clicked') },
],
others: [
{ title: 'Nove skladove misto', icon: faClipboardList, onClick: () => toast('Batch Info clicked') },
]
},
}
type ModalKey = 'setStock' | 'otherReplacement' | 'countStock' | null
export default function PdaView() {
const {
auth: { user },
} = usePage<{ auth: { user: { role: string } } }>().props
const [role, setRole] = React.useState<Role>(
user.role === 'admin' ? 'Expedice' : (user.role as Role)
)
const [action, setAction] = React.useState<string>('')
const [activeModal, setActiveModal] = React.useState<ModalKey>(null)
const isAdmin = true
// const isAdmin = user.role === 'admin'
const tabs: Role[] = ['Expedice', 'Skladnik']
const closeModal = () => setActiveModal(null)
return (
<>
<Head title="PDA View" />
{/* Top bar */}
<div className="flex justify-between items-center bg-base-100 p-4 shadow">
<a className="link" href={route('dashboard')}><FontAwesomeIcon icon={faArrowLeft} /> Back</a>
<button className="btn btn-ghost">
<FontAwesomeIcon icon={faQuestionCircle} /> Help
</button>
</div>
{/* Admin tabs */}
{isAdmin && (
<div className="tabs justify-center bg-base-100">
{tabs.map((r) => (
<button
key={r}
className={`tab ${role === r ? 'tab-active' : ''}`}
onClick={() => {
setRole(r)
setAction('')
}}
>
{r}
</button>
))}
</div>
)}
{/* Action selectors */}
<div className="flex justify-center space-x-4 space-y-4 sm:space-y-0 p-4 sm:flex-nowrap flex-wrap">
{[...(roleActions[role] || []), 'clear'].map((act) => (
<button
key={act}
className="btn btn-outline"
onClick={() => {
const newAct = act === 'clear' ? '' : act
setAction(newAct)
toast(`Action set to ${newAct || 'none'}`)
}}
>
{act === 'clear' ? 'Clear Action' : act}
</button>
))}
</div>
{/* Tiles */}
<TileLayout>
{action &&
(tilesConfig[role][action] || []).map(({ title, icon, onClick, modalKey }) => (
<Tile
key={title}
title={title}
icon={icon}
onClick={() => {
if (modalKey) setActiveModal(modalKey)
else if (onClick) onClick()
}}
/>
))}
</TileLayout>
{/* Single Modal */}
<ModalPDA isOpen={activeModal !== null} onClose={closeModal}>
{activeModal === 'setStock' && <SetStockModal onClose={closeModal} />}
{activeModal === 'otherReplacement' && <OtherReplacementModal onClose={closeModal} />}
{activeModal === 'countStock' && <CountStockModal onClose={closeModal} />}
</ModalPDA>
<Toaster position="top-right" />
</>
)
}