fix(web): Run Biome checks and apply fixes

This commit is contained in:
Bjorn Lammers 2025-04-24 15:53:08 +02:00
parent eb799c3637
commit e9fe6d3842

View File

@ -19,6 +19,7 @@ import { Input } from "@/components/ui/input"
import { Separator } from "@/components/ui/separator" import { Separator } from "@/components/ui/separator"
import { BASE_URL } from "@/constants" import { BASE_URL } from "@/constants"
import type { Icon, IconSearchProps } from "@/types/icons" import type { Icon, IconSearchProps } from "@/types/icons"
import { AnimatePresence, motion } from "framer-motion"
import { ArrowDownAZ, ArrowUpZA, Calendar, ChevronLeft, ChevronRight, Filter, Search, SortAsc, X } from "lucide-react" import { ArrowDownAZ, ArrowUpZA, Calendar, ChevronLeft, ChevronRight, Filter, Search, SortAsc, X } from "lucide-react"
import { useTheme } from "next-themes" import { useTheme } from "next-themes"
import Image from "next/image" import Image from "next/image"
@ -27,31 +28,33 @@ import { usePathname, useRouter, useSearchParams } from "next/navigation"
import posthog from "posthog-js" import posthog from "posthog-js"
import { useCallback, useEffect, useMemo, useRef, useState } from "react" import { useCallback, useEffect, useMemo, useRef, useState } from "react"
import { toast } from "sonner" import { toast } from "sonner"
import { motion, AnimatePresence } from "framer-motion"
type SortOption = "relevance" | "alphabetical-asc" | "alphabetical-desc" | "newest" type SortOption = "relevance" | "alphabetical-asc" | "alphabetical-desc" | "newest"
// Get the display rows count based on viewport size // Get the display rows count based on viewport size
function getDefaultRowsPerPage() { function getDefaultRowsPerPage() {
if (typeof window === "undefined") return 3; // Default for SSR if (typeof window === "undefined") return 3 // Default for SSR
// Calculate based on viewport height and width // Calculate based on viewport height and width
const vh = window.innerHeight; const vh = window.innerHeight
const vw = window.innerWidth; const vw = window.innerWidth
// Determine number of columns based on viewport width // Determine number of columns based on viewport width
let columns = 2; // Default for small screens (sm) let columns = 2 // Default for small screens (sm)
if (vw >= 1280) columns = 8; // xl breakpoint if (vw >= 1280)
else if (vw >= 1024) columns = 6; // lg breakpoint columns = 8 // xl breakpoint
else if (vw >= 768) columns = 4; // md breakpoint else if (vw >= 1024)
else if (vw >= 640) columns = 3; // sm breakpoint columns = 6 // lg breakpoint
else if (vw >= 768)
columns = 4 // md breakpoint
else if (vw >= 640) columns = 3 // sm breakpoint
// Calculate rows (accounting for pagination UI space) // Calculate rows (accounting for pagination UI space)
const rowHeight = 130; // Approximate height of each row in pixels const rowHeight = 130 // Approximate height of each row in pixels
const availableHeight = vh * 0.6; // 60% of viewport height const availableHeight = vh * 0.6 // 60% of viewport height
// Ensure at least 1 row, maximum 5 rows // Ensure at least 1 row, maximum 5 rows
return Math.max(1, Math.min(5, Math.floor(availableHeight / rowHeight))); return Math.max(1, Math.min(5, Math.floor(availableHeight / rowHeight)))
} }
export function IconSearch({ icons }: IconSearchProps) { export function IconSearch({ icons }: IconSearchProps) {
@ -75,33 +78,36 @@ export function IconSearch({ icons }: IconSearchProps) {
// Add resize observer to update iconsPerPage when window size changes // Add resize observer to update iconsPerPage when window size changes
useEffect(() => { useEffect(() => {
const updateIconsPerPage = () => { const updateIconsPerPage = () => {
const rows = getDefaultRowsPerPage(); const rows = getDefaultRowsPerPage()
// Determine columns based on current viewport // Determine columns based on current viewport
const vw = window.innerWidth; const vw = window.innerWidth
let columns = 2; // Default for small screens let columns = 2 // Default for small screens
if (vw >= 1280) columns = 8; // xl breakpoint if (vw >= 1280)
else if (vw >= 1024) columns = 6; // lg breakpoint columns = 8 // xl breakpoint
else if (vw >= 768) columns = 4; // md breakpoint else if (vw >= 1024)
else if (vw >= 640) columns = 3; // sm breakpoint columns = 6 // lg breakpoint
else if (vw >= 768)
columns = 4 // md breakpoint
else if (vw >= 640) columns = 3 // sm breakpoint
setIconsPerPage(rows * columns); setIconsPerPage(rows * columns)
}; }
// Initial setup // Initial setup
updateIconsPerPage(); updateIconsPerPage()
// Add resize listener // Add resize listener
window.addEventListener('resize', updateIconsPerPage); window.addEventListener("resize", updateIconsPerPage)
// Cleanup // Cleanup
return () => window.removeEventListener('resize', updateIconsPerPage); return () => window.removeEventListener("resize", updateIconsPerPage)
}, []); }, [])
// Reset page when search parameters change // Reset page when search parameters change
useEffect(() => { useEffect(() => {
setCurrentPage(1); setCurrentPage(1)
}, [debouncedQuery, selectedCategories, sortOption]); }, [])
useEffect(() => { useEffect(() => {
const timer = setTimeout(() => { const timer = setTimeout(() => {
@ -262,8 +268,8 @@ export function IconSearch({ icons }: IconSearchProps) {
const handlePageChange = useCallback( const handlePageChange = useCallback(
(page: number) => { (page: number) => {
setCurrentPage(page); setCurrentPage(page)
updateResults(searchQuery, selectedCategories, sortOption, page); updateResults(searchQuery, selectedCategories, sortOption, page)
}, },
[updateResults, searchQuery, selectedCategories, sortOption], [updateResults, searchQuery, selectedCategories, sortOption],
) )
@ -565,42 +571,42 @@ function IconsGrid({ filteredIcons, matchedAliases, currentPage, iconsPerPage, o
// Calculate letter ranges for each page // Calculate letter ranges for each page
const getLetterRange = (pageNum: number) => { const getLetterRange = (pageNum: number) => {
if (filteredIcons.length === 0) return ''; if (filteredIcons.length === 0) return ""
const start = (pageNum - 1) * iconsPerPage; const start = (pageNum - 1) * iconsPerPage
const end = Math.min(start + iconsPerPage - 1, filteredIcons.length - 1); const end = Math.min(start + iconsPerPage - 1, filteredIcons.length - 1)
if (start >= filteredIcons.length) return ''; if (start >= filteredIcons.length) return ""
const firstLetter = filteredIcons[start].name.charAt(0).toUpperCase(); const firstLetter = filteredIcons[start].name.charAt(0).toUpperCase()
const lastLetter = filteredIcons[end].name.charAt(0).toUpperCase(); const lastLetter = filteredIcons[end].name.charAt(0).toUpperCase()
return firstLetter === lastLetter ? firstLetter : `${firstLetter} - ${lastLetter}`; return firstLetter === lastLetter ? firstLetter : `${firstLetter} - ${lastLetter}`
}; }
// Get current page letter range // Get current page letter range
const currentLetterRange = getLetterRange(currentPage); const currentLetterRange = getLetterRange(currentPage)
// Handle direct page input // Handle direct page input
const [pageInput, setPageInput] = useState(currentPage.toString()); const [pageInput, setPageInput] = useState(currentPage.toString())
useEffect(() => { useEffect(() => {
setPageInput(currentPage.toString()); setPageInput(currentPage.toString())
}, [currentPage]); }, [currentPage])
const handlePageInputChange = (e: React.ChangeEvent<HTMLInputElement>) => { const handlePageInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setPageInput(e.target.value); setPageInput(e.target.value)
}; }
const handlePageInputSubmit = (e: React.FormEvent) => { const handlePageInputSubmit = (e: React.FormEvent) => {
e.preventDefault(); e.preventDefault()
const pageNumber = parseInt(pageInput); const pageNumber = Number.parseInt(pageInput)
if (!isNaN(pageNumber) && pageNumber >= 1 && pageNumber <= totalPages) { if (!Number.isNaN(pageNumber) && pageNumber >= 1 && pageNumber <= totalPages) {
onPageChange(pageNumber); onPageChange(pageNumber)
} else { } else {
// Reset to current page if invalid // Reset to current page if invalid
setPageInput(currentPage.toString()); setPageInput(currentPage.toString())
}
} }
};
return ( return (
<> <>
@ -624,18 +630,14 @@ function IconsGrid({ filteredIcons, matchedAliases, currentPage, iconsPerPage, o
{/* Mobile view: centered content */} {/* Mobile view: centered content */}
<div className="text-sm text-muted-foreground text-center md:text-left md:hidden"> <div className="text-sm text-muted-foreground text-center md:text-left md:hidden">
Showing {indexOfFirstIcon + 1}-{Math.min(indexOfLastIcon, totalIcons)} of {totalIcons} icons Showing {indexOfFirstIcon + 1}-{Math.min(indexOfLastIcon, totalIcons)} of {totalIcons} icons
{currentLetterRange && ( {currentLetterRange && <span className="ml-2 font-medium">({currentLetterRange})</span>}
<span className="ml-2 font-medium">({currentLetterRange})</span>
)}
</div> </div>
{/* Desktop view layout */} {/* Desktop view layout */}
<div className="hidden md:flex justify-between items-center"> <div className="hidden md:flex justify-between items-center">
<div className="text-sm text-muted-foreground"> <div className="text-sm text-muted-foreground">
Showing {indexOfFirstIcon + 1}-{Math.min(indexOfLastIcon, totalIcons)} of {totalIcons} icons Showing {indexOfFirstIcon + 1}-{Math.min(indexOfLastIcon, totalIcons)} of {totalIcons} icons
{currentLetterRange && ( {currentLetterRange && <span className="ml-2 font-medium">({currentLetterRange})</span>}
<span className="ml-2 font-medium">({currentLetterRange})</span>
)}
</div> </div>
<div className="flex items-center gap-4"> <div className="flex items-center gap-4">
@ -651,7 +653,9 @@ function IconsGrid({ filteredIcons, matchedAliases, currentPage, iconsPerPage, o
aria-label="Go to page" aria-label="Go to page"
/> />
<span className="text-sm whitespace-nowrap">of {totalPages}</span> <span className="text-sm whitespace-nowrap">of {totalPages}</span>
<Button type="submit" size="sm" variant="outline" className="h-8 cursor-pointer">Go</Button> <Button type="submit" size="sm" variant="outline" className="h-8 cursor-pointer">
Go
</Button>
</form> </form>
{/* Pagination controls */} {/* Pagination controls */}
@ -670,19 +674,19 @@ function IconsGrid({ filteredIcons, matchedAliases, currentPage, iconsPerPage, o
<div className="flex items-center overflow-hidden"> <div className="flex items-center overflow-hidden">
{Array.from({ length: Math.min(5, totalPages) }, (_, i) => { {Array.from({ length: Math.min(5, totalPages) }, (_, i) => {
// Show pages around current page // Show pages around current page
let pageNum; let pageNum: number
if (totalPages <= 5) { if (totalPages <= 5) {
pageNum = i + 1; pageNum = i + 1
} else if (currentPage <= 3) { } else if (currentPage <= 3) {
pageNum = i + 1; pageNum = i + 1
} else if (currentPage >= totalPages - 2) { } else if (currentPage >= totalPages - 2) {
pageNum = totalPages - 4 + i; pageNum = totalPages - 4 + i
} else { } else {
pageNum = currentPage - 2 + i; pageNum = currentPage - 2 + i
} }
// Calculate letter range for this page // Calculate letter range for this page
const letterRange = getLetterRange(pageNum); const letterRange = getLetterRange(pageNum)
return ( return (
<Button <Button
@ -703,7 +707,7 @@ function IconsGrid({ filteredIcons, matchedAliases, currentPage, iconsPerPage, o
</span> </span>
)} )}
</Button> </Button>
); )
})} })}
</div> </div>
@ -739,15 +743,15 @@ function IconsGrid({ filteredIcons, matchedAliases, currentPage, iconsPerPage, o
<div className="flex items-center overflow-hidden"> <div className="flex items-center overflow-hidden">
{Array.from({ length: Math.min(5, totalPages) }, (_, i) => { {Array.from({ length: Math.min(5, totalPages) }, (_, i) => {
// Show pages around current page - same logic as desktop // Show pages around current page - same logic as desktop
let pageNum; let pageNum: number
if (totalPages <= 5) { if (totalPages <= 5) {
pageNum = i + 1; pageNum = i + 1
} else if (currentPage <= 3) { } else if (currentPage <= 3) {
pageNum = i + 1; pageNum = i + 1
} else if (currentPage >= totalPages - 2) { } else if (currentPage >= totalPages - 2) {
pageNum = totalPages - 4 + i; pageNum = totalPages - 4 + i
} else { } else {
pageNum = currentPage - 2 + i; pageNum = currentPage - 2 + i
} }
return ( return (
@ -756,15 +760,13 @@ function IconsGrid({ filteredIcons, matchedAliases, currentPage, iconsPerPage, o
onClick={() => onPageChange(pageNum)} onClick={() => onPageChange(pageNum)}
variant={pageNum === currentPage ? "default" : "outline"} variant={pageNum === currentPage ? "default" : "outline"}
size="sm" size="sm"
className={`h-8 w-8 p-0 rounded-none cursor-pointer ${ className={`h-8 w-8 p-0 rounded-none cursor-pointer ${pageNum === currentPage ? "font-medium" : ""}`}
pageNum === currentPage ? "font-medium" : ""
}`}
aria-label={`Page ${pageNum}`} aria-label={`Page ${pageNum}`}
aria-current={pageNum === currentPage ? "page" : undefined} aria-current={pageNum === currentPage ? "page" : undefined}
> >
{pageNum} {pageNum}
</Button> </Button>
); )
})} })}
</div> </div>
@ -792,7 +794,9 @@ function IconsGrid({ filteredIcons, matchedAliases, currentPage, iconsPerPage, o
aria-label="Go to page" aria-label="Go to page"
/> />
<span className="text-sm whitespace-nowrap">of {totalPages}</span> <span className="text-sm whitespace-nowrap">of {totalPages}</span>
<Button type="submit" size="sm" variant="outline" className="h-8 cursor-pointer">Go</Button> <Button type="submit" size="sm" variant="outline" className="h-8 cursor-pointer">
Go
</Button>
</form> </form>
</div> </div>
</div> </div>