feat: add warning handling for contract preview in UserDetailModal

This commit is contained in:
seaznCode 2026-01-19 23:16:13 +01:00
parent 76d2d36172
commit 352aba4c88
2 changed files with 20 additions and 10 deletions

View File

@ -49,8 +49,8 @@ export default function UserDetailModal({ isOpen, onClose, userId, onUserUpdated
// Contract preview state (lazy-loaded, per contract type) // Contract preview state (lazy-loaded, per contract type)
const [activePreviewTab, setActivePreviewTab] = useState<'contract' | 'gdpr'>('contract') const [activePreviewTab, setActivePreviewTab] = useState<'contract' | 'gdpr'>('contract')
const [previewState, setPreviewState] = useState({ const [previewState, setPreviewState] = useState({
contract: { loading: false, html: null as string | null, error: null as string | null }, contract: { loading: false, html: null as string | null, error: null as string | null, warning: null as string | null },
gdpr: { loading: false, html: null as string | null, error: null as string | null }, gdpr: { loading: false, html: null as string | null, error: null as string | null, warning: null as string | null },
}) })
useEffect(() => { useEffect(() => {
@ -63,8 +63,8 @@ export default function UserDetailModal({ isOpen, onClose, userId, onUserUpdated
if (!isOpen) return if (!isOpen) return
setActivePreviewTab('contract') setActivePreviewTab('contract')
setPreviewState({ setPreviewState({
contract: { loading: false, html: null, error: null }, contract: { loading: false, html: null, error: null, warning: null },
gdpr: { loading: false, html: null, error: null } gdpr: { loading: false, html: null, error: null, warning: null }
}) })
}, [isOpen, userId]) }, [isOpen, userId])
@ -153,19 +153,19 @@ export default function UserDetailModal({ isOpen, onClose, userId, onUserUpdated
if (!userId || !token || !userDetails) return if (!userId || !token || !userDetails) return
setPreviewState((prev) => ({ setPreviewState((prev) => ({
...prev, ...prev,
[contractType]: { ...prev[contractType], loading: true, error: null } [contractType]: { ...prev[contractType], loading: true, error: null, warning: null }
})) }))
try { try {
const html = await AdminAPI.getContractPreviewHtml(token, String(userId), userDetails.user.user_type, contractType) const result = await AdminAPI.getContractPreviewHtml(token, String(userId), userDetails.user.user_type, contractType)
setPreviewState((prev) => ({ setPreviewState((prev) => ({
...prev, ...prev,
[contractType]: { loading: false, html, error: null } [contractType]: { loading: false, html: result.html, error: null, warning: result.warning || null }
})) }))
} catch (e: any) { } catch (e: any) {
console.error('UserDetailModal.loadContractPreview error:', e) console.error('UserDetailModal.loadContractPreview error:', e)
setPreviewState((prev) => ({ setPreviewState((prev) => ({
...prev, ...prev,
[contractType]: { loading: false, html: null, error: e?.message || 'Failed to load contract preview' } [contractType]: { loading: false, html: null, error: e?.message || 'Failed to load contract preview', warning: e?.warning || null }
})) }))
} }
} }
@ -459,6 +459,11 @@ export default function UserDetailModal({ isOpen, onClose, userId, onUserUpdated
</div> </div>
</div> </div>
<div className="px-6 py-5"> <div className="px-6 py-5">
{previewState[activePreviewTab].warning && (
<div className="rounded-md border border-amber-200 bg-amber-50 px-4 py-3 text-sm text-amber-800 mb-4">
{previewState[activePreviewTab].warning}
</div>
)}
{previewState[activePreviewTab].error && ( {previewState[activePreviewTab].error && (
<div className="rounded-md border border-red-200 bg-red-50 px-4 py-3 text-sm text-red-700 mb-4"> <div className="rounded-md border border-red-200 bg-red-50 px-4 py-3 text-sm text-red-700 mb-4">
{previewState[activePreviewTab].error} {previewState[activePreviewTab].error}

View File

@ -449,12 +449,17 @@ export class AdminAPI {
const qsStr = qs.toString() const qsStr = qs.toString()
if (qsStr) endpoint += `?${qsStr}` if (qsStr) endpoint += `?${qsStr}`
const response = await ApiClient.get(endpoint, token) const response = await ApiClient.get(endpoint, token)
const warningHeader = response.headers.get('x-contract-preview-warning')
if (!response.ok) { if (!response.ok) {
const error = await response.json().catch(() => ({ message: 'Failed to fetch contract preview' })) const error = await response.json().catch(() => ({ message: 'Failed to fetch contract preview' }))
throw new Error(error.message || 'Failed to fetch contract preview') const err: any = new Error(error.message || 'Failed to fetch contract preview')
if (warningHeader) err.warning = warningHeader
if (error?.warning) err.warning = error.warning
throw err
} }
// Return HTML string // Return HTML string
return response.text() const html = await response.text()
return { html, warning: warningHeader }
} }
} }