529452b0fb
- Route app/dashboard/versions/[id]/ pour URLs spécifiques - Composant VersionPage avec affichage et partage natif - Support modes comparison/content via paramètre URL
138 lines
3.8 KiB
JavaScript
138 lines
3.8 KiB
JavaScript
import {useState} from 'react'
|
|
import PropTypes from 'prop-types'
|
|
import IconButton from '@mui/material/IconButton'
|
|
import Tooltip from '@mui/material/Tooltip'
|
|
import Snackbar from '@mui/material/Snackbar'
|
|
import Alert from '@mui/material/Alert'
|
|
import ShareIcon from '@mui/icons-material/Share'
|
|
import LinkIcon from '@mui/icons-material/Link'
|
|
|
|
export default function ShareButton({
|
|
versionId,
|
|
versionName = 'Version',
|
|
size = 'small',
|
|
hasSnackbarVisible = true,
|
|
onShareSuccess = null,
|
|
onShareError = null
|
|
}) {
|
|
const [shared, setShared] = useState(false)
|
|
const [snackbar, setSnackbar] = useState({open: false, message: '', severity: 'success'})
|
|
|
|
const handleShare = async () => {
|
|
const url = `${window.location.origin}/dashboard/versions/${versionId}`
|
|
|
|
try {
|
|
if (navigator.share) {
|
|
// Use native share API if available
|
|
await navigator.share({
|
|
title: `Version: ${versionName}`,
|
|
text: 'Découvrez cette version sur Konstitisyon.la',
|
|
url
|
|
})
|
|
} else if (navigator.clipboard && window.isSecureContext) {
|
|
await navigator.clipboard.writeText(url)
|
|
} else {
|
|
// Fallback for older browsers
|
|
const textArea = document.createElement('textarea')
|
|
textArea.value = url
|
|
textArea.style.position = 'fixed'
|
|
textArea.style.left = '-999999px'
|
|
textArea.style.top = '-999999px'
|
|
document.body.append(textArea)
|
|
textArea.focus()
|
|
textArea.select()
|
|
|
|
const result = document.execCommand('copy')
|
|
textArea.remove()
|
|
|
|
if (!result) {
|
|
throw new Error('Copy command failed')
|
|
}
|
|
}
|
|
|
|
// Success feedback
|
|
setShared(true)
|
|
setTimeout(() => setShared(false), 2000)
|
|
|
|
if (hasSnackbarVisible) {
|
|
setSnackbar({
|
|
open: true,
|
|
message: navigator.share ? 'Version partagée' : 'Lien copié dans le presse-papier',
|
|
severity: 'success'
|
|
})
|
|
}
|
|
|
|
if (onShareSuccess) {
|
|
onShareSuccess()
|
|
}
|
|
} catch (error) {
|
|
console.error('Failed to share:', error)
|
|
|
|
if (hasSnackbarVisible) {
|
|
setSnackbar({
|
|
open: true,
|
|
message: 'Impossible de partager cette version',
|
|
severity: 'error'
|
|
})
|
|
}
|
|
|
|
if (onShareError) {
|
|
onShareError(error)
|
|
}
|
|
}
|
|
}
|
|
|
|
const handleCloseSnackbar = () => {
|
|
setSnackbar(prev => ({...prev, open: false}))
|
|
}
|
|
|
|
return (
|
|
<>
|
|
<Tooltip title={shared ? 'Partagé !' : 'Partager cette version'}>
|
|
<IconButton
|
|
size={size}
|
|
aria-label='Partager cette version'
|
|
sx={{
|
|
color: shared ? 'success.main' : 'text.secondary',
|
|
'&:hover': {
|
|
color: shared ? 'success.dark' : 'primary.main',
|
|
backgroundColor: shared ? 'success.light' : 'action.hover'
|
|
},
|
|
transition: 'all 0.2s ease-in-out'
|
|
}}
|
|
onClick={handleShare}
|
|
>
|
|
{shared ? <LinkIcon /> : <ShareIcon />}
|
|
</IconButton>
|
|
</Tooltip>
|
|
|
|
{hasSnackbarVisible && (
|
|
<Snackbar
|
|
open={snackbar.open}
|
|
autoHideDuration={3000}
|
|
anchorOrigin={{vertical: 'bottom', horizontal: 'center'}}
|
|
onClose={handleCloseSnackbar}
|
|
>
|
|
<Alert
|
|
variant='filled'
|
|
severity={snackbar.severity}
|
|
sx={{width: '100%'}}
|
|
onClose={handleCloseSnackbar}
|
|
>
|
|
{snackbar.message}
|
|
</Alert>
|
|
</Snackbar>
|
|
)}
|
|
</>
|
|
)
|
|
}
|
|
|
|
ShareButton.propTypes = {
|
|
versionId: PropTypes.string.isRequired,
|
|
versionName: PropTypes.string,
|
|
size: PropTypes.oneOf(['small', 'medium', 'large']),
|
|
hasSnackbarVisible: PropTypes.bool,
|
|
onShareSuccess: PropTypes.func,
|
|
onShareError: PropTypes.func
|
|
}
|