27/02/2025

This commit is contained in:
damarrsyh 2025-02-27 16:32:05 +07:00
parent 167f0f4e0a
commit 7cf8029368
19 changed files with 658 additions and 284 deletions

2
.env
View File

@ -1 +1 @@
VITE_API_URL = http://localhost:3000/queue VITE_API_URL = http://localhost:3000

125
db.json
View File

@ -1,16 +1,115 @@
{ {
"queue": [ "operators": [
{ "id": 1, "number": "P001", "counter": 1, "service": "Siap Print", "customer": { "name": "John Doe", "phone": "081234567890" }, "startTime": "2025-02-26T08:00:00", "endTime": null, "status": "waiting" }, {
{ "id": 2, "number": "D001", "counter": 2, "service": "Design", "customer": { "name": "Jane Smith", "phone": "081298765432" }, "startTime": "2025-02-26T08:05:00", "endTime": null, "status": "called" }, "id": "O001",
{ "id": 3, "number": "F001", "counter": 3, "service": "Fotocopy", "customer": { "name": "Emily Davis", "phone": "081678901234" }, "startTime": "2025-02-26T08:30:00", "endTime": "2025-02-26T08:45:00", "status": "completed" }, "name": "Rina Wijaya",
{ "id": 4, "number": "R001", "counter": 4, "service": "Retur Barang", "customer": { "name": "Sophia Lee", "phone": "081789012345" }, "startTime": "2025-02-26T08:35:00", "endTime": null, "status": "called" }, "email": "rina@example.com",
{ "id": 5, "number": "O001", "counter": 5, "service": "Online Pickup", "customer": { "name": "Daniel Martinez", "phone": "081890123456" }, "startTime": "2025-02-26T08:40:00", "endTime": null, "status": "waiting" }, "queues": [
{ "id": 6, "number": "T001", "counter": 6, "service": "Tamu", "customer": { "name": "Henry Adams", "phone": "081901234567" }, "startTime": "2025-02-26T08:50:00", "endTime": null, "status": "waiting" }, {
{ "id": 7, "number": "P002", "counter": 1, "service": "Siap Print", "customer": { "name": "James Thompson", "phone": "081234567891" }, "startTime": "2025-02-26T09:00:00", "endTime": null, "status": "waiting" }, "queue_id": "Q12345",
{ "id": 8, "number": "D002", "counter": 2, "service": "Design", "customer": { "name": "Benjamin Clark", "phone": "081456789013" }, "startTime": "2025-02-26T09:10:00", "endTime": "2025-02-26T09:20:00", "status": "completed" }, "customer": {
{ "id": 9, "number": "F002", "counter": 3, "service": "Fotocopy", "customer": { "name": "Olivia Brown", "phone": "081567890124" }, "startTime": "2025-02-26T09:15:00", "endTime": null, "status": "waiting" }, "id": "C001",
{ "id": 10, "number": "R002", "counter": 4, "service": "Retur Barang", "customer": { "name": "William White", "phone": "081678901235" }, "startTime": "2025-02-26T09:20:00", "endTime": null, "status": "called" }, "name": "Budi Santoso",
{ "id": 11, "number": "O002", "counter": 5, "service": "Online Pickup", "customer": { "name": "Sophia Harris", "phone": "081789012346" }, "startTime": "2025-02-26T09:25:00", "endTime": null, "status": "waiting" }, "phone": "+628123456789",
{ "id": 12, "number": "T002", "counter": 6, "service": "Tamu", "customer": { "name": "Alexander Nelson", "phone": "081890123457" }, "startTime": "2025-02-26T09:30:00", "endTime": null, "status": "waiting" } "email": "budi@example.com"
},
"service": {
"id": "J0001",
"name": "siap_print"
},
"status": "In Progress",
"created_at": "2025-02-27T08:30:00Z"
},
{
"queue_id": "Q12346",
"customer": {
"id": "C002",
"name": "Siti Aminah",
"phone": "+628987654321",
"email": "siti@example.com"
},
"service": {
"id": "J0001",
"name": "siap_print"
},
"status": "Waiting",
"created_at": "2025-02-27T09:00:00Z"
}
]
},
{
"id": "O002",
"name": "Doni Saputra",
"email": "doni@example.com",
"queues": [
{
"queue_id": "Q12347",
"customer": {
"id": "C003",
"name": "Ahmad Fauzi",
"phone": "+6285566778899",
"email": "ahmad@example.com"
},
"service": {
"id": "J0002",
"name": "design"
},
"status": "Completed",
"created_at": "2025-02-27T09:30:00Z"
},
{
"queue_id": "Q12348",
"customer": {
"id": "C004",
"name": "Lina Kusuma",
"phone": "+6289988776655",
"email": "lina@example.com"
},
"service": {
"id": "J0003",
"name": "fotocopy"
},
"status": "In Progress",
"created_at": "2025-02-27T10:00:00Z"
}
]
},
{
"id": "O003",
"name": "Sari Ningsih",
"email": "sari@example.com",
"queues": [
{
"queue_id": "Q12349",
"customer": {
"id": "j000",
"name": "Rudi Hartono",
"phone": "+6287711223344",
"email": "rudi@example.com"
},
"service": {
"id": "J0002",
"name": "design"
},
"status": "Waiting",
"created_at": "2025-02-27T10:30:00Z"
},
{
"queue_id": "Q12350",
"customer": {
"id": "C006",
"name": "Dewi Anggraini",
"phone": "+6286677889900",
"email": "dewi@example.com"
},
"service": {
"id": "J0001",
"name": "siap_print"
},
"status": "Completed",
"created_at": "2025-02-27T11:00:00Z"
}
]
}
] ]
} }

14
package-lock.json generated
View File

