Skip to content

Commit

Permalink
feat: add session list page and small improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
italux committed Sep 18, 2024
1 parent e282942 commit cd94577
Show file tree
Hide file tree
Showing 10 changed files with 512 additions and 66 deletions.
3 changes: 2 additions & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"extends": ["next/core-web-vitals", "next/typescript"],
"rules": {
"@typescript-eslint/no-explicit-any": "off"
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-unused-vars": "off"
}
}
1 change: 1 addition & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/app/sessions/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { SessionList } from "@/components/session-list";

export default function Page() {
return <SessionList />
}
108 changes: 92 additions & 16 deletions src/components/enter-code.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,57 @@
"use client";

import { useRef, useState } from 'react';
import { useRef, useState, useEffect } from "react";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
import { useRouter } from 'next/navigation';
import { useRouter } from "next/navigation";
import { db } from "@/firebase/firebaseConfig";
import { doc, getDoc } from "firebase/firestore";
import {
collection,
getDocs,
query,
where,
Timestamp,
doc,
getDoc,
} from "firebase/firestore";
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
import Link from 'next/link'; // Import Link from next/link
import Link from "next/link";

export function EnterCode() {
const router = useRouter();
const inputRefs = useRef<(HTMLInputElement | null)[]>([]);
const [errorMessage, setErrorMessage] = useState("");
const [sessionCount, setSessionCount] = useState<number | null>(null);
const [sessionAlert, setSessionAlert] = useState(false);

const handleInputChange = (index: number, event: React.ChangeEvent<HTMLInputElement>) => {
// Fetch session count
useEffect(() => {
async function fetchSessionCount() {
try {
const sessionsCollection = collection(db, "sessions");
const now = Timestamp.now();
const sessionsQuery = query(
sessionsCollection,
where("expiresAt", ">", now)
);
const sessionsSnapshot = await getDocs(sessionsQuery);
setSessionCount(sessionsSnapshot.size);
setSessionAlert(true); // Set the alert to show after fetching data
// setTimeout(() => setSessionAlert(false), 5000);
} catch (error) {
console.error("Error fetching sessions count:", error);
setSessionCount(null);
}
}

fetchSessionCount();
}, []);

// Handle input change in the session code inputs
const handleInputChange = (
index: number,
event: React.ChangeEvent<HTMLInputElement>
) => {
const value = event.target.value.toUpperCase();
event.target.value = value;

Expand All @@ -28,11 +65,12 @@ export function EnterCode() {
}
};

// Handle paste event for the session code
const handlePaste = (event: React.ClipboardEvent<HTMLInputElement>) => {
const paste = event.clipboardData.getData('text').toUpperCase();
const paste = event.clipboardData.getData("text").toUpperCase();
const regex = /^[A-Z2-9]{6}$/; // Matches 6 characters excluding ambiguous ones
if (regex.test(paste)) {
paste.split('').forEach((char, index) => {
paste.split("").forEach((char, index) => {
if (inputRefs.current[index]) {
inputRefs.current[index]!.value = char;
}
Expand All @@ -42,17 +80,20 @@ export function EnterCode() {
event.preventDefault();
};

// Handle form submission
const handleSubmit = async (event: React.FormEvent) => {
event.preventDefault();
setErrorMessage(""); // Reset error message

// Get the entered code
const code = inputRefs.current.map(input => input?.value).join('');
const code = inputRefs.current.map((input) => input?.value).join("");

// Validate code format
const codeRegex = /^[A-Z2-9]{6}$/;
if (!codeRegex.test(code)) {
setErrorMessage("Invalid code format. Please enter a valid 6-character code.");
setErrorMessage(
"Invalid code format. Please enter a valid 6-character code."
);
return;
}

Expand All @@ -64,7 +105,9 @@ export function EnterCode() {
// Redirect to the session page
router.push(`/session/${code}`);
} else {
setErrorMessage("Session not found. Please check the code and try again.");
setErrorMessage(
"Session not found. Please check the code and try again."
);
}
} catch (error) {
console.error("Error checking session: ", error);
Expand All @@ -74,19 +117,46 @@ export function EnterCode() {

return (
<div className="flex flex-col items-center justify-center h-screen bg-background">
{/* Move the alert to the top of the page */}
{sessionAlert && sessionCount !== null && (
<div className="w-full max-w-lg absolute top-0 p-4">
<Link href="/sessions" passHref>
<div className="w-full absolute top-0 p-4 cursor-pointer">
<Alert
variant="default"
className="bg-primary text-primary-foreground transition-colors duration-200 cursor-pointer"
>
<AlertTitle>
{sessionCount === 0
? "There are currently no ongoing sessions."
: `${sessionCount} Ongoing Session${
sessionCount === 1 ? "" : "s"
}`}
</AlertTitle>
<AlertDescription>Click to view</AlertDescription>
</Alert>
</div>
</Link>
</div>
)}

<div className="max-w-md w-full space-y-4 p-6 rounded-lg shadow-lg bg-card">
<div className="text-center space-y-2">
<h1 className="text-3xl font-bold">Enter Session Code</h1>
<p className="text-muted-foreground">
Please enter the 6-character session code to join.
</p>
</div>

{/* Error message for invalid session code */}
{errorMessage && (
<Alert variant="destructive">
<Alert variant="default">
<AlertTitle>Error</AlertTitle>
<AlertDescription>{errorMessage}</AlertDescription>
</Alert>
)}

{/* Session code input form */}
<form className="space-y-4" onSubmit={handleSubmit}>
<div className="flex items-center justify-center gap-2">
{Array.from({ length: 6 }, (_, index) => (
Expand All @@ -98,11 +168,17 @@ export function EnterCode() {
placeholder=""
className="w-12 h-12 text-center text-2xl tracking-widest"
required
ref={(el: HTMLInputElement | null) => { inputRefs.current[index] = el; }}
ref={(el: HTMLInputElement | null) => {
inputRefs.current[index] = el;
}}
onChange={(event) => handleInputChange(index, event)}
onPaste={index === 0 ? handlePaste : undefined}
onKeyDown={(event) => {
if (event.key === "Backspace" && !event.currentTarget.value && index > 0) {
if (
event.key === "Backspace" &&
!event.currentTarget.value &&
index > 0
) {
inputRefs.current[index - 1]?.focus();
}
}}
Expand All @@ -113,13 +189,13 @@ export function EnterCode() {
Submit
</Button>
</form>
{/* Added the new link here */}

<div className="text-center mt-4">
<Link href="/generate" className="text-blue-500 hover:underline">
<Link href="/sessions" className="text-blue-500 hover:underline">
I don&apos;t have a code
</Link>
</div>
</div>
</div>
);
}
}
Loading

0 comments on commit cd94577

Please sign in to comment.