da67ad86d8
- Updated LoginInternify to remove unnecessary state initialization. - Cleaned up NotificationList by removing unused code and fixing button click handler. - Added project_id prop to InternClaimCert for better data handling. - Enhanced CertificateNotAvailable to include claim functionality with loading and error states. - Modified HomeHeader to display a default user name. - Corrected ProjectTimeline to import ProjectTask from the correct type file. - Implemented loading and error handling in CertificateListPage. - Improved MentorProjectDetailPage to handle task updates and navigation correctly. - Enhanced MentorSettingsPage to manage profile picture errors and state. - Updated AddInternsDialog to use the correct hook for fetching interns. - Refactored EditSubmissionTask to handle task updates and errors more effectively. - Improved MentorProjectCard to include project archiving functionality. - Removed deprecated useInterns hook and replaced it with useUser for fetching user data. - Added new useMentors hook for managing mentor-related operations. - Cleaned up CertificateService by removing unused verifyCertificate function. - Created MentorServices for managing mentor data operations. - Updated UserService to include fetching Mahasiswa data and removed unused UserServices file.
79 lines
2.9 KiB
TypeScript
79 lines
2.9 KiB
TypeScript
import { Bell, Menu } from "lucide-react"
|
|
import { useEffect, useState } from "react";
|
|
import humiclogo from "../assets/logo.png";
|
|
import { useNavigate } from "react-router-dom";
|
|
import { useCurrentUser } from "../hooks/useUser";
|
|
|
|
/** Singkatan nama: ambil huruf pertama setiap kata, maksimal 2 huruf.
|
|
* "Andi Mahesa" → "AM"
|
|
* "Andi Bayu Cendika" → "AC" (huruf pertama + huruf pertama kata terakhir)
|
|
*/
|
|
function getInitials(fullName: string | undefined | null): string {
|
|
if (!fullName) return "U";
|
|
const parts = fullName.trim().split(/\s+/).filter(Boolean);
|
|
if (parts.length === 0) return "U";
|
|
if (parts.length === 1) return parts[0].charAt(0).toUpperCase();
|
|
return (parts[0].charAt(0) + parts[parts.length - 1].charAt(0)).toUpperCase();
|
|
}
|
|
|
|
export default function Header({ toggleSidebar }: { toggleSidebar: () => void }) {
|
|
const nav = useNavigate();
|
|
const { user } = useCurrentUser();
|
|
const [imageError, setImageError] = useState(false);
|
|
|
|
useEffect(() => {
|
|
setImageError(false);
|
|
}, [user?.profile_picture, user?.full_name]);
|
|
|
|
// Tentukan base path settings sesuai role
|
|
const settingsPath =
|
|
user?.role === "intern" ? "/intern/settings" : "/mentor/settings";
|
|
|
|
const initials = user?.full_name ? getInitials(user.full_name) : "U";
|
|
const hasPhoto = !!user?.profile_picture && !imageError;
|
|
|
|
return (
|
|
<header className='sticky top-0 flex w-full justify-between items-center py-4 px-12 bg-white border-b border-gray-300 z-10'>
|
|
<div className='flex items-center gap-3'>
|
|
<button
|
|
onClick={toggleSidebar}
|
|
className="p-1 text-gray-600 hover:bg-gray-100 rounded-md lg:hidden"
|
|
>
|
|
<Menu className="w-6 h-6" />
|
|
</button>
|
|
|
|
<button>
|
|
<img src={humiclogo} alt="Humic Logo" className="w-[100px] cursor-pointer" />
|
|
</button>
|
|
</div>
|
|
|
|
<div className="flex flex-row gap-6 items-center">
|
|
<button onClick={() => nav("notifications")}>
|
|
<Bell className="w-5 h-5 hover:text-red-800"/>
|
|
</button>
|
|
|
|
{/* Gambar Profil */}
|
|
<button
|
|
onClick={() => nav(settingsPath)}
|
|
className="rounded-full w-9 h-9 overflow-hidden border-2 border-gray-200 hover:border-red-400 transition-colors flex-shrink-0 focus:outline-none focus:ring-2 focus:ring-red-400"
|
|
title="Profile Settings"
|
|
>
|
|
{hasPhoto ? (
|
|
<img
|
|
src={user?.profile_picture ?? ""}
|
|
alt={user?.full_name ?? "Profile"}
|
|
className="w-full h-full object-cover"
|
|
onError={() => setImageError(true)}
|
|
/>
|
|
) : (
|
|
<div className="w-full h-full bg-[#B30000] flex items-center justify-center">
|
|
<span className="text-white text-xs font-bold tracking-wide">
|
|
{initials}
|
|
</span>
|
|
</div>
|
|
)}
|
|
</button>
|
|
</div>
|
|
</header>
|
|
)
|
|
} |