// ============ TaskQuest — Header & Notifications ============
const { useState, useEffect, useRef } = React;
const { ROLES: R2, PROJECTS: P2, CONSULTANTS: C2 } = window.TQ;
function Dropdown({ trigger, children, width, align = "left" }) {
const [open, setOpen] = useState(false);
const ref = useRef(null);
useClickOutside(ref, () => setOpen(false), open);
return (
{trigger(open, () => setOpen(o => !o))}
{open && (
setOpen(false)}>
{children}
)}
);
}
function Header({ role, setRole, project, setProject, theme, toggleTheme, authUser, onLogout, canSwitchRole = true, notifications, onOpenNotif, notifOpen, notifPanel }) {
const r = R2[role];
const isDM = r.type === "dm";
// PMs/consultants are scoped to the projects they're assigned to; DMs span all.
const myProjs = window.TQ.projectsOf(r).map(k => P2[k]).filter(Boolean);
const projOptions = isDM
? [{ key: "all", name: "All Projects", color: "#8b7cf6" }, ...Object.values(P2)]
: (myProjs.length ? myProjs : Object.values(P2));
const curProj = project === "all" ? { name: "All Projects", color: "#8b7cf6" } : (P2[project] || { name: "—", color: "#878b94" });
const acct = R2[authUser] || r;
const acctUsername = (R2[authUser] && R2[authUser].username) || "";
return (
);
}
function NotificationsPanel({ notifications, onClose, onMarkAll, onClickNotif }) {
const ref = useRef(null);
useClickOutside(ref, onClose, true);
const iconFor = {
date_request: { ic: Ic.Calendar, c: "#f2c94c" },
date_approved: { ic: Ic.CheckCircle, c: "#4cb782" },
approved: { ic: Ic.CheckCircle, c: "#4cb782" },
done: { ic: Ic.Flag, c: "#8b7cf6" },
comment: { ic: Ic.Msg, c: "#4ea7fc" },
bonus: { ic: Ic.Gift, c: "#e0902b" },
rejected: { ic: Ic.X, c: "#eb5757" },
};
return (
Notifications
{notifications.some(n => !n.read) && }
{notifications.length === 0 &&
You're all caught up.
}
{notifications.map(n => {
const meta = iconFor[n.type] || { ic: Ic.Bell, c: "var(--muted)" };
return (
onClickNotif(n)}>
{React.createElement(meta.ic, { size: 15 })}
{n.time}{n.project ? " · " + (P2[n.project] ? P2[n.project].name : "") : ""}
);
})}
);
}
window.Header = Header;
window.NotificationsPanel = NotificationsPanel;
window.Dropdown = Dropdown;