Files
clinicpro/assets/admin/components/ui/PwaLoginCard.tsx
T
2026-06-13 13:28:39 +03:30

168 lines
7.0 KiB
TypeScript

import React, { useState } from 'react';
import { createPortal } from 'react-dom';
import { ArrowDownTrayIcon, XMarkIcon, CheckIcon } from '@heroicons/react/24/outline';
import { usePwaInstall } from '../../hooks/usePwaInstall';
function detectIOS(): boolean {
return /iphone|ipad|ipod/i.test(navigator.userAgent);
}
export default function PwaLoginCard() {
const { promptEvent, isInstalled, isDismissed, install, dismiss } = usePwaInstall();
const [showSteps, setShowSteps] = useState(false);
if (isInstalled || isDismissed) return null;
const isIOS = detectIOS();
const handleInstallClick = async () => {
if (promptEvent) {
const accepted = await install();
if (accepted) return;
}
// native prompt not available or dismissed → show manual steps
setShowSteps(true);
};
const steps = isIOS
? [
'Safari را باز کنید (فقط Safari از نصب پشتیبانی می‌کند)',
'دکمه Share (مربع با فلش رو به بالا) را در پایین صفحه بزنید',
'گزینه «Add to Home Screen» را انتخاب کنید',
'«Add» را بزنید — تمام!',
]
: [
'در Chrome منوی سه‌نقطه (⋮) را در گوشه بالا باز کنید',
'گزینه «Install ClinicPro» یا «Install app» را انتخاب کنید',
'در پنجره‌ای که باز می‌شود «Install» را بزنید',
];
return createPortal(
<div
onClick={dismiss}
style={{
position: 'fixed', inset: 0, zIndex: 10000,
background: 'rgba(0,0,0,0.45)',
display: 'flex', alignItems: 'center', justifyContent: 'center',
padding: 20, direction: 'rtl',
}}
>
<div
onClick={(e) => e.stopPropagation()}
style={{
width: '100%', maxWidth: 380,
background: 'var(--surface)',
borderRadius: 'var(--r)',
boxShadow: '0 20px 60px rgba(0,0,0,0.2)',
overflow: 'hidden',
}}
>
{/* Header */}
<div style={{
display: 'flex', alignItems: 'center', justifyContent: 'space-between',
padding: '16px 18px 14px',
borderBottom: '1px solid var(--border)',
}}>
<div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
<div style={{
width: 36, height: 36, borderRadius: 10,
background: 'var(--primary)', color: 'var(--on-primary)',
display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0,
}}>
<ArrowDownTrayIcon style={{ width: 18, height: 18 }} />
</div>
<span style={{ fontSize: 15, fontWeight: 800, color: 'var(--text)' }}>نصب ClinicPro</span>
</div>
<button onClick={dismiss} style={{
width: 30, height: 30, display: 'flex', alignItems: 'center', justifyContent: 'center',
border: 'none', background: 'transparent', cursor: 'pointer',
color: 'var(--text-3)', borderRadius: 8,
}}>
<XMarkIcon style={{ width: 18, height: 18 }} />
</button>
</div>
{/* Body */}
<div style={{ padding: '20px 18px' }}>
{!showSteps ? (
<>
{/* App icon + name */}
<div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', marginBottom: 20 }}>
<div style={{
width: 72, height: 72, borderRadius: 18,
background: 'var(--primary-soft)',
display: 'flex', alignItems: 'center', justifyContent: 'center',
fontSize: 36, marginBottom: 10,
}}></div>
<p style={{ fontSize: 16, fontWeight: 800, color: 'var(--text)', margin: 0 }}>ClinicPro</p>
<p style={{ fontSize: 12, color: 'var(--text-3)', margin: '4px 0 0' }}>پنل مدیریت کلینیک</p>
</div>
<p style={{ fontSize: 13, color: 'var(--text-2)', textAlign: 'center', lineHeight: 1.7, margin: '0 0 20px' }}>
اپلیکیشن را روی دستگاه خود نصب کنید و بدون باز کردن مرورگر وارد شوید.
</p>
<div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
<button
onClick={handleInstallClick}
style={{
width: '100%', height: 46, borderRadius: 'var(--r-sm)',
border: 'none', background: 'var(--primary)', color: 'var(--on-primary)',
fontSize: 15, fontWeight: 700, cursor: 'pointer',
display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8,
}}>
<ArrowDownTrayIcon style={{ width: 18, height: 18 }} />
نصب اپلیکیشن
</button>
<button
onClick={dismiss}
style={{
width: '100%', height: 40, borderRadius: 'var(--r-sm)',
border: '1px solid var(--border)', background: 'transparent',
color: 'var(--text-2)', fontSize: 13, fontWeight: 600, cursor: 'pointer',
}}>
بعداً
</button>
</div>
</>
) : (
<>
<p style={{ fontSize: 13, fontWeight: 700, color: 'var(--text)', margin: '0 0 16px' }}>
مراحل نصب:
</p>
<div style={{ display: 'flex', flexDirection: 'column', gap: 12, marginBottom: 20 }}>
{steps.map((step, i) => (
<div key={i} style={{ display: 'flex', gap: 12, alignItems: 'flex-start' }}>
<div style={{
width: 24, height: 24, borderRadius: '50%', flexShrink: 0,
background: 'var(--primary-soft)', color: 'var(--primary-700)',
display: 'flex', alignItems: 'center', justifyContent: 'center',
fontSize: 12, fontWeight: 700,
}}>
{i + 1}
</div>
<p style={{ fontSize: 13, color: 'var(--text-2)', lineHeight: 1.6, margin: 0 }}>{step}</p>
</div>
))}
</div>
<button
onClick={dismiss}
style={{
width: '100%', height: 44, borderRadius: 'var(--r-sm)',
border: 'none', background: 'var(--primary)', color: 'var(--on-primary)',
fontSize: 14, fontWeight: 700, cursor: 'pointer',
display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 6,
}}>
<CheckIcon style={{ width: 16, height: 16 }} />
متوجه شدم
</button>
</>
)}
</div>
</div>
</div>,
document.body
);
}