From 9029fb4f6a7131bea738c3d765131a13a29c5811 Mon Sep 17 00:00:00 2001 From: brooktewabe Date: Sun, 1 Mar 2026 14:23:23 +0300 Subject: [PATCH] betting and ui components --- components/betting/betslip.tsx | 260 ++++++++++++---------- components/betting/check-your-bet.tsx | 6 +- components/betting/events-list.tsx | 100 +++++---- components/betting/hero-banner.tsx | 4 +- components/betting/in-play-page.tsx | 10 +- components/betting/live-events-list.tsx | 34 +-- components/betting/match-detail-view.tsx | 269 +++++++++++++++++++++++ components/betting/reload-ticket.tsx | 6 +- components/betting/sports-nav.tsx | 2 +- components/betting/top-matches.tsx | 133 ++++++----- components/games/game-card.tsx | 40 ++++ components/games/game-row.tsx | 95 ++++++++ components/games/gaming-sidebar.tsx | 86 ++++++++ components/games/virtual-sidebar.tsx | 88 ++++++++ 14 files changed, 892 insertions(+), 241 deletions(-) create mode 100644 components/betting/match-detail-view.tsx create mode 100644 components/games/game-card.tsx create mode 100644 components/games/game-row.tsx create mode 100644 components/games/gaming-sidebar.tsx create mode 100644 components/games/virtual-sidebar.tsx diff --git a/components/betting/betslip.tsx b/components/betting/betslip.tsx index a5427f4..0be8f72 100644 --- a/components/betting/betslip.tsx +++ b/components/betting/betslip.tsx @@ -2,183 +2,203 @@ import { useState } from "react" import { useBetslipStore } from "@/lib/store/betslip-store" -import { X, ChevronDown, Trash2 } from "lucide-react" +import { X, Save, Trash2 } from "lucide-react" import { cn } from "@/lib/utils" -const quickStakes = [5, 10, 20, 50, 100, 200] +const quickStakes = [10, 50, 100, 1000, 2000, 5000] export function Betslip() { const { bets, removeBet, clearBets, updateStake, getPotentialWin, getTotalOdds } = useBetslipStore() - const [activeTab, setActiveTab] = useState<"single" | "accumulator">("single") const [globalStake, setGlobalStake] = useState("10") - const potentialWin = getPotentialWin() const totalOdds = getTotalOdds() + const isMulti = bets.length > 1 + const potentialWin = isMulti + ? Number(globalStake) * totalOdds + : getPotentialWin() return ( -
- {/* Header */} -
-
- Betslip - {bets.length > 0 && ( - - {bets.length} - - )} -
- {bets.length > 0 && ( - - )} -
- - {/* Tabs */} - {bets.length > 1 && ( -
- {(["single", "accumulator"] as const).map((tab) => ( - - ))} -
- )} - - {/* Content */} -
+
+
{bets.length === 0 ? ( -
-
🎯
-

- No bets selected. Click on odds to add selections. +

+

+ No bet has been selected. To select a bet, please click on the respective odds

) : ( <> - {/* Bet items */} + {/* Bet cards */}
{bets.map((bet) => ( -
-
+
+
-
{bet.event}
-
{bet.league}
-
- {bet.market}: {bet.selection} +
+ {bet.event}
+
+ {bet.league} +
+
+ + {bet.market}: {bet.selection} + + {bet.odds.toFixed(2)} +
+ {!isMulti && ( +
+ Odds + {bet.odds.toFixed(2)} +
+ )}
-
- {bet.odds.toFixed(2)} - -
+
- {/* Stake input for single */} - {(activeTab === "single" || bets.length === 1) && ( -
-
Stake (ETB)
-
+ {/* Single bet: stake on card */} + {!isMulti && ( +
+
+ updateStake(bet.id, Number(e.target.value))} - className="flex-1 bg-input border border-border rounded px-2 py-1 text-xs text-foreground w-full min-w-0 focus:outline-none focus:border-primary" + onChange={(e) => updateStake(bet.id, Number(e.target.value) || 10)} + className="flex-1 h-7 bg-brand-bg border border-border/40 px-2 text-[11px] text-white text-center font-bold focus:outline-none focus:border-brand-primary" min="1" /> +
-
+
{quickStakes.map((s) => ( ))}
- {/* Potential win */} -
- Potential win: - - {((bet.stake ?? 10) * bet.odds).toFixed(2)} ETB - -
)}
))}
- {/* Accumulator stake section */} - {activeTab === "accumulator" && bets.length > 1 && ( -
-
- Total Odds: - {totalOdds.toFixed(2)} + {/* Single bet: potential winning below card */} + {!isMulti && ( +
+ Potential winning + {potentialWin.toFixed(2)} ETB +
+ )} + + {/* Multiple bets: combined Odds, one stake, quick buttons, potential winning */} + {isMulti && ( +
+
+ Odds + {totalOdds.toFixed(2)}
-
-
Stake (ETB)
+
+ setGlobalStake(e.target.value)} - className="w-full bg-input border border-border rounded px-2 py-1 text-xs text-foreground focus:outline-none focus:border-primary" + className="flex-1 h-7 bg-brand-bg border border-border/40 px-2 text-[11px] text-white text-center font-bold focus:outline-none focus:border-brand-primary" min="1" /> -
- {quickStakes.map((s) => ( - - ))} -
-
- Potential win: - - {(Number(globalStake) * totalOdds).toFixed(2)} ETB - -
+ +
+
+ {quickStakes.map((s) => ( + + ))} +
+
+ Potential winning + {(Number(globalStake) * totalOdds).toFixed(2)} ETB
)} - {/* Place bet button */} - +
+ + You need to login to be able to place a bet. +
+ +
+ + + +
)}
diff --git a/components/betting/check-your-bet.tsx b/components/betting/check-your-bet.tsx index 9970b13..7959c75 100644 --- a/components/betting/check-your-bet.tsx +++ b/components/betting/check-your-bet.tsx @@ -16,19 +16,19 @@ export function CheckYourBet() { return (
-

Check Your Bet

+

Check Your Bet

Your bet ID

setBetId(e.target.value)} - className="flex-1 bg-[#121212] border border-border/40 px-2 py-2 text-[11px] text-white outline-none focus:border-primary" + className="flex-1 bg-brand-bg border border-border/40 px-2 py-2 text-[11px] text-white outline-none focus:border-brand-primary" onKeyDown={(e) => e.key === "Enter" && handleCheck()} /> diff --git a/components/betting/events-list.tsx b/components/betting/events-list.tsx index 9fc1729..c322716 100644 --- a/components/betting/events-list.tsx +++ b/components/betting/events-list.tsx @@ -1,6 +1,7 @@ "use client" import { useState, useEffect } from "react" +import Link from "next/link" import { useSearchParams } from "next/navigation" import { useBetslipStore } from "@/lib/store/betslip-store" import { mockEvents, popularLeagues, type Event } from "@/lib/mock-data" @@ -16,11 +17,11 @@ function OddsButton({ odds, onClick, isSelected }: { ) } @@ -29,12 +30,12 @@ function EventRow({ event }: { event: Event }) { const { bets, addBet } = useBetslipStore() return ( -
+
{/* Small Icons & ID Column */}
- {event.id || "01682"} + {event.id || "01682"}
{/* Time & Team Column */} @@ -58,10 +59,10 @@ function EventRow({ event }: { event: Event }) { isSelected={isSelected} onClick={() => addBet({ id: betId, - event: `${event.homeTeam} vs ${event.awayTeam}`, - league: event.league, + event: `${event.homeTeam} - ${event.awayTeam}`, + league: `${event.sport} - ${event.country} - ${event.league}`, market: "1X2", - selection: `${event.homeTeam} (${market.label})`, + selection: market.label, odds: market.odds, })} /> @@ -69,10 +70,14 @@ function EventRow({ event }: { event: Event }) { })}
- {/* More Markets Button */} - +
) } @@ -112,26 +117,26 @@ export function EventsList({ filter = "All", sport = "all", search = "" }: { const renderTableHeaders = () => ( <> {/* Table Header Categories */} -
-
Main
-
Goals
-
Handicap
-
Half Time / Full Time
-
Correct Score
+
+
Main
+
Goals
+
Handicap
+
Half Time / Full Time
+
Correct Score
{/* Sub Headers */} -
-
1st Half
-
2nd Half
-
Combo
-
Chance Mix
-
Home
+
+
1st Half
+
2nd Half
+
Combo
+
Chance Mix
+
Home
) const renderColumnHeaders = () => ( -
+
Main
Over/Under
@@ -142,13 +147,13 @@ export function EventsList({ filter = "All", sport = "all", search = "" }: { ) const renderEventItem = (event: Event) => ( -
+
{/* Stats & Icons */}
{/* ID */} -
+
{event.id}
{/* Time */} @@ -156,10 +161,13 @@ export function EventsList({ filter = "All", sport = "all", search = "" }: { {event.time} PM
- {/* Event Name */} -
+ {/* Event Name -> same route as + icon (match detail) */} + {event.homeTeam} - {event.awayTeam} -
+ {/* Odds Grid */}
{event.markets.slice(0, 10).map((market) => { @@ -170,15 +178,15 @@ export function EventsList({ filter = "All", sport = "all", search = "" }: { key={market.id} onClick={() => addBet({ id: betId, - event: `${event.homeTeam} vs ${event.awayTeam}`, - league: event.league, + event: `${event.homeTeam} - ${event.awayTeam}`, + league: `${event.sport} - ${event.country} - ${event.league}`, market: "1X2", - selection: `${event.homeTeam} (${market.label})`, + selection: market.label, odds: market.odds, })} className={cn( "flex items-center justify-center text-[10.5px] font-black tabular-nums transition-all border-r border-white/5", - isSelected ? "bg-[#ff9800] text-black" : "text-[#ff9800] hover:bg-white/5" + isSelected ? "bg-brand-primary text-black" : "text-brand-primary hover:bg-white/5" )} > {market.odds.toFixed(2)} @@ -186,10 +194,14 @@ export function EventsList({ filter = "All", sport = "all", search = "" }: { ) })}
- {/* More Button */} - +
) @@ -202,9 +214,9 @@ export function EventsList({ filter = "All", sport = "all", search = "" }: { }, {} as Record) return ( -
+
{/* League Header / Breadcrumbs */} -
+
@@ -220,7 +232,7 @@ export function EventsList({ filter = "All", sport = "all", search = "" }: {
{/* Large Market Tab Grid */} -
+
{[ { label: "Main", active: true }, { label: "Goals" }, { label: "Handicap" }, { label: "Half Time / Full Time" }, { label: "Correct Score" }, { label: "1st Half" }, { label: "2nd Half" }, { label: "Asian Markets" }, { label: "Corners" }, { label: "Home" } @@ -229,7 +241,7 @@ export function EventsList({ filter = "All", sport = "all", search = "" }: { key={i} className={cn( "h-8 border-r border-b border-border/10 flex items-center justify-center text-[10px] font-black uppercase transition-all", - m.active ? "bg-[#ff9800] text-black" : "text-white/60 hover:bg-[#222]" + m.active ? "bg-brand-primary text-black" : "text-white/60 hover:bg-brand-surface" )} > {m.label} @@ -244,7 +256,7 @@ export function EventsList({ filter = "All", sport = "all", search = "" }: {
{Object.entries(groupedEvents).map(([date, dateEvents]) => (
-
+
{date}
{dateEvents.map(event => renderEventItem(event))} @@ -263,12 +275,12 @@ export function EventsList({ filter = "All", sport = "all", search = "" }: { }, {} as Record) return ( -
+
{Object.entries(homeEventsByLeague).map(([leagueName, leagueEvents]) => (
{/* League Box Header */} -
+
{popularLeagues.find(l => l.name === leagueName)?.icon || @@ -285,7 +297,7 @@ export function EventsList({ filter = "All", sport = "all", search = "" }: {
{/* Column Headers for each league box */} -
+
Stats ID diff --git a/components/betting/hero-banner.tsx b/components/betting/hero-banner.tsx index 28cc6e6..30ccfca 100644 --- a/components/betting/hero-banner.tsx +++ b/components/betting/hero-banner.tsx @@ -19,7 +19,7 @@ export function HeroBanner() { }, []) return ( -
+
{images.map((src, index) => ( setCurrentIndex(index)} className={`w-1.5 h-1.5 rounded-full transition-all ${ - index === currentIndex ? "bg-[#ff9800] scale-125" : "bg-white/40" + index === currentIndex ? "bg-brand-primary scale-125" : "bg-white/40" }`} /> ))} diff --git a/components/betting/in-play-page.tsx b/components/betting/in-play-page.tsx index b9c030e..a3b6be3 100644 --- a/components/betting/in-play-page.tsx +++ b/components/betting/in-play-page.tsx @@ -1,3 +1,6 @@ +"use client" + +import { useState } from "react" import { InPlayHeader } from "@/components/betting/in-play-header" import { QuickFilterBar } from "@/components/betting/quick-filter-bar" import { SearchEvent } from "@/components/betting/search-event" @@ -5,11 +8,14 @@ import { BetServices } from "@/components/betting/bet-services" import { EventsList } from "@/components/betting/events-list" export function InPlayPage() { + const [activeFilter, setActiveFilter] = useState("All") + const [searchQuery, setSearchQuery] = useState("") + return (
- - + +
diff --git a/components/betting/live-events-list.tsx b/components/betting/live-events-list.tsx index 5615e9a..6803c28 100644 --- a/components/betting/live-events-list.tsx +++ b/components/betting/live-events-list.tsx @@ -15,16 +15,16 @@ function LiveEventRow({ event, isNoOdds }: { event: Event, isNoOdds?: boolean }) const period = "H2" return ( -
+
{/* Match Info Column (Time & Score) */}
- {time} + {time} {period}
- {event.homeTeam} {score} {event.awayTeam} + {event.homeTeam} {score} {event.awayTeam}
@@ -36,7 +36,7 @@ function LiveEventRow({ event, isNoOdds }: { event: Event, isNoOdds?: boolean }) {/* Odds Grid or Placeholder */}
{isNoOdds ? ( -
+
Sorry, no odds for this match
) : ( @@ -48,16 +48,16 @@ function LiveEventRow({ event, isNoOdds }: { event: Event, isNoOdds?: boolean }) key={m.id} onClick={() => addBet({ id: `${event.id}-${m.id}`, - event: `${event.homeTeam} vs ${event.awayTeam}`, - league: event.league, + event: `${event.homeTeam} - ${event.awayTeam}`, + league: `${event.sport} - ${event.country} - ${event.league}`, market: "1X2", - selection: `${m.label}`, + selection: m.label, odds: m.odds, })} - className="bg-[#1a1a1a] hover:bg-[#2a2a2a] flex items-center justify-between px-4 h-full border-r border-white/5 transition-colors group/btn" + className="bg-brand-bg hover:bg-white/5 flex items-center justify-between px-4 h-full border-r border-white/5 transition-colors group/btn" > {labels[idx]} - {m.odds.toFixed(2)} + {m.odds.toFixed(2)} ) })} @@ -66,7 +66,7 @@ function LiveEventRow({ event, isNoOdds }: { event: Event, isNoOdds?: boolean })
{/* Right Indicator */} -
+
) } @@ -124,9 +124,9 @@ export function LiveEventsList() { ] return ( -
+
{/* Sport Navigation Carousel */} -
+
{/* Favourites & Prematch */} ))} @@ -164,7 +164,7 @@ export function LiveEventsList() {
{/* Category Header (Soccer) */} -
+
âš½

Soccer

@@ -174,7 +174,7 @@ export function LiveEventsList() { {liveMatches.map((group, gIdx) => (
{/* League Header */} -
+
{group.league} {group.league} diff --git a/components/betting/match-detail-view.tsx b/components/betting/match-detail-view.tsx new file mode 100644 index 0000000..d73f1e0 --- /dev/null +++ b/components/betting/match-detail-view.tsx @@ -0,0 +1,269 @@ +"use client" + +import { useState } from "react" +import Link from "next/link" +import { useBetslipStore } from "@/lib/store/betslip-store" +import { + getEventDetailMarkets, + getCardsBookingsMarkets, + type Event, + type DetailMarketSection, +} from "@/lib/mock-data" +import { cn } from "@/lib/utils" +import { ChevronDown, ChevronUp } from "lucide-react" + +const MARKET_CATEGORIES = [ + "Betbuilder", + "All", + "Main", + "Goals", + "Handicap", + "1st Half", + "2nd Half", + "Combo", + "Chance Mix", + "Home", + "Half Time / Full Time", + "Away", + "Correct Score", + "Asian Markets", + "Corners", + "Minutes", + "Cards/Bookings", + "Points Handicap", + "Total Points", + "Team 1", + "Team 2", + "Other", + "Handicap Goals", + "Total Goals", + "Combo", + "Specials", +] + +function MarketSectionBlock({ + section, + event, + marketName, + isExpanded, + onToggle, +}: { + section: DetailMarketSection + event: Event + marketName: string + isExpanded: boolean + onToggle: () => void +}) { + const { bets, addBet } = useBetslipStore() + const hasOutcomes = section.outcomes.length > 0 + + return ( +
+ + {isExpanded && hasOutcomes && ( +
+ {section.outcomes.length > 2 && section.outcomes.length % 2 === 0 ? ( +
+ {section.outcomes.map((outcome) => { + const betId = `${event.id}-${section.id}-${outcome.label.replace(/\s/g, "-").toLowerCase()}` + const isSelected = bets.some((b) => b.id === betId) + return ( +
+ {outcome.label} + +
+ ) + })} +
+ ) : ( + section.outcomes.map((outcome) => { + const betId = `${event.id}-${section.id}-${outcome.label.replace(/\s/g, "-").toLowerCase()}` + const isSelected = bets.some((b) => b.id === betId) + return ( +
+ {outcome.label} + +
+ ) + }) + )} +
+ )} +
+ ) +} + +export function MatchDetailView({ event }: { event: Event }) { + const [expandedSections, setExpandedSections] = useState>({ + "bookings-1x2": true, + "sending-off": true, + "1st-booking": true, + "1st-half-bookings-1x2": true, + "booking-points-ou": true, + "1st-half-1st-booking": true, + }) + const [activeCategory, setActiveCategory] = useState("Cards/Bookings") + + const detailMarkets = getEventDetailMarkets(event.id) + const cardsBookings = getCardsBookingsMarkets(event.id) + + const toggleSection = (id: string) => { + setExpandedSections((prev) => ({ ...prev, [id]: !prev[id] })) + } + + const breadcrumbLeague = + event.league === "Premier League" + ? "England - Premier League" + : `${event.country} - ${event.league}` + + const isCardsBookings = activeCategory === "Cards/Bookings" + const leftSections = isCardsBookings ? cardsBookings.left : detailMarkets + const rightSections = isCardsBookings ? cardsBookings.right : [] + + return ( +
+ {/* Breadcrumb: back arrow, ellipsis, path */} +
+ + < + ... + Football {breadcrumbLeague} / {event.homeTeam} vs. {event.awayTeam} + +

+ {breadcrumbLeague} +

+
+ + {/* Match header */} +
+
+
+
+ + {event.homeTeam.slice(0, 2)} + +
+ {event.homeTeam} +
+ VS +
+
+ + {event.awayTeam.slice(0, 2)} + +
+ {event.awayTeam} +
+
+
+ + {/* Category tabs: horizontal scroll, selected = darker grey */} +
+ {MARKET_CATEGORIES.map((label) => ( + + ))} +
+ + {/* Two-column grid of market sections */} +
+
+ {/* Left column */} +
+ {leftSections.map((section) => ( + toggleSection(section.id)} + /> + ))} +
+ {/* Right column (Cards/Bookings only) */} + {rightSections.length > 0 && ( +
+ {rightSections.map((section) => ( + toggleSection(section.id)} + /> + ))} +
+ )} +
+
+
+ ) +} diff --git a/components/betting/reload-ticket.tsx b/components/betting/reload-ticket.tsx index 9ab5e60..f934014 100644 --- a/components/betting/reload-ticket.tsx +++ b/components/betting/reload-ticket.tsx @@ -8,16 +8,16 @@ export function ReloadTicket() { return (
-

Reload Ticket

+

Reload Ticket

Insert the code to load

setCode(e.target.value)} - className="flex-1 bg-[#121212] border border-border/40 px-2 py-2 text-[11px] text-white outline-none focus:border-primary" + className="flex-1 bg-brand-bg border border-border/40 px-2 py-2 text-[11px] text-white outline-none focus:border-brand-primary" /> -
diff --git a/components/betting/sports-nav.tsx b/components/betting/sports-nav.tsx index 44c3332..ae3f6d8 100644 --- a/components/betting/sports-nav.tsx +++ b/components/betting/sports-nav.tsx @@ -16,7 +16,7 @@ const sports = [ export function SportsNav() { return ( - + {sports.map((sport) => ( - {topMatches.map((match) => ( -
- {/* Top Label Ribbon */} -
-
- TOP + {topMatches.map((match) => { + const eventName = `${match.homeTeam} - ${match.awayTeam}` + const leagueForBet = `Football - ${match.league}` + const outcomes = [ + { key: "1", label: "1", odds: match.odds.home }, + { key: "x", label: "X", odds: match.odds.draw }, + { key: "2", label: "2", odds: match.odds.away }, + ] as const + return ( +
+ {/* Top Label Ribbon */} +
+
+ TOP +
+
+ +
+
+ {match.league} + {match.time} +
+ +
+ +
+
+
+
âš½
+ {match.homeTeam} +
+ VS +
+ {match.awayTeam} +
âš½
+
+
+
+ +
+ {outcomes.map(({ key, label, odds }) => { + const betId = `${match.id}-${key}` + const isSelected = bets.some((b) => b.id === betId) + return ( + + ) + })}
- -
-
- {match.league} - {match.time} -
- -
- -
-
-
-
âš½
- {match.homeTeam} -
- VS -
- {match.awayTeam} -
âš½
-
-
-
- -
- - - -
-
- ))} + ) + })}
) } diff --git a/components/games/game-card.tsx b/components/games/game-card.tsx new file mode 100644 index 0000000..2fb58ca --- /dev/null +++ b/components/games/game-card.tsx @@ -0,0 +1,40 @@ +"use client" + +import Image from "next/image" +import { cn } from "@/lib/utils" + +interface GameCardProps { + id: string + title: string + image: string + provider?: string +} + +export function GameCard({ id, title, image, provider }: GameCardProps) { + return ( +
+
+ {title} +
+ +
+
+
+

+ {title} +

+ {provider && ( +

{provider}

+ )} +
+
+ ) +} diff --git a/components/games/game-row.tsx b/components/games/game-row.tsx new file mode 100644 index 0000000..4e30c4f --- /dev/null +++ b/components/games/game-row.tsx @@ -0,0 +1,95 @@ +"use client" + +import { useRef } from "react" +import { ChevronLeft, ChevronRight } from "lucide-react" +import { GameCard } from "./game-card" +import { cn } from "@/lib/utils" + +interface GameRowProps { + title: string + games: any[] + showSeeMore?: boolean + rows?: 1 | 2 | 3 +} + +export function GameRow({ title, games, showSeeMore = true, rows = 1 }: GameRowProps) { + const scrollRef = useRef(null) + + const scroll = (direction: "left" | "right") => { + if (scrollRef.current) { + const scrollAmount = direction === "left" ? -600 : 600 + scrollRef.current.scrollBy({ left: scrollAmount, behavior: "smooth" }) + } + } + + // Chunk games into rows if rows > 1 + const renderGames = () => { + if (rows === 1) { + return games.map((game, idx) => ( +
+ +
+ )) + } + + // For multi-row, we can use a grid with horizontal scroll on the container + // or wrap items. The requirement "3*6 horizontally scrollable" suggests + // a grid that moves as a block or multi-row horizontal layout. + return ( +
+ {games.map((game, idx) => ( +
+ +
+ ))} +
+ ) + } + + return ( +
+
+

+ {title} +

+
+ {showSeeMore && ( + + )} +
+ + +
+
+
+ +
+ {rows === 1 ? ( +
+ {renderGames()} +
+ ) : ( + renderGames() + )} +
+
+ ) +} diff --git a/components/games/gaming-sidebar.tsx b/components/games/gaming-sidebar.tsx new file mode 100644 index 0000000..fa2d11c --- /dev/null +++ b/components/games/gaming-sidebar.tsx @@ -0,0 +1,86 @@ +"use client" + +import { cn } from "@/lib/utils" +import { Search, Heart, Clock, Star } from "lucide-react" + +export type GameCategory = string + +interface GamingSidebarProps { + title: string + subtitle?: string + activeCategory: GameCategory + onCategoryChange: (category: GameCategory) => void + categories: { + id: string + name: string + icon: any + subtitle?: string + hasChevron?: boolean + }[] +} + +export function GamingSidebar({ title, subtitle, activeCategory, onCategoryChange, categories }: GamingSidebarProps) { + return ( + + ) +} diff --git a/components/games/virtual-sidebar.tsx b/components/games/virtual-sidebar.tsx new file mode 100644 index 0000000..1b2aec3 --- /dev/null +++ b/components/games/virtual-sidebar.tsx @@ -0,0 +1,88 @@ +"use client" + +import { cn } from "@/lib/utils" +import { Search, Heart, Clock, Star, Zap, LayoutGrid, Gamepad2, Award, Coins, Flame, Trophy } from "lucide-react" + +export type GameCategory = + | "all" + | "search" + | "favourite" + | "recently-played" + | "most-popular" + | "harif-special" + | "for-you" + | "slots" + | "crash-games" + | "higher-lower" + | "smartsoft" + | "keno-spin" + | "pragmatic-play" + | "evoplay-bonus" + +interface VirtualSidebarProps { + activeCategory: GameCategory + onCategoryChange: (category: GameCategory) => void +} + +const categories = [ + { id: "all", name: "Virtual", icon: Star, subtitle: "Check out our games!", hasChevron: true }, + { id: "search", name: "Search", icon: Search }, + { id: "favourite", name: "Favourite", icon: Heart }, + { id: "recently-played", name: "Recently Played", icon: Clock }, + { id: "most-popular", name: "Most Popular", icon: Star }, + { id: "harif-special", name: "Harif Special", icon: Zap }, + { id: "for-you", name: "For You", icon: Star }, + { id: "slots", name: "Slots", icon: Star }, + { id: "crash-games", name: "Crash Games", icon: Star }, + { id: "higher-lower", name: "Higher Lower", icon: Star }, + { id: "smartsoft", name: "Smartsoft", icon: Star }, + { id: "keno-spin", name: "Keno & Spin", icon: Star }, + { id: "pragmatic-play", name: "Pragmatic Play", icon: Star }, + { id: "evoplay-bonus", name: "EvoPlay BONUS", icon: Star }, +] + +export function VirtualSidebar({ activeCategory, onCategoryChange }: VirtualSidebarProps) { + return ( + + ) +}