+
+
{
+ prepareFile(event.target.files?.[0]);
+ event.target.value = "";
+ }}
+ className="sr-only"
+ />
+
+ {iconUrl && !selectedFile && (
+
+
+
+
+
Current icon
+
{iconUrl}
+
+
+
+
+
+
+
+ )}
+
+ {!iconUrl && !selectedFile && (
+
+ )}
+
+ {selectedFile && previewUrl && (
+
+
+

+
+
Ready to upload
+
{selectedFile.name}
+
+
+
+
+
+
+
+ )}
+
+ {status === "uploaded" &&
Icon uploaded. Save the sport to apply it.
}
+ {error &&
{error}
}
+
SVG only, up to 1 MB. Existing local icons keep working until replaced.
+
+ );
+}
diff --git a/app/components/ui/__tests__/SportIconUploader.test.tsx b/app/components/ui/__tests__/SportIconUploader.test.tsx
new file mode 100644
index 0000000..3dc7342
--- /dev/null
+++ b/app/components/ui/__tests__/SportIconUploader.test.tsx
@@ -0,0 +1,82 @@
+import { beforeEach, describe, expect, it, vi } from "vitest";
+import { fireEvent, render, screen, waitFor } from "@testing-library/react";
+import { SportIconUploader } from "../SportIconUploader";
+import type { FormEvent } from "react";
+
+beforeEach(() => {
+ vi.restoreAllMocks();
+});
+
+describe("SportIconUploader", () => {
+ it("stores the initial icon URL in a hidden input", () => {
+ const { container } = render(
+