Implementasi API table face dan ktp

This commit is contained in:
Rizqika 2025-01-02 18:38:56 +07:00
parent 7996568d74
commit daf0e7e54d
4 changed files with 145 additions and 113 deletions

@ -1 +1 @@
Subproject commit addaac2b9a73b75761c7449341ecc23bfbe63cc2
Subproject commit e15616c8ba2cd26017469382b0f58121b07e8cac

0
SingleMessage.js Normal file
View File

View File

@ -3,6 +3,7 @@ import { FaChevronLeft, FaChevronRight, FaFastBackward, FaFastForward, FaSort, F
import { NoAvailable } from '../../../assets/icon';
const BASE_URL = process.env.REACT_APP_BASE_URL
const LOCAL_URL = 'http://127.0.0.1:8000'
const API_KEY = process.env.REACT_APP_API_KEY
// Pagination Component
const Pagination = ({ currentPage, totalPages, onPageChange }) => {
@ -126,7 +127,7 @@ const Transaction = () => {
const fetchTransactionData = async (page, limit, search = '', sortColumn = 'tf.id', sortOrder = 'asc') => {
try {
console.log(`Fetching data for page: ${page}, limit: ${limit}, search: ${search}, sortColumn: ${sortColumn}, sortOrder: ${sortOrder}`); // Log page, limit, and search
const response = await fetch(`${BASE_URL}/trx_face/table-log?search=${search}&sortColumn=${sortColumn}&sortOrder=${sortOrder}&limit=${limit}&page=${page}`, {
const response = await fetch(`${LOCAL_URL}/trx_face/table-log?search=${search}&sortColumn=${sortColumn}&sortOrder=${sortOrder}`, {
method: 'GET',
headers: { 'accept': 'application/json', 'x-api-key': API_KEY },
});

View File

@ -2,6 +2,9 @@ import React, { useState, useEffect } from 'react';
import { FaChevronLeft, FaChevronRight, FaFastBackward, FaFastForward, FaSort, FaSortUp, FaSortDown } from 'react-icons/fa'; // Icons for sorting
import { NoAvailable } from '../../../assets/icon';
const BASE_URL = process.env.REACT_APP_BASE_URL
const LOCAL_URL = 'http://127.0.0.1:8000'
const API_KEY = process.env.REACT_APP_API_KEY
// Pagination Component
const Pagination = ({ currentPage, totalPages, onPageChange }) => {
const handlePrev = () => {
@ -106,6 +109,10 @@ const Transaction = () => {
const [transactionData, setTransactionData] = useState([]);
const [sortConfig, setSortConfig] = useState({ key: null, direction: 'asc' }); // Sorting state
const dataPerPage = 10; // Data per page (10 data per page)
const [totalPages, setTotalPages] = useState(1); // Total pages from API
const [searchTerm, setSearchTerm] = useState('');
const [sortColumn, setSortColumn] = useState('tf.id');
const [sortOrder, setSortOrder] = useState('asc');
const buttonData = [
{ label: 'Copy', enabled: true },
@ -116,30 +123,51 @@ const Transaction = () => {
{ label: 'Column Visibility', enabled: true },
];
// Generate 691 dummy transactions
const generateDummyData = (numOfItems) => {
const transactionData = [];
for (let i = 1; i <= numOfItems; i++) {
transactionData.push({
transactionId: `TX${String(i).padStart(3, '0')}`,
applicationName: `App ${Math.floor(Math.random() * 5) + 1}`,
createdAt: new Date(2023, Math.floor(Math.random() * 12), Math.floor(Math.random() * 28) + 1).toLocaleDateString(), // Random date
referenceId: `REF${String(i).padStart(3, '0')}`,
status: ['Completed', 'Pending', 'Failed'][Math.floor(Math.random() * 3)],
mode: Math.random() > 0.5 ? 'Online' : 'Offline',
// Fetch transaction data from API
const fetchTransactionData = async (page, limit, search = '', sortColumn = 'tf.id', sortOrder = 'asc') => {
try {
console.log(`Fetching data for page: ${page}, limit: ${limit}, search: ${search}, sortColumn: ${sortColumn}, sortOrder: ${sortOrder}`); // Log page, limit, and search
const response = await fetch(`${LOCAL_URL}/ocr-ktp/table-transactions?search=${search}&sortColumn=${sortColumn}&sortOrder=${sortOrder}`, {
method: 'GET',
headers: { 'accept': 'application/json', 'x-api-key': API_KEY },
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const result = await response.json();
const { data, total } = result.details.details.data;
setTransactionData(data);
setTotalPages(Math.ceil(total / dataPerPage));
} catch (error) {
console.error('Error fetching transaction data:', error);
}
return transactionData;
};
const fetchPaginationData = async (page, limit, search = '') => {
try {
console.log(`Fetching pagination data for page: ${page}, limit: ${limit}, search: ${search}`); // Log page, limit, and search
const url = `${BASE_URL}/header_detail_param/paging?header_id=1&page=${page}&limit=${limit}&search=${search}`;
console.log(`Fetching URL: ${url}`); // Log the URL
const response = await fetch(url, {
method: 'GET',
headers: { 'accept': 'application/json', 'x-api-key': API_KEY },
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const result = await response.json();
const { data } = result.details;
setTotalPages(Math.ceil(data.length / dataPerPage));
} catch (error) {
console.error('Error fetching pagination data:', error);
}
};
// Set the generated transaction data
// Fetch data when component mounts and when currentPage changes
useEffect(() => {
setTransactionData(generateDummyData(3113)); // count data dummy transactions
}, []);
fetchTransactionData(currentPage, dataPerPage, searchTerm, sortColumn, sortOrder);
fetchPaginationData(currentPage, dataPerPage);
}, [currentPage, searchTerm, sortColumn, sortOrder]);
// Sorting function
const sortData = (data, config) => {
@ -177,8 +205,14 @@ const Transaction = () => {
setCurrentPage(page);
};
// Calculate total pages based on the data and data per page
const totalPages = Math.ceil(transactionData.length / dataPerPage);
// Handle search
const handleSearch = async (event) => {
const searchQuery = event.target.value;
setSearchTerm(searchQuery);
setCurrentPage(1); // Reset to first page on new search
await fetchPaginationData(1, dataPerPage, searchQuery);
await fetchTransactionData(1, dataPerPage, searchQuery);
};
// Paginated data
const paginatedData = getPaginatedData(transactionData, currentPage, dataPerPage);
@ -258,11 +292,12 @@ const Transaction = () => {
</div>
{/* Search Bar with Icon */}
<div className="input-group" style={{ width: '250px', display: 'flex', alignItems: 'center', justifyContent: 'flex-end' }}>
<div className="input-group" style={{ width: '350px', display: 'flex', alignItems: 'center', justifyContent: 'flex-end' }}>
<input
type="text"
placeholder="Search..."
placeholder="Search Application Name or Subject ID" // Placeholder text
className="form-control"
onChange={handleSearch} // Add onChange handler
/>
<span className="input-group-text">
<i className="fas fa-search"></i> {/* FontAwesome search icon */}
@ -276,59 +311,58 @@ const Transaction = () => {
<table className="table table-bordered" style={styles.tableContainer}>
<thead>
<tr>
<th>No.</th> {/* Kolom untuk Nomor Urut */}
<th>
<button className="btn" onClick={() => handleSort('transactionId')}>
<button className="btn" onClick={() => handleSort('transaction_id')}>
Transaction ID
{sortConfig.key === 'transactionId' &&
{sortConfig.key === 'transaction_id' &&
(sortConfig.direction === 'asc' ? <FaSortUp style={styles.iconMarginLeft} /> : <FaSortDown style={styles.iconMarginLeft} />)
}
{sortConfig.key !== 'transactionId' && <FaSort style={styles.iconMarginLeft} />}
{sortConfig.key !== 'transaction_id' && <FaSort style={styles.iconMarginLeft} />}
</button>
</th>
<th>
<button className="btn" onClick={() => handleSort('applicationName')}>
<button className="btn" onClick={() => handleSort('app_name')}>
Application Name
{sortConfig.key === 'applicationName' &&
{sortConfig.key === 'app_name' &&
(sortConfig.direction === 'asc' ? <FaSortUp style={styles.iconMarginLeft} /> : <FaSortDown style={styles.iconMarginLeft} />)
}
{sortConfig.key !== 'applicationName' && <FaSort style={styles.iconMarginLeft} />}
{sortConfig.key !== 'app_name' && <FaSort style={styles.iconMarginLeft} />}
</button>
</th>
<th>
<button className="btn" onClick={() => handleSort('createdAt')}>
<button className="btn" onClick={() => handleSort('created_at')}>
Created At
{sortConfig.key === 'createdAt' &&
{sortConfig.key === 'created_at' &&
(sortConfig.direction === 'asc' ? <FaSortUp style={styles.iconMarginLeft} /> : <FaSortDown style={styles.iconMarginLeft} />)
}
{sortConfig.key !== 'createdAt' && <FaSort style={styles.iconMarginLeft} />}
{sortConfig.key !== 'created_at' && <FaSort style={styles.iconMarginLeft} />}
</button>
</th>
<th>
<button className="btn" onClick={() => handleSort('referenceId')}>
Reference ID
{sortConfig.key === 'referenceId' &&
<button className="btn" onClick={() => handleSort('service_name')}>
Service Name
{sortConfig.key === 'service_name' &&
(sortConfig.direction === 'asc' ? <FaSortUp style={styles.iconMarginLeft} /> : <FaSortDown style={styles.iconMarginLeft} />)
}
{sortConfig.key !== 'referenceId' && <FaSort style={styles.iconMarginLeft} />}
{sortConfig.key !== 'service_name' && <FaSort style={styles.iconMarginLeft} />}
</button>
</th>
<th>
<button className="btn" onClick={() => handleSort('status')}>
Status
{sortConfig.key === 'status' &&
(sortConfig.direction === 'asc' ? <FaSortUp style={styles.iconMarginLeft} /> : <FaSortDown style={styles.iconMarginLeft} />)
}
{sortConfig.key !== 'status' && <FaSort style={styles.iconMarginLeft} />}
</button>
</th>
<th>
<button className="btn" onClick={() => handleSort('mode')}>
<button className="btn" onClick={() => handleSort('mode_name')}>
Mode
{sortConfig.key === 'mode' &&
{sortConfig.key === 'mode_name' &&
(sortConfig.direction === 'asc' ? <FaSortUp style={styles.iconMarginLeft} /> : <FaSortDown style={styles.iconMarginLeft} />)
}
{sortConfig.key !== 'mode' && <FaSort style={styles.iconMarginLeft} />}
{sortConfig.key !== 'mode_name' && <FaSort style={styles.iconMarginLeft} />}
</button>
</th>
<th>
<button className="btn" onClick={() => handleSort('status_name')}>
Status
{sortConfig.key === 'status_name' &&
(sortConfig.direction === 'asc' ? <FaSortUp style={styles.iconMarginLeft} /> : <FaSortDown style={styles.iconMarginLeft} />)
}
{sortConfig.key !== 'status_name' && <FaSort style={styles.iconMarginLeft} />}
</button>
</th>
</tr>
@ -338,19 +372,17 @@ const Transaction = () => {
{paginatedData.length > 0 ? (
paginatedData.map((transaction, index) => (
<tr key={index}>
{/* Kolom Nomor Urut */}
<td>{(currentPage - 1) * dataPerPage + index + 1}</td> {/* Nomor urut berdasarkan halaman dan index */}
<td>{transaction.transactionId}</td>
<td>{transaction.applicationName}</td>
<td>{transaction.createdAt}</td>
<td>{transaction.referenceId}</td>
<td>{transaction.status}</td>
<td>{transaction.mode}</td>
<td>{transaction.transaction_id}</td>
<td>{transaction.app_name}</td>
<td>{transaction.service_name}</td>
<td>{new Date(transaction.created_at).toLocaleString()}</td>
<td>{transaction.mode_name}</td>
<td>{transaction.status_name}</td>
</tr>
))
) : (
<tr>
<td colSpan="7" className="text-center">
<td colSpan="6" className="text-center">
<div className="d-flex flex-column align-items-center mt-5">
<img src={NoAvailable} alt="No Data Available" className="mb-3" style={styles.iconStyle} />
<p>Data not available</p>
@ -397,4 +429,3 @@ const styles = {
marginLeft: '0.7rem', // Adjust as needed
},
};