main page
This commit is contained in:
commit
7fb446c53a
8943 files changed
+1209030
No files matched your search
@@ -0,0 +1,216 @@
|
||||
import { useState } from 'react'
|
||||
import { format } from 'date-fns'
|
||||
import { FaAngleDown, FaSpinner } from 'react-icons/fa6'
|
||||
import { useWorkorders } from '../hooks/useWorkorders'
|
||||
import TicketRow from '../components/TicketRow'
|
||||
import TicketFilters from '../components/TicketFilters'
|
||||
import CreateTicketModal from '../components/CreateTicketModal'
|
||||
import QuickOverviewModal from '../components/QuickOverviewModal'
|
||||
|
||||
export default function TicketsPage() {
|
||||
const [limit, setLimit] = useState(10)
|
||||
const [filters, setFilters] = useState({
|
||||
status: ['Open', 'Occupied', 'Assigned', 'Awaiting', 'Added Info'],
|
||||
type: [],
|
||||
priority: [],
|
||||
limit: 10
|
||||
})
|
||||
|
||||
const { workorders, loading, error, refresh, updateWorkorder, createWorkorder } = useWorkorders(filters)
|
||||
|
||||
const [showCreateModal, setShowCreateModal] = useState(false)
|
||||
const [showOverviewModal, setShowOverviewModal] = useState(false)
|
||||
|
||||
const handleFilterChange = (newFilters) => {
|
||||
setFilters({ ...newFilters, limit })
|
||||
}
|
||||
|
||||
const handleApplyFilters = () => {
|
||||
refresh()
|
||||
}
|
||||
|
||||
const handleLimitChange = (e) => {
|
||||
const newLimit = parseInt(e.target.value)
|
||||
setLimit(newLimit)
|
||||
setFilters(prev => ({ ...prev, limit: newLimit }))
|
||||
}
|
||||
|
||||
const handleUpdate = async (id, data) => {
|
||||
await updateWorkorder(id, data)
|
||||
}
|
||||
|
||||
const handleCreate = async (data) => {
|
||||
const result = await createWorkorder(data)
|
||||
if (result.success) {
|
||||
setShowCreateModal(false)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
const handleLoadMore = () => {
|
||||
setLimit(prev => prev + 10)
|
||||
setFilters(prev => ({ ...prev, limit: prev.limit + 10 }))
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="main-content">
|
||||
<header className="text-center mb-2">
|
||||
<h2>Active Tickets Overview</h2>
|
||||
</header>
|
||||
|
||||
<p className="text-center text-grey">
|
||||
Work Order loading limit is set to <span className="text-xlarge">{limit}</span>.
|
||||
Reduce value to increase reload speed.
|
||||
</p>
|
||||
<p className="text-center text-grey text-small">
|
||||
Last page reload: {format(new Date(), 'dd.MM.yyyy, HH:mm:ss')}
|
||||
</p>
|
||||
|
||||
<hr className="mb-2" />
|
||||
|
||||
<table className="table table-hover">
|
||||
<tbody>
|
||||
<TicketFilters
|
||||
filters={filters}
|
||||
onChange={handleFilterChange}
|
||||
onApply={handleApplyFilters}
|
||||
/>
|
||||
|
||||
<tr>
|
||||
<td colSpan={10} className="bg-dark-grey">
|
||||
<div className="slider-container text-center">
|
||||
<input
|
||||
type="range"
|
||||
min="5"
|
||||
max="50"
|
||||
value={limit}
|
||||
className="slider"
|
||||
onChange={handleLimitChange}
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td colSpan={10} className="text-center p-1">
|
||||
<button
|
||||
className="btn btn-teal"
|
||||
onClick={() => setFilters(prev => ({ ...prev, type: ['Procurement'] }))}
|
||||
>
|
||||
Procurements
|
||||
</button>
|
||||
{' '}
|
||||
<button
|
||||
className="btn btn-teal"
|
||||
onClick={() => setFilters(prev => ({ ...prev, priority: [4] }))}
|
||||
>
|
||||
Criticals
|
||||
</button>
|
||||
{' '}
|
||||
<button
|
||||
className="btn btn-teal"
|
||||
onClick={() => setFilters(prev => ({ ...prev, priority: [3] }))}
|
||||
>
|
||||
Highs
|
||||
</button>
|
||||
{' '}
|
||||
<button
|
||||
className="btn btn-teal"
|
||||
onClick={() => { setLimit(10); setFilters(prev => ({ ...prev, limit: 10 })) }}
|
||||
>
|
||||
10
|
||||
</button>
|
||||
{' '}
|
||||
<button
|
||||
className="btn btn-teal"
|
||||
onClick={() => { setLimit(25); setFilters(prev => ({ ...prev, limit: 25 })) }}
|
||||
>
|
||||
25
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td colSpan={10} className="text-center p-1">
|
||||
<button
|
||||
className="btn btn-dark"
|
||||
onClick={() => setShowCreateModal(true)}
|
||||
>
|
||||
CREATE NEW TICKET
|
||||
</button>
|
||||
{' '}
|
||||
<button
|
||||
className="btn btn-dark"
|
||||
onClick={() => setShowOverviewModal(true)}
|
||||
>
|
||||
QUICK OVERVIEW
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr className="spacer">
|
||||
<td colSpan={10} style={{ height: '16px' }}></td>
|
||||
</tr>
|
||||
|
||||
{loading ? (
|
||||
<tr>
|
||||
<td colSpan={10} className="text-center p-2">
|
||||
<FaSpinner className="spinner" size={32} />
|
||||
<p>Loading...</p>
|
||||
</td>
|
||||
</tr>
|
||||
) : error ? (
|
||||
<tr>
|
||||
<td colSpan={10} className="text-center p-2 text-red">
|
||||
Error: {error}
|
||||
</td>
|
||||
</tr>
|
||||
) : workorders.length === 0 ? (
|
||||
<tr>
|
||||
<td colSpan={10} className="text-center p-2">
|
||||
No tickets found matching your filters.
|
||||
</td>
|
||||
</tr>
|
||||
) : (
|
||||
workorders.map(ticket => (
|
||||
<TicketRow
|
||||
key={ticket.$id}
|
||||
ticket={ticket}
|
||||
onUpdate={handleUpdate}
|
||||
/>
|
||||
))
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
{workorders.length > 0 && workorders.length >= limit && (
|
||||
<div className="text-center mt-2">
|
||||
<button
|
||||
className="btn"
|
||||
style={{ background: 'none', border: 'none' }}
|
||||
onClick={handleLoadMore}
|
||||
>
|
||||
<FaAngleDown size={48} />
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<p className="text-center text-grey mt-2">
|
||||
Summary: Listed a total of {workorders.length} Workorders.
|
||||
<br />EOL =)
|
||||
</p>
|
||||
|
||||
<CreateTicketModal
|
||||
isOpen={showCreateModal}
|
||||
onClose={() => setShowCreateModal(false)}
|
||||
onCreate={handleCreate}
|
||||
/>
|
||||
|
||||
<QuickOverviewModal
|
||||
isOpen={showOverviewModal}
|
||||
onClose={() => setShowOverviewModal(false)}
|
||||
workorders={workorders}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in new issue
Block a user