Compare commits

..

3 Commits

Author SHA1 Message Date
1bb0a2be8a extract registration to a component 2024-05-08 08:36:20 -05:00
e826609f6e Error handling for user registration 2024-05-08 08:16:53 -05:00
63f3b9fa70 Render hidden card 2024-05-07 18:48:09 -05:00
4 changed files with 83 additions and 56 deletions

View File

@ -14,6 +14,9 @@ export function Card(props: {value: number}) {
let icon = null; let icon = null;
switch (cardType) { switch (cardType) {
case CardType.Hidden:
icon = <span class="inline-block absolute left-2 top-2 w-[2.75rem] h-[4.75rem] border-2 border-c-border-1" />;
break;
case CardType.Club: case CardType.Club:
icon = <ClubIcon class="absolute bottom-1 right-1" fill={textColor} />; icon = <ClubIcon class="absolute bottom-1 right-1" fill={textColor} />;
break; break;

View File

@ -2,13 +2,13 @@ import { A } from "@solidjs/router";
import { createSignal, onMount, Show } from "solid-js"; import { createSignal, onMount, Show } from "solid-js";
import { backend, UserInfo } from "../utils"; import { backend, UserInfo } from "../utils";
import { Card } from "../components/Card"; import { Card } from "../components/Card";
import { AxiosError } from "axios";
const userIdKey = "UserId";
const usernameKey = "Username";
export function Index() { export function Index() {
const [loading, setLoading] = createSignal(false); const [userInfo, setUserInfo] = createSignal<UserInfo | null>(null);
const [userInfo] = createSignal<UserInfo | null>(null);
const [error, setError] = createSignal("");
const [username, setUsername] = createSignal("");
onMount(() => { onMount(() => {
// attempt to get userinfo from localstorage // attempt to get userinfo from localstorage
@ -16,29 +16,6 @@ export function Index() {
console.log("validating userinfo in localstorage"); console.log("validating userinfo in localstorage");
}); });
// Register a user in the backend, get their user_id, store it in localStorage.
const registerUser = async(ev: Event) => {
ev.preventDefault();
setLoading(true);
setError("");
try {
const user = username();
if (user.length === 0) {
throw new Error("Username is empty");
}
const response = await backend.get("/register");
console.log(response.data);
} catch (_e) {
const e = _e as Error;
setError(e.message);
} finally {
setLoading(false);
}
};
return ( return (
<div class="w-[40rem] mx-auto bg-c-bg-2 my-4 p-4 rounded shadow-md"> <div class="w-[40rem] mx-auto bg-c-bg-2 my-4 p-4 rounded shadow-md">
<h1 class="text-c-on-bg text-3xl font-black pb-4"> <h1 class="text-c-on-bg text-3xl font-black pb-4">
@ -49,34 +26,10 @@ export function Index() {
<div class="py-4"> <div class="py-4">
<h2 class="text-xl py-2 font-black">Play:</h2> <h2 class="text-xl py-2 font-black">Play:</h2>
<Show when={userInfo() === null}> <Show when={userInfo() === null}>
<form onSubmit={(ev) => registerUser(ev)}> <UserRegistration setUserInfo={setUserInfo} />
<label for="index-register-name">Enter your name (3 to 20 letters, numbers or undescores):</label>
<br />
<input
id="index-register-name"
class="inline-block px-2 py-1 my-2 border border-c-border-1 rounded-md bg-c-bg text-c-on-bg"
type="text"
value={username()}
required
pattern="[a-zA-Z0-9_]{3,20}"
onInput={(ev) => setUsername(ev.target.value)}
/>
<br />
<button
class="inline-block py-2 px-4 rounded bg-teal-500 dark:bg-teal-700 text-white
disabled:opacity-50 disabled:cursor-not-allowed"
type="submit"
disabled={loading()}
>
Register
</button>
</form>
</Show> </Show>
<Show when={userInfo() !== null}> <Show when={userInfo() !== null}>
<p>:D</p> <p>:D (user registered)</p>
</Show>
<Show when={error() !== ""}>
<p class="bg-red-700 text-red-50 inline-block py-1 px-2 my-2 rounded">Error: {error()}</p>
</Show> </Show>
</div> </div>
<hr /> <hr />
@ -100,9 +53,74 @@ export function Index() {
<Card value={4} /> <Card value={4} />
</div> </div>
<div class="inline-block rotate-6 -translate-x-2 translate-y-1 hover:-translate-y-2 transition-transform"> <div class="inline-block rotate-6 -translate-x-2 translate-y-1 hover:-translate-y-2 transition-transform">
<Card value={36} /> <Card value={37} />
</div> </div>
</div> </div>
</div> </div>
); );
} }
function UserRegistration(props: {setUserInfo: (u: UserInfo) => void}) {
const [loading, setLoading] = createSignal(false);
const [error, setError] = createSignal("");
const [username, setUsername] = createSignal("");
// Register a user in the backend, get their user_id, store it in localStorage.
const registerUser = async(ev: Event) => {
ev.preventDefault();
setLoading(true);
setError("");
try {
const user = username();
if (user.length === 0) {
throw new Error("Username is empty");
}
const response = await backend.get(`/register?username=${user}`);
props.setUserInfo(response.data);
localStorage.setItem(userIdKey, response.data.UserId);
localStorage.setItem(usernameKey, response.data.Username);
} catch (_e) {
const e = _e as AxiosError<{error: string}>;
if (e.response && e.response.data && e.response.data.error) {
setError(e.response.data.error);
} else {
setError(e.message);
}
} finally {
setLoading(false);
}
};
return (
<form onSubmit={(ev) => registerUser(ev)}>
<label for="index-register-name">Enter your name (3 to 20 letters, numbers or undescores):</label>
<br />
<input
id="index-register-name"
class="inline-block px-2 py-1 my-2 border border-c-border-1 rounded-md bg-c-bg text-c-on-bg"
type="text"
value={username()}
required
pattern="[a-zA-Z0-9_]{3,20}"
onInput={(ev) => setUsername(ev.target.value)}
/>
<br />
<button
class="inline-block py-2 px-4 rounded bg-teal-500 dark:bg-teal-700 text-white
disabled:opacity-50 disabled:cursor-not-allowed"
type="submit"
disabled={loading()}
>
Register
</button>
<Show when={error() !== ""}>
<p class="bg-red-700 text-red-50 inline-block py-1 px-2 my-2 rounded">Error: {error()}</p>
</Show>
</form>
);
}

View File

@ -1,5 +1,6 @@
export enum CardType { export enum CardType {
Hidden,
Club, Club,
Diamond, Diamond,
Heart, Heart,
@ -20,6 +21,8 @@ const tailwindCardColors: Array<[string, string]> = [
["var(--card-green-bg)", "var(--card-on-green-bg)"], ["var(--card-green-bg)", "var(--card-on-green-bg)"],
// blue // blue
["var(--card-blue-bg)", "var(--card-on-blue-bg)"], ["var(--card-blue-bg)", "var(--card-on-blue-bg)"],
// gray
["", ""],
]; ];
@ -30,6 +33,9 @@ const tailwindCardColors: Array<[string, string]> = [
* @returns The type of card and its value (A, 1, 2, etc), if any * @returns The type of card and its value (A, 1, 2, etc), if any
*/ */
export function intToCardType(value: number): [CardType, string, [string, string]] { export function intToCardType(value: number): [CardType, string, [string, string]] {
if (value === -1) {
return [CardType.Hidden, "", tailwindCardColors[4]];
}
switch ((value << 23) >>> 28) { switch ((value << 23) >>> 28) {
case 0: { case 0: {
const type = ((value & 1) === 1) ? CardType.Club : CardType.Spade; const type = ((value & 1) === 1) ? CardType.Club : CardType.Spade;

View File

@ -5,7 +5,7 @@ export const backend = axios.create({
}); });
export type UserInfo = { export type UserInfo = {
useruiid: number, UserId: number,
username: string, Username: string,
} }