diff --git a/bun.lock b/bun.lock
index c27c08b..9a36ac2 100644
--- a/bun.lock
+++ b/bun.lock
@@ -30,6 +30,7 @@
"browser-image-compression": "^2.0.2",
"dotenv": "^17.2.2",
"embla-carousel-react": "^8.6.0",
+ "facehash": "^0.0.7",
"framer-motion": "^12.23.12",
"ioredis": "^5.7.0",
"pg": "^8.16.3",
@@ -710,6 +711,8 @@
"exsolve": ["exsolve@1.0.8", "", {}, "sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA=="],
+ "facehash": ["facehash@0.0.7", "", { "peerDependencies": { "@types/react": "", "next": ">=15", "react": ">=18 <20", "react-dom": ">=18 <20" }, "optionalPeers": ["@types/react", "next"] }, "sha512-P4fw6z5DIGMbjtqEaOw7fYvYpQetSOSJOfqy3xuET7cDUI6f9CKlSX0UZIYNrtsPpCoz3LoPP5E8bNbpZBP30A=="],
+
"fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="],
"fast-equals": ["fast-equals@5.4.0", "", {}, "sha512-jt2DW/aNFNwke7AUd+Z+e6pz39KO5rzdbbFCg2sGafS4mk13MI7Z8O5z9cADNn5lhGODIgLwug6TZO2ctf7kcw=="],
diff --git a/package.json b/package.json
index c3bac09..2361e11 100644
--- a/package.json
+++ b/package.json
@@ -35,6 +35,7 @@
"browser-image-compression": "^2.0.2",
"dotenv": "^17.2.2",
"embla-carousel-react": "^8.6.0",
+ "facehash": "^0.0.7",
"framer-motion": "^12.23.12",
"ioredis": "^5.7.0",
"pg": "^8.16.3",
diff --git a/src/components/player-avatar.tsx b/src/components/player-avatar.tsx
new file mode 100644
index 0000000..a8006ca
--- /dev/null
+++ b/src/components/player-avatar.tsx
@@ -0,0 +1,85 @@
+import { Paper, useMantineTheme } from "@mantine/core";
+import { Facehash } from "facehash";
+
+interface PlayerAvatarProps {
+ name?: string;
+ size?: number;
+ disableFullscreen?: boolean;
+ style?: React.CSSProperties;
+}
+
+const PlayerAvatar = ({
+ name = "",
+ size = 35,
+ disableFullscreen = false,
+ style,
+}: PlayerAvatarProps) => {
+ const theme = useMantineTheme();
+
+ const getFacehashSize = (size: number): 32 | 48 | 64 | 80 => {
+ if (size <= 40) return 32;
+ if (size <= 56) return 48;
+ if (size <= 72) return 64;
+ return 80;
+ };
+
+ const facehashSize = getFacehashSize(size);
+
+ const colors = [
+ "hsla(314, 100%, 80%, 1)",
+ "hsla(58, 93%, 72%, 1)",
+ "hsla(218, 92%, 72%, 1)",
+ "hsla(19, 99%, 44%, 1)",
+ "hsla(156, 86%, 40%, 1)",
+ "hsla(314, 100%, 85%, 1)",
+ "hsla(58, 92%, 79%, 1)",
+ "hsla(218, 91%, 78%, 1)",
+ "hsla(19, 99%, 50%, 1)",
+ "hsla(156, 86%, 64%, 1)",
+ ];
+
+ return (
+ {
+ if (!disableFullscreen) {
+ e.currentTarget.style.transform = 'scale(1.02)';
+ }
+ }}
+ onMouseLeave={(e) => {
+ e.currentTarget.style.transform = 'scale(1)';
+ }}
+ >
+
+
+
+
+ );
+};
+
+export default PlayerAvatar;
diff --git a/src/features/players/components/league-head-to-head.tsx b/src/features/players/components/league-head-to-head.tsx
index f8b6b49..449bace 100644
--- a/src/features/players/components/league-head-to-head.tsx
+++ b/src/features/players/components/league-head-to-head.tsx
@@ -5,7 +5,7 @@ import { useAllPlayerStats } from "../queries";
import { useSheet } from "@/hooks/use-sheet";
import Sheet from "@/components/sheet/sheet";
import PlayerHeadToHeadSheet from "./player-head-to-head-sheet";
-import Avatar from "@/components/avatar";
+import PlayerAvatar from "@/components/player-avatar";
const LeagueHeadToHead = () => {
const [player1Id, setPlayer1Id] = useState(null);
@@ -89,7 +89,7 @@ const LeagueHeadToHead = () => {
{player1Id ? (
<>
-
+
{player1Name}
@@ -110,7 +110,7 @@ const LeagueHeadToHead = () => {
>
) : (
-
+
Player 1
@@ -145,7 +145,7 @@ const LeagueHeadToHead = () => {
{player2Id ? (
<>
-
+
{player2Name}
@@ -166,7 +166,7 @@ const LeagueHeadToHead = () => {
>
) : (
-
+
Player 2
@@ -241,7 +241,7 @@ const LeagueHeadToHead = () => {
},
}}
>
-
+
{player.player_name}
diff --git a/src/features/players/components/player-list.tsx b/src/features/players/components/player-list.tsx
index af50143..ad2cd68 100644
--- a/src/features/players/components/player-list.tsx
+++ b/src/features/players/components/player-list.tsx
@@ -1,6 +1,6 @@
import { List, ListItem, Skeleton, Text } from "@mantine/core";
import { useNavigate } from "@tanstack/react-router";
-import Avatar from "@/components/avatar";
+import PlayerAvatar from "@/components/player-avatar";
import { Player } from "@/features/players/types";
import { useCallback } from "react";
@@ -29,7 +29,7 @@ const PlayerList = ({ players, loading = false }: PlayerListProps) => {
{players?.map((player) => (
}
+ icon={}
style={{ cursor: 'pointer' }}
onClick={() => handleClick(player.id)}
>
diff --git a/src/features/players/components/player-stats-table.tsx b/src/features/players/components/player-stats-table.tsx
index f2b9fba..e362c43 100644
--- a/src/features/players/components/player-stats-table.tsx
+++ b/src/features/players/components/player-stats-table.tsx
@@ -22,7 +22,7 @@ import {
InfoIcon,
} from "@phosphor-icons/react";
import { PlayerStats } from "../types";
-import Avatar from "@/components/avatar";
+import PlayerAvatar from "@/components/player-avatar";
import { useNavigate } from "@tanstack/react-router";
import { useAllPlayerStats } from "../queries";
@@ -93,7 +93,7 @@ const PlayerListItem = memo(({ stat, onPlayerClick, mmr, onRegisterViewport, onU
}}
>
-
+
diff --git a/src/features/players/components/profile/header.tsx b/src/features/players/components/profile/header.tsx
index ab36c20..9dd8749 100644
--- a/src/features/players/components/profile/header.tsx
+++ b/src/features/players/components/profile/header.tsx
@@ -4,7 +4,7 @@ import { Flex, Title, ActionIcon, Stack, Button, Box } from "@mantine/core";
import { PencilIcon, FootballHelmetIcon } from "@phosphor-icons/react";
import { useMemo } from "react";
import NameUpdateForm from "./name-form";
-import Avatar from "@/components/avatar";
+import PlayerAvatar from "@/components/player-avatar";
import { useSheet } from "@/hooks/use-sheet";
import { Player } from "../../types";
import PlayerHeadToHeadSheet from "../player-head-to-head-sheet";
@@ -41,7 +41,7 @@ const Header = ({ player }: HeaderProps) => {
<>
-
+
{name}
diff --git a/vite.config.ts b/vite.config.ts
index 2cf6de6..cb47ff5 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -3,13 +3,13 @@ import { defineConfig } from 'vite'
import tsConfigPaths from 'vite-tsconfig-paths'
import react from '@vitejs/plugin-react';
-export default defineConfig({
+export default defineConfig(({ mode }) => ({
server: {
port: 3000,
allowedHosts: ["dev.flexxon.app", "flexxon.app"]
},
ssr: {
- noExternal: true,
+ noExternal: mode === 'production' ? true : ['facehash'],
},
plugins: [
tsConfigPaths({
@@ -20,4 +20,4 @@ export default defineConfig({
}),
react()
]
-})
+}))