little tweaks
This commit is contained in:
parent
caf681a4e6
commit
7e9f98f648
|
|
@ -62,7 +62,7 @@ export default function GameModal({ isOpen, onClose }: GameModalProps) {
|
|||
}
|
||||
|
||||
setIsProcessing(true);
|
||||
toast.loading("Creating bet");
|
||||
toast.loading("Creating Game");
|
||||
try {
|
||||
const tx = await createBet(wallet, user?.id ?? "", selectedPrice, selectedGame.id, false);
|
||||
const url = EXPLORER_TX_TEMPLATE.replace("{address}", tx);
|
||||
|
|
@ -70,7 +70,7 @@ export default function GameModal({ isOpen, onClose }: GameModalProps) {
|
|||
connection.confirmTransaction(tx, CONFIRMATION_THRESHOLD).finally(()=>{
|
||||
toast.dismiss();
|
||||
|
||||
toast.success(`Bet created successfully!`, {
|
||||
toast.success(`Game created successfully!`, {
|
||||
action: {
|
||||
label: "View TX",
|
||||
onClick: () => window.open(url, "_blank"),
|
||||
|
|
@ -83,7 +83,7 @@ export default function GameModal({ isOpen, onClose }: GameModalProps) {
|
|||
onClose();
|
||||
} catch (error) {
|
||||
console.error("Error creating bet:", error);
|
||||
toast.error("Failed to create bet. Please try again.");
|
||||
toast.error("Failed to create Game. Please try again.");
|
||||
toast.dismiss();
|
||||
|
||||
} finally {
|
||||
|
|
@ -143,7 +143,7 @@ export default function GameModal({ isOpen, onClose }: GameModalProps) {
|
|||
className="mt-6 w-full py-2 rounded-xl font-semibold bg-[rgb(248,144,22)] text-black hover:bg-white hover:scale-105"
|
||||
onClick={handleCreateGame}
|
||||
>
|
||||
Confirm & Create Bet
|
||||
Confirm & Create Game
|
||||
</button>
|
||||
</>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -6,18 +6,12 @@ import { FaTelegram, FaXTwitter } from "react-icons/fa6";
|
|||
import { useState } from "react";
|
||||
import PrivyButton from "./PrivyButton";
|
||||
import { URL_TELEGRAM, URL_TWITTER, URL_WHITEPAPER } from "@/shared/constants";
|
||||
import SupportModal from "./SupportModal";
|
||||
|
||||
export default function Header() {
|
||||
const [isDrawerOpen, setIsDrawerOpen] = useState(false);
|
||||
const [showSupportModal, setShowSupportModal] = useState(false);
|
||||
|
||||
// Close modal when clicking outside
|
||||
const handleModalClick = (e: React.MouseEvent) => {
|
||||
if (e.target === e.currentTarget) {
|
||||
setShowSupportModal(false);
|
||||
}
|
||||
};
|
||||
|
||||
// Toggle the nav drawer
|
||||
const toggleDrawer = () => {
|
||||
setIsDrawerOpen(!isDrawerOpen);
|
||||
|
|
@ -28,7 +22,7 @@ export default function Header() {
|
|||
<header className="w-full bg-[rgb(22,22,22)] shadow-md h-26">
|
||||
<div className="container mx-auto flex items-center justify-between px-3 h-full max-w-screen-xl w-full">
|
||||
{/* Logo */}
|
||||
<div className="flex items-center">
|
||||
<div className="flex items-center pr-15">
|
||||
<Image
|
||||
src="/duelfiassets/logo.png"
|
||||
alt="Logo"
|
||||
|
|
@ -55,74 +49,6 @@ export default function Header() {
|
|||
>
|
||||
Support
|
||||
</button>
|
||||
|
||||
{showSupportModal && (
|
||||
<div
|
||||
className="fixed inset-0 bg-black/70 flex justify-center items-center z-50"
|
||||
onClick={handleModalClick}
|
||||
>
|
||||
<div className="bg-[rgb(30,30,30)] text-white w-full max-w-lg p-6 rounded-2xl shadow-lg space-y-6 transform transition-all duration-300 ease-out translate-y-0 opacity-100">
|
||||
<div className="flex justify-between items-center">
|
||||
<h2 className="text-2xl font-bold">Support</h2>
|
||||
<button
|
||||
onClick={() => setShowSupportModal(false)}
|
||||
className="text-gray-400 hover:text-white"
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" className="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="space-y-4">
|
||||
<div>
|
||||
<h3 className="text-lg font-semibold">Looking for support?</h3>
|
||||
<p className="text-gray-300">
|
||||
Join our{" "}
|
||||
<a
|
||||
href="https://t.me/duelfidotio"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-[rgb(248,144,22)] hover:underline"
|
||||
>
|
||||
Telegram group
|
||||
</a>{" "}
|
||||
— our mods and community are always happy to help!
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3 className="text-lg font-semibold">Interested in a collaboration or partnership?</h3>
|
||||
<p className="text-gray-300 mb-4">Fill out the form below and we'll get back to you as soon as possible.</p>
|
||||
|
||||
<form className="space-y-4">
|
||||
<input
|
||||
type="email"
|
||||
placeholder="Email"
|
||||
className="w-full bg-[rgb(10,10,10)] text-white p-2 rounded-md border border-gray-700"
|
||||
/>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Subject"
|
||||
className="w-full bg-[rgb(10,10,10)] text-white p-2 rounded-md border border-gray-700"
|
||||
/>
|
||||
<textarea
|
||||
placeholder="Message"
|
||||
rows={4}
|
||||
className="w-full bg-[rgb(10,10,10)] text-white p-2 rounded-md border border-gray-700"
|
||||
/>
|
||||
<button
|
||||
type="submit"
|
||||
className="w-full bg-[rgb(248,144,22)] hover:bg-orange-400 text-black font-semibold px-4 py-2 rounded-md transition duration-500 hover:scale-105"
|
||||
>
|
||||
Submit
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</nav>
|
||||
|
||||
{/* Spacer (for centering) */}
|
||||
|
|
@ -157,18 +83,12 @@ export default function Header() {
|
|||
/>
|
||||
</a>
|
||||
|
||||
{/* Login Button
|
||||
<button className="px-15 py-3 bg-[rgb(248,144,22)] text-black font-bold rounded-lg transition-transform duration-300 hover:scale-115 hover:bg-white hover:text-[rgb(248,144,22)]">
|
||||
Connected
|
||||
</button>*/}
|
||||
<PrivyButton></PrivyButton>
|
||||
</div>
|
||||
|
||||
{/* Mobile-only view (Logo & Login) */}
|
||||
<div className="flex md:hidden items-center ">
|
||||
<div className="scale-[0.8]">
|
||||
<div className="flex md:hidden items-center scale-80 ">
|
||||
<PrivyButton></PrivyButton>
|
||||
</div>
|
||||
|
||||
<button
|
||||
onClick={toggleDrawer}
|
||||
|
|
@ -260,6 +180,7 @@ export default function Header() {
|
|||
</div>
|
||||
)}
|
||||
</header>
|
||||
<SupportModal isOpen={showSupportModal} onClose={() => setShowSupportModal(false)} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,10 +36,10 @@ export function HowItWorksModal({ isOpen, onClose }: HowItWorksModalProps) {
|
|||
|
||||
<div className="space-y-4">
|
||||
{[
|
||||
{ step: "Connect Your Wallet", desc: "Start by linking your wallet securely." },
|
||||
{ step: "Create or Join Game", desc: "Pick a game and set a wager, or join an existing match." },
|
||||
{ step: "Place Your Bet", desc: "Confirm your wager and get ready to play." },
|
||||
{ step: "Claim Your Winnings", desc: "Win the game and collect your rewards instantly!" },
|
||||
{ step: "Sign In or Connect Your Wallet", desc: "Sign up with X, Google, or connect an existing wallet—your wallet is created instantly and securely with Privy." },
|
||||
{ step: "Create or Join a Game", desc: "Start your own match with your preferred entry amount, or join an existing one." },
|
||||
{ step: "Place Your Entry", desc: "Confirm it and get ready to play." },
|
||||
{ step: "Win & Get Paid", desc: "Win the game and your prize is automatically sent to your wallet." },
|
||||
].map(({ step, desc }, index) => (
|
||||
<div key={index}>
|
||||
<h3 className="text-[rgb(248,144,22)] font-bold text-lg">
|
||||
|
|
|
|||
|
|
@ -183,11 +183,11 @@ export default function YourGames({ bets }: GameModalProps) {
|
|||
></path>
|
||||
</svg>
|
||||
<h3 className="text-lg font-semibold">Processing...</h3>
|
||||
<p className="text-gray-400 text-sm mt-2">Joining the bet, please wait...</p>
|
||||
<p className="text-gray-400 text-sm mt-2">Joining the Game, please wait...</p>
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
<h2 className="text-xl font-bold mb-4">Are you sure to join this bet?</h2>
|
||||
<h2 className="text-xl font-bold mb-4">Are you sure to join this Game?</h2>
|
||||
<div className="flex gap-4 mb-4">
|
||||
<div className="w-1/2 relative h-48 overflow-hidden rounded-xl">
|
||||
<Image
|
||||
|
|
@ -214,7 +214,7 @@ export default function YourGames({ bets }: GameModalProps) {
|
|||
</>
|
||||
)}
|
||||
<div className="flex justify-between items-center">
|
||||
<span className="text-gray-400">Wager:</span>
|
||||
<span className="text-gray-400">Entry:</span>
|
||||
<span className="font-bold">{selectedBet.wager} SOL</span>
|
||||
</div>
|
||||
<div className="flex justify-between items-center">
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ export function PriceSelection({ selectedPrice, onSelect }: PriceSelectionProps)
|
|||
>
|
||||
<option>SOL</option>
|
||||
</select>
|
||||
<label className="block text-sm text-gray-300 font-mono mb-1">Enter Price (SOL)</label>
|
||||
<label className="block text-sm text-gray-300 font-mono mb-1">Entry Price (SOL)</label>
|
||||
<div className="flex items-center gap-2">
|
||||
<input
|
||||
type="number"
|
||||
|
|
|
|||
159
src/components/SupportModal.tsx
Normal file
159
src/components/SupportModal.tsx
Normal file
|
|
@ -0,0 +1,159 @@
|
|||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
|
||||
interface SupportModalProps {
|
||||
isOpen: boolean;
|
||||
onClose: () => void;
|
||||
}
|
||||
|
||||
interface FormData {
|
||||
email: string;
|
||||
subject: string;
|
||||
message: string;
|
||||
}
|
||||
|
||||
export default function SupportModal({ isOpen, onClose }: SupportModalProps) {
|
||||
const [formData, setFormData] = useState<FormData>({
|
||||
email: "",
|
||||
subject: "",
|
||||
message: ""
|
||||
});
|
||||
const [isSubmitting, setIsSubmitting] = useState(false);
|
||||
const [submitStatus, setSubmitStatus] = useState<"success" | "error" | null>(null);
|
||||
|
||||
if (!isOpen) return null;
|
||||
|
||||
const handleModalClick = (e: React.MouseEvent) => {
|
||||
if (e.target === e.currentTarget) {
|
||||
onClose();
|
||||
}
|
||||
};
|
||||
|
||||
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
|
||||
const { name, value } = e.target;
|
||||
setFormData(prev => ({
|
||||
...prev,
|
||||
[name]: value
|
||||
}));
|
||||
};
|
||||
|
||||
const handleSubmit = async (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
setIsSubmitting(true);
|
||||
setSubmitStatus(null);
|
||||
|
||||
try {
|
||||
const params = new URLSearchParams({
|
||||
email: formData.email,
|
||||
subject: formData.subject,
|
||||
message: formData.message
|
||||
});
|
||||
|
||||
const response = await fetch(`https://vps.playpoolstudios.com/duelfi/api/add_feedback.php?${params}`, {
|
||||
method: 'GET',
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
setSubmitStatus("success");
|
||||
setFormData({ email: "", subject: "", message: "" });
|
||||
setTimeout(() => {
|
||||
onClose();
|
||||
}, 2000);
|
||||
} else {
|
||||
setSubmitStatus("error");
|
||||
}
|
||||
} catch (error) {
|
||||
setSubmitStatus("error");
|
||||
} finally {
|
||||
setIsSubmitting(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
className="fixed inset-0 bg-black/70 flex justify-center items-center z-50"
|
||||
onClick={handleModalClick}
|
||||
>
|
||||
<div className="bg-[rgb(30,30,30)] text-white w-full max-w-lg p-6 rounded-2xl shadow-lg space-y-6 transform transition-all duration-300 ease-out translate-y-0 opacity-100">
|
||||
<div className="flex justify-between items-center">
|
||||
<h2 className="text-2xl font-bold">Support</h2>
|
||||
<button
|
||||
onClick={onClose}
|
||||
className="text-gray-400 hover:text-white"
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" className="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="space-y-4">
|
||||
<div>
|
||||
<h3 className="text-lg font-semibold">Looking for support?</h3>
|
||||
<p className="text-gray-300">
|
||||
Join our{" "}
|
||||
<a
|
||||
href="https://t.me/duelfidotio"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-[rgb(248,144,22)] hover:underline"
|
||||
>
|
||||
Telegram group
|
||||
</a>{" "}
|
||||
— our mods and community are always happy to help!
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3 className="text-lg font-semibold">Interested in a collaboration or partnership?</h3>
|
||||
<p className="text-gray-300 mb-4">Fill out the form below and we'll get back to you as soon as possible.</p>
|
||||
|
||||
<form onSubmit={handleSubmit} className="space-y-4">
|
||||
<input
|
||||
type="email"
|
||||
name="email"
|
||||
placeholder="Email"
|
||||
value={formData.email}
|
||||
onChange={handleInputChange}
|
||||
required
|
||||
className="w-full bg-[rgb(10,10,10)] text-white p-2 rounded-md border border-gray-700"
|
||||
/>
|
||||
<input
|
||||
type="text"
|
||||
name="subject"
|
||||
placeholder="Subject"
|
||||
value={formData.subject}
|
||||
onChange={handleInputChange}
|
||||
required
|
||||
className="w-full bg-[rgb(10,10,10)] text-white p-2 rounded-md border border-gray-700"
|
||||
/>
|
||||
<textarea
|
||||
name="message"
|
||||
placeholder="Message"
|
||||
value={formData.message}
|
||||
onChange={handleInputChange}
|
||||
rows={4}
|
||||
required
|
||||
className="w-full bg-[rgb(10,10,10)] text-white p-2 rounded-md border border-gray-700"
|
||||
/>
|
||||
<button
|
||||
type="submit"
|
||||
disabled={isSubmitting}
|
||||
className="w-full bg-[rgb(248,144,22)] hover:bg-orange-400 text-black font-semibold px-4 py-2 rounded-md transition duration-500 hover:scale-105 disabled:opacity-50 disabled:cursor-not-allowed"
|
||||
>
|
||||
{isSubmitting ? "Submitting..." : "Submit"}
|
||||
</button>
|
||||
{submitStatus === "success" && (
|
||||
<p className="text-green-500 text-center">Thank you for your message! We'll get back to you soon.</p>
|
||||
)}
|
||||
{submitStatus === "error" && (
|
||||
<p className="text-red-500 text-center">Something went wrong. Please try again later.</p>
|
||||
)}
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -78,10 +78,10 @@ export default function YourGames({bets}:GameModalProps) {
|
|||
|
||||
return (
|
||||
<section className="py-16 px-6">
|
||||
<h2 className="text-3xl font-bold text-white mb-6">Your Games</h2>
|
||||
<h2 className="text-3xl font-bold text-white mb-6">Your Game</h2>
|
||||
|
||||
{loading ? (
|
||||
<p className="text-gray-400">Loading your games...</p>
|
||||
<p className="text-gray-400">Loading...</p>
|
||||
) : myBets.length === 0 ? (
|
||||
<></>
|
||||
) : (
|
||||
|
|
@ -106,7 +106,7 @@ export default function YourGames({bets}:GameModalProps) {
|
|||
{/* Game Info */}
|
||||
<div className="mt-4 px-3 text-left">
|
||||
<h3 className="text-lg font-semibold text-white py-2">{game.name}</h3>
|
||||
<p className="text-xs text-gray-400 font-mono py-1">Wager</p>
|
||||
<p className="text-xs text-gray-400 font-mono py-1">Entry</p>
|
||||
<p className="text-xs text-white font-mono py-1">{bet.wager} SOL</p>
|
||||
</div>
|
||||
|
||||
|
|
@ -127,14 +127,14 @@ export default function YourGames({bets}:GameModalProps) {
|
|||
{selectedBet && !isProcessing && (
|
||||
<div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50">
|
||||
<div className="bg-[rgb(30,30,30)] text-white p-6 rounded-lg shadow-lg w-96">
|
||||
<h3 className="text-lg font-semibold mb-4">Close Bet</h3>
|
||||
<p className="mb-6">Are you sure you want to close this bet? You will receive your refund back to your wallet.</p>
|
||||
<h3 className="text-lg font-semibold mb-4">Close Game</h3>
|
||||
<p className="mb-6">Are you sure you want to close this Game? You will receive your refund back to your wallet.</p>
|
||||
<div className="flex justify-end space-x-4">
|
||||
<button className="px-4 py-2 bg-gray-600 rounded hover:bg-gray-700 hover:scale-105 transition-all duration-300" onClick={() => setSelectedBet(null)}>
|
||||
Cancel
|
||||
</button>
|
||||
<button className="px-4 py-2 bg-red-600 rounded hover:bg-red-700 hover:scale-105 transition-all duration-300" onClick={handleCloseBet}>
|
||||
Close Bet
|
||||
Close Game
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -150,7 +150,7 @@ export default function YourGames({bets}:GameModalProps) {
|
|||
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8v8H4z"></path>
|
||||
</svg>
|
||||
<h3 className="text-lg font-semibold">Processing...</h3>
|
||||
<p className="text-gray-400 text-sm mt-2">Please wait while we close your bet.</p>
|
||||
<p className="text-gray-400 text-sm mt-2">Please wait while we close your Game.</p>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ export const games = [
|
|||
},
|
||||
{
|
||||
id: "snakes",
|
||||
name: "Venom Trails",
|
||||
name: "Venom Trail",
|
||||
entryFee: "0.02 ETH",
|
||||
thumbnail: "/duelfiassets/Venom Trail Game Cover Illustration.png",
|
||||
isAvailable: false
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ export const fetchOpenBets = async (wallets: ConnectedSolanaWallet): Promise<Bet
|
|||
signAllTransactions: wallets.signAllTransactions,
|
||||
};
|
||||
const provider = new AnchorProvider(connection, wallet, {
|
||||
preflightCommitment: 'recent',
|
||||
preflightCommitment: CONFIRMATION_THRESHOLD,
|
||||
});
|
||||
|
||||
const program = new Program<Bets>(idl, provider);
|
||||
|
|
@ -27,7 +27,7 @@ export const fetchOpenBets = async (wallets: ConnectedSolanaWallet): Promise<Bet
|
|||
program.programId
|
||||
);
|
||||
// Fetch all open bet accounts
|
||||
const bet_list = await program.account.betsList.fetch(bet_list_pda, 'recent');
|
||||
const bet_list = await program.account.betsList.fetch(bet_list_pda, CONFIRMATION_THRESHOLD);
|
||||
|
||||
// Extract required bet data
|
||||
const formattedBets = await Promise.all(
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user