This commit is contained in:
Harun CAN
2026-01-30 04:48:46 +03:00
parent b662a88a65
commit 1f123b9f65
20 changed files with 490 additions and 76 deletions

View File

@@ -28,5 +28,9 @@
"name": "Name", "name": "Name",
"low": "Low", "low": "Low",
"medium": "Medium", "medium": "Medium",
"high": "High" "high": "High",
"predictions": "Predictions",
"games": "Games",
"events": "Events",
"calendar": "Calendar"
} }

View File

@@ -28,5 +28,9 @@
"name": "İsim", "name": "İsim",
"low": "Düşük", "low": "Düşük",
"medium": "Orta", "medium": "Orta",
"high": "Yüksek" "high": "Yüksek",
"predictions": "Tahminler",
"games": "Oyunlar",
"events": "Etkinlikler",
"calendar": "Takvim"
} }

2
next-env.d.ts vendored
View File

@@ -1,6 +1,6 @@
/// <reference types="next" /> /// <reference types="next" />
/// <reference types="next/image-types/global" /> /// <reference types="next/image-types/global" />
import "./.next/types/routes.d.ts"; import "./.next/dev/types/routes.d.ts";
// NOTE: This file should not be edited // NOTE: This file should not be edited
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information. // see https://nextjs.org/docs/app/api-reference/config/typescript for more information.

View File

@@ -10,7 +10,7 @@ const nextConfig: NextConfig = {
return [ return [
{ {
source: "/api/backend/:path*", source: "/api/backend/:path*",
destination: "http://localhost:3000/api/:path*", destination: "http://localhost:4000/api/:path*",
}, },
]; ];
}, },

View File

@@ -13,7 +13,7 @@ export default function HomePage() {
<VStack spaceY={8} align="stretch"> <VStack spaceY={8} align="stretch">
{/* Hero Section / GOTY Banner could go here */} {/* Hero Section / GOTY Banner could go here */}
<Box> <Box>
<Heading size="3xl" mb={2} color="white">Game Calendar</Heading> <Heading size="3xl" mb={2} color="white">Calendar</Heading>
<Text fontSize="lg" color="whiteAlpha.800">Track releases, events, and showcases in one place.</Text> <Text fontSize="lg" color="whiteAlpha.800">Track releases, events, and showcases in one place.</Text>
</Box> </Box>

View File

@@ -0,0 +1,12 @@
import { GameDetail } from "@/components/features/games/GameDetail";
type Props = {
params: Promise<{ slug: string }>;
};
export default async function GamePage({ params }: Props) {
const { slug } = await params;
console.log('Server Page received slug:', slug);
return <GameDetail slug={slug} />;
}

View File

@@ -39,3 +39,17 @@ body {
::-webkit-scrollbar-thumb:hover { ::-webkit-scrollbar-thumb:hover {
background: var(--chakra-colors-primary-500); background: var(--chakra-colors-primary-500);
} }
@keyframes text-gradient {
0% {
background-position: 0% 50%;
}
50% {
background-position: 100% 50%;
}
100% {
background-position: 0% 50%;
}
}

View File

@@ -1,4 +1,5 @@
'use client'; 'use client';
import { Link } from '@/i18n/navigation';
import { Box, Grid, Heading, Text, VStack, Badge, Flex, Image as ChakraImage, SimpleGrid } from '@chakra-ui/react'; import { Box, Grid, Heading, Text, VStack, Badge, Flex, Image as ChakraImage, SimpleGrid } from '@chakra-ui/react';
import { useState } from 'react'; import { useState } from 'react';
@@ -66,7 +67,7 @@ export function GameCalendar({ games = [], events = [] }: CalendarProps) {
}; };
return ( return (
<Box w="full" bg="whiteAlpha.50" rounded="xl" p={6} backdropFilter="blur(10px)" border="1px solid" borderColor="whiteAlpha.100"> <Box w="full" bg="whiteAlpha.300" rounded="xl" p={6} backdropFilter="blur(10px)" border="1px solid" borderColor="whiteAlpha.200">
{/* Header */} {/* Header */}
<Flex justify="space-between" align="center" mb={6}> <Flex justify="space-between" align="center" mb={6}>
<Heading size="lg" color="white"> <Heading size="lg" color="white">
@@ -107,7 +108,7 @@ export function GameCalendar({ games = [], events = [] }: CalendarProps) {
return ( return (
<Box <Box
key={date.toString()} key={date.toString()}
bg={isToday ? 'primary.900' : 'whiteAlpha.50'} bg={isToday ? 'primary.900' : 'whiteAlpha.200'}
border="1px solid" border="1px solid"
borderColor={isToday ? 'primary.500' : 'whiteAlpha.100'} borderColor={isToday ? 'primary.500' : 'whiteAlpha.100'}
rounded="md" rounded="md"
@@ -124,7 +125,8 @@ export function GameCalendar({ games = [], events = [] }: CalendarProps) {
</Text> </Text>
<VStack align="stretch" gap={1}> <VStack align="stretch" gap={1}>
{items.map((item: any, idx) => ( {items.map((item: any, idx) => {
const badge = (
<Badge <Badge
key={`${item.id}-${idx}`} key={`${item.id}-${idx}`}
size="sm" size="sm"
@@ -133,10 +135,23 @@ export function GameCalendar({ games = [], events = [] }: CalendarProps) {
truncate truncate
fontSize="xs" fontSize="xs"
px={1} px={1}
cursor="pointer"
_hover={{ opacity: 0.8 }}
> >
{item.title} {item.title}
</Badge> </Badge>
))} );
if (item.type === 'game') {
return (
<Link key={`${item.id}-${idx}`} href={`/games/${item.slug}`}>
{badge}
</Link>
);
}
return badge;
})}
</VStack> </VStack>
{/* Background image effect for heavy days? Optional polish */} {/* Background image effect for heavy days? Optional polish */}

View File

@@ -0,0 +1,203 @@
'use client';
import { Box, Container, Heading, Text, Image, Badge, Flex, Grid, GridItem, Button, Icon, Stack, Tag, TagLabel, AspectRatio } from '@chakra-ui/react';
import { Game, gamesApi } from '@/lib/api/games';
import { notificationsApi } from '@/lib/api/notifications';
import { useEffect, useState } from 'react';
import { FaPlaystation, FaXbox, FaDesktop, FaGamepad, FaStar, FaBuilding, FaCalendar, FaSync, FaBell } from 'react-icons/fa'; // Assuming react-icons is installed, or use lucid-react if available in project
import { useQuery } from '@tanstack/react-query'; // Assuming react-query is used
import { toaster } from '@/components/ui/feedback/toaster'; // Updated path
// Import UI components (assuming they exist or use basic Chakra)
// I will use basic Chakra v3 components. For icons, I'll fallback to text if icons missing or Import from react-icons if available.
// The prompted file said Chakra UI v3.
interface GameDetailProps {
slug: string;
}
export function GameDetail({ slug }: GameDetailProps) {
const { data: response, isLoading, error, refetch } = useQuery({
queryKey: ['game', slug],
queryFn: () => gamesApi.getBySlug(slug),
});
useEffect(() => {
console.log('GameDetail mounted for slug:', slug);
}, [slug]);
const [isSyncing, setIsSyncing] = useState(false);
const [isSubscribing, setIsSubscribing] = useState(false);
const handleSync = async () => {
setIsSyncing(true);
try {
await gamesApi.sync(slug);
toaster.create({ title: 'Game synced successfully', type: 'success' });
refetch();
} catch (e) {
toaster.create({ title: 'Failed to sync game', type: 'error' });
} finally {
setIsSyncing(false);
}
};
const handleSubscribe = async () => {
setIsSubscribing(true);
try {
if (!game?.id) return;
await notificationsApi.subscribe(game.id);
toaster.create({ title: 'Subscribed to alerts!', type: 'success' });
} catch (e: any) {
// Handle "Already subscribed" specifically if possible, else generic error
const msg = e.response?.data?.message || 'Failed to subscribe';
toaster.create({ title: msg, type: msg.includes('Already') ? 'info' : 'error' });
} finally {
setIsSubscribing(false);
}
};
if (isLoading) return <Box p={10}>Loading...</Box>;
if (error || !response?.data?.data) return (
<Container centerContent py={20}>
<Heading>Game not found</Heading>
<Button mt={4} onClick={handleSync} loading={isSyncing}>Try Syncing from External Source</Button>
</Container>
);
const game = response.data.data;
return (
<Box pb={20}>
{/* Hero Section */}
<Box position="relative" h={{ base: "400px", md: "500px" }} w="full" overflow="hidden">
{/* Background Blur */}
<Box
position="absolute"
top={0}
left={0}
right={0}
bottom={0}
bgImage={`url(${game.coverImage})`}
bgSize="cover"
bgPos="center"
filter="blur(20px) brightness(0.4)"
zIndex={0}
/>
<Container maxW="container.xl" position="relative" zIndex={1} h="full" display="flex" alignItems="center">
<Grid templateColumns={{ base: "1fr", md: "300px 1fr" }} gap={8} alignItems="center" w="full">
<GridItem display={{ base: "none", md: "block" }}>
<Image
src={game.coverImage?.replace('t_thumb', 't_cover_big_2x')} // Try to get higher res if possible by replacing IGDB logic if used, else just src
alt={game.title}
borderRadius="xl"
boxShadow="2xl"
objectFit="cover"
h="400px"
w="full"
/>
</GridItem>
<GridItem color="white">
<Stack>
<Heading size="4xl" fontWeight="black" letterSpacing="tight">{game.title}</Heading>
<Flex gap={4} alignItems="center" flexWrap="wrap">
{game.rating && (
<Badge colorPalette="yellow" size="lg" variant="solid">
<Icon as={FaStar} mr={1} /> {Math.round(game.rating).toFixed(1)}
</Badge>
)}
{game.releaseDate && (
<Badge colorPalette="gray" size="lg" variant="surface">
<Icon as={FaCalendar} mr={2} />
{new Date(game.releaseDate).toLocaleDateString()}
</Badge>
)}
</Flex>
<Flex gap={2} mt={4} flexWrap="wrap">
{game.platforms?.map(p => (
<Tag.Root key={p.platform.slug} size="lg" variant="subtle">
<Tag.Label>{p.platform.name}</Tag.Label>
</Tag.Root>
))}
</Flex>
<Flex gap={2} mt={2} flexWrap="wrap">
{game.genres?.map(g => (
<Badge key={g.genre.slug} variant="outline" colorPalette="purple">
{g.genre.name}
</Badge>
))}
</Flex>
<Flex mt={6} gap={4}>
<Button onClick={handleSubscribe} loading={isSubscribing} colorPalette="purple" variant="solid">
<Icon as={FaBell} mr={2} /> Receive Alerts
</Button>
<Button onClick={handleSync} loading={isSyncing} variant="ghost" colorPalette="whiteAlpha">
<Icon as={FaSync} mr={2} /> Refresh Data
</Button>
</Flex>
</Stack>
</GridItem>
</Grid>
</Container>
</Box>
{/* Content Section */}
<Container maxW="container.xl" py={12}>
<Grid templateColumns={{ base: "1fr", lg: "2fr 1fr" }} gap={12}>
<GridItem>
<Heading size="xl" mb={6}>About</Heading>
<Text fontSize="lg" lineHeight="tall" color="fg.muted">
{game.description || "No description available."}
</Text>
{game.screenshots && game.screenshots.length > 0 && (
<Box mt={12}>
<Heading size="xl" mb={6}>Gallery</Heading>
<Grid templateColumns={{ base: "1fr", md: "repeat(2, 1fr)" }} gap={4}>
{game.screenshots.map((shot, idx) => (
<GridItem key={idx}>
<AspectRatio ratio={16 / 9} borderRadius="lg" overflow="hidden">
<Image
src={shot.url.replace('t_thumb', 't_screenshot_med')}
alt={`Screenshot ${idx}`}
objectFit="cover"
transition="transform 0.2s"
_hover={{ transform: 'scale(1.05)' }}
/>
</AspectRatio>
</GridItem>
))}
</Grid>
</Box>
)}
</GridItem>
<GridItem>
<Box p={6} borderRadius="xl" borderWidth="1px" borderColor="border">
<Heading size="md" mb={6}>Information</Heading>
<Stack gap={4}>
<Box>
<Text fontWeight="bold" mb={1} color="fg.muted">Developer</Text>
<Text fontSize="lg">{game.developer || "Unknown"}</Text>
</Box>
<Box>
<Text fontWeight="bold" mb={1} color="fg.muted">Publisher</Text>
<Text fontSize="lg">{game.publisher || "Unknown"}</Text>
</Box>
<Box>
<Text fontWeight="bold" mb={1} color="fg.muted">Release Date</Text>
<Text fontSize="lg">{game.releaseDate ? new Date(game.releaseDate).toLocaleDateString(undefined, { dateStyle: 'long' }) : 'TBD'}</Text>
</Box>
</Stack>
</Box>
</GridItem>
</Grid>
</Container>
</Box>
);
}

View File

@@ -1,38 +1,45 @@
'use client'; "use client";
import { HStack, Button, Text } from '@chakra-ui/react'; import { HStack, Box, Text } from '@chakra-ui/react';
import { useDynamicTheme, DynamicThemeProvider } from '@/components/ui/dynamic-theme-provider'; import { useDynamicTheme } from '@/components/ui/dynamic-theme-provider';
import { ThemeConfig, defaultTheme } from '@/types/theme'; import { defaultTheme } from '@/types/theme';
import { additionalThemes } from '@/theme/palettes';
const eldenRingTheme: ThemeConfig = { import { Button } from '@/components/ui/buttons/button';
key: 'elden_ring', import {
isActive: true, MenuContent,
gameTitle: 'Elden Ring', MenuItem,
primaryColor: '#C4A484', // Goldish/Beige MenuRoot,
secondaryColor: '#8B4513', // Brown MenuTrigger,
backgroundColor: '#1a1815', // Dark brown/black } from "@/components/ui/overlays/menu";
backgroundImage: 'https://images.igdb.com/igdb/image/upload/t_1080p/co4jni.jpg', // Elden Ring Art
};
const cyberPunkTheme: ThemeConfig = {
key: 'cyberpunk',
isActive: true,
gameTitle: 'Cyberpunk 2077',
primaryColor: '#FCEE0A', // Yellow
secondaryColor: '#00F0FF', // Blue
backgroundColor: '#0a0a0a',
backgroundImage: 'https://images.igdb.com/igdb/image/upload/t_1080p/co2mjs.jpg'
}
export function ThemeSwitcher() { export function ThemeSwitcher() {
const { setTheme } = useDynamicTheme(); const { setTheme } = useDynamicTheme();
return ( return (
<HStack p={4} bg="blackAlpha.500" rounded="lg" position="fixed" bottom={4} right={4} zIndex={9999}> <HStack p={4} bg="blackAlpha.500" rounded="lg" position="fixed" bottom={4} right={4} zIndex={9999}>
<Text fontSize="xs" color="white" fontWeight="bold">Simulate GOTY:</Text> <MenuRoot>
<Button size="xs" onClick={() => setTheme(defaultTheme)}>Default</Button> <MenuTrigger asChild>
<Button size="xs" colorPalette="yellow" onClick={() => setTheme(eldenRingTheme)}>Elden Ring</Button> <Button size="xs" variant="surface">Themes</Button>
<Button size="xs" colorPalette="cyan" onClick={() => setTheme(cyberPunkTheme)}>Cyberpunk</Button> </MenuTrigger>
<MenuContent>
<MenuItem value="default" onClick={() => setTheme(defaultTheme)}>
Default
</MenuItem>
{additionalThemes.map((theme) => (
<MenuItem
key={theme.key}
value={theme.key}
onClick={() => setTheme(theme)}
>
<HStack gap="2">
<Box boxSize="4" bg={theme.primaryColor} rounded="full" border="1px solid white" />
<Box boxSize="4" bg={theme.backgroundColor} rounded="full" border="1px solid white" ml="-3" />
<Text>{theme.gameTitle}</Text>
</HStack>
</MenuItem>
))}
</MenuContent>
</MenuRoot>
</HStack> </HStack>
); );
} }

View File

@@ -23,12 +23,12 @@ export default function Footer() {
<ChakraLink <ChakraLink
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
href="https://www.fcs.com.tr" href="/"
color={{ base: "primary.500", _dark: "primary.300" }} color={{ base: "primary.500", _dark: "primary.300" }}
focusRing="none" focusRing="none"
ml="1" ml="1"
> >
{"FCS"} {"Game Calendar"}
</ChakraLink> </ChakraLink>
. {t("all-right-reserved")} . {t("all-right-reserved")}
</Text> </Text>

View File

@@ -165,17 +165,23 @@ export default function Header() {
<ChakraLink <ChakraLink
as={Link} as={Link}
href="/home" href="/home"
fontSize="lg" fontSize="3xl"
fontWeight="bold" fontWeight="extrabold"
color={{ base: "primary.500", _dark: "primary.300" }} letterSpacing="wide"
bgGradient="to-r"
gradientFrom="primary.400"
gradientTo="primary.600"
bgClip="text"
bgSize="200% auto"
animation="text-gradient 12s linear infinite"
focusRing="none" focusRing="none"
textDecor="none" textDecor="none"
transition="all 0.3s ease-in-out" transition="all 0.3s ease-in-out"
_hover={{ _hover={{
color: { base: "primary.900", _dark: "primary.50" }, opacity: 0.8,
}} }}
> >
{"FCS "} {"Game Calendar"}
</ChakraLink> </ChakraLink>
</HStack> </HStack>

View File

@@ -2325,10 +2325,10 @@ function HomeCard() {
)} )}
</For> </For>
<For each={["solid", "outline", "subtle"]}> <For each={["solid", "outline", "subtle"]}>
{(variant) => <Avatar key={variant} variant={variant} name="FCS" />} {(variant) => <Avatar key={variant} variant={variant} name="GC" />}
</For> </For>
<Avatar shape="square" name="FCS" /> <Avatar shape="square" name="GC" />
<Avatar shape="rounded" name="FCS" /> <Avatar shape="rounded" name="GC" />
<Avatar <Avatar
src="https://picsum.photos/id/23/200/300" src="https://picsum.photos/id/23/200/300"
css={{ css={{

View File

@@ -2,6 +2,7 @@
import { ThemeConfig, defaultTheme } from '@/types/theme'; import { ThemeConfig, defaultTheme } from '@/types/theme';
import { createContext, useContext, useEffect, useState } from 'react'; import { createContext, useContext, useEffect, useState } from 'react';
import { themeApi } from '@/lib/api/theme';
interface DynamicThemeContextType { interface DynamicThemeContextType {
theme: ThemeConfig; theme: ThemeConfig;
@@ -23,25 +24,43 @@ interface DynamicThemeProviderProps {
export function DynamicThemeProvider({ children, initialTheme }: DynamicThemeProviderProps) { export function DynamicThemeProvider({ children, initialTheme }: DynamicThemeProviderProps) {
const [theme, setTheme] = useState<ThemeConfig>(initialTheme || defaultTheme); const [theme, setTheme] = useState<ThemeConfig>(initialTheme || defaultTheme);
// Fetch theme on mount
useEffect(() => {
const fetchTheme = async () => {
try {
const response = await themeApi.getTheme();
// @ts-ignore - The API response wrapper might be generic, assuming response.data is the payload if wrapped, or response if not.
// Based on standard axios + nestjs wrapper: response.data.data or response is the data.
// Let's assume our client unwraps it or we check.
// If createApiClient returns axios instance, .get returns AxiosResponse.
// api-service.ts unwraps response.data.
// BUT theme.ts calls client.get directly.
// Let's fix theme.ts to use apiRequest or handle .data
// Correction: theme.ts uses client.get. client is axios instance.
// So response is AxiosResponse. response.data is the body ({ success, data: theme }).
if (response.data && response.data.success && response.data.data) {
setTheme(response.data.data);
}
} catch (error) {
console.error('Failed to fetch theme:', error);
}
};
fetchTheme();
}, []);
// Apply theme to CSS variables // Apply theme to CSS variables
useEffect(() => { useEffect(() => {
if (!theme) return; if (!theme) return;
const root = document.documentElement; const root = document.documentElement;
// We update the CSS variables that map to our Chakra tokens
// Note: You might need to adjust the exact variable names based on your final theme.ts generation
// Chakra v3 usually uses var(--chakra-colors-primary-500) etc.
// For this simple implementation, we will assume we can override specific brand colors
// In a real generic system, we might need a more complex palette generator to generate 50-950 scales
root.style.setProperty('--chakra-colors-primary-500', theme.primaryColor); root.style.setProperty('--chakra-colors-primary-500', theme.primaryColor);
// ... rest of logic
root.style.setProperty('--chakra-colors-primary-600', theme.secondaryColor); root.style.setProperty('--chakra-colors-primary-600', theme.secondaryColor);
// Backgrounds for the app // Backgrounds for the app
if (theme.backgroundColor) { if (theme.backgroundColor) {
// We can create a custom variable for app-bg
root.style.setProperty('--app-background', theme.backgroundColor); root.style.setProperty('--app-background', theme.backgroundColor);
} }

View File

@@ -18,7 +18,14 @@ const LocaleSwitcher = () => {
const [isPending, startTransition] = useTransition(); const [isPending, startTransition] = useTransition();
const router = useRouter(); const router = useRouter();
const pathname = usePathname(); const pathname = usePathname();
/* eslint-disable react-hooks/exhaustive-deps */
const params = useParams(); const params = useParams();
const [mounted, setMounted] = React.useState(false);
// Effect to handle hydration match
React.useEffect(() => {
setMounted(true);
}, []);
const collections = createListCollection({ const collections = createListCollection({
items: [ items: [
@@ -39,6 +46,11 @@ const LocaleSwitcher = () => {
); );
}); });
} }
if (!mounted) {
return null;
}
return ( return (
<SelectRoot <SelectRoot
disabled={isPending} disabled={isPending}

25
src/lib/api/games.ts Normal file
View File

@@ -0,0 +1,25 @@
import { createApiClient } from './create-api-client';
export interface Game {
id: string;
slug: string;
title: string;
coverImage?: string;
description?: string;
releaseDate?: string;
rating?: number;
developer?: string;
publisher?: string;
platforms?: { platform: { name: string; slug: string; icon?: string } }[];
genres?: { genre: { name: string; slug: string } }[];
screenshots?: { url: string }[];
}
const client = createApiClient('/games');
export const gamesApi = {
getAll: (params?: any) => client.get<{ items: Game[]; meta: any }>('/', { params }),
getBySlug: (slug: string) => client.get<{ data: Game }>(`/${slug}`),
sync: (slug: string) => client.post(`/${slug}/sync`),
};

View File

@@ -0,0 +1,8 @@
import { createApiClient } from './create-api-client';
const client = createApiClient('/api/backend/notifications');
export const notificationsApi = {
subscribe: (gameId: string) => client.post('/subscribe', { gameId }),
unsubscribe: (gameId: string) => client.post('/unsubscribe', { gameId }),
};

9
src/lib/api/theme.ts Normal file
View File

@@ -0,0 +1,9 @@
import { createApiClient } from './create-api-client';
import { ThemeConfig } from '@/types/theme';
const client = createApiClient('/api/backend/theme');
export const themeApi = {
getTheme: () => client.get<{ data: ThemeConfig; success: boolean }>('/'),
updateTheme: (data: Partial<ThemeConfig>) => client.patch<{ data: ThemeConfig; success: boolean }>('/', data),
};

View File

@@ -4,6 +4,8 @@ import { routing } from './i18n/routing';
export default createMiddleware(routing); export default createMiddleware(routing);
export const config = { export const config = {
// Match only internationalized pathnames // Match all pathnames except for
matcher: ['/', '/(tr|en)/:path*'] // - … if they start with `/api`, `/_next` or `/_vercel`
// - … the ones containing a dot (e.g. `favicon.ico`)
matcher: ['/((?!api|_next|_vercel|.*\\..*).*)']
}; };

74
src/theme/palettes.ts Normal file
View File

@@ -0,0 +1,74 @@
import { ThemeConfig } from '@/types/theme';
export const eldenRingTheme: ThemeConfig = {
key: 'elden_ring',
isActive: true,
gameTitle: 'Elden Ring',
primaryColor: '#C4A484', // Goldish/Beige
secondaryColor: '#8B4513', // Brown
backgroundColor: '#1a1815', // Dark brown/black
backgroundImage: 'https://images.igdb.com/igdb/image/upload/t_1080p/co4jni.jpg', // Elden Ring Art
};
export const cyberPunkTheme: ThemeConfig = {
key: 'cyberpunk',
isActive: true,
gameTitle: 'Cyberpunk 2077',
primaryColor: '#FCEE0A', // Yellow
secondaryColor: '#00F0FF', // Blue
backgroundColor: '#0a0a0a',
backgroundImage: 'https://images.igdb.com/igdb/image/upload/t_1080p/co2mjs.jpg'
};
// Palette 1: https://colorhunt.co/palette/280905740a03c3110ce6501b
// Colors: #280905, #740a03, #c3110c, #e6501b
export const fireTheme: ThemeConfig = {
key: 'fire',
isActive: true,
gameTitle: 'Blazing Fast',
primaryColor: '#e6501b', // Bright orange
secondaryColor: '#c3110c', // Darker red/orange
backgroundColor: '#280905', // Deep dark brown/red
};
// Palette 2: https://colorhunt.co/palette/3b060a8a0000c83f12fff287
// Colors: #3b060a, #8a0000, #c83f12, #fff287
export const crimsonTheme: ThemeConfig = {
key: 'crimson',
isActive: true,
gameTitle: 'Crimson Tide',
primaryColor: '#fff287', // Light yellow accent
secondaryColor: '#c83f12', // Red/Orange
backgroundColor: '#3b060a', // Deep dark red
};
// Palette 3: https://colorhunt.co/palette/0054610c7779249e943bc1a8
// Colors: #005461, #0c7779, #249e94, #3bc1a8
export const oceanTheme: ThemeConfig = {
key: 'ocean',
isActive: true,
gameTitle: 'Oceanic Depths',
primaryColor: '#3bc1a8', // Light teal
secondaryColor: '#249e94', // Teal
backgroundColor: '#005461', // Dark blue/teal
};
// Palette 4: https://colorhunt.co/palette/1a3263547792fab95be8e2db
// Colors: #1a3263, #547792, #fab95b, #e8e2db
export const nightTheme: ThemeConfig = {
key: 'night',
isActive: true,
gameTitle: 'Starry Night',
primaryColor: '#fab95b', // Golden yellow
secondaryColor: '#547792', // Muted blue
backgroundColor: '#1a3263', // Deep blue
};
export const additionalThemes = [
eldenRingTheme,
cyberPunkTheme,
fireTheme,
crimsonTheme,
oceanTheme,
nightTheme,
];