@ -9,7 +9,7 @@
"version": "0.0.0", "version": "0.0.0",
"dependencies": { "dependencies": {
"@reduxjs/toolkit": "^2.6.0", "@reduxjs/toolkit": "^2.6.0",
"axios": "^1.7.9", "axios": "^1.8.1",
"bcryptjs": "^3.0.2", "bcryptjs": "^3.0.2",
"bootstrap": "^5.3.3", "bootstrap": "^5.3.3",
"cors": "^2.8.5", "cors": "^2.8.5",
@ -1772,9 +1772,9 @@
} }
}, },
"node_modules/axios": { "node_modules/axios": {
"version": "1.7.9", "version": "1.8.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.7.9.tgz", "resolved": "https://registry.npmjs.org/axios/-/axios-1.8.1.tgz",
"integrity": "sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==", "integrity": "sha512-NN+fvwH/kV01dYUQ3PTOZns4LWtWhOFCAhQ/pHb88WQ1hNe5V/dvFwc4VJcDL11LT9xSX0QtsR8sWUuyOuOq7g==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"follow-redirects": "^1.15.6", "follow-redirects": "^1.15.6",
@ -6220,9 +6220,9 @@
} }
}, },
"axios": { "axios": {
"version": "1.7.9", "version": "1.8.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.7.9.tgz", "resolved": "https://registry.npmjs.org/axios/-/axios-1.8.1.tgz",
"integrity": "sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==", "integrity": "sha512-NN+fvwH/kV01dYUQ3PTOZns4LWtWhOFCAhQ/pHb88WQ1hNe5V/dvFwc4VJcDL11LT9xSX0QtsR8sWUuyOuOq7g==",
"requires": { "requires": {
"follow-redirects": "^1.15.6", "follow-redirects": "^1.15.6",
"form-data": "^4.0.0", "form-data": "^4.0.0",

View File

@ -11,7 +11,7 @@
}, },
"dependencies": { "dependencies": {
"@reduxjs/toolkit": "^2.6.0", "@reduxjs/toolkit": "^2.6.0",
"axios": "^1.7.9", "axios": "^1.8.1",
"bcryptjs": "^3.0.2", "bcryptjs": "^3.0.2",
"bootstrap": "^5.3.3", "bootstrap": "^5.3.3",
"cors": "^2.8.5", "cors": "^2.8.5",

View File

@ -1,56 +1,35 @@
import axios from "axios"; import axios from "axios";
const API_URL = "http://localhost:5000/queue"; const API_URL = import.meta.env.VITE_API_URL;
export const fetchOperators = async () => { export const fetchQueues = async () => {
try { try {
const response = await axios.get(API_URL); const response = await axios.get(`${API_URL}/operators`);
return response.data; return response.data;
} catch (error) { } catch (error) {
console.error("Error fetching operators", error); console.error("Error fetching queues:", error);
return []; return [];
} }
}; };
export const addCustomerToOperator = async (operatorId, customerData) => { export const updateQueueStatus = async (queueId, status) => {
try { try {
const response = await axios.get(`${API_URL}/${operatorId}`); const response = await axios.put(`${API_URL}/queues/${queueId}`, {
const operator = response.data; status,
});
operator.customers.push(customerData); return response.data;
} catch (error) {
const updateResponse = await axios.put(`${API_URL}/${operatorId}`, operator); console.error("Error updating queue status:", error);
return updateResponse.data; return null;
} catch (error) { }
console.error("Error adding customer", error);
}
}; };
export const updateCustomerStatus = async (operatorId, customerId, updatedData) => { export const createQueue = async (customerData) => {
try { try {
const response = await axios.get(`${API_URL}/${operatorId}`); const response = await axios.post(`${API_URL}/queues`, customerData);
const operator = response.data; return response.data;
operator.customers = operator.customers.map(customer =>
customer.id === customerId ? { ...customer, ...updatedData } : customer
);
const updateResponse = await axios.put(`${API_URL}/${operatorId}`, operator);
return updateResponse.data;
} catch (error) { } catch (error) {
console.error("Error updating customer status", error); console.error("Error creating queue:", error);
return null;
} }
}; };
export const deleteCustomerFromOperator = async (operatorId, customerId) => {
try {
const response = await axios.get(`${API_URL}/${operatorId}`);
const operator = response.data;
operator.customers = operator.customers.filter(customer => customer.id !== customerId);
await axios.put(`${API_URL}/${operatorId}`, operator);
} catch (error) {
console.error("Error deleting customer", error);
}
};

View File

@ -28,9 +28,9 @@ const AdminSidebar = () => {
<NavLink to="/admin/queue-list" className="btn btn-light shadow-sm d-flex align-items-center"> <NavLink to="/admin/queue-list" className="btn btn-light shadow-sm d-flex align-items-center">
<FaList className="me-2" /> Daftar Antrian <FaList className="me-2" /> Daftar Antrian
</NavLink> </NavLink>
<NavLink to="/admin/call-queue" className="btn btn-light shadow-sm d-flex align-items-center"> {/* <NavLink to="/admin/call-queue" className="btn btn-light shadow-sm d-flex align-items-center">
<FaPhone className="me-2" /> Panggil Antrian <FaPhone className="me-2" /> Panggil Antrian
</NavLink> </NavLink> */}
{/* <NavLink to="/admin/queue-report" className="btn btn-light shadow-sm d-flex align-items-center"> {/* <NavLink to="/admin/queue-report" className="btn btn-light shadow-sm d-flex align-items-center">
<FaChartBar className="me-2" /> Laporan Antrian <FaChartBar className="me-2" /> Laporan Antrian
</NavLink> */} </NavLink> */}

View File

@ -1,29 +1,29 @@
const queueData = [ const queueData = [
{ id: 1, name: "John Doe", phone: "08123456789", service: "Siap Print", serviceId: "J0001", locket: "01", startAt: "10:30 AM", completedAt: "10:30 AM", queueNumber: "001", status: "Menunggu", called: false, active: true, audio: "Default"}, { id: 1, name: "John Doe", phone: "08123456789", service: "Siap Print", serviceId: "J0001", locket: "loket 01", startAt: "10:30 AM", completedAt: "10:30 AM", queueNumber: "001", status: "Menunggu", called: false, active: true},
{ id: 2, name: "Jane Smith", phone: "08234567890", service: "Design", serviceId: "J0002", locket: "04", startAt: "11:15 AM", completedAt: "11:15 AM", queueNumber: "002", status: "Dilayani", called: false, active: true, audio: "Beep"}, { id: 2, name: "Jane Smith", phone: "08234567890", service: "Design", serviceId: "J0002", locket: "loket 04", startAt: "11:15 AM", completedAt: "11:15 AM", queueNumber: "002", status: "Menunggu", called: false, active: true},
{ id: 3, name: "Michael Johnson", phone: "08345678901", service: "FotoCopy", serviceId: "J0003", locket: "08", startAt: "11:50 AM", completedAt: "11:50 AM", queueNumber: "003", status: "Selesai", called: false, active: true, audio: "Bell"}, { id: 3, name: "Michael Johnson", phone: "08345678901", service: "FotoCopy", serviceId: "J0003", locket: "loket 08", startAt: "11:50 AM", completedAt: "11:50 AM", queueNumber: "003", status: "Menunggu", called: false, active: true},
{ id: 4, name: "Emily Brown", phone: "08456789012", service: "Tamu", serviceId: "J0006", locket: "02", startAt: "12:10 PM", completedAt: "12:10 PM", queueNumber: "004", status: "Menunggu", called: false, active: true, audio: "Chime"}, { id: 4, name: "Emily Brown", phone: "08456789012", service: "Tamu", serviceId: "J0006", locket: "loket 02", startAt: "12:10 PM", completedAt: "12:10 PM", queueNumber: "004", status: "Menunggu", called: false, active: true},
{ id: 5, name: "David Wilson", phone: "08567890123", service: "Online", serviceId: "J0005", locket: "05", startAt: "12:50 PM", completedAt: "12:50 PM", queueNumber: "005", status: "Dilayani", called: false, active: true, audio: "Ding"}, { id: 5, name: "David Wilson", phone: "08567890123", service: "Online", serviceId: "J0005", locket: "loket 05", startAt: "04:00 PM", completedAt: "12:50 PM", queueNumber: "005", status: "Menunggu", called: false, active: true},
{ id: 6, name: "Sophia Martinez", phone: "08678901234", service: "Online", serviceId: "J0005", locket: "06", startAt: "01:30 PM", completedAt: "01:30 PM", queueNumber: "006", status: "Selesai", called: false, active: true, audio: "Ping"}, { id: 6, name: "Sophia Martinez", phone: "08678901234", service: "Online", serviceId: "J0005", locket: "loket 06", startAt: "01:30 PM", completedAt: "01:30 PM", queueNumber: "006", status: "Menunggu", called: false, active: true},
{ id: 7, name: "James Anderson", phone: "08789012345", service: "Siap Print", serviceId: "J0001", locket: "03", startAt: "02:15 PM", completedAt: "02:15 PM", queueNumber: "007", status: "Menunggu", called: false, active: true, audio: "Chirp"}, { id: 7, name: "James Anderson", phone: "08789012345", service: "Siap Print", serviceId: "J0001", locket: "loket 03", startAt: "02:15 PM", completedAt: "02:15 PM", queueNumber: "007", status: "Menunggu", called: false, active: true},
{ id: 8, name: "Olivia Thomas", phone: "08890123456", service: "Design", serviceId: "J0002", locket: "07", startAt: "02:50 PM", completedAt: "02:50 PM", queueNumber: "008", status: "Dilayani", called: false, active: true, audio: "Ring"}, { id: 8, name: "Olivia Thomas", phone: "08890123456", service: "Design", serviceId: "J0002", locket: "loket 07", startAt: "02:50 PM", completedAt: "02:50 PM", queueNumber: "008", status: "Menunggu", called: false, active: true},
{ id: 9, name: "Liam White", phone: "08901234567", service: "FotoCopy", serviceId: "J0003", locket: "09", startAt: "03:20 PM", completedAt: "03:20 PM", queueNumber: "009", status: "Selesai", called: false, active: true, audio: "Tone"}, { id: 9, name: "Liam White", phone: "08901234567", service: "FotoCopy", serviceId: "J0003", locket: "loket 09", startAt: "03:20 PM", completedAt: "03:20 PM", queueNumber: "009", status: "Menunggu", called: false, active: true},
{ id: 10, name: "Emma Harris", phone: "08012345678", service: "Siap Print", serviceId: "J0001", locket: "10", startAt: "03:50 PM", completedAt: "03:50 PM", queueNumber: "010", status: "Menunggu", called: false, active: true, audio: "Alarm" }, { id: 10, name: "Emma Harris", phone: "08012345678", service: "Siap Print", serviceId: "J0001", locket: "loket 10", startAt: "03:50 PM", completedAt: "03:50 PM", queueNumber: "010", status: "Menunggu", called: false, active: true},
{ id: 11, name: "John Doe", phone: "08123456789", service: "Siap Print", serviceId: "J0001", locket: "01", startAt: "10:30 AM", completedAt: "10:30 AM", queueNumber: "001", status: "Menunggu", called: false, active: true, audio: "Default"}, { id: 11, name: "John Doe", phone: "08123456789", service: "Siap Print", serviceId: "J0001", locket: "loket 01", startAt: "10:30 AM", completedAt: "10:30 AM", queueNumber: "001", status: "Menunggu", called: false, active: true},
{ id: 12, name: "Jane Smith", phone: "08234567890", service: "Design", serviceId: "J0002", locket: "04", startAt: "11:15 AM", completedAt: "11:15 AM", queueNumber: "002", status: "Dilayani", called: false, active: true, audio: "Beep"}, { id: 12, name: "Jane Smith", phone: "08234567890", service: "Design", serviceId: "J0002", locket: "loket 04", startAt: "11:15 AM", completedAt: "11:15 AM", queueNumber: "002", status: "Menunggu", called: false, active: true},
{ id: 13, name: "Michael Johnson", phone: "08345678901", service: "FotoCopy", serviceId: "J0003", locket: "08", startAt: "11:50 AM", completedAt: "11:50 AM", queueNumber: "003", status: "Selesai", called: false, active: true, audio: "Bell"}, { id: 13, name: "Michael Johnson", phone: "08345678901", service: "FotoCopy", serviceId: "J0003", locket: "loket 08", startAt: "11:50 AM", completedAt: "11:50 AM", queueNumber: "003", status: "Menunggu", called: false, active: true},
{ id: 14, name: "Emily Brown", phone: "08456789012", service: "Online", serviceId: "J0005", locket: "02", startAt: "12:10 PM", completedAt: "12:10 PM", queueNumber: "004", status: "Menunggu", called: false, active: true, audio: "Chime"}, { id: 14, name: "Emily Brown", phone: "08456789012", service: "Online", serviceId: "J0005", locket: "loket 02", startAt: "12:10 PM", completedAt: "12:10 PM", queueNumber: "004", status: "Menunggu", called: false, active: true},
{ id: 15, name: "David Wilson", phone: "08567890123", service: "Design", serviceId: "J0002", locket: "05", startAt: "12:50 PM", completedAt: "12:50 PM", queueNumber: "005", status: "Dilayani", called: false, active: true, audio: "Ding"}, { id: 15, name: "David Wilson", phone: "08567890123", service: "Design", serviceId: "J0002", locket: "loket 05", startAt: "04:00 PM", completedAt: "12:50 PM", queueNumber: "005", status: "Menunggu", called: false, active: true},
{ id: 16, name: "John Doe", phone: "08123456789", service: "Online", serviceId: "J0005", locket: "01", startAt: "10:30 AM", completedAt: "10:30 AM", queueNumber: "001", status: "Menunggu", called: false, active: true, audio: "Default"}, { id: 16, name: "John Doe", phone: "08123456789", service: "Online", serviceId: "J0005", locket: "loket 01", startAt: "10:30 AM", completedAt: "10:30 AM", queueNumber: "001", status: "Menunggu", called: false, active: true},
{ id: 17, name: "Jane Smith", phone: "08234567890", service: "Design", serviceId: "J0002", locket: "04", startAt: "11:15 AM", completedAt: "11:15 AM", queueNumber: "002", status: "Dilayani", called: false, active: true, audio: "Beep"}, { id: 17, name: "Jane Smith", phone: "08234567890", service: "Design", serviceId: "J0002", locket: "loket 04", startAt: "11:15 AM", completedAt: "11:15 AM", queueNumber: "002", status: "Menunggu", called: false, active: true},
{ id: 18, name: "Michael Johnson", phone: "08345678901", service: "Retur", serviceId: "J0004", locket: "08", startAt: "11:50 AM", completedAt: "11:50 AM", queueNumber: "003", status: "Selesai", called: false, active: true, audio: "Bell"}, { id: 18, name: "Michael Johnson", phone: "08345678901", service: "Retur", serviceId: "J0004", locket: "loket 08", startAt: "11:50 AM", completedAt: "11:50 AM", queueNumber: "003", status: "Menunggu", called: false, active: true},
{ id: 19, name: "Emily Brown", phone: "08456789012", service: "Online", serviceId: "J0005", locket: "02", startAt: "12:10 PM", completedAt: "12:10 PM", queueNumber: "004", status: "Menunggu", called: false, active: true, audio: "Chime"}, { id: 19, name: "Emily Brown", phone: "08456789012", service: "Online", serviceId: "J0005", locket: "loket 02", startAt: "12:10 PM", completedAt: "12:10 PM", queueNumber: "004", status: "Menunggu", called: false, active: true},
{ id: 20, name: "David Wilson", phone: "08567890123", service: "Design", serviceId: "J0002", locket: "05", startAt: "12:50 PM", completedAt: "12:50 PM", queueNumber: "005", status: "Dilayani", called: false, active: true, audio: "Ding"}, { id: 20, name: "David Wilson", phone: "08567890123", service: "Design", serviceId: "J0002", locket: "loket 05", startAt: "04:00 PM", completedAt: "12:50 PM", queueNumber: "005", status: "Menunggu", called: false, active: true},
{ id: 21, name: "Sophia Martinez", phone: "08678901234", service: "Retur", serviceId: "J0004", locket: "06", startAt: "01:30 PM", completedAt: "01:30 PM", queueNumber: "006", status: "Selesai", called: false, active: true, audio: "Ping"}, { id: 21, name: "Sophia Martinez", phone: "08678901234", service: "Retur", serviceId: "J0004", locket: "loket 06", startAt: "01:30 PM", completedAt: "01:30 PM", queueNumber: "006", status: "Menunggu", called: false, active: true},
{ id: 22, name: "James Anderson", phone: "08789012345", service: "Online", serviceId: "J0005", locket: "03", startAt: "02:15 PM", completedAt: "02:15 PM", queueNumber: "007", status: "Menunggu", called: false, active: true, audio: "Chirp"}, { id: 22, name: "James Anderson", phone: "08789012345", service: "Online", serviceId: "J0005", locket: "loket 03", startAt: "02:15 PM", completedAt: "02:15 PM", queueNumber: "007", status: "Menunggu", called: false, active: true},
{ id: 23, name: "Olivia Thomas", phone: "08890123456", service: "Design", serviceId: "J0002", locket: "07", startAt: "02:50 PM", completedAt: "02:50 PM", queueNumber: "008", status: "Dilayani", called: false, active: true, audio: "Ring"}, { id: 23, name: "Olivia Thomas", phone: "08890123456", service: "Design", serviceId: "J0002", locket: "loket 07", startAt: "02:50 PM", completedAt: "02:50 PM", queueNumber: "008", status: "Menunggu", called: false, active: true},
{ id: 24, name: "Liam White", phone: "08901234567", service: "Tamu", serviceId: "J0006", locket: "09", startAt: "03:20 PM", completedAt: "03:20 PM", queueNumber: "009", status: "Selesai", called: false, active: true, audio: "Tone"}, { id: 24, name: "Liam White", phone: "08901234567", service: "Tamu", serviceId: "J0006", locket: "loket 09", startAt: "03:20 PM", completedAt: "03:20 PM", queueNumber: "009", status: "Menunggu", called: false, active: true},
{ id: 25, name: "Emma Harris", phone: "08012345678", service: "Siap Print", serviceId: "J0001", locket: "10", startAt: "03:50 PM", completedAt: "03:50 PM", queueNumber: "010", status: "Menunggu", called: false, active: true, audio: "Alarm"}, { id: 25, name: "Emma Harris", phone: "08012345678", service: "Siap Print", serviceId: "J0001", locket: "loket 10", startAt: "03:50 PM", completedAt: "03:50 PM", queueNumber: "010", status: "Menunggu", called: false, active: true},
]; ];
export const getQueueSettingsData = () => { export const getQueueSettingsData = () => {
@ -61,10 +61,21 @@ export const toggleServiceStatus = (id) => {
}; };
export const getFilteredQueueData = (callQueueView = false) => { export const getFilteredQueueData = (callQueueView = false) => {
if (callQueueView) { let filteredQueue = queueData.filter((item) =>
return queueData.filter((item) => item.status === "Menunggu"); callQueueView ? item.status === "Menunggu" : true
} );
return queueData;
// Urutkan berdasarkan status "Menunggu" terlebih dahulu, lalu berdasarkan startAt
filteredQueue.sort((a, b) => {
if (a.status === "Menunggu" && b.status !== "Menunggu") return -1;
if (b.status === "Menunggu" && a.status !== "Menunggu") return 1;
const timeA = new Date(`1970/01/01 ${a.startAt}`);
const timeB = new Date(`1970/01/01 ${b.startAt}`);
return timeA - timeB;
});
return filteredQueue;
}; };
export const getQueueDisplayData = () => { export const getQueueDisplayData = () => {
@ -79,9 +90,6 @@ export const getQueueDisplayData = () => {
})); }));
}; };
// QueueActions.js
import { useState } from "react"; import { useState } from "react";
export const useQueueData = (settingsView, callQueueView) => { export const useQueueData = (settingsView, callQueueView) => {
@ -113,7 +121,7 @@ export const useQueueData = (settingsView, callQueueView) => {
searchQuery, searchQuery,
setSearchQuery, setSearchQuery,
setCurrentPage, setCurrentPage,
indexOfFirstItem, // Tambahkan ini indexOfFirstItem,
}; };
}; };

