-
Notifications
You must be signed in to change notification settings - Fork 18
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add swipper for phone play #74
Changes from all commits
0ba99be
a776719
5abc21b
4ca5736
e2f98f9
2faed68
248f2eb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
import React, { useMemo } from "react"; | ||
import { Hourglass, Trophy, Coins, Zap, HelpCircle } from "lucide-react"; | ||
import { | ||
Card, | ||
CardContent, | ||
CardFooter, | ||
CardHeader, | ||
CardTitle, | ||
} from "../elements/card"; | ||
import { ModeType } from "@/dojo/game/types/mode"; | ||
import { useSettings } from "@/hooks/useSettings"; | ||
import useTournament from "@/hooks/useTournament"; | ||
import { Start } from "../actions/Start"; | ||
import TournamentTimer from "./TournamentTimer"; | ||
import { | ||
Tooltip, | ||
TooltipContent, | ||
TooltipProvider, | ||
TooltipTrigger, | ||
} from "../elements/tooltip"; | ||
import { useMediaQuery } from "react-responsive"; | ||
import { formatPrize } from "@/utils/price"; | ||
import NftImage from "./ImageNFTZkube"; | ||
|
||
const { VITE_PUBLIC_GAME_TOKEN_SYMBOL } = import.meta.env; | ||
|
||
interface GameModeCardProps { | ||
mode: ModeType; | ||
handleGameMode: () => void; | ||
} | ||
|
||
const GameModeCardMobile: React.FC<GameModeCardProps> = ({ | ||
mode, | ||
handleGameMode, | ||
}) => { | ||
const { settings } = useSettings(); | ||
|
||
const { endTimestamp, tournament } = useTournament(mode); | ||
|
||
Comment on lines
+32
to
+39
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add error handling for hook failures. The hooks const GameModeCardMobile: React.FC<GameModeCardProps> = ({
mode,
handleGameMode,
}) => {
- const { settings } = useSettings();
+ const { settings, error: settingsError } = useSettings();
+ const { endTimestamp, tournament, error: tournamentError } = useTournament(mode);
- const { endTimestamp, tournament } = useTournament(mode);
+ if (settingsError || tournamentError) {
+ return (
+ <Card className="w-full h-full bg-gray-800 text-white border-2 border-white">
+ <CardContent>
+ <div className="text-center text-red-500">
+ Failed to load game mode data. Please try again.
+ </div>
+ </CardContent>
+ </Card>
+ );
+ }
|
||
const potentialWin = useMemo(() => { | ||
if (!tournament) return formatPrize(0n, VITE_PUBLIC_GAME_TOKEN_SYMBOL); | ||
return formatPrize(tournament.prize, VITE_PUBLIC_GAME_TOKEN_SYMBOL); | ||
}, [tournament]); | ||
|
||
const cost = useMemo(() => { | ||
if (!settings) return formatPrize(0n, VITE_PUBLIC_GAME_TOKEN_SYMBOL); | ||
const weiCost = settings.game_price; | ||
return formatPrize(weiCost, VITE_PUBLIC_GAME_TOKEN_SYMBOL); | ||
}, [settings]); | ||
|
||
const difficultyRule = useMemo(() => { | ||
switch (mode) { | ||
case ModeType.Daily: | ||
return { | ||
name: "Pro Mode", | ||
description: | ||
"A fixed high-difficulty challenge that tests your skills at their peak.", | ||
}; | ||
case ModeType.Normal: | ||
return { | ||
name: "Escalation Mode", | ||
description: | ||
"Difficulty increases over time, pushing you to adapt and improve.", | ||
}; | ||
case ModeType.Free: | ||
return { | ||
name: "Escalation Mode", | ||
description: | ||
"Difficulty increases over time, pushing you to adapt and improve.", | ||
}; | ||
default: | ||
return { | ||
name: "Normal Mode", | ||
description: | ||
"A standard mode with a fixed difficulty level for consistent play.", | ||
}; | ||
} | ||
}, [mode]); | ||
Comment on lines
+40
to
+78
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Refactor duplicate difficulty rules and add price formatting error handling. There are two issues to address:
const potentialWin = useMemo(() => {
- if (!tournament) return formatPrize(0n, VITE_PUBLIC_GAME_TOKEN_SYMBOL);
- return formatPrize(tournament.prize, VITE_PUBLIC_GAME_TOKEN_SYMBOL);
+ try {
+ if (!tournament) return formatPrize(0n, VITE_PUBLIC_GAME_TOKEN_SYMBOL);
+ return formatPrize(tournament.prize, VITE_PUBLIC_GAME_TOKEN_SYMBOL);
+ } catch (error) {
+ console.error('Error formatting prize:', error);
+ return { withImage: '0' };
+ }
}, [tournament]);
const difficultyRule = useMemo(() => {
+ const ESCALATION_MODE = {
+ name: "Escalation Mode",
+ description: "Difficulty increases over time, pushing you to adapt and improve.",
+ };
+
switch (mode) {
case ModeType.Daily:
return {
name: "Pro Mode",
description:
"A fixed high-difficulty challenge that tests your skills at their peak.",
};
case ModeType.Normal:
- return {
- name: "Escalation Mode",
- description:
- "Difficulty increases over time, pushing you to adapt and improve.",
- };
+ return ESCALATION_MODE;
case ModeType.Free:
- return {
- name: "Escalation Mode",
- description:
- "Difficulty increases over time, pushing you to adapt and improve.",
- };
+ return ESCALATION_MODE;
default:
return {
name: "Normal Mode",
|
||
|
||
return ( | ||
<Card className="w-full h-full bg-gray-800 text-white border-2 border-white"> | ||
<CardHeader className="pt-4 pb-10 md:pb-4"> | ||
<CardTitle className="text-2xl md:text-2xl font-bold text-center"> | ||
{mode} | ||
</CardTitle> | ||
</CardHeader> | ||
<CardContent className="space-y-2 text-sm md:text-base pb-4"> | ||
<div className="flex items-center space-x-2 gap-2"> | ||
<Coins className="h-5 w-5 flex-shrink-0" /> | ||
<div className="flex-grow flex justify-between items-center"> | ||
<span className="font-semibold">Cost</span> | ||
<div className="text-slate-300"> | ||
{mode === ModeType.Free ? ( | ||
"Free" | ||
) : ( | ||
<div className="flex items-center gap-3 -mr-1"> | ||
{cost.withImage} <p>or</p> | ||
<div className="flex items-center gap-1"> | ||
<p>1</p> | ||
<NftImage /> | ||
</div> | ||
</div> | ||
)} | ||
</div> | ||
</div> | ||
</div> | ||
|
||
<div className="flex items-center space-x-2 gap-2"> | ||
<Zap className="h-5 w-5 flex-shrink-0" /> | ||
<div className="flex-grow flex justify-between items-center"> | ||
<span className="font-semibold">Difficulty</span> | ||
<span className="flex items-center text-slate-300 relative"> | ||
{difficultyRule.name} | ||
</span> | ||
</div> | ||
</div> | ||
|
||
{(mode === ModeType.Daily || mode === ModeType.Normal) && ( | ||
<> | ||
<div className="flex items-center space-x-2 w-full gap-2"> | ||
<Hourglass className="h-5 w-5 flex-shrink-0" /> | ||
<div className="flex-grow flex justify-between items-center"> | ||
<span className="font-semibold">Ends in</span> | ||
<div className="text-slate-300"> | ||
<TournamentTimer mode={mode} endTimestamp={endTimestamp} /> | ||
</div> | ||
</div> | ||
</div> | ||
<div className="flex items-center space-x-2 w-full gap-2"> | ||
<Trophy className="h-5 w-5 flex-shrink-0" /> | ||
<div className="flex-grow flex justify-between items-center"> | ||
<span className="font-semibold">Prize Pool</span> | ||
{potentialWin.withImage} | ||
</div> | ||
</div> | ||
</> | ||
)} | ||
</CardContent> | ||
<CardFooter className="mt-8"> | ||
<Start mode={mode} handleGameMode={handleGameMode} /> | ||
</CardFooter> | ||
</Card> | ||
); | ||
}; | ||
|
||
export default GameModeCardMobile; |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,48 @@ | ||||||||||||||||||||||||||||||||||||||||||
import { Swiper, SwiperSlide } from "swiper/react"; | ||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||
import "swiper/css"; | ||||||||||||||||||||||||||||||||||||||||||
import "swiper/css/effect-cards"; | ||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||
import "@/index.css"; | ||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||
import { EffectCards } from "swiper/modules"; | ||||||||||||||||||||||||||||||||||||||||||
import { ModeType } from "@/dojo/game/types/mode"; | ||||||||||||||||||||||||||||||||||||||||||
import GameModeCardMobile from "./GameModeCardMobile"; | ||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||
interface SwiperProps { | ||||||||||||||||||||||||||||||||||||||||||
setIsGameOn: (isOn: string) => void; | ||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+12
to
+14
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Consider using more specific types for better type safety. The Consider this improvement: interface SwiperProps {
- setIsGameOn: (isOn: string) => void;
+ setIsGameOn: (state: boolean) => void;
} Then update the usage: - handleGameMode={() => setIsGameOn("isOn")}
+ handleGameMode={() => setIsGameOn(true)}
|
||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||
export default function Swipper({ setIsGameOn }: SwiperProps) { | ||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix component name spelling. The component name "Swipper" is misspelled. It should be "Swiper" to maintain consistency with the library name and common naming conventions. -export default function Swipper({ setIsGameOn }: SwiperProps) {
+export default function Swiper({ setIsGameOn }: SwiperProps) { 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||
return ( | ||||||||||||||||||||||||||||||||||||||||||
<> | ||||||||||||||||||||||||||||||||||||||||||
<Swiper | ||||||||||||||||||||||||||||||||||||||||||
effect={"cards"} | ||||||||||||||||||||||||||||||||||||||||||
grabCursor={true} | ||||||||||||||||||||||||||||||||||||||||||
modules={[EffectCards]} | ||||||||||||||||||||||||||||||||||||||||||
className="mySwiper" | ||||||||||||||||||||||||||||||||||||||||||
initialSlide={1} | ||||||||||||||||||||||||||||||||||||||||||
> | ||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+19
to
+25
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Add accessibility attributes to the Swiper component. The slider component lacks proper accessibility attributes which could make it difficult for users with assistive technologies. <Swiper
effect={"cards"}
grabCursor={true}
modules={[EffectCards]}
className="mySwiper"
initialSlide={1}
+ a11y={{
+ prevSlideMessage: 'Previous game mode',
+ nextSlideMessage: 'Next game mode',
+ firstSlideMessage: 'This is the first game mode',
+ lastSlideMessage: 'This is the last game mode'
+ }}
> 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||
<SwiperSlide> | ||||||||||||||||||||||||||||||||||||||||||
<GameModeCardMobile | ||||||||||||||||||||||||||||||||||||||||||
mode={ModeType.Free} | ||||||||||||||||||||||||||||||||||||||||||
handleGameMode={() => setIsGameOn("isOn")} | ||||||||||||||||||||||||||||||||||||||||||
/> | ||||||||||||||||||||||||||||||||||||||||||
</SwiperSlide> | ||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||
<SwiperSlide> | ||||||||||||||||||||||||||||||||||||||||||
<GameModeCardMobile | ||||||||||||||||||||||||||||||||||||||||||
mode={ModeType.Daily} | ||||||||||||||||||||||||||||||||||||||||||
handleGameMode={() => setIsGameOn("isOn")} | ||||||||||||||||||||||||||||||||||||||||||
/> | ||||||||||||||||||||||||||||||||||||||||||
</SwiperSlide> | ||||||||||||||||||||||||||||||||||||||||||
<SwiperSlide> | ||||||||||||||||||||||||||||||||||||||||||
<GameModeCardMobile | ||||||||||||||||||||||||||||||||||||||||||
mode={ModeType.Normal} | ||||||||||||||||||||||||||||||||||||||||||
handleGameMode={() => setIsGameOn("isOn")} | ||||||||||||||||||||||||||||||||||||||||||
/> | ||||||||||||||||||||||||||||||||||||||||||
</SwiperSlide> | ||||||||||||||||||||||||||||||||||||||||||
</Swiper> | ||||||||||||||||||||||||||||||||||||||||||
</> | ||||||||||||||||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||||||||||||||||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Codebase verification
Remove unused @egjs/flicking dependencies
Based on the codebase analysis, only the Swiper library is being actively used in the implementation (Swipper.tsx component). The @egjs/flicking-plugins and @egjs/react-flicking packages are included in package.json but are not used anywhere in the codebase. These should be removed to avoid unnecessary dependencies.
@egjs/flicking-plugins
from package.json@egjs/react-flicking
from package.json🔗 Analysis chain
Consider consolidating slider libraries
I notice that both Swiper and @egjs/flicking (with plugins) are being added, which serve similar purposes for creating slider/carousel components. Consider using just one of these libraries to reduce bundle size and maintain consistency.
Let's check the bundle sizes and peer dependencies:
If you decide to proceed with both libraries, please document the specific use case for each to justify maintaining both dependencies.
Also applies to: 89-89
Let me gather more information about how these libraries are actually used in the codebase.
Let me try again with correct file type flags for ripgrep.
Let me check the actual implementation of the Swiper component and the CSS to understand if both libraries are actually being used.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
Length of output: 287
Script:
Length of output: 578
Script:
Length of output: 1483
Script:
Length of output: 1801