This commit is contained in:
lendry
2026-07-10 12:21:44 +03:00
parent a0966e7ba2
commit f00f3d411d
8 changed files with 395 additions and 54 deletions

View File

@@ -1,9 +1,9 @@
'use client';
import * as React from 'react';
import { createPortal } from 'react-dom';
import { DoorOpen, KeyRound } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog';
import { PinInput } from '@/components/ui/pin-input';
import { isPinInputComplete } from '@/lib/pin-input';
@@ -17,6 +17,11 @@ interface PinLockModalProps {
export function PinLockModal({ open, isSubmitting, error, onSubmit, onLogout }: PinLockModalProps) {
const [pin, setPin] = React.useState('');
const [mounted, setMounted] = React.useState(false);
React.useEffect(() => {
setMounted(true);
}, []);
React.useEffect(() => {
if (open) {
@@ -24,18 +29,32 @@ export function PinLockModal({ open, isSubmitting, error, onSubmit, onLogout }:
}
}, [open]);
React.useEffect(() => {
if (!open || typeof document === 'undefined') return;
const previousOverflow = document.body.style.overflow;
document.body.style.overflow = 'hidden';
return () => {
document.body.style.overflow = previousOverflow;
};
}, [open]);
async function handleSubmit(event: React.FormEvent<HTMLFormElement>) {
event.preventDefault();
await onSubmit(pin);
}
return (
<Dialog open={open} onOpenChange={() => undefined}>
<DialogContent
placement="upper"
className="relative [&>button]:hidden"
onPointerDownOutside={(event) => event.preventDefault()}
onEscapeKeyDown={(event) => event.preventDefault()}
if (!open || !mounted) return null;
return createPortal(
<div className="fixed inset-0 z-[6000]">
<div className="absolute inset-0 bg-black/50 backdrop-blur-[1px]" aria-hidden />
<div
role="dialog"
aria-modal="true"
aria-labelledby="pin-lock-title"
className="fixed left-1/2 w-[min(92vw,520px)] -translate-x-1/2 rounded-[28px] bg-white p-6 shadow-2xl"
style={{ top: 'max(1.5rem, 10vh)' }}
>
{onLogout ? (
<button
@@ -50,15 +69,17 @@ export function PinLockModal({ open, isSubmitting, error, onSubmit, onLogout }:
</button>
) : null}
<DialogHeader>
<div className="mb-5 flex flex-col gap-1">
<div className="mx-auto mb-2 flex h-14 w-14 items-center justify-center rounded-full bg-[#f4f5f8]">
<KeyRound className="h-7 w-7 text-[#111]" />
</div>
<DialogTitle className="text-center">Введите PIN-код</DialogTitle>
<h2 id="pin-lock-title" className="text-center text-xl font-semibold">
Введите PIN-код
</h2>
<p className="text-center text-sm text-[#6b6f7b]">
Сессия заблокирована из-за бездействия. Подтвердите PIN, чтобы продолжить работу.
</p>
</DialogHeader>
</div>
<form onSubmit={handleSubmit} className="space-y-4">
<PinInput
@@ -89,7 +110,8 @@ export function PinLockModal({ open, isSubmitting, error, onSubmit, onLogout }:
</Button>
) : null}
</form>
</DialogContent>
</Dialog>
</div>
</div>,
document.body
);
}