View File

@ -1,142 +1,143 @@
import { Table, Button, Form, Pagination, InputGroup, FormControl } from "react-bootstrap"; import { useState } from "react";
import { Card, Table, Button, Form, Pagination, InputGroup, FormControl, Modal } from "react-bootstrap";
import { FaSearch } from "react-icons/fa"; import { FaSearch } from "react-icons/fa";
import { handleCall, toggleServiceStatus, handleDelete, handleEdit, useQueueData } from "./QueueActions"; import { handleCall, useQueueData } from "./QueueActions";
// eslint-disable-next-line react/prop-types // eslint-disable-next-line react/prop-types
const QueueTable = ({ showActions = true, reportView = false, settingsView = false, displayView = false, callQueueView = false }) => { const QueueTable = ({ settingsView = false, displayView = false }) => {
const { currentItems, currentPage, totalPages, searchQuery, setSearchQuery, setCurrentPage, indexOfFirstItem } = useQueueData(settingsView);
const { currentItems, currentPage, totalPages, searchQuery, setSearchQuery, setCurrentPage, indexOfFirstItem } = useQueueData(settingsView, callQueueView);
// State untuk modal
const [showModal, setShowModal] = useState(false);
const [selectedQueue, setSelectedQueue] = useState(null);
const [selectedLocket, setSelectedLocket] = useState("");
// Data loket operator (bisa diganti dengan API)
const availableLockets = ["Loket 1", "Loket 2", "Loket 3", "Loket 4", "Loket 5", "Loket 6", "Loket 7", "Loket 8", "Loket 9"];
// Fungsi membuka modal dan menyimpan antrian yang dipilih
const handleOpenModal = (queue) => {
setSelectedQueue(queue);
setShowModal(true);
};
// Fungsi menutup modal
const handleCloseModal = () => {
setShowModal(false);
setSelectedQueue(null);
setSelectedLocket("");
};
// Fungsi memilih loket dan panggil antrian
const handleSelectLocket = () => {
if (selectedLocket) {
handleCall(selectedQueue.id, selectedLocket); // Panggil dengan loket
handleCloseModal(); // Tutup modal setelah memilih
}
};
return ( return (
<> <>
{(callQueueView || reportView || (!settingsView && !displayView)) && ( <Card className="shadow-sm">
<InputGroup className="mb-3"> <Card.Header className="d-flex justify-content-between align-items-center">
<InputGroup.Text> {(!settingsView && !displayView) && (
<FaSearch /> <InputGroup className="w-auto">
</InputGroup.Text> <InputGroup.Text>
<FormControl <FaSearch />
type="text" </InputGroup.Text>
placeholder="Cari nama atau layanan..." <FormControl
value={searchQuery} type="text"
onChange={(e) => setSearchQuery(e.target.value)} placeholder="Cari nama atau layanan..."
/> value={searchQuery}
</InputGroup> onChange={(e) => setSearchQuery(e.target.value)}
)} />
<Table striped bordered hover responsive> </InputGroup>
<thead> )}
<tr> <Pagination className="mb-0">
<th>#</th> <Pagination.Prev onClick={() => setCurrentPage(prev => Math.max(prev - 1, 1))} disabled={currentPage === 1} />
{displayView ? ( {[...Array(totalPages)].map((_, index) => (
<> <Pagination.Item key={index + 1} active={index + 1 === currentPage} onClick={() => setCurrentPage(index + 1)}>
<th>Pengaturan Suara</th> {index + 1}
<th>Video Komersil</th> </Pagination.Item>
<th className="text-center">Aksi</th> ))}
</> <Pagination.Next onClick={() => setCurrentPage(prev => Math.min(prev + 1, totalPages))} disabled={currentPage === totalPages} />
) : settingsView ? ( </Pagination>
<> </Card.Header>
<th>Nama Layanan</th>
<th>ID Layanan</th> <Card.Body style={{ minHeight: "500px", display: "flex", flexDirection: "column" }}>
<th>Status</th> <div style={{ flex: "1", overflowY: "auto" }}>
<th className="text-center">Aksi</th> <Table striped bordered hover responsive>
</> <thead>
) : reportView ? ( <tr>
<> <th>#</th>
<th>Nama</th> <th>Nama</th>
<th>No. Telepon</th> <th>Layanan</th>
<th>Layanan</th> <th>Kode Layanan</th>
<th>Loket</th> <th>Nomor Antrian</th>
<th>Cetak Antrian</th> <th>Pengambilan</th>
<th>Selesai Antrian</th> <th>Loket</th>
<th className="text-center">Aksi</th> <th>Status</th>
</> <th className="text-center">Aksi</th>
) : ( </tr>
<> </thead>
<th>Nama</th> <tbody>
<th>Layanan</th> {currentItems.map((item, index) => (
<th>Kode Layanan</th> <tr key={item.id}>
<th>Nomor Antrian</th> <td>{index + 1 + indexOfFirstItem}</td>
<th>Loket</th> <td>{item.name}</td>
<th>Status</th> <td>{item.service}</td>
{showActions && <th className="text-center">Aksi</th>} <td>{item.serviceId}</td>
</> <td>{item.queueNumber}</td>
)} <td>{item.startAt}</td>
</tr> <td>{item.status === "Dilayani" ? item.locket : "-"}</td>
</thead> <td>{item.status}</td>
<tbody>
{currentItems.map((item, index) => (
<tr key={item.id}>
<td>{index + 1 + indexOfFirstItem}</td>
{displayView ? (
<>
<td>
<Form.Select defaultValue={item.audio}>
<option>Default</option>
<option>Beep</option>
<option>Bell</option>
</Form.Select>
</td>
<td>{item.video}</td>
<td className="text-center">
<Button variant="info" size="sm" className="me-2">View</Button>
<Button variant="warning" size="sm" className="me-2">Edit</Button>
<Button variant="danger" size="sm">Hapus</Button>
</td>
</>
) : settingsView ? (
<>
<td>{item.service}</td>
<td>{item.serviceId}</td>
<td>{item.active ? "Aktif" : "Nonaktif"}</td>
<td className="text-center">
<Button variant={item.active ? "danger" : "success"} size="sm" onClick={() => toggleServiceStatus(item.id)}>
{item.active ? "Nonaktifkan" : "Aktifkan"}
</Button>
</td>
</>
) : reportView ? (
<>
<td>{item.name}</td>
<td>{item.phone}</td>
<td>{item.service}</td>
<td>{item.locket}</td>
<td>{item.startAt}</td>
<td>{item.completedAt}</td>
<td className="text-center">
<Button variant="warning" size="sm" className="me-2" onClick={() => handleEdit(item.id)}>Edit</Button>
<Button variant="danger" size="sm" onClick={() => handleDelete(item.id)}>Hapus</Button>
</td>
</>
) : (
<>
<td>{item.name}</td>
<td>{item.service}</td>
<td>{item.serviceId}</td>
<td>{item.queueNumber}</td>
<td>{item.status === "Dilayani" ? item.locket : "-"}</td>
<td>{item.status}</td>
{showActions && (
<td className="text-center"> <td className="text-center">
<Button variant={item.called ? "warning" : "primary"} size="sm" className="me-2" onClick={() => handleCall(item.id)}> <Button variant="primary" size="sm" className="me-2" onClick={() => handleOpenModal(item)}>
{item.called ? "Panggil Ulang" : "Panggil"} Panggil
</Button> </Button>
<Button variant="danger" size="sm">Hapus</Button>
</td> </td>
)} </tr>
</> ))}
)} {Array.from({ length: Math.max(0, 10 - currentItems.length) }).map((_, index) => (
</tr> <tr key={`empty-${index}`} className="empty-row">
))} <td colSpan="9">&nbsp;</td>
</tbody> </tr>
</Table> ))}
<Pagination className="justify-content-center"> </tbody>
<Pagination.Prev onClick={() => setCurrentPage(prev => Math.max(prev - 1, 1))} disabled={currentPage === 1} /> </Table>
{[...Array(totalPages)].map((_, index) => ( </div>
<Pagination.Item key={index + 1} active={index + 1 === currentPage} onClick={() => setCurrentPage(index + 1)}> </Card.Body>
{index + 1} </Card>
</Pagination.Item>
))} {/* Modal untuk memilih loket */}
<Pagination.Next onClick={() => setCurrentPage(prev => Math.min(prev + 1, totalPages))} disabled={currentPage === totalPages} /> <Modal show={showModal} onHide={handleCloseModal} centered>
</Pagination> <Modal.Header closeButton>
<Modal.Title>Pilih Loket Operator</Modal.Title>
</Modal.Header>
<Modal.Body>
<Form>
{availableLockets.map((locket, index) => (
<Form.Check
key={index}
type="radio"
label={locket}
name="locket"
value={locket}
checked={selectedLocket === locket}
onChange={(e) => setSelectedLocket(e.target.value)}
/>
))}
</Form>
</Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={handleCloseModal}>
Batal
</Button>
<Button variant="primary" onClick={handleSelectLocket} disabled={!selectedLocket}>
Panggil
</Button>
</Modal.Footer>
</Modal>
</> </>
); );
}; };

