From 5a809e59039e3304f657c01ffc15d09dc6107cf0 Mon Sep 17 00:00:00 2001 From: gibbyb Date: Tue, 23 Jul 2024 11:33:29 -0500 Subject: [PATCH] Add TV Mode --- src/app/layout.tsx | 9 +- src/app/page.tsx | 6 +- src/components/auth/client/Sign_In.tsx | 15 ++++ src/components/auth/client/Sign_Out.tsx | 30 +++++++ src/components/auth/{ => server}/Sign_In.tsx | 0 src/components/auth/{ => server}/Sign_Out.tsx | 2 +- src/components/context/TVModeContext.tsx | 32 +++++++ src/components/ui/Header.tsx | 53 +++++++---- src/components/ui/No_Session.tsx | 2 +- src/components/ui/TV_Toggle.tsx | 19 ++++ .../ui/{TechTable.tsx => Tech_Table.tsx} | 90 +++++++++---------- src/styles/globals.css | 11 +++ 12 files changed, 198 insertions(+), 71 deletions(-) create mode 100644 src/components/auth/client/Sign_In.tsx create mode 100644 src/components/auth/client/Sign_Out.tsx rename src/components/auth/{ => server}/Sign_In.tsx (100%) rename src/components/auth/{ => server}/Sign_Out.tsx (93%) create mode 100644 src/components/context/TVModeContext.tsx create mode 100644 src/components/ui/TV_Toggle.tsx rename src/components/ui/{TechTable.tsx => Tech_Table.tsx} (74%) diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 291b59c..39cdc4f 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -2,7 +2,7 @@ import "~/styles/globals.css"; import { Inter as FontSans } from "next/font/google"; import { cn } from "~/lib/utils"; import { SessionProvider } from "next-auth/react"; -import Sign_Out from "~/components/auth/Sign_Out"; +import { TVModeProvider } from "~/components/context/TVModeContext"; import { type Metadata } from "next"; export const metadata: Metadata = { @@ -43,10 +43,9 @@ export default function RootLayout({ fontSans.variable)} > -
- -
- {children} + + {children} +
diff --git a/src/app/page.tsx b/src/app/page.tsx index 36b3429..8b8bee1 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -3,7 +3,7 @@ import { auth } from "~/auth"; import No_Session from "~/components/ui/No_Session"; import Header from "~/components/ui/Header"; import { getEmployees } from "~/server/functions"; -import TechTable from "~/components/ui/TechTable"; +import Tech_Table from "~/components/ui/Tech_Table"; export default async function HomePage() { const session = await auth(); @@ -14,8 +14,8 @@ export default async function HomePage() { return (
-
- +
+
); } diff --git a/src/components/auth/client/Sign_In.tsx b/src/components/auth/client/Sign_In.tsx new file mode 100644 index 0000000..c7624ef --- /dev/null +++ b/src/components/auth/client/Sign_In.tsx @@ -0,0 +1,15 @@ +import { signIn } from "next-auth/react"; +import { Button } from "~/components/ui/shadcn/button"; + +export default function Sign_In() { + return ( + + ); +}; diff --git a/src/components/auth/client/Sign_Out.tsx b/src/components/auth/client/Sign_Out.tsx new file mode 100644 index 0000000..1e6db4c --- /dev/null +++ b/src/components/auth/client/Sign_Out.tsx @@ -0,0 +1,30 @@ +import { signOut } from "next-auth/react"; +import { useSession } from "next-auth/react"; +import Image from "next/image"; +import { Button } from "~/components/ui/shadcn/button"; + +export default function Sign_Out() { + const { data: session } = useSession(); + if (!session) { + return
; + } else { + const pfp = session?.user?.image ? session.user.image : "/images/default_user_pfp.png"; + return ( +
+ + +
+ ); + } +}; + + // diff --git a/src/components/auth/Sign_In.tsx b/src/components/auth/server/Sign_In.tsx similarity index 100% rename from src/components/auth/Sign_In.tsx rename to src/components/auth/server/Sign_In.tsx diff --git a/src/components/auth/Sign_Out.tsx b/src/components/auth/server/Sign_Out.tsx similarity index 93% rename from src/components/auth/Sign_Out.tsx rename to src/components/auth/server/Sign_Out.tsx index e9f4aae..846c912 100644 --- a/src/components/auth/Sign_Out.tsx +++ b/src/components/auth/server/Sign_Out.tsx @@ -10,7 +10,7 @@ export default async function Sign_Out() { // Add User profile picture next to Sign Out button const pfp = session?.user?.image ? session.user.image : "/images/default_user_pfp.png"; return ( -
{ "use server" await signOut() diff --git a/src/components/context/TVModeContext.tsx b/src/components/context/TVModeContext.tsx new file mode 100644 index 0000000..97abc76 --- /dev/null +++ b/src/components/context/TVModeContext.tsx @@ -0,0 +1,32 @@ +"use client"; +import React, { createContext, useContext, useState } from 'react'; +import type { ReactNode } from 'react'; + +interface TVModeContextProps { + tvMode: boolean; + toggleTVMode: () => void; +} + +const TVModeContext = createContext(undefined); + +export const TVModeProvider = ({ children }: { children: ReactNode }) => { + const [tvMode, setTVMode] = useState(false); + + const toggleTVMode = () => { + setTVMode((prev) => !prev); + }; + + return ( + + {children} + + ); +}; + +export const useTVMode = () => { + const context = useContext(TVModeContext); + if (!context) { + throw new Error('useTVMode must be used within a TVModeProvider'); + } + return context; +}; diff --git a/src/components/ui/Header.tsx b/src/components/ui/Header.tsx index f5fb8da..47109e3 100644 --- a/src/components/ui/Header.tsx +++ b/src/components/ui/Header.tsx @@ -1,20 +1,41 @@ +"use client"; import Image from "next/image"; +import Sign_Out from "~/components/auth/client/Sign_Out"; +import TV_Toggle from "~/components/ui/TV_Toggle"; +import { useTVMode } from "~/components/context/TVModeContext"; export default function Header() { - return ( -
-
- Tech Tracker Logo -

- Tech Tracker -

-
-
- ); + const { tvMode } = useTVMode(); + if (tvMode) { + return ( +
+
+ < TV_Toggle /> +
+
+ ); + } else { + return ( +
+
+
+ < TV_Toggle /> + < Sign_Out /> +
+
+
+ Tech Tracker Logo +

+ Tech Tracker +

+
+
+ ); + } }; diff --git a/src/components/ui/No_Session.tsx b/src/components/ui/No_Session.tsx index 0d34da6..b3fde77 100644 --- a/src/components/ui/No_Session.tsx +++ b/src/components/ui/No_Session.tsx @@ -1,6 +1,6 @@ import Link from "next/link"; import Image from "next/image"; -import Sign_In from "~/components/auth/Sign_In"; +import Sign_In from "~/components/auth/server/Sign_In"; import Header from "~/components/ui/Header"; export default function No_Session() { diff --git a/src/components/ui/TV_Toggle.tsx b/src/components/ui/TV_Toggle.tsx new file mode 100644 index 0000000..53b66ac --- /dev/null +++ b/src/components/ui/TV_Toggle.tsx @@ -0,0 +1,19 @@ +"use client"; +import { Switch } from "~/components/ui/shadcn/switch"; +import { useTVMode } from "~/components/context/TVModeContext"; +import { useSession } from "next-auth/react"; + +export default function TV_Toggle() { + const { tvMode, toggleTVMode } = useTVMode(); + const { data: session } = useSession(); + if (!session) return
; + return ( + + ); +} diff --git a/src/components/ui/TechTable.tsx b/src/components/ui/Tech_Table.tsx similarity index 74% rename from src/components/ui/TechTable.tsx rename to src/components/ui/Tech_Table.tsx index c620262..a501c1b 100644 --- a/src/components/ui/TechTable.tsx +++ b/src/components/ui/Tech_Table.tsx @@ -1,7 +1,8 @@ -'use client'; +"use client"; import { useState, useEffect, useCallback } from 'react'; import { useSession } from "next-auth/react"; import Loading from "~/components/ui/Loading"; +import { useTVMode } from "~/components/context/TVModeContext"; // Define the Employee interface to match data fetched on the server interface Employee { @@ -11,8 +12,9 @@ interface Employee { updatedAt: Date; } -export default function TechTable({ employees }: { employees: Employee[] }) { +export default function Tech_Table({ employees }: { employees: Employee[] }) { const { data: session, status } = useSession(); + const { tvMode } = useTVMode(); const [loading, setLoading] = useState(true); const [selectedIds, setSelectedIds] = useState([]); const [selectAll, setSelectAll] = useState(false); @@ -34,7 +36,7 @@ export default function TechTable({ employees }: { employees: Employee[] }) { alert("You must be signed in to update status."); return; } - // If no employee is selected and status is not empty + if (selectedIds.length === 0 && employeeStatus.trim() !== '') { const cur_user = employees.find(employee => employee.name === session.user?.name); if (cur_user) { @@ -57,6 +59,7 @@ export default function TechTable({ employees }: { employees: Employee[] }) { body: JSON.stringify({ employeeIds: selectedIds, newStatus: employeeStatus }), }); } + const updatedEmployees = await fetch_employees(); setEmployeeData(updatedEmployees); setSelectedIds([]); @@ -88,11 +91,9 @@ export default function TechTable({ employees }: { employees: Employee[] }) { const handleKeyDown = async (e: React.KeyboardEvent) => { if (e.key === 'Enter') { await update_status(); - // if key is i then focus text input } }; - // Format time for display const formatTime = (timestamp: Date) => { const date = new Date(timestamp); const time = date.toLocaleTimeString('en-US', { @@ -104,41 +105,37 @@ export default function TechTable({ employees }: { employees: Employee[] }) { return `${time} - ${month} ${day}`; }; - // Loading bar while we wait for auth useEffect(() => { if (status !== "loading") { setLoading(false); } - }, [status]); + }, [status]); - // Refresh employee data if needed after state updates useEffect(() => { setEmployeeData(employees); }, [employees]); - // Fetch employees from the server every 10 seconds useEffect(() => { const fetchAndUpdateEmployees = async () => { const updatedEmployees = await fetch_employees(); setEmployeeData(updatedEmployees); }; - fetchAndUpdateEmployees() - .catch((error) => { + + fetchAndUpdateEmployees().catch((error) => { console.error('Error fetching employees:', error); }); + const intervalId = setInterval(() => { (async () => { await fetchAndUpdateEmployees(); - })() - .catch((error) => { + })().catch((error) => { console.error('Error fetching employees:', error); }); - }, 10000); // Poll every 10 seconds - - return () => clearInterval(intervalId); // Clear interval on component unmount + }, 10000); + + return () => clearInterval(intervalId); }, [fetch_employees]); - // Handle checkbox changes useEffect(() => { if (selectedIds.length === employeeData.length && employeeData.length > 0) { setSelectAll(true); @@ -150,10 +147,10 @@ export default function TechTable({ employees }: { employees: Employee[] }) { if (loading) return ; else { return ( -
- - +
+
+ {employeeData.map((employee) => ( -
@@ -195,28 +193,30 @@ export default function TechTable({ employees }: { employees: Employee[] }) { ))}
-
- - -
+ {!tvMode && ( +
+ + +
+ )}
); } diff --git a/src/styles/globals.css b/src/styles/globals.css index b9807fc..bb4b31c 100644 --- a/src/styles/globals.css +++ b/src/styles/globals.css @@ -119,3 +119,14 @@ font-size:18px; } } + +.content-fullscreen { + width: 100vw; + height: 100vh; + overflow: hidden; +} + +.techtable-fullscreen { + width: 100%; + height: 100%; +}