refactor: overhaul UI for streamlined user experience
Redesign navigation, home overview, user portrait, and valuation pages with improved functionality and responsive design. Co-authored-by: null <4804959+fnvtk@users.noreply.github.com>
This commit is contained in:
572
app/workspace/pricing/edit/[id]/page.tsx
Normal file
572
app/workspace/pricing/edit/[id]/page.tsx
Normal file
@@ -0,0 +1,572 @@
|
||||
"use client"
|
||||
|
||||
import { useState, useEffect } from "react"
|
||||
import { useRouter } from "next/navigation"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Input } from "@/components/ui/input"
|
||||
import { Label } from "@/components/ui/label"
|
||||
import { ChevronLeft } from "lucide-react"
|
||||
import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from "@/components/ui/command"
|
||||
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover"
|
||||
import { Check, ChevronsUpDown } from "lucide-react"
|
||||
import { cn } from "@/app/lib/utils"
|
||||
import { Badge } from "@/components/ui/badge"
|
||||
import { ScrollArea } from "@/components/ui/scroll-area"
|
||||
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"
|
||||
import { Switch } from "@/components/ui/switch"
|
||||
import { Card } from "@/components/ui/card"
|
||||
|
||||
// 模拟标签数据
|
||||
const tagOptions = [
|
||||
{ value: "new_user", label: "新用户" },
|
||||
{ value: "low_activity", label: "低活跃度" },
|
||||
{ value: "high_spending", label: "高消费" },
|
||||
{ value: "high_activity", label: "高活跃度" },
|
||||
{ value: "potential", label: "潜在客户" },
|
||||
{ value: "purchase_intent", label: "有购买意向" },
|
||||
{ value: "holiday_consumer", label: "节日消费" },
|
||||
{ value: "promotion_sensitive", label: "促销敏感" },
|
||||
{ value: "tech_savvy", label: "科技爱好者" },
|
||||
{ value: "luxury_buyer", label: "奢侈品买家" },
|
||||
{ value: "price_sensitive", label: "价格敏感" },
|
||||
{ value: "brand_loyal", label: "品牌忠诚" },
|
||||
]
|
||||
|
||||
// 模拟区域数据
|
||||
const regionOptions = [
|
||||
{ value: "nationwide", label: "全国" },
|
||||
{ value: "beijing", label: "北京" },
|
||||
{ value: "shanghai", label: "上海" },
|
||||
{ value: "guangzhou", label: "广州" },
|
||||
{ value: "shenzhen", label: "深圳" },
|
||||
{ value: "hangzhou", label: "杭州" },
|
||||
{ value: "chengdu", label: "成都" },
|
||||
{ value: "wuhan", label: "武汉" },
|
||||
{ value: "east_china", label: "华东地区" },
|
||||
{ value: "south_china", label: "华南地区" },
|
||||
{ value: "north_china", label: "华北地区" },
|
||||
{ value: "central_china", label: "华中地区" },
|
||||
{ value: "tier_1", label: "一线城市" },
|
||||
{ value: "tier_2", label: "二线城市" },
|
||||
{ value: "tier_3", label: "三线城市" },
|
||||
]
|
||||
|
||||
// 模拟设备数据
|
||||
const deviceOptions = [
|
||||
{ id: "1", name: "设备 A-001", status: "online" },
|
||||
{ id: "2", name: "设备 B-002", status: "online" },
|
||||
{ id: "3", name: "设备 C-003", status: "offline" },
|
||||
{ id: "4", name: "设备 D-004", status: "online" },
|
||||
{ id: "5", name: "设备 E-005", status: "online" },
|
||||
]
|
||||
|
||||
// 模拟分发规则数据
|
||||
const mockDistributionData = [
|
||||
{
|
||||
id: "1",
|
||||
ruleType: "trafficPackage",
|
||||
name: "普通流量包",
|
||||
price: 0.5,
|
||||
tags: ["new_user", "low_activity"],
|
||||
regions: ["nationwide"],
|
||||
deviceAddQuantity: 10,
|
||||
selectAllDevices: true,
|
||||
selectedDevices: [],
|
||||
autoAdd: false,
|
||||
},
|
||||
{
|
||||
id: "2",
|
||||
ruleType: "distributionRule",
|
||||
name: "高质量流量分发",
|
||||
price: 2.5,
|
||||
tags: ["high_spending", "high_activity"],
|
||||
regions: ["tier_1"],
|
||||
deviceAddQuantity: 5,
|
||||
selectAllDevices: false,
|
||||
selectedDevices: ["1", "4", "5"],
|
||||
autoAdd: true,
|
||||
},
|
||||
]
|
||||
|
||||
type RuleType = "trafficPackage" | "distributionRule"
|
||||
|
||||
export default function EditDistributionPage({ params }: { params: { id: string } }) {
|
||||
const router = useRouter()
|
||||
const { id } = params
|
||||
|
||||
const [currentStep, setCurrentStep] = useState(1)
|
||||
const [ruleType, setRuleType] = useState<RuleType>("trafficPackage")
|
||||
const [name, setName] = useState("")
|
||||
const [selectedTags, setSelectedTags] = useState<string[]>([])
|
||||
const [selectedRegions, setSelectedRegions] = useState<string[]>([])
|
||||
const [selectedDevices, setSelectedDevices] = useState<string[]>([])
|
||||
const [selectAllDevices, setSelectAllDevices] = useState(false)
|
||||
const [deviceAddQuantity, setDeviceAddQuantity] = useState("10")
|
||||
const [price, setPrice] = useState("")
|
||||
const [tagsOpen, setTagsOpen] = useState(false)
|
||||
const [regionsOpen, setRegionsOpen] = useState(false)
|
||||
const [devicesOpen, setDevicesOpen] = useState(false)
|
||||
const [autoAdd, setAutoAdd] = useState(false)
|
||||
const [loading, setLoading] = useState(true)
|
||||
|
||||
useEffect(() => {
|
||||
// 在实际应用中,这里会从API获取数据
|
||||
// 这里使用模拟数据
|
||||
const distributionItem = mockDistributionData.find((item) => item.id === id)
|
||||
|
||||
if (distributionItem) {
|
||||
setRuleType(distributionItem.ruleType as RuleType)
|
||||
setName(distributionItem.name)
|
||||
setSelectedTags(distributionItem.tags)
|
||||
setSelectedRegions(distributionItem.regions)
|
||||
setSelectAllDevices(distributionItem.selectAllDevices)
|
||||
setSelectedDevices(distributionItem.selectedDevices)
|
||||
setDeviceAddQuantity(distributionItem.deviceAddQuantity.toString())
|
||||
setPrice(distributionItem.price.toString())
|
||||
setAutoAdd(distributionItem.autoAdd)
|
||||
} else {
|
||||
// 如果找不到数据,返回列表页
|
||||
router.push("/workspace/pricing")
|
||||
}
|
||||
|
||||
setLoading(false)
|
||||
}, [id, router])
|
||||
|
||||
// 当选择"全部设备"时,自动选中所有设备
|
||||
const handleSelectAllDevices = (value: boolean) => {
|
||||
setSelectAllDevices(value)
|
||||
if (value) {
|
||||
setSelectedDevices(deviceOptions.map((device) => device.id))
|
||||
} else {
|
||||
setSelectedDevices([])
|
||||
}
|
||||
}
|
||||
|
||||
const handleNext = () => {
|
||||
if (name.trim()) {
|
||||
setCurrentStep(2)
|
||||
} else {
|
||||
alert("请填写名称")
|
||||
}
|
||||
}
|
||||
|
||||
const handlePrevious = () => {
|
||||
setCurrentStep(1)
|
||||
}
|
||||
|
||||
const handleSubmit = () => {
|
||||
// 在实际应用中,这里会发送API请求更新数据
|
||||
console.log({
|
||||
id,
|
||||
ruleType,
|
||||
name,
|
||||
tags: selectedTags,
|
||||
regions: selectedRegions,
|
||||
devices: selectAllDevices ? "all" : selectedDevices,
|
||||
deviceAddQuantity: Number.parseInt(deviceAddQuantity),
|
||||
price: Number.parseFloat(price),
|
||||
autoAdd,
|
||||
})
|
||||
|
||||
// 返回到列表页
|
||||
router.push("/workspace/pricing")
|
||||
}
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<div className="flex justify-center items-center min-h-screen">
|
||||
<div className="animate-spin rounded-full h-12 w-12 border-t-2 border-b-2 border-primary"></div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex flex-col min-h-screen bg-gray-50">
|
||||
{/* 顶部栏 */}
|
||||
<header className="bg-white border-b border-gray-200 sticky top-0 z-10">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 h-16 flex items-center justify-between">
|
||||
<Button variant="ghost" size="icon" onClick={() => router.push("/workspace/pricing")} className="mr-2">
|
||||
<ChevronLeft className="h-5 w-5" />
|
||||
</Button>
|
||||
<h1 className="text-lg font-medium">编辑分发</h1>
|
||||
<div className="w-10"></div> {/* 占位,保持标题居中 */}
|
||||
</div>
|
||||
</header>
|
||||
|
||||
{/* 进度条 */}
|
||||
<div className="bg-white border-b border-gray-200">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4">
|
||||
<div className="flex items-center">
|
||||
<div className="flex-1">
|
||||
<div className="flex items-center">
|
||||
<div
|
||||
className={`rounded-full h-8 w-8 flex items-center justify-center ${
|
||||
currentStep >= 1 ? "bg-blue-600 text-white" : "bg-gray-200 text-gray-600"
|
||||
}`}
|
||||
>
|
||||
1
|
||||
</div>
|
||||
<div className={`h-1 flex-1 mx-2 ${currentStep >= 2 ? "bg-blue-600" : "bg-gray-200"}`}></div>
|
||||
<div
|
||||
className={`rounded-full h-8 w-8 flex items-center justify-center ${
|
||||
currentStep >= 2 ? "bg-blue-600 text-white" : "bg-gray-200 text-gray-600"
|
||||
}`}
|
||||
>
|
||||
2
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex mt-2">
|
||||
<div className="flex-1 text-center text-sm font-medium">选择规则类型</div>
|
||||
<div className="flex-1 text-center text-sm font-medium">设置规则</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 主内容区 */}
|
||||
<main className="flex-1 max-w-3xl mx-auto px-4 sm:px-6 lg:px-8 py-6">
|
||||
{currentStep === 1 ? (
|
||||
<div className="space-y-6">
|
||||
<div className="space-y-4">
|
||||
<h2 className="text-lg font-medium">选择规则类型</h2>
|
||||
|
||||
<RadioGroup
|
||||
value={ruleType}
|
||||
onValueChange={(value) => setRuleType(value as RuleType)}
|
||||
className="grid grid-cols-1 md:grid-cols-2 gap-4"
|
||||
>
|
||||
<Card
|
||||
className={`p-4 cursor-pointer border-2 ${ruleType === "trafficPackage" ? "border-blue-500" : "border-transparent"}`}
|
||||
>
|
||||
<div className="flex items-center space-x-2">
|
||||
<RadioGroupItem value="trafficPackage" id="trafficPackage" />
|
||||
<Label htmlFor="trafficPackage" className="cursor-pointer flex-1">
|
||||
创建流量包
|
||||
</Label>
|
||||
</div>
|
||||
<p className="mt-2 text-sm text-gray-500 pl-6">按照用户标签和地区创建流量包</p>
|
||||
</Card>
|
||||
<Card
|
||||
className={`p-4 cursor-pointer border-2 ${ruleType === "distributionRule" ? "border-blue-500" : "border-transparent"}`}
|
||||
>
|
||||
<div className="flex items-center space-x-2">
|
||||
<RadioGroupItem value="distributionRule" id="distributionRule" />
|
||||
<Label htmlFor="distributionRule" className="cursor-pointer flex-1">
|
||||
创建分发规则
|
||||
</Label>
|
||||
</div>
|
||||
<p className="mt-2 text-sm text-gray-500 pl-6">创建流量自动分发规则</p>
|
||||
</Card>
|
||||
</RadioGroup>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="name">{ruleType === "trafficPackage" ? "流量包名称" : "分发规则名称"}</Label>
|
||||
<Input
|
||||
id="name"
|
||||
value={name}
|
||||
onChange={(e) => setName(e.target.value)}
|
||||
placeholder={ruleType === "trafficPackage" ? "请输入流量包名称" : "请输入分发规则名称"}
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex justify-end pt-4">
|
||||
<Button type="button" onClick={handleNext}>
|
||||
下一步
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<h2 className="text-lg font-medium mb-4">设置规则</h2>
|
||||
|
||||
{/* 用户标签选择 */}
|
||||
<div className="space-y-2 mb-6">
|
||||
<Label>用户标签</Label>
|
||||
<Popover open={tagsOpen} onOpenChange={setTagsOpen}>
|
||||
<PopoverTrigger asChild>
|
||||
<Button
|
||||
variant="outline"
|
||||
role="combobox"
|
||||
aria-expanded={tagsOpen}
|
||||
className="w-full justify-between h-auto min-h-10"
|
||||
>
|
||||
{selectedTags.length > 0 ? (
|
||||
<div className="flex flex-wrap gap-1 py-1">
|
||||
{selectedTags.map((tag) => (
|
||||
<Badge key={tag} variant="secondary" className="mr-1">
|
||||
{tagOptions.find((t) => t.value === tag)?.label}
|
||||
<button
|
||||
className="ml-1 ring-offset-background rounded-full outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2"
|
||||
onMouseDown={(e) => {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
setSelectedTags(selectedTags.filter((t) => t !== tag))
|
||||
}}
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
</Badge>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<span className="text-muted-foreground">选择用户标签</span>
|
||||
)}
|
||||
<ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="w-full p-0">
|
||||
<Command>
|
||||
<CommandInput placeholder="搜索标签..." />
|
||||
<CommandList>
|
||||
<CommandEmpty>未找到相关标签</CommandEmpty>
|
||||
<CommandGroup>
|
||||
<ScrollArea className="h-60">
|
||||
{tagOptions.map((tag) => (
|
||||
<CommandItem
|
||||
key={tag.value}
|
||||
value={tag.value}
|
||||
onSelect={() => {
|
||||
setSelectedTags(
|
||||
selectedTags.includes(tag.value)
|
||||
? selectedTags.filter((t) => t !== tag.value)
|
||||
: [...selectedTags, tag.value],
|
||||
)
|
||||
}}
|
||||
>
|
||||
<Check
|
||||
className={cn(
|
||||
"mr-2 h-4 w-4",
|
||||
selectedTags.includes(tag.value) ? "opacity-100" : "opacity-0",
|
||||
)}
|
||||
/>
|
||||
{tag.label}
|
||||
</CommandItem>
|
||||
))}
|
||||
</ScrollArea>
|
||||
</CommandGroup>
|
||||
</CommandList>
|
||||
</Command>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
</div>
|
||||
|
||||
{/* 用户区域选择 */}
|
||||
<div className="space-y-2 mb-6">
|
||||
<Label>用户区域</Label>
|
||||
<Popover open={regionsOpen} onOpenChange={setRegionsOpen}>
|
||||
<PopoverTrigger asChild>
|
||||
<Button
|
||||
variant="outline"
|
||||
role="combobox"
|
||||
aria-expanded={regionsOpen}
|
||||
className="w-full justify-between h-auto min-h-10"
|
||||
>
|
||||
{selectedRegions.length > 0 ? (
|
||||
<div className="flex flex-wrap gap-1 py-1">
|
||||
{selectedRegions.map((region) => (
|
||||
<Badge key={region} variant="outline" className="mr-1 bg-amber-50">
|
||||
{regionOptions.find((r) => r.value === region)?.label}
|
||||
<button
|
||||
className="ml-1 ring-offset-background rounded-full outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2"
|
||||
onMouseDown={(e) => {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
setSelectedRegions(selectedRegions.filter((r) => r !== region))
|
||||
}}
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
</Badge>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<span className="text-muted-foreground">选择用户区域</span>
|
||||
)}
|
||||
<ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="w-full p-0">
|
||||
<Command>
|
||||
<CommandInput placeholder="搜索区域..." />
|
||||
<CommandList>
|
||||
<CommandEmpty>未找到相关区域</CommandEmpty>
|
||||
<CommandGroup>
|
||||
<ScrollArea className="h-60">
|
||||
{regionOptions.map((region) => (
|
||||
<CommandItem
|
||||
key={region.value}
|
||||
value={region.value}
|
||||
onSelect={() => {
|
||||
setSelectedRegions(
|
||||
selectedRegions.includes(region.value)
|
||||
? selectedRegions.filter((r) => r !== region.value)
|
||||
: [...selectedRegions, region.value],
|
||||
)
|
||||
}}
|
||||
>
|
||||
<Check
|
||||
className={cn(
|
||||
"mr-2 h-4 w-4",
|
||||
selectedRegions.includes(region.value) ? "opacity-100" : "opacity-0",
|
||||
)}
|
||||
/>
|
||||
{region.label}
|
||||
</CommandItem>
|
||||
))}
|
||||
</ScrollArea>
|
||||
</CommandGroup>
|
||||
</CommandList>
|
||||
</Command>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
</div>
|
||||
|
||||
{/* 设备设置 */}
|
||||
<div className="space-y-4 mb-6">
|
||||
<h3 className="font-medium">设备范围设置</h3>
|
||||
|
||||
<div className="flex items-center space-x-2">
|
||||
<Switch id="selectAll" checked={selectAllDevices} onCheckedChange={handleSelectAllDevices} />
|
||||
<Label htmlFor="selectAll">选择所有设备</Label>
|
||||
</div>
|
||||
|
||||
{!selectAllDevices && (
|
||||
<div className="space-y-2">
|
||||
<Label>选择指定设备</Label>
|
||||
<Popover open={devicesOpen} onOpenChange={setDevicesOpen}>
|
||||
<PopoverTrigger asChild>
|
||||
<Button
|
||||
variant="outline"
|
||||
role="combobox"
|
||||
aria-expanded={devicesOpen}
|
||||
className="w-full justify-between h-auto min-h-10"
|
||||
>
|
||||
{selectedDevices.length > 0 ? (
|
||||
<div className="flex flex-wrap gap-1 py-1">
|
||||
{selectedDevices.map((deviceId) => (
|
||||
<Badge key={deviceId} variant="outline" className="mr-1">
|
||||
{deviceOptions.find((d) => d.id === deviceId)?.name}
|
||||
<button
|
||||
className="ml-1 ring-offset-background rounded-full outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2"
|
||||
onMouseDown={(e) => {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
setSelectedDevices(selectedDevices.filter((d) => d !== deviceId))
|
||||
}}
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
</Badge>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<span className="text-muted-foreground">选择设备</span>
|
||||
)}
|
||||
<ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="w-full p-0">
|
||||
<Command>
|
||||
<CommandInput placeholder="搜索设备..." />
|
||||
<CommandList>
|
||||
<CommandEmpty>未找到相关设备</CommandEmpty>
|
||||
<CommandGroup>
|
||||
<ScrollArea className="h-60">
|
||||
{deviceOptions.map((device) => (
|
||||
<CommandItem
|
||||
key={device.id}
|
||||
value={device.id}
|
||||
onSelect={() => {
|
||||
setSelectedDevices(
|
||||
selectedDevices.includes(device.id)
|
||||
? selectedDevices.filter((d) => d !== device.id)
|
||||
: [...selectedDevices, device.id],
|
||||
)
|
||||
}}
|
||||
>
|
||||
<Check
|
||||
className={cn(
|
||||
"mr-2 h-4 w-4",
|
||||
selectedDevices.includes(device.id) ? "opacity-100" : "opacity-0",
|
||||
)}
|
||||
/>
|
||||
{device.name}
|
||||
<span
|
||||
className={`ml-2 px-1.5 py-0.5 rounded text-xs ${
|
||||
device.status === "online"
|
||||
? "bg-green-100 text-green-800"
|
||||
: "bg-gray-100 text-gray-800"
|
||||
}`}
|
||||
>
|
||||
{device.status === "online" ? "在线" : "离线"}
|
||||
</span>
|
||||
</CommandItem>
|
||||
))}
|
||||
</ScrollArea>
|
||||
</CommandGroup>
|
||||
</CommandList>
|
||||
</Command>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* 单设备添加数量 */}
|
||||
<div className="space-y-2 mb-6">
|
||||
<Label htmlFor="deviceAddQuantity">单设备添加数量</Label>
|
||||
<Input
|
||||
id="deviceAddQuantity"
|
||||
type="number"
|
||||
min="1"
|
||||
value={deviceAddQuantity}
|
||||
onChange={(e) => setDeviceAddQuantity(e.target.value)}
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* 价格设置 */}
|
||||
<div className="space-y-2 mb-6">
|
||||
<Label htmlFor="price">价格(元/人次)</Label>
|
||||
<div className="relative">
|
||||
<span className="absolute left-3 top-1/2 transform -translate-y-1/2">¥</span>
|
||||
<Input
|
||||
id="price"
|
||||
type="number"
|
||||
step="0.01"
|
||||
min="0"
|
||||
value={price}
|
||||
onChange={(e) => setPrice(e.target.value)}
|
||||
placeholder="0.00"
|
||||
className="pl-8"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 自动添加设置 */}
|
||||
<div className="flex items-center space-x-2 mb-6">
|
||||
<Switch id="autoAdd" checked={autoAdd} onCheckedChange={setAutoAdd} />
|
||||
<Label htmlFor="autoAdd">自动添加</Label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 按钮组 */}
|
||||
<div className="flex justify-between pt-4">
|
||||
<Button type="button" variant="outline" onClick={handlePrevious}>
|
||||
上一步
|
||||
</Button>
|
||||
<Button type="button" onClick={handleSubmit}>
|
||||
确认
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</main>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user