View File

@ -0,0 +1,30 @@
// FILE INI UNTUK TEST TAMPILAN DATA DENGAN API
import { fetchQueues, updateQueueStatus } from "../../api/queueApi";
export const getProcessedQueues = async () => {
const data = await fetchQueues();
// Ubah struktur data jika diperlukan
const processedData = data.map((operator) => ({
operatorId: operator.id,
operatorName: operator.name,
queues: operator.queues.map((queue) => ({
id: queue.queue_id,
customerName: queue.customer.name,
customerEmail: queue.customer.email,
customerPhone: queue.customer.phone,
serviceId: queue.service.id,
serviceName: queue.service.name,
status: queue.status,
createdAt: queue.created_at,
})),
}));
return processedData;
};
export const changeQueueStatus = async (queueId, newStatus) => {
return await updateQueueStatus(queueId, newStatus);
};

View File

@ -0,0 +1,133 @@
// FILE INI UNTUK TEST TAMPILAN DATA DENGAN API
import { useEffect, useState } from "react";
import { getProcessedQueues } from "./TestQueueActions";
import { Card, Table, Container, Button, Modal, ListGroup } from "react-bootstrap";
const TestQueueTable = () => {
const [queues, setQueues] = useState([]);
const [selectedQueue, setSelectedQueue] = useState(null);
const [showModal, setShowModal] = useState(false);
useEffect(() => {
const fetchData = async () => {
const data = await getProcessedQueues();
// Flatten data agar tidak dikelompokkan per operator
const allQueues = data.flatMap((operator) =>
operator.queues.map((queue) => ({
...queue,
operatorName: operator.operatorName, // Menyimpan nama operator di setiap antrian
}))
);
// Sort data: Prioritaskan yang Waiting dan urutkan berdasarkan createdAt
allQueues.sort((a, b) => {
if (a.status === "Waiting" && b.status !== "Waiting") return -1;
if (a.status !== "Waiting" && b.status === "Waiting") return 1;
return new Date(a.createdAt) - new Date(b.createdAt);
});
setQueues(allQueues);
};
fetchData();
}, []);
// Data dummy untuk loket operator yang tersedia
const availableCounters = [
{ id: "LKT001", name: "Loket 1" },
{ id: "LKT002", name: "Loket 2" },
{ id: "LKT003", name: "Loket 3" },
];
// Handler untuk membuka modal dan memilih queue
const handleCallQueue = (queue) => {
setSelectedQueue(queue);
setShowModal(true);
};
return (
<Container className="mt-4">
<Card className="shadow">
<Card.Header className="bg-primary text-white">
<h5 className="mb-0">List Antrian</h5>
</Card.Header>
<Card.Body>
<Table striped bordered hover size="sm" responsive>
<thead>
<tr>
<th>Customer</th>
<th>Email</th>
<th>Phone</th>
<th>Service</th>
<th>Status</th>
<th>Created At</th>
<th>Action</th>
</tr>
</thead>
<tbody>
{queues.length > 0 ? (
queues.map((queue) => (
<tr key={queue.id}>
<td>{queue.customerName}</td>
<td>{queue.customerEmail}</td>
<td>{queue.customerPhone}</td>
<td>{queue.serviceName}</td>
<td>
<span
className={`badge ${
queue.status === "Completed"
? "bg-success"
: queue.status === "In Progress"
? "bg-warning text-dark"
: "bg-danger"
}`}
>
{queue.status}
</span>
</td>
<td>{new Date(queue.createdAt).toLocaleString()}</td>
<td>
{queue.status !== "In Progress" && queue.status !== "Completed" && (
<Button
variant="info"
size="sm"
onClick={() => handleCallQueue(queue)}
>
Panggil Antrian
</Button>
)}
</td>
</tr>
))
) : (
<tr>
<td colSpan="9" className="text-center text-muted">
No queues available
</td>
</tr>
)}
</tbody>
</Table>
</Card.Body>
</Card>
{/* Modal Pilih Loket */}
<Modal show={showModal} onHide={() => setShowModal(false)} centered>
<Modal.Header closeButton>
<Modal.Title>Pilih Loket Operator</Modal.Title>
</Modal.Header>
<Modal.Body>
<p>Memanggil antrian <strong>{selectedQueue?.customerName}</strong></p>
<ListGroup>
{availableCounters.map((counter) => (
<ListGroup.Item key={counter.id} action>
{counter.name}
</ListGroup.Item>
))}
</ListGroup>
</Modal.Body>
</Modal>
</Container>
);
};
export default TestQueueTable;

