Add Audible region config and user password change modal

Implements configurable Audible region selection in setup and admin settings, affecting all Audible API calls and triggering data refresh on change. Adds a user-facing 'Change Password' modal in the header for local users, moving password change from admin-only to all local users via a new /api/auth/change-password endpoint. Updates documentation, API routes, and context to support these features, and removes the old admin-only password change flow.
This commit is contained in:
kikootwo
2026-01-13 01:51:22 -05:00
parent 50fb5a68af
commit e346f88f42
24 changed files with 932 additions and 317 deletions
+22
View File
@@ -11,6 +11,7 @@ import Link from 'next/link';
import { useAuth } from '@/contexts/AuthContext';
import { Button } from '@/components/ui/Button';
import { VersionBadge } from '@/components/ui/VersionBadge';
import { ChangePasswordModal } from '@/components/ui/ChangePasswordModal';
import { useSmartDropdownPosition } from '@/hooks/useSmartDropdownPosition';
export function Header() {
@@ -18,8 +19,12 @@ export function Header() {
const [showUserMenu, setShowUserMenu] = useState(false);
const [showMobileMenu, setShowMobileMenu] = useState(false);
const [showBookDate, setShowBookDate] = useState(false);
const [showChangePasswordModal, setShowChangePasswordModal] = useState(false);
const { containerRef, dropdownRef, positionAbove, style } = useSmartDropdownPosition(showUserMenu);
// Check if user can change password (local users only)
const canChangePassword = user?.authProvider === 'local';
// Check if BookDate is configured
useEffect(() => {
async function checkBookDate() {
@@ -85,6 +90,17 @@ export function Header() {
>
Profile
</Link>
{canChangePassword && (
<button
onClick={() => {
setShowUserMenu(false);
setShowChangePasswordModal(true);
}}
className="w-full text-left px-4 py-2 text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700"
>
Change Password
</button>
)}
<button
onClick={() => {
logout();
@@ -268,6 +284,12 @@ export function Header() {
{/* User menu dropdown (rendered via portal) */}
{typeof window !== 'undefined' && userMenuDropdown && createPortal(userMenuDropdown, document.body)}
{/* Change Password Modal */}
<ChangePasswordModal
isOpen={showChangePasswordModal}
onClose={() => setShowChangePasswordModal(false)}
/>
</header>
);
}