'use client'; import { useCallback, useState } from 'react'; import { useProofing } from './ProofingContext'; import { useDictionary } from './I18nProvider'; import { useModalDialog } from '@/hooks/useModalDialog'; const barStyle: React.CSSProperties = { position: 'fixed', bottom: '24px', right: '24px', left: 'auto', zIndex: 990, display: 'flex', alignItems: 'center', flexWrap: 'wrap', gap: '10px', padding: '8px 12px', borderRadius: 'var(--radius-lg)', background: 'var(--bg-card, #1e1e1e)', color: 'var(--text-primary, #ffffff)', border: '1px solid var(--border-subtle, rgba(255,255,255,0.15))', boxShadow: '0 8px 24px rgba(0,0,0,0.4)', backdropFilter: 'blur(8px)', maxWidth: 'calc(100vw - 32px)', }; const barButton: React.CSSProperties = { display: 'flex', alignItems: 'center', justifyContent: 'center', gap: '0.4rem', padding: '7px 12px', borderRadius: 'var(--radius-md)', background: 'var(--bg-card-hover)', color: 'var(--text-primary)', border: '1px solid var(--border-subtle)', fontFamily: 'inherit', fontSize: '0.85rem', fontWeight: 500, lineHeight: 1.3, cursor: 'pointer', textDecoration: 'none', }; const downloadButton: React.CSSProperties = { ...barButton, background: 'var(--accent, #e60012)', color: 'var(--on-accent, #fff)', border: 'none', fontWeight: 600, }; const primaryButton: React.CSSProperties = { display: 'flex', alignItems: 'center', justifyContent: 'center', gap: '0.5rem', padding: '0.75rem 1rem', borderRadius: 'var(--radius-sm, 6px)', background: 'var(--accent, #e60012)', color: 'var(--on-accent, #fff)', border: 'none', fontWeight: 500, fontFamily: 'inherit', fontSize: '0.9rem', lineHeight: 1.3, cursor: 'pointer', }; export function ProofSessionControls() { const t = useDictionary(); const proofing = useProofing(); const [open, setOpen] = useState(false); const [submitting, setSubmitting] = useState(false); const close = useCallback(() => setOpen(false), []); const cardRef = useModalDialog(close, open); if (!proofing?.session) return null; const { session, isFilterActive, setIsFilterActive, getSelectedTokens, albumCount, toggleSelectAll, } = proofing; const count = getSelectedTokens().length; const allSelected = albumCount > 0 && count === albumCount; const p = t.proofSession; const status = session.saveState === 'saving' ? p.saving : session.saveState === 'error' ? p.saveFailed : session.saveState === 'saved' ? p.saved : ''; const handleSubmit = async () => { setSubmitting(true); await session.submit(); setSubmitting(false); }; const downloadsLeft = session.downloadsRemaining; /* * "selection" and legacy "album" are both treated simply as * "downloads allowed" in our UI. */ const downloadsAllowed = session.download !== 'none' && (downloadsLeft === null || downloadsLeft > 0); /* * The ZIP route reads the server-side saved selection, not merely the * current browser state. Do not enable the button until autosave has * caught up, otherwise a very fast click could download the previous * selection. */ const selectionSaved = !session.unsaved && session.saveState !== 'saving' && session.saveState !== 'error'; const downloadReady = downloadsAllowed && count > 0 && selectionSaved; const downloadHref = `${session.archiveUrl}?scope=selection`; return ( <>
{/* Persistent download button */} {session.download !== 'none' && (downloadReady ? ( ↓ Download ZIP ({count}) ) : ( ))} {/* Select / deselect every photo */} {!session.submitted && ( )} {/* Selection counter / filter */} {session.submitted ? p.locked : status}
{open && (
e.stopPropagation()} style={{ background: 'var(--bg-card, #1e1e1e)', color: 'var(--text-primary, #ffffff)', borderRadius: 'var(--radius-md, 12px)', border: '1px solid var(--border-subtle, rgba(255,255,255,0.1))', padding: '1.5rem', maxWidth: '480px', width: '100%', boxShadow: '0 20px 40px rgba(0,0,0,0.5)', }} >

{p.modalTitle(count)}

{session.submitted ? p.submitted : count === 0 ? p.empty : p.confirmSubmit(count)}

{!session.submitted && ( )} {session.download !== 'none' && downloadsLeft !== null && (

{downloadsLeft > 0 ? p.downloadsLeft(downloadsLeft) : t.download.limitReached}

)} {session.saveState === 'error' && (

{p.saveFailed}

)}
)} ); }