View File

@ -80,19 +80,53 @@ const QueueDisplay = () => {
</Row> </Row>
{/* Loket Antrian */} {/* Loket Antrian */}
<Row className="text-center d-flex flex-wrap justify-content-center g-0"> <Row className="d-flex flex-wrap g-0">
<Col className="d-flex justify-content-center p-2"> <Col className="d-flex p-2">
<Card className="d-flex align-items-center justify-content-center text-center flex-grow-1" <Card className="flex-grow-1"
style={{ borderRadius: "10px", width: "100%", minHeight: "150px" }}> style={{ borderRadius: "10px", width: "100%", minHeight: "150px" }}>
<Card.Title className="p-3">
<h2>
List Antrian Layanan
</h2>
</Card.Title>
<Row>
<Col>
<Card.Body>
<Card.Title>List Antrian Layanan</Card.Title> <Card.Title>List Antrian Layanan</Card.Title>
<Row> <p>data antrian</p>
<Col> </Card.Body>
<Card.Body> </Col>
<Card.Title>List Antrian Layanan</Card.Title> <Col>
<h2 style={{ fontSize: "40px", fontWeight: "bold" }}></h2> <Card.Body>
</Card.Body> <Card.Title>List Antrian Layanan</Card.Title>
</Col> <p>data antrian</p>
</Row> </Card.Body>
</Col>
<Col>
<Card.Body>
<Card.Title>List Antrian Layanan</Card.Title>
<p>data antrian</p>
</Card.Body>
</Col>
<Col>
<Card.Body>
<Card.Title>List Antrian Layanan</Card.Title>
<p>data antrian</p>
</Card.Body>
</Col>
<Col>
<Card.Body>
<Card.Title>List Antrian Layanan</Card.Title>
<p>data antrian</p>
</Card.Body>
</Col>
<Col>
<Card.Body>
<Card.Title>List Antrian Layanan</Card.Title>
<p>data antrian</p>
</Card.Body>
</Col>
</Row>
</Card> </Card>
</Col> </Col>
</Row> </Row>

View File

@ -1,5 +1,5 @@
import { Container, Card, Button, Row, Col, Form, Carousel } from 'react-bootstrap'; import { Container, Card, Button, Row, Col, Form, Carousel } from 'react-bootstrap';
import { useState } from 'react'; import { useState, useEffect } from 'react';
import { FaPrint, FaPalette, FaFileAlt, FaUndo, FaTruck, FaUser } from 'react-icons/fa'; import { FaPrint, FaPalette, FaFileAlt, FaUndo, FaTruck, FaUser } from 'react-icons/fa';
const services = [ const services = [
@ -18,15 +18,17 @@ const ServiceSelection = () => {
const [ticket, setTicket] = useState(null); const [ticket, setTicket] = useState(null);
const [enableForm, setEnableForm] = useState(false); const [enableForm, setEnableForm] = useState(false);
useEffect(() => {
if (selectedService && !enableForm) {
generateTicket();
}
}, [selectedService]);
const handleServiceSelect = (serviceId) => { const handleServiceSelect = (serviceId) => {
setSelectedService(services.find(service => service.id === serviceId)); setSelectedService(services.find(service => service.id === serviceId));
if (!enableForm) {
handleSubmit(new Event("submit"));
}
}; };
const handleSubmit = (e) => { const generateTicket = () => {
e.preventDefault();
if (selectedService) { if (selectedService) {
const queueNumber = `${selectedService.id}-${Math.floor(1000 + Math.random() * 9000)}`; const queueNumber = `${selectedService.id}-${Math.floor(1000 + Math.random() * 9000)}`;
const newTicket = { const newTicket = {
@ -41,31 +43,35 @@ const ServiceSelection = () => {
} }
}; };
const handleSubmit = (e) => {
e.preventDefault();
generateTicket();
};
return ( return (
<Container> <Container>
{!ticket ? ( {!ticket ? (
<Row className="vh-100"> <Row className="vh-100">
<Col md={6} className="d-flex flex-column"> <Col md={6} className="d-flex flex-column">
<h3 className="my-4">Pilih Layanan</h3> <div className="my-4">
<h3>Pilih Layanan</h3>
</div>
<Row className="flex-grow-1"> <Row className="flex-grow-1">
{services.map(service => { {services.map(service => (
const isSelected = selectedService?.id === service.id; <Col key={service.id} md={6} className="mb-3">
return ( <Card
<Col key={service.id} md={6} className="mb-3"> className="h-100 shadow rounded-3 bg-light"
<Card onClick={() => handleServiceSelect(service.id)}
className={`h-100 shadow rounded-3 ${isSelected ? "bg-primary text-white border-primary" : "bg-light"}`} >
onClick={() => handleServiceSelect(service.id)} <Card.Body className="d-flex flex-column justify-content-center align-items-center">
> {service.icon}
<Card.Body className="d-flex flex-column justify-content-center align-items-center"> <Card.Text className="text-center mt-5">
{service.icon} <h5>{service.name}</h5>
<Card.Text className="text-center mt-5"> </Card.Text>
<h5>{service.name}</h5> </Card.Body>
</Card.Text> </Card>
</Card.Body> </Col>
</Card> ))}
</Col>
);
})}
</Row> </Row>
</Col> </Col>
<Col md={6} className="d-flex flex-column"> <Col md={6} className="d-flex flex-column">
@ -91,7 +97,6 @@ const ServiceSelection = () => {
value={name} value={name}
onChange={(e) => setName(e.target.value)} onChange={(e) => setName(e.target.value)}
disabled={!enableForm} disabled={!enableForm}
className={`border ${enableForm ? "border-primary" : "border-secondary"} ${enableForm ? "" : "bg-light text-secondary"}`}
/> />
</Form.Group> </Form.Group>
<Form.Group className="mb-3" controlId="formPhone"> <Form.Group className="mb-3" controlId="formPhone">
@ -102,7 +107,6 @@ const ServiceSelection = () => {
value={phone} value={phone}
onChange={(e) => setPhone(e.target.value)} onChange={(e) => setPhone(e.target.value)}
disabled={!enableForm} disabled={!enableForm}
className={`border ${enableForm ? "border-primary" : "border-secondary"} ${enableForm ? "" : "bg-light text-secondary"}`}
/> />
</Form.Group> </Form.Group>
<Button variant={enableForm ? "primary" : "secondary"} type="submit" disabled={!enableForm}> <Button variant={enableForm ? "primary" : "secondary"} type="submit" disabled={!enableForm}>
@ -111,11 +115,11 @@ const ServiceSelection = () => {
</Form> </Form>
</Card.Body> </Card.Body>
</Card> </Card>
<div className="d-flex flex-grow-1 my-3 align-items-center justify-content-center"> <div className="d-flex flex-grow-1 align-items-center justify-content-center">
<Carousel> <Carousel className='w-100'>
{["c1.png", "c2.jpg", "c3.jpg"].map((image, index) => ( {["c1.png", "c2.jpg", "c3.jpg"].map((image, index) => (
<Carousel.Item key={index} interval={3000}> <Carousel.Item key={index} interval={3000} className='rounded'>
<img className="d-block w-100" src={`/public/${image}`} alt={`Slide ${index + 1}`} height={300} /> <img className="d-block w-100 img-fluid rounded" src={`/public/${image}`} alt={`Slide ${index + 1}`}/>
</Carousel.Item> </Carousel.Item>
))} ))}
</Carousel> </Carousel>

View File

@ -0,0 +1,45 @@
// FILE INI UNTUK TEST TAMPILAN DATA DENGAN API
import { useEffect, useState } from "react";
import { getProcessedQueues } from "../Admin/TestQueueActions";
import { Card, Container } from "react-bootstrap";
const TestQueueDisplay = () => {
const [queues, setQueues] = useState([]);
useEffect(() => {
const fetchData = async () => {
const data = await getProcessedQueues();
// Ambil hanya antrian yang masih berlangsung atau menunggu, lalu urutkan
const sortedQueues = data
.flatMap((operator) => operator.queues)
.filter((queue) => queue.status !== "Completed")
.sort((a, b) => new Date(a.createdAt) - new Date(b.createdAt));
setQueues(sortedQueues);
};
fetchData();
const interval = setInterval(fetchData, 2000); // Auto-refresh tiap 5 detik
return () => clearInterval(interval);
}, []);
return (
<Container className="mt-4 text-center">
<h2 className="mb-4">Layar Antrian</h2>
{queues.length > 0 ? (
<Card className="shadow p-4">
<h1 className="display-3 text-primary">{queues[0].id}</h1>
<h4>{queues[0].customerName}</h4>
<p>{queues[0].serviceName}</p>
</Card>
) : (
<p className="text-muted">Tidak ada antrian aktif</p>
)}
</Container>
);
};
export default TestQueueDisplay;

View File

@ -0,0 +1,34 @@
// FILE INI UNTUK TEST TAMPILAN DATA DENGAN API
import { useEffect, useState } from "react";
import { getProcessedQueues } from "../Admin/TestQueueActions";
import { Container, Card, Row, Col, Table } from "react-bootstrap";
const ServiceSelection = () => {
const [queues, setQueues] = useState([]);
useEffect(() => {
getProcessedQueues().then(setQueues);
}, []);
return (
<Container>
<Row>
{queues.map((operator) => (
<Col key={operator.operatorId}>
<h3>{operator.operatorName}</h3>
<ul>
{operator.queues.map((queue) => (
<li key={queue.id}>{queue.serviceName}</li>
))}
</ul>
</Col>
))}
</Row>
</Container>
);
};
export default ServiceSelection;

View File

@ -1,10 +1,10 @@
import QueueTable from "../../components/Admin/QueueTable"; import TestQueueTable from "../../components/Admin/TestQueueTable";
const CallQueuePage = () => { const CallQueuePage = () => {
return ( return (
<div> <div>
<h2>Panggil Atrian Page</h2> <h2>Panggil Atrian Page</h2>
<QueueTable callQueueView={true}/> <TestQueueTable/>
</div> </div>
) )
} }

View File

@ -1,11 +1,14 @@
import TestQueueTable from "../../components/Admin/TestQueueTable";
import QueueTable from "../../components/Admin/QueueTable"; import QueueTable from "../../components/Admin/QueueTable";
const QueueListPage = () => { const QueueListPage = () => {
return ( return (
<div> <div>
<h2>Daftar Antrian</h2>
<QueueTable showActions={false}/> {/* <TestQueueTable/> INI ADALAH UNTUK TEST DATA DENGAN API */}
<QueueTable/>
</div> </div>
); );
}; };

View File

@ -1,8 +1,10 @@
import TestQueueDisplay from "../../components/Display/TestQueueDisplay"
import QueueDisplay from "../../components/Display/QueueDisplay" import QueueDisplay from "../../components/Display/QueueDisplay"
const QueueDisplayPage = () => { const QueueDisplayPage = () => {
return ( return (
<> <>
{/* <TestQueueDisplay/> INI ADALAH UNTUK TEST DATA DENGAN API */}
<QueueDisplay/> <QueueDisplay/>
</> </>
) )

View File

@ -1,8 +1,10 @@
import TestServiceSelection from "../../components/Display/TestServiceSelection"
import ServiceSelection from "../../components/Display/ServiceSelection" import ServiceSelection from "../../components/Display/ServiceSelection"
const QueueMenuPage = () => { const QueueMenuPage = () => {
return ( return (
<> <>
{/* <TestServiceSelection/> INI ADALAH UNTUK TEST DATA DENGAN API */}
<ServiceSelection/> <ServiceSelection/>
</> </>
) )

View File

@ -1,8 +1,8 @@
import { BrowserRouter as Router, Routes, Route, Navigate } from "react-router-dom"; import { BrowserRouter as Router, Routes, Route, Navigate } from "react-router-dom";
import AdminLayout from "../layouts/AdminLayout"; import AdminLayout from "../layouts/AdminLayout";
import QueueListPage from "../pages/admin/QueueListPage"; import QueueListPage from "../pages/admin/QueueListPage";
import CallQueuePage from "../pages/admin/CallQueuePage"; // import CallQueuePage from "../pages/admin/CallQueuePage";
import QueueReportPage from "../pages/admin/QueueReportPage"; // import QueueReportPage from "../pages/admin/QueueReportPage";
import QueueSettingsDisplayPage from "../pages/admin/QueueSettingsDisplayPage"; import QueueSettingsDisplayPage from "../pages/admin/QueueSettingsDisplayPage";
import QueueSettingsMenuPage from "../pages/admin/QueueSettingsMenuPage"; import QueueSettingsMenuPage from "../pages/admin/QueueSettingsMenuPage";
import QueueDisplayPage from "../pages/display/QueueDisplayPage"; import QueueDisplayPage from "../pages/display/QueueDisplayPage";
@ -18,8 +18,8 @@ const AppRoutes = () => {
{/* Rute untuk Admin */} {/* Rute untuk Admin */}
<Route path="/admin" element={<AdminLayout />}> <Route path="/admin" element={<AdminLayout />}>
<Route path="queue-list" element={<QueueListPage />} /> <Route path="queue-list" element={<QueueListPage />} />
<Route path="call-queue" element={<CallQueuePage />} /> {/* <Route path="call-queue" element={<CallQueuePage />} />
<Route path="queue-report" element={<QueueReportPage />} /> <Route path="queue-report" element={<QueueReportPage />} /> */}
<Route path="queue-settings-display" element={<QueueSettingsDisplayPage />} /> <Route path="queue-settings-display" element={<QueueSettingsDisplayPage />} />
<Route path="queue-settings-menu" element={<QueueSettingsMenuPage />} /> <Route path="queue-settings-menu" element={<QueueSettingsMenuPage />} />
</Route> </Route>