存客宝 React
This commit is contained in:
143
Cunkebao/app/workspace/moments-sync/[id]/edit/page.tsx
Normal file
143
Cunkebao/app/workspace/moments-sync/[id]/edit/page.tsx
Normal file
@@ -0,0 +1,143 @@
|
||||
"use client"
|
||||
|
||||
import { useState } from "react"
|
||||
import { useRouter } from "next/navigation"
|
||||
import { ChevronLeft, Search } from "lucide-react"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { StepIndicator } from "../../components/step-indicator"
|
||||
import { BasicSettings } from "../../components/basic-settings"
|
||||
import { DeviceSelectionDialog } from "../../components/device-selection-dialog"
|
||||
import { Input } from "@/components/ui/input"
|
||||
|
||||
export default function EditMomentsSyncPage() {
|
||||
const router = useRouter()
|
||||
const [currentStep, setCurrentStep] = useState(1)
|
||||
const [deviceDialogOpen, setDeviceDialogOpen] = useState(false)
|
||||
const [formData, setFormData] = useState({
|
||||
taskName: "同步卡若主号",
|
||||
startTime: "06:00",
|
||||
endTime: "23:59",
|
||||
syncCount: 5,
|
||||
accountType: "business" as const,
|
||||
enabled: true,
|
||||
selectedDevices: [] as string[],
|
||||
selectedLibraries: [] as string[],
|
||||
})
|
||||
|
||||
const handleUpdateFormData = (data: Partial<typeof formData>) => {
|
||||
setFormData((prev) => ({ ...prev, ...data }))
|
||||
}
|
||||
|
||||
const handleNext = () => {
|
||||
setCurrentStep((prev) => Math.min(prev + 1, 3))
|
||||
}
|
||||
|
||||
const handlePrev = () => {
|
||||
setCurrentStep((prev) => Math.max(prev - 1, 1))
|
||||
}
|
||||
|
||||
const handleComplete = () => {
|
||||
console.log("Form submitted:", formData)
|
||||
router.push("/workspace/moments-sync")
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-[#F8F9FA] pb-20">
|
||||
<header className="sticky top-0 z-10 bg-white">
|
||||
<div className="flex items-center h-14 px-4">
|
||||
<Button variant="ghost" size="icon" onClick={() => router.back()} className="hover:bg-gray-50">
|
||||
<ChevronLeft className="h-6 w-6" />
|
||||
</Button>
|
||||
<h1 className="ml-2 text-lg font-medium">编辑朋友圈同步</h1>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div className="mt-8">
|
||||
<StepIndicator currentStep={currentStep} />
|
||||
|
||||
<div className="mt-8">
|
||||
{currentStep === 1 && (
|
||||
<BasicSettings formData={formData} onChange={handleUpdateFormData} onNext={handleNext} />
|
||||
)}
|
||||
|
||||
{currentStep === 2 && (
|
||||
<div className="space-y-6 px-6">
|
||||
<div className="relative">
|
||||
<Search className="absolute left-3 top-4 h-5 w-5 text-gray-400" />
|
||||
<Input
|
||||
placeholder="选择设备"
|
||||
className="h-12 pl-11 rounded-xl border-gray-200 text-base"
|
||||
onClick={() => setDeviceDialogOpen(true)}
|
||||
readOnly
|
||||
/>
|
||||
</div>
|
||||
|
||||
{formData.selectedDevices.length > 0 && (
|
||||
<div className="text-base text-gray-500">已选设备:{formData.selectedDevices.length} 个</div>
|
||||
)}
|
||||
|
||||
<div className="flex space-x-4 pt-4">
|
||||
<Button variant="outline" onClick={handlePrev} className="flex-1 h-12 rounded-xl text-base">
|
||||
上一步
|
||||
</Button>
|
||||
<Button
|
||||
onClick={handleNext}
|
||||
className="flex-1 h-12 bg-blue-600 hover:bg-blue-700 rounded-xl text-base shadow-sm"
|
||||
>
|
||||
下一步
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<DeviceSelectionDialog
|
||||
open={deviceDialogOpen}
|
||||
onOpenChange={setDeviceDialogOpen}
|
||||
selectedDevices={formData.selectedDevices}
|
||||
onSelect={(devices) => {
|
||||
handleUpdateFormData({ selectedDevices: devices })
|
||||
setDeviceDialogOpen(false)
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{currentStep === 3 && (
|
||||
<div className="space-y-6 px-6">
|
||||
<div className="relative">
|
||||
<Search className="absolute left-3 top-4 h-5 w-5 text-gray-400" />
|
||||
<Input placeholder="选择内容库" className="h-12 pl-11 rounded-xl border-gray-200 text-base" />
|
||||
</div>
|
||||
|
||||
<div className="flex space-x-4 pt-4">
|
||||
<Button variant="outline" onClick={handlePrev} className="flex-1 h-12 rounded-xl text-base">
|
||||
上一步
|
||||
</Button>
|
||||
<Button
|
||||
onClick={handleComplete}
|
||||
className="flex-1 h-12 bg-blue-600 hover:bg-blue-700 rounded-xl text-base shadow-sm"
|
||||
>
|
||||
完成
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<nav className="fixed bottom-0 left-0 right-0 h-16 bg-white border-t flex items-center justify-around px-6">
|
||||
<button className="flex flex-col items-center text-blue-600">
|
||||
<span className="text-sm mt-1">首页</span>
|
||||
</button>
|
||||
<button className="flex flex-col items-center text-gray-400">
|
||||
<span className="text-sm mt-1">场景获客</span>
|
||||
</button>
|
||||
<button className="flex flex-col items-center text-gray-400">
|
||||
<span className="text-sm mt-1">工作台</span>
|
||||
</button>
|
||||
<button className="flex flex-col items-center text-gray-400">
|
||||
<span className="text-sm mt-1">我的</span>
|
||||
</button>
|
||||
</nav>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
interface StepIndicatorProps {
|
||||
currentStep: number
|
||||
}
|
||||
|
||||
export function StepIndicator({ currentStep }: StepIndicatorProps) {
|
||||
const steps = [
|
||||
{ number: 1, title: "步骤 1", subtitle: "基础设置" },
|
||||
{ number: 2, title: "步骤 2", subtitle: "设备选择" },
|
||||
{ number: 3, title: "步骤 3", subtitle: "选择内容库" },
|
||||
]
|
||||
|
||||
return (
|
||||
<div className="flex justify-between relative">
|
||||
{steps.map((step, index) => (
|
||||
<div key={step.number} className="flex flex-col items-center relative z-10">
|
||||
<div
|
||||
className={`w-8 h-8 rounded-full flex items-center justify-center text-sm
|
||||
${currentStep >= step.number ? "bg-blue-600 text-white" : "bg-gray-100 text-gray-400"}`}
|
||||
>
|
||||
{step.number}
|
||||
</div>
|
||||
<div className={`text-xs mt-2 ${currentStep >= step.number ? "text-blue-600" : "text-gray-400"}`}>
|
||||
{step.title}
|
||||
</div>
|
||||
<div className={`text-xs ${currentStep >= step.number ? "text-gray-600" : "text-gray-400"}`}>
|
||||
{step.subtitle}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
<div className="absolute top-4 left-0 right-0 h-[1px] bg-gray-200 -z-10">
|
||||
<div
|
||||
className="h-full bg-blue-600 transition-all duration-300"
|
||||
style={{ width: `${((currentStep - 1) / (steps.length - 1)) * 100}%` }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
"use client"
|
||||
|
||||
import { Input } from "@/components/ui/input"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Switch } from "@/components/ui/switch"
|
||||
import { Plus, Minus } from "lucide-react"
|
||||
|
||||
interface BasicSettingsProps {
|
||||
formData: {
|
||||
taskName: string
|
||||
startTime: string
|
||||
endTime: string
|
||||
syncCount: number
|
||||
accountType: string
|
||||
enabled: boolean
|
||||
}
|
||||
onChange: (data: Partial<BasicSettingsProps["formData"]>) => void
|
||||
onNext: () => void
|
||||
}
|
||||
|
||||
export function BasicSettings({ formData, onChange, onNext }: BasicSettingsProps) {
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<div className="text-sm mb-2">任务名称</div>
|
||||
<Input
|
||||
value={formData.taskName}
|
||||
onChange={(e) => onChange({ taskName: e.target.value })}
|
||||
placeholder="请输入任务名称"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div className="text-sm mb-2">允许发布时间段</div>
|
||||
<div className="flex items-center space-x-3">
|
||||
<Input
|
||||
type="time"
|
||||
value={formData.startTime}
|
||||
onChange={(e) => onChange({ startTime: e.target.value })}
|
||||
className="w-32"
|
||||
/>
|
||||
<span className="text-gray-500">至</span>
|
||||
<Input
|
||||
type="time"
|
||||
value={formData.endTime}
|
||||
onChange={(e) => onChange({ endTime: e.target.value })}
|
||||
className="w-32"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div className="text-sm mb-2">每日同步数量</div>
|
||||
<div className="flex items-center space-x-4">
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
onClick={() => onChange({ syncCount: Math.max(1, formData.syncCount - 1) })}
|
||||
>
|
||||
<Minus className="h-4 w-4" />
|
||||
</Button>
|
||||
<span className="w-8 text-center">{formData.syncCount}</span>
|
||||
<Button variant="outline" size="icon" onClick={() => onChange({ syncCount: formData.syncCount + 1 })}>
|
||||
<Plus className="h-4 w-4" />
|
||||
</Button>
|
||||
<span className="text-gray-500">条朋友圈</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div className="text-sm mb-2">账号类型</div>
|
||||
<div className="flex space-x-4">
|
||||
<Button
|
||||
variant={formData.accountType === "business" ? "default" : "outline"}
|
||||
onClick={() => onChange({ accountType: "business" })}
|
||||
className="flex-1"
|
||||
>
|
||||
业务号
|
||||
</Button>
|
||||
<Button
|
||||
variant={formData.accountType === "personal" ? "default" : "outline"}
|
||||
onClick={() => onChange({ accountType: "personal" })}
|
||||
className="flex-1"
|
||||
>
|
||||
人设号
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-sm">是否启用</span>
|
||||
<Switch checked={formData.enabled} onCheckedChange={(checked) => onChange({ enabled: checked })} />
|
||||
</div>
|
||||
|
||||
<Button onClick={onNext} className="w-full mt-8">
|
||||
下一步
|
||||
</Button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
"use client"
|
||||
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Input } from "@/components/ui/input"
|
||||
import { Search } from "lucide-react"
|
||||
|
||||
interface ContentLibrarySelectionProps {
|
||||
selectedLibraries: string[]
|
||||
onChange: (libraries: string[]) => void
|
||||
onComplete: () => void
|
||||
onPrev: () => void
|
||||
}
|
||||
|
||||
export function ContentLibrarySelection({
|
||||
selectedLibraries,
|
||||
onChange,
|
||||
onComplete,
|
||||
onPrev,
|
||||
}: ContentLibrarySelectionProps) {
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<div className="relative">
|
||||
<Search className="absolute left-3 top-2.5 h-4 w-4 text-gray-400" />
|
||||
<Input placeholder="选择内容库" className="pl-9" />
|
||||
</div>
|
||||
|
||||
<div className="min-h-[300px] flex items-center justify-center text-gray-400">选择内容库组件将在这里实现</div>
|
||||
|
||||
<div className="flex space-x-3 mt-8">
|
||||
<Button variant="outline" onClick={onPrev} className="flex-1">
|
||||
上一步
|
||||
</Button>
|
||||
<Button onClick={onComplete} className="flex-1">
|
||||
完成
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
"use client"
|
||||
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Input } from "@/components/ui/input"
|
||||
import { Search } from "lucide-react"
|
||||
|
||||
interface DeviceSelectionProps {
|
||||
selectedDevices: string[]
|
||||
onChange: (devices: string[]) => void
|
||||
onNext: () => void
|
||||
onPrev: () => void
|
||||
}
|
||||
|
||||
export function DeviceSelection({ selectedDevices, onChange, onNext, onPrev }: DeviceSelectionProps) {
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<div className="relative">
|
||||
<Search className="absolute left-3 top-2.5 h-4 w-4 text-gray-400" />
|
||||
<Input placeholder="选择设备" className="pl-9" />
|
||||
</div>
|
||||
|
||||
<div className="min-h-[300px] flex items-center justify-center text-gray-400">选择设备组件将在这里实现</div>
|
||||
|
||||
<div className="flex space-x-3 mt-8">
|
||||
<Button variant="outline" onClick={onPrev} className="flex-1">
|
||||
上一步
|
||||
</Button>
|
||||
<Button onClick={onNext} className="flex-1">
|
||||
下一步
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
108
Cunkebao/app/workspace/moments-sync/[id]/page.tsx
Normal file
108
Cunkebao/app/workspace/moments-sync/[id]/page.tsx
Normal file
@@ -0,0 +1,108 @@
|
||||
"use client"
|
||||
|
||||
import { useState, useEffect } from "react"
|
||||
import { useRouter } from "next/navigation"
|
||||
import { ChevronLeft } from "lucide-react"
|
||||
import { Card } from "@/components/ui/card"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Badge } from "@/components/ui/badge"
|
||||
import { Switch } from "@/components/ui/switch"
|
||||
|
||||
interface SyncTask {
|
||||
id: string
|
||||
name: string
|
||||
status: "running" | "paused"
|
||||
deviceCount: number
|
||||
contentLib: string
|
||||
syncCount: number
|
||||
lastSyncTime: string
|
||||
createTime: string
|
||||
creator: string
|
||||
}
|
||||
|
||||
export default function ViewMomentsSyncTask({ params }: { params: { id: string } }) {
|
||||
const router = useRouter()
|
||||
const [task, setTask] = useState<SyncTask | null>(null)
|
||||
|
||||
useEffect(() => {
|
||||
// Fetch task data from API
|
||||
// For now, we'll use mock data
|
||||
setTask({
|
||||
id: params.id,
|
||||
name: "同步卡若主号",
|
||||
deviceCount: 2,
|
||||
contentLib: "卡若朋友圈",
|
||||
syncCount: 307,
|
||||
lastSyncTime: "2025-02-06 13:12:35",
|
||||
createTime: "2024-11-20 19:04:14",
|
||||
creator: "karuo",
|
||||
status: "running",
|
||||
})
|
||||
}, [params.id])
|
||||
|
||||
const toggleTaskStatus = () => {
|
||||
if (task) {
|
||||
setTask({ ...task, status: task.status === "running" ? "paused" : "running" })
|
||||
}
|
||||
}
|
||||
|
||||
if (!task) {
|
||||
return <div>Loading...</div>
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex-1 bg-gray-50 min-h-screen">
|
||||
<header className="sticky top-0 z-10 bg-white border-b">
|
||||
<div className="flex items-center justify-between p-4">
|
||||
<div className="flex items-center space-x-3">
|
||||
<Button variant="ghost" size="icon" onClick={() => router.back()}>
|
||||
<ChevronLeft className="h-5 w-5" />
|
||||
</Button>
|
||||
<h1 className="text-lg font-medium">查看朋友圈同步任务</h1>
|
||||
</div>
|
||||
<Button onClick={() => router.push(`/workspace/moments-sync/${task.id}/edit`)}>编辑任务</Button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div className="p-4">
|
||||
<Card className="p-6">
|
||||
<div className="flex items-center justify-between mb-6">
|
||||
<div className="flex items-center space-x-2">
|
||||
<h2 className="text-2xl font-bold">{task.name}</h2>
|
||||
<Badge variant={task.status === "running" ? "success" : "secondary"}>
|
||||
{task.status === "running" ? "进行中" : "已暂停"}
|
||||
</Badge>
|
||||
</div>
|
||||
<Switch checked={task.status === "running"} onCheckedChange={toggleTaskStatus} />
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-2 gap-6 mb-6">
|
||||
<div>
|
||||
<h3 className="text-lg font-semibold mb-2">任务详情</h3>
|
||||
<div className="space-y-2">
|
||||
<p>推送设备:{task.deviceCount} 个</p>
|
||||
<p>内容库:{task.contentLib}</p>
|
||||
<p>已同步:{task.syncCount} 条</p>
|
||||
<p>创建人:{task.creator}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-lg font-semibold mb-2">时间信息</h3>
|
||||
<div className="space-y-2">
|
||||
<p>创建时间:{task.createTime}</p>
|
||||
<p>上次同步:{task.lastSyncTime}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="border-t pt-4">
|
||||
<h3 className="text-lg font-semibold mb-2">同步内容预览</h3>
|
||||
{/* Add content preview here */}
|
||||
<p className="text-gray-500">暂无内容预览</p>
|
||||
</div>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
130
Cunkebao/app/workspace/moments-sync/[id]/view/page.tsx
Normal file
130
Cunkebao/app/workspace/moments-sync/[id]/view/page.tsx
Normal file
@@ -0,0 +1,130 @@
|
||||
"use client"
|
||||
|
||||
import { useState } from "react"
|
||||
import { ChevronLeft, Edit2, RefreshCw } from "lucide-react"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Card } from "@/components/ui/card"
|
||||
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"
|
||||
|
||||
interface MomentContent {
|
||||
id: string
|
||||
type: string
|
||||
content: string
|
||||
images: string[]
|
||||
publishTime: string
|
||||
pushTime: string
|
||||
status: "已发送" | "待发送" | "已终止"
|
||||
}
|
||||
|
||||
const mockData: MomentContent[] = [
|
||||
{
|
||||
id: "399401",
|
||||
type: "图文",
|
||||
content: "一定要把安全意识这件事情,刻在DNA里......",
|
||||
images: [
|
||||
"https://hebbkx1anhila5yf.public.blob.vercel-storage.com/image-Z8LxL98X5Bwm5Jr5ke3755Qd97PSYC.png",
|
||||
"https://hebbkx1anhila5yf.public.blob.vercel-storage.com/image-Z8LxL98X5Bwm5Jr5ke3755Qd97PSYC.png",
|
||||
"https://hebbkx1anhila5yf.public.blob.vercel-storage.com/image-Z8LxL98X5Bwm5Jr5ke3755Qd97PSYC.png",
|
||||
],
|
||||
publishTime: "2025-02-15 23:37:49",
|
||||
pushTime: "2025-02-16 08:50:36",
|
||||
status: "已发送",
|
||||
},
|
||||
]
|
||||
|
||||
export default function MomentsSyncViewPage() {
|
||||
const [syncName] = useState("同步卡若主号")
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-gray-50">
|
||||
<header className="sticky top-0 z-10 bg-white border-b">
|
||||
<div className="flex items-center justify-between h-14 px-4">
|
||||
<div className="flex items-center">
|
||||
<Button variant="ghost" size="icon" onClick={() => window.history.back()}>
|
||||
<ChevronLeft className="h-5 w-5" />
|
||||
</Button>
|
||||
<h1 className="ml-2 text-lg font-medium">{syncName}</h1>
|
||||
</div>
|
||||
<div className="flex items-center space-x-2">
|
||||
<Button variant="outline" size="sm">
|
||||
<Edit2 className="h-4 w-4 mr-2" />
|
||||
编辑
|
||||
</Button>
|
||||
<Button variant="outline" size="sm">
|
||||
<RefreshCw className="h-4 w-4 mr-2" />
|
||||
刷新
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div className="p-4 max-w-7xl mx-auto space-y-6">
|
||||
<Card className="p-6">
|
||||
<h2 className="text-lg font-medium mb-4">基本信息</h2>
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-center">
|
||||
<span className="text-gray-500 w-32">朋友圈同步名称:</span>
|
||||
<span>{syncName}</span>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
<Card className="p-6">
|
||||
<h2 className="text-lg font-medium mb-4">推送日志</h2>
|
||||
<div className="overflow-x-auto">
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead className="w-[100px]">ID</TableHead>
|
||||
<TableHead>内容类型</TableHead>
|
||||
<TableHead>内容</TableHead>
|
||||
<TableHead>图片</TableHead>
|
||||
<TableHead>推送时间</TableHead>
|
||||
<TableHead>内容发布时间</TableHead>
|
||||
<TableHead>状态</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{mockData.map((item) => (
|
||||
<TableRow key={item.id}>
|
||||
<TableCell>{item.id}</TableCell>
|
||||
<TableCell>{item.type}</TableCell>
|
||||
<TableCell className="max-w-[300px] truncate">{item.content}</TableCell>
|
||||
<TableCell>
|
||||
<div className="flex space-x-2">
|
||||
{item.images.map((img, index) => (
|
||||
<img
|
||||
key={index}
|
||||
src={img || "/placeholder.svg"}
|
||||
alt={`Content ${index + 1}`}
|
||||
className="w-16 h-16 object-cover rounded"
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</TableCell>
|
||||
<TableCell>{item.pushTime}</TableCell>
|
||||
<TableCell>{item.publishTime}</TableCell>
|
||||
<TableCell>
|
||||
<span
|
||||
className={`px-2 py-1 rounded-full text-xs ${
|
||||
item.status === "已发送"
|
||||
? "bg-green-100 text-green-800"
|
||||
: item.status === "待发送"
|
||||
? "bg-blue-100 text-blue-800"
|
||||
: "bg-red-100 text-red-800"
|
||||
}`}
|
||||
>
|
||||
{item.status}
|
||||
</span>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</div>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user