fix(17): WR-05 IN-03 IN-01 resize-aware useIsPhone hook; OidcRedirect side-effect in effect
This commit is contained in:
@@ -55,6 +55,7 @@ import { SyncStateToast } from './SyncStateToast.js';
|
||||
import { ColorLegend } from './ColorLegend.js';
|
||||
import { SkeletonCalendar } from './SkeletonCalendar.js';
|
||||
import { InstallPrompt } from './InstallPrompt.js';
|
||||
import { useIsPhone } from '../hooks/useIsPhone.js';
|
||||
|
||||
// ── Helpers ────────────────────────────────────────────────────────────────
|
||||
|
||||
@@ -71,10 +72,6 @@ function resolveDefaultView(persistedView: string): string {
|
||||
return persistedView;
|
||||
}
|
||||
|
||||
function isPhone(): boolean {
|
||||
return typeof window !== 'undefined' && window.matchMedia('(max-width: 767px)').matches;
|
||||
}
|
||||
|
||||
// ── Component ──────────────────────────────────────────────────────────────
|
||||
|
||||
export function CalendarShell() {
|
||||
@@ -249,7 +246,7 @@ export function CalendarShell() {
|
||||
const isInitialLoading = eventsQuery.isLoading && !eventsQuery.data;
|
||||
const isEventsError = eventsQuery.isError;
|
||||
|
||||
const phone = isPhone();
|
||||
const phone = useIsPhone();
|
||||
|
||||
// ── Auth splash (D-10) ────────────────────────────────────────────────────
|
||||
// Gate the calendar render on auth state so no calendar shell, skeleton, or
|
||||
|
||||
@@ -31,6 +31,7 @@ import {
|
||||
type SaveCredentialPayload,
|
||||
type SaveMyCredentialPayload,
|
||||
} from '../api/client.js';
|
||||
import { useIsPhone } from '../hooks/useIsPhone.js';
|
||||
|
||||
export type CredentialSheetMode = 'admin-rotate' | 'admin-add' | 'self-service';
|
||||
|
||||
@@ -76,6 +77,7 @@ export function CredentialSheet({
|
||||
triggerRef,
|
||||
}: CredentialSheetProps) {
|
||||
const queryClient = useQueryClient();
|
||||
const phone = useIsPhone();
|
||||
const [password, setPassword] = useState('');
|
||||
const [email, setEmail] = useState('');
|
||||
const [validationError, setValidationError] = useState<string | null>(null);
|
||||
@@ -153,7 +155,6 @@ export function CredentialSheet({
|
||||
const heading = headingFor(mode);
|
||||
const isPending = credentialMutation.isPending;
|
||||
const saveDisabled = isPending || password.trim().length === 0 || email.trim().length === 0;
|
||||
const phone = window.matchMedia('(max-width: 767px)').matches;
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
@@ -26,6 +26,7 @@ import { X, Bell, AlertCircle, Loader2, LogOut } from 'lucide-react';
|
||||
import { useQuery, useMutation } from '@tanstack/react-query';
|
||||
import { useNavigate } from 'react-router';
|
||||
import { usePushSubscription } from '../hooks/usePushSubscription.js';
|
||||
import { useIsPhone } from '../hooks/useIsPhone.js';
|
||||
import { InstructionSheet } from './InstructionSheet.js';
|
||||
import { fetchMe, fetchAuthMode, fetchChangePassword, fetchLinkOidc, fetchLocalLogout } from '../api/client.js';
|
||||
|
||||
@@ -55,6 +56,8 @@ interface SettingsSheetProps {
|
||||
export function SettingsSheet({ isOpen, onClose }: SettingsSheetProps) {
|
||||
const { subscribe, permission, isSubscribed, setEnabled } = usePushSubscription();
|
||||
const navigate = useNavigate();
|
||||
// WR-05: resize-aware so an iPad rotation across 767px reflows the sheet.
|
||||
const phone = useIsPhone();
|
||||
const [isTogglingOn, setIsTogglingOn] = useState(false);
|
||||
const [instructionsOpen, setInstructionsOpen] = useState(false);
|
||||
|
||||
@@ -132,8 +135,6 @@ export function SettingsSheet({ isOpen, onClose }: SettingsSheetProps) {
|
||||
|
||||
if (!isOpen) return null;
|
||||
|
||||
const phone = window.matchMedia('(max-width: 767px)').matches;
|
||||
|
||||
// D-07: fire-and-best-effort logout — navigate to /login regardless of API success/failure
|
||||
const handleSignOut = async () => {
|
||||
try {
|
||||
@@ -589,6 +590,7 @@ interface ChangePasswordSheetProps {
|
||||
}
|
||||
|
||||
function ChangePasswordSheet({ isOpen, onClose }: ChangePasswordSheetProps) {
|
||||
const phone = useIsPhone();
|
||||
const [currentPassword, setCurrentPassword] = useState('');
|
||||
const [newPassword, setNewPassword] = useState('');
|
||||
const [confirmPassword, setConfirmPassword] = useState('');
|
||||
@@ -647,8 +649,6 @@ function ChangePasswordSheet({ isOpen, onClose }: ChangePasswordSheetProps) {
|
||||
|
||||
if (!isOpen) return null;
|
||||
|
||||
const phone = window.matchMedia('(max-width: 767px)').matches;
|
||||
|
||||
return (
|
||||
<>
|
||||
{/* Backdrop */}
|
||||
@@ -921,6 +921,7 @@ interface LinkOidcSheetProps {
|
||||
}
|
||||
|
||||
function LinkOidcSheet({ isOpen, onClose }: LinkOidcSheetProps) {
|
||||
const phone = useIsPhone();
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const headingRef = useRef<HTMLHeadingElement>(null);
|
||||
|
||||
@@ -959,8 +960,6 @@ function LinkOidcSheet({ isOpen, onClose }: LinkOidcSheetProps) {
|
||||
|
||||
if (!isOpen) return null;
|
||||
|
||||
const phone = window.matchMedia('(max-width: 767px)').matches;
|
||||
|
||||
return (
|
||||
<>
|
||||
{/* Backdrop */}
|
||||
|
||||
Reference in New Issue
Block a user