gw/web/src/pages/Home/index.tsx
2024-12-26 11:00:16 +00:00

144 lines
No EOL
5.3 KiB
TypeScript

import { useEffect, useState } from 'preact/hooks';
type EntryBody = {
err: boolean;
referral: string;
key: string;
}
export const Home = () => {
const [referral, setReferral] = useState('');
const [entryBody, setEntryBody] = useState<EntryBody | null>({
err: true,
referral: '',
key: ''
});
const [timeLeft, setTimeLeft] = useState<string>('...');
useEffect(() => {
console.log('Referral:', referral);
}, [referral]);
const entry = async () => {
let res = await fetch("http://localhost:8080/entry", {
method: 'GET',
headers: { referral }
})
if (!res.ok) {
console.error('Error:', res.status);
return
}
let body: EntryBody = await res.json();
if (body.err) {
console.error('Error:', body.referral);
window.location.href = '/error';
return
}
console.log('Entry:', body);
setEntryBody(body);
setReferral('');
}
const eventDateCET = new Date('2025-01-01T00:00:00Z');
const userTime = new Intl.DateTimeFormat(undefined, {
year: 'numeric',
month: 'long',
day: 'numeric',
hour: '2-digit',
minute: '2-digit',
timeZoneName: 'short'
}).format(eventDateCET);
const getTimeLeft = (date: Date) => {
const now = new Date();
const diff = date.getTime() - now.getTime();
const days = Math.floor(diff / (1000 * 60 * 60 * 24));
const hours = Math.floor(diff / (1000 * 60 * 60) % 24);
const minutes = Math.floor(diff / (1000 * 60) % 60);
const seconds = Math.floor(diff / 1000 % 60);
let s = "";
if (days > 0) s += days + "d ";
if (hours > 0) s += hours + "h ";
if (minutes > 0) s += minutes + "m ";
if (seconds > 0) s += seconds + "s";
if (s === "") s = "the time is upon us.";
else s += " remaining.";
return s;
}
useEffect(() => {
const interval = setInterval(() => {
setTimeLeft(getTimeLeft(eventDateCET));
}, 1000);
return () => clearInterval(interval);
}, []);
return (
<div class="flex flex-col gap-6 w-full h-full justify-center items-center">
<h1 class="text-6xl font-bold animate-pulse">???</h1>
<p>{timeLeft}</p>
<span>
<p class="opacity-100 hover:opacity-75 transition-opacity">
Referral:
</p>
<div class="flex gap-2">
<input
type="text"
value={referral}
onInput={(e) => setReferral(e.currentTarget.value)}
class="bg-black text-green-500 border-green-500 border-2 px-2 hover:bg-green-500 hover:text-black active:bg-green-500 active:text-black transition-colors"
/>
<button
onClick={async () => await entry()}
class="bg-green-500 text-black hover:bg-black hover:text-green-500 transition-colors px-4"
>
Submit
</button>
</div>
</span>
{
!entryBody.err ? (
<div class="flex flex-col gap-1.5 mt-3 justify-center items-center">
<p class="text-green-700">tip: click to copy.</p>
<h2 onClick={() => navigator.clipboard.writeText(entryBody?.key)}>Key: <code class="cursor-pointer bg-green-800 hover:bg-green-900 active:bg-green-700 transition-colors py-1 px-2 rounded-lg text-white">{entryBody?.key}</code></h2>
<h2 onClick={() => navigator.clipboard.writeText(entryBody?.referral)}>Referral: <code class="cursor-pointer bg-green-800 hover:bg-green-900 active:bg-green-700 transition-colors py-1 px-2 rounded-lg text-white">{entryBody?.referral}</code></h2>
<p class="text-green-700">good luck. keep note of these, if you lose them, you can't reroll.</p>
</div>
) : (
<div class="w-2/3 text-center flex flex-col gap-2">
<div>
<b>What is this?</b>
<p>At exactly {userTime} (00:00 CET on 1 Jan), the system will choose a random entry. Their referral key shall be publicly
displayed on this page. The person associated with this referral key shall contact us with their private key.
They shall win a little prize. To have one's entry weigh more than the rest, one shall have to spread their
referral key amongst people. Every referral shall increase their chance of getting selected.
</p>
</div>
<div>
<b>How does one enter?</b>
<p>One needs a referral key to enter.</p>
</div>
</div>
)
}
</div>
)
};