mirror of
https://github.com/Kizuren/uLinkShortener.git
synced 2025-12-21 21:16:17 +01:00
Biome format
This commit is contained in:
parent
47969209eb
commit
8729e57def
85 changed files with 2467 additions and 1983 deletions
|
|
@ -1,4 +1,4 @@
|
|||
"use client";
|
||||
'use client';
|
||||
|
||||
import { useState, useEffect } from 'react';
|
||||
import { Analytics } from '@/types/analytics';
|
||||
|
|
@ -21,22 +21,22 @@ export default function AnalyticsTable({
|
|||
currentPage,
|
||||
itemsPerPage,
|
||||
onPageChange,
|
||||
onDeleteClick
|
||||
onDeleteClick,
|
||||
}: AnalyticsTableProps) {
|
||||
const [expandedRows, setExpandedRows] = useState<Set<string>>(new Set());
|
||||
const [searchQuery, setSearchQuery] = useState<string>('');
|
||||
const [searchResults, setSearchResults] = useState<Analytics[]>([]);
|
||||
const [isSearching, setIsSearching] = useState(false);
|
||||
|
||||
|
||||
const totalPages = Math.ceil(totalItems / itemsPerPage);
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
if (!searchQuery.trim()) {
|
||||
setSearchResults([]);
|
||||
setIsSearching(false);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
setIsSearching(true);
|
||||
const query = searchQuery.toLowerCase();
|
||||
const filtered = allAnalytics.filter(item => {
|
||||
|
|
@ -46,15 +46,17 @@ export default function AnalyticsTable({
|
|||
item.ip_version.toLowerCase().includes(query) ||
|
||||
item.country.toLowerCase().includes(query) ||
|
||||
(item.ip_data?.isp && item.ip_data.isp.toLowerCase().includes(query)) ||
|
||||
|
||||
// Device and browser info
|
||||
item.platform.toLowerCase().includes(query) ||
|
||||
item.platform
|
||||
.toLowerCase()
|
||||
.includes(query) ||
|
||||
item.browser.toLowerCase().includes(query) ||
|
||||
item.version.toLowerCase().includes(query) ||
|
||||
item.language.toLowerCase().includes(query) ||
|
||||
|
||||
// Additional details
|
||||
item.user_agent.toLowerCase().includes(query) ||
|
||||
item.user_agent
|
||||
.toLowerCase()
|
||||
.includes(query) ||
|
||||
item.referrer.toLowerCase().includes(query) ||
|
||||
item.remote_port.toLowerCase().includes(query) ||
|
||||
item.accept?.toLowerCase().includes(query) ||
|
||||
|
|
@ -62,10 +64,10 @@ export default function AnalyticsTable({
|
|||
item.accept_encoding?.toLowerCase().includes(query)
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
setSearchResults(filtered);
|
||||
}, [searchQuery, allAnalytics]);
|
||||
|
||||
|
||||
const toggleRowExpansion = (id: string) => {
|
||||
const newExpandedRows = new Set(expandedRows);
|
||||
if (expandedRows.has(id)) {
|
||||
|
|
@ -75,56 +77,56 @@ export default function AnalyticsTable({
|
|||
}
|
||||
setExpandedRows(newExpandedRows);
|
||||
};
|
||||
|
||||
|
||||
const handleSearchChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setSearchQuery(e.target.value);
|
||||
|
||||
|
||||
if (currentPage !== 1) {
|
||||
onPageChange(1);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const clearSearch = () => {
|
||||
setSearchQuery('');
|
||||
|
||||
|
||||
if (currentPage !== 1) {
|
||||
onPageChange(1);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const displayedAnalytics = isSearching ? searchResults : analytics;
|
||||
|
||||
|
||||
return (
|
||||
<div className={styles.tableContainer}>
|
||||
<div className={styles.tableHeader}>
|
||||
<h3 className={styles.tableTitle}>Click Details</h3>
|
||||
<div className={styles.searchContainer}>
|
||||
<input
|
||||
type="text"
|
||||
type='text'
|
||||
value={searchQuery}
|
||||
onChange={handleSearchChange}
|
||||
placeholder="Search analytics..."
|
||||
placeholder='Search analytics...'
|
||||
className={styles.searchInput}
|
||||
aria-label="Search analytics"
|
||||
aria-label='Search analytics'
|
||||
/>
|
||||
{searchQuery && (
|
||||
<button
|
||||
<button
|
||||
onClick={clearSearch}
|
||||
className={styles.clearSearchButton}
|
||||
aria-label="Clear search"
|
||||
aria-label='Clear search'
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
{isSearching && (
|
||||
<div className={styles.searchResults}>
|
||||
Found {searchResults.length} result{searchResults.length !== 1 ? 's' : ''}
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
||||
<div className={styles.tableWrapper}>
|
||||
<table className={styles.analyticsTable}>
|
||||
<thead>
|
||||
|
|
@ -141,7 +143,7 @@ export default function AnalyticsTable({
|
|||
{displayedAnalytics.map(item => {
|
||||
const id = item._id?.toString() || '';
|
||||
const isExpanded = expandedRows.has(id);
|
||||
|
||||
|
||||
return (
|
||||
<tr key={id} className={isExpanded ? styles.expandedRow : ''}>
|
||||
<td>{new Date(item.timestamp).toLocaleString()}</td>
|
||||
|
|
@ -151,28 +153,28 @@ export default function AnalyticsTable({
|
|||
</td>
|
||||
<td>
|
||||
{item.country}
|
||||
<div className={styles.secondaryInfo}>ISP: {item.ip_data?.isp || 'Unknown'}</div>
|
||||
</td>
|
||||
<td>
|
||||
{item.platform}
|
||||
<div className={styles.secondaryInfo}>
|
||||
ISP: {item.ip_data?.isp || 'Unknown'}
|
||||
</div>
|
||||
</td>
|
||||
<td>{item.platform}</td>
|
||||
<td>
|
||||
{item.browser} {item.version}
|
||||
<div className={styles.secondaryInfo}>Lang: {item.language}</div>
|
||||
</td>
|
||||
<td>
|
||||
<div className={styles.actions}>
|
||||
<button
|
||||
<button
|
||||
className={styles.expandButton}
|
||||
onClick={() => toggleRowExpansion(id)}
|
||||
aria-label={isExpanded ? "Collapse details" : "Expand details"}
|
||||
aria-label={isExpanded ? 'Collapse details' : 'Expand details'}
|
||||
>
|
||||
{isExpanded ? '−' : '+'}
|
||||
</button>
|
||||
<button
|
||||
<button
|
||||
className={styles.deleteButton}
|
||||
onClick={() => onDeleteClick(id)}
|
||||
aria-label="Delete entry"
|
||||
aria-label='Delete entry'
|
||||
>
|
||||
Delete
|
||||
</button>
|
||||
|
|
@ -184,21 +186,19 @@ export default function AnalyticsTable({
|
|||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
|
||||
{displayedAnalytics.length === 0 && (
|
||||
<div className={styles.noResults}>
|
||||
{isSearching
|
||||
? `No results found for "${searchQuery}"`
|
||||
: "No analytics data available"}
|
||||
{isSearching ? `No results found for "${searchQuery}"` : 'No analytics data available'}
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
||||
{expandedRows.size > 0 && (
|
||||
<div className={styles.expandedDetails}>
|
||||
{displayedAnalytics.map(item => {
|
||||
const id = item._id?.toString() || '';
|
||||
if (!expandedRows.has(id)) return null;
|
||||
|
||||
|
||||
return (
|
||||
<div key={`details-${id}`} className={styles.detailsCard}>
|
||||
<h4>Additional Details</h4>
|
||||
|
|
@ -233,22 +233,22 @@ export default function AnalyticsTable({
|
|||
})}
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
||||
{totalPages > 1 && !isSearching && (
|
||||
<div className={styles.pagination}>
|
||||
<button
|
||||
<button
|
||||
disabled={currentPage === 1}
|
||||
onClick={() => onPageChange(currentPage - 1)}
|
||||
className={styles.pageButton}
|
||||
>
|
||||
Previous
|
||||
</button>
|
||||
|
||||
|
||||
<span className={styles.pageInfo}>
|
||||
Page {currentPage} of {totalPages}
|
||||
</span>
|
||||
|
||||
<button
|
||||
|
||||
<button
|
||||
disabled={currentPage === totalPages}
|
||||
onClick={() => onPageChange(currentPage + 1)}
|
||||
className={styles.pageButton}
|
||||
|
|
@ -259,4 +259,4 @@ export default function AnalyticsTable({
|
|||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue