From 3f822f353f3ee79a33573d3643138767dc4eac49 Mon Sep 17 00:00:00 2001 From: EdiFarcas Date: Wed, 30 Apr 2025 15:05:01 +0300 Subject: [PATCH] Update homepage, giveaway creation and view update. --- src/app/admin/AdminClient.tsx | 15 ++- src/app/admin/AdminServer.tsx | 2 +- src/app/api/admin/create-giveaway/route.ts | 3 +- src/app/api/admin/update-coins/route.ts | 21 ---- src/app/giveaways/page.tsx | 30 ++++- src/app/page.tsx | 137 +++++++++++---------- src/components/GiveawayCard.tsx | 2 +- 7 files changed, 109 insertions(+), 101 deletions(-) delete mode 100644 src/app/api/admin/update-coins/route.ts diff --git a/src/app/admin/AdminClient.tsx b/src/app/admin/AdminClient.tsx index b917863..42c8212 100644 --- a/src/app/admin/AdminClient.tsx +++ b/src/app/admin/AdminClient.tsx @@ -8,7 +8,15 @@ interface AdminClientProps { } export default function AdminClient({ email }: AdminClientProps) { - const [giveaway, setGiveaway] = useState({ title: "", description: "", value: 0, prize: "", duration: 0, endsAt: 0 }); + const [giveaway, setGiveaway] = useState({ + title: "", + description: "", + value: 0, + prize: "", + entryCost: 70000000, + duration: 0, + endsAt: new Date(Date.now() + 24 * 60 * 60 * 1000).getTime() // Set to tomorrow + }); const [youtube_url, setYoutubeUrl] = useState(""); const [coin_value, setCoinValue] = useState(0); @@ -20,7 +28,8 @@ export default function AdminClient({ email }: AdminClientProps) { }); if (response.ok) { alert("Giveaway created successfully!"); - setGiveaway({ title: "", description: "", value: 0, prize: "", duration: 0, endsAt: 0 }); // Reset form + + setGiveaway({ title: "", description: "", value: 0, prize: "", entryCost: 70000000, duration: 0, endsAt: new Date(Date.now() + 24 * 60 * 60 * 1000).getTime() }); // Reset form } else { const error = await response.json(); alert(`Failed to create giveaway: ${error.error}`); @@ -58,7 +67,7 @@ export default function AdminClient({ email }: AdminClientProps) { /> setGiveaway({ ...giveaway, value: Number(e.target.value) })} className="block w-full mt-2 p-2 border rounded bg-gray-700 text-gray-200" diff --git a/src/app/admin/AdminServer.tsx b/src/app/admin/AdminServer.tsx index 5bb2f44..443f027 100644 --- a/src/app/admin/AdminServer.tsx +++ b/src/app/admin/AdminServer.tsx @@ -79,7 +79,7 @@ const handleUpdateCoins = async (youtubeUrl: string, coinValue: number) => { // Continue with the next author } } - },{timeout: 60000}); // Set a timeout of 60 seconds for the transaction + },{timeout: 60000}); // Set a timeout of 60 seconds for the transaction (Modify as needed) console.log("Coins updated successfully for all authors."); diff --git a/src/app/api/admin/create-giveaway/route.ts b/src/app/api/admin/create-giveaway/route.ts index a98cd9e..5e3a3ba 100644 --- a/src/app/api/admin/create-giveaway/route.ts +++ b/src/app/api/admin/create-giveaway/route.ts @@ -3,7 +3,7 @@ import { db } from "@/lib/db"; export async function POST(req: Request) { const body = await req.json(); - const { title, description, value, prize, duration, endsAt } = body; + const { title, description, value, prize, duration, endsAt } = body; if (!title || !description || !prize || !value) { return NextResponse.json({ error: "Missing required fields" }, { status: 400 }); @@ -16,6 +16,7 @@ export async function POST(req: Request) { description, prize, value, + entryCost: value * 0.1, duration, endsAt: new Date(endsAt), }, diff --git a/src/app/api/admin/update-coins/route.ts b/src/app/api/admin/update-coins/route.ts deleted file mode 100644 index f2750fe..0000000 --- a/src/app/api/admin/update-coins/route.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { NextResponse } from "next/server"; -import { db } from "@/lib/db"; - -export async function POST(req: Request) { - const body = await req.json(); - const { userId, coins } = body; - - if (!userId || coins === undefined) { - return NextResponse.json({ error: "Missing required fields" }, { status: 400 }); - } - - try { - const user = await db.user.update({ - where: { id: userId }, - data: { coins }, - }); - return NextResponse.json(user); - } catch { - return NextResponse.json({ error: "Failed to update user coins" }, { status: 500 }); - } -} \ No newline at end of file diff --git a/src/app/giveaways/page.tsx b/src/app/giveaways/page.tsx index e106a53..7551f7e 100644 --- a/src/app/giveaways/page.tsx +++ b/src/app/giveaways/page.tsx @@ -18,23 +18,41 @@ export default async function GiveawaysPage() { title: true, description: true, prize: true, + endsAt: true, }, }); return (
-

Active Giveaways

-
- {giveaways.map((giveaway) => ( +

Active Giveaways

+
+ {giveaways.map((giveaway) => { + const remainingTime = Math.max( + 0, + new Date(giveaway.endsAt ?? 0).getTime() - Date.now() + ); + + const days = Math.floor(remainingTime / (1000 * 60 * 60 * 24)); + + const hours = Math.floor( + (remainingTime % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60) + ); + + const minutes = Math.floor( + (remainingTime % (1000 * 60 * 60)) / (1000 * 60) + ); + + return ( - ))} -
+ ); + })} +
); diff --git a/src/app/page.tsx b/src/app/page.tsx index a53a995..4ba63ea 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -2,120 +2,121 @@ import Image from "next/image"; export default function GiveawaySystem() { return ( -
+
{/* Header */}
-

- 🎁 Community Giveaway System + TCG Love Openings Logo +

+ 🎁 TCG Love Giveaway System

-

Revamped engagement-powered rewards system

+

Join the fun — earn coins, win cool cards!

{/* Coin System Section */} -
+
🪙 -

Coin System Overview

+

How Coins Work

-
    -
  • Earn coins by commenting on videos and other engagement
  • -
  • Coins serve dual purpose: -
      -
    • Eligibility requirement for giveaways
    • -
    • Weighted entries (1 coin = 1 ticket, with diminishing returns)
    • +
        +
      • Earn coins by: +
          +
        • Commenting on TCG Love Openings videos
        • +
        • Liking and subscribing
        • +
        • Engaging with the community
      • +
      • Coins = your gateway to exclusive giveaways!
      • +
      • More coins mean more chances to win — but with balance!
- {/* Weighted Lottery Section */} -
+ {/* Lottery Multiplier */} +
- 🧮 -

Weighted Lottery System

+ 🎲 +

Weighted Lottery

- +
-
-
- 1–100 coins - 1x multiplier -
-
- 101–200 coins - 0.5x multiplier -
-
- 201–300 coins - 0.25x multiplier -
-
- 301+ coins - 0.1x multiplier -
+
+ {[{ range: "1–100", mult: "1x", color: "text-yellow-600" }, + { range: "101–200", mult: "0.5x", color: "text-green-600" }, + { range: "201–300", mult: "0.25x", color: "text-blue-600" }, + { range: "301+", mult: "0.1x", color: "text-red-500" }] + .map((tier) => ( +
+ {tier.range} coins + {tier.mult} +
+ ))}
- -
-

Example Calculation

-

- User with 450 coins:
- 100 × 1 + 100 × 0.5 + 100 × 0.25 + 50 × 0.1 =
- 100 + 50 + 25 + 5 = 180 tickets +

+

🎯 Example

+

+ 450 coins =
+ 100×1 + 100×0.5 + 100×0.25 + 50×0.1 =
+ 180 tickets!

{/* Entry Requirements */} -
+
- 🔐 -

Entry Requirements

+ 🎟️ +

Giveaway Entry Requirements

- +
- - +
+ - - - + + + - - - + + + - - - - - - + - + + + + + + - +
Giveaway ValueMinimum CoinsCoins BurnedPrize TierMin. CoinsBurn (Optional)
$1–5
$1–5 card 500None
$10–251,000NoneNone
$50+$10–25 card1,000None
$50+ special set 2,000+Optional (e.g., 50 coins)+50 for extra entries
-
+

- 💡 Note: Coins are not spent to enter - minimum balance acts as eligibility requirement. - Optional burns for higher tiers provide bonus entry weight. + 📌 You keep your coins — they arent spent to enter! But optional burns can boost your odds.

- {/* Disclaimer */} -
-

System subject to change. See full rules for complete details.

+ {/* Footer */} +
+

⚠️ Subject to change. See full rules in description or Discord.

); -} \ No newline at end of file +} diff --git a/src/components/GiveawayCard.tsx b/src/components/GiveawayCard.tsx index 9f5e26d..931e05c 100644 --- a/src/components/GiveawayCard.tsx +++ b/src/components/GiveawayCard.tsx @@ -9,7 +9,7 @@ interface GiveawayCardProps { const GiveawayCard: React.FC = ({ title, description, imageUrl }) => { return (
- {title} + {/* {title} */}

{title}

{description}