diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 349f8c4..1917787 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -5,6 +5,7 @@ import Hosting from './components/Hosting'; import InitialSetup from './components/InitialSetup'; import Program from './components/Program'; import Snowflakes from './components/Snowflakes'; +import { FullScreenLoading } from './components/Loading'; function App() { const [isNavOpen, setIsNavOpen] = useState(false); @@ -15,6 +16,7 @@ function App() { return ( <> + diff --git a/frontend/src/components/InitialSetup.tsx b/frontend/src/components/InitialSetup.tsx index e8e1d70..d6fb81f 100644 --- a/frontend/src/components/InitialSetup.tsx +++ b/frontend/src/components/InitialSetup.tsx @@ -4,6 +4,7 @@ import { GUESTS } from '../constants/constants'; import useFetchUser from '../utils/fetchUser'; // Import your custom hook import { useNotification } from '../NotificationContext'; import ApologyMessage from './Attendance'; +import {Loading} from './Loading'; const InitialSetup = () => { const [cookie, setCookie] = useCookies(); @@ -14,7 +15,7 @@ const InitialSetup = () => { const [isPasswordSet, setIsPasswordSet] = useState(false); // To track if password is set const [userAttendance, setUserAttendance] = useState(null); - const { userSet, passwordCreate, signUser, validToken, getAttendance } = useFetchUser(); // Destructure functions from the hook + const { userSet, passwordCreate, signUser, validToken, getAttendance, isLoading } = useFetchUser(); // Destructure functions from the hook const notify = useNotification(); const checkUserPassword = async (name: string) => { @@ -76,6 +77,14 @@ const InitialSetup = () => { ) } + if (isLoading) { + return ( +
+ +
+ ) + } + return (

Выбери себя

diff --git a/frontend/src/components/Loading.css b/frontend/src/components/Loading.css new file mode 100644 index 0000000..aec122a --- /dev/null +++ b/frontend/src/components/Loading.css @@ -0,0 +1,29 @@ +.spinner { + font-size: 100px; /* Adjust size as needed */ + animation: spin 2s linear infinite; /* Spin animation */ + position: fixed; /* Keep the snowflake in a fixed position */ + top: 50%; /* Adjust vertical position */ + left: 50%; /* Center horizontally */ + transform: translateX(-50%); /* Center the snowflake */ + z-index: 10000; /* Ensure it's above the full-screen loading */ +} + +/* Keyframes for spinning */ +@keyframes spin { + 0% { transform: translateX(-50%) rotate(0deg); } + 100% { transform: translateX(-50%) rotate(360deg); } +} + + +.full-screen { + display: flex; /* Use flexbox for centering */ + align-items: center; /* Center vertically */ + justify-content: center; /* Center horizontally */ + height: 100vh; /* Full viewport height */ + width: 100vw; /* Full viewport width */ + background-color: rgba(4, 0, 0); /* Semi-transparent background */ + position: fixed; /* Fix it in the viewport */ + top: 0; + left: 0; + z-index: 9999; /* Ensure it's above other content */ +} \ No newline at end of file diff --git a/frontend/src/components/Loading.tsx b/frontend/src/components/Loading.tsx new file mode 100644 index 0000000..13bab4e --- /dev/null +++ b/frontend/src/components/Loading.tsx @@ -0,0 +1,34 @@ +import React, { useEffect, useState } from 'react'; +import './Loading.css'; // Import CSS for styling + +export const Loading: React.FC = () => { + return ( +
+ 🎅🏻 +
+ ); +}; + +export const FullScreenLoading: React.FC = () => { + const [isLoading, setIsLoading] = useState(true); + + useEffect(() => { + // Set a timeout to change the loading state + const timer = setTimeout(() => { + setIsLoading(false); + }, 1000); // 1000 ms = 1 second + + // Cleanup function to clear the timeout if the component unmounts + return () => clearTimeout(timer); + }, []); // Empty dependency array means it runs once on mount + + if (!isLoading) { + return null; + } + + return ( +
+ +
+ ) +} diff --git a/frontend/src/components/Snowflakes.css b/frontend/src/components/Snowflakes.css index 719697d..e86b9b2 100644 --- a/frontend/src/components/Snowflakes.css +++ b/frontend/src/components/Snowflakes.css @@ -6,7 +6,7 @@ height: 100%; pointer-events: none; /* Make snowflakes non-interactive */ overflow: hidden; /* Hide overflow */ - z-index: 1000; /* Ensure snowflakes are above other content */ + z-index: 998; /* Ensure snowflakes are above other content */ } .snowflake { diff --git a/frontend/src/utils/fetchUser.tsx b/frontend/src/utils/fetchUser.tsx index d40ad40..cd59f61 100644 --- a/frontend/src/utils/fetchUser.tsx +++ b/frontend/src/utils/fetchUser.tsx @@ -1,14 +1,18 @@ import { useCookies } from 'react-cookie'; import { API_URL } from '../constants/constants'; import { hashPassword } from './hashPassword'; +import { useState } from 'react'; const useFetchUser = () => { + const [isLoading, setIsLoading] = useState(false) const [apiCookie, setApiCookie] = useCookies(['apiToken']); const [, setUserNameCookie] = useCookies(['userName']) const userSet = async (userName: string): Promise => { try { + setIsLoading(true) const response = await fetch(`${API_URL}/users/isSet?userName=${encodeURIComponent(userName)}`); + setIsLoading(false) if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`); const data = await response.json(); return data; // Assuming the server returns true/false @@ -84,6 +88,7 @@ const useFetchUser = () => { const validToken = async (token: string | undefined): Promise => { try { + setIsLoading(true) const response = await fetch(`${API_URL}/login/validateToken`, { method: 'POST', headers: { @@ -93,6 +98,7 @@ const useFetchUser = () => { token }), }); + setIsLoading(false) if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`); const data = await response.json(); @@ -156,7 +162,7 @@ const useFetchUser = () => { } } - return { userSet, passwordCreate, signUser, validToken, updateAttendance, getAttendance }; + return { userSet, passwordCreate, signUser, validToken, updateAttendance, getAttendance, isLoading }; }; export default useFetchUser;