flnxi-Wu/app/share/[id]/page.tsx
WuYongJie 63ec6b7dfb fix: 修复排行榜按钮消失、tag排序和输入框浅色模式问题
1. 排行榜悬浮窗关闭后小按钮消失问题
   - 修复面板居中模式关闭时按钮位置错误
   - 保存并恢复按钮的居中状态

2. 首页tag按钮按素材数量排序
   - 添加按素材数量降序排序逻辑

3. 上传弹窗输入框浅色模式文字不可见
   - 添加 text-slate-900 确保浅色模式下文字可见
   - 添加 placeholder 样式确保占位符正确显示
2025-12-14 21:41:29 +08:00

660 lines
28 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* SharePage 组件
*
* 素材分享页面
* 显示素材详情、预览图、下载等功能
* 支持PSD/模特类型的多图展示
* 使用三层架构样式系统,支持深浅色主题
*
* @created 2025-01-XX
* @component
*/
'use client'
import { useEffect, useState, useCallback } from 'react'
import { useSession } from 'next-auth/react'
import { useRouter, useParams } from 'next/navigation'
import Image from 'next/image'
import { format } from 'date-fns'
import Header from '@/components/Header'
import { useDialog } from '@/components/ui/DialogProvider'
import { useThemeStyles, useTheme, cn } from '@/lib/ui-styles'
interface Material {
id: string
previewUrl: string
productModel: string
brandName?: string | null
seriesName?: string | null
skuCode?: string | null
materialTexture?: string | null
categoryName: string
sceneName: string
materialType: string
renderer?: string | null
renderTime?: string | null
imageResolution?: string | null
colorMode?: string | null
authorName: string
zipFileName: string
zipFileSize: string | number
downloadCount: number
likeCount: number
displayImages: string[] // PSD展示图片URLs
createdAt: string
}
export default function SharePage() {
const styles = useThemeStyles()
const theme = useTheme()
const { data: session, status } = useSession()
const router = useRouter()
const { alert } = useDialog()
const params = useParams()
const materialId = params.id as string
const [material, setMaterial] = useState<Material | null>(null)
const [loading, setLoading] = useState(true)
const [downloading, setDownloading] = useState(false)
const [downloadProgress, setDownloadProgress] = useState(0)
const [showBackToTop, setShowBackToTop] = useState(false)
const [aiEditEnabled, setAiEditEnabled] = useState(
(process.env.NEXT_PUBLIC_AI_EDIT_ENABLED || '').toLowerCase() === 'true'
)
const fetchMaterial = useCallback(async () => {
try {
const response = await fetch(`/api/materials/share?id=${materialId}`)
if (response.ok) {
const data = await response.json()
setMaterial(data)
// 记录浏览历史(仅登录用户)
if (session?.user) {
fetch('/api/user/history', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ materialId }),
}).catch((err) => console.warn('记录浏览历史失败:', err))
}
} else {
alert({
title: '错误',
message: '素材不存在或已被删除',
variant: 'error',
})
router.push('/')
}
} catch (error) {
console.error('Error fetching material:', error)
alert({
title: '加载失败',
message: '加载失败',
variant: 'error',
})
router.push('/')
} finally {
setLoading(false)
}
}, [materialId, router, session])
useEffect(() => {
if (status !== 'loading') {
fetchMaterial()
}
}, [status, fetchMaterial])
useEffect(() => {
const ensureFeatureFlags = async () => {
if (aiEditEnabled) return
try {
const response = await fetch('/api/system-settings')
if (response.ok) {
const data = await response.json()
if (data?.enableAiImageEdit) {
setAiEditEnabled(true)
}
}
} catch (err) {
console.warn('加载系统设置失败(AI改图判断):', err)
}
}
ensureFeatureFlags()
}, [aiEditEnabled])
useEffect(() => {
// 监听滚动,控制返回顶部按钮显示
const handleScroll = () => {
setShowBackToTop(window.scrollY > 400)
}
window.addEventListener('scroll', handleScroll)
return () => window.removeEventListener('scroll', handleScroll)
}, [])
const formatFileSize = (bytes: string | number): string => {
const size = typeof bytes === 'string' ? parseInt(bytes) : bytes
if (size === 0) return '未知'
const units = ['B', 'KB', 'MB', 'GB']
const i = Math.floor(Math.log(size) / Math.log(1024))
return `${(size / Math.pow(1024, i)).toFixed(2)} ${units[i]}`
}
const scrollToTop = () => {
window.scrollTo({ top: 0, behavior: 'smooth' })
}
const renderAdditionalInfo = (variant: 'compact' | 'full' = 'compact') => {
if (!material) return null
const entries = [
{ label: '品牌', value: material.brandName },
{ label: '系列', value: material.seriesName },
{ label: 'SKU', value: material.skuCode },
{ label: '材质 / 工艺', value: material.materialTexture },
{ label: '渲染耗时', value: material.renderTime },
{ label: '输出分辨率', value: material.imageResolution },
{ label: '颜色模式', value: material.colorMode },
].filter(entry => entry.value)
if (entries.length === 0) return null
const labelClass = variant === 'compact'
? 'text-xs text-slate-500 dark:text-slate-400 mb-1'
: 'text-sm text-slate-500 dark:text-slate-400 mb-1'
const valueClass = variant === 'compact'
? 'text-sm font-medium text-slate-900 dark:text-white break-all'
: 'text-base font-medium text-slate-900 dark:text-white break-all'
return (
<div className={cn(
'grid grid-cols-1',
variant === 'compact'
? 'gap-3 mt-4 pt-4 border-t border-slate-100 dark:border-slate-700'
: 'gap-4 mt-6 pt-6 border-t border-slate-200 dark:border-slate-700'
)}>
{entries.map((entry, index) => (
<div key={`${entry.label}-${index}`}>
<p className={labelClass}>{entry.label}</p>
<p className={valueClass}>{entry.value}</p>
</div>
))}
</div>
)
}
const handleDownload = () => {
if (!material) return
setDownloading(true)
setDownloadProgress(0)
const xhr = new XMLHttpRequest()
xhr.addEventListener('progress', (e) => {
if (e.lengthComputable) {
const percentComplete = Math.round((e.loaded / e.total) * 100)
setDownloadProgress(percentComplete)
}
})
xhr.addEventListener('load', () => {
if (xhr.status === 200) {
try {
const blob = new Blob([xhr.response], { type: 'application/zip' })
const contentDisposition = xhr.getResponseHeader('Content-Disposition')
let filename = 'material.zip'
if (contentDisposition) {
const filenameMatch = contentDisposition.match(/filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/)
if (filenameMatch && filenameMatch[1]) {
filename = decodeURIComponent(filenameMatch[1].replace(/['"]/g, ''))
}
}
const url = window.URL.createObjectURL(blob)
const a = document.createElement('a')
a.href = url
a.download = filename
document.body.appendChild(a)
a.click()
a.remove()
window.URL.revokeObjectURL(url)
} catch (error) {
console.error('下载处理失败:', error)
alert({
title: '下载失败',
message: '下载失败,请稍后重试',
variant: 'error',
})
}
} else {
alert({
title: '下载失败',
message: '下载失败',
variant: 'error',
})
}
setDownloading(false)
setDownloadProgress(0)
})
xhr.addEventListener('error', () => {
alert({
title: '下载失败',
message: '下载失败,请稍后重试',
variant: 'error',
})
setDownloading(false)
setDownloadProgress(0)
})
xhr.open('GET', `/api/materials/download?id=${material.id}`)
xhr.responseType = 'arraybuffer'
xhr.send()
}
if (loading) {
return (
<div className="min-h-screen bg-slate-50 dark:bg-slate-900">
<main className="container mx-auto px-4 py-8">
<div className="text-center py-16">
<p className="text-slate-500 dark:text-slate-400 text-lg">加载中...</p>
</div>
</main>
</div>
)
}
if (!material) {
return (
<div className="min-h-screen bg-slate-50 dark:bg-slate-900">
<Header session={session} />
<main className="container mx-auto px-4 py-8">
<div className="text-center py-16">
<p className="text-slate-500 dark:text-slate-400 text-lg">素材不存在</p>
</div>
</main>
</div>
)
}
return (
<div className="min-h-screen bg-slate-50 dark:bg-slate-900">
<Header session={session} />
<main className="container mx-auto px-4 py-8">
{(material.materialType === 'PSD' || material.materialType === '模特') && material.displayImages && material.displayImages.length > 0 ? (
/* PSD/模特类型:左右布局 */
<div className="flex gap-8 max-w-7xl mx-auto">
{/* 左侧:展示图片(固定790px宽度) */}
<div className="flex-shrink-0" style={{ width: '790px' }}>
<div className={cn('rounded-2xl shadow-lg overflow-hidden', styles.cardStyles.base)}>
<div className="w-full bg-slate-200 dark:bg-slate-700 flex flex-col items-center">
{material.displayImages.map((imageUrl, index) => (
<div key={index} className="relative" style={{ maxWidth: '790px', width: '100%' }}>
<Image
src={imageUrl}
alt={`${material.productModel} - 展示图 ${index + 1}`}
width={790}
height={1500}
unoptimized
className="w-full h-auto"
style={{ display: 'block', maxWidth: '790px' }}
/>
</div>
))}
</div>
</div>
</div>
{/* 右侧:素材信息(固定) */}
<div className="w-80 flex-shrink-0">
<div className={cn('sticky top-24 rounded-2xl shadow-lg p-6 space-y-6', styles.cardStyles.base)}>
<div>
<h1 className={cn('text-2xl font-bold mb-3', theme === 'dark' ? 'text-white' : 'text-slate-900')}>
{material.productModel}
</h1>
<div className="flex flex-wrap gap-2">
<span className="inline-flex items-center px-3 py-1 bg-blue-100 dark:bg-blue-900/30 text-blue-700 dark:text-blue-300 rounded-full text-xs font-medium">
{material.categoryName}
</span>
<span className="inline-flex items-center px-3 py-1 bg-green-100 dark:bg-green-900/30 text-green-700 dark:text-green-300 rounded-full text-xs font-medium">
{material.sceneName}
</span>
<span className="inline-flex items-center px-3 py-1 bg-purple-100 dark:bg-purple-900/30 text-purple-700 dark:text-purple-300 rounded-full text-xs font-medium">
{material.materialType}
</span>
</div>
</div>
<div className="space-y-4">
<div>
<p className={cn('text-xs mb-1', theme === 'dark' ? 'text-slate-400' : 'text-slate-500')}>作者</p>
<p className={cn('text-sm font-medium', theme === 'dark' ? 'text-white' : 'text-slate-900')}>{material.authorName}</p>
</div>
<div>
<p className={cn('text-xs mb-1', theme === 'dark' ? 'text-slate-400' : 'text-slate-500')}>文件大小</p>
<p className="text-sm font-medium text-blue-600 dark:text-blue-400">{formatFileSize(material.zipFileSize)}</p>
</div>
<div className="grid grid-cols-2 gap-4">
<div>
<p className={cn('text-xs mb-1', theme === 'dark' ? 'text-slate-400' : 'text-slate-500')}>下载</p>
<p className={cn('text-sm font-medium', theme === 'dark' ? 'text-white' : 'text-slate-900')}>{material.downloadCount}</p>
</div>
<div>
<p className={cn('text-xs mb-1', theme === 'dark' ? 'text-slate-400' : 'text-slate-500')}>点赞</p>
<p className={cn('text-sm font-medium', theme === 'dark' ? 'text-white' : 'text-slate-900')}>{material.likeCount}</p>
</div>
</div>
<div>
<p className={cn('text-xs mb-1', theme === 'dark' ? 'text-slate-400' : 'text-slate-500')}>文件名</p>
<p className={cn('text-xs break-all', theme === 'dark' ? 'text-slate-300' : 'text-slate-700')}>{material.zipFileName}</p>
</div>
<div>
<p className={cn('text-xs mb-1', theme === 'dark' ? 'text-slate-400' : 'text-slate-500')}>上传时间</p>
<p className={cn('text-xs', theme === 'dark' ? 'text-slate-300' : 'text-slate-700')}>
{format(new Date(material.createdAt), 'yyyy-MM-dd HH:mm')}
</p>
</div>
{renderAdditionalInfo('compact')}
</div>
{/* Download Button */}
<button
onClick={handleDownload}
disabled={downloading}
className={cn(
'w-full py-3 text-sm font-medium relative overflow-hidden disabled:opacity-75 rounded-xl',
'bg-blue-600 hover:bg-blue-700 text-white transition-colors',
styles.buttonStyles.primary
)}
>
{downloading ? (
<>
<div
className="absolute left-0 top-0 bottom-0 bg-blue-600 transition-all duration-300"
style={{ width: `${downloadProgress}%` }}
/>
<span className="relative z-10 flex items-center justify-center gap-2">
<svg className="w-5 h-5 animate-spin" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />
</svg>
下载中 {downloadProgress}%
</span>
</>
) : (
<span className="flex items-center justify-center gap-2">
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4" />
</svg>
立即下载
</span>
)}
</button>
{/* AI改图(占位,默认隐藏。后续由开关控制显示) */}
{aiEditEnabled && (
<button
onClick={() => alert({
title: '提示',
message: 'AI改图功能待开放',
variant: 'warning',
})}
className="w-full mt-3 py-2.5 bg-purple-600 text-white rounded-xl text-sm font-medium hover:bg-purple-700 transition-colors"
>
AI改图(预留)
</button>
)}
<button
onClick={() => router.back()}
className={cn(
'w-full py-2.5 rounded-xl text-sm font-medium transition-colors',
styles.buttonStyles.secondary
)}
>
返回上一页
</button>
</div>
</div>
</div>
) : material.materialType === '视频' ? (
/* 视频类型:视频播放布局 */
<div className="max-w-6xl mx-auto">
<div className={cn('rounded-2xl shadow-lg overflow-hidden', styles.cardStyles.base)}>
{/* 视频播放器 */}
<div className="relative w-full bg-black">
<video
controls
className="w-full h-auto max-h-[800px]"
poster={material.previewUrl}
preload="metadata"
>
<source src={`/api/materials/stream?id=${material.id}`} type="video/mp4" />
您的浏览器不支持视频播放。
</video>
</div>
{/* Material Info */}
<div className="p-8">
<div className="mb-6">
<h1 className={cn('text-3xl font-bold mb-2', theme === 'dark' ? 'text-white' : 'text-slate-900')}>
{material.productModel}
</h1>
<div className="flex items-center gap-3 mb-4">
<span className="inline-flex items-center px-3 py-1 bg-blue-100 dark:bg-blue-900/30 text-blue-700 dark:text-blue-300 rounded-full text-sm font-medium">
{material.categoryName}
</span>
<span className="inline-flex items-center px-3 py-1 bg-green-100 dark:bg-green-900/30 text-green-700 dark:text-green-300 rounded-full text-sm font-medium">
{material.sceneName}
</span>
<span className="inline-flex items-center px-3 py-1 bg-red-100 dark:bg-red-900/30 text-red-700 dark:text-red-300 rounded-full text-sm font-medium">
视频
</span>
</div>
</div>
<div className="grid grid-cols-2 gap-6 mb-6">
<div>
<p className={cn('text-sm mb-1', theme === 'dark' ? 'text-slate-400' : 'text-slate-500')}>作者</p>
<p className={cn('text-lg font-medium', theme === 'dark' ? 'text-white' : 'text-slate-900')}>{material.authorName}</p>
</div>
<div>
<p className={cn('text-sm mb-1', theme === 'dark' ? 'text-slate-400' : 'text-slate-500')}>文件大小</p>
<p className="text-lg font-medium text-blue-600 dark:text-blue-400">{formatFileSize(material.zipFileSize)}</p>
</div>
<div>
<p className={cn('text-sm mb-1', theme === 'dark' ? 'text-slate-400' : 'text-slate-500')}>下载次数</p>
<p className={cn('text-lg font-medium', theme === 'dark' ? 'text-white' : 'text-slate-900')}>{material.downloadCount}</p>
</div>
<div>
<p className={cn('text-sm mb-1', theme === 'dark' ? 'text-slate-400' : 'text-slate-500')}>点赞数</p>
<p className={cn('text-lg font-medium', theme === 'dark' ? 'text-white' : 'text-slate-900')}>{material.likeCount}</p>
</div>
</div>
<div className="mb-6">
<p className={cn('text-sm mb-1', theme === 'dark' ? 'text-slate-400' : 'text-slate-500')}>文件名</p>
<p className={cn('text-sm break-all', theme === 'dark' ? 'text-slate-300' : 'text-slate-700')}>{material.zipFileName}</p>
</div>
<div className="mb-6">
<p className={cn('text-sm mb-1', theme === 'dark' ? 'text-slate-400' : 'text-slate-500')}>上传时间</p>
<p className={cn('text-sm', theme === 'dark' ? 'text-slate-300' : 'text-slate-700')}>
{format(new Date(material.createdAt), 'yyyy-MM-dd HH:mm')}
</p>
</div>
{/* Download Button */}
<button
onClick={handleDownload}
disabled={downloading}
className={cn(
'w-full py-4 text-lg font-medium relative overflow-hidden disabled:opacity-75 rounded-xl',
'bg-blue-600 hover:bg-blue-700 text-white transition-colors',
styles.buttonStyles.primary
)}
>
{downloading ? (
<>
<div
className="absolute left-0 top-0 bottom-0 bg-blue-600 transition-all duration-300"
style={{ width: `${downloadProgress}%` }}
/>
<span className="relative z-10 flex items-center justify-center gap-2">
<svg className="w-6 h-6 animate-spin" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />
</svg>
下载中 {downloadProgress}%
</span>
</>
) : (
<span className="flex items-center justify-center gap-2">
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4" />
</svg>
立即下载
</span>
)}
</button>
<button
onClick={() => router.push('/')}
className={cn(
'w-full mt-4 py-3 rounded-xl font-medium transition-colors',
styles.buttonStyles.secondary
)}
>
返回首页
</button>
</div>
</div>
</div>
) : (
/* 非PSD/非视频类型:统一布局 */
<div className="max-w-4xl mx-auto">
<div className={cn('rounded-2xl shadow-lg overflow-hidden', styles.cardStyles.base)}>
{/* 普通预览图 */}
<div className={cn('relative w-full h-96', theme === 'dark' ? 'bg-slate-800' : 'bg-slate-200')}>
<Image
src={material.previewUrl}
alt={material.productModel}
fill
unoptimized
className="object-contain"
sizes="(max-width: 1024px) 100vw, 1024px"
/>
</div>
{/* Material Info */}
<div className="p-8">
<div className="mb-6">
<h1 className={cn('text-3xl font-bold mb-2', theme === 'dark' ? 'text-white' : 'text-slate-900')}>
{material.productModel}
</h1>
<div className="flex items-center gap-3 mb-4">
<span className="inline-flex items-center px-3 py-1 bg-blue-100 dark:bg-blue-900/30 text-blue-700 dark:text-blue-300 rounded-full text-sm font-medium">
{material.categoryName}
</span>
<span className="inline-flex items-center px-3 py-1 bg-green-100 dark:bg-green-900/30 text-green-700 dark:text-green-300 rounded-full text-sm font-medium">
{material.sceneName}
</span>
</div>
</div>
<div className="grid grid-cols-2 gap-6 mb-6">
<div>
<p className={cn('text-sm mb-1', theme === 'dark' ? 'text-slate-400' : 'text-slate-500')}>作者</p>
<p className={cn('text-lg font-medium', theme === 'dark' ? 'text-white' : 'text-slate-900')}>{material.authorName}</p>
</div>
<div>
<p className={cn('text-sm mb-1', theme === 'dark' ? 'text-slate-400' : 'text-slate-500')}>文件大小</p>
<p className="text-lg font-medium text-blue-600 dark:text-blue-400">{formatFileSize(material.zipFileSize)}</p>
</div>
<div>
<p className={cn('text-sm mb-1', theme === 'dark' ? 'text-slate-400' : 'text-slate-500')}>下载次数</p>
<p className={cn('text-lg font-medium', theme === 'dark' ? 'text-white' : 'text-slate-900')}>{material.downloadCount}</p>
</div>
<div>
<p className={cn('text-sm mb-1', theme === 'dark' ? 'text-slate-400' : 'text-slate-500')}>点赞数</p>
<p className={cn('text-lg font-medium', theme === 'dark' ? 'text-white' : 'text-slate-900')}>{material.likeCount}</p>
</div>
</div>
<div className="mb-6">
<p className={cn('text-sm mb-1', theme === 'dark' ? 'text-slate-400' : 'text-slate-500')}>文件名</p>
<p className={cn('text-sm break-all', theme === 'dark' ? 'text-slate-300' : 'text-slate-700')}>{material.zipFileName}</p>
</div>
<div className="mb-6">
<p className={cn('text-sm mb-1', theme === 'dark' ? 'text-slate-400' : 'text-slate-500')}>上传时间</p>
<p className={cn('text-sm', theme === 'dark' ? 'text-slate-300' : 'text-slate-700')}>
{format(new Date(material.createdAt), 'yyyy-MM-dd HH:mm')}
</p>
</div>
{renderAdditionalInfo('full')}
{/* Download Button */}
<button
onClick={handleDownload}
disabled={downloading}
className={cn(
'w-full py-4 text-lg font-medium relative overflow-hidden disabled:opacity-75 rounded-xl',
'bg-blue-600 hover:bg-blue-700 text-white transition-colors',
styles.buttonStyles.primary
)}
>
{downloading ? (
<>
<div
className="absolute left-0 top-0 bottom-0 bg-blue-600 transition-all duration-300"
style={{ width: `${downloadProgress}%` }}
/>
<span className="relative z-10 flex items-center justify-center gap-2">
<svg className="w-6 h-6 animate-spin" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />
</svg>
下载中 {downloadProgress}%
</span>
</>
) : (
<span className="flex items-center justify-center gap-2">
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4" />
</svg>
立即下载
</span>
)}
</button>
<button
onClick={() => router.push('/')}
className={cn(
'w-full mt-4 py-3 rounded-xl font-medium transition-colors',
styles.buttonStyles.secondary
)}
>
返回首页
</button>
</div>
</div>
</div>
)}
</main>
{/* 返回顶部按钮 */}
{showBackToTop && (
<button
onClick={scrollToTop}
className="fixed bottom-8 right-8 w-12 h-12 bg-blue-600 hover:bg-blue-700 text-white rounded-full shadow-lg flex items-center justify-center transition-all z-50"
title="返回顶部"
>
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 10l7-7m0 0l7 7m-7-7v18" />
</svg>
</button>
)}
</div>
)
}