@ieltsrealtest/ui
Version:
Reusable UI components for IELTS Real Test platform, built with React and TypeScript.
120 lines (119 loc) • 7.06 kB
JavaScript
/* eslint-disable @typescript-eslint/no-unused-vars */
"use client";
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import NavBar from "./Navbar";
import MobileNavbar from "../MobileNavbar/Navbar";
import DropdownMenu from "./DropdownMenu";
import { useState, useEffect, useMemo } from "react";
import Image from "next/image";
import { BsDropletFill } from "react-icons/bs";
import NotificationsDropdown from "./NotificationsDropdown";
const logo = "https://ieltsrealtest.s3.us-east-1.amazonaws.com/public/common/Logo+ngang_.png";
const Header = ({ isDev = false }) => {
const [isLoggedIn, setIsLoggedIn] = useState(false);
const [userName, setUserName] = useState("");
const [avatar, setAvatar] = useState("");
const [isLoading, setIsLoading] = useState(false);
const [nutrientsCount, setNutrientsCount] = useState(0);
const [notificationsCount, setNotificationsCount] = useState(0);
const [logoError, setLogoError] = useState(false);
const { USER_API_BASE_URL } = useMemo(() => {
if (isDev) {
return {
USER_API_BASE_URL: "https://devapi.youready.net/ielts/user/api/",
};
}
return {
USER_API_BASE_URL: "https://api.youready.net/ielts/user/api/",
};
}, [isDev]);
useEffect(() => {
const userStr = sessionStorage.getItem("user");
const cachedUser = userStr ? JSON.parse(userStr) : null;
let userFields = ["nutrients"]; // always refetch nutrients
if (!cachedUser?.avatar)
userFields.push("avatar");
if (!cachedUser?.first_name || !cachedUser?.last_name) {
userFields.push("first_name", "last_name");
}
if (cachedUser?.avatar)
setAvatar(cachedUser.avatar);
if (cachedUser?.first_name && cachedUser?.last_name) {
setUserName(`${cachedUser.first_name} ${cachedUser.last_name}`);
}
const userAPIUrl = `${USER_API_BASE_URL}profile/users/?fields=${userFields.join(",")}`;
const handleSessionExpired = () => {
sessionStorage.removeItem("user");
setIsLoggedIn(false);
setIsLoading(false);
};
const fetchUserData = async () => {
try {
let res = await fetch(userAPIUrl, {
method: "GET",
headers: { "Content-Type": "application/json" },
credentials: "include",
});
// If token expired, try refreshing once
if (res.status === 401 || res.status === 400) {
const refreshUrl = `${USER_API_BASE_URL}auth/refresh_Token/`;
const refreshRes = await fetch(refreshUrl, {
method: "POST",
credentials: "include",
});
if (refreshRes.ok) {
// Retry original request with new token
res = await fetch(userAPIUrl, {
method: "GET",
headers: { "Content-Type": "application/json" },
credentials: "include",
});
}
else {
handleSessionExpired();
return;
}
}
if (!res.ok)
throw new Error("Failed to fetch user data");
const data = await res.json();
const user = data.data || {};
// Update nutrients every time
setNutrientsCount(Number.isFinite(user.nutrients) ? user.nutrients : 0);
// Only update cached info if it was missing
const updatedUser = {
...cachedUser,
...user,
};
sessionStorage.setItem("user", JSON.stringify(updatedUser));
// Also update UI if new avatar or name just arrived
if (user.avatar && !cachedUser?.avatar) {
setAvatar(user.avatar);
}
if (user.first_name && user.last_name && (!cachedUser?.first_name || !cachedUser?.last_name)) {
setUserName(`${user.first_name} ${user.last_name}`);
}
setIsLoggedIn(true);
setIsLoading(false);
}
catch (error) {
setIsLoggedIn(false);
setIsLoading(true);
}
};
fetchUserData();
}, []);
return (_jsxs("div", { children: [_jsx("header", { className: "bg-[#FFF9F1] shadow-md py-0 px-8 text-black", children: _jsxs("div", { className: "mx-auto grid grid-cols-[auto_1fr_auto] items-center", children: [_jsx("div", { className: "text-xl font-bold justify-self-start", children: _jsx("a", { href: isDev ? `https://dev.youready.net/ielts/` : "https://www.youready.net/ielts/", children: _jsx(Image, { src: logoError ? "/ielts/assets/youReady.jpg" : logo, alt: "Logo", width: 140, height: 60, priority: true, onError: () => setLogoError(true) }) }) }), _jsx("div", { className: "justify-self-center min-w-0", children: _jsx(NavBar, { isDev: isDev }) }), _jsx("div", { className: "flex justify-end items-center gap-4 relative justify-self-end", children: isLoggedIn ? (isLoading ? (_jsx("div", { className: "w-full flex items-center justify-end text-gray-500", children: "Loading..." })) : (_jsxs(_Fragment, { children: [_jsx(NotificationsDropdown, { count: notificationsCount, isDev: isDev }), _jsxs("div", { className: "flex items-center gap-1 text-sm leading-none", children: [_jsx(BsDropletFill, { className: "text-[#1E90FF] text-lg" }), _jsx("span", { className: "text-black", children: nutrientsCount })] }), _jsx("span", { className: "h-6 w-px bg-gray-300" }), _jsx(DropdownMenu, { items: [
{ label: "Profile", path: "profile" },
{ label: "Payment", path: "payment" },
{ label: "Performance", path: "performance" },
// { label: 'Logout', path: 'auth/signin' },
], userName: userName, avatar: avatar, isDev: isDev })] }))) : (_jsx("button", { className: "border bg-red-600 text-white px-4 py-1 rounded-md transition duration-200 hover:bg-red-700", onClick: () => {
isDev
? (window.location.href =
"https://dev.youready.net/ielts/user/pages/auth/signin/")
: (window.location.href =
"https://www.youready.net/ielts/user/pages/auth/signin/");
}, children: "SIGN IN" })) })] }) }), _jsx(MobileNavbar, { isDev: isDev })] }));
};
export default Header;