chore: update packages, format all files, fix downshift errors

This commit is contained in:
trafficlunar 2026-02-21 19:34:01 +00:00
parent df7901b525
commit a6c2d924f1
36 changed files with 864 additions and 1154 deletions

View file

@ -54,10 +54,7 @@ export default function AdminBanner() {
<span>{data.message}</span>
</div>
<button
onClick={handleClose}
className="min-sm:absolute right-2 cursor-pointer p-1.5"
>
<button onClick={handleClose} className="min-sm:absolute right-2 cursor-pointer p-1.5">
<Icon icon="humbleicons:times" className="text-2xl min-w-6" />
</button>
</div>

View file

@ -87,7 +87,7 @@ export default function PunishmentDeletionDialog({ punishmentId }: Props) {
</div>
</div>
</div>,
document.body
document.body,
)}
</>
);

View file

@ -79,7 +79,7 @@ export default function RegenerateImagesButton() {
</div>
</div>
</div>,
document.body
document.body,
)}
</>
);

View file

@ -42,8 +42,8 @@ export default async function Reports() {
report.status == "OPEN"
? "bg-orange-200 text-orange-800 border-orange-400"
: report.status == "RESOLVED"
? "bg-green-200 text-green-800 border-green-400"
: "bg-zinc-200 text-zinc-800 border-zinc-400"
? "bg-green-200 text-green-800 border-green-400"
: "bg-zinc-200 text-zinc-800 border-zinc-400"
}`}
>
{report.status}
@ -68,10 +68,7 @@ export default async function Reports() {
<div className="grid grid-cols-4 text-xs text-zinc-600 mt-4 max-sm:grid-cols-2">
<div>
<p>Target ID</p>
<Link
href={report.reportType === "MII" ? `/mii/${report.targetId}` : `/profile/${report.targetId}`}
className="text-blue-600 text-sm"
>
<Link href={report.reportType === "MII" ? `/mii/${report.targetId}` : `/profile/${report.targetId}`} className="text-blue-600 text-sm">
{report.targetId}
</Link>
</div>

View file

@ -146,8 +146,8 @@ export default function Punishments() {
punishment.type === "WARNING"
? "bg-yellow-50 border-yellow-400"
: punishment.type === "TEMP_EXILE"
? "bg-orange-100 border-orange-200"
: "bg-red-50 border-red-200"
? "bg-orange-100 border-orange-200"
: "bg-red-50 border-red-200"
}`}
>
<div className="flex items-center justify-between mb-2">
@ -156,8 +156,8 @@ export default function Punishments() {
punishment.type === "WARNING"
? "bg-yellow-200 text-yellow-800 border-yellow-500"
: punishment.type === "TEMP_EXILE"
? "bg-orange-200 text-orange-800 border-orange-500"
: "bg-red-200 text-red-800 border-red-500"
? "bg-orange-200 text-orange-800 border-orange-500"
: "bg-red-200 text-red-800 border-red-500"
}`}
>
{punishment.type}
@ -286,9 +286,7 @@ export default function Punishments() {
<div key={index} className="bg-white border border-orange-200 rounded-md p-3 flex items-center justify-between">
<div className="flex-1">
<div className="flex items-center gap-2">
<span className="bg-orange-200 text-orange-800 border border-orange-400 px-2 py-1 rounded text-xs font-semibold">
ID: {mii.id}
</span>
<span className="bg-orange-200 text-orange-800 border border-orange-400 px-2 py-1 rounded text-xs font-semibold">ID: {mii.id}</span>
<span className="text-sm text-gray-500">{mii.reason}</span>
</div>
</div>

View file

@ -56,13 +56,7 @@ export default function DeleteMiiButton({ miiId, miiName, likes, inMiiPage }: Pr
<span>Delete</span>
</button>
) : (
<button
onClick={() => setIsOpen(true)}
aria-label="Delete Mii"
title="Delete Mii"
data-tooltip="Delete"
className="cursor-pointer aspect-square"
>
<button onClick={() => setIsOpen(true)} aria-label="Delete Mii" title="Delete Mii" data-tooltip="Delete" className="cursor-pointer aspect-square">
<Icon icon="mdi:trash" />
</button>
)}
@ -111,7 +105,7 @@ export default function DeleteMiiButton({ miiId, miiName, likes, inMiiPage }: Pr
</div>
</div>
</div>,
document.body
document.body,
)}
</>
);

View file

@ -63,12 +63,7 @@ export default function Description({ text, className }: Props) {
href={`/profile/${id}`}
className="inline-flex items-center align-bottom gap-1.5 pr-2 bg-orange-100 border border-orange-400 rounded-lg mx-1 text-orange-800 text-xs"
>
<ProfilePicture
src={linkedProfile.image || "/guest.webp"}
width={24}
height={24}
className="bg-white rounded-lg border-r border-orange-400"
/>
<ProfilePicture src={linkedProfile.image || "/guest.webp"} width={24} height={24} className="bg-white rounded-lg border-r border-orange-400" />
{linkedProfile.name}
</Link>
);

View file

@ -54,11 +54,7 @@ export default function Footer() {
</span>
<a
href="https://trafficlunar.net"
target="_blank"
className="text-zinc-500 hover:text-zinc-700 transition-colors duration-200 hover:underline group"
>
<a href="https://trafficlunar.net" target="_blank" className="text-zinc-500 hover:text-zinc-700 transition-colors duration-200 hover:underline group">
Made by <span className="text-orange-400 group-hover:text-orange-500 font-medium transition-colors duration-200">trafficlunar</span>
</a>
</div>

View file

@ -21,7 +21,7 @@ export default function Pagination({ lastPage }: Props) {
params.set("page", pageNumber.toString());
return `${pathname}?${params.toString()}`;
},
[searchParams, pathname]
[searchParams, pathname],
);
const numbers = useMemo(() => {
@ -44,9 +44,7 @@ export default function Pagination({ lastPage }: Props) {
aria-label="Go to First Page"
aria-disabled={page === 1}
tabIndex={page === 1 ? -1 : undefined}
className={`pill button bg-orange-100! p-0.5! aspect-square text-2xl ${
page === 1 ? "pointer-events-none opacity-50" : "hover:bg-orange-400!"
}`}
className={`pill button bg-orange-100! p-0.5! aspect-square text-2xl ${page === 1 ? "pointer-events-none opacity-50" : "hover:bg-orange-400!"}`}
>
<Icon icon="stash:chevron-double-left" />
</Link>
@ -83,9 +81,7 @@ export default function Pagination({ lastPage }: Props) {
aria-label="Go to Next Page"
aria-disabled={page >= lastPage}
tabIndex={page >= lastPage ? -1 : undefined}
className={`pill button bg-orange-100! p-0.5! aspect-square text-2xl ${
page >= lastPage ? "pointer-events-none opacity-50" : "hover:bg-orange-400!"
}`}
className={`pill button bg-orange-100! p-0.5! aspect-square text-2xl ${page >= lastPage ? "pointer-events-none opacity-50" : "hover:bg-orange-400!"}`}
>
<Icon icon="stash:chevron-right" />
</Link>
@ -96,9 +92,7 @@ export default function Pagination({ lastPage }: Props) {
aria-label="Go to Last Page"
aria-disabled={page >= lastPage}
tabIndex={page >= lastPage ? -1 : undefined}
className={`pill button bg-orange-100! p-0.5! aspect-square text-2xl ${
page >= lastPage ? "pointer-events-none opacity-50" : "hover:bg-orange-400!"
}`}
className={`pill button bg-orange-100! p-0.5! aspect-square text-2xl ${page >= lastPage ? "pointer-events-none opacity-50" : "hover:bg-orange-400!"}`}
>
<Icon icon="stash:chevron-double-right" />
</Link>

View file

@ -51,8 +51,7 @@ export default async function ProfileInformation({ userId, page }: Props) {
<div className="mt-3 text-sm flex gap-8">
<h4 title={`${user.createdAt.toLocaleTimeString("en-GB", { timeZone: "UTC" })} UTC`}>
<span className="font-medium">Created:</span>{" "}
{user.createdAt.toLocaleDateString("en-GB", { month: "long", day: "2-digit", year: "numeric" })}
<span className="font-medium">Created:</span> {user.createdAt.toLocaleDateString("en-GB", { month: "long", day: "2-digit", year: "numeric" })}
</h4>
<h4>
Liked <span className="font-bold">{likedMiis}</span> Miis

View file

@ -7,12 +7,7 @@ export default async function ProfileOverview() {
return (
<li title="Your profile">
<Link
href={`/profile/${session?.user.id}`}
aria-label="Go to profile"
className="pill button gap-2! p-0! h-full max-w-64"
data-tooltip="Your Profile"
>
<Link href={`/profile/${session?.user.id}`} aria-label="Go to profile" className="pill button gap-2! p-0! h-full max-w-64" data-tooltip="Your Profile">
<Image
src={session?.user?.image ?? "/guest.webp"}
alt="profile picture"

View file

@ -39,11 +39,7 @@ export default function DeleteAccount() {
return (
<>
<button
name="deletion"
onClick={() => setIsOpen(true)}
className="pill button w-fit h-min ml-auto bg-red-400! border-red-500! hover:bg-red-500!"
>
<button name="deletion" onClick={() => setIsOpen(true)} className="pill button w-fit h-min ml-auto bg-red-400! border-red-500! hover:bg-red-500!">
Delete Account
</button>
@ -69,9 +65,7 @@ export default function DeleteAccount() {
</button>
</div>
<p className="text-sm text-zinc-500">
Are you sure? This is permanent and will remove all uploaded Miis. This action cannot be undone.
</p>
<p className="text-sm text-zinc-500">Are you sure? This is permanent and will remove all uploaded Miis. This action cannot be undone.</p>
{error && <span className="text-red-400 font-bold mt-2">Error: {error}</span>}
@ -83,7 +77,7 @@ export default function DeleteAccount() {
</div>
</div>
</div>,
document.body
document.body,
)}
</>
);

View file

@ -151,13 +151,7 @@ export default function ProfileSettings({ currentDescription }: Props) {
</div>
<div className="flex justify-end gap-1 h-min col-span-2">
<input
type="text"
className="pill input flex-1"
placeholder="Type here..."
value={displayName}
onChange={(e) => setDisplayName(e.target.value)}
/>
<input type="text" className="pill input flex-1" placeholder="Type here..." value={displayName} onChange={(e) => setDisplayName(e.target.value)} />
<SubmitDialogButton
title="Confirm Display Name Change"
description="Are you sure? This will only be visible on your profile. You can change it again later."

View file

@ -86,8 +86,8 @@ export default function ProfilePictureSettings() {
onSubmit={handleSubmit}
>
<p className="text-sm text-zinc-500 mt-2">
After submitting, you can change it again on{" "}
{changeDate.toDate().toLocaleDateString("en-US", { month: "long", day: "numeric", year: "numeric" })}.
After submitting, you can change it again on {changeDate.toDate().toLocaleDateString("en-US", { month: "long", day: "numeric", year: "numeric" })}
.
</p>
<div className="bg-orange-100 rounded-xl border-2 border-amber-500 mt-4 px-2 py-1 flex items-center">

View file

@ -76,7 +76,7 @@ export default function SubmitDialogButton({ title, description, onSubmit, error
</div>
</div>
</div>,
document.body
document.body,
)}
</>
);

View file

@ -36,12 +36,7 @@ export default function ReasonSelector({ reason, setReason }: Props) {
return (
<div className="relative w-full col-span-2">
{/* Toggle button to open the dropdown */}
<button
type="button"
{...getToggleButtonProps()}
aria-label="Report reason dropdown"
className="pill input w-full gap-1 justify-between! text-nowrap"
>
<button type="button" {...getToggleButtonProps()} aria-label="Report reason dropdown" className="pill input w-full gap-1 justify-between! text-nowrap">
{selectedItem?.label || <span className="text-black/40">Select a reason for the report...</span>}
<Icon icon="tabler:chevron-down" className="ml-2 size-5" />
</button>

View file

@ -91,11 +91,7 @@ export default function ShareMiiButton({ miiId }: Props) {
<input type="text" disabled className="pill input w-full text-sm" value={url} />
{/* Copy button */}
<button
className="absolute! top-2.5 right-2.5 cursor-pointer"
data-tooltip={hasCopiedUrl ? "Copied!" : "Copy URL"}
onClick={handleCopyUrl}
>
<button className="absolute! top-2.5 right-2.5 cursor-pointer" data-tooltip={hasCopiedUrl ? "Copied!" : "Copy URL"} onClick={handleCopyUrl}>
<div className="relative text-xl">
{/* Copy icon */}
<Icon
@ -124,14 +120,7 @@ export default function ShareMiiButton({ miiId }: Props) {
</div>
<div className="flex justify-center items-center p-4 w-full bg-orange-100 border border-orange-400 rounded-lg">
<Image
src={`/mii/${miiId}/image?type=metadata`}
alt="mii 'metadata' image"
width={248}
height={248}
unoptimized
className="drop-shadow-md"
/>
<Image src={`/mii/${miiId}/image?type=metadata`} alt="mii 'metadata' image" width={248} height={248} unoptimized className="drop-shadow-md" />
</div>
<div className="flex justify-end gap-2 mt-4">
@ -158,9 +147,7 @@ export default function ShareMiiButton({ miiId }: Props) {
{/* Copy icon */}
<Icon
icon="solar:copy-bold"
className={` transition-all duration-300 ${
hasCopiedImage ? "opacity-0 scale-75 rotate-12" : "opacity-100 scale-100 rotate-0"
}`}
className={` transition-all duration-300 ${hasCopiedImage ? "opacity-0 scale-75 rotate-12" : "opacity-100 scale-100 rotate-0"}`}
/>
{/* Check icon */}
@ -180,7 +167,7 @@ export default function ShareMiiButton({ miiId }: Props) {
</div>
</div>
</div>,
document.body
document.body,
)}
</>
);

View file

@ -30,7 +30,7 @@ export default function EditForm({ mii, likes }: Props) {
setFiles((prev) => [...prev, ...acceptedFiles]);
},
[files.length]
[files.length],
);
const [error, setError] = useState<string | undefined>(undefined);
@ -91,7 +91,7 @@ export default function EditForm({ mii, likes }: Props) {
const blob = await response.blob();
return Object.assign(new File([blob], `image${index}.webp`, { type: "image/webp" }), { path });
})
}),
);
setFiles(existing);
@ -107,9 +107,7 @@ export default function EditForm({ mii, likes }: Props) {
<form className="flex justify-center gap-4 w-full max-lg:flex-col max-lg:items-center">
<div className="flex justify-center">
<div className="w-75 h-min flex flex-col bg-zinc-50 rounded-3xl border-2 border-zinc-300 shadow-lg p-3">
<Carousel
images={[`/mii/${mii.id}/image?type=mii`, `/mii/${mii.id}/image?type=qr-code`, ...files.map((file) => URL.createObjectURL(file))]}
/>
<Carousel images={[`/mii/${mii.id}/image?type=mii`, `/mii/${mii.id}/image?type=qr-code`, ...files.map((file) => URL.createObjectURL(file))]} />
<div className="p-4 flex flex-col gap-1 h-full">
<h1 className="font-bold text-2xl line-clamp-1" title={name}>

View file

@ -144,10 +144,8 @@ export default function QrScanner({ isOpen, setIsOpen, setQrBytesRaw }: Props) {
};
}, [isOpen, permissionGranted, selectedDeviceId, scanQRCode]);
if (!isOpen) return null;
return (
<div className="fixed inset-0 h-[calc(100%-var(--header-height))] top-(--header-height) flex items-center justify-center z-40">
<div className={`fixed inset-0 h-[calc(100%-var(--header-height))] top-(--header-height) flex items-center justify-center z-40 ${!isOpen ? "hidden" : ""}`}>
<div
onClick={close}
className={`z-40 absolute inset-0 backdrop-brightness-75 backdrop-blur-xs transition-opacity duration-300 ${isVisible ? "opacity-100" : "opacity-0"}`}
@ -165,43 +163,41 @@ export default function QrScanner({ isOpen, setIsOpen, setQrBytesRaw }: Props) {
</button>
</div>
{devices.length > 1 && (
<div className="mb-4 flex flex-col gap-1">
<label className="text-sm font-semibold">Camera:</label>
<div className="relative w-full">
{/* Toggle button to open the dropdown */}
<button
type="button"
aria-label="Select camera dropdown"
{...getToggleButtonProps({}, { suppressRefError: true })}
className="pill input w-full px-2! py-0.5! justify-between! text-sm"
>
{selectedItem?.label || "Select a camera"}
<div className={`mb-4 flex flex-col gap-1 ${devices.length <= 1 ? "hidden" : ""}`}>
<label className="text-sm font-semibold">Camera:</label>
<div className="relative w-full">
{/* Toggle button to open the dropdown */}
<button
type="button"
aria-label="Select camera dropdown"
{...getToggleButtonProps({}, { suppressRefError: true })}
className="pill input w-full px-2! py-0.5! justify-between! text-sm"
>
{selectedItem?.label || "Select a camera"}
<Icon icon="tabler:chevron-down" className="ml-2 size-5" />
</button>
<Icon icon="tabler:chevron-down" className="ml-2 size-5" />
</button>
{/* Dropdown menu */}
<ul
{...getMenuProps({}, { suppressRefError: true })}
className={`absolute z-50 w-full bg-orange-200 border-2 border-orange-400 rounded-lg mt-1 shadow-lg max-h-60 overflow-y-auto ${
isDropdownOpen ? "block" : "hidden"
}`}
>
{isDropdownOpen &&
cameraItems.map((item, index) => (
<li
key={item.value}
{...getItemProps({ item, index })}
className={`px-4 py-1 cursor-pointer text-sm ${highlightedIndex === index ? "bg-black/15" : ""}`}
>
{item.label}
</li>
))}
</ul>
</div>
{/* Dropdown menu */}
<ul
{...getMenuProps({}, { suppressRefError: true })}
className={`absolute z-50 w-full bg-orange-200 border-2 border-orange-400 rounded-lg mt-1 shadow-lg max-h-60 overflow-y-auto ${
isDropdownOpen ? "block" : "hidden"
}`}
>
{isDropdownOpen &&
cameraItems.map((item, index) => (
<li
key={item.value}
{...getItemProps({ item, index })}
className={`px-4 py-1 cursor-pointer text-sm ${highlightedIndex === index ? "bg-black/15" : ""}`}
>
{item.label}
</li>
))}
</ul>
</div>
)}
</div>
<div className="relative w-full aspect-square">
{!permissionGranted && (

View file

@ -41,7 +41,7 @@ export default function QrUpload({ setQrBytesRaw }: Props) {
reader.readAsDataURL(file);
});
},
[setQrBytesRaw]
[setQrBytesRaw],
);
return (

View file

@ -102,9 +102,7 @@ export default function Tutorial({ tutorials, isOpen, setIsOpen }: Props) {
<div className="fixed inset-0 h-[calc(100%-var(--header-height))] top-(--header-height) flex items-center justify-center z-40">
<div
onClick={close}
className={`z-40 absolute inset-0 backdrop-brightness-75 backdrop-blur-xs transition-opacity duration-300 ${
isVisible ? "opacity-100" : "opacity-0"
}`}
className={`z-40 absolute inset-0 backdrop-brightness-75 backdrop-blur-xs transition-opacity duration-300 ${isVisible ? "opacity-100" : "opacity-0"}`}
/>
<div
@ -191,11 +189,7 @@ export default function Tutorial({ tutorials, isOpen, setIsOpen }: Props) {
</button>
{/* Only show tutorial name on step slides */}
<span
className={`text-sm transition-opacity duration-300 ${
(currentSlide.type === "finish" || currentSlide.type === "start") && "opacity-0"
}`}
>
<span className={`text-sm transition-opacity duration-300 ${(currentSlide.type === "finish" || currentSlide.type === "start") && "opacity-0"}`}>
{currentSlide?.tutorialTitle}
</span>

View file

@ -35,7 +35,7 @@ export default function ScanTutorialButton() {
isOpen={isOpen}
setIsOpen={setIsOpen}
/>,
document.body
document.body,
)}
</>
);

View file

@ -57,7 +57,7 @@ export default function SubmitTutorialButton() {
isOpen={isOpen}
setIsOpen={setIsOpen}
/>,
document.body
document.body,
)}
</>
);